1 /* $NetBSD: si_obio.c,v 1.35 2008/04/28 20:23:38 martin 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.35 2008/04/28 20:23:38 martin 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 #include <sys/user.h> 88 89 #include <dev/scsipi/scsi_all.h> 90 #include <dev/scsipi/scsipi_all.h> 91 #include <dev/scsipi/scsipi_debug.h> 92 #include <dev/scsipi/scsiconf.h> 93 94 #include <machine/autoconf.h> 95 #include <machine/dvma.h> 96 97 /* #define DEBUG XXX */ 98 99 #include <dev/ic/ncr5380reg.h> 100 #include <dev/ic/ncr5380var.h> 101 102 #include "sireg.h" 103 #include "sivar.h" 104 #include "am9516.h" 105 106 /* 107 * How many uS. to delay after touching the am9516 UDC. 108 */ 109 #define UDC_WAIT_USEC 5 110 111 void si_obio_dma_setup(struct ncr5380_softc *); 112 void si_obio_dma_start(struct ncr5380_softc *); 113 void si_obio_dma_eop(struct ncr5380_softc *); 114 void si_obio_dma_stop(struct ncr5380_softc *); 115 116 static void si_obio_reset(struct ncr5380_softc *); 117 118 static inline void si_obio_udc_write(volatile struct si_regs *, int, int); 119 static inline int si_obio_udc_read(volatile struct si_regs *, int); 120 121 122 /* 123 * New-style autoconfig attachment 124 */ 125 126 static int si_obio_match(device_t, cfdata_t, void *); 127 static void si_obio_attach(device_t, device_t, void *); 128 129 CFATTACH_DECL_NEW(si_obio, sizeof(struct si_softc), 130 si_obio_match, si_obio_attach, NULL, NULL); 131 132 /* 133 * Options for disconnect/reselect, DMA, and interrupts. 134 * By default, allow disconnect/reselect on targets 4-6. 135 * Those are normally tapes that really need it enabled. 136 */ 137 int si_obio_options = 0x0f; 138 139 140 static int 141 si_obio_match(device_t parent, cfdata_t cf, void *aux) 142 { 143 struct confargs *ca = aux; 144 145 /* Make sure something is there... */ 146 if (bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1) == -1) 147 return 0; 148 149 /* Default interrupt priority. */ 150 if (ca->ca_intpri == -1) 151 ca->ca_intpri = 2; 152 153 return 1; 154 } 155 156 static void 157 si_obio_attach(device_t parent, device_t self, void *args) 158 { 159 struct si_softc *sc = device_private(self); 160 struct ncr5380_softc *ncr_sc = &sc->ncr_sc; 161 struct cfdata *cf = device_cfdata(self); 162 struct confargs *ca = args; 163 164 ncr_sc->sc_dev = self; 165 sc->sc_bst = ca->ca_bustag; 166 sc->sc_dmat = ca->ca_dmatag; 167 168 if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct si_regs), 0, 169 &sc->sc_bsh) != 0) { 170 aprint_error(": can't map register\n"); 171 return; 172 } 173 sc->sc_regs = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 174 175 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 176 BUS_DMA_NOWAIT, &sc->sc_dmap) != 0) { 177 aprint_error(": can't create DMA map\n"); 178 return; 179 } 180 181 /* Get options from config flags if specified. */ 182 if (cf->cf_flags) 183 sc->sc_options = cf->cf_flags; 184 else 185 sc->sc_options = si_obio_options; 186 187 aprint_normal(": options=0x%x\n", sc->sc_options); 188 189 sc->sc_adapter_type = ca->ca_bustype; 190 191 /* 192 * MD function pointers used by the MI code. 193 */ 194 ncr_sc->sc_pio_out = ncr5380_pio_out; 195 ncr_sc->sc_pio_in = ncr5380_pio_in; 196 ncr_sc->sc_dma_alloc = si_dma_alloc; 197 ncr_sc->sc_dma_free = si_dma_free; 198 ncr_sc->sc_dma_setup = si_obio_dma_setup; 199 ncr_sc->sc_dma_start = si_obio_dma_start; 200 ncr_sc->sc_dma_poll = si_dma_poll; 201 ncr_sc->sc_dma_eop = si_obio_dma_eop; 202 ncr_sc->sc_dma_stop = si_obio_dma_stop; 203 ncr_sc->sc_intr_on = NULL; 204 ncr_sc->sc_intr_off = NULL; 205 206 /* Need DVMA-capable memory for the UDC command block. */ 207 sc->sc_dmacmd = dvma_malloc(sizeof(struct udc_table)); 208 209 /* Attach interrupt handler. */ 210 isr_add_autovect(si_intr, (void *)sc, ca->ca_intpri); 211 212 /* Reset the hardware. */ 213 si_obio_reset(ncr_sc); 214 215 /* Do the common attach stuff. */ 216 si_attach(sc); 217 } 218 219 static void 220 si_obio_reset(struct ncr5380_softc *ncr_sc) 221 { 222 struct si_softc *sc = (struct si_softc *)ncr_sc; 223 volatile struct si_regs *si = sc->sc_regs; 224 225 #ifdef DEBUG 226 if (si_debug) { 227 printf("%s\n", __func__); 228 } 229 #endif 230 231 /* 232 * The SCSI3 controller has an 8K FIFO to buffer data between the 233 * 5380 and the DMA. Make sure it starts out empty. 234 * 235 * The reset bits in the CSR are active low. 236 */ 237 si->si_csr = 0; 238 delay(10); 239 si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN; 240 delay(10); 241 si->fifo_count = 0; 242 } 243 244 static inline void 245 si_obio_udc_write(volatile struct si_regs *si, int regnum, int value) 246 { 247 248 si->udc_addr = regnum; 249 delay(UDC_WAIT_USEC); 250 si->udc_data = value; 251 delay(UDC_WAIT_USEC); 252 } 253 254 static inline int 255 si_obio_udc_read(volatile struct si_regs *si, int regnum) 256 { 257 int value; 258 259 si->udc_addr = regnum; 260 delay(UDC_WAIT_USEC); 261 value = si->udc_data; 262 delay(UDC_WAIT_USEC); 263 264 return value; 265 } 266 267 268 /* 269 * This function is called during the COMMAND or MSG_IN phase 270 * that precedes a DATA_IN or DATA_OUT phase, in case we need 271 * to setup the DMA engine before the bus enters a DATA phase. 272 * 273 * The OBIO "si" IGNORES any attempt to set the FIFO count 274 * register after the SCSI bus goes into any DATA phase, so 275 * this function has to setup the evil FIFO logic. 276 */ 277 void 278 si_obio_dma_setup(struct ncr5380_softc *ncr_sc) 279 { 280 struct si_softc *sc = (struct si_softc *)ncr_sc; 281 struct sci_req *sr = ncr_sc->sc_current; 282 struct si_dma_handle *dh = sr->sr_dma_hand; 283 volatile struct si_regs *si = sc->sc_regs; 284 struct udc_table *cmd; 285 long data_pa, cmd_pa; 286 int xlen; 287 288 /* 289 * Get the DVMA mapping for this segment. 290 * XXX - Should separate allocation and mapin. 291 */ 292 data_pa = dh->dh_dmaaddr; 293 if (data_pa & 1) 294 panic("%s: bad pa=0x%lx", __func__, data_pa); 295 xlen = dh->dh_dmalen; 296 sc->sc_reqlen = xlen; /* XXX: or less? */ 297 298 #ifdef DEBUG 299 if (si_debug & 2) { 300 printf("%s: dh=%p, pa=0x%lx, xlen=0x%x\n", 301 __func__, dh, data_pa, xlen); 302 } 303 #endif 304 305 /* Reset the UDC. (In case not already reset?) */ 306 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 307 308 /* Reset the FIFO */ 309 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 310 si->si_csr |= SI_CSR_FIFO_RES; 311 312 /* Set direction (send/recv) */ 313 if (dh->dh_flags & SIDH_OUT) { 314 si->si_csr |= SI_CSR_SEND; 315 } else { 316 si->si_csr &= ~SI_CSR_SEND; 317 } 318 319 /* Set the FIFO counter. */ 320 si->fifo_count = xlen; 321 322 /* Reset the UDC. */ 323 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 324 325 /* 326 * XXX: Reset the FIFO again! Comment from Sprite: 327 * Go through reset again because of the bug on the 3/50 328 * where bytes occasionally linger in the DMA fifo. 329 */ 330 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 331 si->si_csr |= SI_CSR_FIFO_RES; 332 333 #ifdef DEBUG 334 /* Make sure the extra FIFO reset did not hit the count. */ 335 if (si->fifo_count != xlen) { 336 printf("%s: fifo_count=0x%x, xlen=0x%x\n", 337 __func__, si->fifo_count, xlen); 338 Debugger(); 339 } 340 #endif 341 342 /* 343 * Set up the DMA controller. The DMA controller on 344 * OBIO needs a command block in DVMA space. 345 */ 346 cmd = sc->sc_dmacmd; 347 cmd->addrh = ((data_pa & 0xFF0000) >> 8) | UDC_ADDR_INFO; 348 cmd->addrl = data_pa & 0xFFFF; 349 cmd->count = xlen / 2; /* bytes -> words */ 350 cmd->cmrh = UDC_CMR_HIGH; 351 if (dh->dh_flags & SIDH_OUT) { 352 if (xlen & 1) 353 cmd->count++; 354 cmd->cmrl = UDC_CMR_LSEND; 355 cmd->rsel = UDC_RSEL_SEND; 356 } else { 357 cmd->cmrl = UDC_CMR_LRECV; 358 cmd->rsel = UDC_RSEL_RECV; 359 } 360 361 /* Tell the DMA chip where the control block is. */ 362 cmd_pa = dvma_kvtopa(cmd, BUS_OBIO); 363 si_obio_udc_write(si, UDC_ADR_CAR_HIGH, (cmd_pa & 0xff0000) >> 8); 364 si_obio_udc_write(si, UDC_ADR_CAR_LOW, (cmd_pa & 0xffff)); 365 366 /* Tell the chip to be a DMA master. */ 367 si_obio_udc_write(si, UDC_ADR_MODE, UDC_MODE); 368 369 /* Tell the chip to interrupt on error. */ 370 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE); 371 372 /* Will do "start chain" command in _dma_start. */ 373 } 374 375 376 void 377 si_obio_dma_start(struct ncr5380_softc *ncr_sc) 378 { 379 struct si_softc *sc = (struct si_softc *)ncr_sc; 380 struct sci_req *sr = ncr_sc->sc_current; 381 struct si_dma_handle *dh = sr->sr_dma_hand; 382 volatile struct si_regs *si = sc->sc_regs; 383 int s; 384 385 #ifdef DEBUG 386 if (si_debug & 2) { 387 printf("%s: sr=%p\n", __func__, sr); 388 } 389 #endif 390 391 /* This MAY be time critical (not sure). */ 392 s = splhigh(); 393 394 /* Finally, give the UDC a "start chain" command. */ 395 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN); 396 397 /* 398 * Acknowledge the phase change. (After DMA setup!) 399 * Put the SBIC into DMA mode, and start the transfer. 400 */ 401 if (dh->dh_flags & SIDH_OUT) { 402 *ncr_sc->sci_tcmd = PHASE_DATA_OUT; 403 SCI_CLR_INTR(ncr_sc); 404 *ncr_sc->sci_icmd = SCI_ICMD_DATA; 405 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 406 *ncr_sc->sci_dma_send = 0; /* start it */ 407 } else { 408 *ncr_sc->sci_tcmd = PHASE_DATA_IN; 409 SCI_CLR_INTR(ncr_sc); 410 *ncr_sc->sci_icmd = 0; 411 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 412 *ncr_sc->sci_irecv = 0; /* start it */ 413 } 414 415 splx(s); 416 ncr_sc->sc_state |= NCR_DOINGDMA; 417 418 #ifdef DEBUG 419 if (si_debug & 2) { 420 printf("%s: started, flags=0x%x\n", 421 __func__, ncr_sc->sc_state); 422 } 423 #endif 424 } 425 426 427 void 428 si_obio_dma_eop(struct ncr5380_softc *ncr_sc) 429 { 430 431 /* Not needed - DMA was stopped prior to examining sci_csr */ 432 } 433 434 435 void 436 si_obio_dma_stop(struct ncr5380_softc *ncr_sc) 437 { 438 struct si_softc *sc = (struct si_softc *)ncr_sc; 439 struct sci_req *sr = ncr_sc->sc_current; 440 struct si_dma_handle *dh = sr->sr_dma_hand; 441 volatile struct si_regs *si = sc->sc_regs; 442 int resid, ntrans, tmo, udc_cnt; 443 444 if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) { 445 #ifdef DEBUG 446 printf("%s: DMA not running\n", __func__); 447 #endif 448 return; 449 } 450 ncr_sc->sc_state &= ~NCR_DOINGDMA; 451 452 NCR_TRACE("si_dma_stop: top, csr=0x%x\n", si->si_csr); 453 454 /* OK, have either phase mis-match or end of DMA. */ 455 /* Set an impossible phase to prevent data movement? */ 456 *ncr_sc->sci_tcmd = PHASE_INVALID; 457 458 /* Check for DMA errors. */ 459 if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) { 460 printf("si: DMA error, csr=0x%x, reset\n", si->si_csr); 461 sr->sr_xs->error = XS_DRIVER_STUFFUP; 462 ncr_sc->sc_state |= NCR_ABORTING; 463 si_obio_reset(ncr_sc); 464 goto out; 465 } 466 467 /* Note that timeout may have set the error flag. */ 468 if (ncr_sc->sc_state & NCR_ABORTING) 469 goto out; 470 471 /* 472 * After a read, wait for the FIFO to empty. 473 * Note: this only works on the OBIO version. 474 */ 475 if ((dh->dh_flags & SIDH_OUT) == 0) { 476 tmo = 200000; /* X10 = 2 sec. */ 477 for (;;) { 478 if (si->si_csr & SI_CSR_FIFO_EMPTY) 479 break; 480 if (--tmo <= 0) { 481 printf("si: DMA FIFO did not empty, reset\n"); 482 ncr_sc->sc_state |= NCR_ABORTING; 483 /* si_obio_reset(ncr_sc); */ 484 goto out; 485 } 486 delay(10); 487 } 488 } 489 490 /* 491 * Now try to figure out how much actually transferred. 492 * The fifo_count might not reflect how many bytes were 493 * actually transferred. 494 */ 495 resid = si->fifo_count & 0xFFFF; 496 ntrans = sc->sc_reqlen - resid; 497 498 #ifdef DEBUG 499 if (si_debug & 2) { 500 printf("%s: resid=0x%x ntrans=0x%x\n", 501 __func__, resid, ntrans); 502 } 503 #endif 504 505 /* XXX: Treat (ntrans==0) as a special, non-error case? */ 506 if (ntrans < MIN_DMA_LEN) { 507 printf("si: fifo count: 0x%x\n", resid); 508 ncr_sc->sc_state |= NCR_ABORTING; 509 goto out; 510 } 511 if (ntrans > ncr_sc->sc_datalen) 512 panic("%s: excess transfer", __func__); 513 514 /* Adjust data pointer */ 515 ncr_sc->sc_dataptr += ntrans; 516 ncr_sc->sc_datalen -= ntrans; 517 518 /* 519 * After a read, we may need to clean-up 520 * "Left-over bytes" (yuck!) 521 */ 522 if ((dh->dh_flags & SIDH_OUT) == 0) { 523 /* If odd transfer count, grab last byte by hand. */ 524 if (ntrans & 1) { 525 NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n", 526 (int) ncr_sc->sc_dataptr - 1); 527 ncr_sc->sc_dataptr[-1] = 528 (si->fifo_data & 0xff00) >> 8; 529 goto out; 530 } 531 /* UDC might not have transfered the last word. */ 532 udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT); 533 if (((udc_cnt * 2) - resid) == 2) { 534 NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n", 535 (int) ncr_sc->sc_dataptr - 2); 536 ncr_sc->sc_dataptr[-2] = 537 (si->fifo_data & 0xff00) >> 8; 538 ncr_sc->sc_dataptr[-1] = 539 (si->fifo_data & 0x00ff); 540 } 541 } 542 543 out: 544 /* Reset the UDC. */ 545 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 546 si->fifo_count = 0; 547 si->si_csr &= ~SI_CSR_SEND; 548 549 /* Reset the FIFO */ 550 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 551 si->si_csr |= SI_CSR_FIFO_RES; 552 553 /* Put SBIC back in PIO mode. */ 554 /* XXX: set tcmd to PHASE_INVALID? */ 555 *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE); 556 *ncr_sc->sci_icmd = 0; 557 } 558 559