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