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.
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
> 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
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.
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.