|
@@ -1,685 +1,1525 @@
|
|
|
-%
|
|
|
-% $Id$
|
|
|
-% This file is part of the FPC documentation.
|
|
|
-% Copyright (C) 1997, by Michael Van Canneyt
|
|
|
-%
|
|
|
-% The FPC documentation is free text; you can redistribute it and/or
|
|
|
-% modify it under the terms of the GNU Library General Public License as
|
|
|
-% published by the Free Software Foundation; either version 2 of the
|
|
|
-% License, or (at your option) any later version.
|
|
|
-%
|
|
|
-% The FPC Documentation is distributed in the hope that it will be useful,
|
|
|
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-% Library General Public License for more details.
|
|
|
-%
|
|
|
-% You should have received a copy of the GNU Library General Public
|
|
|
-% License along with the FPC documentation; see the file COPYING.LIB. If not,
|
|
|
-% write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
-% Boston, MA 02111-1307, USA.
|
|
|
-%
|
|
|
-\chapter{The GO32 unit.}
|
|
|
-This chapter describes the \var{GO32} unit for Free Pascal under \dos.
|
|
|
-The unit was first written for \dos by Florian kl\"ampfl.
|
|
|
+\chapter{The GO32 unit}
|
|
|
|
|
|
-This chapter is divided in three sections.
|
|
|
-\begin{itemize}
|
|
|
-\item The first section is an introduction to the GO32 unit.
|
|
|
-\item The second section lists the pre-defined constants, types and variables.
|
|
|
-\item The third section describes the functions which appear in the
|
|
|
-interface part of the GO32 unit.
|
|
|
-\end{itemize}
|
|
|
-Many function descriptions were made by Thomas Schatzl\footnote{
|
|
|
-E-Mail: \var{tom\_at\[email protected]}}, for which my thanks.
|
|
|
+This chapter of the documentation describe the GO32 unit for the Free Pascal
|
|
|
+compiler under DOS.
|
|
|
+
|
|
|
+This unit was first written for DOS by Florian Klämpfl.
|
|
|
+
|
|
|
+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.
|
|
|
+
|
|
|
+A lot of function descriptions were made by Thomas Schatzl, for which my
|
|
|
+thanks.
|
|
|
|
|
|
\section{Introduction}
|
|
|
|
|
|
-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.
|
|
|
+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}
|
|
|
|
|
|
-The \dos memory access is done by the \var{dosmem}
|
|
|
-functions and it's \textbf {strongly recommended } to use these functions.
|
|
|
-
|
|
|
-Example:
|
|
|
-\begin{verbatim}
|
|
|
-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;
|
|
|
-\end{verbatim}
|
|
|
+
|
|
|
+DOS memory is accessed by the predefined 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
|
|
|
+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 by the \var{inport} and \var{outport} functions.
|
|
|
-It's not necessary to use these functions but it makes life easier. \fpc
|
|
|
-\textbf {doesn't} support the \var{PORT} array, as under Turbo Pascal.
|
|
|
+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}
|
|
|
-There are some functions to access the segment registers, which makes
|
|
|
-your work easier.
|
|
|
+
|
|
|
+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}
|
|
|
|
|
|
-The \file{GO32} unit helps you to redirect interrupts. \var{SetIntVec}
|
|
|
-and \var{GetIntVec} don't work with \fpc. This is now done via the functions
|
|
|
-\var{set\_pm\_interrupt} and \var{get\_pm\_interrupt}.
|
|
|
-
|
|
|
-As an example we show how to redirect the interrupt \var{8h}.
|
|
|
-\begin{verbatim}
|
|
|
-{ 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 versions > 0.9.2 of FPCPascal }
|
|
|
-
|
|
|
- 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.
|
|
|
-\end{verbatim}
|
|
|
+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.
|
|
|
+
|
|
|
+\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}
|
|
|
+
|
|
|
+The following examples illustrate the use of software interrupts.
|
|
|
+
|
|
|
+\input{go32ex/softint.tex}
|
|
|
+
|
|
|
+\input{go32ex/rmpm_int.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
|
|
|
-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) }
|
|
|
-\end{verbatim}\label{co:rmmode}
|
|
|
-These constants can be returned by the \htmlref{get\_run\_mode}{GetRunMode} function.
|
|
|
-\subsection{Types}
|
|
|
+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;
|
|
|
+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}\label{ty:tmeminfo}
|
|
|
-Returns information about the memory allocation etc.
|
|
|
+\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.
|
|
|
|
|
|
-\textbf {NOTE:} The
|
|
|
-value of a field is zero if the value is unknown, it's only guaranteed,
|
|
|
-that \var{available\_memory} contains a valid value.
|
|
|
\begin{verbatim}
|
|
|
-type
|
|
|
+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}\label{ty:trealregs}
|
|
|
-This data structure is used to pass register values to an real mode
|
|
|
-interrupt handler.
|
|
|
-\begin{verbatim}
|
|
|
-type
|
|
|
- tseginfo = record
|
|
|
- offset : pointer;
|
|
|
- segment : word;
|
|
|
- end;
|
|
|
-\end{verbatim}\label{ty:tseginfo}
|
|
|
-This record is used to store a 48-bit pointer.
|
|
|
-\subsection{Variables.}
|
|
|
+ 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}
|
|
|
-var
|
|
|
- { puts count bytes from data to ptr(seg:ofs) of the DOS memory }
|
|
|
- dosmemput : procedure(seg : word;ofs : word;var data;count : longint);
|
|
|
+type tseginfo = record
|
|
|
+ offset : Pointer; segment : Word; end;
|
|
|
+\end{verbatim}
|
|
|
|
|
|
- { gets count bytes from ptr(seg:ofs) of the DOS memory to data }
|
|
|
- dosmemget : procedure(seg : word;ofs : word;var data;count : longint);
|
|
|
+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.
|
|
|
|
|
|
- { moves count bytes from ptr(sseg:sofs) to ptr(dseg:dofs) }
|
|
|
- dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint);
|
|
|
+See also: Selectors and descriptors, DOS memory access, Interrupt
|
|
|
+redirection
|
|
|
|
|
|
- { fills count bytes beginning with ptr(seg:ofs) with c }
|
|
|
- dosmemfillchar : procedure(seg,ofs : word;count : longint;c : char);
|
|
|
+\subsection{Variables.}
|
|
|
|
|
|
- { fills count words beginning with ptr(seg:ofs) with w }
|
|
|
- { this function is especially used by the CRT unit. }
|
|
|
- dosmemfillword : procedure(seg,ofs : word;count : longint;w : word);
|
|
|
+\begin{verbatim}
|
|
|
+var dosmemselector : Word;
|
|
|
\end{verbatim}
|
|
|
-These procedure variables give you access to the \dos memory in each mode
|
|
|
-of the \dos extender. It is strongly recommended to use these functions.
|
|
|
|
|
|
-The procedural variables are assigned by the startup code of the \var{GO32}
|
|
|
-unit to the correct procedures.
|
|
|
+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
|
|
|
- dosmemselector : word;
|
|
|
+ var int31error : Word;
|
|
|
\end{verbatim}
|
|
|
-Selector to the \dos memory. The whole \dos memory is mapped to a
|
|
|
-single segment. This function will only work in DPMI mode.
|
|
|
+
|
|
|
+This variable holds the result of a DPMI interrupt call. Any nonzero value
|
|
|
+must be treated as a critical failure.
|
|
|
|
|
|
\section{Functions and Procedures}
|
|
|
|
|
|
-\functionl{Allocate\_Ldt\_Descriptors}{AllocateLdtDescriptors}{(Count :
|
|
|
-word)}{word}
|
|
|
-{\var{Allocate\_ldt\_descriptors} allocates \var{Count} descriptors in the
|
|
|
-Local Descriptor Table (LDT).
|
|
|
-The descriptors allocated must be initialized by the application with
|
|
|
-other function calls.
|
|
|
+\functionl{allocate\_ldt\_descriptors}{allocateldtdescriptors}{(count : Word)}{Word}
|
|
|
+{
|
|
|
+Allocates a number of new descriptors.
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[count:\ ] specifies the number of requested unique descriptors
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return value: 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
|
|
|
+get\_next\_selector\_increment\_value() function.
|
|
|
+}
|
|
|
+{
|
|
|
+Check int31error variable
|
|
|
+}
|
|
|
+{
|
|
|
+\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}
|
|
|
+}
|
|
|
|
|
|
-The function returns a base descriptor with a limit and size value set to
|
|
|
-zero.
|
|
|
+\input{go32ex/sel_des.tex}
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works with real DPMI.
|
|
|
-\item 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
|
|
|
-\var{get\_next\_selector\_increment\_value.}
|
|
|
-\end{itemize}
|
|
|
-}{None.}{
|
|
|
-\seep{SetSegmentBaseAddress},
|
|
|
-\seep{SetSegmentLimit},
|
|
|
-\seef{GetLinearAddr},
|
|
|
-\seep{FreeLdtDescriptor},
|
|
|
-\seef{GetNextSelectorIncrementValue}
|
|
|
-}
|
|
|
-\begin{FPCList}
|
|
|
-\item[Example]
|
|
|
-\begin{verbatim}
|
|
|
+\functionl{free\_ldt\_descriptor}{freeldtdescriptor}{(des : Word)}{boolean}
|
|
|
+{
|
|
|
+Frees a previously allocated descriptor.
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[des:\ ] The descriptor to be freed
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return value: True if successful, false otherwise.
|
|
|
+
|
|
|
+Notes: After this call this selector is invalid and must not be used for any
|
|
|
+memory operations anymore. Each descriptor allocated with
|
|
|
+allocate\_ltd\_descriptor() must be freed individually with this function,
|
|
|
+even if it was previously allocated as a part of a contiguous array of
|
|
|
+descriptors.
|
|
|
+}{
|
|
|
+Check int31error variable}{
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
|
+\seefl{get\_next\_selector\_increment\_value}{getnextselectorincrementvalue}
|
|
|
+}
|
|
|
|
|
|
-uses go32;
|
|
|
-
|
|
|
-var VGAsel : word;
|
|
|
- r : trealregs;
|
|
|
-
|
|
|
-begin
|
|
|
- {...}
|
|
|
- r.realeax := $13; realintr($10, r);
|
|
|
- { set VGA mode }
|
|
|
- {...}
|
|
|
- VGAsel := allocate_ldt_descriptors(1);
|
|
|
- { allocate one descriptor to the VGA }
|
|
|
- set_segment_base_address(VGAsel,
|
|
|
- get_linear_addr($A0000,$FFFF));
|
|
|
-
|
|
|
- { set the base address to the VGA }
|
|
|
- set_segment_limit(VGAsel, $FFFF);
|
|
|
- { set the limit of the descriptor }
|
|
|
- {...}
|
|
|
- seg_fillchar(VGAsel, 100*320+100, 1, #15);
|
|
|
-
|
|
|
-
|
|
|
- { put a pixel at (6/100) in color 15 }
|
|
|
- readln;
|
|
|
- {...}
|
|
|
- free_ldt_descriptor(VGAsel);
|
|
|
-
|
|
|
- r.realeax := $3; realintr($10, r);
|
|
|
- { set textmode again }
|
|
|
- {...}
|
|
|
-end.
|
|
|
-\end{verbatim}
|
|
|
-\end{FPCList}
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
|
|
|
-\functionl{Create\_Code\_Segment\_Alias\_Descriptor}
|
|
|
-{CreateCodeSegmentAliasDescriptor}{(Des : Word)}{Word}
|
|
|
-{\var{Create\_Code\_Segment\_Alias\_Descriptor}
|
|
|
-Creates a new descriptor that has the same base and limit as the
|
|
|
-specified descriptor. In effect, the function returns a copy of the
|
|
|
-descriptor.
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works under real DPMI.
|
|
|
-\item 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.
|
|
|
-\end{itemize}
|
|
|
+\functionl{segment\_to\_descriptor}{segmenttodescriptor}{(seg : Word)}{Word}
|
|
|
+{
|
|
|
+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 allocate\_ldt\_descriptors() and change
|
|
|
+the base address as necessary.
|
|
|
+}{
|
|
|
+Check int31error variable.
|
|
|
+}
|
|
|
+{\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
|
+\seefl{free\_ldt\_descriptor}{freeldtdescriptor},
|
|
|
+\seefl{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
|
}
|
|
|
-{None.}
|
|
|
-{}
|
|
|
-\begin{FPCList}
|
|
|
-\item[Example]
|
|
|
-\begin{verbatim}
|
|
|
-uses go32;
|
|
|
|
|
|
-var copysel : word;
|
|
|
+For an example, see \seepl{seg\_fillchar}{segfillchar}.
|
|
|
|
|
|
-begin
|
|
|
- copysel := create_code_segment_alias_descriptor(get_ds);
|
|
|
- {...}
|
|
|
- free_ldt_descriptor(copysel);
|
|
|
-end.
|
|
|
-\end{verbatim}
|
|
|
-\end{FPCList}
|
|
|
+\Functionl{get\_next\_selector\_increment\_value}
|
|
|
+{getnextselectorincrementvalue}{Word}
|
|
|
+{
|
|
|
+Returns the selector increment value when allocating multiple subsequent
|
|
|
+descriptors via \seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors} .
|
|
|
+
|
|
|
+Parameters: none
|
|
|
|
|
|
+Return value: Selector increment value
|
|
|
|
|
|
-\procedure {Disable}{}{
|
|
|
-Clears the interrupt flag with CLD and disables the interrupts.
|
|
|
+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.
|
|
|
+}
|
|
|
+{
|
|
|
+Check int31error variable
|
|
|
+}
|
|
|
+{
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
|
+\seefl{free\_ldt\_descriptor}{freeldtdescriptor}
|
|
|
}
|
|
|
-{None.}{\seep{Enable}}
|
|
|
-\par {\bf NOTE: }This
|
|
|
-function works only in DPMI mode\par
|
|
|
|
|
|
-\procedure{Enable}{}{
|
|
|
-Sets the interrupt flag with STI and allows the processor to handle
|
|
|
-interrupts.
|
|
|
-}{None.}{\seep{Disable}}
|
|
|
+\functionl{get\_segment\_base\_address}{getsegmentbaseaddress}{
|
|
|
+(d : Word)}{Longint}{
|
|
|
+
|
|
|
+Returns the 32-bit linear base address from the descriptor table for the
|
|
|
+specified segment.
|
|
|
|
|
|
-\procedurel{Free\_Ldt\_Descriptor}{FreeLdtDescriptor}{(Sel : word)}
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[d:\ ] selector of the descriptor you want the base address
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return values: Linear base address of specified descriptor
|
|
|
+}
|
|
|
{
|
|
|
-\var{Free\_Ldt\_Descriptor} frees a previously allocated selector
|
|
|
-with descriptor \var{Sel}
|
|
|
+Check int31error variable.
|
|
|
+}
|
|
|
+{
|
|
|
+\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}
|
|
|
+}
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works with real DPMI.
|
|
|
-\item After this call this selector is invalid and must not be used for any
|
|
|
-memory operations anymore.
|
|
|
-\item Each descriptor allocated with \var{allocate\_ltd\_descriptor} must be
|
|
|
-freed
|
|
|
-individually with this function, even if it was previously allocated as
|
|
|
-a part of a contiguous array of descriptors.
|
|
|
-\end{itemize}
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
+
|
|
|
+\functionl{set\_segment\_base\_address}{setsegmentbaseaddress}
|
|
|
+{(d : Word; s : Longint)}{boolean}{
|
|
|
+
|
|
|
+Sets the 32-bit linear base address of a descriptor.
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[d:\ ] selector s - new base address of the descriptor
|
|
|
+\end{description}
|
|
|
+}
|
|
|
+{ Check int31error variable}
|
|
|
+{
|
|
|
+\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}
|
|
|
}
|
|
|
-{None.}
|
|
|
-{\seef{AllocateLdtDescriptors}}
|
|
|
|
|
|
-For an example, see \seef{AllocateLdtDescriptors}.
|
|
|
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
|
|
|
-\functionl{get\_cs}{GetCs}{}{word}{Returns the value of the CS
|
|
|
-register.}{None.}{\seef{GetDs},\seef{GetSs}}
|
|
|
+\functionl{get\_segment\_limit}{getsegmentlimit}{(d : Word)}{Longint}{
|
|
|
|
|
|
-\functionl{Get\_Descriptor\_Access\_right}{GetDescriptorAccesRight}{(Des: word)}{Longint}
|
|
|
-{\var{Get\_Descriptor\_Access\_right} gets the access rights of a
|
|
|
-descriptor \var{Des}.}
|
|
|
-{None.}{seef{SetDescriptorAccesRight}}
|
|
|
+Returns a descriptors segment limit
|
|
|
|
|
|
-\functionl{get\_ds}{GetDs}{}{word}{Returns the value of the DS
|
|
|
-register.}{None.}{\seef{GetCs},\seef{GetSs}}
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item [d:\ ] selector
|
|
|
+\end{description}
|
|
|
|
|
|
-\functionl{Get\_Linear\_Addr}{GetLinearAddr}{(PhysAddr : longint;Size : longint)}{longint}
|
|
|
-{\var{Get\_Linear\_Addr} converts a physical address \var{PhysAddr} into
|
|
|
-a linear address.
|
|
|
+Return value: Limit of the descriptor in bytes
|
|
|
+}{
|
|
|
+Returns zero if descriptor is invalid
|
|
|
+}
|
|
|
+{\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
|
+\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
|
+\seefl{set\_segment\_base\_address}{setsegmentbaseaddress},
|
|
|
+\seefl{get\_segment\_base\_address}{getsegmentbaseaddress},
|
|
|
+}
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works under real DPMI.
|
|
|
-\end{itemize}
|
|
|
-}{None.}{}
|
|
|
|
|
|
-For an example, see \seef{AllocateLdtDescriptors}.
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
|
|
|
-\procedurel{get\_meminfo}{GetMeminfo}{(var meminfo : tmeminfo)}{
|
|
|
-Returns the current state of memory allocation of the \dos extender.
|
|
|
+\functionl{set\_segment\_limit}{setsegmentlimit}{(d : Word; s : Longint)}{boolean}
|
|
|
+{
|
|
|
+Sets the limit of a descriptor.
|
|
|
|
|
|
-\textbf{NOTE: }This procedure has nothing to do with the Pascal function
|
|
|
-\var{maxavail} and \var{memavail}.}{None.}
|
|
|
-{\htmlref{tmeminfo}{ty:tmeminfo}}
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[d:\ ] selector s - new limit of the descriptor
|
|
|
+\end{description}
|
|
|
|
|
|
-\Functionl{Get\_Next\_Selector\_Increment\_Value}
|
|
|
-{GetNextSelectorIncrementValue}{word}
|
|
|
-{\var{Get\_Next\_Selector\_Increment\_Value} returns the selector increment
|
|
|
-value when allocating multiple subsequent descriptors
|
|
|
+Return values: Returns true if successful, else false.
|
|
|
|
|
|
-The function \var{allocate\_ldt\_descriptors} can allocate an array of
|
|
|
-contiguous descriptors, but only return the selector for the first. The
|
|
|
-value returned by this function can be used to calculate the selectors
|
|
|
-for subsequent descriptors in the array.
|
|
|
+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.
|
|
|
+}
|
|
|
+{
|
|
|
+Check int31error variable
|
|
|
+}
|
|
|
+{\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
|
+\seefl{set\_segment\_base\_address}{setsegmentbaseaddress},
|
|
|
+\seefl{get\_segment\_limit}{getsegmentlimit},
|
|
|
+\seefl{set\_segment\_limit}{setsegmentlimit}
|
|
|
+}
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works under real DPMI.
|
|
|
-\item the increment is always a power of 2.
|
|
|
-\end{itemize}
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
+
|
|
|
+\functionl{set\_descriptor\_access\_rights}{setdescriptoraccessrights}
|
|
|
+{(d : Word; w : Word)}{Longint}
|
|
|
+{
|
|
|
+Sets the access rights of a descriptor
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[d:\ ] selector w - new descriptor access rights
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return values: This function doesn't return anything useful.
|
|
|
}
|
|
|
-{None.}
|
|
|
-{\seef{AllocateLdtDescriptors}}
|
|
|
+{ Check int31error variable}
|
|
|
+{
|
|
|
+\seefl{get\_descriptor\_access\_rights}{getdescriptoraccessrights} }
|
|
|
|
|
|
+\functionl{get\_descriptor\_access\_rights}{getdescriptoraccessrights}
|
|
|
+{(d : Word)}{Longint}
|
|
|
+{
|
|
|
+Gets the access rights of a descriptor
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item{d} selector to descriptor
|
|
|
+\end{description}
|
|
|
+}{
|
|
|
+Return value: Access rights bit field
|
|
|
+}
|
|
|
+{Check int31error variable}{
|
|
|
+\seefl{set\_descriptor\_access\_rights}{setdescriptoraccessrights}}
|
|
|
|
|
|
-\procedurel{get\_pm\_interrupt}{GetPmInterrupt}{(vector : byte;var intaddr : tseginfo)}
|
|
|
+\functionl{create\_code\_segment\_alias\_descriptor}
|
|
|
+{createcodesegmentaliasdescriptor}{(seg : Word)}{Word}
|
|
|
{
|
|
|
-Returns the address of the current protected mode handler for the interrupt
|
|
|
-\var{vector}.}{None.}
|
|
|
-{\seep{SetPmInterrupt},\htmlref{tseginfo}{ty:tseginfo}}
|
|
|
+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: Data selector (alias)
|
|
|
|
|
|
-\functionl{get\_run\_mode}{GetRunMode}{}{word}{
|
|
|
-This function returns the mode which the extender is currently running.
|
|
|
-The function is mostly used to determine if DPMI is supported.
|
|
|
+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.
|
|
|
+}
|
|
|
+{ Check int31error variable}
|
|
|
+{
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors},
|
|
|
+\seefl{set\_segment\_limit}{setsegmentlimit},
|
|
|
+\seefl{set\_segment\_base\_address}{setsegmentbaseaddress} }
|
|
|
+
|
|
|
+\functionl{get\_meminfo}{getmeminfo}
|
|
|
+{(var meminfo : tmeminfo)}
|
|
|
+{boolean}{
|
|
|
+
|
|
|
+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
|
|
|
+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 -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.
|
|
|
+}
|
|
|
+{Check the int31error variable}
|
|
|
+{\seefl{get\_page\_size}{getpagesize} }
|
|
|
|
|
|
+\input{go32ex/meminfo.tex}
|
|
|
|
|
|
-}{None.}
|
|
|
-{\htmlref{rm}{co:rmmode}}
|
|
|
-Example :
|
|
|
-\begin{verbatim}
|
|
|
-uses
|
|
|
- go32;
|
|
|
-
|
|
|
-begin
|
|
|
- if get_run_mode=rm_dpmi then
|
|
|
- writeln('DPMI available')
|
|
|
- else
|
|
|
- writeln('No DPMI available');
|
|
|
-end.
|
|
|
-\end{verbatim}
|
|
|
+\functionl{allocate\_memory\_block}{allocatememoryblock}
|
|
|
+{(size:Longint)}{Longint}{
|
|
|
+
|
|
|
+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.
|
|
|
+}{ Check int31error variable}{
|
|
|
+\seefl{free\_memory\_block}{freememoryblock} }
|
|
|
+
|
|
|
+\functionl{free\_memory\_block}{freememoryblock}{(blockhandle :
|
|
|
+Longint)}{boolean}{
|
|
|
+
|
|
|
+Frees a previously allocated memory block
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item{blockhandle:} the handle to the memory area to free
|
|
|
+\end{description}
|
|
|
|
|
|
-\functionl{Get\_Segment\_Base\_Address}{GetSegmentBaseAddress}{(Sel: word)}{Longint}
|
|
|
+Return value: True if successful, 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.
|
|
|
+}
|
|
|
+{ Check int31error variable}
|
|
|
+{\seefl{allocate\_memory\_block}{allocatememoryblock} }
|
|
|
+
|
|
|
+%\functionl{request\_linear\_region}{requestlinearregion}
|
|
|
+%{(linearaddr, size : Longint; var blockhandle : Longint)}{boolean}
|
|
|
+%{
|
|
|
+%DOESN'T WORK AT ALL, AND WON'T IN THE FUTURE BECAUSE IT IS A DPMI 1.0
|
|
|
+%FUNCTION !!!!!!! (a good reason to skip this description)
|
|
|
+%
|
|
|
+%\functionl{map\_device\_in\_memory\_block}{mapdeviceinmemoryblock}{(handle, offset, pagecount, device :}
|
|
|
+%Longint) : boolean;
|
|
|
+%
|
|
|
+%!!!!!! DOESN'T WORK AT ALL, AND WON'T IN THE FUTURE BECAUSE IT IS A DPMI 1.0
|
|
|
+%!!!!!! FUNCTION !!!!!!! (a good reason to skip this description)
|
|
|
+
|
|
|
+\functionl{get\_linear\_addr}{getlinearaddr}
|
|
|
+{(phys\_addr : Longint; size : Longint)}{Longint}
|
|
|
{
|
|
|
-\var{Get\_Segment\_Base\_Address} returns the 32-bit linear base address
|
|
|
-from the LDT descriptor for the specified segment (\var{Sel}).
|
|
|
+Converts a physical address into a linear address.
|
|
|
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item [phys\_addr:\ ] - physical address of device size - size of region to
|
|
|
+map in bytes
|
|
|
+\end{description}
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works under real DPMI.
|
|
|
-\end{itemize}
|
|
|
+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.
|
|
|
}
|
|
|
-{None.}
|
|
|
-{\seep{SetSegmentBaseAddress}}
|
|
|
+{ Check int31error variable.}
|
|
|
+{
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}, \seefl{set\_segment\_limit}{setsegmentlimit},
|
|
|
+\seefl{set\_segment\_base\_address}{setsegmentbaseaddress} }
|
|
|
|
|
|
-\begin{FPCList}
|
|
|
-\item[Example:]
|
|
|
-\begin{verbatim}
|
|
|
-uses go32;
|
|
|
+\functionl{global\_dos\_alloc}{globaldosalloc}
|
|
|
+{(bytes : Longint)}{Longint}
|
|
|
+{
|
|
|
+Allocates a block of DOS real mode memory
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item [bytes:\ ] size of requested real mode memory
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return values: The high word of the returned value contains the selector to
|
|
|
+the allocated DOS memory block, the low 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.
|
|
|
+}{ Check int31error variable}
|
|
|
+{ \seefl{global\_dos\_free}{globaldosfree} }
|
|
|
+
|
|
|
+\input{go32ex/buffer.tex}
|
|
|
+
|
|
|
+\functionl{global\_dos\_free}{globaldosfree}{(selector :
|
|
|
+Word)}{boolean}{
|
|
|
+
|
|
|
+Frees a previously allocated DOS memory block
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[selector:\ ] selector to the DOS memory block
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return value: True if successful, 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} .
|
|
|
+}
|
|
|
+{ Check int31error variable}
|
|
|
+{\seefl{global\_dos\_alloc}{globaldosalloc} }
|
|
|
|
|
|
-begin
|
|
|
- Writeln(get_segment_base_address(get_ds));
|
|
|
-end.
|
|
|
-\end{verbatim}
|
|
|
-\end{FPCList}
|
|
|
+For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
|
|
|
|
-\functionl{get\_ss}{GetSs}{word}{Returns the value of the SS
|
|
|
-register.}{None.}{\seef{GetDs},\seef{GetCs}}
|
|
|
+\procedure{dosmemput}{(seg : Word; ofs : Word; var data; count : Longint)}{
|
|
|
|
|
|
-\functionl{Global\_Dos\_Alloc}{GlobalDosAlloc}{(Len : longint)}{longint}
|
|
|
-{\var{Global\_Dos\_Alloc}
|
|
|
-allocates a block of memory with length \var{Len} from the \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.
|
|
|
+Copies heap data to DOS real mode memory.
|
|
|
|
|
|
-The function returns both the real mode segment base address of
|
|
|
-the block and one or more descriptors that can be used by protected mode
|
|
|
-applications to access the block.
|
|
|
-The high word is the selector to this block, and the low word the
|
|
|
-\dos real mode segment. The offset of this block is always zero.
|
|
|
+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}
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Should only used for temporary buffers to get real mode information
|
|
|
-(e.g. interrupts that need a data structure in ES:DI), because every
|
|
|
-single block needs an unique selector.
|
|
|
-\end{itemize}
|
|
|
-}{None.}{\seep{GlobalDosFree}}
|
|
|
+Return value: none
|
|
|
|
|
|
-\begin{FPCList}
|
|
|
-\item[Example]
|
|
|
-\begin{verbatim}
|
|
|
-uses go32;
|
|
|
-
|
|
|
-procedure dosalloc (var selector : word;
|
|
|
- var segment : word;
|
|
|
- size : longint);
|
|
|
-var result : longint;
|
|
|
-
|
|
|
-begin
|
|
|
- result := global_dos_alloc(size);
|
|
|
- selector := word(result);
|
|
|
- segment := word(result shr 16);
|
|
|
-end;
|
|
|
-
|
|
|
-procedure dosfree(selector : word);
|
|
|
-begin
|
|
|
- global_dos_free(selector);
|
|
|
-end;
|
|
|
-
|
|
|
-var selector : word;
|
|
|
- segment : word;
|
|
|
- r : trealregs;
|
|
|
-
|
|
|
-begin
|
|
|
- fillchar(r, sizeof(r), 0);
|
|
|
- fillchar(any_record, sizeof(any_record), 0);
|
|
|
- dosalloc(selector, segment, sizeof(VBE_vgainfo));
|
|
|
- { allocate a real mode memory block }
|
|
|
- any_record.any_entry := 1000;
|
|
|
- dosmemput(segment, 0, any_record, sizeof(any_record));
|
|
|
- { copy the record to real mode memory }
|
|
|
- r.realeax := $0000;
|
|
|
- r.reales := segment; r.realedi := 0;
|
|
|
- realintr(IntNr, r); { do our interrupt }
|
|
|
- dosmemget(segment, 0, any_record, sizeof(any_record));
|
|
|
- { get the record from real mode memory }
|
|
|
- dosfree(selector); { free selector afterwards }
|
|
|
-end.
|
|
|
-\end{verbatim}
|
|
|
-\end{FPCList}
|
|
|
+Notes: No range checking is performed.
|
|
|
+}{ none }
|
|
|
+{\seep{dosmemget},
|
|
|
+\seep{dosmemmove},
|
|
|
+\seep{dosmemfillchar},
|
|
|
+\seep{dosmemfillword},
|
|
|
+\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{seg\_fillword}{segfillword} }
|
|
|
|
|
|
-\procedurel{Global\_Dos\_Free}{GlobalDosFree}{(Sel : word)}
|
|
|
-{var{Global\_Dos\_Free} frees a previously allocated \dos memory
|
|
|
-block, described by selector \var{Sel}.
|
|
|
+For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
|
+
|
|
|
+\procedure{dosmemget}{(seg : Word; ofs : Word; var data; count : Longint)}{
|
|
|
+
|
|
|
+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.
|
|
|
+}{ none }
|
|
|
+{
|
|
|
+\seep{dosmemput},
|
|
|
+\seep{dosmemmove},
|
|
|
+\seep{dosmemfillchar},
|
|
|
+\seep{dosmemfillword},
|
|
|
+\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{seg\_fillword}{segfillword} }
|
|
|
+
|
|
|
+For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
|
+
|
|
|
+\procedure{dosmemmove}{(sseg, sofs, dseg, dofs : Word; count : Longint)}
|
|
|
+{
|
|
|
+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}
|
|
|
+
|
|
|
+Return values: none
|
|
|
+
|
|
|
+Notes: No range check is performed in any way.
|
|
|
}
|
|
|
-{None.}
|
|
|
-{\seef{GlobalDosAlloc}}
|
|
|
+{ none}
|
|
|
+{
|
|
|
+\seep{dosmemput},
|
|
|
+\seep{dosmemget},
|
|
|
+\seep{dosmemfillchar},
|
|
|
+\seep{dosmemfillword}
|
|
|
+\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{seg\_fillword}{segfillword} }
|
|
|
+
|
|
|
+For an example, see \seepl{seg\_fillchar}{segfillchar}.
|
|
|
+
|
|
|
|
|
|
-For an example, see \seef{GlobalDosAlloc}.
|
|
|
+\procedure{dosmemfillchar}{(seg, ofs : Word; count : Longint; c : char)}{
|
|
|
|
|
|
-\function{inportb}{(port : word)}{byte}{Reads a byte from the given I/O
|
|
|
-port.}{None.}{\seep{outportb},\seef{inportw},\seef{inportl}}
|
|
|
+Sets a region of DOS memory to a specific byte value
|
|
|
|
|
|
-\function{inportl}{(port : word)}{longint}{Reads a longint from the given I/O
|
|
|
-port.}{None.}{\seep{outportl},\seef{inportw},\seef{inportb}}
|
|
|
+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}
|
|
|
|
|
|
-\function{inportw}{(port : word)}{word}{Reads a word from the given I/O
|
|
|
-port.}{None.}{\seep{outportw},\seef{inportb},\seef{inportl}}
|
|
|
+Return values: none
|
|
|
+
|
|
|
+Notes: No range check is performed.
|
|
|
+}
|
|
|
+{ none
|
|
|
+}{
|
|
|
+\seep{dosmemput},
|
|
|
+\seep{dosmemget},
|
|
|
+\seep{dosmemmove}{dosmemmove},
|
|
|
+\seepl{dosmemfillword}{dosmemfillword},
|
|
|
+\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{seg\_fillword}{segfillword} }
|
|
|
+
|
|
|
+\input{go32ex/textmess.tex}
|
|
|
+
|
|
|
+\procedure{dosmemfillword}{(seg,ofs : Word; count : Longint; w : Word)}
|
|
|
+{
|
|
|
+Sets a region of DOS memory to a specific word value
|
|
|
|
|
|
-\procedure{outportb}{(port : word;data : byte)}{Writes a byte to the
|
|
|
-specified port.}{None.}{\seef{inportb},\seep{outportw},\seep{outportl}}
|
|
|
+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}
|
|
|
|
|
|
-\procedure{outportl}{(port : word;data : longint)}{Writes a longint to the
|
|
|
-specified port.}{None.}{\seef{inportl},\seep{outportb},\seep{outportw}}
|
|
|
+Return values: none
|
|
|
|
|
|
-\procedure{outportw}{(port : word;data : word)}{Writes a word to the
|
|
|
-specified port.}{None.}{\seef{inportw},\seep{outportb},\seep{outportl}}
|
|
|
+Notes: No range check is performed.
|
|
|
+}
|
|
|
+{ none}{
|
|
|
+\seep{dosmemput},
|
|
|
+\seepl{dosmemget}{dosmemget},
|
|
|
+\seepl{dosmemmove}{dosmemmove},
|
|
|
+\seepl{dosmemfillchar}{dosmemfillchar},
|
|
|
+\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{seg\_fillword}{segfillword} }
|
|
|
+
|
|
|
+\functionl{get\_rm\_interrupt}{getrminterrupt}{(vector : byte; var intaddr :
|
|
|
+tseginfo)}{boolean}
|
|
|
+{
|
|
|
+Returns the contents of the current machine's real mode interrupt vector for
|
|
|
+the specified interrupt.
|
|
|
|
|
|
-\procedure{realintr}{(intnr : word;var regs : trealregs)}{
|
|
|
-\textbf {NOTE: }This procedure works only in DPMI mode.}
|
|
|
-{None.}{}
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[vector:\ ] interrupt vector number
|
|
|
+\item[intaddr:\ ] buffer to store real mode segment:offset address
|
|
|
+\end{description}
|
|
|
|
|
|
-\procedurel{seg\_fillchar}{SegFillChar}{(seg : word;ofs : longint;count : longint;c :
|
|
|
-char)}
|
|
|
-{Fills a memory area specified by a 48 bit pointer with the given number
|
|
|
-of chars.
|
|
|
+Return values: True if successful, false otherwise
|
|
|
|
|
|
-\textbf {NOTE:} Be careful using this function in non-DPMI mode.
|
|
|
-}{None.}{\seep{SegFillWord}, \seep{SegMove}}
|
|
|
+Notes: The returned address is a real mode segment address, which isn't
|
|
|
+valid in protected mode.
|
|
|
+}
|
|
|
+{ Check int31error variable
|
|
|
+}{
|
|
|
+\seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
|
+\seefl{set\_pm\_interrupt}{setpminterrupt},
|
|
|
+\seefl{get\_pm\_interrupt}{getpminterrupt} }
|
|
|
|
|
|
-\procedurel {seg\_fillword}{SegFillWord}{(seg : word;ofs : longint;count : longint;w :
|
|
|
-word)}{Fills a memory area specified by a 48 bit pointer with the given number
|
|
|
-of words.
|
|
|
+\functionl{set\_rm\_interrupt}{setrminterrupt}{(vector : byte; const intaddr :
|
|
|
+tseginfo)}{boolean}{
|
|
|
|
|
|
-\textbf {NOTE:} Be careful using this function in non-DPMI mode.
|
|
|
-}{None.}{\seep{SegFillChar}, \seep{SegMove}}
|
|
|
+Sets a real mode interrupt handler
|
|
|
|
|
|
-\functionl{Segment\_To\_Descriptor}{SegmentToDescriptor}{(Seg : Word)}{Word}
|
|
|
-{\var{Segment\_To\_Descriptor} Maps a real mode segment (paragraph) address
|
|
|
-(in \var{Seg}) onto an descriptor that can be used by a protected mode
|
|
|
-program to access the same memory.
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[vector:\ ] the interrupt vector number to set
|
|
|
+\item[intaddr:\ ] address of new interrupt vector
|
|
|
+\end{description}
|
|
|
|
|
|
-The function returns a selector to the DOS real-mode segment.
|
|
|
+Return values: True if successful, otherwise false.
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works with real DPMI.
|
|
|
-\item The descriptors limit will be set to 64KB.
|
|
|
-\item multiple calls to this function with the same segment address will
|
|
|
- return the same selector.
|
|
|
-\item Descriptors created by this function can never be modified or freed.
|
|
|
-For this reason this function shouldn't be used too often. Programs
|
|
|
-which need to examine various real mode addresses using the same
|
|
|
-selector should use the function \var{allocate\_ldt\_descriptors} and change
|
|
|
-the base address as necessary.
|
|
|
-\end{itemize}
|
|
|
+Notes: The address supplied MUST be a real mode segment address, not a
|
|
|
+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} .
|
|
|
}
|
|
|
-{None.}
|
|
|
-{}
|
|
|
-\begin{FPCList}
|
|
|
-\item[Example]
|
|
|
-\begin{verbatim}
|
|
|
-uses go32;
|
|
|
-
|
|
|
-var r : trealregs;
|
|
|
- VGAsel : word;
|
|
|
-
|
|
|
-begin
|
|
|
- r.realeax := $13; realintr($10, r);
|
|
|
- { set VGA mode 13h }
|
|
|
- VGASel := segment_to_descriptor($A000);
|
|
|
- {...}
|
|
|
- seg_fillchar(VGAsel, 100*320+6, 1, #15);
|
|
|
- { put a pixel at (6/100) in color 15 }
|
|
|
- readln;
|
|
|
- {...}
|
|
|
- r.realeax := $3; realintr($10, r);
|
|
|
-end.
|
|
|
-\end{verbatim}
|
|
|
-\end{FPCList}
|
|
|
-
|
|
|
-\procedurel{seg\_move}{SegMove}{(sseg : word;source : longint;dseg : word;dest : longint;count :
|
|
|
-longint)}
|
|
|
-{This procedure copies data when the source and destination are specified
|
|
|
-by 48 bit pointers. For example, this function is used by the DPMI version
|
|
|
-of \var{dosmemget} and \var{dosmemput}. }{The procedure checks only
|
|
|
-for overlapping if source selector equals the destination selector.
|
|
|
-Be also careful using this function in non-DPMI
|
|
|
-mode.}{\seep{SegFillWord},\seep{SegFillChar}}
|
|
|
-
|
|
|
-\functionl{Set\_Descriptor\_Access\_right}{SetDescriptorAccesRight}{(Des: word; W: word)}{Longint}
|
|
|
-{\var{Set\_Descriptor\_Access\_right} sets the access rights of a
|
|
|
-descriptor \var{Des}.}
|
|
|
-{None.}{seef{GetDescriptorAccesRight}}
|
|
|
-
|
|
|
-\procedurel{set\_pm\_interrupt}{SetPmInterrupt}{(vector : byte;const intaddr : tseginfo)}
|
|
|
-{Sets a new protected mode handler for the interrupt \var{vector}.}
|
|
|
-{None.}{\seep{GetPmInterrupt}, \htmlref{tseginfo}{ty:tseginfo}}
|
|
|
-
|
|
|
-\procedurel{Set\_Segment\_Base\_Address}{SetSegmentBaseAddress}
|
|
|
-{(var Des : word;Sel : longint)}
|
|
|
-{\var{{Set\_Segment\_Base\_Address}} sets the 32-bit linear base address
|
|
|
-of the descriptor \var{Des} for the specified selector \var{Sel}.
|
|
|
-
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item only works under real DPMI
|
|
|
-\end{itemize}
|
|
|
+{ Check int31error variable }
|
|
|
+{
|
|
|
+\seefl{get\_rm\_interrupt}{getrminterrupt},
|
|
|
+\seefl{set\_pm\_interrupt}{setpminterrupt}, \seefl{get\_pm\_interrupt}{getpminterrupt},
|
|
|
+\seefl{get\_rm\_callback}{getrmcallback} }
|
|
|
+
|
|
|
+\functionl{get\_pm\_interrupt}{getpminterrupt}
|
|
|
+{(vector : byte; var intaddr : tseginfo)}{boolean}{
|
|
|
+
|
|
|
+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: True if successful, false if not.
|
|
|
+
|
|
|
+Notes: The returned address is a protected mode selector:offset address.
|
|
|
}
|
|
|
-{None.}
|
|
|
-{ \seef{AllocateLdtDescriptors}, \seep{SetSegmentLimit}}
|
|
|
+{ Check int31error variable}
|
|
|
+{ \seefl{set\_pm\_interrupt}{setpminterrupt},
|
|
|
+\seefl{set\_rm\_interrupt}{setrminterrupt}, \seefl{get\_rm\_interrupt}{getrminterrupt} }
|
|
|
|
|
|
-For an example, see \seef{AllocateLdtDescriptors}.
|
|
|
+For an example, see \seefl{set\_pm\_interrupt}{setpminterrupt}.
|
|
|
|
|
|
-\procedurel{Set\_Segment\_Limit}{SetSegmentLimit}{(Des : word;Len : longint)}
|
|
|
-{\var{Set\_Segment\_Limit} sets the limit of the descriptor \var{Des}
|
|
|
-to the specified length \var{Len}
|
|
|
+\functionl{set\_pm\_interrupt}{setpminterrupt}
|
|
|
+{(vector : byte; const intaddr : tseginfo)}{boolean}{
|
|
|
|
|
|
-{\em Notes:}
|
|
|
-\begin{itemize}
|
|
|
-\item Only works under real DPMI.
|
|
|
-\item The new limit is the byte length of the segment-1.
|
|
|
-\item Segment limits bigger than or equal to 1MB must be page aligned, they
|
|
|
-must have the lower 12 bits set.
|
|
|
-\end{itemize}
|
|
|
+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: True if successful, false otherwise.
|
|
|
+
|
|
|
+Notes: The address supplied must be a valid selector:offset protected mode
|
|
|
+address.
|
|
|
+}
|
|
|
+{ Check int31error variable
|
|
|
+}{\seefl{get\_pm\_interrupt}{getpminterrupt},
|
|
|
+\seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
|
+\seefl{get\_rm\_interrupt}{getrminterrupt} }
|
|
|
+
|
|
|
+\input{go32ex/int_pm.tex}
|
|
|
+
|
|
|
+\Procedure{disable}{
|
|
|
+
|
|
|
+Disables all hardware interrupts by execution a CLI instruction.
|
|
|
+
|
|
|
+Parameters: none
|
|
|
+
|
|
|
+Return values: none
|
|
|
+}{none }
|
|
|
+{\seep{enable} }
|
|
|
+
|
|
|
+\Procedure{enable}{
|
|
|
+
|
|
|
+Enables all hardware interrupts by executing a STI instruction.
|
|
|
+
|
|
|
+Parameters: none
|
|
|
+
|
|
|
+Return values: none
|
|
|
+}{None}
|
|
|
+{ \seep{disable} }
|
|
|
+
|
|
|
+
|
|
|
+\function{realintr}{(intnr: Word; var regs : trealregs)}{ boolean}{
|
|
|
+
|
|
|
+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. True if successful, 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.
|
|
|
+}
|
|
|
+{ Check int31error variable
|
|
|
+}{}
|
|
|
+
|
|
|
+%For an example, see \seefl{global\_dos\_alloc}{globaldosalloc}.
|
|
|
+\input{go32ex/flags.tex}
|
|
|
+
|
|
|
+\functionl{get\_rm\_callback}{getrmcallback}
|
|
|
+{(pm\_func : pointer; const reg : trealregs; var rmcb: tseginfo)}{boolean}
|
|
|
+{
|
|
|
+Returns a unique real mode 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: True if successful, otherwise 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.
|
|
|
+}{Check int31error variable}
|
|
|
+{\seefl{free\_rm\_callback}{freermcallback} }
|
|
|
+
|
|
|
+\input{go32ex/callback.tex}
|
|
|
+
|
|
|
+\functionl{free\_rm\_callback}{freermcallback}{(var intaddr : tseginfo)}{boolean}
|
|
|
+{
|
|
|
+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: True if successful, false if not
|
|
|
+}{ Check int31error variable }
|
|
|
+{
|
|
|
+\seefl{set\_rm\_interrupt}{setrminterrupt},
|
|
|
+\seefl{get\_rm\_callback}{getrmcallback}
|
|
|
+}
|
|
|
+
|
|
|
+For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
|
+
|
|
|
+
|
|
|
+\functionl{lock\_linear\_region}{locklinearregion}{(linearaddr, size : Longint)}{boolean}
|
|
|
+{
|
|
|
+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: True if successful, False otherwise
|
|
|
+}
|
|
|
+{ Check int31error variable}
|
|
|
+{
|
|
|
+\seefl{lock\_data}{lockdata},
|
|
|
+\seefl{lock\_code}{lockcode},
|
|
|
+\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
|
+\seefl{unlock\_data}{unlockdata},
|
|
|
+\seefl{unlock\_code}{unlockcode}}
|
|
|
+
|
|
|
+\functionl{lock\_data}{lockdata}{(var data; size : Longint)}{boolean}
|
|
|
+{
|
|
|
+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: True if successful, false otherwise
|
|
|
+}
|
|
|
+{ Check int31error variable}{
|
|
|
+\seefl{lock\_linear\_region}{locklinearregion},
|
|
|
+\seefl{lock\_code}{lockcode},
|
|
|
+\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
|
+\seefl{unlock\_data}{unlockdata},
|
|
|
+\seefl{unlock\_code}{unlockcode} }
|
|
|
+
|
|
|
+For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
|
+
|
|
|
+\functionl{lock\_code}{lockcode}{(functionaddr : pointer; size : Longint)}
|
|
|
+{boolean}{
|
|
|
+
|
|
|
+Locks a memory range which is in the code segment selector.
|
|
|
+
|
|
|
+Parameters:
|
|
|
+\begin{description}
|
|
|
+\item[functionaddr:\ ] address of the function to be lockd
|
|
|
+\item[size:\ ] size in bytes to be locked
|
|
|
+\end{description}
|
|
|
+
|
|
|
+Return values: True if successful, false otherwise
|
|
|
+}{Check int31error variable}{
|
|
|
+\seefl{lock\_linear\_region}{locklinearregion},
|
|
|
+\seefl{lock\_data}{lockdata},
|
|
|
+\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
|
+\seefl{unlock\_data}{unlockdata},
|
|
|
+\seefl{unlock\_code}{unlockcode} }
|
|
|
+
|
|
|
+For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
|
+
|
|
|
+\functionl{unlock\_linear\_region}{unlocklinearregion}
|
|
|
+{(linearaddr, size : Longint)}{boolean}{
|
|
|
+
|
|
|
+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: True if successful, false otherwise
|
|
|
+}
|
|
|
+{ Check int31error variable}{
|
|
|
+\seefl{unlock\_data}{unlockdata},
|
|
|
+\seefl{unlock\_code}{unlockcode},
|
|
|
+\seefl{lock\_linear\_region}{locklinearregion},
|
|
|
+\seefl{lock\_data}{lockdata},
|
|
|
+\seefl{lock\_code}{lockcode}}
|
|
|
+
|
|
|
+
|
|
|
+\functionl{unlock\_data}{unlockdata}{(var data; size : Longint)}{boolean}
|
|
|
+{
|
|
|
+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: True if successful, false otherwise
|
|
|
+}
|
|
|
+{ Check int31error variable
|
|
|
+}{
|
|
|
+\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
|
+\seefl{unlock\_code}{unlockcode},
|
|
|
+\seefl{lock\_linear\_region}{locklinearregion},
|
|
|
+\seefl{lock\_data}{lockdata},
|
|
|
+\seefl{lock\_code}{lockcode} }
|
|
|
+
|
|
|
+For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
|
+
|
|
|
+\functionl{unlock\_code}{unlockcode}
|
|
|
+{(functionaddr : pointer; size : Longint)}{boolean}
|
|
|
+{
|
|
|
+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: True if successful, false otherwise
|
|
|
+}
|
|
|
+{ Check int31error variable }
|
|
|
+{\seefl{unlock\_linear\_region}{unlocklinearregion},
|
|
|
+ \seefl{unlock\_data}{unlockdata},
|
|
|
+\seefl{lock\_linear\_region}{locklinearregion},
|
|
|
+\seefl{lock\_data}{lockdata},
|
|
|
+\seefl{lock\_code}{lockcode} }
|
|
|
+
|
|
|
+For an example, see \seefl{get\_rm\_callback}{getrmcallback}.
|
|
|
+
|
|
|
+
|
|
|
+\Functionl{get\_page\_size}{getpagesize}{ Longint}
|
|
|
+{
|
|
|
+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.
|
|
|
}
|
|
|
-{None}
|
|
|
-{ \seep{SetSegmentBaseAddress}, \seef{AllocateLdtDescriptors}}
|
|
|
+{ Check int31error variable
|
|
|
+}{ \seefl{get\_meminfo}{getmeminfo} }
|
|
|
+
|
|
|
+For an example, see \seefl{get\_meminfo}{getmeminfo}.
|
|
|
+
|
|
|
+\procedurel{seg\_move}{segmove}{(sseg : Word; source : Longint; dseg : Word; dest :
|
|
|
+Longint; count : Longint)}{
|
|
|
+
|
|
|
+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.
|
|
|
+}
|
|
|
+{ none}
|
|
|
+{
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{seg\_fillword}{segfillword},
|
|
|
+\seepl{dosmemfillchar}{dosmemfillchar},
|
|
|
+\seepl{dosmemfillword}{dosmemfillword},
|
|
|
+\seepl{dosmemget}{dosmemget},
|
|
|
+\seepl{dosmemput}{dosmemput},
|
|
|
+\seepl{dosmemmove}{dosmemmove} }
|
|
|
+
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
+
|
|
|
+
|
|
|
+\procedurel{seg\_fillchar}{segfillchar}
|
|
|
+{(seg : Word; ofs : Longint; count : Longint; c : char)}{
|
|
|
+
|
|
|
+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.
|
|
|
+}{ none }
|
|
|
+{\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillword}{segfillword},
|
|
|
+\seepl{dosmemfillchar}{dosmemfillchar},
|
|
|
+\seepl{dosmemfillword}{dosmemfillword},
|
|
|
+\seepl{dosmemget}{dosmemget},
|
|
|
+\seepl{dosmemput}{dosmemput},
|
|
|
+\seepl{dosmemmove}{dosmemmove} }
|
|
|
+
|
|
|
+\input{go32ex/vgasel.tex}
|
|
|
+
|
|
|
+\procedurel{seg\_fillword}{segfillword}
|
|
|
+{(seg : Word; ofs : Longint; count : Longint; w :Word)}
|
|
|
+{
|
|
|
+Sets a memory area to a specific value.
|
|
|
|
|
|
-For an example, see \seef{AllocateLdtDescriptors}.
|
|
|
+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.
|
|
|
+}{none }
|
|
|
+{
|
|
|
+\seepl{seg\_move}{segmove},
|
|
|
+\seepl{seg\_fillchar}{segfillchar},
|
|
|
+\seepl{dosmemfillchar}{dosmemfillchar},
|
|
|
+\seepl{dosmemfillword}{dosmemfillword},
|
|
|
+\seepl{dosmemget}{dosmemget},
|
|
|
+\seepl{dosmemput}{dosmemput},
|
|
|
+\seepl{dosmemmove}{dosmemmove} }
|
|
|
+
|
|
|
+For an example, see
|
|
|
+\seefl{allocate\_ldt\_descriptors}{allocateldtdescriptors}.
|
|
|
+
|
|
|
+\Functionl{get\_cs}{getcs}{Word}{
|
|
|
+
|
|
|
+Returns the cs selector
|
|
|
+
|
|
|
+Parameters: none
|
|
|
+
|
|
|
+Return values: The content of the cs segment register
|
|
|
+}{none}{ \seefl{get\_ds}{getds}, \seefl{get\_ss}{getss}}
|
|
|
+
|
|
|
+For an example, see \seefl{set\_pm\_interrupt}{setpminterrupt}.
|
|
|
+
|
|
|
+\Functionl{get\_ds}{getds}{Word}
|
|
|
+{
|
|
|
+Returns the ds selector
|
|
|
+
|
|
|
+Parameters: none
|
|
|
+
|
|
|
+Return values: The content of the ds segment register
|
|
|
+}{ none}{ \seefl{get\_cs}{getcs}, \seefl{get\_ss}{getss}}
|
|
|
+
|
|
|
+\Functionl{get\_ss}{getss}{Word}{
|
|
|
+
|
|
|
+Returns the ss selector
|
|
|
+
|
|
|
+Parameters: none
|
|
|
+
|
|
|
+Return values: The content of the ss segment register
|
|
|
+}{ none}{ \seefl{get\_ds}{getds}, \seefl{get\_cs}{getcs}}
|
|
|
+
|
|
|
+\function{inportb}{(port : Word)}{byte}{
|
|
|
+
|
|
|
+Reads data 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
|
|
|
+
|
|
|
+Notes: The returned data is either be byte, word or longint sized, dependant
|
|
|
+of the function.
|
|
|
+}{ none }{\seep{outportb}, \seef{inportw}, \seef{inportl}}
|
|
|
+
|
|
|
+\function{inportw}{(port : Word)}{Word}{
|
|
|
+
|
|
|
+Reads data 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
|
|
|
+
|
|
|
+Notes: The returned data is either be byte, word or longint sized, dependant
|
|
|
+of the function.
|
|
|
+}{ none }{\seep{outportw} \seef{inportb}, \seef{inportl} }
|
|
|
+
|
|
|
+\function{inportl}{(port : Word)}{Longint}{
|
|
|
+
|
|
|
+Reads data 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
|
|
|
+
|
|
|
+Notes: The returned data is either be byte, word or longint sized, dependant
|
|
|
+of the function.
|
|
|
+}{none }{\seep{outportb}, \seef{inportb}, \seef{inportw} }
|
|
|
+
|
|
|
+\procedure{outportb}{(port : Word; data : byte)}{
|
|
|
+
|
|
|
+Sends 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
|
|
|
+}{ none }{\seef{inportb}, \seep{outportl}, \seep{outportw} }
|
|
|
+
|
|
|
+input{go32ex/outport.tex}
|
|
|
+
|
|
|
+\procedure{outportw}{(port : Word; data : Word)}{
|
|
|
+
|
|
|
+Sends 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
|
|
|
+}{ none }
|
|
|
+{\seef{inportw}, \seep{outportl}, \seep{outportb}}
|
|
|
+
|
|
|
+For an example, see \seep{outportb}.
|
|
|
+
|
|
|
+\procedure{outportl}{(port : Word; data : Longint)}{
|
|
|
+
|
|
|
+Sends 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
|
|
|
+
|
|
|
+}{none }{\seef{inportl}, \seep{outportw}, \seep{outportb}}
|
|
|
+
|
|
|
+For an example, see \seep{outportb}.
|
|
|
+
|
|
|
+\Functionl{get\_run\_mode}{getrunmode}{Word}{
|
|
|
+
|
|
|
+Returns the current mode your application runs with
|
|
|
+
|
|
|
+Return values: One of the constants used by this function
|
|
|
+}
|
|
|
+{none }
|
|
|
+{ constants returned by \seefl{get\_run\_mode}{getrunmode} }
|
|
|
|
|
|
+\input{go32ex/getrunmd.tex}
|