jason.harmening at gmail.com
Sun Jun 8 05:03:32 UTC 2008
I've written a FreeBSD driver for Conexant CX2388x-based PCI TV capture cards.
Of course the driver uses busdma to be as machine-independent as possible.
One problem I've encountered is that bus_dmamem_alloc is inadequate for my
needs. The CX2388x only understands 32-bit physical addreses, and the driver
has two separate use cases for busdma:
1) Data buffers: These buffers may be relatively large (a 640x480 RGB32 video
frame is ~1.2M), and therefore it is desirable that these buffers not be
2) DMA program buffers: The DMA engine on the CX2388x is controlled by
special-purpose RISC instructions, usually stored in host memory, that
provide information on, among other things, the physical layout of the data
buffers, which enables handling of non-contiguous data buffers. These
programs are rarely more than a few pages in size, so for the sake of
simplicity it is desirable that DMA program buffers be physically contiguous.
For case 1), I malloc(9) the buffers and then feed them to busdma, since on
most machines bus_dmamem_alloc just calls contigmalloc. Use of malloc(9) is
suboptimal as it may result in bounce buffering for non-IOMMU machines with
large amounts of RAM.
For case 2), I contigmalloc the DMA program buffers in the 32-bit physical
address range and then feed them to busdma. I don't use bus_dmamem_alloc
here because it always allocates the maximum size specified in the
bus_dma_tag_t. Since the driver supports dynamic data buffer allocation and
DMA program generation, DMA program sizes may vary significantly. I
therefore just create the bus_dma_tag_t with the maximum possible size for a
DMA program buffer since I'd prefer not to have to re-create the tag every
time the DMA program size changes. But always allocating the maximum buffer
size would be a huge waste of contiguous memory, so bus_dmamem_alloc is out
of the question here too. At the same time, use of contigmalloc is
suboptimal as it may not be necessary to restrict the allocation to 32-bit
physical addresses on IOMMU-equipped machines. This is something that
bus_dmamem_alloc could take care of, if only it supported a size parameter
(as I believe the NetBSD version does).
So I have 3 questions:
1) Would it be possible to provide a bus_dmamem_alloc overload that takes a
size parameter? We could call it bus_dmamem_alloc_size and have
bus_dmamem_alloc just call bus_dmamem_alloc_size with dmat->maxsize to
preserve source-level compatibility with existing drivers.
2) Are there currently any serious plans to have bus_dmamem_alloc perform
multi-segment allocations on non-IOMMU machines? It looks like NetBSD does
this by reserving the physical segments and then stitching them together into
a virtually contiguous range. Is something like this feasible for FreeBSD?
3) Are there currently any serious plans to support IOMMUs on anything besides
Sun machines? The AMD AGP GART, PowerPC 970 DART, and Intel VT-d and AMD
IOMMU all come to mind.
If any of these ideas sound feasible, I'd be more than willing to help
More information about the freebsd-hackers