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

Annotation of sys/arch/sparc/dev/dma.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: dma.c,v 1.24 2007/05/29 09:54:07 sobrado Exp $        */
                      2: /*     $NetBSD: dma.c,v 1.46 1997/08/27 11:24:16 bouyer Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1994 Paul Kranenburg.  All rights reserved.
                      6:  * Copyright (c) 1994 Peter Galbavy.  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:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     19:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     20:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     21:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     22:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     23:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     24:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     25:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     26:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/types.h>
                     30: #include <sys/param.h>
                     31: #include <sys/systm.h>
                     32: #include <sys/kernel.h>
                     33: #include <sys/errno.h>
                     34: #include <sys/ioctl.h>
                     35: #include <sys/device.h>
                     36: #include <sys/malloc.h>
                     37: #include <sys/buf.h>
                     38: #include <sys/proc.h>
                     39: #include <sys/user.h>
                     40:
                     41: #include <sparc/autoconf.h>
                     42: #include <sparc/cpu.h>
                     43:
                     44: #include <sparc/sparc/cpuvar.h>
                     45:
                     46: #include <scsi/scsi_all.h>
                     47: #include <scsi/scsiconf.h>
                     48:
                     49: #include <dev/ic/ncr53c9xreg.h>
                     50: #include <dev/ic/ncr53c9xvar.h>
                     51:
                     52: #include <sparc/dev/sbusvar.h>
                     53: #include <sparc/dev/dmareg.h>
                     54: #include <sparc/dev/dmavar.h>
                     55: #include <sparc/dev/espvar.h>
                     56:
                     57: int dmaprint(void *, const char *);
                     58: void dmaattach(struct device *, struct device *, void *);
                     59: int dmamatch(struct device *, void *, void *);
                     60: void dma_reset(struct dma_softc *, int);
                     61: void espdma_reset(struct dma_softc *);
                     62: int ledmamatch(struct device *, void *, void *);
                     63: void ledma_reset(struct dma_softc *);
                     64: void dma_enintr(struct dma_softc *);
                     65: int dma_isintr(struct dma_softc *);
                     66: int espdmaintr(struct dma_softc *);
                     67: int ledmaintr(struct dma_softc *);
                     68: int dma_setup(struct dma_softc *, caddr_t *, size_t *,
                     69:                             int, size_t *);
                     70: void dma_go(struct dma_softc *);
                     71:
                     72: struct cfattach dma_ca = {
                     73:        sizeof(struct dma_softc), dmamatch, dmaattach
                     74: };
                     75:
                     76: struct cfdriver dma_cd = {
                     77:        NULL, "dma", DV_DULL
                     78: };
                     79:
                     80: struct cfattach ledma_ca = {
                     81:        sizeof(struct dma_softc), ledmamatch, dmaattach
                     82: };
                     83:
                     84: struct cfdriver ledma_cd = {
                     85:        NULL, "ledma", DV_DULL
                     86: };
                     87:
                     88: int
                     89: dmaprint(aux, name)
                     90:        void *aux;
                     91:        const char *name;
                     92: {
                     93:        struct confargs *ca = aux;
                     94:
                     95:        if (name)
                     96:                printf("[%s at %s]", ca->ca_ra.ra_name, name);
                     97:        printf(" offset 0x%x", ca->ca_offset);
                     98:        return (UNCONF);
                     99: }
                    100:
                    101: int
                    102: dmamatch(parent, vcf, aux)
                    103:        struct device *parent;
                    104:        void *vcf, *aux;
                    105: {
                    106:        struct cfdata *cf = vcf;
                    107:        struct confargs *ca = aux;
                    108:        struct romaux *ra = &ca->ca_ra;
                    109:
                    110:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
                    111:            strcmp("espdma", ra->ra_name))
                    112:                return (0);
                    113: #if defined(SUN4C) || defined(SUN4M)
                    114:        if (ca->ca_bustype == BUS_SBUS) {
                    115:                if (!sbus_testdma((struct sbus_softc *)parent, ca))
                    116:                        return (0);
                    117:                return (1);
                    118:        }
                    119: #endif
                    120:        ra->ra_len = NBPG;
                    121:        return (probeget(ra->ra_vaddr, 4) != -1);
                    122: }
                    123:
                    124: /*
                    125:  * Attach all the sub-devices we can find
                    126:  */
                    127: void
                    128: dmaattach(parent, self, aux)
                    129:        struct device *parent, *self;
                    130:        void *aux;
                    131: {
                    132:        struct confargs *ca = aux;
                    133:        struct dma_softc *sc = (void *)self;
                    134:        int devnode;
                    135: #if defined(SUN4C) || defined(SUN4M)
                    136:        int node;
                    137:        struct confargs oca;
                    138:        char *name;
                    139: #endif
                    140:
                    141:        if (ca->ca_ra.ra_vaddr == NULL || ca->ca_ra.ra_nvaddrs == 0)
                    142:                ca->ca_ra.ra_vaddr =
                    143:                    mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
                    144:
                    145:        sc->sc_regs = (struct dma_regs *) ca->ca_ra.ra_vaddr;
                    146:        devnode = ca->ca_ra.ra_node;
                    147:
                    148:        /*
                    149:         * If we're a ledma, check to see what cable type is currently
                    150:         * active and set the appropriate bit in the ledma csr so that
                    151:         * it gets used. If we didn't netboot, the PROM won't have the
                    152:         * "cable-selection" property; default to TP and then the user
                    153:         * can change it via a "link0" option to ifconfig.
                    154:         */
                    155:        if (strcmp(ca->ca_ra.ra_name, "ledma") == 0) {
                    156:                char *cabletype = getpropstring(devnode, "cable-selection");
                    157:                if (strcmp(cabletype, "tpe") == 0) {
                    158:                        sc->sc_regs->csr |= E_TP_AUI;
                    159:                } else if (strcmp(cabletype, "aui") == 0) {
                    160:                        sc->sc_regs->csr &= ~E_TP_AUI;
                    161:                } else {
                    162:                        /* assume TP if nothing there */
                    163:                        sc->sc_regs->csr |= E_TP_AUI;
                    164:                }
                    165:                delay(20000);   /* manual says we need 20ms delay */
                    166:        }
                    167:
                    168:        /*
                    169:         * Get transfer burst size from PROM and plug it into the
                    170:         * controller registers. This is needed on the Sun4m; do
                    171:         * others need it too?
                    172:         */
                    173:        if (CPU_ISSUN4M) {
                    174:                int sbusburst = ((struct sbus_softc *)parent)->sc_burst;
                    175:                if (sbusburst == 0)
                    176:                        sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
                    177:
                    178:                sc->sc_burst = getpropint(devnode, "burst-sizes", -1);
                    179:                if (sc->sc_burst == -1)
                    180:                        /* take SBus burst sizes */
                    181:                        sc->sc_burst = sbusburst;
                    182:
                    183:                /* Clamp at parent's burst sizes */
                    184:                sc->sc_burst &= sbusburst;
                    185:        }
                    186:
                    187:        printf(": rev ");
                    188:        sc->sc_rev = sc->sc_regs->csr & D_DEV_ID;
                    189:        switch (sc->sc_rev) {
                    190:        case DMAREV_0:
                    191:                printf("0");
                    192:                break;
                    193:        case DMAREV_ESC:
                    194:                printf("esc");
                    195:                break;
                    196:        case DMAREV_1:
                    197:                printf("1");
                    198:                break;
                    199:        case DMAREV_PLUS:
                    200:                printf("1+");
                    201:                break;
                    202:        case DMAREV_2:
                    203:                printf("2");
                    204:                break;
                    205:        case DMAREV_HME:
                    206:                printf("fas");
                    207:                break;
                    208:        default:
                    209:                printf("unknown (0x%x)", sc->sc_rev);
                    210:        }
                    211:        printf("\n");
                    212:
                    213:        /* indirect functions */
                    214:        dma_setuphandlers(sc);
                    215:
                    216:        if (CPU_ISSUN4)
                    217:                goto espsearch;
                    218:
                    219: #if defined(SUN4C) || defined(SUN4M)
                    220:        /* Propagate bootpath */
                    221:        if (ca->ca_ra.ra_bp != NULL &&
                    222:            (strcmp(ca->ca_ra.ra_bp->name, "espdma") == 0 ||
                    223:             strcmp(ca->ca_ra.ra_bp->name, "dma") == 0 ||
                    224:             strcmp(ca->ca_ra.ra_bp->name, "ledma") == 0))
                    225:                oca.ca_ra.ra_bp = ca->ca_ra.ra_bp + 1;
                    226:        else
                    227:                oca.ca_ra.ra_bp = NULL;
                    228:
                    229:        /* search through children */
                    230:        node = firstchild(devnode);
                    231:        if (node != 0) do {
                    232:                name = getpropstring(node, "name");
                    233:                if (!romprop(&oca.ca_ra, name, node))
                    234:                        continue;
                    235:
                    236:                sbus_translate(parent, &oca);
                    237:                oca.ca_bustype = BUS_SBUS;
                    238:                (void) config_found(&sc->sc_dev, (void *)&oca, dmaprint);
                    239:        } while ((node = nextsibling(node)) != 0); else
                    240: #endif /* SUN4C || SUN4M */
                    241:
                    242:        if (strcmp(ca->ca_ra.ra_name, "dma") == 0) {
                    243: espsearch:
                    244:                /*
                    245:                 * find the ESP by poking around the esp device structures
                    246:                 *
                    247:                 * What happens here is that if the esp driver has not been
                    248:                 * configured, then this returns a NULL pointer. Then when the
                    249:                 * esp actually gets configured, it does the opposing test, and
                    250:                 * if the sc->sc_dma field in its softc is NULL, then tries to
                    251:                 * find the matching dma driver.
                    252:                 *
                    253:                 */
                    254:                sc->sc_esp = (struct esp_softc *)
                    255:                             getdevunit("esp", sc->sc_dev.dv_unit);
                    256:
                    257:                /*
                    258:                 * and a back pointer to us, for DMA
                    259:                 */
                    260:                if (sc->sc_esp)
                    261:                        sc->sc_esp->sc_dma = sc;
                    262:        }
                    263: }
                    264:
                    265: void
                    266: dma_setuphandlers(struct dma_softc *sc)
                    267: {
                    268:        if (sc->sc_dev.dv_cfdata == NULL ||     /* happens on SUNW,fas */
                    269:            sc->sc_dev.dv_cfdata->cf_attach == &dma_ca) {
                    270:                sc->reset = espdma_reset;
                    271:                sc->intr = espdmaintr;
                    272:        } else {
                    273:                sc->reset = ledma_reset;
                    274:                sc->intr = ledmaintr;
                    275:        }
                    276:        sc->enintr = dma_enintr;
                    277:        sc->isintr = dma_isintr;
                    278:        sc->setup = dma_setup;
                    279:        sc->go = dma_go;
                    280: }
                    281:
                    282: #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) {               \
                    283:        int count = 500000;                                             \
                    284:        while ((COND) && --count > 0) DELAY(1);                         \
                    285:        if (count == 0) {                                               \
                    286:                printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \
                    287:                        (SC)->sc_regs->csr);                            \
                    288:                if (DONTPANIC)                                          \
                    289:                        printf(MSG);                                    \
                    290:                else                                                    \
                    291:                        panic(MSG);                                     \
                    292:        }                                                               \
                    293: } while (0)
                    294:
                    295: #define DMA_DRAIN(sc, dontpanic) do {                                  \
                    296:        /*                                                              \
                    297:         * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
                    298:         *     and "drain" bits while it is still thinking about a      \
                    299:         *     request.                                                 \
                    300:         * other revs: D_ESC_R_PEND bit reads as 0                      \
                    301:         */                                                             \
                    302:        DMAWAIT(sc, sc->sc_regs->csr & D_ESC_R_PEND, "R_PEND", dontpanic);\
                    303:        if (sc->sc_rev != DMAREV_HME) {                                 \
                    304:                /*                                                      \
                    305:                 * Select drain bit based on revision                   \
                    306:                 * also clears errors and D_TC flag                     \
                    307:                 */                                                     \
                    308:                if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0)   \
                    309:                        DMACSR(sc) |= D_ESC_DRAIN;                      \
                    310:                else                                                    \
                    311:                        DMACSR(sc) |= D_INVALIDATE;                     \
                    312:        }                                                               \
                    313:        /*                                                              \
                    314:         * Wait for draining to finish                                  \
                    315:         *  rev0 & rev1 call this PACKCNT                               \
                    316:         */                                                             \
                    317:        DMAWAIT(sc, sc->sc_regs->csr & D_DRAINING, "DRAINING", dontpanic);\
                    318: } while(0)
                    319:
                    320: #define DMA_FLUSH(sc, dontpanic) do {                                  \
                    321:        int csr;                                                        \
                    322:        /*                                                              \
                    323:         * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
                    324:         *     and "drain" bits while it is still thinking about a      \
                    325:         *     request.                                                 \
                    326:         * other revs: D_ESC_R_PEND bit reads as 0                      \
                    327:         */                                                             \
                    328:        DMAWAIT(sc, sc->sc_regs->csr & D_ESC_R_PEND, "R_PEND", dontpanic);\
                    329:        csr = DMACSR(sc);                                               \
                    330:        csr &= ~(D_WRITE|D_EN_DMA);     /* no-ops on ENET */            \
                    331:        csr |= D_INVALIDATE;            /* XXX FAS ? */                 \
                    332:        DMACSR(sc) = csr;                                               \
                    333: } while(0)
                    334:
                    335: void
                    336: dma_reset(sc, isledma)
                    337:        struct dma_softc *sc;
                    338:        int isledma;
                    339: {
                    340:        int csr;
                    341:
                    342:        DMA_FLUSH(sc, 1);
                    343:        csr = DMACSR(sc);
                    344:
                    345:        if (sc->sc_rev == DMAREV_HME)
                    346:                DMACSR(sc) = csr | D_HW_RESET_FAS366;
                    347:
                    348:        csr |= D_RESET;                         /* reset DMA */
                    349:        DMACSR(sc) = csr;
                    350:        DELAY(200);                             /* > 10 SBus clocks(?) */
                    351:
                    352:        /*DMAWAIT1(sc); why was this here? */
                    353:        DMACSR(sc) &= ~D_RESET;                 /* de-assert reset line */
                    354:        DELAY(5);
                    355:
                    356:        csr = DMACSR(sc);
                    357:        csr |= D_INT_EN;                        /* enable interrupts */
                    358:        if (sc->sc_rev > DMAREV_1 && isledma == 0) {
                    359:                if (sc->sc_rev == DMAREV_HME)
                    360:                        csr |= D_TWO_CYCLE;
                    361:                else
                    362:                        csr |= D_FASTER;
                    363:        }
                    364:
                    365:        switch (sc->sc_rev) {
                    366:        case DMAREV_HME:
                    367:        case DMAREV_2:
                    368:                csr &= ~L64854_BURST_SIZE; /* must clear first */
                    369:                if (sc->sc_burst & SBUS_BURST_32) {
                    370:                        csr |= L64854_BURST_32;
                    371:                } else if (sc->sc_burst & SBUS_BURST_16) {
                    372:                        csr |= L64854_BURST_16;
                    373:                } else {
                    374:                        csr |= L64854_BURST_0;
                    375:                }
                    376:                break;
                    377:        case DMAREV_ESC:
                    378:                csr |= D_ESC_AUTODRAIN; /* Auto-drain */
                    379:                if (sc->sc_burst & SBUS_BURST_32) {
                    380:                        csr &= ~D_ESC_BURST;
                    381:                } else
                    382:                        csr |= D_ESC_BURST;
                    383:                break;
                    384:        default:
                    385:                break;
                    386:        }
                    387:        DMACSR(sc) = csr;
                    388:
                    389:        if (sc->sc_rev == DMAREV_HME) {
                    390:                DMADDR(sc) = 0;
                    391:                sc->sc_dmactl = csr;
                    392:        }
                    393:
                    394:        sc->sc_active = 0;                      /* and of course we aren't */
                    395: }
                    396:
                    397: void
                    398: espdma_reset(sc)
                    399:        struct dma_softc *sc;
                    400: {
                    401:        dma_reset(sc, 0);
                    402: }
                    403:
                    404: int
                    405: ledmamatch(parent, vcf, aux)
                    406:        struct device *parent;
                    407:        void *vcf, *aux;
                    408: {
                    409:        struct cfdata *cf = vcf;
                    410:        struct confargs *ca = aux;
                    411:        struct romaux *ra = &ca->ca_ra;
                    412:
                    413:         if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
                    414:                return (0);
                    415: #if defined(SUN4C) || defined(SUN4M)
                    416:        if (!sbus_testdma((struct sbus_softc *)parent, ca))
                    417:                return(0);
                    418: #endif
                    419:        return (1);
                    420: }
                    421:
                    422: void
                    423: ledma_reset(sc)
                    424:        struct dma_softc *sc;
                    425: {
                    426:        dma_reset(sc, 1);
                    427: }
                    428:
                    429: void
                    430: dma_enintr(sc)
                    431:        struct dma_softc *sc;
                    432: {
                    433:        sc->sc_regs->csr |= D_INT_EN;
                    434: }
                    435:
                    436: int
                    437: dma_isintr(sc)
                    438:        struct dma_softc *sc;
                    439: {
                    440:        return (sc->sc_regs->csr & (D_INT_PEND|D_ERR_PEND));
                    441: }
                    442:
                    443: #define DMAMAX(a)      (0x01000000 - ((a) & 0x00ffffff))
                    444:
                    445:
                    446: /*
                    447:  * setup a dma transfer
                    448:  */
                    449: int
                    450: dma_setup(sc, addr, len, datain, dmasize)
                    451:        struct dma_softc *sc;
                    452:        caddr_t *addr;
                    453:        size_t *len;
                    454:        int datain;
                    455:        size_t *dmasize;        /* IN-OUT */
                    456: {
                    457:        u_long csr;
                    458:
                    459:        DMA_FLUSH(sc, 0);
                    460:
                    461: #if 0
                    462:        DMACSR(sc) &= ~D_INT_EN;
                    463: #endif
                    464:        sc->sc_dmaaddr = addr;
                    465:        sc->sc_dmalen = len;
                    466:
                    467:        NCR_DMA(("%s: start %d@%p,%d\n", sc->sc_dev.dv_xname,
                    468:                *sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0));
                    469:
                    470:        /*
                    471:         * the rules say we cannot transfer more than the limit
                    472:         * of this DMA chip (64k for old and 16Mb for new),
                    473:         * and we cannot cross a 16Mb boundary.
                    474:         */
                    475:        *dmasize = sc->sc_dmasize =
                    476:                min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
                    477:
                    478:        NCR_DMA(("dma_setup: dmasize = %d\n", sc->sc_dmasize));
                    479:
                    480:        /*
                    481:         * XXX what length?
                    482:         */
                    483:        if (sc->sc_rev == DMAREV_HME) {
                    484:                DMACSR(sc) = sc->sc_dmactl | L64854_RESET;
                    485:                DMACSR(sc) = sc->sc_dmactl;
                    486:                DMACNT(sc) = *dmasize;
                    487:        }
                    488:
                    489:        /* Program the DMA address */
                    490:        if (CPU_ISSUN4M && sc->sc_dmasize) {
                    491:                /*
                    492:                 * Use dvma mapin routines to map the buffer into DVMA space.
                    493:                 */
                    494:                sc->sc_dvmaaddr = *sc->sc_dmaaddr;
                    495:                sc->sc_dvmakaddr = kdvma_mapin(sc->sc_dvmaaddr,
                    496:                                               sc->sc_dmasize, 0);
                    497:                if (sc->sc_dvmakaddr == NULL)
                    498:                        panic("dma: cannot allocate DVMA address");
                    499:                DMADDR(sc) = sc->sc_dvmakaddr;
                    500:        } else
                    501:                DMADDR(sc) = *sc->sc_dmaaddr;
                    502:
                    503:        if (sc->sc_rev == DMAREV_ESC) {
                    504:                /* DMA ESC chip bug work-around */
                    505:                long bcnt = sc->sc_dmasize;
                    506:                long eaddr = bcnt + (long)*sc->sc_dmaaddr;
                    507:                if ((eaddr & PGOFSET) != 0)
                    508:                        bcnt = round_page(bcnt);
                    509:                DMACNT(sc) = bcnt;
                    510:        }
                    511:        /* Setup DMA control register */
                    512:        csr = DMACSR(sc);
                    513:        if (datain)
                    514:                csr |= D_WRITE;
                    515:        else
                    516:                csr &= ~D_WRITE;
                    517:        csr |= D_INT_EN;
                    518:
                    519:        if (sc->sc_rev == DMAREV_HME) {
                    520:                csr |= (D_DSBL_SCSI_DRN | D_EN_DMA);
                    521:        }
                    522:
                    523:        DMACSR(sc) = csr;
                    524:
                    525:        return 0;
                    526: }
                    527:
                    528: void
                    529: dma_go(sc)
                    530:        struct dma_softc *sc;
                    531: {
                    532:
                    533:        /* Start DMA */
                    534:        DMACSR(sc) |= D_EN_DMA;
                    535:        sc->sc_active = 1;
                    536: }
                    537:
                    538: /*
                    539:  * Pseudo (chained) interrupt from the esp driver to kick the
                    540:  * current running DMA transfer. I am replying on espintr() to
                    541:  * pickup and clean errors for now
                    542:  *
                    543:  * return 1 if it was a DMA continue.
                    544:  */
                    545: int
                    546: espdmaintr(sc)
                    547:        struct dma_softc *sc;
                    548: {
                    549:        struct ncr53c9x_softc *nsc = &sc->sc_esp->sc_ncr53c9x;
                    550:        int trans, resid;
                    551:        u_long csr;
                    552:
                    553:        csr = DMACSR(sc);
                    554:
                    555:        NCR_DMA(("%s: intr: addr %p, csr %b\n", sc->sc_dev.dv_xname,
                    556:                 DMADDR(sc), csr, DDMACSR_BITS));
                    557:
                    558:        if (csr & (D_ERR_PEND|D_SLAVE_ERR)) {
                    559:                printf("%s: error: csr=%b\n", sc->sc_dev.dv_xname,
                    560:                        csr, DDMACSR_BITS);
                    561:                DMACSR(sc) &= ~D_EN_DMA;        /* Stop DMA */
                    562:                /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
                    563:                DMACSR(sc) |= D_INVALIDATE|D_SLAVE_ERR;
                    564:                return (-1);
                    565:        }
                    566:
                    567:        /* This is an "assertion" :) */
                    568:        if (sc->sc_active == 0)
                    569:                panic("dmaintr: DMA wasn't active");
                    570:
                    571:        DMA_DRAIN(sc, 0);
                    572:
                    573:        /* DMA has stopped */
                    574:        DMACSR(sc) &= ~D_EN_DMA;
                    575:        sc->sc_active = 0;
                    576:
                    577:        if (sc->sc_dmasize == 0) {
                    578:                /* A "Transfer Pad" operation completed */
                    579:                NCR_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n",
                    580:                        NCR_READ_REG(nsc, NCR_TCL) |
                    581:                                (NCR_READ_REG(nsc, NCR_TCM) << 8),
                    582:                        NCR_READ_REG(nsc, NCR_TCL),
                    583:                        NCR_READ_REG(nsc, NCR_TCM)));
                    584:                return 0;
                    585:        }
                    586:
                    587:        resid = 0;
                    588:        /*
                    589:         * If a transfer onto the SCSI bus gets interrupted by the device
                    590:         * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
                    591:         * as residual since the ESP counter registers get decremented as
                    592:         * bytes are clocked into the FIFO.
                    593:         */
                    594:        if (!(csr & D_WRITE) &&
                    595:            (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
                    596:                NCR_DMA(("dmaintr: empty esp FIFO of %d ", resid));
                    597:        }
                    598:
                    599:        if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
                    600:                /*
                    601:                 * `Terminal count' is off, so read the residue
                    602:                 * out of the ESP counter registers.
                    603:                 */
                    604:                resid += (NCR_READ_REG(nsc, NCR_TCL) |
                    605:                          (NCR_READ_REG(nsc, NCR_TCM) << 8) |
                    606:                           ((nsc->sc_cfg2 & NCRCFG2_FE)
                    607:                                ? (NCR_READ_REG(nsc, NCR_TCH) << 16)
                    608:                                : 0));
                    609:
                    610:                if (resid == 0 && sc->sc_dmasize == 65536 &&
                    611:                    (nsc->sc_cfg2 & NCRCFG2_FE) == 0)
                    612:                        /* A transfer of 64K is encoded as `TCL=TCM=0' */
                    613:                        resid = 65536;
                    614:        }
                    615:
                    616:        trans = sc->sc_dmasize - resid;
                    617:        if (trans < 0) {                        /* transferred < 0 ? */
                    618: #if 0
                    619:                /*
                    620:                 * This situation can happen in perfectly normal operation
                    621:                 * if the ESP is reselected while using DMA to select
                    622:                 * another target.  As such, don't print the warning.
                    623:                 */
                    624:                printf("%s: xfer (%d) > req (%d)\n",
                    625:                    sc->sc_dev.dv_xname, trans, sc->sc_dmasize);
                    626: #endif
                    627:                trans = sc->sc_dmasize;
                    628:        }
                    629:
                    630:        NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
                    631:                NCR_READ_REG(nsc, NCR_TCL),
                    632:                NCR_READ_REG(nsc, NCR_TCM),
                    633:                (nsc->sc_cfg2 & NCRCFG2_FE)
                    634:                        ? NCR_READ_REG(nsc, NCR_TCH) : 0,
                    635:                trans, resid));
                    636:
                    637:        if (csr & D_WRITE)
                    638:                cpuinfo.cache_flush(*sc->sc_dmaaddr, trans);
                    639:
                    640:        if (CPU_ISSUN4M && sc->sc_dvmakaddr)
                    641:                dvma_mapout((vaddr_t)sc->sc_dvmakaddr,
                    642:                            (vaddr_t)sc->sc_dvmaaddr, sc->sc_dmasize);
                    643:
                    644:        *sc->sc_dmalen -= trans;
                    645:        *sc->sc_dmaaddr += trans;
                    646:
                    647: #if 0  /* this is not normal operation just yet */
                    648:        if (*sc->sc_dmalen == 0 ||
                    649:            nsc->sc_phase != nsc->sc_prevphase)
                    650:                return 0;
                    651:
                    652:        /* and again */
                    653:        dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
                    654:        return 1;
                    655: #endif
                    656:        return 0;
                    657: }
                    658:
                    659: /*
                    660:  * Pseudo (chained) interrupt from the le driver to handle DMA
                    661:  * errors.
                    662:  *
                    663:  * XXX: untested
                    664:  */
                    665: int
                    666: ledmaintr(sc)
                    667:        struct dma_softc *sc;
                    668: {
                    669:        u_long csr;
                    670:
                    671:        csr = DMACSR(sc);
                    672:
                    673:        if (csr & D_ERR_PEND) {
                    674:                DMACSR(sc) &= ~D_EN_DMA;        /* Stop DMA */
                    675:                DMACSR(sc) |= D_INVALIDATE;
                    676:                printf("%s: error: csr=%b\n", sc->sc_dev.dv_xname,
                    677:                        csr, DDMACSR_BITS);
                    678:                DMA_RESET(sc);
                    679:        }
                    680:        return 1;
                    681: }

CVSweb