The GO32 Unit


The GO32 provides an interface to the DOS extender, DOS memory access, I/O ports and processor access. Some of this functions work with all modes of the extender, other only with DPMI.

DOS memory access

The DOS memory access is done by the dosmem* functions and it's strongly recommended to use this functions.

Example:

function shift_state : byte;
  
  begin
     { $40:$17 contains the current contents of the shift, alt and strg keys } 
     dosmemget($40,$17,shift_state,1);
  end;

I/O port access

The I/O port access is done by the inport* and outport* functions. It's not necessary to use this functions but it makes life easier. FPKPascal doesn't support the PORT array.

Processor access

There are some functions to access the segment registers, which makes your work easier, look for get_*.

Interrupt redirection

The GO32 unit supports you to redirect interrupts, the method via setintvec and getintvec doesn't work with FPKPascal. This is now done by the function set_pm_interrupt and get_pm_interrupt.

Example how to redirect the interrupt 8h.

{ the unit CRT _is_ needed because the program doesn't get an interrupt while DOS is active }
uses
   go32,crt;

var
   timer : longint;
   ds : word;
procedure s; { interrupt; comes with the next version of FPKPascal }
  begin
     asm
        { save used registers }
        pushl %eax
        pushw %ds
        { load ds }
        { prefix for cs }
        .byte 0x2e
        movw ALAB,%ax
        movw %ax,%ds
     end;
     inc(timer);
     asm
        { restore processor state }
        popw %ds
        popl %eax
        leave
        { call old interrupt }
        ljmp %cs:OLDINT
        iret
        { we need some data in the code segment, since only CS is set in the }
        { entry point of the procedure }
     ALAB:
        .word 0
        { old vector as 48 bit pointer (16:32) }
     OLDINT:
        .long 0
        .word 0
     end;
  end;

  var
     oldint,myint : tseginfo; 
     i : longint;

  begin 
     timer:=0;
     { save old interrupt }
     get_pm_interrupt(8,oldint); 
     ds:=get_ds; 
     asm 
        { copy some data to the code segment }
        movw _DS,%ax
        movw %ax,ALAB
        movl _OLDINT,%eax
        movl %eax,OLDINT
        movw _OLDINT+4,%ax
        movw %ax,OLDINT+4
     end;
     { new handler }
     myint.segment:=get_cs;
     myint.offset:=@s;
     { install the handler }
     set_pm_interrupt(8,myint);
     { do something }
     for i:=1 to 10000 do
       writeln(timer);
     { install the old handler }
     set_pm_interrupt(8,oldint);
  end.


(Currently) undocumented functions

{ this works only with real DPMI } 
function allocate_ldt_descriptors(count : word) : word;
procedure free_ldt_descriptor(d : word);
function segment_to_descriptor(seg : word) : word;
function get_next_selector_increment_value : word;
function get_segment_base_address(d : word) : longint;
procedure set_segment_base_address(d : word;s : longint);
procedure set_segment_limit(d : word;s : longint);
function create_code_segment_alias_descriptor(seg : word) : word;
function get_linear_addr(phys_addr : longint;size : longint) : longint;
{ is needed for functions which need a real mode buffer }
function global_dos_alloc(bytes : longint) : longint;
procedure global_dos_free(selector : word);


disable

procedure disable;

Clears the interrupt flag with CLD and disables the interrupts.

See also: enable


dosmem*

var 
   { puts count bytes from data to ptr(seg:ofs) of the DOS memory }
   dosmemput : procedure(seg : word;ofs : word;var data;count : longint);

   { gets count bytes from ptr(seg:ofs) of the DOS memory to data }
   dosmemget : procedure(seg : word;ofs : word;var data;count : longint);

   { moves count bytes from ptr(sseg:sofs) to ptr(dseg:dofs) }
   dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint);

   { fills count bytes beginning with ptr(seg:ofs) with c }
   dosmemfillchar : procedure(seg,ofs : word;count : longint;c : char);

   { fills count words beginning with ptr(seg:ofs) with w }
   { this function is esspecially by the CRT unit used    }
   dosmemfillword : procedure(seg,ofs : word;count : longint;w : word);

This procedure variables give you access to the DOS memory in each mode of the DOS extender, it's strongly recommended to use this functions.

The procedures variables are assigned by the startup code of the GO32 unit to the correct procedures.

uses
   go32;

var
   b : byte;

begin
   dosmemget($40,$49,b,1);
   writeln('The current screen mode is: ',b);
end.

See also: dosmemselector, seg_move, seg_fillchar, seg_fillword


dosmemselector

var
   dosmemselector : word;

Selector to the DOS memory, the whole DOS memory is mapped to a single segment.

uses
    go32;

var
   l : longint;

begin
   ...
   { Move the contents of l to the frame buffer } 
   seg_move(get_ds,longint(@l),dosmemselector,$b800*16+12);
end.

NOTE: This function works only in DPMI mode

See also: dosmem*, seg_move, seg_fillchar, seg_fillword


enable

procedure enable;

Sets the interrupt flag with STI and allows the processor to handle interrupts.

See also: disable


get_meminfo

procedure get_meminfo(var meminfo : tmeminfo);

Returns the current state of memory allocation of the DOS extender.

NOTE: This procedure has nothing to do with the pascal function maxavail and memavail.

See also: tmeminfo


get_pm_interrupt

procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);

Returns the address of the current protected mode handler for the interrupt vector.

See also: interrupt redirection, set_pm_interrupt, tseginfo


get_run_mode

function get_run_mode : word;

This function returns the mode which the extender is currently running (see rm_xxxx). The function is mostly used to determine if DPMI is supported.

uses
   go32;

begin
   if get_run_mode=rm_dpmi then
     writeln('DPMI available')
   else
     writeln('No DPMI available');
end.


get_xxxx

function get_cs : word;
function get_ds : word;
function get_ss : word;

This functions returns the value of the segment registers.


inport*

function inportb(port : word) : byte;
function inportw(port : word) : word;
function inportl(port : word) : longint;

Reads a byte, word or longint from the given I/O port.

See also: outport*


outport*

procedure outportb(port : word;data : byte);
procedure outportw(port : word;data : word);
procedure outportl(port : word;data : longint);

Writes a byte, word or longint from the given port.

See also: inport*


realintr

procedure realintr(intnr : word;var regs : trealregs);

NOTE: This procedure works only in DPMI mode


rm_xxxx

rm_unknown = 0; 
rm_raw = 1; { raw (without HIMEM) } 
rm_xms = 2; { XMS (for example with HIMEM, without EMM386) } 
rm_vcpi = 3; { VCPI (for example HIMEM and EMM386) } 
rm_dpmi = 4; { DPMI (for example DOS box or 386Max) }

This constants are returned by the get_run_mode which determines the mode which the DOS extender is running.


seg_fill*

procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);

Fills a memory area specified by a 48 bit pointer with the given number of chars or words.

NOTE: Be careful using this function in non DPMI mode.

See also: seg_move


seg_move

procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);

This procedure copies data where the source and destination are specified by 48 bit pointers. For example, this function is used by the DPMI version of dosmemget and dosmemput.

NOTE: The procedure checks only for overlapping if source selector=destination selector. Be also careful using this function in non DPMI mode.

See also: seg_fill*


set_pm_interrupt

procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);

Sets a new protected mode handler for the interrupt vector.

See also: interrupt redirection, get_pm_interrupt, tseginfo


tmeminfo

type 
   tmeminfo = record 
      available_memory : longint;
      available_pages : longint;
      available_lockable_pages : longint;
      linear_space : longint;
      unlocked_pages : longint;
      available_physical_pages : longint;
      total_physical_pages : longint;
      free_linear_space : longint;
      max_pages_in_paging_file : longint;
      reserved : array[0..2] of longint;
   end;

Returns informations about the memory allocation etc.

NOTE: The value of a field is zero if the value is unknown, it's only guaranted, that available_memory contains a valid value.

See also: get_meminfo


trealreags

type
   trealregs=record 
      realedi,realesi,realebp,realres, realebx,realedx,realecx,realeax : longint;
      realflags, reales,realds,realfs,realgs,realip,realcs,realsp,realss : word;
   end;

This data structure is used to pass register values to an real mode interrupt handler.

See also: realintr


tseginfo

type
   tseginfo = record 
      offset : pointer;
      segment : word;
   end;

This record is used to store a 48-bit pointer.

See also: get_pm_interrupt, set_pm_interrupt


back to FPKPascal homepage

klaempfl@haegar.cip.mw.uni-muenchen.de

Copyright (c) 1996 by Florian Klaempfl