439 lines
15 KiB
Plaintext
439 lines
15 KiB
Plaintext
program Ems_Test;
|
||
{ *************************************************************
|
||
* This program shows you how to use the basic functions of *
|
||
* the LIM Expanded Memory Specification. Since it does not *
|
||
* use any of the LIM EMS 4.0 function calls, you can also *
|
||
* use it on systems with EMS versions less than 4.0 *
|
||
************************************************************* }
|
||
|
||
{ Written by:
|
||
Peter Immarco.
|
||
Thought Dynamics
|
||
Manhattan Beach, CA
|
||
Compuserve ID# 73770,123
|
||
*** Public Domain ***
|
||
|
||
Used by permission of the author.
|
||
}
|
||
|
||
{ This program does the following:
|
||
+------------------------------------------------------------+
|
||
| * Makes sure the LIM Expanded Memory Manager (EMM) has |
|
||
| been installed in memory |
|
||
| * Displays the version number of the EMM present in memory |
|
||
| * Determines if there are enough pages (16k blocks) of |
|
||
| memory for our test program's usage. It then displays |
|
||
| the total number of EMS pages present in the system, |
|
||
| and how many are available for our usage |
|
||
| * Requests the desired number of pages from the EMM |
|
||
| * Maps a logical page onto one of the physical pages given |
|
||
| to us |
|
||
| * Displays the base address of our EMS memory page frame |
|
||
| * Performs a simple read/write test on the EMS memory given|
|
||
| to us |
|
||
| * Returns the EMS memory given to us back to the EMM, and |
|
||
| exits |
|
||
+------------------------------------------------------------|}
|
||
|
||
|
||
{ All the calls are structured to return the result or error
|
||
code of the Expanded Memory function performed as an integer.
|
||
If the error code is not zero, which means the call failed,
|
||
a simple error procedure is called and the program terminates.}
|
||
|
||
uses Crt, Dos;
|
||
|
||
Type
|
||
ST3 = string[3];
|
||
ST80 = string[80];
|
||
ST5 = string[5];
|
||
|
||
Const
|
||
EMM_INT = $67;
|
||
DOS_Int = $21;
|
||
GET_PAGE_FRAME = $41;
|
||
GET_UNALLOCATED_PAGE_COUNT= $42;
|
||
ALLOCATE_PAGES = $43;
|
||
MAP_PAGES = $44;
|
||
DEALLOCATE_PAGES = $45;
|
||
GET_VERSION = $46;
|
||
|
||
STATUS_OK = 0;
|
||
|
||
{ We'll say we need 1 EMS page for our application }
|
||
APPLICATION_PAGE_COUNT = 1;
|
||
|
||
Var
|
||
Regs: Registers;
|
||
Emm_Handle,
|
||
Page_Frame_Base_Address,
|
||
Pages_Needed,
|
||
Physical_Page,
|
||
Logical_Page,
|
||
Offset,
|
||
Error_Code,
|
||
Pages_EMS_Available,
|
||
Total_EMS_Pages,
|
||
Available_EMS_Pages: Word;
|
||
Version_Number,
|
||
Pages_Number_String: ST3;
|
||
Verify: Boolean;
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
{ The function Hex_String converts an Word into a four
|
||
character hexadecimal number(string) with leading zeroes. }
|
||
Function Hex_String(Number: Word): ST5;
|
||
Function Hex_Char(Number: Word): Char;
|
||
Begin
|
||
If Number<10 then
|
||
Hex_Char:=Char(Number+48)
|
||
else
|
||
Hex_Char:=Char(Number+55);
|
||
end; { Function Hex_Char }
|
||
|
||
Var
|
||
S: ST5;
|
||
Begin
|
||
S:='';
|
||
S:=Hex_Char( (Number shr 1) div 2048);
|
||
Number:=( ((Number shr 1) mod 2048) shl 1)+
|
||
(Number and 1) ;
|
||
S:=S+Hex_Char(Number div 256);
|
||
Number:=Number mod 256;
|
||
S:=S+Hex_Char(Number div 16);
|
||
Number:=Number mod 16;
|
||
S:=S+Hex_Char(Number);
|
||
Hex_String:=S+'h';
|
||
end; { Function Hex_String }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ The function Emm_Installed checks to see if the Expanded
|
||
Memory Manager (EMM) is loaded in memory. It does this by
|
||
looking for the string 'EMMXXXX0', which should be located
|
||
at 10 bytes from the beginning of the code segment pointed
|
||
to by the EMM interrupt, 67h }
|
||
Function Emm_Installed: Boolean;
|
||
Var
|
||
Emm_Device_Name : string[8];
|
||
Int_67_Device_Name : string[8];
|
||
Position : Word;
|
||
Regs : registers;
|
||
|
||
Begin
|
||
Int_67_Device_Name:='';
|
||
Emm_Device_Name :='EMMXXXX0';
|
||
with Regs do
|
||
Begin
|
||
{ Get the code segment pointed to by Interrupt 67h, the EMM
|
||
interrupt by using DOS call $35, 'get interrupt vector' }
|
||
AH:=$35;
|
||
AL:=EMM_INT;
|
||
Intr(DOS_int,Regs);
|
||
|
||
{ The ES pseudo-register contains the segment address pointed
|
||
to by Interrupt 67h }
|
||
{ Create an 8 character string from the 8 successive bytes
|
||
pointed to by ES:$0A (10 bytes from ES) }
|
||
For Position:=0 to 7 do
|
||
Int_67_Device_Name:=
|
||
Int_67_Device_Name+Chr(mem[ES:Position+$0A]);
|
||
Emm_Installed:=True;
|
||
{ Is it the EMM manager signature, 'EMMXXXX0'? then EMM is
|
||
installed and ready for use, if not, then the EMM manager
|
||
is not present }
|
||
If Int_67_Device_Name<>Emm_Device_Name
|
||
then Emm_Installed:=False;
|
||
end; { with Regs do }
|
||
end; { Function Emm_Installed }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This function returns the total number of EMS pages present
|
||
in the system, and the number of EMS pages that are
|
||
available for our use }
|
||
Function EMS_Pages_Available
|
||
(Var Total_EMS_Pages,Pages_Available: Word): Word;
|
||
Var
|
||
Regs: Registers;
|
||
Begin
|
||
with Regs do
|
||
Begin
|
||
{ Put the desired EMS function number in the AH pseudo-
|
||
register }
|
||
AH:=Get_Unallocated_Page_Count;
|
||
intr(EMM_INT,Regs);
|
||
{ The number of EMS pages available is returned in BX }
|
||
Pages_Available:=BX;
|
||
{ The total number of pages present in the system is
|
||
returned in DX }
|
||
Total_EMS_Pages:=DX;
|
||
{ Return the error code }
|
||
EMS_Pages_Available:=AH
|
||
end;
|
||
end; { EMS_Pages_Available }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This function requests the desired number of pages from the
|
||
EMM }
|
||
Function Allocate_Expanded_Memory_Pages
|
||
(Pages_Needed: Word; Var Handle: Word ): Word;
|
||
Var
|
||
Regs: Registers;
|
||
Begin
|
||
with Regs do
|
||
Begin
|
||
{ Put the desired EMS function number in the AH pseudo-
|
||
register }
|
||
AH:= Allocate_Pages;
|
||
{ Put the desired number of pages in BX }
|
||
BX:=Pages_Needed;
|
||
intr(EMM_INT,Regs);
|
||
{ Our EMS handle is returned in DX }
|
||
Handle:=DX;
|
||
{ Return the error code }
|
||
Allocate_Expanded_Memory_Pages:=AH;
|
||
end;
|
||
end; { Function Allocate_Expanded_Memory_Pages }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This function maps a logical page onto one of the physical
|
||
pages made available to us by the
|
||
Allocate_Expanded_Memory_Pages function }
|
||
Function Map_Expanded_Memory_Pages
|
||
(Handle,Logical_Page,Physical_Page: Word): Word;
|
||
Var
|
||
Regs: Registers;
|
||
Begin
|
||
with Regs do
|
||
Begin
|
||
{ Put the desired EMS function number in the AH pseudo-
|
||
register }
|
||
AH:=Map_Pages;
|
||
{ Put the physical page number to be mapped into AL }
|
||
AL:=Physical_Page;
|
||
{ Put the logical page number to be mapped in BX }
|
||
BX:=Logical_Page;
|
||
{ Put the EMS handle assigned to us earlier in DX }
|
||
DX:=Handle;
|
||
Intr(EMM_INT,Regs);
|
||
{ Return the error code }
|
||
Map_Expanded_Memory_Pages:=AH;
|
||
end; { with Regs do }
|
||
end; { Function Map_Expanded_Memory_Pages }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This function gets the physical address of the EMS page
|
||
frame we are using. The address returned is the segment
|
||
of the page frame. }
|
||
Function Get_Page_Frame_Base_Address
|
||
(Var Page_Frame_Address: Word): Word;
|
||
Var
|
||
Regs: Registers;
|
||
Begin
|
||
with Regs do
|
||
Begin
|
||
{ Put the desired EMS function number in the AH pseudo-
|
||
register }
|
||
AH:=Get_Page_Frame;
|
||
intr(EMM_INT,Regs);
|
||
{ The page frame base address is returned in BX }
|
||
Page_Frame_Address:=BX;
|
||
{ Return the error code }
|
||
Get_Page_Frame_Base_Address:=AH;
|
||
end; { Regs }
|
||
end; { Function Get_Page_Frame_Base_Address }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This function releases the EMS memory pages allocated to
|
||
us, back to the EMS memory pool. }
|
||
Function Deallocate_Expanded_Memory_Pages
|
||
(Handle: Word): Word;
|
||
Var
|
||
Regs: Registers;
|
||
Begin
|
||
with Regs do
|
||
Begin
|
||
{ Put the desired EMS function number in the AH pseudo-register }
|
||
AH:=DEALLOCATE_PAGES;
|
||
{ Put the EMS handle assigned to our EMS memory pages in DX }
|
||
DX:=Emm_Handle;
|
||
Intr(EMM_INT,Regs);
|
||
{ Return the error code }
|
||
Deallocate_Expanded_Memory_Pages:=AH;
|
||
end; { with Regs do }
|
||
end; { Function Deallocate_Expanded_Memory_Pages }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This function returns the version number of the EMM as
|
||
a 3 character string. }
|
||
Function Get_Version_Number(Var Version_String: ST3): Word;
|
||
Var
|
||
Regs: Registers;
|
||
Word_Part,Fractional_Part: Char;
|
||
|
||
Begin
|
||
with Regs do
|
||
Begin
|
||
{ Put the desired EMS function number in the AH pseudo-register }
|
||
AH:=GET_VERSION;
|
||
Intr(EMM_INT,Regs);
|
||
{ See if call was successful }
|
||
If AH=STATUS_OK then
|
||
Begin
|
||
{ The upper four bits of AH are the Word portion of the
|
||
version number, the lower four bits are the fractional
|
||
portion. Convert the Word value to ASCII by adding 48. }
|
||
Word_Part := Char( AL shr 4 + 48);
|
||
Fractional_Part:= Char( AL and $F +48);
|
||
Version_String:= Word_Part+'.'+Fractional_Part;
|
||
end; { If AH=STATUS_OK }
|
||
{ Return the function calls error code }
|
||
Get_Version_Number:=AH;
|
||
end; { with Regs do }
|
||
end; { Function Get_Version_Number }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ This procedure prints an error message passed by the caller,
|
||
prints the error code passed by the caller in hex, and then
|
||
terminates the program with the an error level of 1 }
|
||
|
||
Procedure Error(Error_Message: ST80; Error_Number: Word);
|
||
Begin
|
||
Writeln(Error_Message);
|
||
Writeln(' Error_Number = ',Hex_String(Error_Number) );
|
||
Writeln('EMS test program aborting.');
|
||
Halt(1);
|
||
end; { Procedure Error_Message }
|
||
|
||
{ * --------------------------------------------------------- * }
|
||
|
||
{ EMS_TEST }
|
||
|
||
{ This program is an example of the basic EMS functions that you
|
||
need to execute in order to use EMS memory with Turbo Pascal }
|
||
|
||
Begin
|
||
ClrScr;
|
||
Window(5,2,77,22);
|
||
|
||
{ Determine if the Expanded Memory Manager is installed, If
|
||
not, then terminate 'main' with an ErrorLevel code of 1. }
|
||
|
||
If not (Emm_Installed) then
|
||
Begin
|
||
Writeln('The LIM Expanded Memory Manager is not installed.');
|
||
Halt(1);
|
||
end;
|
||
|
||
{ Get the version number and display it }
|
||
Error_Code:= Get_Version_Number(Version_Number);
|
||
If Error_Code<>STATUS_OK then
|
||
Error('Error trying to get the EMS version number ',
|
||
Error_code)
|
||
else
|
||
Writeln('LIM Expanded Memory Manager, version ',
|
||
Version_Number,' is ready for use.');
|
||
Writeln;
|
||
|
||
{ Determine if there are enough expanded memory pages for this
|
||
application. }
|
||
Pages_Needed:=APPLICATION_PAGE_COUNT;
|
||
Error_Code:=
|
||
EMS_Pages_Available(Total_EMS_Pages,Available_EMS_Pages);
|
||
If Error_Code<>STATUS_OK then
|
||
Error('Error trying to determine the number of EMS pages available.',
|
||
Error_code);
|
||
|
||
Writeln('There are a total of ',Total_EMS_Pages,
|
||
' expanded memory pages present in this system.');
|
||
Writeln(' ',Available_EMS_Pages,
|
||
' of those pages are available for your usage.');
|
||
Writeln;
|
||
|
||
{ If there is an insufficient number of pages for our application,
|
||
then report the error and terminate the EMS test program }
|
||
If Pages_Needed>Available_EMS_Pages then
|
||
Begin
|
||
Str(Pages_Needed,Pages_Number_String);
|
||
Error('We need '+Pages_Number_String+
|
||
' EMS pages. There are not that many available.',
|
||
Error_Code);
|
||
end; { Pages_Needed>Available_EMS_Pages }
|
||
|
||
{ Allocate expanded memory pages for our usage }
|
||
Error_Code:= Allocate_Expanded_Memory_Pages(Pages_Needed,Emm_Handle);
|
||
Str(Pages_Needed,Pages_Number_String);
|
||
If Error_Code<>STATUS_OK then
|
||
Error('EMS test program failed trying to allocate '+Pages_Number_String+
|
||
' pages for usage.',Error_Code);
|
||
Writeln(APPLICATION_PAGE_COUNT,
|
||
' EMS page(s) allocated for the EMS test program.');
|
||
Writeln;
|
||
|
||
{ Map in the required logical pages to the physical pages
|
||
given to us, in this case just one page }
|
||
Logical_Page :=0;
|
||
Physical_Page:=0;
|
||
Error_Code:=
|
||
Map_Expanded_Memory_Pages(
|
||
Emm_Handle,Logical_Page,Physical_Page);
|
||
If Error_Code<>STATUS_OK then
|
||
Error('EMS test program failed trying to map '+
|
||
'logical pages onto physical pages.',Error_Code);
|
||
|
||
Writeln('Logical Page ',Logical_Page,
|
||
' successfully mapped onto Physical Page ',
|
||
Physical_Page);
|
||
Writeln;
|
||
|
||
{ Get the expanded memory page frame address }
|
||
Error_Code:= Get_Page_Frame_Base_Address(Page_Frame_Base_Address);
|
||
If Error_Code<>STATUS_OK then
|
||
Error('EMS test program unable to get the base Page'+
|
||
' Frame Address.',Error_Code);
|
||
Writeln('The base address of the EMS page frame is - '+
|
||
Hex_String(Page_Frame_Base_Address) );
|
||
Writeln;
|
||
|
||
{ Write a test pattern to expanded memory }
|
||
For Offset:=0 to 16382 do
|
||
Mem[Page_Frame_Base_Address:Offset]:=Offset mod 256;
|
||
|
||
{ Make sure that what is in EMS memory is what we just wrote }
|
||
Writeln('Testing EMS memory.');
|
||
|
||
Offset:=1;
|
||
Verify:=True;
|
||
while (Offset<=16382) and (Verify=True) do
|
||
Begin
|
||
If Mem[Page_Frame_Base_Address:Offset]<>Offset mod 256 then
|
||
Verify:=False;
|
||
Offset:=Succ(Offset);
|
||
end; { while (Offset<=16382) and (Verify=True) }
|
||
|
||
{ If it isn't report the error }
|
||
If not Verify then
|
||
Error('What was written to EMS memory was not found during '+
|
||
'memory verification test.',0);
|
||
Writeln('EMS memory test successful.');
|
||
Writeln;
|
||
|
||
{ Return the expanded memory pages given to us back to the
|
||
EMS memory pool before terminating our test program }
|
||
Error_Code:=Deallocate_Expanded_Memory_Pages(Emm_Handle);
|
||
If Error_Code<>STATUS_OK then
|
||
Error('EMS test program was unable to deallocate '+
|
||
'the EMS pages in use.',Error_Code);
|
||
Writeln(APPLICATION_PAGE_COUNT,
|
||
' page(s) deallocated.');
|
||
Writeln;
|
||
Writeln('EMS test program completed.');
|
||
end.
|
||
|