[BACK]Return to isadma_bounce.c CVS log [TXT][DIR] Up to [local] / sys / arch / alpha / isa

Annotation of sys/arch/alpha/isa/isadma_bounce.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: isadma_bounce.c,v 1.6 2006/05/12 20:48:19 brad Exp $  */
                      2: /* $NetBSD: isadma_bounce.c,v 1.3 2000/06/29 09:02:57 mrg Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                     10:  * NASA Ames Research Center.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the NetBSD
                     23:  *     Foundation, Inc. and its contributors.
                     24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     25:  *    contributors may be used to endorse or promote products derived
                     26:  *    from this software without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     38:  * POSSIBILITY OF SUCH DAMAGE.
                     39:  */
                     40:
                     41: #define _ALPHA_BUS_DMA_PRIVATE
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/syslog.h>
                     45: #include <sys/device.h>
                     46: #include <sys/malloc.h>
                     47: #include <sys/proc.h>
                     48: #include <sys/mbuf.h>
                     49:
                     50: #include <machine/bus.h>
                     51:
                     52: #include <dev/isa/isareg.h>
                     53: #include <dev/isa/isavar.h>
                     54:
                     55: #include <uvm/uvm_extern.h>
                     56:
                     57: extern paddr_t avail_end;
                     58:
                     59: /*
                     60:  * ISA can only DMA to 0-16M.
                     61:  */
                     62: #define        ISA_DMA_BOUNCE_THRESHOLD        (16 * 1024 * 1024)
                     63:
                     64: /*
                     65:  * Cookie used by bouncing ISA DMA.  A pointer to one of these is stashed
                     66:  * in the DMA map.
                     67:  */
                     68: struct isadma_bounce_cookie {
                     69:        int     id_flags;               /* flags; see below */
                     70:
                     71:        /*
                     72:         * Information about the original buffer used during
                     73:         * DMA map syncs.  Note that origbuflen is only used
                     74:         * for ID_BUFTYPE_LINEAR.
                     75:         */
                     76:        void    *id_origbuf;            /* pointer to orig buffer if
                     77:                                           bouncing */
                     78:        bus_size_t id_origbuflen;       /* ...and size */
                     79:        int     id_buftype;             /* type of buffer */
                     80:
                     81:        void    *id_bouncebuf;          /* pointer to the bounce buffer */
                     82:        bus_size_t id_bouncebuflen;     /* ...and size */
                     83:        int     id_nbouncesegs;         /* number of valid bounce segs */
                     84:        bus_dma_segment_t id_bouncesegs[1]; /* array of bounce buffer
                     85:                                               physical memory segments */
                     86: };
                     87:
                     88: /* id_flags */
                     89: #define        ID_MIGHT_NEED_BOUNCE    0x01    /* map could need bounce buffers */
                     90: #define        ID_HAS_BOUNCE           0x02    /* map currently has bounce buffers */
                     91: #define        ID_IS_BOUNCING          0x04    /* map is bouncing current xfer */
                     92:
                     93: /* id_buftype */
                     94: #define        ID_BUFTYPE_INVALID      0
                     95: #define        ID_BUFTYPE_LINEAR       1
                     96: #define        ID_BUFTYPE_MBUF         2
                     97: #define        ID_BUFTYPE_UIO          3
                     98: #define        ID_BUFTYPE_RAW          4
                     99:
                    100: int    isadma_bounce_alloc_bouncebuf(bus_dma_tag_t, bus_dmamap_t,
                    101:            bus_size_t, int);
                    102: void   isadma_bounce_free_bouncebuf(bus_dma_tag_t, bus_dmamap_t);
                    103:
                    104: /*
                    105:  * Create an ISA DMA map.
                    106:  */
                    107: int
                    108: isadma_bounce_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
                    109:     bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
                    110: {
                    111:        struct isadma_bounce_cookie *cookie;
                    112:        bus_dmamap_t map;
                    113:        int error, cookieflags;
                    114:        void *cookiestore;
                    115:        size_t cookiesize;
                    116:
                    117:        /* Call common function to create the basic map. */
                    118:        error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary,
                    119:            flags, dmamp);
                    120:        if (error)
                    121:                return (error);
                    122:
                    123:        map = *dmamp;
                    124:        map->_dm_cookie = NULL;
                    125:
                    126:        cookiesize = sizeof(*cookie);
                    127:
                    128:        /*
                    129:         * ISA only has 24-bits of address space.  This means
                    130:         * we can't DMA to pages over 16M.  In order to DMA to
                    131:         * arbitrary buffers, we use "bounce buffers" - pages
                    132:         * in memory below the 16M boundary.  On DMA reads,
                    133:         * DMA happens to the bounce buffers, and is copied into
                    134:         * the caller's buffer.  On writes, data is copied into
                    135:         * but bounce buffer, and the DMA happens from those
                    136:         * pages.  To software using the DMA mapping interface,
                    137:         * this looks simply like a data cache.
                    138:         *
                    139:         * If we have more than 16M of RAM in the system, we may
                    140:         * need bounce buffers.  We check and remember that here.
                    141:         *
                    142:         * ...or, there is an opposite case.  The most segments
                    143:         * a transfer will require is (maxxfer / PAGE_SIZE) + 1.  If
                    144:         * the caller can't handle that many segments (e.g. the
                    145:         * ISA DMA controller), we may have to bounce it as well.
                    146:         */
                    147:        cookieflags = 0;
                    148:        if (avail_end > (t->_wbase + t->_wsize) ||
                    149:            ((map->_dm_size / PAGE_SIZE) + 1) > map->_dm_segcnt) {
                    150:                cookieflags |= ID_MIGHT_NEED_BOUNCE;
                    151:                cookiesize += (sizeof(bus_dma_segment_t) *
                    152:                    (map->_dm_segcnt - 1));
                    153:        }
                    154:
                    155:        /*
                    156:         * Allocate our cookie.
                    157:         */
                    158:        if ((cookiestore = malloc(cookiesize, M_DEVBUF,
                    159:            (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) {
                    160:                error = ENOMEM;
                    161:                goto out;
                    162:        }
                    163:        memset(cookiestore, 0, cookiesize);
                    164:        cookie = (struct isadma_bounce_cookie *)cookiestore;
                    165:        cookie->id_flags = cookieflags;
                    166:        map->_dm_cookie = cookie;
                    167:
                    168:        if (cookieflags & ID_MIGHT_NEED_BOUNCE) {
                    169:                /*
                    170:                 * Allocate the bounce pages now if the caller
                    171:                 * wishes us to do so.
                    172:                 */
                    173:                if ((flags & BUS_DMA_ALLOCNOW) == 0)
                    174:                        goto out;
                    175:
                    176:                error = isadma_bounce_alloc_bouncebuf(t, map, size, flags);
                    177:        }
                    178:
                    179:  out:
                    180:        if (error) {
                    181:                if (map->_dm_cookie != NULL)
                    182:                        free(map->_dm_cookie, M_DEVBUF);
                    183:                _bus_dmamap_destroy(t, map);
                    184:        }
                    185:        return (error);
                    186: }
                    187:
                    188: /*
                    189:  * Destroy an ISA DMA map.
                    190:  */
                    191: void
                    192: isadma_bounce_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
                    193: {
                    194:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    195:
                    196:        /*
                    197:         * Free any bounce pages this map might hold.
                    198:         */
                    199:        if (cookie->id_flags & ID_HAS_BOUNCE)
                    200:                isadma_bounce_free_bouncebuf(t, map);
                    201:
                    202:        free(cookie, M_DEVBUF);
                    203:        _bus_dmamap_destroy(t, map);
                    204: }
                    205:
                    206: /*
                    207:  * Load an ISA DMA map with a linear buffer.
                    208:  */
                    209: int
                    210: isadma_bounce_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
                    211:     size_t buflen, struct proc *p, int flags)
                    212: {
                    213:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    214:        int error;
                    215:
                    216:        /*
                    217:         * Make sure that on error condition we return "no valid mappings."
                    218:         */
                    219:        map->dm_mapsize = 0;
                    220:        map->dm_nsegs = 0;
                    221:
                    222:        /*
                    223:         * Try to load the map the normal way.  If this errors out,
                    224:         * and we can bounce, we will.
                    225:         */
                    226:        error = _bus_dmamap_load_direct(t, map, buf, buflen, p, flags);
                    227:        if (error == 0 ||
                    228:            (error != 0 && (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) == 0))
                    229:                return (error);
                    230:
                    231:        /*
                    232:         * First attempt failed; bounce it.
                    233:         */
                    234:
                    235:        /*
                    236:         * Allocate bounce pages, if necessary.
                    237:         */
                    238:        if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) {
                    239:                error = isadma_bounce_alloc_bouncebuf(t, map, buflen, flags);
                    240:                if (error)
                    241:                        return (error);
                    242:        }
                    243:
                    244:        /*
                    245:         * Cache a pointer to the caller's buffer and load the DMA map
                    246:         * with the bounce buffer.
                    247:         */
                    248:        cookie->id_origbuf = buf;
                    249:        cookie->id_origbuflen = buflen;
                    250:        cookie->id_buftype = ID_BUFTYPE_LINEAR;
                    251:        error = _bus_dmamap_load_direct(t, map, cookie->id_bouncebuf, buflen,
                    252:            p, flags);
                    253:        if (error) {
                    254:                /*
                    255:                 * Free the bounce pages, unless our resources
                    256:                 * are reserved for our exclusive use.
                    257:                 */
                    258:                if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
                    259:                        isadma_bounce_free_bouncebuf(t, map);
                    260:                return (error);
                    261:        }
                    262:
                    263:        /* ...so isadma_bounce_dmamap_sync() knows we're bouncing */
                    264:        cookie->id_flags |= ID_IS_BOUNCING;
                    265:        map->_dm_window = t;
                    266:        return (0);
                    267: }
                    268:
                    269: /*
                    270:  * Like isadma_bounce_dmamap_load(), but for mbufs.
                    271:  */
                    272: int
                    273: isadma_bounce_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map,
                    274:     struct mbuf *m0, int flags)
                    275: {
                    276:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    277:        int error;
                    278:
                    279:        /*
                    280:         * Make sure on error condition we return "no valid mappings."
                    281:         */
                    282:        map->dm_mapsize = 0;
                    283:        map->dm_nsegs = 0;
                    284:
                    285: #ifdef DIAGNOSTIC
                    286:        if ((m0->m_flags & M_PKTHDR) == 0)
                    287:                panic("isadma_bounce_dmamap_load_mbuf: no packet header");
                    288: #endif
                    289:
                    290:        if (m0->m_pkthdr.len > map->_dm_size)
                    291:                return (EINVAL);
                    292:
                    293:        /*
                    294:         * Try to load the map the normal way.  If this errors out,
                    295:         * and we can bounce, we will.
                    296:         */
                    297:        error = _bus_dmamap_load_mbuf_direct(t, map, m0, flags);
                    298:        if (error == 0 ||
                    299:            (error != 0 && (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) == 0))
                    300:                return (error);
                    301:
                    302:        /*
                    303:         * First attempt failed; bounce it.
                    304:         */
                    305:
                    306:        /*
                    307:         * Allocate bounce pages, if necessary.
                    308:         */
                    309:        if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) {
                    310:                error = isadma_bounce_alloc_bouncebuf(t, map, m0->m_pkthdr.len,
                    311:                    flags);
                    312:                if (error)
                    313:                        return (error);
                    314:        }
                    315:
                    316:        /*
                    317:         * Cache a pointer to the caller's buffer and load the DMA map
                    318:         * with the bounce buffer.
                    319:         */
                    320:        cookie->id_origbuf = m0;
                    321:        cookie->id_origbuflen = m0->m_pkthdr.len;       /* not really used */
                    322:        cookie->id_buftype = ID_BUFTYPE_MBUF;
                    323:        error = _bus_dmamap_load_direct(t, map, cookie->id_bouncebuf,
                    324:            m0->m_pkthdr.len, NULL, flags);
                    325:        if (error) {
                    326:                /*
                    327:                 * Free the bounce pages, unless our resources
                    328:                 * are reserved for our exclusive use.
                    329:                 */
                    330:                if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
                    331:                        isadma_bounce_free_bouncebuf(t, map);
                    332:                return (error);
                    333:        }
                    334:
                    335:        /* ...so isadma_bounce_dmamap_sync() knows we're bouncing */
                    336:        cookie->id_flags |= ID_IS_BOUNCING;
                    337:        map->_dm_window = t;
                    338:        return (0);
                    339: }
                    340:
                    341: /*
                    342:  * Like isadma_bounce_dmamap_load(), but for uios.
                    343:  */
                    344: int
                    345: isadma_bounce_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map,
                    346:     struct uio *uio, int flags)
                    347: {
                    348:
                    349:        panic("isadma_bounce_dmamap_load_uio: not implemented");
                    350: }
                    351:
                    352: /*
                    353:  * Like isadma_bounce_dmamap_load(), but for raw memory allocated with
                    354:  * bus_dmamem_alloc().
                    355:  */
                    356: int
                    357: isadma_bounce_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map,
                    358:     bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags)
                    359: {
                    360:
                    361:        panic("isadma_bounce_dmamap_load_raw: not implemented");
                    362: }
                    363:
                    364: /*
                    365:  * Unload an ISA DMA map.
                    366:  */
                    367: void
                    368: isadma_bounce_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
                    369: {
                    370:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    371:
                    372:        /*
                    373:         * If we have bounce pages, free them, unless they're
                    374:         * reserved for our exclusive use.
                    375:         */
                    376:        if ((cookie->id_flags & ID_HAS_BOUNCE) &&
                    377:            (map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
                    378:                isadma_bounce_free_bouncebuf(t, map);
                    379:
                    380:        cookie->id_flags &= ~ID_IS_BOUNCING;
                    381:        cookie->id_buftype = ID_BUFTYPE_INVALID;
                    382:
                    383:        /*
                    384:         * Do the generic bits of the unload.
                    385:         */
                    386:        _bus_dmamap_unload(t, map);
                    387: }
                    388:
                    389: void
                    390: isadma_bounce_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
                    391:        bus_size_t len, int ops)
                    392: {
                    393:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    394:
                    395:        /*
                    396:         * Mixing PRE and POST operations is not allowed.
                    397:         */
                    398:        if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
                    399:            (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
                    400:                panic("isadma_bounce_dmamap_sync: mix PRE and POST");
                    401:
                    402: #ifdef DIAGNOSTIC
                    403:        if ((ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTREAD)) != 0) {
                    404:                if (offset >= map->dm_mapsize)
                    405:                        panic("isadma_bounce_dmamap_sync: bad offset");
                    406:                if (len == 0 || (offset + len) > map->dm_mapsize)
                    407:                        panic("isadma_bounce_dmamap_sync: bad length");
                    408:        }
                    409: #endif
                    410:
                    411:        /*
                    412:         * If we're not bouncing, just drain the write buffer
                    413:         * and return.
                    414:         */
                    415:        if ((cookie->id_flags & ID_IS_BOUNCING) == 0) {
                    416:                alpha_mb();
                    417:                return;
                    418:        }
                    419:
                    420:        switch (cookie->id_buftype) {
                    421:        case ID_BUFTYPE_LINEAR:
                    422:                /*
                    423:                 * Nothing to do for pre-read.
                    424:                 */
                    425:
                    426:                if (ops & BUS_DMASYNC_PREWRITE) {
                    427:                        /*
                    428:                         * Copy the caller's buffer to the bounce buffer.
                    429:                         */
                    430:                        memcpy((char *)cookie->id_bouncebuf + offset,
                    431:                            (char *)cookie->id_origbuf + offset, len);
                    432:                }
                    433:
                    434:                if (ops & BUS_DMASYNC_POSTREAD) {
                    435:                        /*
                    436:                         * Copy the bounce buffer to the caller's buffer.
                    437:                         */
                    438:                        memcpy((char *)cookie->id_origbuf + offset,
                    439:                            (char *)cookie->id_bouncebuf + offset, len);
                    440:                }
                    441:
                    442:                /*
                    443:                 * Nothing to do for post-write.
                    444:                 */
                    445:                break;
                    446:
                    447:        case ID_BUFTYPE_MBUF:
                    448:            {
                    449:                struct mbuf *m, *m0 = cookie->id_origbuf;
                    450:                bus_size_t minlen, moff;
                    451:
                    452:                /*
                    453:                 * Nothing to do for pre-read.
                    454:                 */
                    455:
                    456:                if (ops & BUS_DMASYNC_PREWRITE) {
                    457:                        /*
                    458:                         * Copy the caller's buffer to the bounce buffer.
                    459:                         */
                    460:                        m_copydata(m0, offset, len,
                    461:                            (char *)cookie->id_bouncebuf + offset);
                    462:                }
                    463:
                    464:                if (ops & BUS_DMASYNC_POSTREAD) {
                    465:                        /*
                    466:                         * Copy the bounce buffer to the caller's buffer.
                    467:                         */
                    468:                        for (moff = offset, m = m0; m != NULL && len != 0;
                    469:                             m = m->m_next) {
                    470:                                /* Find the beginning mbuf. */
                    471:                                if (moff >= m->m_len) {
                    472:                                        moff -= m->m_len;
                    473:                                        continue;
                    474:                                }
                    475:
                    476:                                /*
                    477:                                 * Now at the first mbuf to sync; nail
                    478:                                 * each one until we have exhausted the
                    479:                                 * length.
                    480:                                 */
                    481:                                minlen = len < m->m_len - moff ?
                    482:                                    len : m->m_len - moff;
                    483:
                    484:                                memcpy(mtod(m, caddr_t) + moff,
                    485:                                    (char *)cookie->id_bouncebuf + offset,
                    486:                                    minlen);
                    487:
                    488:                                moff = 0;
                    489:                                len -= minlen;
                    490:                                offset += minlen;
                    491:                        }
                    492:                }
                    493:
                    494:                /*
                    495:                 * Nothing to do for post-write.
                    496:                 */
                    497:                break;
                    498:            }
                    499:
                    500:        case ID_BUFTYPE_UIO:
                    501:                panic("isadma_bounce_dmamap_sync: ID_BUFTYPE_UIO");
                    502:                break;
                    503:
                    504:        case ID_BUFTYPE_RAW:
                    505:                panic("isadma_bounce_dmamap_sync: ID_BUFTYPE_RAW");
                    506:                break;
                    507:
                    508:        case ID_BUFTYPE_INVALID:
                    509:                panic("isadma_bounce_dmamap_sync: ID_BUFTYPE_INVALID");
                    510:                break;
                    511:
                    512:        default:
                    513:                panic("isadma_bounce_dmamap_sync: unknown buffer type %d",
                    514:                    cookie->id_buftype);
                    515:        }
                    516:
                    517:        /* Drain the write buffer. */
                    518:        alpha_mb();
                    519: }
                    520:
                    521: /*
                    522:  * Allocate memory safe for ISA DMA.
                    523:  */
                    524: int
                    525: isadma_bounce_dmamem_alloc(bus_dma_tag_t t, bus_size_t size,
                    526:     bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs,
                    527:     int nsegs, int *rsegs, int flags)
                    528: {
                    529:        paddr_t high;
                    530:
                    531:        if (avail_end > ISA_DMA_BOUNCE_THRESHOLD)
                    532:                high = trunc_page(ISA_DMA_BOUNCE_THRESHOLD);
                    533:        else
                    534:                high = trunc_page(avail_end);
                    535:
                    536:        return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
                    537:            segs, nsegs, rsegs, flags, 0, high));
                    538: }
                    539:
                    540: /**********************************************************************
                    541:  * ISA DMA utility functions
                    542:  **********************************************************************/
                    543:
                    544: int
                    545: isadma_bounce_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map,
                    546:     bus_size_t size, int flags)
                    547: {
                    548:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    549:        int error = 0;
                    550:
                    551:        cookie->id_bouncebuflen = round_page(size);
                    552:        error = isadma_bounce_dmamem_alloc(t, cookie->id_bouncebuflen,
                    553:            PAGE_SIZE, map->_dm_boundary, cookie->id_bouncesegs,
                    554:            map->_dm_segcnt, &cookie->id_nbouncesegs, flags);
                    555:        if (error)
                    556:                goto out;
                    557:        error = _bus_dmamem_map(t, cookie->id_bouncesegs,
                    558:            cookie->id_nbouncesegs, cookie->id_bouncebuflen,
                    559:            (caddr_t *)&cookie->id_bouncebuf, flags);
                    560:
                    561:  out:
                    562:        if (error) {
                    563:                _bus_dmamem_free(t, cookie->id_bouncesegs,
                    564:                    cookie->id_nbouncesegs);
                    565:                cookie->id_bouncebuflen = 0;
                    566:                cookie->id_nbouncesegs = 0;
                    567:        } else
                    568:                cookie->id_flags |= ID_HAS_BOUNCE;
                    569:
                    570:        return (error);
                    571: }
                    572:
                    573: void
                    574: isadma_bounce_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map)
                    575: {
                    576:        struct isadma_bounce_cookie *cookie = map->_dm_cookie;
                    577:
                    578:        _bus_dmamem_unmap(t, cookie->id_bouncebuf,
                    579:            cookie->id_bouncebuflen);
                    580:        _bus_dmamem_free(t, cookie->id_bouncesegs,
                    581:            cookie->id_nbouncesegs);
                    582:        cookie->id_bouncebuflen = 0;
                    583:        cookie->id_nbouncesegs = 0;
                    584:        cookie->id_flags &= ~ID_HAS_BOUNCE;
                    585: }

CVSweb