A few questions about SD/MMC drivers
Martin Galvan
omgalvan.86 at gmail.com
Tue Oct 14 00:19:36 UTC 2014
Well, that makes sense now. I'll try it out and let you know if it
worked, thanks a ton!
Just to be clear, though (and forgive me for my ignorance on this
matter): is the "buffer" referenced in mmc_data always contiguous in
memory? If so, why use segments/scatterlists at all? I thought the
whole point of using descriptor lists in DMA transfers was to work
with portions of memory that weren't next to each other. If the data
we want to transfer is all in a single contiguous region, wouldn't a
single descriptor with the required bus address and buffer length be
enough?
2014-10-13 20:41 GMT-03:00 Ian Lepore <ian at freebsd.org>:
> On Mon, 2014-10-13 at 20:25 -0300, Martin Galvan wrote:
>> 2014-10-13 11:57 GMT-03:00 Warner Losh <imp at bsdimp.com>:
>> > On Oct 12, 2014, at 11:24 PM, Martin Galvan <omgalvan.86 at gmail.com> wrote:
>> >> The host found in Allwinner SoCs uses a DMA controller which works
>> >> with a linked list of descriptors, each having info on a data buffer.
>> >> In the Linux driver they allocate a coherent DMA buffer using
>> >> dma_alloc_coherent to get both the virtual and bus addresses of the
>> >> descriptor list. When it's time to do a DMA transfer, the Linux driver
>> >> allocates a scatterlist with each entry being a buffer corresponding
>> >> to a descriptor; it then loops through the descriptor list setting the
>> >> "buffer pointer" field of each one to the bus address of the
>> >> corresponding scatterlist entry, and the "next descriptor" to the bus
>> >> address of the following descriptor. It's pretty neat, though it's
>> >> worth mentioning the scatterlist that the MMC request handler maps
>> >> already contains the virtual addresses of the requested buffers.
>> >>
>> >> Do we have anything like that on BSD? If not, what would be a simple
>> >> algorithm to make this work?
>> >
>> > Pretty much all of that is covered in busdma(8). The mechanics are a bit
>> > different than Linux, sure, but all that functionality is there.
>>
>> Actually, other than being able to alloc DMA buffers and get their bus
>> addresses I didn't see anything like the Linux scatterlists.
>>
>> The main problem here is that the Linux mmc_data struct comes with an
>> already-filled scatterlist. In that case, all I have to do is build
>> the descriptor chain with the buffer addresses from the scatterlist
>> entries. The only thing that's similar to that in the BSD API is
>> mbuf_sg, which is used for network stuff. I didn't see anything that
>> could allow me to build a descriptor chain-- all I saw was that the
>> BSD mmc_data type has a buffer instead of a scatterlist.
>>
>> I'm thinking of telling the DMA controller to work with a single
>> descriptor whose buffer is the one that comes inside mmc_data, but I'm
>> not sure if this would be right.
>>
>> Again thanks a lot for your answers.
>
> When you map the buffer with bus_dmamap_load() your callback function is
> passed an array of bus_dma_segment structures, each element of the array
> is the physical address and size of a contiguous physical segment that
> makes up part of the overall buffer. You are g'teed not to get more
> segments than the limit specified in the dma tag used for the map (but
> that just means the map function fails if there are too many segments,
> not that some sort of automatic copy/consolidate is done for you). In
> general you won't have a problem if you handle (512 * MAX_DATA +
> PAGE_SIZE - 1) / PAGE_SIZE segments (MAX_DATA is a horrible ivar name
> but I guess we're stuck with it now).
>
> If you need a linked list rather than an array of physical addr/size
> tuples, you'll have to write a callback function that creates the list
> from the array.
>
> -- Ian
>
>
More information about the freebsd-embedded
mailing list