1 /* $NetBSD: esp.c,v 1.55 2012/02/18 23:51:27 rmind 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/cdefs.h> 80 __KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.55 2012/02/18 23:51:27 rmind Exp $"); 81 82 #include <sys/types.h> 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/kernel.h> 86 #include <sys/errno.h> 87 #include <sys/ioctl.h> 88 #include <sys/device.h> 89 #include <sys/buf.h> 90 #include <sys/proc.h> 91 #include <sys/queue.h> 92 #include <sys/mutex.h> 93 94 #include <dev/scsipi/scsi_all.h> 95 #include <dev/scsipi/scsipi_all.h> 96 #include <dev/scsipi/scsiconf.h> 97 #include <dev/scsipi/scsi_message.h> 98 99 #include <machine/cpu.h> 100 #include <machine/bus.h> 101 #include <machine/param.h> 102 103 #include <dev/ic/ncr53c9xreg.h> 104 #include <dev/ic/ncr53c9xvar.h> 105 106 #include <machine/viareg.h> 107 108 #include <mac68k/obio/espvar.h> 109 #include <mac68k/obio/obiovar.h> 110 111 int espmatch(device_t, cfdata_t, void *); 112 void espattach(device_t, device_t, void *); 113 114 /* Linkup to the rest of the kernel */ 115 CFATTACH_DECL_NEW(esp, sizeof(struct esp_softc), 116 espmatch, espattach, NULL, NULL); 117 118 /* 119 * Functions and the switch for the MI code. 120 */ 121 uint8_t esp_read_reg(struct ncr53c9x_softc *, int); 122 void esp_write_reg(struct ncr53c9x_softc *, int, uint8_t); 123 int esp_dma_isintr(struct ncr53c9x_softc *); 124 void esp_dma_reset(struct ncr53c9x_softc *); 125 int esp_dma_intr(struct ncr53c9x_softc *); 126 int esp_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *, int, 127 size_t *); 128 void esp_dma_go(struct ncr53c9x_softc *); 129 void esp_dma_stop(struct ncr53c9x_softc *); 130 int esp_dma_isactive(struct ncr53c9x_softc *); 131 void esp_quick_write_reg(struct ncr53c9x_softc *, int, u_char); 132 int esp_quick_dma_intr(struct ncr53c9x_softc *); 133 int esp_quick_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *, int, 134 size_t *); 135 void esp_quick_dma_go(struct ncr53c9x_softc *); 136 137 void esp_intr(void *); 138 void esp_dualbus_intr(void *); 139 static struct esp_softc *esp0, *esp1; 140 141 static inline int esp_dafb_have_dreq(struct esp_softc *); 142 static inline int esp_iosb_have_dreq(struct esp_softc *); 143 int (*esp_have_dreq)(struct esp_softc *); 144 145 struct ncr53c9x_glue esp_glue = { 146 esp_read_reg, 147 esp_write_reg, 148 esp_dma_isintr, 149 esp_dma_reset, 150 esp_dma_intr, 151 esp_dma_setup, 152 esp_dma_go, 153 esp_dma_stop, 154 esp_dma_isactive, 155 NULL, /* gl_clear_latched_intr */ 156 }; 157 158 int 159 espmatch(device_t parent, cfdata_t cf, void *aux) 160 { 161 struct obio_attach_args *oa = aux; 162 163 if (oa->oa_addr == 0 && mac68k_machine.scsi96) { 164 return 1; 165 } 166 if (oa->oa_addr == 1 && mac68k_machine.scsi96_2) { 167 return 1; 168 } 169 return 0; 170 } 171 172 /* 173 * Attach this instance, and then all the sub-devices 174 */ 175 void 176 espattach(device_t parent, device_t self, void *aux) 177 { 178 struct esp_softc *esc = device_private(self); 179 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 180 struct obio_attach_args *oa = aux; 181 int quick = 0; 182 unsigned long reg_offset; 183 extern vaddr_t SCSIBase; 184 185 sc->sc_dev = self; 186 187 reg_offset = SCSIBase - IOBase; 188 esc->sc_tag = oa->oa_tag; 189 190 /* 191 * For Wombat, Primus and Optimus motherboards, DREQ is 192 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and 193 * the scsi registers are offset 0x1000 bytes from IOBase). 194 * 195 * For the Q700/900/950 it's at f9800024 for bus 0 and 196 * f9800028 for bus 1 (900/950). For these machines, that is also 197 * a (12-bit) configuration register for DAFB's control of the 198 * pseudo-DMA timing. The default value is 0x1d1. 199 */ 200 esp_have_dreq = esp_dafb_have_dreq; 201 if (oa->oa_addr == 0) { 202 if (reg_offset == 0x10000) { 203 quick = 1; 204 esp_have_dreq = esp_iosb_have_dreq; 205 } else if (reg_offset == 0x18000) { 206 quick = 0; 207 } else { 208 if (bus_space_map(esc->sc_tag, 0xf9800024, 209 4, 0, &esc->sc_bsh)) { 210 aprint_error(": failed to map 4" 211 " 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 aprint_error(": 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 (oa->oa_addr == 0) { 243 esp0 = esc; 244 245 esc->sc_reg = (volatile uint8_t *)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 aprint_normal(" (quick)"); 257 } 258 } else { 259 esp1 = esc; 260 261 esc->sc_reg = (volatile uint8_t *)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 aprint_normal(": 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 switch (current_mac_model->machineid) { 303 case MACH_MACQ630: 304 /* XXX on LC630 64k xfer causes timeout error */ 305 sc->sc_maxxfer = 63 * 1024; 306 break; 307 } 308 309 if (!quick) { 310 sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */ 311 sc->sc_maxxfer = 8 * 1024; 312 } 313 314 /* 315 * Configure interrupts. 316 */ 317 if (esc->irq_mask) { 318 via2_reg(vPCR) = 0x22; 319 via2_reg(vIFR) = esc->irq_mask; 320 via2_reg(vIER) = 0x80 | esc->irq_mask; 321 } 322 323 /* 324 * Now try to attach all the sub-devices 325 */ 326 sc->sc_adapter.adapt_minphys = minphys; 327 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 328 ncr53c9x_attach(sc); 329 } 330 331 /* 332 * Glue functions. 333 */ 334 335 uint8_t 336 esp_read_reg(struct ncr53c9x_softc *sc, int reg) 337 { 338 struct esp_softc *esc = (struct esp_softc *)sc; 339 340 return esc->sc_reg[reg * 16]; 341 } 342 343 void 344 esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val) 345 { 346 struct esp_softc *esc = (struct esp_softc *)sc; 347 uint8_t v = val; 348 349 if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) { 350 v = NCRCMD_TRANS; 351 } 352 esc->sc_reg[reg * 16] = v; 353 } 354 355 void 356 esp_dma_stop(struct ncr53c9x_softc *sc) 357 { 358 } 359 360 int 361 esp_dma_isactive(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(struct ncr53c9x_softc *sc) 370 { 371 struct esp_softc *esc = (struct esp_softc *)sc; 372 373 return esc->sc_reg[NCR_STAT * 16] & 0x80; 374 } 375 376 void 377 esp_dma_reset(struct ncr53c9x_softc *sc) 378 { 379 struct esp_softc *esc = (struct esp_softc *)sc; 380 381 esc->sc_active = 0; 382 esc->sc_tc = 0; 383 } 384 385 int 386 esp_dma_intr(struct ncr53c9x_softc *sc) 387 { 388 struct esp_softc *esc = (struct esp_softc *)sc; 389 volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg; 390 uint8_t *p; 391 u_int espphase, espstat, espintr; 392 int cnt, s; 393 394 if (esc->sc_active == 0) { 395 printf("dma_intr--inactive DMA\n"); 396 return -1; 397 } 398 399 if ((sc->sc_espintr & NCRINTR_BS) == 0) { 400 esc->sc_active = 0; 401 return 0; 402 } 403 404 cnt = *esc->sc_dmalen; 405 if (*esc->sc_dmalen == 0) { 406 printf("data interrupt, but no count left."); 407 } 408 409 p = *esc->sc_dmaaddr; 410 espphase = sc->sc_phase; 411 espstat = (u_int)sc->sc_espstat; 412 espintr = (u_int)sc->sc_espintr; 413 cmdreg = esc->sc_reg + NCR_CMD * 16; 414 fiforeg = esc->sc_reg + NCR_FIFO * 16; 415 statreg = esc->sc_reg + NCR_STAT * 16; 416 intrreg = esc->sc_reg + NCR_INTR * 16; 417 do { 418 if (esc->sc_datain) { 419 *p++ = *fiforeg; 420 cnt--; 421 if (espphase == DATA_IN_PHASE) { 422 *cmdreg = NCRCMD_TRANS; 423 } else { 424 esc->sc_active = 0; 425 } 426 } else { 427 if ( (espphase == DATA_OUT_PHASE) 428 || (espphase == MESSAGE_OUT_PHASE)) { 429 *fiforeg = *p++; 430 cnt--; 431 *cmdreg = NCRCMD_TRANS; 432 } else { 433 esc->sc_active = 0; 434 } 435 } 436 437 if (esc->sc_active) { 438 while (!(*statreg & 0x80)); 439 s = splhigh(); 440 espstat = *statreg; 441 espintr = *intrreg; 442 espphase = (espintr & NCRINTR_DIS) 443 ? /* Disconnected */ BUSFREE_PHASE 444 : espstat & PHASE_MASK; 445 splx(s); 446 } 447 } while (esc->sc_active && (espintr & NCRINTR_BS)); 448 sc->sc_phase = espphase; 449 sc->sc_espstat = (u_char)espstat; 450 sc->sc_espintr = (u_char)espintr; 451 *esc->sc_dmaaddr = p; 452 *esc->sc_dmalen = cnt; 453 454 if (*esc->sc_dmalen == 0) { 455 esc->sc_tc = NCRSTAT_TC; 456 } 457 sc->sc_espstat |= esc->sc_tc; 458 return 0; 459 } 460 461 int 462 esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 463 int datain, size_t *dmasize) 464 { 465 struct esp_softc *esc = (struct esp_softc *)sc; 466 467 esc->sc_dmaaddr = addr; 468 esc->sc_dmalen = len; 469 esc->sc_datain = datain; 470 esc->sc_dmasize = *dmasize; 471 esc->sc_tc = 0; 472 473 return 0; 474 } 475 476 void 477 esp_dma_go(struct ncr53c9x_softc *sc) 478 { 479 struct esp_softc *esc = (struct esp_softc *)sc; 480 481 if (esc->sc_datain == 0) { 482 esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr; 483 (*esc->sc_dmalen)--; 484 (*esc->sc_dmaaddr)++; 485 } 486 esc->sc_active = 1; 487 } 488 489 void 490 esp_quick_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val) 491 { 492 struct esp_softc *esc = (struct esp_softc *)sc; 493 494 esc->sc_reg[reg * 16] = val; 495 } 496 497 #if DEBUG 498 int mac68k_esp_debug=0; 499 #endif 500 501 int 502 esp_quick_dma_intr(struct ncr53c9x_softc *sc) 503 { 504 struct esp_softc *esc = (struct esp_softc *)sc; 505 int trans=0, resid=0; 506 507 if (esc->sc_active == 0) 508 panic("dma_intr--inactive DMA"); 509 510 esc->sc_active = 0; 511 512 if (esc->sc_dmasize == 0) { 513 int res; 514 515 res = NCR_READ_REG(sc, NCR_TCL); 516 res += NCR_READ_REG(sc, NCR_TCM) << 8; 517 /* This can happen in the case of a TRPAD operation */ 518 /* Pretend that it was complete */ 519 sc->sc_espstat |= NCRSTAT_TC; 520 #if DEBUG 521 if (mac68k_esp_debug) { 522 printf("dmaintr: DMA xfer of zero xferred %d\n", 523 65536 - res); 524 } 525 #endif 526 return 0; 527 } 528 529 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 530 if (esc->sc_datain == 0) { 531 resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f; 532 #if DEBUG 533 if (mac68k_esp_debug) { 534 printf("Write FIFO residual %d bytes\n", resid); 535 } 536 #endif 537 } 538 resid += NCR_READ_REG(sc, NCR_TCL); 539 resid += NCR_READ_REG(sc, NCR_TCM) << 8; 540 if (resid == 0) 541 resid = 65536; 542 } 543 544 trans = esc->sc_dmasize - resid; 545 if (trans < 0) { 546 printf("dmaintr: trans < 0????"); 547 trans = *esc->sc_dmalen; 548 } 549 550 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid)); 551 #if DEBUG 552 if (mac68k_esp_debug) { 553 printf("eqd_intr: trans %d, resid %d.\n", trans, resid); 554 } 555 #endif 556 *esc->sc_dmaaddr += trans; 557 *esc->sc_dmalen -= trans; 558 559 return 0; 560 } 561 562 int 563 esp_quick_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 564 int datain, size_t *dmasize) 565 { 566 struct esp_softc *esc = (struct esp_softc *)sc; 567 568 esc->sc_dmaaddr = addr; 569 esc->sc_dmalen = len; 570 571 if (*len & 1) { 572 esc->sc_pad = 1; 573 } else { 574 esc->sc_pad = 0; 575 } 576 577 esc->sc_datain = datain; 578 esc->sc_dmasize = *dmasize; 579 580 #if DIAGNOSTIC 581 if (esc->sc_dmasize == 0) { 582 /* This can happen in the case of a TRPAD operation */ 583 } 584 #endif 585 #if DEBUG 586 if (mac68k_esp_debug) { 587 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n", 588 (long) *addr, (long) *len, datain, (long) esc->sc_dmasize); 589 } 590 #endif 591 592 return 0; 593 } 594 595 static inline int 596 esp_dafb_have_dreq(struct esp_softc *esc) 597 { 598 599 return *(volatile uint32_t *)(esc->sc_bsh.base) & 0x200; 600 } 601 602 static inline int 603 esp_iosb_have_dreq(struct esp_softc *esc) 604 { 605 606 return via2_reg(vIFR) & V2IF_SCSIDRQ; 607 } 608 609 static volatile int espspl = -1; 610 611 /* 612 * Apple "DMA" is weird. 613 * 614 * Basically, the CPU acts like the DMA controller. The DREQ/ off the 615 * chip goes to a register that we've mapped at attach time (on the 616 * IOSB or DAFB, depending on the machine). Apple also provides some 617 * space for which the memory controller handshakes data to/from the 618 * NCR chip with the DACK/ line. This space appears to be mapped over 619 * and over, every 4 bytes, but only the lower 16 bits are valid (but 620 * reading the upper 16 bits will handshake DACK/ just fine, so if you 621 * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get 622 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff... 623 * 624 * When you're attempting to read or write memory to this DACK/ed space, 625 * and the NCR is not ready for some timeout period, the system will 626 * generate a bus error. This might be for one of several reasons: 627 * 628 * 1) (on write) The FIFO is full and is not draining. 629 * 2) (on read) The FIFO is empty and is not filling. 630 * 3) An interrupt condition has occurred. 631 * 4) Anything else? 632 * 633 * So if a bus error occurs, we first turn off the nofault bus error handler, 634 * then we check for an interrupt (which would render the first two 635 * possibilities moot). If there's no interrupt, check for a DREQ/. If we 636 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If 637 * neither condition holds, pause briefly and check again. 638 * 639 * NOTE!!! In order to make allowances for the hardware structure of 640 * the mac, spl values in here are hardcoded!!!!!!!!! 641 * This is done to allow serial interrupts to get in during 642 * scsi transfers. This is ugly. 643 */ 644 void 645 esp_quick_dma_go(struct ncr53c9x_softc *sc) 646 { 647 struct esp_softc *esc = (struct esp_softc *)sc; 648 extern long mac68k_a2_fromfault; 649 extern int *nofault; 650 label_t faultbuf; 651 uint16_t volatile *pdma; 652 uint16_t *addr; 653 int len, res; 654 uint16_t cnt32, cnt2; 655 volatile uint8_t *statreg; 656 657 esc->sc_active = 1; 658 659 espspl = splhigh(); 660 661 addr = (uint16_t *)*esc->sc_dmaaddr; 662 len = esc->sc_dmasize; 663 664 restart_dmago: 665 #if DEBUG 666 if (mac68k_esp_debug) { 667 printf("eqdg: a %lx, l %lx, in? %d ... ", 668 (long) addr, (long) len, esc->sc_datain); 669 } 670 #endif 671 nofault = (int *)&faultbuf; 672 if (setjmp((label_t *)nofault)) { 673 int i = 0; 674 675 nofault = NULL; 676 #if DEBUG 677 if (mac68k_esp_debug) { 678 printf("be\n"); 679 } 680 #endif 681 /* 682 * Bus error... 683 * So, we first check for an interrupt. If we have 684 * one, go handle it. Next we check for DREQ/. If 685 * we have it, then we restart the transfer. If 686 * neither, then loop until we get one or the other. 687 */ 688 statreg = esc->sc_reg + NCR_STAT * 16; 689 for (;;) { 690 spl2(); /* Give serial a chance... */ 691 splhigh(); /* That's enough... */ 692 693 if (*statreg & 0x80) { 694 goto gotintr; 695 } 696 697 if (esp_have_dreq(esc)) { 698 /* 699 * Get the remaining length from the address 700 * differential. 701 */ 702 addr = (uint16_t *)mac68k_a2_fromfault; 703 len = esc->sc_dmasize - 704 ((long)addr - (long)*esc->sc_dmaaddr); 705 706 if (esc->sc_datain == 0) { 707 /* 708 * Let the FIFO drain before we read 709 * the transfer count. 710 * Do we need to do this? 711 * Can we do this? 712 */ 713 while (NCR_READ_REG(sc, NCR_FFLAG) 714 & 0x1f); 715 /* 716 * Get the length from the transfer 717 * counters. 718 */ 719 res = NCR_READ_REG(sc, NCR_TCL); 720 res += NCR_READ_REG(sc, NCR_TCM) << 8; 721 /* 722 * If they don't agree, 723 * adjust accordingly. 724 */ 725 while (res > len) { 726 len+=2; addr--; 727 } 728 if (res != len) { 729 panic("%s: res %d != len %d", 730 __func__, res, len); 731 } 732 } 733 break; 734 } 735 736 DELAY(1); 737 if (i++ > 1000000) 738 panic("%s: Bus error, but no condition! Argh!", 739 __func__); 740 } 741 goto restart_dmago; 742 } 743 744 len &= ~1; 745 746 statreg = esc->sc_reg + NCR_STAT * 16; 747 pdma = (volatile uint16_t *)(esc->sc_reg + 0x100); 748 749 /* 750 * These loops are unrolled into assembly for two reasons: 751 * 1) We can make sure that they are as efficient as possible, and 752 * 2) (more importantly) we need the address that we are reading 753 * from or writing to to be in a2. 754 */ 755 cnt32 = len / 32; 756 cnt2 = (len % 32) / 2; 757 if (esc->sc_datain == 0) { 758 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */ 759 /* while (cnt2--) { *pdma = *addr++; } */ 760 __asm volatile ( 761 " movl %1, %%a2 \n" 762 " movl %2, %%a3 \n" 763 " movw %3, %%d2 \n" 764 " cmpw #0, %%d2 \n" 765 " beq 2f \n" 766 " subql #1, %%d2 \n" 767 "1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 768 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 769 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 770 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 771 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 772 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 773 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 774 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 775 " movw #8704,%%sr \n" 776 " movw #9728,%%sr \n" 777 " dbra %%d2, 1b \n" 778 "2: movw %4, %%d2 \n" 779 " cmpw #0, %%d2 \n" 780 " beq 4f \n" 781 " subql #1, %%d2 \n" 782 "3: movw %%a2@+,%%a3@ \n" 783 " dbra %%d2, 3b \n" 784 "4: movl %%a2, %0" 785 : "=g" (addr) 786 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 787 : "a2", "a3", "d2"); 788 if (esc->sc_pad) { 789 volatile uint8_t *c; 790 c = (volatile uint8_t *) addr; 791 /* Wait for DREQ */ 792 while (!esp_have_dreq(esc)) { 793 if (*statreg & 0x80) { 794 nofault = NULL; 795 goto gotintr; 796 } 797 } 798 *(volatile int8_t *)pdma = *c; 799 } 800 } else { 801 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */ 802 /* while (cnt2--) { *addr++ = *pdma; } */ 803 __asm volatile ( 804 " movl %1, %%a2 \n" 805 " movl %2, %%a3 \n" 806 " movw %3, %%d2 \n" 807 " cmpw #0, %%d2 \n" 808 " beq 6f \n" 809 " subql #1, %%d2 \n" 810 "5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 811 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 812 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 813 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 814 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 815 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 816 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 817 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 818 " movw #8704,%%sr \n" 819 " movw #9728,%%sr \n" 820 " dbra %%d2, 5b \n" 821 "6: movw %4, %%d2 \n" 822 " cmpw #0, %%d2 \n" 823 " beq 8f \n" 824 " subql #1, %%d2 \n" 825 "7: movw %%a3@,%%a2@+ \n" 826 " dbra %%d2, 7b \n" 827 "8: movl %%a2, %0" 828 : "=g" (addr) 829 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 830 : "a2", "a3", "d2"); 831 if (esc->sc_pad) { 832 volatile uint8_t *c; 833 c = (volatile int8_t *)addr; 834 /* Wait for DREQ */ 835 while (!esp_have_dreq(esc)) { 836 if (*statreg & 0x80) { 837 nofault = NULL; 838 goto gotintr; 839 } 840 } 841 *c = *(volatile uint8_t *)pdma; 842 } 843 } 844 845 nofault = NULL; 846 847 /* 848 * If we have not received an interrupt yet, we should shortly, 849 * and we can't prevent it, so return and wait for it. 850 */ 851 if ((*statreg & 0x80) == 0) { 852 #if DEBUG 853 if (mac68k_esp_debug) { 854 printf("g.\n"); 855 } 856 #endif 857 if (espspl != -1) 858 splx(espspl); 859 espspl = -1; 860 return; 861 } 862 863 gotintr: 864 #if DEBUG 865 if (mac68k_esp_debug) { 866 printf("g!\n"); 867 } 868 #endif 869 /* 870 * We have been called from the MI ncr53c9x_intr() handler, 871 * which protects itself against multiple invocation with a 872 * lock. Follow the example of ncr53c9x_poll(). 873 */ 874 mutex_exit(&sc->sc_lock); 875 ncr53c9x_intr(sc); 876 mutex_enter(&sc->sc_lock); 877 if (espspl != -1) 878 splx(espspl); 879 espspl = -1; 880 } 881 882 void 883 esp_intr(void *sc) 884 { 885 struct esp_softc *esc = (struct esp_softc *)sc; 886 887 if (esc->sc_reg[NCR_STAT * 16] & 0x80) { 888 ncr53c9x_intr((struct ncr53c9x_softc *)esp0); 889 } 890 } 891 892 void 893 esp_dualbus_intr(void *sc) 894 { 895 if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) { 896 ncr53c9x_intr((struct ncr53c9x_softc *)esp0); 897 } 898 899 if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) { 900 ncr53c9x_intr((struct ncr53c9x_softc *)esp1); 901 } 902 } 903