Example 2 This program shows you how to use the basic functions of the LIM Expanded Memory Specification with Turbo Pascal. The program does the following: 1. Makes sure the LIM Expanded Memory Manager (EMM) has been installed. 2. Displays the version number of the EMM. 3. Determines if there are enough pages of memory for the program. It then displays the total number of EMM pages present in the system and the number available for use. 4. Requests the desired number of pages from the EMM. 5. Maps a logical page into one of the physical pages. 6. Displays the base address of our EMM memory page frame. Performs a simple read/write test on the EMM memory. 7. Returns the EMM memory given to us back to the EMM. 8. 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, an error has occurred, a simple error procedure is called, and the program terminates. Type ST3 = string[3]; ST80 = string[80]; ST5 = string[5]; Registers = record case integer of 1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: Integer); 2: (AL,AH,BL,BH,CL,CH,DL,DH : Byte); end; 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; Writing Programs That Use Expanded Memory 19 {------------------------------------------------------------} { Assume the application needs one EMM page. } {------------------------------------------------------------} APPLICATION_PAGE_COUNT = 1; Var Regs: Registers; Emm_handle, Page_Frame_Base_Address, Pages_Needed, Physical_Page, Logical_Page, Offset, Error_Code, Pages_EMM_Available, Total_EMM_Pages, Available_EMM_Pages: Integer; Version_Number, Pages_Number_String: ST3; Verify: Boolean; {------------------------------------------------------------} { The function Hex_String converts an integer into a four } { character hexadecimal number (string) with leading zeros. } {------------------------------------------------------------} Function Hex_String (Number: Integer): ST5; Function Hex_Char (Number: Integer): 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 } Writing Programs That Use Expanded Memory 20 {------------------------------------------------------------} { The function Emm_Installed checks to see if the } { 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 the } { EMM interrupt, 67h, points to. } {------------------------------------------------------------} Function Emm_Installed: Boolean; Var Emm_Device_Name : string[8]; Int_67_Device_Name: string[8]; Position : integer; Regs : registers; Begin Int_67_Device_Name := ''; Emm_Device_Name := 'EMMXXXX0'; with Regs do Begin {----------------------------------------------------} { Get the code segment interrupt 67h points to } { the EMM interrupt by using DOS function 35h. } { (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 } { eight character string from the eight successive } { bytes at address ES:$000A (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; {----------------------------------------------------} { If the string is the EMM manager signature, } { 'EMMXXXX0', then EMM is installed and ready for } { use. If not, then EMM is not present. } {----------------------------------------------------} If Int_67_Device_Name <> Emm_Device_Name then Emm_Installed := False; end; { with Regs do } end; { Function Emm_Installed } Writing Programs That Use Expanded Memory 21 {------------------------------------------------------------} { This function returns the total number of EMM pages } { present in the system, and the number of EMM pages that } { are available. } {------------------------------------------------------------} Function EMM_Pages_Available (Var Total_EMM_Pages, Pages_Available: Integer): Integer; Var Regs: Registers; Begin with Regs do Begin {----------------------------------------------------} { Get the number of currently unallocated pages and } { the total number of pages in the system from EMM. } { Load pseudo-registers prior to invoking EMM. } { AH = get unallocated page count function } {----------------------------------------------------} AH := GET_UNALLOCATED_PAGE_COUNT; Intr (EMM_INT, Regs); {----------------------------------------------------} { Unload the pseudo-registers after invoking EMM. } { BX = currently unallocated pages } { DX = total pages in the system } { AH = status } {----------------------------------------------------} Pages_Available := BX; Total_EMM_Pages := DX; EMM_Pages_Available := AH; end; end; { Function EMM_Pages_Available } {------------------------------------------------------------} { This function requests the specified number of pages } { from the EMM. } {------------------------------------------------------------} Function Allocate_Expanded_Memory_Pages (Pages_Needed: Integer; Var Handle: Integer): Integer; Var Regs: Registers; Writing Programs That Use Expanded Memory 22 Begin with Regs do Begin {----------------------------------------------------} { Allocate the specified number of pages from EMM. } { Load pseudo-registers prior to invoking EMM. } { AH = allocate pages function. } { BX = number of pages to allocate. } {----------------------------------------------------} AH := ALLOCATE_PAGES; BX := Pages_Needed; Intr (EMM_INT, Regs); {----------------------------------------------------} { Unload the pseudo-registers after invoking EMM. } { DX = EMM handle } { AH = status } {----------------------------------------------------} Handle := DX; Allocate_Expanded_Memory_Pages := AH; end; end; { Function Allocate_Expanded_Memory_Pages } {------------------------------------------------------------} { This function maps a logical page allocated by the } { Allocate_Expanded_Memory_Pages function into one of the } { four physical pages. } {------------------------------------------------------------} Function Map_Expanded_Memory_Pages (Handle, Logical_Page, Physical_Page: Integer): Integer; Var Regs: Registers; Begin with Regs do Begin {----------------------------------------------------} { Map a logical page at a physical page. } { Load pseudo-registers prior to invoking EMM. } { AH = map page function } { DX = handle } { BX = logical page number } { AL = physical page number } {----------------------------------------------------} AH := MAP_PAGES; DX := Handle; BX := Logical_Page; AL := Physical_Page; Intr (EMM_INT, Regs); Writing Programs That Use Expanded Memory 23 {----------------------------------------------------} { Unload the pseudo-registers after invoking EMM. } { AH = status } {----------------------------------------------------} Map_Expanded_Memory_Pages := AH; end; { with Regs do } end; { Function Map_Expanded_Memory_Pages } {------------------------------------------------------------} { This function gets the physical address of the EMM 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: Integer): Integer; Var Regs: Registers; Begin with Regs do Begin {----------------------------------------------------} { Get the page frame segment address from EMM. } { Load pseudo-registers prior to invoking EMM. } { AH = get page frame segment function } {----------------------------------------------------} AH := GET_PAGE_FRAME; Intr (EMM_INT, Regs); {----------------------------------------------------} { Unload the pseudo-registers after invoking EMM. } { BX = page frame segment address } { AH = status } {----------------------------------------------------} Page_Frame_Address := BX; Get_Page_Frame_Base_Address := AH; end; { with Regs do } end; { Function Get_Page_Frame_Base_Address } {------------------------------------------------------------} { This function releases the EMM memory pages allocated to } { us, back to the EMM memory pool. } {------------------------------------------------------------} Function Deallocate_Expanded_Memory_Pages (Handle: Integer): Integer; Var Regs: Registers; Writing Programs That Use Expanded Memory 24 Begin with Regs do Begin {----------------------------------------------------} { Deallocate the pages allocated to an EMM handle. } { Load pseudo-registers prior to invoking EMM. } { AH = deallocate pages function } { DX = EMM handle } {----------------------------------------------------} AH := DEALLOCATE_PAGES; DX := Handle; Intr (EMM_INT, Regs); {----------------------------------------------------} { Unload the pseudo-registers after invoking EMM. } { AH = status } {----------------------------------------------------} 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 three-character string. } {------------------------------------------------------------} Function Get_Version_Number (Var Version_String: ST3): Integer; Var Regs: Registers; Integer_Part, Fractional_Part: Char; Begin with Regs do Begin {----------------------------------------------------} { Get the version of EMM. } { Load pseudo-registers prior to invoking EMM. } { AH = get EMM version function } {----------------------------------------------------} AH := GET_VERSION; Intr (EMM_INT, Regs); Writing Programs That Use Expanded Memory 25 {----------------------------------------------------} { If the version number returned was OK, then } { convert it to a three-character string. } {----------------------------------------------------} If AH=STATUS_OK then Begin {------------------------------------------------} { The upper four bits of AH are the integer } { portion of the version number, the lower four } { bits are the fractional portion. Convert the } { integer value to ASCII by adding 48. } {------------------------------------------------} Integer_Part := Char (AL shr 4 + 48); Fractional_Part := Char (AL and $F + 48); Version_String := Integer_Part + '.' + Fractional_Part; end; { If AH=STATUS_OK } {----------------------------------------------------} { Unload the pseudo-registers after invoking EMM. } { AH = status } {----------------------------------------------------} 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 an error level of 1. } {------------------------------------------------------------} Procedure Error (Error_Message: ST80; Error_Number: Integer); Begin Writeln (Error_Message); Writeln (' Error_Number = ', Hex_String (Error_Number)); Writeln ('EMM test program aborting.'); Halt (1); end; { Procedure Error } {--------------------------------------------------------------} { This program is an example of the basic EMM functions that } { you need in order to use EMM memory with Turbo Pascal. } {--------------------------------------------------------------} Begin ClrScr; Window (5,2,77,22); Writing Programs That Use Expanded Memory 26 {------------------------------------------------------------} { 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 EMM is not installed.'); Halt (1); end else Begin { Get the version number and display it } Error_Code := Get_Version_Number (Version_Number); If Error_Code <> STATUS_OK then Error ('Error getting EMM version number.', Error_Code) else Writeln ('LIM Expanded Memory Manager, version ', Version_Number, ' is ready for use.'); end; Writeln; {------------------------------------------------------------} { Determine if there are enough expanded memory pages for } { this application. } {------------------------------------------------------------} Pages_Needed := APPLICATION_PAGE_COUNT; Error_Code := EMM_Pages_Available (Total_EMM_Pages, Available_EMM_Pages); If Error_Code <> STATUS_OK then Error ('Error determining number of EMM pages available.', Error_Code); Writeln ('There are a total of ', Total_EMM_Pages, ' expanded memory pages present in this system.'); Writeln (' ', Available_EMM_Pages, ' of those pages are available for use.'); Writeln; {------------------------------------------------------------} { If there is an insufficient number of pages for the } { application, then report the error and terminate the EMM } { example program. } {------------------------------------------------------------} If Pages_Needed > Available_EMM_Pages then Begin Str (Pages_Needed, Pages_Number_String); Error ('We need ' + Pages_Number_String + ' EMM pages. There are not that many available.', Error_Code); end; { Pages_Needed > Available_EMM_Pages } Writing Programs That Use Expanded Memory 27 {------------------------------------------------------------} { Allocate expanded memory pages for our use. } {------------------------------------------------------------} Error_Code := Allocate_Expanded_Memory_Pages (Pages_Needed, Emm_Handle); Str (Pages_Needed, Pages_Number_String); If Error_Code <> STATUS_OK then Error ('EMM test program failed trying to allocate ' + Pages_Number_String + ' pages for usage.', Error_Code); Writeln (APPLICATION_PAGE_COUNT, ' EMM page(s) allocated for the EMM 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 ('EMM test program failed trying to map ' + 'logical pages into physical pages.', Error_Code); Writeln ('Logical Page ', Logical_Page, ' successfully mapped into 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 ('EMM test program unable to get the base Page' + ' Frame Address.', Error_Code); Writeln ('The base address of the EMM page frame is = ' + Hex_String (Page_Frame_Base_Address)); Writeln; Writing Programs That Use Expanded Memory 28 {------------------------------------------------------------} { Write a test pattern to expanded memory. } {------------------------------------------------------------} For Offset := 0 to 16382 do Begin Mem[Page_Frame_Base_Address:Offset] := Offset mod 256; end; {------------------------------------------------------------} { Make sure that what is in EMM memory is what was just } { written. } {------------------------------------------------------------} Writeln ('Testing EMM 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 what is read does not match what was written, } { an error occurred. } {------------------------------------------------------------} If not Verify then Error ('What was written to EMM memory was not found during' + ' memory verification test.', 0); Writeln ('EMM memory test successful.'); Writeln; {------------------------------------------------------------} { Return the expanded memory pages given to us back to the } { EMM memory pool before terminating our test program. } {------------------------------------------------------------} Error_Code := Deallocate_Expanded_Memory_Pages (Emm_Handle); If Error_Code <> STATUS_OK then Error ('EMM test program was unable to deallocate ' + 'the EMM pages in use.', Error_Code); Writeln (APPLICATION_PAGE_COUNT, ' pages(s) deallocated.'); Writeln; Writeln ('EMM test program completed.'); end. Writing Programs That Use Expanded Memory 29 Function 4. Allocate Pages The Allocate Pages function allocates the number of pages requested and assigns a unique EMM handle to these pages. The EMM handle owns these pages until the application deallocates them. Handles which are assigned using this function will have 16K-byte pages, the size of a standard expanded memory page. If the expanded memory board hardware isn't able to supply 16K-byte pages, it will emulate them by combining multiple non-standard size pages to form a single 16K-byte page. All application programs and functions that use the handles this function returns will deal with 16K-byte pages. The numeric value of the handles the EMM returns are in the range of 1 to 254 decimal (0001h to 00FEh). The OS handle (handle value 0) is never returned by the Allocate Pages function. Also, the uppermost byte of the handle will be zero and cannot be used by the application. A memory manager should be able to supply up to 255 handles, includ- ing the OS handle. An application can use Function 21 to find out how many handles an EMM supports. Allocating zero pages to a handle is not valid. If an application needs to allocate 0 pages to a handle it should use Function 27 (Allocate Standard Pages subfunction) provided for this purpose. Note............................................................ This note affects expanded memory manager implementors and operating system developers only. Applications should not use the following characteristics of the memory manager. An application violating this rule will be incompatible with future versions of Microsoft's operating systems and environments. To be compatible with this specification, an expanded memory manager will provide a special handle which is available to the operating system only. This handle will have a value of 0000h and will have a set of pages allocated to it when the expanded memory manager driver installs. The pages that the memory manager will automatically allocate to handle 0000h are those that backfill conventional memory. Typically, this backfill occurs between addresses 40000h (256K) and 9FFFFh (640K). However, the range can extend below and above this limit if the hardware and memory manager have the capability. EMM Functions 42 Function 4. Allocate Pages An operating system won't have to invoke Function 4 to obtain this handle because it can assume the handle already exists and is available for use immediately after the expanded memory device driver installs. When an operating system wants to use this handle, it uses the special handle value of 0000h. The operating system will be able to invoke any EMM function using this special handle value. To allocate pages to this handle, the operating system need only invoke Function 18 (Reallocate Pages). There are two special cases for this handle: 1. Function 4 (Allocate Pages). This function must never return zero as a handle value. Applications must always invoke Function 4 to allocate pages and obtain a handle which identifies the pages which belong to it. Since Function 4 never returns a handle value of zero, an application will never gain access to this special handle. 2. Function 6 (Deallocate Pages). If the operating system uses it to deallocate the pages which are allocated to this special handle, the pages the handle owns will be returned to the manager for use. But the handle will not be available for reassignment. The manager should treat a deallocate pages function request for this handle the same as a reallocate pages function request, where the number of pages to reallocate to this handle is zero. CALLING PARAMETERS AH = 43h Contains the Allocate Pages function. BX = num_of_pages_to_alloc Contains the number of pages you want your program to allocate. EMM Functions 43 Function 4. Allocate Pages RESULTS These results are valid only if the status returned is zero. DX = handle Contains a unique EMM handle. Your program must use this EMM handle (as a parameter) in any function that requires it. You can use up to 255 handles. The uppermost byte of the handle will be zero and cannot be used by the application. REGISTERS MODIFIED AX, DX STATUS AH = 0 SUCCESSFUL. The manager has allocated the requested pages to the assigned EMM handle. AH = 80h NON-RECOVERABLE. The manager detected a malfunction in the memory manager software. AH = 81h NON-RECOVERABLE. The manager detected a malfunction in the expanded memory hardware. AH = 84h NON-RECOVERABLE. The function code passed to the memory manager is not defined. AH = 85h RECOVERABLE. All EMM handles are being used. AH = 87h RECOVERABLE. There aren't enough expanded memory pages present in the system to satisfy your program's request. AH = 88h RECOVERABLE. There aren't enough unallocated pages to satisfy your program's request. AH = 89h RECOVERABLE. Your program attempted to allocate zero pages. EMM Functions 44 Function 4. Allocate Pages EXAMPLE num_of_pages_to_alloc DW ? emm_handle DW ? MOV BX,num_of_pages_to_alloc ; load number of pages MOV AH,43h ; load function code INT 67h ; call the memory manager OR AH,AH ; check EMM status JNZ emm_err_handler ; jump to error handler on error MOV emm_handle,DX ; save EMM handle EMM Functions 45 Function 27. Allocate Standard/Raw Pages Allocate Standard Pages subfunction PURPOSE The Allocate Standard Pages subfunction allocates the number of standard size (16K bytes) pages that the operating system requests and assigns a unique EMM handle to these pages. The EMM handle owns these pages until the operating system deallocates them. This subfunction allows you to allocate zero pages to a handle, unlike Function 4 (Allocate Pages). Note............................................................ This note affects expanded memory manager implementors and operating system developers only. Applications should not use the following characteristic of the memory manager. An application violating this rule will be incompatible with future versions of Microsoft's operating systems and environments. To be compatible with this specification, an expanded memory manager will provide a special handle which is available to the operating system only. This handle will have a value of 0000h and will have a set of pages allocated to it when the expanded memory manager driver installs. The pages that the memory manager will automatically allocate to handle 0000h are those that backfill conventional memory. Typically, this backfill occurs between addresses 40000h (256K) and 9FFFFh (640K). However, the range can extend below and above this limit if the hardware and memory manager have the capability. An operating system won't have to invoke Function 27 to obtain this handle because it can assume the handle already exists and is available for use immediately after the expanded memory device driver installs. When an operating system wants to use this handle, it uses the special handle value of 0000h. The operating system will be able to invoke any EMM function using this special handle value. To allocate pages to this handle, the operating system need only invoke Function 18 (Reallocate Pages). There are two special cases for this handle: 1. Function 27 (Allocate Standard Pages subfunction). This function must never return zero as a handle value. Applications must always invoke Function 27 to allocate pages and obtain a handle which identifies the pages which belong to it. Since Function 27 never returns a EMM Functions 144 Function 27. Allocate Standard/Raw Pages Allocate Standard Pages subfunction handle value of zero, an application will never gain access to this special handle. 2. Function 6 (Deallocate Pages). If the operating system uses it to deallocate the pages which are allocated to this handle, the pages the handle owns will be returned to the manager for use. But the handle will not be available for reassignment. The manager should treat a deallocate pages function request for this handle the same as a reallocate pages function request, where the number of pages to reallocate to this handle is zero. CALLING PARAMETERS AX = 5A00h Contains the Allocate Standard Pages subfunction. BX = num_of_standard_pages_to_alloc Contains the number of standard pages the operating system wants to allocate. RESULTS These results are valid only if the status returned is zero. DX = handle Contains a unique EMM handle. The operating system must use this EMM handle as a parameter in any function that requires it. Up to 255 handles may be obtained. (Both Function 27 and Function 4 must share the same 255 handles.) For all functions using this handle, the length of the physical and logical pages allocated to it are standard length (that is, 16K bytes). REGISTERS MODIFIED AX, DX EMM Functions 145 Function 27. Allocate Standard/Raw Pages Allocate Standard Pages subfunction STATUS AH = 0 SUCCESSFUL. The manager has allocated the pages to an assigned EMM standard handle. AH = 80h NON-RECOVERABLE. The manager detected a malfunction in the memory manager software. AH = 81h NON-RECOVERABLE. The manager detected a malfunction in the expanded memory hardware. AH = 84h NON-RECOVERABLE. The function code passed to the memory manager is not defined. AH = 85h RECOVERABLE. All EMM handles are being used. AH = 87h RECOVERABLE. There aren't enough expanded memory pages present in the system to satisfy the operating system's request. AH = 88h RECOVERABLE. There aren't enough unallocated pages to satisfy the operating system's request. AH = 8Fh NON-RECOVERABLE. The subfunction parameter is invalid. EXAMPLE num_of_standard_pages_to_alloc DW ? emm_handle DW ? MOV BX,num_of_standard_pages_to_alloc MOV AX,5A00h ; load function code INT 67h ; call the memory manager OR AH,AH ; check EMM status JNZ emm_err_handler ; jump to error handler on ; error MOV emm_handle,DX ; save handle EMM Functions 146 Function 27. Allocate Standard/Raw Pages Allocate Raw Pages subfunction PURPOSE The Allocate Raw Pages function allocates the number of non- standard size pages that the operating system requests and assigns a unique EMM handle to these pages. The EMM handle owns these pages until the operating system deallocates them. This function allows you to allocate zero pages to a handle, unlike Function 4 (Allocate Pages). A hardware vendor may design an expanded memory board that has a page size which is a sub-multiple of 16K bytes. A physical page which is a sub-multiple of 16K is termed a raw page. The operating system may deal with page sizes which are sub-multiples of 16K bytes. The memory manager must treat any function using a handle with raw pages allocated to it by Function 27 (Allocate Raw Pages subfunction) differently than it does a handle that has normal 16K-byte pages allocated to it. Handles which are assigned using Function 4 (Allocate Pages) or Function 27 (Allocate Standard Pages subfunction) must have pages which are 16K bytes -- this is the length of a standard expanded memory page. If the expanded memory board hardware is not able to supply 16K-byte pages, the memory manager must emulate pages which are 16K bytes combining multiple non-standard size pages to form a single 16K-byte page. Handles which are assigned using Function 27 (Allocate Raw Pages subfunction) are called raw handles. All logical pages allocated to a raw handle may have a non-standard length (that is, not 16K bytes). However, once the operat- ing system has allocated a number of raw pages to a handle, it is the responsibility of the memory manager to recognize that raw handle as one that has non-standard size pages allocated to it. The memory manager must identify these handles and treat all functions which use handles which have non-standard page lengths differently. The logical page length becomes the length of the non-standard size page for any raw handle that Function 27 assigns. Note............................................................ This note affects expanded memory manager implementors and operating system developers only. Applications should not use the following characteristic of the memory manager. An application violating this rule will be incompatible with EMM Functions 147 Function 27. Allocate Standard/Raw Pages Allocate Raw Pages subfunction future versions of Microsoft's operating systems and environments. To be compatible with this specification, an expanded memory manager will provide a special handle which is available to the operating system only. This handle will have a value of 0000h and will have a set of pages allocated to it when the expanded memory manager driver installs. The pages that the memory manager will automatically allocate to handle 0000h are those that backfill conventional memory. Typically, this backfill occurs between addresses 40000h (256K) and 9FFFFh (640K). However, the range can extend below and above this limit if the hardware and memory manager have the capability. An operating system won't have to invoke Function 27 to obtain this handle because it can assume the handle already exists and is available for use immediately after the expanded memory device driver installs. When an operating system wants to use this handle, it uses the special handle value of 0000h. The operating system will be able to invoke any EMM function using this special handle value. To allocate pages to this handle, the operating system need only invoke Function 18 (Reallocate Pages). There are two special cases for this handle: 1. Function 27 (Allocate Raw Pages subfunction). This function must never return zero as a handle value. Applications must always invoke Function 27 to allocate pages and obtain a handle which identifies the pages which belong to it. Since Function 27 never returns a handle value of zero, an application will never gain access to this special handle. 2. Function 6 (Deallocate Pages). If the operating system uses it to deallocate the pages which are allocated to this handle, the pages the handle owns will be returned to the manager for use. But the handle will not be available for reassignment. The manager should treat a deallocate pages function request for this handle the same as a reallocate pages function request, where the number of pages to reallocate to this handle is zero. EMM Functions 148 Function 27. Allocate Standard/Raw Pages Allocate Raw Pages subfunction CALLING PARAMETERS AX = 5A01h Contains the Allocate Raw Pages subfunction. BX = num_of_raw_pages_to_alloc Contains the number of raw pages the operating system wishes to allocate. RESULTS These results are valid only if the status returned is zero. DX = raw handle Contains a unique EMM raw handle. The operating system must use this EMM raw handle as a parameter in any function that requires it. Up to 255 handles may be obtained. (Both Function 4 and Function 27 must share the same 255 handles). For all functions using this raw handle, the length of the physical and logical pages allocated to it may be non-standard (that is, not 16K bytes). REGISTERS MODIFIED AX, DX STATUS AH = 0 SUCCESSFUL. The manager has allocated the raw pages to an assigned EMM raw handle. AH = 80h NON-RECOVERABLE. The manager detected a malfunction in the memory manager software. AH = 81h NON-RECOVERABLE. The manager detected a malfunction in the expanded memory hardware. EMM Functions 149 Function 27. Allocate Standard/Raw Pages Allocate Raw Pages subfunction AH = 84h NON-RECOVERABLE. The function code passed to the memory manager is not defined. AH = 85h RECOVERABLE. All EMM handles are being used. AH = 87h RECOVERABLE. There aren't enough expanded memory raw pages present in the system to satisfy the operating system's request. AH = 88h RECOVERABLE. There aren't enough unallocated raw pages to satisfy the operating system's request. AH = 8Fh NON-RECOVERABLE. The subfunction parameter is invalid. EXAMPLE num_of_raw_pages_to_alloc DW ? emm_raw_handle DW ? MOV BX,num_of_raw_pages_to_alloc MOV AX,5A01h ; load function code INT 67h ; call the memory manager OR AH,AH ; check EMM status JNZ emm_err_handler ; jump to error handler ; on error MOV emm_raw_handle,DX ; save raw handle EMM Functions 150