1 /* $NetBSD: si_obio.c,v 1.36 2009/11/21 04:16:52 rmind Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Adam Glass, David Jones, and Gordon W. Ross. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This file contains only the machine-dependent parts of the 34 * Sun3 SCSI driver. (Autoconfig stuff and DMA functions.) 35 * The machine-independent parts are in ncr5380sbc.c 36 * 37 * Supported hardware includes: 38 * Sun SCSI-3 on OBIO (Sun3/50,Sun3/60) 39 * Sun SCSI-3 on VME (Sun3/160,Sun3/260) 40 * 41 * Could be made to support the Sun3/E if someone wanted to. 42 * 43 * Note: Both supported variants of the Sun SCSI-3 adapter have 44 * some really unusual "features" for this driver to deal with, 45 * generally related to the DMA engine. The OBIO variant will 46 * ignore any attempt to write the FIFO count register while the 47 * SCSI bus is in DATA_IN or DATA_OUT phase. This is dealt with 48 * by setting the FIFO count early in COMMAND or MSG_IN phase. 49 * 50 * The VME variant has a bit to enable or disable the DMA engine, 51 * but that bit also gates the interrupt line from the NCR5380! 52 * Therefore, in order to get any interrupt from the 5380, (i.e. 53 * for reselect) one must clear the DMA engine transfer count and 54 * then enable DMA. This has the further complication that you 55 * CAN NOT touch the NCR5380 while the DMA enable bit is set, so 56 * we have to turn DMA back off before we even look at the 5380. 57 * 58 * What wonderfully whacky hardware this is! 59 * 60 * Credits, history: 61 * 62 * David Jones wrote the initial version of this module, which 63 * included support for the VME adapter only. (no reselection). 64 * 65 * Gordon Ross added support for the OBIO adapter, and re-worked 66 * both the VME and OBIO code to support disconnect/reselect. 67 * (Required figuring out the hardware "features" noted above.) 68 * 69 * The autoconfiguration boilerplate came from Adam Glass. 70 */ 71 72 /***************************************************************** 73 * OBIO functions for DMA 74 ****************************************************************/ 75 76 #include <sys/cdefs.h> 77 __KERNEL_RCSID(0, "$NetBSD: si_obio.c,v 1.36 2009/11/21 04:16:52 rmind Exp $"); 78 79 #include <sys/param.h> 80 #include <sys/systm.h> 81 #include <sys/errno.h> 82 #include <sys/kernel.h> 83 #include <sys/malloc.h> 84 #include <sys/device.h> 85 #include <sys/buf.h> 86 #include <sys/proc.h> 87 88 #include <dev/scsipi/scsi_all.h> 89 #include <dev/scsipi/scsipi_all.h> 90 #include <dev/scsipi/scsipi_debug.h> 91 #include <dev/scsipi/scsiconf.h> 92 93 #include <machine/autoconf.h> 94 #include <machine/dvma.h> 95 96 /* #define DEBUG XXX */ 97 98 #include <dev/ic/ncr5380reg.h> 99 #include <dev/ic/ncr5380var.h> 100 101 #include "sireg.h" 102 #include "sivar.h" 103 #include "am9516.h" 104 105 /* 106 * How many uS. to delay after touching the am9516 UDC. 107 */ 108 #define UDC_WAIT_USEC 5 109 110 void si_obio_dma_setup(struct ncr5380_softc *); 111 void si_obio_dma_start(struct ncr5380_softc *); 112 void si_obio_dma_eop(struct ncr5380_softc *); 113 void si_obio_dma_stop(struct ncr5380_softc *); 114 115 static void si_obio_reset(struct ncr5380_softc *); 116 117 static inline void si_obio_udc_write(volatile struct si_regs *, int, int); 118 static inline int si_obio_udc_read(volatile struct si_regs *, int); 119 120 121 /* 122 * New-style autoconfig attachment 123 */ 124 125 static int si_obio_match(device_t, cfdata_t, void *); 126 static void si_obio_attach(device_t, device_t, void *); 127 128 CFATTACH_DECL_NEW(si_obio, sizeof(struct si_softc), 129 si_obio_match, si_obio_attach, NULL, NULL); 130 131 /* 132 * Options for disconnect/reselect, DMA, and interrupts. 133 * By default, allow disconnect/reselect on targets 4-6. 134 * Those are normally tapes that really need it enabled. 135 */ 136 int si_obio_options = 0x0f; 137 138 139 static int 140 si_obio_match(device_t parent, cfdata_t cf, void *aux) 141 { 142 struct confargs *ca = aux; 143 144 /* Make sure something is there... */ 145 if (bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1) == -1) 146 return 0; 147 148 /* Default interrupt priority. */ 149 if (ca->ca_intpri == -1) 150 ca->ca_intpri = 2; 151 152 return 1; 153 } 154 155 static void 156 si_obio_attach(device_t parent, device_t self, void *args) 157 { 158 struct si_softc *sc = device_private(self); 159 struct ncr5380_softc *ncr_sc = &sc->ncr_sc; 160 struct cfdata *cf = device_cfdata(self); 161 struct confargs *ca = args; 162 163 ncr_sc->sc_dev = self; 164 sc->sc_bst = ca->ca_bustag; 165 sc->sc_dmat = ca->ca_dmatag; 166 167 if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct si_regs), 0, 168 &sc->sc_bsh) != 0) { 169 aprint_error(": can't map register\n"); 170 return; 171 } 172 sc->sc_regs = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 173 174 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 175 BUS_DMA_NOWAIT, &sc->sc_dmap) != 0) { 176 aprint_error(": can't create DMA map\n"); 177 return; 178 } 179 180 /* Get options from config flags if specified. */ 181 if (cf->cf_flags) 182 sc->sc_options = cf->cf_flags; 183 else 184 sc->sc_options = si_obio_options; 185 186 aprint_normal(": options=0x%x\n", sc->sc_options); 187 188 sc->sc_adapter_type = ca->ca_bustype; 189 190 /* 191 * MD function pointers used by the MI code. 192 */ 193 ncr_sc->sc_pio_out = ncr5380_pio_out; 194 ncr_sc->sc_pio_in = ncr5380_pio_in; 195 ncr_sc->sc_dma_alloc = si_dma_alloc; 196 ncr_sc->sc_dma_free = si_dma_free; 197 ncr_sc->sc_dma_setup = si_obio_dma_setup; 198 ncr_sc->sc_dma_start = si_obio_dma_start; 199 ncr_sc->sc_dma_poll = si_dma_poll; 200 ncr_sc->sc_dma_eop = si_obio_dma_eop; 201 ncr_sc->sc_dma_stop = si_obio_dma_stop; 202 ncr_sc->sc_intr_on = NULL; 203 ncr_sc->sc_intr_off = NULL; 204 205 /* Need DVMA-capable memory for the UDC command block. */ 206 sc->sc_dmacmd = dvma_malloc(sizeof(struct udc_table)); 207 208 /* Attach interrupt handler. */ 209 isr_add_autovect(si_intr, (void *)sc, ca->ca_intpri); 210 211 /* Reset the hardware. */ 212 si_obio_reset(ncr_sc); 213 214 /* Do the common attach stuff. */ 215 si_attach(sc); 216 } 217 218 static void 219 si_obio_reset(struct ncr5380_softc *ncr_sc) 220 { 221 struct si_softc *sc = (struct si_softc *)ncr_sc; 222 volatile struct si_regs *si = sc->sc_regs; 223 224 #ifdef DEBUG 225 if (si_debug) { 226 printf("%s\n", __func__); 227 } 228 #endif 229 230 /* 231 * The SCSI3 controller has an 8K FIFO to buffer data between the 232 * 5380 and the DMA. Make sure it starts out empty. 233 * 234 * The reset bits in the CSR are active low. 235 */ 236 si->si_csr = 0; 237 delay(10); 238 si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN; 239 delay(10); 240 si->fifo_count = 0; 241 } 242 243 static inline void 244 si_obio_udc_write(volatile struct si_regs *si, int regnum, int value) 245 { 246 247 si->udc_addr = regnum; 248 delay(UDC_WAIT_USEC); 249 si->udc_data = value; 250 delay(UDC_WAIT_USEC); 251 } 252 253 static inline int 254 si_obio_udc_read(volatile struct si_regs *si, int regnum) 255 { 256 int value; 257 258 si->udc_addr = regnum; 259 delay(UDC_WAIT_USEC); 260 value = si->udc_data; 261 delay(UDC_WAIT_USEC); 262 263 return value; 264 } 265 266 267 /* 268 * This function is called during the COMMAND or MSG_IN phase 269 * that precedes a DATA_IN or DATA_OUT phase, in case we need 270 * to setup the DMA engine before the bus enters a DATA phase. 271 * 272 * The OBIO "si" IGNORES any attempt to set the FIFO count 273 * register after the SCSI bus goes into any DATA phase, so 274 * this function has to setup the evil FIFO logic. 275 */ 276 void 277 si_obio_dma_setup(struct ncr5380_softc *ncr_sc) 278 { 279 struct si_softc *sc = (struct si_softc *)ncr_sc; 280 struct sci_req *sr = ncr_sc->sc_current; 281 struct si_dma_handle *dh = sr->sr_dma_hand; 282 volatile struct si_regs *si = sc->sc_regs; 283 struct udc_table *cmd; 284 long data_pa, cmd_pa; 285 int xlen; 286 287 /* 288 * Get the DVMA mapping for this segment. 289 * XXX - Should separate allocation and mapin. 290 */ 291 data_pa = dh->dh_dmaaddr; 292 if (data_pa & 1) 293 panic("%s: bad pa=0x%lx", __func__, data_pa); 294 xlen = dh->dh_dmalen; 295 sc->sc_reqlen = xlen; /* XXX: or less? */ 296 297 #ifdef DEBUG 298 if (si_debug & 2) { 299 printf("%s: dh=%p, pa=0x%lx, xlen=0x%x\n", 300 __func__, dh, data_pa, xlen); 301 } 302 #endif 303 304 /* Reset the UDC. (In case not already reset?) */ 305 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 306 307 /* Reset the FIFO */ 308 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 309 si->si_csr |= SI_CSR_FIFO_RES; 310 311 /* Set direction (send/recv) */ 312 if (dh->dh_flags & SIDH_OUT) { 313 si->si_csr |= SI_CSR_SEND; 314 } else { 315 si->si_csr &= ~SI_CSR_SEND; 316 } 317 318 /* Set the FIFO counter. */ 319 si->fifo_count = xlen; 320 321 /* Reset the UDC. */ 322 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 323 324 /* 325 * XXX: Reset the FIFO again! Comment from Sprite: 326 * Go through reset again because of the bug on the 3/50 327 * where bytes occasionally linger in the DMA fifo. 328 */ 329 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 330 si->si_csr |= SI_CSR_FIFO_RES; 331 332 #ifdef DEBUG 333 /* Make sure the extra FIFO reset did not hit the count. */ 334 if (si->fifo_count != xlen) { 335 printf("%s: fifo_count=0x%x, xlen=0x%x\n", 336 __func__, si->fifo_count, xlen); 337 Debugger(); 338 } 339 #endif 340 341 /* 342 * Set up the DMA controller. The DMA controller on 343 * OBIO needs a command block in DVMA space. 344 */ 345 cmd = sc->sc_dmacmd; 346 cmd->addrh = ((data_pa & 0xFF0000) >> 8) | UDC_ADDR_INFO; 347 cmd->addrl = data_pa & 0xFFFF; 348 cmd->count = xlen / 2; /* bytes -> words */ 349 cmd->cmrh = UDC_CMR_HIGH; 350 if (dh->dh_flags & SIDH_OUT) { 351 if (xlen & 1) 352 cmd->count++; 353 cmd->cmrl = UDC_CMR_LSEND; 354 cmd->rsel = UDC_RSEL_SEND; 355 } else { 356 cmd->cmrl = UDC_CMR_LRECV; 357 cmd->rsel = UDC_RSEL_RECV; 358 } 359 360 /* Tell the DMA chip where the control block is. */ 361 cmd_pa = dvma_kvtopa(cmd, BUS_OBIO); 362 si_obio_udc_write(si, UDC_ADR_CAR_HIGH, (cmd_pa & 0xff0000) >> 8); 363 si_obio_udc_write(si, UDC_ADR_CAR_LOW, (cmd_pa & 0xffff)); 364 365 /* Tell the chip to be a DMA master. */ 366 si_obio_udc_write(si, UDC_ADR_MODE, UDC_MODE); 367 368 /* Tell the chip to interrupt on error. */ 369 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE); 370 371 /* Will do "start chain" command in _dma_start. */ 372 } 373 374 375 void 376 si_obio_dma_start(struct ncr5380_softc *ncr_sc) 377 { 378 struct si_softc *sc = (struct si_softc *)ncr_sc; 379 struct sci_req *sr = ncr_sc->sc_current; 380 struct si_dma_handle *dh = sr->sr_dma_hand; 381 volatile struct si_regs *si = sc->sc_regs; 382 int s; 383 384 #ifdef DEBUG 385 if (si_debug & 2) { 386 printf("%s: sr=%p\n", __func__, sr); 387 } 388 #endif 389 390 /* This MAY be time critical (not sure). */ 391 s = splhigh(); 392 393 /* Finally, give the UDC a "start chain" command. */ 394 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN); 395 396 /* 397 * Acknowledge the phase change. (After DMA setup!) 398 * Put the SBIC into DMA mode, and start the transfer. 399 */ 400 if (dh->dh_flags & SIDH_OUT) { 401 *ncr_sc->sci_tcmd = PHASE_DATA_OUT; 402 SCI_CLR_INTR(ncr_sc); 403 *ncr_sc->sci_icmd = SCI_ICMD_DATA; 404 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 405 *ncr_sc->sci_dma_send = 0; /* start it */ 406 } else { 407 *ncr_sc->sci_tcmd = PHASE_DATA_IN; 408 SCI_CLR_INTR(ncr_sc); 409 *ncr_sc->sci_icmd = 0; 410 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 411 *ncr_sc->sci_irecv = 0; /* start it */ 412 } 413 414 splx(s); 415 ncr_sc->sc_state |= NCR_DOINGDMA; 416 417 #ifdef DEBUG 418 if (si_debug & 2) { 419 printf("%s: started, flags=0x%x\n", 420 __func__, ncr_sc->sc_state); 421 } 422 #endif 423 } 424 425 426 void 427 si_obio_dma_eop(struct ncr5380_softc *ncr_sc) 428 { 429 430 /* Not needed - DMA was stopped prior to examining sci_csr */ 431 } 432 433 434 void 435 si_obio_dma_stop(struct ncr5380_softc *ncr_sc) 436 { 437 struct si_softc *sc = (struct si_softc *)ncr_sc; 438 struct sci_req *sr = ncr_sc->sc_current; 439 struct si_dma_handle *dh = sr->sr_dma_hand; 440 volatile struct si_regs *si = sc->sc_regs; 441 int resid, ntrans, tmo, udc_cnt; 442 443 if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) { 444 #ifdef DEBUG 445 printf("%s: DMA not running\n", __func__); 446 #endif 447 return; 448 } 449 ncr_sc->sc_state &= ~NCR_DOINGDMA; 450 451 NCR_TRACE("si_dma_stop: top, csr=0x%x\n", si->si_csr); 452 453 /* OK, have either phase mis-match or end of DMA. */ 454 /* Set an impossible phase to prevent data movement? */ 455 *ncr_sc->sci_tcmd = PHASE_INVALID; 456 457 /* Check for DMA errors. */ 458 if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) { 459 printf("si: DMA error, csr=0x%x, reset\n", si->si_csr); 460 sr->sr_xs->error = XS_DRIVER_STUFFUP; 461 ncr_sc->sc_state |= NCR_ABORTING; 462 si_obio_reset(ncr_sc); 463 goto out; 464 } 465 466 /* Note that timeout may have set the error flag. */ 467 if (ncr_sc->sc_state & NCR_ABORTING) 468 goto out; 469 470 /* 471 * After a read, wait for the FIFO to empty. 472 * Note: this only works on the OBIO version. 473 */ 474 if ((dh->dh_flags & SIDH_OUT) == 0) { 475 tmo = 200000; /* X10 = 2 sec. */ 476 for (;;) { 477 if (si->si_csr & SI_CSR_FIFO_EMPTY) 478 break; 479 if (--tmo <= 0) { 480 printf("si: DMA FIFO did not empty, reset\n"); 481 ncr_sc->sc_state |= NCR_ABORTING; 482 /* si_obio_reset(ncr_sc); */ 483 goto out; 484 } 485 delay(10); 486 } 487 } 488 489 /* 490 * Now try to figure out how much actually transferred. 491 * The fifo_count might not reflect how many bytes were 492 * actually transferred. 493 */ 494 resid = si->fifo_count & 0xFFFF; 495 ntrans = sc->sc_reqlen - resid; 496 497 #ifdef DEBUG 498 if (si_debug & 2) { 499 printf("%s: resid=0x%x ntrans=0x%x\n", 500 __func__, resid, ntrans); 501 } 502 #endif 503 504 /* XXX: Treat (ntrans==0) as a special, non-error case? */ 505 if (ntrans < MIN_DMA_LEN) { 506 printf("si: fifo count: 0x%x\n", resid); 507 ncr_sc->sc_state |= NCR_ABORTING; 508 goto out; 509 } 510 if (ntrans > ncr_sc->sc_datalen) 511 panic("%s: excess transfer", __func__); 512 513 /* Adjust data pointer */ 514 ncr_sc->sc_dataptr += ntrans; 515 ncr_sc->sc_datalen -= ntrans; 516 517 /* 518 * After a read, we may need to clean-up 519 * "Left-over bytes" (yuck!) 520 */ 521 if ((dh->dh_flags & SIDH_OUT) == 0) { 522 /* If odd transfer count, grab last byte by hand. */ 523 if (ntrans & 1) { 524 NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n", 525 (int) ncr_sc->sc_dataptr - 1); 526 ncr_sc->sc_dataptr[-1] = 527 (si->fifo_data & 0xff00) >> 8; 528 goto out; 529 } 530 /* UDC might not have transfered the last word. */ 531 udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT); 532 if (((udc_cnt * 2) - resid) == 2) { 533 NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n", 534 (int) ncr_sc->sc_dataptr - 2); 535 ncr_sc->sc_dataptr[-2] = 536 (si->fifo_data & 0xff00) >> 8; 537 ncr_sc->sc_dataptr[-1] = 538 (si->fifo_data & 0x00ff); 539 } 540 } 541 542 out: 543 /* Reset the UDC. */ 544 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 545 si->fifo_count = 0; 546 si->si_csr &= ~SI_CSR_SEND; 547 548 /* Reset the FIFO */ 549 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 550 si->si_csr |= SI_CSR_FIFO_RES; 551 552 /* Put SBIC back in PIO mode. */ 553 /* XXX: set tcmd to PHASE_INVALID? */ 554 *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE); 555 *ncr_sc->sci_icmd = 0; 556 } 557 558