1 /* $NetBSD: si_obio.c,v 1.6 1996/10/30 00:31:39 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 132 133 static int 134 si_obio_match(parent, vcf, args) 135 struct device *parent; 136 void *vcf, *args; 137 { 138 struct cfdata *cf = vcf; 139 struct confargs *ca = args; 140 141 /* Make sure there is something there... */ 142 if (bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1) == -1) 143 return (0); 144 145 /* Default interrupt priority. */ 146 if (ca->ca_intpri == -1) 147 ca->ca_intpri = 2; 148 149 return (1); 150 } 151 152 static void 153 si_obio_attach(parent, self, args) 154 struct device *parent, *self; 155 void *args; 156 { 157 struct si_softc *sc = (struct si_softc *) self; 158 struct ncr5380_softc *ncr_sc = &sc->ncr_sc; 159 struct cfdata *cf = self->dv_cfdata; 160 struct confargs *ca = args; 161 162 /* Get options from config flags... */ 163 sc->sc_options = cf->cf_flags | si_obio_options; 164 printf(": options=%d\n", sc->sc_options); 165 166 sc->sc_adapter_type = ca->ca_bustype; 167 sc->sc_regs = (struct si_regs *) 168 obio_alloc(ca->ca_paddr, sizeof(struct si_regs)); 169 170 /* 171 * MD function pointers used by the MI code. 172 */ 173 ncr_sc->sc_pio_out = ncr5380_pio_out; 174 ncr_sc->sc_pio_in = ncr5380_pio_in; 175 ncr_sc->sc_dma_alloc = si_dma_alloc; 176 ncr_sc->sc_dma_free = si_dma_free; 177 ncr_sc->sc_dma_setup = si_obio_dma_setup; 178 ncr_sc->sc_dma_start = si_obio_dma_start; 179 ncr_sc->sc_dma_poll = si_dma_poll; 180 ncr_sc->sc_dma_eop = si_obio_dma_eop; 181 ncr_sc->sc_dma_stop = si_obio_dma_stop; 182 ncr_sc->sc_intr_on = NULL; 183 ncr_sc->sc_intr_off = NULL; 184 185 /* Need DVMA-capable memory for the UDC command block. */ 186 sc->sc_dmacmd = dvma_malloc(sizeof (struct udc_table)); 187 188 /* Attach interrupt handler. */ 189 isr_add_autovect(si_intr, (void *)sc, ca->ca_intpri); 190 191 /* Do the common attach stuff. */ 192 si_attach(sc); 193 } 194 195 196 static __inline__ void 197 si_obio_udc_write(si, regnum, value) 198 volatile struct si_regs *si; 199 int regnum, value; 200 { 201 si->udc_addr = regnum; 202 delay(UDC_WAIT_USEC); 203 si->udc_data = value; 204 delay(UDC_WAIT_USEC); 205 } 206 207 static __inline__ int 208 si_obio_udc_read(si, regnum) 209 volatile struct si_regs *si; 210 int regnum; 211 { 212 int value; 213 214 si->udc_addr = regnum; 215 delay(UDC_WAIT_USEC); 216 value = si->udc_data; 217 delay(UDC_WAIT_USEC); 218 219 return (value); 220 } 221 222 223 /* 224 * This function is called during the COMMAND or MSG_IN phase 225 * that preceeds a DATA_IN or DATA_OUT phase, in case we need 226 * to setup the DMA engine before the bus enters a DATA phase. 227 * 228 * The OBIO "si" IGNORES any attempt to set the FIFO count 229 * register after the SCSI bus goes into any DATA phase, so 230 * this function has to setup the evil FIFO logic. 231 */ 232 void 233 si_obio_dma_setup(ncr_sc) 234 struct ncr5380_softc *ncr_sc; 235 { 236 struct si_softc *sc = (struct si_softc *)ncr_sc; 237 struct sci_req *sr = ncr_sc->sc_current; 238 struct si_dma_handle *dh = sr->sr_dma_hand; 239 volatile struct si_regs *si = sc->sc_regs; 240 struct udc_table *cmd; 241 long data_pa, cmd_pa; 242 int xlen; 243 244 /* 245 * Get the DVMA mapping for this segment. 246 * XXX - Should separate allocation and mapin. 247 */ 248 data_pa = dvma_kvtopa(dh->dh_dvma, sc->sc_adapter_type); 249 data_pa += (ncr_sc->sc_dataptr - dh->dh_addr); 250 if (data_pa & 1) 251 panic("si_dma_start: bad pa=0x%x", data_pa); 252 xlen = ncr_sc->sc_datalen; 253 sc->sc_reqlen = xlen; /* XXX: or less? */ 254 255 #ifdef DEBUG 256 if (si_debug & 2) { 257 printf("si_dma_setup: dh=0x%x, pa=0x%x, xlen=%d\n", 258 dh, data_pa, xlen); 259 } 260 #endif 261 262 /* Reset the UDC. (In case not already reset?) */ 263 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 264 265 /* Reset the FIFO */ 266 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 267 si->si_csr |= SI_CSR_FIFO_RES; 268 269 /* Set direction (send/recv) */ 270 if (dh->dh_flags & SIDH_OUT) { 271 si->si_csr |= SI_CSR_SEND; 272 } else { 273 si->si_csr &= ~SI_CSR_SEND; 274 } 275 276 /* Set the FIFO counter. */ 277 si->fifo_count = xlen; 278 279 /* Reset the UDC. */ 280 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 281 282 /* 283 * XXX: Reset the FIFO again! Comment from Sprite: 284 * Go through reset again becuase of the bug on the 3/50 285 * where bytes occasionally linger in the DMA fifo. 286 */ 287 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 288 si->si_csr |= SI_CSR_FIFO_RES; 289 290 #ifdef DEBUG 291 /* Make sure the extra FIFO reset did not hit the count. */ 292 if (si->fifo_count != xlen) { 293 printf("si_dma_setup: fifo_count=0x%x, xlen=0x%x\n", 294 si->fifo_count, xlen); 295 Debugger(); 296 } 297 #endif 298 299 /* 300 * Set up the DMA controller. The DMA controller on 301 * OBIO needs a command block in DVMA space. 302 */ 303 cmd = sc->sc_dmacmd; 304 cmd->addrh = ((data_pa & 0xFF0000) >> 8) | UDC_ADDR_INFO; 305 cmd->addrl = data_pa & 0xFFFF; 306 cmd->count = xlen / 2; /* bytes -> words */ 307 cmd->cmrh = UDC_CMR_HIGH; 308 if (dh->dh_flags & SIDH_OUT) { 309 if (xlen & 1) 310 cmd->count++; 311 cmd->cmrl = UDC_CMR_LSEND; 312 cmd->rsel = UDC_RSEL_SEND; 313 } else { 314 cmd->cmrl = UDC_CMR_LRECV; 315 cmd->rsel = UDC_RSEL_RECV; 316 } 317 318 /* Tell the DMA chip where the control block is. */ 319 cmd_pa = dvma_kvtopa((long)cmd, BUS_OBIO); 320 si_obio_udc_write(si, UDC_ADR_CAR_HIGH, 321 (cmd_pa & 0xff0000) >> 8); 322 si_obio_udc_write(si, UDC_ADR_CAR_LOW, 323 (cmd_pa & 0xffff)); 324 325 /* Tell the chip to be a DMA master. */ 326 si_obio_udc_write(si, UDC_ADR_MODE, UDC_MODE); 327 328 /* Tell the chip to interrupt on error. */ 329 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE); 330 331 /* Will do "start chain" command in _dma_start. */ 332 } 333 334 335 void 336 si_obio_dma_start(ncr_sc) 337 struct ncr5380_softc *ncr_sc; 338 { 339 struct si_softc *sc = (struct si_softc *)ncr_sc; 340 struct sci_req *sr = ncr_sc->sc_current; 341 struct si_dma_handle *dh = sr->sr_dma_hand; 342 volatile struct si_regs *si = sc->sc_regs; 343 int s; 344 345 #ifdef DEBUG 346 if (si_debug & 2) { 347 printf("si_dma_start: sr=0x%x\n", sr); 348 } 349 #endif 350 351 /* This MAY be time critical (not sure). */ 352 s = splhigh(); 353 354 /* Finally, give the UDC a "start chain" command. */ 355 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN); 356 357 /* 358 * Acknowledge the phase change. (After DMA setup!) 359 * Put the SBIC into DMA mode, and start the transfer. 360 */ 361 if (dh->dh_flags & SIDH_OUT) { 362 *ncr_sc->sci_tcmd = PHASE_DATA_OUT; 363 SCI_CLR_INTR(ncr_sc); 364 *ncr_sc->sci_icmd = SCI_ICMD_DATA; 365 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 366 *ncr_sc->sci_dma_send = 0; /* start it */ 367 } else { 368 *ncr_sc->sci_tcmd = PHASE_DATA_IN; 369 SCI_CLR_INTR(ncr_sc); 370 *ncr_sc->sci_icmd = 0; 371 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 372 *ncr_sc->sci_irecv = 0; /* start it */ 373 } 374 375 splx(s); 376 ncr_sc->sc_state |= NCR_DOINGDMA; 377 378 #ifdef DEBUG 379 if (si_debug & 2) { 380 printf("si_dma_start: started, flags=0x%x\n", 381 ncr_sc->sc_state); 382 } 383 #endif 384 } 385 386 387 void 388 si_obio_dma_eop(ncr_sc) 389 struct ncr5380_softc *ncr_sc; 390 { 391 392 /* Not needed - DMA was stopped prior to examining sci_csr */ 393 } 394 395 396 void 397 si_obio_dma_stop(ncr_sc) 398 struct ncr5380_softc *ncr_sc; 399 { 400 struct si_softc *sc = (struct si_softc *)ncr_sc; 401 struct sci_req *sr = ncr_sc->sc_current; 402 struct si_dma_handle *dh = sr->sr_dma_hand; 403 volatile struct si_regs *si = sc->sc_regs; 404 int resid, ntrans, tmo, udc_cnt; 405 406 if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) { 407 #ifdef DEBUG 408 printf("si_dma_stop: dma not running\n"); 409 #endif 410 return; 411 } 412 ncr_sc->sc_state &= ~NCR_DOINGDMA; 413 414 NCR_TRACE("si_dma_stop: top, csr=0x%x\n", si->si_csr); 415 416 /* OK, have either phase mis-match or end of DMA. */ 417 /* Set an impossible phase to prevent data movement? */ 418 *ncr_sc->sci_tcmd = PHASE_INVALID; 419 420 /* Check for DMA errors. */ 421 if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) { 422 printf("si: DMA error, csr=0x%x, reset\n", si->si_csr); 423 sr->sr_xs->error = XS_DRIVER_STUFFUP; 424 ncr_sc->sc_state |= NCR_ABORTING; 425 si_reset_adapter(ncr_sc); 426 goto out; 427 } 428 429 /* Note that timeout may have set the error flag. */ 430 if (ncr_sc->sc_state & NCR_ABORTING) 431 goto out; 432 433 /* 434 * After a read, wait for the FIFO to empty. 435 * Note: this only works on the OBIO version. 436 */ 437 if ((dh->dh_flags & SIDH_OUT) == 0) { 438 tmo = 200000; /* X10 = 2 sec. */ 439 for (;;) { 440 if (si->si_csr & SI_CSR_FIFO_EMPTY) 441 break; 442 if (--tmo <= 0) { 443 printf("si: dma fifo did not empty, reset\n"); 444 ncr_sc->sc_state |= NCR_ABORTING; 445 /* si_reset_adapter(ncr_sc); */ 446 goto out; 447 } 448 delay(10); 449 } 450 } 451 452 /* 453 * Now try to figure out how much actually transferred 454 * The fifo_count might not reflect how many bytes were 455 * actually transferred. 456 */ 457 resid = si->fifo_count & 0xFFFF; 458 ntrans = sc->sc_reqlen - resid; 459 460 #ifdef DEBUG 461 if (si_debug & 2) { 462 printf("si_dma_stop: resid=0x%x ntrans=0x%x\n", 463 resid, ntrans); 464 } 465 #endif 466 467 /* XXX: Treat (ntrans==0) as a special, non-error case? */ 468 if (ntrans < MIN_DMA_LEN) { 469 printf("si: fifo count: 0x%x\n", resid); 470 ncr_sc->sc_state |= NCR_ABORTING; 471 goto out; 472 } 473 if (ntrans > ncr_sc->sc_datalen) 474 panic("si_dma_stop: excess transfer"); 475 476 /* Adjust data pointer */ 477 ncr_sc->sc_dataptr += ntrans; 478 ncr_sc->sc_datalen -= ntrans; 479 480 /* 481 * After a read, we may need to clean-up 482 * "Left-over bytes" (yuck!) 483 */ 484 if ((dh->dh_flags & SIDH_OUT) == 0) { 485 /* If odd transfer count, grab last byte by hand. */ 486 if (ntrans & 1) { 487 NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n", 488 (int) ncr_sc->sc_dataptr - 1); 489 ncr_sc->sc_dataptr[-1] = 490 (si->fifo_data & 0xff00) >> 8; 491 goto out; 492 } 493 /* UDC might not have transfered the last word. */ 494 udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT); 495 if (((udc_cnt * 2) - resid) == 2) { 496 NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n", 497 (int) ncr_sc->sc_dataptr - 2); 498 ncr_sc->sc_dataptr[-2] = 499 (si->fifo_data & 0xff00) >> 8; 500 ncr_sc->sc_dataptr[-1] = 501 (si->fifo_data & 0x00ff); 502 } 503 } 504 505 out: 506 /* Reset the UDC. */ 507 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 508 si->fifo_count = 0; 509 si->si_csr &= ~SI_CSR_SEND; 510 511 /* Reset the FIFO */ 512 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 513 si->si_csr |= SI_CSR_FIFO_RES; 514 515 /* Put SBIC back in PIO mode. */ 516 /* XXX: set tcmd to PHASE_INVALID? */ 517 *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE); 518 *ncr_sc->sci_icmd = 0; 519 } 520 521