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

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

1.1       nbrk        1: /*     $OpenBSD: dma.c,v 1.17 2005/11/17 23:56:02 miod Exp $   */
                      2: /*     $NetBSD: dma.c,v 1.19 1997/05/05 21:02:39 thorpej Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995, 1996, 1997
                      6:  *     Jason R. Thorpe.  All rights reserved.
                      7:  * Copyright (c) 1982, 1990, 1993
                      8:  *     The Regents of the University of California.  All rights reserved.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  *
                     34:  *     @(#)dma.c       8.1 (Berkeley) 6/10/93
                     35:  */
                     36:
                     37: /*
                     38:  * DMA driver
                     39:  */
                     40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/time.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/device.h>
                     47: #include <sys/timeout.h>
                     48:
                     49: #include <machine/frame.h>
                     50: #include <machine/cpu.h>
                     51: #include <machine/intr.h>
                     52:
                     53: #include <hp300/dev/dmareg.h>
                     54: #include <hp300/dev/dmavar.h>
                     55:
                     56: #include <uvm/uvm_extern.h>
                     57:
                     58: /*
                     59:  * The largest single request will be MAXPHYS bytes which will require
                     60:  * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
                     61:  * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
                     62:  * buffer is not page aligned (+1).
                     63:  */
                     64: #define        DMAMAXIO        (MAXPHYS/NBPG+1)
                     65:
                     66: struct dma_chain {
                     67:        u_int   dc_count;
                     68:        paddr_t dc_addr;
                     69: };
                     70:
                     71: struct dma_channel {
                     72:        struct  dmaqueue *dm_job;               /* current job */
                     73:        struct  dmadevice *dm_hwaddr;           /* registers if DMA_C */
                     74:        struct  dmaBdevice *dm_Bhwaddr;         /* registers if not DMA_C */
                     75:        char    dm_flags;                       /* misc. flags */
                     76:        u_short dm_cmd;                         /* DMA controller command */
                     77:        u_int   dm_cur;                         /* current segment */
                     78:        u_int   dm_last;                        /* last segment */
                     79:        struct  dma_chain dm_chain[DMAMAXIO];   /* all segments */
                     80: };
                     81:
                     82: struct dma_softc {
                     83:        struct  dmareg *sc_dmareg;              /* pointer to our hardware */
                     84:        struct  isr sc_isr;
                     85:        struct  dma_channel sc_chan[NDMACHAN];  /* 2 channels */
                     86: #ifdef DEBUG
                     87:        struct  timeout sc_timeout;             /* DMA timeout */
                     88: #endif
                     89:        TAILQ_HEAD(, dmaqueue) sc_queue;        /* job queue */
                     90:        char    sc_type;                        /* A, B, or C */
                     91: } dma_softc;
                     92:
                     93: /* types */
                     94: #define        DMA_B   0
                     95: #define DMA_C  1
                     96:
                     97: /* flags */
                     98: #define DMAF_PCFLUSH   0x01
                     99: #define DMAF_VCFLUSH   0x02
                    100: #define DMAF_NOINTR    0x04
                    101:
                    102: void   dmacflush(struct dma_channel *);
                    103: int    dmaintr(void *);
                    104:
                    105: #ifdef DEBUG
                    106: int    dmadebug = 0;
                    107: #define DDB_WORD       0x01    /* same as DMAGO_WORD */
                    108: #define DDB_LWORD      0x02    /* same as DMAGO_LWORD */
                    109: #define        DDB_FOLLOW      0x04
                    110: #define DDB_IO         0x08
                    111:
                    112: void   dmatimeout(void *);
                    113: int    dmatimo[NDMACHAN];
                    114:
                    115: long   dmahits[NDMACHAN];
                    116: long   dmamisses[NDMACHAN];
                    117: long   dmabyte[NDMACHAN];
                    118: long   dmaword[NDMACHAN];
                    119: long   dmalword[NDMACHAN];
                    120: #endif
                    121:
                    122: /*
                    123:  * Initialize the DMA engine, called by dioattach()
                    124:  */
                    125: void
                    126: dmainit()
                    127: {
                    128:        struct dma_softc *sc = &dma_softc;
                    129:        struct dmareg *dma;
                    130:        struct dma_channel *dc;
                    131:        int i;
                    132:        char rev;
                    133:
                    134:        /* There's just one. */
                    135:        sc->sc_dmareg = (struct dmareg *)DMA_BASE;
                    136:        dma = sc->sc_dmareg;
                    137:
                    138:        /*
                    139:         * Determine the DMA type.  A DMA_A or DMA_B will fail the
                    140:         * following probe.
                    141:         *
                    142:         * XXX Don't know how to easily differentiate the A and B cards,
                    143:         * so we just hope nobody has an A card (A cards will work if
                    144:         * splbio works out to ipl 3).
                    145:         */
                    146:        if (badbaddr((char *)&dma->dma_id[2])) {
                    147:                rev = 'B';
                    148: #if !defined(HP320)
                    149:                panic("dmainit: DMA card requires hp320 support");
                    150: #endif
                    151:        } else
                    152:                rev = dma->dma_id[2];
                    153:
                    154:        sc->sc_type = (rev == 'B') ? DMA_B : DMA_C;
                    155:
                    156:        TAILQ_INIT(&sc->sc_queue);
                    157:
                    158:        for (i = 0; i < NDMACHAN; i++) {
                    159:                dc = &sc->sc_chan[i];
                    160:                dc->dm_job = NULL;
                    161:                switch (i) {
                    162:                case 0:
                    163:                        dc->dm_hwaddr = &dma->dma_chan0;
                    164:                        dc->dm_Bhwaddr = &dma->dma_Bchan0;
                    165:                        break;
                    166:
                    167:                case 1:
                    168:                        dc->dm_hwaddr = &dma->dma_chan1;
                    169:                        dc->dm_Bhwaddr = &dma->dma_Bchan1;
                    170:                        break;
                    171:
                    172:                default:
                    173:                        panic("dmainit: more than 2 channels?");
                    174:                        /* NOTREACHED */
                    175:                }
                    176:        }
                    177:
                    178: #ifdef DEBUG
                    179:        /* make sure timeout is really not needed */
                    180:        timeout_set(&sc->sc_timeout, dmatimeout, sc);
                    181:        timeout_add(&sc->sc_timeout, 30 * hz);
                    182: #endif
                    183:
                    184:        printf("98620%c, 2 channels, %d bit DMA\n",
                    185:            rev, (rev == 'B') ? 16 : 32);
                    186:
                    187:        /*
                    188:         * Defer hooking up our interrupt until the first
                    189:         * DMA-using controller has hooked up theirs.
                    190:         */
                    191:        sc->sc_isr.isr_func = NULL;
                    192:        sc->sc_isr.isr_arg = sc;
                    193:        sc->sc_isr.isr_priority = IPL_BIO;
                    194: }
                    195:
                    196: /*
                    197:  * Compute the ipl and (re)establish the interrupt handler
                    198:  * for the DMA controller.
                    199:  */
                    200: void
                    201: dmacomputeipl()
                    202: {
                    203:        struct dma_softc *sc = &dma_softc;
                    204:
                    205:        if (sc->sc_isr.isr_func != NULL)
                    206:                intr_disestablish(&sc->sc_isr);
                    207:
                    208:        /*
                    209:         * Our interrupt level must be as high as the highest
                    210:         * device using DMA (i.e. splbio).
                    211:         */
                    212:        sc->sc_isr.isr_ipl = PSLTOIPL(hp300_bioipl);
                    213:
                    214:        sc->sc_isr.isr_func = dmaintr;
                    215:        intr_establish(&sc->sc_isr, "dma");
                    216: }
                    217:
                    218: int
                    219: dmareq(struct dmaqueue *dq)
                    220: {
                    221:        struct dma_softc *sc = &dma_softc;
                    222:        int i, chan, s;
                    223:
                    224: #if 1
                    225:        s = splhigh();  /* XXXthorpej */
                    226: #else
                    227:        s = splbio();
                    228: #endif
                    229:
                    230:        chan = dq->dq_chan;
                    231:        for (i = NDMACHAN - 1; i >= 0; i--) {
                    232:                /*
                    233:                 * Can we use this channel?
                    234:                 */
                    235:                if ((chan & (1 << i)) == 0)
                    236:                        continue;
                    237:
                    238:                /*
                    239:                 * We can use it; is it busy?
                    240:                 */
                    241:                if (sc->sc_chan[i].dm_job != NULL)
                    242:                        continue;
                    243:
                    244:                /*
                    245:                 * Not busy; give the caller this channel.
                    246:                 */
                    247:                sc->sc_chan[i].dm_job = dq;
                    248:                dq->dq_chan = i;
                    249:                splx(s);
                    250:                return (1);
                    251:        }
                    252:
                    253:        /*
                    254:         * Couldn't get a channel now; put this in the queue.
                    255:         */
                    256:        TAILQ_INSERT_TAIL(&sc->sc_queue, dq, dq_list);
                    257:        splx(s);
                    258:        return (0);
                    259: }
                    260:
                    261: void
                    262: dmacflush(struct dma_channel *dc)
                    263: {
                    264: #if defined(CACHE_HAVE_PAC) || defined(M68040)
                    265:        if (dc->dm_flags & DMAF_PCFLUSH) {
                    266:                PCIA();
                    267:                dc->dm_flags &= ~DMAF_PCFLUSH;
                    268:        }
                    269: #endif
                    270:
                    271: #if defined(CACHE_HAVE_VAC)
                    272:        if (dc->dm_flags & DMAF_VCFLUSH) {
                    273:                /*
                    274:                 * 320/350s have VACs that may also need flushing.
                    275:                 * In our case we only flush the supervisor side
                    276:                 * because we know that if we are DMAing to user
                    277:                 * space, the physical pages will also be mapped
                    278:                 * in kernel space (via vmapbuf) and hence cache-
                    279:                 * inhibited by the pmap module due to the multiple
                    280:                 * mapping.
                    281:                 */
                    282:                DCIS();
                    283:                dc->dm_flags &= ~DMAF_VCFLUSH;
                    284:        }
                    285: #endif
                    286: }
                    287:
                    288: void
                    289: dmafree(struct dmaqueue *dq)
                    290: {
                    291:        int unit = dq->dq_chan;
                    292:        struct dma_softc *sc = &dma_softc;
                    293:        struct dma_channel *dc = &sc->sc_chan[unit];
                    294:        struct dmaqueue *dn;
                    295:        int chan, s;
                    296:
                    297: #if 1
                    298:        s = splhigh();  /* XXXthorpej */
                    299: #else
                    300:        s = splbio();
                    301: #endif
                    302:
                    303: #ifdef DEBUG
                    304:        dmatimo[unit] = 0;
                    305: #endif
                    306:
                    307:        DMA_CLEAR(dc);
                    308:
                    309:        /*
                    310:         * XXX we may not always go through the flush code in dmastop()
                    311:         */
                    312:        dmacflush(dc);
                    313:
                    314:        /*
                    315:         * Channel is now free.  Look for another job to run on this
                    316:         * channel.
                    317:         */
                    318:        dc->dm_job = NULL;
                    319:        chan = 1 << unit;
                    320:        TAILQ_FOREACH(dn, &sc->sc_queue, dq_list) {
                    321:                if (dn->dq_chan & chan) {
                    322:                        /* Found one... */
                    323:                        TAILQ_REMOVE(&sc->sc_queue, dn, dq_list);
                    324:                        dc->dm_job = dn;
                    325:                        dn->dq_chan = dq->dq_chan;
                    326:                        splx(s);
                    327:
                    328:                        /* Start the initiator. */
                    329:                        (*dn->dq_start)(dn->dq_softc);
                    330:                        return;
                    331:                }
                    332:        }
                    333:        splx(s);
                    334: }
                    335:
                    336: void
                    337: dmago(int unit, char *addr, u_int count, int flags)
                    338: {
                    339:        struct dma_softc *sc = &dma_softc;
                    340:        struct dma_channel *dc = &sc->sc_chan[unit];
                    341:        paddr_t dmaend = 0;
                    342:        u_int seg, tcount;
                    343:
                    344: #ifdef DIAGNOSTIC
                    345:        if (count > MAXPHYS)
                    346:                panic("dmago: count > MAXPHYS");
                    347: #endif
                    348:
                    349: #if defined(HP320)
                    350:        if (sc->sc_type == DMA_B && (flags & DMAGO_LWORD))
                    351:                panic("dmago: no can do 32-bit DMA");
                    352: #endif
                    353:
                    354: #ifdef DEBUG
                    355:        if (dmadebug & DDB_FOLLOW)
                    356:                printf("dmago(%d, %p, %x, %x)\n",
                    357:                       unit, addr, count, flags);
                    358:        if (flags & DMAGO_LWORD)
                    359:                dmalword[unit]++;
                    360:        else if (flags & DMAGO_WORD)
                    361:                dmaword[unit]++;
                    362:        else
                    363:                dmabyte[unit]++;
                    364: #endif
                    365:        /*
                    366:         * Build the DMA chain
                    367:         */
                    368:        for (seg = 0; count > 0; seg++) {
                    369:                if (pmap_extract(pmap_kernel(), (vaddr_t)addr,
                    370:                    &dc->dm_chain[seg].dc_addr) == FALSE)
                    371:                        panic("dmago: pmap_extract(%x) failed", addr);
                    372: #if defined(M68040)
                    373:                /*
                    374:                 * Push back dirty cache lines
                    375:                 */
                    376:                if (mmutype == MMU_68040)
                    377:                        DCFP(dc->dm_chain[seg].dc_addr);
                    378: #endif
                    379:                if (count < (tcount = PAGE_SIZE - ((int)addr & PAGE_MASK)))
                    380:                        tcount = count;
                    381:                dc->dm_chain[seg].dc_count = tcount;
                    382:                addr += tcount;
                    383:                count -= tcount;
                    384:                if (flags & DMAGO_LWORD)
                    385:                        tcount >>= 2;
                    386:                else if (flags & DMAGO_WORD)
                    387:                        tcount >>= 1;
                    388:
                    389:                /*
                    390:                 * Try to compact the DMA transfer if the pages are adjacent.
                    391:                 * Note: this will never happen on the first iteration.
                    392:                 */
                    393:                if (dc->dm_chain[seg].dc_addr == dmaend
                    394: #if defined(HP320)
                    395:                    /* only 16-bit count on 98620B */
                    396:                    && (sc->sc_type != DMA_B ||
                    397:                        dc->dm_chain[seg - 1].dc_count + tcount <= 65536)
                    398: #endif
                    399:                ) {
                    400: #ifdef DEBUG
                    401:                        dmahits[unit]++;
                    402: #endif
                    403:                        dmaend += dc->dm_chain[seg].dc_count;
                    404:                        dc->dm_chain[--seg].dc_count += tcount;
                    405:                } else {
                    406: #ifdef DEBUG
                    407:                        dmamisses[unit]++;
                    408: #endif
                    409:                        dmaend = dc->dm_chain[seg].dc_addr +
                    410:                            dc->dm_chain[seg].dc_count;
                    411:                        dc->dm_chain[seg].dc_count = tcount;
                    412:                }
                    413:        }
                    414:        dc->dm_cur = 0;
                    415:        dc->dm_last = --seg;
                    416:        dc->dm_flags = 0;
                    417:        /*
                    418:         * Set up the command word based on flags
                    419:         */
                    420:        dc->dm_cmd = DMA_ENAB | DMA_IPL(sc->sc_isr.isr_ipl) | DMA_START;
                    421:        if ((flags & DMAGO_READ) == 0)
                    422:                dc->dm_cmd |= DMA_WRT;
                    423:        if (flags & DMAGO_LWORD)
                    424:                dc->dm_cmd |= DMA_LWORD;
                    425:        else if (flags & DMAGO_WORD)
                    426:                dc->dm_cmd |= DMA_WORD;
                    427:        if (flags & DMAGO_PRI)
                    428:                dc->dm_cmd |= DMA_PRI;
                    429:
                    430:        if (flags & DMAGO_READ) {
                    431: #if defined(M68040)
                    432:                /*
                    433:                 * On the 68040 we need to flush (push) the data cache before a
                    434:                 * DMA (already done above) and flush again after DMA completes.
                    435:                 * In theory we should only need to flush prior to a write DMA
                    436:                 * and purge after a read DMA but if the entire page is not
                    437:                 * involved in the DMA we might purge some valid data.
                    438:                 */
                    439:                if (mmutype == MMU_68040)
                    440:                        dc->dm_flags |= DMAF_PCFLUSH;
                    441: #endif
                    442:
                    443: #if defined(CACHE_HAVE_PAC)
                    444:                /*
                    445:                 * Remember if we need to flush external physical cache when
                    446:                 * DMA is done.  We only do this if we are reading
                    447:                 * (writing memory).
                    448:                 */
                    449:                if (ectype == EC_PHYS)
                    450:                        dc->dm_flags |= DMAF_PCFLUSH;
                    451: #endif
                    452:
                    453: #if defined(CACHE_HAVE_VAC)
                    454:                if (ectype == EC_VIRT)
                    455:                        dc->dm_flags |= DMAF_VCFLUSH;
                    456: #endif
                    457:        }
                    458:
                    459:        /*
                    460:         * Remember if we can skip the dma completion interrupt on
                    461:         * the last segment in the chain.
                    462:         */
                    463:        if (flags & DMAGO_NOINT) {
                    464:                if (dc->dm_cur == dc->dm_last)
                    465:                        dc->dm_cmd &= ~DMA_ENAB;
                    466:                else
                    467:                        dc->dm_flags |= DMAF_NOINTR;
                    468:        }
                    469: #ifdef DEBUG
                    470:        if (dmadebug & DDB_IO) {
                    471:                if (((dmadebug&DDB_WORD) && (dc->dm_cmd&DMA_WORD)) ||
                    472:                    ((dmadebug&DDB_LWORD) && (dc->dm_cmd&DMA_LWORD))) {
                    473:                        printf("dmago: cmd %x, flags %x\n",
                    474:                               dc->dm_cmd, dc->dm_flags);
                    475:                        for (seg = 0; seg <= dc->dm_last; seg++)
                    476:                                printf("  %d: %d@%p\n", seg,
                    477:                                    dc->dm_chain[seg].dc_count,
                    478:                                    dc->dm_chain[seg].dc_addr);
                    479:                }
                    480:        }
                    481:        dmatimo[unit] = 1;
                    482: #endif
                    483:        DMA_ARM(sc, dc);
                    484: }
                    485:
                    486: void
                    487: dmastop(int unit)
                    488: {
                    489:        struct dma_softc *sc = &dma_softc;
                    490:        struct dma_channel *dc = &sc->sc_chan[unit];
                    491:
                    492: #ifdef DEBUG
                    493:        if (dmadebug & DDB_FOLLOW)
                    494:                printf("dmastop(%d)\n", unit);
                    495:        dmatimo[unit] = 0;
                    496: #endif
                    497:        DMA_CLEAR(dc);
                    498:
                    499:        dmacflush(dc);
                    500:
                    501:        /*
                    502:         * We may get this interrupt after a device service routine
                    503:         * has freed the dma channel.  So, ignore the intr if there's
                    504:         * nothing on the queue.
                    505:         */
                    506:        if (dc->dm_job != NULL)
                    507:                (*dc->dm_job->dq_done)(dc->dm_job->dq_softc);
                    508: }
                    509:
                    510: int
                    511: dmaintr(void *arg)
                    512: {
                    513:        struct dma_softc *sc = arg;
                    514:        struct dma_channel *dc;
                    515:        int i, stat;
                    516:        int found = 0;
                    517:
                    518: #ifdef DEBUG
                    519:        if (dmadebug & DDB_FOLLOW)
                    520:                printf("dmaintr\n");
                    521: #endif
                    522:        for (i = 0; i < NDMACHAN; i++) {
                    523:                dc = &sc->sc_chan[i];
                    524:                stat = DMA_STAT(dc);
                    525:                if ((stat & DMA_INTR) == 0)
                    526:                        continue;
                    527:                found++;
                    528: #ifdef DEBUG
                    529:                if (dmadebug & DDB_IO) {
                    530:                        if (((dmadebug&DDB_WORD) && (dc->dm_cmd&DMA_WORD)) ||
                    531:                            ((dmadebug&DDB_LWORD) && (dc->dm_cmd&DMA_LWORD)))
                    532:                          printf("dmaintr: flags %x unit %d stat %x next %d\n",
                    533:                           dc->dm_flags, i, stat, dc->dm_cur + 1);
                    534:                }
                    535:                if (stat & DMA_ARMED)
                    536:                        printf("dma channel %d: intr when armed\n", i);
                    537: #endif
                    538:                /*
                    539:                 * Load the next segment, or finish up if we're done.
                    540:                 */
                    541:                dc->dm_cur++;
                    542:                if (dc->dm_cur <= dc->dm_last) {
                    543: #ifdef DEBUG
                    544:                        dmatimo[i] = 1;
                    545: #endif
                    546:                        /*
                    547:                         * If we're the last segment, disable the
                    548:                         * completion interrupt, if necessary.
                    549:                         */
                    550:                        if (dc->dm_cur == dc->dm_last &&
                    551:                            (dc->dm_flags & DMAF_NOINTR))
                    552:                                dc->dm_cmd &= ~DMA_ENAB;
                    553:                        DMA_CLEAR(dc);
                    554:                        DMA_ARM(sc, dc);
                    555:                } else
                    556:                        dmastop(i);
                    557:        }
                    558:        return(found);
                    559: }
                    560:
                    561: #ifdef DEBUG
                    562: void
                    563: dmatimeout(void *arg)
                    564: {
                    565:        int i, s;
                    566:        struct dma_softc *sc = arg;
                    567:
                    568:        for (i = 0; i < NDMACHAN; i++) {
                    569:                s = splbio();
                    570:                if (dmatimo[i]) {
                    571:                        if (dmatimo[i] > 1)
                    572:                                printf("dma channel %d timeout #%d\n",
                    573:                                    i, dmatimo[i]-1);
                    574:                        dmatimo[i]++;
                    575:                }
                    576:                splx(s);
                    577:        }
                    578:        timeout_add(&sc->sc_timeout, 30 * hz);
                    579: }
                    580: #endif

CVSweb