

          The associated file (LIMEMS41.DOC) is a complete transcription of
          the Lotus/Intel/Microsoft (LIM) Expanded Memory Specification
          (EMS) Version 4.0, updated October 1987.  It can be printed by
          "COPY LIMEMS41.DOC PRN:"

          I created this transcription because of the difficulty I origin-
          ally had finding a copy of the document, because of the number of
          people who have subsequently expressed an interest in having
          access to a machine-readable copy of the specification, and,
          finally, because of the annoying number of typographical errors
          contained in the original and updated documents.

          This transcription is not an exact letter-for-letter duplicate of
          the original document.  Some minor changes were necessitated by
          the simple fact that the document's proportionally-spaced, multi-
          fonted typography and line drawings did not lend themselves to
          the generic fixed-spacing, single-fonted, non-graphical ASCII
          transcription I wanted to produce for general dissemination.

          Other minor changes were made to correct obvious typographical
          and grammatical errors, or to simply improve the visual aes-
          thetics of the presented material.

          In one area, however, I simply trashed their original material
          and substituted my own.  This area is the Index.  The original
          document contains an Index that is little more than a reformatt-
          ing of the Table of Contents.  As anyone who has ever indexed a
          large document knows, it is very difficult to produce an Index
          that is both complete AND easy to use.  I didn't have time to
          produce one that was both, so I aimed for the former.  In fact,
          the Index I have provided is more of an alphabetical listing of
          key words and phrases and the pages where they are referenced,
          than it is a more typical Index with its multi-level headings and
          subheadings.

          You should be able obtain a printed, 3-hole-punched, 5.5 x 8.5"
          copy of the original (and uncorrected) document directly from
          Intel by calling their "Information Department" at 1-800-538-3373
          and asking for a copy of the "LIM EMS 4.0 Developer's Kit."  It
          is available free of charge and mine arrived in about two weeks. 
          (European availability, however, is reported to be from poor to
          non-existent.)

          It is my intent to provide this transcription as a public
          service.  I am, therefore, releasing it into the public domain. 
          The original document has also been released into the public
          domain by Lotus, Intel, and Microsoft, though it remains their
          copyrighted property (I'm not quite sure how they manage to do
          that).

          I have tried as best I can to provide an accurate and corrected
          transcription of the original document.  It is inevitable,
          however, that some typographical errors have slipped through in
          spite of my hours of bleary-eyed proof reading.  For these errors
          I apologize and plead simple human frailty.

               THIS TRANSCRIPTION IS PROVIDED WITHOUT ANY GUARANTEES
               OR WARRANTIES OF ANY KIND, AND I ASSUME ABSOLUTELY NO
               LIABILITY FOR ITS ACCURACY, CONTENT, OR SUBSEQUENT USE.

          Dick Flanagan, W6OLD, Ben Lomond, California        November 1987











                           LOTUS(R)/INTEL(R)/MICROSOFT(R)

                          EXPANDED MEMORY SPECIFICATION [1]












                                     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 35th Way
          Box 97017
          Redmond, WA  98073


               [1] Transcribed into machine-readable form by Dick Flanagan,
          Ben Lomond, California.  This transcription is released into the
          public domain without warranty or assumption of liability.





               This specification was jointly developed by Lotus Develop-
               ment Corporation, Intel Corporation, and Microsoft Corpora-
               tion.  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 MICRO-
               SOFT 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 MODIF-
               ICATION 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
























                                                                         ii





          CONTENTS



          Chapter 1
          INTRODUCTION
            What is Expanded Memory? . . . . . . . . . . . . . . . . .    1
            How Expanded Memory Works  . . . . . . . . . . . . . . . .    1

          Chapter 2
          WRITING PROGRAMS THAT USE EXPANDED MEMORY
            What Every Program Must Do . . . . . . . . . . . . . . . .    4
            Advanced Programming . . . . . . . . . . . . . . . . . . .    5
              Saving The State of Mapping Hardware . . . . . . . . . .    6
              Retrieving Handle and Page Counts  . . . . . . . . . . .    6
              Mapping and Unmapping Multiple Pages . . . . . . . . . .    6
              Reallocating Pages . . . . . . . . . . . . . . . . . . .    6
              Using Handles and Assigning Names to Handles . . . . . .    6
              Using Handle Attributes  . . . . . . . . . . . . . . . .    7
              Altering Page Maps and Jumping/Calling . . . . . . . . .    7
              Moving or Exchanging Memory Regions  . . . . . . . . . .    7
              Getting the Amount of Mappable Memory  . . . . . . . . .    8
              Operating System Functions . . . . . . . . . . . . . . .    8
            Programming Guidelines . . . . . . . . . . . . . . . . . .   12
            Examples . . . . . . . . . . . . . . . . . . . . . . . . .   14
              Example 1  . . . . . . . . . . . . . . . . . . . . . . .   14
              Example 2  . . . . . . . . . . . . . . . . . . . . . . .   19
              Example 3  . . . . . . . . . . . . . . . . . . . . . . .   30
              Example 4  . . . . . . . . . . . . . . . . . . . . . . .   32

          Chapter 3
          EMM FUNCTIONS
            Function 1. Get Status . . . . . . . . . . . . . . . . . .   37
            Function 2. Get Page Frame Address . . . . . . . . . . . .   38
            Function 3. Get Unallocated Page Count . . . . . . . . . .   40
            Function 4. Allocate Pages . . . . . . . . . . . . . . . .   42
            Function 5. Map/Unmap Handle Pages . . . . . . . . . . . .   46
            Function 6. Deallocate Pages . . . . . . . . . . . . . . .   49
            Function 7. Get Version  . . . . . . . . . . . . . . . . .   51
            Function 8. Save Page Map  . . . . . . . . . . . . . . . .   53
            Function 9. Restore Page Map . . . . . . . . . . . . . . .   55
            Function 10. Reserved  . . . . . . . . . . . . . . . . . .   57
            Function 11. Reserved  . . . . . . . . . . . . . . . . . .   58
            Function 12. Get Handle Count  . . . . . . . . . . . . . .   59
            Function 13. Get Handle Pages  . . . . . . . . . . . . . .   61
            Function 14. Get All Handle Pages  . . . . . . . . . . . .   63
            Function 15. Get/Set Page Map  . . . . . . . . . . . . . .   65
              Get Page Map subfunction . . . . . . . . . . . . . . . .   65
              Set Page Map subfunction . . . . . . . . . . . . . . . .   67
              Get & Set Page Map subfunction . . . . . . . . . . . . .   69
              Get Size of Page Map Save Array subfunction  . . . . . .   71


                                                                        iii





            Function 16. Get/Set Partial Page Map  . . . . . . . . . .   73
              Get Partial Page Map subfunction . . . . . . . . . . . .   73
              Set Partial Page Map subfunction . . . . . . . . . . . .   76
              Get Size of Partial Page Map Save Array subfunction  . .   78
            Function 17. Map/Unmap Multiple Handle Pages . . . . . . .   80
              Mapping Multiple Pages . . . . . . . . . . . . . . . . .   80
              Unmapping Multiple Pages . . . . . . . . . . . . . . . .   80
              Mapping and Unmapping Multiple Pages Simultaneously  . .   80
              Alternate Mapping and Unmapping Methods  . . . . . . . .   81
              Logical Page/Physical Page Method  . .OF THE EXPANDED MEMORY MANAGER
            Which method should your program use?  . . . . . . . . . .  199
            The "open handle" technique  . . . . . . . . . . . . . . .  199
            The "get interrupt vector" technique . . . . . . . . . . .  204

          Appendix C
          EXPANDED MEMORY MANAGER IMPLEMENTATION GUIDELINES
            The amount of expanded memory supported  . . . . . . . . .  206
            The number of handles supported  . . . . . . . . . . . . .  206
            Handle Numbering . . . . . . . . . . . . . . . . . . . . .  206
            New handle type:  Handles versus Raw Handles . . . . . . .  206
            The system Raw Handle (Raw Handle = 0000h) . . . . . . . .  207
            Terminate and Stay Resident (TSR) Program Cooperation  . .  208
            Accelerator Cards  . . . . . . . . . . . . . . . . . . . .  208

          Appendix D
          OPERATING SYSTEM/ENVIRONMENT USE OF FUNCTION 28
            Examples . . . . . . . . . . . . . . . . . . . . . . . . .  209
              Example 1  . . . . . . . . . . . . . . . . . . . . . . .  209
              Example 2  . . . . . . . . . . . . . . . . . . . . . . .  210
              Example 3  . . . . . . . . . . . . . . . . . . . . . . .  211

          GLOSSARY

          INDEX















                                                                          v





          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 Micro-
               soft 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 bytes 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.

               Figure 1-1 shows the relationship among the page frame,
               physical pages, and logical pages.


          Introduction                                                    1





                                                       32M +--------------+
                                                          /|              |
                                                           |              |
                                                     /     |              |
                                                           |              |
                                                /          |              |
                                                           |              |
                                           /               |              |
                                                           |   Expanded   |
                                      /                    |    Memory    |
          1024K +--------------+                           |              |
                | / / / / / /  | /                         |              |
           960K +--------------+                           |              |
                |  Page Frame  |                           |              |
                |              |                           |              |
                | 12 16K-Byte  |                           |              |
                |   Physical   |                           |              |
                |    Pages     |                           |              |
           768K +--------------+                           | Divided into |
                | / / / / / /  | \                         |   logical    |
           640K +--------------+                           |    pages     |
                |              |   \                       |              |
                |              |                           |              |
                |              |     \                     |              |
                |              |                           |              |
                | 24 16K-Byte  |       \                   |              |
                |   Physical   |                           |              |
                |    Pages*    |         \                 |              |
                |              |                           |              |
                |              |           \               |              |
                |              |                           |              |
                |              |             \             |              |
           256K +--------------+                           |              |
                |              |               \           |              |
                | / / / / / /  |                           |              |
                |              |                 \         |              |
                | / / / / / /  |                           |              |
                |              |                   \       |              |
                | / / / / / /  |                           |              |
                |              |                     \     |              |
              0 +--------------+                           |              |
                                                       \   |              |
                                                           |              |
          *Intended for operating                        \ |              |
           system/environment use only                   0 +--------------+



          Figure 1-1.  Expanded Memory




          Introduction                                                    2





               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.













































          Introduction                                                    3





          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, 18, or 27)

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












          Writing Programs That Use Expanded Memory                       4





          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.

             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/Micro-
               soft 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.

          Writing Programs That Use Expanded Memory                       5





          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.


          Reallocating Pages

               Reallocating pages (Function 18) lets applications dynami-
               cally 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.

          Writing Programs That Use Expanded Memory                       6





               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 as-
               sociated 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 & Jump) and 23
               (Alter Page Map & 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 conven-
               tional 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 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 applica-

          Writing Programs That Use Expanded Memory                       7





               tions 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 Array subfunction returns a cross refer-
               ence 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/en-
               vironments.  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.



















          Writing Programs That Use Expanded Memory                       8





          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.

             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.



          Writing Programs That Use Expanded Memory                       9





          Table 2-2.  The Advanced Functions (continued)
          ----------------------------------------------------------------

          Function                        Description

          ----------------------------------------------------------------

             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 informa-
                       tion 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 speci-
                       fied 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.

             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.


          Writing Programs That Use Expanded Memory                      10





          Table 2-2.  The Advanced Functions (continued)
          ----------------------------------------------------------------

          Function                        Description

          ----------------------------------------------------------------

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

          ----------------------------------------------------------------









































          Writing Programs That Use Expanded Memory                      11





          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

          Writing Programs That Use Expanded Memory                      12





                   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 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 & Call and
                   Alter Map & Jump) are the only exceptions.









          Writing Programs That Use Expanded Memory                      13





          Examples

               This section lists four example programs that demonstrate
               the use of expanded memory.


          Example 1

               This program was written using the Microsoft C compiler
               Version 3.0.  EMM function calls are made with the int86
               function found in the dos.h library.  To create an ex-
               ecutable program use the following compile command line:

                         msc /Gs /Oat /Ml program,,program;

          #include <dos.h>
          #include <stdio.h>

          #define EMM_INT                 0x67  /* EMM interrupt number */
          #define GET_PAGE_FRAME          0x41  /* EMM get page frame */
                                                /* function number */
          #define GET_UNALLOC_PAGE_COUNT  0x42  /* EMM get unallocated */
                                                /* page count */
                                                /* function number */
          #define ALLOCATE_PAGES          0x43  /* EMM allocate pages */
                                                /* function number */
          #define MAP_PAGES               0x44  /* EMM map pages */
                                                /* function number */
          #define DEALLOCATE_PAGES        0x45  /* EMM deallocate pages */
                                                /* function number */
          #define DEVICE_NAME_LENGTH      8     /* length of a device */
                                                /* name string */
          #define TRUE                    1
          #define FALSE                   0

          union REGS input_regs, output_regs;
          struct SREGS segment_regs;
          int pf_addr;

          /*------------------------------------------------------------*/
          /* Routine to convert a segment:offset pair to a far ptr.     */
          /*------------------------------------------------------------*/
          char *build_ptr (segment, offset)

              unsigned int segment;
              unsigned int offset;
          {
              char *ptr;

              ptr = (char *)(((unsigned long)segment << 16) + offset);
              return (ptr);
          }

          Writing Programs That Use Expanded Memory                      14





          /*------------------------------------------------------------*/
          /* Function which determines whether EMM device driver        */
          /* is installed.                                              */
          /*------------------------------------------------------------*/
          char emm_installed()

          {
              char *EMM_device_name = "EMMXXXX0";
              char *int_67_device_name_ptr;

              /*--------------------------------------------------------*/
              /* AH = DOS get interrupt vector function.                */
              /*--------------------------------------------------------*/
              input_regs.h.ah = 0x35;

              /*--------------------------------------------------------*/
              /* AL = EMM interrupt vector number.                      */
              /*--------------------------------------------------------*/
              input_regs.h.al = EMM_INT;
              intdosx (&input_regs, &output_regs, &segment_regs);

              /*--------------------------------------------------------*/
              /* Upon return ES:0Ah points to location where            */
              /* device name should be.                                 */
              /*--------------------------------------------------------*/
              int_67_device_name_ptr = build_ptr (segment_regs.es, 0x0A);

              /*--------------------------------------------------------*/
              /* Compare memory with EMM device name.                   */
              /*--------------------------------------------------------*/
              if (memcmp (EMM_device_name, int_67_device_name_ptr,
                                             DEVICE_NAME_LENGTH) == 0)
                  return (TRUE);
              else
                  return (FALSE);
          }

          /*------------------------------------------------------------*/
          /* Function which determines if there are enough unallocated  */
          /* expanded memory pages for the application.                 */
          /*------------------------------------------------------------*/
          char enough_unallocated_pages (pages_needed)

              int pages_needed;
          {
              input_regs.h.ah = GET_UNALLOCATED_PAGE_COUNT;
              int86 (EMM_INT, &input_regs, &output_regs);
              if (output_regs.h.ah != 0 || pages_needed > output_regs.x.bx)
                  return (FALSE);
              else
                  return (TRUE);
          }

          Writing Programs That Use Expanded Memory                      15





          /*------------------------------------------------------------*/
          /* Function which allocates expanded memory pages and passes  */
          /* back to the main EMM handle.                               */
          /*------------------------------------------------------------*/
          char allocate_expanded_memory_pages (pages_needed,emm_handle_ptr)

              int pages_needed;
              unsigned int *emm_handle_ptr;
          {
              input_regs.h.ah = ALLOCATE_PAGES;
              input_regs.x.bx = pages_needed;
              int86 (EMM_INT, &input_regs, &output_regs);
              if (output_regs.h.ah == 0) {
                  *emm_handle_ptr = output_regs.x.dx;
                  return (TRUE);
              }
              else
                  return (FALSE);
          }

          /*------------------------------------------------------------*/
          /* Routine to map a logical page to a physical page.          */
          /*------------------------------------------------------------*/
          char map_expanded_memory_pages (emm_handle, physical_page,       
                                                             logical_page)
              unsigned int emm_handle;
              int physical_page;
              int logical_page;
          {
              input_regs.h.ah = MAP_PAGES;
              input_regs.h.al = physical_page;
              input_regs.x.bx = logical_page;
              input_regs.x.dx = emm_handle;
              int86 (EMM_INT, &input_regs, &output_regs);
              if (output_regs.h.ah == 0)
                  return (TRUE);
              else
                  return (FALSE);
          }














          Writing Programs That Use Expanded Memory                      16





          /*------------------------------------------------------------*/
          /* Routine which gets the page frame base address from EMM.   */
          /*------------------------------------------------------------*/
          char get_page_frame_address (pf_ptr)

              char **pf_ptr;
          {
              input_regs.h.ah = GET_PAGE_FRAME;
              int86 (EMM_INT, &input_regs, &output_regs);
              if (output_regs.h.ah != 0)       /* check EMM status */
                  return (FALSE);
              else
                 *pf_ptr = build_ptr (output_regs.x.bx, 0);
              return (TRUE);
          }

          /*------------------------------------------------------------*/
          /* Routine to release all expanded memory pages allocated     */
          /* by an EMM handle.                                          */
          /*------------------------------------------------------------*/

          char deallocate_expanded_memory_pages (emm_handle)

              unsigned int emm_handle;
          {
              input_regs.h.ah = DEALLOCATE_PAGES;
              input_regs.x.dx = emm_handle;
              int86 (EMM_INT, &input_regs, &output_regs);
              if (output_regs.h.ah == 0)
                  return (TRUE);
              else
                  return (FALSE);
          }

          main()

          {
              unsigned int emm_handle;
              char *pf_addr;
              int pages_needed;
              int physical_page;
              int logical_page;
              int index;

              /*--------------------------------------------------------*/
              /* Determine if EMM is installed.                         */
              /*--------------------------------------------------------*/
              if (!emm_installed())
                  exit(1);




          Writing Programs That Use Expanded Memory                      17





              /*--------------------------------------------------------*/
              /* Determine if enough expanded memory pages exist for    */
              /* application.                                           */
              /*--------------------------------------------------------*/
              pages_needed = 1;
              if (!enough_unallocated_pages (pages_needed))
                  exit(1);

              /*--------------------------------------------------------*/
              /* Allocate expanded memory pages.                        */
              /*--------------------------------------------------------*/
              if (!allocate_expanded_memory_pages (pages_needed,
                                                             &emm_handle))
                  exit(1);

              /*--------------------------------------------------------*/
              /* Map in the required pages.                             */
              /*--------------------------------------------------------*/
              physical_page = 0;
              logical_page = 0;
              if (!map_expanded_memory_pages (emm_handle, physical_page,
                                                            logical_page))
                  exit(1);

              /*--------------------------------------------------------*/
              /* Get expanded memory page frame address.                */
              /*--------------------------------------------------------*/
              if (!get_page_frame_address (&pf_addr))
                  exit(1);

              /*--------------------------------------------------------*/
              /* Write to expanded memory.                              */
              /*--------------------------------------------------------*/
              for (index = 0; index < 0x3fff; index++)
                  pf_addr[index] = index;

              /*--------------------------------------------------------*/
              /* Return expanded memory pages before exiting.           */
              /*--------------------------------------------------------*/
              if (!deallocate_expanded_memory_pages (emm_handle))
                  exit(1);
          }











          Writing Programs That Use Expanded Memory                      18





          Example 2

          This program shows you how to use the basic functions of the LIM
          Expanded Memory Specification with Turbo Pascal.  The program
          does the following:

               1.  Makes sure the LIM Expanded Memory Manager (EMM) has
                   been installed.

               2.  Displays the version number of the EMM.

               3.  Determines if there are enough pages of memory for the
                   program.  It then displays the total number of EMM pages
                   present in the system and the number available for use.

               4.  Requests the desired number of pages from the EMM.

               5.  Maps a logical page into one of the physical pages.

               6.  Displays the base address of our EMM memory page frame. 
                   Performs a simple read/write test on the EMM memory.

               7.  Returns the EMM memory given to us back to the EMM.

               8.  Exits.

          All the calls are structured to return the result or error code
          of the Expanded Memory function performed as an integer.  If the
          error code is not zero, an error has occurred, a simple error
          procedure is called, and the program terminates.

          Type
            ST3  = string[3];
            ST80 = string[80];
            ST5  = string[5];

            Registers = record
              case integer of
                1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: Integer);
                2: (AL,AH,BL,BH,CL,CH,DL,DH         : Byte);
              end;

          Const
            EMM_INT                    = $67;
            DOS_Int                    = $21;
            GET_PAGE_FRAME             = $41;
            GET_UNALLOCATED_PAGE_COUNT = $42;
            ALLOCATE_PAGES             = $43;
            MAP_PAGES                  = $44;
            DEALLOCATE_PAGES           = $45;
            GET_VERSION                = $46;
            STATUS_OK                  = 0;

          Writing Programs That Use Expanded Memory                      19





            {------------------------------------------------------------}
            { Assume the application needs one EMM page.                 }
            {------------------------------------------------------------}
            APPLICATION_PAGE_COUNT = 1;

          Var
            Regs: Registers;

            Emm_handle,
            Page_Frame_Base_Address,
            Pages_Needed,
            Physical_Page,
            Logical_Page,
            Offset,
            Error_Code,
            Pages_EMM_Available,
            Total_EMM_Pages,
            Available_EMM_Pages: Integer;

            Version_Number,
            Pages_Number_String: ST3;

            Verify: Boolean;

            {------------------------------------------------------------}
            { The function Hex_String converts an integer into a four    }
            { character hexadecimal number (string) with leading zeros.  }
            {------------------------------------------------------------}
            Function Hex_String (Number: Integer): ST5;
              Function Hex_Char (Number: Integer): Char;
                Begin
                  If Number < 10 then
                    Hex_Char := Char (Number + 48)
                  else
                    Hex_Char := Char (Number + 55);
                end; { Function Hex_char }

            Var
              S: ST5;

            Begin
              S := '';
              S := Hex_Char ((Number shr 1) div 2048);
              Number := (((Number shr 1) mod 2048) shl 1) + (Number and 1);
              S := S + Hex_Char (Number div 256);
              Number := Number mod 256;
              S := S + Hex_Char (Number div 16);
              Number := Number mod 16;
              S := S + Hex_Char (Number);
              Hex_String := S + 'h';
            end; { Function Hex_String }


          Writing Programs That Use Expanded Memory                      20





            {------------------------------------------------------------}
            { The function Emm_Installed checks to see if the            }
            { EMM is loaded in memory.  It does this by looking          }
            { for the string 'EMMXXXX0', which should be located         }
            { at 10 bytes from the beginning of the code segment the     }
            { EMM interrupt, 67h, points to.                             }
            {------------------------------------------------------------}
            Function Emm_Installed: Boolean;
              Var
                Emm_Device_Name   : string[8];
                Int_67_Device_Name: string[8];
                Position          : integer;
                Regs              : registers;

              Begin
                Int_67_Device_Name := '';
                Emm_Device_Name    := 'EMMXXXX0';
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Get the code segment interrupt 67h points to       }
                    { the EMM interrupt by using DOS function 35h.       }
                    { (get interrupt vector)                             }
                    {----------------------------------------------------}
                    AH := $35;
                    AL := EMM_INT;
                    Intr (DOS_Int, Regs);
                    {----------------------------------------------------}
                    { The ES pseudo-register contains the segment        }
                    { address pointed to by interrupt 67h.  Create an    }
                    { eight character string from the eight successive   }
                    { bytes at address ES:$000A (10 bytes from ES)       }
                    {----------------------------------------------------}
                    For Position := 0 to 7 do
                      Int_67_Device_Name :=
                        Int_67_Device_Name + Chr (mem[ES:Position + $0A]);
                    Emm_Installed := True;
                    {----------------------------------------------------}
                    { If the string is the EMM manager signature,        }
                    { 'EMMXXXX0', then EMM is installed and ready for    }
                    { use.  If not, then EMM is not present.             }
                    {----------------------------------------------------}
                    If Int_67_Device_Name <> Emm_Device_Name
                      then Emm_Installed := False;
                  end; { with Regs do }
              end; { Function Emm_Installed }







          Writing Programs That Use Expanded Memory                      21





            {------------------------------------------------------------}
            { This function returns the total number of EMM pages        }
            { present in the system, and the number of EMM pages that    }
            { are available.                                             }
            {------------------------------------------------------------}
            Function EMM_Pages_Available
              (Var Total_EMM_Pages, Pages_Available: Integer): Integer;
              Var
                Regs: Registers;

              Begin
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Get the number of currently unallocated pages and  }
                    { the total number of pages in the system from EMM.  }
                    { Load pseudo-registers prior to invoking EMM.       }
                    {    AH = get unallocated page count function        }
                    {----------------------------------------------------}
                    AH := GET_UNALLOCATED_PAGE_COUNT;
                    Intr (EMM_INT, Regs);
                    {----------------------------------------------------}
                    { Unload the pseudo-registers after invoking EMM.    }
                    {    BX = currently unallocated pages                }
                    {    DX = total pages in the system                  }
                    {    AH = status                                     }
                    {----------------------------------------------------}
                    Pages_Available := BX;
                    Total_EMM_Pages := DX;
                    EMM_Pages_Available := AH;
                  end;
              end; { Function EMM_Pages_Available }


            {------------------------------------------------------------}
            { This function requests the specified number of pages       }
            { from the EMM.                                              }
            {------------------------------------------------------------}
            Function Allocate_Expanded_Memory_Pages
              (Pages_Needed: Integer; Var Handle: Integer): Integer;
              Var
                Regs: Registers;











          Writing Programs That Use Expanded Memory                      22





              Begin
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Allocate the specified number of pages from EMM.   }
                    { Load pseudo-registers prior to invoking EMM.       }
                    {    AH = allocate pages function.                   }
                    {    BX = number of pages to allocate.               }
                    {----------------------------------------------------}
                    AH := ALLOCATE_PAGES;
                    BX := Pages_Needed;
                    Intr (EMM_INT, Regs);
                    {----------------------------------------------------}
                    { Unload the pseudo-registers after invoking EMM.    }
                    {    DX = EMM handle                                 }
                    {    AH = status                                     }
                    {----------------------------------------------------}
                    Handle := DX;
                    Allocate_Expanded_Memory_Pages := AH;
                  end;
              end; { Function Allocate_Expanded_Memory_Pages }


            {------------------------------------------------------------}
            { This function maps a logical page allocated by the         }
            { Allocate_Expanded_Memory_Pages function into one of the    }
            { four physical pages.                                       }
            {------------------------------------------------------------}
            Function Map_Expanded_Memory_Pages
              (Handle, Logical_Page, Physical_Page: Integer): Integer;
              Var
                Regs: Registers;

              Begin
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Map a logical page at a physical page.             }
                    { Load pseudo-registers prior to invoking EMM.       }
                    {    AH = map page function                          }
                    {    DX = handle                                     }
                    {    BX = logical page number                        }
                    {    AL = physical page number                       }
                    {----------------------------------------------------}
                    AH := MAP_PAGES;
                    DX := Handle;
                    BX := Logical_Page;
                    AL := Physical_Page;
                    Intr (EMM_INT, Regs);




          Writing Programs That Use Expanded Memory                      23





                    {----------------------------------------------------}
                    { Unload the pseudo-registers after invoking EMM.    }
                    {    AH = status                                     }
                    {----------------------------------------------------}
                    Map_Expanded_Memory_Pages := AH;
                  end; { with Regs do }
              end; { Function Map_Expanded_Memory_Pages }


            {------------------------------------------------------------}
            { This function gets the physical address of the EMM page    }
            { frame we are using.  The address returned is the segment   }
            { of the page frame.                                         }
            {------------------------------------------------------------}
            Function Get_Page_Frame_Base_Address
              (Var Page_Frame_Address: Integer): Integer;
              Var
                Regs: Registers;

              Begin
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Get the page frame segment address from EMM.       }
                    { Load pseudo-registers prior to invoking EMM.       }
                    {    AH = get page frame segment function            }
                    {----------------------------------------------------}
                    AH := GET_PAGE_FRAME;
                    Intr (EMM_INT, Regs);
                    {----------------------------------------------------}
                    { Unload the pseudo-registers after invoking EMM.    }
                    {    BX = page frame segment address                 }
                    {    AH = status                                     }
                    {----------------------------------------------------}
                    Page_Frame_Address := BX;
                    Get_Page_Frame_Base_Address := AH;
                  end; { with Regs do }
              end; { Function Get_Page_Frame_Base_Address }


            {------------------------------------------------------------}
            { This function releases the EMM memory pages allocated to   }
            { us, back to the EMM memory pool.                           }
            {------------------------------------------------------------}
            Function Deallocate_Expanded_Memory_Pages
              (Handle: Integer): Integer;
              Var
                Regs: Registers;





          Writing Programs That Use Expanded Memory                      24





              Begin
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Deallocate the pages allocated to an EMM handle.   }
                    { Load pseudo-registers prior to invoking EMM.       }
                    {    AH = deallocate pages function                  }
                    {    DX = EMM handle                                 }
                    {----------------------------------------------------}
                    AH := DEALLOCATE_PAGES;
                    DX := Handle;
                    Intr (EMM_INT, Regs);
                    {----------------------------------------------------}
                    { Unload the pseudo-registers after invoking EMM.    }
                    {    AH = status                                     }
                    {----------------------------------------------------}
                    Deallocate_Expanded_Memory_Pages := AH;
                  end; { with Regs do }
              end; { Function Deallocate_Expanded_Memory_Pages }


            {------------------------------------------------------------}
            { This function returns the version number of the EMM as     }
            { a three-character string.                                  }
            {------------------------------------------------------------}
            Function Get_Version_Number (Var Version_String: ST3): Integer;
              Var
                Regs: Registers;
                Integer_Part, Fractional_Part: Char;

              Begin
                with Regs do
                  Begin
                    {----------------------------------------------------}
                    { Get the version of EMM.                            }
                    { Load pseudo-registers prior to invoking EMM.       }
                    {    AH = get EMM version function                   }
                    {----------------------------------------------------}
                    AH := GET_VERSION;
                    Intr (EMM_INT, Regs);













          Writing Programs That Use Expanded Memory                      25





                    {----------------------------------------------------}
                    { If the version number returned was OK, then        }
                    { convert it to a three-character string.            }
                    {----------------------------------------------------}
                    If AH=STATUS_OK then
                      Begin
                        {------------------------------------------------}
                        { The upper four bits of AH are the integer      }
                        { portion of the version number, the lower four  }
                        { bits are the fractional portion.  Convert the  }
                        { integer value to ASCII by adding 48.           }
                        {------------------------------------------------}
                        Integer_Part    := Char (AL shr 4  + 48);
                        Fractional_Part := Char (AL and $F + 48);
                        Version_String  := Integer_Part + '.' +
                                                          Fractional_Part;
                      end; { If AH=STATUS_OK }
                    {----------------------------------------------------}
                    { Unload the pseudo-registers after invoking EMM.    }
                    {    AH = status                                     }
                    {----------------------------------------------------}
                    Get_Version_Number := AH;
                  end; { with Regs do }
              end; { Function Get_Version_Number }


            {------------------------------------------------------------}
            { This procedure prints an error message passed by the       }
            { caller, prints the error code passed by the caller in hex, }
            { and then terminates the program with an error level of 1.  }
            {------------------------------------------------------------}
            Procedure Error (Error_Message: ST80; Error_Number: Integer);
              Begin
                Writeln (Error_Message);
                Writeln ('  Error_Number = ', Hex_String (Error_Number));
                Writeln ('EMM test program aborting.');
                Halt (1);
              end; { Procedure Error }


          {--------------------------------------------------------------}
          { This program is an example of the basic EMM functions that   }
          { you need in order to use EMM memory with Turbo Pascal.       }
          {--------------------------------------------------------------}
          Begin
            ClrScr;
            Window (5,2,77,22);






          Writing Programs That Use Expanded Memory                      26





            {------------------------------------------------------------}
            { Determine if the Expanded Memory Manager is installed.  If }
            { not, then terminate 'main' with an ErrorLevel code of 1.   }
            {------------------------------------------------------------}
            If not (Emm_Installed) then
              Begin
                Writeln ('The LIM EMM is not installed.');
                Halt (1);
              end
            else
              Begin
                { Get the version number and display it }
                Error_Code := Get_Version_Number (Version_Number);
                If Error_Code <> STATUS_OK then
                  Error ('Error getting EMM version number.', Error_Code)
                else
                  Writeln ('LIM Expanded Memory Manager, version ',
                           Version_Number, ' is ready for use.');
              end;
            Writeln;

            {------------------------------------------------------------}
            { Determine if there are enough expanded memory pages for    }
            { this application.                                          }
            {------------------------------------------------------------}
            Pages_Needed := APPLICATION_PAGE_COUNT;
            Error_Code   := EMM_Pages_Available (Total_EMM_Pages,
                                                 Available_EMM_Pages);
            If Error_Code <> STATUS_OK then
              Error ('Error determining number of EMM pages available.',
                     Error_Code);
            Writeln ('There are a total of ', Total_EMM_Pages,
                     ' expanded memory pages present in this system.');
            Writeln ('  ', Available_EMM_Pages,
                     ' of those pages are available for use.');
            Writeln;

            {------------------------------------------------------------}
            { If there is an insufficient number of pages for the        }
            { application, then report the error and terminate the EMM   }
            { example program.                                           }
            {------------------------------------------------------------}
            If Pages_Needed > Available_EMM_Pages then
              Begin
                Str (Pages_Needed, Pages_Number_String);
                Error ('We need ' + Pages_Number_String +
                       ' EMM pages.  There are not that many available.',
                       Error_Code);
              end; { Pages_Needed > Available_EMM_Pages }




          Writing Programs That Use Expanded Memory                      27





            {------------------------------------------------------------}
            { Allocate expanded memory pages for our use.                }
            {------------------------------------------------------------}
            Error_Code :=
              Allocate_Expanded_Memory_Pages (Pages_Needed, Emm_Handle);
            Str (Pages_Needed, Pages_Number_String);
            If Error_Code <> STATUS_OK then
              Error ('EMM test program failed trying to allocate '
                     + Pages_Number_String
                     + ' pages for usage.', Error_Code);
            Writeln (APPLICATION_PAGE_COUNT,
                     ' EMM page(s) allocated for the EMM test program.');
            Writeln;

            {------------------------------------------------------------}
            { Map in the required logical pages to the physical pages    }
            { given to us, in this case just one page.                   }
            {------------------------------------------------------------}
            Logical_Page  := 0;
            Physical_Page := 0;
            Error_Code := Map_Expanded_Memory_Pages (Emm_Handle,
                                                     Logical_Page,
                                                     Physical_Page);
            If Error_Code <> STATUS_OK then
              Error ('EMM test program failed trying to map '
                     + 'logical pages into physical pages.',
                     Error_Code);

            Writeln ('Logical Page ',
                     Logical_Page,
                     ' successfully mapped into Physical Page ',
                     Physical_Page);
            Writeln;

            {------------------------------------------------------------}
            { Get the expanded memory page frame address.                }
            {------------------------------------------------------------}
            Error_Code := Get_Page_Frame_Base_Address
                            (Page_Frame_Base_Address);
            If Error_Code <> STATUS_OK then
              Error ('EMM test program unable to get the base Page'
                     + ' Frame Address.',
                     Error_Code);
            Writeln ('The base address of the EMM page frame is = '
                     + Hex_String (Page_Frame_Base_Address));
            Writeln;







          Writing Programs That Use Expanded Memory                      28





            {------------------------------------------------------------}
            { Write a test pattern to expanded memory.                   }
            {------------------------------------------------------------}
            For Offset := 0 to 16382 do
              Begin
                Mem[Page_Frame_Base_Address:Offset] := Offset mod 256;
              end;

            {------------------------------------------------------------}
            { Make sure that what is in EMM memory is what was just      }
            { written.                                                   }
            {------------------------------------------------------------}
            Writeln ('Testing EMM memory.');

            Offset := 1;
            Verify := True;
            while (Offset <= 16382) and (Verify = True) do
              Begin
                If Mem[Page_Frame_Base_Address:Offset] <> Offset mod 256
                  then Verify := False;
                Offset := Succ (Offset);
              end; { while (Offset <= 16382) and (Verify = True) }

            {------------------------------------------------------------}
            { If what is read does not match what was written,           }
            { an error occurred.                                         }
            {------------------------------------------------------------}
            If not Verify then
              Error ('What was written to EMM memory was not found during'
                     + ' memory verification test.',
                     0);
            Writeln ('EMM memory test successful.');
            Writeln;

            {------------------------------------------------------------}
            { Return the expanded memory pages given to us back to the   }
            { EMM memory pool before terminating our test program.       }
            {------------------------------------------------------------}
            Error_Code := Deallocate_Expanded_Memory_Pages (Emm_Handle);
            If Error_Code <> STATUS_OK then
              Error ('EMM test program was unable to deallocate '
                     + 'the EMM pages in use.',
                     Error_Code);
            Writeln (APPLICATION_PAGE_COUNT,
                     ' pages(s) deallocated.');
            Writeln;
            Writeln ('EMM test program completed.');

          end.




          Writing Programs That Use Expanded Memory                      29





          Example 3

               This program is written in Microsoft's macro assembler.


          CODE SEGMENT
               ASSUME CS:CODE, DS:CODE

          MOV   AX,CS
          MOV   DX,AX
               .
               .
               .
          check_emm_installed:

          MOV   AH,35h                  ; AH = DOS get interrupt vector
                                        ; function
          MOV   AL,67h                  ; AL = EMM interrupt vector number
          INT   21h
          MOV   DI,0Ah                  ; ES:DI points to where device     
                                        ; name should be
          LEA   SI,EMM_device_name      ; DS:SI points to ASCII string     
                                        ; containing EMM device name

          MOV   CX,device_name_length   ; set up loop counter for string op
          CLD                           ; set up direction flag for forward
          REPE  CMPSB                   ; Compare the strings
          JNE   exit                    ; IF strings not equal THEN exit
                                        ; ELSE
          check_enough_unallocated_pages:

          MOV   AH,41h                  ;    AH = EMM get unallocated page
                                        ;    count function code
          INT   67h
          OR    AH,AH                   ; Check EMM status
          JNZ   emm_error_handler       ; IF error THEN goto error handler
                                        ; ELSE
          allocate_expanded_memory_pages:

          MOV   AH,43h                  ;    AH = EMM allocate pages
                                        ;    function code
          MOV   BX,2                    ;    BX = number of pages needed
          INT   67h
          OR    AH,AH                   ; Check EMM status
          JNZ   emm_error_handler       ; IF error THEN goto error handler
                                        ; ELSE
          MOV   emm_handle,DX           ;    save EMM handle

          map_expanded_memory_pages:

          MOV   AH,44h                  ; AH = EMM map pages function
          MOV   DX,emm_handle           ; DX = application's handle

          Writing Programs That Use Expanded Memory                      30





          map_0_to_0:

          MOV   BX,0                    ; BX = logical page 0
          MOV   AL,0                    ; AL = physical page 0
          INT   67h
          OR    AH,AH                   ; Check EMM status
          JNZ   emm_error_handler       ; If error THEN goto error handler
                                        ; ELSE
          get_page_frame_address:

          MOV   AH,41h                  ; AH = EMM get page frame base
                                        ; address function
          INT   67h
          OR    AH,AH                   ; Check EMM status
          JNZ   emm_error_handler       ; IF error THEN goto error handler
          MOV   pf_addr,BX              ; ELSE save pf_addr

          write_to_expanded_memory:     ; Write zeros to memory mapped at
                                        ; physical page 0
          MOV   AX,pf_addr
          MOV   ES,AX                   ; ES points to physical page 0
          MOV   DI,0                    ; DI indexes into physical page 0
          MOV   AL,0                    ; Initialize AL for string STOSB
          MOV   CX,4000h                ; Initialize loop counter to length 
                                        ; of expanded memory page size
          CLD                           ; set up direction flag for forward
          REP   STOSB

          deallocate_pages:

          MOV   AH,45h                  ; AH = EMM deallocate pages        
                                        ; function
          MOV   DX,emm_handle
          INT   67h                     ; return handle's pages to EMM
          OR    AH,AH                   ; Check EMM status
          JNZ   emm_error_handler       ; IF error THEN goto error handler

          exit:

          MOV   AH,4Ch                  ; AH = DOS exit function
          INT   21h                     ; return to DOS


          EMM_device_name DB 'EMMXXXX0' ; ASCII EMM device name string

          device_name_length EQU 8

          CODE ENDS
               END




          Writing Programs That Use Expanded Memory                      31





          Example 4

               This program is an example of how to exchange a 256K-byte
               block of data from conventional memory to expanded memory.


          CODE SEGMENT
               ASSUME CS:CODE, DS:CODE
               .
               .
               .
          xchg_packet_set_up:

          ;DS:SI = xchg_packet

          MOV   AX,SEG xchg_packet
          MOV   DS,AX
          MOV   SI,OFFSET xchg_packet

          ;Moving 256K of data from conventional memory to expanded memory

          MOV   WORD PTR [SI].region_length[0],0
          MOV   WORD PTR [SI].region_length[2],4
          MOV   [SI].src_mem_type,0
          MOV   [SI].dest_mem_type,1

          ;starting at segment: 4000h, offset: 0

          MOV   [SI].src_init_seg_page,4000h
          MOV   [SI].src_init_offset,0

          ;Move data into expanded memory logical page 0, offset 0.

          MOV   [SI].dest_init_seg_page,0
          MOV   [SI].dest_init_offset,0

          ;Initialize for future compatibility

          MOV   [SI].src_handle,0

          ;Need handle for expanded memory destination.

          MOV   DX,emm_handle
          MOV   [SI].dest_handle,DX

          ;AX = EMM Exchange Memory function

          MOV   AX,5701h
          INT   67h
          OR    AH,AH
          JNZ   emm_error_handler


          Writing Programs That Use Expanded Memory                      32





          xchg_struct                    STRUC
             region_length               DD ?
             src_mem_type                DB ?
             src_handle                  DW ?
             src_init_offset             DW ?
             src_init_seg_page           DW ?
             dest_mem_type               DB ?
             dest_handle                 DW ?
             dest_init_offset            DW ?
             dest_init_seg_page          DW ?
          xchg_struct                    ENDS

          xchg_packet                    xchg_struct

          CODE  ENDS
                END





































          Writing Programs That Use Expanded Memory                      33





          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         37

             2    Get Page Frame Address                    41h         38

             3    Get Unallocated Page Count                42h         40

             4    Allocate Pages                            43h         42

             5    Map/Unmap Handle Page                     44h         46

             6    Deallocate Pages                          45h         49

             7    Get Version                               46h         51

             8    Save Page Map                             47h         53

             9    Restore Page Map                          48h         55

            10    Reserved                                  49h         57

            11    Reserved                                  4Ah         58

            12    Get Handle Count                          4Bh         59

            13    Get Handle Pages                          4Ch         61

            14    Get All Handle Pages                      4Dh         63


          EMM Functions                                                  34





          Table 3-1.  List of EMM Functions (continued)
          ----------------------------------------------------------------

          Number             Function Name                Hex Value   Page

          ----------------------------------------------------------------

            15    Get Page Map                              4E00h       65
                  Set Page Map                              4E01h       67
                  Get & Set Page Map                        4E02h       69
                  Get Size of Page Map Save Array           4E03h       71

            16    Get Partial Page Map                      4F00h       73
                  Set Partial Page Map                      4F01h       76
                  Get Size of Partial Page Map
                     Save Array                             4F02h       78

            17    Map/Unmap Multiple Handle Pages
                  (Physical page number mode)               5000h       82
                  Map/Unmap Multiple Handle Pages
                  (Segment address mode)                    5001h       85

            18    Reallocate Pages                          51h         88

            19    Get Handle Attribute                      5200h       92
                  Set Handle Attribute                      5201h       94
                  Get Handle Attribute Capability           5202h       96

            20    Get Handle Name                           5300h       98
                  Set Handle Name                           5301h      100

            21    Get Handle Directory                      5400h      102
                  Search for Named Handle                   5401h      105
                  Get Total Handles                         5402h      107

            22    Alter Page Map & Jump
                  (Physical page number mode)               5500h      109
                  Alter Page Map & Jump
                  (Segment address mode)                    5501h      109

            23    Alter Page Map & Call
                  (Physical page number mode)               5600h      113
                  Alter Page Map & Call
                  (Segment address mode)                    5601h      113
                  Get Page Map Stack Space Size             5602h      118

            24    Move Memory Region                        5700h      120
                  Exchange Memory Region                    5701h      126

            25    Get Mappable Physical Address Array       5800h      132
                  Get Mappable Physical Address Array
                     Entries                                5801h      136

          EMM Functions                                                  35





          Table 3-1.  List of EMM Functions (continued)
          ----------------------------------------------------------------

          Number             Function Name                Hex Value   Page

          ----------------------------------------------------------------

            26    Get Hardware Configuration Array          5900h      138
                  Get Unallocated Raw Page Count            5901h      142

            27    Allocate Standard Pages                   5A00h      144
                  Allocate Raw Pages                        5A01h      147

            28    Get Alternate Map Register Set            5B00h      153
                  Set Alternate Map Register Set            5B01h      157
                  Get Alternate Map Save Array Size         5B02h      161
                  Allocate Alternate Map Register Set       5B03h      163
                  Deallocate Alternate Map Register Set     5B04h      166
                  Allocate DMA Register Set                 5B05h      168
                  Enable DMA on Alternate Map
                     Register Set                           5B06h      170
                  Disable DMA on Alternate Map
                     Register Set                           5B07h      173
                  Deallocate DMA Register Set               5B08h      175

            29    Prepare Expanded Memory Hardware
                     for Warmboot                           5Ch        177

            30    Enable OS/E Function Set                  5D00h      179
                  Disable OS/E Function Set                 5D01h      182
                  Return OS/E Access Key                    5D02h      185

          ----------------------------------------------------------------




















          EMM Functions                                                  36





          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






          EMM Functions                                                  37





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







          EMM Functions                                                  38





          Function 2. Get Page Frame Address



          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








































          EMM Functions                                                  39





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


          EMM Functions                                                  40





          Function 3. Get Unallocated Page Count



          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






































          EMM Functions                                                  41





          Function 4. Allocate Pages



               The Allocate Pages function allocates the number of pages
               requested and assigns a unique EMM handle to these pages. 
               The EMM handle owns these pages until the application
               deallocates them.

               Handles which are assigned using this function will have
               16K-byte pages, the size of a standard expanded memory page. 
               If the expanded memory board hardware isn't able to supply
               16K-byte pages, it will emulate them by combining multiple
               non-standard size pages to form a single 16K-byte page.  All
               application programs and functions that use the handles this
               function returns will deal with 16K-byte pages.

               The numeric value of the handles the EMM returns are in the
               range of 1 to 254 decimal (0001h to 00FEh).  The OS handle
               (handle value 0) is never returned by the Allocate Pages
               function.  Also, the uppermost byte of the handle will be
               zero and cannot be used by the application.  A memory
               manager should be able to supply up to 255 handles, includ-
               ing the OS handle.  An application can use Function 21 to
               find out how many handles an EMM supports.

               Allocating zero pages to a handle is not valid.  If an
               application needs to allocate 0 pages to a handle it should
               use Function 27 (Allocate Standard Pages subfunction)
               provided for this purpose.

          Note............................................................
               This note affects expanded memory manager implementors and
               operating system developers only.  Applications should not
               use the following characteristics of the memory manager.  An
               application violating this rule will be incompatible with
               future versions of Microsoft's operating systems and
               environments.

               To be compatible with this specification, an expanded memory
               manager will provide a special handle which is available to
               the operating system only.  This handle will have a value of
               0000h and will have a set of pages allocated to it when the
               expanded memory manager driver installs.  The pages that the
               memory manager will automatically allocate to handle 0000h
               are those that backfill conventional memory.  Typically,
               this backfill occurs between addresses 40000h (256K) and
               9FFFFh (640K).  However, the range can extend below and
               above this limit if the hardware and memory manager have the
               capability.



          EMM Functions                                                  42





          Function 4. Allocate Pages



               An operating system won't have to invoke Function 4 to
               obtain this handle because it can assume the handle already
               exists and is available for use immediately after the
               expanded memory device driver installs.  When an operating
               system wants to use this handle, it uses the special handle
               value of 0000h.  The operating system will be able to invoke
               any EMM function using this special handle value.  To
               allocate pages to this handle, the operating system need
               only invoke Function 18 (Reallocate Pages).

               There are two special cases for this handle:

               1.  Function 4 (Allocate Pages).  This function must never
                   return zero as a handle value.  Applications must always
                   invoke Function 4 to allocate pages and obtain a handle
                   which identifies the pages which belong to it.  Since
                   Function 4 never returns a handle value of zero, an
                   application will never gain access to this special
                   handle.

               2.  Function 6 (Deallocate Pages).  If the operating system
                   uses it to deallocate the pages which are allocated to
                   this special handle, the pages the handle owns will be
                   returned to the manager for use.  But the handle will
                   not be available for reassignment.  The manager should
                   treat a deallocate pages function request for this
                   handle the same as a reallocate pages function request,
                   where the number of pages to reallocate to this handle
                   is zero.


          CALLING PARAMETERS

               AH = 43h
                   Contains the Allocate Pages function.

               BX = num_of_pages_to_alloc
                   Contains the number of pages you want your program to
                   allocate.










          EMM Functions                                                  43





          Function 4. Allocate Pages



          RESULTS

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

               DX = handle
                   Contains a unique EMM handle.  Your program must use
                   this EMM handle (as a parameter) in any function that
                   requires it.  You can use up to 255 handles.  The
                   uppermost byte of the handle will be zero and cannot be
                   used by the application.


          REGISTERS MODIFIED

               AX, DX


          STATUS

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

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

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

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

               AH = 85h   RECOVERABLE.
                   All EMM handles are being used.

               AH = 87h   RECOVERABLE.
                   There aren't enough expanded memory pages present in the
                   system to satisfy your program's request.

               AH = 88h   RECOVERABLE.
                   There aren't enough unallocated pages to satisfy your
                   program's request.

               AH = 89h   RECOVERABLE.
                   Your program attempted to allocate zero pages.

          EMM Functions                                                  44





          Function 4. Allocate Pages



          EXAMPLE

          num_of_pages_to_alloc          DW ?
          emm_handle                     DW ?

          MOV   BX,num_of_pages_to_alloc ; load number of pages
          MOV   AH,43h                   ; load function code
          INT   67h                      ; call the memory manager
          OR    AH,AH                    ; check EMM status
          JNZ   emm_err_handler          ; jump to error handler on error
          MOV   emm_handle,DX            ; save EMM handle






































          EMM Functions                                                  45





          Function 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 mapped 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.




          EMM Functions                                                  46





          Function 5. Map/Unmap Handle Pages



               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

               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 to map a logical
                   page when no logical pages are allocated to the handle.



          EMM Functions                                                  47





          Function 5. Map/Unmap Handle Pages



               AH = 8Bh   RECOVERABLE.
                   The physical page number is out of the range of allow-
                   able 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





























          EMM Functions                                                  48





          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, its 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 allo-
                   cated 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.

          EMM Functions                                                  49





          Function 6. Deallocate Pages



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
























          EMM Functions                                                  50





          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.




          EMM Functions                                                  51





          Function 7. Get Version



               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

          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



























          EMM Functions                                                  52





          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
               routine, 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.




          EMM Functions                                                  53





          Function 8. Save Page Map



          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.

               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



          EMM Functions                                                  54





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

               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.





          EMM Functions                                                  55





          Function 9. Restore Page Map



          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.

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






          EMM Functions                                                  56





          Function 10. Reserved



               In earlier versions of the Lotus/Intel/Microsoft Expanded
               Memory Specification, Function 10 returned the page mapping
               register I/O array.  This function is now reserved 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. 
               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 your
               program attempts to mix the use of the new functions
               (Functions 16 through 30) and Functions 10 and 11.  Func-
               tions 10 and 11 are specific to the hardware on Intel
               expanded memory boards and will not work correctly on all
               vendors' expanded memory boards.


































          EMM Functions                                                  57





          Function 11. Reserved



               In earlier versions of the Lotus/Intel/Microsoft Expanded
               Memory Specification, Function 11 returned a page transla-
               tion array.  This function is now reserved 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. 
               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 your
               program attempts to mix the use of the new functions
               (Functions 16 through 30) and Functions 10 and 11.  Func-
               tions 10 and 11 are specific to the hardware on Intel
               expanded memory boards and will not work correctly on all
               vendors' expanded memory boards.


































          EMM Functions                                                  58





          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.




          EMM Functions                                                  59





          Function 12. Get Handle Count



          EXAMPLE

          total_open_emm_handles              DW ?

          MOV   AH,4Bh                        ; load function code
          INT   67h                           ; call the memory manger
          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






































          EMM Functions                                                  60





          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.

          EMM Functions                                                  61





          Function 13. Get Handle Pages



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


          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






























          EMM Functions                                                  62





          Function 14. Get All Handle 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.





          EMM Functions                                                  63





          Function 14. Get All Handle Pages



          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.

               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

          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 the EMM status
          JNZ   emm_err_handler          ; jump to error handler on error
          MOV   total_open_handles,BX    ; save total open handle count













          EMM Functions                                                  64





          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 applica-
               tion 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 regis-
                   ters 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.

          EMM Functions                                                  65





          Function 15. Get/Set Page Map
          Get Page Map subfunction



               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

          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





















          EMM Functions                                                  66





          Function 15. Get/Set Page Map
          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.




          EMM Functions                                                  67





          Function 15. Get/Set Page Map
          Set Page Map subfunction



               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 (?)

          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

























          EMM Functions                                                  68





          Function 15. Get/Set Page Map
          Get & Set Page Map subfunction



          PURPOSE

               The Get & Set Page Map 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 subfunc-
                   tion.


          EMM Functions                                                  69





          Function 15. Get/Set Page Map
          Get & Set Page Map subfunction



          REGISTERS MODIFIED

               AX


          STATUS

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

               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


          EMM Functions                                                  70





          Function 15. Get/Set Page Map
          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 subfunc-
                   tion.  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 subfunc-
                   tions.


          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.

          EMM Functions                                                  71





          Function 15. Get/Set Page Map
          Get Size of Page Map Save Array subfunction



               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
          MOV   size_of_array,AL         ; save array size































          EMM Functions                                                  72





          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 immediate-
                       ly follows it.  This number should not exceed the
                       number of mappable segments in the system.






          EMM Functions                                                  73





          Function 16. Get/Set Partial Page Map
          Get Partial Page Map subfunction



                   .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

               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.


          EMM Functions                                                  74





          Function 16. Get/Set Partial Page Map
          Get Partial Page Map subfunction



               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 partial_page_map
          MOV   AX,SEG dest_array
          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



















          EMM Functions                                                  75





          Function 16. Get/Set Partial Page Map
          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 potential-
               ly 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 deter-
                   mine 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.


          EMM Functions                                                  76





          Function 16. Get/Set Partial Page Map
          Set Partial Page Map subfunction



               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

          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























          EMM Functions                                                  77





          Function 16. Get/Set Partial Page Map
          Get Size of Partial Page Map Save Array subfunction



          PURPOSE

               The Get Size of Partial Page Map Save Array 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 implementa-
                   tion 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_seg-
                   ment_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 areas 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.



          EMM Functions                                                  78





          Function 16. Get/Set Partial Page Map
          Get Size of Partial Page Map Save Array subfunction



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
















          EMM Functions                                                  79





          Function 17. Map/Unmap 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 subfunc-
               tion) 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.


          EMM Functions                                                  80





          Function 17. Map/Unmap Multiple Handle Pages



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

               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.
























          EMM Functions                                                  81





          Function 17. 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 (maximum number of physical
                       pages supported in the system - 1).



          EMM Functions                                                  82





          Function 17. Map/Unmap Multiple Handle Pages
          Logical Page/Physical Page Method



          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 pertain-
                   ing 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 the 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.


          EMM Functions                                                  83





          Function 17. Map/Unmap Multiple Handle Pages
          Logical Page/Physical Page Method



               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
          MOV   DS,AX
          LEA   SI,log_to_phys_map            ; DS:SI points to
                                              ; log_to_phys_map
          MOV   CX,LENGTH log_to_phys_map     ; set length field
          MOV   DX,emm_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



























          EMM Functions                                                  84





          Function 17. 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

          EMM Functions                                                  85





          Function 17. Map/Unmap Multiple Handle Pages
          Logical Page/Segment Address Method



          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 could not 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 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 speci-
                   fied 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.



          EMM Functions                                                  86





          Function 17. Map/Unmap Multiple Handle Pages
          Logical Page/Segment Address Method



          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
          MOV   DX,emm_handle
          MOV   AX,5001h                      ; 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































          EMM Functions                                                  87





          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
                   the 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 success-
                   ful 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 alloca-
                   tion 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.







          EMM Functions                                                  88





          Function 18. Reallocate Pages



          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.


          CALLING PARAMETERS

               AH = 51h
                   Contains the Reallocate Handle Pages function.

               DX = handle
                   Contains the EMM handle.

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


          RESULTS

               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 informa-
                   tion can be used to verify that the request generated
                   the expected results.


          REGISTERS MODIFIED

               AX, BX


          STATUS

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

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

          EMM Functions                                                  89





          Function 18. Reallocate Pages



               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 cor-
                   rupted 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 addition-
                   al 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
          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









          EMM Functions                                                  90





          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 deficien-
               cy 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.

















          EMM Functions                                                  91





          Function 19. Get/Set Handle Attribute
          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 at-
                   tributes 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 handle's attribute has been obtained.



          EMM Functions                                                  92





          Function 19. Get/Set Handle Attribute
          Get Handle Attribute subfunction



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













          EMM Functions                                                  93





          Function 19. Get/Set Handle Attribute
          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






          EMM Functions                                                  94





          Function 19. Get/Set Handle Attribute
          Set Handle Attribute subfunction



          STATUS

               AH = 0   SUCCESSFUL.
                   The handle's 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 manager doesn't have any information pertaining to
                   the specified EMM handle.  The program may have cor-
                   rupted 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





          EMM Functions                                                  95





          Function 19. Get/Set Handle Attribute
          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.

          EMM Functions                                                  96





          Function 19. Get/Set Handle Attribute
          Get Attribute Capability subfunction



          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







































          EMM Functions                                                  97





          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.


          EMM Functions                                                  98





          Function 20. Get/Set Handle Name
          Get Handle Name subfunction



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














          EMM Functions                                                  99





          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 handle's
               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.



          EMM Functions                                                 100





          Function 20. Get/Set Handle Name
          Set Handle Name subfunction



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










          EMM Functions                                                 101





          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 allo-
               cated, 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 assign-
               ment 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.





          EMM Functions                                                 102





          Function 21. Get Handle Directory
          Get Handle Directory subfunction



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

               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.



          EMM Functions                                                 103





          Function 21. Get Handle Directory
          Get Handle Directory subfunction



          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

































          EMM Functions                                                 104





          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 distin-
               guish 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 being 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.



          EMM Functions                                                 105





          Function 21. Get Handle Directory
          Search For Named Handle subfunction



               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 = A0h   NON-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

















          EMM Functions                                                 106





          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.

          EMM Functions                                                 107





          Function 21. Get Handle Directory
          Get Total Handles subfunction



          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







































          EMM Functions                                                 108





          Function 22. Alter Page Map & Jump



          PURPOSE

               This function alters the memory mapping context and trans-
               fers 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

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




          EMM Functions                                                 109





          Function 22. Alter Page Map & Jump



               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 trans-
                       ferred.  The address is represented in segment:of-
                       fset 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 follows it.  The array is as long as the
                       application developer needs in order 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 struc-
                       tures which contain the logical page numbers and
                       physical pages or segment address 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



          EMM Functions                                                 110





          Function 22. Alter Page Map & Jump



          Note............................................................
               Values in registers which don't contain required parameters
               maintain the values across the jump.  The values in regis-
               ters (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.

               AH = 8Ah   RECOVERABLE.
                   One or more of the logical pages to map into a cor-
                   responding 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.



          EMM Functions                                                 111





          Function 22. Alter Page Map & Jump



               AH = 8Fh   NON-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 segment mode
          INT   67h                           ; call memory manager
          OR    AH,AH                         ; check EMM status
          JNZ   emm_err_handler               ; jump to error handler on   
                                              ; error
























          EMM Functions                                                 112





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





          EMM Functions                                                 113





          Function 23. Alter Page Map & Call
          Alter Page Map & Call subfunction



                   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

                       .new_page_map.phys_page_number_seg
                       .old_page_map.phys_page_number_seg

                   members are physical page 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 trans-
                       ferred.  The address is represented in segment:of-
                       fset 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.


          EMM Functions                                                 114





          Function 23. Alter Page Map & Call
          Alter Page Map & Call subfunction



                   .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 num-
                       bers/segments at which they are to be mapped im-
                       mediately 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 num-
                       bers/segments at which they are to be mapped im-
                       mediately 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:

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

          EMM Functions                                                 115





          Function 23. Alter Page Map & Call
          Alter Page Map & Call subfunction



          REGISTERS MODIFIED

               AX

          Note............................................................
               Values in registers which don't contain required parameters
               maintain the values across the call.  The values in regis-
               ters (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 cor-
                   responding 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.







          EMM Functions                                                 116





          Function 23. Alter Page Map & Call
          Alter Page Map & Call subfunction



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











          EMM Functions                                                 117





          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.



          EMM Functions                                                 118





          Function 23. Alter Page Map & Call
          Get Page Map Stack Space Size subfunction



               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
          MOV   stack_space_reqd,BX      ; save required stack size count



































          EMM Functions                                                 119





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


          EMM Functions                                                 120





          Function 24. Move/Exchange Memory Region
          Move Memory Region subfunction



          CALLING PARAMETERS

               AX = 5700h
                   Contains the Move Memory Region function.

                   move_source_dest_struct         STRUC
                       region_length               DD ?
                       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 move_source_dest structure
                   Contains a pointer to a data structure which contains
                   the source and destination information for the move. 
                   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 seg-
                       ment).  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.

          EMM Functions                                                 121





          Function 24. Move/Exchange Memory Region
          Move Memory Region subfunction



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

          EMM Functions                                                 122





          Function 24. Move/Exchange Memory Region
          Move Memory Region subfunction



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

                       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.

               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.

          EMM Functions                                                 123





          Function 24. Move/Exchange Memory Region
          Move Memory Region subfunction



               AH = 83h   NON-RECOVERABLE.
                   The manager couldn't find either the source or destina-
                   tion 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 physi-
                   cally 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 applica-
                   tion 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.



          EMM Functions                                                 124





          Function 24. Move/Exchange Memory Region
          Move Memory Region subfunction



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

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
















          EMM Functions                                                 125





          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 convention-
               al 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 conven-
               tional 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 bytes 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 an exchange are invalid, and the
               exchange will not take place.

          EMM Functions                                                 126





          Function 24. Move/Exchange Memory Region
          Exchange Memory Region subfunction



          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 ?
                       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 xchg_source_dest structure
                   Contains a pointer to the 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 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.



          EMM Functions                                                 127





          Function 24. Move/Exchange Memory Region
          Exchange Memory Region subfunction



                       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 exchange at. 
                       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 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.

                       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, this variable has no meaning
                       and should be set to zero for future compatibility.




          EMM Functions                                                 128





          Function 24. Move/Exchange Memory Region
          Exchange Memory Region subfunction



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

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



          REGISTERS MODIFIED

               AX


          STATUS

               AH = 0   SUCCESSFUL.
                   The memory regions have been exchanged.



          EMM Functions                                                 129





          Function 24. Move/Exchange Memory Region
          Exchange Memory Region subfunction



               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 destina-
                   tion EMM handles.  The memory manager does not currently
                   have any information pertaining to the handles speci-
                   fied.  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.





          EMM Functions                                                 130





          Function 24. Move/Exchange Memory Region
          Exchange Memory Region subfunction



               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.

               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
                   combination of source/destination starting address and
                   length of the region to be exchanged exceeds 1M bytes. 
                   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





          EMM Functions                                                 131





          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.







          EMM Functions                                                 132





          Function 25. Get Mappable Physical Address Array
          Get Mappable Physical Address Array subfunction



                   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

                       An expanded memory board has a large page frame
                       starting at address C0000h and has mappable conven-
                       tional 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




          EMM Functions                                                 133





          Function 25. Get Mappable Physical Address Array
          Get Mappable Physical Address Array subfunction



          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.















          EMM Functions                                                 134





          Function 25. Get Mappable Physical Address Array
          Get Mappable Physical Address Array subfunction



          EXAMPLE

          mappable_phys_page             mappable_phys_page_struct (?)

          mappable_page_entry_count      DW ?

          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






























          EMM Functions                                                 135





          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 Entries
                   subfunction.  This subfunction returns a word which
                   represents the number of entries in the array returned
                   by the previous subfunction.  This number also repre-
                   sents 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 number of mappable physical pages 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.


          EMM Functions                                                 136





          Function 25. Get Mappable Physical Address Array
          Get Mappable Physical Address Array Entries subfunction



               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
          JNZ   emm_err_handler               ; jump to error handler
                                              ; on error
          MOV   mappable_page_entry_count,CX  ; save mappable
                                              ; page entry count

































          EMM Functions                                                 137





          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 subfunc-
                   tion.

                   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.




          EMM Functions                                                 138





          Function 26. Get Expanded Memory Hardware Information
          Get Hardware Configuration Array subfunction



                   .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 alter-
                       nate 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 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_register_sets
                       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.






          EMM Functions                                                 139





          Function 26. Get Expanded Memory Hardware Information
          Get Hardware Configuration Array subfunction



                       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 informa-
                   tion described above.


          REGISTERS MODIFIED

               AX


          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.

          EMM Functions                                                 140





          Function 26. Get Expanded Memory Hardware Information
          Get Hardware Configuration Array subfunction



               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





























          EMM Functions                                                 141





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







          EMM Functions                                                 142





          Function 26. Get Expanded Memory Hardware Information
          Get Unallocated Raw Page Count subfunction



          STATUS

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

               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














          EMM Functions                                                 143





          Function 27. Allocate Standard/Raw Pages
          Allocate Standard Pages subfunction



          PURPOSE

               The Allocate Standard Pages subfunction allocates the number
               of standard size (16K bytes) pages that the operating system
               requests and assigns a unique EMM handle to these pages. 
               The EMM handle owns these pages until the operating system
               deallocates them.  This subfunction allows you to allocate
               zero pages to a handle, unlike Function 4 (Allocate Pages).

          Note............................................................
               This note affects expanded memory manager implementors and
               operating system developers only.  Applications should not
               use the following characteristic of the memory manager.  An
               application violating this rule will be incompatible with
               future versions of Microsoft's operating systems and
               environments.

               To be compatible with this specification, an expanded memory
               manager will provide a special handle which is available to
               the operating system only.  This handle will have a value of
               0000h and will have a set of pages allocated to it when the
               expanded memory manager driver installs.  The pages that the
               memory manager will automatically allocate to handle 0000h
               are those that backfill conventional memory.  Typically,
               this backfill occurs between addresses 40000h (256K) and
               9FFFFh (640K).  However, the range can extend below and
               above this limit if the hardware and memory manager have the
               capability.

               An operating system won't have to invoke Function 27 to
               obtain this handle because it can assume the handle already
               exists and is available for use immediately after the
               expanded memory device driver installs.  When an operating
               system wants to use this handle, it uses the special handle
               value of 0000h.  The operating system will be able to invoke
               any EMM function using this special handle value.  To
               allocate pages to this handle, the operating system need
               only invoke Function 18 (Reallocate Pages).

               There are two special cases for this handle:

               1.  Function 27 (Allocate Standard Pages subfunction).  This
                   function must never return zero as a handle value. 
                   Applications must always invoke Function 27 to allocate
                   pages and obtain a handle which identifies the pages
                   which belong to it.  Since Function 27 never returns a


          EMM Functions                                                 144





          Function 27. Allocate Standard/Raw Pages
          Allocate Standard Pages subfunction



                   handle value of zero, an application will never gain
                   access to this special handle.

               2.  Function 6 (Deallocate Pages).  If the operating system
                   uses it to deallocate the pages which are allocated to
                   this handle, the pages the handle owns will be returned
                   to the manager for use.  But the handle will not be
                   available for reassignment.  The manager should treat a
                   deallocate pages function request for this handle the
                   same as a reallocate pages function request, where the
                   number of pages to reallocate to this handle is zero.


          CALLING PARAMETERS

               AX = 5A00h
                   Contains the Allocate Standard Pages subfunction.

               BX = num_of_standard_pages_to_alloc
                   Contains the number of standard pages the operating
                   system wants to allocate.


          RESULTS

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

               DX = handle
                   Contains a unique EMM handle.  The operating system must
                   use this EMM handle as a parameter in any function that
                   requires it.  Up to 255 handles may be obtained.  (Both
                   Function 27 and Function 4 must share the same 255
                   handles.)

                   For all functions using this handle, the length of the
                   physical and logical pages allocated to it are standard
                   length (that is, 16K bytes).


          REGISTERS MODIFIED

               AX, DX






          EMM Functions                                                 145





          Function 27. Allocate Standard/Raw Pages
          Allocate Standard Pages subfunction



          STATUS

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

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

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

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

               AH = 85h   RECOVERABLE.
                   All EMM handles are being used.

               AH = 87h   RECOVERABLE.
                   There aren't enough expanded memory pages present in the
                   system to satisfy the operating system's request.

               AH = 88h   RECOVERABLE.
                   There aren't enough unallocated pages to satisfy the
                   operating system's request.

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


          EXAMPLE

          num_of_standard_pages_to_alloc      DW ?
          emm_handle                          DW ?

          MOV   BX,num_of_standard_pages_to_alloc
          MOV   AX,5A00h                      ; load function code
          INT   67h                           ; call the memory manager
          OR    AH,AH                         ; check EMM status
          JNZ   emm_err_handler               ; jump to error handler on
                                              ; error
          MOV   emm_handle,DX                 ; save handle



          EMM Functions                                                 146





          Function 27. Allocate Standard/Raw Pages
          Allocate Raw Pages subfunction



          PURPOSE

               The Allocate Raw Pages function allocates the number of non-
               standard size pages that the operating system requests and
               assigns a unique EMM handle to these pages.  The EMM handle
               owns these pages until the operating system deallocates
               them.  This function allows you to allocate zero pages to a
               handle, unlike Function 4 (Allocate Pages).

               A hardware vendor may design an expanded memory board that
               has a page size which is a sub-multiple of 16K bytes.  A
               physical page which is a sub-multiple of 16K is termed a raw
               page.  The operating system may deal with page sizes which
               are sub-multiples of 16K bytes.  The memory manager must
               treat any function using a handle with raw pages allocated
               to it by Function 27 (Allocate Raw Pages subfunction)
               differently than it does a handle that has normal 16K-byte
               pages allocated to it.

               Handles which are assigned using Function 4 (Allocate Pages)
               or Function 27 (Allocate Standard Pages subfunction) must
               have pages which are 16K bytes -- this is the length of a
               standard expanded memory page.  If the expanded memory board
               hardware is not able to supply 16K-byte pages, the memory
               manager must emulate pages which are 16K bytes combining
               multiple non-standard size pages to form a single 16K-byte
               page.

               Handles which are assigned using Function 27 (Allocate Raw
               Pages subfunction) are called raw handles.  All logical
               pages allocated to a raw handle may have a non-standard
               length (that is, not 16K bytes).  However, once the operat-
               ing system has allocated a number of raw pages to a handle,
               it is the responsibility of the memory manager to recognize
               that raw handle as one that has non-standard size pages
               allocated to it.  The memory manager must identify these
               handles and treat all functions which use handles which have
               non-standard page lengths differently.  The logical page
               length becomes the length of the non-standard size page for
               any raw handle that Function 27 assigns.

          Note............................................................
               This note affects expanded memory manager implementors and
               operating system developers only.  Applications should not
               use the following characteristic of the memory manager.  An
               application violating this rule will be incompatible with


          EMM Functions                                                 147





          Function 27. Allocate Standard/Raw Pages
          Allocate Raw Pages subfunction



               future versions of Microsoft's operating systems and
               environments.

               To be compatible with this specification, an expanded memory
               manager will provide a special handle which is available to
               the operating system only.  This handle will have a value of
               0000h and will have a set of pages allocated to it when the
               expanded memory manager driver installs.  The pages that the
               memory manager will automatically allocate to handle 0000h
               are those that backfill conventional memory.  Typically,
               this backfill occurs between addresses 40000h (256K) and
               9FFFFh (640K).  However, the range can extend below and
               above this limit if the hardware and memory manager have the
               capability.

               An operating system won't have to invoke Function 27 to
               obtain this handle because it can assume the handle already
               exists and is available for use immediately after the
               expanded memory device driver installs.  When an operating
               system wants to use this handle, it uses the special handle
               value of 0000h.  The operating system will be able to invoke
               any EMM function using this special handle value.  To
               allocate pages to this handle, the operating system need
               only invoke Function 18 (Reallocate Pages).

               There are two special cases for this handle:

               1.  Function 27 (Allocate Raw Pages subfunction).  This
                   function must never return zero as a handle value. 
                   Applications must always invoke Function 27 to allocate
                   pages and obtain a handle which identifies the pages
                   which belong to it.  Since Function 27 never returns a
                   handle value of zero, an application will never gain
                   access to this special handle.

               2.  Function 6 (Deallocate Pages).  If the operating system
                   uses it to deallocate the pages which are allocated to
                   this handle, the pages the handle owns will be returned
                   to the manager for use.  But the handle will not be
                   available for reassignment.  The manager should treat a
                   deallocate pages function request for this handle the
                   same as a reallocate pages function request, where the
                   number of pages to reallocate to this handle is zero.





          EMM Functions                                                 148





          Function 27. Allocate Standard/Raw Pages
          Allocate Raw Pages subfunction



          CALLING PARAMETERS

               AX = 5A01h
                   Contains the Allocate Raw Pages subfunction.

               BX = num_of_raw_pages_to_alloc
                   Contains the number of raw pages the operating system
                   wishes to allocate.


          RESULTS

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

               DX = raw handle
                   Contains a unique EMM raw handle.  The operating system
                   must use this EMM raw handle as a parameter in any
                   function that requires it.  Up to 255 handles may be
                   obtained.  (Both Function 4 and Function 27 must share
                   the same 255 handles).

                   For all functions using this raw handle, the length of
                   the physical and logical pages allocated to it may be
                   non-standard (that is, not 16K bytes).


          REGISTERS MODIFIED

               AX, DX


          STATUS

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

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

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




          EMM Functions                                                 149





          Function 27. Allocate Standard/Raw Pages
          Allocate Raw Pages subfunction



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

               AH = 85h   RECOVERABLE.
                   All EMM handles are being used.

               AH = 87h   RECOVERABLE.
                   There aren't enough expanded memory raw pages present in
                   the system to satisfy the operating system's request.

               AH = 88h   RECOVERABLE.
                   There aren't enough unallocated raw pages to satisfy the
                   operating system's request.

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


          EXAMPLE

          num_of_raw_pages_to_alloc           DW ?
          emm_raw_handle                      DW ?

          MOV   BX,num_of_raw_pages_to_alloc
          MOV   AX,5A01h                      ; load function code
          INT   67h                           ; call the memory manager
          OR    AH,AH                         ; check EMM status
          JNZ   emm_err_handler               ; jump to error handler
                                              ; on error
          MOV   emm_raw_handle,DX             ; save raw handle

















          EMM Functions                                                 150





          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 provid-
               ed.  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 register 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 register sets follows:

                                      Example 1

               1.  Allocate a DMA register set.

               2.  Get current register set.

               3.  Set the DMA register set.

          EMM Functions                                                 151





          Function 28. Alternate Map 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 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.

































          EMM Functions                                                 152





          Function 28. Alternate Map Register Set
          Get 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 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 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.



          EMM Functions                                                 153





          Function 28. Alternate Map Register Set
          Get Alternate Map Register Set subfunction



                   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

               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 seg-
                   ment:offset format.  This pointer is always returned if
                   the expanded memory hardware does not supply alternate
                   mapping register sets.








          EMM Functions                                                 154





          Function 28. Alternate Map Register Set
          Get Alternate Map Register Set subfunction



                   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.

               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.



          EMM Functions                                                 155





          Function 28. Alternate Map Register Set
          Get Alternate Map Register Set subfunction



               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:
























          EMM Functions                                                 156





          Function 28. Alternate Map Register Set
          Set 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 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 Register Set subfunction.






          EMM Functions                                                 157





          Function 28. Alternate Map Register Set
          Set Alternate Map Register Set 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 is 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.

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





          EMM Functions                                                 158





          Function 28. Alternate Map Register Set
          Set Alternate Map Register Set subfunction



          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.

               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.








          EMM Functions                                                 159





          Function 28. Alternate Map Register Set
          Set Alternate Map Register Set subfunction



          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 manger
          OR    AH,AH                            ; check EMM status
          JNZ   emm_err_handler                  ; jump to error handler
                                                 ; on error




























          EMM Functions                                                 160





          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 subfunc-
                   tion.


          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.



          EMM Functions                                                 161





          Function 28. Alternate Map Register Set
          Get Alternate Map Save Array Size subfunction



               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.


          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























          EMM Functions                                                 162





          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 set's 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.








          EMM Functions                                                 163





          Function 28. Alternate Map Register Set
          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 area.  The
                   save area is necessary because the hardware doesn't
                   support alternate map register sets.


          REGISTERS MODIFIED

               AX, BX


          STATUS

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

               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.




          EMM Functions                                                 164





          Function 28. Alternate Map Register Set
          Allocate Alternate Map Register Set subfunction



               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 number of
                                         ; alternate map register set

































          EMM Functions                                                 165





          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






          EMM Functions                                                 166





          Function 28. Alternate Map Register Set
          Deallocate Alternate Map Register Set subfunction



          STATUS

               AH = 0   SUCCESSFUL.
                   The manager has deallocated 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 = 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   BL,alternate_map_reg_set      ; specify alternate map
                                              ; register 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


          EMM Functions                                                 167





          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 alter-
               nate 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.

          EMM Functions                                                 168





          Function 28. Alternate Map Register Set
          Allocate DMA Register Set subfunction



          REGISTERS MODIFIED

               AX, BX


          STATUS

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



          EMM Functions                                                 169





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




          EMM Functions                                                 170





          Function 28. Alternate Map Register Set
          Enable DMA on Alternate Map Register Set subfunction



          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.

               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.





          EMM Functions                                                 171





          Function 28. Alternate Map Register Set
          Enable DMA on Alternate Map Register Set subfunction



          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





































          EMM Functions                                                 172





          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 disabled DMA operations on the alternate
                   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.




          EMM Functions                                                 173





          Function 28. Alternate Map Register Set
          Disable DMA on Alternate Map Register Set subfunction



               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

          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








          EMM Functions                                                 174





          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.




          EMM Functions                                                 175





          Function 28. Alternate Map Register Set
          Deallocate DMA on Alternate Map Register Set subfunction



               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.

               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   BL,DMA_reg_set_num
          MOV   AX,5B08h                 ; 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



















          EMM Functions                                                 176





          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 Expanded Memory Hardware for Warm
                   Boot 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.






          EMM Functions                                                 177





          Function 29. Prepare Expanded Memory Hardware for Warm Boot



          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











































          EMM Functions                                                 178





          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.





          EMM Functions                                                 179





          Function 30. Enable/Disable OS/E Function Set Functions
          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 subfunc-
               tions.  Since the access_key is returned only on the first
               invocation of the Enable/Disable OS/E Function Set subfunc-
               tions, 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

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




          EMM Functions                                                 180





          Function 30. Enable/Disable OS/E Function Set Functions
          Enable OS/E Function Set subfunction



               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
          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 error handler on error


          EMM Functions                                                 181





          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.












          EMM Functions                                                 182





          Function 30. Enable/Disable OS/E Function Set Functions
          Disable OS/E Function Set subfunction



          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

               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.





          EMM Functions                                                 183





          Function 30. Enable/Disable OS/E Function Set Functions
          Disable OS/E Function Set subfunction



          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
























          EMM Functions                                                 184




 
          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.



          EMM Functions                                                 185





          Function 30. Enable/Disable OS/E Function Set Functions
          Return Access Key subfunction



               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

          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
























          EMM Functions                                                 186





          Appendix A
          FUNCTION AND STATUS CODE CROSS REFERENCE TABLES



               This appendix contains two cross reference tables:  one
               lists the 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, 89h

             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


          Cross Reference Tables                                        187





          Table A-1.  Function and Status Code Cross Reference (continued)
          ----------------------------------------------------------------

          Function        Status                 Description

          ----------------------------------------------------------------

           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

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


          Cross Reference Tables                                        188





          Table A-1.  Function and Status Code Cross Reference (continued)
          ----------------------------------------------------------------

          Function        Status                 Description

          ----------------------------------------------------------------

           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 (Physical   
                    84h, 8Ah, 8Bh, 8Fh   page mode)

           5501h    00h, 80h, 81h, 83h   Alter Page Map & Jump (Segment    
                    84h, 8Ah, 8Bh, 8Fh   address mode)

           5600h    00h, 80h, 81h, 83h   Alter Page Map & Call (Physical   
                    84h, 8Ah, 8Bh, 8Fh   page mode)

           5601h    00h, 80h, 81h, 83h   Alter Page Map & Call (Segment    
                    84h, 8Ah, 8Bh, 8Fh   address mode)

           5602h    00h, 80h, 81h, 84h   Get Alter Page Map & Call Stack   
                    8Fh                  Space Size

           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     
                    8Fh                  Array

           5801h    00h, 80h, 81h, 84h   Get Mappable Physical Address     
                    8Fh                  Array Entries

           5900h    00h, 80h, 81h, 84h   Get Expanded Memory Hardware      
                    8Fh, A4h             Information

           5901h    00h, 80h, 81h, 84h   Get Unallocated Raw Page Count
                    8Fh

          Cross Reference Tables                                        189





          Table A-1.  Function and Status Code Cross Reference (continued)
          ----------------------------------------------------------------

          Function        Status                 Description

          ----------------------------------------------------------------

           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   
                    8Fh, 9Bh, A4h        Set

           5B04h    00h, 80h, 81h, 84h   Deallocate Alternate Map Register 
                    8Fh, 9Ch, 9Dh, A4h   Set

           5B05h    00h, 80h, 81h, 84h   Allocate DMA Register Set
                    8Fh, 9Bh, A4h

           5B06h    00h, 80h, 81h, 84h   Enable DMA on Alternate Map       
                    8Fh, 9Ah, 9Ch, 9Dh   Register Set
                    9Eh, 9Fh, A4h

           5B07h    00h, 80h, 81h, 84h   Disable DMA on Alternate Map      
                    8Fh, 9Ah, 9Ch, 9Dh   Register Set
                    9Eh, 9Fh, A4h

           5B08h    00h, 80h, 81h, 84h   Deallocate DMA Register Set
                    8Fh, 9Ch, 9Dh, A4h

             5Ch    00h, 80h, 81h, 84h   Prepare Expanded Memory Hardware
                                         for Warmboot

           5D00h    00h, 80h, 81h, 84h   Enable Operating System Function  
                    8Fh, A4h             Set

           5D01h    00h, 80h, 81h, 84h   Disable Operating System Function 
                    8Fh, A4h             Set


          Cross Reference Tables                                        190





          Table A-1.  Function and Status Code Cross Reference (continued)
          ----------------------------------------------------------------

          Function        Status                 Description

          ----------------------------------------------------------------

           5D02h    00h, 80h, 81h, 84h   Return Operating System Access Key
                    8Fh, A4h
          ----------------------------------------------------------------











































          Cross Reference Tables                                        191





          Table A-2.  Status and Function Code Cross Reference
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

           00h   All                  The function completed normally.

           80h   All                  The memory manager has detected a
                                      malfunction in the expanded memory
                                      software.  A condition has been
                                      detected which would not have
                                      occurred if the memory manager had
                                      been operating correctly.

           81h   All                  The memory manager has detected a
                                      malfunction in the expanded memory
                                      hardware.  A condition has been
                                      detected which would not occur if the
                                      memory hardware were working correct-
                                      ly.  Diagnostics should be run on the
                                      expanded memory system to determine
                                      the source of the problem.

           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 the
                 4Ch, 5000h, 5001h    handle specified.  The program has
                 51h, 5200h, 5201h    probably corrupted its specified
                 5300h, 5301h         handle.  The memory manager does not
                 5500h, 5501h         have any information pertaining to
                 5600h, 5601h         the  specified handle.  The program
                 5700h, 5701h         has probably corrupted its handle.

           84h   All                  The function code passed to the
                                      manager is not currently defined. 
                                      Function codes in the range 40h
                                      through 5Dh are currently defined.


          Cross Reference Tables                                        192





          Table A-2.  Status and Function Code Cross Reference (continued)
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

           85h   43h, 5A00h, 5A01h    No handles are currently available. 
                                      All assignable handles are currently
                                      in use.  The program may re-request
                                      the assignment of a handle in the
                                      hope that another program has
                                      released a handle.  The maximum
                                      number of handles that may be
                                      supported is 255.

           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.  A program can
                                      recover from this error by restoring
                                      the mapping context before returning
                                      the handle.

           87h   43h, 51h, 5A00h,     The number of total pages that are
                 5A01h                available in the system is insuffi-
                                      cient to honor the request.  The
                                      program can recover from this
                                      condition by requesting fewer pages.

           88h   43h, 51h, 5A00h,     The number of unallocated pages
                 5A01h                currently available is insufficient
                                      to honor the allocation request.  The
                                      program can recover from this
                                      condition by re-posting the request
                                      or by requesting fewer pages.

           89h   43h                  A Function 4 (Allocate Pages) request
                                      has been made specifying zero pages. 
                                      Zero pages cannot be assigned to a
                                      handle with Function 4 (Allocate
                                      Pages).  If it is necessary to assign
                                      zero pages to a handle, Function 27
                                      (Allocate Standard Pages and Allocate
                                      Raw Pages subfunctions) may be used.






          Cross Reference Tables                                        193





          Table A-2.  Status and Function Code Cross Reference (continued)
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

           8Ah   44h, 5000h, 5001h    The logical page to map into memory
                 5500h, 5501h         is out of the range of logical pages
                 5600h, 5601h         which are allocated to the handle. 
                 5700h, 5701h         The program can recover from this
                                      condition by attempting to map a
                                      logical page which is within the
                                      bounds for the handle.

           8Bh   44h, 4F00h, 4F02h    One or more of the physical pages is
                 5000h, 5001h         out of the range of allowable
                 5600h, 5601h         physical pages.  Physical page
                 5500h, 5501          numbers are numbered zero-relative. 
                                      The program can recover from this
                                      condition by mapping at a physical
                                      page which is in the range from zero
                                      to three.

           8Ch   47h                  The mapping register context save
                                      area is full.  The program can
                                      recover from this condition by
                                      attempting to save the mapping
                                      registers again.

           8Dh   47h                  The mapping register context stack
                                      already has a context associated with
                                      the handle.  The program has at-
                                      tempted to save the mapping register
                                      context when there was already a
                                      context for the handle on the stack. 
                                      The program can recover from this
                                      condition by not attempting to save
                                      the context again (this assumes the
                                      mapping register context on the stack
                                      for the handle is correct).












          Cross Reference Tables                                        194





          Table A-2.  Status and Function Code Cross Reference (continued)
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

           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. 
                                      The program can recover from this
                                      condition by not attempting to
                                      restore the context again (this
                                      assumes the current mapping register
                                      context is correct).

           8Fh   All functions        The subfunction parameter passed to
                 requiring            the function is not defined.
                 subfunction codes

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











          Cross Reference Tables                                        195





          Table A-2.  Status and Function Code Cross Reference (continued)
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

           93h   5700h, 5701h         The length of the specified source or
                                      destination expanded memory region
                                      exceeds the length of the expanded
                                      memory region allocated to the
                                      specified source or destination
                                      handle.  There are insufficient pages
                                      allocated to this handle to move/ex-
                                      change a region of the size speci-
                                      fied.  The program can recover from
                                      this condition by attempting to
                                      allocate additional pages to the
                                      destination or source handle or by
                                      reducing the specified length. 
                                      However, if the application program
                                      has allocated as much expanded memory
                                      as it thought it needed, this may be
                                      a program error and is therefore not
                                      recoverable.

           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 destina-
                                      tion 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.












          Cross Reference Tables                                        196





          Table A-2.  Status and Function Code Cross Reference (continued)
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

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

           98h   5700h, 5701h         The memory source and destination
                                      types are undefined/not supported.

           9Ah   5B01h, 5B06h         Alternate map register sets are
                 5B07h                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         Alternate map/DMA register sets are
                 5B06h, 5B07h         not supported, and the alternate
                 5B08h                map/DMA register set specified is not
                                      zero.

           9Dh   5B01h, 5B04h         Alternate map/DMA register sets are
                 5B06h, 5B07h         supported, but the alternate map
                 5B08h                register set specified is not
                                      defined, not allocated, or is the
                                      currently allocated map register set.

           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.



          Cross Reference Tables                                        197





          Table A-2.  Status and Function Code Cross Reference (continued)
          ----------------------------------------------------------------

          Status      Function                   Description

          ----------------------------------------------------------------

           A0h   5401h                No corresponding handle value could
                                      be found for the handle name speci-
                                      fied.

           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 bytes.  No data was
                                      moved/exchanged.

           A3h   4E01h, 4E02h         The contents of the data structure
                 4F00h, 4F01h         passed to the function have either
                 5B01h                been corrupted or are meaningless.

           A4h   5900h, 5B00h         The operating system has denied
                 5B01h, 5B02h         access to this function.  The 
                 5B03h, 5B04h         function cannot be used at this time.
                 5B05h, 5B06h
                 5B07h, 5B08h
                 5D00h, 5D01h
                 5D02h

          ----------------------------------------------------------------

















          Cross Reference Tables                                        198





          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 pro-
               grams.


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


          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:

          Testing For The Presence Of The EMM                           199





               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

                   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 through 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 = 0).  DOS function 44h determines whether EMMXXXX0
                   is a device or a file.



          Testing For The Presence Of The EMM                           200





                   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 contain-
                   ing 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 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.

                   If bit 7 contains a one, then EMMXXXX0 is a device.  Go
                   to Step 10.

               10. Issue an "I/O Control for Devices" command (DOS function
                   44h) with a "get output status" command (register AL =
                   7).

                   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 "FFh" 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.





          Testing For The Presence Of The EMM                           201





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

















































          Testing For The Presence Of The EMM                           202





          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 "device open"
          MOV   BX,AX                          ; get the "file
                                               ; handle" returned by DOS
          MOV   AX,4400h                       ; issue "IOCTL
          INT   21h                            ; get device info"
          JC    first_test_for_EMM_error_exit  ; test for error
                                               ; during "get device info"
          TEST  DX,0080h                       ; test to determine
          JZ    first_test_for_EMM_error_exit  ; 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 error
                                               ; during "IOCTL"
          PUSH  AX                             ; save "IOCTL" status
          MOV   AH,3Eh                         ; issue "close
          INT   21h                            ; file handle"
          POP   AX                             ; restore "IOCTL" status
          CMP   AL,0FFh                        ; test for "device
          JNE   first_test_for_EMM_error_exit  ; ready" status
                                               ; returned by the driver
          first_test_for_EMM_exit:
          POP   DS                             ; EMM is present
          STC                                  ; in the system
          RET

          first_test_for_EMM_error_exit:
          POP   DS                             ; EMM is NOT present
          CLC                                  ; in the system
          RET
          ASCII_device_name   DB  'EMMXXXX0', 0
          first_test_for_EMM  ENDP

          Testing For The Presence Of The EMM                           203





          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:019Ch thru 0000:019Fh).

                   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 is present.





          Testing For The Presence Of The EMM                           204





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


          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
          STC                                  ; the system
          RET

          second_test_for_EMM_error_exit:
          POP   DS                             ; EMM is NOT present
          CLC                                  ; in the system
          RET

          ASCII_device_name   DB  'EMMXXXX0'
          second_test_for_EMM ENDP







          Testing For The Presence Of The EMM                           205





          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 of 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 00h 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 16K-byte 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.



          EMM Implementation Guidelines                                 206





                   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
                   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 = 0000h):
                   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 0000h 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 dif-
                   ferently 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.







          EMM Implementation Guidelines                                 207





                   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.





















          EMM Implementation Guidelines                                 208





          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 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 ret set                ; Switch back to MS-DOS
          (for MS-DOS Executive)         ; Executive












          Operating System Use Of Function 28                           209





               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.

                                      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.











          Operating System Use Of Function 28                           210





               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 MS-DOS Executive)         ; Executive

          Get Page Map
          (for MS-DOS 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)

          Get Page Map
          (for Reversi)

          Set alt ret set                ; Switch back to MS-DOS
          (for MS-DOS Executive)         ; Executive

















          Operating System Use Of Function 28                           211





          GLOSSARY



               The following terms are used frequently in this specifica-
               tion:


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

          Expanded Memory          A device driver that controls the
            Manager (EMM)          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.


          Glossary                                                      212





          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.

          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               A page frame base address is the
            Base Address           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     A resident application program is loaded
            Program                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 example
                                   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 the expanded
                                   memory hardware or software.








          Glossary                                                      213





          Transient Application    A transient application program is
            Program                loaded 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.











































          Glossary                                                      214





          INDEX



               Allocate Alternate Map Register Set  36, 163
               Allocate DMA Register Set  36, 168, 190
               Allocate Pages  5, 14, 23, 30, 34, 42, 43, 47, 49, 144,
                   147, 148, 193, 206, 208
               Allocate Raw Pages  36, 46, 80, 89, 147-149, 190, 193,
                   206
               Allocate Standard Pages  36, 42, 46, 80, 89, 144, 145,
                   147, 190, 193
               Alter Page Map & Call  7, 10, 35, 113, 118, 189
               Alter Page Map & Jump  7, 10, 35, 109, 189
               Alternate Map  10, 36, 151, 153-155, 157-159, 161, 163,
                   164, 165-168, 170, 173, 175, 179, 182, 190, 197,
                   209, 210, 211
               Alternate Map Register Set  10, 36, 151, 153-155, 157,
                   158, 159, 161, 163-168, 170, 173, 175, 190, 197,
                   209, 210
               Alternate Mapping and Unmapping Methods  81
               Alternate Register  139, 166, 173, 177
               Data Aliasing  12
               Deallocate Alternate Map Register Set  36, 166
               Deallocate DMA Register Set  36, 175, 190
               Deallocate Pages  5, 14, 25, 31, 34, 43, 49, 88, 145,
                   148, 208
               Design Considerations  91, 151
               Device Driver  1, 15, 43, 53, 55, 144, 148, 199, 201,
                   202, 204, 212
               Disable DMA on Alternate Map Register Set  173
               Disable OS/E Function Set  36, 179, 180, 182, 185
               DMA  36, 138-140, 151, 152, 168-176, 190, 197
               DMA Channels  139, 171, 173, 174, 197
               DMA Register  36, 139, 140, 151, 152, 168-171, 173-176,
                   190, 197
               DOS  1, 12, 14, 15, 19, 21, 30, 31, 49, 53, 88, 199-205,
                   207-214
               Enable DMA on Alternate Map Register Set  170
               Enable OS/E Function Set  36, 179, 180
               Enable/Disable OS/E Function Set  179, 180, 182, 185
               Exchange Memory Region  7, 10, 35, 120, 126, 127, 189
               Expanded Memory Support of DMA  151
               Expanded Memory Support of DMA Register Sets  151
               Extended Memory  91
               Function 1  37
               Function 10  57
               Function 11  58
               Function 12  59
               Function 13  61
               Function 14  7, 63


          Index                                                         215





               Function 15  13, 53, 55, 65, 67, 69, 71, 73, 76, 139,
                   153, 154, 155, 158, 211
               Function 16  13, 73, 76, 78
               Function 17  6, 80, 82, 85
               Function 18  6, 43, 88, 144, 148, 207
               Function 19  7, 91, 92, 94, 96
               Function 2  4, 38
               Function 20  7, 98, 100
               Function 21  7, 42, 102, 105, 107
               Function 22  109
               Function 23  113, 118
               Function 24  7, 120, 126
               Function 25  6, 8, 46, 74, 85, 132, 136
               Function 26  138, 142, 179, 182, 206
               Function 27  42, 46, 80, 89, 144, 145, 147-149, 193, 206
               Function 28  140, 151, 153, 157, 161, 163, 164, 166,
                   168, 170, 173, 175, 179, 182, 209
               Function 29  177
               Function 3  4, 40, 142
               Function 30  138, 151, 153, 157, 161, 163, 166, 168,
                   170, 173, 175, 179, 182, 185
               Function 4  4, 42, 43, 46, 47, 49, 80, 89, 144, 145,
                   147, 149, 193, 206, 208
               Function 5  4, 46, 81
               Function 6  4, 43, 49, 88, 145, 148, 208
               Function 7  5, 51
               Function 8  46, 50, 53, 55
               Function 9  46, 50, 53, 55
               Get & Set Page Map  35, 69
               Get All Handle Pages  9, 34, 63
               Get Alternate Map Register Set  36, 153, 154, 157, 190
               Get Alternate Map Save Array Size  36, 161, 190
               Get Attribute Capability  7, 96
               Get Expanded Memory Hardware Information  10, 138, 142,
                   179, 182
               Get Handle Attribute  35, 92
               Get Handle Count  9, 34, 59
               Get Handle Directory  10, 35, 102, 105, 107
               Get Handle Name  35, 98
               Get Handle Pages  7, 9, 34, 61
               Get Hardware Configuration Array  36, 138
               Get Interrupt Vector  15, 21, 30, 199, 204, 205
               Get Mappable Physical Address Array  6, 8, 10, 35, 46,
                   85, 132, 136
               Get Mappable Physical Address Array Entries  8, 136
               Get Page Frame Address  5, 34, 38
               Get Page Map  35, 65, 118, 153-155, 158, 211
               Get Page Map Stack Space Size  35, 118
               Get Partial Page Map  35, 73, 78
               Get Size of Page Map Save Array  35, 65, 67, 71, 139
               Get Size of Partial Page Map Save Array  74, 76, 78
               Get Status  5, 34, 37

          Index                                                         216





               Get Total Handles  35, 107
               Get Unallocated Page Count  5, 22, 34, 40, 142
               Get Unallocated Raw Page Count  36, 142, 189
               Get Version  5, 34, 51
               Get/Set Handle Attribute  9, 91, 92, 94, 96
               Get/Set Handle Name  10, 98, 100
               Get/Set Page Map  9, 13, 65, 67, 69, 71
               Get/Set Partial Page Map  9, 13, 73, 76, 78
               Handle Attribute  9, 35, 91-94, 96, 188
               Handle Name  6, 7, 10, 35, 98, 100, 105, 106, 188, 198
               Intel  i, ii, 1, 5, 57, 58
               Interrupt Vector  12, 15, 21, 30, 199, 204, 205
               LIM  1, 7, 13, 19, 27, 53, 55, 138, 140, 206, 207
               Logical Page  1, 5, 12, 16, 19, 23, 28, 31, 32, 46-48,
                   80-83, 85, 86, 88, 110, 111, 115, 116, 120, 122,
                   123, 125, 126, 128, 129, 131, 147, 194, 196, 207,
                   212-214
               Logical Page/Physical Page Method  82
               Logical Page/Segment Address Method  85
               Lotus  i, ii, 1, 5, 57, 58
               Map Register  10, 13, 36, 53, 55, 151, 153-155, 157-159,
                   161, 163-168, 170, 173, 175, 179, 182, 190, 197,
                   209-211
               Map/Unmap Handle Pages  46
               Map/Unmap Multiple Handle Pages  9, 35, 80, 82, 85
               Mapping and Unmapping Multiple Pages Simultaneously  80
               Mapping Multiple Pages  6, 80
               Microsoft  i, ii, 1, 5, 14, 30, 42, 57, 58, 144, 148
               Move Memory Region  35, 120, 121, 189
               Move/Exchange Memory Region  7, 10, 120, 126
               Open Handle  64, 102, 199, 200, 203, 204
               Operating System  3, 8, 10-12, 42, 43, 59, 63, 107, 138,
                   139, 141, 142, 144-151, 153-159, 161-163, 165-171,
                   173-177, 179-183, 185, 186, 190, 191, 198, 206,
                   207-209, 213
               Page Frame  1-6, 14, 17-19, 24, 28, 31, 34, 38, 39, 47,
                   53, 55, 121, 128, 133, 187, 213
               Page Map  7, 9, 10, 13, 34, 35, 50, 53, 55, 65, 67, 69,
                   71, 73-76, 78, 109, 113, 118, 139, 153-155, 158,
                   187, 188, 189, 211
               Page Mapping Register I/O Array  57
               Page Translation Array  58
               Physical Page  1, 5, 6, 8, 10, 12, 16, 23, 28, 31, 35,
                   46, 47, 48, 80-83, 85, 109-112, 114-117, 132-134,
                   136, 138, 139, 142, 147, 188, 194, 207, 209, 213
               Prepare Expanded Memory Hardware For Warm Boot  10, 177
               Raw Handle  147, 149, 150, 206, 207
               Raw Page  36, 142, 143, 147, 189, 206
               Reallocate Pages  9, 35, 43, 88, 144, 145, 148, 208
               Restore Page Map  9, 13, 34, 50, 53, 55
               Return Access Key  185
               Save Page Map  9, 13, 34, 50, 53, 55

          Index                                                         217





               Search For Named Handle  7, 35, 105
               Set Alternate Map Register Set  36, 153-155, 157, 158,
                   163, 190
               Set Handle Attribute  9, 35, 91, 92, 94, 96
               Set Handle Name  7, 10, 35, 98, 100
               Set Page Map  9, 13, 35, 65, 67, 69, 71, 188
               Set Partial Page Map  9, 13, 35, 73, 76, 78
               Standard Handle  146
               Standard Page  147
               System DMA Capabilities  151
               TSR  12, 13, 208
               Unmapping Multiple Pages  6, 80









































          Index                                                         218

 Mp  ALLINFO.TXT  
Following are BBSes that are members of DV-NET.  DV-Net is an informal
network of BBS's that carry files that would be useful to DESQview users. 
Not all BBSes that carry the DESQview conference are members of DV-Net.

All address are NetMail addresses.

            ----------------------------------------------
                 DVNet DESQview Support File Network
            ----------------------------------------------
         DESQview is a trademark of Quarterdeck Office Systems
       -----------------------------------------------------------
         DVNet is not affiliated with Quarterdeck Office Systems
   ----------------------------------------------------------------

   Name, City and State             NetAddress  Telephone     Maxbaud
   -------------------------------  ---------- ------------  -------
 *65'North, Fairbanks, AK         1:17/38    907-452-1460  9600HSTV32
  Opus 386, Davis, CA             1:203/910  916-753-6321  2400
  Carl's Corner, San Jose, CA     1:10/1     408-248-9704  9600HSTV32
  Carl's Corner, San Jose, CA     1:10/2     408-248-0198  2400
  SeaHunt BBS, Burlingame, CA     1:125/20   415-344-4348  9600HST
  Stingray!, Clovis CA            1:205/12   209-298-9461  9600HST
  SF PCUG BBS, San Francisco CA   1:1/310    415-621-2609  9600HSTV32RE
  Bink of an Aye, Portland, OR    1:105/42   503-297-9043  9600PEPV32MO
  P C Support, Portland, OR       1:105/66   503-297-9078  2400
  Atarian BBS, Portland, OR       1:105/10   503-245-9730  9600HSTV32
  Busker's BoneYard, Portland,OR  1:105/14   503-771-4773  9600PEP
  Busker's Boneyard, Portland,OR  1:105/41   503-775-7926  9600HSTV32
  Pacifier BBS, Vancouver, WA     1:105/103  206-253-9770  9600HSTV32
  Puget Sound Gtwy., Puyallup, WA 1:138/3    206-566-8854  9600HST
  Rampart General,Kansas City,MO  1:280/6    816-761-4039  9600HST
  Oregon Trail XRoads, Casper WY  1:303/5    307-472-3615  9600H96
  Dawg Byte, Nashville, TN        1:116/29   615-385-4268  9600HST
  Dickson County, Dickson, TN     1:116/25   615-446-4475  2400
  Programmers' Attic, Will., MI   1:159/850  517-655-3347  2400
  Dark Side Of the Moon,Savoy IL  1:233/493  217-356-6922  9600HSTV32
  Ecclesia Place, Monroeville, PA 1:129/75   412-373-8612  9600HST
  The Other BBS, Harrisburg PA    1:270/101  717-657-2223  9600HST
  IBM Tech Fido, Pepperell, MA    1:322/1    508-433-8452  9600HSTV32
  Waystar BBS, Marlborough, MA    1:322/14   508-481-7147  9600HST
  Andromeda Galaxy, Troy NY       1:267/167  518-273-8313  9600HST
  Treasure Island, Danbury, CT    1:141/730  203-791-8532, 9600HST
  Addict's Attic,Germantown MD    1:109/423  301-428-8998  9600HST
  Maple Shade Opus,Maple Shade NJ 1:266/12   609-482-8604  9600HSTV32
  Capital City , Burlington NJ   99:9230/1   609-386-1989  9600HSTV32
  Capital City , Burlington NJ    8:950/10   609-386-1989  9600HSTV32
  Southern Cross BBS, Miami FL    1:135/69   305-220-8752  9600HST
  Software Designer, Albany, GA   1:3617/1   912-432-2440  9600HSTV32
  Software Designer, Albany, GA   8:928/1    912-432-2440  9600HSTV32
  Dragon's Lair, Galveston, TX    1:386/451  409-762-2761  9600HST
  Dragon's Lair, Galveston, TX    1:386/1451 409-762-7456  2400MNP
  Conch Opus, Houston, TX         1:106/357  713-667-7213  2400PCP
  Inns of Court, Dallas, TX       1:124/6101 214-458-2620  9600HSTV32
  Dallas Email, Dallas, TX        8:930/101  214-358-1205  9600HSTV32MO
  Spare Parts, Bedford, TX        1:130/38   817-540-3527  9600HST
  QE2, Austin TX                  1:382/58   512-328-1229  2400
  Ned's Opus HST Ottawa,ON Canada 1:163/211  613-523-8965  9600HST
  Ned's Opus, Ottawa ON Canada    1:163/210  613-731-8132  2400
  Imperial Terran, St Cath,ON     1:247/102  416-646-7105  9600HST
  Arcane BBS, Laval PQ Canada     1:167/116  514-687-9586  9600HST
  Zone 2 & Zone 3
  ------------------------------  ---------  ------------- -------
  The HEKOM Board (Netherlands)   2:286/3    31-3483-4072  2400MNP5
  BBS_D.C.V.V., Maaseik (Belgium) 2:295/26   32-11-568620