1 /* $NetBSD: esp.c,v 1.30 2001/11/18 05:22:32 briggs Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Jason R. Thorpe. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Jason R. Thorpe. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 1994 Peter Galbavy 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by Peter Galbavy 49 * 4. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 54 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 55 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 56 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 57 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 58 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 60 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 61 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 62 * POSSIBILITY OF SUCH DAMAGE. 63 */ 64 65 /* 66 * Based on aic6360 by Jarle Greipsland 67 * 68 * Acknowledgements: Many of the algorithms used in this driver are 69 * inspired by the work of Julian Elischer (julian@tfs.com) and 70 * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million! 71 */ 72 73 /* 74 * Initial m68k mac support from Allen Briggs <briggs@macbsd.com> 75 * (basically consisting of the match, a bit of the attach, and the 76 * "DMA" glue functions). 77 */ 78 79 #include <sys/types.h> 80 #include <sys/param.h> 81 #include <sys/systm.h> 82 #include <sys/kernel.h> 83 #include <sys/errno.h> 84 #include <sys/ioctl.h> 85 #include <sys/device.h> 86 #include <sys/buf.h> 87 #include <sys/proc.h> 88 #include <sys/user.h> 89 #include <sys/queue.h> 90 91 #include <dev/scsipi/scsi_all.h> 92 #include <dev/scsipi/scsipi_all.h> 93 #include <dev/scsipi/scsiconf.h> 94 #include <dev/scsipi/scsi_message.h> 95 96 #include <machine/cpu.h> 97 #include <machine/bus.h> 98 #include <machine/param.h> 99 100 #include <dev/ic/ncr53c9xreg.h> 101 #include <dev/ic/ncr53c9xvar.h> 102 103 #include <machine/viareg.h> 104 105 #include <mac68k/obio/espvar.h> 106 #include <mac68k/obio/obiovar.h> 107 108 void espattach __P((struct device *, struct device *, void *)); 109 int espmatch __P((struct device *, struct cfdata *, void *)); 110 111 /* Linkup to the rest of the kernel */ 112 struct cfattach esp_ca = { 113 sizeof(struct esp_softc), espmatch, espattach 114 }; 115 116 /* 117 * Functions and the switch for the MI code. 118 */ 119 u_char esp_read_reg __P((struct ncr53c9x_softc *, int)); 120 void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char)); 121 int esp_dma_isintr __P((struct ncr53c9x_softc *)); 122 void esp_dma_reset __P((struct ncr53c9x_softc *)); 123 int esp_dma_intr __P((struct ncr53c9x_softc *)); 124 int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *, 125 size_t *, int, size_t *)); 126 void esp_dma_go __P((struct ncr53c9x_softc *)); 127 void esp_dma_stop __P((struct ncr53c9x_softc *)); 128 int esp_dma_isactive __P((struct ncr53c9x_softc *)); 129 void esp_quick_write_reg __P((struct ncr53c9x_softc *, int, u_char)); 130 int esp_quick_dma_intr __P((struct ncr53c9x_softc *)); 131 int esp_quick_dma_setup __P((struct ncr53c9x_softc *, caddr_t *, 132 size_t *, int, size_t *)); 133 void esp_quick_dma_go __P((struct ncr53c9x_softc *)); 134 135 void esp_intr __P((void *sc)); 136 void esp_dualbus_intr __P((void *sc)); 137 static struct esp_softc *esp0 = NULL, *esp1 = NULL; 138 139 static __inline__ int esp_dafb_have_dreq __P((struct esp_softc *esc)); 140 static __inline__ int esp_iosb_have_dreq __P((struct esp_softc *esc)); 141 int (*esp_have_dreq) __P((struct esp_softc *esc)); 142 143 struct ncr53c9x_glue esp_glue = { 144 esp_read_reg, 145 esp_write_reg, 146 esp_dma_isintr, 147 esp_dma_reset, 148 esp_dma_intr, 149 esp_dma_setup, 150 esp_dma_go, 151 esp_dma_stop, 152 esp_dma_isactive, 153 NULL, /* gl_clear_latched_intr */ 154 }; 155 156 int 157 espmatch(parent, cf, aux) 158 struct device *parent; 159 struct cfdata *cf; 160 void *aux; 161 { 162 int found = 0; 163 164 if ((cf->cf_unit == 0) && mac68k_machine.scsi96) { 165 found = 1; 166 } 167 if ((cf->cf_unit == 1) && mac68k_machine.scsi96_2) { 168 found = 1; 169 } 170 171 return found; 172 } 173 174 /* 175 * Attach this instance, and then all the sub-devices 176 */ 177 void 178 espattach(parent, self, aux) 179 struct device *parent, *self; 180 void *aux; 181 { 182 struct obio_attach_args *oa = (struct obio_attach_args *)aux; 183 extern vaddr_t SCSIBase; 184 struct esp_softc *esc = (void *)self; 185 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 186 int quick = 0; 187 unsigned long reg_offset; 188 189 reg_offset = SCSIBase - IOBase; 190 esc->sc_tag = oa->oa_tag; 191 /* 192 * For Wombat, Primus and Optimus motherboards, DREQ is 193 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and 194 * the scsi registers are offset 0x1000 bytes from IOBase). 195 * 196 * For the Q700/900/950 it's at f9800024 for bus 0 and 197 * f9800028 for bus 1 (900/950). For these machines, that is also 198 * a (12-bit) configuration register for DAFB's control of the 199 * pseudo-DMA timing. The default value is 0x1d1. 200 */ 201 esp_have_dreq = esp_dafb_have_dreq; 202 if (sc->sc_dev.dv_unit == 0) { 203 if (reg_offset == 0x10000) { 204 quick = 1; 205 esp_have_dreq = esp_iosb_have_dreq; 206 } else if (reg_offset == 0x18000) { 207 quick = 0; 208 } else { 209 if (bus_space_map(esc->sc_tag, 0xf9800024, 210 4, 0, &esc->sc_bsh)) { 211 printf("failed to map 4 at 0xf9800024.\n"); 212 } else { 213 quick = 1; 214 bus_space_write_4(esc->sc_tag, 215 esc->sc_bsh, 0, 0x1d1); 216 } 217 } 218 } else { 219 if (bus_space_map(esc->sc_tag, 0xf9800028, 220 4, 0, &esc->sc_bsh)) { 221 printf("failed to map 4 at 0xf9800028.\n"); 222 } else { 223 quick = 1; 224 bus_space_write_4(esc->sc_tag, esc->sc_bsh, 0, 0x1d1); 225 } 226 } 227 if (quick) { 228 esp_glue.gl_write_reg = esp_quick_write_reg; 229 esp_glue.gl_dma_intr = esp_quick_dma_intr; 230 esp_glue.gl_dma_setup = esp_quick_dma_setup; 231 esp_glue.gl_dma_go = esp_quick_dma_go; 232 } 233 234 /* 235 * Set up the glue for MI code early; we use some of it here. 236 */ 237 sc->sc_glue = &esp_glue; 238 239 /* 240 * Save the regs 241 */ 242 if (sc->sc_dev.dv_unit == 0) { 243 esp0 = esc; 244 245 esc->sc_reg = (volatile u_char *) SCSIBase; 246 via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc); 247 esc->irq_mask = V2IF_SCSIIRQ; 248 if (reg_offset == 0x10000) { 249 /* From the Q650 developer's note */ 250 sc->sc_freq = 16500000; 251 } else { 252 sc->sc_freq = 25000000; 253 } 254 255 if (esp_glue.gl_dma_go == esp_quick_dma_go) { 256 printf(" (quick)"); 257 } 258 } else { 259 esp1 = esc; 260 261 esc->sc_reg = (volatile u_char *) SCSIBase + 0x402; 262 via2_register_irq(VIA2_SCSIIRQ, esp_dualbus_intr, NULL); 263 esc->irq_mask = 0; 264 sc->sc_freq = 25000000; 265 266 if (esp_glue.gl_dma_go == esp_quick_dma_go) { 267 printf(" (quick)"); 268 } 269 } 270 271 printf(": address %p", esc->sc_reg); 272 273 sc->sc_id = 7; 274 275 /* gimme Mhz */ 276 sc->sc_freq /= 1000000; 277 278 /* 279 * It is necessary to try to load the 2nd config register here, 280 * to find out what rev the esp chip is, else the esp_reset 281 * will not set up the defaults correctly. 282 */ 283 sc->sc_cfg1 = sc->sc_id; /* | NCRCFG1_PARENB; */ 284 sc->sc_cfg2 = NCRCFG2_SCSI2; 285 sc->sc_cfg3 = 0; 286 sc->sc_rev = NCR_VARIANT_NCR53C96; 287 288 /* 289 * This is the value used to start sync negotiations 290 * Note that the NCR register "SYNCTP" is programmed 291 * in "clocks per byte", and has a minimum value of 4. 292 * The SCSI period used in negotiation is one-fourth 293 * of the time (in nanoseconds) needed to transfer one byte. 294 * Since the chip's clock is given in MHz, we have the following 295 * formula: 4 * period = (1000 / freq) * 4 296 */ 297 sc->sc_minsync = 1000 / sc->sc_freq; 298 299 /* We need this to fit into the TCR... */ 300 sc->sc_maxxfer = 64 * 1024; 301 302 if (!quick) { 303 sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */ 304 sc->sc_maxxfer = 8 * 1024; 305 } 306 307 /* 308 * Configure interrupts. 309 */ 310 if (esc->irq_mask) { 311 via2_reg(vPCR) = 0x22; 312 via2_reg(vIFR) = esc->irq_mask; 313 via2_reg(vIER) = 0x80 | esc->irq_mask; 314 } 315 316 /* 317 * Now try to attach all the sub-devices 318 */ 319 sc->sc_adapter.adapt_minphys = minphys; 320 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 321 ncr53c9x_attach(sc); 322 } 323 324 /* 325 * Glue functions. 326 */ 327 328 u_char 329 esp_read_reg(sc, reg) 330 struct ncr53c9x_softc *sc; 331 int reg; 332 { 333 struct esp_softc *esc = (struct esp_softc *)sc; 334 335 return esc->sc_reg[reg * 16]; 336 } 337 338 void 339 esp_write_reg(sc, reg, val) 340 struct ncr53c9x_softc *sc; 341 int reg; 342 u_char val; 343 { 344 struct esp_softc *esc = (struct esp_softc *)sc; 345 u_char v = val; 346 347 if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) { 348 v = NCRCMD_TRANS; 349 } 350 esc->sc_reg[reg * 16] = v; 351 } 352 353 void 354 esp_dma_stop(sc) 355 struct ncr53c9x_softc *sc; 356 { 357 } 358 359 int 360 esp_dma_isactive(sc) 361 struct ncr53c9x_softc *sc; 362 { 363 struct esp_softc *esc = (struct esp_softc *)sc; 364 365 return esc->sc_active; 366 } 367 368 int 369 esp_dma_isintr(sc) 370 struct ncr53c9x_softc *sc; 371 { 372 struct esp_softc *esc = (struct esp_softc *)sc; 373 374 return esc->sc_reg[NCR_STAT * 16] & 0x80; 375 } 376 377 void 378 esp_dma_reset(sc) 379 struct ncr53c9x_softc *sc; 380 { 381 struct esp_softc *esc = (struct esp_softc *)sc; 382 383 esc->sc_active = 0; 384 esc->sc_tc = 0; 385 } 386 387 int 388 esp_dma_intr(sc) 389 struct ncr53c9x_softc *sc; 390 { 391 struct esp_softc *esc = (struct esp_softc *)sc; 392 volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg; 393 u_char *p; 394 u_int espphase, espstat, espintr; 395 int cnt, s; 396 397 if (esc->sc_active == 0) { 398 printf("dma_intr--inactive DMA\n"); 399 return -1; 400 } 401 402 if ((sc->sc_espintr & NCRINTR_BS) == 0) { 403 esc->sc_active = 0; 404 return 0; 405 } 406 407 cnt = *esc->sc_dmalen; 408 if (*esc->sc_dmalen == 0) { 409 printf("data interrupt, but no count left."); 410 } 411 412 p = *esc->sc_dmaaddr; 413 espphase = sc->sc_phase; 414 espstat = (u_int) sc->sc_espstat; 415 espintr = (u_int) sc->sc_espintr; 416 cmdreg = esc->sc_reg + NCR_CMD * 16; 417 fiforeg = esc->sc_reg + NCR_FIFO * 16; 418 statreg = esc->sc_reg + NCR_STAT * 16; 419 intrreg = esc->sc_reg + NCR_INTR * 16; 420 do { 421 if (esc->sc_datain) { 422 *p++ = *fiforeg; 423 cnt--; 424 if (espphase == DATA_IN_PHASE) { 425 *cmdreg = NCRCMD_TRANS; 426 } else { 427 esc->sc_active = 0; 428 } 429 } else { 430 if ( (espphase == DATA_OUT_PHASE) 431 || (espphase == MESSAGE_OUT_PHASE)) { 432 *fiforeg = *p++; 433 cnt--; 434 *cmdreg = NCRCMD_TRANS; 435 } else { 436 esc->sc_active = 0; 437 } 438 } 439 440 if (esc->sc_active) { 441 while (!(*statreg & 0x80)); 442 s = splhigh(); 443 espstat = *statreg; 444 espintr = *intrreg; 445 espphase = (espintr & NCRINTR_DIS) 446 ? /* Disconnected */ BUSFREE_PHASE 447 : espstat & PHASE_MASK; 448 splx(s); 449 } 450 } while (esc->sc_active && (espintr & NCRINTR_BS)); 451 sc->sc_phase = espphase; 452 sc->sc_espstat = (u_char) espstat; 453 sc->sc_espintr = (u_char) espintr; 454 *esc->sc_dmaaddr = p; 455 *esc->sc_dmalen = cnt; 456 457 if (*esc->sc_dmalen == 0) { 458 esc->sc_tc = NCRSTAT_TC; 459 } 460 sc->sc_espstat |= esc->sc_tc; 461 return 0; 462 } 463 464 int 465 esp_dma_setup(sc, addr, len, datain, dmasize) 466 struct ncr53c9x_softc *sc; 467 caddr_t *addr; 468 size_t *len; 469 int datain; 470 size_t *dmasize; 471 { 472 struct esp_softc *esc = (struct esp_softc *)sc; 473 474 esc->sc_dmaaddr = addr; 475 esc->sc_dmalen = len; 476 esc->sc_datain = datain; 477 esc->sc_dmasize = *dmasize; 478 esc->sc_tc = 0; 479 480 return 0; 481 } 482 483 void 484 esp_dma_go(sc) 485 struct ncr53c9x_softc *sc; 486 { 487 struct esp_softc *esc = (struct esp_softc *)sc; 488 489 if (esc->sc_datain == 0) { 490 esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr; 491 (*esc->sc_dmalen)--; 492 (*esc->sc_dmaaddr)++; 493 } 494 esc->sc_active = 1; 495 } 496 497 void 498 esp_quick_write_reg(sc, reg, val) 499 struct ncr53c9x_softc *sc; 500 int reg; 501 u_char val; 502 { 503 struct esp_softc *esc = (struct esp_softc *)sc; 504 505 esc->sc_reg[reg * 16] = val; 506 } 507 508 #if DEBUG 509 int mac68k_esp_debug=0; 510 #endif 511 512 int 513 esp_quick_dma_intr(sc) 514 struct ncr53c9x_softc *sc; 515 { 516 struct esp_softc *esc = (struct esp_softc *)sc; 517 int trans=0, resid=0; 518 519 if (esc->sc_active == 0) 520 panic("dma_intr--inactive DMA\n"); 521 522 esc->sc_active = 0; 523 524 if (esc->sc_dmasize == 0) { 525 int res; 526 527 res = NCR_READ_REG(sc, NCR_TCL); 528 res += NCR_READ_REG(sc, NCR_TCM) << 8; 529 /* This can happen in the case of a TRPAD operation */ 530 /* Pretend that it was complete */ 531 sc->sc_espstat |= NCRSTAT_TC; 532 #if DEBUG 533 if (mac68k_esp_debug) { 534 printf("dmaintr: DMA xfer of zero xferred %d\n", 535 65536 - res); 536 } 537 #endif 538 return 0; 539 } 540 541 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 542 if (esc->sc_datain == 0) { 543 resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f; 544 #if DEBUG 545 if (mac68k_esp_debug) { 546 printf("Write FIFO residual %d bytes\n", resid); 547 } 548 #endif 549 } 550 resid += NCR_READ_REG(sc, NCR_TCL); 551 resid += NCR_READ_REG(sc, NCR_TCM) << 8; 552 if (resid == 0) 553 resid = 65536; 554 } 555 556 trans = esc->sc_dmasize - resid; 557 if (trans < 0) { 558 printf("dmaintr: trans < 0????"); 559 trans = *esc->sc_dmalen; 560 } 561 562 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid)); 563 #if DEBUG 564 if (mac68k_esp_debug) { 565 printf("eqd_intr: trans %d, resid %d.\n", trans, resid); 566 } 567 #endif 568 *esc->sc_dmaaddr += trans; 569 *esc->sc_dmalen -= trans; 570 571 return 0; 572 } 573 574 int 575 esp_quick_dma_setup(sc, addr, len, datain, dmasize) 576 struct ncr53c9x_softc *sc; 577 caddr_t *addr; 578 size_t *len; 579 int datain; 580 size_t *dmasize; 581 { 582 struct esp_softc *esc = (struct esp_softc *)sc; 583 584 esc->sc_dmaaddr = addr; 585 esc->sc_dmalen = len; 586 587 if (*len & 1) { 588 esc->sc_pad = 1; 589 } else { 590 esc->sc_pad = 0; 591 } 592 593 esc->sc_datain = datain; 594 esc->sc_dmasize = *dmasize; 595 596 #if DIAGNOSTIC 597 if (esc->sc_dmasize == 0) { 598 /* This can happen in the case of a TRPAD operation */ 599 } 600 #endif 601 #if DEBUG 602 if (mac68k_esp_debug) { 603 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n", 604 (long) *addr, (long) *len, datain, (long) esc->sc_dmasize); 605 } 606 #endif 607 608 return 0; 609 } 610 611 static __inline__ int 612 esp_dafb_have_dreq(esc) 613 struct esp_softc *esc; 614 { 615 return (*(volatile u_int32_t *)(esc->sc_bsh.base) & 0x200); 616 } 617 618 static __inline__ int 619 esp_iosb_have_dreq(esc) 620 struct esp_softc *esc; 621 { 622 return (via2_reg(vIFR) & V2IF_SCSIDRQ); 623 } 624 625 static volatile int espspl=-1; 626 627 /* 628 * Apple "DMA" is weird. 629 * 630 * Basically, the CPU acts like the DMA controller. The DREQ/ off the 631 * chip goes to a register that we've mapped at attach time (on the 632 * IOSB or DAFB, depending on the machine). Apple also provides some 633 * space for which the memory controller handshakes data to/from the 634 * NCR chip with the DACK/ line. This space appears to be mapped over 635 * and over, every 4 bytes, but only the lower 16 bits are valid (but 636 * reading the upper 16 bits will handshake DACK/ just fine, so if you 637 * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get 638 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff... 639 * 640 * When you're attempting to read or write memory to this DACK/ed space, 641 * and the NCR is not ready for some timeout period, the system will 642 * generate a bus error. This might be for one of several reasons: 643 * 644 * 1) (on write) The FIFO is full and is not draining. 645 * 2) (on read) The FIFO is empty and is not filling. 646 * 3) An interrupt condition has occurred. 647 * 4) Anything else? 648 * 649 * So if a bus error occurs, we first turn off the nofault bus error handler, 650 * then we check for an interrupt (which would render the first two 651 * possibilities moot). If there's no interrupt, check for a DREQ/. If we 652 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If 653 * neither condition holds, pause briefly and check again. 654 * 655 * NOTE!!! In order to make allowances for the hardware structure of 656 * the mac, spl values in here are hardcoded!!!!!!!!! 657 * This is done to allow serial interrupts to get in during 658 * scsi transfers. This is ugly. 659 */ 660 void 661 esp_quick_dma_go(sc) 662 struct ncr53c9x_softc *sc; 663 { 664 struct esp_softc *esc = (struct esp_softc *)sc; 665 extern long mac68k_a2_fromfault; 666 extern int *nofault; 667 label_t faultbuf; 668 u_int16_t volatile *pdma; 669 u_int16_t *addr; 670 int len, res; 671 u_short cnt32, cnt2; 672 u_char volatile *statreg; 673 674 esc->sc_active = 1; 675 676 espspl = splhigh(); 677 678 addr = (u_int16_t *) *esc->sc_dmaaddr; 679 len = esc->sc_dmasize; 680 681 restart_dmago: 682 #if DEBUG 683 if (mac68k_esp_debug) { 684 printf("eqdg: a %lx, l %lx, in? %d ... ", 685 (long) addr, (long) len, esc->sc_datain); 686 } 687 #endif 688 nofault = (int *) &faultbuf; 689 if (setjmp((label_t *) nofault)) { 690 int i=0; 691 692 nofault = (int *) 0; 693 #if DEBUG 694 if (mac68k_esp_debug) { 695 printf("be\n"); 696 } 697 #endif 698 /* 699 * Bus error... 700 * So, we first check for an interrupt. If we have 701 * one, go handle it. Next we check for DREQ/. If 702 * we have it, then we restart the transfer. If 703 * neither, then loop until we get one or the other. 704 */ 705 statreg = esc->sc_reg + NCR_STAT * 16; 706 for (;;) { 707 spl2(); /* Give serial a chance... */ 708 splhigh(); /* That's enough... */ 709 710 if (*statreg & 0x80) { 711 goto gotintr; 712 } 713 714 if (esp_have_dreq(esc)) { 715 /* 716 * Get the remaining length from the address 717 * differential. 718 */ 719 addr = (u_int16_t *) mac68k_a2_fromfault; 720 len = esc->sc_dmasize - 721 ((long) addr - (long) *esc->sc_dmaaddr); 722 723 if (esc->sc_datain == 0) { 724 /* 725 * Let the FIFO drain before we read 726 * the transfer count. 727 * Do we need to do this? 728 * Can we do this? 729 */ 730 while (NCR_READ_REG(sc, NCR_FFLAG) 731 & 0x1f); 732 /* 733 * Get the length from the transfer 734 * counters. 735 */ 736 res = NCR_READ_REG(sc, NCR_TCL); 737 res += NCR_READ_REG(sc, NCR_TCM) << 8; 738 /* 739 * If they don't agree, 740 * adjust accordingly. 741 */ 742 while (res > len) { 743 len+=2; addr--; 744 } 745 if (res != len) { 746 panic("esp_quick_dma_go: res %d != len %d\n", 747 res, len); 748 } 749 } 750 break; 751 } 752 753 DELAY(1); 754 if (i++ > 1000000) 755 panic("esp_dma_go: Bus error, but no condition! Argh!"); 756 } 757 goto restart_dmago; 758 } 759 760 len &= ~1; 761 762 statreg = esc->sc_reg + NCR_STAT * 16; 763 pdma = (u_int16_t *) (esc->sc_reg + 0x100); 764 765 /* 766 * These loops are unrolled into assembly for two reasons: 767 * 1) We can make sure that they are as efficient as possible, and 768 * 2) (more importantly) we need the address that we are reading 769 * from or writing to to be in a2. 770 */ 771 cnt32 = len / 32; 772 cnt2 = (len % 32) / 2; 773 if (esc->sc_datain == 0) { 774 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */ 775 /* while (cnt2--) { *pdma = *addr++; } */ 776 __asm __volatile (" 777 movl %1, %%a2 778 movl %2, %%a3 779 movw %3, %%d2 780 cmpw #0, %%d2 781 beq 2f 782 subql #1, %%d2 783 1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 784 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 785 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 786 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 787 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 788 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 789 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 790 movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ 791 movw #8704,%%sr 792 movw #9728,%%sr 793 dbra %%d2, 1b 794 2: movw %4, %%d2 795 cmpw #0, %%d2 796 beq 4f 797 subql #1, %%d2 798 3: movw %%a2@+,%%a3@ 799 dbra %%d2, 3b 800 4: movl %%a2, %0" 801 : "=g" (addr) 802 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 803 : "a2", "a3", "d2"); 804 if (esc->sc_pad) { 805 unsigned char *c; 806 c = (unsigned char *) addr; 807 /* Wait for DREQ */ 808 while (!esp_have_dreq(esc)) { 809 if (*statreg & 0x80) { 810 nofault = (int *) 0; 811 goto gotintr; 812 } 813 } 814 *(unsigned char *)pdma = *c; 815 } 816 } else { 817 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */ 818 /* while (cnt2--) { *addr++ = *pdma; } */ 819 __asm __volatile (" 820 movl %1, %%a2 821 movl %2, %%a3 822 movw %3, %%d2 823 cmpw #0, %%d2 824 beq 6f 825 subql #1, %%d2 826 5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 827 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 828 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 829 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 830 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 831 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 832 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 833 movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ 834 movw #8704,%%sr 835 movw #9728,%%sr 836 dbra %%d2, 5b 837 6: movw %4, %%d2 838 cmpw #0, %%d2 839 beq 8f 840 subql #1, %%d2 841 7: movw %%a3@,%%a2@+ 842 dbra %%d2, 7b 843 8: movl %%a2, %0" 844 : "=g" (addr) 845 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 846 : "a2", "a3", "d2"); 847 if (esc->sc_pad) { 848 unsigned char *c; 849 c = (unsigned char *) addr; 850 /* Wait for DREQ */ 851 while (!esp_have_dreq(esc)) { 852 if (*statreg & 0x80) { 853 nofault = (int *) 0; 854 goto gotintr; 855 } 856 } 857 *c = *(unsigned char *)pdma; 858 } 859 } 860 861 nofault = (int *) 0; 862 863 /* 864 * If we have not received an interrupt yet, we should shortly, 865 * and we can't prevent it, so return and wait for it. 866 */ 867 if ((*statreg & 0x80) == 0) { 868 #if DEBUG 869 if (mac68k_esp_debug) { 870 printf("g.\n"); 871 } 872 #endif 873 if (espspl != -1) splx(espspl); espspl = -1; 874 return; 875 } 876 877 gotintr: 878 #if DEBUG 879 if (mac68k_esp_debug) { 880 printf("g!\n"); 881 } 882 #endif 883 ncr53c9x_intr(sc); 884 if (espspl != -1) splx(espspl); espspl = -1; 885 } 886 887 void 888 esp_intr(sc) 889 void *sc; 890 { 891 struct esp_softc *esc = (struct esp_softc *)sc; 892 893 if (esc->sc_reg[NCR_STAT * 16] & 0x80) { 894 ncr53c9x_intr((struct ncr53c9x_softc *) esp0); 895 } 896 } 897 898 void 899 esp_dualbus_intr(sc) 900 void *sc; 901 { 902 if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) { 903 ncr53c9x_intr((struct ncr53c9x_softc *) esp0); 904 } 905 906 if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) { 907 ncr53c9x_intr((struct ncr53c9x_softc *) esp1); 908 } 909 } 910