I need to porting a bunch of pci dma pool functions “pci_pool_*()” from linux, e.g. “pci_pool_create()” and “pci_pool_alloc()”. I’m wondering if there’s similar functions in QNX or I have to write my own DMA pool functions in QNX?
I’m not familliar with the pool function from LINUX. QNX has none but I suspect it doesn’t need it in most cases. Just get DMAable memory when you need it.
It think this might be usefull if you need lots a big chunck of contiguous memory and want to make sure there is enough contiguous memory big enough during the entire life of the program.
We had contact with QNX for DMAable copy operations, there are no functions like this under QNX. As mario mentioned try mmap DMAable memory if you need this. As mario already mentioned, the biggest problem is the size of the contigous memory and the mapping of it ^^
Well, I encounter a problem when I’m trying to resolve this issue.
As for my device, its DMAable memory is 4k-page aligned and the DMA data size is 4k bytes once a time. So my idea is to allocate a big chunck of DMAable memory pool during the device initialization, the size of this memory pool is DMA_BLOCK_SIZE(4k) * MAX_CONCURRENT_DMA, say the MAX_CONCURRENT_DMA is 32. Later on when a DMA transfer is to start, a block of free DMA memory is allocated from this memory pool. It seems quite simple but I have a problem of getting the correct DMA memory block address. Here is my code:
//Create a DMA memory pool
dev->dma.pool.addr = mmap64(0, DMA_BLOCK_SIZE * MAX_CONCURRENT_DMA, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON | MAP_NOX64K , NOFD, 0 );
mem_offset64(dev->dma.pool.addr, NOFD, 1, &dev->dma.pool.offset, 0);
########allocate DMA block from the DMA pool before a DMA transfer#####
id = get_free_dma_block();
if (id == -1 || id > (MAX_CONCURRENT_DMA - 1))
//do some error handling…
dma_buf = dev->dma.pool.addr + id * DMA_BLOCK_SIZE ;
dma_addr = dev->dma.pool.offset + id * DMA_BLOCK_SIZE;
The above two lines are the trouble points. When id is 0, the dma address works fine. But if id is not 0, the returned “dma_buf” and “dma_addr” will cause my device a internal address error.
So my question is how to get the correct virtual and dma address here?
dma_buf contains the virtual address and dma_addr contains the physical addres. However how are dma.pool.addr and dma.pool.offset defined? If they are for example defined as pointer to int that may not give you the math you where hoping for.
Thanks! Here is the defination:
unsigned int *addr;
Should I use “void *” instead of “unsigned int *” for dma.pool.addr?
the fact that addr is a pointer to an int means that what really happens is (that’s basic C stuff):
dma_buf = dev->dma.pool.addr + ( id * DMA_BLOCK_SIZE ) * sizeof ( int );
but dma_addr shoud be ok because pool.offset is an integer and not a pointer.