allocate physical memory

Hello!


How do I allocate contiguos regions of physical memory in QNX4?

I’ve tried qnx_segment_alloc_* functions and I have found
two options here.

  1. Use qnx_segment_alloc_flags() with _PMF_DMA_SAFE flag. Then use
    qnx_segment_query() to obtain physical address (using
    flags other then _PMF_DMA_SAFE will result in that
    qnx_segment_query() gives me virtual address - not physical)
    The problem here is that I cannot allocate more than 64k
    of contiguos memory this way. (But I need 500k!!!)

  2. Use qnx_segment_alloc_raw().
    But how do I access this memory?
    I’m not sure that I can use
    shm_open and mmap funtions, because the memory chunk is
    removed from the system.

Can I use shm_open(“Physical”, ) and mmap() for this purpose?
In this case if I give certain phys_addr and buf_len to mmap as parameters
how do I
know this memory chunk isn’t used by QNX for other purpose?

Any suggestions or weblinks are welcome.

Best regards
Dmitri

check out the DMA_HIGH flag to qnx_segment_alloc_flags()
using it will cause the allocation to start on a 64k boundary above 1M

here’s some code to illustrate… notice also how you can get phys from the
virtual address.

/*-
SYNOPSIS
alloc_dmabuf, free_dmabuf – access memory for direct
memory access devices.

DESCRIPTION

This module provides two routines, which encapsulate
mechanisms for allocating and addressing memory regions
which are appropriate for use with direct memory access
devices.

alloc_dmabuf requires two arguments, a number of bytes, and
a pointer to a dma_t. The dma_t should not be modified nor
accessed directly by calling routines. The useful members
are exported through the manifests PADDR, VADDR for Physical
ADDRess and Virtual ADDRess respectively.

The actual amount of dma memory allocated may be more than
nbytes, but applications should not rely upon this.


free_dmabuf removes the mapping and allocation of memory for
the dma region. After calling free_dmabuf, the value of
the dma_t structure is undefined.

*/



#include <limits.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/proc_msg.h>
#include <sys/seginfo.h>

#include <fcntl.h>
#include <sys/mman.h>

/*-

  • alloc_dmabuf, free_dmabuf - access dma buffers.
    */

#ifndef dma_alloc_h
#define dma_alloc_h
#endif

#ifndef __TYPES_H_INCLUDED
#include <sys/types.h>
#endif

#define PHYSICAL_MEMORY “Physical”

typedef struct {
int segno; /* allocated segment number /
int seglen; /
length of segment /
paddr_t phys_addr; /
physical address /
caddr_t bufp; /
logical address */
} dma_t;

int alloc_dmabuf(dma_t * dbuf, int nbytes);
int free_dmabuf(dma_t * dbuf);

#define P_ADDR(d) ((d)->phys_addr)
#define V_ADDR(d) ((d)->bufp)


int
alloc_dmabuf(dma_t *p, int nbytes)
{
struct _seginfo sbuf;
int selector;
int fd;

if ((selector = qnx_segment_alloc_flags(nbytes,
_PMF_DMA_SAFE | _PMF_DMA_HIGH )) == -1) {
return -1;
}
if (qnx_segment_info(PROC_PID, 0, selector, &sbuf) == -1) {
qnx_segment_free(selector);
return -1;
}
P_ADDR(p) = sbuf.addr;
if ((fd=shm_open(PHYSICAL_MEMORY,O_RDWR,0)) == -1) {
qnx_segment_free(selector);
return -1;
}
p->segno = selector;
p->seglen = nbytes;
V_ADDR(p) = mmap(0,nbytes, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, P_ADDR(p));
close(fd);
if (P_ADDR(p) == (paddr_t)-1) {
qnx_segment_free(selector);
return -1;
}
return 0;
}

int
free_dmabuf(dma_t *dp)
{
munmap(V_ADDR(dp), dp->seglen);
qnx_segment_free(dp->segno);
return 0;
}

main(int argc, char **argv)
{
int ret;
dma_t d1;
unsigned nbytes = 0;

nbytes = atoi(argv[1]);

if ( nbytes == 0 ) {
printf(“use dma1 nbytes\n”);
exit(1);
}

printf(“allocating %u bytes in dma safe, high memory\n”, nbytes );

ret = alloc_dmabuf(&d1, nbytes);

printf(“ret=%d\n”, ret);
if ( ret != -1 ) {
printf(“d1: segno=%d, seglen=%d, phsy=0x%lx, log=0x%x\n”,
d1.segno, d1.seglen,
d1.phys_addr,
d1.bufp
);
}
sleep(500);
printf(“check out the mem with ‘sin mem’ … ctrl-c to quit\n”);
}


Dmitry Ivanov <id@pa.ru> wrote:

Hello!


How do I allocate contiguos regions of physical memory in QNX4?

I’ve tried qnx_segment_alloc_* functions and I have found
two options here.

  1. Use qnx_segment_alloc_flags() with _PMF_DMA_SAFE flag. Then use
    qnx_segment_query() to obtain physical address (using
    flags other then _PMF_DMA_SAFE will result in that
    qnx_segment_query() gives me virtual address - not physical)
    The problem here is that I cannot allocate more than 64k
    of contiguos memory this way. (But I need 500k!!!)

  2. Use qnx_segment_alloc_raw().
    But how do I access this memory?
    I’m not sure that I can use
    shm_open and mmap funtions, because the memory chunk is
    removed from the system.

Can I use shm_open(“Physical”, ) and mmap() for this purpose?
In this case if I give certain phys_addr and buf_len to mmap as parameters
how do I
know this memory chunk isn’t used by QNX for other purpose?

Any suggestions or weblinks are welcome.

Best regards
Dmitri


Randy Martin randy@qnx.com
Manager of FAE Group, North America
QNX Software Systems www.qnx.com
175 Terence Matthews Crescent, Kanata, Ontario, Canada K2M 1W8
Tel: 613-591-0931 Fax: 613-591-3579

“Randy Martin” <randy@qnx.com> wrote in message
news:97j326$o64$2@nntp.qnx.com

check out the DMA_HIGH flag to qnx_segment_alloc_flags()
using it will cause the allocation to start on a 64k boundary above 1M

The DMA_HIGH flag is not documented in my qnx_segment_alloc_flags. Is this
new? Where can I get the docs for this?

Thanks

Augie

here’s some code to illustrate… notice also how you can get phys from
the
virtual address.

/*-
SYNOPSIS
alloc_dmabuf, free_dmabuf – access memory for direct
memory access devices.

DESCRIPTION

This module provides two routines, which encapsulate
mechanisms for allocating and addressing memory regions
which are appropriate for use with direct memory access
devices.

alloc_dmabuf requires two arguments, a number of bytes, and
a pointer to a dma_t. The dma_t should not be modified nor
accessed directly by calling routines. The useful members
are exported through the manifests PADDR, VADDR for Physical
ADDRess and Virtual ADDRess respectively.

The actual amount of dma memory allocated may be more than
nbytes, but applications should not rely upon this.


free_dmabuf removes the mapping and allocation of memory for
the dma region. After calling free_dmabuf, the value of
the dma_t structure is undefined.

*/



#include <limits.h
#include <unistd.h

#include <sys/types.h
#include <sys/kernel.h
#include <sys/proc_msg.h
#include <sys/seginfo.h

#include <fcntl.h
#include <sys/mman.h

/*-

  • alloc_dmabuf, free_dmabuf - access dma buffers.
    */

#ifndef dma_alloc_h
#define dma_alloc_h
#endif

#ifndef __TYPES_H_INCLUDED
#include <sys/types.h
#endif

#define PHYSICAL_MEMORY “Physical”

typedef struct {
int segno; /* allocated segment number /
int seglen; /
length of segment /
paddr_t phys_addr; /
physical address /
caddr_t bufp; /
logical address */
} dma_t;

int alloc_dmabuf(dma_t * dbuf, int nbytes);
int free_dmabuf(dma_t * dbuf);

#define P_ADDR(d) ((d)->phys_addr)
#define V_ADDR(d) ((d)->bufp)


int
alloc_dmabuf(dma_t *p, int nbytes)
{
struct _seginfo sbuf;
int selector;
int fd;

if ((selector = qnx_segment_alloc_flags(nbytes,
_PMF_DMA_SAFE | _PMF_DMA_HIGH )) == -1) {
return -1;
}
if (qnx_segment_info(PROC_PID, 0, selector, &sbuf) == -1) {
qnx_segment_free(selector);
return -1;
}
P_ADDR(p) = sbuf.addr;
if ((fd=shm_open(PHYSICAL_MEMORY,O_RDWR,0)) == -1) {
qnx_segment_free(selector);
return -1;
}
p->segno = selector;
p->seglen = nbytes;
V_ADDR(p) = mmap(0,nbytes, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, P_ADDR(p));
close(fd);
if (P_ADDR(p) == (paddr_t)-1) {
qnx_segment_free(selector);
return -1;
}
return 0;
}

int
free_dmabuf(dma_t *dp)
{
munmap(V_ADDR(dp), dp->seglen);
qnx_segment_free(dp->segno);
return 0;
}

main(int argc, char **argv)
{
int ret;
dma_t d1;
unsigned nbytes = 0;

nbytes = atoi(argv[1]);

if ( nbytes == 0 ) {
printf(“use dma1 nbytes\n”);
exit(1);
}

printf(“allocating %u bytes in dma safe, high memory\n”, nbytes );

ret = alloc_dmabuf(&d1, nbytes);

printf(“ret=%d\n”, ret);
if ( ret != -1 ) {
printf(“d1: segno=%d, seglen=%d, phsy=0x%lx, log=0x%x\n”,
d1.segno, d1.seglen,
d1.phys_addr,
d1.bufp
);
}
sleep(500);
printf(“check out the mem with ‘sin mem’ … ctrl-c to quit\n”);
}


Dmitry Ivanov <> id@pa.ru> > wrote:
Hello!


How do I allocate contiguos regions of physical memory in QNX4?

I’ve tried qnx_segment_alloc_* functions and I have found
two options here.

  1. Use qnx_segment_alloc_flags() with _PMF_DMA_SAFE flag. Then use
    qnx_segment_query() to obtain physical address (using
    flags other then _PMF_DMA_SAFE will result in that
    qnx_segment_query() gives me virtual address - not physical)
    The problem here is that I cannot allocate more than 64k
    of contiguos memory this way. (But I need 500k!!!)

  2. Use qnx_segment_alloc_raw().
    But how do I access this memory?
    I’m not sure that I can use
    shm_open and mmap funtions, because the memory chunk is
    removed from the system.

Can I use shm_open(“Physical”, ) and mmap() for this purpose?
In this case if I give certain phys_addr and buf_len to mmap as
parameters
how do I
know this memory chunk isn’t used by QNX for other purpose?

Any suggestions or weblinks are welcome.

Best regards
Dmitri


\

Randy Martin > randy@qnx.com
Manager of FAE Group, North America
QNX Software Systems > www.qnx.com
175 Terence Matthews Crescent, Kanata, Ontario, Canada K2M 1W8
Tel: 613-591-0931 Fax: 613-591-3579

Augie Henriques <augiehenriques@hotmail.com> wrote:

“Randy Martin” <> randy@qnx.com> > wrote in message
news:97j326$o64$> 2@nntp.qnx.com> …
check out the DMA_HIGH flag to qnx_segment_alloc_flags()
using it will cause the allocation to start on a 64k boundary above 1M

The DMA_HIGH flag is not documented in my qnx_segment_alloc_flags. Is this
new? Where can I get the docs for this?

Take a look at /etc/readme/technotes/shmem.txt. It talks about allocating
and accessing DMA safe memory – including sample code. (This is shipped.)

-David

QNX Training Services
dagibbs@qnx.com

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:97jauu$sbh$1@nntp.qnx.com

Augie Henriques <> augiehenriques@hotmail.com> > wrote:

“Randy Martin” <> randy@qnx.com> > wrote in message
news:97j326$o64$> 2@nntp.qnx.com> …
check out the DMA_HIGH flag to qnx_segment_alloc_flags()
using it will cause the allocation to start on a 64k boundary above
1M

The DMA_HIGH flag is not documented in my qnx_segment_alloc_flags. Is
this
new? Where can I get the docs for this?

Take a look at /etc/readme/technotes/shmem.txt. It talks about allocating
and accessing DMA safe memory – including sample code. (This is
shipped.)

I’m aware of the /etc/readme/technotes/shmem.txt file. However, the
DMA_HIGH flag is not documented there nor in the qnx_segment_alloc_flags()
docs.

What is the DMA_HIGH flag for? What does it do?

BTW, it would be nice if someone took the time to put the contents of the
/etc/readme/technotes/shmem.txt file into the QNX 4 docs. Then someone
looking for info on DMA, would find what he/she needs (in helpviwer) and
wouldn’t waste time looking for the answer (I can’t count how many times I
have seen people ask for this :slight_smile: )!

Thanks

Augie

-David

QNX Training Services
dagibbs@qnx.com

Augie Henriques <augiehenriques@hotmail.com> wrote:

Take a look at /etc/readme/technotes/shmem.txt. It talks about allocating
and accessing DMA safe memory – including sample code. (This is
shipped.)

I’m aware of the /etc/readme/technotes/shmem.txt file. However, the
DMA_HIGH flag is not documented there nor in the qnx_segment_alloc_flags()
docs.

What is the DMA_HIGH flag for? What does it do?

Oops sorry, thought it was. Well, the comment in the header file says:
“Allow DMA requests above 16 meg”. And, that is exactly what it does.

PMF_DMA_SAFE enforces that the memory allocated will be useable for ISA
DMA – that is, contiguous in RAM, 64K-byte aligned, not crossing
a 64K boundary (if less than 64K allocated), and below 16M physical
address. PMF_DMA_HIGH removes the “below 16M physical address”
restriction, allowing high-address RAM to be allocated for DMA,
generally to/from a PCI device.

-David

QNX Training Services
dagibbs@qnx.com

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:97je6n$1gj$1@nntp.qnx.com

Augie Henriques <> augiehenriques@hotmail.com> > wrote:

Take a look at /etc/readme/technotes/shmem.txt. It talks about
allocating
and accessing DMA safe memory – including sample code. (This is
shipped.)

I’m aware of the /etc/readme/technotes/shmem.txt file. However, the
DMA_HIGH flag is not documented there nor in the
qnx_segment_alloc_flags()
docs.

What is the DMA_HIGH flag for? What does it do?

Oops sorry, thought it was. Well, the comment in the header file says:
“Allow DMA requests above 16 meg”. And, that is exactly what it does.

PMF_DMA_SAFE enforces that the memory allocated will be useable for ISA
DMA – that is, contiguous in RAM, 64K-byte aligned, not crossing
a 64K boundary (if less than 64K allocated), and below 16M physical
address. PMF_DMA_HIGH removes the “below 16M physical address”
restriction, allowing high-address RAM to be allocated for DMA,
generally to/from a PCI device.

So this is something that may work with dual port ram cards?

Augie

-David

QNX Training Services
dagibbs@qnx.com

Augie Henriques <augiehenriques@hotmail.com> wrote:

What is the DMA_HIGH flag for? What does it do?

Oops sorry, thought it was. Well, the comment in the header file says:
“Allow DMA requests above 16 meg”. And, that is exactly what it does.

PMF_DMA_SAFE enforces that the memory allocated will be useable for ISA
DMA – that is, contiguous in RAM, 64K-byte aligned, not crossing
a 64K boundary (if less than 64K allocated), and below 16M physical
address. PMF_DMA_HIGH removes the “below 16M physical address”
restriction, allowing high-address RAM to be allocated for DMA,
generally to/from a PCI device.

So this is something that may work with dual port ram cards?

No. For a dual-port ram card, you don’t have to allocate system
RAM – the RAM on the card won’t be owned by the system. For
something like that, you would:

fd = shm_open( PHYSICAL );
ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED,fd, phys_addr );

-David

QNX Training Services
dagibbs@qnx.com

Augie Henriques <augiehenriques@hotmail.com> wrote:
: BTW, it would be nice if someone took the time to put the contents of the
: /etc/readme/technotes/shmem.txt file into the QNX 4 docs. Then someone
: looking for info on DMA, would find what he/she needs (in helpviwer) and
: wouldn’t waste time looking for the answer (I can’t count how many times I
: have seen people ask for this :slight_smile: )!

It is in the latest version of the docs here, but I don’t know when we last
released a patch for them. I’ll ask QA.

Here’s what the docs include:

_PMF_DMA_HIGH
Remove the restriction the a DMA-safe segment be in the first 16M
of physical memory.


Steve Reid stever@qnx.com
TechPubs (Technical Publications)
QNX Software Systems