Mail Archives: djgpp/2006/04/20/06:31:04
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.)
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);
-aw
- Raw text -