Setting up memory for ISA DMA use

I’m developing an ISA peripheral card that uses 16-bit DMA in either direction. I use mmap_device_memory( ) to allocate buffers for transmit and receive, using the MAP_* flags needed for ISA DMA (the DMA controller has limited addressing capabilities on ISA, so the buffer cannot cross a page boundary or be above 16 Mb) There’s evidence that this call is still causing memory stompage (transferring large messages cause strange system behaviour) so I’m wondering if my call is missing a parameter:

  temp_ptr = mmap_device_memory(  NULL,
                   256,
                   PROT_READ|PROT_WRITE|PROT_NOCACHE,
                   MAP_BELOW16M|MAP_NOX64K,
                   NULL);

I tried this one, but got the exception “Invalid FD” or something… the call failed, anyway.
With the addition of MAP_ANON, only the 1st word of each buffer was non-zero, and that didn’t work very well either.

temp_ptr = mmap( NULL,
256,
PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_BELOW16M|MAP_NOX64K|MAP_PRIVATE,
NOFD,
0); /* Use a zero offset? */

The documentation does not give an example of how to use mmap/mmap_device_memory() to allocate a buffer for ISA DMA use, just PCI DMA use (and PCI doesn’t have the same restrictions). Can someone point out what I’m doing wrong? There’s got to be a QNX driver for an ISA DMA device that already has this figured out; it shouldn’t be this hard!

Thanks very much,

Tony Nordstrom

mmap give you a virtual address.
for dma controllers (ISA and PCI) you should use phisical address.
so try to use the next couple of operators:

off_t dma_offset;

addr=mmap(NULL, DMA_BUF_SIZE, PROT_READ|PROT_WRITE,MAP_PHYS|MAP_BELOW16M|MAP_NOX64K|MAP_ANON|MAP_PRIVATE, NOFD, 0);
mem_offset(addr, NOFD, 1, &dma_offset, 0);

mem_offset returns for you value, that you can push to DMA controller.

PS: excuse my English.

SKB,

Thanks for your reply.

I tried the code you suggested, and observed some strange results; it suggests to me that I may have a problem with translating the physical address I get from mem_offset( ) to the DMA controller registers, or perhaps some other problem.

I currently use a mem_offset( ) call with the following parameters:

mem_offset(	msg_p,
			NOFD,
		ISL2_HW_TRANSFER_SIZE,	/* Buffer size, 256 */
		&physical_address,
			NULL);

I noticed that your example uses a length (3rd parameter) of 1, where I use 256.

I don’t understand your MAP_PHYS parameter specified by the mmap( ) call. Does the option map physical device memory, as opposed to allocating system RAM? My ISA device has a couple of IO registers for data, and the DMA controller needs to read/write from these registers into system memory; it is this system memory buffer that I need to set up. This is my first time working with ISA / DMA / QNX, so unfortunately I have something that “appears to work, most of the time” instead of starting from a point of expertise / experience. Would it help for me to describe further what I’m trying to do, and you can critique my approach?

Thanks very much

Tony

The doc (qnx.com/developers/docs/mome … /mmap.html) is clear on what MAP_PHYS is for.

A buffer of 256 bytes seems rather small for DMA?

“The most of the time” portion of the problem is I beleive relating to the setup of DMA controller and the device itself. If you follow what SKB suggest you should be ok.

the size parameter given by mem_offset isn’t really used (you could put the size you want and it wouldn’t make any difference)

I have found success with the following options for mmap( ):

temp_ptr = mmap(	NULL, 256,
			PROT_READ|PROT_WRITE|PROT_NOCACHE,
			MAP_PHYS|MAP_ANON|MAP_BELOW16M|MAP_NOX64K,
			NOFD, 0); 

The difference between this one and SKB’s suggested is that I’ve added PROT_NOCACHE, and I do not use MAP_PRIVATE. QNX Tech Support confirmed my version. In the meantime, I found other bugs in how I translate the physical address into DMA control register settings. For 16-bit DMA, the page register’s LSBit is zeroed; plus the address register (two bytes, written one at a time) is equal to the lower 16 bits of the physical address, right shifted by 1 (“word” addressing). The DMA controller is such a black box. :angry: :angry:

Thanks for your help everyone. Now on to the next problem…