DMA buffer again
Jan Kiszka
kiszka at rts.uni-hannover.de
Tue Jan 27 16:47:39 CET 2004
Rodrigo Amestica schrieb:
> if I use rt_malloc I cannot make the buffer available to user-land, or?
> I did not say it before, but the buffer must be readable from user space.
>
This makes things slightly more complicated...
> Looks like I cannot make a DMA contiguous buffer available to user land,
> it looks like I will need to copy from the DMA buffer to a place where
> user-land can read. I was trying to avoid this copying step.
>
Hard real-time user land? Then don't forget to lock the memory!
It is not impossible. I just found some code remainder in our CVS. The
skb header and data are in the same chunk of memory to which "skb" is
pointing:
rtskb.h:
/* sanity check */
#if PAGE_SIZE < DEFAULT_MAX_RTSKB_SIZE
#error The page size is smaller than the rtskb size. This may
prevent
#error DMA mapping of non-continuous rtskbs. You have to disable
#error CONFIG_RTAI_MM_VMALLOC in RTAI to compile RTnet for the
selected
#error architecture.
#endif
/* This macro calculates the kernel virtual address which can be
passed to
* pci_map_single(). */
#define RTSKB_KVA(skb, addr) \
(void*)((unsigned long)skb->buf_page_addr | ((unsigned
long)addr & (PAGE_SIZE-1)))
/* The rtskb structure and its data buffer are allocated as one
chunk. If
* vmalloc'ed memory is used for rtskb's, the buffer has to fit into a
* single page to allow DMA mapping. This macro extends the rtskb
structure
* size in order to be able to adjust the buffer start
appropriately. */
#define ALIGN_RTSKB_STRUCT_LEN SKB_DATA_ALIGN(sizeof(struct
rtskb)) + \
SKB_DATA_ALIGN(DEFAULT_MAX_RTSKB_SIZE)
rtskb.c:
/* align buffer start so that it fits into a single page */
skb->buf_start = ((char *)skb) + ALIGN_RTSKB_BUF;
if (((unsigned long)skb->buf_start & (PAGE_SIZE-1)) +
DEFAULT_MAX_RTSKB_SIZE > PAGE_SIZE)
skb->buf_start =
(unsigned char*)(((unsigned long)skb->buf_start &
~(PAGE_SIZE-1)) +
PAGE_SIZE);
/* calculate logical buffer page address */
skb->buf_page_addr = page_address(vmalloc_to_page(skb->buf_start));
You can see, the approach was to pre-calculate the physical address in
order to pass it fast to the hardware when needed.
Of course, copy_to/from_user is a bit easier :)
Jan
More information about the Rtai
mailing list