The C-Library for DPMI-Specification 0.9 and Protected Mode

This is a short documentation for the interface functions. For details, read the
DPMI-specification 0.9 . Protected Mode is discribed in some special books like
Ray Duncan "Extended Dos".

This library allows DOS-programs to run in protected mode.The great advantage is
the big address space. You can use the DPMI Interface 0.9 functions only in
enhanced mode in Windows 3.0 . In standard mode the function real_to_protected
is not supported. So you can't use the other funtion using int 31H.
A 286 computer can only use DPMI-functions in a Window-program, but i don't know
if this is useful.I hope other programs will support the DPMI-Interface.

The most compiler run in 16-bit mode. The limit for the selectors should be
set to 64KB. The functions extmalloc for example creates a continue array of
selectors if you allocate more than 64KB. This is neccesary, because you can't
address the whole space with a 16-bit compiler pointer,if you have only one
descriptor(limit more than 64KB). The library can be modified to run 32-bit
programs.

There are some printf statements in the protected mode code. This is allowed, 
because Windows provides a DOS-Extender.In other Environments this may be not
and you must write a protected mode handler for int 21h.

The library is not complete. Some of the DPMI 0.9 functions miss here.
In a next update i will complete it.
The c-code is for TurboC/Tasm but there are only few special TurboC statements.
Look in the files 'dpmiutil.c' and 'dpmi.h'.

Execute the files in the DosBox or from the File-manager. Be sure that the
PIF-files are there. This is neccessary because program memory must be locked.
Don't execute from the Turbo-Shell. This can cause a system-crash.

Files include in dpmi_lib.zip:

        dpmi.txt      : this file
        dpmiutil.c    : Main C-file include the Dpmi/PM -library
        dpmiutil.obj  : Object-file
        dpmi.h        : Header file for dpmi programs
        dpmi_v1.exe   : Demo 1 : shows the System-Tables used in Protected Mode
        dpmi_v1.c     : sources demo1
        dpmi_v1.mak   : Makefile demo1
        dpmi_v1.pif   : Windows 3.0 386/PIF-file for demo1
        dpmi_v2.exe   : Demo 2 : memory info and test program
        dpmi_v2.c     : sources demo2
        dpmi_v2.mak   : Makefile demo2
        dpmi_v2.pif   : Windows 3.0 386/PIF-file for demo2

If you already work with protected mode or you have some questions send mail to

Email Number : rainer@math5.uni-bielefeld.de

Home Address: Rainer Schnitker , Heeper Stasse 283 , 4800 Bielefeld , Germany



In "DPMI.H" you can find the following structures:

     1.  struct {
                WORD lim_lo,base_lo;
                BYTE base_mi,access;
                BYTE lim_hi,base_hi;
                } DESCRIPTOR ;
        this is the main structure in protected mode

     2. struct {
		WORD limit,lo,hi ;
	       } GDTR ;
        this structure is used to call the instruction sgdt
         ( save Global Descriptor Table )

     3. struct {
		WORD off_lo;
		WORD sel;
		BYTE count;
		BYTE type;
		WORD off_hi;
		} GATE;
        this structure is used in the IDT


The structure
        struct { DWORD i1,i2,i3,i4,i5,i6,i7,i8,i9,r1,r2,r3 ;
               }  FREEMEMINFO;
 is used in DPMI memory info (see below).

The line
 #define DPMI(function)  { _AX = function ; __int__(0x31) ; }
calls the DPMI Interface via int 31h


THE DPMI INTERFACE :

* CPU switching for DPMI 0.9

void real_to_protected(void);
        - 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(void);
        - switch cpu back to real mode
        - terminates the program ( like real mode int21,function 4c)

* LDT Descriptor management services  DPMI 0.9

WORD AllocLDT(WORD n);
        - this allocates n descriptors from the Local Descriptor Table
        - return value of the first selector , 0  on error
        - 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() ,
        - return    0 : successful    -1 : not successful

WORD SegtoSel(WORD realsegment);
        - this converts real mode segments into descriptors
        - return selector with limit 64 KB , or 0 on error

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

int LockSel(WORD selector);
        - undocumented function ("should not be called")
        - this locks the address area of the selector
        - return   0 : successful   -1 : not successful

int UnlockSel(WORD selector);
        - undocumented function ("should not be called")
        - this function is used to unlock the memory area
        - return   0 : successful   -1 : not successful

DWORD GetBaseAddress(WORD selector);
        - return the 32-bit-address of the selector , 0 on error

int SetBaseAddress(WORD selector ,DWORD 32bitaddress);
        - set the base address of the specified selector
        - return   0 : successful   -1 : not successful

int SetLimit(WORD sel,DWORD limit);
        - set the limit for the selector
        - if limit>1MB low 12 bits must be set
          then the granular bit will be set
        - return   0 : successful   -1 : not successful
        - to get the limit use the function lsl()

int SetAccess(WORD,BYTE accessbyte,BYTE 386extendedbyte);
        - set access rights for the selector
        - return   0 : successful   -1 : not successful
        - to get the access right use the function lar()

WORD CreatAlias(WORD codeselector);
        - this creates a data descriptor with the same address and limit as
          the code descriptor
        - return 0 if the function was not successful

int AllocSpecialLDT(WORD selector);
        - this allocates a specific LDT descriptor
        - return   0 : successful   -1 : not successful

int GetDescriptor(WORD selector,DESCRIPTOR *buffer);
        - this copies the 8 bytes descriptor table into the buffer
        - return   0 : successful   -1 : not successful

int SetDescriptor(WORD selector,DESCRIPTOR *buffer);
        - this function is used to set a descriptor
        - return   0 : successful   -1 : not successful

* Interrupt Services DPMI 0.9

int GetExceptionVektor(BYTE intnumber,WORD *selector,WORD *offset);
        - give the current protected mode exception handler
        - return   0 : successful   -1 : not successful

int SetExceptionVektor(BYTE intnumber,WORD selector,WORD offset);
        - set new protected mode exception handler
        - read DPMI-specification 0.9 for some details
        - return   0 : successful   -1 : not successful

int GetPMinterruptVector(BYTE,WORD *selector,WORD *offset);
        - get the current protected mode interrupt handler
        - return   0 : successful   -1 : not successful

int SetPMinterruptVektor(BYTE,WORD selector,WORD offset);
        - set new protected mode interrupt handler
        - return   0 : successful   -1 : not successful

* Memory management services DPMI 0.9

void getfreeinfo(FREEMEMINFO *);
        - get struct contains free mem info

void printfreeinfo(FREEMEMINFO *);
        - this prints a free memory info

DWORD GlobalAlloc(DWORD bytes,DWORD *memhandle);
        - allocate memory block , size = bytes
        - in Windows you get memory page granular. This means that allocation
          of 534 bytes allocate 4096 = 4 KB.
        - return linear address of allocated block , 0 on error
        - memhandle is used to free memory blocks

int GlobalFree(DWORD memhandle);
        - frees a memory block that was allocate though GlobalAlloc()
        - return   0 : successful   -1 : not successful

* Page locking services DPMI 0.9

int LockLinRegion(DWORD size,DWORD linaddress);
        - locks linear address range , size = region to lock
        - return   0 : successful   -1 : not successful

int UnlockLinRegion(DWORD size,DWORD linaddress);
        - unlock linear address range
        - return   0 : successful   -1 : not successful

* other int 2F

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 lsl(WORD selector);
        - load selector limit
        - uses 32-bit commands , only for >386
        - 286 must use lsl16()

WORD lsl16(WORD selector);
        - load selector limit on 286 machines

WORD lar(WORD selector);
        - load selector access rights

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

* protected mode pointer

void far * incfp(void far *);
        - increment descriptor to the next

void far * decfp(void far *);
        - decrement descriptor to the next

void printdescriptor(DESCRIPTOR);
        - print the 8 bytes from the descriptor table

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)

* high level memory functions in the DPMI-Enviroment:

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()
