[BACK]Return to lsi64854.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/lsi64854.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: lsi64854.c,v 1.8 2007/02/28 18:48:35 miod Exp $       */
        !             2: /*     $NetBSD: lsi64854.c,v 1.18 2001/06/04 20:56:51 mrg Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Paul Kranenburg.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: #include <sys/types.h>
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/kernel.h>
        !            44: #include <sys/errno.h>
        !            45: #include <sys/device.h>
        !            46:
        !            47: #include <uvm/uvm_extern.h>
        !            48:
        !            49: #include <machine/bus.h>
        !            50: #include <machine/autoconf.h>
        !            51: #include <machine/cpu.h>
        !            52:
        !            53: #include <scsi/scsi_all.h>
        !            54: #include <scsi/scsiconf.h>
        !            55:
        !            56: #include <dev/ic/lsi64854reg.h>
        !            57: #include <dev/ic/lsi64854var.h>
        !            58:
        !            59: #include <dev/ic/ncr53c9xreg.h>
        !            60: #include <dev/ic/ncr53c9xvar.h>
        !            61:
        !            62: void   lsi64854_reset(struct lsi64854_softc *);
        !            63: int    lsi64854_setup(struct lsi64854_softc *, caddr_t *, size_t *,
        !            64:                             int, size_t *);
        !            65: int    lsi64854_setup_pp(struct lsi64854_softc *, caddr_t *, size_t *,
        !            66:                             int, size_t *);
        !            67: int    lsi64854_scsi_intr(void *);
        !            68: int    lsi64854_pp_intr(void *);
        !            69:
        !            70: #ifdef DEBUG
        !            71: #define LDB_SCSI       1
        !            72: #define LDB_ENET       2
        !            73: #define LDB_PP         4
        !            74: #define LDB_ANY                0xff
        !            75: int lsi64854debug = 0;
        !            76: #define DPRINTF(a,x) do { if (lsi64854debug & (a)) printf x ; } while (0)
        !            77: #else
        !            78: #define DPRINTF(a,x)
        !            79: #endif
        !            80:
        !            81: #define MAX_DMA_SZ     (16*1024*1024)
        !            82:
        !            83: /*
        !            84:  * Finish attaching this DMA device.
        !            85:  * Front-end must fill in these fields:
        !            86:  *     sc_bustag
        !            87:  *     sc_dmatag
        !            88:  *     sc_regs
        !            89:  *     sc_burst
        !            90:  *     sc_channel (one of SCSI, ENET, PP)
        !            91:  *     sc_client (one of SCSI, ENET, PP `soft_c' pointers)
        !            92:  */
        !            93: int
        !            94: lsi64854_attach(sc)
        !            95:        struct lsi64854_softc *sc;
        !            96: {
        !            97:        u_int32_t csr;
        !            98:        int rc;
        !            99:
        !           100:        /* Indirect functions */
        !           101:        switch (sc->sc_channel) {
        !           102:        case L64854_CHANNEL_SCSI:
        !           103:                sc->intr = lsi64854_scsi_intr;
        !           104:                sc->setup = lsi64854_setup;
        !           105:                break;
        !           106:        case L64854_CHANNEL_ENET:
        !           107:                sc->intr = lsi64854_enet_intr;
        !           108:                sc->setup = lsi64854_setup;
        !           109:                break;
        !           110:        case L64854_CHANNEL_PP:
        !           111:                sc->intr = lsi64854_pp_intr;
        !           112:                sc->setup = lsi64854_setup_pp;
        !           113:                break;
        !           114:        default:
        !           115:                printf("%s: unknown channel\n", sc->sc_dev.dv_xname);
        !           116:        }
        !           117:        sc->reset = lsi64854_reset;
        !           118:
        !           119:        /* Allocate a dmamap */
        !           120:        if ((rc = bus_dmamap_create(sc->sc_dmatag, MAX_DMA_SZ, 1, MAX_DMA_SZ,
        !           121:                              0, BUS_DMA_WAITOK, &sc->sc_dmamap)) != 0) {
        !           122:                printf(": dma map create failed\n");
        !           123:                return (rc);
        !           124:        }
        !           125:
        !           126:        printf(": dma rev ");
        !           127:        csr = L64854_GCSR(sc);
        !           128:        sc->sc_rev = csr & L64854_DEVID;
        !           129:        switch (sc->sc_rev) {
        !           130:        case DMAREV_0:
        !           131:                printf("0");
        !           132:                break;
        !           133:        case DMAREV_ESC:
        !           134:                printf("esc");
        !           135:                break;
        !           136:        case DMAREV_1:
        !           137:                printf("1");
        !           138:                break;
        !           139:        case DMAREV_PLUS:
        !           140:                printf("1+");
        !           141:                break;
        !           142:        case DMAREV_2:
        !           143:                printf("2");
        !           144:                break;
        !           145:        case DMAREV_HME:
        !           146:                printf("fas");
        !           147:                break;
        !           148:        default:
        !           149:                printf("unknown (0x%x)", sc->sc_rev);
        !           150:        }
        !           151:
        !           152:        DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr));
        !           153:        printf("\n");
        !           154:
        !           155:        return (0);
        !           156: }
        !           157:
        !           158: /*
        !           159:  * DMAWAIT  waits while condition is true
        !           160:  */
        !           161: #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) {               \
        !           162:        int count = 500000;                                             \
        !           163:        while ((COND) && --count > 0) DELAY(1);                         \
        !           164:        if (count == 0) {                                               \
        !           165:                printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \
        !           166:                        (u_long)L64854_GCSR(SC));                       \
        !           167:                if (DONTPANIC)                                          \
        !           168:                        printf(MSG);                                    \
        !           169:                else                                                    \
        !           170:                        panic(MSG);                                     \
        !           171:        }                                                               \
        !           172: } while (0)
        !           173:
        !           174: #define DMA_DRAIN(sc, dontpanic) do {                                  \
        !           175:        u_int32_t csr;                                                  \
        !           176:        /*                                                              \
        !           177:         * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
        !           178:         *     and "drain" bits while it is still thinking about a      \
        !           179:         *     request.                                                 \
        !           180:         * other revs: D_ESC_R_PEND bit reads as 0                      \
        !           181:         */                                                             \
        !           182:        DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
        !           183:        if (sc->sc_rev != DMAREV_HME) {                                 \
        !           184:                /*                                                      \
        !           185:                 * Select drain bit based on revision                   \
        !           186:                 * also clears errors and D_TC flag                     \
        !           187:                 */                                                     \
        !           188:                csr = L64854_GCSR(sc);                                  \
        !           189:                if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0)   \
        !           190:                        csr |= D_ESC_DRAIN;                             \
        !           191:                else                                                    \
        !           192:                        csr |= L64854_INVALIDATE;                       \
        !           193:                                                                        \
        !           194:                L64854_SCSR(sc,csr);                                    \
        !           195:        }                                                               \
        !           196:        /*                                                              \
        !           197:         * Wait for draining to finish                                  \
        !           198:         *  rev0 & rev1 call this PACKCNT                               \
        !           199:         */                                                             \
        !           200:        DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", dontpanic);\
        !           201: } while(0)
        !           202:
        !           203: #define DMA_FLUSH(sc, dontpanic) do {                                  \
        !           204:        u_int32_t csr;                                                  \
        !           205:        /*                                                              \
        !           206:         * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
        !           207:         *     and "drain" bits while it is still thinking about a      \
        !           208:         *     request.                                                 \
        !           209:         * other revs: D_ESC_R_PEND bit reads as 0                      \
        !           210:         */                                                             \
        !           211:        DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
        !           212:        csr = L64854_GCSR(sc);                                  \
        !           213:        csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */      \
        !           214:        csr |= L64854_INVALIDATE;               /* XXX FAS ? */         \
        !           215:        L64854_SCSR(sc,csr);                                            \
        !           216: } while(0)
        !           217:
        !           218: void
        !           219: lsi64854_reset(sc)
        !           220:        struct lsi64854_softc *sc;
        !           221: {
        !           222:        u_int32_t csr;
        !           223:
        !           224:        DMA_FLUSH(sc, 1);
        !           225:        csr = L64854_GCSR(sc);
        !           226:
        !           227:        DPRINTF(LDB_ANY, ("lsi64854_reset: csr 0x%x\n", csr));
        !           228:
        !           229:        /*
        !           230:         * XXX is sync needed?
        !           231:         */
        !           232:        if (sc->sc_dmamap->dm_nsegs > 0)
        !           233:                bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
        !           234:
        !           235:        if (sc->sc_rev == DMAREV_HME)
        !           236:                L64854_SCSR(sc, csr | D_HW_RESET_FAS366);
        !           237:
        !           238:
        !           239:        csr |= L64854_RESET;            /* reset DMA */
        !           240:        L64854_SCSR(sc, csr);
        !           241:        DELAY(200);                     /* > 10 Sbus clocks(?) */
        !           242:
        !           243:        /*DMAWAIT1(sc); why was this here? */
        !           244:        csr = L64854_GCSR(sc);
        !           245:        csr &= ~L64854_RESET;           /* de-assert reset line */
        !           246:        L64854_SCSR(sc, csr);
        !           247:        DELAY(5);                       /* allow a few ticks to settle */
        !           248:
        !           249:        csr = L64854_GCSR(sc);
        !           250:        csr |= L64854_INT_EN;           /* enable interrupts */
        !           251:        if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) {
        !           252:                if (sc->sc_rev == DMAREV_HME)
        !           253:                        csr |= D_TWO_CYCLE;
        !           254:                else
        !           255:                        csr |= D_FASTER;
        !           256:        }
        !           257:
        !           258:        /* Set burst */
        !           259:        switch (sc->sc_rev) {
        !           260:        case DMAREV_HME:
        !           261:        case DMAREV_2:
        !           262:                csr &= ~L64854_BURST_SIZE;
        !           263:                if (sc->sc_burst == 32) {
        !           264:                        csr |= L64854_BURST_32;
        !           265:                } else if (sc->sc_burst == 16) {
        !           266:                        csr |= L64854_BURST_16;
        !           267:                } else {
        !           268:                        csr |= L64854_BURST_0;
        !           269:                }
        !           270:                break;
        !           271:        case DMAREV_ESC:
        !           272:                csr |= D_ESC_AUTODRAIN; /* Auto-drain */
        !           273:                if (sc->sc_burst == 32) {
        !           274:                        csr &= ~D_ESC_BURST;
        !           275:                } else
        !           276:                        csr |= D_ESC_BURST;
        !           277:                break;
        !           278:        default:
        !           279:                break;
        !           280:        }
        !           281:        L64854_SCSR(sc, csr);
        !           282:
        !           283:        if (sc->sc_rev == DMAREV_HME) {
        !           284:                bus_space_write_4(sc->sc_bustag, sc->sc_regs, L64854_REG_ADDR, 0);
        !           285:                sc->sc_dmactl = csr;
        !           286:        }
        !           287:        sc->sc_active = 0;
        !           288:
        !           289:        DPRINTF(LDB_ANY, ("lsi64854_reset: done, csr 0x%x\n", csr));
        !           290: }
        !           291:
        !           292:
        !           293: #define DMAMAX(a)      (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ-1)))
        !           294: /*
        !           295:  * setup a dma transfer
        !           296:  */
        !           297: int
        !           298: lsi64854_setup(sc, addr, len, datain, dmasize)
        !           299:        struct lsi64854_softc *sc;
        !           300:        caddr_t *addr;
        !           301:        size_t *len;
        !           302:        int datain;
        !           303:        size_t *dmasize;        /* IN-OUT */
        !           304: {
        !           305:        u_int32_t csr;
        !           306:
        !           307:        DMA_FLUSH(sc, 0);
        !           308:
        !           309: #if 0
        !           310:        DMACSR(sc) &= ~D_INT_EN;
        !           311: #endif
        !           312:        sc->sc_dmaaddr = addr;
        !           313:        sc->sc_dmalen = len;
        !           314:
        !           315:        /*
        !           316:         * the rules say we cannot transfer more than the limit
        !           317:         * of this DMA chip (64k for old and 16Mb for new),
        !           318:         * and we cannot cross a 16Mb boundary.
        !           319:         */
        !           320:        *dmasize = sc->sc_dmasize =
        !           321:                min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
        !           322:
        !           323:        DPRINTF(LDB_ANY, ("dma_setup: dmasize = %ld\n", (long)sc->sc_dmasize));
        !           324:
        !           325:        /*
        !           326:         * XXX what length?
        !           327:         */
        !           328:        if (sc->sc_rev == DMAREV_HME) {
        !           329:
        !           330:                L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET);
        !           331:                L64854_SCSR(sc, sc->sc_dmactl);
        !           332:
        !           333:                bus_space_write_4(sc->sc_bustag, sc->sc_regs, L64854_REG_CNT, *dmasize);
        !           334:        }
        !           335:
        !           336:        /* Program the DMA address */
        !           337:        if (sc->sc_dmasize) {
        !           338:                sc->sc_dvmaaddr = *sc->sc_dmaaddr;
        !           339:                if (bus_dmamap_load(sc->sc_dmatag, sc->sc_dmamap,
        !           340:                                *sc->sc_dmaaddr, sc->sc_dmasize,
        !           341:                                NULL /* kernel address */,
        !           342:                                BUS_DMA_NOWAIT | BUS_DMA_STREAMING))
        !           343:                        panic("%s: cannot allocate DVMA address",
        !           344:                              sc->sc_dev.dv_xname);
        !           345:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, 0, sc->sc_dmasize,
        !           346:                                datain
        !           347:                                        ? BUS_DMASYNC_PREREAD
        !           348:                                        : BUS_DMASYNC_PREWRITE);
        !           349:                bus_space_write_4(sc->sc_bustag, sc->sc_regs, L64854_REG_ADDR,
        !           350:                                  sc->sc_dmamap->dm_segs[0].ds_addr);
        !           351:        }
        !           352:
        !           353:        if (sc->sc_rev == DMAREV_ESC) {
        !           354:                /* DMA ESC chip bug work-around */
        !           355:                long bcnt = sc->sc_dmasize;
        !           356:                long eaddr = bcnt + (long)*sc->sc_dmaaddr;
        !           357:                if ((eaddr & PGOFSET) != 0)
        !           358:                        bcnt = roundup(bcnt, PAGE_SIZE);
        !           359:                bus_space_write_4(sc->sc_bustag, sc->sc_regs, L64854_REG_CNT,
        !           360:                                  bcnt);
        !           361:        }
        !           362:
        !           363:        /* Setup DMA control register */
        !           364:        csr = L64854_GCSR(sc);
        !           365:
        !           366:        if (datain)
        !           367:                csr |= L64854_WRITE;
        !           368:        else
        !           369:                csr &= ~L64854_WRITE;
        !           370:        csr |= L64854_INT_EN;
        !           371:
        !           372:        if (sc->sc_rev == DMAREV_HME) {
        !           373:                csr |= (D_DSBL_SCSI_DRN | D_EN_DMA);
        !           374:        }
        !           375:
        !           376:        L64854_SCSR(sc, csr);
        !           377:
        !           378:        return (0);
        !           379: }
        !           380:
        !           381: /*
        !           382:  * Pseudo (chained) interrupt from the esp driver to kick the
        !           383:  * current running DMA transfer. Called from ncr53c9x_intr()
        !           384:  * for now.
        !           385:  *
        !           386:  * return 1 if it was a DMA continue.
        !           387:  */
        !           388: int
        !           389: lsi64854_scsi_intr(arg)
        !           390:        void *arg;
        !           391: {
        !           392:        struct lsi64854_softc *sc = arg;
        !           393:        struct ncr53c9x_softc *nsc = sc->sc_client;
        !           394:        char bits[64];
        !           395:        int trans, resid;
        !           396:        u_int32_t csr;
        !           397:
        !           398:        csr = L64854_GCSR(sc);
        !           399:
        !           400:        DPRINTF(LDB_SCSI, ("%s: dmaintr: addr 0x%x, csr %b\n", sc->sc_dev.dv_xname,
        !           401:            bus_space_read_4(sc->sc_bustag, sc->sc_regs, L64854_REG_ADDR),
        !           402:            csr, DDMACSR_BITS));
        !           403:
        !           404:        if (csr & (D_ERR_PEND|D_SLAVE_ERR)) {
        !           405:                snprintf(bits, sizeof(bits), "%b", csr, DDMACSR_BITS);
        !           406:                printf("%s: error: csr=%s\n", sc->sc_dev.dv_xname, bits);
        !           407:                csr &= ~D_EN_DMA;       /* Stop DMA */
        !           408:                /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
        !           409:                csr |= D_INVALIDATE|D_SLAVE_ERR;
        !           410:                L64854_SCSR(sc, csr);
        !           411:                return (-1);
        !           412:        }
        !           413:
        !           414:        /* This is an "assertion" :) */
        !           415:        if (sc->sc_active == 0)
        !           416:                panic("dmaintr: DMA wasn't active");
        !           417:
        !           418:        DMA_DRAIN(sc, 0);
        !           419:
        !           420:        /* DMA has stopped */
        !           421:        csr &= ~D_EN_DMA;
        !           422:        L64854_SCSR(sc, csr);
        !           423:        sc->sc_active = 0;
        !           424:
        !           425:        if (sc->sc_dmasize == 0) {
        !           426:                /* A "Transfer Pad" operation completed */
        !           427:                DPRINTF(LDB_SCSI, ("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n",
        !           428:                        NCR_READ_REG(nsc, NCR_TCL) |
        !           429:                                (NCR_READ_REG(nsc, NCR_TCM) << 8),
        !           430:                        NCR_READ_REG(nsc, NCR_TCL),
        !           431:                        NCR_READ_REG(nsc, NCR_TCM)));
        !           432:                return 0;
        !           433:        }
        !           434:
        !           435:        resid = 0;
        !           436:        /*
        !           437:         * If a transfer onto the SCSI bus gets interrupted by the device
        !           438:         * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
        !           439:         * as residual since the NCR53C9X counter registers get decremented
        !           440:         * as bytes are clocked into the FIFO.
        !           441:         */
        !           442:        if (!(csr & D_WRITE) &&
        !           443:            (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
        !           444:                DPRINTF(LDB_SCSI, ("dmaintr: empty esp FIFO of %d ", resid));
        !           445:                if (nsc->sc_rev == NCR_VARIANT_FAS366 &&
        !           446:                    (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE))
        !           447:                        resid <<= 1;
        !           448:        }
        !           449:
        !           450:        if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
        !           451:                /*
        !           452:                 * `Terminal count' is off, so read the residue
        !           453:                 * out of the NCR53C9X counter registers.
        !           454:                 */
        !           455:                resid += (NCR_READ_REG(nsc, NCR_TCL) |
        !           456:                          (NCR_READ_REG(nsc, NCR_TCM) << 8) |
        !           457:                           ((nsc->sc_cfg2 & NCRCFG2_FE)
        !           458:                                ? (NCR_READ_REG(nsc, NCR_TCH) << 16)
        !           459:                                : 0));
        !           460:
        !           461:                if (resid == 0 && sc->sc_dmasize == 65536 &&
        !           462:                    (nsc->sc_cfg2 & NCRCFG2_FE) == 0)
        !           463:                        /* A transfer of 64K is encoded as `TCL=TCM=0' */
        !           464:                        resid = 65536;
        !           465:        }
        !           466:
        !           467:        trans = sc->sc_dmasize - resid;
        !           468:        if (trans < 0) {                        /* transferred < 0 ? */
        !           469: #if 0
        !           470:                /*
        !           471:                 * This situation can happen in perfectly normal operation
        !           472:                 * if the ESP is reselected while using DMA to select
        !           473:                 * another target.  As such, don't print the warning.
        !           474:                 */
        !           475:                printf("%s: xfer (%d) > req (%d)\n",
        !           476:                    sc->sc_dev.dv_xname, trans, sc->sc_dmasize);
        !           477: #endif
        !           478:                trans = sc->sc_dmasize;
        !           479:        }
        !           480:
        !           481:        DPRINTF(LDB_SCSI, ("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
        !           482:                NCR_READ_REG(nsc, NCR_TCL),
        !           483:                NCR_READ_REG(nsc, NCR_TCM),
        !           484:                (nsc->sc_cfg2 & NCRCFG2_FE)
        !           485:                        ? NCR_READ_REG(nsc, NCR_TCH) : 0,
        !           486:                trans, resid));
        !           487:
        !           488:        if (sc->sc_dmamap->dm_nsegs > 0) {
        !           489:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, 0, sc->sc_dmasize,
        !           490:                                (csr & D_WRITE) != 0
        !           491:                                        ? BUS_DMASYNC_POSTREAD
        !           492:                                        : BUS_DMASYNC_POSTWRITE);
        !           493:                bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
        !           494:        }
        !           495:
        !           496:        *sc->sc_dmalen -= trans;
        !           497:        *sc->sc_dmaaddr += trans;
        !           498:
        !           499: #if 0  /* this is not normal operation just yet */
        !           500:        if (*sc->sc_dmalen == 0 ||
        !           501:            nsc->sc_phase != nsc->sc_prevphase)
        !           502:                return 0;
        !           503:
        !           504:        /* and again */
        !           505:        dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
        !           506:        return 1;
        !           507: #endif
        !           508:        return 0;
        !           509: }
        !           510:
        !           511: /*
        !           512:  * Pseudo (chained) interrupt to le driver to handle DMA errors.
        !           513:  */
        !           514: int
        !           515: lsi64854_enet_intr(arg)
        !           516:        void    *arg;
        !           517: {
        !           518:        struct lsi64854_softc *sc = arg;
        !           519:        char bits[64];
        !           520:        u_int32_t csr;
        !           521:        static int dodrain = 0;
        !           522:        int rv;
        !           523:
        !           524:        csr = L64854_GCSR(sc);
        !           525:
        !           526:        /* If the DMA logic shows an interrupt, claim it */
        !           527:        rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
        !           528:
        !           529:        if (csr & (E_ERR_PEND|E_SLAVE_ERR)) {
        !           530:                snprintf(bits, sizeof(bits), "%b", csr, EDMACSR_BITS);
        !           531:                printf("%s: error: csr=%s\n", sc->sc_dev.dv_xname, bits);
        !           532:                csr &= ~L64854_EN_DMA;  /* Stop DMA */
        !           533:                /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
        !           534:                csr |= E_INVALIDATE|E_SLAVE_ERR;
        !           535:                L64854_SCSR(sc, csr);
        !           536:                DMA_RESET(sc);
        !           537:                dodrain = 1;
        !           538:                return (1);
        !           539:        }
        !           540:
        !           541:        if (dodrain) {  /* XXX - is this necessary with D_DSBL_WRINVAL on? */
        !           542:                int i = 10;
        !           543:                csr |= E_DRAIN;
        !           544:                L64854_SCSR(sc, csr);
        !           545:                while (i-- > 0 && (L64854_GCSR(sc) & D_DRAINING))
        !           546:                        delay(1);
        !           547:        }
        !           548:
        !           549:        return (rv | (*sc->sc_intrchain)(sc->sc_intrchainarg));
        !           550: }
        !           551:
        !           552: /*
        !           553:  * setup a dma transfer
        !           554:  */
        !           555: int
        !           556: lsi64854_setup_pp(sc, addr, len, datain, dmasize)
        !           557:        struct lsi64854_softc *sc;
        !           558:        caddr_t *addr;
        !           559:        size_t *len;
        !           560:        int datain;
        !           561:        size_t *dmasize;        /* IN-OUT */
        !           562: {
        !           563:        u_int32_t csr;
        !           564:
        !           565:        DMA_FLUSH(sc, 0);
        !           566:
        !           567:        sc->sc_dmaaddr = addr;
        !           568:        sc->sc_dmalen = len;
        !           569:
        !           570:        DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", sc->sc_dev.dv_xname,
        !           571:                (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0));
        !           572:
        !           573:        /*
        !           574:         * the rules say we cannot transfer more than the limit
        !           575:         * of this DMA chip (64k for old and 16Mb for new),
        !           576:         * and we cannot cross a 16Mb boundary.
        !           577:         */
        !           578:        *dmasize = sc->sc_dmasize =
        !           579:                min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
        !           580:
        !           581:        DPRINTF(LDB_PP, ("dma_setup_pp: dmasize = %ld\n", (long)sc->sc_dmasize));
        !           582:
        !           583:        /* Program the DMA address */
        !           584:        if (sc->sc_dmasize) {
        !           585:                sc->sc_dvmaaddr = *sc->sc_dmaaddr;
        !           586:                if (bus_dmamap_load(sc->sc_dmatag, sc->sc_dmamap,
        !           587:                                *sc->sc_dmaaddr, sc->sc_dmasize,
        !           588:                                NULL /* kernel address */,
        !           589:                                    BUS_DMA_NOWAIT/*|BUS_DMA_COHERENT*/))
        !           590:                        panic("%s: pp cannot allocate DVMA address",
        !           591:                              sc->sc_dev.dv_xname);
        !           592:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, 0, sc->sc_dmasize,
        !           593:                                datain
        !           594:                                        ? BUS_DMASYNC_PREREAD
        !           595:                                        : BUS_DMASYNC_PREWRITE);
        !           596:                bus_space_write_4(sc->sc_bustag, sc->sc_regs, L64854_REG_ADDR,
        !           597:                                  sc->sc_dmamap->dm_segs[0].ds_addr);
        !           598:
        !           599:                bus_space_write_4(sc->sc_bustag, sc->sc_regs, L64854_REG_CNT,
        !           600:                                  sc->sc_dmasize);
        !           601:        }
        !           602:
        !           603:        /* Setup DMA control register */
        !           604:        csr = L64854_GCSR(sc);
        !           605:        csr &= ~L64854_BURST_SIZE;
        !           606:        if (sc->sc_burst == 32) {
        !           607:                csr |= L64854_BURST_32;
        !           608:        } else if (sc->sc_burst == 16) {
        !           609:                csr |= L64854_BURST_16;
        !           610:        } else {
        !           611:                csr |= L64854_BURST_0;
        !           612:        }
        !           613:        csr |= P_EN_DMA|P_INT_EN|P_EN_CNT;
        !           614: #if 0
        !           615:        /* This bit is read-only in PP csr register */
        !           616:        if (datain)
        !           617:                csr |= P_WRITE;
        !           618:        else
        !           619:                csr &= ~P_WRITE;
        !           620: #endif
        !           621:        L64854_SCSR(sc, csr);
        !           622:
        !           623:        return (0);
        !           624: }
        !           625: /*
        !           626:  * Parallel port DMA interrupt.
        !           627:  */
        !           628: int
        !           629: lsi64854_pp_intr(arg)
        !           630:        void *arg;
        !           631: {
        !           632:        struct lsi64854_softc *sc = arg;
        !           633:        int ret, trans, resid = 0;
        !           634:        u_int32_t csr;
        !           635:
        !           636:        csr = L64854_GCSR(sc);
        !           637:
        !           638:        DPRINTF(LDB_PP, ("%s: pp intr: addr 0x%x, csr %b\n", sc->sc_dev.dv_xname,
        !           639:                 bus_space_read_4(sc->sc_bustag, sc->sc_regs, L64854_REG_ADDR),
        !           640:                 csr, PDMACSR_BITS));
        !           641:
        !           642:        if (csr & (P_ERR_PEND|P_SLAVE_ERR)) {
        !           643:                resid = bus_space_read_4(sc->sc_bustag, sc->sc_regs,
        !           644:                                         L64854_REG_CNT);
        !           645:                printf("%s: pp error: resid %d csr=%b\n", sc->sc_dev.dv_xname,
        !           646:                       resid, csr, PDMACSR_BITS);
        !           647:                csr &= ~P_EN_DMA;       /* Stop DMA */
        !           648:                /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
        !           649:                csr |= P_INVALIDATE|P_SLAVE_ERR;
        !           650:                L64854_SCSR(sc, csr);
        !           651:                return (1);
        !           652:        }
        !           653:
        !           654:        ret = (csr & P_INT_PEND) != 0;
        !           655:
        !           656:        if (sc->sc_active != 0) {
        !           657:                DMA_DRAIN(sc, 0);
        !           658:                resid = bus_space_read_4(sc->sc_bustag, sc->sc_regs,
        !           659:                                         L64854_REG_CNT);
        !           660:        }
        !           661:
        !           662:        /* DMA has stopped */
        !           663:        csr &= ~D_EN_DMA;
        !           664:        L64854_SCSR(sc, csr);
        !           665:        sc->sc_active = 0;
        !           666:
        !           667:        trans = sc->sc_dmasize - resid;
        !           668:        if (trans < 0) {                        /* transferred < 0 ? */
        !           669:                trans = sc->sc_dmasize;
        !           670:        }
        !           671:        *sc->sc_dmalen -= trans;
        !           672:        *sc->sc_dmaaddr += trans;
        !           673:
        !           674:        if (sc->sc_dmamap->dm_nsegs > 0) {
        !           675:                bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, 0, sc->sc_dmasize,
        !           676:                                (csr & D_WRITE) != 0
        !           677:                                        ? BUS_DMASYNC_POSTREAD
        !           678:                                        : BUS_DMASYNC_POSTWRITE);
        !           679:                bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
        !           680:        }
        !           681:
        !           682:        return (ret != 0);
        !           683: }

CVSweb