mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 07:19:28 +02:00
1613 lines
55 KiB
TeX
1613 lines
55 KiB
TeX
\chapter{The GO32 unit}
|
|
This chapter of the documentation describe the GO32 unit for the Free Pascal
|
|
compiler under \dos. It was donated by Thomas Schatzl
|
|
(tom\_at\_work@geocities.com), for which my thanks.
|
|
This unit was first written for \dos by Florian Klaempfl.
|
|
This chapter is divided in three sections. The first section is an
|
|
introduction to the GO32 unit. The second section lists the pre-defined
|
|
constants, types and variables. The third section describes the functions
|
|
which appear in the interface part of the GO32 unit.
|
|
\section{Introduction}
|
|
These docs contain information about the GO32 unit. Only the GO32V2 DPMI
|
|
mode is discussed by me here due to the fact that new applications shouldn't
|
|
be created with the older GO32V1 model. The former is much more advanced and
|
|
better. Additionally a lot of functions only work in DPMI mode anyway.
|
|
I hope the following explanations and introductions aren't too confusing at
|
|
all. If you notice an error or bug send it to the FPC mailing list or
|
|
directly to me.
|
|
So let's get started and happy and error free coding I wish you....
|
|
\hfill Thomas Schatzl, 25. August 1998
|
|
\section{Protected mode memory organization}
|
|
\subsection{What is DPMI}
|
|
The \dos Protected Mode Interface helps you with various aspects of protected
|
|
mode programming. These are roughly divided into descriptor handling, access
|
|
to \dos memory, management of interrupts and exceptions, calls to real mode
|
|
functions and other stuff. Additionally it automatically provides swapping
|
|
to disk for memory intensive applications.
|
|
A DPMI host (either a Windows \dos box or CWSDPMI.EXE) provides these
|
|
functions for your programs.
|
|
\subsection{Selectors and descriptors}
|
|
Descriptors are a bit like real mode segments; they describe (as the name
|
|
implies) a memory area in protected mode. A descriptor contains information
|
|
about segment length, its base address and the attributes of it (i.e. type,
|
|
access rights, ...).
|
|
These descriptors are stored internally in a so-called descriptor table,
|
|
which is basically an array of such descriptors.
|
|
Selectors are roughly an index into this table.
|
|
Because these 'segments' can be up to 4 GB in size, 32 bits aren't
|
|
sufficient anymore to describe a single memory location like in real mode.
|
|
48 bits are now needed to do this, a 32 bit address and a 16 bit sized
|
|
selector. The GO32 unit provides the tseginfo record to store such a
|
|
pointer.
|
|
But due to the fact that most of the time data is stored and accessed in the
|
|
\%ds selector, FPC assumes that all pointers point to a memory location of
|
|
this selector. So a single pointer is still only 32 bits in size. This value
|
|
represents the offset from the data segment base address to this memory
|
|
location.
|
|
\subsection{FPC specialities}
|
|
The \%ds and \%es selector MUST always contain the same value or some system
|
|
routines may crash when called. The \%fs selector is preloaded with the
|
|
DOSMEMSELECTOR variable at startup, and it MUST be restored after use,
|
|
because again FPC relys on this for some functions. Luckily we asm
|
|
programmers can still use the \%gs selector for our own purposes, but for how
|
|
long ?
|
|
See also:
|
|
% tseginfo, dosmemselector, \dos memory access,
|
|
\seefl{get\_cs}{getcs},
|
|
\seefl{get\_ds}{getds},
|
|
\seefl{gett\_ss}{getss},
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{free\_ldt\_descriptor}{freeldtdescriptor},
|
|
\seefl{segment\_to\_descriptor}{segmenttodescriptor},
|
|
\seefl{get\_next\_selector\_increment\_value}{getnextselectorincrementvalue},
|
|
\seefl{get\_segment\_base\_address}{getsegmentbaseaddress},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{create\_code\_segment\_alias\_descriptor}{createcodesegmentaliasdescriptor}
|
|
\subsection{\dos memory access}
|
|
\dos memory is accessed by the predefined \var{dosmemselector} selector;
|
|
the GO32 unit additionally provides some functions to help you with standard tasks,
|
|
like copying memory from heap to \dos memory and the likes. Because of this
|
|
it is strongly recommened to use them, but you are still free to use the
|
|
provided standard memory accessing functions which use 48 bit pointers. The
|
|
third, but only thought for compatibility purposes, is using the
|
|
\var{mem[]}-arrays. These arrays map the whole 1 Mb \dos space. They shouldn't be
|
|
used within new programs.
|
|
To convert a segment:offset real mode address to a protected mode linear
|
|
address you have to multiply the segment by 16 and add its offset. This
|
|
linear address can be used in combination with the DOSMEMSELECTOR variable.
|
|
See also:
|
|
\seep{dosmemget},
|
|
\seepl{dosmemput}{dosmemput},
|
|
\seepl{dosmemmove}{dosmemmove},
|
|
\seepl{dosmemfillchar}{dosmemfillchar},
|
|
\seepl{dosmemfillword}{dosmemfillword},
|
|
mem[]-arrays,
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword}.
|
|
\subsection{I/O port access}
|
|
The I/O port access is done via the various \seef{inportb}, \seep{outportb}
|
|
functions
|
|
which are available. Additionally Free Pascal supports the Turbo Pascal
|
|
PORT[]-arrays but it is by no means recommened to use them, because they're
|
|
only for compatibility purposes.
|
|
See also: \seep{outportb}, \seef{inportb}, PORT[]-arrays
|
|
\subsection{Processor access}
|
|
These are some functions to access various segment registers (\%cs, \%ds, \%ss)
|
|
which makes your work a bit easier.
|
|
See also: \seefl{get\_cs}{getcs}, \seefl{get\_ds}{getds},
|
|
\seefl{get\_ss}{getss}
|
|
\subsection{Interrupt redirection}
|
|
Interrupts are program interruption requests, which in one or another way
|
|
get to the processor; there's a distinction between software and hardware
|
|
interrupts. The former are explicitely called by an 'int' instruction and
|
|
are a bit comparable to normal functions. Hardware interrupts come from
|
|
external devices like the keyboard or mouse. These functions are called
|
|
handlers.
|
|
\subsection{Handling interrupts with DPMI}
|
|
The interrupt functions are real-mode procedures; they normally can't be
|
|
called in protected mode without the risk of an protection fault. So the
|
|
DPMI host creates an interrupt descriptor table for the application.
|
|
Initially all software interrupts (except for int 31h, 2Fh and 21h function
|
|
4Ch) or external hardware interrupts are simply directed to a handler that
|
|
reflects the interrupt in real-mode, i.e. the DPMI host's default handlers
|
|
switch the CPU to real-mode, issue the interrupt and switch back to
|
|
protected mode. The contents of general registers and flags are passed to
|
|
the real mode handler and the modified registers and flags are returned to
|
|
the protected mode handler. Segment registers and stack pointer are not
|
|
passed between modes.
|
|
\subsection{Protected mode interrupts vs. Real mode interrupts}
|
|
As mentioned before, there's a distinction between real mode interrupts and
|
|
protected mode interrupts; the latter are protected mode programs, while the
|
|
former must be real mode programs. To call a protected mode interrupt
|
|
handler, an assembly 'int' call must be issued, while the other is called
|
|
via the realintr() or intr() function. Consequently, a real mode interrupt
|
|
then must either reside in \dos memory (<1MB) or the application must
|
|
allocate a real mode callback address via the get\_rm\_callback() function.
|
|
\subsection{Creating own interrupt handlers}
|
|
Interrupt redirection with FPC pascal is done via the set\_pm\_interrupt() for
|
|
protected mode interrupts or via the set\_rm\_interrupt() for real mode
|
|
interrupts.
|
|
\subsection{Disabling interrupts}
|
|
The GO32 unit provides the two procedures disable() and enable() to disable
|
|
and enable all interrupts.
|
|
\subsection{Hardware interrupts}
|
|
Hardware interrupts are generated by hardware devices when something unusual
|
|
happens; this could be a keypress or a mouse move or any other action. This
|
|
is done to minimize CPU time, else the CPU would have to check all installed
|
|
hardware for data in a big loop (this method is called 'polling') and this
|
|
would take much time.
|
|
A standard IBM-PC has two interrupt controllers, that are responsible for
|
|
these hardware interrupts: both allow up to 8 different interrupt sources
|
|
(IRQs, interrupt requests). The second controller is connected to the first
|
|
through IRQ 2 for compatibility reasons, e.g. if controller 1 gets an IRQ 2,
|
|
he hands the IRQ over to controller 2. Because of this up to 15 different
|
|
hardware interrupt sources can be handled.
|
|
IRQ 0 through IRQ 7 are mapped to interrupts 8h to Fh and the second
|
|
controller (IRQ 8 to 15) is mapped to interrupt 70h to 77h.
|
|
All of the code and data touched by these handlers MUST be locked (via the
|
|
various locking functions) to avoid page faults at interrupt time. Because
|
|
hardware interrupts are called (as in real mode) with interrupts disabled,
|
|
the handler has to enable them before it returns to normal program
|
|
execution. Additionally a hardware interrupt must send an EOI (end of
|
|
interrupt) command to the responsible controller; this is acomplished by
|
|
sending the value 20h to port 20h (for the first controller) or A0h (for the
|
|
second controller).
|
|
The following example shows how to redirect the keyboard interrupt.
|
|
\latex{\lstinputlisting{go32ex/keyclick.pp}}
|
|
\html{\input{go32ex/keyclick.tex}}
|
|
\subsection{Software interrupts}
|
|
Ordinarily, a handler installed with
|
|
\seefl{set\_pm\_interrupt}{setpminterrupt} only services software
|
|
interrupts that are executed in protected mode; real mode software
|
|
interrupts can be redirected by \seefl{set\_rm\_interrupt}{setrminterrupt}.
|
|
See also \seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
\seefl{get\_rm\_interrupt}{getrminterrupt},
|
|
\seefl{set\_pm\_interrupt}{setpminterrupt},
|
|
\seefl{get\_pm\_interrupt}{getpminterrupt},
|
|
\seefl{lock\_data}{lockdata},
|
|
\seefl{lock\_code}{lockcode},
|
|
\seep{enable},
|
|
\seep{disable},
|
|
\seepl{outportb}{outportb}
|
|
Executing software interrupts
|
|
Simply execute a realintr() call with the desired interrupt number and the
|
|
supplied register data structure.
|
|
But some of these interrupts require you to supply them a pointer to a
|
|
buffer where they can store data to or obtain data from in memory. These
|
|
interrupts are real mode functions and so they only can access the first Mb
|
|
of linear address space, not FPC's data segment.
|
|
For this reason FPC supplies a pre-initialized \dos memory location within
|
|
the GO32 unit. This buffer is internally used for \dos functions too and so
|
|
it's contents may change when calling other procedures. It's size can be
|
|
obtained with \seefl{tb\_size}{tbsize} and it's linear address via
|
|
\seefl{transfer\_buffer}{transferbuffer}.
|
|
Another way is to allocate a completely new \dos memory area via the
|
|
\seefl{global\_dos\_alloc}{globaldosalloc} function for your use and
|
|
supply its real mode address.
|
|
See also:
|
|
\seefl{tb\_size}{tbsize},
|
|
\seefl{transfer\_buffer}{transferbuffer}.
|
|
\seefl{global\_dos\_alloc}{globaldosalloc},
|
|
\seefl{global\_dos\_free}{globaldosfree},
|
|
\seef{realintr}
|
|
The following examples illustrate the use of software interrupts.
|
|
\latex{\lstinputlisting{go32ex/softint.pp}}
|
|
\html{\input{go32ex/softint.tex}}
|
|
\latex{\lstinputlisting{go32ex/rmpmint.pp}}
|
|
\html{\input{go32ex/rmpmint.tex}}
|
|
\subsection{Real mode callbacks}
|
|
The callback mechanism can be thought of as the converse of calling a real
|
|
mode procedure (i.e. interrupt), which allows your program to pass
|
|
information to a real mode program, or obtain services from it in a manner
|
|
that's transparent to the real mode program.
|
|
In order to make a real mode callback available, you must first get the real
|
|
mode callback address of your procedure and the selector and offset of a
|
|
register data structure. This real mode callback address (this is a
|
|
segment:offset address) can be passed to a real mode program via a software
|
|
interrupt, a \dos memory block or any other convenient mechanism.
|
|
When the real mode program calls the callback (via a far call), the DPMI
|
|
host saves the registers contents in the supplied register data structure,
|
|
switches into protected mode, and enters the callback routine with the
|
|
following conditions:
|
|
\begin{itemize}
|
|
\item interrupts disabled
|
|
\item \var{\%CS:\%EIP} = 48 bit pointer specified in the original call to
|
|
\seefl{get\_rm\_callback}{getrmcallback}
|
|
\item \var{\%DS:\%ESI} = 48 bit pointer to to real mode \var{SS:SP}
|
|
\item \var{\%ES:\%EDI} = 48 bit pointer of real mode register data
|
|
structure.
|
|
\item \var{\%SS:\%ESP} = locked protected mode stack
|
|
\item All other registers undefined
|
|
\end{itemize}
|
|
The callback procedure can then extract its parameters from the real mode
|
|
register data structure and/or copy parameters from the real mode stack to
|
|
the protected mode stack. Recall that the segment register fields of the
|
|
real mode register data structure contain segment or paragraph addresses
|
|
that are not valid in protected mode. Far pointers passed in the real mode
|
|
register data structure must be translated to virtual addresses before they
|
|
can be used with a protected mode program.
|
|
The callback procedure exits by executing an IRET with the address of the
|
|
real mode register data structure in \var{\%ES:\%EDI}, passing information back to
|
|
the real mode caller by modifying the contents of the real mode register
|
|
data structure and/or manipulating the contents of the real mode stack. The
|
|
callback procedure is responsible for setting the proper address for
|
|
resumption of real mode execution into the real mode register data
|
|
structure; typically, this is accomplished by extracting the return address
|
|
from the real mode stack and placing it into the \var{\%CS:\%EIP} fields of the real
|
|
mode register data structure. After the IRET, the DPMI host switches the CPU
|
|
back into real mode, loads ALL registers with the contents of the real mode
|
|
register data structure, and finally returns control to the real mode
|
|
program.
|
|
All variables and code touched by the callback procedure MUST be locked to
|
|
prevent page faults.
|
|
See also: \seefl{get\_rm\_callback}{getrmcallback},
|
|
\seefl{free\_rm\_callback}{freermcallback},
|
|
\seefl{lock\_code}{lockcode},
|
|
\seefl{lock\_data}{lockdata}
|
|
\section{Types, Variables and Constants}
|
|
\subsection{Constants}
|
|
\subsubsection{Constants returned by get\_run\_mode}
|
|
Tells you under what memory environment (e.g. memory manager) the program
|
|
currently runs.
|
|
\begin{verbatim}
|
|
rm_unknown = 0; { unknown }
|
|
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) }
|
|
\end{verbatim}
|
|
Note: GO32V2 {\em always} creates DPMI programs, so you need a suitable DPMI
|
|
host like \file{CWSDPMI.EXE} or a Windows \dos box. So you don't need to check it,
|
|
these constants are only useful in GO32V1 mode.
|
|
\subsubsection{Processor flags constants}
|
|
They are provided for a simple check with the flags identifier in the
|
|
trealregs type. To check a single flag, simply do an AND operation with the
|
|
flag you want to check. It's set if the result is the same as the flag
|
|
value.
|
|
\begin{verbatim}
|
|
const carryflag = $001;
|
|
parityflag = $004;
|
|
auxcarryflag = $010;
|
|
zeroflag = $040;
|
|
signflag = $080;
|
|
trapflag = $100;
|
|
interruptflag = $200;
|
|
directionflag = $400;
|
|
overflowflag = $800;
|
|
\end{verbatim}
|
|
\subsection{Predefined types}
|
|
\begin{verbatim}
|
|
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;
|
|
\end{verbatim}
|
|
Holds information about the memory allocation, etc.
|
|
\begin{tabular}{ll}
|
|
Record entry & Description \\ \hline
|
|
\var{available\_memory} & Largest available free block in bytes. \\
|
|
\var{available\_pages} & Maximum unlocked page allocation in pages \\
|
|
\var{available\_lockable\_pages} & Maximum locked page allocation in pages. \\
|
|
\var{linear\_space} & Linear address space size in pages. \\
|
|
\var{unlocked\_pages} & Total number of unlocked pages. \\
|
|
\var{available\_physical\_pages} & Total number of free pages.\\
|
|
\var{total\_physical\_pages} & Total number of physical pages. \\
|
|
\var{free\_linear\_space} & Free linear address space in pages.\\
|
|
\var{max\_pages\_in\_paging\_file} & Size of paging file/partition in
|
|
pages. \\
|
|
\end{tabular}
|
|
NOTE: The value of a field is -1 (0ffffffffh) if the value is unknown, it's
|
|
only guaranteed, that \var{available\_memory} contains a valid value.
|
|
The size of the pages can be determined by the get\_page\_size() function.
|
|
\begin{verbatim}
|
|
type
|
|
trealregs = record
|
|
case Integer of
|
|
1: { 32-bit }
|
|
(EDI, ESI, EBP, Res, EBX, EDX, ECX, EAX: Longint;
|
|
Flags, ES, DS, FS, GS, IP, CS, SP, SS: Word);
|
|
2: { 16-bit }
|
|
(DI, DI2, SI, SI2, BP, BP2, R1, R2: Word;
|
|
BX, BX2, DX, DX2, CX, CX2, AX, AX2: Word);
|
|
3: { 8-bit }
|
|
(stuff: array[1..4] of Longint;
|
|
BL, BH, BL2, BH2, DL, DH, DL2, DH2, CL,
|
|
CH, CL2, CH2, AL, AH, AL2, AH2: Byte);
|
|
4: { Compat }
|
|
(RealEDI, RealESI, RealEBP, RealRES, RealEBX,
|
|
RealEDX, RealECX, RealEAX: Longint;
|
|
RealFlags, RealES, RealDS, RealFS, RealGS,
|
|
RealIP, RealCS, RealSP, RealSS: Word);
|
|
end;
|
|
registers = trealregs;
|
|
\end{verbatim}
|
|
These two types contain the data structure to pass register values to a
|
|
interrupt handler or real mode callback.
|
|
\begin{verbatim}
|
|
type tseginfo = record
|
|
offset : Pointer; segment : Word; end;
|
|
\end{verbatim}
|
|
This record is used to store a full 48-bit pointer. This may be either a
|
|
protected mode selector:offset address or in real mode a segment:offset
|
|
address, depending on application.
|
|
See also: Selectors and descriptors, \dos memory access, Interrupt
|
|
redirection
|
|
\subsection{Variables.}
|
|
\begin{verbatim}
|
|
var dosmemselector : Word;
|
|
\end{verbatim}
|
|
Selector to the \dos memory. The whole \dos memory is automatically mapped to
|
|
this single descriptor at startup. This selector is the recommened way to
|
|
access \dos memory.
|
|
\begin{verbatim}
|
|
var int31error : Word;
|
|
\end{verbatim}
|
|
This variable holds the result of a DPMI interrupt call. Any nonzero value
|
|
must be treated as a critical failure.
|
|
\section{Functions and Procedures}
|
|
\begin{functionl}{allocate\_ldt\_descriptors}{allocateldtdescriptors}
|
|
\Declaration
|
|
Function allocate\_ldt\_descriptors (count : Word) : Word;
|
|
|
|
\Description
|
|
Allocates a number of new descriptors.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[count:\ ] specifies the number of requested unique descriptors.
|
|
\end{description}
|
|
Return value: The base selector.
|
|
Notes: The descriptors allocated must be initialized by the application with
|
|
other function calls. This function returns descriptors with a limit and
|
|
size value set to zero. If more than one descriptor was requested, the
|
|
function returns a base selector referencing the first of a contiguous array
|
|
of descriptors. The selector values for subsequent descriptors in the array
|
|
can be calculated by adding the value returned by the
|
|
\seefl{get\_next\_selector\_increment\_value}{getnextselectorincrementvalue}
|
|
function.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{free\_ldt\_descriptor}{freeldtdescriptor},
|
|
\seefl{get\_next\_selector\_increment\_value}{getnextselectorincrementvalue},
|
|
\seefl{segment\_to\_descriptor}{segmenttodescriptor},
|
|
\seefl{create\_code\_segment\_alias\_descriptor}{createcodesegmentaliasdescriptor},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
|
|
\end{functionl}
|
|
\latex{\lstinputlisting{go32ex/seldes.pp}}
|
|
\html{\input{go32ex/seldes.tex}}
|
|
\begin{functionl}{allocate\_memory\_block}{allocatememoryblock}
|
|
\Declaration
|
|
Function allocate\_memory\_block (size:Longint) : Longint;
|
|
|
|
\Description
|
|
Allocates a block of linear memory.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[size:\ ] Size of requested linear memory block in bytes.
|
|
\end{description}
|
|
Returned values: blockhandle - the memory handle to this memory block. Linear
|
|
address of the requested memory.
|
|
Notes: WARNING: According to my DPMI docs this function is not implemented
|
|
correctly. Normally you should also get a blockhandle to this block after
|
|
successful operation. This handle is used to free the memory block
|
|
afterwards or use this handle for other purposes. So this block can't be
|
|
deallocated and is henceforth unusuable !
|
|
This function doesn't allocate any descriptors for this block, it's the
|
|
applications resposibility to allocate and initialize for accessing this
|
|
memory.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{free\_memory\_block}{freememoryblock}
|
|
\end{functionl}
|
|
\begin{procedure}{copyfromdos}
|
|
\Declaration
|
|
Procedure copyfromdos (var addr; len : Longint);
|
|
|
|
\Description
|
|
|
|
Copies data from the pre-allocated \dos memory transfer buffer to the heap.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[addr:\ ] data to copy to.
|
|
\item[len:\ ] number of bytes to copy to heap.
|
|
\end{description}
|
|
Notes:
|
|
Can only be used in conjunction with the \dos memory transfer buffer.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{tb\_size}{tbsize}, \seefl{transfer\_buffer}{transferbuffer},
|
|
\seep{copytodos}
|
|
\end{procedure}
|
|
\begin{procedure}{copytodos}
|
|
\Declaration
|
|
Procedure copytodos (var addr; len : Longint);
|
|
|
|
\Description
|
|
Copies data from heap to the pre-allocated \dos memory buffer.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[addr:\ ] data to copy from.
|
|
\item[len:\ ] number of bytes to copy to \dos memory buffer.
|
|
\end{description}
|
|
Notes: This function fails if you try to copy more bytes than the transfer
|
|
buffer is in size. It can only be used in conjunction with the transfer
|
|
buffer.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{tb\_size}{tbsize}, \seefl{transfer\_buffer}{transferbuffer},
|
|
\seep{copyfromdos}
|
|
\end{procedure}
|
|
\begin{functionl}{create\_code\_segment\_alias\_descriptor}{createcodesegmentaliasdescriptor}
|
|
\Declaration
|
|
Function create\_code\_segment\_alias\_descriptor (seg : Word) : Word;
|
|
|
|
\Description
|
|
|
|
Creates a new descriptor that has the same base and limit as the specified
|
|
descriptor.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] selector.
|
|
\end{description}
|
|
Return values: The data selector (alias).
|
|
Notes: In effect, the function returns a copy of the descriptor. The
|
|
descriptor alias returned by this function will not track changes to the
|
|
original descriptor. In other words, if an alias is created with this
|
|
function, and the base or limit of the original segment is then changed, the
|
|
two descriptors will no longer map the same memory.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
\end{functionl}
|
|
\begin{procedure}{disable}
|
|
\Declaration
|
|
Procedure disable ;
|
|
|
|
\Description
|
|
Disables all hardware interrupts by execution a CLI instruction.
|
|
Parameters: None.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{enable}
|
|
\end{procedure}
|
|
\begin{procedure}{dosmemfillchar}
|
|
\Declaration
|
|
Procedure dosmemfillchar (seg, ofs : Word; count : Longint; c : char);
|
|
|
|
\Description
|
|
Sets a region of \dos memory to a specific byte value.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] real mode segment.
|
|
\item[ofs:\ ] real mode offset.
|
|
\item[count:\ ] number of bytes to set.
|
|
\item[c:\ ] value to set memory to.
|
|
\end{description}
|
|
Notes: No range check is performed.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
|
|
\seep{dosmemput},
|
|
\seep{dosmemget},
|
|
\seep{dosmemmove}{dosmemmove},
|
|
\seepl{dosmemfillword}{dosmemfillword},
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword}
|
|
\end{procedure}
|
|
\latex{\lstinputlisting{go32ex/textmess.pp}}
|
|
\html{\input{go32ex/textmess.tex}}
|
|
\begin{procedure}{dosmemfillword}
|
|
\Declaration
|
|
Procedure dosmemfillword (seg,ofs : Word; count : Longint; w : Word);
|
|
|
|
\Description
|
|
Sets a region of \dos memory to a specific word value.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] real mode segment.
|
|
\item[ofs:\ ] real mode offset.
|
|
\item[count:\ ] number of words to set.
|
|
\item[w:\ ] value to set memory to.
|
|
\end{description}
|
|
Notes: No range check is performed.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
|
|
\seep{dosmemput},
|
|
\seepl{dosmemget}{dosmemget},
|
|
\seepl{dosmemmove}{dosmemmove},
|
|
\seepl{dosmemfillchar}{dosmemfillchar},
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword}
|
|
\end{procedure}
|
|
\begin{procedure}{dosmemget}
|
|
\Declaration
|
|
Procedure dosmemget (seg : Word; ofs : Word; var data; count : Longint);
|
|
|
|
\Description
|
|
Copies data from the \dos memory onto the heap.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] source real mode segment.
|
|
\item[ofs:\ ] source real mode offset.
|
|
\item[data:\ ] destination.
|
|
\item[count:\ ] number of bytes to copy.
|
|
\end{description}
|
|
Notes: No range checking is performed.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{dosmemput},
|
|
\seep{dosmemmove},
|
|
\seep{dosmemfillchar},
|
|
\seep{dosmemfillword},
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword}
|
|
\end{procedure}
|
|
For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
\begin{procedure}{dosmemmove}
|
|
\Declaration
|
|
Procedure dosmemmove (sseg, sofs, dseg, dofs : Word; count : Longint);
|
|
|
|
\Description
|
|
Copies count bytes of data between two \dos real mode memory locations.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[sseg:\ ] source real mode segment.
|
|
\item[sofs:\ ] source real mode offset.
|
|
\item[dseg:\ ] destination real mode segment.
|
|
\item[dofs:\ ] destination real mode offset.
|
|
\item[count:\ ] number of bytes to copy.
|
|
\end{description}
|
|
Notes: No range check is performed in any way.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{dosmemput},
|
|
\seep{dosmemget},
|
|
\seep{dosmemfillchar},
|
|
\seep{dosmemfillword}
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword}
|
|
\end{procedure}
|
|
For an example, see \seepl{seg\_fillchar}{segfillchar}.
|
|
\begin{procedure}{dosmemput}
|
|
\Declaration
|
|
Procedure dosmemput (seg : Word; ofs : Word; var data; count : Longint);
|
|
|
|
\Description
|
|
Copies heap data to \dos real mode memory.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] destination real mode segment.
|
|
\item[ofs:\ ] destination real mode offset.
|
|
\item[data:\ ] source.
|
|
\item[count:\ ] number of bytes to copy.
|
|
\end{description}
|
|
Notes: No range checking is performed.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{dosmemget},
|
|
\seep{dosmemmove},
|
|
\seep{dosmemfillchar},
|
|
\seep{dosmemfillword},
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword}
|
|
\end{procedure}
|
|
For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
\begin{procedure}{enable}
|
|
\Declaration
|
|
Procedure enable ;
|
|
|
|
\Description
|
|
|
|
Enables all hardware interrupts by executing a STI instruction.
|
|
Parameters: None.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{disable}
|
|
\end{procedure}
|
|
\begin{functionl}{free\_ldt\_descriptor}{freeldtdescriptor}
|
|
\Declaration
|
|
Function free\_ldt\_descriptor (des : Word) : boolean;
|
|
|
|
\Description
|
|
Frees a previously allocated descriptor.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[des:\ ] The descriptor to be freed.
|
|
\end{description}
|
|
Return value: \var{True} if successful, \var{False} otherwise.
|
|
Notes: After this call this selector is invalid and must not be used for any
|
|
memory operations anymore. Each descriptor allocated with
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors} must be freed
|
|
individually with this function,
|
|
even if it was previously allocated as a part of a contiguous array of
|
|
descriptors.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{get\_next\_selector\_increment\_value}{getnextselectorincrementvalue}
|
|
|
|
\end{functionl}
|
|
For an example, see
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
\begin{functionl}{free\_memory\_block}{freememoryblock}
|
|
\Declaration
|
|
Function free\_memory\_block (blockhandle :
|
|
Longint) : boolean;
|
|
|
|
\Description
|
|
Frees a previously allocated memory block.
|
|
Parameters:
|
|
\begin{description}
|
|
\item{blockhandle:} the handle to the memory area to free.
|
|
\end{description}
|
|
Return value: \var{True} if successful, \var{false} otherwise.
|
|
Notes: Frees memory that was previously allocated with
|
|
\seefl{allocate\_memory\_block}{allocatememoryblock} .
|
|
This function doesn't free any descriptors mapped to this block,
|
|
it's the application's responsibility.
|
|
|
|
\Errors
|
|
Check \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{allocate\_memory\_block}{allocatememoryblock}
|
|
\end{functionl}
|
|
\begin{functionl}{free\_rm\_callback}{freermcallback}
|
|
\Declaration
|
|
Function free\_rm\_callback (var intaddr : tseginfo) : boolean;
|
|
|
|
\Description
|
|
|
|
Releases a real mode callback address that was previously allocated with the
|
|
\seefl{get\_rm\_callback}{getrmcallback} function.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[intaddr:\ ] real mode address buffer returned by
|
|
\seefl{get\_rm\_callback}{getrmcallback} .
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} if not
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
\seefl{get\_rm\_callback}{getrmcallback}
|
|
|
|
\end{functionl}
|
|
For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
\begin{functionl}{get\_cs}{getcs}
|
|
\Declaration
|
|
Function get\_cs : Word;
|
|
|
|
\Description
|
|
|
|
Returns the cs selector.
|
|
Parameters: None.
|
|
Return values: The content of the cs segment register.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seefl{get\_ds}{getds}, \seefl{get\_ss}{getss}
|
|
\end{functionl}
|
|
For an example, see \seefl{set\_pm\_interrupt}{setpminterrupt}.
|
|
\begin{functionl}{get\_descriptor\_access\_rights}{getdescriptoraccessrights}
|
|
\Declaration
|
|
Function get\_descriptor\_access\_rights (d : Word) : Longint;
|
|
|
|
\Description
|
|
Gets the access rights of a descriptor.
|
|
Parameters:
|
|
\begin{description}
|
|
\item{d} selector to descriptor.
|
|
\end{description}
|
|
Return value: Access rights bit field.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{set\_descriptor\_access\_rights}{setdescriptoraccessrights}
|
|
\end{functionl}
|
|
\begin{functionl}{get\_ds}{getds}
|
|
\Declaration
|
|
Function get\_ds : Word;
|
|
|
|
\Description
|
|
Returns the ds selector.
|
|
Parameters: None.
|
|
Return values: The content of the ds segment register.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seefl{get\_cs}{getcs}, \seefl{get\_ss}{getss}
|
|
\end{functionl}
|
|
\begin{functionl}{get\_linear\_addr}{getlinearaddr}
|
|
\Declaration
|
|
Function get\_linear\_addr (phys\_addr : Longint; size : Longint) : Longint;
|
|
|
|
\Description
|
|
Converts a physical address into a linear address.
|
|
Parameters:
|
|
\begin{description}
|
|
\item [phys\_addr:\ ] physical address of device.
|
|
\item [size:\ ] Size of region to map in bytes.
|
|
\end{description}
|
|
Return value: Linear address that can be used to access the physical memory.
|
|
Notes: It's the applications resposibility to allocate and set up a
|
|
descriptor for access to the memory. This function shouldn't be used to map
|
|
real mode addresses.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}, \seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
\end{functionl}
|
|
\begin{functionl}{get\_meminfo}{getmeminfo}
|
|
\Declaration
|
|
Function get\_meminfo (var meminfo : tmeminfo) : boolean;
|
|
|
|
\Description
|
|
Returns information about the amount of available physical memory, linear
|
|
address space, and disk space for page swapping.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[meminfo:\ ] buffer to fill memory information into.
|
|
\end{description}
|
|
Return values: Due to an implementation bug this function always returns
|
|
\var{False}, but it always succeeds.
|
|
Notes: Only the first field of the returned structure is guaranteed to
|
|
contain a valid value. Any fields that are not supported by the DPMI host
|
|
will be set by the host to \var{-1 (0FFFFFFFFH)} to indicate that the information
|
|
is not available. The size of the pages used by the DPMI host can be
|
|
obtained with the \seefl{get\_page\_size}{getpagesize} function.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{get\_page\_size}{getpagesize}
|
|
\end{functionl}
|
|
\latex{\lstinputlisting{go32ex/meminfo.pp}}
|
|
\html{\input{go32ex/meminfo.tex}}
|
|
\begin{functionl}{get\_next\_selector\_increment\_value}{getnextselectorincrementvalue}
|
|
\Declaration
|
|
Function get\_next\_selector\_increment\_value : Word;
|
|
|
|
\Description
|
|
Returns the selector increment value when allocating multiple subsequent
|
|
descriptors via \seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
Parameters: None.
|
|
Return value: Selector increment value.
|
|
Notes: Because \seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors} only returns the selector for the
|
|
first descriptor and so the value returned by this function can be used to
|
|
calculate the selectors for subsequent descriptors in the array.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{free\_ldt\_descriptor}{freeldtdescriptor}
|
|
\end{functionl}
|
|
\begin{functionl}{get\_page\_size}{getpagesize}
|
|
\Declaration
|
|
Function get\_page\_size : Longint;
|
|
|
|
\Description
|
|
Returns the size of a single memory page.
|
|
Return value: Size of a single page in bytes.
|
|
Notes: The returned size is typically 4096 bytes.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{get\_meminfo}{getmeminfo}
|
|
\end{functionl}
|
|
For an example, see \seefl{get\_meminfo}{getmeminfo}.
|
|
\begin{functionl}{get\_pm\_interrupt}{getpminterrupt}
|
|
\Declaration
|
|
Function get\_pm\_interrupt (vector : byte; var intaddr : tseginfo) : boolean;
|
|
|
|
\Description
|
|
Returns the address of a current protected mode interrupt handler.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[vector:\ ] interrupt handler number you want the address to.
|
|
\item[intaddr:\ ] buffer to store address.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} if not.
|
|
Notes: The returned address is a protected mode selector:offset address.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{set\_pm\_interrupt}{setpminterrupt},
|
|
\seefl{set\_rm\_interrupt}{setrminterrupt}, \seefl{get\_rm\_interrupt}{getrminterrupt}
|
|
\end{functionl}
|
|
For an example, see \seefl{set\_pm\_interrupt}{setpminterrupt}.
|
|
\begin{functionl}{get\_rm\_callback}{getrmcallback}
|
|
\Declaration
|
|
Function get\_rm\_callback (pm\_func : pointer; const reg : trealregs; var rmcb: tseginfo) : boolean;
|
|
|
|
\Description
|
|
|
|
Returns a unique real mode \var{segment:offset} address, known as a "real mode
|
|
callback," that will transfer control from real mode to a protected mode
|
|
procedure.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[pm\_func:\ ] pointer to the protected mode callback function.
|
|
\item[reg:\ ] supplied registers structure.
|
|
\item[rmcb:\ ] buffer to real mode address of callback function.
|
|
\end{description}
|
|
Return values: \var{True} if successful, otherwise \var{False}.
|
|
Notes: Callback addresses obtained with this function can be passed by a
|
|
protected mode program for example to an interrupt handler, device driver,
|
|
or TSR, so that the real mode program can call procedures within the
|
|
protected mode program or notify the protected mode program of an event. The
|
|
contents of the supplied regs structure is not valid after function call,
|
|
but only at the time of the actual callback.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{free\_rm\_callback}{freermcallback}
|
|
\end{functionl}
|
|
\latex{\lstinputlisting{go32ex/callback.pp}}
|
|
\html{\input{go32ex/callback.tex}}
|
|
\begin{functionl}{get\_rm\_interrupt}{getrminterrupt}
|
|
\Declaration
|
|
Function get\_rm\_interrupt (vector : byte; var intaddr :
|
|
tseginfo) : boolean;
|
|
|
|
\Description
|
|
Returns the contents of the current machine's real mode interrupt vector for
|
|
the specified interrupt.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[vector:\ ] interrupt vector number.
|
|
\item[intaddr:\ ] buffer to store real mode \var{segment:offset} address.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} otherwise.
|
|
Notes: The returned address is a real mode segment address, which isn't
|
|
valid in protected mode.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
\seefl{set\_pm\_interrupt}{setpminterrupt},
|
|
\seefl{get\_pm\_interrupt}{getpminterrupt}
|
|
\end{functionl}
|
|
\begin{functionl}{get\_run\_mode}{getrunmode}
|
|
\Declaration
|
|
Function get\_run\_mode : Word;
|
|
|
|
\Description
|
|
Returns the current mode your application runs with.
|
|
Return values: One of the constants used by this function.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
constants returned by \seefl{get\_run\_mode}{getrunmode}
|
|
\end{functionl}
|
|
\latex{\lstinputlisting{go32ex/getrunmd.pp}}
|
|
\html{\input{go32ex/getrunmd.tex}}
|
|
\begin{functionl}{get\_segment\_base\_address}{getsegmentbaseaddress}
|
|
\Declaration
|
|
Function get\_segment\_base\_address
|
|
(d : Word) : Longint;
|
|
|
|
\Description
|
|
Returns the 32-bit linear base address from the descriptor table for the
|
|
specified segment.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[d:\ ] selector of the descriptor you want the base address.
|
|
\end{description}
|
|
Return values: Linear base address of specified descriptor.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress},
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{get\_segment\_limit}{getsegmentlimit}
|
|
|
|
\end{functionl}
|
|
For an example, see
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
\begin{functionl}{get\_segment\_limit}{getsegmentlimit}
|
|
\Declaration
|
|
Function get\_segment\_limit (d : Word) : Longint;
|
|
|
|
\Description
|
|
Returns a descriptors segment limit.
|
|
Parameters:
|
|
\begin{description}
|
|
\item [d:\ ] selector.
|
|
\end{description}
|
|
Return value: Limit of the descriptor in bytes.
|
|
|
|
\Errors
|
|
Returns zero if descriptor is invalid.
|
|
\SeeAlso
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress},
|
|
\seefl{get\_segment\_base\_address}{getsegmentbaseaddress},
|
|
|
|
\end{functionl}
|
|
\begin{functionl}{get\_ss}{getss}
|
|
\Declaration
|
|
Function get\_ss : Word;
|
|
|
|
\Description
|
|
|
|
Returns the ss selector.
|
|
Parameters: None.
|
|
Return values: The content of the ss segment register.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seefl{get\_ds}{getds}, \seefl{get\_cs}{getcs}
|
|
\end{functionl}
|
|
\begin{functionl}{global\_dos\_alloc}{globaldosalloc}
|
|
\Declaration
|
|
Function global\_dos\_alloc (bytes : Longint) : Longint;
|
|
|
|
\Description
|
|
Allocates a block of \dos real mode memory.
|
|
Parameters:
|
|
\begin{description}
|
|
\item [bytes:\ ] size of requested real mode memory.
|
|
\end{description}
|
|
Return values: The low word of the returned value contains the selector to
|
|
the allocated \dos memory block, the high word the corresponding real mode
|
|
segment value. The offset value is always zero.
|
|
This function allocates memory from \dos memory pool, i.e. memory below the 1
|
|
MB boundary that is controlled by \dos. Such memory blocks are typically used
|
|
to exchange data with real mode programs, TSRs, or device drivers. The
|
|
function returns both the real mode segment base address of the block and
|
|
one descriptor that can be used by protected mode applications to access the
|
|
block. This function should only used for temporary buffers to get real mode
|
|
information (e.g. interrupts that need a data structure in ES:(E)DI),
|
|
because every single block needs an unique selector. The returned selector
|
|
should only be freed by a \seefl{global\_dos\_free}{globaldosfree} call.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{global\_dos\_free}{globaldosfree}
|
|
\end{functionl}
|
|
\latex{\lstinputlisting{go32ex/buffer.pp}}
|
|
\html{\input{go32ex/buffer.tex}}
|
|
\begin{functionl}{global\_dos\_free}{globaldosfree}
|
|
\Declaration
|
|
Function global\_dos\_free (selector :Word) : boolean;
|
|
|
|
\Description
|
|
Frees a previously allocated \dos memory block.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[selector:\ ] selector to the \dos memory block.
|
|
\end{description}
|
|
Return value: \var{True} if successful, \var{False} otherwise.
|
|
Notes: The descriptor allocated for the memory block is automatically freed
|
|
and hence invalid for further use. This function should only be used for
|
|
memory allocated by \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{global\_dos\_alloc}{globaldosalloc}
|
|
\end{functionl}
|
|
For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
\begin{function}{inportb}
|
|
\Declaration
|
|
Function inportb (port : Word) : byte;
|
|
|
|
\Description
|
|
Reads 1 byte from the selected I/O port.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[port:\ ] the I/O port number which is read.
|
|
\end{description}
|
|
Return values: Current I/O port value.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{outportb}, \seef{inportw}, \seef{inportl}
|
|
\end{function}
|
|
\begin{function}{inportl}
|
|
\Declaration
|
|
Function inportl (port : Word) : Longint;
|
|
|
|
\Description
|
|
|
|
Reads 1 longint from the selected I/O port.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[port:\ ] the I/O port number which is read.
|
|
\end{description}
|
|
Return values: Current I/O port value.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{outportb}, \seef{inportb}, \seef{inportw}
|
|
\end{function}
|
|
\begin{function}{inportw}
|
|
\Declaration
|
|
Function inportw (port : Word) : Word;
|
|
|
|
\Description
|
|
|
|
Reads 1 word from the selected I/O port.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[port:\ ] the I/O port number which is read.
|
|
\end{description}
|
|
Return values: Current I/O port value.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seep{outportw} \seef{inportb}, \seef{inportl}
|
|
\end{function}
|
|
\begin{functionl}{lock\_code}{lockcode}
|
|
\Declaration
|
|
Function lock\_code (functionaddr : pointer; size : Longint) : boolean;
|
|
|
|
\Description
|
|
Locks a memory range which is in the code segment selector.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[functionaddr:\ ] address of the function to be locked.
|
|
\item[size:\ ] size in bytes to be locked.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} otherwise.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{lock\_linear\_region}{locklinearregion},
|
|
\seefl{lock\_data}{lockdata},
|
|
\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
\seefl{unlock\_data}{unlockdata},
|
|
\seefl{unlock\_code}{unlockcode}
|
|
\end{functionl}
|
|
For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
\begin{functionl}{lock\_data}{lockdata}
|
|
\Declaration
|
|
Function lock\_data (var data; size : Longint) : boolean;
|
|
|
|
\Description
|
|
Locks a memory range which resides in the data segment selector.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[data:\ ] address of data to be locked.
|
|
\item[size:\ ] length of data to be locked.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} otherwise.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{lock\_linear\_region}{locklinearregion},
|
|
\seefl{lock\_code}{lockcode},
|
|
\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
\seefl{unlock\_data}{unlockdata},
|
|
\seefl{unlock\_code}{unlockcode}
|
|
\end{functionl}
|
|
For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
\begin{functionl}{lock\_linear\_region}{locklinearregion}
|
|
\Declaration
|
|
Function lock\_linear\_region (linearaddr, size : Longint) : boolean;
|
|
|
|
\Description
|
|
Locks a memory region to prevent swapping of it.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[linearaddr:\ ] the linear address of the memory are to be locked.
|
|
\item[size:\ ] size in bytes to be locked.
|
|
\end{description}
|
|
Return value: \var{True} if successful, False otherwise.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{lock\_data}{lockdata},
|
|
\seefl{lock\_code}{lockcode},
|
|
\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
\seefl{unlock\_data}{unlockdata},
|
|
\seefl{unlock\_code}{unlockcode}
|
|
\end{functionl}
|
|
\begin{procedure}{outportb}
|
|
\Declaration
|
|
Procedure outportb (port : Word; data : byte);
|
|
|
|
\Description
|
|
Sends 1 byte of data to the specified I/O port.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[port:\ ] the I/O port number to send data to.
|
|
\item[data:\ ] value sent to I/O port.
|
|
\end{description}
|
|
Return values: None.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seef{inportb}, \seep{outportl}, \seep{outportw}
|
|
\end{procedure}
|
|
\latex{\lstinputlisting{go32ex/outport.pp}}
|
|
\html{\input{go32ex/outport.tex}}
|
|
\begin{procedure}{outportl}
|
|
\Declaration
|
|
Procedure outportl (port : Word; data : Longint);
|
|
|
|
\Description
|
|
Sends 1 longint of data to the specified I/O port.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[port:\ ] the I/O port number to send data to.
|
|
\item[data:\ ] value sent to I/O port.
|
|
\end{description}
|
|
Return values: None.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seef{inportl}, \seep{outportw}, \seep{outportb}
|
|
\end{procedure}
|
|
For an example, see \seep{outportb}.
|
|
\begin{procedure}{outportw}
|
|
\Declaration
|
|
Procedure outportw (port : Word; data : Word);
|
|
|
|
\Description
|
|
Sends 1 word of data to the specified I/O port.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[port:\ ] the I/O port number to send data to.
|
|
\item[data:\ ] value sent to I/O port.
|
|
\end{description}
|
|
Return values: None.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seef{inportw}, \seep{outportl}, \seep{outportb}
|
|
\end{procedure}
|
|
For an example, see \seep{outportb}.
|
|
\begin{function}{realintr}
|
|
\Declaration
|
|
Function realintr (intnr: Word; var regs : trealregs) : boolean;
|
|
|
|
\Description
|
|
Simulates an interrupt in real mode.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[intnr:\ ] interrupt number to issue in real mode.
|
|
\item[regs:\ ] registers data structure.
|
|
\end{description}
|
|
Return values: The supplied registers data structure contains the values
|
|
that were returned by the real mode interrupt. \var{True} if successful, \var{False} if
|
|
not.
|
|
Notes: The function transfers control to the address specified by the real
|
|
mode interrupt vector of intnr. The real mode handler must return by
|
|
executing an IRET.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\end{function}
|
|
\latex{\lstinputlisting{go32ex/flags.pp}}
|
|
\html{\input{go32ex/flags.tex}}
|
|
\begin{procedurel}{seg\_fillchar}{segfillchar}
|
|
\Declaration
|
|
Procedure seg\_fillchar (seg : Word; ofs : Longint; count : Longint; c : char);
|
|
|
|
\Description
|
|
|
|
Sets a memory area to a specific value.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] selector to memory area.
|
|
\item[ofs:\ ] offset to memory.
|
|
\item[count:\ ] number of bytes to set.
|
|
\item[c:\ ] byte data which is set.
|
|
\end{description}
|
|
Return values: None.
|
|
Notes: No range check is done in any way.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillword}{segfillword},
|
|
\seepl{dosmemfillchar}{dosmemfillchar},
|
|
\seepl{dosmemfillword}{dosmemfillword},
|
|
\seepl{dosmemget}{dosmemget},
|
|
\seepl{dosmemput}{dosmemput},
|
|
\seepl{dosmemmove}{dosmemmove}
|
|
\end{procedurel}
|
|
\latex{\lstinputlisting{go32ex/vgasel.pp}}
|
|
\html{\input{go32ex/vgasel.tex}}
|
|
\begin{procedurel}{seg\_fillword}{segfillword}
|
|
\Declaration
|
|
Procedure seg\_fillword (seg : Word; ofs : Longint; count : Longint; w :Word);
|
|
|
|
\Description
|
|
|
|
Sets a memory area to a specific value.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[seg:\ ] selector to memory area.
|
|
\item[ofs:\ ] offset to memory.
|
|
\item[count:\ ] number of words to set.
|
|
\item[w:\ ] word data which is set.
|
|
\end{description}
|
|
Return values: None.
|
|
Notes: No range check is done in any way.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
|
|
\seepl{seg\_move}{segmove},
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{dosmemfillchar}{dosmemfillchar},
|
|
\seepl{dosmemfillword}{dosmemfillword},
|
|
\seepl{dosmemget}{dosmemget},
|
|
\seepl{dosmemput}{dosmemput},
|
|
\seepl{dosmemmove}{dosmemmove}
|
|
\end{procedurel}
|
|
For an example, see
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
\begin{functionl}{segment\_to\_descriptor}{segmenttodescriptor}
|
|
\Declaration
|
|
Function segment\_to\_descriptor (seg : Word) : Word;
|
|
|
|
\Description
|
|
|
|
Maps a real mode segment (paragraph) address onto an descriptor that can be
|
|
used by a protected mode program to access the same memory.
|
|
Parameters:
|
|
\begin{description}
|
|
\item [seg:\ ] the real mode segment you want the descriptor to.
|
|
\end{description}
|
|
Return values: Descriptor to real mode segment address.
|
|
Notes: The returned descriptors limit will be set to 64 kB. Multiple calls
|
|
to this function with the same segment address will return the same
|
|
selector. Descriptors created by this function can never be modified or
|
|
freed. Programs which need to examine various real mode addresses using the
|
|
same selector should use the function
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors} and change
|
|
the base address as necessary.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{free\_ldt\_descriptor}{freeldtdescriptor},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
|
|
\end{functionl}
|
|
For an example, see \seepl{seg\_fillchar}{segfillchar}.
|
|
\begin{procedurel}{seg\_move}{segmove}
|
|
\Declaration
|
|
Procedure seg\_move (sseg : Word; source : Longint; dseg : Word; dest :
|
|
Longint; count : Longint);
|
|
|
|
\Description
|
|
Copies data between two memory locations.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[sseg:\ ] source selector.
|
|
\item[source:\ ] source offset.
|
|
\item[dseg:\ ] destination selector.
|
|
\item[dest:\ ] destination offset.
|
|
\item[count:\ ] size in bytes to copy.
|
|
\end{description}
|
|
Return values: None.
|
|
Notes: Overlapping is only checked if the source selector is equal to the
|
|
destination selector. No range check is done.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
|
|
\seepl{seg\_fillchar}{segfillchar},
|
|
\seepl{seg\_fillword}{segfillword},
|
|
\seepl{dosmemfillchar}{dosmemfillchar},
|
|
\seepl{dosmemfillword}{dosmemfillword},
|
|
\seepl{dosmemget}{dosmemget},
|
|
\seepl{dosmemput}{dosmemput},
|
|
\seepl{dosmemmove}{dosmemmove}
|
|
\end{procedurel}
|
|
For an example, see
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
\begin{functionl}{set\_descriptor\_access\_rights}{setdescriptoraccessrights}
|
|
\Declaration
|
|
Function set\_descriptor\_access\_rights (d : Word; w : Word) : Longint;
|
|
|
|
\Description
|
|
|
|
Sets the access rights of a descriptor.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[d:\ ] selector.
|
|
\item[w:\ ] new descriptor access rights.
|
|
\end{description}
|
|
Return values: This function doesn't return anything useful.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{get\_descriptor\_access\_rights}{getdescriptoraccessrights}
|
|
\end{functionl}
|
|
\begin{functionl}{set\_pm\_interrupt}{setpminterrupt}
|
|
\Declaration
|
|
Function set\_pm\_interrupt (vector : byte; const intaddr : tseginfo) : boolean;
|
|
|
|
\Description
|
|
Sets the address of the protected mode handler for an interrupt.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[vector:\ ] number of protected mode interrupt to set.
|
|
\item[intaddr:\ ] selector:offset address to the interrupt vector.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} otherwise.
|
|
Notes: The address supplied must be a valid \var{selector:offset}
|
|
protected mode address.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{get\_pm\_interrupt}{getpminterrupt},
|
|
\seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
\seefl{get\_rm\_interrupt}{getrminterrupt}
|
|
\end{functionl}
|
|
\latex{\lstinputlisting{go32ex/intpm.pp}}
|
|
\html{\input{go32ex/intpm.tex}}
|
|
\begin{functionl}{set\_rm\_interrupt}{setrminterrupt}
|
|
\Declaration
|
|
Function set\_rm\_interrupt (vector : byte; const intaddr :
|
|
tseginfo) : boolean;
|
|
|
|
\Description
|
|
Sets a real mode interrupt handler.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[vector:\ ] the interrupt vector number to set.
|
|
\item[intaddr:\ ] address of new interrupt vector.
|
|
\end{description}
|
|
Return values: \var{True} if successful, otherwise \var{False}.
|
|
Notes: The address supplied MUST be a real mode segment address, not a
|
|
\var{selector:offset} address. So the interrupt handler must either reside in \dos
|
|
memory (below 1 Mb boundary) or the application must allocate a real mode
|
|
callback address with \seefl{get\_rm\_callback}{getrmcallback}.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{get\_rm\_interrupt}{getrminterrupt},
|
|
\seefl{set\_pm\_interrupt}{setpminterrupt}, \seefl{get\_pm\_interrupt}{getpminterrupt},
|
|
\seefl{get\_rm\_callback}{getrmcallback}
|
|
\end{functionl}
|
|
\begin{functionl}{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
\Declaration
|
|
Function set\_segment\_base\_address (d : Word; s : Longint) : boolean;
|
|
|
|
\Description
|
|
Sets the 32-bit linear base address of a descriptor.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[d:\ ] selector.
|
|
\item[s:\ ] new base address of the descriptor.
|
|
\end{description}
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{get\_segment\_base\_address}{getsegmentbaseaddress},
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
\seefl{get\_segment\_base\_address}{getsegmentbaseaddress},
|
|
\seefl{get\_segment\_limit}{getsegmentlimit}
|
|
|
|
\end{functionl}
|
|
\begin{functionl}{set\_segment\_limit}{setsegmentlimit}
|
|
\Declaration
|
|
Function set\_segment\_limit (d : Word; s : Longint) : boolean;
|
|
|
|
\Description
|
|
Sets the limit of a descriptor.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[d:\ ] selector.
|
|
\item[s:\ ] new limit of the descriptor.
|
|
\end{description}
|
|
Return values: Returns \var{True} if successful, else \var{False}.
|
|
Notes: The new limit specified must be the byte length of the segment - 1.
|
|
Segment limits bigger than or equal to 1MB must be page aligned, they must
|
|
have the lower 12 bits set.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
\seefl{set\_segment\_base\_address}{setsegmentbaseaddress},
|
|
\seefl{get\_segment\_limit}{getsegmentlimit},
|
|
\seefl{set\_segment\_limit}{setsegmentlimit}
|
|
|
|
\end{functionl}
|
|
For an example, see
|
|
\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
\begin{functionl}{tb\_size}{tbsize}
|
|
\Declaration
|
|
Function tb\_size : Longint;
|
|
|
|
\Description
|
|
Returns the size of the pre-allocated \dos memory buffer.
|
|
Parameters: None.
|
|
Return values: The size of the pre-allocated \dos memory buffer.
|
|
Notes:
|
|
This block always seems to be 16k in size, but don't rely on this.
|
|
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seefl{transfer\_buffer}{transferbuffer}, \seep{copyfromdos}
|
|
\seep{copytodos}
|
|
\end{functionl}
|
|
|
|
\begin{functionl}{transfer\_buffer}{transferbuffer}
|
|
\Declaration
|
|
Function transfer\_buffer : Longint;
|
|
\Description
|
|
\var{transfer\_buffer} returns the offset of the transfer buffer.
|
|
\Errors
|
|
None.
|
|
\SeeAlso
|
|
\seefl{tb\_size}{tbsize}
|
|
\end{functionl}
|
|
|
|
\begin{functionl}{unlock\_code}{unlockcode}
|
|
\Declaration
|
|
Function unlock\_code (functionaddr : pointer; size : Longint) : boolean;
|
|
|
|
\Description
|
|
Unlocks a memory range which resides in the code segment selector.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[functionaddr:\ ] address of function to be unlocked.
|
|
\item[size:\ ] size bytes to be unlocked.
|
|
\end{description}
|
|
Return value: \var{True} if successful, \var{False} otherwise.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
\seefl{unlock\_data}{unlockdata},
|
|
\seefl{lock\_linear\_region}{locklinearregion},
|
|
\seefl{lock\_data}{lockdata},
|
|
\seefl{lock\_code}{lockcode}
|
|
\end{functionl}
|
|
For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
\begin{functionl}{unlock\_data}{unlockdata}
|
|
\Declaration
|
|
Function unlock\_data (var data; size : Longint) : boolean;
|
|
|
|
\Description
|
|
Unlocks a memory range which resides in the data segment selector.
|
|
Paramters:
|
|
\begin{description}
|
|
\item[data:\ ] address of memory to be unlocked.
|
|
\item[size:\ ] size bytes to be unlocked.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} otherwise.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
\seefl{unlock\_code}{unlockcode},
|
|
\seefl{lock\_linear\_region}{locklinearregion},
|
|
\seefl{lock\_data}{lockdata},
|
|
\seefl{lock\_code}{lockcode}
|
|
\end{functionl}
|
|
For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
\begin{functionl}{unlock\_linear\_region}{unlocklinearregion}
|
|
\Declaration
|
|
Function unlock\_linear\_region (linearaddr, size : Longint) : boolean;
|
|
|
|
\Description
|
|
Unlocks a previously locked linear region range to allow it to be swapped
|
|
out again if needed.
|
|
Parameters:
|
|
\begin{description}
|
|
\item[linearaddr:\ ] linear address of the memory to be unlocked.
|
|
\item[size:\ ] size bytes to be unlocked.
|
|
\end{description}
|
|
Return values: \var{True} if successful, \var{False} otherwise.
|
|
|
|
\Errors
|
|
Check the \var{int31error} variable.
|
|
\SeeAlso
|
|
|
|
\seefl{unlock\_data}{unlockdata},
|
|
\seefl{unlock\_code}{unlockcode},
|
|
\seefl{lock\_linear\_region}{locklinearregion},
|
|
\seefl{lock\_data}{lockdata},
|
|
\seefl{lock\_code}{lockcode}
|
|
\end{functionl}
|
|
|