[BACK]Return to esp.c CVS log [TXT][DIR] Up to [local] / sys / arch / mac68k / dev

Annotation of sys/arch/mac68k/dev/esp.c, Revision 1.1.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