The main points which are discussed within this document are :
In protected mode you may get in big troubles, even when loading a random value of a segment address into a segment register, because this causes the processor to stop executing the program. This doesn't reset or crash the processor, but he simply calls an exception (an interrupt) which returns control to the underlying operating system again, which in term simply terminates the program. It's that easy in protected mode.
This is only possible because segment addresses aren't segment addresses anymore, but (segment-)selectors. Selectors are indexes into a table of segment descriptors which describe a single memory area. The CPU gets the base address of the memory segment. Finally he adds the offset address from the pointer to this value to get the real memory address of e.g. a variable. (No more multiply of the segment by 16 and then adding the offset like in real mode, hence memory segments can start at any address)
A descriptor holds more than simply the base address of the segment, but several additional information. These are the base address, the length of the segment and finally some flags. (Please refer to a good book / documentation for further reference, because that's all that a protected mode programmer needs to know as long as he doesn't want to make his own operating system....)
This is where a DPMI extender comes into play.
Several issues of the DPMI API are handled by this unit:
type
Registers = record
case integer of
0 : (edi, esi, ebp, res1, ebx, edx, ecx, eax : DWord;
Flags, es, ds, fs, gs, ip, cs, sp, ss : Word);
1 : (di, di2, si, si2, bp, bp2, res2, res3,
bx, bx2, dx, dx2, cx, cx2, ax, ax2 : Word);
2 : (res4 : array[1..4] of DWord;
bl, bh, bl2, bh2, dl, dh, dl2, dh2,
cl, ch, cl2, ch2, al, ah, al2, ah2 : Byte);
end;
This data structure contains the values which must be passed to or are
returned by an interrupt call or a real mode callback structure. See at
Translation services for further
reference about the usage of this structure
These constants define the bit location of the various flags within the flags-entry of the 'register' data structure. See registers type.
type
pm_Addr = record
offset : DWord;
selector : Word;
end;
This is the full definition of a single memory address in protected mode. It is 48 bit in size, since a single memory segment is still 16 bit and it can be up to 32 bits in size. See Interrupt services or Translation services for applications.
type
rm_Addr = record
offset : Word;
segment : Word;
end;
Definition of a real mode address in segment:offset notation. See Translation
or Interrupt services for applications
type
MemInfoBuf = record
largest_available_free_block : Longint;
max_unlocked_pages : Longint;
max_lockable_pages : Longint;
linear_address_space_size : Longint;
number_of_unlocked_pages : Longint;
number_of_free_pages : Longint;
number_of_physical_pages : Longint;
free_linear_address_space : Longint;
size_of_paging_file : Longint;
reserved : array[0..2] of Longint;
end;
The information block about memory used/allocated of the program which
is returned by dpmi_get_free_memory_information()
only.
Field identifier | Description |
largest_available_free_block | Largest available free block in bytes |
max_unlocked_pages | Maximum unlocked page allocation |
max_lockable_pages | Maximum locked page allocation |
linear_address_space_size | Linear address space size in pages |
number_of_unlocked_pages | Total number of unlocked pages |
number_of_free_pages | Number of free pages |
number_of_physical_pages | Total number of physical pages |
free_linear_address_space | Free linear address space in pages |
size_of_paging_file | Size of paging file/partition in pages |
reserved | Reserved |
Contains the last error number occured by a DPMI call. See Error handling too
Such an error code consists of three parts: First comes the warning/fatal bits, then a unit identifier to get to know which unit caused the error and last the error code itself.
The fatal/warning bits are the upper 2 bits of the parameter dword.
They may be ignored by the error handler (because the caller decides the
type of the error), but it's generally a good idea to halt on a fatal error.
Then comes a 10 bit sized unit identifier, which tells the error handler
at which unit the error happened.
And last a 20 bit sized error code, which can be output for reference.
Additionally *every* dpmi_xxxx function returns a boolean result which indicates success or fail, in the case you don't want to care about the dpmi_error variable every time (and added a dummy error handler which does completely nothing).
Btw, error handling will be changed soon (too unflexible now), to
something like done in the API unit, so the error codes in the function
descriptions aren't entered into the proper row. But there is still Table
2, where the error codes for all functions which return errors are
listed with their associated error code.
procedure dpmi_set_error_handler(handler : error_proc); | |
Description: | Sets a new error handler for the DPMI unit |
Parameters: | handler - the address of the new error handler procedure |
Return values: | none |
Error code: | none |
Notes: | The standard error handler updates the dpmi_error variable, writes a message to stdout, and triggers an RTE 216 (General Protection Fault) if the error was a fatal one. |
See also: | dpmi_error (var), Error handling, Table 2 |
function dpmi_get_cpu_mode(var in_pm : Boolean) : Boolean; | |
Description: | Returns information about the current CPU mode |
Parameters: | none |
Return values: | in_pm - true if running under protected mode, false if not |
Error code: | none |
Notes: | GO32V2 applications generally don't need to care about this. |
See also: | Initialization services, Table 1 |
function dpmi_allocate_ldt_descriptors(number : Word; var basesel : Word) : Boolean; | |
Description: | Allocates one or more descriptors from the local task's LDT. The descriptors allocated must be initializd by the application. |
Parameters: | number - number of selectors to allocate |
Return values: | basesel - the base selector to the array of selectors allocated |
Error code: | $0000 |
Notes: | If more than one descriptor was requested, basesel contains the first of a contiguous array of descriptors. You should add the value returned by dpmi_get_next_selector_increment_value() to get to the next selector in the array. |
See also: | LDT management services, dpmi_free_ldt_descriptor(), dpmi_set_segment_base_address(), dpmi_get_segment_base_address(), dpmi_set_segment_limit(), dpmi_get_segment_limit(), dpmi_segment_to_descriptor(), dpmi_get_next_selector_increment_values(), create_selector(), free_selector(), map_physical_memory(), Table 1, Table 2 |
function dpmi_free_ldt_descriptor(sel : Word) : Boolean; | |
Description: | This function is used to free previously allocated selectors by dpmi_allocate_ldt_descriptors() |
Parameters: | sel - the selector to de-allocate |
Return values: | none |
Error code: | $0001 |
Notes: | Arrays of selectors must be freed individually by calling this function for each single selector. You may use the free_selector() function instead of this too. |
See also: | LDT management services, dpmi_allocate_ldt_descriptors(), free_selector(), Table 1, Table 2 |
function dpmi_segment_to_descriptor(seg : Word; var sel : Word) : Boolean; | |
Description: | Converts a real mode segment into a descriptor which can be accessed by protected mode programs. |
Parameters: | seg - real mode segment address |
Return values: | sel - selector mapped to real mode address |
Error code: | $0002 |
Notes: | The selectors limit is always set to $FFFF (64k). Multiple calls to this function with the same segment address will return the same selector. For this reason, selectors created by this selector should never be freed or modified. Use this function sparingly. If you want to examine different real mode segments it is better to allocate a single selector by dpmi_allocate_ldt_descriptors() and change its base address via dpmi_set_segment_base_address() accordingly. |
See also: | LDT management services, dpmi_allocate_ldt_descriptors(), dpmi_set_segment_limit(), dpmi_set_segment_base_address(), Table 1, Table 2 |
function dpmi_get_next_selector_increment_value(var incval : Word) : Boolean; | |
Description: | Some functions (like allocate_ldt_descriptors()) can return more than one descriptor. You must call this function to determine the value which must be added to a selector to gain access to the next descriptor in the array. |
Parameters: | none |
Return values: | incval - value to add to get to next selector |
Error code: | $0003 |
Notes: | The returned value will be a power of two, but don't make assumptions about the value this function will return. |
See also: | LDT management services, dpmi_allocate_ldt_descriptors(), Table 1, Table 2 |
function dpmi_get_segment_base_address(sel : Word; var baseaddr : DWord) : Boolean; | |
Description: | This function returns the 32-bit linear base address of the specified segment. |
Parameters: | sel - selector |
Return values: | baseaddr - 32 bit linear base address of segment |
Error code: | $0006 |
Notes: | This function fails if sel is invalid. |
See also: | LDT management services, dpmi_allocate_ldt_descriptors(), dpmi_set_segment_base_address(), dpmi_set_segment_limit(), dpmi_get_segment_limit(), get_linear_address(), Table 1, Table 2 |
function dpmi_set_segment_base_address(sel : Word; baseaddr : DWord) : Boolean; | |
Description: | This function changes the 32 bit linear address of the specified segment |
Parameters: | sel - segment to change base address
baseaddr - new 32 bit base address |
Return values: | none |
Error code: | $0007 |
Notes: | This function fails if sel is invalid. You should only modify descriptors that were allocated via dpmi_allocate_ldt_descriptors() before. |
See also: | LDT management services, dpmi_allocate_ldt_descriptors(), dpmi_get_segment_base_address(), dpmi_set_segment_limit(), dpmi_get_segment_limit(), create_selector(), change_selector(), Table 1, Table 2 |
function dpmi_get_segment_limit(sel : Word; var limit : DWord) : Boolean; | |
Description: | Returns the 32 bit limit of the specified segment |
Parameters: | sel - selector |
Return values: | limit - limit of the specified segment in bytes - 1 |
Error code: | See table about Error codes |
Notes: | This function will fail if the supplied selector is invalid. |
See also: | LDT management services, dpmi_set_segment_limit(), dpmi_get_segment_base_address(), dpmi_set_segment_base_address(), Table 1, Table 2 |
function dpmi_set_segment_limit(sel : Word; limit : DWord) : Boolean; | |
Description: | This function sets the limit for the specified segment |
Parameters: | sel - selector
limit - new 32 bit limit of segment in bytes - 1 |
Return values: | none |
Error code: | $0008 |
Notes: | This function will fail when the specified selector is invalid or the requested limit couldn't be set. Segment limits greater than 1 MB must be page aligned, that means, the lower 12 bits of the limit field must have the lower 12 bits set. Your program should only modify descriptors that were previously allocated via the dpmi_allocate_ldt_descriptors() function. |
See also: | LDT management services, dpmi_allocate_ldt_descriptors(), dpmi_get_segment_limit(), dpmi_set_segment_base_address(), dpmi_get_segment_base_address(), dpmi_change_selector(), Table 1, Table 2 |
function dpmi_get_descriptor_access_rights(sel : Word; var rights : Word) : Boolean; | |
Description: | Returns the access rights and type field of the specified descriptor. |
Parameters: | sel - selector |
Return values: | rights - access rights / type field of the descriptor |
Error code: | See notes in Error codes table. |
Notes: | This function fails if the specified selector is invalid. See a DPMI specification for the exact contents of the rights variable. |
See also: | LDT management services, dpmi_set_descriptor_access_rights(), dpmi_get_descriptor(), dpmi_set_descriptor(), dpmi_allocate_specific_descriptor(), Table 1, Table 2 |
function dpmi_set_descriptor_access_rights(sel : Word; rights : Word) : Boolean; | |
Description: | This function allows protected mode programs to modify the access rights field of a descriptor |
Parameters: | sel - selector
rights - new access rights / type |
Return values: | none |
Error code: | $0009 |
Notes: | This function will fail if the selector specified is invalid. Your program should only change the access rights / type of descriptors allocated via the dpmi_allocate_ldt_descriptors() function. |
See also: | LDT management services, dpmi_get_descriptor_access_rights, dpmi_get_descriptor(), dpmi_set_descriptor(), dpmi_allocate_specific_descriptor(), Table 1, Table 2 |
function dpmi_create_code_segment_alias_descriptor(codesel : Word; var sel : Word) : Boolean; | |
Description: | This function will create a data descriptor that has the same base and limit as the specified code segment descriptor. |
Parameters: | codesel - code segment selector |
Return values: | sel - new data segment selector |
Error code: | $000A |
Notes: | This function fails if the specified selector is invalid or not a code segment selector. You have to use the dpmi_free_ldt_descriptor() function to free such a descriptor afterwards. The new data segment descriptor will not track changes from the code segment descriptor. With FPC you don't need this function, because you can write to the code segment too (because it is automatically set as read/writeable at startup) |
See also: | LDT management services, dpmi_get_descriptor_access_rights(), dpmi_set_descriptor_access_rights(), Table 1, Table 2 |
function dpmi_get_descriptor(sel : Word; var descr : Descriptor) : Boolean; | |
Description: | This function copies the descriptor table entry for a specified descriptor into a buffer |
Parameters: | sel - selector |
Return values: | descr - 8 byte buffer holding the descriptor values |
Error code: | $000B |
Notes: | This function will fail if the selector specified is invalid or unallocated. |
See also: | LDT management services, dpmi_set_descriptor(), dpmi_allocate_specific_descriptor(), dpmi_set_descriptor_access_rights(), dpmi_get_descriptor_access_rights(), Table 1, Table 2 |
function dpmi_set_descriptor(sel : Word; descr : Descriptor) : Boolean; | |
Description: | This function copies an 8 byte buffer into the LDT entry for a specified descriptor |
Parameters: | sel - selector
desc - 8 byte buffer containing descriptor |
Return values: | none |
Error code: | $000C |
Notes: | This function will fail if the selector specified is invalid. You should only modify descriptors allocated by the dpmi_allocate_ldt_descriptors() function. For a complete description of the contents of the 8 byte buffer, please refer to a DPMI specification. |
See also: | LDT management services, dpmi_get_descriptor(), dpmi_allocate_specific_descriptor(), Table 1, Table 2 |
function dpmi_allocate_specific_descriptor(sel : Word) : Boolean; | |
Description: | This function attempts to allocate a specific LDT descriptor. |
Parameters: | sel - selector |
Return values: | none |
Error code: | $000D |
Notes: | This function will fail if the specified selector is in use or not an LDT selector. You need to use the dpmi_free_ldt_descriptor() function to free this descriptor again. |
See also: | LDT management services, dpmi_get_descriptor(), dpmi_set_descriptor(), Table 1, Table 2 |
function dpmi_get_free_memory_information(var mem : meminfobuf) : Boolean; | |
Description: | This function is provided so that protected mode applications can determine how much memory is available. Under DPMI implementations that support virtual memory, it is important to consider issues such as the amount of available physical memory. |
Parameters: | mem - 30 byte buffer |
Return values: | mem - buffer filled out with memory information |
Error code: | $0002 |
Notes: | To determine the size of pages, call the dpmi_get_page_size() function. |
See also: | Memory management services, dpmi_get_page_size(), Table 1, Table 2 |
function dpmi_allocate_memory_block(size : DWord; var linearaddr : DWord; var blockhandle : DWord) : Boolean; | |
Description: | This function allocates and commits linear memory. |
Parameters: | size - size of requested memory block in bytes |
Return values: | linearaddr - linear address of allocated memory block
blockhandle - memory block handle (used to resize and free memory) |
Error code: | $0002 |
Notes: | This function does not allocate any selectors for the memory block. It is up to the application to allocate and initialize selectors needed for access. The block is allocated unlocked. Allocations will be page granular, this means that an allocation of $1001 bytes will result in allocation of $2000 bytes. Therefore it's best to always allocate memory in multiplies of 4K. |
See also: | Memory management services, dpmi_free_memory_block(), dpmi_resize_memory_block(), Table 1, Table 2 |
function dpmi_free_memory_block(blockhandle : DWord) : Boolean; | |
Description: | This function frees a memory block that was allocated trough the dpmi_allocate_memory_block() function. |
Parameters: | blockhandle - handle of memory block to free |
Return values: | none |
Error code: | $0002 |
Notes: | Your programs must also free selectors that it allocated to access the memory. |
See also: | Memory management services, dpmi_allocate_memory_block(), Table 1, Table 2 |
function dpmi_resize_memory_block(newsize : DWord; var blockhandle : DWord; var linearaddr : DWord) : Boolean; | |
Description: | This function changes the size of a memory block that was allocated through the dpmi_allocate_memory_block() function. |
Parameters: | newsize - new size of memory block in bytes
blockhandle - handle of memory block to resize |
Return values: | linearaddr - new linear address of memory block
blockhandle - new blockhandle of memory block |
Error code: | $0002 |
Notes: | This function may change the linear address of the memory block and its handle. Therefore, you'll need to update any selectors that point to the block after resizing it. You must use the new handle instead of the old one. |
See also: | Memory management services, dpmi_allocate_memory_block(), dpmi_free_memory_block(), Table 1, Table 2 |
function dpmi_physical_address_mapping(physaddr : DWord; size : DWord; var linearaddr : DWord) : Boolean; | |
Description: | Converts physical memory addresses of devices into 32 bit linear addresses |
Parameters: | physaddr - physical address of memory range
size - size of memory region in bytes - 1 |
Return values: | linearaddr - linear address of device memory |
Error code: | |
Notes: | The returned linear address can be used to access the devices' memory. The application must create a valid descriptor to this memory before accessing it. Do not use this service to access memory that is mapped into the first megabyte of address space. (The physical address equals the linear address in this memory area only) |
See also: | Physical address mapping, map_physical_memory(), Table 1, Table 2 |
For easier access to this region the FPC team decided to automatically load the %fs segment register with a selector which maps the entire 1 Mb memory region. So you must make sure that this segment register never changes in your code, because some functions rely on this. Additionally they automatically provide a pre-allocated transfer buffer to be available for temporary use (e.g. as long as you don't call certain FPC functions).
Some tips about address calculation follow:
To obtain the linear address (offset) from the DOS memory selector, you need to calculate the address like it was in real mode. This linear address then can be used to copy it to protected mode heap.
(linear_address := segment * 16 + offset)
In reverse, to generate a segment:offset address out of a linear address do the following:
segment := linear_address div 16;
offset := linear_address and 15;
This can be useful when you need to pass the segment:offset address
of e.g. the transfer buffer to a real mode interrupt.
function
dpmi_allocate_DOS_memory_block(size : DWord; var realaddr : rm_Addr;
var sel : Word) : Boolean;or function dpmi_allocate_DOS_memory_block (size : DWord; var realseg : Word; var sel : Word) : Boolean; |
|
Description: | This function will allocate a block of memory from the DOS memory pool. It returns both the real mode memory segment and a descriptor which can be used by protected mode applications. |
Parameters: | size - size of requested DOS memory block in bytes |
Return values: | realaddr - DOS real mode segment:offset address of the allocated memory block realseg - DOS real mode segment of the allocated memory block sel - protected mode selector for allocated block |
Error code: | $0002 |
Notes: | Your program should never modify or deallocate any descriptors allocated by this function. The dpmi_free_DOS_memory_block() function will automatically deallocate the descriptors |
See also: | DOS memory managment, dpmi_free_DOS_memory_block(), dpmi_resize_DOS_memory_block(), Table 1, Table 2 |
function dpmi_free_DOS_memory_block(sel : Word) : Boolean; | |
Description: | This function frees memory that was previously allocated by the dpmi_allocate_DOS_memory_block() function. |
Parameters: | sel - selector |
Return values: | none |
Error code: | $0002 |
Notes: | The descriptor allocated for the memory block is automatically freed and therefore should not be accessed once the freed by this function. |
See also: | DOS memory managment, dpmi_allocate_DOS_memory_block(), Table 1, Table 2 |
function dpmi_resize_DOS_memory_block(newsize : DWord; sel : Word) : Boolean; | |
Description: | This function is used to grow or shrink a memory block that was previously allocated by the dpmi_allocated_DOS_memory_block() function. |
Parameters: | newsize - new block size in bytes
sel - selector of block to modify |
Return values: | none |
Error code: | $0002 |
Notes: | Growing a DOS memory block is often likely to fail because other DOS memory allocations will prevent increasing the size of the block. Therefore, this function is usually only used to shrink a block |
See also: | DOS memory managment, dpmi_allocate_DOS_memory_block(), dpmi_free_DOS_memory_block(), Table 1, Table 2 |
All interrupts from hardware (like keyboard, or timer) will always be
reflected to the protected mode handler first. If the protected mode handler
jumps or calls the previous interrupt handler, then the interrupt will
be reflected to real mode.
As in real mode, interrupt procedures can either service the interrupt
via iret or they can chain to the next interrupt handler in an interrupt
chain. The final handler for all protected mode handlers will reflect the
interrupt to real mode (e.g. the real mode interrupt gets executed).
When an interrupt is reflected to real mode %eax, %ebx, %ecx, %edx,
%esi, %edi, %ebp registers and flags will all be passed unaltered from
protected to real mode. The segment registers contain undefined values.
The DPMI host automatically provides a real mode stack for interrupts that
are reflected to real mode.
function dpmi_get_rm_interrupt(number : Byte; var addr : rm_Addr) : Boolean; | |
Description: | This function returns the value of the current task's real mode interrupt vector for the specified interrupt |
Parameters: | number - interrupt number |
Return values: | rm_Addr - address of real mode interrupt vector |
Error code: | |
Notes: | The returned address is a real mode segment:offset address, not a protected mode one. |
See also: | Interrupt services, dpmi_set_rm_interrupt(), dpmi_get_pm_interrupt(), dpmi_set_pm_interrupt(), dpmi_get_exception_handler(), dpmi_set_exception_handler(), dpmi_simulate_rm_interrupt(), dpmi_allocate_rm_callback(), intr(), realintr(), rm_Addr (Type), Table 1, Table 2 |
function dpmi_set_rm_interrupt(number : Byte; addr : rm_Addr) : Boolean; | |
Description: | This function sets the value of the current task's real mode vector for the specified interrupt. |
Parameters: | number - interrupt number to set
addr - address of real mode interrupt |
Return values: | none |
Error code: | $0002 |
Notes: | The address passed to this function must be a real mode segment:offset address, not a protected mode selector:offset address. This means that the code for the interrupt handler must either be in DOS addressable memory or you must use a real mode callback address. Refer to dpmi_allocate_DOS_memory() on allocating memory below 1 Mb. Information on real mode callbacks can be found at the Translation services section. |
See also: | Interrupt services, dpmi_get_rm_interrupt(), dpmi_get_pm_interrupt(), dpmi_set_pm_interrupt(), dpmi_get_exception_handler(), dpmi_set_exception_handler(), dpmi_simulate_rm_interrupt(), dpmi_allocate_rm_callback(), intr(), realintr(), rm_Addr (Type), Table 1, Table 2 |
function dpmi_get_exception_handler(number : Byte; var addr : pm_Addr) : Boolean; | |
Description: | This function returns the address of the current protected mode exception handler for the specified exception number. |
Parameters: | number - exception number |
Return values: | addr - selector:offset of the exception |
Error code: | $0002 |
Notes: | This function fails if the number passed was invalid. |
See also: | Interrupt services, dpmi_set_exception_handler(), dpmi_get_rm_interrupt(), dpmi_set_rm_interrupt(), dpmi_get_pm_interrupt(), dpmi_set_pm_interrupt(), dpmi_allocate_rm_callback(), dpmi_simulate_rm_interrupt(), intr(), realintr(), pm_Addr (Type), Table 1, Table 2 |
function dpmi_set_exception_handler(number : Byte; addr : pm_Addr) : Boolean; | |
Description: | This function allows protected mode programs to intercept processor exceptions that are not handled by the DPMI environment. Programs may wish to handle exceptions such as protection faults which would otherwise generate a fatal error. |
Parameters: | number - exception/fault number ($00-$1F)
pm_addr - selector:offset address of exception handler |
Return values: | none |
Error code: | $0002 |
Notes: | Every exception is first examined by the protected mode operating system. If it cannot handle it, it then reflects it through the protected mode exception handler chain. The final handler in the chain may either reflect the exception as an interrupt or terminate the program. This function fails if the exception/fault number passed is invalid. For further reference on how to deal with exceptions (and setting up a handler), please consult a DPMI reference. |
See also: | Interrupt services, dpmi_get_exception_handler(), dpmi_get_rm_interrupt(), dpmi_set_rm_interrupt(), dpmi_get_pm_interrupt(), dpmi_set_pm_interrupt(), dpmi_allocate_rm_callback(), dpmi_simulate_rm_interrupt(), intr(), realintr(), pm_Addr (Type), Table 1, Table 2 |
function dpmi_get_pm_interrupt(number : Byte; var addr : pm_Addr) : Boolean; | |
Description: | This function returns the current selector:offset address for the specified protected mode interrupt handler. |
Parameters: | number - interrupt number |
Return values: | addr - protected mode selector:offset vector of interrupt |
Error code: | $0002 |
Notes: | The address returned is a protected mode selector:offset address, not a real mode address. All 256 interrupts are supported by the DPMI host. |
See also: | Interrupt services, dpmi_set_pm_interrupt(), dpmi_set_exception_handler(), dpmi_get_exception_handler(), dpmi_get_rm_interrupt(), dpmi_set_rm_interrupt(), dpmi_allocate_rm_callback(), dpmi_simulate_rm_interrupt(), intr(), realintr(), pm_Addr (Type), Table 1, Table 2 |
function dpmi_set_pm_interrupt(number : Byte; addr : pm_Addr) : Boolean; | |
Description: | Sets the specified protected mode interrupt vector of the current task. |
Parameters: | number - interrupt number to set
addr - new protected mode address of interrupt. |
Return values: | none |
Error code: | $0002 |
Notes: | The address passed to this function must be a valid selector:offset protected mode address. |
See also: | Interrupt services, dpmi_get_pm_interrupt(), dpmi_set_rm_interrupt(), dpmi_get_rm_interrupt(), dpmi_set_exception_handler(), dpmi_get_exception_handler(), dpmi_allocate_rm_callback(), dpmi_simulate_rm_interrupt(), intr(), realintr(), pm_Addr (Type), Table 1, Table 2 |
function dpmi_get_and_disable_virtual_interrupts(var prevstate : Boolean) : Boolean; | |
Description: | This function will disable the virtual interrupt state and return the previous state of the virtual interrupt flag. |
Parameters: | none |
Return values: | prevstate - previous virtual interrupt state |
Error code: | |
Notes: | Virtual interrupts are disabled after this call. |
See also: | Virtual interrupt state functions, dpmi_get_and_enable_virtual_interrupts(), dpmi_get_virtual_interrupt_state() Table 1, Table 2 |
function dpmi_get_and_enable_virtual_interrupts(var prevstate : Boolean) : Boolean; | |
Description: | This function will enable virtual interrupts and return the previous state of the virtual interrupt flag |
Parameters: | none |
Return values: | prevstate - previous virtual interrupt state |
Error code: | |
Notes: | Virtual interrupts are enabled after this call |
See also: | Virtual interrupt state functions, dpmi_get_and_disable_virtual_interrupts(), dpmi_get_virtual_interrupt_state() Table 1, Table 2 |
function dpmi_get_virtual_interrupt_state(var state : Boolean) : Boolean; | |
Description: | Returns the current state of the virtual interrupt flag |
Parameters: | none |
Return values: | state - current virtual interrupt flag state |
Error code: | |
Notes: | none |
See also: | Virtual interrupt state functions, dpmi_get_and_enable_virtual_interrupts(), dpmi_get_and_disable_virtual_interrupts(), Table 1, Table 2 |
All functions automatically provide a locked real-mode stack of about 30 words.
If your program needs to perform a series of calls to a real mode API it's sometimes more convenient to use the translation services to call a real mode procedure in your own program. That procedure can then issue the API calls in real mode and then return to protected mode.
There is also a mechanism for protected mode software to gain control
from real mode via a real mode call-back address. Real mode call-backs
can be used to hook to real mode interrupts or to be called in protected
mode by a real mode driver. For example, many mouse drivers will call a
specified address whenever the mouse is moved. This service allows the
call-back to be handled by software running in protected mode.
function dpmi_simulate_rm_interrupt(number : Byte; var regs : Registers) : Boolean; | |
Description: | This function simulates an interrupt in real-mode. |
Parameters: | number - interrupt to call
regs - register values supplied to interrupt |
Return values: | regs - register values changed by interrupt |
Error code: | $0002 |
Notes: | |
See also: | Translation services, intr(), realintr(), registers (Type), dpmi_call_rm_procedure_with_iret_frame(), Table 1, Table 2 |
function dpmi_call_rm_procedure_with_retf_frame(var regs : Registers) : Boolean; | |
Description: | This function calls a real mode procedure. The called procedure must end with a far return when it completes. |
Parameters: | regs - register values supplied to real-mode procedure |
Return values: | regs - register values modified by real mode procedure |
Error code: | $0002 |
Notes: | The cs:ip in the register values structure specifies the address of procedure to call. Note that all given segment registers in this structure need to be real mode segments. |
See also: | Translation services, Table 1, Table 2 |
function dpmi_call_rm_procedure_with_iret_frame(var regs : Registers) : Boolean; | |
Description: | This function calls a real-mode procedure which must return with an iret instruction |
Parameters: | regs - registers supplied to real-mode procedure |
Return values: | regs - register values modified by real-mode procedure |
Error code: | |
Notes: | The cs:ip fields in the register values structure specifies the address of the procedure to call. |
See also: | Translation services, Table 1, Table 2 |
function dpmi_allocate_rm_callback(procaddr : pm_Addr; regs : pm_Addr; var realaddr : rm_Addr) : Boolean; | |
Description: | This function is used to obtain a unique real-mode segment-offset address that will transfer control from real-mode to a protected mode procedure. |
Parameters: | procaddr - selector:offset of procedure to call
regs - selector:offset of real mode call structure |
Return values: | realaddr - segment:offset of real mode call address |
Error code: | |
Notes: | Call-back procedure parameters at entry:
Interrupts disabled %DS:%ESI = selector:offset of real mode SS:SP %ES:%EDI = selector:offset of real mode call structure %SS:%ESP =Locked protected mode API stack Return from callback procedure:
The called procedur is responsible for modifying the real-mode CS:IP
before returning. If the real mode CS:IP is left unchanged the real-mode
callback will be executed immediately and your protected mode procedure
will be called again. Normally you'll pop a return address off the real-mode
stack and place it in the real mode CS:IP.
|
See also: | Translation services, Table 1, Table 2 |
function dpmi_free_rm_callback(procaddr : rm_Addr) : Boolean; | |
Description: | This function frees a real mode call-back address that was previously allocated through the dpmi_allocate_rm_callback() function. |
Parameters: | rm_Addr - real-mode segment:offset callback address to free |
Return values: | none |
Error code: | $0002 |
Notes: | Real mode callbacks are a limited resource. They should be freed when no longer used. |
See also: | Translation services, Table 1, Table 2 |
Although memory ranges are in specified in bytes, the actual unit of
memory that is locked will be one or more pages. Page locks are maintained
as a count. When the count is decremented to zero, the page is unlocked
and can be swapped to disk. This means if a region is locked three times
then it must be unlocked three times before the pages will be unlocked.
function dpmi_lock_linear_region(linaddr : DWord; size : DWord) : Boolean; | |
Description: | This function locks a specified memory range |
Parameters: | linaddr - starting linear address of memory range to lock
size - size of region to lock in bytes |
Return values: | none |
Error code: | |
Notes: | If this function fails, no memory was locked. If the specified region overlaps part of a page at the beginning or end, the whole page(s) will be locked. |
See also: | Page locking services, Table 1, Table 2 |
function dpmi_unlock_linear_region(linaddr : DWord; size : DWord) : Boolean; | |
Description: | Unlocks a specified linear address memory range that was previously locked by dpmi_lock_linear_region(). |
Parameters: | linaddr - starting linear address of memory range
size - size of region to be locked in bytes |
Return values: | none |
Error code: | $0002 |
Notes: | If the function fails, none of the memory will be unlocked. An error will be returned if the memory was not previously locked or if the specified region is invalid. If the specified region overlaps part of a page at the beginning or end, the page(s) will be unlocked. Even if the function succeeds, the memory will remain locked if the lock count is not decremented to zero. |
See also: | Page locking services, Table 1, Table 2 |
function dpmi_mark_rm_region_as_pageable(startaddr : DWord; size : DWord) : Boolean; | |
Description: | Normally some DPMI implementations lock the DOS real mode memory by default to prevent disk swapping of this memory. If a protected mode program is using DOS memory, it is a good idea to use this function to turn off automatic page locking for regions of memory that are not touched by interrupts |
Parameters: | startaddr - starting linear address of memory to be marked as pageable
size - size of memory to page in bytes |
Return values: | none |
Error code: | |
Notes: | Do not mark memory not owned by your program as pageable. It is very important to relock any real mode memory using dpmi_relock_rm_region() before terminating the program. Memory that remains unlocked after program exit may cause fatal page faults when other software is accessing the same address space. Note that address space marked as pageable may be locked by using dpmi_lock_linear_region(). This function is only an advisory for the DPMI host to allow memory that doesn't be locked to be paged out. This function just disables any automatic locking of real-mode memory performed by the DPMI host. If this function fails then none of the memory will be unlocked. If the specified region overlaps part of a page at the beginning or end these page(s) will not marked as pageable. |
See also: | Page locking services, Table 1, Table 2 |
function dpmi_relock_rm_region(startaddr : DWord; size : DWord) : Boolean; | |
Description: | This function is used to relock real-mode memory previously locked via dpmi_mark_rm_region_as_pageable(). |
Parameters: | startaddr - starting linear address of memory to be relocked
size - size of memory region in bytes |
Return values: | none |
Error code: | |
Notes: | If this function fails, none of the memory specified will be relocked. If the specified region overlaps part of a page at the beginning or end of the region, the page(s) will not be relocked. |
See also: | Page locking services, Table 1, Table 2 |
function dpmi_get_page_size(var pagesize : DWord) : Boolean; | |
Description: | Returns the size of a single memory page |
Parameters: | none |
Return values: | pagesize - size of page in bytes |
Error code: | none (this function never fails) |
Notes: | The typical size is 4 kb, but don't make any assumptions on this. |
See also: | Page locking services, Table 1, Table 2 |
Although these functions are only relevant for DPMI implementations that support virtual memory (both CWSDPMI and Win9x do this), other implementations may ignore this (although they always succeed).
Since both of this functions are simply advisory, the operating system
may choose to ignore these calls.
function dpmi_mark_page_as_demand_paging_candidate(startaddr : DWord; size : DWord) : Boolean; | |
Description: | This function is used to inform the operating system that a range of pages should be placed on top of the page out candidate list. This will force these pages to be swapped to disk even if they were accessed recently. However all memory contents will be preserved. |
Parameters: | startaddr - starting linear address of pages to mark
size - size of region in bytes to mark as paging candidates |
Return values: | none |
Error code: | |
Notes: | This function does not force the pages to be swapped immediately. Partial pages will not be marked. |
See also: | Demand paging performance tuning services, Table 1, Table 2 |
function dpmi_discard_page_contents(startaddr : DWord; size : DWord) : Boolean; | |
Description: | This function discards the entire memory contents of a given linear memory range. It is used after a memory object that occupied a given piece of memory has been discarded. |
Parameters: | startaddr - starting linear address of pages to discard
size - number of bytes to discard |
Return values: | none |
Error code: | |
Notes: | The contents of the memory region will be undefined the next time memory is accessed. All values previously stored in this memory will be lost. Partial pages will not be discarded. |
See also: | Demand paging performance tuning services, Table 1, Table 2 |
function dpmi_get_version(var ver : Word; var flags : Word; var processor : Byte; picbase : Word) : Boolean; | |
Description: | Returns the version of the DPMI services supported. |
Parameters: | none |
Return values: | ver - the hi-byte is the major version number, the low-byte the minor
version number
flags - refer to DPMI specification processor - processor type (2=286..4=486) picbase - refer to DPMI specification |
Error code: | $0002 |
Notes: | none :) |
See also: | Miscellanous services, Table 1, Table 2 |
A list which DPMI functions what function calls can be seen in Table
5.
function create_selector(var sel : Word; baseaddr, size : DWord) : Boolean; | |
Description: | Allocates a single new selector and initializes it to the specified values |
Parameters: | baseaddr - linear 32 bit base address of new selector
size - new 32 bit segment limit in bytes - 1 |
Return values: | none |
Error code: | See notes |
Notes: | This function calls several different DPMI functions, the error code returned is the one from the DPMI functions called which caused the error. |
See also: | Commonly used combinations, Table 1, Table 5 |
function change_selector(sel : Word; new_baseaddr, new_size : DWord) : Boolean; | |
Description: | Changes base address and limit of a single selector. |
Parameters: | new_baseaddr - new linear 32 bit base address of selector
new_size - new 32 bit segment limit in bytes - 1 |
Return values: | none |
Error code: | See notes |
Notes: | This function calls several different DPMI functions, the error code returned is the one from the DPMI functions called which caused the error. |
See also: | Commonly used combinations, Table 1, Table 5 |
function free_selector(sel : Word) : Boolean; | |
Description: | Frees a previously allocated selector |
Parameters: | sel - selector to free |
Return values: | none |
Error code: | See dpmi_free_ldt_descriptor() |
Notes: | See dpmi_free_ldt_descriptor() |
See also: | Commonly used combinations, Table 1, Table 5 |
function get_linear_address(sel : Word; offset : DWord) : DWord; | |
Description: | Returns the 32 bit linear address of a protected mode selector:offset address |
Parameters: | sel - selector
offset - offset into selector |
Return values: | 32 bit linear address |
Error code: | See dpmi_get_segment_base_address() |
Notes: | See dpmi_get_segment_base_address() |
See also: | Commonly used combinations, Table 1, Table 5 |
function map_physical_memory(physaddr : DWord; size : DWord; var sel : Word) : Boolean; | |
Description: | Maps a memory area of a physical device to a single descriptor |
Parameters: | physaddr - physical address of device to map
size - size of memory region to map in bytes - 1 |
Return values: | sel - selector to memory region |
Error code: | See notes |
Notes: | This function uses several different DPMI calls, so the error code returned is the one from the function which caused the error. |
See also: | Commonly used combinations, Table 1, Table 5 |
function intr(num : Byte; var r : registers) : Boolean; | |
Description: | Issues a real mode interrupt. |
Parameters: | num - number of interrupt
r - supplied registers data structure |
Return values: | r - registers data structure with the values changed by the interrupt |
Error code: | See dpmi_simulate_rm_interrupt() |
Notes: | See dpmi_simulate_rm_interrupt() |
See also: | Commonly used combinations, Table 1, Table 5 |
function realintr(num : Byte; var r : registers) : Boolean; | |
Description: | Issues a real mod interrupt |
Parameters: | num - number of interrupt
r - supplied registers data structure |
Return values: | r - register values data structure changed by interrupt |
Error code: | See dpmi_simulate_rm_interrupt() |
Notes: | See dpmi_simulate_rm_interrupt() |
See also: | Commonly used combinations, Table 1, Table 5 |
function lock_data(var data; size : DWord) : Boolean; | |
Description: | Locks a memory range in the %ds segment |
Parameters: | data - address of data to be locked
size - size of memory range to be locked |
Return values: | none |
Error code: | See dpmi_lock_linear_region() |
Notes: | See dpmi_lock_linear_region() |
See also: | Commonly used combinations, Table 1, Table 5 |
function lock_code(faddr : pointer; size : DWord) : Boolean; | |
Description: | Locks a memory range in the %cs segment |
Parameters: | faddr - starting address to data (typically code) to be locked
size - size of memory range to be locked |
Return values: | none |
Error code: | See dpmi_lock_linear_region() |
Notes: | See dpmi_lock_linear_region() |
See also: | Commonly used combinations, Table 1, Table 5 |
function unlock_data(var data; size : DWord) : Boolean; | |
Description: | Unlocks a memory range in the %ds segment |
Parameters: | data - address of data to be unlocked
size - size of memory region to be unlocked |
Return values: | none |
Error code: | See dpmi_unlock_linear_region() |
Notes: | See dpmi_unlock_linear_region() |
See also: | Commonly used combinations, Table 1, Table 5 |
function unlock_code(faddr : Pointer; size : DWord) : Boolean; | |
Description: | Unlocks a memory range in the %cs segment |
Parameters: | faddr - starting address of region to be unlocked
size - size of memory range in bytes |
Return values: | none |
Error code: | See dpmi_unlock_linear_region() |
Notes: | See dpmi_unlock_linear_region() |
See also: | Commonly used combinations, Table 1, Table 5 |
function CSeg : Word; | |
Description: | Returns the contents of the %cs segment register |
Parameters: | none |
Return values: | current value of %cs |
Error code: | none (This function never fails) |
Notes: | It is allowed under FPC (GO32V2) to write to the code segment by default. |
See also: | Segment register access, dseg(), dsegalias(), eseg(), fseg(), gseg(), sseg(), Table 1 |
function DSeg : Word; | |
Description: | Returns the contents of the %ds segment register |
Parameters: | none |
Return values: | current value of %ds |
Error code: | none (This function never fails) |
Notes: | %ds and %es must always contain the same value, as some FPC function rely on this |
See also: | Segment register access, cseg(), dsegalias(), eseg(), fseg(), gseg(), sseg(), Table 1 |
function DSegAlias : Word; | |
Description: | Returns ___djgpp_ds_alias, which is a copy of the %ds segment register. |
Parameters: | none |
Return values: | value of ___djgpp_ds_alias |
Error code: | none (This function never fails) |
Notes: | The only difference between %ds and this value is, that the limit of
___djgpp_ds_alias isn't set to zero at a run-time error. This is used by
FPC so that the program automatically exits at the next %ds-access.
It is good to use this value instead of the standard %ds register in real-mode callbacks, so that run-time errors do not occur while executing in real-mode (done automatically). |
See also: | Segment register access, cseg(), dseg(), eseg(), fseg(), gseg(), sseg(), Table 1 |
function ESeg : Word; | |
Description: | Returns the contents of the %es segment register |
Parameters: | none |
Return values: | current value of %es |
Error code: | none (This function never fails) |
Notes: | %ds and %es must always contain the same value, as some FPC function rely on this |
See also: | Segment register access, cseg(), dseg(), dsegalias(), fseg(), gseg(), sseg(), Table 1 |
function FSeg : Word; | |
Description: | Returns the contents of the %fs segment register |
Parameters: | none |
Return values: | current value of %fs |
Error code: | none (This function never fails) |
Notes: | %fs stores the selector to DOS real mode memory by default. Some FPC functions rely on this, so make sure that you restore it after use. |
See also: | Segment register access, cseg(), dseg(), dsegalias(), eseg(), gseg(), sseg(), Table 1 |
function GSeg : Word; | |
Description: | Returns the contents of the %gs segment register |
Parameters: | none |
Return values: | current value of %gs |
Error code: | none (This function never fails) |
Notes: | This is the only segment register that can be changed without restoring it. |
See also: | Segment register access, cseg(), dseg(), dsegalias(), eseg(), fseg(), sseg(), Table 1 |
function SSeg : Word; | |
Description: | Returns the contents of the %ss segment register |
Parameters: | none |
Return values: | current value of %s |
Error code: | none (This function never fails) |
Notes: | |
See also: | Segment register access, cseg(), dseg(), dsegalias(), eseg(), fseg(), gseg(), Table 1 |
procedure outportb(port : Word; data : Byte); | |
Description: | Sends a single byte to the specified port address |
Parameters: | port - port address to send data to
data - data byte sent |
Return values: | none |
Error code: | none (This function never fails) |
Notes: | |
See also: | Port access, outportw(), outportl(), inportb(), inportw(), inportl(), Table 1 |
procedure outportw(port : Word; data : Word); | |
Description: | Sends a single word to the specified port address |
Parameters: | port - port address to send data to
data - data word sent |
Return values: | none |
Error code: | none (This function never fails) |
Notes: | |
See also: | Port access, outportb(), outportl(), inportb(), inportw(), inportl(), Table 1 |
procedure outportl(port : Word; data : Longint); | |
Description: | Sends a single longint to the specified port address |
Parameters: | port - port address to send data to
data - data longint sent |
Return values: | none |
Error code: | none (This function never fails) |
Notes: | |
See also: | Port access, outportb(), outportw(), inportb(), inportw(), inportl(), Table 1 |
function inportb(port : Word) : Byte; | |
Description: | Reads a single byte from the specified port address |
Parameters: | port - Port address to get data from |
Return values: | Data byte read |
Error code: | none (This function never fails) |
Notes: | |
See also: | Port access, outportb(), outportw(), outportl(), inportw(), inportl(), Table 1 |
function inportw(port : Word) : Word; | |
Description: | Reads a single word from the specified port address |
Parameters: | port - Port address to get data from |
Return values: | Data word read |
Error code: | none (This function never fails) |
Notes: | |
See also: | Port access, outportb(), outportw(), outportl(), inportb(), inportl(), Table 1 |
function inportl(port : Word) : Longint; | |
Description: | Reads a single longint from the specified port address |
Parameters: | port - Port address to get data from |
Return values: | Data Longint read |
Error code: | none (This function never fails) |
Notes: | |
See also: | Port access, outportb(), outportw(), outportl(), inportb(), inportw(), Table 1 |
procedure Enable; | |
Description: | Enables hardware interrupts |
Parameters: | none |
Return values: | none |
Error code: | none (This function never fails) |
Notes: | Issues a sti instruction |
See also: | Enable/Disable hardware interrupts, disable(), Table 1 |
procedure Disable; | |
Description: | Disables all hardware interrupts |
Parameters: | none |
Return values: | none |
Error code: | none (This function never fails) |
Notes: | Hardware interrupts shouldn't be turned off for longer periods of time, because several components of a modern PC rely on this. |
See also: | Enable/Disable hardware interrupts, enable(), Table 1 |
function tb_size : DWord; | |
Description: | Returns the size of the pre-allocated transfer buffer. |
Parameters: | none |
Return values: | Size in bytes of the buffer |
Error code: | none (This function never fails) |
Notes: | Don't make any assumptions about the size of this buffer, although it is typically 16 kb. |
See also: | Transfer buffer, DOS memory management, tb_size(), Table 1 |
function tb_address : DWord; | |
Description: | Returns the linear offset of the transfer buffer from the %fs segment. |
Parameters: | none |
Return values: | Offset of buffer from the beginning of the %fs segment |
Error code: | none (This function never fails) |
Notes: | The fseg() function can be used to determine the full 48 bit protected
mode selector:offset address for copying purposes.
The real mode segment:offset address of this block is (tb_address() shr 4):(tb_address() and $F) as usual.. |
See also: | Transfer buffer, DOS memory management, tb_address(), Table 1 |
This is what the following functions do: They extend the limit of the
%ds and %es segment register to $FFFFFFFF and return control to your application.
Since the limit doesn't affect system functions and procedures, everything
works fine as long as FPC does not try to grow the heap. FPC does this
in a way that the %ds segment base may change, additionally it GPF's with
a 'Not enough memory' error, because it notices that the segment limit
is at the maximum and it can't increase it any further.
So you have several options when designing programs:
function dpmi_enable_nearptr : Boolean; | |
Description: | Enables "near-pointer" mapping by setting 32 bit limit of %ds and %es to $FFFFFFFF |
Parameters: | none |
Return values: | none |
Error code: | $F000 |
Notes: | Near pointer mapping can be disabled at any time by issuing a dpmi_disable_nearptr() call. |
See also: | "Near pointer" handling, dpmi_disable_nearptr(), dpmi_nearptr_enabled(), dpmi_nearptr_address_mapping(), Table 1 |
function dpmi_disable_nearptr : Boolean; | |
Description: | Disables "near-pointer" mapping by restoring the old values of %ds and %es again |
Parameters: | none |
Return values: | none |
Error code: | $F001 |
Notes: | "Near pointer" mapping can be enabled and disabled at any time, but once you disabled near pointers, you'll need to restore pointers which where gained via dpmi_nearptr_address_mapping() again since the base segment address may have changed. All other FPC functions and procedures work as usual. |
See also: | "Near pointer" handling, dpmi_enable_nearptr(), dpmi_nearptr_enabled(), dpmi_nearptr_address_mapping(), Table 1 |
function dpmi_nearptr_enabled(var enabled : Boolean) : Boolean; | |
Description: | Returns the current status of near pointer mapping |
Parameters: | none |
Return values: | enabled - true if "near pointers" are enabled, false if not |
Error code: | none (This function never fails) |
Notes: | none |
See also: | "Near pointer" handling, dpmi_enable_nearptr(), dpmi_disable_nearptr(), dpmi_nearptr_address_mapping(), Table 1 |
function dpmi_nearptr_address_mapping(physaddr, size : DWord; var nearptr : Pointer) : Boolean; | |
Description: | Returns a 32 bit "near pointer" to a physical memory area (e.g. VGA) |
Parameters: | physaddr - the physical address of the device
size - the memory size of the physical device to be mapped - 1 |
Return values: | nearptr - the 32 bit "near pointer" to the phyiscal memory area |
Error code: | $F002 |
Notes: | Fails if not in near pointer mode. This function uses several different other DPMI functions, if they fail, they return their own error code. |
See also: | "Near pointer" handling, dpmi_enable_nearptr(), dpmi_disable_nearptr(), dpmi_nearptr_enabled(), Table 1 |
See Table 3 for a rough comparison between the two units, and some suggestions which DPMI functions you could use for what GO32 function.
In Table 4 a comparison between the different syntax of the units is made
GO32 term |
Equivalent DPMI term |
Notes |
|
||
|
||
carryflag | See flag constants | 1 |
parityflag | See flag constants | 1 |
auxcarryflag | See flag constants | 1 |
zeroflag | See flag constants | 1 |
signflag | See flag constants | 1 |
trapflag | See flag constants | 1 |
interruptflag | See flag constants | 1 |
directionflag | See flag constants | 1 |
overflowflag | See flag constants | 1 |
|
||
tmeminfo | See MemInfoBuf | |
tseginfo | See pm_Addr, rm_Addr | |
trealregs | See registers | |
registers | See registers | |
|
||
dosmemselector | See fseg() | |
int31error | See dpmi_error, dpmi_set_error_handler() | 2 |
|
||
function allocate_ldt_descriptors() | See dpmi_allocate_ldt_descriptors(), create_selector() | |
function free_ldt_descriptor() | See dpmi_free_ldt_descriptor(), free_selector() | |
function segment_to_descriptor() | See dpmi_segment_to_descriptor() | |
function get_next_selector_increment_value() | See dpmi_get_next_selector_increment_value() | |
function get_segment_base_address() | See dpmi_get_segment_base_address() | |
function set_segment_base_address() | See dpmi_set_segment_base_address(), create_selector() | |
function set_segment_limit() | See dpmi_set_segment_limit() | |
function set_descriptor_access_rights() | See dpmi_set_descriptor_access_rights() | |
function create_code_segment_alias_descriptor() | See dpmi_create_code_segment_alias_descriptor() | |
function get_linear_addr() | See dpmi_physical_address_mapping(), map_physical_memory(), get_linear_address() | |
function get_segment_limit() | See dpmi_get_segment_limit() | |
function get_descriptor_access_right() | See dpmi_get_descriptor_access_rights() | |
function get_page_size() | See dpmi_get_page_size() | |
function map_device_in_memory_block() | See notes | 3 |
function realintr() | See dpmi_simulate_rm_interrupt(), intr(), realintr() | |
function global_dos_alloc() | See dpmi_allocate_DOS_memory_block() | |
function global_dos_free() | See dpmi_free_DOS_memory_block() | |
procedure seg_fillchar() | See notes | |
procedure seg_fillword() | See notes | |
function get_meminfo() | See dpmi_get_free_memory_information() | |
function get_pm_interrupt() | See dpmi_get_pm_interrupt() | |
function set_pm_interrupt() | See dpmi_set_pm_interrupt() | |
function get_rm_interrupt() | See dpmi_get_rm_interrupt() | |
function set_rm_interrupt() | See dpmi_set_rm_interrupt() | |
function get_exception_handler() | See dpmi_get_exception_handler() | |
function set_exception_handler() | See dpmi_set_exception_handler() | |
function get_pm_exception_handler() | See notes | 3, 4 |
function set_pm_exception_handler() | See notes | 3, 4 |
function free_rm_callback() | See dpmi_free_rm_callback() | |
function get_rm_callback() | See dpmi_allocate_rm_callback() | |
function get_cs() | See cseg() | 1 |
function get_ds() | See dseg(), dsegalias() | 1 |
function get_ss() | See sseg() | 1 |
function allocate_memory_block() | See dpmi_allocate_memory_block() | 5, 6 |
function free_memory_block() | See dpmi_free_memory_block() | 6 |
function request_linear_region() | See notes | 3, 4 |
function lock_linear_region() | See dpmi_lock_linear_region() | |
function lock_data() | See lock_data() | |
function lock_code() | See lock_code() | |
function unlock_linear_region() | See dpmi_unlock_linear_region() | |
function unlock_data() | See unlock_data() | |
function unlock_code() | See unlock_code() | |
procedure disable() | See disable() | |
procedure enable() | See enable() | |
function inportb() | See inportb() | |
function inportw() | See inportw() | |
function inportl() | See inportl() | |
procedure outportb() | See outportb() | |
procedure outportw() | See outportw() | |
procedure outportl() | See outportl() | |
function get_run_mode() | See notes | 7 |
function transfer_buffer() | See tb_address() | |
function tb_segment() | See tb_address() | |
function tb_offset() | See tb_address() | |
function tb_size() | See tb_size() | |
procedure copytodos() | See notes | 8 |
procedure copyfromdos() | See notes | 8 |
procedure dosmemput() | See notes | 8 |
procedure dosmemget() | See notes | 8 |
procedure dosmemmove() | See seg_memcpy() | 9 |
procedure dosmemfillchar() | See seg_memsetb() | 9 |
procedure dosmemfillword() | See seg_memsetw() | 9 |
Btw, this table shows only a *direct* translation of these GO32 calls.
It's often much better and easier to use other functions or "time-saver"
functions. See Table 5
GO32 syntax example |
DPMI syntax example |
Notes |
|
||
selector := allocate_ldt_descriptors(2) | dpmi_allocate_ldt_descriptors(2, selector) | 1 |
free_ldt_descriptor(selector) | dpmi_free_ldt_descriptor(selector) | 2 |
selector := segment_to_descriptor($A000) | dpmi_segment_to_descriptor($A000, selector) | |
selincr := get_next_selector_increment_value() | dpmi_get_next_selector_increment_value(selincr) | |
base_address := get_segment_base_address(selector) | dpmi_get_segment_base_address(selector, base_address) | |
set_segment_base_address(selector, new_address) | dpmi_set_segment_base_address(selector, new_address) | 1 |
set_segment_limit(selector, new_limit) | dpmi_set_segment_limit(selector, limit) | |
set_descriptor_access_rights(selector, new_rights) | dpmi_set_descriptor_access_rights(selector, new_rights) | |
datasel := create_code_segment_alias_descriptor(code_sel) | dpmi_create_code_segment_alias_descriptor(code_sel, data_sel) | |
linear_addr := get_linear_addr(phys_addr, size) | dpmi_physical_address_mapping(phys_addr, size, linear_addr) | 3 |
limit := get_segment_limit(selector) | dpmi_get_segment_limit(selector, limit) | |
rights := get_descriptor_access_right(selector) | dpmi_get_descriptor_access_rights(selector, rights) | |
page_size := get_page_size() | dpmi_get_page_size(page_size) | |
function map_device_in_memory_block() | See notes | 4 |
function realintr(reg_num, reg_buffer) | dpmi_simulate_rm_interrupt(reg_num, reg_buffer) | 5 |
result := global_dos_alloc(size);
realseg := word(result); dos_selector := word(result shr 16); |
dpmi_allocate_DOS_memory_block(size, realseg, dos_selector) | |
global_dos_free(dos_selector) | dpmi_free_DOS_memory_block(dos_selector) | |
procedure seg_fillchar(selector, offset, size, char(byte_value)) | seg_memsetb(selector, offset, size, byte_value) | 6, 7 |
seg_fillword(selector, offset, size, word_value) | seg_memsetw(selector, offset, size, word_value) | 6, 7 |
get_meminfo(buffer) | dpmi_get_free_memory_information(buffer) | |
get_pm_interrupt(number, tseginfo_buffer) | dpmi_get_pm_interrupt(number, pm_Addr(buffer)) | 8 |
set_pm_interrupt(number, tseginfo_buffer) | dpmi_set_pm_interrupt(number, pm_Addr(buffer)) | 8 |
get_rm_interrupt(number, tseginfo_buffer) | dpmi_get_rm_interrupt(number, rm_Addr(buffer)) | 8 |
set_rm_interrupt(number, tseginfo(buffer)) | dpmi_set_rm_interrupt(number, rm_Addr(buffer)) | 8 |
get_exception_handler(number, tseginfo(buffer)) | dpmi_get_exception_handler(number, pm_Addr(buffer)) | 8 |
set_exception_handler(number, tseginfo(buffer)) | dpmi_set_exception_handler(number, pm_Addr(buffer)) | 8 |
get_pm_exception_handler() | See notes | 4 |
set_pm_exception_handler() | See notes | 4 |
free_rm_callback(tseginfo(intaddr)) | dpmi_free_rm_callback(rm_Addr(intaddr)) | |
get_rm_callback(pointer(func_addr), registers, tseginfo(rmcb)) | dpmi_allocate_rm_callback(pm_Addr(func_Addr), pm_Addr(registers), rm_Addr(rmcb)) | 7 |
cs := get_cs() | cs := cseg() | 6 |
ds := get_ds() | ds := dseg() | 6, 9 |
ss := get_ss() | ss := sseg() | 6 |
linaddr := allocate_memory_block(size) | dpmi_allocate_memory_block(size, handle, linaddr) | 10 |
free_memory_block(handle) | dpmi_free_memory_block(handle) | 11 |
function request_linear_region() | See notes | 4 |
lock_linear_region(linear_addr, size) | dpmi_lock_linear_region(linear_addr, size) | 6 |
lock_data(buffer, size) | lock_data(buffer, size) | 6 |
lock_code(func_addr, size) | lock_code(func_addr, size) | 6 |
unlock_linear_region(linear_addr, size) | dpmi_unlock_linear_region(linear_addr, size) | 6 |
unlock_data(buffer, size) | unlock_data(buffer, size) | 6 |
unlock_code(func_addr, size) | unlock_code(func_addr, size) | 6 |
disable() | disable() | 6 |
enable() | enable() | 6 |
data := inportb(port) | data := inportb(port) | 6 |
data := inportw(port) | data := inportw(port) | 6 |
data := inportl(port) | data := inportl(port) | 6 |
outportb(port, data) | outportb(port, data) | 6 |
outportw(port, data) | outportw(port, data) | 6 |
outportl(port, data) | outportl(port, data) | 6 |
get_run_mode() | See notes | 12 |
address := transfer_buffer() | address := tb_address() | 6 |
seg := tb_segment() | seg := tb_address() shr 4 | |
ofs := tb_offset() | ofs := tb_address() and $F | |
size := tb_size() | size := tb_size() | 6 |
copytodos(buffer, size) | seg_memcpy(dseg, dword(@buffer), fseg, tb_address(), size) | 7 |
copyfromdos(buffer, size) | seg_memcpy(fseg, tb_address(), dseg, dword(@address), size)) | 7 |
dosmemput(seg, ofs, buffer, size) | seg_memcpy(dseg, dword(@buffer), fseg, seg shl 4 + ofs, size) | 7 |
procedure dosmemget(seg, ofs, buffer, size) | seg_memcpy(fseg, seg shl 4 + ofs, dseg, dword(@buffer), size) | 7 |
dosmemmove(srcseg, srcofs, dstseg, dstofs, size) | seg_memcpy(fseg, srcseg shl 4 + ofs, fseg, dstseg shl4 + dstofs, size) | 7 |
dosmemfillchar(seg, ofs, size, char(value)) | seg_memsetb(fseg, seg shl 4 + ofs, size, byte(value)) | 7, 8 |
dosmemfillword(seg, ofs, size, value) | seg_memsetw(fseg, seg shl 4 + ofs, size, value) | 7 |
seg_move(srcsel, srcofs, dstsel, dstofs, size) | seg_memcpy(srcsel, srcofs, dstsel, dstofs, size) | 6, 7 |
seg_fillchar(sel, ofs, size, char(value)) | seg_memsetb(sel, ofs, size, char(value)) | 6, 7 |
seg_fillword(sel, ofs, size, value) | seg_memsetw(sel, ofs, size, value) | 6, 7 |