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