allocate DMA cache help

Hi, averyone

I´m porting device driver for vxworks to qnx 6.30.

i’ve found this function “cacheDmaMalloc” and in linux use this function “kmem_cache_create” for do it same, below are the description of this functions, can you tell me what is the function equivalent or how can the same functionality on qnx?


NAME
cacheDmaMalloc( ) - allocate a cache-safe buffer for DMA devices and drivers

SYNOPSIS

void * cacheDmaMalloc
(
size_t bytes /* number of bytes to allocate */
)
DESCRIPTION
This routine returns a pointer to a section of memory that will not experience any cache coherency problems. Function pointers in the CACHE_FUNCS structure provide access to DMA support routines.

RETURNS
A pointer to the cache-safe buffer, or NULL.



Name
kmem_cache_create – Create a cache.
Synopsis

kmem_cache_t * kmem_cache_create (const char * name, size_t size, size_t offset, unsigned long flags, void (ctor) (void, kmem_cache_t *, unsigned long), void (dtor) (void, kmem_cache_t *, unsigned long));

Arguments

name
A string which is used in /proc/slabinfo to identify this cache.

size
The size of objects to be created in this cache.

offset
The offset to use within the page.

flags
SLAB flags

ctor
A constructor for the objects.

dtor
A destructor for the objects.

Description
Returns a ptr to the cache on success, NULL on failure. Cannot be called within a int, but can be interrupted. The ctor is run when new pages are allocated by the cache and the dtor is run before the pages are handed back. The flags are

SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) to catch references to uninitialised memory.

SLAB_RED_ZONE - Insert `Red’ zones around the allocated memory to check for buffer overruns.

SLAB_NO_REAP - Don’t automatically reap this cache when we’re under memory pressure.

SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware cacheline. This can be beneficial if you’re counting cycles as closely as davem.


thanks!!!

and i´m sorry if my english is bad, i’m learning yet.

Here’s how to do it with Posix (QNX is Posix compliant):

addr = mmap( 0,
XXXX,
PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_ANON,
NOFD,
0 );

Where XXXX is the amount of physically contiguous uncached memory required.

Now, since QNX uses virtual memory, “addr” is a virtual address which is fine for accessing the memory from your program, but if this is to be used with DMA, then the device performing the DMA will need the physical address.

So (anticipating your next question), in order to translate “addr” to a physical address, you need to call, mem_offset() which is a proprietary QNX call (there is a Posix function for this - posix_mem_offset(), but it is currently unimplemented in QNX).

Here is how you use mem_offset() to translate “addr” into a physical address (so that you can program the DMA):


uint32_t offset;

mem_offset(addr, NOFD, 1, &offset, 0) ;

Following this call, offset contains the physical address of the memory “pointed to” by “addr”.

You can now reference the memory area in your program via “addr” and program DMA operations using “offset”.

thanks rgallen.

Thanks. I was read something of that but was not safe if that were the answer, thanks for confirmme!

For most primitive DMA controllers that is only half the addressing answer. If it is even that much.

Do we then take the phys address we get from mem_offset() and transform it somehow to get the page that the DMA controller demands to go with the offset? And do we not have to actually transform that offset to match the expectations of the DMA controller? I am muddling through this very process myself now, and I am not a happy camper.

respectfully
BJ

Sounds like your refering to an old 8237. They aren’t that difficult. Just make sure that when you mmap() you “or in” MAP_BELOW16M and MAP_NOX64K.

The following two macros will get you the page and offset.

DMA_PAGE(paddr) ((uint8_t)((paddr >> 16) & 0xff))
DMA_OFFSET(paddr) ((uint16_t)(paddr & 0xffff))

Well there’s your problem. Coding while camping sucks (generator noise, flaky satellite internet connection, bears, squirrels, etc.).

Thanks… I REALLY needed those Macros because I couldn’t relate the prehistoric documentation on the web and lack of a “segment” concept in neutrino to the 8237 which is indeed the target of my efforts. Unable to be certain of the format of the phys_addr I have been indulging in archaeology while I am camping out here :slight_smile:

That should be all - Thanks again

BJ

No problem; although, since I predate the “prehistoric” documentation, and I remember when segments were so integral to QNX that there was a “QNX C” language extension for referencing off of them, your making me feel old :slight_smile: