[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     ! 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