I want to realize scatter/gather DMA operations on a scatter/gather DMA capable PCI device we have developped. My platform is running QNX 6.3 w/ PPC603e (MPC8245).
I have build a chained list of pages descriptor (AddrLo, AddrHi, Size and Next).
I retrieve the physical address of each page using mem_offset.
Read / write operations seem to work if we want to transfer up to 1MBytes. But not above.
Thanks Mario and Evanh.
My PCI device works fine in scatter / gather mode under Windows XP and Linux 2.4 where I can transfer up to 16M.
I wonder If if use the correct method to allocate DMA. My allocation function resides in the attached file dma_alloc.c.
Do I have to use
mmap_device_memory(
pDesc, // virt addr of page desc list structure
ulRequiredPages * sizeof(page_desc_t),
PROT_READ | PROT_WRITE | PROT_NO_CACHE,
MAP_FIXED,
phys // phys addr of pDesc given by mem_offset
);
or equivalent in order to map pDesc into a physically contiguous memory area ?
Furthermore we are able to store up to 256 page descriptors inside one page (contiguous) (__PAGESIZE/sizeof(page_desc_t) = 256). Each page descriptor defines a 4K user buffer block. So 4K*256 = 1MBytes (perhaps the 1MBytes limit that I have noted earlier).
I think you got it backward mmap_device_memory is used to map a physical device memory into a program space, hence because it’s physical device memory it is by definition contigeous. In your case you don’t show how you allocate the user space. I assume you are doing a malloc or something of that nature (?), the memory returned by calloc is NOT guaranty to be allocated in contigeous memory. calling mmap_device_memory on a pointer will not make the memory contigeous.
You must allocated the DMA memory with mmap in the first place and specify the MAP_PHYS | MAP_ANON | MAP_NO64K, ans possible MAP_BELOW16M if the device is ISA based.
When I use mmap with MAP_PHYS, the help doc tells that physical memory is required (the off parameter ???). So, when I allocate the DMA memory with mmap specifying the MAP_PHYS | MAP_ANON | MAP_NO64K what is the meaning of the off parameter ? Could I set off to 0 ?