-------------------------------------------------
Copyright	Rainer Schnitker	'91 '92
-------------------------------------------------


THE DPMI INTERFACE :

This is a short documentation for the interface functions.
For details, read the DPMI-specification 0.9 .
DOS Extenders and DPMI is described in some special books like:
Ray Duncan "Extended Dos".


Most DPMI-functions return 0 if successful, -1 on error
        (later error code of DPMI 1.0).


****** LDT Descriptor management services  DPMI 0.9 ******

Constants in dpmi.h for LDT management:
	- set access rights for descriptors
		ACCESS_BIT, READ_BIT, WRITE_BIT, CONFIRMING_BIT, EXPAND_BIT,
                CODE_BIT, SEGMENT_BIT, PRESENT_BIT
		AVL_BIT, DEFAULT_BIT, GRANULAR_BIT
	- mask out special fields in descriptor
		DPL_MASK, TYPE_MASK, LIMIT_HI_MASK
	- normal access type for dpl3 programs
		APP_CODE_SEL, APP_DATA_SEL
	- types of gates
		TYPE_CODE, TYPE_CONFIRM_CODE, TYPE_DATA, TYPE_EXPAND_DATA,
                TYPE_286TSS, TYPE_LDT, TYPE_BUSY286TSS, TYPE_286CALLGATE
                TYPE_TASKGATE, TYPE_286INTGATE, TYPE_286TRAPGATE,
                TYPE_386TSS, TYPE_BUSY386TSS, TYPE_386CALLGATE
                TYPE_386INTGATE, TYPE_386TRAPGATE

int AllocLDT(WORD n,WORD *firstselector);
        - this allocates n descriptors from the Local Descriptor Table
        - add the value returned from function SelInc() to get the next selector
	- the descriptors will be set to present data type, base=0, limit=0

int FreeLDT(WORD selector);
        - this function is used to free descriptors that were allocated
          by the function AllocLDT()

int SegtoSel(WORD realsegment,WORD *selector);
        - this converts real mode segments into descriptors
        - selector has limit 64 KB

WORD SelInc(void);
        - return the increment value to get the next selector (typical 8).
        - function can't fail

int LockSel(WORD selector);
        - undocumented function
        - this locks the address area of the selector

int UnlockSel(WORD selector);
        - undocumented function
        - this function is used to unlock the memory area

int GetBaseAddress(WORD selector,DWORD *address);
        - gives the 32bit-linear address of the selector

int SetBaseAddress(WORD selector ,DWORD 32bitaddress);
        - set the base address of the specified selector

int SetLimit(WORD sel,DWORD limit);
	- set the limit for the selector (note: limit = blocksize - 1)
	- if limit > 1 MB, low 12 bits must be set
	  (then the granular bit will be set)
        - to get the limit use the function lsl32() or lsl16()

int SetAccess(WORD,BYTE accessbyte,BYTE 386extendedbyte);
        - set access rights for the selector
        - SEGMENT-bit must be set. You can't create a system descriptor.
        - to get the access right use the function lar32() or lar16()

int CreatAlias(WORD codeselector,WORD *alias_selector);
        - this creates a data descriptor with the same address and limit as
          the code descriptor

int GetDescriptor(WORD selector,NPDESCRIPTOR buffer);
        - this copies the 8 bytes descriptor table into the buffer

int SetDescriptor(WORD selector,NPDESCRIPTOR buffer);
        - this function is used to set a descriptor

int AllocSpecialLDT(WORD selector);
        - this allocates a specific LDT descriptor


****** DOS Memory Services DPMI 0.9 ******

int AllocDosMem(WORD paragraphs,WORD *segment,WORD *selector);
        - multiple contiguous selectors are allocated for blocks of more
          than 64K
        - if the caller is a 16-bit program never modify or
          deallocate returned descriptors
        - return 0 if successful, else DOS errors:
          07h memory control blocks damaged
          08h insufficient memory available

int FreeDosMem(WORD selector);
        - all descriptors allocated for the block are automatically freed

int ResizeDosMem(WORD newparagraphs,WORD oldselector,WORD *newselector);
        - increasing the size of a block past a 64K boundary will fail if the
	  next descriptor in the LDT is already in use
        - shrinking a block past a 64K boundary will cause some selectors to
          be freed


****** Interrupt Services DPMI 0.9 ******

int GetRealModeVector(BYTE intnumber,WORD segment*,WORD *offset);
        - get real mode interrupt vector

int SetRealModeVector(BYTE intnumber,WORD segment,WORD offset);
        - set real mode interrupt vector
        - hardware interrupt handler memory must be locked

int GetExceptionVektor(BYTE intnumber,WORD *selector,WORD *offset);
        - give the current protected mode exception handler

int SetExceptionVektor(BYTE intnumber,WORD selector,WORD offset);
        - set new protected mode exception handler
        - read DPMI-specification 0.9 for some details
        - use higher C-level functions, described later SetExcep13 etc.

int GetProtModeVector(BYTE,WORD *selector,WORD *offset);
        - get the current protected mode interrupt handler

int SetProtModeVektor(BYTE,WORD selector,WORD offset);
        - set new protected mode interrupt handler


****** Translation services DPMI 0.9 ******

int SimulateRMint(BYTE intnr,BYTE flags,WORD stackwords,NPTRANSLATION call,...)
        - CS:IP in the real mode call structure is ignored for this call,
	  instead, the indicated interrupt vector is used for the address
        - the flags in the call structure are pushed on the real mode stack to
	  form an interrupt stack frame, and the trace and interrupt flags are
	  clear on entry to the handler
        - DPMI will provide a small (30 words) real mode stack if SS:SP is zero
          the real mode handler must return with the stack in the same state as
	  it was on being called

int CallRMprocFar(BYTE flags,WORD stackwords,NPTRANSLATION call,...)
        - the real mode procedure must exit with a FAR return
        - DPMI will provide a small (30 words) real mode stack if SS:SP is zero
        - the real mode handler must return with the stack in the same state as
	  it was on being called

int CallRMprocIret(BYTE flags,WORD stackwords,NPTRANSLATION call,...)
        - the real mode procedure must exit with an IRET

int AllocRMcallAddress(WORD sel,WORD off,NPTRANSLATION call,
                WORD *rmseg,WORD *rmoff)
        - the real mode call structure is static, causing reentrancy problems
        - the called procedure must modify the real mode CS:IP before returning
        - values are returned to real mode by modifying the
          real mode call struct

int FreeRMcallAddress(WORD rmseg,WORD rmoff)
        - frees real mode callback address


****** Get Version DPMI 0.9 ******

void GetDPMIVersion(DPMIVERSION *)
        DPMIVERSION struct contains:
        - flags:
	    bit 0: running under an 80386 (32-bit) implementation
	    bit 1: processor returns to real mode for reflected interrupts
		   instead of V86 mode
	    bit 2: virtual memory supported
	    bit 3: reserved (undefined)
	    others reserved (zero)
        - cpu : processor type (02h=80286, 03h=80386, 04h=80486)
        - pic
          curr value of virtual master interrupt controller base interrupt
          curr value of virtual slave interrupt controller base interrupt


****** Memory management services DPMI 0.9 ******

void GetFreeMemInfo(NPFREEMEMINFO freemempointer);
        - get struct contains free mem info
        - struct FREEMEMINFO:
          DWORD   largest available block in bytes
          DWORD   maximum unlocked page allocation
          DWORD   maximum locked page allocation
          DWORD   total linear address space in pages
          DWORD   total unlocked pages
          DWORD   free pages
          DWORD   total physical pages
          DWORD   free linear address space in pages
          DWORD   size of paging file/partition in pages
          DWORD   reserved
          DWORD   reserved
          DWORD   reserved

int GlobalAlloc(DWORD bytes,DWORD *handle,DWORD *memaddress);
        - allocate memory block , size = bytes
        - in Windows you get memory page granular. This means that allocation
          of 534 bytes allocate 4096 = 4 KB.
        - handle is used to free memory blocks

int GlobalFree(DWORD handle);
        - frees a memory block that was allocate though GlobalAlloc()

int GlobalResize(DWORD size,DWORD oldhandle,DWORD *handle,DWORD *newmemaddress);
        - reallocate memory block , size = bytes
	- old handle is unvalid


****** Page locking services DPMI 0.9 ******

int LockLinRegion(DWORD size,DWORD linaddress);
        - locks linear address range , size = region to lock

int UnlockLinRegion(DWORD size,DWORD linaddress);
        - unlock linear address range

int MarkRealModePageable(DWORD size,DWORD address);
	- mark real mode region pageable
	- relock region before terminating program
	- use only programs own memory
	- be sure dpmi-host-memory not pageable

int RelockRealModeRegion(DWORD size,DWORD address);
	- relocks real mode region

int GetPageSize(DWORD *size);
        - get pagesize in bytes


****** Damand page performance tuning services DPMI 0.9 ******

int MarkPageDemand(DWORD address,DWORD n)
        - mark n pages as demand paging candidate
        - return   0 : successful   -1 : not successful

int DiscardPage(DWORD address_of_page,DWORD size)
        - discard contents of page
        - return   0 : successful   -1 : not successful


****** Physical Address Mapping DPMI 0.9 ******

int PhysicalMap(DWORD address,DWORD size,DWORD *physical)
        - implementations may refuse this call because it can circumvent
          protects
        - the caller must build an appropriate selector for the memory
        - do not use for memory mapped in the first megabyte


****** Virtuel interrupt state functions DPMI 0.9 ******

BYTE DisableVirtuelInterruptState(void)
        returns  0 if previously disabled
                 1 if previously enabled
        - disable interrupts
        - a CLI instruction may be used if the previous state is unimportant,
	  but should be assumed to be very slow due to trapping by the host

BYTE EnableVirtuelInterruptState(void)
        returns  0 if previously disabled
                 1 if previously enabled
        - enable interrupts
        - a STI instruction may be used if the previous state is unimportant,
	  but should be assumed to be very slow due to trapping by the host

BYTE GetVirtuelInterruptState(void)
        returns  0 if previously disabled
                 1 if previously enabled
        - should be used rather than PUSHF

****** Get Vendor Specific Api Entry Point ******

int GetVendorEntry(NPBYTE APIname,WORD *selector,WORD *offset)
        - APIname = case-sensitive ASCIZ vendor name or identifier
        - gives entry point for extended function


****** Debug Register support DPMI 0.9 ******

Constants in dpmi.h for breakpoints
		BREAK_CODE, BREAK_DATA_W1, BREAK_DATA_RW1, BREAK_DATA_W2
		BREAK_DATA_RW2, BREAK_DATA_W4, BREAK_DATA_RW4

int SetDebugWatchpoint(DWORD linear_address,WORD break_type,WORD *handle)
        - set breakpoint on linear address
        - types defined in dpmi.h
          data breakpoint : 1/2/4 byte read/write

int ClearDebugWatchpoint(WORD handle)
        - clear breakpoint

int GetStateDebugWatchpoint(WORD handle, WORD *execute_flag)
        - get state of breakpoint
        - execute_flag=1, if watchpoint has been executed

int ResetDebugWatchpoint(WORD handle)
        - reset state of breakpoint


****** CPU switching for DPMI 0.9 ******
int hangin_extender(void);
        - installs a DOS-Extender
        - return 0 , if successful


****** CPU switching for DPMI 0.9 ******

void real_to_protected(WORD type);
        - type=0 16 bit program , type=1 32 bit program
        - call this function switch the cpu in protected mode
        - other funtions are not execute if this function fails
        - cs,ds,es were set by the dpmi host

void protected_to_real(WORD errorcode);
        - switch cpu back to real mode
        - terminates the program ( like real mode int21,function 4c)
        - errorcode = errorleved to msdos


******* c-functions using DPMI **********

int FreeManyLDT(WORD sel,WORD n)
        - this frees n continius selectors

void PrintFreeMemInfo(NPFREEMEMINFO freemem);
        - this prints a free memory info

void PrintDescriptor(NPDESCRIPTOR descriptor);
        - print the descriptor address,limit,access type etc.

void far * IncFP(void far *);
        - increment selector to the next

void far * DecFP(void far *);
        - decrement selector to the next


****** high level memory functions in the DPMI-Enviroment *******

void set_memory_type(WORD type)
	- set memory allocating strategy for extmalloc
	- types 0, XMSLIMIT, LOCKMEM
	- XMSLIMIT allocates only memory <= XMS-POOL
	  useful to limit memory for PIF's in Windows 3.0
	- LOCKMEM allocates locked memory only

void far *extmalloc(DWORD nbytes);
        - allocates n bytes
        - if n is greater than 64 KB then continues descriptors will be
          allocated. To access the next descriptor add the value return by
          function IncSel() to the base selector
        - return base selector , NULL if insufficient memory available

void extfree(void far *filepointer);
        - frees memory that was allocated by extmalloc()


******** extended c-functions *********

void farcopy(void far *dest,void far *source,DWORD bytes)
        - copy memory block from far pointer to far pointer
        - bytes must min(limit-dest,limit-source) , ( -> GP-fault)
        - useful to copy pointers given by extmalloc(more then 64KB)

int extmovedata(void far *source,void far *dest,DWORD bytes)
        - same as movedata for size_t bytes
        - useful to copy pointers given by extmalloc(more then 64KB)
        - offsets should be the same


******** others *************

int IsWindowsEnhanced(void);
	- return 1 , if Windows Enhanced mode is running
	- else 0

int IsPM(void);
        - return 1 if cpu is in protected mode, 0 not

void Yield(void);
        - call int 2F function 1680h
        - useful in a program loop in a multitasking environment like Windows
          ( like GetMassage )


******* The Protected Mode Interface *******

DWORD lsl32(WORD selector);
        - load selector limit
        - uses 32-bit commands , only for >386
        - 286 must use lsl16()

WORD lsl16(WORD selector);
        - load selector limit

DWORD lar32(WORD selector);
        - load selector access rights and extended access rights
        - uses 32-bit commands , only for >386

WORD lar16(WORD selector);
        - load selector access rights
        - 286 must use lar16()

WORD verr(WORD selector);
        - verify if read flags is set
        - return 1 : read   0 : not

WORD verw(WORD selector);
        - verify if write flag is set
        - return 1 : write  0 : not

void sgdt(GDTR *gdtregister);
        - save GDT base address and limit

void sidt(GDTR *idtregister);
        - save IDT base address and limit

WORD sldt(void);
        - save LDT selector
        - return LDTselector

WORD str(void);
        - save task register
        - return TASKselector

