/* $Id: at91pdc.c,v 1.3 2011/07/01 19:31:17 dyoung Exp $ */ #include #include #include int at91pdc_alloc_fifo(bus_dma_tag_t dmat, at91pdc_fifo_t *fifo, int size, int flags) { bus_dma_segment_t segs; int rsegs; int err; int f; memset(fifo, 0, sizeof(*fifo)); /* allocate map: */ f = flags & (BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4); err = bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_WAITOK | f, &fifo->f_dmamap); if (err) goto fail_0; /* allocate DMA safe memory: */ f |= flags & BUS_DMA_STREAMING; err = bus_dmamem_alloc(dmat, size, 0, size, &segs, 1, &rsegs, BUS_DMA_WAITOK | f); if (err) goto fail_1; /* allocate virtual memory: */ f |= flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE); err = bus_dmamem_map(dmat, &segs, 1, size, &fifo->f_buf, BUS_DMA_WAITOK | f); if (err) goto fail_2; /* connect physical to virtual memory: */ f |= flags & (BUS_DMA_READ | BUS_DMA_WRITE); f &= ~(BUS_DMA_COHERENT | BUS_DMA_NOCACHE); err = bus_dmamap_load(dmat, fifo->f_dmamap, fifo->f_buf, size, NULL, BUS_DMA_NOWAIT | f); if (err) goto fail_3; /* initialize rest of the structure: */ fifo->f_buf_size = size; fifo->f_ndx = fifo->f_length = 0; fifo->f_buf_addr = fifo->f_dmamap->dm_segs[0].ds_addr; fifo->f_pdc_rd_ndx = fifo->f_pdc_wr_ndx = 0; fifo->f_pdc_space = fifo->f_buf_size; return 0; fail_3: bus_dmamem_unmap(dmat, fifo->f_buf, size); fail_2: bus_dmamem_free(dmat, &segs, rsegs); fail_1: bus_dmamap_destroy(dmat, fifo->f_dmamap); fail_0: return err; }