Mail Archives: djgpp/2006/04/20/22:01:43
"A. Wik" <aw AT aw DOT gs> wrote in message
news:20060420034145 DOT K3950 AT dynamite DOT narpes DOT com...
> On Wed, 19 Apr 2006, Rod Pemberton wrote:
>
> >
> > Anyway, I've written two examples. They both compile cleanly, but
haven't
> > been thoroughly tested (i.e., possible bugs...). If there are any bugs,
> > you'll need to sort them out yourself.
> >
> > Method 1)
> > ----
> > #include <dpmi.h>
> > #include <go32.h>
> > #include <sys/farptr.h>
> >
> > #define BUFF 32768
> > int main(void)
> > {
> > unsigned long base;
> > /* unsigned short segment,offset; */
> > int selector;
> > char buf[BUFF];
> >
> > /* base is the physical address of the low mem buffer */
> > /* selector is used for virtual addressing, i.e., within application
space
> > */
> > __dpmi_allocate_dos_memory((BUFF+15)>>4,&selector);
> > __dpmi_get_segment_base_address(selector,&base);
>
> Some nit-picking regarding terminology:
>
> "physical" = The primitive, most low-level form of address from
> a system software (privileged) point of view, and
> which in the good old days referred to an address
> output by the CPU onto the bus for referencing main
> memory, hardware registers (memory mapped IO), the
> video BIOS, RAM buffers on SCSI/EMS/Ethernet cards,
> and so on (or non-existent address space). In this
> day and age, references to "physical" addresses
> usually never leave the chip (instead landing on
> the cache). Various CPUs are capable of generating
> 20-, 24-, 32-, 36-, 40-bit physical addresses or
> some other size.
>
> "logical" = The address formed (explicitly or implicitly) by a
> 16-bit segment + a 16-, 32-, or 64-bit offset, all
> depending CPU type and mode. Translated into a
> linear address through the classical "SHL 4 & ADD"-
> scheme, or starting from the 286 in protected mode,
> via the descriptor cache initialised from the GDT
> and optional LDT table(s) upon loading a segment
> register.
>
> "linear" = The 0-based address space derived from a logical
> address. From the 8086-80286, and on 386+ in the
> absence of paging, physical addresses are formed
> directly by copying/extending/truncating the linear
> address. With paging enabled on the 386+,
> translation into physical is instead done according
> to the page tables, configurable in an ever
> increasing numbers of ways. At least one of those
> ways must be sizeable enough to cover the CPU's
> physical addressing capabilities (or the latter
> would be rather pointless), however awkward it may
> be to implement and use (e.g. 36-bit addressing,
> for using more than 4 GB RAM on 32-bit CPUs would
> require a scheme of swapping physical memory in and
> out of the address space, much like the classical
> 16-bit DOS technologies: EMS, bank-switching,
> overlays...).
>
> "flat" = The memory management scheme in which the code-,
> stack- and data-segments are all set up with a
> base address of 0 and a limit including all the
> memory the program is intended reference.
>
> "virtual" = Linear address not equal to the physical address
> by sign/zero-extension. Might even be swapped
> out to disk.
>
> .. (Corrections/additions welcome.)
>
>
That's a bit different than the way I use those terms. I usually use
'virtual' for EIP address since it's relative to the base address of the CS
selector. I usually use physical for a base 0, flat address space or what
is the closest thing to the hardware lines...
> The __dpmi_physical_address_mapping() function can be used to
> request a virtual address (range) mapped to a specific physical
> address, such as the linear frame buffer for a SVGA graphics
> mode - sample code (error checking omitted):
>
> __dpmi_meminfo dmemi;
> unsigned sel;
> int st; /* status of calls */
>
> dmemi.size = xres * yres * bpp + 4093 & ~4093;
> dmemi.address = lfb_addr;
> st = __dpmi_physical_address_mapping(&dmemi);
>
> sel = __dpmi_allocate_ldt_descriptors(1);
> st = __dpmi_set_segment_base_address(sel, dmemi.address);
> st = __dpmi_set_segment_limit(sel, dmemi.size-1);
>
Just remember that the DPMI host has already mapped memory below 1Mb (or is
it 1Mb+64k?). So, you shouldn't pass addresses below 1Mb to
__dpmi_physical_address_mapping. This will cause failures with certain DPMI
hosts. Also, the Charles Sandmann based DPMI hosts (CWSDPMI, and CWSDPR0)
have a hardcoded physical address limit of 128Mb.
You only need two selectors for DJGPP, both of which are provided _dos_ds
and _my_ds() (and/or _my_cs()). The limit of _dos_ds can be extended to 4Gb
with __dpmi_set_segment_limit, providing a base 0, flat or linear address
space. But, you must use non-standard functions like _far/nearptr.
_my_ds() can also be extended to 4Gb (except under Windows), but it's base
address is set by the DPMI host. This allows a full 4Gb address space (with
32-bit wraparound), and standard C pointers. But, the pointers need to be
adjusted for the base address... If you want a non-segmented programming
environment, i.e., true base 0, flat or linear address space, OpenWatcom
compiles that way.
Rod Pemberton
- Raw text -