Annotation of sys/arch/mac68k/dev/esp.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: esp.c,v 1.27 2007/07/29 21:24:02 miod Exp $ */
! 2: /* $NetBSD: esp.c,v 1.17 1998/09/05 15:15:35 pk Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1997 Jason R. Thorpe.
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed for the NetBSD Project
! 19: * by Jason R. Thorpe.
! 20: * 4. The name of the author may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: /*
! 36: * Copyright (c) 1994 Peter Galbavy
! 37: * All rights reserved.
! 38: *
! 39: * Redistribution and use in source and binary forms, with or without
! 40: * modification, are permitted provided that the following conditions
! 41: * are met:
! 42: * 1. Redistributions of source code must retain the above copyright
! 43: * notice, this list of conditions and the following disclaimer.
! 44: * 2. Redistributions in binary form must reproduce the above copyright
! 45: * notice, this list of conditions and the following disclaimer in the
! 46: * documentation and/or other materials provided with the distribution.
! 47: *
! 48: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 49: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 50: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 51: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 52: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 53: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 54: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 56: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 57: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 58: * POSSIBILITY OF SUCH DAMAGE.
! 59: */
! 60:
! 61: /*
! 62: * Based on aic6360 by Jarle Greipsland
! 63: *
! 64: * Acknowledgements: Many of the algorithms used in this driver are
! 65: * inspired by the work of Julian Elischer (julian@tfs.com) and
! 66: * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
! 67: */
! 68:
! 69: /*
! 70: * Initial m68k mac support from Allen Briggs <briggs@macbsd.com>
! 71: * (basically consisting of the match, a bit of the attach, and the
! 72: * "DMA" glue functions).
! 73: */
! 74:
! 75: #include <sys/types.h>
! 76: #include <sys/param.h>
! 77: #include <sys/systm.h>
! 78: #include <sys/kernel.h>
! 79: #include <sys/errno.h>
! 80: #include <sys/ioctl.h>
! 81: #include <sys/device.h>
! 82: #include <sys/buf.h>
! 83: #include <sys/proc.h>
! 84: #include <sys/user.h>
! 85: #include <sys/queue.h>
! 86:
! 87: #include <scsi/scsi_all.h>
! 88: #include <scsi/scsiconf.h>
! 89: #include <scsi/scsi_message.h>
! 90:
! 91: #include <machine/cpu.h>
! 92: #include <machine/bus.h>
! 93: #include <machine/param.h>
! 94:
! 95: #include <dev/ic/ncr53c9xreg.h>
! 96: #include <dev/ic/ncr53c9xvar.h>
! 97:
! 98: #include <machine/viareg.h>
! 99:
! 100: #include <mac68k/dev/espvar.h>
! 101: #include <mac68k/dev/obiovar.h>
! 102:
! 103: void espattach(struct device *, struct device *, void *);
! 104: int espmatch(struct device *, void *, void *);
! 105:
! 106: /* Linkup to the rest of the kernel */
! 107: struct cfattach esp_ca = {
! 108: sizeof(struct esp_softc), espmatch, espattach
! 109: };
! 110:
! 111: struct scsi_adapter esp_switch = {
! 112: ncr53c9x_scsi_cmd,
! 113: minphys, /* no max at this level; handled by DMA code */
! 114: NULL,
! 115: NULL,
! 116: };
! 117:
! 118: struct scsi_device esp_dev = {
! 119: NULL, /* Use default error handler */
! 120: NULL, /* have a queue, served by this */
! 121: NULL, /* have no async handler */
! 122: NULL, /* Use default 'done' routine */
! 123: };
! 124:
! 125: /*
! 126: * Functions and the switch for the MI code.
! 127: */
! 128: u_char esp_read_reg(struct ncr53c9x_softc *, int);
! 129: void esp_write_reg(struct ncr53c9x_softc *, int, u_char);
! 130: int esp_dma_isintr(struct ncr53c9x_softc *);
! 131: void esp_dma_reset(struct ncr53c9x_softc *);
! 132: int esp_dma_intr(struct ncr53c9x_softc *);
! 133: int esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
! 134: size_t *, int, size_t *);
! 135: void esp_dma_go(struct ncr53c9x_softc *);
! 136: void esp_dma_stop(struct ncr53c9x_softc *);
! 137: int esp_dma_isactive(struct ncr53c9x_softc *);
! 138: void esp_quick_write_reg(struct ncr53c9x_softc *, int, u_char);
! 139: int esp_quick_dma_intr(struct ncr53c9x_softc *);
! 140: int esp_quick_dma_setup(struct ncr53c9x_softc *, caddr_t *,
! 141: size_t *, int, size_t *);
! 142: void esp_quick_dma_go(struct ncr53c9x_softc *);
! 143: int esp_intr(void *);
! 144:
! 145: static __inline__ int esp_dafb_have_dreq(struct esp_softc *esc);
! 146: static __inline__ int esp_iosb_have_dreq(struct esp_softc *esc);
! 147: int (*esp_have_dreq) (struct esp_softc *esc);
! 148:
! 149: struct ncr53c9x_glue esp_glue = {
! 150: esp_read_reg,
! 151: esp_write_reg,
! 152: esp_dma_isintr,
! 153: esp_dma_reset,
! 154: esp_dma_intr,
! 155: esp_dma_setup,
! 156: esp_dma_go,
! 157: esp_dma_stop,
! 158: esp_dma_isactive,
! 159: NULL, /* gl_clear_latched_intr */
! 160: };
! 161:
! 162: int
! 163: espmatch(parent, vcf, aux)
! 164: struct device *parent;
! 165: void *vcf, *aux;
! 166: {
! 167: struct cfdata *cf = vcf;
! 168:
! 169: if ((cf->cf_unit == 0) && mac68k_machine.scsi96) {
! 170: return 1;
! 171: }
! 172: if ((cf->cf_unit == 1) && mac68k_machine.scsi96_2) {
! 173: return 1;
! 174: }
! 175: return 0;
! 176: }
! 177:
! 178: /*
! 179: * Attach this instance, and then all the sub-devices
! 180: */
! 181: void
! 182: espattach(parent, self, aux)
! 183: struct device *parent, *self;
! 184: void *aux;
! 185: {
! 186: struct obio_attach_args *oa = (struct obio_attach_args *)aux;
! 187: extern vaddr_t SCSIBase;
! 188: struct esp_softc *esc = (void *)self;
! 189: struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
! 190: int quick = 0;
! 191: unsigned long reg_offset;
! 192:
! 193: reg_offset = SCSIBase - IOBase;
! 194: esc->sc_tag = oa->oa_tag;
! 195:
! 196: /*
! 197: * For Wombat, Primus and Optimus motherboards, DREQ is
! 198: * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and
! 199: * the SCSI registers are offset 0x1000 bytes from IOBase).
! 200: *
! 201: * For the Q700/900/950 it's at f9800024 for bus 0 and
! 202: * f9800028 for bus 1 (900/950). For these machines, that is also
! 203: * a (12-bit) configuration register for DAFB's control of the
! 204: * pseudo-DMA timing. The default value is 0x1d1.
! 205: */
! 206: esp_have_dreq = esp_dafb_have_dreq;
! 207: if (sc->sc_dev.dv_unit == 0) {
! 208: if (reg_offset == 0x10000) {
! 209: quick = 1;
! 210: esp_have_dreq = esp_iosb_have_dreq;
! 211: } else if (reg_offset == 0x18000) {
! 212: quick = 0;
! 213: } else {
! 214: if (bus_space_map(esc->sc_tag, 0xf9800024,
! 215: 4, 0, &esc->sc_bsh)) {
! 216: printf("failed to map 4 at 0xf9800024.\n");
! 217: } else {
! 218: quick = 1;
! 219: bus_space_write_4(esc->sc_tag,
! 220: esc->sc_bsh, 0, 0x1d1);
! 221: }
! 222: }
! 223: } else {
! 224: if (bus_space_map(esc->sc_tag, 0xf9800028, 4, 0,
! 225: &esc->sc_bsh)) {
! 226: printf("failed to map 4 at 0xf9800028.\n");
! 227: } else {
! 228: quick = 1;
! 229: bus_space_write_4(esc->sc_tag, esc->sc_bsh, 0, 0x1d1);
! 230: }
! 231: }
! 232: if (quick) {
! 233: esp_glue.gl_write_reg = esp_quick_write_reg;
! 234: esp_glue.gl_dma_intr = esp_quick_dma_intr;
! 235: esp_glue.gl_dma_setup = esp_quick_dma_setup;
! 236: esp_glue.gl_dma_go = esp_quick_dma_go;
! 237: }
! 238:
! 239: /*
! 240: * Set up the glue for MI code early; we use some of it here.
! 241: */
! 242: sc->sc_glue = &esp_glue;
! 243:
! 244: esc->sc_ih.vh_fn = esp_intr;
! 245: esc->sc_ih.vh_arg = esc;
! 246: esc->sc_ih.vh_ipl = VIA2_SCSIIRQ;
! 247:
! 248: /*
! 249: * Save the regs
! 250: */
! 251: if (sc->sc_dev.dv_unit == 0) {
! 252: esc->sc_reg = (volatile u_char *) SCSIBase;
! 253: via2_register_irq(&esc->sc_ih, self->dv_xname);
! 254: esc->irq_mask = V2IF_SCSIIRQ;
! 255: if (reg_offset == 0x10000) {
! 256: /* From the Q650 developer's note */
! 257: sc->sc_freq = 16500000;
! 258: } else {
! 259: sc->sc_freq = 25000000;
! 260: }
! 261: } else {
! 262: esc->sc_reg = (volatile u_char *) SCSIBase + 0x402;
! 263: via2_register_irq(&esc->sc_ih, self->dv_xname);
! 264: esc->irq_mask = 0;
! 265: sc->sc_freq = 25000000;
! 266: }
! 267:
! 268: if (quick) {
! 269: printf(" (pseudo-DMA)");
! 270: }
! 271:
! 272: #ifdef DEBUG
! 273: printf(" address %p", esc->sc_reg);
! 274: #endif
! 275:
! 276: sc->sc_id = 7;
! 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 * 1000000) / sc->sc_freq;
! 298:
! 299: /* We need this to fit into the TCR... */
! 300: sc->sc_maxxfer = 64 * 1024;
! 301:
! 302: if (quick == 0) {
! 303: sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */
! 304: sc->sc_maxxfer = 8 * 1024;
! 305: }
! 306:
! 307: /* gimme MHz */
! 308: sc->sc_freq /= 1000000;
! 309:
! 310: /*
! 311: * Configure interrupts.
! 312: */
! 313: if (esc->irq_mask) {
! 314: via2_reg(vPCR) = 0x22;
! 315: via2_reg(vIFR) = esc->irq_mask;
! 316: via2_reg(vIER) = 0x80 | esc->irq_mask;
! 317: }
! 318:
! 319: /*
! 320: * Now try to attach all the sub-devices
! 321: */
! 322: ncr53c9x_attach(sc, &esp_switch, &esp_dev);
! 323: }
! 324:
! 325: /*
! 326: * Glue functions.
! 327: */
! 328:
! 329: u_char
! 330: esp_read_reg(sc, reg)
! 331: struct ncr53c9x_softc *sc;
! 332: int reg;
! 333: {
! 334: struct esp_softc *esc = (struct esp_softc *)sc;
! 335:
! 336: return esc->sc_reg[reg * 16];
! 337: }
! 338:
! 339: void
! 340: esp_write_reg(sc, reg, val)
! 341: struct ncr53c9x_softc *sc;
! 342: int reg;
! 343: u_char val;
! 344: {
! 345: struct esp_softc *esc = (struct esp_softc *)sc;
! 346: u_char v = val;
! 347:
! 348: if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) {
! 349: v = NCRCMD_TRANS;
! 350: }
! 351: esc->sc_reg[reg * 16] = v;
! 352: }
! 353:
! 354: void
! 355: esp_dma_stop(sc)
! 356: struct ncr53c9x_softc *sc;
! 357: {
! 358: }
! 359:
! 360: int
! 361: esp_dma_isactive(sc)
! 362: struct ncr53c9x_softc *sc;
! 363: {
! 364: struct esp_softc *esc = (struct esp_softc *)sc;
! 365:
! 366: return esc->sc_active;
! 367: }
! 368:
! 369: int
! 370: esp_dma_isintr(sc)
! 371: struct ncr53c9x_softc *sc;
! 372: {
! 373: struct esp_softc *esc = (struct esp_softc *)sc;
! 374:
! 375: return esc->sc_reg[NCR_STAT * 16] & 0x80;
! 376: }
! 377:
! 378: void
! 379: esp_dma_reset(sc)
! 380: struct ncr53c9x_softc *sc;
! 381: {
! 382: struct esp_softc *esc = (struct esp_softc *)sc;
! 383:
! 384: esc->sc_active = 0;
! 385: esc->sc_tc = 0;
! 386: }
! 387:
! 388: int
! 389: esp_dma_intr(sc)
! 390: struct ncr53c9x_softc *sc;
! 391: {
! 392: struct esp_softc *esc = (struct esp_softc *)sc;
! 393: volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg;
! 394: u_char *p;
! 395: u_int espphase, espstat, espintr;
! 396: int cnt;
! 397:
! 398: if (esc->sc_active == 0) {
! 399: printf("dma_intr--inactive DMA\n");
! 400: return -1;
! 401: }
! 402:
! 403: if ((sc->sc_espintr & NCRINTR_BS) == 0) {
! 404: esc->sc_active = 0;
! 405: return 0;
! 406: }
! 407:
! 408: cnt = *esc->sc_dmalen;
! 409: if (*esc->sc_dmalen == 0) {
! 410: printf("data interrupt, but no count left.");
! 411: }
! 412:
! 413: p = *esc->sc_dmaaddr;
! 414: espphase = sc->sc_phase;
! 415: espstat = (u_int) sc->sc_espstat;
! 416: espintr = (u_int) sc->sc_espintr;
! 417: cmdreg = esc->sc_reg + NCR_CMD * 16;
! 418: fiforeg = esc->sc_reg + NCR_FIFO * 16;
! 419: statreg = esc->sc_reg + NCR_STAT * 16;
! 420: intrreg = esc->sc_reg + NCR_INTR * 16;
! 421: do {
! 422: if (esc->sc_datain) {
! 423: *p++ = *fiforeg;
! 424: cnt--;
! 425: if (espphase == DATA_IN_PHASE) {
! 426: *cmdreg = NCRCMD_TRANS;
! 427: } else {
! 428: esc->sc_active = 0;
! 429: }
! 430: } else {
! 431: if ( (espphase == DATA_OUT_PHASE)
! 432: || (espphase == MESSAGE_OUT_PHASE)) {
! 433: *fiforeg = *p++;
! 434: cnt--;
! 435: *cmdreg = NCRCMD_TRANS;
! 436: } else {
! 437: esc->sc_active = 0;
! 438: }
! 439: }
! 440:
! 441: if (esc->sc_active) {
! 442: while (!(*statreg & 0x80));
! 443: espstat = *statreg;
! 444: espintr = *intrreg;
! 445: espphase = (espintr & NCRINTR_DIS)
! 446: ? /* Disconnected */ BUSFREE_PHASE
! 447: : espstat & PHASE_MASK;
! 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:
! 463: int
! 464: esp_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:
! 482: void
! 483: esp_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:
! 496: void
! 497: esp_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: u_char v = val;
! 504:
! 505: esc->sc_reg[reg * 16] = v;
! 506: }
! 507:
! 508: int
! 509: esp_quick_dma_intr(sc)
! 510: struct ncr53c9x_softc *sc;
! 511: {
! 512: struct esp_softc *esc = (struct esp_softc *)sc;
! 513: int trans=0, resid=0;
! 514:
! 515: if (esc->sc_active == 0)
! 516: panic("dma_intr--inactive DMA");
! 517:
! 518: esc->sc_active = 0;
! 519:
! 520: if (esc->sc_dmasize == 0) {
! 521: int res;
! 522:
! 523: res = 65536;
! 524: res -= NCR_READ_REG(sc, NCR_TCL);
! 525: res -= NCR_READ_REG(sc, NCR_TCM) << 8;
! 526: printf("dmaintr: discarded %d b (last transfer was %d b).\n",
! 527: res, esc->sc_prevdmasize);
! 528: return 0;
! 529: }
! 530:
! 531: if (esc->sc_datain &&
! 532: (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
! 533: printf("dmaintr: empty FIFO of %d\n", resid);
! 534: DELAY(1);
! 535: }
! 536:
! 537: if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
! 538: resid += NCR_READ_REG(sc, NCR_TCL);
! 539: resid += NCR_READ_REG(sc, NCR_TCM) << 8;
! 540:
! 541: if (resid == 0)
! 542: resid = 65536;
! 543: }
! 544:
! 545: trans = esc->sc_dmasize - resid;
! 546: if (trans < 0) {
! 547: printf("dmaintr: trans < 0????");
! 548: trans = esc->sc_dmasize;
! 549: }
! 550:
! 551: NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid));
! 552: *esc->sc_dmaaddr += trans;
! 553: *esc->sc_dmalen -= trans;
! 554:
! 555: return 0;
! 556: }
! 557:
! 558: int
! 559: esp_quick_dma_setup(sc, addr, len, datain, dmasize)
! 560: struct ncr53c9x_softc *sc;
! 561: caddr_t *addr;
! 562: size_t *len;
! 563: int datain;
! 564: 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: esc->sc_pdmaddr = (u_int16_t *) *addr;
! 572: esc->sc_pdmalen = *len;
! 573:
! 574: if (esc->sc_pdmalen & 1) {
! 575: esc->sc_pdmalen--;
! 576: esc->sc_pad = 1;
! 577: } else {
! 578: esc->sc_pad = 0;
! 579: }
! 580:
! 581: esc->sc_datain = datain;
! 582: esc->sc_prevdmasize = esc->sc_dmasize;
! 583: esc->sc_dmasize = *dmasize;
! 584:
! 585: return 0;
! 586: }
! 587:
! 588: static __inline__ int
! 589: esp_dafb_have_dreq(esc)
! 590: struct esp_softc *esc;
! 591: {
! 592: return (*(volatile u_int32_t *)
! 593: bus_space_vaddr(esc->sc_tag, esc->sc_bsh) & 0x200);
! 594: }
! 595:
! 596: static __inline__ int
! 597: esp_iosb_have_dreq(esc)
! 598: struct esp_softc *esc;
! 599: {
! 600: return (via2_reg(vIFR) & V2IF_SCSIDRQ);
! 601: }
! 602:
! 603: /* Faster spl constructs, without saving old values */
! 604: #define __splx(s) __asm __volatile ("movew %0,sr" : : "di" (s));
! 605: #define __splvm() __splx(mac68k_vmipl)
! 606: #define __splbio() __splx(PSL_S | PSL_IPL2)
! 607:
! 608: void
! 609: esp_quick_dma_go(sc)
! 610: struct ncr53c9x_softc *sc;
! 611: {
! 612: struct esp_softc *esc = (struct esp_softc *)sc;
! 613: extern int *nofault;
! 614: label_t faultbuf;
! 615: u_int16_t volatile *pdma;
! 616: u_char volatile *statreg;
! 617: int espspl;
! 618:
! 619: esc->sc_active = 1;
! 620:
! 621: espspl = splbio();
! 622:
! 623: restart_dmago:
! 624: nofault = (int *) &faultbuf;
! 625: if (setjmp((label_t *) nofault)) {
! 626: int i=0;
! 627:
! 628: nofault = (int *) 0;
! 629: statreg = esc->sc_reg + NCR_STAT * 16;
! 630: for (;;) {
! 631: if (*statreg & 0x80) {
! 632: goto gotintr;
! 633: }
! 634:
! 635: if (esp_have_dreq(esc)) {
! 636: break;
! 637: }
! 638:
! 639: DELAY(1);
! 640: if (i++ > 10000)
! 641: panic("esp_dma_go: Argh!");
! 642: }
! 643: goto restart_dmago;
! 644: }
! 645:
! 646: statreg = esc->sc_reg + NCR_STAT * 16;
! 647: pdma = (u_int16_t *) (esc->sc_reg + 0x100);
! 648:
! 649: #define WAIT while (!esp_have_dreq(esc)) if (*statreg & 0x80) goto gotintr
! 650:
! 651: if (esc->sc_datain == 0) {
! 652: while (esc->sc_pdmalen) {
! 653: WAIT;
! 654: __splvm(); *pdma = *(esc->sc_pdmaddr)++; __splbio();
! 655: esc->sc_pdmalen -= 2;
! 656: }
! 657: if (esc->sc_pad) {
! 658: unsigned short us;
! 659: unsigned char *c;
! 660: c = (unsigned char *) esc->sc_pdmaddr;
! 661: us = *c;
! 662: WAIT;
! 663: __splvm(); *pdma = us; __splbio();
! 664: }
! 665: } else {
! 666: while (esc->sc_pdmalen) {
! 667: WAIT;
! 668: __splvm(); *(esc->sc_pdmaddr)++ = *pdma; __splbio();
! 669: esc->sc_pdmalen -= 2;
! 670: }
! 671: if (esc->sc_pad) {
! 672: unsigned short us;
! 673: unsigned char *c;
! 674: WAIT;
! 675: __splvm(); us = *pdma; __splbio();
! 676: c = (unsigned char *) esc->sc_pdmaddr;
! 677: *c = us & 0xff;
! 678: }
! 679: }
! 680: #undef WAIT
! 681: nofault = (int *) 0;
! 682:
! 683: if ((*statreg & 0x80) == 0) {
! 684: splx(espspl);
! 685: return;
! 686: }
! 687:
! 688: gotintr:
! 689: ncr53c9x_intr(sc);
! 690: splx(espspl);
! 691: }
! 692:
! 693: int
! 694: esp_intr(void *v)
! 695: {
! 696: struct esp_softc *esc = (struct esp_softc *)v;
! 697:
! 698: if (esc->sc_reg[NCR_STAT * 16] & NCRSTAT_INT)
! 699: return (ncr53c9x_intr(v));
! 700:
! 701: return (0);
! 702: }
CVSweb