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

Obtaining the physical address of a pointer using PMODE

14 views
Skip to first unread message

Roland Zitzke

unread,
Nov 15, 2005, 6:16:27 AM11/15/05
to
Hi,
I read somewhere, that the pmode/dj extender has a fixed mapping of pointers
to physical memory.
Thus, if I write something like
unsigned char* p = malloc(1024);
how can I obtain the physical location of the data pointed to by p, provided
that I use pmode?
Background is that I need this to allocate a DMA buffer and I do not
necessarily need virtual memory in my application.

Thanks and regards
Roland


Schumacher, Gordon

unread,
Nov 16, 2005, 12:06:45 PM11/16/05
to DJGPP List (E-mail)
# From: "Roland Zitzke" <NZEONTQYRAHL AT spammotel DOT com>
# Sent: Tuesday, November 15, 2005 12:16 PM
# To: dj...@delorie.com
# Subject: Re: Obtaining the physical address of a pointer using PMODE
#
# Hi,
# I read somewhere, that the pmode/dj extender has a fixed mapping of
# pointers to physical memory.
# Thus, if I write something like
# unsigned char* p = malloc(1024);
# how can I obtain the physical location of the data pointed to by p,
# provided that I use pmode?
# Background is that I need this to allocate a DMA buffer and I do not
# necessarily need virtual memory in my application.
#
# Thanks and regards
# Roland

Try this thread:

http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp/2001/04/13/12:21:37
http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp/2001/04/14/01:01:55
http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp/2001/05/09/17:04:12
http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp/2001/05/09/16:33:37

Charles Sandmann gave us some example code, and put it at
ftp://clio.rice.edu/djgpp/cwsdma.zip. He was talking about cleaning
it up and making it more publicized; I don't know if that ever happened.

But hopefully that's a good start. If you get stuck, I still have the
e-mail thread that went on when we were tackling this same problem.

Roland Zitzke

unread,
Nov 16, 2005, 1:45:18 PM11/16/05
to
Hello and thanks for the links.
as far as I can tell people were discussing to allocate mory in a fassion
suitable for different extenders. However if I use pmode/dj, isn't there a
way to malloc a chunk of memory and somehow detect the physical address of
this chunk?

DOS with himem.sys installed and WITHOUT EMM386 is the only environment I am
really interested in.

>
> Charles Sandmann gave us some example code, and put it at
> ftp://clio.rice.edu/djgpp/cwsdma.zip. He was talking about cleaning
> it up and making it more publicized; I don't know if that ever happened.
>

I had a look at this code and I'm not sure I understand it completely.
In the test routine there's:
...
dmabuf = AllocateDMABuffer(8*1024*1024);
if(dmabuf)
printf("Allocated 8M DMA buffer at DJGPP address 0x%x, physical 0x%x\n",
dmabuf,Physical_Address(dmabuf));
...

and it appears to me if that's really all that is needed to allocate a chunk
of memory and obtain the physical address for DMA.
However, the code goes on:

i = physical_map(0, __djgpp_selector_limit, MAXSIZE, virtual, physical,
size);
if(i == 2)
return printf("CWSDPMI PD in UMB not supported, sorry\n");
if(i)
...

and I have no idea what that is good for i.e. what I need the physical_map
function for.
Any hints?

Thanks in advance and regards
Roland


Rod Pemberton

unread,
Nov 16, 2005, 7:34:53 PM11/16/05
to

"Roland Zitzke" <NZEONT...@spammotel.com> wrote in message
news:4379c...@news.ecore.net...

> I read somewhere, that the pmode/dj extender has a fixed mapping of
pointers
> to physical memory.
> Thus, if I write something like
> unsigned char* p = malloc(1024);
> how can I obtain the physical location of the data pointed to by p,
provided
> that I use pmode?

All the virtual address in DJGPP are offset from some base address. For any
virtual address in DJGPP, you can use three methods:
1) add __djgpp_base_address (which is an int)
2) subtract __djgpp_conventional_base (which is a #define)
3) call __dpmi_get_segment_base_address(_my_ds(), &base) (where base is an
unsigned long)

PMODEDJ (pmodetsr.exe) is non-paging. That means you don't have to use a
DPMI function call to map the memory you are about to access. Basically,
you have a mapped 4Gb page. With CWSDPMI, you must use a DPMI call to map
the memory into the DPMI hosts paging tables. If you don't map the memory
with CWSDPMI, you'll get a SIGSEGV error.

Fortunately, there are some selectors setup in DJGPP that we can use or we'd
need to call these five functions:
1) __dpmi_allocate_ldt_descriptors()
2) __dpmi_set_descriptor_access_rights()
3) __dpmi_set_segment_base_address()
4) __dpmi_set_segment_limit()
5) __dpmi_allocate...memory...()
or __dpmi_map...memory...()
or __dpmi_physical_address_mapping()

We have a number of selector to choose from:
cs _my_cs(), selector for code segment
ds data for cs _my_ds(), selector for data segment used by gcc
ss same as ds _my_ss(), selector for stack segment
es same as ds selector for psp segment used by gcc
fs selector unused, but used for farptrs (farpeek,
farpoke)
gs selector for dos segment (1M+64k), and used by libc
dsa alias for ds __djgpp_ds_alias, automatically mirrors ds
dsl is gs __djgpp_dos_sel
dds is gs _dos_ds
cms is gs _go32_conventional_mem_selector()

__djgpp_nearptr_enable() can be used to boost the segment limit to 4Gb for
cs,ds,es,ss,and dsa
__dpmi_set_segment_limit(_selector_, 0xFFFFFFFFU) can be used to boost the
segment limit to 4Gb for _dos_ds, etc.

Basically, one has a choice of using _dos_ds or _my_ds(). By
default, _dos_ds allows access to all data below 1Mb+64k and
_my_ds() allows access to all data in the program space. The
advantage of _dos_ds is that it has a base address of zero (0)
e.g., physical addressing, and can be boosted to a 4Gb limit.
It's disadvantage is that special functions instead of standard
C pointers must be used. The advantage of _my_ds() is that it
can be boosted to a 4Gb limit and standard C pointers can be used.
It's disadvantage is that an offset must be subtracted for physical
addresses. Using fs has the same issues as _dos_ds. Allocating
a new local selector provides no advantages over using _dos_ds
or _my_ds(). In all cases, if a paging DPMI server is used, the
memory must be allocated or mapped by the DPMI server first.

Rod Pemberton

PS. The following 9 tables show what the selector defaults, selectors
after nearptr enable, and selectors after set segment limit for CWSDPMI,
PMODEDJ, and CWSDPR0:

CWSDPMI defaults
selector 0x00a7 : select= cs, base=0x10000000, limit=0x0009ffff,
flags=0x40fb
selector 0x00af : select= ds, base=0x10000000, limit=0x0009ffff,
flags=0x40f3
selector 0x00af : select= ss, base=0x10000000, limit=0x0009ffff,
flags=0x40f3
selector 0x00af : select= es, base=0x10000000, limit=0x0009ffff,
flags=0x40f3
selector 0x008f : select= fs, base=0x00007c00, limit=0x0000ffff,
flags=0x40f3
selector 0x00bf : select= gs, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3
selector 0x00b7 : select=dsa, base=0x10000000, limit=0x0009ffff,
flags=0x40f3
selector 0x00bf : select=dsl, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3
selector 0x00bf : select=dds, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3
selector 0x00bf : select=cms, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3

PMODEDJ defaults
selector 0x03f0 : select= cs, base=0x00110000, limit=0x0009ffff,
flags=0x509b
selector 0x03e8 : select= ds, base=0x00110000, limit=0x0009ffff,
flags=0x5093
selector 0x03e8 : select= ss, base=0x00110000, limit=0x0009ffff,
flags=0x5093
selector 0x03e8 : select= es, base=0x00110000, limit=0x0009ffff,
flags=0x5093
selector 0x00e0 : select= fs, base=0x00007c40, limit=0x0000ffff,
flags=0x5093
selector 0x03d8 : select= gs, base=0x00000000, limit=0x0010ffff,
flags=0x9093
selector 0x03e0 : select=dsa, base=0x00110000, limit=0x0009ffff,
flags=0x5093
selector 0x03d8 : select=dsl, base=0x00000000, limit=0x0010ffff,
flags=0x9093
selector 0x03d8 : select=dds, base=0x00000000, limit=0x0010ffff,
flags=0x9093
selector 0x03d8 : select=cms, base=0x00000000, limit=0x0010ffff,
flags=0x9093

CWSDPR0 defaults
selector 0x00a4 : select= cs, base=0x10000000, limit=0x0009ffff,
flags=0x409b
selector 0x00ac : select= ds, base=0x10000000, limit=0x0009ffff,
flags=0x4093
selector 0x00ac : select= ss, base=0x10000000, limit=0x0009ffff,
flags=0x4093
selector 0x00ac : select= es, base=0x10000000, limit=0x0009ffff,
flags=0x4093
selector 0x008c : select= fs, base=0x00007c40, limit=0x0000ffff,
flags=0x4093
selector 0x00bc : select= gs, base=0x00000000, limit=0x0010ffff,
flags=0xc093
selector 0x00b4 : select=dsa, base=0x10000000, limit=0x0009ffff,
flags=0x4093
selector 0x00bc : select=dsl, base=0x00000000, limit=0x0010ffff,
flags=0xc093
selector 0x00bc : select=dds, base=0x00000000, limit=0x0010ffff,
flags=0xc093
selector 0x00bc : select=cms, base=0x00000000, limit=0x0010ffff,
flags=0xc093


CWSDPMI after __djgpp_nearptr_enable();
selector 0x00a7 : select= cs, base=0x10000000, limit=0xffffffff,
flags=0xc0fb
selector 0x00af : select= ds, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00af : select= ss, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00af : select= es, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x008f : select= fs, base=0x00007c00, limit=0x0000ffff,
flags=0x40f3
selector 0x00bf : select= gs, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3
selector 0x00b7 : select=dsa, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00bf : select=dsl, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3
selector 0x00bf : select=dds, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3
selector 0x00bf : select=cms, base=0x00000000, limit=0x0010ffff,
flags=0xc0f3

PMODEDJ after __djgpp_nearptr_enable();
selector 0x03f0 : select= cs, base=0x00110000, limit=0xffffffff,
flags=0xd09b
selector 0x03e8 : select= ds, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x03e8 : select= ss, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x03e8 : select= es, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x00e0 : select= fs, base=0x00007c40, limit=0x0000ffff,
flags=0x5093
selector 0x03d8 : select= gs, base=0x00000000, limit=0x0010ffff,
flags=0x9093
selector 0x03e0 : select=dsa, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x03d8 : select=dsl, base=0x00000000, limit=0x0010ffff,
flags=0x9093
selector 0x03d8 : select=dds, base=0x00000000, limit=0x0010ffff,
flags=0x9093
selector 0x03d8 : select=cms, base=0x00000000, limit=0x0010ffff,
flags=0x9093

CWSDPR0 after __djgpp_nearptr_enable();
selector 0x00a4 : select= cs, base=0x10000000, limit=0xffffffff,
flags=0xc09b
selector 0x00ac : select= ds, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x00ac : select= ss, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x00ac : select= es, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x008c : select= fs, base=0x00007c40, limit=0x0000ffff,
flags=0x4093
selector 0x00bc : select= gs, base=0x00000000, limit=0x0010ffff,
flags=0xc093
selector 0x00b4 : select=dsa, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x00bc : select=dsl, base=0x00000000, limit=0x0010ffff,
flags=0xc093
selector 0x00bc : select=dds, base=0x00000000, limit=0x0010ffff,
flags=0xc093
selector 0x00bc : select=cms, base=0x00000000, limit=0x0010ffff,
flags=0xc093


CWSDPMI after __djgpp_nearptr_enable();
and __dpmi_set_segment_limit(_dos_ds, 0xFFFFFFFFU);
selector 0x00a7 : select= cs, base=0x10000000, limit=0xffffffff,
flags=0xc0fb
selector 0x00af : select= ds, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00af : select= ss, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00af : select= es, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x008f : select= fs, base=0x00007c00, limit=0x0000ffff,
flags=0x40f3
selector 0x00bf : select= gs, base=0x00000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00b7 : select=dsa, base=0x10000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00bf : select=dsl, base=0x00000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00bf : select=dds, base=0x00000000, limit=0xffffffff,
flags=0xc0f3
selector 0x00bf : select=cms, base=0x00000000, limit=0xffffffff,
flags=0xc0f3

PMODEDJ after __djgpp_nearptr_enable();
and __dpmi_set_segment_limit(_dos_ds, 0xFFFFFFFFU);
selector 0x03f0 : select= cs, base=0x00110000, limit=0xffffffff,
flags=0xd09b
selector 0x03e8 : select= ds, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x03e8 : select= ss, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x03e8 : select= es, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x00e0 : select= fs, base=0x00007c40, limit=0x0000ffff,
flags=0x5093
selector 0x03d8 : select= gs, base=0x00000000, limit=0xffffffff,
flags=0x9093
selector 0x03e0 : select=dsa, base=0x00110000, limit=0xffffffff,
flags=0xd093
selector 0x03d8 : select=dsl, base=0x00000000, limit=0xffffffff,
flags=0x9093
selector 0x03d8 : select=dds, base=0x00000000, limit=0xffffffff,
flags=0x9093
selector 0x03d8 : select=cms, base=0x00000000, limit=0xffffffff,
flags=0x9093

CWSDPR0 after __djgpp_nearptr_enable();
and __dpmi_set_segment_limit(_dos_ds, 0xFFFFFFFFU);
selector 0x00a4 : select= cs, base=0x10000000, limit=0xffffffff,
flags=0xc09b
selector 0x00ac : select= ds, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x00ac : select= ss, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x00ac : select= es, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x008c : select= fs, base=0x00007c40, limit=0x0000ffff,
flags=0x4093
selector 0x00bc : select= gs, base=0x00000000, limit=0xffffffff,
flags=0xc093
selector 0x00b4 : select=dsa, base=0x10000000, limit=0xffffffff,
flags=0xc093
selector 0x00bc : select=dsl, base=0x00000000, limit=0xffffffff,
flags=0xc093
selector 0x00bc : select=dds, base=0x00000000, limit=0xffffffff,
flags=0xc093
selector 0x00bc : select=cms, base=0x00000000, limit=0xffffffff,
flags=0xc093


Charles Sandmann

unread,
Nov 19, 2005, 12:14:27 AM11/19/05
to
> However if I use pmode/dj, isn't there a way to malloc a chunk of memory
> and somehow detect the physical address of this chunk?

Use malloc(), use the excellent instructions from Rod's note from 16-Nov-2005
to compute the physical address, and apply the appropriate alignments. In
particular, quoting Rod...

All the virtual address in DJGPP are offset from some base address. For any
virtual address in DJGPP, you can use three methods:
1) add __djgpp_base_address (which is an int)

(rest of informative message snipped)

> DOS with himem.sys installed and WITHOUT EMM386 is the only environment I am
> really interested in.

That's good, because EMM386/VCPI active even pmode needs paging enabled.

> > Charles Sandmann gave us some example code, and put it at
> > ftp://clio.rice.edu/djgpp/cwsdma.zip. He was talking about cleaning
> > it up and making it more publicized; I don't know if that ever happened.

I never made significant cleanup; but there is a cwsdma2 there. I don't
remember how it was different anymore.

> I had a look at this code and I'm not sure I understand it completely.
> In the test routine there's:

> ....


> dmabuf = AllocateDMABuffer(8*1024*1024);
> if(dmabuf)
> printf("Allocated 8M DMA buffer at DJGPP address 0x%x, physical 0x%x\n",
> dmabuf,Physical_Address(dmabuf));

> ....


>
> and it appears to me if that's really all that is needed to allocate a chunk
> of memory and obtain the physical address for DMA.

Under a paging system with virtual memory, the allocated memory may be paged
out to disk, or scattered about in physical memory (not contiguous), or
potentially not even mapped yet. So your simple assumption works for
something like PMODE without EMM386, but not in general.

> i = physical_map(0, __djgpp_selector_limit, MAXSIZE, virtual, physical, size);
> if(i == 2)
> return printf("CWSDPMI PD in UMB not supported, sorry\n");
> if(i)
>

> and I have no idea what that is good for i.e. what I need the physical_map
> function for.

For any CWSDPMI environment (including emm386, swapped out, etc) this will tell
exactly where the memory is. If you know how to program the DMA scatter/gather
maps you can use the physical map info to use the fragmented buffer.

So, if you distribute software and don't have complete control of the
boot environment, this is a useful technique.

Schumacher, Gordon

unread,
Nov 21, 2005, 7:30:52 PM11/21/05
to DJGPP List (E-mail)
# From: "Roland Zitzke" <NZEONT...@spammotel.com>

# Subject: Re: Obtaining the physical address of a pointer using PMODE
# Date: Wed, 16 Nov 2005 19:45:18 +0100
# Message-ID: <dlfunv$2ta4$1...@ulysses.news.tiscali.de>
# X-Trace: ulysses.news.tiscali.de 1132166719 95556
#
# Hello and thanks for the links.
# as far as I can tell people were discussing to allocate mory
# in a fassion suitable for different extenders. However if I use
# pmode/dj, isn't there a way to malloc a chunk of memory and somehow
# detect the physical address of this chunk?

I'm not sure about this, actually. We're running using CWSDPMI,
not PMODE, and that's been working for us.

# DOS with himem.sys installed and WITHOUT EMM386 is the only
# environment I am really interested in.

That's how we're running too. We *can* run with EMM386 - but only
poorly. It allocates memory from the top down, which is the worst
thing possible for building scatter/gather tables.

# and I have no idea what that is good for i.e. what I need the
# physical_map function for.
# Any hints?

I'm afraid that I personally wasn't the person on our team working
on this code; the main guy who was is no longer at the company (but
he may be reading this list anyway *ping*). My life is spent up in
app-space :)

Charles Sandmann would probably be the right person to talk to about
this for details.

0 new messages