1 /* $NetBSD: esp.c,v 1.43 2005/12/24 23:24:01 perry 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.43 2005/12/24 23:24:01 perry 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/user.h> 92 #include <sys/queue.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 void espattach(struct device *, struct device *, void *); 112 int espmatch(struct device *, struct cfdata *, void *); 113 114 /* Linkup to the rest of the kernel */ 115 CFATTACH_DECL(esp, sizeof(struct esp_softc), 116 espmatch, espattach, NULL, NULL); 117 118 /* 119 * Functions and the switch for the MI code. 120 */ 121 u_char esp_read_reg(struct ncr53c9x_softc *, int); 122 void esp_write_reg(struct ncr53c9x_softc *, int, u_char); 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 *, caddr_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 *, caddr_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(struct device *parent, struct cfdata *cf, void *aux) 160 { 161 struct obio_attach_args *oa = (struct obio_attach_args *)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(struct device *parent, struct device *self, void *aux) 177 { 178 struct obio_attach_args *oa = (struct obio_attach_args *)aux; 179 extern vaddr_t SCSIBase; 180 struct esp_softc *esc = (void *)self; 181 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 182 int quick = 0; 183 unsigned long reg_offset; 184 185 reg_offset = SCSIBase - IOBase; 186 esc->sc_tag = oa->oa_tag; 187 188 /* 189 * For Wombat, Primus and Optimus motherboards, DREQ is 190 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and 191 * the scsi registers are offset 0x1000 bytes from IOBase). 192 * 193 * For the Q700/900/950 it's at f9800024 for bus 0 and 194 * f9800028 for bus 1 (900/950). For these machines, that is also 195 * a (12-bit) configuration register for DAFB's control of the 196 * pseudo-DMA timing. The default value is 0x1d1. 197 */ 198 esp_have_dreq = esp_dafb_have_dreq; 199 if (oa->oa_addr == 0) { 200 if (reg_offset == 0x10000) { 201 quick = 1; 202 esp_have_dreq = esp_iosb_have_dreq; 203 } else if (reg_offset == 0x18000) { 204 quick = 0; 205 } else { 206 if (bus_space_map(esc->sc_tag, 0xf9800024, 207 4, 0, &esc->sc_bsh)) { 208 printf("failed to map 4 at 0xf9800024.\n"); 209 } else { 210 quick = 1; 211 bus_space_write_4(esc->sc_tag, 212 esc->sc_bsh, 0, 0x1d1); 213 } 214 } 215 } else { 216 if (bus_space_map(esc->sc_tag, 0xf9800028, 217 4, 0, &esc->sc_bsh)) { 218 printf("failed to map 4 at 0xf9800028.\n"); 219 } else { 220 quick = 1; 221 bus_space_write_4(esc->sc_tag, esc->sc_bsh, 0, 0x1d1); 222 } 223 } 224 if (quick) { 225 esp_glue.gl_write_reg = esp_quick_write_reg; 226 esp_glue.gl_dma_intr = esp_quick_dma_intr; 227 esp_glue.gl_dma_setup = esp_quick_dma_setup; 228 esp_glue.gl_dma_go = esp_quick_dma_go; 229 } 230 231 /* 232 * Set up the glue for MI code early; we use some of it here. 233 */ 234 sc->sc_glue = &esp_glue; 235 236 /* 237 * Save the regs 238 */ 239 if (oa->oa_addr == 0) { 240 esp0 = esc; 241 242 esc->sc_reg = (volatile u_char *) SCSIBase; 243 via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc); 244 esc->irq_mask = V2IF_SCSIIRQ; 245 if (reg_offset == 0x10000) { 246 /* From the Q650 developer's note */ 247 sc->sc_freq = 16500000; 248 } else { 249 sc->sc_freq = 25000000; 250 } 251 252 if (esp_glue.gl_dma_go == esp_quick_dma_go) { 253 printf(" (quick)"); 254 } 255 } else { 256 esp1 = esc; 257 258 esc->sc_reg = (volatile u_char *) SCSIBase + 0x402; 259 via2_register_irq(VIA2_SCSIIRQ, esp_dualbus_intr, NULL); 260 esc->irq_mask = 0; 261 sc->sc_freq = 25000000; 262 263 if (esp_glue.gl_dma_go == esp_quick_dma_go) { 264 printf(" (quick)"); 265 } 266 } 267 268 printf(": address %p", esc->sc_reg); 269 270 sc->sc_id = 7; 271 272 /* gimme Mhz */ 273 sc->sc_freq /= 1000000; 274 275 /* 276 * It is necessary to try to load the 2nd config register here, 277 * to find out what rev the esp chip is, else the esp_reset 278 * will not set up the defaults correctly. 279 */ 280 sc->sc_cfg1 = sc->sc_id; /* | NCRCFG1_PARENB; */ 281 sc->sc_cfg2 = NCRCFG2_SCSI2; 282 sc->sc_cfg3 = 0; 283 sc->sc_rev = NCR_VARIANT_NCR53C96; 284 285 /* 286 * This is the value used to start sync negotiations 287 * Note that the NCR register "SYNCTP" is programmed 288 * in "clocks per byte", and has a minimum value of 4. 289 * The SCSI period used in negotiation is one-fourth 290 * of the time (in nanoseconds) needed to transfer one byte. 291 * Since the chip's clock is given in MHz, we have the following 292 * formula: 4 * period = (1000 / freq) * 4 293 */ 294 sc->sc_minsync = 1000 / sc->sc_freq; 295 296 /* We need this to fit into the TCR... */ 297 sc->sc_maxxfer = 64 * 1024; 298 299 if (!quick) { 300 sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */ 301 sc->sc_maxxfer = 8 * 1024; 302 } 303 304 /* 305 * Configure interrupts. 306 */ 307 if (esc->irq_mask) { 308 via2_reg(vPCR) = 0x22; 309 via2_reg(vIFR) = esc->irq_mask; 310 via2_reg(vIER) = 0x80 | esc->irq_mask; 311 } 312 313 /* 314 * Now try to attach all the sub-devices 315 */ 316 sc->sc_adapter.adapt_minphys = minphys; 317 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 318 ncr53c9x_attach(sc); 319 } 320 321 /* 322 * Glue functions. 323 */ 324 325 u_char 326 esp_read_reg(struct ncr53c9x_softc *sc, int reg) 327 { 328 struct esp_softc *esc = (struct esp_softc *)sc; 329 330 return esc->sc_reg[reg * 16]; 331 } 332 333 void 334 esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val) 335 { 336 struct esp_softc *esc = (struct esp_softc *)sc; 337 u_char v = val; 338 339 if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) { 340 v = NCRCMD_TRANS; 341 } 342 esc->sc_reg[reg * 16] = v; 343 } 344 345 void 346 esp_dma_stop(struct ncr53c9x_softc *sc) 347 { 348 } 349 350 int 351 esp_dma_isactive(struct ncr53c9x_softc *sc) 352 { 353 struct esp_softc *esc = (struct esp_softc *)sc; 354 355 return esc->sc_active; 356 } 357 358 int 359 esp_dma_isintr(struct ncr53c9x_softc *sc) 360 { 361 struct esp_softc *esc = (struct esp_softc *)sc; 362 363 return esc->sc_reg[NCR_STAT * 16] & 0x80; 364 } 365 366 void 367 esp_dma_reset(struct ncr53c9x_softc *sc) 368 { 369 struct esp_softc *esc = (struct esp_softc *)sc; 370 371 esc->sc_active = 0; 372 esc->sc_tc = 0; 373 } 374 375 int 376 esp_dma_intr(struct ncr53c9x_softc *sc) 377 { 378 struct esp_softc *esc = (struct esp_softc *)sc; 379 volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg; 380 u_char *p; 381 u_int espphase, espstat, espintr; 382 int cnt, s; 383 384 if (esc->sc_active == 0) { 385 printf("dma_intr--inactive DMA\n"); 386 return -1; 387 } 388 389 if ((sc->sc_espintr & NCRINTR_BS) == 0) { 390 esc->sc_active = 0; 391 return 0; 392 } 393 394 cnt = *esc->sc_dmalen; 395 if (*esc->sc_dmalen == 0) { 396 printf("data interrupt, but no count left."); 397 } 398 399 p = *esc->sc_dmaaddr; 400 espphase = sc->sc_phase; 401 espstat = (u_int) sc->sc_espstat; 402 espintr = (u_int) sc->sc_espintr; 403 cmdreg = esc->sc_reg + NCR_CMD * 16; 404 fiforeg = esc->sc_reg + NCR_FIFO * 16; 405 statreg = esc->sc_reg + NCR_STAT * 16; 406 intrreg = esc->sc_reg + NCR_INTR * 16; 407 do { 408 if (esc->sc_datain) { 409 *p++ = *fiforeg; 410 cnt--; 411 if (espphase == DATA_IN_PHASE) { 412 *cmdreg = NCRCMD_TRANS; 413 } else { 414 esc->sc_active = 0; 415 } 416 } else { 417 if ( (espphase == DATA_OUT_PHASE) 418 || (espphase == MESSAGE_OUT_PHASE)) { 419 *fiforeg = *p++; 420 cnt--; 421 *cmdreg = NCRCMD_TRANS; 422 } else { 423 esc->sc_active = 0; 424 } 425 } 426 427 if (esc->sc_active) { 428 while (!(*statreg & 0x80)); 429 s = splhigh(); 430 espstat = *statreg; 431 espintr = *intrreg; 432 espphase = (espintr & NCRINTR_DIS) 433 ? /* Disconnected */ BUSFREE_PHASE 434 : espstat & PHASE_MASK; 435 splx(s); 436 } 437 } while (esc->sc_active && (espintr & NCRINTR_BS)); 438 sc->sc_phase = espphase; 439 sc->sc_espstat = (u_char) espstat; 440 sc->sc_espintr = (u_char) espintr; 441 *esc->sc_dmaaddr = p; 442 *esc->sc_dmalen = cnt; 443 444 if (*esc->sc_dmalen == 0) { 445 esc->sc_tc = NCRSTAT_TC; 446 } 447 sc->sc_espstat |= esc->sc_tc; 448 return 0; 449 } 450 451 int 452 esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len, int datain, 453 size_t *dmasize) 454 { 455 struct esp_softc *esc = (struct esp_softc *)sc; 456 457 esc->sc_dmaaddr = addr; 458 esc->sc_dmalen = len; 459 esc->sc_datain = datain; 460 esc->sc_dmasize = *dmasize; 461 esc->sc_tc = 0; 462 463 return 0; 464 } 465 466 void 467 esp_dma_go(struct ncr53c9x_softc *sc) 468 { 469 struct esp_softc *esc = (struct esp_softc *)sc; 470 471 if (esc->sc_datain == 0) { 472 esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr; 473 (*esc->sc_dmalen)--; 474 (*esc->sc_dmaaddr)++; 475 } 476 esc->sc_active = 1; 477 } 478 479 void 480 esp_quick_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val) 481 { 482 struct esp_softc *esc = (struct esp_softc *)sc; 483 484 esc->sc_reg[reg * 16] = val; 485 } 486 487 #if DEBUG 488 int mac68k_esp_debug=0; 489 #endif 490 491 int 492 esp_quick_dma_intr(struct ncr53c9x_softc *sc) 493 { 494 struct esp_softc *esc = (struct esp_softc *)sc; 495 int trans=0, resid=0; 496 497 if (esc->sc_active == 0) 498 panic("dma_intr--inactive DMA"); 499 500 esc->sc_active = 0; 501 502 if (esc->sc_dmasize == 0) { 503 int res; 504 505 res = NCR_READ_REG(sc, NCR_TCL); 506 res += NCR_READ_REG(sc, NCR_TCM) << 8; 507 /* This can happen in the case of a TRPAD operation */ 508 /* Pretend that it was complete */ 509 sc->sc_espstat |= NCRSTAT_TC; 510 #if DEBUG 511 if (mac68k_esp_debug) { 512 printf("dmaintr: DMA xfer of zero xferred %d\n", 513 65536 - res); 514 } 515 #endif 516 return 0; 517 } 518 519 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 520 if (esc->sc_datain == 0) { 521 resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f; 522 #if DEBUG 523 if (mac68k_esp_debug) { 524 printf("Write FIFO residual %d bytes\n", resid); 525 } 526 #endif 527 } 528 resid += NCR_READ_REG(sc, NCR_TCL); 529 resid += NCR_READ_REG(sc, NCR_TCM) << 8; 530 if (resid == 0) 531 resid = 65536; 532 } 533 534 trans = esc->sc_dmasize - resid; 535 if (trans < 0) { 536 printf("dmaintr: trans < 0????"); 537 trans = *esc->sc_dmalen; 538 } 539 540 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid)); 541 #if DEBUG 542 if (mac68k_esp_debug) { 543 printf("eqd_intr: trans %d, resid %d.\n", trans, resid); 544 } 545 #endif 546 *esc->sc_dmaaddr += trans; 547 *esc->sc_dmalen -= trans; 548 549 return 0; 550 } 551 552 int 553 esp_quick_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len, 554 int datain, size_t *dmasize) 555 { 556 struct esp_softc *esc = (struct esp_softc *)sc; 557 558 esc->sc_dmaaddr = addr; 559 esc->sc_dmalen = len; 560 561 if (*len & 1) { 562 esc->sc_pad = 1; 563 } else { 564 esc->sc_pad = 0; 565 } 566 567 esc->sc_datain = datain; 568 esc->sc_dmasize = *dmasize; 569 570 #if DIAGNOSTIC 571 if (esc->sc_dmasize == 0) { 572 /* This can happen in the case of a TRPAD operation */ 573 } 574 #endif 575 #if DEBUG 576 if (mac68k_esp_debug) { 577 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n", 578 (long) *addr, (long) *len, datain, (long) esc->sc_dmasize); 579 } 580 #endif 581 582 return 0; 583 } 584 585 static inline int 586 esp_dafb_have_dreq(struct esp_softc *esc) 587 { 588 return (*(volatile u_int32_t *)(esc->sc_bsh.base) & 0x200); 589 } 590 591 static inline int 592 esp_iosb_have_dreq(struct esp_softc *esc) 593 { 594 return (via2_reg(vIFR) & V2IF_SCSIDRQ); 595 } 596 597 static volatile int espspl=-1; 598 599 /* 600 * Apple "DMA" is weird. 601 * 602 * Basically, the CPU acts like the DMA controller. The DREQ/ off the 603 * chip goes to a register that we've mapped at attach time (on the 604 * IOSB or DAFB, depending on the machine). Apple also provides some 605 * space for which the memory controller handshakes data to/from the 606 * NCR chip with the DACK/ line. This space appears to be mapped over 607 * and over, every 4 bytes, but only the lower 16 bits are valid (but 608 * reading the upper 16 bits will handshake DACK/ just fine, so if you 609 * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get 610 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff... 611 * 612 * When you're attempting to read or write memory to this DACK/ed space, 613 * and the NCR is not ready for some timeout period, the system will 614 * generate a bus error. This might be for one of several reasons: 615 * 616 * 1) (on write) The FIFO is full and is not draining. 617 * 2) (on read) The FIFO is empty and is not filling. 618 * 3) An interrupt condition has occurred. 619 * 4) Anything else? 620 * 621 * So if a bus error occurs, we first turn off the nofault bus error handler, 622 * then we check for an interrupt (which would render the first two 623 * possibilities moot). If there's no interrupt, check for a DREQ/. If we 624 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If 625 * neither condition holds, pause briefly and check again. 626 * 627 * NOTE!!! In order to make allowances for the hardware structure of 628 * the mac, spl values in here are hardcoded!!!!!!!!! 629 * This is done to allow serial interrupts to get in during 630 * scsi transfers. This is ugly. 631 */ 632 void 633 esp_quick_dma_go(struct ncr53c9x_softc *sc) 634 { 635 struct esp_softc *esc = (struct esp_softc *)sc; 636 extern long mac68k_a2_fromfault; 637 extern int *nofault; 638 label_t faultbuf; 639 u_int16_t volatile *pdma; 640 u_int16_t *addr; 641 int len, res; 642 u_short cnt32, cnt2; 643 u_char volatile *statreg; 644 645 esc->sc_active = 1; 646 647 espspl = splhigh(); 648 649 addr = (u_int16_t *) *esc->sc_dmaaddr; 650 len = esc->sc_dmasize; 651 652 restart_dmago: 653 #if DEBUG 654 if (mac68k_esp_debug) { 655 printf("eqdg: a %lx, l %lx, in? %d ... ", 656 (long) addr, (long) len, esc->sc_datain); 657 } 658 #endif 659 nofault = (int *) &faultbuf; 660 if (setjmp((label_t *) nofault)) { 661 int i=0; 662 663 nofault = (int *) 0; 664 #if DEBUG 665 if (mac68k_esp_debug) { 666 printf("be\n"); 667 } 668 #endif 669 /* 670 * Bus error... 671 * So, we first check for an interrupt. If we have 672 * one, go handle it. Next we check for DREQ/. If 673 * we have it, then we restart the transfer. If 674 * neither, then loop until we get one or the other. 675 */ 676 statreg = esc->sc_reg + NCR_STAT * 16; 677 for (;;) { 678 spl2(); /* Give serial a chance... */ 679 splhigh(); /* That's enough... */ 680 681 if (*statreg & 0x80) { 682 goto gotintr; 683 } 684 685 if (esp_have_dreq(esc)) { 686 /* 687 * Get the remaining length from the address 688 * differential. 689 */ 690 addr = (u_int16_t *) mac68k_a2_fromfault; 691 len = esc->sc_dmasize - 692 ((long) addr - (long) *esc->sc_dmaaddr); 693 694 if (esc->sc_datain == 0) { 695 /* 696 * Let the FIFO drain before we read 697 * the transfer count. 698 * Do we need to do this? 699 * Can we do this? 700 */ 701 while (NCR_READ_REG(sc, NCR_FFLAG) 702 & 0x1f); 703 /* 704 * Get the length from the transfer 705 * counters. 706 */ 707 res = NCR_READ_REG(sc, NCR_TCL); 708 res += NCR_READ_REG(sc, NCR_TCM) << 8; 709 /* 710 * If they don't agree, 711 * adjust accordingly. 712 */ 713 while (res > len) { 714 len+=2; addr--; 715 } 716 if (res != len) { 717 panic("esp_quick_dma_go: res %d != len %d", 718 res, len); 719 } 720 } 721 break; 722 } 723 724 DELAY(1); 725 if (i++ > 1000000) 726 panic("esp_dma_go: Bus error, but no condition! Argh!"); 727 } 728 goto restart_dmago; 729 } 730 731 len &= ~1; 732 733 statreg = esc->sc_reg + NCR_STAT * 16; 734 pdma = (volatile u_int16_t *) (esc->sc_reg + 0x100); 735 736 /* 737 * These loops are unrolled into assembly for two reasons: 738 * 1) We can make sure that they are as efficient as possible, and 739 * 2) (more importantly) we need the address that we are reading 740 * from or writing to to be in a2. 741 */ 742 cnt32 = len / 32; 743 cnt2 = (len % 32) / 2; 744 if (esc->sc_datain == 0) { 745 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */ 746 /* while (cnt2--) { *pdma = *addr++; } */ 747 __asm volatile ( 748 " movl %1, %%a2 \n" 749 " movl %2, %%a3 \n" 750 " movw %3, %%d2 \n" 751 " cmpw #0, %%d2 \n" 752 " beq 2f \n" 753 " subql #1, %%d2 \n" 754 "1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 755 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 756 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 757 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 758 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 759 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 760 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 761 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 762 " movw #8704,%%sr \n" 763 " movw #9728,%%sr \n" 764 " dbra %%d2, 1b \n" 765 "2: movw %4, %%d2 \n" 766 " cmpw #0, %%d2 \n" 767 " beq 4f \n" 768 " subql #1, %%d2 \n" 769 "3: movw %%a2@+,%%a3@ \n" 770 " dbra %%d2, 3b \n" 771 "4: movl %%a2, %0" 772 : "=g" (addr) 773 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 774 : "a2", "a3", "d2"); 775 if (esc->sc_pad) { 776 volatile unsigned char *c; 777 c = (volatile unsigned char *) addr; 778 /* Wait for DREQ */ 779 while (!esp_have_dreq(esc)) { 780 if (*statreg & 0x80) { 781 nofault = (int *) 0; 782 goto gotintr; 783 } 784 } 785 *(volatile unsigned char *)pdma = *c; 786 } 787 } else { 788 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */ 789 /* while (cnt2--) { *addr++ = *pdma; } */ 790 __asm volatile ( 791 " movl %1, %%a2 \n" 792 " movl %2, %%a3 \n" 793 " movw %3, %%d2 \n" 794 " cmpw #0, %%d2 \n" 795 " beq 6f \n" 796 " subql #1, %%d2 \n" 797 "5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 798 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 799 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 800 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 801 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 802 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 803 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 804 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 805 " movw #8704,%%sr \n" 806 " movw #9728,%%sr \n" 807 " dbra %%d2, 5b \n" 808 "6: movw %4, %%d2 \n" 809 " cmpw #0, %%d2 \n" 810 " beq 8f \n" 811 " subql #1, %%d2 \n" 812 "7: movw %%a3@,%%a2@+ \n" 813 " dbra %%d2, 7b \n" 814 "8: movl %%a2, %0" 815 : "=g" (addr) 816 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 817 : "a2", "a3", "d2"); 818 if (esc->sc_pad) { 819 volatile unsigned char *c; 820 c = (volatile unsigned char *) addr; 821 /* Wait for DREQ */ 822 while (!esp_have_dreq(esc)) { 823 if (*statreg & 0x80) { 824 nofault = (int *) 0; 825 goto gotintr; 826 } 827 } 828 *c = *(volatile unsigned char *)pdma; 829 } 830 } 831 832 nofault = (int *) 0; 833 834 /* 835 * If we have not received an interrupt yet, we should shortly, 836 * and we can't prevent it, so return and wait for it. 837 */ 838 if ((*statreg & 0x80) == 0) { 839 #if DEBUG 840 if (mac68k_esp_debug) { 841 printf("g.\n"); 842 } 843 #endif 844 if (espspl != -1) splx(espspl); espspl = -1; 845 return; 846 } 847 848 gotintr: 849 #if DEBUG 850 if (mac68k_esp_debug) { 851 printf("g!\n"); 852 } 853 #endif 854 ncr53c9x_intr(sc); 855 if (espspl != -1) splx(espspl); espspl = -1; 856 } 857 858 void 859 esp_intr(void *sc) 860 { 861 struct esp_softc *esc = (struct esp_softc *)sc; 862 863 if (esc->sc_reg[NCR_STAT * 16] & 0x80) { 864 ncr53c9x_intr((struct ncr53c9x_softc *) esp0); 865 } 866 } 867 868 void 869 esp_dualbus_intr(void *sc) 870 { 871 if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) { 872 ncr53c9x_intr((struct ncr53c9x_softc *) esp0); 873 } 874 875 if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) { 876 ncr53c9x_intr((struct ncr53c9x_softc *) esp1); 877 } 878 } 879