LOTUS /INTEL /MICROSOFT

                             EXPANDED MEMORY SPECIFICATION

                                      Version 4.0

                                       300275-005

                                     October, 1987

         Copyright (c) 1987

         Lotus Development Corporation
         55 Cambridge Parkway
         Cambridge, MA 02142

         Intel Corporation
         5200 NE Elam Young Parkway
         Hillsboro, OR 97124

         Microsoft Corporation
         16011 NE 36TH Way
         Box 97017
         Redmond, WA 98073

         This specification was jointly developed by Lotus Development
         Corporation, Intel Corporation, and Microsoft Corporation.  Although
         it has been released into the public domain and is not confidential or
         proprietary, the specification is still the copyright and property of
         Lotus Development Corporation, Intel Corporation, and Microsoft
         Corporation.

         DISCLAIMER OF WARRANTY

         LOTUS DEVELOPMENT CORPORATION, INTEL CORPORATION, AND MICROSOFT
         CORPORATION EXCLUDE ANY AND ALL IMPLIED WARRANTIES, INCLUDING
         WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
         NEITHER LOTUS NOR INTEL NOR MICROSOFT MAKE ANY WARRANTY OF
         REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS
         SPECIFICATION, ITS QUALITY, PERFORMANCE, MERCHANTABILITY, OR FITNESS
         FOR A PARTICULAR PURPOSE.  NEITHER LOTUS NOR INTEL NOR MICROSOFT SHALL
         HAVE ANY LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
         ARISING OUT OF OR RESULTING FROM THE USE OR MODIFICATION OF THIS
         SPECIFICATION.

         This specification uses the following trademarks:

         Intel is a trademark of Intel Corporation
         Lotus is a trademark of Lotus Development Corporation
         Microsoft is a trademark of Microsoft Corporation







                                                                       1







    CHAPTER 1

         INTRODUCTION

         Because even the maximum amount (640K bytes) of conventional memory
         isn't always enough for large application programs, Lotus Development
         Corporation, Intel Corporation, and Microsoft Corporation created the
         Lotus/Intel/Microsoft (LIM) Expanded Memory Specification.

         The LIM Expanded Memory Specification defines the software interface
         between the Expanded Memory Manager (EMM) -- a device driver that
         controls and manages expanded memory -- and application programs that
         use expanded memory.

         WHAT IS EXPANDED MEMORY?

         Expanded memory is memory beyond DOS's 640K-byte limit.  The LIM
         specification supports up to 32M bytes of expanded memory.  Because
         the 8086, 8088, and 80286 (in real mode) microprocessors can
         physically address only 1M byte of memory, they access expanded memory
         through a window in their physical address range.  The next section
         explains how this is done.

         HOW EXPANDED MEMORY WORKS

         Expanded memory is divided into segments called logical pages.  These
         pages are typically 16K-bytes of memory.  Your computer accesses
         logical pages through a physical block of memory called a page frame.
         The page frame contains multiple physical pages, pages that the
         microprocessor can address directly.  Physical pages are also
         typically 16K bytes of memory.

         This page frame serves as a window into expanded memory.  Just as your
         computer screen is a window into a large spreadsheet, so the page
         frame is a window into expanded memory.

         A logical page of expanded memory can be mapped into (made to appear
         in) any one of the physical pages in the page frame.  Thus, a read or
         write to the physical page actually becomes a read or write to the
         associated logical page.  One logical page can be mapped into the page
         frame for each physical page.

         The page frame is located above 640K bytes.  Normally, only video
         adapters, network cards, and similar devices exist between 640K and
         1024K.

         This specification also defines methods for operating systems and
         environments to access expanded memory through physical pages below
         640K bytes.  These methods are intended for operating
         system/environment developers only.








                                                                       2







    CHAPTER 2

         WRITING PROGRAMS THAT USE EXPANDED MEMORY

         This chapter describes what every program must do to use expanded
         memory and describes more advanced techniques of using expanded
         memory.

         This chapter also lists programming guidelines you should follow when
         writing programs that use expanded memory and provides the listings of
         some example programs.

         WHAT EVERY PROGRAM MUST DO

         This section describes the steps every program must take to use
         expanded memory.

         In order to use expanded memory, applications must perform these steps
         in the following order:

         1.  Determine if EMM is installed.

         2.  Determine if enough expanded memory pages exist for your
             application. (Function 3)

         3.  Allocate expanded memory pages.  (Function 4 or 18)

         4.  Get the page frame base address.  (Function 2)

         5.  Map in expanded memory pages.  (Function 5 or 17)

         6.  Read/write/execute data in expanded memory, just as if it were
             conventional memory.

         7.  Return expanded memory pages to expanded memory pool before
             exiting.  (Function 6 or 18)

         Table 2-1 overviews the functions while Chapter 3 describes each of
         these functions in detail.  Example programs at the end of this
         chapter illustrate using expanded memory.

    TABLE 2-1.  THE BASIC FUNCTIONS

         ----------------------------------------------------------------------
         Function                      Description
         ----------------------------------------------------------------------

         1   The Get Status function returns a status code indicating whether
             the memory manager hardware is working correctly.

         2   The Get Page Frame Address function returns the address where the
             64K-byte page frame is located.

         3   The Get Unallocated Page Count function returns the number of
             unallocated pages (pages available to your program) and the total
             number of pages in expanded memory.


                                                                       3







         4   The Allocate Pages function allocates the number of pages
             requested and assigns a unique EMM handle to these pages.

         5   The Map/Unmap Handle Page function maps a logical page to a
             specific physical page anywhere in the mappable regions of system
             memory.

         6   The Deallocate Pages deallocates the logical pages currently
             allocated to an EMM handle.

         7   The Get Version function returns the version number of the memory
             manager software.

         ADVANCED PROGRAMMING

         In addition to the basic functions, the Lotus/Intel/Microsoft Expanded
         Memory Specification provides several advanced functions which enhance
         the capabilities of software that uses expanded memory.

         The following sections describe the advanced programming capabilities
         and list the advanced EMM functions.

         Note.............................................................

         Before using the advanced functions, programs should first call
         Function 7 (Get Version) to determine whether the installed version of
         EMM supports these functions.

         SAVING THE STATE OF MAPPING HARDWARE

         Some software (such as interrupt service routines, device drivers, and
         resident software) must save the current state of the mapping
         hardware, switch mapping contexts, manipulate sections of expanded
         memory, and restore the original context of the memory mapping
         hardware.   Use Functions 8 and 9 or 15 and 16 to save the state of
         the hardware.

         RETRIEVING HANDLE AND PAGE COUNTS

         Some utility programs need to keep track of how expanded memory is
         being used; use Functions 12 through 14 to do this.

         MAPPING AND UNMAPPING MULTIPLE PAGES

         Mapping multiple pages reduces the overhead an application must
         perform during mapping.  Function 17 lets a program map (or unmap)
         multiple pages at one time.

         In addition, you can map pages using segment addresses instead of
         physical pages.  For example, if the page frame base address is set to
         D000, you can map to either physical page 0 or segment D000.  Function
         25 (Get Mappable Physical Address Array) returns a cross reference
         between all expanded memory physical pages and their corresponding
         segment values.




                                                                       4







         REALLOCATING PAGES

         Reallocating pages (Function 18) lets applications dynamically
         allocate expanded memory pages without acquiring another handle or
         obtain a handle without allocating pages.  Reallocating pages is an
         efficient means for applications to obtain and release expanded memory
         pages.

         USING HANDLES AND ASSIGNING NAMES TO HANDLES

         This specification lets you associate a name with a handle, so a
         family of applications can share information in expanded memory.  For
         example, a software package consisting of a word processor,
         spreadsheet, and print spooler can share the same data among the
         different applications.  The print spooler could use a handle name to
         reference data that either the spreadsheet or word processor put in
         expanded memory and could check for data in a particular handle name's
         expanded memory pages.

         Use Function 20 (Set Handle Name subfunction) to assign a handle name
         to an EMM handle or Function 21 (Search for Named Handle subfunction)
         to obtain the EMM handle associated with the handle name.  In
         addition, you can use Function 14 (Get Handle Pages) to determine the
         number of expanded memory pages allocated to an EMM handle.

         USING HANDLE ATTRIBUTES

         In addition to naming a handle, you can use Function 19 to associate
         an attribute (volatile or non-volatile) with a handle name.  A non-
         volatile attribute enables expanded memory pages to preserve their
         data through a warmboot.

         With a volatile attribute, the data is not preserved.  The default
         attribute for handles is volatile.

         Because using this function depends on the capabilities of the
         expanded memory hardware installed in the system, you should use the
         Get Attribute Capability subfunction before attempting to assign an
         attribute to a handle's pages.

         ALTERING PAGE MAPS AND JUMPING/CALLING

         You can use Functions 22 (Alter Page Map and Jump) and 23 (Alter Page
         Map and Call) to map a new set of values into the map registers and
         transfer program control to a specified address within expanded
         memory.  These functions can be used to load and execute code in
         expanded memory.  An application using this feature can significantly
         reduce the amount of conventional memory it requires.  Programs can
         load needed modules into expanded memory at run time and use Functions
         22 and 23 to transfer control to these modules.

         Using expanded memory to store code can improve program execution in
         many ways.  For example, sometimes programs need to be divided into
         small overlays because of conventional memory size limitations.
         Overlays targeted for expanded memory can be very large because LIM
         EMS 4.0 supports up to 32M bytes of expanded memory.  This method of
         loading overlays improves overall system performance by conserving

                                                                       5







         conventional memory and eliminating conventional memory allocation
         errors.

         MOVING OR EXCHANGING MEMORY REGIONS

         Using Function 24 (Move/Exchange Memory Region), you can easily move
         and exchange data between conventional and expanded memory.  Function
         24 can manipulate up to one megabyte of data with one function call.
         Although applications can perform this operation without this
         function, having the expanded memory manager do it reduces the amount
         of overhead for the application.  In addition, this function checks
         for overlapping regions and performs all the necessary mapping,
         preserving the mapping context from before the exchange/move call.

         GETTING THE AMOUNT OF MAPPABLE MEMORY

         Function 25 enables applications to determine the total amount of
         mappable memory the hardware/system currently supports.   Not all
         expanded memory boards supply the same number of physical pages (map
         registers).

         The Get Mappable Physical Address Array Entries subfunction returns
         the total number of physical pages the expanded memory hardware/system
         is capable of supporting.  The Get Mappable Physical Address Array
         subfunction returns a cross reference between physical page numbers
         and the actual segment address for each of the physical pages.

         OPERATING SYSTEM FUNCTIONS

         In addition to the functions for application programs, this
         specification defines functions for operating systems/environments.
         These functions can be disabled at any time by the operating
         system/environment, so programs should not depend on their presence.
         Applications that avoid this warning and use these functions run a
         great risk of being incompatible with other programs, including the
         operating system.

         TABLE 2-2.  THE ADVANCED FUNCTIONS

         ----------------------------------------------------------------------
         Function                 Description
         ----------------------------------------------------------------------

         8   The Save Page Map saves the contents of the page mapping registers
             from all expanded memory boards in an internal save area.

         9   The Restore Page Map function restores (from an internal save
             area) the page mapping register contents on the expanded memory
             boards for a particular EMM handle.

         10  Reserved.

         11  Reserved.

         12  The Get Handle Count function returns the number of open EMM
             handles in the system.


                                                                       6







         13  The Get Handle Pages function returns the number of pages
             allocated to a specific EMM handle.

         14  The Get All Handle Pages function returns an array of the active
             EMM handles and the number of pages allocated to each one.

         15  The Get/Set Page Map subfunction saves or restores the mapping
             context for all mappable memory regions (conventional and
             expanded) in a destination array which the application supplies.

         16  The Get/Set Partial Page Map subfunction provides a mechanism for
             saving a partial mapping context for specific mappable memory
             regions in a system.

         17  The Map/Unmap Multiple Handle Pages function can, in a single
             invocation, map (or unmap) logical pages into as many physical
             pages as the system supports.

         18  The Reallocate Pages function can increase or decrease the amount
             of expanded memory allocated to a handle.

         19  The Get/Set Handle Attribute function allows an application
             program to determine and set the attribute associated with a
             handle.

         20  The Get/Set Handle Name function gets the eight character name
             currently assigned to a handle and can assign an eight character
             name to a handle.

         21  The Get Handle Directory function returns information about active
             handles and the names assigned to each.

         22  The Alter Page Map & Jump function alters the memory mapping
             context and transfers control to the specified address.

         23  The Alter Page Map & Call function alters the specified mapping
             context and transfers control to the specified address.  A return
             can then restore the context and return control to the caller.

         24  The Move/Exchange Memory Region function copies or exchanges a
             region of memory from conventional to conventional memory,
             conventional to expanded memory, expanded to conventional memory,
             or expanded to expanded memory.

         25  The Get Mappable Physical Address Array function returns an array
             containing the segment address and physical page number for each
             mappable physical page in a system.

         26  The Get Expanded Memory Hardware Information function returns an
             array containing the hardware capabilities of the expanded memory
             system.

         27  The Allocate Standard/Raw Pages function allocates the number of
             standard or non-standard size pages that the operating system
             requests and assigns a unique EMM handle to these pages.



                                                                       7







         28  The Alternate Map Register Set function enables an application to
             simulate alternate sets of hardware mapping registers.

         29  The Prepare Expanded Memory Hardware for Warm Boot function
             prepares the expanded memory hardware for an "impending" warm
             boot.

         30  The Enable/Disable OS/E function enables operating systems
             developers to enable and disable functions designed for operating
             system use.
















































                                                                       8







         PROGRAMMING GUIDELINES

         The following section contains guidelines for programmers writing
         applications that use EMM.

         o   Do not put a program's stack in expanded memory.

         o   Do not replace interrupt 67h.  This is the interrupt vector the
             EMM uses.  Replacing interrupt 67h could result in disabling the
             Expanded Memory Manager.

         o   Do not map into conventional memory address space your application
             doesn't own.  Applications that use the EMM to swap into
             conventional memory space, must first allocate this space from the
             operating system.  If the operating system is not aware that a
             region of memory it manages is in use, it will think it is
             available.  This could have disastrous results.  EMM should not be
             used to 'allocate' conventional memory.  DOS is the proper manager
             of conventional memory space.  EMM should only be used to swap
             data in conventional memory space previously allocated from DOS.

         o   Applications that plan on using data aliasing in expanded memory
             must check for the presence of expanded memory hardware.  Data
             aliasing occurs when mapping one logical page into two or more
             mappable segments.  This makes one 16K-byte expanded memory page
             appear to be in more than one 16K-byte memory address space.  Data
             aliasing is legal and sometimes useful for applications.

             Software-only expanded memory emulators cannot perform data
             aliasing.  A simple way to distinguish software emulators from
             actual expanded memory hardware is to attempt data aliasing and
             check the results.  For example, map one logical page into four
             physical pages.  Write to physical page 0.  Read physical pages 1-
             3 to see if the data is there as well.  If the data appears in all
             four physical pages, then expanded memory hardware is installed in
             the system, and data aliasing is supported.

         o   Applications should always return expanded memory pages to the
             expanded memory manager upon termination.  These pages will be
             made available for other applications.  If unneeded pages are not
             returned to the expanded memory manager, the system could 'run
             out' of expanded memory pages or expanded memory handles.

         o   Terminate and stay resident programs (TSR's) should ALWAYS save
             the state of the map registers before changing them.  Since TSR's
             may interrupt other programs which may be using expanded memory,
             they must not change the state of the page mapping registers
             without first saving them.  Before exiting, TSR's must restore the
             state of the map registers.

             The following sections describe the three ways to save and restore
             the state of the map registers.

             1  Save Page Map and Restore Page Map (Functions 8 and 9).
                This is the simplest of the three methods.  The EMM saves
                the map register contents in its own data structures --
                the application does not need to provide extra storage

                                                                       9







                locations for the mapping context.  The last mapping
                context to be saved, under a particular handle, will be
                restored when a call to Restore Page Map is issued with
                the same handle.  This method is limited to one mapping
                context for each handle and saves the context for only LIM
                standard 64K-byte page frames.

             2  Get/Set Page Map (Function 15).  This method requires the
                application to allocate space for the storage array.   The
                EMM saves the mapping context in an array whose address is
                passed to the EMM.  When restoring the mapping context
                with this method, an application passes the address of an
                array which contains a previously stored mapping context.

                This method is preferable if an application needs to do
                more than one save before a restore.  It provides a
                mechanism for switching between more than one mapping
                context.

             3  Get/Set Partial Page Map (Function 16).  This method
                provides a way for saving a partial mapping context.  It
                should be used when the application does not need to save
                the context of all mappable memory.  This function also
                requires that the storage array be part of the
                application's data.

         o   All functions using pointers to data structures must have those
             data structures in memory which will not be mapped out.  Functions
             22 and 23 (Alter Map and Call and Alter Map and Jump) are the only
             exceptions.




























                                                                      10







    CHAPTER 3

         EMM FUNCTIONS

         This chapter provides you with a standardized set of expanded memory
         functions.  Because they are standardized, you avoid potential
         compatibility problems with other expanded memory programs that also
         adhere to the memory manager specification.  Programs that deal
         directly with the hardware or that don't adhere to this specification
         will be incompatible.

         Table 3-1 presents a sequential list of the EMM functions. The
         remainder of this chapter provides detailed descriptions of each
         function.

         TABLE 3-1.  LIST OF EMM FUNCTIONS

         ----------------------------------------------------------------------
         Number       Function Name                        Hex Value Page
         ----------------------------------------------------------------------

         1  Get Status                                     40h       14

         2  Get Page Frame Segment Address                 41h       15

         3  Get Unallocated Page Count                     42h       16

         4  Allocate Pages                                 43h       17

         5  Map/Unmap Handle Page                          44h       20

         6  Deallocate Pages                               45h       22

         7  Get Version                                    46h       24

         8  Save Page Map                                  47h       26

         9  Restore Page Map                               48h       28

         10 Reserved                                       49h       30

         11 Reserved                                       4Ah       31

         12 Get Handle Count                               4Bh       32

         13 Get Handle Pages                               4Ch       34

         14 Get All Handle Pages                           4Dh       36

         15 Get Page Map                                   4E00h     38

            Set Page Map                                   4E01h     40

            Get & Set Page Map                             4E02h     42

            Get Size of Page Map Save Array                4E03h     44


                                                                      11







         16 Get Partial Page Map                           4F00h     46

            Set Partial Page Map                           4F01h     48

            Get Size of Partial Page Map Save Array        4F02h     50

         17 Map/Unmap Multiple Handle Pages
            (Physical page number mode)                    5000h     52

            Map/Unmap Multiple Handle Pages
            (Segment address mode)                         5001h     56

         18 Reallocate Pages                               51h       59

         19 Get Handle Attribute                           5200h     62

            Set Handle Attribute                           5201h     65

            Get Handle Attribute Capability                5202h     67

         20 Get Handle Name                                5300h     68

            Set Handle Name                                5301h     70

         21 Get Handle Directory                           5400h     72

            Search for Named Handle                        5401h     74

            Get Total Handles                              5402h     76

         22 Alter Page Map & Jump
            (Physical page number mode)                    5500h     77

            Alter Page Map & Jump
            (Segment address mode)                         5501h     77

         23 Alter Page Map & Call
            (Physical page number mode)                    5600h     80

            Alter Page Map & Call
            (Segment address mode)                         5601h     80

            Get Page Map Stack Space Size                  5602h     84

         24 Move Memory Region                             5700h     86

            Exchange Memory Region                         5701h     91

         25 Get Mappable Physical Address Array            5800h     96

            Get Mappable Physical Address Array Entries    5801h     99

         26 Get Hardware Configuration Array               5900h     101

            Get Unallocated Raw Page Count                 5901h     104

         27 Allocate Standard Pages                        5A00h     106

                                                                      12







            Allocate Raw Pages                             5A01h     109

         28 Get Alternate Map Register Set                 5B00h     112

            Set Alternate Map Register Set                 5B01h     117

            Get Alternate Map Save Array Size              5B02h     120

            Allocate Alternate Map Register Set            5B03h     122

            Deallocate Alternate Map Register Set          5B04h     124

            Allocate DMA Register Set                      5B05h     126

            Enable DMA on Alternate Map Register Set       5B06h     128

            Disable DMA on Alternate Map Register Set      5B07h     130

            Deallocate DMA Register Set                    5B08h     132

         29 Prepare Expanded Memory Hardware for Warmboot  5Ch       134

         30 Enable OS/E Function Set                       5D00h     135

            Disable OS/E Function Set                      5D01h     138

            Return OS/E Access Key                         5D02h     140































                                                                      13







    FUNCTION 1    GET STATUS

         PURPOSE

         The Get Status function returns a status code indicating whether the
         memory manager is present and the hardware is working correctly.

         CALLING PARAMETERS

         AH = 40h
                    Contains the Get Status function.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager is present in the system, and the hardware is
                    working correctly.

         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.

         EXAMPLE

         MOV  AH, 40h                       ; 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


















                                                                      14







    FUNCTION 2    GET PAGE FRAME ADDRESS

         PURPOSE

         The Get Page Frame Address function returns the segment address where
         the page frame is located.

         CALLING PARAMETERS

         AH = 41h
                    Contains the Get Page Frame function.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = page frame segment address
                    Contains the segment address of the page frame.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the page frame address in the BX
                    register.

         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.

         EXAMPLE

         page_frame_segment                 DW  ?

         MOV  AH, 41h                       ; 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  page_frame_segment, BX        ; save page frame address








                                                                      15







    FUNCTION 3    GET UNALLOCATED PAGE COUNT

         PURPOSE

         The Get Unallocated Page Count function returns the number of
         unallocated pages and the total number of expanded memory pages.

         CALLING PARAMETERS

         AH = 42h   Contains the Get Unallocated Page Count function.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = unallocated pages
                    The number of expanded memory pages that are currently
                    available for use (unallocated).

         DX = total pages
                    The total number expanded memory pages.

         REGISTERS MODIFIED

         AX, BX, DX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the number of unallocated pages
                    and the number of total pages in expanded memory.

         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.

         EXAMPLE

         un_alloc_pages                     DW  ?
         total_pages                        DW  ?

         MOV  AH, 42h                       ; 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  un_alloc_pages, BX            ; save unallocated page count
         MOV  total_pages, DX               ; save total page count



                                                                      16







    FUNCTION 4    ALLOCATE PAGES

         PURPOSE

         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, including
         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
         provided for this purpose.

         Note...............................................................

         This note affects expanded memory manager implementers 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 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:



                                                                      17







         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.

         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.


                                                                      18







         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.

         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

































                                                                      19







    FUNCTION 5    MAP/UNMAP HANDLE PAGES

         PURPOSE

         The Map/Unmap Handle Page function maps a logical page at a specific
         physical page anywhere in the mappable regions of system memory.
         The lowest valued physical page numbers are associated with regions of
         memory outside the conventional memory range.  Use Function 25 (Get
         Mappable Physical Address Array) to determine which physical pages
         within a system are mappable and determine the segment addresses which
         correspond to a specific physical page number.  Function 25 provides a
         cross reference between physical page numbers and segment addresses.

         This function can also unmap physical pages, making them inaccessible
         for reading or writing.  You unmap a physical page by setting its
         associated logical page to FFFFh.

         You might unmap an entire set of mapped pages, for example, before
         loading and executing a program.  Doing so ensures the loaded program,
         if it accesses expanded memory, won't access the pages your program
         has mapped.  However, you must save the mapping context before you
         unmap the physical pages.  This enables you to restore it later so you
         can access the memory you mapped there.  To save the mapping context,
         use Function 8, 15, or 16.  To restore the mapping context, use
         Function 9, 15, or 16.

         The handle determines what type of pages are being mapped. Logical
         pages allocated by Function 4 and Function 27 (Allocate Standard Pages
         subfunction) are referred to as pages and are 16K bytes long.  Logical
         pages allocated by Function 27 (Allocate Raw Pages subfunction) are
         referred to as raw pages and might not be the same size as logical
         pages.

         CALLING PARAMETERS

         AH = 44h
                    Contains the Map Handle Page function.

         AL = physical_page_number
                    Contains the number of the physical page into which the
                    logical page number is to be mapped.  Physical pages are
                    numbered zero relative.

         BX = logical_page_number
                    Contains the number of the logical page to be mapped at the
                    physical page within the page frame.  Logical pages are
                    numbered zero relative.  The logical page must be in the
                    range zero through (number of pages allocated to the EMM
                    handle - 1).  However, if BX contains logical page number
                    FFFFh, the physical page specified in AL will be unmapped
                    (be made inaccessible for reading or writing).

         DX = emm_handle
                    Contains the EMM handle your program received from Function
                    4 (Allocate Pages).

         REGISTERS MODIFIED

                                                                      20







         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has mapped the page.  The page is ready to be
                    accessed.

         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 = 83h   NON-RECOVERABLE
                    The memory manager couldn't find the EMM handle your
                    program specified.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager isn't
                    defined.

         AH = 8Ah   RECOVERABLE
                    The logical page is out of the range of logical pages which
                    are allocated to the EMM handle.  This status is also
                    returned if a program attempts map a logical page when no
                    logical pages are allocated to the handle.

         AH = 8Bh   RECOVERABLE
                    The physical page number is out of the range of allowable
                    physical pages.  The program can recover by attempting to
                    map into memory at a physical page which is within the
                    range of allowable physical pages.

         EXAMPLE

         emm_handle                         DW  ?
         logical_page_number                DW  ?
         physical_page_number               DB  ?

         MOV  DX, emm_handle                ; load EMM handle
         MOV  BX, logical_page_number       ; load logical page number
         MOV  AL, physical_page_number      ; load physical page number
         MOV  AH, 44h                       ; 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









                                                                      21







    FUNCTION 6    DEALLOCATE PAGES

         PURPOSE

         Deallocate Pages deallocates the logical pages currently allocated to
         an EMM handle.  Only after the application deallocates these pages can
         other applications use them.  When a handle is deallocated, it name is
         set to all ASCII nulls (binary zeros).

         Note...............................................................

         A program must perform this function before it exits to DOS. If it
         doesn't, no other programs can use these pages or the EMM handle.
         This means that a program using expanded memory should trap critical
         errors and control-break if there is a chance that the program will
         have allocated pages when either of these events occur.

         Calling Parameters

         AH = 45h
                    Contains the Deallocate Pages function.

         DX = handle
                    Contains the EMM handle returned by Function 4 (Allocate
                    Pages).

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has deallocated the pages previously allocated
                    to the 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 = 83h   NON-RECOVERABLE
                    The manager couldn't find the specified EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager is not
                    defined.

         AH = 86h   RECOVERABLE
                    The memory manager detected a save or restore  page mapping
                    context error (Function 8 or 9).  There is a page mapping
                    register state in the save area for the specified EMM
                    handle.  Save Page Map (Function 8) placed it there and a
                    subsequent Restore Page Map (Function 9) has not removed

                                                                      22







                    it.  If you have saved the mapping context, you must
                    restore it before you deallocate the EMM handle's pages.

         EXAMPLE

         emm_handle                         DW  ?

         MOV  DX, emm_handle                ; load EMM handle
         MOV  AH, 45h                       ; 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














































                                                                      23







    FUNCTION 7    GET VERSION

         PURPOSE

         The Get Version function returns the version number of the memory
         manager software.

         CALLING PARAMETERS

         AH = 46h
                    Contains the Get Version function.

         RESULTS

         These results are valid only if the status returned is zero.

         AL = version number
                    Contains the memory manager's version number in binary
                    coded decimal (BCD) format.  The upper four bits contain
                    the integer digit of the version number.  The lower four
                    bits contain the fractional digit of version number.  For
                    example, version 4.0 is represented like this:

                                            0100 0000
                                              /   \
                                             4  .  0

                    When checking for a version number, an application should
                    check for a version number or greater.  Vendors may use the
                    fractional digit to indicate enhancements or corrections to
                    their memory managers.  Therefore, to allow for future
                    versions of memory managers, an application shouldn't
                    depend on an exact version number.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager is present in the system and the hardware is
                    working correctly.

         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.

         EXAMPLE

                                                                      24








         emm_version                        DB  ?

         MOV  AH, 46h                       ; 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_version, AL               ; save version number


















































                                                                      25







    FUNCTION 8    SAVE PAGE MAP

         PURPOSE

         Save Page Map saves the contents of the page mapping registers on all
         expanded memory boards in an internal save area.  The function is
         typically used to save the memory mapping context of the EMM handle
         that was active when a software or hardware interrupt occurred.  (See
         Function 9, Restore Page Map, for the restore operation.)  If you're
         writing a resident program, an interrupt service, or a device driver
         that uses expanded memory, you must save the state of the mapping
         hardware.  You must save this state because application software using
         expanded memory may be running when your program is invoked by a
         hardware interrupt, a software interrupt, or DOS.

         The Save Page Map function requires the EMM handle that was assigned
         to your resident program, interrupt service routine, or device driver
         at the time it was initialized. This is not the EMM handle that the
         application software was using when your software interrupted it.

         The Save Page Map function saves the state of the map registers for
         only the 64K-byte page frame defined in versions 3.x of this
         specification.  Since all applications written to LIM versions 3.x
         require saving the map register state of only this 64K-byte page
         frame, saving the entire mapping state for a large number of mappable
         pages would be inefficient use of memory.  Applications that use a
         mappable memory region outside the LIM 3.x page frame should use
         Function 15 or 16 to save and restore the state of the map registers.

         CALLING PARAMETERS

         AH = 47h
                    Contains the Save Page Map function.

         DX = handle
                    Contains the EMM handle assigned to the interrupt service
                    routine that's servicing the software or hardware
                    interrupt.  The interrupt service routine needs to save the
                    state of the page mapping hardware before mapping any
                    pages.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has saved the state of the page mapping
                    hardware.

         AH = 80h   NON-RECOVERABLE
                    The manager detected a malfunction in the memory manager
                    software.




                                                                      26







         AH = 81h   NON-RECOVERABLE
                    The manager detected a malfunction in the expanded memory
                    hardware.

         AH = 83h   NON-RECOVERABLE
                    The memory manager couldn't find the EMM handle your
                    program specified.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager is not
                    defined.

         AH = 8Ch   NON-RECOVERABLE
                    There is no room in the save area to store the state of the
                    page mapping registers.  The state of the map registers has
                    not been saved.

         AH = 8Dh   CONDITIONALLY-RECOVERABLE
                    The save area already contains the page mapping register
                    state for the EMM handle your program specified.

         EXAMPLE

         emm_handle                         DW  ?

         MOV  DX, emm_handle                ; load EMM handle
         MOV  AH, 47h                       ; 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




























                                                                      27







    FUNCTION 9    RESTORE PAGE MAP

         PURPOSE

         The Restore Page Map function restores the page mapping register
         contents on the expanded memory boards for a particular EMM handle.
         This function lets your program restore the contents of the mapping
         registers its EMM handle saved. (See Function 8, Save Page Map for the
         save operation.)

         If you're writing a resident program, an interrupt service routine, or
         a device driver that uses expanded memory, you must restore the
         mapping hardware to the state it was in before your program took over.
         You must save this state because application software using expanded
         memory might have been running when your program was invoked.

         The Restore Page Map function requires the EMM handle that was
         assigned to your resident program, interrupt service routine, or
         device driver at the time it was initialized.  This is not the EMM
         handle that the application software was using when your software
         interrupted it.

         The Restore Page Map function restores the state of the map registers
         for only the 64K-byte page frame defined in versions 3.x of this
         specification.  Since all applications written to LIM versions 3.x
         require restoring the map register state of only this 64K-byte page
         frame, restoring the entire mapping state for a large number of
         mappable pages would be inefficient use of memory.  Applications that
         use a mappable memory region outside the LIM 3.x page frame should use
         Function 15 or 16 to save and restore the state of the map registers.

         CALLING PARAMETERS

         AH = 48h
                    Contains the Restore Page Map function.

         DX = emm_handle
                    Contains the EMM handle assigned to the interrupt service
                    routine that's servicing the software or hardware
                    interrupt.  The interrupt service routine needs to restore
                    the state of the page mapping hardware.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has restored the state of the page mapping
                    registers.

         AH = 80h   NON-RECOVERABLE
                    The manager detected a malfunction in the memory manager
                    software.



                                                                      28







         AH = 81h   NON-RECOVERABLE
                    The manager detected a malfunction in the expanded memory
                    hardware.

         AH = 83h   NON-RECOVERABLE
                    The memory manager couldn't find the EMM handle your
                    program specified.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager is not
                    defined.

         AH = 8Eh   CONDITIONALLY-RECOVERABLE
                    There is no page mapping register state in the save area
                    for the specified EMM handle.  Your program didn't save the
                    contents of the page mapping hardware, so Restore Page Map
                    can't restore it.

         EXAMPLE

         emm_handle                         DW  ?

         MOV  DX, emm_handle                ; load EMM handle
         MOV  AH, 48h                       ; 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































                                                                      29







    FUNCTION 10   RESERVED

         In earlier versions of the Lotus/Intel/Microsoft Expanded Memory
         Specification the use of this function was documented.  This function
         is now documented as "RESERVED" (i.e. not documented) in the public
         versions of the specification and new programs should not use it.

         Existing programs that use this function may still work correctly if
         the hardware is capable of supporting them.  Since IBM Microchannel
         hardware is not capable of supporting this function, it cannot be
         implemented in the IBM Microchannel architecture.  However, programs
         that use Functions 16 through 30 in Version 4.0 of this specification
         must not use Functions 10 and 11.  These functions won't work
         correctly if a program attempts to mix the use of the new functions
         (Functions 16 through 30) and functions 10 and 11.  Functions 10 and
         11 are specific to the hardware on Intel expanded memory boards and
         will not work correctly on all vendors expanded memory boards.









































                                                                      30







    FUNCTION 11   RESERVED

         In earlier versions of the Lotus/Intel/Microsoft Expanded Memory
         Specification the use of this function was documented.  This function
         is now documented as "RESERVED" (i.e. not documented) in the public
         versions of the specification and new programs should not use it.

         Existing programs that use this function may still work correctly if
         the hardware is capable of supporting them.  Since IBM Microchannel
         hardware is not capable of supporting this function, it cannot be
         implemented in the IBM Microchannel architecture.  However, programs
         that use Functions 16 through 30 in Version 4.0 of this specification
         must not use Functions 10 and 11.  These functions won't work
         correctly if a program attempts to mix the use of the new functions
         (Functions 16 through 30) and functions 10 and 11.  Functions 10 and
         11 are specific to the hardware on Intel expanded memory boards and
         will not work correctly on all vendors expanded memory boards.









































                                                                      31







    FUNCTION 12   GET HANDLE COUNT

         PURPOSE

         The Get Handle Count function returns the number of open EMM handles
         (including the operating system handle 0) in the system.

         CALLING PARAMETERS

         AH = 4Bh
                    Contains the Get Handle Count function.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = total_open_emm_handles
                    Contains the number of open EMM handles [including the
                    operating system handle (0)].  This number will not exceed
                    255.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the number of active EMM handles.

         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.

















                                                                      32







         EXAMPLE

         total_open_emm_handles             DW  ?

         MOV  AH, 4Bh                       ; 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  total_open_emm_handles, BX    ; save total active handle count

















































                                                                      33







    FUNCTION 13   GET HANDLE PAGES

         PURPOSE

         The Get Handle Pages function returns the number of pages allocated to
         a specific EMM handle.

         CALLING PARAMETERS

         AH = 4Ch
                    Contains the Get Handle Pages function.

         DX = emm_handle
                    Contains the EMM handle.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = num_pages_alloc_to_emm_handle
                    Contains the number of logical pages allocated to the
                    specified EMM handle.  This number never exceeds 2048
                    because the memory manager allows a maximum of 2048 pages
                    (32M bytes) of expanded memory.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the number of pages allocated to
                    the 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 = 83h   NON-RECOVERABLE
                    The memory manager couldn't find the EMM handle your
                    program specified.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager is not
                    defined.








                                                                      34







         EXAMPLE

         emm_handle                         DW  ?
         pages_alloc_to_handle              DW  ?

         MOV  DX, emm_handle                ; load EMM handle
         MOV  AH, 4Ch                       ; 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  pages_alloc_to_handle, BX     ; save number of pages allocated
                                            ; to specified handle














































                                                                      35







    FUNCTION 14   GET ALL HANDLES PAGES

         PURPOSE

         The Get All Handle Pages function returns an array of the open emm
         handles and the number of pages allocated to each one.

         CALLING PARAMETERS

         AH = 4Dh
                    Contains the Get All Handle Pages function.

         handle_page_struct         STRUC
            emm_handle              DW ?
            pages_alloc_to_handle   DW ?
         handle_page_struct         ENDS

         ES:DI = pointer to handle_page
                    Contains a pointer to an array of structures where a copy
                    of all open EMM handles and the number of pages allocated
                    to each will be stored.  Each structure has these two
                    members:

         .emm_handle
                    The first member is a word which contains the value of the
                    open EMM handle.  The values of the handles this function
                    returns will be in the range of 0 to 255 decimal (0000h to
                    00FFh).  The uppermost byte of the handle is always zero.

         .pages_alloc_to_handle
                    The second member is a word which contains the number of
                    pages allocated to the open EMM handle.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = total_open_emm_handles
                    Contains the number of open EMM handles (including the
                    operating system handle [0]).  The number cannot be zero
                    because the operating system handle is always active and
                    cannot be deallocated.  This number will not exceed 255.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array.

         AH = 80h   NON-RECOVERABLE
                    The manager detected a malfunction in the memory manager
                    software.



                                                                      36







         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 isn't
                    defined.

         EXAMPLE

         handle_page                        handle_page_struct 255 DUP (?)
         total_open_handles                 DW  ?

         MOV  AX, SEG handle_page
         MOV  ES, AX
         LEA  DI, handle_page               ; ES:DI points to handle_page
         MOV  AH, 4Dh                       ; 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  total_open_handles, BX        ; save total open handle count





































                                                                      37







    FUNCTION 15   GET/SET PAGE MAP

         GET PAGE MAP SUBFUNCTION

         PURPOSE

         The Get Page Map subfunction saves the mapping context for all
         mappable memory regions (conventional and expanded) by copying the
         contents of the mapping registers from each expanded memory board to a
         destination array.  The application must pass a pointer to the
         destination array.  This subfunction doesn't require an EMM handle.
         Use this function instead of Functions 8 and 9 if you need to save or
         restore the mapping context but don't want (or have) to use a handle.

         CALLING PARAMETERS

         AX = 4E00h
                    Contains the Get Page Map subfunction.

         ES:DI = dest_page_map
                    Contains a pointer to the destination array address in
                    segment:offset format.  Use the Get Size of Page Map Save
                    Array subfunction to determine the size of the desired
                    array.

         RESULTS

         These results are valid only if the status returned is zero.

         dest_page_map
                    The array contains the state of all the mapping registers
                    on all boards in the system.  It also contains any
                    additional information necessary to restore the boards to
                    their original state when the program invokes a Set
                    subfunction.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array.

         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.


                                                                      38







         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         dest_page_map                      DB  ?  DUP  (?)

         MOV  AX, SEG dest_page_map
         MOV  ES, AX
         LEA  DI, dest_page_map             ; ES:DI points to dest_page_map
         MOV  AX, 4E00h                     ; 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












































                                                                      39







    FUNCTION 15   GET/SET PAGE MAP (CONTINUED)

         SET PAGE MAP SUBFUNCTION

         PURPOSE

         The Set Page Map subfunction restores the mapping context for all
         mappable memory regions (conventional and expanded) by copying the
         contents of a source array into the mapping registers on each expanded
         memory board in the system.  The application must pass a pointer to
         the source array.  This subfunction doesn't require an EMM handle.
         Use this function instead of Functions 8 and 9 if you need to save or
         restore the mapping context but don't want (or have) to use a handle.

         CALLING PARAMETERS

         AX = 4E01h
                    Contains the Set Page Map subfunction.

         DS:SI = source_page_map
                    Contains a pointer to the source array address in
                    segment:offset format.  The application must point to an
                    array which contains the mapping register state.  Use the
                    Get Size of Page Map Save Array subfunction to determine
                    the size of the desired array.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has passed the array.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A3h   NON-RECOVERABLE
                    The contents of the source array have been corrupted, or
                    the pointer passed to the subfunction is invalid.

         EXAMPLE

         source_page_map                    DB  ?  DUP  (?)

                                                                      40








         MOV  AX, SEG source_page_map
         MOV  DS, AX
         LEA  SI, source_page_map           ; DS:SI points to source_page_map
         MOV  AX, 4E01h                     ; 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


















































                                                                      41







    FUNCTION 15   GET/SET PAGE MAP (CONTINUED)

         GET & SET PAGE MAP SUBFUNCTION

         PURPOSE

         The Get & Set subfunction simultaneously saves a current mapping
         context and restores a previous mapping context for all mappable
         memory regions (both conventional and expanded).  It first copies the
         contents of the mapping registers from each expanded memory board in
         the system into a destination array.  (The application must pass a
         pointer to the destination array.)  Then, the subfunction copies the
         contents of a source array into the mapping registers on each of the
         expanded memory boards.  (The application must pass a pointer to the
         source array.)

         Use this function instead of Functions 8 and 9 if you need to save or
         restore the mapping context but don't want (or have) to use a handle.

         CALLING PARAMETERS

         AX = 4E02h
                    Contains the Get & Set Page Map subfunction.

         ES:DI = dest_page_map
                    Contains a pointer to the destination array address in
                    segment:offset format.  The current contents of the map
                    registers will be saved in this array.

         DS:SI = source_page_map
                    Contains a pointer to the source array address in
                    segment:offset format.  The contents of this array will be
                    copied into the map registers.  The application must point
                    to an array which contains the mapping register state.
                    This address is required only for the Set or Get and Set
                    subfunctions.

         RESULTS

         These results are valid only if the status returned is zero.

         dest_page_map
                    The array contains the mapping state.  It also contains any
                    additional information necessary to restore the original
                    state when the program invokes a Set subfunction.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned and passed both arrays.




                                                                      42







         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A3h   NON-RECOVERABLE
                    The contents of the source array have been corrupted, or
                    the pointer passed to the subfunction is invalid.

         EXAMPLE

         dest_page_map                      DB  ?  DUP  (?)
         source_page_map                    DB  ?  DUP  (?)

         MOV  AX, SEG dest_page_map
         MOV  ES, AX
         MOV  AX, SEG source_page_map
         MOV  DS, AX
         LEA  DI, dest_page_map             ; ES:DI points to dest_page_map
         LEA  SI, source_page_map           ; DS:SI points to source_page_map
         MOV  AX, 4E02h                     ; 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

























                                                                      43







    FUNCTION 15   GET/SET PAGE MAP (CONTINUED)

         GET SIZE OF PAGE MAP SAVE ARRAY SUBFUNCTION

         PURPOSE

         The Get Size of Page Map Save Array subfunction returns the storage
         requirements for the array passed by the other three subfunctions.
         This subfunction doesn't require an EMM handle.

         CALLING PARAMETERS

         AX = 4E03h
                    Contains the Get Size of Page Map Save Array subfunction.
                    The size of this array depends on how the expanded memory
                    system is configured and how the expanded memory manager is
                    implemented.  Therefore, the size must be determined after
                    the memory manager is loaded.

         RESULTS

         These results are valid only if the status returned is zero.

         AL = size_of_array
                    Contains the number of bytes that will be transferred to
                    the memory area an application supplies whenever a program
                    requests the Get, Set, or Get and Set subfunctions.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array size.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         size_of_array                      DB  ?

         MOV  AX, 4E03h                     ; 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

                                                                      44







         MOV  size_of_array, AL             ; save array size

























































                                                                      45







    FUNCTION 16   GET/SET PARTIAL PAGE MAP

         GET PARTIAL PAGE MAP SUBFUNCTION

         PURPOSE

         The Get Partial Page Map subfunction saves a partial mapping context
         for specific mappable memory regions in a system.  Because this
         function saves only a subset of the entire mapping context, it uses
         much less memory for the save area and may be potentially faster than
         Function 15.  The subfunction does this by copying the contents of
         selected mapping registers from each expanded memory board to a
         destination array.

         The application must pass a pair of pointers.  The first points to a
         structure which specifies which mappable segments to save; the second
         points to the destination array.

         Use this function instead of Functions 8 and 9 if you need to save or
         restore the mapping context but don't want (or have) to use a handle.

         CALLING PARAMETERS

         AX = 4F00h
                    Contains the Get Partial Page Map subfunction.

         partial_page_map_struct     STRUC
            mappable_segment_count   DW  ?
            mappable_segment         DW  (?)  DUP  (?)
         partial_page_map_struct     ENDS

         DS:SI = partial_page_map
                    Contains a pointer to a structure which specifies only
                    those mappable memory regions which are to have their
                    mapping context saved.  The structure members are described
                    below.

         .mappable_segment_count
                    The first member is a word which specifies the number of
                    members in the word array which immediately follows it.
                    This number should not exceed the number of mappable
                    segments in the system.

         .mappable_segment
                    The second member is a word array which contains the
                    segment addresses of the mappable memory regions whose
                    mapping contexts are to be saved.  The segment address must
                    be a mappable segment.  Use Function 25 to determine which
                    segments are mappable.

         ES:DI = dest_array
                    Contains a pointer to the destination array address in
                    Segment:Offset format.  To determine the size of the
                    required array, see the Get Size of Partial Page Map Save
                    Array subfunction.

         RESULTS

                                                                      46







         These results are valid only if the status returned is zero.

         dest_array
                    The array contains the partial mapping context and any
                    additional information necessary to restore this context to
                    its original state when the program invokes a Set
                    subfunction.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has saved the partial map context.

         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 = 8Bh   NON-RECOVERABLE
                    One of the specified segments is not a mappable segment.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A3h   NON-RECOVERABLE
                    The contents of the partial page map structure have been
                    corrupted, the pointer passed to the subfunction is
                    invalid, or the mappable_segment_count exceeds the number
                    of mappable segments in the system.

         EXAMPLE

         partial_page_map                   partial_page_map_struct <>
         dest_array                         DB ? DUP (?)

         MOV  AX, SEG partial_page_map
         MOV  DS, AX
         LEA  SI, partial_page_map          ; DS:SI points to
         MOV  AX, SEG dest_array            ; partial_page_map
         MOV  ES, AX
         LEA  DI, dest_array                ; ES:DI points to dest_array
         MOV  AX, 4F00h                     ; 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


                                                                      47







    FUNCTION 16   GET/SET PARTIAL PAGE MAP (CONTINUED)

         SET PARTIAL PAGE MAP SUBFUNCTION

         PURPOSE

         The Set Partial Page Map subfunction provides a mechanism for
         restoring the mapping context for a partial mapping context for
         specific mappable memory regions in a system.  Because this function
         restores only a subset of the entire mapping context and not the
         entire systems mapping context, it uses much less memory for the save
         area and is potentially faster than Function 15.  The subfunction does
         this by copying the contents of the source array to selected mapping
         registers on each expanded memory board.  The application passes a
         pointer to the source array.  Use this function instead of Functions 8
         and 9 if you need to save or restore the mapping context but don't
         want (or have) to use a handle.

         CALLING PARAMETERS

         AX = 4F01h
                    Contains the Set Partial Page Map subfunction.

         source_array DB  ?  DUP  (?)

         DS:SI = source_array
                    Contains a pointer to the source array in segment:offset
                    format.  The application must point to an array which
                    contains the partial mapping register state.  To determine
                    the size of the required array, see the Get Size of Partial
                    Page Map Save Array subfunction.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has restored the partial mapping context.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.



                                                                      48







         AH = A3h   NON-RECOVERABLE
                    The contents of the source array have been corrupted, or
                    the pointer passed to the subfunction is invalid.

         EXAMPLE

         MOV  AX, SEG source_array
         MOV  DS, AX
         LEA  SI, source_array              ; DS:SI points to source_array
         MOV  AX, 4F01h                     ; 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













































                                                                      49







    FUNCTION 16   GET/SET PARTIAL PAGE MAP (CONTINUED)

         GET SIZE OF PARTIAL PAGE MAP SAVE ARRAY SUBFUNCTION

         PURPOSE

         The Return Size subfunction returns the storage requirements for the
         array passed by the other two subfunctions.  This subfunction doesn't
         require an EMM handle.

         CALLING PARAMETERS

         AX = 4F02h
                    Contains the Get Size of Partial Page Map Save Array
                    subfunction.  The size of this array depends on the
                    expanded memory system configuration and the implementation
                    of the expanded memory manager.  Therefore, it will vary
                    between hardware configurations and implementations and
                    must be determined after a specific memory manager is
                    loaded.

         BX = number of pages in the partial array
                    Contains the number of pages in the partial map to be saved
                    by the Get/Set Partial Page Map subfunctions.  This number
                    should be the same as the mappable_segment_count in the Get
                    Partial Page Map subfunction.

         Results

         These results are valid only if the status returned is zero.

         AL = size_of_partial_save_array
                    Contains the number of bytes that will be transferred to
                    the memory area supplied by an application whenever a
                    program requests the Get or Set subfunction.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array size.

         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.


                                                                      50







         AH = 8Bh   NON-RECOVERABLE
                    The number of pages in the partial array is outside the
                    range of physical pages in the system.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         number_of_pages_to_map             DW  ?
         size_of_partial_save_array         DB  ?

         MOV  BX, number_of_pages_to_map
         MOV  AX, 4F02h                     ; 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  size_of_partial_save_array, AL; save array size








































                                                                      51







    FUNCTION 17   MAP/UNAMP MULTIPLE HANDLE PAGES

         PURPOSE

         This function can, in a single invocation, map (or unmap) logical
         pages into as many physical pages as the system supports.
         Consequently, it has less execution overhead than mapping pages one at
         a time.  For applications which do a lot of page mapping, this is the
         preferred mapping method.

         MAPPING MULTIPLE PAGES

         The handle passed to this function determines what type of logical
         pages are being mapped.  Logical pages that Function 4 and Function 27
         (Allocate Standard Pages subfunction) allocate are referred to as
         pages and are 16K bytes.  Logical pages that Function 27 (Allocate Raw
         Pages subfunction) allocates are referred to as raw pages and might
         not be the same size as the pages Function 4 and Function 27 (Allocate
         Standard Pages subfunction) allocate.

         UNMAPPING MULTIPLE PAGES

         This function can make specific physical pages unavailable for reading
         or writing.  A logical page which is unmapped from a specific physical
         page cannot be read or written from that physical page.  The logical
         page which is unavailable (unmapped) can be made available again by
         mapping it, or a new logical page, at the physical page that was
         unmapped. Unmapping a physical page is accomplished by setting the
         logical page it is associated with to FFFFh.

         You might unmap an entire set of mapped pages, for example, before
         loading and executing a program.  This ensures that the loaded program
         won't be able to access the pages your program has mapped.  However,
         you must save the mapping context before you unmap the physical pages.
         This enables you to restore it later so that you may access the memory
         you had mapped there.  You can save the mapping context with Functions
         8, 15, or 16.  You can restore the mapping context with Functions 9,
         15, or 16.

         MAPPING AND UNMAPPING MULTIPLE PAGES SIMULTANEOUSLY

         Both mapping and unmapping pages can be done in the same invocation.

         Mapping or unmapping no pages is not considered an error.  If a
         request to map or unmap zero pages is made, nothing is done and no
         error is returned.

         ALTERNATE MAPPING AND UNMAPPING METHODS

         You can map or unmap pages using two methods.  Both methods produce
         identical results.

         1   The first method specifies both a logical page and a physical page
             at which the logical page is to be mapped.  This method is an
             extension of Function 5 (Map Handle Page).



                                                                      52







         2   The second method specifies both a logical page and a
             corresponding segment address at which the logical page is to be
             mapped.  While this is functionally the same as the first method,
             it may be easier to use the actual segment address of a physical
             page than to use a number which only represents its location.  The
             memory manager verifies whether the specified segment address
             falls on the boundary of a mappable physical page.  The manager
             then translates the segment address passed to it into the
             necessary internal representation to map the pages.

         MAP/UNMAP MULTIPLE HANDLE PAGES

         LOGICAL PAGE/PHYSICAL PAGE METHOD

         CALLING PARAMETERS

         AX = 5000h
                    Contains the Map/Unmap Multiple Handle Pages subfunction
                    using the logical page/physical page method.

         log_to_phys_map_struct   STRUC
            log_page_number       DW  ?
            phys_page_number      DW  ?
         log_to_phys_map_struct   ENDS

         DX = handle
                    Contains the EMM handle.

         CX = log_to_phys_map_len
                    Contains the number of entries in the array.  For example,
                    if the array contained four pages to map or unmap, then CX
                    would contain 4.  The number in CX should not exceed the
                    number of mappable pages in the system.

         DS:SI = pointer to log_to_phys_map array
                    Contains a pointer to an array of structures that contains
                    the information necessary to map the desired pages.  The
                    array is made up of the following two elements:

         .log_page_number
                    The first member is a word which contains the number of the
                    logical page which is to be mapped.  Logical pages are
                    numbered zero relative, so the number for a logical page
                    can only range from zero to (maximum number of logical
                    pages allocated to the handle - 1).

                    If the logical page number is set to FFFFh, the physical
                    page associated with it is unmapped rather than mapped.
                    Unmapping a physical page makes it inaccessible for reading
                    or writing.

         .phys_page_number
                    The second member is a word which contains the number of
                    the physical page at which the logical page is to be
                    mapped.  Physical pages are numbered zero relative, so the
                    number for a physical page can only range from zero to


                                                                      53







                    (maximum number of physical pages supported in the system -
                    1).

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The logical pages have been mapped, or unmapped, at the
                    specified physical pages.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager couldn't find the specified EMM handle.  The
                    manager doesn't currently have any information pertaining
                    to the specified EMM handle.  The program has probably
                    corrupted its EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Ah   RECOVERABLE
                    One or more of the mapped logical pages is out of the range
                    of logical pages allocated to the EMM handle.  The program
                    can recover by attempting to map a logical page which is
                    within the bounds for the specified EMM handle.  When this
                    error occurs, the only pages mapped were the ones valid up
                    to the point that the error occurred.

         AH = 8Bh   RECOVERABLE
                    One or more of the physical pages is out of the range of
                    mappable physical pages, or the log_to_phys_map_len exceeds
                    the number of mappable pages in the system.  The program
                    can recover from this condition by attempting to map into
                    memory at a physical page which is in the range of the
                    physical page numbers supported by the system.  When this
                    error occurs, the only pages mapped were the ones valid up
                    to the point that the error occurred.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         log_to_phys_map                    log_to_phys_map_struct ? DUP (?)
         emm_handle                         DW ?

         MOV  AX, SEG log_to_phys_map       ; DS:SI points to

                                                                      54







         MOV  DS, AX                        ; log_to_phys_map
         LEA  SI, log_to_phys_map
         MOV  CX, LENGTH log_to_phys_map    ; set length field
         MOV  DX, emm_handle                ; load handle
         MOV  AX, 5000h                     ; 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


















































                                                                      55









         MAP/UNMAP MULTIPLE HANDLE PAGES

         LOGICAL PAGE/SEGMENT ADDRESS METHOD

         CALLING PARAMETERS

         AX = 5001h
                    Contains the Map/Unmap Multiple Handle Pages subfunction
                    using the logical page/segment address method.

         log_to_seg_map_struct         STRUC
            log_page_number            DW  ?
            mappable_segment_address   DW  ?
         log_to_seg_map_struct         ENDS

         DX = handle
                    Contains the EMM handle.

         CX = log_to_segment_map_len
                    Contains the number of entries in the array.  For example,
                    if the array contained four pages to map or unmap, then CX
                    would contain four.

         DS:SI = pointer to log_to_segment_map array
                    Contains a pointer to an array of structures that contains
                    the information necessary to map the desired pages.  The
                    array is made up of the following elements:

         .log_page_number
                    The first member is a word which contains the number of the
                    logical pages to be mapped.  Logical pages are numbered
                    zero relative, so the number for a logical page can range
                    from zero to (maximum number of logical pages allocated to
                    the handle - 1).

                    If the logical page number is set to FFFFh, the physical
                    page associated with it is unmapped rather than mapped.
                    Unmapping a physical page makes it inaccessible for reading
                    or writing.

         .mappable_segment_address
                    The second member is a word which contains the segment
                    address at which the logical page is to be mapped.  This
                    segment address must correspond exactly to a mappable
                    segment address.  The mappable segment addresses are
                    available with Function 25 (Get Mappable Physical Address
                    Array)

         REGISTERS MODIFIED

         AX

         STATUS



                                                                      56







         AH = 0     SUCCESSFUL
                    The logical pages have been mapped (or unmapped), at the
                    specified physical pages.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager could not find the specified EMM handle.  The
                    manager doesn't have any information pertaining to the
                    specified EMM handle.  The program has probably corrupted
                    its EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Ah   RECOVERABLE
                    One or more of the logical pages to be mapped is out of the
                    range of logical pages allocated to the EMM handle.  The
                    program can recover from this condition by mapping a
                    logical page which is within the bounds for the specified
                    EMM handle.  When this error occurs, the only pages mapped
                    or unmapped were the ones valid up to the point that the
                    error occurred.

         AH = 8Bh  RECOVERABLE
                    One or more of the mappable segment addresses specified is
                    not mappable, the segment address doesn't fall exactly on a
                    mappable address boundary, or the log_to_segment_map_len
                    exceeds the number of mappable segments in the system. The
                    program can recover from this condition by mapping into
                    memory on an exact mappable segment address.  When this
                    error occurs, the only pages mapped were the ones valid up
                    to the point that the error occurred.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         log_to_seg_map                     log_to_seg_map_struct 4 DUP (?)
         emm_handle                         DW ?

         MOV  AX, SEG log_to_seg_map
         MOV  DS, AX
         LEA  SI, log_to_seg_map            ; DS:SI points to log_to_seg_map
         MOV  CX, LENGTH log_to_seg_map     ; load # of segments to
                                            ; map/unmap
         MOV  DX, emm_handle                ; load handle
         MOV  AX, 5001h                     ; load function code
         INT  67h                           ; call the memory manager
         OR   AH, AH                        ; check EMM status

                                                                      57







         JNZ  emm_err_handler               ; jump to error handler on error

























































                                                                      58







    FUNCTION 18   REALLOCATE PAGES

         PURPOSE

         This function allows an application program to increase or decrease
         (reallocate) the number of logical pages allocated to an EMM handle.
         There are four reallocation cases of interest:

         1   A reallocation count of zero.  The handle assigned to application
             remains assigned and is still available for use by the
             application.  The memory manager won't reassign the handle to any
             other application.  However, the handle will have any currently
             allocated pages returned to the memory manager.  The application
             must invoke the Deallocate Pages function (Function 6) before
             returning to DOS, or the handle will remain assigned and no other
             application will be able to use it.

         2   A reallocation count equal to the current allocation count.  This
             is not treated as an error, and a successful status is returned.

         3   A reallocation count greater than the current allocation count.
             The memory manager will attempt to add new pages to those pages
             already allocated to the specified EMM handle.  The number of new
             pages added is the difference between the reallocation count and
             the current allocation count.  The sequence of logical pages
             allocated to the EMM handle remains continuous after this
             operation.  The newly allocated pages have logical page numbers
             which begin where the previously allocated pages ended, and
             continue in ascending sequence.

         4   A reallocation count less than the current allocation count.  The
             memory manager will attempt to subtract some of the currently
             allocated pages and return them to the memory manager.  The number
             of old pages subtracted is the difference between the current
             allocation count and the re-allocation count.  The pages are
             subtracted from the end of the sequence of pages currently
             allocated to the specified EMM handle.  The sequence of logical
             pages allocated to the EMM handle remains continuous after this
             operation.

         The handle determines what type of logical pages are being
         reallocated.  Logical pages which were originally allocated with
         Function 4 or Function 27 (Allocate Standard Pages subfunction) are
         called pages and are 16K bytes long.  Logical pages which were
         allocated with Function 27 (Allocate Raw Pages subfunction) are called
         raw pages and might not be the same size as pages allocated with
         Function 4 or Function 27 (Allocate Standard Pages subfunction).

         CALLING PARAMETERS

         AH = 51h
                    Contains the Reallocate Handle Pages function.

         DX = handle
                    Contains the EMM handle.



                                                                      59







         BX = reallocation_count
                    Contains the total number of pages this handle should have
                    allocated to it after this function is invoked.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = number of pages allocated to handle after reallocation
                    Contains the number of pages now allocated to the EMM
                    handle after the pages have been added or subtracted.  If
                    the status returned is not zero, the value in BX is equal
                    to the number of pages allocated to the handle prior to the
                    invocation of this function.  This information can be used
                    to verify that the request generated the expected results.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 00h   SUCCESSFUL
                    The pages specified have been added or subtracted to or
                    from the handle specified.

         AH = 80h   NON-Recoverable the manager has detected a malfunction in
                    the memory manager software.

         AH = 81h   NON-Recoverable the manager has detected a malfunction in
                    the expanded memory hardware.

         AH = 83h   NON-Recoverable the manager could not find the specified
                    EMM handle.  The manager doesn't have any information
                    pertaining to the specified EMM handle.  The program may
                    have corrupted its EMM handle.

         AH = 84h   NON-Recoverable the function code passed to the manager is
                    not defined.

         AH = 87h   Recoverable the number of pages that are available in the
                    system is insufficient for the new allocation request.  The
                    program can recover from this condition by specifying fewer
                    pages be allocated to the EMM handle.

         AH = 88h   Recoverable the number of unallocated pages is insufficient
                    for the new allocation request.  The program can recover
                    from this condition by either requesting again when
                    additional pages are available or specifying fewer pages.

         EXAMPLE

         emm_handle                         DW   ?
         realloc_count                      DW   ?
         current_alloc_page_count           DW   ?

         MOV  DX, emm_handle                ; specify EMM handle

                                                                      60







         MOV  BX, realloc_count             ; specify count
         MOV  AH, 51h                       ; 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  current_alloc_page_count, BX




















































                                                                      61







    FUNCTION 19   GET/SET HANDLE ATTRIBUTE

         DESIGN CONSIDERATIONS

         This function is an option which will probably not be available in a
         typical expanded memory manager, system, or memory board.  Most
         personal computer systems disable memory refresh signals for a
         considerable period during a warm boot.  This can corrupt some of the
         data in memory boards, even though there is no problem with the design
         of the memory board, its operation, or the memory chips.  This memory
         refresh deficiency is present in the software design of the ROM BIOS
         in most personal computer systems.

         The majority of memory board designs, chip types, or personal computer
         systems won't be able to support the non-volatility feature.  The
         reason that this ROM BIOS deficiency is not evident in the
         conventional or extended memory area is that the ROM BIOS always
         initializes this area during a warm boot.  Memory data integrity is
         not a problem with the conventional or extended memory region, because
         it isn't physically possible to have data retained there across a warm
         boot event -- the ROM BIOS sets it to zero.

         Consequently, expanded memory board manufacturers should not supply
         this function unless their board can guarantee the integrity of data
         stored in the board's memory during a warm boot.  Generally, this
         means the memory board has an independent memory refresh controller
         which does not depend on the system board's memory refresh.

         If the expanded memory manager, system, or memory board cannot support
         this feature, it should return the not supported status described in
         the function.



























                                                                      62







    FUNCTION 19   GET/SET HANDLE ATTRIBUTE (CONTINUED)

         GET HANDLE ATTRIBUTE SUBFUNCTION

         PURPOSE

         This subfunction returns the attribute associated with a handle.  The
         attributes are volatile or non-volatile.  Handles with non-volatile
         attributes enable the memory manager to save the contents of a
         handle's pages between warm boots.  However, this function may be
         disabled with a user option or may not be supported by the memory
         board or system hardware.

         If the handle's attribute has been set to non-volatile, the handle,
         its name (if it is assigned one), and the contents of the pages
         allocated to the handle are all maintained after a warm boot.

         CALLING PARAMETERS

         AX = 5200h
                    Contains the Get Handle Attribute subfunction.

         DX = handle
                    Contains the EMM handle.

         RESULTS

         These results are valid only if the status returned is zero.

         AL = handle attribute
                    Contains the EMM handle's attribute.  The only attributes a
                    handle may have are volatile or non-volatile.  A value of
                    zero indicates the handle is volatile.  A value of one
                    indicates that the handle is non-volatile.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The handles attribute has been obtained.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager couldn't find the specified EMM handle.  The
                    manager doesn't have any information pertaining to the
                    specified EMM handle.  The program may have corrupted its
                    EMM handle.

                                                                      63







         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 91h   NON-RECOVERABLE
                    This feature is not supported.

         EXAMPLE

         emm_handle                         DW   ?
         handle_attrib                      DB   ?

         MOV  DX, emm_handle                ; specify EMM handle
         MOV  AX, 5200h                     ; 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  handle_attrib, AL             ; save handle attribute






































                                                                      64







    FUNCTION 19   GET/SET HANDLE ATTRIBUTE (CONTINUED)

         SET HANDLE ATTRIBUTE SUBFUNCTION

         PURPOSE

         This subfunction can be used to modify the attribute which a handle
         has associated with it.  The attributes which a handle may have are
         volatile or non-volatile.  The non-volatile attribute enables the EMM
         to save the contents of a handle's pages between warm boots.  However,
         this function may be disabled with a user option or may not be
         supported by the memory board or system hardware.

         If the handle's attribute has been set to non-volatile, the handle,
         its name (if it is assigned one), and the contents of the pages
         allocated to the handle are all maintained after a warm boot.

         CALLING PARAMETERS

         AX = 5201h
                    Contains the Set Handle Attribute function.

         DX = handle
                    Contains the EMM handle.

         BL = new handle attribute
                    Contains the handle's new attribute.  A value of zero
                    indicates that the handle should be made volatile.  A value
                    of one indicates that the handle should be made non-
                    volatile.

                    A volatile handle attribute instructs the memory manager to
                    deallocate both the handle and the pages allocated to it
                    after a warm boot.  If all handles have the volatile
                    attribute (the default attribute) at warm boot, the handle
                    directory will be empty and all of expanded memory will be
                    initialized to zero immediately after a warm boot.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The handles attribute has been modified.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager could not find the specified EMM handle.  The

                                                                      65







                    manager doesn't have any information pertaining to the
                    specified EMM handle.  The program may have corrupted its
                    EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 90h   NON-RECOVERABLE
                    The attribute type is undefined.

         AH = 91h   NON-RECOVERABLE
                    This feature is not supported.

         EXAMPLE

         emm_handle                         DW   ?
         new_handle_attrib                  DB   ?

         MOV  DX, emm_handle                ; specify EMM handle
         MOV  BL, new_handle_attrib         ; specify the set attribute
         MOV  AX, 5201h                     ; 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































                                                                      66







    FUNCTION 19   GET/SET HANDLE ATTRIBUTE (CONTINUED)

         GET ATTRIBUTE CAPABILITY SUBFUNCTION

         PURPOSE

         This subfunction can be used to determine whether the memory manager
         can support the non-volatile attribute.

         CALLING PARAMETERS

         AX = 5202h
                    Contains the Get Attribute Capability subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         AL = attribute capability
                    Contains the attribute capability.  A value of zero
                    indicates that the memory manager and hardware supports
                    only volatile handles.  A value of one indicates that the
                    memory manager/hardware supports both volatile and non-
                    volatile handles.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The attribute capability has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         attrib_capability                  DB  ?

         MOV  AX, 5202h                     ; 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  attrib_capability, AL         ; save attribute capability

                                                                      67







    FUNCTION 20   GET/SET HANDLE NAME

         GET HANDLE NAME SUBFUNCTION

         PURPOSE

         This subfunction gets the eight character name currently assigned to a
         handle.  There is no restriction on the characters which may be used
         in the handle name (that is, anything from 00h through FFh).

         The handle name is initialized to ASCII nulls (binary zeros) three
         times: when the memory manager is installed, when a handle is
         allocated, and when a handle is deallocated.  A handle with a name
         which is all ASCII nulls, by definition, has no name.  When a handle
         is assigned a name, at least one character in the name must be a non-
         null character in order to distinguish it from a handle without a
         name.

         CALLING PARAMETERS

         AX = 5300h
                    Contains the Get Handle Name function.

         DX = handle number
                    Contains the EMM handle.

         ES:DI = pointer to handle_name array
                    Contains a pointer to an eight-byte array into which the
                    name currently assigned to the handle will be copied.

         RESULTS

         These results are valid only if the status returned is zero.

         handle_name array
                    Contains the name associated with the specified handle.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The handle name has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager couldn't find the specified EMM handle.  The


                                                                      68







                    manager doesn't have any information on the specified EMM
                    handle.  The program may have corrupted its EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         handle_name                        DB 8 DUP (?)
         emm_handle                         DW   ?

         MOV  AX, SEG handle_name
         MOV  ES, AX
         LEA  DI, handle_name               ; ES:DI points to handle_name
         MOV  DX, emm_handle                ; specify EMM handle
         MOV  AX, 5300h                     ; 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




































                                                                      69







    FUNCTION 20   GET/SET HANDLE NAME

         SET HANDLE NAME SUBFUNCTION

         PURPOSE

         This subfunction assigns an eight character name to a handle.  There
         is no restriction on the characters which may be used in the handle
         name.  The full range of values may be assigned to each character in a
         name (that is, 00h through FFh).

         At installation, all handles have their name initialized to ASCII
         nulls (binary zeros).  A handle with a name consisting of all ASCII
         nulls has no name.  When a handle is assigned a name, at least one
         character in the name must be a non-null character in order to
         distinguish it from a handle without a name.  No two handles may have
         the same name.

         A handle can be renamed at any time by setting the handles name to a
         new value.  A handle can have its name removed by setting the handle's
         name to all ASCII nulls.  When a handle is deallocated, its name is
         removed (set to ASCII nulls).

         CALLING PARAMETERS

         AX = 5301h
                    Contains the Set Handle Name function.

         DX = handle number
                    Contains the EMM handle.

         DS:SI = pointer to handle_name
                    Contains a pointer to a byte array which contains the name
                    that is to be assigned to the handle.  The handle name must
                    be padded with nulls if the name is less than eight
                    characters long.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The handle name has been assigned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager couldn't find the specified EMM handle.  The
                    manager doesn't currently have any information pertaining

                                                                      70







                    to the specified EMM handle.  The program may have
                    corrupted its EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A1h   RECOVERABLE
                    A handle with this name already exists.  The specified
                    handle was not assigned a name.

         EXAMPLE

         handle_name                        DB "AARDVARK"
         emm_handle                         DW   ?

         MOV  AX, SEG handle_name
         MOV  DS, AX
         LEA  SI, handle_name               ; DS:SI points to handle_name
         MOV  DX, emm_handle                ; specify EMM handle
         MOV  AX, 5301h                     ; 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
































                                                                      71







    FUNCTION 21   GET HANDLE DIRECTORY

         GET HANDLE DIRECTORY SUBFUNCTION

         PURPOSE

         This function returns an array which contains all active handles and
         the names associated with each.  Handles which have not been assigned
         names have a default name of all ASCII nulls (binary zeros).  When a
         handle is first allocated, or when all the pages belonging to a handle
         are deallocated (that is, an open handle is closed), its default name
         is set to ASCII nulls.  It takes a subsequent assignment of a name for
         a handle to have a name after it has been opened.  The full range of
         values may be assigned to each character in a name (that is, 00h
         through FFh).

         The number of bytes required by the array is:

                   10 bytes * total number of handles

         The maximum size of this array is:

                   (10 bytes/entry) * 255 entries = 2550 bytes.

         CALLING PARAMETERS

         AX = 5400h
                    Contains the Get Handle Directory function.

         handle_dir_struct   STRUC
            handle_value     DW  ?
            handle_name      DB  8  DUP  (?)
         handle_dir_struct   ENDS

         ES:DI = pointer to handle_dir
                    Contains a pointer to an area of memory into which the
                    memory manager will copy the handle directory.  The handle
                    directory is an array of structures.  There are as many
                    entries in the array as there are open EMM handles.  The
                    structure consists of the following elements:

         .handle_value
                    The first member is a word which contains the value of the
                    open EMM handle.

         .handle_name
                    The second member is an 8 byte array which contains the
                    ASCII name associated with the EMM handle.  If there is no
                    name currently associated with the handle, it has a value
                    of all zeros (ASCII nulls).

         RESULTS

         These results are valid only if the status returned is zero.




                                                                      72







         handle_dir
                    Contains the handle values and handle names associated with
                    each handle value.

         AL = number of entries in the handle_dir array
                    Contains the number of entries in the handle directory
                    array.  This is also the same as the number of open
                    handles.  For example, if only one handle is active, AL
                    will contain a one.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The handle directory has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         handle_dir                         handle_dir_struct 255 DUP (?)
         num_entries_in_handle_dir          DB ?

         MOV  AX, SEG handle_dir
         MOV  ES, AX
         LEA  DI, handle_dir                ; ES:DI points to handle_dir
         MOV  AX, 5400h                     ; 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  num_entries_in_handle_dir, AL ; save number of entries












                                                                      73







    FUNCTION 21   GET HANDLE DIRECTORY

         SEARCH FOR NAMED HANDLE SUBFUNCTION

         PURPOSE

         This subfunction searches the handle name directory for a handle with
         a particular name.  If the named handle is found, this subfunction
         returns the handle number associated with the name.  At the time of
         installation, all handles have their names initialized to ASCII nulls.
         A handle with a name which is all ASCII nulls has, by definition, no
         name.  When a handle is assigned a name, at least one character in the
         name must be a non-null character in order to distinguish it from a
         handle without a name.

         CALLING PARAMETERS

         AX = 5401h
                    Contains the Search for Named Handle subfunction.

         DS:SI = handle_name
                    Contains a pointer to an 8-byte string that contains the
                    name of the handle be searched for.

         RESULTS

         These results are valid only if the status returned is zero.

         DX = value of named handle
                    The value of the handle which matches the handle name
                    specified.

         REGISTERS MODIFIED

         AX, DX

         STATUS

         AH = 0     SUCCESSFUL
                    The handle value for the named handle has been found.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.




                                                                      74







         AH = A0h   RECOVERABLE
                    No corresponding handle could be found for the handle name
                    specified.

         AH = A1h   NON-RECOVERABLE
                    A handle found had no name (all ASCII nulls).

         EXAMPLE

         named_handle                       DB  'AARDVARK'
         named_handle_value                 DW  ?

         MOV  AX, SEG named_handle
         MOV  DS, AX
         LEA  SI, named_handle              ; DS:SI points to named_handle
         MOV  AX, 5401h                     ; 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  named_handle_value, DX        ; save value of named handle






































                                                                      75







    FUNCTION 21   GET HANDLE DIRECTORY

         GET TOTAL HANDLES SUBFUNCTION

         PURPOSE

         This subfunction returns the total number of handles that the memory
         manager supports, including the operating system handle (handle value
         0).

         CALLING PARAMETERS

         AX = 5402h
                    Contains the Get Total Handles subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = total_handles
                    The value returned represents the maximum number of handles
                    which a program may request the memory manager to allocate
                    memory to.  The value returned includes the operating
                    system handle (handle value 0).

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The total number of handles supported has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         total_handles                      DW     ?

         MOV  AX, 5402h                     ; 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  total_handles, BX             ; save total handle count

                                                                      76







    FUNCTION 22   ALTER PAGE MAP & JUMP

         PURPOSE

         This function alters the memory mapping context and transfers control
         to the specified address.  It is analogous to the FAR JUMP in the 8086
         family architecture.  The memory mapping context which existed before
         the invocation of this function is lost.

         Mapping no pages and jumping is not considered an error.  If a request
         to map zero pages and jump is made, control is transferred to the
         target address, and this function performs a far jump.

         CALLING PARAMETERS

         AH = 55h
                    Contains the Alter Page Map & Jump function.

         log_phys_map_struct       STRUC
            log_page_number        DW ?
            phys_page_number_seg   DW ?
         log_phys_map_struct       ENDS

         map_and_jump_struct       STRUC
         target_address            DD ?
         log_phys_map_len          DB ?
         log_phys_map_ptr          DD ?
         map_and_jump_struct       ENDS

         AL = physical page number/segment selector
                    Contains a code which indicates whether the value contained
                    in the .log_phys_map.phys_page_number_seg are physical page
                    numbers or are the segment address representation of the
                    physical page numbers.  A zero in AL indicates that the
                    values are physical page numbers.  A one in AL indicates
                    that the values in these members are the segment address
                    representations of the physical page numbers.

         DX = handle number
                    Contains the EMM handle.

         DS:SI = pointer to map_and_jump structure
                    Contains a pointer to a structure that contains the
                    information necessary to map the desired physical pages and
                    jump to the target address.  The structure consists of the
                    following elements:

         .target_address
                    The first member is a far pointer which contains the target
                    address to which control is to be transferred.  The address
                    is represented in segment:offset format.  The offset
                    portion of the address is stored in the low portion of the
                    double word.

         .log_phys_map_len
                    The second member is a byte which contains the number of
                    entries in the array of structures which immediately

                                                                      77







                    follows it.  The array is as long as the application
                    developer needs to map the desired logical pages into
                    physical pages.  The number of entries cannot exceed the
                    number of mappable pages in the system.

         .log_phys_map_ptr
                    The third member is a pointer to an array of structures
                    which contain the logical page numbers and  Alternate DMA
                    register sets physical page numbers or segment addresses at
                    which they are to be mapped.  Each entry in the array of
                    structures contains the following two elements:

         .log_page_number
                    The first member of this structure is a word which contains
                    the number of the logical page to be mapped.

         .phys_page_number_seg
                    The second member of this structure is a word which
                    contains either the physical page number or the segment
                    address representation of the physical page number at which
                    the previous logical page number is to be mapped.  The
                    value passed in AL determines the type of representation.

         REGISTERS MODIFIED

         AX

         Note...............................................................

         Values in registers which don't contain required parameters maintain
         the values across the jump.  The values in registers (with the
         exception of AX) and the flag state at the beginning of the function
         are still in the registers and flags when the target address is
         reached.

         STATUS

         AH = 0     SUCCESSFUL
                    Control has been transferred to the target address.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager could not find the specified EMM handle.  The
                    manager does not currently have any information pertaining
                    to the specified EMM handle.  The program may have
                    corrupted its EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.


                                                                      78







         AH = 8Ah   RECOVERABLE
                    One or more of the logical pages to map into a
                    corresponding physical page is out of the range of logical
                    pages which are allocated to the EMM handle.  The program
                    can recover from this condition by mapping a logical page
                    which is within the bounds for the EMM handle.

         AH = 8Bh   RECOVERABLE
                    One or more of the physical pages is out of the range of
                    allowable physical pages, or the log_phys_map_len exceeds
                    the number of mappable pages in the system.  Physical page
                    numbers are numbered zero relative.  The program can
                    recover from this condition by mapping into memory at a
                    physical page which is in the range of supported physical
                    pages.

         AH = 8Fh   RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         log_phys_map                       log_phys_map_struct (?) DUP (?)
         map_and_jump                       map_and_jump_struct (?)
         emm_handle                         DW ?
         phys_page_or_seg_mode              DB ?

         MOV  AX, SEG map_and_jump
         MOV  DS, AX
         LEA  SI, map_and_jump              ; DS:SI points to map_and_jump
         MOV  DX, emm_handle
         MOV  AH, 55h                       ; load function code
         MOV  AL, phys_page_or_seg_mode     ; specify physical page or seg
                                            ; mode
         INT  67h                           ; call memory manager
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to error handler on error






















                                                                      79







    FUNCTION 23   ALTER PAGE MAP & CALL

         ALTER PAGE MAP & CALL SUBFUNCTION

         PURPOSE

         This subfunction saves the current memory mapping context, alters the
         specified memory mapping context, and transfers control to the
         specified address.  It is analogous to the FAR CALL in the 8086 family
         architecture.  Just as a return from a FAR CALL restores the original
         value in the code segment register, this subfunction restores the
         state of the specified mapping context after the return.

         There is no explicit expanded memory subfunction which emulates a
         return from a FAR CALL.  However, this facility is implicitly
         available through the standard return from a FAR CALL.  The following
         paragraphs describe how this works:

         After this function is invoked, unless an error is detected, the
         memory manager will transfer control to the address specified.  If an
         error occurs, the memory manager returns immediately with the error
         code in the AH register.  Otherwise, the memory manager pushes on the
         stack information which enables it to restore the mapping context
         after the return.

         When the called procedure wants to return to the calling procedure, it
         simply issues a standard FAR RETURN.  The memory manager traps this
         return, restores the specified mapping context, and returns to the
         calling procedure.  The memory manager also returns a status from a
         successful return just as it does for all functions.

         Developers using this subfunction must make allowances for the
         additional stack space this subfunction will use.

         CALLING PARAMETERS

         AH = 56h
                    Contains the Alter Page Map & Call function.

         log_phys_map_struct       STRUC
            log_page_number        DW ?
            phys_page_number_seg   DW ?
         log_phys_map_struct       ENDS

         map_and_call_struct       STRUC
            target_address         DD ?
            new_page_map_len       DB ?
            new_page_map_ptr       DD ?
            old_page_map_len       DB ?
            old_page_map_ptr       DD ?
            reserved               DW  4 DUP (?)
         map_and_call_struct       ENDS

         AL = physical page number/segment selector
                    Contains a code which indicates whether the value contained
                    in the


                                                                      80







         .new_page_map.phys_page_number_seg/.old_page_map.phys_page_number_seg
                    members are physical pages numbers or are the segment
                    address representation of the physical page numbers.  A
                    value of zero in AL indicates that the values in these
                    members are physical page numbers.  A value of one in AL
                    indicates that the values in these members are the segment
                    address representations of the physical page numbers.

         DX = handle number
                    Contains the EMM handle.

         DS:SI = pointer to map_and_call structure
                    Contains a pointer to a structure which contains the
                    information necessary to map the desired physical pages and
                    call the target address.  The structure members are
                    described here:

         .target_address
                    The first member is a far pointer which contains the target
                    address to which control is to be transferred.  The address
                    is represented in segment:offset format.  The offset
                    portion of the address is stored in the low portion of the
                    pointer.  The application must supply this value.

         .new_page_map_len
                    The second member is a byte which contains the number of
                    entries in the new mapping context to which
                    new_page_map_ptr points.  This number cannot exceed the
                    number of mappable pages in the system.

         .new_page_map_ptr
                    The third member is a far pointer that points to an array
                    of structures which contains a list of the logical page
                    numbers and the physical page numbers/segments at which
                    they are to be mapped immediately after the call.  The
                    contents of the new array of structures are described at
                    the end of the map_and_call structure.

         .old_page_map_len
                    The fourth member is a byte which contains the number of
                    entries in the old mapping context to which
                    old_page_map_ptr points.  This number cannot exceed the
                    number of mappable pages in the system.

         .old_page_map_ptr
                    The fifth member is a far pointer that points to an array
                    of structures which contains a list of the logical page
                    numbers and the physical page numbers/segments at which
                    they are to be mapped immediately after the return.  The
                    contents of the old array of structures are described at
                    the end of the map_and_call structure.

         .reserved
                    The sixth member is reserved for use by the memory manager.

         Each entry in the old and new array of structures contains two
         elements:

                                                                      81







         .log_page_number
                    The first member of this structure is a word which contains
                    a logical page number which is to be mapped at the
                    succeeding physical page number/segment immediately after
                    the CALL (in the case of the new array of structures) or
                    after the RETURN (in the case of the old array of
                    structures).

         .phys_page_number_seg
                    The second member of this structure is a word which
                    contains either the physical page number or the segment
                    address representation of the physical page number/segment
                    at which the preceding logical page is to be mapped
                    immediately after the CALL (in the case of the new array of
                    structures) or after the RETURN (in the case of the old
                    array of structures).

         REGISTERS MODIFIED

         AX

         Note..............................................................

         Values in registers which don't contain required parameters maintain
         the values across the call.  The values in registers (with the
         exception of AX) and the flag state at the beginning of the function
         are still in the registers and flags when the target address is
         reached.

         STATUS

         AH = 0     SUCCESSFUL
                    Control has been transferred to the target address.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager couldn't find the specified EMM handle.  The
                    manager doesn't have any information pertaining to the
                    specified EMM handle.  The program may have corrupted its
                    EMM handle.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Ah   RECOVERABLE
                    One or more of the logical pages to map into a
                    corresponding physical page is out of the range of logical
                    pages which are allocated to the EMM handle.  The program
                    can recover from this condition by mapping a logical page
                    which is within the bounds for the EMM handle.

                                                                      82







         AH = 8Bh   RECOVERABLE
                    One or more of the physical pages is out of the range of
                    allowable physical pages, or you've specified more physical
                    pages than exist in the system.  Physical page numbers are
                    numbered zero relative.  The program can recover from this
                    condition by mapping a physical page which is in the range
                    from zero to three.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         new_page_map             log_phys_map_struct (?) DUP (?)
         old_page_map             log_phys_map_struct (?) DUP (?)
         map_and_call             map_and_call_struct (?)
         emm_handle               DW ?
         phys_page_or_seg_mode    DB ?

         MOV  AX, SEG map_and_call
         MOV  DS, AX
         LEA  SI, map_and_call              ; DS:SI points to map_and_call
         MOV  DX, emm_handle                ; specify EMM handle
         MOV  AH, 56h                       ; load function code
         MOV  AL, phys_page_or_seg_mode     ; specify physical page or seg
                                            ; mode
         INT  67h                           ; control is actually
                                            ; transferred to the called
                                            ; procedure at this point
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to error handler on error



























                                                                      83







    FUNCTION 23   ALTER PAGE MAP & CALL

         GET PAGE MAP STACK SPACE SIZE SUBFUNCTION

         PURPOSE

         Since the Alter Page Map & Call function pushes additional information
         onto the stack, this subfunction returns the number of bytes of stack
         space the function requires.

         CALLING PARAMETERS

         AX = 5602h
                    Contains the Get Page Map Stack Space Size subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = stack space required
                    Contains the number of bytes which the Alter Page Map &
                    Call function will require.  In other words, BX contains
                    the number (including the return address) which has to be
                    added to the stack pointer to remove all elements from the
                    stack.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The size of the array has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         stack_space_reqd                   DW ?

         MOV  AX, 5602h                     ; 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

                                                                      84







         MOV  stack_space_reqd, BX          ; save required stack size count

























































                                                                      85







    FUNCTION 24   MOVE/EXCHANGE MEMORY REGION

         MOVE MEMORY REGION SUBFUNCTION

         PURPOSE

         This subfunction copies a region of memory in the following memory
         source/destination combinations.

         o   conventional memory to conventional memory

         o   conventional memory to expanded memory

         o   expanded memory to conventional memory

         o   expanded memory to expanded memory

         You do not have to save and restore the expanded memory mapping
         context to perform these move operations.  The current mapping context
         is maintained throughout this operation.

         The length of the region is limited by the amount of expanded memory
         allocated to the handles specified.

         However, in most practical applications, the region length will be
         considerably smaller.  A region length of zero is not an error, and no
         move will be performed.

         A region length which exceeds 16K bytes is not an error.  In this case
         the function assumes that a group of logical pages is the target for
         the move.  The logical page specified represents the first logical
         page in which the move will take place.  If the region length exceeds
         16K bytes, or if the region is less than 16K bytes but spans logical
         pages, there must be sufficient logical pages remaining after the
         first logical page for the entire region to fit.

         If your application needs to save a region of conventional memory in
         expanded memory, you can move it without having to perform a save or
         restore of the current mapping context.

         The memory manager maintains the context.  A move of up to 1M byte may
         be performed, although practical lengths are substantially less than
         this value.

         If the source and destination handles are identical, the source and
         destination regions are tested for overlap before the move.  If they
         overlap, the move direction is chosen so that the destination region
         receives an intact copy of the source region.  A status will be
         returned indicating that this overlap has occurred.

         CALLING PARAMETERS

         AX = 5700h
                    Contains the Move Memory Region function.

         move_source_dest_struct      STRUC
            region_length             DD  ?

                                                                      86







            source_memory_type        DB  ?
            source_handle             DW  ?
            source_initial_offset     DW  ?
            source_initial_seg_page   DW  ?
            dest_memory_type          DB  ?
            dest_handle               DW  ?
            dest_initial_offset       DW  ?
            dest_initial_seg_page     DW  ?
         move_source_dest_struct      ENDS

         DS:SI = pointer to exchange_source_dest structure
                    Contains a pointer to a data structure which contains the
                    source and destination information for the exchange.  The
                    structure members are described here:

         .region_length
                    The first member is a double word which specifies the
                    length of the memory region (in bytes) to be moved.

         .source_memory_type
                    The second member is a byte which specifies the type of
                    memory where the source region resides.  A value of zero
                    indicates that the source region resides in conventional
                    memory (excluding the page frame segment).  A value of one
                    indicates that the source region resides in expanded
                    memory.

         .source_handle
                    If the source region resides in expanded memory, the third
                    member is a word which specifies the handle number
                    associated with the source memory region.  If the source
                    region resides in conventional memory, this variable has no
                    meaning and should be set to zero for future compatibility.

         .source_initial_offset
                    The fourth member is a word which specifies the offset
                    within the source region from which to begin the move.  If
                    the source region resides in expanded memory, the
                    source_initial_offset is relative to the beginning of the
                    16K logical page.  Because the offset is relative to the
                    beginning of a 16K expanded memory page, it may only take
                    on values between 0000h and 3FFFh.

                    If the source region resides in conventional memory, the
                    source_initial_offset is a word which specifies the offset,
                    relative to the beginning of the source segment, from which
                    to begin the move.  Because the offset is relative to the
                    beginning of a 64K-byte conventional memory segment, it may
                    take on values between 0000h and FFFFh.

         .source_initial_seg_page
                    The fifth member  is a word which specifies the initial
                    segment or logical page number within the source region
                    from which to begin the move.  If the source region resides
                    in expanded memory, the value specifies the logical page
                    within the source region from which to begin the move.  If
                    the source region resides in conventional memory, the

                                                                      87







                    source_initial_seg_page specifies the initial segment
                    address within conventional memory from which to begin the
                    move.

         .dest_memory_type
                    The sixth member is a byte which specifies the type of
                    memory where the destination region resides.  A value of
                    zero indicates conventional memory; a value of one
                    indicates expanded memory.

         .dest_handle
                    If the destination region resides in expanded memory, the
                    seventh member is a word which specifies the handle number
                    associated with the destination memory region.  If the
                    destination region resides in conventional memory, this
                    variable has no meaning and should be set to zero for
                    future compatibility.

         .dest_initial_offset
                    The eighth member is a word which specifies the offset
                    within the destination region from which to begin the move.

                    If the destination region resides in expanded memory, the
                    dest_initial_offset is relative to the beginning of the
                    16K-byte logical page.  Because the offset is relative to
                    the beginning of a 16K-byte expanded memory page, it may
                    take on values between 0000h and 3FFFh.

                    If the destination region resides in conventional memory,
                    the dest_initial_offset is a word which specifies the
                    offset, relative to the beginning of the destination
                    segment, to begin the move.  Because the offset is relative
                    to the beginning of a 64K conventional memory segment, it
                    may take on values between 0000h and FFFFh.

         .dest_initial_seg_page
                    The ninth member is a word which specifies the initial
                    segment or logical page number within the destination
                    region from which to begin the move.

                    If the destination region resides in expanded memory then
                    the value specifies the logical page within the destination
                    region from which to begin the exchange.

                    If the destination region resides in conventional memory,
                    the dest_initial_seg_page specifies the initial segment
                    address within conventional memory from which to begin the
                    move.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The memory regions have been moved.

                                                                      88







         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager couldn't find either the source or destination
                    EMM handles.  The memory manager doesn't have any
                    information on the handles specified.  The program may have
                    corrupted its EMM handles.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Ah   NON-RECOVERABLE
                    One or more of the logical pages is out of the range of
                    logical pages allocated to the source/destination handle.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 92h   SUCCESSFUL
                    The source and destination expanded memory regions have the
                    same handle and overlap.  This is valid for a move.  The
                    move has been completed and the destination region has a
                    full copy of the source region.  However, at least a
                    portion of the source region has been overwritten by the
                    move.  Note that the source and destination expanded memory
                    regions with different handles will never physically
                    overlap because the different handles specify totally
                    different regions of expanded memory.

         AH = 93h   CONDITIONALLY-RECOVERABLE
                    The length of the source or destination expanded memory
                    region specified exceeds the length of the expanded memory
                    region allocated either the source or destination handle.
                    Insufficient pages are allocated to this handle to move a
                    region of the size specified.  The program can recover from
                    this condition by allocating additional pages to the
                    destination or source handle and attempting to execute the
                    function again.  However, if the application program
                    allocated as much expanded memory as it thought it needed,
                    this may be a program error and is not recoverable.

         AH = 94h   NON-RECOVERABLE
                    The conventional memory region and expanded memory region
                    overlap.  This is invalid, the conventional memory region
                    cannot overlap the expanded memory region.

         AH = 95h   NON-RECOVERABLE
                    The offset within the logical page exceeds the length of
                    the logical page.  The initial source or destination
                    offsets within an expanded memory region must be between
                    0000h and 3FFFh (16383 or (length of a logical page - 1)).

                                                                      89







         AH = 96h   NON-RECOVERABLE
                    Region length exceeds 1M byte.

         AH = 98h   NON-RECOVERABLE
                    The memory source and destination types are undefined.

         AH = A2h   NON-RECOVERABLE
                    An attempt was made to wrap around the 1M-byte address
                    space of conventional memory during the move.  The
                    combination of source/destination starting address and
                    length of the region to be moved exceeds 1M byte.  No data
                    was moved.

         EXAMPLE

         move_source_dest                   move_source_dest_struct (?)

         MOV  AX, SEG move_source_dest
         MOV  DS, AX
         LEA  SI, move_source_dest          ; DS:SI points to
                                            ; move_source_dest
         MOV  AX, 5700h                     ; 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

































                                                                      90







    FUNCTION 24   MOVE/EXCHANGE MEMORY REGION

         EXCHANGE MEMORY REGION SUBFUNCTION

         PURPOSE

         This subfunction exchanges (using a string move) a region of memory in
         any of the following memory source/destination combinations.

         o   conventional memory to conventional memory

         o   conventional memory to expanded memory

         o   expanded memory to conventional memory

         o   expanded memory to expanded memory

         The term expanded memory region refers only to the area of memory
         above 640K bytes (9FFFFh).  If a system provides mappable conventional
         memory, this function treats the mappable conventional memory regions
         as ordinary conventional memory.  The contents of the source region
         and the destination region are exchanged.

         The exchange operation can be performed without having to save and
         restore the expanded memory mapping context.  The current mapping
         context is maintained throughout this operation.  The length of the
         region is limited to the amount of expanded memory allocated to the
         specified EMM handles.  A length of zero is not an error; however, no
         exchange will be performed.  A region length which exceeds 16K bytes
         is not an error.  In this case the function assumes that a group of
         logical pages is the target for the exchange.  The logical page
         specified represents the first logical page in which the exchange will
         take place.  If the region length exceeds 16K bytes, or if the region
         is less than 16K bytes but spans logical pages, there must be
         sufficient logical pages remaining after the first logical page for
         the entire region to fit.

         If your application needs to exchange a region of conventional memory
         with expanded memory, you can simply exchange it with the region of
         interest without having to perform a save or restore of the current
         mapping context.

         An exchange of up to 1M byte may be performed, although practical
         lengths are obviously below that value.  Checking is done before
         starting the exchange to prevent the possibility of overlap during the
         exchange operation.  Overlapping source and destination regions for a
         exchange are invalid, and the exchange will not take place.

         CALLING PARAMETERS

         AX = 5701h
                    Contains the Exchange Memory Region function.

         xchg_source_dest_struct      STRUC
            region_length             DD ?
            source_memory_type        DB ?
            source_handle             DW ?

                                                                      91







            source_initial_offset     DW ?
            source_initial_seg_page   DW ?
            dest_memory_type          DB ?
            dest_handle               DW ?
            dest_initial_offset       DW ?
            dest_initial_seg_page     DW ?
         xchg_source_dest_struct      ENDS

         DS:SI = pointer to move_source_dest structure
                    Contains a pointer to the data structure which contains the
                    source & destination information for the exchange.  The
                    structure members are described here:

         .region_length
                    The first member is a double word which specifies the
                    length of the memory region to be exchanged.

         .source_memory_type
                    The second member is a byte which specifies the type of
                    memory where the source region resides.  A value of zero
                    indicates that the source region resides in conventional
                    memory.  A value of one indicates that the source region
                    resides in expanded memory.

         .source_handle
                    If the source region resides in expanded memory, the third
                    member is a word which specifies the handle number
                    associated with the source memory region.  If the source
                    region resides in conventional memory, this variable has no
                    meaning and should be set to zero for future compatibility.

         .source_initial_offset
                    The fourth member is a word which specifies the offset
                    within the source region from which to begin the exchange.

                    If the source region resides in expanded memory, the
                    source_initial_offset is relative to the beginning of the
                    16K-byte logical page.  Because the offset is relative to
                    the beginning of a 16K-byte expanded memory page, it may
                    only take on values between 0000h and 3FFFh.

                    If the source region resides in conventional memory, the
                    source_initial_offset is a word which specifies the offset,
                    relative to the beginning of the source segment, to begin
                    the exchange at.  Because the offset is relative to the
                    beginning of a 64K-byte conventional memory segment, it may
                    only take on values between 0000h and FFFFh.

         .source_initial_seg_page
                    The fifth member is a word which specifies the initial
                    segment or logical page number within the source region
                    from which to begin the exchange.

                    If the source region resides in expanded memory then the
                    value specifies the logical page within the source region
                    from which to begin the exchange.


                                                                      92







                    If the source region resides in conventional memory, the
                    source_initial_seg_page specifies the initial segment
                    address within conventional memory from which to begin the
                    exchange.

         .dest_memory_type
                    The sixth member is a byte which specifies the type of
                    memory where the destination region resides.  A value of
                    zero indicates that the destination region resides in
                    conventional memory (excluding the page frame segment).  A
                    value of one indicates that the destination region resides
                    in expanded memory.

         .dest_handle
                    If the destination region resides in expanded memory, the
                    seventh member is a word which specifies the handle number
                    associated with the destination memory region.  If the
                    destination region resides in conventional memory , then
                    this variable has no meaning and should be set to zero for
                    future compatibility.

         .dest_initial_offset
                    The eighth member is a word which specifies the offset
                    within the destination region from which to begin the
                    exchange.

                    If the destination region resides in expanded memory, the
                    dest_initial_offset is relative to the beginning of the
                    16K-byte logical page.  Because the offset is relative to
                    the beginning of a 16K-byte expanded memory page, it may
                    only take on values between 0000h and 3FFFh.

                    If the destination region resides in conventional memory,
                    the dest_initial_offset is a word which specifies the
                    offset, relative to the beginning of the destination
                    segment, to begin the exchange at.  Because the offset is
                    relative to the beginning of a 64K-byte conventional memory
                    segment, it may only take on values between 0000h and
                    FFFFh.

         .dest_initial_seg_page
                    The ninth member is a word which specifies the initial
                    segment or logical page number within the destination
                    region from which to begin the exchange.

                    If the destination region resides in expanded memory, the
                    value specifies the logical page within the destination
                    region from which to begin the exchange.

                    If the destination region resides in conventional memory,
                    the dest_initial_seg_page specifies the initial segment
                    address within conventional memory from which to begin the
                    exchange.

         REGISTERS MODIFIED

         AX

                                                                      93







         STATUS

         AH = 0     SUCCESSFUL
                    The memory regions have been exchanged.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 83h   NON-RECOVERABLE
                    The manager could not find either the source or destination
                    EMM handles.  The memory manager does not currently have
                    any information pertaining to the handles specified.  The
                    program may have corrupted its EMM handles.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Ah   NON-RECOVERABLE
                    One or more of the logical pages is out of the range of
                    logical pages allocated to the source/destination handle.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 93h   CONDITIONALLY RECOVERABLE
                    The length of the source or destination expanded memory
                    region specified, exceeds the length of the expanded memory
                    region allocated to the source or destination specified EMM
                    handle.  There are insufficient pages allocated to this
                    handle to exchange a region of the size specified.  The
                    program can recover from this condition by attempting to
                    allocate additional pages to the destination or source
                    handle and attempting to execute the function again.
                    However, if the application program was allocated as much
                    expanded memory as it thought it needed, this may be a
                    program error and is therefore not recoverable.

         AH = 94h   NON-RECOVERABLE
                    The conventional memory region and expanded memory region
                    overlap.  This is invalid, the conventional memory region
                    cannot overlap the expanded memory region.

         AH = 95h   NON-RECOVERABLE
                    The offset within the logical page exceeds the length of
                    the logical page.  The initial source or destination
                    offsets within an expanded memory region must be between
                    0000h and 3FFFh (16383 or (length of a logical page - 1)).

         AH = 96h   NON-RECOVERABLE
                    Region length exceeds 1M Byte limit.



                                                                      94







         AH = 97h   NON-RECOVERABLE
                    The source and destination expanded memory regions have the
                    same handle and overlap.  This is invalid, the source and
                    destination expanded memory regions cannot have the same
                    handle and overlap when they are being exchanged. Note that
                    the source and destination expanded memory regions which
                    have different handles will never physically overlap
                    because the different handles specify totally different
                    regions of expanded memory.

         AH = 98h   NON-RECOVERABLE
                    The memory source and destination types are undefined.

         AH = A2h   NON-RECOVERABLE
                    An attempt was made to wrap around the 1M-byte address
                    space of conventional memory during the exchange.  The
                    source starting address together with the length of the
                    region to be exchanged exceeds 1M byte.  No data was
                    exchanged.

         EXAMPLE

         xchg_source_dest                   xchg_source_dest_struct (?)

         MOV  AX, SEG xchg_source_dest
         MOV  DS, AX
         LEA  SI, xchg_source_dest          ; DS:SI points to
                                            ; xchg_source_dest
         MOV  AX, 5701h                     ; 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


























                                                                      95







    FUNCTION 25   GET MAPPABLE PHYSICAL ADDRESS ARRAY

         GET MAPPABLE PHYSICAL ADDRESS ARRAY SUBFUNCTION

         PURPOSE

         This subfunction returns an array containing the segment address and
         physical page number for each mappable physical page in a system.  The
         contents of this array provide a cross reference between physical page
         numbers and the actual segment addresses for each mappable page in the
         system.  The array is sorted in ascending segment order.  This does
         not mean that the physical page numbers associated with the segment
         addresses are also in ascending order.

         CALLING PARAMETERS

         AX = 5800h
                    Contains the Get Mappable Physical Address Array
                    subfunction.

         mappable_phys_page_struct   STRUC
            phys_page_segment        DW ?
            phys_page_number         DW ?
         mappable_phys_page_struct   ENDS

         ES:DI = mappable_phys_page
                    Contains a pointer to an application-supplied memory area
                    where the memory manager will copy the physical address
                    array.  Each entry in the array is a structure containing
                    two members:

         .phys_page_segment
                    The first member is a word which contains the segment
                    address of the mappable physical page associated with the
                    physical page number following it.  The array entries are
                    sorted in ascending segment address order.

         .phys_page_number
                    The second member is a word which contains the physical
                    page number which corresponds to the previous segment
                    address.  The physical page numbers are not necessarily in
                    ascending order.

         EXAMPLE 1

         An expanded memory board has its page frame starting at address C0000h
         and has no mappable conventional memory.  For this configuration,
         physical page 0 corresponds to segment address C000h, physical page 1
         corresponds to segment address C400h, etc.  The array would contain
         the following data (in this order):

         C000h, 00h
         C400h, 01h
         C800h, 02h
         CC00h, 03h

         EXAMPLE 2

                                                                      96







         An expanded memory board has a large page frame starting at address
         C0000h and has mappable conventional memory from 90000h through
         9FFFFh.  For this configuration, physical page 0 corresponds to
         segment address C000h, physical page 1 corresponds to segment address
         C400h, etc.  The array would contain the following data in the order
         specified.  Note that the expanded memory region always has the lowest
         numerically valued physical page numbers.

         9000h, 0Ch
         9400h, 0Dh
         9800h, 0Eh
         9C00h, 0Fh
         C000h, 00h
         C400h, 01h
         C800h, 02h
         CC00h, 03h
         D000h, 04h
         D400h, 05h
         D800h, 06h
         DC00h, 07h
         E000h, 08h
         E400h, 09h
         E800h, 0Ah
         EC00h, 0Bh

         RESULTS

         These results are valid only if the status returned is zero.

         CX = number of entries in the mappable_phys_page
                    Multiply this number by (SIZE mappable_phys_page_struct) to
                    determine the number of bytes the physical page address
                    array requires.

         REGISTERS MODIFIED

         AX, CX

         STATUS

         AH = 0     SUCCESSFUL
                    The hardware configuration array has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.


                                                                      97







         EXAMPLE

         mappable_phys_page                 mappable_phys_page_struct (?)

         MOV  AX, SEG mappable_phys_page
         MOV  ES, AX
         LEA  DI, mappable_phys_page        ; ES:DI points to
                                            ; mappable_phys_page
         MOV  AX, 5800h                     ; 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  mappable_page_entry_count, CX ; save mappable page entry count













































                                                                      98







    FUNCTION 25   GET MAPPABLE PHYSICAL ADDRESS ARRAY

         GET MAPPABLE PHYSICAL ADDRESS ARRAY ENTRIES SUBFUNCTION

         PURPOSE

         This subfunction gets the number of entries which will be required for
         the array the first subfunction returns.

         CALLING PARAMETERS

         AX = 5801h
                    Contains the Get Physical Page Address Array Entry Count
                    subfunction.  This subfunction returns a word which
                    represents the number of entries in the array returned by
                    the previous subfunction.  This number also represents the
                    number of mappable physical pages in a system.

         RESULTS

         These results are valid only if the status returned is zero.

         CX = number of entries in the mappable_phys_page
                    Multiply this number by (SIZE mappable_phys_page_struct) to
                    determine the number of bytes the physical page address
                    array will require.

         REGISTERS MODIFIED

         AX, CX

         STATUS

         AH = 0     SUCCESSFUL
                    The physical page address array has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         mappable_page_entry_count          DW ?

         MOV  AX, 5801h                     ; load function code
         INT  67h                           ; call memory manager
         OR   AH, AH                        ; check EMM status

                                                                      99







         JNZ  emm_err_handler               ; jump to error handler on error
         MOV  mappable_page_entry_count, CX ; save mappable page entry count
























































                                                                     100







    FUNCTION 26   GET EXPANDED MEMORY HARDWARE INFORMATION

         GET HARDWARE CONFIGURATION ARRAY SUBFUNCTION

         Note..............................................................

         This function is for use by operating systems only.  This function can
         be disabled at any time by the operating system.  Refer to Function 30
         for a description of how an operating system does this.

         PURPOSE

         This subfunction returns an array containing expanded memory hardware
         configuration information for use by an operating system/environment.

         CALLING PARAMETERS

         AX = 5900h
                    Contains the Get Hardware Configuration Array subfunction.

         hardware_info_struct         STRUC
            raw_page_size             DW ?
            alternate_register_sets   DW ?
            context_save_area_size    DW ?
            DMA_register_sets         DW ?
            DMA_channel_operation     DW ?
         hardware_info_struct         ENDS

         ES:DI = hardware_info
                    Contains a pointer to a memory area that the operating
                    system supplies where the memory manager will copy expanded
                    memory hardware information.  The structure contains these
                    five members:

         .raw_page_size
                    The first member is a word which contains the size of a raw
                    mappable physical page in paragraphs (16 bytes).  LIM
                    standard pages are always 16K bytes.  However, other
                    implementations of expanded memory boards do not
                    necessarily comply with this standard and can emulate a
                    16K-byte page by mapping in multiple smaller pages.  This
                    member specifies the size of a mappable physical page
                    viewed from the hardware implementation level.

         .alternate_register_sets
                    The second member is a word which specifies the number of
                    alternate mapping register sets.  The additional mapping
                    register sets are termed alternate mapping register sets in
                    this document.

                    All expanded memory boards have at least one set of
                    hardware registers to perform the logical to physical page
                    mapping.  Some expanded memory boards have more than one
                    set of these mapping registers.  This member specifies how
                    many of these alternate mapping register sets exist (beyond
                    the one set that all expanded memory boards have) on the
                    expanded memory boards in the system.  If an expanded

                                                                     101







                    memory card has only one set of mapping registers (that is,
                    no alternate mapping register sets) this member has a value
                    of zero.

         .context_save_area_size
                    The third member is a word which contains the storage
                    requirements for the array required to save a mapping
                    context.  The value returned in this member is exactly the
                    same as that returned by Function 15 (Get Size of Page Map
                    Save Array subfunction).

         .DMA_channels
                    The fourth member is a word which contains the number of
                    register sets that can be assigned to DMA channels.  These
                    DMA register sets, although similar in use to alternate
                    register sets, are for DMA mapping and not task mapping.

                    If the expanded memory hardware does not support DMA
                    register sets, care must be taken when DMA is taking place.

                    In a multitasking operating system, when one task is
                    waiting for DMA to complete, it is useful to be able to
                    switch to another task.  However, if the DMA is taking
                    place in memory that the second task will need to remap,
                    remapping would be disastrous.

                    If the expanded memory hardware can detect when DMA is
                    occurring, the OS/E should allow task switches and
                    remapping during DMA.  If no special support for DMA is
                    available, no remapping should be done when DMA is in
                    progress.

         .DMA_channel_operation
                    The fifth member is a word which specifies a special case
                    for the DMA register sets.  A value of zero specifies that
                    the DMA register sets behave as described in Function 28.
                    A value of one specifies that the expanded memory hardware
                    has only one DMA register set.  In addition, if any channel
                    is mapped through this register set, then all channels are
                    mapped through it.  For LIM standard boards, this value is
                    zero.

         RESULTS

         These results are valid only if the status returned is zero.

         hardware_info
                    Contains the expanded memory hardware specific information
                    described above.

         REGISTERS MODIFIED

         AX

         STATUS



                                                                     102







         AH = 0     SUCCESSFUL
                    The hardware configuration array has been returned.

         AH = 80h   NON-RECOVERABLE
                    The manager has detected a malfunction in the memory
                    manager software.

         AH = 81h   NON-RECOVERABLE
                    The manager has detected a malfunction in the expanded
                    memory hardware.

         AH = 84h   NON-RECOVERABLE
                    The function code passed to the manager is not defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A4h   NON-RECOVERABLE
                    Access to this function has been denied by the operating
                    system.  The function cannot be used at this time.

         EXAMPLE

         hardware_info                      hardware_info_struct (?)

         MOV  AX, SEG hardware_info
         MOV  ES, AX
         LEA  DI, hardware_info             ; ES:DI points to hardware_info
         MOV  AX, 5900h                     ; 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


























                                                                     103







    FUNCTION 26   GET EXPANDED MEMORY HARDWARE INFORMATION

         GET UNALLOCATED RAW PAGE COUNT SUBFUNCTION

         PURPOSE

         The Get Unallocated Raw Page Count subfunction returns the number of
         unallocated non-standard length mappable pages as well as the total
         number of non-standard length mappable pages in expanded memory to the
         operating system.

         One variety of expanded memory board has a page size which is a sub-
         multiple of 16K bytes.  An expanded memory page which is a sub-
         multiple of 16K is termed a raw page.  An operating system may deal
         with mappable physical page sizes which are sub-multiples of 16K
         bytes.

         If the expanded memory board supplies pages in exact multiples of 16K
         bytes, the number of pages this function returns is identical to the
         number Function 3 (Get Unallocated Page Count) returns.  In this case,
         there is no difference between a page and a raw page.

         CALLING PARAMETERS

         AX = 5901h
                    Contains the Get Unallocated Raw Page Count subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         BX = unallocated raw pages
                    The number of raw pages that are currently available for
                    use.

         DX = total raw pages
                    The total number of raw pages in expanded memory.

         REGISTERS MODIFIED

         AX, BX, DX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the number unallocated raw pages
                    and the number of total raw pages in expanded memory.

         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.



                                                                     104







         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager is not
                    defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         EXAMPLE

         unalloc_raw_pages                  DW ?
         total_raw_pages                    DW ?

         MOV  AX, 5901h                     ; 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  unalloc_raw_pages, BX         ; save unallocated raw page
                                            ; count
         MOV  total_raw_pages, DX           ; save total raw page count







































                                                                     105







    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 implementers 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).  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.


                                                                     106







         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

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has allocated the 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.

         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.


                                                                     107







         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












































                                                                     108







    FUNCTION 27   ALLOCATE STANDARD/RAW PAGES

         ALLOCATE RAW PAGES SUBFUNCTION

         PURPOSE

         The Allocate Raw Pages subfunction 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 Allocate Raw Pages 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) 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 operating 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 implementers 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.

                                                                     109







         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).  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 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

         AX = 5A01h
                    Contains the Allocate Raw Pages subfunction.

         BX = num_of_raw_pages_to_alloc
                    Contains the number of raw pages the operating system wants
                    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

         AH = 0     SUCCESSFUL
                    The manager has allocated the raw pages to an assigned EMM
                    raw handle.



                                                                     110







         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 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





















                                                                     111







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         DESIGN CONSIDERATIONS

         The hardware support for the entire set of subfunctions described is
         generally not present on every expanded memory board from every vendor
         of expanded memory board products.  For some of the subfunctions,
         software emulation is provided.  For other subfunctions, a certain
         protocol in their use must be observed.  The subfunctions for which
         this is most crucial are those which address system DMA capabilities.

         System DMA Capabilities & Expanded Memory Support of DMA

         In a multitasking operating system, when one task is waiting for DMA
         to complete, it is useful to be able to switch to another task.  This
         specification describes a capability which may be designed into
         expanded memory boards to provide DMA into memory regions which may be
         mapped out while the DMA is occurring.  For expanded memory boards
         that do not provide this, it is crucial to understand that while DMA
         is in progress into a region of mappable memory, the memory mapping
         context cannot be changed.  That is, all DMA action must be complete
         before any remapping of pages can be done.

         Expanded Memory Support of DMA Register Sets

         Expanded memory boards which have DMA registers sets could support DMA
         into a region of mappable memory while the memory mapping context is
         being switched.  It is important to realize that these DMA register
         sets are separate from the alternate map register sets.  An example of
         how an OS/E might use DMA registers sets follows:

         EXAMPLE 1

         1.  Allocate a DMA register set.

         2.  Get current register set.

         3.  Set the DMA register set.

         4.  Map in the memory desired.

         5.  Get the DMA register set.

         6.  Set the original register set.

         7.  Assign the desired DMA channel to the DMA register set.

         The preceding set of calls makes all DMA accesses for the desired DMA
         channel get mapped through the current DMA register set regardless of
         the current register set.  In other words, the DMA register set

                                                                     112







         overrides the current mapping register set for DMA operations on the
         DMA channel specified.  A DMA channel that is not assigned to a DMA
         register set has all its DMA operations mapped through the current
         mapping register set.






















































                                                                     113







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         GET ALTERNATE MAP REGISTER SET SUBFUNCTION

         Note..ss...........................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         The subfunction does one of two things depending on the map register
         set which is active at the time this function is invoked:

         1.  If the preceding Set Alternate Map Register Set call was done with
             the alternate map register set equal to zero (BL = 0), these
             points apply:

             a. The context save area pointer saved within EMM by the Set
                Alternate Map Register Set subfunction) is returned by
                this call.  This pointer is always returned for boards
                which do not supply alternate mapping register sets.

             b. If the context save area pointer returned is not equal to
                zero, this subfunction copies the contents of the mapping
                registers on each expanded memory board in the system into
                the save area specified by the pointer.  The format of
                this save area is the same as that returned by Function 15
                (Get Page Map subfunction).  This is intended to simulate
                getting an alternate map register set.  Note that the
                memory manager does not allocate the space for the
                context: the operating system must do so.

             c. If the context save area pointer returned is equal to
                zero, this subfunction does not copy the contents of the
                mapping registers on each expanded memory board in the
                system into the save area specified by the pointer.

             d. The context save area pointer must have been initialized
                by a previous Set Alternate Map Register Set call.  Note
                that the value of the context save area pointer saved
                within EMM is zero immediately after installation.

             e. The context save area must be initialized by a previous
                Get Page Map call (Function 15).

         2.  If the preceding Set Alternate Map Register Set call was done with
             the alternate map register set  greater than zero (BL > 0), then
             the number of the alternate map register set which is in use at
             the time that this function is invoked is returned.  The context
             save area pointer is not returned in this case.

         CALLING PARAMETERS



                                                                     114







         AX = 5B00h
                    Contains the Get Alternate Map Register Set subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         IF (BL <> 0) current active alternate map register set number
                    Contains the alternate map register set which was active at
                    the time that this function was invoked.

         ES:DI
                    Unaffected.

         IF (BL = 0)
                    Indicates that a pointer to an area which contains the
                    state of all the map registers on all boards in the system,
                    and any additional information necessary to restore the
                    boards to their original state, has been returned.

         ES:DI = pointer to a map register context save area
                    Contains a pointer to an operating system supplied context
                    save area.  The pointer is in standard segment:offset
                    format.  This pointer is always returned if the expanded
                    memory hardware does not supply alternate mapping register
                    sets.

         The operating system first passes this pointer to the memory manager
         whenever it invokes a Set Alternate Map Register Set subfunction (the
         description follows).  If the OS/E invokes this function before
         invoking a Set Alternate Map Register Set subfunction, this function
         returns a pointer value of zero.  The OS/E must have allocated the
         space for the save area.  However, the OS must request that the memory
         manager initialize the contents of this save area before it contains
         any useful information.

         The OS/E must initialize the save area it has allocated by invoking
         Function 15 (Get Page Map subfunction).  After the OS/E has done this,
         the save area will contain the state of all the map registers on all
         boards in the system.  The save area will also contain any additional
         information necessary to restore the boards to their original state
         when the operating system invokes a Set Alternate Map Register Set
         subfunction.

         REGISTERS MODIFIED

         AX, BX, ES:DI

         STATUS

         AH = 0     SUCCESSFUL
                    The manager got the alternate map register set.

         AH = 80h   NON-RECOVERABLE
                    The manager detected a malfunction in the memory manager
                    software.


                                                                     115







         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A4h   NON-RECOVERABLE
                    The operating system denied access to this function.  The
                    function cannot be used at this time.

         EXAMPLE

         alt_map_reg_set                    DB ?
         context_save_area_ptr_seg          DW ?
         context_save_area_ptr_offset       DW ?

         MOV  AX, 5B00h                     ; 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  alt_map_reg_set, BL
         TEST BL, BL
         JNZ  no_ptr_returned
         MOV  context_save_area_ptr_seg, ES ; save pointer values
         MOV  context_save_area_ptr_offset,  DI

         no_ptr_returned:


























                                                                     116







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         SET ALTERNATE MAP REGISTER SET SUBFUNCTION

         Notes..............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         The subfunction does one of two things, depending on the map register
         set specified:

         1   If the alternate map register set specified is zero, map register
             set zero is activated.  If the map register context restore area
             pointer is not equal to zero, the contents of the restore area
             pointed to by ES:DI are copied into register set zero on each
             expanded memory board in the system.  If the pointer is equal to
             zero, the contents are not copied.

             Regardless of its value, the map register context restore area
             pointer is saved within the memory manager.  It will be used
             during the Get Alternate Map Register Set subfunction.

             The operating system must supply the pointer to the area.  This
             subfunction is intended to simulate setting an alternate map
             register set.  Note that the operating system must allocate the
             space for the context.  The memory manager saves the context save
             area pointer internally.

         2   If the alternate map register set specified is not zero, the
             alternate map register set specified is activated.  The restore
             area, which the operating system is pointing to, is not used.

         CALLING PARAMETERS

         AX = 5B01h
                    Contains the Set Alternate Map subfunction.

         BL = new alternate map register set number
                    Contains the number of the alternate map register set which
                    is to be activated.

         If BL <> 0
                    A pointer to a map register context restore area is not
                    required and the contents of ES:DI are unaffected and
                    ignored.  The alternate map register set specified in BL is
                    activated if the board supports it.

         If BL = 0
                    A pointer to an area which contains the state of all the
                    map registers on all boards in the system, and any
                    additional information necessary to restore the boards to
                    their original state, has been passed in ES:DI.

                                                                     117







         ES:DI = pointer to a map register context restore area
                    Contains a pointer to an OS/E supplied map register context
                    restore area.  The pointer is in standard segment:offset
                    format.  This pointer must always be passed if the expanded
                    memory hardware does not supply alternate mapping register
                    sets.

                    The memory manager must save this pointer whenever the OS/E
                    invokes this function.  The OS/E must have allocated the
                    space for the restore area.  Additionally, the contents of
                    this restore area must have been initialized by the memory
                    manager before it will contain any useful information.  The
                    OS/E initializes the restore area it has allocated by
                    invoking Function 15 (Get Page Map subfunction).  After the
                    OS/E has done this, the restore area will contain the state
                    of the map registers on all boards in the system, and any
                    additional information necessary to restore the boards to
                    their original state when the operating system invokes a
                    Set Alternate Map Register Set subfunction.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager set the alternate map register set.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Ah   NON-RECOVERABLE
                    Alternate map register sets are supported, but the
                    alternate map register set specified is not supported.

         AH = 9Ch   NON-RECOVERABLE
                    Alternate map register sets are not supported, and the
                    alternate map register set specified is not zero.

         AH = 9Dh   NON-RECOVERABLE
                    Alternate map register sets are supported, but the
                    alternate map register set specified is either not defined
                    or not allocated.


                                                                     118







         AH = A3h   NON-RECOVERABLE
                    The contents of the source array have been corrupted, or
                    the pointer passed to the subfunction is invalid.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         alt_map_reg_set                    DB ?
         context_restore_area_ptr_seg       DW ?
         context_restore_area_ptr_offset    DW ?

         MOV  AX, 5B01h                     ; load function code
         MOV  BL, alt_map_reg_set
         TEST BL, BL
         JZ   no_ptr_passed
         MOV  ES, context_restore_area_ptr_seg
         MOV  DI, context_restore_area_ptr_offset

         no_ptr_passed:

         INT  67h                           ; call the memory manager
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to error handler on error
































                                                                     119







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         GET ALTERNATE MAP SAVE ARRAY SIZE SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         This subfunction returns the storage requirements for the map register
         context save area referenced by the other subfunctions.

         CALLING PARAMETERS

         AX = 5B02h
                    Contains the Get Alternate Map Save Array Size subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         DX = size_of_array
                    Contains the number of bytes that will be transferred to
                    the memory area supplied by an operating system whenever an
                    operating system requests the Get, Set, or Get and Set
                    subfunction.

         REGISTERS MODIFIED

         AX, DX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array size.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.




                                                                     120







         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         size_of_array                      DW ?

         MOV  AX, 5B02h                     ; 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  size_of_array, DX             ; save size of array













































                                                                     121







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         ALLOCATE ALTERNATE MAP REGISTER SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.   Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         The Allocate Alternate Map Register Set subfunction gets the number of
         an alternate map register set for an operating system if an alternate
         map register set is currently available for use.  If the hardware does
         not support alternate map register sets, an alternate map register set
         number of zero will be returned.

         The alternate map register set allocated may be referred to by this
         number when using the Get or Set Alternate Map Register Set
         subfunctions.  The operating system can use these subfunctions to
         switch map contexts very rapidly on expanded memory boards with
         alternate map register sets.

         This subfunction copies the currently active alternate map register
         sets contents into the newly allocated alternate map register set's
         mapping registers.  This is done so that when the OS/E performs a Set
         Alternate Map Register Set subfunction the memory mapped before the
         allocation of the new alternate map will be available for reading and
         writing.  This function does not actually change the alternate map
         register set in use, but in addition to allocating a new alternate map
         register set, it prepares the new alternate map register set for a
         subsequent Set Alternate Map Register Set subfunction.

         CALLING PARAMETERS

         AX = 5B03h
                    Contains the Allocate Alternate Map Register Set
                    subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         BL = alternate map register set number
                    Contains the number of an alternate map register set.  If
                    there are no alternate map register sets supported by the
                    hardware, a zero will be returned.  In this case, the Get
                    Alternate Map function (Function 28) should be invoked in
                    order to obtain a pointer to a map register context save
                    area.  The OS/E must supply this save area.  The save area
                    is necessary because the hardware doesn't support alternate
                    map register sets.

         REGISTERS MODIFIED


                                                                     122







         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array size.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Bh   NON-RECOVERABLE
                    Alternate map register sets are supported.  However, all
                    alternate map register sets are currently allocated.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         alt_map_reg_num                    DB ?

         MOV  AX, 5B03h                     ; 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  alt_map_reg_num, BL           ; save # of alternate map reg
                                            ; set


















                                                                     123







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         DEALLOCATE ALTERNATE MAP REGISTER SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         The Deallocate Alternate Map Register Set subfunction returns the
         alternate map register set to the memory manager for future use.  The
         memory manager may reallocate the alternate map register set when
         needed.

         This subfunction also makes the mapping context of the alternate map
         register specified unavailable for reading or writing (unmapping).
         This protects the pages previously mapped in an alternate map register
         set by making them inaccessible.  Note that the current alternate map
         register set cannot be deallocated.  This makes all memory which was
         currently mapped into conventional and expanded memory inaccessible.

         CALLING PARAMETERS

         AX = 5B04h
                    Contains the Deallocate Alternate Map Register Set
                    subfunction.

         BL = alternate register set number
                    Contains the number of the alternate map register set to
                    deallocate.  Map register set zero cannot be allocated or
                    deallocated.  However, if alternate map register set zero
                    is specified and this subfunction is invoked, no error will
                    be returned.  The function invocation is ignored in this
                    case.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array size.

         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.



                                                                     124







         AH = 84h   NON-RECOVERABLE
                    The function code passed to the memory manager is not
                    defined.

         AH = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Ch   NON-RECOVERABLE
                    Alternate map register sets are not supported and the
                    alternate map register set specified is not zero.

         AH = 9Dh   NON-RECOVERABLE
                    Alternate map register sets are supported, but the
                    alternate map register set specified is either not defined
                    or not allocated.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         alternate_map_reg_set              DB ?

         MOV  AL, alternate_map_reg_set     ; specify alternate map reg set
         MOV  AX, 5B04h                     ; 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





























                                                                     125







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         ALLOCATE DMA REGISTER SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         The Allocate DMA Register Set subfunction gets the number of a DMA
         register set for an OS/E, if a DMA register set is currently available
         for use.  If the hardware does not support DMA register sets, a DMA
         register set number of zero will be returned.

         In a multitasking operating system, when one task is waiting for DMA
         to complete, it is useful to be able to switch to another task.
         However, if the DMA is being mapped through the current register set,
         the switching cannot occur.  That is, all DMA action must be complete
         before any remapping of pages can be done.

         The operating system would initiate a DMA operation on a specific DMA
         channel using a specific alternate map register set.  This alternate
         map register set would not be used again, by the operating system or
         an application, until after the DMA operation is complete.  The
         operating system guarantees this by not changing the contents of the
         alternate map register set, or allowing an application to change the
         contents of the alternate map register set, for the duration of the
         DMA operation.

         CALLING PARAMETERS

         AX = 5B05h
                    Contains the Allocate DMA Register Set subfunction.

         RESULTS

         These results are valid only if the status returned is zero.

         BL = DMA register set number
                    Contains the number of a DMA register set.  If there are no
                    DMA register sets supported by the hardware, a zero will be
                    returned.

         REGISTERS MODIFIED

         AX, BX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has allocated the DMA register set.



                                                                     126







         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Bh   NON-RECOVERABLE
                    DMA register sets are supported.  However, all DMA register
                    sets are currently allocated.

         AH = A4h   NON-RECOVERABLE
                    Access to this function has been denied by the operating
                    system.  The function cannot be used at this time.

         EXAMPLE

         DMA_reg_set_number                 DB ?

         MOV  AX, 5B05h                     ; load function code
         INT  67h                           ; call memory manager
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to error handler on error
         MOV  DMA_reg_set_number, BL        ; save number of DMA register
                                            ; set

























                                                                     127







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         ENABLE DMA ON ALTERNATE MAP REGISTER SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         This subfunction allows DMA accesses on a specific DMA channel to be
         associated with a specific alternate map register set.  In a
         multitasking operating system, when a task is waiting for the
         completion of DMA, it is useful to be able to switch to another task
         until the DMA operation completes.

         Any DMA on the specified channel will go through the specified DMA
         register set regardless of the current register set.  If a DMA channel
         is not assigned to a DMA register set, DMA for that channel will be
         mapped through the current register set.

         CALLING PARAMETERS

         AX = 5B06h
                    Contains the Enable DMA on Alternate Map Register Set
                    subfunction.

         BL = DMA register set number
                    Contains the number of the alternate map register set to be
                    used for DMA operations on the DMA channel specified by DL.
                    If the alternate map register set specified is zero, no
                    special action will be taken on DMA accesses for the DMA
                    channel specified.

         DL = DMA channel number
                    Contains the DMA channel which is to be associated with the
                    DMA map register set specified in BL.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has enabled DMA on the DMA register set and the
                    DMA channel specified.

         AH = 80h   NON-RECOVERABLE
                    The manager detected a malfunction in the memory manager
                    software.




                                                                     128







         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Ah   NON-RECOVERABLE
                    Alternate DMA register sets are supported, but the
                    alternate DMA register set specified is not supported.

         AH = 9Ch   NON-RECOVERABLE
                    Alternate DMA register sets are not supported, and the DMA
                    register set specified is not zero.

         AH = 9Dh   NON-RECOVERABLE
                    DMA register sets are supported, but the DMA register set
                    specified is either not defined or not allocated.

         AH = 9Eh   NON-RECOVERABLE
                    Dedicated DMA channels are not supported.

         AH = 9Fh   NON-RECOVERABLE
                    Dedicated DMA channels are supported.  But the DMA channel
                    specified is not supported.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         alt_map_reg_set                    DB ?
         DMA_channel_num                    DB ?

         MOV  BL, alt_map_reg_set
         MOV  DL, DMA_channel_num
         MOV  AX, 5B06h                     ; 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













                                                                     129







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         DISABLE DMA ON ALTERNATE MAP REGISTER SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         This subfunction disables DMA accesses for all DMA channels which were
         associated with a specific alternate map register set.

         CALLING PARAMETERS

         AX = 5B07h
                    Contains the Disable DMA on Alternate Map Register Set
                    subfunction.

         BL = alternate register set number
                    Contains the number of the DMA register set for which all
                    operations are to be disabled.  If the alternate map
                    register set specified is zero, no action will be taken.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has returned the array size.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Ah   NON-RECOVERABLE
                    Alternate DMA register sets are supported, but the
                    alternate DMA register set specified is not supported.




                                                                     130







         AH = 9Ch   NON-RECOVERABLE
                    Alternate DMA register sets are not supported, and the DMA
                    register set specified is not zero.

         AH = 9Dh   NON-RECOVERABLE
                    DMA register sets are supported, but the DMA register set
                    specified is either not defined or not allocated.

         AH = 9Eh   NON-RECOVERABLE
                    Dedicated DMA channels are not supported.

         AH = 9Fh   NON-RECOVERABLE
                    Dedicated DMA channels are supported, but the DMA channel
                    specified is not supported.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         DMA_reg_set                        DB ?

         MOV  BL, DMA_reg_set
         MOV  AX, 5B07h                     ; 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






























                                                                     131







    FUNCTION 28   ALTERNATE MAP REGISTER SET

         DEALLOCATE DMA REGISTER SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.  Refer to Function 30
         for a description of how an operating system can enable or disable
         this function.

         PURPOSE

         The Deallocate DMA Register Set subfunction deallocates the specified
         DMA register set.

         CALLING PARAMETERS

         AX = 5B08h
                    Contains the Deallocate DMA Register Set subfunction.

         BL = DMA register set number
                    Contains the number of the DMA register set which should
                    not be used for DMA operations any longer.  The DMA
                    register set would have been previously allocated and
                    enabled for DMA operations on a specific DMA channel.  If
                    the DMA register set specified is zero, no action will be
                    taken.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has deallocated the DMA register set.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = 9Ch   NON-RECOVERABLE
                    DMA register sets are not supported, and the DMA register
                    set specified is not zero.


                                                                     132







         AH = 9Dh   NON-RECOVERABLE
                    DMA register sets are supported, but the DMA register set
                    specified is either not defined or not allocated.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.

         EXAMPLE

         DMA_reg_set_num                    DB  ?

         MOV  DMA_reg_set_num, BL
         MOV  AX, 5B08h                     ; load function code
         INT  67h                           ; call memory manager
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to error handler on error









































                                                                     133







    FUNCTION 29   PREPARE EXPANDED MEMORY HARDWARE FOR WARM BOOT

         PURPOSE

         This function prepares the expanded memory hardware for an impending
         warm boot.  This function assumes that the next operation that the
         operating system performs is a warm boot of the system.  In general,
         this function will effect the current mapping context, the alternate
         register set in use, and any other expanded memory hardware
         dependencies which need to be initialized at boot time.  If an
         application decides to map memory below 640K, the application must
         trap all possible conditions leading to a warm boot and invoke this
         function before performing the warm boot itself.

         CALLING PARAMETERS

         AH = 5Ch
                    Contains the Prepare for Warmboot function.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The manager has prepared the expanded memory hardware for a
                    warm boot.

         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.

         EXAMPLE

         MOV  AH, 5Ch                       ; 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











                                                                     134







    FUNCTION 30   ENABLE/DISABLE OS/E FUNCTION SET FUNCTIONS

         ENABLE OS/E FUNCTION SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.

         PURPOSE

         This subfunction provides an OS/E with the ability to enable all
         programs or device drivers to use the OS/E specific functions.  The
         capability is provided only for an OS/E which manages regions of
         mappable conventional memory and cannot permit programs to use any of
         the functions which affect mappable conventional memory regions, but
         must be able to use these functions itself.  When an OS/E disables
         these functions and a program attempts to use them, the memory manager
         returns a status to the program indicating that the OS/E has denied
         the program access to the function.  In other words, the functions
         will not work when disabled.  However, all programs may use them when
         enabled.  The OS/E (Operating System/Environment) functions this
         subfunction enables are:

         Function 26.  Get Expanded Memory Hardware Information.

         Function 28.  Alternate Map Register Sets.

         Function 30.  Enable/Disable Operating System Functions.

         It appears contradictory that the OS/E can re-enable these functions
         when the function which re-enables them is itself disabled.  An
         overview of the process follows.

         The memory manager enables all the OS/E specific functions, including
         this one, when it is loaded.  The OS/E gets exclusive access to these
         functions by invoking either of the Enable/Disable OS/E Function Set
         subfunctions before any other software does.

         On the first invocation of either of these subfunctions, the memory
         manager returns an access_key which the OS/E must use in all future
         invocations of either of these subfunctions.  The memory manager does
         not require the access_key on the first invocation of the
         Enable/Disable OS/E Function Set subfunctions.

         ENABLE OS/E FUNCTION SET SUBFUNCTION

         On all subsequent invocations, the access_key is required for either
         the Enable or Disable OS/E Function Set subfunctions.  Since the
         access_key is returned only on the first invocation of the
         Enable/Disable OS/E Function Set subfunctions, and presumably the OS/E
         is the first software to invoke this function, only the OS/E obtains a
         copy of this key.  The memory manager must return an access key with a
         random value, a fixed value key defeats the purpose of providing this
         level of security for an OS/E.

         CALLING PARAMETERS

                                                                     135







         AX = 5D00h
                    Contains the Enable OS/E Function Set subfunction.

         BX,CX = access_key
                    Required on all function invocations after the first.  The
                    access_key value returned by the first function invocation
                    is required.

         RESULTS

         These results are valid only if the status returned is zero.

         BX,CX = access_key
                    Returned only on the first function invocation, the memory
                    manager returns a random valued key which will be required
                    thereafter for the execution of this function.  On all
                    invocations after the first, this key is not returned.
                    Neither BX or CX is affected after the first time this
                    function is invoked.

         REGISTERS MODIFIED

         AX, BX, CX

         STATUS

         AH = 0     SUCCESSFUL
                    The operating system function set has been enabled.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.  The value of the
                    key which was passed to this function does not entitle the
                    program to execute this function.

         EXAMPLE

         First invocation

         access_key                         DW 2 DUP (?)

         MOV  AX, 5D00h                     ; load function code

                                                                     136







         INT  67h                           ; call the memory manager
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to error handler on error
         MOV  access_key[0], BX
         MOV  access_key[2], CX

         All invocations after the first

         access_key                         DW 2 DUP (?)

         MOV  BX, access_key[0]
         MOV  CX, access_key[2]
         MOV  AX, 5D00h                     ; load function code
         INT  67h                           ; call the memory manager
         OR   AH, AH                        ; check EMM status
         JNZ  emm_err_handler               ; jump to test handler on error










































                                                                     137







    FUNCTION 30   ENABLE/DISABLE OS/E FUNCTION SET FUNCTIONS

         DISABLE OS/E FUNCTION SET SUBFUNCTION

         Note...............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.

         PURPOSE

         This subfunction provides an OS/E with the ability to disable all
         programs or device drivers from using the OS/E specific functions.
         The capability is provided only for an OS/E which manages regions of
         mappable conventional memory and cannot permit programs to use any of
         the functions which would affect mappable conventional memory regions.
         When an OS/E disables these functions and a program attempts to use
         them, the memory manager returns a status to the program indicating
         that the OS/E has denied the program access to the function.  In other
         words, the functions will not work when disabled.

         The OS/E (Operating System) functions which are disabled by this
         subfunction are:

         Function 26.  Get Expanded Memory Hardware Information.

         Function 28.  Alternate Map Register Sets.

         Function 30.  Enable/Disable Operating System Functions.

         CALLING PARAMETERS

         AX = 5D01h
                    Contains the Disable OS/E Function Set subfunction.

         BX,CX = access_key
                    Required on all function invocations after the first.  The
                    access_key value returned by the first function invocation
                    is required.

         RESULTS

         These results are valid only if the status returned is zero.

         BX,CX = access_key
                    Returned only on the first function invocation, the memory
                    manager returns a random valued key which will be required
                    thereafter for the execution of this function.  On all
                    invocations after the first, this key is not returned.
                    Neither BX nor CX is affected after the first time this
                    function is invoked.

         REGISTERS MODIFIED

         AX, BX, CX

         STATUS

                                                                     138







         AH = 0     SUCCESSFUL
                    The operating system function set has been disabled.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A4h   NON-RECOVERABLE
                    The operating system has denied access to this function.
                    The function cannot be used at this time.  The value of the
                    key which was passed to this function does not entitle the
                    program to execute this function.

         EXAMPLE

         First Function invocation:

         access_key                         DW 2 DUP (?)

         MOV  AX, 5D01h                     ; 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  access_key[0], BX
         MOV  access_key[2], CX

         All invocations after the first:

         access_key                         DW 2 DUP (?)

         MOV  BX, access_key[0]
         MOV  CX, access_key[2]
         MOV  AX, 5D01h                     ; 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











                                                                     139







    FUNCTION 30   ENABLE/DISABLE OS/E FUNCTION SET FUNCTIONS

         RETURN ACCESS KEY SUBFUNCTION

         Note.............................................................

         This function is for use by operating systems only.  The operating
         system can disable this function at any time.

         PURPOSE

         This subfunction provides an OS/E with the ability to return the
         access key to the memory manager.  Returning the access key to the
         memory manager places the memory manager in the state it is in at
         installation time (regarding the use of the OS/E function set and the
         access key).  That is, access to the OS/E function set is enabled.
         Upon execution of the next enable/disable OS/E function set
         subfunction, the access key will once again be returned.

         CALLING PARAMETERS

         AX = 5D02h
                    Contains the Return Access Key subfunction.

         BX,CX = access_key
                    Required on all function invocations.  The access_key value
                    returned by the first function invocation of the enable or
                    disable subfunctions is required.

         REGISTERS MODIFIED

         AX

         STATUS

         AH = 0     SUCCESSFUL
                    The access key has been returned to the memory manager.

         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 = 8Fh   NON-RECOVERABLE
                    The subfunction parameter is invalid.

         AH = A4h   NON-RECOVERABLE
                    Access to this function has been denied by the operating
                    system.  The function cannot be used at this time.  The


                                                                     140







                    value of the key which was passed to this function does not
                    entitle the program to execute this function.

         EXAMPLE

         access_key                         DW 2 DUP (?)

         MOV  BX, access_key[0]
         MOV  CX, access_key[2]
         MOV  AX, 5D02h                     ; 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













































                                                                     141







    APPENDIX A    FUNCTION AND STATUS CODE CROSS REFERENCE TABLES

         This appendix contains two cross reference tables: one lists this
         function codes and the status codes they return; the other lists the
         status codes and the functions that return them.

         TABLE A-1.  FUNCTION AND STATUS CODE CROSS REFERENCE

         ----------------------------------------------------------------------
         Function   Status       Description
         ----------------------------------------------------------------------

         40h   00h 80h 81h 84h   Get memory manager status

         41h   00h 80h 81h 84h   Get Page Frame Segment Address

         42h   00h 80h 81h 84h   Get Unallocated Page Count

         43h   00h 80h 81h 84h   Allocate Pages
               85h 87h 88h

         44h   00h 80h 81h 83h   Map/Unmap Handle Page
               84h 8Ah 8Bh

         45h   00h 80h 81h 83h   Deallocate Pages
               84h 86h

         46h   00h 80h 81h 84h   Get EMM Version

         47h   00h 80h 81h 83h   Save Page Map
               84h 8Ch 8Dh

         48h   00h 80h 81h 83h   Restore Page Map
               84h 8Eh

         49h                     Reserved

         4Ah                     Reserved

         4Bh   00h 80h 81h 84h   Get EMM Handle Count

         4Ch   00h 80h 81h 83h   Get EMM Handle Pages
               84h

         4Dh   00h 80h 81h 84h   Get All EMM Handle Pages

         4E00h 00h 80h 81h 84h   Get Page Map
               8Fh

         4E01h 00h 80h 81h 84h   Set Page Map
               8Fh A3h

         4E02h 00h 80h 81h 84h   Get & Set Page Map
               8Fh A3h

         4E03h 00h 80h 81h 84h   Get Size of Page Map Save Array
               8Fh

                                                                     142







         4F00h 00h 80h 81h 84h   Get Partial Page Map
               8Bh 8Fh A3h

         4F01h 00h 80h 81h 84h   Set Partial Page Map
               8Fh A3h

         4F02h 00h 80h 81h 84h   Get Size of Partial Page Map Array
               8Bh 8Fh

         5000h 00h 80h 81h 83h   Map/Unmap Multiple Handle Pages
               84h 8Ah 8Bh 8Fh   (Physical page mode)

         5001h 00h 80h 81h 83h   Map/Unmap Multiple Handle Pages
               84h 8Ah 8Bh 8Fh   (Segment address mode)

         51h   00h 80h 81h 83h   Reallocate Pages
               84h 87h 88h

         5200h 00h 80h 81h 83h   Get Handle Attribute
               84h 8Fh 91h

         5201h 00h 80h 81h 83h   Set Handle Attribute
               84h 8Fh 90h 91h

         5202h 00h 80h 81h 84h   Get Handle Attribute Capability
               8Fh

         5300h 00h 80h 81h 83h   Get Handle Name
               84h 8Fh

         5301h 00h 80h 81h 83h   Set Handle Name
               84h 8FH A1h

         5400h 00h 80h 81h 84h   Get Handle Directory
               8Fh

         5401h 00h 80h 81h 84h   Search for Named Handle
               8Fh A0h A1h

         5402h 00h 80h 81h 84h   Get Total Handles
               8Fh

         5500h 00h 80h 81h 83h   Alter Page Map & Jump
               84h 8Ah 8Bh 8Fh   (Physical page mode)

         5501h 00h 80h 81h 83h   Alter Page Map & Jump
               84h 8Ah 8Bh 8Fh   (Segment address mode)

         5600h 00h 80h 81h 83h   Alter Page Map & Call
               84h 8Ah 8Bh 8Fh   (Physical page mode)

         5601h 00h 80h 81h 83h   Alter Page Map & Call
               84h 8Ah 8Bh 8Fh   (Segment address mode)

         5602h 00h 80h 81h 84h   Get Alter Page Map & Call Stack Space Size
               8Fh


                                                                     143







         5700h 00h 80h 81h 83h   Move Memory Region
               84h 8Ah 8Fh 92h
               93h 94h 95h 96h
               98h A2h

         5701h 00h 80h 81h 83h   Exchange Memory Region
               84h 8Ah 8Fh 93h
               94h 95h 96h 97h
               98h A2h

         5800h 00h 80h 81h 84h   Get Mappable Physical Address Array
               8Fh

         5801h 00h 80h 81h 84h   Get Mappable Physical Address Array Entries
               8Fh

         5900h 00h 80h 81h 84h   Get Expanded Memory Hardware Information
               8Fh A4h

         5901h 00h 80h 81h 84h   Get Unallocated Raw Page Count
               8Fh

         5A00h 00h 80h 81h 84h   Allocate Standard Pages
               85h 87h 88h 8Fh

         5A01h 00h 80h 81h 84h   Allocate Raw Pages
               85h 87h 88h 8Fh

         5B00h 00h 80h 81h 84h   Get Alternate Map Register Set
               8Fh A4h

         5B01h 00h 80h 81h 84h   Set Alternate Map Register Set
               8Fh 9Ah 9Ch 9Dh
               A3h A4h

         5B02h 00h 80h 81h 84h   Get Alternate Map Save Array Size
               8Fh A4h

         5B03h 00h 80h 81h 84h   Allocate Alternate Map Register Set
               8Fh 9Bh A4h

         5B04h 00h 80h 81h 84h   Deallocate Alternate Map Register Set
               8Fh 9Ch 9Dh A4h

         5B05h 00h 80h 81h 84h   Allocate DMA Register Set
               8Fh 9Bh A4h

         5B06h 00h 80h 81h 84h   Enable DMA on Alternate Map Register Set
               8Fh 9Ah 9Ch 9Dh
               9Eh 9Fh A4h

         5B07h 00h 80h 81h 84h   Disable DMA on Alternate Map Register Set
               8Fh 9Ah 9Ch 9Dh
               9Eh 9Fh A4h

         5B08h 00h 80h 81h 84h   Deallocate DMA Register Set
               8Fh 9Ch 9Dh A4h

                                                                     144







         5Ch   00h 80h 81h 84h   Prepare Expanded Memory Hardware for
                                 Warmboot

         5D00h 00h 80h 81h 84h   Enable Operating System Function Set
               8Fh A4h

         5D01h 00h 80h 81h 84h   Disable Operating System Function Set
               8Fh A4h

         5D02h 00h 80h 81h 84h   Return Operating System Access Key
               8Fh A4h















































                                                                     145







         TABLE A-2.  STATUS AND FUNCTION CODE CROSS REFERENCE

         ----------------------------------------------------------------------
         Status     Functions            Description
         ----------------------------------------------------------------------

         00h   All                       The function completed normally.

         80h   All                       The memory manager has detected a
                                         malfunction in the expanded memory
                                         software.

         81h   All                       The memory manager has detected a
                                         malfunction in the expanded memory
                                         hardware.

         82h   None                      This error code is not returned in
                                         version 3.2 of the memory manager
                                         or above.  In earlier versions of
                                         the memory manager this code meant
                                         a "busy" status.  This status
                                         indicated that the memory manager
                                         was already processing an expanded
                                         memory request when the current
                                         request was made and is unable to
                                         process another request.  In
                                         versions 3.2 of the memory manager
                                         and above, the memory manager is
                                         never "busy" and can always honor
                                         requests.

         83h   44h   45h   47h   48h     The memory manager can not find
               4Ch   5000h 5001h 51h     the handle specified.
               5200h 5201h 5300h 5301h
               5500h 5501h 5600h 5601h
               5700h 5701h

         84h   All                       The function code passed to the
                                         manager is not currently defined.

         85h   43h   5A00h 5A01h         No handles are currently available.
                                         All assignable handles are
                                         currently in use.

         86h   45h                       A mapping context restoration error
                                         has been detected.  This error
                                         occurs when a program attempts to
                                         return a handle and there is still
                                         a "mapping context" on the context
                                         stack for the indicated handle.

         87h   43h   51h   5A00h 5A01h   The number of total pages that are
                                         available in the system is
                                         insufficient to honor the request.




                                                                     146







         88h   43h   51h   5A00h 5A01h   The number of unallocated pages
                                         currently available is insufficient
                                         to honor the allocation request.

         89h   43h                       Zero pages could not be assigned to
                                         a handle.

         8Ah   44h   5000h 5001h 5500h   The logical page to map into memory
               5501h 5600h 5601h 5700h   is out of the range of logical
               5701h                     pages which are allocated to the
                                         handle.

         8Bh   44h   4F00h 4F02h 5000h   One or more of the physical pages
               5001h 5600h 5601h 5500h   is out of the range of allowable
               5501h                     physical pages.

         8Ch   47h                       The mapping register context save
                                         area is full.

         8Dh   47h                       The mapping register context stack
                                         already has a context associated
                                         with the handle.  The program has
                                         attempted to save the mapping
                                         register context when there was
                                         already a context for the handle on
                                         the stack.

         8Eh   48h                       The mapping register context stack
                                         does not have a context associated
                                         with the handle.  The program has
                                         attempted to restore the mapping
                                         register context when there was no
                                         context for the handle on the
                                         stack.

         8Fh   All                       The subfunction parameter passed to
                                         the function requiring a
                                         subfunction code is not defined.

         90h   5201h                     The attribute type is undefined.

         91h   5200h 5201h               The system configuration does not
                                         support non-volatility.

         92h    5700h                    The source and destination expanded
                                         memory regions have the same handle
                                         and overlap.  This is valid for a
                                         move.  The move has been completed
                                         and the destination region has a
                                         full copy of the source region.
                                         However, at least a portion of the
                                         source region has been overwritten
                                         by the move.

         93h   5700h 5701h               The length of the specified source
                                         or destination expanded memory
                                         region exceeds the length of the

                                                                     147







                                         expanded memory region allocated to
                                         the specified source or destination
                                         handle.  There are insufficient
                                         pages allocated to this handle to
                                         move/exchange a region of the size
                                         specified.

         94h   5700h 5701h               The conventional memory region and
                                         expanded memory region overlap.
                                         This is invalid, the conventional
                                         memory region cannot overlap the
                                         expanded memory region.

         95h   5700h 5701h               The offset within the logical page
                                         exceeds the length of the logical
                                         page.  The initial source or
                                         destination offsets within an
                                         expanded memory region must be
                                         between 0 and the (length of a
                                         logical page - 1) or 16383 (3FFFh).

         96h   5700h 5701h               Region length exceeds 1M-byte
                                         limit.

         97h   5701h                     The source and destination expanded
                                         memory regions have the SAME handle
                                         AND overlap.  This is invalid; the
                                         source and destination expanded
                                         memory regions cannot have the same
                                         handle and overlap when they are
                                         being exchanged.

         98h   5700h 5701h               The memory source and destination
                                         types are undefined/not supported.

         9Ah   5B01h 5B06h 5B07h         Alternate map register sets are
                                         supported, but the alternate map
                                         register set specified is not
                                         supported.

         9Bh   5B03h 5B05h               Alternate map/DMA register sets are
                                         supported.  However, all alternate
                                         map/DMA register sets are currently
                                         allocated.

         9Ch   5B01h 5B04h 5B06h 5B07h   Alternate map/DMA register sets are
               5B08h                     not supported, and the alternate
                                         map/DMA register set specified is
                                         not zero.

         9Dh   5B01h 5B04h 5B06h 5B07h   Alternate map/DMA register sets are
               5B08h                     supported, but the alternate map
                                         register set specified is not
                                         defined, not allocated, or is the
                                         currently allocated map register
                                         set.


                                                                     148







         9Eh   5B06h 5B07h               Dedicated DMA channels are not
                                         supported.

         9Fh   5B06h 5B07h               Dedicated DMA channels are
                                         supported.  But the DMA channel
                                         specified is not supported.

         A0h   5401h                     No corresponding handle value could
                                         be found for the handle name
                                         specified.

         A1h   5301h 5401h               A handle with this name already
                                         exists.  The specified handle was
                                         not assigned a name.

         A2h   5700h 5701h               An attempt was made to "wrap
                                         around" the 1M-byte address space
                                         during the move/exchange.  The
                                         source starting address together
                                         with the length of the region to be
                                         moved/exchanged exceeds 1M-byte.  No
                                         data was moved/exchanged.

         A3h   4E01h 4E02h 4F00h 4F01h   The contents of the data  structure
               5B01h                     passed to the function have either
                                         been corrupted or are meaningless.

         A4h   5900h 5B00h 5B01h 5B02h   The operating system has denied
               5B03h 5B04h 5B05h 5B06h   access to this function.  The
               5B07h 5B08h 5D00h 5D01h   function cannot be used at this
               5D02h                     time.



























                                                                     149







    APPENDIX B

         TESTING FOR THE PRESENCE OF THE EXPANDED MEMORY MANAGER

         Before an application program can use the Expanded Memory Manager, it
         must determine whether DOS has loaded the manager.  This appendix
         describes two methods your program can use to test for the presence of
         the memory manager and how to choose the correct one for your
         situation.

         The first method uses the DOS "open handle" technique; the second
         method uses the DOS "get interrupt vector" technique.

         WHICH METHOD SHOULD YOUR PROGRAM USE?

         The majority of application programs can use either the "open handle"
         or the "get interrupt vector" method.  However, if your program is a
         device driver or if it interrupts DOS during file system operations,
         you must use only the "get interrupt vector" method.

         Device drivers execute from within DOS and can't access the DOS file
         system; programs that interrupt DOS during file system operations have
         a similar restriction.  During their interrupt processing procedures,
         they can't access the DOS file system because another program may be
         using the system.

         Since the "get interrupt vector" method doesn't require the DOS file
         system, you must use it for these types of programs.

         THE "OPEN HANDLE" TECHNIQUE

         Most application programs can use the DOS "open handle" technique to
         test for the presence of the memory manager.  This section describes
         how to use the technique and gives an example.

         Caution..........................................................

         Don't use this technique if your program is a device driver or if it
         interrupts DOS during file system operations.  Use the "get interrupt
         vector" technique described later in this chapter.

         USING THE "OPEN HANDLE" TECHNIQUE

         This section describes how to use the DOS "open handle" technique to
         test for the presence of the memory manager. Follow these steps in
         order:

         1.  Issue an "open handle" command (DOS function 3Dh) in "read only"
             access mode (register AL = 0).  This function requires your
             program to point to an ASCII string which contains the path name
             of the file or device in which you're interested (register set
             DS:DX contains the pointer).  In this case the file is actually
             the name of the memory manager.

             You should format the ASCII string as follows:

             ASCII_device_name   DB   "EMMXXXX0", 0

                                                                     150







             The ASCII codes for the capital letters EMMXXXX0 are terminated by
             a byte containing a value of zero.

         2.  If DOS returns no error status code, skip Steps 3 and 4 and go to
             Step 5.  If DOS returns a "Too many open files" error status code,
             go to Step 3. If DOS returns a "File/Path not found" error status
             code, skip Step 3 and go to Step 4.

         3.  If DOS returns a "Too many open files" (not enough handles),
             status code, your program should invoke the "open file" command
             before it opens any other files.  This will guarantee that at
             least one file handle will be available to perform the function
             without causing this error.

             After the program performs the "open file" command, it should
             perform the test described in Step 6 and close the "file handle"
             (DOS function 3Eh).  Don't keep the manager "open" after this
             status test is performed since "manager" functions are not
             available thru DOS.  Go to Step 6.

         4.  If DOS returns a "File/Path not found", the memory manager is not
             installed.  If your application requires the memory manager, the
             user will have to reboot the system with a disk containing the
             memory manager and the appropriate CONFIG.SYS file before
             proceeding.

         5.  If DOS doesn't return an error status code you can assume that
             either a device with the name EMMXXXX0 is resident in the system,
             or a file with this name is on disk in the current disk drive.  Go
             to Step 6.

         6.  Issue an "I/O Control for Devices" command (DOS function 44h) with
             a "get device information" command (register AL = 0h).  DOS
             function 44h determines whether EMMXXXX0 is a device or a file.

             You must use the file handle (register BX) which you obtained in
             Step 1 to access the "EMM" device.  This function returns the
             "device information" in a word (register DX).  Go to step 7.

         7.  If DOS returns any error status code, you should assume that the
             memory manager device driver is not installed.  If your
             application requires the memory manager, the user will have to
             reboot the system with a disk containing the memory manager and
             the appropriate CONFIG.SYS file before proceeding.

         8.  If DOS didn't return an error status, test the contents of bit 7
             (counting from 0) of the "device information" word (register DX)
             the function returned.  Go to Step 9.

         9.  If bit 7 of the "device information" word contains a zero, then
             EMMXXXX0 is a file, and the memory manager device driver is not
             present.  If your application requires its presence, the user will
             have to reboot the system with a disk containing the memory
             manager and the appropriate CONFIG.SYS file before proceeding.  If
             bit 7 contains a one, then EMMXXXX0 is a device. Go to Step 10.



                                                                     151







         10. Issue an "I/O Control for Devices" command (DOS function 44h) with
             a "get output status" command (register AL = 7h).

             You must use the file handle you obtained in Step 1 to access the
             "EMM" device (register BX).  Go to Step 11.

         11. If the expanded memory device driver is "ready," the memory
             manager passes a status value of "0FFh" in register AL.  The
             status value is "00h" if the device driver is "not ready."

             If the memory manager device driver is "not ready" and your
             application requires its presence, the user will have to reboot
             the system with a disk containing the memory manager and the
             appropriate CONFIG.SYS file before proceeding.

             If the memory manager device driver is "ready", go to Step 12.

         12. Issue a "Close File Handle" command (DOS function 3Eh) to close
             the expanded memory device driver.  You must use the file handle
             you obtained in Step 1 to close the "EMM" device (register BX)

         AN EXAMPLE OF THE "OPEN HANDLE" TECHNIQUE

         The following procedure is an example of the "open handle" technique
         outlined in the previous section.

         ;---------------------------------------------------------------;
         ;   The following procedure tests for the presence of the EMM   ;
         ;   in the system.  It returns the CARRY FLAG SET if the EMM is ;
         ;   present.  If the EMM is not present, this procedure returns ;
         ;   the CARRY FLAG CLEAR.                                       ;
         ;---------------------------------------------------------------;

         first_test_for_EMM  PROC  NEAR

         PUSH DS
         PUSH CS
         POP  DS
         MOV  AX, 3D00h                     ; issue device open in
         LEA  DX, ASCII_device_name         ; read only mode
         INT  21h
         JC   first_test_for_EMM_error_exit ; test for error during open

         MOV  BX, AX                        ; get file handle returned by DOS
         MOV  AX, 4400h                     ; issue IOCTL get device info
         INT  21h
         JC   first_test_for_EMM_err_exit   ; test for get device info error

         TEST DX, 0080h                     ; test to determine
         JZ   first_test_for_EMM_err_exit   ; if ASCII_device_name
                                            ; is a device or a file
         MOV  AX, 4407h                     ; issue "IOCTL"
         INT  21h
         JC   first_test_for_EMM_error_exit ; test for IOCTL error
         PUSH AX                            ; save "IOCTL" status
         MOV  AH, 3Eh                       ; issue "close
         INT  21h                           ; file handle"

                                                                     152







         POP  AX                            ; restore "IOCTL" status
         CMP  AL, 0FFh                      ; test for "device ready" status
         JNE  first_test_for_EMM_error_exit ; returned by the driver
         first_test_for_EMM_exit:

         POP  DS                            ; EMM is present in the system
         STC
         RET

         first_test_for_EMM_error_exit:

         POP  DS                            ; EMM is NOT present in the system
         CLC
         RET

         ASCII_device_name                  DB  "EMMXXXX0", 0

         first_test_for_EMM ENDP








































                                                                     153







         THE "GET INTERRUPT VECTOR" TECHNIQUE

         Any type of program can use the DOS "get interrupt vector" technique
         to test for the presence of the memory manager.  This section
         describes how to use the technique and gives an example.

         Caution..........................................................

         Be sure to use this technique (and not the "open handle technique) if
         your program is a device driver or if it interrupts DOS during file
         system operations.

         USING THE "GET INTERRUPT VECTOR" TECHNIQUE

         This section describes how to use the DOS "get interrupt vector"
         technique to test for the presence of the memory manager.  Follow
         these steps in order:

         1.  Issue a "get vector" command (DOS function 35h) to obtain the
             contents of interrupt vector array entry number 67h (addresses
             0000:019C thru 0000:019F).

             The memory manager uses this interrupt vector to perform all
             manager functions.  The Offset portion of this interrupt service
             routine address is stored in the word located at address
             0000:019Ch;  the Segment portion is stored in the word located at
             address 0000:019Eh.

         2.  Compare the "device name field" with the contents of the ASCII
             string which starts at the address specified by the segment
             portion of the contents of interrupt vector address 67h and a
             fixed offset of 000Ah.  If DOS loaded the memory manager at boot
             time this name field will have the name of the device in it.

             Since the memory manager is implemented as a character device
             driver, its program origin is 0000h.  Device drivers are required
             to have a "device header" located at the program origin.  Within
             the "device header" is an 8 byte "device name field."  For a
             character mode device driver this name field is always located at
             offset 000Ah within the device header.  The device name field
             contains the name of the device which DOS uses when it references
             the device.

             If the result of the "string compare" in this technique is
             positive, the memory manager driver is present.

         AN EXAMPLE OF THE "GET INTERRUPT VECTOR" TECHNIQUE

         The following procedure is an example of the "get interrupt vector"
         technique outlined in the previous section.

         ;---------------------------------------------------------------;
         ;   The following procedure tests for the presence of the EMM   ;
         ;   in the system.  It returns the CARRY FLAG SET if the EMM is ;
         ;   present.  If the EMM is not present, this procedure returns ;
         ;    the CARRY FLAG CLEAR.                                      ;
         ;---------------------------------------------------------------;

                                                                     154








         second_test_for_EMM                PROC    NEAR

         PUSH DS
         PUSH CS
         POP  DS
         MOV  AX, 3567h                     ; issue "get interrupt vector"
         INT  21h
         MOV  DI, 000Ah                     ; use the SEGMENT in ES returned by
                                            ; DOS, place the "device name
                                            ; field" OFFSET in DI
         LEA  SI, ASCII_device_name         ; place the OFFSET of the device
                                            ; name string in SI, the SEGMENT
                                            ; is already in DS
         MOV  CX, 8                         ; compare the name strings
         CLD
         REPE CMPSB
         JNE  second_test_for_EMM_error_exit

         second_test_for_EMM_exit:

         POP  DS                            ; EMM is present in the system
         STC
         RET

         second_test_for_EMM_error_exit:

         POP  DS                            ; EMM is NOT present in the system
         CLC
         RET

         ASCII_device_name                  DB "EMMXXXX0"

         second_test_for_EMM                ENDP
























                                                                     155







    APPENDIX C

         EXPANDED MEMORY MANAGER IMPLEMENTATION GUIDELINES


         In addition to the functional specification, the expanded memory
         manager should provide certain resources.  The following guidelines
         are provided so required resources are present in expanded memory
         managers which comply with this version of the LIM specification.

         o   The amount of expanded memory supported:

             Up to a maximum of 32M bytes of expanded memory should be
             supported.

         o   The number of handles supported:

             The maximum number expanded memory handles provided should be 255,
             the minimum should be 64.

         o   Handle Numbering:

             Although a handle is a word quantity, there is a maximum of 255
             handles, including the operating system handle.  This
             specification defines the handle word as follows: the low byte of
             the word is the actual handle value, the high byte of the handle
             is set to 00 by the memory manager.  Previous versions of this
             specification did not specify the value of handles.

         o   New handle type: Handles versus Raw Handles:

             The difference between a raw handle and a regular handle is
             slight. If you use Function 27 to "Allocate raw pages to a
             handle", what is returned in DX is termed a raw handle. The raw
             handle does not necessarily refer to 16 Kbyte pages. Instead it
             refers to the "raw" page size, which depends on the expanded
             memory hardware.

             An application program can use Function 26 to find the raw page
             size, and by using the raw handle Function 27 returns, it can
             access them with the finer resolution that a particular expanded
             memory board may allow.

             On the other hand, applications which use Function 4 to "allocate
             pages to handle" receive a handle which always refers to 16K-byte
             pages. On expanded memory boards with smaller raw pages, the EMM
             driver will allocate and maintain the number of raw pages it takes
             to create a single composite 16K-byte page.  The difference
             between the expanded memory boards raw page size and the 16K-byte
             LIM page size is transparent to the application when it is using a
             handle obtained with Function 4.

             The memory manager must differentiate between pages allocated to
             handles and pages allocated to raw handles.  The meaning of a call
             to the driver changes depending on whether a handle or a raw
             handle is passed to the memory manager. If, for example, a handle
             is passed to Function 18 (Reallocate), the memory manager will

                                                                     156







             increase or decrease the number of 16K-byte pages allocated to the
             handle.  If Function 18 is passed a raw handle, the memory manager
             will increase or decrease the number of raw (non-16K-byte) pages
             allocated to the raw handle.  For LIM standard boards, there is no
             difference between pages and raw pages.

         o   The system Raw Handle (Raw Handle = 0000):

             For expanded memory boards that can remap the memory in the lower
             640K-byte address space, managing the pages of memory which are
             used to fill in the lower 640K can be a problem.  To solve this
             problem, the memory manager will create a raw handle with a value
             of 0000 when DOS loads the manager.  This raw handle is called the
             system handle.

             At power up, the memory manager will allocate all of the pages
             that are mapped into the lower 640K bytes to the system handle.
             These pages should be mapped in their logical order.  For example,
             if the system board supplies 256K bytes of RAM, and the 384K bytes
             above it is mappable, the system handle should have its logical
             page zero mapped into the first physical page at 256K, its logical
             page one mapped into the next physical page, and so on.

             The system handle should deal with raw pages.  To release some of
             these pages so application programs can use them, an operating
             system could decrease the number of pages allocated to the system
             handle with the "Reallocate" function.  Invoking the "Deallocate"
             function would decrease the system handle to zero size, but it
             must not deallocate the raw handle itself.  The "Deallocate"
             function treats the system handle differently than it treats other
             raw handles.  If the operating system can ever be "exited" (for
             example, the way Windows can be exited), it must increase the size
             of the system handle back to what is needed to fill 640K and map
             these logical pages back into physical memory before returning to
             DOS.























                                                                     157







             There are two functional special cases for this handle:

             -  The first special case deals with 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 its
                pages.  Since Function 4 will never return a handle value
                of zero, an application will never gain access to this
                special handle.

             -  The second special case deals with Function 6 (Deallocate
                Pages). If the operating system uses Function 6 to
                deallocate the pages which are allocated to the system
                handle, the pages 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.

         o   Terminate and Stay Resident (TSR) Program Cooperation In order for
             TSR's to cooperate with each other and with other applications,
             TSR's must follow this rule:  a program may only remap the DOS
             partition it lives in.

             This rule applies at all times, even when no expanded memory is
             present.

         o   Accelerator Cards: To support generic accelerator cards, the
             support of Function 34, as defined by AST, is encouraged.




























                                                                     158







    APPENDIX D

         OPERATING SYSTEM/ENVIRONMENT USE OF FUNCTION 28

         All expanded memory boards have a set of registers that "remember" the
         logical to physical page mappings.  Some boards have extra (or
         alternate) sets of these mapping registers.  Because no expanded
         memory board can supply an infinite number of alternate map register
         sets, this specification provides a way to simulate them using
         Function 28 (Alternate Map Register Set).

         EXAMPLES

         For the examples in this section, assume the hardware supports
         alternate map register sets.  First Windows is brought up, then
         "Reversi" is started.  Then control is switched back to the MS-DOS
         Executive.  For this procedure, here are the calls to the expanded
         memory manager:

         EXAMPLE 1

         Allocate alt reg set               ; Start up the MS-DOS
         (for the MS-DOS executive)         ; Executive

         Set alt reg set
         (for MS-DOS Executive)

         Allocate alt reg set               ; Start up Reversi
         (for Reversi)

         Set alt reg set
         (for Reversi)

         Map pages
         (for Reversi)

         Set alt reg set                    ; Switch back to MS-DOS
         (for MS-DOS Executive)             ; Executive

         Notice this procedure needed no "get" calls because the register set
         contained all the information needed to save a context.  However,
         using "Get" calls would have no ill effects.
















                                                                     159







         EXAMPLE 2

         Allocate alt reg set               ; Start up MS-DOS
         (for MS-DOS Executive)             ; Executive

         Set alt reg set
         (for MS-DOS Executive)

         Get alt reg set
         (for MS-DOS Executive)

         Allocate alt reg set               ; Start up Reversi
         (for Reversi)

         Set alt reg set
         (for Reversi)

         Map pages
         (for Reversi)

         Get alt reg set
         (for Reversi)

         Set alt reg set                    ; Switch back to MS-DOS
         (for MS-DOS Executive)             ; Executive

         The important point to follow is that a Set must always precede a Get.
         The model of Set then Get is the inverse of what interrupt handlers
         use, which is Get then Set (Get the old map context and Set the new
         one).  Another crucial point is that an alternate map register set
         must have the current mapping when allocated; otherwise, the Set will
         create chaos.

         What happens if this is simulated in software?  The same Set and Get
         model applies.  The main difference is where the context is saved.

         Since the allocate call is dynamic and there is no limit on the number
         of sets allocated, the OS/E must supply the space required.  Device
         drivers cannot allocate space dynamically, since the request would
         fail.  If the Allocate register set call returns a status indicating
         the alternate map register sets aren't supported, the OS/E must
         allocate space for the context.  It must also initialize the context
         using Function 15.  At that point it can do the Set, passing a pointer
         to the map context space.  On the Get call, the EMM driver is to
         return a pointer to the same context space.

         EXAMPLE 3

         Allocate alt reg set               ; Start up MS-DOS
         (for the MS-DOS executive)         ;Executive

         Get Page Map
         (for the MS-DOS executive)

         Set alt reg set
         (for MS-DOS Executive)


                                                                     160







         Allocate alt reg set               ; Start up Reversi
         (for Reversi)

         Set alt reg set
         (for Reversi)

         Map pages
         (for Reversi)

         Get Page Map
         (for Reversi)

         Set alt reg set                    ; Switch back to MS-DOS
         (for MS-DOS Executive)             ; Executive












































                                                                     161







    GLOSSARY

         The following terms are used frequently in this specification:

         Allocate
              To reserve a specified amount of expanded memory pages.

         Application Program
              An application program is the program you write and your customer
              uses.  Some categories of application software are word
              processors, database managers, spreadsheet managers, and project
              managers.

         Conventional Memory
              The memory between 0 and 640K bytes, address range 00000h thru
              9FFFFh.

         Deallocate
              To return previously allocated expanded memory to the memory
              manager.

         EMM
              See Expanded Memory Manager.

         Expanded Memory
              Expanded memory is memory outside DOS's 640K-byte limit (usually
              in the range of C0000h through EFFFFH).

         Expanded Memory Manager (EMM)
              A device driver that controls the interface between DOS
              application programs and expanded memory.

         Extended Memory
              The 15M-byte address range between 100000h thru FFFFFFh available
              on an 80286 processor when it is operating in protected virtual
              address mode.

         Handle
              A value that the EMM assigns and uses to identify a block of
              memory requested by an application program.  All allocated
              logical pages are associated with a particular handle.

         Logical Page
              The EMM allocates expanded memory in units (typically 16K-bytes)
              called logical pages.

         Mappable Segment
              A 16K-byte region of memory which can have a logical page mapped
              at it.

         Map Registers
              The set of registers containing the current mapping context of
              the EMM hardware.

         Mapping
              The process of making a logical page of memory appear at a
              physical page.

                                                                     162







         Mapping Context
              The contents of the mapping registers at a specific instant.
              This context represents a map state.

         Page Frame
              A collection of 16K-byte contiguous physical pages from which an
              application program accesses expanded memory.

         Page Frame Base Address
              A page frame base address is the location (in segment format) of
              the first byte of the page frame.

         Physical Page
              A physical page is the range of memory addresses occupied by a
              single 16K-byte page.

         Raw Page
              The smallest unit of mappable memory that an expanded memory
              board can supply.

         Resident Application Program
              A resident application program is loaded by DOS, executes, and
              remains resident in the system after it returns control to DOS.
              This type of program occupies memory and is usually invoked by
              the operating system, an application program, or the hardware.
              Some examples of resident application programs are RAM disks,
              print spoolers, and "pop-up" desktop programs.

         Status Code
              A code that an EMM function returns which indicates something
              about the result of running the function.  Some status codes
              indicate whether the function worked correctly and others may
              tell you something about he expanded memory hardware or software.

         Transient Application
              A transient application program is loaded Program by DOS,
              executes, and doesn't remain in the system after it returns
              control to DOS.  After a transient application program returns
              control to DOS, the memory it used is available for other
              programs.

         Unmap
              To make a logical page inaccessible for reading or writing.















                                                                     163