Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to do DMA

274 views
Skip to first unread message

gfe...@lerc.nasa.gov

unread,
Jun 24, 1998, 3:00:00 AM6/24/98
to

I have an application where I need to use DMA. The rub is that I've never
worked with DMA and am fairly new to QNX so I'm already in the hole.

I'm working with an A/D board (Versalogic 1295) to do some high speed data
acquitisition (~5000Hz). My processor is the Ziatech 8905 (pentium 100MHz)
that has two 8237 DMA controllers.

In any case, I have alot to learn in a short time and was hoping someone out
there can point me to where I can learn more about what DMA is and how to use
it under QNX. It would be too much to ask for someone who has worked with
this hardware before, so I won't be so brash...but if you have...:)

Any assistance would be appreciated.
Thanks

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

Dave Nickerson

unread,
Jun 24, 1998, 3:00:00 AM6/24/98
to

You can read a document that is shipped with QNX4.2x called
/etc/readme/technotes/shmem.txt . You will likely need to use shared memory
for the DMA programming and this doc has a section on setting-up the shared
memory for DMA use.


gfe...@lerc.nasa.gov wrote in message <6mqt3j$853$1...@nnrp1.dejanews.com>...

Armin Steinhoff

unread,
Jun 24, 1998, 3:00:00 AM6/24/98
to

In article <6mqt3j$853$1...@nnrp1.dejanews.com>, gfe...@lerc.nasa.gov says...

>
>I have an application where I need to use DMA. The rub is that I've never
>worked with DMA and am fairly new to QNX so I'm already in the hole.

OK ... fill it with the DAS_toolkit.tgz at quics:

/usr/free/qnx4/os/samples/misc

Armin Steinhoff

http://www.DACHS.net

>
>I'm working with an A/D board (Versalogic 1295) to do some high speed data
>acquitisition (~5000Hz). My processor is the Ziatech 8905 (pentium 100MHz)
>that has two 8237 DMA controllers.
>
>In any case, I have alot to learn in a short time and was hoping someone out
>there can point me to where I can learn more about what DMA is and how to use
>it under QNX. It would be too much to ask for someone who has worked with
>this hardware before, so I won't be so brash...but if you have...:)
>
>Any assistance would be appreciated.
>Thanks
>
>-----== Posted via Deja News, The Leader in Internet Discussion ==-----
>http://www.dejanews.com/ Now offering spam-free web-based newsreading

------------------
Spam free Usenet news http://www.newsguy.com

Mitchell Schoenbrun

unread,
Jun 24, 1998, 3:00:00 AM6/24/98
to

gfe...@lerc.nasa.gov wrote:
> I have an application where I need to use DMA. The rub is that I've never
> worked with DMA and am fairly new to QNX so I'm already in the hole.

Here is some basic background on DMA channels.

A DMA channel is a single function separate microprocessor that is wired
between the system memory and the BUS. It is capable of moving data
between an external device and memory directly. When operating it
shares access to memory with the processor.

There are two versions of setting up a DMA transfer. In on scenario
you setup the DMA channel, and then setup your hardware to do the
transfer. Typically then you wait for an interrupt, or poll for
the end of the transfer.

The other version is known as DMA bus mastering. In this case, you
simply program your hardware to do the transfer. It then takes
over and controls the DMA directly.

Most ISA cards used the former method, although some such as the
Adaptec AHA1540 are bus masters. All PCI cards I've come across so far
have been bus masters.

With ISA DMA channels you are limited to 64Kbyte transfers. Worse yet
the data must be on a 64Kbyte memory boundardy. This is because the
ISA DMA channels came from the 8bit world. An 8 bit "Page"
register allows you to set the 64Kbyte block, but a single transfer
cannot transverse this block. Instead it would wrap around.
PCI DMA channels do not have this limitation.

A central problem is dealing with DMA transfers is that DMA channels
deal in Real memory. All programs running under QNX 4 are running
in a doubly virtualized memory space. Memory that appears contiguous
in virtual space may not be in real. To get memory that
you will use for DMA transfers, you can use either the shmem
routines (recommended) or the qnx_segment_alloc_flags() routine.
With the shmem routines you must specify _PMF_DMA_SAFE and
possibly _PMF_DMA_HIGH.

To get the real address from the virtual address, you could use
qnx_segment_overlay_flags() using the _PMF_VOVERLAY
flag to create a segment pointer, and then use
qnx_segment_info() to get the real address.


Mitchell Schoenbrun --------- masc...@pobox.com

Barry Millman

unread,
Jun 26, 1998, 3:00:00 AM6/26/98
to Mitchell Schoenbrun

Mitchell Schoenbrun wrote:

> A central problem is dealing with DMA transfers is that DMA channels
> deal in Real memory. All programs running under QNX 4 are running
> in a doubly virtualized memory space. Memory that appears contiguous
> in virtual space may not be in real. To get memory that
> you will use for DMA transfers, you can use either the shmem
> routines (recommended) or the qnx_segment_alloc_flags() routine.
> With the shmem routines you must specify _PMF_DMA_SAFE and
> possibly _PMF_DMA_HIGH.
>
> To get the real address from the virtual address, you could use
> qnx_segment_overlay_flags() using the _PMF_VOVERLAY
> flag to create a segment pointer, and then use
> qnx_segment_info() to get the real address.
>
> Mitchell Schoenbrun --------- masc...@pobox.com

Mitchell:
I have been spending a wonderfuol day experimenting with this stuff. I
think there is a bit of confusion here.

I suspect that there are at least two ways to get some DMA memory:

First way:

// get a block of ram and get the physical address to it
segno = qnx_segment_alloc_flags(size, _PMF_DMA_SAFE);
qnx_segment_info(..., &sbuf);
// map it to your data space
fd =shm_open("Physical",...);
ptr = mmap(0, size, prots, shares, fd, sbuf.addr);

Tell the DMA controller the physical address (sbuf.addr) and use the
pointer (ptr).

Second way (you don't like the qnx_segment functions...you said EITHER
OR in your post)

// get a block of memory (1 meg, just for fun)
fd = shmem_open("dma",...);
ltrunc(fd, 1000000,SEEK_SET);
//get its physical address (qnx_segment_overlay_flags with
_PMF_VOVERLAY doesn't work, when
// followed by qnx_segment_info....at least I couldn't get it to work in
QNX 4.23...it returned the
// virtual address)
// instead, I did this to get its PHYSICAL address
fstat(fd, &stat_buf);
// stat_buf.st_ino contains the physical address AFTER the
ltrunc

Now I mapped this into my address space using "Physical" and the mmap as
described in the above example.

Is this what you mean by using either the qnx_segment_alloc_flags() OR
the shmem?
If you use the qnx_segment_alloc_flags() you still have to use
shmen_open and mmap to map
a pointer (in your address space) to the physical address.

BTW, the technote uses the first type, not the second, which uses
fstat(...)

BTW, this stuff is actually documented...you just have to read a lot of
function stuff to find it, and spend about a day experimenting.

Please tell me if you were able (as you said in your post) to get the
PHYSICAL address using
qnx_segment_overlay_flags() and qnx_segment_info(). As I mentioned this
kept giving me a virtual address.

Thanks,
Barry

--------------------------------------------------
Training in QNX 4 Real-Time Programming
- on YOUR desktop
- with your success guaranteed!
Coming soon from Igetitnow! Training, Inc.
--------------------------------------------------

David Gibbs

unread,
Jun 30, 1998, 3:00:00 AM6/30/98
to

In article <35914...@news.tsoft.net>,

Mitchell Schoenbrun <masc...@tsoft.com> wrote:
>gfe...@lerc.nasa.gov wrote:
>> I have an application where I need to use DMA. The rub is that I've never
>> worked with DMA and am fairly new to QNX so I'm already in the hole.
>
>Here is some basic background on DMA channels.
>
>
>A central problem is dealing with DMA transfers is that DMA channels
>deal in Real memory. All programs running under QNX 4 are running
>in a doubly virtualized memory space. Memory that appears contiguous
>in virtual space may not be in real.

Good summary up to this point.

> To get memory that
>you will use for DMA transfers, you can use either the shmem
>routines (recommended) or the qnx_segment_alloc_flags() routine.
>With the shmem routines you must specify _PMF_DMA_SAFE and
>possibly _PMF_DMA_HIGH.

The shmem routines don't allow you to allocate the DMA safe memory,
you have to use the qnx_segment_alloc_flags() to do so. The shmem/mmap
routines then allow you to map this memory into your (32 bit) program's
address space in order for you program to conveniently access this
memory area (pass it to library routines, write data to it, etc.)

>To get the real address from the virtual address, you could use
>qnx_segment_overlay_flags() using the _PMF_VOVERLAY
>flag to create a segment pointer, and then use
>qnx_segment_info() to get the real address.

I would not use qnx_segment_overlay[_flags]() in a 32 bit program.
qnx_segment_info() is useful in both 16 & 32 bit programs for getting
the physical address of the memory area -- needed for passing to your
DMA controller and for mmap() when you map the allocated memory into
your process' address space in 32 bit.

-David
--
David Gibbs
dag...@qnx.com

Mitchell Schoenbrun

unread,
Jul 2, 1998, 3:00:00 AM7/2/98
to

Barry Millman <bmil...@entrenet.com> wrote:

> First way:

> // get a block of ram and get the physical address to it
> segno = qnx_segment_alloc_flags(size, _PMF_DMA_SAFE);
> qnx_segment_info(..., &sbuf);
> // map it to your data space
> fd =shm_open("Physical",...);
> ptr = mmap(0, size, prots, shares, fd, sbuf.addr);

> Tell the DMA controller the physical address (sbuf.addr) and use the
> pointer (ptr).

Sorry for the confusion here. This first way is the only way under
QNX 4.24. Even if you are using an older version in which
shared memory is DMA safe, you should still use this method, as
it will break in 4.24. The last tow lines are incorrect. Leave
out the shm_open and the mmap(). The sbuf data returned from
qnx_segment_info() will have the real address. To access the
data from QNX:

char far *ptr;

ptr = MK_FP(segno,0);

> Second way (you don't like the qnx_segment functions...you said EITHER
> OR in your post)

My mistake. I'd gotten used to using shmem in 4.23 and forgot that it
was broke. The reason I liked shmem is that it is Posix compliant,
and avoids the use of far pointers. It is no longer an option as
QNX does not allocate DMA safe memory when you create shared memory.

Mitchell Schoenbrun --------- masc...@pobox.com

Barry Millman

unread,
Jul 3, 1998, 3:00:00 AM7/3/98
to Mitchell Schoenbrun

Mitchell Schoenbrun wrote:
>
> Barry Millman <bmil...@entrenet.com> wrote:
>
> > First way:
>
> > // get a block of ram and get the physical address to it
> > segno = qnx_segment_alloc_flags(size, _PMF_DMA_SAFE);
> > qnx_segment_info(..., &sbuf);
> > // map it to your data space
> > fd =shm_open("Physical",...);
> > ptr = mmap(0, size, prots, shares, fd, sbuf.addr);
>
> > Tell the DMA controller the physical address (sbuf.addr) and use the
> > pointer (ptr).
>
The sbuf data returned from
> qnx_segment_info() will have the real address. To access the
> data from QNX:
>
> char far *ptr;
>
> ptr = MK_FP(segno,0);
>

Mitchell:
I prefer to use the shm_open(with "Physical"...) and mmap() to get my
"local" pointer, rather than the MK_FP macro. Perhaps I am just
superstitious ;-).

Thanks for the comments,
Barry

> Mitchell Schoenbrun --------- masc...@pobox.com

--

David Gibbs

unread,
Jul 9, 1998, 3:00:00 AM7/9/98
to
In article <359CFB...@entrenet.com>,

Barry Millman <bmil...@entrenet.com> wrote:
>Mitchell Schoenbrun wrote:
>>
>> Barry Millman <bmil...@entrenet.com> wrote:
>>
>> > First way:
>>
>> > // get a block of ram and get the physical address to it
>> > segno = qnx_segment_alloc_flags(size, _PMF_DMA_SAFE);
>> > qnx_segment_info(..., &sbuf);
>> > // map it to your data space
>> > fd =shm_open("Physical",...);
>> > ptr = mmap(0, size, prots, shares, fd, sbuf.addr);
>>
>> > Tell the DMA controller the physical address (sbuf.addr) and use the
>> > pointer (ptr).
>>
> The sbuf data returned from
>> qnx_segment_info() will have the real address. To access the
>> data from QNX:
>>
>> char far *ptr;
>>
>> ptr = MK_FP(segno,0);
>>
>
>Mitchell:
> I prefer to use the shm_open(with "Physical"...) and mmap() to get my
>"local" pointer, rather than the MK_FP macro. Perhaps I am just
>superstitious ;-).

I agree -- the problem with MK_FP is that you get a far pointer, that is
a 16 bit segment & 32 bit offset -> 48 bit pointer. Unfortunately, all
library routines (and probably most of your code unless you are careful
to pass FAR * everywhere) take near (32 bit) pointers, so you will get
lots of pointer truncations, and none of the library routines, even if
you get them to compile, will do what you want them to.

Mitchell Schoenbrun

unread,
Jul 10, 1998, 3:00:00 AM7/10/98
to
David Gibbs <dag...@qnx.com> wrote:

> I agree -- the problem with MK_FP is that you get a far pointer, that is
> a 16 bit segment & 32 bit offset -> 48 bit pointer. Unfortunately, all
> library routines (and probably most of your code unless you are careful
> to pass FAR * everywhere) take near (32 bit) pointers, so you will get
> lots of pointer truncations, and none of the library routines, even if
> you get them to compile, will do what you want them to.

This has been going around so much I'm dizzy. Did we cover the fact
that once you get the memory with qnx_segment_alloc_flags()
you can find the real address with qnx_segment_info() and then
use the shared memory routines with the "Physical" object to
map in without using far pointers? Sorry if I'm repeating.

David Gibbs

unread,
Jul 15, 1998, 3:00:00 AM7/15/98
to
In article <35a67...@news.tsoft.net>,

Yes, we did. I was just covering the WHY you should do that,
instead of just doing a MK_FP.

0 new messages