esp.c revision 1.49
1/* $NetBSD: esp.c,v 1.49 2007/10/17 19:55:16 garbled 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.49 2007/10/17 19:55:16 garbled 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 111void espattach(struct device *, struct device *, void *); 112int espmatch(struct device *, struct cfdata *, void *); 113 114/* Linkup to the rest of the kernel */ 115CFATTACH_DECL(esp, sizeof(struct esp_softc), 116 espmatch, espattach, NULL, NULL); 117 118/* 119 * Functions and the switch for the MI code. 120 */ 121u_char esp_read_reg(struct ncr53c9x_softc *, int); 122void esp_write_reg(struct ncr53c9x_softc *, int, u_char); 123int esp_dma_isintr(struct ncr53c9x_softc *); 124void esp_dma_reset(struct ncr53c9x_softc *); 125int esp_dma_intr(struct ncr53c9x_softc *); 126int esp_dma_setup(struct ncr53c9x_softc *, void **, size_t *, int, 127 size_t *); 128void esp_dma_go(struct ncr53c9x_softc *); 129void esp_dma_stop(struct ncr53c9x_softc *); 130int esp_dma_isactive(struct ncr53c9x_softc *); 131void esp_quick_write_reg(struct ncr53c9x_softc *, int, u_char); 132int esp_quick_dma_intr(struct ncr53c9x_softc *); 133int esp_quick_dma_setup(struct ncr53c9x_softc *, void **, size_t *, int, 134 size_t *); 135void esp_quick_dma_go(struct ncr53c9x_softc *); 136 137void esp_intr(void *); 138void esp_dualbus_intr(void *); 139static struct esp_softc *esp0, *esp1; 140 141static inline int esp_dafb_have_dreq(struct esp_softc *); 142static inline int esp_iosb_have_dreq(struct esp_softc *); 143int (*esp_have_dreq)(struct esp_softc *); 144 145struct 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 158int 159espmatch(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 */ 175void 176espattach(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 switch (current_mac_model->machineid) { 300 case MACH_MACQ630: 301 /* XXX on LC630 64k xfer causes timeout error */ 302 sc->sc_maxxfer = 63 * 1024; 303 break; 304 } 305 306 if (!quick) { 307 sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */ 308 sc->sc_maxxfer = 8 * 1024; 309 } 310 311 /* 312 * Configure interrupts. 313 */ 314 if (esc->irq_mask) { 315 via2_reg(vPCR) = 0x22; 316 via2_reg(vIFR) = esc->irq_mask; 317 via2_reg(vIER) = 0x80 | esc->irq_mask; 318 } 319 320 /* 321 * Now try to attach all the sub-devices 322 */ 323 sc->sc_adapter.adapt_minphys = minphys; 324 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 325 ncr53c9x_attach(sc); 326} 327 328/* 329 * Glue functions. 330 */ 331 332u_char 333esp_read_reg(struct ncr53c9x_softc *sc, int reg) 334{ 335 struct esp_softc *esc = (struct esp_softc *)sc; 336 337 return esc->sc_reg[reg * 16]; 338} 339 340void 341esp_write_reg(struct ncr53c9x_softc *sc, int reg, 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(struct ncr53c9x_softc *sc) 354{ 355} 356 357int 358esp_dma_isactive(struct ncr53c9x_softc *sc) 359{ 360 struct esp_softc *esc = (struct esp_softc *)sc; 361 362 return esc->sc_active; 363} 364 365int 366esp_dma_isintr(struct ncr53c9x_softc *sc) 367{ 368 struct esp_softc *esc = (struct esp_softc *)sc; 369 370 return esc->sc_reg[NCR_STAT * 16] & 0x80; 371} 372 373void 374esp_dma_reset(struct ncr53c9x_softc *sc) 375{ 376 struct esp_softc *esc = (struct esp_softc *)sc; 377 378 esc->sc_active = 0; 379 esc->sc_tc = 0; 380} 381 382int 383esp_dma_intr(struct ncr53c9x_softc *sc) 384{ 385 struct esp_softc *esc = (struct esp_softc *)sc; 386 volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg; 387 u_char *p; 388 u_int espphase, espstat, espintr; 389 int cnt, s; 390 391 if (esc->sc_active == 0) { 392 printf("dma_intr--inactive DMA\n"); 393 return -1; 394 } 395 396 if ((sc->sc_espintr & NCRINTR_BS) == 0) { 397 esc->sc_active = 0; 398 return 0; 399 } 400 401 cnt = *esc->sc_dmalen; 402 if (*esc->sc_dmalen == 0) { 403 printf("data interrupt, but no count left."); 404 } 405 406 p = *esc->sc_dmaaddr; 407 espphase = sc->sc_phase; 408 espstat = (u_int) sc->sc_espstat; 409 espintr = (u_int) sc->sc_espintr; 410 cmdreg = esc->sc_reg + NCR_CMD * 16; 411 fiforeg = esc->sc_reg + NCR_FIFO * 16; 412 statreg = esc->sc_reg + NCR_STAT * 16; 413 intrreg = esc->sc_reg + NCR_INTR * 16; 414 do { 415 if (esc->sc_datain) { 416 *p++ = *fiforeg; 417 cnt--; 418 if (espphase == DATA_IN_PHASE) { 419 *cmdreg = NCRCMD_TRANS; 420 } else { 421 esc->sc_active = 0; 422 } 423 } else { 424 if ( (espphase == DATA_OUT_PHASE) 425 || (espphase == MESSAGE_OUT_PHASE)) { 426 *fiforeg = *p++; 427 cnt--; 428 *cmdreg = NCRCMD_TRANS; 429 } else { 430 esc->sc_active = 0; 431 } 432 } 433 434 if (esc->sc_active) { 435 while (!(*statreg & 0x80)); 436 s = splhigh(); 437 espstat = *statreg; 438 espintr = *intrreg; 439 espphase = (espintr & NCRINTR_DIS) 440 ? /* Disconnected */ BUSFREE_PHASE 441 : espstat & PHASE_MASK; 442 splx(s); 443 } 444 } while (esc->sc_active && (espintr & NCRINTR_BS)); 445 sc->sc_phase = espphase; 446 sc->sc_espstat = (u_char) espstat; 447 sc->sc_espintr = (u_char) espintr; 448 *esc->sc_dmaaddr = p; 449 *esc->sc_dmalen = cnt; 450 451 if (*esc->sc_dmalen == 0) { 452 esc->sc_tc = NCRSTAT_TC; 453 } 454 sc->sc_espstat |= esc->sc_tc; 455 return 0; 456} 457 458int 459esp_dma_setup(struct ncr53c9x_softc *sc, void **addr, size_t *len, int datain, 460 size_t *dmasize) 461{ 462 struct esp_softc *esc = (struct esp_softc *)sc; 463 464 esc->sc_dmaaddr = (char **)addr; 465 esc->sc_dmalen = len; 466 esc->sc_datain = datain; 467 esc->sc_dmasize = *dmasize; 468 esc->sc_tc = 0; 469 470 return 0; 471} 472 473void 474esp_dma_go(struct ncr53c9x_softc *sc) 475{ 476 struct esp_softc *esc = (struct esp_softc *)sc; 477 478 if (esc->sc_datain == 0) { 479 esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr; 480 (*esc->sc_dmalen)--; 481 (*esc->sc_dmaaddr)++; 482 } 483 esc->sc_active = 1; 484} 485 486void 487esp_quick_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val) 488{ 489 struct esp_softc *esc = (struct esp_softc *)sc; 490 491 esc->sc_reg[reg * 16] = val; 492} 493 494#if DEBUG 495int mac68k_esp_debug=0; 496#endif 497 498int 499esp_quick_dma_intr(struct ncr53c9x_softc *sc) 500{ 501 struct esp_softc *esc = (struct esp_softc *)sc; 502 int trans=0, resid=0; 503 504 if (esc->sc_active == 0) 505 panic("dma_intr--inactive DMA"); 506 507 esc->sc_active = 0; 508 509 if (esc->sc_dmasize == 0) { 510 int res; 511 512 res = NCR_READ_REG(sc, NCR_TCL); 513 res += NCR_READ_REG(sc, NCR_TCM) << 8; 514 /* This can happen in the case of a TRPAD operation */ 515 /* Pretend that it was complete */ 516 sc->sc_espstat |= NCRSTAT_TC; 517#if DEBUG 518 if (mac68k_esp_debug) { 519 printf("dmaintr: DMA xfer of zero xferred %d\n", 520 65536 - res); 521 } 522#endif 523 return 0; 524 } 525 526 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 527 if (esc->sc_datain == 0) { 528 resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f; 529#if DEBUG 530 if (mac68k_esp_debug) { 531 printf("Write FIFO residual %d bytes\n", resid); 532 } 533#endif 534 } 535 resid += NCR_READ_REG(sc, NCR_TCL); 536 resid += NCR_READ_REG(sc, NCR_TCM) << 8; 537 if (resid == 0) 538 resid = 65536; 539 } 540 541 trans = esc->sc_dmasize - resid; 542 if (trans < 0) { 543 printf("dmaintr: trans < 0????"); 544 trans = *esc->sc_dmalen; 545 } 546 547 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid)); 548#if DEBUG 549 if (mac68k_esp_debug) { 550 printf("eqd_intr: trans %d, resid %d.\n", trans, resid); 551 } 552#endif 553 *esc->sc_dmaaddr += trans; 554 *esc->sc_dmalen -= trans; 555 556 return 0; 557} 558 559int 560esp_quick_dma_setup(struct ncr53c9x_softc *sc, void **addr, size_t *len, 561 int datain, size_t *dmasize) 562{ 563 struct esp_softc *esc = (struct esp_softc *)sc; 564 565 esc->sc_dmaaddr = (char **)addr; 566 esc->sc_dmalen = len; 567 568 if (*len & 1) { 569 esc->sc_pad = 1; 570 } else { 571 esc->sc_pad = 0; 572 } 573 574 esc->sc_datain = datain; 575 esc->sc_dmasize = *dmasize; 576 577#if DIAGNOSTIC 578 if (esc->sc_dmasize == 0) { 579 /* This can happen in the case of a TRPAD operation */ 580 } 581#endif 582#if DEBUG 583 if (mac68k_esp_debug) { 584 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n", 585 (long) *addr, (long) *len, datain, (long) esc->sc_dmasize); 586 } 587#endif 588 589 return 0; 590} 591 592static inline int 593esp_dafb_have_dreq(struct esp_softc *esc) 594{ 595 return (*(volatile u_int32_t *)(esc->sc_bsh.base) & 0x200); 596} 597 598static inline int 599esp_iosb_have_dreq(struct esp_softc *esc) 600{ 601 return (via2_reg(vIFR) & V2IF_SCSIDRQ); 602} 603 604static volatile int espspl=-1; 605 606/* 607 * Apple "DMA" is weird. 608 * 609 * Basically, the CPU acts like the DMA controller. The DREQ/ off the 610 * chip goes to a register that we've mapped at attach time (on the 611 * IOSB or DAFB, depending on the machine). Apple also provides some 612 * space for which the memory controller handshakes data to/from the 613 * NCR chip with the DACK/ line. This space appears to be mapped over 614 * and over, every 4 bytes, but only the lower 16 bits are valid (but 615 * reading the upper 16 bits will handshake DACK/ just fine, so if you 616 * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get 617 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff... 618 * 619 * When you're attempting to read or write memory to this DACK/ed space, 620 * and the NCR is not ready for some timeout period, the system will 621 * generate a bus error. This might be for one of several reasons: 622 * 623 * 1) (on write) The FIFO is full and is not draining. 624 * 2) (on read) The FIFO is empty and is not filling. 625 * 3) An interrupt condition has occurred. 626 * 4) Anything else? 627 * 628 * So if a bus error occurs, we first turn off the nofault bus error handler, 629 * then we check for an interrupt (which would render the first two 630 * possibilities moot). If there's no interrupt, check for a DREQ/. If we 631 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If 632 * neither condition holds, pause briefly and check again. 633 * 634 * NOTE!!! In order to make allowances for the hardware structure of 635 * the mac, spl values in here are hardcoded!!!!!!!!! 636 * This is done to allow serial interrupts to get in during 637 * scsi transfers. This is ugly. 638 */ 639void 640esp_quick_dma_go(struct ncr53c9x_softc *sc) 641{ 642 struct esp_softc *esc = (struct esp_softc *)sc; 643 extern long mac68k_a2_fromfault; 644 extern int *nofault; 645 label_t faultbuf; 646 u_int16_t volatile *pdma; 647 u_int16_t *addr; 648 int len, res; 649 u_short cnt32, cnt2; 650 u_char volatile *statreg; 651 652 esc->sc_active = 1; 653 654 espspl = splhigh(); 655 656 addr = (u_int16_t *) *esc->sc_dmaaddr; 657 len = esc->sc_dmasize; 658 659restart_dmago: 660#if DEBUG 661 if (mac68k_esp_debug) { 662 printf("eqdg: a %lx, l %lx, in? %d ... ", 663 (long) addr, (long) len, esc->sc_datain); 664 } 665#endif 666 nofault = (int *) &faultbuf; 667 if (setjmp((label_t *) nofault)) { 668 int i=0; 669 670 nofault = (int *) 0; 671#if DEBUG 672 if (mac68k_esp_debug) { 673 printf("be\n"); 674 } 675#endif 676 /* 677 * Bus error... 678 * So, we first check for an interrupt. If we have 679 * one, go handle it. Next we check for DREQ/. If 680 * we have it, then we restart the transfer. If 681 * neither, then loop until we get one or the other. 682 */ 683 statreg = esc->sc_reg + NCR_STAT * 16; 684 for (;;) { 685 spl2(); /* Give serial a chance... */ 686 splhigh(); /* That's enough... */ 687 688 if (*statreg & 0x80) { 689 goto gotintr; 690 } 691 692 if (esp_have_dreq(esc)) { 693 /* 694 * Get the remaining length from the address 695 * differential. 696 */ 697 addr = (u_int16_t *) mac68k_a2_fromfault; 698 len = esc->sc_dmasize - 699 ((long) addr - (long) *esc->sc_dmaaddr); 700 701 if (esc->sc_datain == 0) { 702 /* 703 * Let the FIFO drain before we read 704 * the transfer count. 705 * Do we need to do this? 706 * Can we do this? 707 */ 708 while (NCR_READ_REG(sc, NCR_FFLAG) 709 & 0x1f); 710 /* 711 * Get the length from the transfer 712 * counters. 713 */ 714 res = NCR_READ_REG(sc, NCR_TCL); 715 res += NCR_READ_REG(sc, NCR_TCM) << 8; 716 /* 717 * If they don't agree, 718 * adjust accordingly. 719 */ 720 while (res > len) { 721 len+=2; addr--; 722 } 723 if (res != len) { 724 panic("esp_quick_dma_go: res %d != len %d", 725 res, len); 726 } 727 } 728 break; 729 } 730 731 DELAY(1); 732 if (i++ > 1000000) 733 panic("esp_dma_go: Bus error, but no condition! Argh!"); 734 } 735 goto restart_dmago; 736 } 737 738 len &= ~1; 739 740 statreg = esc->sc_reg + NCR_STAT * 16; 741 pdma = (volatile u_int16_t *) (esc->sc_reg + 0x100); 742 743 /* 744 * These loops are unrolled into assembly for two reasons: 745 * 1) We can make sure that they are as efficient as possible, and 746 * 2) (more importantly) we need the address that we are reading 747 * from or writing to to be in a2. 748 */ 749 cnt32 = len / 32; 750 cnt2 = (len % 32) / 2; 751 if (esc->sc_datain == 0) { 752 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */ 753 /* while (cnt2--) { *pdma = *addr++; } */ 754 __asm volatile ( 755 " movl %1, %%a2 \n" 756 " movl %2, %%a3 \n" 757 " movw %3, %%d2 \n" 758 " cmpw #0, %%d2 \n" 759 " beq 2f \n" 760 " subql #1, %%d2 \n" 761 "1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 762 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 763 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 764 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 765 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 766 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 767 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 768 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 769 " movw #8704,%%sr \n" 770 " movw #9728,%%sr \n" 771 " dbra %%d2, 1b \n" 772 "2: movw %4, %%d2 \n" 773 " cmpw #0, %%d2 \n" 774 " beq 4f \n" 775 " subql #1, %%d2 \n" 776 "3: movw %%a2@+,%%a3@ \n" 777 " dbra %%d2, 3b \n" 778 "4: movl %%a2, %0" 779 : "=g" (addr) 780 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 781 : "a2", "a3", "d2"); 782 if (esc->sc_pad) { 783 volatile unsigned char *c; 784 c = (volatile unsigned char *) addr; 785 /* Wait for DREQ */ 786 while (!esp_have_dreq(esc)) { 787 if (*statreg & 0x80) { 788 nofault = (int *) 0; 789 goto gotintr; 790 } 791 } 792 *(volatile unsigned char *)pdma = *c; 793 } 794 } else { 795 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */ 796 /* while (cnt2--) { *addr++ = *pdma; } */ 797 __asm volatile ( 798 " movl %1, %%a2 \n" 799 " movl %2, %%a3 \n" 800 " movw %3, %%d2 \n" 801 " cmpw #0, %%d2 \n" 802 " beq 6f \n" 803 " subql #1, %%d2 \n" 804 "5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 805 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 806 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 807 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 808 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 809 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 810 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 811 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 812 " movw #8704,%%sr \n" 813 " movw #9728,%%sr \n" 814 " dbra %%d2, 5b \n" 815 "6: movw %4, %%d2 \n" 816 " cmpw #0, %%d2 \n" 817 " beq 8f \n" 818 " subql #1, %%d2 \n" 819 "7: movw %%a3@,%%a2@+ \n" 820 " dbra %%d2, 7b \n" 821 "8: movl %%a2, %0" 822 : "=g" (addr) 823 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 824 : "a2", "a3", "d2"); 825 if (esc->sc_pad) { 826 volatile unsigned char *c; 827 c = (volatile unsigned char *) addr; 828 /* Wait for DREQ */ 829 while (!esp_have_dreq(esc)) { 830 if (*statreg & 0x80) { 831 nofault = (int *) 0; 832 goto gotintr; 833 } 834 } 835 *c = *(volatile unsigned char *)pdma; 836 } 837 } 838 839 nofault = (int *) 0; 840 841 /* 842 * If we have not received an interrupt yet, we should shortly, 843 * and we can't prevent it, so return and wait for it. 844 */ 845 if ((*statreg & 0x80) == 0) { 846#if DEBUG 847 if (mac68k_esp_debug) { 848 printf("g.\n"); 849 } 850#endif 851 if (espspl != -1) splx(espspl); espspl = -1; 852 return; 853 } 854 855gotintr: 856#if DEBUG 857 if (mac68k_esp_debug) { 858 printf("g!\n"); 859 } 860#endif 861 ncr53c9x_intr(sc); 862 if (espspl != -1) splx(espspl); espspl = -1; 863} 864 865void 866esp_intr(void *sc) 867{ 868 struct esp_softc *esc = (struct esp_softc *)sc; 869 870 if (esc->sc_reg[NCR_STAT * 16] & 0x80) { 871 ncr53c9x_intr((struct ncr53c9x_softc *) esp0); 872 } 873} 874 875void 876esp_dualbus_intr(void *sc) 877{ 878 if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) { 879 ncr53c9x_intr((struct ncr53c9x_softc *) esp0); 880 } 881 882 if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) { 883 ncr53c9x_intr((struct ncr53c9x_softc *) esp1); 884 } 885} 886