home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / intel / limems.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  306.8 KB  |  8,031 lines

  1.  LOTUS /INTEL /MICROSOFT EXPANDED MEMORY SPECIFICATION VERSION 4.0
  2.  
  3.  Version 4.0
  4.  300275-005
  5.  October, 1987
  6.  Copyright (c) 1987
  7.  
  8.  Lotus Development Corporation
  9.  55 Cambridge Parkway
  10.  Cambridge, MA 02142
  11.  
  12.  Intel Corporation
  13.  5200 NE Elam Young Parkway
  14.  Hillsboro, OR 97124
  15.  
  16.  Microsoft Corporation
  17.  16011 NE 36TH Way
  18.  Box 97017
  19.  Redmond, WA 98073
  20.  
  21.  This specification was jointly developed by Lotus Development Corporation,
  22.  Intel Corporation, and Microsoft Corporation. Although it has been released
  23.  into the public domain and is not confidential or proprietary, the
  24.  specification is still the copyright and property of Lotus Development
  25.  Corporation, Intel Corporation, and Microsoft Corporation.
  26.  
  27.  DISCLAIMER OF WARRANTY
  28.  
  29.  LOTUS DEVELOPMENT CORPORATION, INTEL CORPORATION, AND MICROSOFT CORPORATION
  30.  EXCLUDE ANY AND ALL IMPLIED WARRANTIES, INCLUDING WARRANTIES OF
  31.  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. NEITHER LOTUS NOR
  32.  INTEL NOR MICROSOFT MAKE ANY WARRANTY OF REPRESENTATION, EITHER EXPRESS OR
  33.  IMPLIED, WITH RESPECT TO THIS SPECIFICATION, ITS QUALITY, PERFORMANCE,
  34.  MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. NEITHER LOTUS NOR
  35.  INTEL NOR MICROSOFT SHALL HAVE ANY LIABILITY FOR SPECIAL, INCIDENTAL, OR
  36.  CONSEQUENTIAL DAMAGES ARISING OUT OF OR RESULTING FROM THE USE OR
  37.  MODIFICATION OF THIS SPECIFICATION.
  38.  
  39.  This specification uses the following trademarks:
  40.  
  41.  Intel is a trademark of Intel Corporation
  42.  Lotus is a trademark of Lotus Development Corporation
  43.  Microsoft is a trademark of Microsoft Corporation
  44.  
  45.  
  46.  
  47.  TABLE OF CONTENTS
  48.  
  49.  CHAPTER 1. Introduction
  50.    What is Expanded Memory?
  51.    How Expanded Memory Works
  52.  
  53.  CHAPTER 2. Writing Programs that Use Expanded Memory
  54.    What Every Program Must Do
  55.    Advanced Programming
  56.      Saving the State of Mapping Hardware
  57.      Retrieving Handle and Page Counts
  58.      Mapping and Unmapping Multiple Pages
  59.      Reallocating Pages
  60.      Using Handles and Assigning Names to Handles
  61.      Using Handle Attributes
  62.      Altering Page Maps and Jumping/Calling
  63.      Moving or Exchanging Memory Regions
  64.      Getting the Amount of Mappable Memory
  65.      Operating System Functions
  66.  
  67.    Programming Guidelines
  68.    Examples
  69.      Example 1
  70.      Example 2
  71.      Example 3
  72.      Example 4
  73.  
  74.  CHAPTER 3. EMM Functions
  75.    Function  1. Get Status
  76.    Function  2. Get Page Frame Address
  77.    Function  3. Get Unallocated Page Count
  78.    Function  4. Allocate Pages
  79.    Function  5. Map/Unmap Handle Page
  80.    Function  6. Deallocate Pages
  81.    Function  7. Get Version
  82.    Function  8. Save Page Map
  83.    Function  9. Restore Page Map
  84.    Function 10. Reserved
  85.    Function 11. Reserved
  86.    Function 12. Get Handle Count
  87.    Function 13. Get Handle Pages
  88.    Function 14. Get All Handle Pages
  89.    Function 15. Get/Set Page Map
  90.      Get Page Map Subfunction
  91.      Set Page Map Subfunction
  92.      Get & Set Page Map Subfunction
  93.      Get Size of Page Map Save Array Subfunction
  94.  
  95.    Function 16. Get/Set Partial Page Map
  96.      Get Partial Page Map Subfunction
  97.      Set Partial Page Map Subfunction
  98.      Get Size of Partial Page Map Save Array Subfunction
  99.  
  100.    Function 17. Map/Unmap Multiple Handle Pages
  101.      Mapping Multiple Pages
  102.      Unmapping Multiple Pages
  103.      Mapping & Unmapping Multiple Pages Simultaneously
  104.      Alternative Mapping & Unmapping Methods
  105.      Logical Page/Physical Page Method
  106.      Logical Page/Segment Address Method
  107.  
  108.    Function 18. Reallocate Pages
  109.  
  110.    Function 19. Get/Set Handle Attribute
  111.      Design Considerations
  112.      Get Handle Attribute Subfunction
  113.      Set Handle Attribute Subfunction
  114.      Get Attribute Capability Subfunction
  115.  
  116.    Function 20. Get/Set Handle Name
  117.      Get Handle Name Subfunction
  118.      Set Handle Name Subfunction
  119.  
  120.    Function 21. Get Handle Directory
  121.      Get Handle Directory Subfunction
  122.      Search for Named Handle Subfunction
  123.      Get Total Handles Subfunction
  124.  
  125.    Function 22. Alter Page Map & Jump
  126.  
  127.    Function 23. Alter Page Map & Call
  128.      Alter Page Map & Call Subfunction
  129.      Get Page Map Stack Space Size Subfunction
  130.  
  131.    Function 24. Move/Exchange Memory Region
  132.      Move Memory Region Subfunction
  133.      Exchange Memory Region Subfunction
  134.  
  135.    Function 25. Get Mappable Physical Address Array
  136.      Get Mappable Physical Address Array Subfunction
  137.      Get Mappable Physical Address Array Entries Subfunction
  138.  
  139.    Function 26. Get Expanded Memory Hardware Information
  140.      Get Hardware Configuration Array Subfunction
  141.      Get Unallocated Raw Page Count Subfunction
  142.  
  143.    Function 27. Allocate Standard/Raw Pages
  144.      Allocate Standard Pages Subfunction
  145.      Allocate Raw Pages Subfunction
  146.  
  147.    Function 28. Alternate Map Register Set
  148.      Design Considerations
  149.      System DMA Capabilities & Expanded Memory Support of DMA
  150.      Expanded Memory Support of DMA Register Sets
  151.      Get Alternate Map Register Set Subfunction
  152.      Set Alternate Map Register Set Subfunction
  153.      Get Alternate Map Save Array Size Subfunction
  154.      Allocate Alternate Map Register Set Subfunction
  155.      Deallocate Alternate Map Register Set Subfunction
  156.      Allocate DMA Register Set Subfunction
  157.      Enable DMA on Alternate Map Register Set Subfunction
  158.      Disable DMA on Alternate Map Register Set Subfunction
  159.      Deallocate DMA Register Set Subfunction
  160.  
  161.    Function 29. Prepare Expanded Memory Hardware Warmboot
  162.  
  163.    Function 30. Enable/Disable OS/E Function Set Functions
  164.      Enable OS/E Function Set Subfunction
  165.      Disable OS/E Function Set Subfunction
  166.      Return Access Key Subfunction
  167.  
  168.  APPENDIX A.  Function and Status Code Cross Reference Tables
  169.  
  170.  APPENDIX B.  Testing for the presence of the Expanded Memory Manager
  171.  
  172.  APPENDIX C.  Expanded Memory Manager Implementation Guidelines
  173.  
  174.  APPENDIX D.  Operating System/Environment Use of Function 28
  175.  
  176.  GLOSSARY
  177.  
  178.  INDEX
  179.  
  180.  
  181.  
  182.  CHAPTER 1  INTRODUCTION
  183.  
  184.  Because even the maximum amount (640K bytes) of conventional memory isn't
  185.  always enough for large application programs, Lotus Development Corporation,
  186.  Intel Corporation, and Microsoft Corporation created the
  187.  Lotus/Intel/Microsoft (LIM) Expanded Memory Specification.
  188.  
  189.  The LIM Expanded Memory Specification defines the software interface between
  190.  the Expanded Memory Manager (EMM)──a device driver that controls and manages
  191.  expanded memory──and application programs that use expanded memory.
  192.  
  193.  
  194.  WHAT IS EXPANDED MEMORY?
  195.  
  196.  Expanded memory is memory beyond DOS's 640K-byte limit. The LIM
  197.  specification supports up to 32M bytes of expanded memory. Because the 8086,
  198.  8088, and 80286 (in real mode) microprocessors can physically address only
  199.  1M byte of memory, they access expanded memory through a window in their
  200.  physical address range. The next section explains how this is done.
  201.  
  202.  
  203.  HOW EXPANDED MEMORY WORKS
  204.  
  205.  Expanded memory is divided into segments called logical pages. These pages
  206.  are typically 16K-bytes of memory. Your computer accesses logical pages
  207.  through a physical block of memory called a page frame. The page frame
  208.  contains multiple physical pages, pages that the microprocessor can address
  209.  directly. Physical pages are also typically 16K bytes of memory.
  210.  
  211.  This page frame serves as a window into expanded memory. Just as your
  212.  computer screen is a window into a large spreadsheet, so the page frame is a
  213.  window into expanded memory.
  214.  
  215.  A logical page of expanded memory can be mapped into (made to appear in) any
  216.  one of the physical pages in the page frame. Thus, a read or write to the
  217.  physical page actually becomes a read or write to the associated logical
  218.  page. One logical page can be mapped into the page frame for each physical
  219.  page.
  220.  
  221.  Figure 1-1 shows the relationship among the page frame, physical pages, and
  222.  logical pages.
  223.  
  224.  
  225.  Figure 1-1  Expanded Memory
  226.  
  227.                                          32M ┌─────────────┐
  228.                                           ∙  │             │
  229.                                         ∙    │             │
  230.              1024K ┌─────────────┐    ∙      │             │
  231.                    │             │  ∙        │             │
  232.               960K ├─────────────┤∙          │             │
  233.                    │ Page Frame  │           │  Expanded   │
  234.                    │ 24 16K-Byte │           │  Memory     │
  235.                    │ Physical    │           │             │
  236.                    │ Pages       │           │             │
  237.               768K ├─────────────┤∙          │  Divided    │
  238.                    │             │           │  into       │
  239.               640K ├─────────────┤           │  logical    │
  240.                    │             │  ∙        │  pages      │
  241.                    │ 24 16K-Byte │           │             │
  242.                    │ Physical    │           │             │
  243.                    │ Pages      │    ∙      │             │
  244.                    │             │           │             │
  245.               256K ├─────────────┤           │             │
  246.                    │             │      ∙    │             │
  247.                    │             │           │             │
  248.                 0  └─────────────┘           │             │
  249.                                           ∙  │             │
  250.                                              │             │
  251.                                            0 └─────────────┘
  252.  
  253.  
  254.  The page frame is located above 640K bytes. Normally, only video adapters,
  255.  network cards, and similar devices exist between 640K and 1024K.
  256.  
  257.  This specification also defines methods for operating systems and
  258.  environments to access expanded memory through physical pages below 640K
  259.  bytes. These methods are intended for operating system/environment
  260.  developers only.
  261.  
  262.  
  263.  
  264.  CHAPTER 2  WRITING PROGRAMS THAT USE EXPANDED MEMORY
  265.  
  266.  This chapter describes what every program must do to use expanded memory and
  267.  describes more advanced techniques of using expanded memory.
  268.  
  269.  This chapter also lists programming guidelines you should follow when
  270.  writing programs that use expanded memory and provides the listings of some
  271.  example programs.
  272.  
  273.  
  274.  WHAT EVERY PROGRAM MUST DO
  275.  
  276.  This section describes the steps every program must take to use expanded
  277.  memory.
  278.  
  279.  In order to use expanded memory, applications must perform these steps in
  280.  the following order:
  281.  
  282.    1.  Determine if EMM is installed.
  283.  
  284.    2.  Determine if enough expanded memory pages exist for your application.
  285.        (Function 3)
  286.  
  287.    3.  Allocate expanded memory pages. (Function 4 or 18)
  288.  
  289.    4.  Get the page frame base address. (Function 2)
  290.  
  291.    5.  Map in expanded memory pages. (Function 5 or 17)
  292.  
  293.    6.  Read/write/execute data in expanded memory, just as if it were
  294.        conventional memory.
  295.  
  296.    7.  Return expanded memory pages to expanded memory pool before exiting.
  297.        (Function 6 or 18)
  298.  
  299.  Table 2-1 overviews the functions while Chapter 3 describes each of these
  300.  functions in detail. Example programs at the end of this chapter illustrate
  301.  using expanded memory.
  302.  
  303.  Table 2-1  The Basic Functions
  304.  
  305. ╓┌─────────┌─────────────────────────────────────────────────────────────────╖
  306.  Function  Description
  307.  
  308.    1      The Get Status function returns a status code indicating whether
  309.            the memory manager hardware is working correctly.
  310.  
  311.    2      The Get Page Frame Address function returns the address where the
  312.            64K-byte page frame is located.
  313.  
  314.    3      The Get Unallocated Page Count function returns the number of
  315.            unallocated pages (pages available to your program) and the total
  316.            number of pages in expanded memory.
  317.  Function  Description
  318.           number of pages in expanded memory.
  319.  
  320.    4      The Allocate Pages function allocates the number of pages
  321.            requested and assigns a unique EMM handle to these pages.
  322.  
  323.    5      The Map/Unmap Handle Page function maps a logical page to a
  324.            specific physical page anywhere in the mappable regions of system
  325.            memory.
  326.  
  327.    6      The Deallocate Pages deallocates the logical pages currently
  328.            allocated to an EMM handle.
  329.  
  330.    7      The Get Version function returns the version number of the memory
  331.            manager software.
  332.  
  333.  
  334.  ADVANCED PROGRAMMING
  335.  
  336.  In addition to the basic functions, the Lotus/Intel/Microsoft Expanded
  337.  Memory Specification provides several advanced functions which enhance the
  338.  capabilities of software that uses expanded memory.
  339.  
  340.  The following sections describe the advanced programming capabilities and
  341.  list the advanced EMM functions.
  342.  
  343.  ───────────────────────────────────────────────────────────────────────────
  344.  NOTE:
  345.    Before using the advanced functions, programs should first call Function
  346.    7 (Get Version) to determine whether the installed version of EMM
  347.    supports these functions.
  348.  ───────────────────────────────────────────────────────────────────────────
  349.  
  350.  Saving The State of Mapping Hardware
  351.  
  352.  Some software (such as interrupt service routines, device drivers, and
  353.  resident software) must save the current state of the mapping hardware,
  354.  switch mapping contexts, manipulate sections of expanded memory, and restore
  355.  the original context of the memory mapping hardware. Use Functions 8 and
  356.  9 or 15 and 16 to save the state of the hardware.
  357.  
  358.  Retrieving Handle and Page Counts
  359.  
  360.  Some utility programs need to keep track of how expanded memory is being
  361.  used; use Functions 12 through 14 to do this.
  362.  
  363.  Mapping and Unmapping Multiple Pages
  364.  
  365.  Mapping multiple pages reduces the overhead an application must perform
  366.  during mapping. Function 17 lets a program map (or unmap) multiple pages at
  367.  one time.
  368.  
  369.  In addition, you can map pages using segment addresses instead of physical
  370.  pages. For example, if the page frame base address is set to D000, you can
  371.  map to either physical page 0 or segment D000. Function 25 (Get Mappable
  372.  Physical Address Array) returns a cross reference between all expanded
  373.  memory physical pages and their corresponding segment values.
  374.  
  375.  Reallocating Pages
  376.  
  377.  Reallocating pages (Function 18) lets applications dynamically allocate
  378.  expanded memory pages without acquiring another handle or obtain a handle
  379.  without allocating pages. Reallocating pages is an efficient means for
  380.  applications to obtain and release expanded memory pages.
  381.  
  382.  Using Handles and Assigning Names to Handles
  383.  
  384.  This specification lets you associate a name with a handle, so a family of
  385.  applications can share information in expanded memory. For example, a
  386.  software package consisting of a word processor, spreadsheet, and print
  387.  spooler can share the same data among the different applications. The print
  388.  spooler could use a handle name to reference data that either the
  389.  spreadsheet or word processor put in expanded memory and could check for
  390.  data in a particular handle name's expanded memory pages.
  391.  
  392.  Use Function 20 (Set Handle Name subfunction) to assign a handle name to an
  393.  EMM handle or Function 21 (Search for Named Handle subfunction) to obtain
  394.  the EMM handle associated with the handle name. In addition, you can use
  395.  Function 14 (Get Handle Pages) to determine the number of expanded memory
  396.  pages allocated to an EMM handle.
  397.  
  398.  Using Handle Attributes
  399.  
  400.  In addition to naming a handle, you can use Function 19 to associate an
  401.  attribute (volatile or non-volatile) with a handle name. A non-volatile
  402.  attribute enables expanded memory pages to preserve their data through a
  403.  warmboot. With a volatile attribute, the data is not preserved. The default
  404.  attribute for handles is volatile.
  405.  
  406.  Because using this function depends on the capabilities of the expanded
  407.  memory hardware installed in the system, you should use the Get Attribute
  408.  Capability subfunction before attempting to assign an attribute to a
  409.  handle's pages.
  410.  
  411.  Altering Page Maps and Jumping/Calling
  412.  
  413.  You can use Functions 22 (Alter Page Map and Jump) and 23 (Alter Page Map
  414.  and Call) to map a new set of values into the map registers and transfer
  415.  program control to a specified address within expanded memory. These
  416.  functions can be used to load and execute code in expanded memory. An
  417.  application using this feature can significantly reduce the amount of
  418.  conventional memory it requires. Programs can load needed modules into
  419.  expanded memory at run time and use Functions 22 and 23 to transfer control
  420.  to these modules.
  421.  
  422.  Using expanded memory to store code can improve program execution in many
  423.  ways. For example, sometimes programs need to be divided into small overlays
  424.  because of conventional memory size limitations. Overlays targeted for
  425.  expanded memory can be very large because LIM EMS 4.0 supports up to 32M
  426.  bytes of expanded memory. This method of loading overlays improves overall
  427.  system performance by conserving conventional memory and eliminating
  428.  conventional memory allocation errors.
  429.  
  430.  Moving or Exchanging Memory Regions
  431.  
  432.  Using Function 24 (Move/Exchange Memory Region), you can easily move and
  433.  exchange data between conventional and expanded memory. Function 24 can
  434.  manipulate up to one megabyte of data with one function call. Although
  435.  applications can perform this operation without this function, having the
  436.  expanded memory manager do it reduces the amount of overhead for the
  437.  application.
  438.  
  439.  In addition, this function checks for overlapping regions and performs all
  440.  the necessary mapping, preserving the mapping context from before the
  441.  exchange/move call.
  442.  
  443.  Getting the Amount of Mappable Memory
  444.  
  445.  Function 25 enables applications to determine the total amount of mappable
  446.  memory the hardware/system currently supports. Not all expanded memory
  447.  boards supply the same number of physical pages (map registers).
  448.  
  449.  The Get Mappable Physical Address Array Entries subfunction returns the
  450.  total number of physical pages the expanded memory hardware/system is
  451.  capable of supporting. The Get Mappable Physical Address Array subfunction
  452.  returns a cross reference between physical page numbers and the actual
  453.  segment address for each of the physical pages.
  454.  
  455.  Operating System Functions
  456.  
  457.  In addition to the functions for application programs, this specification
  458.  defines functions for operating systems/environments. These functions can be
  459.  disabled at any time by the operating system/environment, so programs should
  460.  not depend on their presence. Applications that avoid this warning and use
  461.  these functions run a great risk of being incompatible with other programs,
  462.  including the operating system.
  463.  
  464.  Table 2-2  The Advanced Functions
  465.  
  466. ╓┌─────────┌─────────────────────────────────────────────────────────────────╖
  467.  Function  Description
  468.  
  469.    8      The Save Page Map saves the contents of the page mapping registers
  470.            from all expanded memory boards in an internal save area.
  471.  
  472.    9      The Restore Page Map function restores (from an internal save
  473.            area) the page mapping register contents on the expanded memory
  474.            boards for a particular EMM handle.
  475.  
  476.    10     Reserved.
  477.  
  478.    11     Reserved.
  479.  
  480.    12     The Get Handle Count function returns the number of open EMM
  481.            handles in the system.
  482.  
  483.    13     The Get Handle Pages function returns the number of pages
  484.            allocated to a specific EMM handle.
  485.  Function  Description
  486.           allocated to a specific EMM handle.
  487.  
  488.    14     The Get All Handle Pages function returns an array of the active
  489.            EMM handles and the number of pages allocated to each one.
  490.  
  491.    15     The Get/Set Page Map subfunction saves or restores the mapping
  492.            context for all mappable memory regions (conventional and
  493.            expanded) in a destination array which the application supplies.
  494.  
  495.    16     The Get/Set Partial Page Map subfunction provides a mechanism for
  496.            saving a partial mapping context for specific mappable memory
  497.            regions in a system.
  498.  
  499.    17     The Map/Unmap Multiple Handle Pages function can, in a single
  500.            invocation, map (or unmap) logical pages into as many physical
  501.            pages as the system supports.
  502.  
  503.    18     The Reallocate Pages function can increase or decrease the amount
  504.            of expanded memory allocated to a handle.
  505.  
  506.  Function  Description
  507. 
  508.    19     The Get/Set Handle Attribute function allows an application
  509.            program to determine and set the attribute associated with a
  510.            handle.
  511.  
  512.    20     The Get/Set Handle Name function gets the eight character name
  513.            currently assigned to a handle and can assign an eight character
  514.            name to a handle.
  515.  
  516.    21     The Get Handle Directory function returns information about active
  517.            handles and the names assigned to each.
  518.  
  519.    22     The Alter Page Map & Jump function alters the memory mapping
  520.            context and transfers control to the specified address.
  521.  
  522.    23     The Alter Page Map & Call function alters the specified mapping
  523.            context and transfers control to the specified address. A return
  524.            can then restore the context and return control to the caller.
  525.  
  526.    24     The Move/Exchange Memory Region function copies or exchanges a
  527.  Function  Description
  528.   24     The Move/Exchange Memory Region function copies or exchanges a
  529.            region of memory from conventional to conventional memory,
  530.            conventional to expanded memory, expanded to conventional memory,
  531.            or expanded to expanded memory.
  532.  
  533.    25     The Get Mappable Physical Address Array function returns an array
  534.            containing the segment address and physical page number for each
  535.            mappable physical page in a system.
  536.  
  537.    26     The Get Expanded Memory Hardware Information function returns an
  538.            array containing the hardware capabilities of the expanded memory
  539.            system.
  540.  
  541.    27     The Allocate Standard/Raw Pages function allocates the number of
  542.            standard or non-standard size pages that the operating system
  543.            requests and assigns a unique EMM handle to these pages.
  544.  
  545.    28     The Alternate Map Register Set function enables an application to
  546.            simulate alternate sets of hardware mapping registers.
  547.  
  548.  Function  Description
  549. 
  550.    29     The Prepare Expanded Memory Hardware for Warm Boot function
  551.            prepares the expanded memory hardware for an "impending" warm
  552.            boot.
  553.  
  554.    30     The Enable/Disable OS/E function enables operating systems
  555.            developers to enable and disable functions designed for operating
  556.            system use.
  557.  
  558.  
  559.  PROGRAMMING GUIDELINES
  560.  
  561.  The following section contains guidelines for programmers writing
  562.  applications that use EMM.
  563.  
  564.    ■  Do not put a program's stack in expanded memory.
  565.  
  566.    ■  Do not replace interrupt 67h. This is the interrupt vector the EMM
  567.       uses. Replacing interrupt 67h could result in disabling the Expanded
  568.       Memory Manager.
  569.  
  570.    ■  Do not map into conventional memory address space your application
  571.       doesn't own. Applications that use the EMM to swap into conventional
  572.       memory space, must first allocate this space from the operating
  573.       system. If the operating system is not aware that a region of memory
  574.       it manages is in use, it will think it is available. This could have
  575.       disastrous results. EMM should not be used to 'allocate' conventional
  576.       memory. DOS is the proper manager of conventional memory space. EMM
  577.       should only be used to swap data in conventional memory space
  578.       previously allocated from DOS.
  579.  
  580.    ■  Applications that plan on using data aliasing in expanded memory must
  581.       check for the presence of expanded memory hardware. Data aliasing
  582.       occurs when mapping one logical page into two or more mappable
  583.       segments. This makes one 16K-byte expanded memory page appear to be in
  584.       more than one 16K-byte memory address space. Data aliasing is legal
  585.       and sometimes useful for applications.
  586.  
  587.       Software-only expanded memory emulators cannot perform data aliasing.
  588.       A simple way to distinguish software emulators from actual expanded
  589.       memory hardware is to attempt data aliasing and check the results. For
  590.       example, map one logical page into four physical pages. Write to
  591.       physical page 0. Read physical pages 1-3 to see if the data is there
  592.       as well. If the data appears in all four physical pages, then expanded
  593.       memory hardware is installed in the system, and data aliasing is
  594.       supported.
  595.  
  596.    ■  Applications should always return expanded memory pages to the
  597.       expanded memory manager upon termination. These pages will be made
  598.       available for other applications. If unneeded pages are not returned
  599.       to the expanded memory manager, the system could 'run out' of expanded
  600.       memory pages or expanded memory handles.
  601.  
  602.    ■  Terminate and stay resident programs (TSR's) should ALWAYS save the
  603.       state of the map registers before changing them. Since TSR's may
  604.       interrupt other programs which may be using expanded memory, they must
  605.       not change the state of the page mapping registers without first
  606.       saving them. Before exiting, TSR's must restore the state of the map
  607.       registers.
  608.  
  609.       The following sections describe the three ways to save and restore the
  610.       state of the map registers.
  611.  
  612.         1. Save Page Map and Restore Page Map (Functions 8 and 9). This is
  613.            the simplest of the three methods. The EMM saves the map register
  614.            contents in its own data structures──the application does not
  615.            need to provide extra storage locations for the mapping context.
  616.            The last mapping context to be saved, under a particular handle,
  617.            will be restored when a call to Restore Page Map is issued with
  618.            the same handle. This method is limited to one mapping context
  619.            for each handle and saves the context for only LIM standard 64K-
  620.            byte page frames.
  621.  
  622.         2. Get/Set Page Map (Function 15). This method requires the
  623.            application to allocate space for the storage array. The EMM
  624.            saves the mapping context in an array whose address is passed to
  625.            the EMM. When restoring the mapping context with this method, an
  626.            application passes the address of an array which contains a
  627.            previously stored mapping context.
  628.  
  629.            This method is preferable if an application needs to do more than
  630.            one save before a restore. It provides a mechanism for switching
  631.            between more than one mapping context.
  632.  
  633.         3. Get/Set Partial Page Map (Function 16). This method provides a
  634.            way for saving a partial mapping context. It should be used when
  635.            the application does not need to save the context of all mappable
  636.            memory. This function also requires that the storage array be
  637.            part of the application's data.
  638.  
  639.    ■  All functions using pointers to data structures must have those data
  640.       structures in memory which will not be mapped out. Functions 22
  641.       and 23 (Alter Map and Call and Alter Map and Jump) are the only
  642.       exceptions.
  643.  
  644.  
  645.  EXAMPLES
  646.  
  647.  This section lists four example programs that demonstrate the use of
  648.  expanded memory.
  649.  
  650.  Example 1
  651.  
  652.  This program was written using the Microsoft C compiler Version 3.0. EMM
  653.  function calls are made with the int86 function found in the dos.h library.
  654.  To create an executable program use the following compile command line:
  655.  
  656.    msc /Gs /Oat /Ml program,,program;
  657.  
  658.  #include <dos.h>
  659.  #include <stdio.h>
  660.  
  661.  #define EMM_INT                 0x67 /* EMM interrupt number */
  662.  #define GET_PAGE_FRAME          0x41 /* EMM get page frame */
  663.                                       /* function number */
  664.  #define GET_UNALLOC_PAGE_COUNT  0x42 /* EMM get unallocated */
  665.                                       /* page count */
  666.                                       /* function number */
  667.  #define ALLOCATE_PAGES          0x43 /* EMM allocate pages */
  668.                                       /* function number */
  669.  #define MAP_PAGES               0x44 /* EMM map pages */
  670.                                       /* function number */
  671.  #define DEALLOCATE_PAGES        0x45 /* EMM deallocate pages */
  672.                                       /* function number */
  673.  #define DEVICE_NAME_LENGTH      8    /* Length of a device */
  674.                                       /* name string */
  675.  #define TRUE                    1
  676.  #define FALSE                   0
  677.  
  678.  
  679.  union REGS input_regs, output_regs;
  680.  struct SREGS segment_regs;
  681.  int   pf_addr;
  682.  
  683.  /*----------------------------------------------------------*/
  684.  /* Routine to convert a segment:offset pair to a far ptr.   */
  685.  /*----------------------------------------------------------*/
  686.  char *build_ptr(segment,offset)
  687.  
  688.  unsigned int    segment;
  689.  unsigned int    offset;
  690.  
  691.  {
  692.        char   *ptr;
  693.  
  694.        ptr = (char *) (((unsigned long)segment << 16) + offset);
  695.        return (ptr);
  696.  }
  697.  
  698.  /*-----------------------------------------------------------------------*/
  699.  /* Function which determines whether the EMM device driver is installed. */
  700.  /*-----------------------------------------------------------------------*/
  701.  char  emm_installed()
  702.  
  703.  {
  704.        char *EMM_device_name = "EMMXXXX0";
  705.        char *int_67_device_name_ptr;
  706.  
  707.        /*------------------------------------------*/
  708.        /* AH = DOS get interrupt vector function.  */
  709.        /*------------------------------------------*/
  710.        input_regs.h.ah = 0x35;
  711.  
  712.        /*------------------------------------------*/
  713.        /* AL = EMM interrupt vector number.        */
  714.        /*------------------------------------------*/
  715.        input_regs.h.al = EMM_INT;
  716.  
  717.        intdosx (&input_regs, &output_regs, &segment_regs);
  718.  
  719.        /*---------------------------------------------------------*/
  720.        /* Upon return ES:0Ah points to location where device name */
  721.        /* should be.                                              */
  722.        /*---------------------------------------------------------*/
  723.        int_67_device_name_ptr = build_ptr(segment_regs.es,0xA);
  724.  
  725.        /*------------------------------------------*/
  726.        /* Compare memory with EMM device name.     */
  727.        /*------------------------------------------*/
  728.        if (memcmp(EMM_device_name, int_67_device_name_ptr,
  729.                                  DEVICE_NAME_LENGTH) == 0)
  730.                return (TRUE);
  731.        else
  732.                return (FALSE);
  733.  }
  734.  
  735.  
  736.  /*-----------------------------------------------------------*/
  737.  /* Function which determines if there are enough unallocated */
  738.  /* expanded memory pages for the application.                */
  739.  /*-----------------------------------------------------------*/
  740.  char enough_unallocated_pages (pages_needed)
  741.  
  742.        int   pages_needed;
  743.  {
  744.        input_regs.h.ah = GET_UNALLOCATED_PAGE_COUNT;
  745.        int86 (EMM_INT, &input_regs, &output_regs);
  746.        if (output_regs.h.ah != 0 || pages_needed > output_regs.x.bx)
  747.                return (FALSE);
  748.        else
  749.                return (TRUE);
  750.  }
  751.  
  752.  /*----------------------------------------------------------*/
  753.  /* Routine which allocates expanded memory pages and passes */
  754.  /* back to the main EMM handle.                             */
  755.  /*----------------------------------------------------------*/
  756.  char allocate_expanded_memory_pages (pages_needed, emm_handle_ptr)
  757.  
  758.        int    pages_needed;
  759.        unsigned int *emm_handle_ptr;
  760.  {
  761.        input_regs.h.ah = ALLOCATE_PAGES;
  762.        input_regs.x.bx = pages_needed;
  763.        int86 (EMM_INT, &input_regs, &output_regs);
  764.        if (output_regs.h.ah == 0) {
  765.                *emm_handle_ptr = output_regs.x.dx;
  766.                return (TRUE);
  767.        }
  768.        else
  769.                return (FALSE);
  770.  }
  771.  
  772.  /*---------------------------------------------------*/
  773.  /* Routine to map a logical page to a physical page. */
  774.  /*---------------------------------------------------*/
  775.  char map_expanded_memory_pages (emm_handle, physical_page, logical_page)
  776.  
  777.        unsigned int emm_handle;
  778.        int     physical_page;
  779.        int     logical_page;
  780.  {
  781.        input_regs.h.ah = MAP_PAGES;
  782.        input_regs.h.al = physical_page;
  783.        input_regs.x.bx = logical_page;
  784.        input_regs.x.dx = emm_handle;
  785.        int86 (EMM_INT, &input_regs, &output_regs);
  786.        if (output_regs.h.ah == 0)
  787.                return (TRUE);
  788.        else
  789.                return (FALSE);
  790.  }
  791.  
  792.  /*----------------------------------------------------------*/
  793.  /* Routine which gets the page frame base address from EMM. */
  794.  /*----------------------------------------------------------*/
  795.  char  get_page_frame_address (pf_ptr)
  796.  
  797.        char **pf_ptr;
  798.  {
  799.        input_regs.h.ah = GET_PAGE_FRAME;
  800.        int86 (EMM_INT, &input_regs, &output_regs);
  801.        if (output_regs.h.ah != 0)   /* check EMM status */
  802.                return (FALSE);
  803.        else
  804.                *pf_ptr = build_ptr(output_regs.x.bx,0);
  805.        return (TRUE);
  806.  }
  807.  
  808.  /*--------------------------------------------------------------*/
  809.  /* Routine to release all expanded memory pages allocated by an */
  810.  /* EMM handle.                                                  */
  811.  /*--------------------------------------------------------------*/
  812.  char deallocate_expanded_memory_pages (emm_handle)
  813.  
  814.        unsigned int           emm_handle;
  815.  {
  816.        input_regs.h.ah = DEALLOCATE_PAGES;
  817.        input_regs.x.dx = emm_handle;
  818.        int86 (EMM_INT, &input_regs, &output_regs);
  819.        if (output_regs.h.ah == 0)
  820.                return (TRUE);
  821.        else
  822.                return (FALSE);
  823.  }
  824.  
  825.  main() {
  826.        unsigned int emm_handle;
  827.        char *pf_addr;
  828.        int pages_needed;
  829.        int physical_page;
  830.        int logical_page;
  831.        int     index;
  832.  
  833.        /*------------------------------------------*/
  834.        /* Determine if EMM is installed.           */
  835.        /*------------------------------------------*/
  836.        if (!emm_installed())
  837.                exit(1);
  838.  
  839.        /*------------------------------------------------------------------*/
  840.        /* Determine if enough expanded memory pages exist for application. */
  841.        /*------------------------------------------------------------------*/
  842.        pages_needed = 1;
  843.        if (!enough_unallocated_pages(pages_needed))
  844.                exit (1);
  845.  
  846.        /*------------------------------------------*/
  847.        /* Allocate expanded memory pages.          */
  848.        /*------------------------------------------*/
  849.        if (!allocate_expanded_memory_pages (pages_needed, &emm_handle))
  850.                exit (1);
  851.  
  852.        /*------------------------------------------*/
  853.        /* Map in the required pages.               */
  854.        /*------------------------------------------*/
  855.        physical_page = 0;
  856.        logical_page = 0;
  857.        if (!map_expanded_memory_pages (emm_handle, physical_page,
  858.                                  logical_page))
  859.                exit (1);
  860.  
  861.        /*------------------------------------------*/
  862.        /* Get expanded memory page frame address.  */
  863.        /*------------------------------------------*/
  864.        if (!get_page_frame_address(&pf_addr))
  865.                exit (1);
  866.  
  867.        /*------------------------------------------*/
  868.        /* Write to expanded memory.                */
  869.        /*------------------------------------------*/
  870.        for (index = 0; index < 0x3fff; index++)
  871.                pf_addr[index] = index;
  872.  
  873.        /*----------------------------------------------*/
  874.        /* Return expanded memory pages before exiting. */
  875.        /*----------------------------------------------*/
  876.        if (!deallocate_expanded_memory_pages (emm_handle))
  877.                exit (1);
  878.  
  879.  }
  880.  
  881.  Example 2
  882.  
  883.  This program shows you how to use the basic functions of the LIM Expanded
  884.  Memory Specification with Turbo Pascal. The program does the following:
  885.  
  886.    1.  Makes sure the LIM Expanded Memory Manager (EMM) has been installed.
  887.  
  888.    2.  Displays the version number of the EMM.
  889.  
  890.    3.  Determines if there are enough pages of memory for the test program.
  891.        It then displays the total number of EMM pages present in the system
  892.        and the number available for use.
  893.  
  894.    4.  Requests the desired number of pages from the EMM.
  895.  
  896.    5.  Maps a logical page into one of the physical pages.
  897.  
  898.    6.  Displays the base address of our EMM memory page frame. Performs a
  899.        simple read/write test on the EMM memory.
  900.  
  901.    7.  Returns the EMM memory given to us back to the EMM.
  902.  
  903.    8.  Exits.
  904.  
  905.  All the calls are structured to return the result or error code of the
  906.  Expanded Memory function performed as an integer. If the error code is not
  907.  zero, an error has occurred, a simple error procedure is called, and the
  908.  program terminates.
  909.  
  910.  Type
  911.    ST3  = string[3];
  912.    ST80 = string[80];
  913.    ST5  = string[5];
  914.  
  915.    Registers = record
  916.      case integer of
  917.        1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: Integer);
  918.        2: (AL,AH,BL,BH,CL,DL,DH            : Byte);
  919.      end;
  920.  
  921.  Const
  922.    EMM_INT                   = $67;
  923.    DOS_Int                   = $21;
  924.    GET_PAGE_FRAME            = $41;
  925.    GET_UNALLOCATED_PAGE_COUNT= $42;
  926.    ALLOCATE_PAGES            = $43;
  927.    MAP_PAGES                 = $44;
  928.    DEALLOCATE_PAGES          = $45;
  929.    GET_VERSION               = $46;
  930.    STATUS_OK                 = 0;
  931.  
  932.    {-----------------------------------------------------------}
  933.    {Assume the application needs one EMM page.                 }
  934.    {-----------------------------------------------------------}
  935.    APPLICATION_PAGE_COUNT    = 1;
  936.  
  937.  Var
  938.    Regs: Registers;
  939.  
  940.    Emm_Handle,
  941.    Page_Frame_Base_Address,
  942.    Pages_Needed,
  943.    Physical_Page,
  944.    Logical_Page,
  945.    Offset,
  946.    Error_Code,
  947.    Pages_EMM_Available,
  948.    Total_EMM_Pages,
  949.    Available_EMM_Pages: Integer;
  950.  
  951.    Version_Number,
  952.    Pages_Number_String: ST3;
  953.  
  954.    Verify: Boolean;
  955.  
  956.    {-----------------------------------------------------------}
  957.    {The function Hex_String converts an integer into a four    }
  958.    {character hexadecimal number (string) with leading zeros.  }
  959.    {-----------------------------------------------------------}
  960.    Function Hex_String (Number: Integer): ST5;
  961.      Function Hex_Char (Number: Integer): Char;
  962.        Begin
  963.          If Number < 10 then
  964.            Hex_Char := Char (Number+48)
  965.          else
  966.            Hex_Char := Char (Number+55);
  967.        end; {Function Hex_Char}
  968.  
  969.      Var
  970.        S: ST5;
  971.  
  972.      Begin
  973.        S := '';
  974.        S := Hex_Char ((Number shr 1) div 2048);
  975.        Number:=(((Number shr 1) mod 2048) shl 1)+(Number and 1);
  976.        S := S+Hex_Char (Number div 256);
  977.        Number := Number mod 256;
  978.        S := S+Hex_Char (Number div 16);
  979.        Number := Number mod 16;
  980.        S := S+Hex_Char (Number);
  981.        Hex_String := S+'h';
  982.    end; {Function Hex_String}
  983.  
  984.    {-----------------------------------------------------------}
  985.    {The function Emm_Installed checks to see if the            }
  986.    {EMM is loaded in memory. It does this by                   }
  987.    {looking for the string 'EMMXXXX0', which should be located }
  988.    {at 10 bytes from the beginning of the code segment the     }
  989.    {EMM interrupt, 67h, points to.                             }
  990.    {-----------------------------------------------------------}
  991.    Function Emm_Installed: Boolean;
  992.      Var
  993.        Emm_Device_Name       : string[8];
  994.        Int_67_Device_Name    : string[8];
  995.        Position              : integer;
  996.        Regs                  : registers;
  997.  
  998.      Begin
  999.        Int_67_Device_Name := '';
  1000.        Emm_Device_Name    := 'EMMXXXX0';
  1001.        with Regs do
  1002.          Begin
  1003.            {---------------------------------------------------}
  1004.            {Get the code segment interrupt 67h points to       }
  1005.            {the EMM interrupt by using DOS function 35h.       }
  1006.            {(get interrupt vector)                             }
  1007.            {---------------------------------------------------}
  1008.            AH := $35;
  1009.            AL := EMM_INT;
  1010.            Intr (DOS_int,Regs);
  1011.            {---------------------------------------------------}
  1012.            {The ES pseudo-register contains the segment        }
  1013.            {address pointed to by interrupt 67h. Create an     }
  1014.            {eight character string from the eight successive   }
  1015.            {bytes at address ES:$000A (10 bytes from ES)       }
  1016.            {---------------------------------------------------}
  1017.            For Position := 0 to 7 do
  1018.              Int_67_Device_Name :=
  1019.                 Int_67_Device_Name+Chr (mem[ES:Position+$0A]);
  1020.            Emm_Installed := True;
  1021.            {---------------------------------------------------}
  1022.            { If the string is the EMM manager signature,       }
  1023.            {'EMMXXXX0', then EMM is installed and ready for    }
  1024.            {use. If not, then EMM is not present.              }
  1025.            {---------------------------------------------------}
  1026.            If Int_67_Device_Name <> Emm_Device_Name
  1027.              then Emm_Installed := False;
  1028.          end; {with Regs do}
  1029.      end; {Function Emm_Installed }
  1030.  
  1031.    {-----------------------------------------------------------}
  1032.    {This function returns the total number of EMM pages present}
  1033.    {in the system, and the number of EMM pages that are        }
  1034.    {Available.                                                 }
  1035.    {-----------------------------------------------------------}
  1036.    Function EMM_Pages_Available
  1037.      (Var Total_EMM_Pages, Pages_Available: Integer): Integer;
  1038.      Var
  1039.        Regs: Registers;
  1040.  
  1041.      Begin
  1042.        with Regs do
  1043.          Begin
  1044.            {---------------------------------------------------}
  1045.            {Get the number of currently unallocated pages and  }
  1046.            {the total number of pages in the system from EMM.  }
  1047.            {Load pseudo-registers prior to invoking EMM.       }
  1048.            {   AH = get unallocated page count function        }
  1049.            {---------------------------------------------------}
  1050.            AH := Get_Unallocated_Page_Count;
  1051.            intr (EMM_INT, Regs);
  1052.            {---------------------------------------------------}
  1053.            {Unload the pseudo-registers after invoking EMM.    }
  1054.            {   BX = currently unallocated pages                }
  1055.            {   DX = total pages in the system                  }
  1056.            {   AH = status                                     }
  1057.            {---------------------------------------------------}
  1058.            Pages_Available := BX;
  1059.            Total_EMM_Pages := DX;
  1060.            EMM_Pages_Available := AH;
  1061.          end;
  1062.      end; {EMM_Pages_Available }
  1063.  
  1064.    {-----------------------------------------------------------}
  1065.    {This function requests the specified number of pages       }
  1066.    {from the EMM.                                              }
  1067.    {-----------------------------------------------------------}
  1068.    Function Allocate_Expanded_Memory_Pages
  1069.      (Pages_Needed: Integer; Var Handle: Integer): Integer;
  1070.      Var
  1071.        Regs: Registers;
  1072.  
  1073.      Begin
  1074.        with Regs do
  1075.          Begin
  1076.            {---------------------------------------------------}
  1077.            {Allocate the specified number of pages from EMM.   }
  1078.            {Load pseudo-registers prior to invoking EMM.       }
  1079.            {   AH = allocate pages function.                   }
  1080.            {   BX = number of pages to allocate.               }
  1081.            {---------------------------------------------------}
  1082.            AH := Allocate_Pages;
  1083.            BX := Pages_Needed;
  1084.            intr (EMM_INT,Regs);
  1085.            {---------------------------------------------------}
  1086.            {Unload the pseudo-registers after invoking EMM.    }
  1087.            {   DX = EMM handle                                 }
  1088.            {   AH = status                                     }
  1089.            {---------------------------------------------------}
  1090.            Handle := DX;
  1091.            Allocate_Expanded_Memory_Pages := AH;
  1092.          end;
  1093.      end; {Function Allocate_Expanded_Memory_Pages}
  1094.  
  1095.    {-----------------------------------------------------------}
  1096.    {This function maps a logical page allocated by the         }
  1097.    {Allocate_Expanded_Memory_Pages function into one of the    }
  1098.    {four physical pages.                                       }
  1099.    {-----------------------------------------------------------}
  1100.    Function Map_Expanded_Memory_Pages
  1101.      (Handle, Logical_Page, Physical_Page: Integer): Integer;
  1102.      Var
  1103.        Regs: Registers;
  1104.  
  1105.      Begin
  1106.        with Regs do
  1107.          Begin
  1108.            {---------------------------------------------------}
  1109.            {Map a logical page at physical page 0.             }
  1110.            {Load pseudo-registers prior to invoking EMM.       }
  1111.            {   AH = map page function                          }
  1112.            {   DX = handle                                     }
  1113.            {   BX = logical page number                        }
  1114.            {   AL = physical page number                       }
  1115.            {---------------------------------------------------}
  1116.            AH := Map_Pages;
  1117.            DX := Handle;
  1118.            BX := Logical_Page;
  1119.            AL := Physical_Page;
  1120.            Intr (EMM_INT, Regs);
  1121.            {---------------------------------------------------}
  1122.            {Unload the pseudo-registers after invoking EMM.    }
  1123.            {   AH = status                                     }
  1124.            {---------------------------------------------------}
  1125.            Map_Expanded_Memory_Pages := AH;
  1126.          end; {with Regs do}
  1127.      end; {Function Map_Expanded_Memory_Pages}
  1128.  
  1129.    {-----------------------------------------------------------}
  1130.    {This function gets the physical address of the EMM page    }
  1131.    {frame we are using. The address returned is the segment    }
  1132.    {of the page frame.                                         }
  1133.    {-----------------------------------------------------------}
  1134.    Function Get_Page_Frame_Base_Address
  1135.      (Var Page_Frame_Address: Integer): Integer;
  1136.      Var
  1137.        Regs: Registers;
  1138.  
  1139.      Begin
  1140.        with Regs do
  1141.          Begin
  1142.            {---------------------------------------------------}
  1143.            {Get the page frame segment address from EMM.       }
  1144.            {Load pseudo-registers prior to invoking EMM.       }
  1145.            {   AH = get page frame segment function            }
  1146.            {---------------------------------------------------}
  1147.            AH := Get_Page_Frame;
  1148.            intr (EMM_INT,Regs);
  1149.            {---------------------------------------------------}
  1150.            {Unload the pseudo-registers after invoking EMM.    }
  1151.            {   BX = page frame segment address                 }
  1152.            {   AH = status                                     }
  1153.            {---------------------------------------------------}
  1154.            Page_Frame_Address := BX;
  1155.            Get_Page_Frame_Base_Address := AH;
  1156.           end; {with Regs do }
  1157.      end; {Function Get_Page_Frame_Base_Address }
  1158.  
  1159.    {-----------------------------------------------------------}
  1160.    {This function releases the EMM memory pages allocated to   }
  1161.    {us, back to the EMM memory pool.                           }
  1162.    {-----------------------------------------------------------}
  1163.    Function Deallocate_Expanded_Memory_Pages
  1164.      (Handle: Integer): Integer;
  1165.      Var
  1166.        Regs: Registers;
  1167.  
  1168.      Begin
  1169.        with Regs do
  1170.          Begin
  1171.            {---------------------------------------------------}
  1172.            {Deallocate the pages allocated to an EMM handle.   }
  1173.            {Load pseudo-registers prior to invoking EMM.       }
  1174.            {   AH = deallocate pages function                  }
  1175.            {   DX = EMM handle                                 }
  1176.            {---------------------------------------------------}
  1177.            AH := DEALLOCATE_PAGES;
  1178.            DX := Emm_Handle;
  1179.            Intr (EMM_INT,Regs);
  1180.            {---------------------------------------------------}
  1181.            {Unload the pseudo-registers after invoking EMM.    }
  1182.            {   AH = status                                     }
  1183.            {---------------------------------------------------}
  1184.            Deallocate_Expanded_Memory_Pages := AH;
  1185.          end; {with Regs do}
  1186.      end; {Function Deallocate_Expanded_Memory_Pages}
  1187.  
  1188.    {-----------------------------------------------------------}
  1189.    {This function returns the version number of the EMM as     }
  1190.    {a three-character string.                                  }
  1191.    {-----------------------------------------------------------}
  1192.    Function Get_Version_Number (Var Version_String: ST3): Integer;
  1193.      Var
  1194.        Regs: Registers;
  1195.        Integer_Part, Fractional_Part: Char;
  1196.  
  1197.      Begin
  1198.        with Regs do
  1199.          Begin
  1200.            {---------------------------------------------------}
  1201.            {Get the version of EMM.                            }
  1202.            {Load pseudo-registers prior to invoking EMM.       }
  1203.            {   AH = get EMM version function                   }
  1204.            {---------------------------------------------------}
  1205.            AH := GET_VERSION;
  1206.            Intr (EMM_INT,Regs);
  1207.  
  1208.            {---------------------------------------------------}
  1209.            {If the version number returned was OK, then        }
  1210.            {convert it to a three-character string.            }
  1211.            {---------------------------------------------------}
  1212.            If AH=STATUS_OK then
  1213.              Begin
  1214.                {-----------------------------------------------}
  1215.                {The upper four bits of AH are the integer      }
  1216.                {portion of the version number, the lower four  }
  1217.                {bits are the fractional portion. Convert the   }
  1218.                {integer value to ASCII by adding 48.           }
  1219.                {-----------------------------------------------}
  1220.                Integer_Part    := Char (AL shr 4  + 48);
  1221.                Fractional_Part := Char (AL and $F + 48);
  1222.                Version_String  := Integer_Part + '.' + Fractional_Part;
  1223.              end; {If AH=STATUS_OK}
  1224.            {---------------------------------------------------}
  1225.            {Unload the pseudo-registers after invoking EMM.    }
  1226.            {   AH = status                                     }
  1227.            {---------------------------------------------------}
  1228.            Get_Version_Number := AH;
  1229.          end; {with Regs do }
  1230.      end; {Function Get_Version_Number }
  1231.  
  1232.    {-----------------------------------------------------------}
  1233.    {This procedure prints an error message passed by the       }
  1234.    {caller, prints the error code passed by the caller in hex, }
  1235.    {and then terminates the program with the an error level    }
  1236.    {of 1.                                                      }
  1237.    {-----------------------------------------------------------}
  1238.    Procedure Error (Error_Message: ST80; Error_Number: Integer);
  1239.      Begin
  1240.        Writeln (Error_Message);
  1241.        Writeln (' Error_Number = ',Hex_String (Error_Number));
  1242.        Writeln ('EMM test program aborting.');
  1243.        Halt (1);
  1244.      end; {Procedure Error_Message}
  1245.  
  1246.  {-------------------------------------------------------------}
  1247.  {This program is an example of the basic EMM functions that   }
  1248.  {you need in order to use EMM memory with Turbo Pascal.       }
  1249.  {-------------------------------------------------------------}
  1250.  Begin
  1251.    ClrScr;
  1252.    Window (5,2,77,22);
  1253.  
  1254.    {-----------------------------------------------------------}
  1255.    {Determine if the Expanded Memory Manager is installed, If  }
  1256.    {not, then terminate 'main' with an ErrorLevel code of 1.   }
  1257.    {-----------------------------------------------------------}
  1258.    If not (Emm_Installed) then
  1259.      Begin
  1260.        Writeln ('The LIM EMM is not installed.');
  1261.        Halt (1);
  1262.      end
  1263.    else
  1264.      Begin
  1265.        {Get the version number and display it}
  1266.        Error_Code := Get_Version_Number (Version_Number);
  1267.        If Error_Code <> STATUS_OK then
  1268.          Error ('Error getting EMM version number ', Error_code)
  1269.        else
  1270.          Writeln ('LIM Expanded Memory Manager, version ',
  1271.                  Version_Number,' is ready for use.');
  1272.      end;
  1273.    Writeln;
  1274.  
  1275.    {-----------------------------------------------------------}
  1276.    {Determine if there are enough expanded memory pages for    }
  1277.    {this application.                                          }
  1278.    {-----------------------------------------------------------}
  1279.    Pages_Needed := APPLICATION_PAGE_COUNT;
  1280.    Error_Code   := EMM_Pages_Available (Total_EMM_Pages,
  1281.                                         Available_EMM_Pages);
  1282.    If Error_Code <> STATUS_OK then
  1283.      Error ('Error determining number of EMM pages available.',
  1284.            Error_code);
  1285.  
  1286.    Writeln ('There are a total of ', Total_EMM_Pages,
  1287.             ' expanded memory pages present in this system.');
  1288.    Writeln (' ', Available_EMM_Pages,
  1289.             ' of those pages are available for use.');
  1290.    Writeln;
  1291.  
  1292.    {-----------------------------------------------------------}
  1293.    {If there is an insufficient number of pages for the        }
  1294.    {application, then report the error and terminate the EMM   }
  1295.    {example program.                                           }
  1296.    {-----------------------------------------------------------}
  1297.    If Pages_Needed > Available_EMM_Pages then
  1298.      Begin
  1299.        Str (Pages_Needed, Pages_Number_String);
  1300.        Error ('We need ' + Pages_Number_String+
  1301.               ' EMM pages. There are not that many available.',
  1302.               Error_Code);
  1303.      end; {Pages_Needed > Available_EMM_Pages }
  1304.  
  1305.    {-----------------------------------------------------------}
  1306.    {Allocate expanded memory pages for our use.                }
  1307.    {-----------------------------------------------------------}
  1308.    Error_Code :=
  1309.      Allocate_Expanded_Memory_Pages (Pages_Needed, Emm_Handle);
  1310.    Str (Pages_Needed,Pages_Number_String);
  1311.    If Error_Code <> STATUS_OK then
  1312.      Error ('EMM test program failed trying to allocate '
  1313.             + Pages_Number_String
  1314.             + ' pages for usage.',Error_Code);
  1315.    Writeln (APPLICATION_PAGE_COUNT,
  1316.             ' EMM page(s) allocated for the EMM test program.');
  1317.    Writeln;
  1318.  
  1319.    {---------------------------------------------------------}
  1320.    {Map in the required logical pages to the physical pages  }
  1321.    {given to us, in this case just one page.                 }
  1322.    {---------------------------------------------------------}
  1323.    Logical_Page  := 0;
  1324.    Physical_Page := 0;
  1325.    Error_Code := Map_Expanded_Memory_Pages (Emm_Handle,
  1326.                                             Logical_Page,
  1327.                                             Physical_Page);
  1328.    If Error_Code <> STATUS_OK then
  1329.      Error ('EMM test program failed trying to map '
  1330.             + 'logical pages into physical pages.',
  1331.             Error_Code);
  1332.  
  1333.    Writeln ('Logical Page ',
  1334.             Logical_Page,
  1335.             ' successfully mapped into Physical Page ',
  1336.             Physical_Page);
  1337.    Writeln;
  1338.  
  1339.    {-----------------------------------------------------------}
  1340.    { Get the expanded memory page frame address.              }
  1341.    {-----------------------------------------------------------}
  1342.    Error_Code := Get_Page_Frame_Base_Address (Page_Frame_Base_Address);
  1343.    If Error_Code <> STATUS_OK then
  1344.      Error ('EMM test program unable to get the base Page'
  1345.             + ' Frame Address.',
  1346.             Error_Code);
  1347.    Writeln ('The base address of the EMM page frame is = '
  1348.             + Hex_String (Page_Frame_Base_Address));
  1349.    Writeln;
  1350.  
  1351.    {-----------------------------------------------------------}
  1352.    {Write a test pattern to expanded memory.                   }
  1353.    {-----------------------------------------------------------}
  1354.    For Offset := 0 to 16382 do
  1355.      Begin
  1356.        Mem[Page_Frame_Base_Address:Offset] := Offset mod 256;
  1357.      end;
  1358.  
  1359.    {-----------------------------------------------------------}
  1360.    {Make sure that what is in EMM memory is what was just      }
  1361.    {written.                                                   }
  1362.    {-----------------------------------------------------------}
  1363.    Writeln ('Testing EMM memory.');
  1364.  
  1365.    Offset := 1;
  1366.    Verify := True;
  1367.    while (Offset <= 16382) and (Verify = True) do
  1368.      Begin
  1369.        If Mem[Page_Frame_Base_Address:Offset] <> Offset mod 256 then
  1370.          Verify := False;
  1371.        Offset := Succ (Offset);
  1372.      end; {while (Offset <= 16382) and (Verify = True) }
  1373.  
  1374.    {-----------------------------------------------------------}
  1375.    {If what is read does not match what was written,           }
  1376.    {an error occurred.                                         }
  1377.    {-----------------------------------------------------------}
  1378.    If not Verify then
  1379.      Error ('What was written to EMM memory was not found during '
  1380.             + 'memory verification test.',
  1381.             0);
  1382.    Writeln ('EMM memory test successful.');
  1383.    Writeln;
  1384.  
  1385.    {-----------------------------------------------------------}
  1386.    {Return the expanded memory pages given to us back to the   }
  1387.    {EMM memory pool before terminating our test program.       }
  1388.    {-----------------------------------------------------------}
  1389.    Error_Code := Deallocate_Expanded_Memory_Pages (Emm_Handle);
  1390.    If Error_Code <> STATUS_OK then
  1391.      Error ('EMM test program was unable to deallocate '
  1392.             + 'the EMM pages in use.',
  1393.             Error_Code);
  1394.    Writeln (APPLICATION_PAGE_COUNT,
  1395.             ' page(s) deallocated.');
  1396.    Writeln;
  1397.    Writeln ('EMM test program completed.');
  1398.  
  1399.  end.
  1400.  
  1401.  Example 3
  1402.  
  1403.  This program is written in Microsoft's macro assembler.
  1404.  
  1405.  CODE SEGMENT
  1406.        ASSUME CS:CODE, DS:CODE
  1407.  
  1408.        MOV  AX, CS
  1409.        MOV  DS, AX
  1410.                                      ∙
  1411.                                      ∙
  1412.                                      ∙
  1413.  check_emm_installed:
  1414.  
  1415.    MOV  AH, 35h             ; AH = DOS get interrupt vector function
  1416.    MOV  AL, 67h             ; AL = EMM interrupt vector number
  1417.    INT  21h
  1418.    MOV  DI, 0Ah             ; ES:DI points to where device name
  1419.                             ; should be
  1420.    LEA  SI, EMM_device_name ; DS:SI points to ASCIIZ string containing
  1421.                             ; EMM device name
  1422.  
  1423.    MOV  CX, device_name_length ; set up loop counter for string op
  1424.    CLD                      ; set up direction flag for forward
  1425.    REPE CMPSB               ; Compare the strings
  1426.    JNE  exit                ; IF strings are not equal THEN exit
  1427.                             ; ELSE
  1428.  
  1429.  check_enough_unallocated_pages:
  1430.  
  1431.    MOV  AH, 41h             ; AH = EMM get unallocated page
  1432.                             ; count function code
  1433.    INT  67h
  1434.    OR   AH, AH              ; Check EMM status
  1435.    JNZ  emm_error_handler   ; IF emm_error THEN goto error handler
  1436.                             ; ELSE
  1437.  allocate_expanded_memory_pages:
  1438.  
  1439.    MOV  AH, 43h             ; AH = EMM allocate pages
  1440.                             ; function code
  1441.    MOV  BX, 2               ; BX = number of pages needed
  1442.    INT  67h
  1443.    OR   AH, AH              ; Check EMM status
  1444.    JNZ  emm_error_handler   ; IF emm_error THEN goto error handler
  1445.                             ; ELSE
  1446.    MOV  emm_handle, DX      ; save EMM handle
  1447.  
  1448.  map_expanded_memory_pages:
  1449.  
  1450.    MOV  AH, 44h             ; AH = EMM map pages function
  1451.    MOV  DX, emm_handle      ; DX = application's handle
  1452.  
  1453.  map_0_to_0:
  1454.    MOV  BX, 0               ; BX = logical page 0
  1455.    MOV  AL, 0               ; AL = physical page 0
  1456.    INT  67h
  1457.    OR   AH, AH              ; Check EMM status
  1458.    JNZ  emm_error_handler   ; IF error THEN goto error handler
  1459.                             ; ELSE
  1460.  get_page_frame_address:
  1461.    MOV  AH, 41h             ; AH = EMM get page frame base
  1462.                             ; address function
  1463.    INT  67h
  1464.    OR   AH, AH              ; Check EMM status
  1465.    JNZ  emm_error_handler   ; IF error THEN goto error handler
  1466.    MOV  pf_addr, BX         ; ELSE save pf_addr
  1467.  
  1468.  write_to_expanded_memory:  ; Write zeros to memory mapped at
  1469.                             ; physical page 0.
  1470.    MOV  AX, pf_addr
  1471.    MOV  ES, AX              ; Set up ES to point to physical page 0
  1472.    MOV  DI, 0               ; DI used as index into physical page 0
  1473.    MOV  AL, 0               ; Initialize AL for string STOSB operation
  1474.    MOV  CX, 4000h           ; Initialize loop counter to length
  1475.                             ; of expanded memory page size
  1476.    CLD                      ; Set direction forward for string op
  1477.    REP  STOSB
  1478.  
  1479.  deallocate_pages:
  1480.    MOV  AH, 45h             ; AH = EMM deallocate pages function
  1481.    MOV  DX, emm_handle
  1482.    INT  67h                 ; return handle's pages to EMM
  1483.    OR   AH, AH              ; Check EMM status
  1484.    JNZ  emm_error_handler   ; IF error THEN goto error handler
  1485.  
  1486.  exit:
  1487.    MOV  AH, 4ch             ; AH = DOS exit function
  1488.    INT  21h                 ; Return to DOS
  1489.  
  1490.  EMM_device_name DB 'EMMXXXX0" ; ASCIIZ EMM device name string
  1491.  
  1492.  device_name_length  EQU  8
  1493.  
  1494.  CODE   ENDS
  1495.    END
  1496.  
  1497.  Example 4
  1498.  
  1499.  This program is an example of how to exchange a 256K-byte block of data from
  1500.  conventional memory to expanded memory.
  1501.  
  1502.  CODE SEGMENT
  1503.   ASSUME   CS:CODE, DS:CODE
  1504.                                      ∙
  1505.                                      ∙
  1506.                                      ∙
  1507.  xchg_packet_set_up:
  1508.  
  1509.  ; DS:SI = xchg_packet
  1510.    MOV   AX, SEG xchg_packet
  1511.    MOV   DS, AX
  1512.    MOV   SI, OFFSET xchg_packet
  1513.  
  1514.  ; Moving 256K of data from conventional memory to expanded memory
  1515.    MOV   WORD PTR [SI].region_length [0], 0
  1516.    MOV   WORD PTR [SI].region_length [2], 4
  1517.    MOV   [SI].src_mem_type, 0
  1518.    MOV   [SI].dest_mem_type, 1
  1519.  
  1520.  ; starting at segment: 4000h, offset: 0
  1521.    MOV   [SI].src_init_seg_page, 4000h
  1522.    MOV   [SI].src_init_offset, 0
  1523.  
  1524.  ; Move data into expanded memory logical page 0, offset 0.
  1525.    MOV   [SI].dest_init_seg_page, 0
  1526.    MOV   [SI].dest_init_offset, 0
  1527.  
  1528.  ; Initialize for future compatibility
  1529.    MOV   [SI].src_handle, 0
  1530.  
  1531.  ; Need handle for expanded memory destination.
  1532.    MOV   DX, emm_handle
  1533.    MOV   [SI].dest_handle, DX
  1534.  
  1535.  ; AX = EMM Exchange Memory function
  1536.    MOV   AX, 5F01h
  1537.    INT   67h
  1538.    OR    AH, AH
  1539.    JNZ   emm_error_handler
  1540.  
  1541.                                  xchg_struct  STRUC
  1542.    region_length              DD ?
  1543.    src_mem_type               DB ?
  1544.    src_handle                 DW ?
  1545.    src_init_offset            DW ?
  1546.    src_init_seg_page          DW ?
  1547.    dest_mem_type              DB ?
  1548.    dest_handle                DW ?
  1549.    dest_init_offset           DW ?
  1550.    dest_init_seg_page         DW ?
  1551.  xchg_struct                  ENDS
  1552.  
  1553.  xchg_packet                  xchg_struct
  1554.  
  1555.  CODE  ENDS
  1556.  END
  1557.  
  1558.  
  1559.  
  1560.  CHAPTER 3  EMM FUNCTIONS
  1561.  
  1562.  This chapter provides you with a standardized set of expanded memory
  1563.  functions. Because they are standardized, you avoid potential compatibility
  1564.  problems with other expanded memory programs that also adhere to the memory
  1565.  manager specification. Programs that deal directly with the hardware or that
  1566.  don't adhere to this specification will be incompatible.
  1567.  
  1568.  Table 3-1 presents a sequential list of the EMM functions. The remainder of
  1569.  this chapter provides detailed descriptions of each function.
  1570.  
  1571.  Table 3-1  List of EMM Functions
  1572.  
  1573. ╓┌───────┌───────────────────────────────────────┌───────────────────────────╖
  1574.  Number  Function Name                           Hex Value
  1575.  
  1576.    1     Get Status                              40h
  1577.  Number  Function Name                           Hex Value
  1578.   1     Get Status                              40h
  1579.  
  1580.    2     Get Page Frame Segment Address          41h
  1581.  
  1582.    3     Get Unallocated Page Count              42h
  1583.  
  1584.    4     Allocate Pages                          43h
  1585.  
  1586.    5     Map/Unmap Handle Page                   44h
  1587.  
  1588.    6     Deallocate Pages                        45h
  1589.  
  1590.    7     Get Version                             46h
  1591.  
  1592.    8     Save Page Map                           47h
  1593.  
  1594.    9     Restore Page Map                        48h
  1595.  
  1596.   10     Reserved                                49h
  1597.  
  1598.  Number  Function Name                           Hex Value
  1599. 
  1600.   11     Reserved                                4Ah
  1601.  
  1602.   12     Get Handle Count                        4Bh
  1603.  
  1604.   13     Get Handle Pages                        4Ch
  1605.  
  1606.   14     Get All Handle Pages                    4Dh
  1607.  
  1608.   15     Get Page Map                            4E00h
  1609.          Set Page Map                            4E01h
  1610.          Get & Set Page Map                      4E02h
  1611.          Get Size of Page Map Save Array         4E03h
  1612.  
  1613.   16     Get Partial Page Map                    4F00h
  1614.          Set Partial Page Map                    4F01h
  1615.          Get Size of Partial Page Map
  1616.          Save Array                              4F02h
  1617.  
  1618.   17     Map/Unmap Multiple Handle Pages
  1619.  Number  Function Name                           Hex Value
  1620.  17     Map/Unmap Multiple Handle Pages
  1621.          (Physical page number mode)             5000h
  1622.          Map/Unmap Multiple Handle Pages
  1623.          (Segment address mode)                  5001h
  1624.  
  1625.   18     Reallocate Pages                        51h
  1626.  
  1627.   19     Get Handle Attribute                    5200h
  1628.          Set Handle Attribute                    5201h
  1629.          Get Handle Attribute Capability         5202h
  1630.  
  1631.   20     Get Handle Name                         5300h
  1632.          Set Handle Name                         5301h
  1633.  
  1634.   21     Get Handle Directory                    5400h
  1635.          Search for Named Handle                 5401h
  1636.          Get Total Handles                       5402h
  1637.  
  1638.   22     Alter Page Map & Jump
  1639.          (Physical page number mode)             5500h
  1640.  Number  Function Name                           Hex Value
  1641.         (Physical page number mode)             5500h
  1642.          Alter Page Map & Jump
  1643.          (Segment address mode)                  5501h
  1644.  
  1645.   23     Alter Page Map & Call
  1646.          (Physical page number mode)             5600h
  1647.          Alter Page Map & Call
  1648.          (Segment address mode)                  5601h
  1649.          Get Page Map Stack Space Size           5602h
  1650.  
  1651.   24     Move Memory Region                      5700h
  1652.          Exchange Memory Region                  5701h
  1653.  
  1654.   25     Get Mappable Physical Address Array     5800h
  1655.          Get Mappable Physical Address Array
  1656.              Entries                             5801h
  1657.  
  1658.   26     Get Hardware Configuration Array        5900h
  1659.          Get Unallocated Raw Page Count          5901h
  1660.  
  1661.  Number  Function Name                           Hex Value
  1662. 
  1663.   27     Allocate Standard Pages                 5A00h
  1664.          Allocate Raw Pages                      5A01h
  1665.  
  1666.   28     Get Alternate Map Register Set          5B00h
  1667.          Set Alternate Map Register Set          5B01h
  1668.          Get Alternate Map Save Array Size       5B02h
  1669.          Allocate Alternate Map Register Set     5B03h
  1670.          Deallocate Alternate Map Register Set   5B04h
  1671.          Allocate DMA Register Set.              5B05h
  1672.          Enable DMA on Alternate Map
  1673.              Register Set                        5B06h
  1674.          Disable DMA on Alternate Map
  1675.              Register Set                        5B07h
  1676.          Deallocate DMA Register Set             5B08h
  1677.  
  1678.   29     Prepare Expanded Memory Hardware for
  1679.              Warmboot                              5Ch
  1680.  
  1681.   30     Enable OS/E Function Set                5D00h
  1682.  Number  Function Name                           Hex Value
  1683.  30     Enable OS/E Function Set                5D00h
  1684.          Disable OS/E Function Set               5D01h
  1685.          Return OS/E Access Key                  5D02h
  1686.  
  1687.  
  1688.  FUNCTION 1  GET STATUS
  1689.  
  1690.  PURPOSE
  1691.  
  1692.  The Get Status function returns a status code indicating whether the memory
  1693.  manager is present and the hardware is working correctly.
  1694.  
  1695.  CALLING PARAMETERS
  1696.  
  1697.  AH = 40h
  1698.    Contains the Get Status function.
  1699.  
  1700.  REGISTERS MODIFIED
  1701.  
  1702.  AX
  1703.  
  1704.  STATUS
  1705.  
  1706.  AH = 0        SUCCESSFUL.
  1707.    The manager is present in the system, and the hardware is working
  1708.    correctly.
  1709.  
  1710.  AH = 80h      NON-RECOVERABLE.
  1711.    The manager detected a malfunction in the memory manager software.
  1712.  
  1713.  AH = 81h      NON-RECOVERABLE.
  1714.    The manager detected a malfunction in the expanded memory hardware.
  1715.  
  1716.  AH = 84h      NON-RECOVERABLE.
  1717.    The function code passed to the memory manager is not defined.
  1718.  
  1719.  EXAMPLE
  1720.  
  1721.  MOV   AH, 40h            ; load function code
  1722.  INT   67h                ; call the memory manager
  1723.  OR    AH, AH             ; check EMM status
  1724.  JNZ   emm_err_handler    ; jump to error handler on error
  1725.  
  1726.  
  1727.  FUNCTION 2  GET PAGE FRAME ADDRESS
  1728.  
  1729.  PURPOSE
  1730.  
  1731.  The Get Page Frame Address function returns the segment address where the
  1732.  page frame is located.
  1733.  
  1734.  CALLING PARAMETERS
  1735.  
  1736.  AH = 41h
  1737.    Contains the Get Page Frame function.
  1738.  
  1739.  RESULTS
  1740.  
  1741.  These results are valid only if the status returned is zero.
  1742.  
  1743.  BX = page frame segment address
  1744.    Contains the segment address of the page frame.
  1745.  
  1746.  REGISTERS MODIFIED
  1747.  
  1748.  AX, BX
  1749.  
  1750.  STATUS
  1751.  
  1752.  AH = 0        SUCCESSFUL.
  1753.    The manager has returned the page frame address in the BX register.
  1754.  
  1755.  AH = 80h      NON-RECOVERABLE.
  1756.    The manager detected a malfunction in the memory manager software.
  1757.  
  1758.  AH = 81h      NON-RECOVERABLE.
  1759.    The manager detected a malfunction in the expanded memory hardware.
  1760.  
  1761.  AH = 84h      NON-RECOVERABLE.
  1762.    The function code passed to the memory manager is not defined.
  1763.  
  1764.  EXAMPLE
  1765.  
  1766.  page_frame_segment           DW  ?
  1767.  
  1768.  MOV   AH, 41h                ; load function code
  1769.  INT   67h                    ; call the memory manager
  1770.  OR    AH, AH                 ; check EMM status
  1771.  JNZ   emm_err_handler        ; jump to error handler on error
  1772.  MOV   page_frame_segment, BX ; save page frame address
  1773.  
  1774.  
  1775.  FUNCTION 3  GET UNALLOCATED PAGE COUNT
  1776.  
  1777.  PURPOSE
  1778.  
  1779.  The Get Unallocated Page Count function returns the number of unallocated
  1780.  pages and the total number of expanded memory pages.
  1781.  
  1782.  CALLING PARAMETERS
  1783.  
  1784.  AH = 42h
  1785.    Contains the Get Unallocated Page Count function.
  1786.  
  1787.  RESULTS
  1788.  
  1789.  These results are valid only if the status returned is zero.
  1790.  
  1791.  BX = unallocated pages
  1792.    The number of expanded memory pages that are currently available for use
  1793.    (unallocated).
  1794.  
  1795.  DX = total pages
  1796.    The total number expanded memory pages.
  1797.  
  1798.  REGISTERS MODIFIED
  1799.  
  1800.  AX, BX, DX
  1801.  
  1802.  STATUS
  1803.  
  1804.  AH = 0        SUCCESSFUL.
  1805.    The manager has returned the number of unallocated pages and the number of
  1806.    total pages in expanded memory.
  1807.  
  1808.  AH = 80h      NON-RECOVERABLE.
  1809.    The manager detected a malfunction in the memory manager software.
  1810.  
  1811.  AH = 81h      NON-RECOVERABLE.
  1812.    The manager detected a malfunction in the expanded memory hardware.
  1813.  
  1814.  AH = 84h      NON-RECOVERABLE.
  1815.    The function code passed to the memory manager is not defined.
  1816.  
  1817.  EXAMPLE
  1818.  
  1819.  un_alloc_pages           DW  ?
  1820.  total_pages              DW  ?
  1821.  
  1822.  MOV   AH, 42h            ; load function code
  1823.  INT   67h                ; call the memory manager
  1824.  OR    AH, AH             ; check EMM status
  1825.  JNZ   emm_err_handler    ; jump to error handler on error
  1826.  MOV   un_alloc_pages, BX ; save unallocated page count
  1827.  MOV   total_pages, DX    ; save total page count
  1828.  
  1829.  
  1830.  FUNCTION 4  ALLOCATE PAGES
  1831.  
  1832.  PURPOSE
  1833.  
  1834.  The Allocate Pages function allocates the number of pages requested and
  1835.  assigns a unique EMM handle to these pages. The EMM handle owns these pages
  1836.  until the application deallocates them.
  1837.  
  1838.  Handles which are assigned using this function will have 16K-byte pages, the
  1839.  size of a standard expanded memory page. If the expanded memory board
  1840.  hardware isn't able to supply 16K-byte pages, it will emulate them by
  1841.  combining multiple non-standard size pages to form a single 16K-byte page.
  1842.  All application programs and functions that use the handles this function
  1843.  returns will deal with 16K-byte pages.
  1844.  
  1845.  The numeric value of the handles the EMM returns are in the range of 1 to
  1846.  254 decimal (0001h to 00FEh). The OS handle (handle value 0) is never
  1847.  returned by the Allocate Pages function. Also, the uppermost byte of the
  1848.  handle will be zero and cannot be used by the application. A memory manager
  1849.  should be able to supply up to 255 handles, including the OS handle. An
  1850.  application can use Function 21 to find out how many handles an EMM
  1851.  supports.
  1852.  
  1853.  Allocating zero pages to a handle is not valid. If an application needs to
  1854.  allocate 0 pages to a handle it should use Function 27 provided for this
  1855.  purpose.
  1856.  
  1857.  ────────────────────────────────────────────────────────────────────────────
  1858.  NOTE:
  1859.    This note affects expanded memory manager implementers and operating
  1860.    system developers only. Applications should not use the following
  1861.    characteristic of the memory manager. An application violating this rule
  1862.    will be incompatible with future versions of Microsoft's operating systems
  1863.    and environments.
  1864.  
  1865.    To be compatible with this specification, an expanded memory manager will
  1866.    provide a special handle which is available to the operating system only.
  1867.    This handle will have a value of 0000h and will have a set of pages
  1868.    allocated to it when the expanded memory manager driver installs. The
  1869.    pages that the memory manager will automatically allocate to handle 0000h
  1870.    are those that backfill conventional memory. Typically, this backfill
  1871.    occurs between addresses 40000h (256K) and 9FFFFh (640K). However, the
  1872.    range can extend below and above this limit if the hardware and memory
  1873.    manager have the capability.
  1874.  
  1875.    An operating system won't have to invoke Function 4 to obtain this handle
  1876.    because it can assume the handle already exists and is available for use
  1877.    immediately after the expanded memory device driver installs. When an
  1878.    operating system wants to use this handle, it uses the special handle
  1879.    value of 0000h. The operating system will be able to invoke any EMM
  1880.    function using this special handle value. To allocate pages to this
  1881.    handle, the operating system need only invoke Function 18 (Reallocate
  1882.    pages).
  1883.  
  1884.    There are two special cases for this handle:
  1885.  
  1886.      1.  Function 4 (Allocate Pages). This function must never return zero
  1887.          as a handle value. Applications must always invoke Function 4 to
  1888.          allocate pages and obtain a handle which identifies the pages which
  1889.          belong to it. Since Function 4 never returns a handle value of
  1890.          zero, an application will never gain access to this special handle.
  1891.  
  1892.      2.  Function 6 (Deallocate Pages). If the operating system uses it to
  1893.          deallocate the pages which are allocated to this special handle, the
  1894.          pages the handle owns will be returned to the manager for use. But
  1895.          the handle will not be available for reassignment. The manager
  1896.          should treat a deallocate pages function request for this handle the
  1897.          same as a reallocate pages function request, where the number of
  1898.          pages to reallocate to this handle is zero.
  1899.  ────────────────────────────────────────────────────────────────────────────
  1900.  
  1901.  CALLING PARAMETERS
  1902.  
  1903.  AH = 43h
  1904.    Contains the Allocate Pages function.
  1905.  
  1906.  BX = num_of_pages_to_alloc
  1907.    Contains the number of pages you want your program to allocate.
  1908.  
  1909.  RESULTS
  1910.  
  1911.  These results are valid only if the status returned is zero.
  1912.  
  1913.  DX = handle
  1914.    Contains a unique EMM handle. Your program must use this EMM handle (as a
  1915.    parameter) in any function that requires it. You can use up to 255
  1916.    handles. The uppermost byte of the handle will be zero and cannot be used
  1917.    by the application.
  1918.  
  1919.  REGISTERS MODIFIED
  1920.  
  1921.  AX, DX
  1922.  
  1923.  STATUS
  1924.  
  1925.  AH = 0        SUCCESSFUL.
  1926.    The manager has allocated the requested pages to the assigned EMM handle.
  1927.  
  1928.  AH = 80h      NON-RECOVERABLE.
  1929.    The manager detected a malfunction in the memory manager software.
  1930.  
  1931.  AH = 81h      NON-RECOVERABLE.
  1932.    The manager detected a malfunction in the expanded memory hardware.
  1933.  
  1934.  AH = 84h      NON-RECOVERABLE.
  1935.    The function code passed to the memory manager is not defined.
  1936.  
  1937.  AH = 85h      RECOVERABLE.
  1938.    All EMM handles are being used.
  1939.  
  1940.  AH = 87h      RECOVERABLE.
  1941.    There aren't enough expanded memory pages present in the system to satisfy
  1942.    your program's request.
  1943.  
  1944.  AH = 88h      RECOVERABLE.
  1945.    There aren't enough unallocated pages to satisfy your program's request.
  1946.  
  1947.  AH = 89h      RECOVERABLE.
  1948.    Your program attempted to allocate zero pages.
  1949.  
  1950.  EXAMPLE
  1951.  
  1952.  num_of_pages_to_alloc           DW  ?
  1953.  emm_handle                      DW  ?
  1954.  
  1955.  MOV   BX, num_of_pages_to_alloc ; load number of pages
  1956.  MOV   AH, 43h                   ; load function code
  1957.  INT   67h                       ; call the memory manager
  1958.  OR    AH, AH                    ; check EMM status
  1959.  JNZ   emm_err_handler           ; jump to error handler
  1960.                                  ; on error
  1961.  MOV   emm_handle, DX            ; save EMM handle
  1962.  
  1963.  
  1964.  FUNCTION 5  MAP/UNMAP HANDLE PAGES
  1965.  
  1966.  PURPOSE
  1967.  
  1968.  The Map/Unmap Handle Page function maps a logical page at a specific
  1969.  physical page anywhere in the mappable regions of system memory. The lowest
  1970.  valued physical page numbers are associated with regions of memory outside
  1971.  the conventional memory range. Use Function 25 (Get Mappable Physical
  1972.  Address Array) to determine which physical pages within a system are
  1973.  mappable and determine the segment addresses which correspond to a specific
  1974.  physical page number. Function 25 provides a cross reference between
  1975.  physical page numbers and segment addresses.
  1976.  
  1977.  This function can also unmap physical pages, making them inaccessible for
  1978.  reading or writing. You unmap a physical page by setting its associated
  1979.  logical page to FFFFh.
  1980.  
  1981.  You might unmap an entire set of mapped pages, for example, before loading
  1982.  and executing a program. Doing so ensures the loaded program, if it accesses
  1983.  expanded memory, won't access the pages your program has mapped. However,
  1984.  you must save the mapping context before you unmap the physical pages. This
  1985.  enables you to restore it later so you can access the memory you mapped
  1986.  there. To save the mapping context, use Function 8, 15, or 16. To restore
  1987.  the mapping context, use Function 9, 15, or 16.
  1988.  
  1989.  The handle determines what type of pages are being mapped. Logical pages
  1990.  allocated by Function 4 and Function 27 (Allocate Standard Pages
  1991.  subfunction) are referred to as pages and are 16K bytes long. Logical pages
  1992.  allocated by Function 27 (Allocate Raw Pages subfunction) are referred to
  1993.  as raw pages and might not be the same size as logical pages.
  1994.  
  1995.  CALLING PARAMETERS
  1996.  
  1997.  AH = 44h
  1998.    Contains the Map Handle Page function.
  1999.  
  2000.  AL = physical_page_number
  2001.    Contains the number of the physical page into which the logical page
  2002.    number is to be mapped. Physical pages are numbered zero relative.
  2003.  
  2004.  BX = logical_page_number
  2005.    Contains the number of the logical page to be mapped at the physical page
  2006.    within the page frame. Logical pages are numbered zero relative. The
  2007.    logical page must be in the range zero through (number of pages allocated
  2008.    to the EMM handle - 1). However, if BX contains logical page number FFFFh,
  2009.    the physical page specified in AL will be unmapped (be made inaccessible
  2010.    for reading or writing).
  2011.  
  2012.  DX = emm_handle
  2013.    Contains the EMM handle your program received from Function 4 (Allocate
  2014.    Pages).
  2015.  
  2016.  REGISTERS MODIFIED
  2017.  
  2018.  AX
  2019.  
  2020.  STATUS
  2021.  
  2022.  AH = 0        SUCCESSFUL.
  2023.    The manager has mapped the page. The page is ready to be accessed.
  2024.  
  2025.  AH = 80h      NON-RECOVERABLE.
  2026.    The manager detected a malfunction in the memory manager software.
  2027.  
  2028.  AH = 81h      NON-RECOVERABLE.
  2029.    The manager detected a malfunction in the expanded memory hardware.
  2030.  
  2031.  AH = 83h      NON-RECOVERABLE.
  2032.    The memory manager couldn't find the EMM handle your program specified.
  2033.  
  2034.  AH = 84h      NON-RECOVERABLE.
  2035.    The function code passed to the memory manager isn't defined.
  2036.  
  2037.  AH = 8Ah      RECOVERABLE.
  2038.    The logical page is out of the range of logical pages which are allocated
  2039.    to the EMM handle. This status is also returned if a program attempts map
  2040.    a logical page when no logical pages are allocated to the handle.
  2041.  
  2042.  AH = 8Bh      RECOVERABLE.
  2043.    The physical page number is out of the range of allowable physical pages.
  2044.    The program can recover by attempting to map into memory at a physical
  2045.    page which is within the range of allowable physical pages.
  2046.  
  2047.  EXAMPLE
  2048.  
  2049.  emm_handle                      DW  ?
  2050.  logical_page_number             DW  ?
  2051.  physical_page_number            DB  ?
  2052.  
  2053.  MOV   DX, emm_handle            ; load EMM handle
  2054.  MOV   BX, logical_page_number   ; load logical page number
  2055.  MOV   AL, physical_page_number  ; load physical page number
  2056.  MOV   AH, 44h                   ; load function code
  2057.  INT   67h                       ; call the memory manager
  2058.  OR    AH, AH                    ; check EMM status
  2059.  JNZ   emm_err_handler           ; jump to error handler on error
  2060.  
  2061.  
  2062.  FUNCTION 6  DEALLOCATE PAGES
  2063.  
  2064.  PURPOSE
  2065.  
  2066.  Deallocate Pages deallocates the logical pages currently allocated to an EMM
  2067.  handle. Only after the application deallocates these pages can other
  2068.  applications use them. When a handle is deallocated, it name is set to all
  2069.  ASCII nulls (binary zeros).
  2070.  
  2071.  ────────────────────────────────────────────────────────────────────────────
  2072.  NOTE:
  2073.    A program must perform this function before it exits to DOS. If it
  2074.    doesn't, no other programs can use these pages or the EMM handle. This
  2075.    means that a program using expanded memory should trap critical errors and
  2076.    control-break if there is a chance that the program will have allocated
  2077.    pages when either of these events occur.
  2078.  ────────────────────────────────────────────────────────────────────────────
  2079.  
  2080.  CALLING PARAMETERS
  2081.  
  2082.  AH = 45h
  2083.    Contains the Deallocate Pages function.
  2084.  
  2085.  DX = handle
  2086.    Contains the EMM handle returned by Function 4 (Allocate Pages).
  2087.  
  2088.  REGISTERS MODIFIED
  2089.  
  2090.  AX
  2091.  
  2092.  STATUS
  2093.  
  2094.  AH = 0        SUCCESSFUL.
  2095.    The manager has deallocated the pages previously allocated to the EMM
  2096.    handle.
  2097.  
  2098.  AH = 80h      NON-RECOVERABLE.
  2099.    The manager detected a malfunction in the memory manager software.
  2100.  
  2101.  AH = 81h      NON-RECOVERABLE.
  2102.    The manager detected a malfunction in the expanded memory hardware.
  2103.  
  2104.  AH = 83h      NON-RECOVERABLE.
  2105.    The manager couldn't find the specified EMM handle.
  2106.  
  2107.  AH = 84h      NON-RECOVERABLE.
  2108.    The function code passed to the memory manager is not defined.
  2109.  
  2110.  AH = 86h      RECOVERABLE.
  2111.    The memory manager detected a save or restore page mapping context error
  2112.    (Function 8 or 9). There is a page mapping register state in the save
  2113.    area for the specified EMM handle. Save Page Map (Function 8) placed it
  2114.    there and a subsequent Restore Page Map (Function 9) has not removed it.
  2115.  
  2116.    If you have saved the mapping context, you must restore it before you
  2117.    deallocate the EMM handle's pages.
  2118.  
  2119.  EXAMPLE
  2120.  
  2121.  emm_handle               DW  ?
  2122.  
  2123.  MOV   DX, emm_handle     ; load EMM handle
  2124.  MOV   AH, 45h            ; load function code
  2125.  INT   67h                ; call the memory manager
  2126.  OR    AH, AH             ; check EMM status
  2127.  JNZ   emm_err_handler    ; jump to error handler on error
  2128.  
  2129.  
  2130.  FUNCTION 7  GET VERSION
  2131.  
  2132.  PURPOSE
  2133.  
  2134.  The Get Version function returns the version number of the memory manager
  2135.  software.
  2136.  
  2137.  CALLING PARAMETERS
  2138.  
  2139.  AH = 46h
  2140.    Contains the Get Version function.
  2141.  
  2142.  RESULTS
  2143.  
  2144.  These results are valid only if the status returned is zero.
  2145.  
  2146.  AL = version number
  2147.    Contains the memory manager's version number in binary coded decimal (BCD)
  2148.    format. The upper four bits contain the integer digit of the version
  2149.    number. The lower four bits contain the fractional digit of version
  2150.    number. For example, version 4.0 is represented like this:
  2151.  
  2152.             0100 0000
  2153.               /   \
  2154.              4  .  0
  2155.  
  2156.    When checking for a version number, an application should check for a
  2157.    version number or greater. Vendors may use the fractional digit to
  2158.    indicate enhancements or corrections to their memory managers. Therefore,
  2159.    to allow for future versions of memory managers, an application shouldn't
  2160.    depend on an exact version number.
  2161.  
  2162.  REGISTERS MODIFIED
  2163.  
  2164.  AX
  2165.  
  2166.  STATUS
  2167.  
  2168.  AH = 0        SUCCESSFUL.
  2169.    The manager is present in the system and the hardware is working
  2170.    correctly.
  2171.  
  2172.  AH = 80h      NON-RECOVERABLE.
  2173.    The manager detected a malfunction in the memory manager software.
  2174.  
  2175.  AH = 81h      NON-RECOVERABLE.
  2176.    The manager detected a malfunction in the expanded memory hardware.
  2177.  
  2178.  AH = 84h      NON-RECOVERABLE.
  2179.    The function code passed to the memory manager is not defined.
  2180.  
  2181.  EXAMPLE
  2182.  
  2183.  emm_version              DB  ?
  2184.  
  2185.  MOV   AH, 46h            ; load function code
  2186.  INT   67h                ; call the memory manager
  2187.  OR    AH, AH             ; check EMM status
  2188.  JNZ   emm_err_handler    ; jump to error handler on error
  2189.  MOV   emm_version, AL    ; save version number
  2190.  
  2191.  
  2192.  FUNCTION 8  SAVE PAGE MAP
  2193.  
  2194.  PURPOSE
  2195.  
  2196.  Save Page Map saves the contents of the page mapping registers on all
  2197.  expanded memory boards in an internal save area. The function is typically
  2198.  used to save the memory mapping context of the EMM handle that was active
  2199.  when a software or hardware interrupt occurred. (See Function 9, Restore
  2200.  Page Map, for the restore operation.)
  2201.  
  2202.  If you're writing a resident program, an interrupt service routine, or a
  2203.  device driver that uses expanded memory, you must save the state of the
  2204.  mapping hardware. You must save this state because application software
  2205.  using expanded memory may be running when your program is invoked by a
  2206.  hardware interrupt, a software interrupt, or DOS.
  2207.  
  2208.  The Save Page Map function requires the EMM handle that was assigned to your
  2209.  resident program, interrupt service routine, or device driver at the time it
  2210.  was initialized. This is not the EMM handle that the application software
  2211.  was using when your software interrupted it.
  2212.  
  2213.  The Save Page Map function saves the state of the map registers for only the
  2214.  64K-byte page frame defined in versions 3.x of this specification. Since all
  2215.  applications written to LIM versions 3.x require saving the map register
  2216.  state of only this 64K-byte page frame, saving the entire mapping state for
  2217.  a large number of mappable pages would be inefficient use of memory.
  2218.  Applications that use a mappable memory region outside the LIM 3.x page
  2219.  frame should use Function 15 or 16 to save and restore the state of the
  2220.  map registers.
  2221.  
  2222.  CALLING PARAMETERS
  2223.  
  2224.  AH = 47h
  2225.    Contains the Save Page Map function.
  2226.  
  2227.  DX = handle
  2228.    Contains the EMM handle assigned to the interrupt service routine that's
  2229.    servicing the software or hardware interrupt. The interrupt service
  2230.    routine needs to save the state of the page mapping hardware before
  2231.    mapping any pages.
  2232.  
  2233.  REGISTERS MODIFIED
  2234.  
  2235.  AX
  2236.  
  2237.  STATUS
  2238.  
  2239.  AH = 0        SUCCESSFUL.
  2240.    The manager has saved the state of the page mapping hardware.
  2241.  
  2242.  AH = 80h      NON-RECOVERABLE.
  2243.    The manager detected a malfunction in the memory manager software.
  2244.  
  2245.  AH = 81h      NON-RECOVERABLE.
  2246.    The manager detected a malfunction in the expanded memory hardware.
  2247.  
  2248.  AH = 83h      NON-RECOVERABLE.
  2249.    The memory manager couldn't find the EMM handle your program specified.
  2250.  
  2251.  AH = 84h      NON-RECOVERABLE.
  2252.    The function code passed to the memory manager is not defined.
  2253.  
  2254.  AH = 8Ch      NON-RECOVERABLE.
  2255.    There is no room in the save area to store the state of the page mapping
  2256.    registers. The state of the map registers has not been saved.
  2257.  
  2258.  AH = 8Dh      CONDITIONALLY-RECOVERABLE.
  2259.    The save area already contains the page mapping register state for the EMM
  2260.    handle your program specified.
  2261.  
  2262.  EXAMPLE
  2263.  
  2264.  emm_handle               DW  ?
  2265.  
  2266.  MOV   DX, emm_handle     ; load EMM handle
  2267.  MOV   AH, 47h            ; load function code
  2268.  INT   67h                ; call the memory manager
  2269.  OR    AH, AH             ; check EMM status
  2270.  JNZ   emm_err_handler    ; jump to error handler on error
  2271.  
  2272.  
  2273.  FUNCTION 9  RESTORE PAGE MAP
  2274.  
  2275.  PURPOSE
  2276.  
  2277.  The Restore Page Map function restores the page mapping register contents on
  2278.  the expanded memory boards for a particular EMM handle. This function lets
  2279.  your program restore the contents of the mapping registers its EMM handle
  2280.  saved. (See Function 8, Save Page Map for the save operation.)
  2281.  
  2282.  If you're writing a resident program, an interrupt service routine, or a
  2283.  device driver that uses expanded memory, you must restore the mapping
  2284.  hardware to the state it was in before your program took over. You must save
  2285.  this state because application software using expanded memory might have
  2286.  been running when your program was invoked.
  2287.  
  2288.  The Restore Page Map function requires the EMM handle that was assigned to
  2289.  your resident program, interrupt service routine, or device driver at the
  2290.  time it was initialized. This is not the EMM handle that the application
  2291.  software was using when your software interrupted it.
  2292.  
  2293.  The Restore Page Map function restores the state of the map registers for
  2294.  only the 64K-byte page frame defined in versions 3.x of this specification.
  2295.  Since all applications written to LIM versions 3.x require restoring the map
  2296.  register state of only this 64K-byte page frame, restoring the entire
  2297.  mapping state for a large number of mappable pages would be inefficient use
  2298.  of memory. Applications that use a mappable memory region outside the LIM
  2299.  3.x page frame should use Function 15 or 16 to save and restore the state
  2300.  of the map registers.
  2301.  
  2302.  CALLING PARAMETERS
  2303.  
  2304.  AH = 48h
  2305.    Contains the Restore Page Map function.
  2306.  
  2307.  DX = emm_handle
  2308.    Contains the EMM handle assigned to the interrupt service routine that's
  2309.    servicing the software or hardware interrupt. The interrupt service
  2310.    routine needs to restore the state of the page mapping hardware.
  2311.  
  2312.  REGISTERS MODIFIED
  2313.  
  2314.  AX
  2315.  
  2316.  STATUS
  2317.  
  2318.  AH = 0        SUCCESSFUL.
  2319.    The manager has restored the state of the page mapping registers.
  2320.  
  2321.  AH = 80h      NON-RECOVERABLE.
  2322.    The manager detected a malfunction in the memory manager software.
  2323.  
  2324.  AH = 81h      NON-RECOVERABLE.
  2325.    The manager detected a malfunction in the expanded memory hardware.
  2326.  
  2327.  AH = 83h      NON-RECOVERABLE.
  2328.    The memory manager couldn't find the EMM handle your program specified.
  2329.  
  2330.  AH = 84h      NON-RECOVERABLE.
  2331.    The function code passed to the memory manager is not defined.
  2332.  
  2333.  AH = 8Eh      CONDITIONALLY-RECOVERABLE.
  2334.    There is no page mapping register state in the save area for the specified
  2335.    EMM handle. Your program didn't save the contents of the page mapping
  2336.    hardware, so Restore Page Map can't restore it.
  2337.  
  2338.  EXAMPLE
  2339.  
  2340.  emm_handle               DW  ?
  2341.  
  2342.  MOV   DX, emm_handle     ; load EMM handle
  2343.  MOV   AH, 48h            ; load function code
  2344.  INT   67h                ; call the memory manager
  2345.  OR    AH, AH             ; check EMM status
  2346.  JNZ   emm_err_handler    ; jump to error handler on error
  2347.  
  2348.  
  2349.  FUNCTION 10  RESERVED
  2350.  
  2351.  In earlier versions of the Lotus/Intel/Microsoft Expanded Memory
  2352.  Specification, Function 10 returned the page mapping register I/O array.
  2353.  This function is now reserved and, new programs should not use it.
  2354.  
  2355.  Existing programs that use this function may still work correctly if the
  2356.  hardware is capable of supporting them. However, programs that use Functions
  2357.  16 through 30 in Version 4.0 of this specification must not use Functions 10
  2358.  and 11. These functions won't work correctly if your program attempts to mix
  2359.  the use of the new functions (Functions 16 through 30) and functions 10 and
  2360.  11. Functions 10 and 11 are specific to the hardware on Intel expanded
  2361.  memory boards and will not work correctly on all vendors expanded memory
  2362.  boards.
  2363.  
  2364.  
  2365.  FUNCTION 11  RESERVED
  2366.  
  2367.  In earlier versions of the Lotus/Intel/Microsoft Expanded Memory
  2368.  Specification, Function 11 returned a page translation array. This function
  2369.  is now reserved, and new programs should not use it.
  2370.  
  2371.  Existing programs that use this function may still work correctly if the
  2372.  hardware is capable of supporting them. However, programs that use Functions
  2373.  16 through 30 in Version 4.0 of this specification must not use Functions 10
  2374.  and 11. These functions won't work correctly if your program attempts to mix
  2375.  the use of the new functions (Functions 16 through 30) and functions 10 and
  2376.  11. Functions 10 and 11 are specific to the hardware on Intel expanded
  2377.  memory boards and will not work correctly on all vendors expanded memory
  2378.  boards.
  2379.  
  2380.  
  2381.  FUNCTION 12  GET HANDLE COUNT
  2382.  
  2383.  PURPOSE
  2384.  
  2385.  The Get Handle Count function returns the number of open EMM handles
  2386.  (including the operating system handle 0) in the system.
  2387.  
  2388.  CALLING PARAMETERS
  2389.  
  2390.  AH = 4Bh
  2391.    Contains the Get Handle Count function.
  2392.  
  2393.  RESULTS
  2394.  
  2395.  These results are valid only if the status returned is zero.
  2396.  
  2397.  BX = total_open_emm_handles
  2398.    Contains the number of open EMM handles [including the operating system
  2399.    handle (0)]. This number will not exceed 255.
  2400.  
  2401.  REGISTERS MODIFIED
  2402.  
  2403.  AX, BX
  2404.  
  2405.  STATUS
  2406.  
  2407.  AH = 0        SUCCESSFUL.
  2408.    The manager has returned the number of active EMM handles.
  2409.  
  2410.  AH = 80h      NON-RECOVERABLE.
  2411.    The manager detected a malfunction in the memory manager software.
  2412.  
  2413.  AH = 81h      NON-RECOVERABLE.
  2414.    The manager detected a malfunction in the expanded memory hardware.
  2415.  
  2416.  AH = 84h      NON-RECOVERABLE.
  2417.    The function code passed to the memory manager is not defined.
  2418.  
  2419.  EXAMPLE
  2420.  
  2421.  total_open_emm_handles          DW  ?
  2422.  
  2423.  MOV  AH, 4Bh                    ; load function code
  2424.  INT  67h                        ; call the memory manager
  2425.  OR   AH, AH                     ; check EMM status
  2426.  JNZ  emm_err_handler            ; jump to error handler
  2427.                                  ; on error
  2428.  MOV  total_open_emm_handles, BX ; save total active handle
  2429.                                  ; count
  2430.  
  2431.  
  2432.  FUNCTION 13  GET HANDLE PAGES
  2433.  
  2434.  PURPOSE
  2435.  
  2436.  The Get Handle Pages function returns the number of pages allocated to a
  2437.  specific EMM handle.
  2438.  
  2439.  CALLING PARAMETERS
  2440.  
  2441.  AH = 4Ch
  2442.    Contains the Get Handle Pages function.
  2443.  
  2444.  DX = emm_handle
  2445.    Contains the EMM handle.
  2446.  
  2447.  RESULTS
  2448.  
  2449.  These results are valid only if the status returned is zero.
  2450.  
  2451.  BX = num_pages_alloc_to_emm_handle
  2452.    Contains the number of logical pages allocated to the specified EMM
  2453.    handle. This number never exceeds 2048 because the memory manager allows a
  2454.    maximum of 2048 pages (32M bytes) of expanded memory.
  2455.  
  2456.  REGISTERS MODIFIED
  2457.  
  2458.  AX, BX
  2459.  
  2460.  STATUS
  2461.  
  2462.  AH = 0        SUCCESSFUL.
  2463.    The manager has returned the number of pages allocated to the EMM handle.
  2464.  
  2465.  AH = 80h      NON-RECOVERABLE.
  2466.    The manager detected a malfunction in the memory manager software.
  2467.  
  2468.  AH = 81h      NON-RECOVERABLE.
  2469.    The manager detected a malfunction in the expanded memory hardware.
  2470.  
  2471.  AH = 83h      NON-RECOVERABLE.
  2472.    The memory manager couldn't find the EMM handle your program specified.
  2473.  
  2474.  AH = 84h      NON-RECOVERABLE.
  2475.    The function code passed to the memory manager is not defined.
  2476.  
  2477.  EXAMPLE
  2478.  
  2479.  emm_handle                      DW  ?
  2480.  pages_alloc_to_handle           DW  ?
  2481.  
  2482.  MOV  DX, emm_handle             ; load EMM handle
  2483.  MOV  AH, 4Ch                    ; load function code
  2484.  INT  67h                        ; call the memory manager
  2485.  OR   AH, AH                     ; check EMM status
  2486.  JNZ  emm_err_handler            ; jump to error handler
  2487.                                  ; on error
  2488.  MOV  pages_alloc_to_handle, BX  ; save number of pages
  2489.                                  ; allocated to specified
  2490.                                  ; handle
  2491.  
  2492.  
  2493.  FUNCTION 14  GET ALL HANDLE PAGES
  2494.  
  2495.  PURPOSE
  2496.  
  2497.  The Get All Handle Pages function returns an array of the open EMM handles
  2498.  and the number of pages allocated to each one.
  2499.  
  2500.  CALLING PARAMETERS
  2501.  
  2502.  AH = 4Dh
  2503.    Contains the Get All Handle Pages function.
  2504.  
  2505.          handle_page_struct         STRUC
  2506.              emm_handle             DW ?
  2507.              pages_alloc_to_handle  DW ?
  2508.          handle_page_struct         ENDS
  2509.  
  2510.  ES:DI = pointer to handle_page
  2511.    Contains a pointer to an array of structures where a copy of all open EMM
  2512.    handles and the number of pages allocated to each will be stored. Each
  2513.    structure has these two members:
  2514.  
  2515.      .emm_handle
  2516.          The first member is a word which contains the value of the open EMM
  2517.          handle. The values of the handles this function returns will be in
  2518.          the range of 0 to 255 decimal (0000h to 00FFh). The uppermost byte
  2519.          of the handle is always zero.
  2520.  
  2521.      .pages_alloc_to_handle
  2522.          The second member is a word which contains the number of pages
  2523.          allocated to the open EMM handle.
  2524.  
  2525.  RESULTS
  2526.  
  2527.  These results are valid only if the status returned is zero.
  2528.  
  2529.  BX = total_open_emm_handles
  2530.    Contains the number of open EMM handles (including the operating system
  2531.    handle [0]). The number cannot be zero because the operating system handle
  2532.    is always active and cannot be deallocated. This number will not exceed
  2533.    255.
  2534.  
  2535.  REGISTERS MODIFIED
  2536.  
  2537.  AX, BX
  2538.  
  2539.  STATUS
  2540.  
  2541.  AH = 0   SUCCESSFUL.
  2542.    The manager has returned the array.
  2543.  
  2544.  AH = 80h   NON-RECOVERABLE.
  2545.    The manager detected a malfunction in the memory manager software.
  2546.  
  2547.  AH = 81h   NON-RECOVERABLE.
  2548.    The manager detected a malfunction in the expanded memory hardware.
  2549.  
  2550.  AH = 84h   NON-RECOVERABLE.
  2551.    The function code passed to the memory manager isn't defined.
  2552.  
  2553.  EXAMPLE
  2554.  
  2555.  handle_page              handle_page_struct 255 DUP (?)
  2556.  total_open_handles            DW  ?
  2557.  
  2558.  
  2559.  MOV   AX, SEG handle_page
  2560.  MOV   ES, AX
  2561.  LEA   DI, handle_page         ; ES:DI points to handle_page
  2562.  MOV   AH, 4Dh                 ; load function code
  2563.  INT   67h                     ; call the memory manager
  2564.  OR    AH, AH                  ; check EMM status
  2565.  JNZ   emm_err_handler         ; jump to error handler on error
  2566.  MOV   total_open_handles, BX  ; save total open handle count
  2567.  
  2568.  
  2569.  FUNCTION 15  GET/SET PAGE MAP Get Page Map Subfunction
  2570.  
  2571.  PURPOSE
  2572.  
  2573.  The Get Page Map subfunction saves the mapping context for all mappable
  2574.  memory regions (conventional and expanded) by copying the contents of the
  2575.  mapping registers from each expanded memory board to a destination array.
  2576.  The application must pass a pointer to the destination array. This
  2577.  subfunction doesn't require an EMM handle.
  2578.  
  2579.  Use this function instead of Functions 8 and 9 if you need to save or
  2580.  restore the mapping context but don't want (or have) to use a handle.
  2581.  
  2582.  CALLING PARAMETERS
  2583.  
  2584.  AX = 4E00h
  2585.    Contains the Get Page Map subfunction.
  2586.  
  2587.  ES:DI = dest_page_map
  2588.    Contains a pointer to the destination array address in segment:offset
  2589.    format. Use the Get Size of Page Map Save Array subfunction to determine
  2590.    the size of the desired array.
  2591.  
  2592.  RESULTS
  2593.  
  2594.  These results are valid only if the status returned is zero.
  2595.  
  2596.  dest_page_map
  2597.    The array contains the state of all the mapping registers on all boards in
  2598.    the system. It also contains any additional information necessary to
  2599.    restore the boards to their original state when the program invokes a Set
  2600.    subfunction.
  2601.  
  2602.  REGISTERS MODIFIED
  2603.  
  2604.  AX
  2605.  
  2606.  STATUS
  2607.  
  2608.  AH = 0        SUCCESSFUL.
  2609.    The manager has returned the array.
  2610.  
  2611.  AH = 80h      NON-RECOVERABLE.
  2612.    The manager detected a malfunction in the memory manager software.
  2613.  
  2614.  AH = 81h      NON-RECOVERABLE.
  2615.    The manager detected a malfunction in the expanded memory hardware.
  2616.  
  2617.  AH = 84h      NON-RECOVERABLE.
  2618.    The function code passed to the memory manager is not defined.
  2619.  
  2620.  AH = 8Fh      NON-RECOVERABLE.
  2621.    The subfunction parameter is invalid.
  2622.  
  2623.  EXAMPLE
  2624.  
  2625.  dest_page_map            DB  ?  DUP  (?)
  2626.  
  2627.  MOV   AX, SEG dest_page_map
  2628.  MOV   ES, AX
  2629.  LEA   DI, dest_page_map  ; ES:DI points to dest_page_map
  2630.  MOV   AX, 4E00h          ; load function code
  2631.  INT   67h                ; call the memory manager
  2632.  OR    AH, AH             ; check EMM status
  2633.  JNZ   emm_err_handler    ; jump to error handler on error
  2634.  
  2635.  
  2636.  FUNCTION 15  Set Page Map Subfunction
  2637.  
  2638.  PURPOSE
  2639.  
  2640.  The Set Page Map subfunction restores the mapping context for all mappable
  2641.  memory regions (conventional and expanded) by copying the contents of a
  2642.  source array into the mapping registers on each expanded memory board in the
  2643.  system. The application must pass a pointer to the source array. This
  2644.  subfunction doesn't require an EMM handle.
  2645.  
  2646.  Use this function instead of Functions 8 and 9 if you need to save or
  2647.  restore the mapping context but don't want (or have) to use a handle.
  2648.  
  2649.  CALLING PARAMETERS
  2650.  
  2651.  AX = 4E01h
  2652.    Contains the Set Page Map subfunction.
  2653.  
  2654.  DS:SI = source_page_map
  2655.    Contains a pointer to the source array address in segment:offset format.
  2656.    The application must point to an array which contains the mapping register
  2657.    state. Use the Get Size of Page Map Save Array subfunction to determine
  2658.    the size of the desired array.
  2659.  
  2660.  REGISTERS MODIFIED
  2661.  
  2662.  AX
  2663.  
  2664.  STATUS
  2665.  
  2666.  AH = 0        SUCCESSFUL.
  2667.    The manager has passed the array.
  2668.  
  2669.  AH = 80h      NON-RECOVERABLE.
  2670.    The manager detected a malfunction in the memory manager software.
  2671.  
  2672.  AH = 81h      NON-RECOVERABLE.
  2673.    The manager detected a malfunction in the expanded memory hardware.
  2674.  
  2675.  AH = 84h      NON-RECOVERABLE.
  2676.    The function code passed to the memory manager is not defined.
  2677.  
  2678.  AH = 8Fh      NON-RECOVERABLE.
  2679.    The subfunction parameter is invalid.
  2680.  
  2681.  AH = A3h      NON-RECOVERABLE. The contents of the source array
  2682.    have been corrupted, or the pointer passed to the subfunction is invalid.
  2683.  
  2684.  EXAMPLE
  2685.  
  2686.  source_page_map            DB  ?  DUP  (?)
  2687.  
  2688.  MOV   AX, SEG source_page_map
  2689.  MOV   DS, AX
  2690.  LEA   SI, source_page_map  ; DS:SI points to source_page_map
  2691.  MOV   AX, 4E01h            ; load function code
  2692.  INT   67h                  ; call the memory manager
  2693.  OR    AH, AH               ; check EMM status
  2694.  JNZ   emm_err_handler      ; jump to error handler on error
  2695.  
  2696.  
  2697.  FUNCTION 15  Get & Set Page Map Subfunction
  2698.  
  2699.  PURPOSE
  2700.  
  2701.  The Get & Set subfunction simultaneously saves a current mapping context and
  2702.  restores a previous mapping context for all mappable memory regions (both
  2703.  conventional and expanded). It first copies the contents of the mapping
  2704.  registers from each expanded memory board in the system into a destination
  2705.  array. (The application must pass a pointer to the destination array.)
  2706.  Then, the subfunction copies the contents of a source array into the mapping
  2707.  registers on each of the expanded memory boards. (The application must pass
  2708.  a pointer to the source array.)
  2709.  
  2710.  Use this function instead of Functions 8 and 9 if you need to save or
  2711.  restore the mapping context but don't want (or have) to use a handle.
  2712.  
  2713.  CALLING PARAMETERS
  2714.  
  2715.  AX = 4E02h
  2716.    Contains the Get & Set Page Map subfunction.
  2717.  
  2718.  ES:DI = dest_page_map
  2719.    Contains a pointer to the destination array address in segment:offset
  2720.    format. The current contents of the map registers will be saved in this
  2721.    array.
  2722.  
  2723.  DS:SI = source_page_map
  2724.    Contains a pointer to the source array address in segment:offset format.
  2725.    The contents of this array will be copied into the map registers. The
  2726.    application must point to an array which contains the mapping register
  2727.    state. This address is required only for the Set or Get and Set
  2728.    subfunctions.
  2729.  
  2730.  RESULTS
  2731.  
  2732.  These results are valid only if the status returned is zero.
  2733.  
  2734.  dest_page_map
  2735.    The array contains the mapping state. It also contains any additional
  2736.    information necessary to restore the original state when the program
  2737.    invokes a Set subfunction.
  2738.  
  2739.  REGISTERS MODIFIED
  2740.  
  2741.  AX
  2742.  
  2743.  STATUS
  2744.  
  2745.  AH = 0        SUCCESSFUL.
  2746.    The manager has returned and passed both arrays.
  2747.  
  2748.  AH = 80h      NON-RECOVERABLE.
  2749.    The manager detected a malfunction in the memory manager software.
  2750.  
  2751.  AH = 81h      NON-RECOVERABLE.
  2752.    The manager detected a malfunction in the expanded memory hardware.
  2753.  
  2754.  AH = 84h      NON-RECOVERABLE.
  2755.    The function code passed to the memory manager is not defined.
  2756.  
  2757.  AH = 8Fh      NON-RECOVERABLE.
  2758.    The subfunction parameter is invalid.
  2759.  
  2760.  AH = A3h      NON-RECOVERABLE. The contents of the source array
  2761.    have been corrupted, or the pointer passed to the subfunction is invalid.
  2762.  
  2763.  EXAMPLE
  2764.  
  2765.  dest_page_map              DB  ?  DUP  (?)
  2766.  
  2767.  source_page_map            DB  ?  DUP  (?)
  2768.  
  2769.  MOV   AX, SEG dest_page_map
  2770.  MOV   ES, AX
  2771.  MOV   AX, SEG source_page_map
  2772.  MOV   DS, AX
  2773.  LEA   DI, dest_page_map    ; ES:DI points to dest_page_map
  2774.  LEA   SI, source_page_map  ; DS:SI points to source_page_map
  2775.  MOV   AX, 4E02h            ; load function code
  2776.  INT   67h                  ; call the memory manager
  2777.  OR    AH, AH               ; check EMM status
  2778.  JNZ   emm_err_handler      ; jump to error handler on error
  2779.  
  2780.  
  2781.  FUNCTION 15  Get Size of Page Map Save Array Subfunction
  2782.  
  2783.  PURPOSE
  2784.  
  2785.  The Get Size of Page Map Save Array subfunction returns the storage
  2786.  requirements for the array passed by the other three subfunctions. This
  2787.  subfunction doesn't require an EMM handle.
  2788.  
  2789.  CALLING PARAMETERS
  2790.  
  2791.  AX = 4E03h
  2792.    Contains the Get Size of Page Map Save Array subfunction. The size of this
  2793.    array depends on how the expanded memory system is configured and how the
  2794.    expanded memory manager is implemented. Therefore, the size must be
  2795.    determined after the memory manager is loaded.
  2796.  
  2797.  RESULTS
  2798.  
  2799.  These results are valid only if the status returned is zero.
  2800.  
  2801.  AL = size_of_array
  2802.    Contains the number of bytes that will be transferred to the memory area
  2803.    an application supplies whenever a program requests the Get, Set, or Get
  2804.    and Set subfunctions.
  2805.  
  2806.  REGISTERS MODIFIED
  2807.  
  2808.  AX
  2809.  
  2810.  STATUS
  2811.  
  2812.  AH = 0        SUCCESSFUL.
  2813.    The manager has returned the array size.
  2814.  
  2815.  AH = 80h      NON-RECOVERABLE.
  2816.    The manager detected a malfunction in the memory manager software.
  2817.  
  2818.  AH = 81h      NON-RECOVERABLE.
  2819.    The manager detected a malfunction in the expanded memory hardware.
  2820.  
  2821.  AH = 84h      NON-RECOVERABLE.
  2822.    The function code passed to the memory manager is not defined.
  2823.  
  2824.  AH = 8Fh      NON-RECOVERABLE.
  2825.    The subfunction parameter is invalid.
  2826.  
  2827.  EXAMPLE
  2828.  
  2829.  size_of_array            DB  ?
  2830.  
  2831.  MOV   AX, 4E03h          ; load function code
  2832.  INT   67h                ; call the memory manager
  2833.  OR    AH, AH             ; check EMM status
  2834.  JNZ   emm_err_handler    ; jump to error handler on error
  2835.  MOV   size_of_array, AL  ; save array size
  2836.  
  2837.  
  2838.  FUNCTION 16  GET/SET PARTIAL PAGE MAP Get Partial Page Map Subfunction
  2839.  
  2840.  PURPOSE
  2841.  
  2842.  The Get Partial Page Map subfunction saves a partial mapping context for
  2843.  specific mappable memory regions in a system. Because this function saves
  2844.  only a subset of the entire mapping context, it uses much less memory for
  2845.  the save area and may be potentially faster than Function 15. The
  2846.  subfunction does this by copying the contents of selected mapping registers
  2847.  from each expanded memory board to a destination array.
  2848.  
  2849.  The application must pass a pair of pointers. The first points to a
  2850.  structure which specifies which mappable segments to save; the second points
  2851.  to the destination array.
  2852.  
  2853.  Use this function instead of Functions 8 and 9 if you need to save or
  2854.  restore the mapping context but don't want (or have) to use a handle.
  2855.  
  2856.  CALLING PARAMETERS
  2857.  
  2858.  AX = 4F00h
  2859.    Contains the Get Partial Page Map subfunction.
  2860.  
  2861.           partial_page_map_struct  STRUC
  2862.           mappable_segment_count   DW  ?
  2863.           mappable_segment         DW  (?)  DUP  (?)
  2864.       partial_page_map_struct      ENDS
  2865.  
  2866.  DS:SI = partial_page_map
  2867.    Contains a pointer to a structure which specifies only those mappable
  2868.    memory regions which are to have their mapping context saved. The
  2869.    structure members are described below.
  2870.  
  2871.      .mappable_segment_count
  2872.          The first member is a word which specifies the number of members in
  2873.          the word array which immediately follows it. This number should not
  2874.          exceed the number of mappable segments in the system.
  2875.  
  2876.      .mappable_segment
  2877.          The second member is a word array which contains the segment
  2878.          addresses of the mappable memory regions whose mapping contexts are
  2879.          to be saved. The segment address must be a mappable segment. Use
  2880.          Function 25 to determine which segments are mappable.
  2881.  
  2882.  ES:DI = dest_array
  2883.    Contains a pointer to the destination array address in Segment:Offset
  2884.    format. To determine the size of the required array, see the Get Size of
  2885.    Partial Page Map Save Array subfunction.
  2886.  
  2887.  RESULTS
  2888.  
  2889.  These results are valid only if the status returned is zero.
  2890.  
  2891.  dest_array
  2892.    The array contains the partial mapping context and any additional
  2893.    information necessary to restore this context to its original state when
  2894.    the program invokes a Set subfunction.
  2895.  
  2896.  REGISTERS MODIFIED
  2897.  
  2898.  AX
  2899.  
  2900.  STATUS
  2901.  
  2902.  AH = 0        SUCCESSFUL.
  2903.    The manager has saved the partial map context.
  2904.  
  2905.  AH = 80h      NON-RECOVERABLE.
  2906.    The manager detected a malfunction in the memory manager software.
  2907.  
  2908.  AH = 81h      NON-RECOVERABLE.
  2909.    The manager detected a malfunction in the expanded memory hardware.
  2910.  
  2911.  AH = 84h      NON-RECOVERABLE.
  2912.    The function code passed to the memory manager is not defined.
  2913.  
  2914.  AH = 8Bh      NON-RECOVERABLE.
  2915.    One of the specified segments is not a mappable segment.
  2916.  
  2917.  AH = 8Fh      NON-RECOVERABLE.
  2918.    The subfunction parameter is invalid.
  2919.  
  2920.  AH = A3h      NON-RECOVERABLE.
  2921.    The contents of the partial page map structure have been corrupted, the
  2922.    pointer passed to the subfunction is invalid, or the
  2923.    mappable_segment_count exceeds the number of mappable segments in the
  2924.    system.
  2925.  
  2926.  EXAMPLE
  2927.  
  2928.  partial_page_map        partial_page_map_struct <>
  2929.  
  2930.  dest_array                   DB ? DUP (?)
  2931.  
  2932.  MOV   AX, SEG partial_page_map
  2933.  MOV   DS, AX
  2934.  LEA   SI, partial_page_map   ; DS:SI points to partial_page_map
  2935.  MOV   AX, SEG dest_array
  2936.  MOV   ES, AX
  2937.  LEA   DI, dest_array         ; ES:DI points to dest_array
  2938.  MOV   AX, 4F00h              ; load function code
  2939.  INT   67h                    ; call the memory manager
  2940.  OR    AH, AH                 ; check EMM status
  2941.  JNZ   emm_err_handler        ; jump to error handler on error
  2942.  
  2943.  
  2944.  FUNCTION 16  Set Partial Page Map Subfunction
  2945.  
  2946.  PURPOSE
  2947.  
  2948.  The Set Partial Page Map subfunction provides a mechanism for restoring the
  2949.  mapping context for a partial mapping context for specific mappable memory
  2950.  regions in a system. Because this function restores only a subset of the
  2951.  entire mapping context and not the entire systems mapping context, it uses
  2952.  much less memory for the save area and is potentially faster than Function
  2953.  15. The subfunction does this by copying the contents of the source array
  2954.  to selected mapping registers on each expanded memory board. The
  2955.  application passes a pointer to the source array.
  2956.  
  2957.  Use this function instead of Functions 8 and 9 if you need to save or
  2958.  restore the mapping context but don't want (or have) to use a handle.
  2959.  
  2960.  CALLING PARAMETERS
  2961.  
  2962.  AX = 4F01h
  2963.    Contains the Set Partial Page Map subfunction.
  2964.  
  2965.              source_array  DB  ?  DUP  (?)
  2966.  
  2967.  DS:SI = source_array
  2968.    Contains a pointer to the source array in segment:offset format. The
  2969.    application must point to an array which contains the partial mapping
  2970.    register state. To determine the size of the required array, see the Get
  2971.    Size of Partial Page Map Save Array subfunction.
  2972.  
  2973.  REGISTERS MODIFIED
  2974.  
  2975.  AX
  2976.  
  2977.  STATUS
  2978.  
  2979.  AH = 0        SUCCESSFUL.
  2980.    The manager has restored the partial mapping context.
  2981.  
  2982.  AH = 80h      NON-RECOVERABLE.
  2983.    The manager detected a malfunction in the memory manager software.
  2984.  
  2985.  AH = 81h      NON-RECOVERABLE.
  2986.    The manager detected a malfunction in the expanded memory hardware.
  2987.  
  2988.  AH = 84h      NON-RECOVERABLE.
  2989.    The function code passed to the memory manager is not defined.
  2990.  
  2991.  AH = 8Fh      NON-RECOVERABLE.
  2992.    The subfunction parameter is invalid.
  2993.  
  2994.  AH = A3h      NON-RECOVERABLE.
  2995.    The contents of the source array have been corrupted, or the pointer
  2996.    passed to the subfunction is invalid.
  2997.  
  2998.  EXAMPLE
  2999.  
  3000.  MOV   AX, SEG source_array
  3001.  MOV   DS, AX
  3002.  LEA   SI, source_array   ; DS:SI points to source_array
  3003.  MOV   AX, 4F01h          ; load function code
  3004.  INT   67h                ; call the memory manager
  3005.  OR    AH, AH             ; check EMM status
  3006.  JNZ   emm_err_handler    ; jump to error handler on error
  3007.  
  3008.  
  3009.  FUNCTION 16  Get Size of Partial Page Map Save Array Subfunction
  3010.  
  3011.  PURPOSE
  3012.  
  3013.  The Return Size subfunction returns the storage requirements for the array
  3014.  passed by the other two subfunctions. This subfunction doesn't require an
  3015.  EMM handle.
  3016.  
  3017.  CALLING PARAMETERS
  3018.  
  3019.  AX = 4F02h
  3020.    Contains the Get Size of Partial Page Map Save Array subfunction. The size
  3021.    of this array depends on the expanded memory system configuration and the
  3022.    implementation of the expanded memory manager. Therefore, it will vary
  3023.    between hardware configurations and implementations and must be determined
  3024.    after a specific memory manager is loaded.
  3025.  
  3026.  BX = number of pages in the partial array
  3027.    Contains the number of pages in the partial map to be saved by the Get/Set
  3028.    Partial Page Map subfunctions. This number should be the same as the
  3029.    mappable_segment_count in the Get Partial Page Map subfunction.
  3030.  
  3031.  RESULTS
  3032.  
  3033.  These results are valid only if the status returned is zero.
  3034.  
  3035.  AL = size_of_partial_save_array
  3036.    Contains the number of bytes that will be transferred to the memory area
  3037.    supplied by an application whenever a program requests the Get or Set
  3038.    subfunction.
  3039.  
  3040.  REGISTERS MODIFIED
  3041.  
  3042.  AX
  3043.  
  3044.  STATUS
  3045.  
  3046.  AH = 0        SUCCESSFUL.
  3047.    The manager has returned the array size.
  3048.  
  3049.  AH = 80h      NON-RECOVERABLE.
  3050.    The manager detected a malfunction in the memory manager software.
  3051.  
  3052.  AH = 81h      NON-RECOVERABLE.
  3053.    The manager detected a malfunction in the expanded memory hardware.
  3054.  
  3055.  AH = 84h      NON-RECOVERABLE.
  3056.    The function code passed to the memory manager is not defined.
  3057.  
  3058.  AH = 8Bh      NON-RECOVERABLE.
  3059.    The number of pages in the partial array is outside the range of physical
  3060.    pages in the system.
  3061.  
  3062.  AH = 8Fh      NON-RECOVERABLE.
  3063.    The subfunction parameter is invalid.
  3064.  
  3065.  EXAMPLE
  3066.  
  3067.  number_of_pages_to_map               DW  ?
  3068.  size_of_partial_save_array           DB  ?
  3069.  
  3070.  MOV  BX, number_of_pages_to_map
  3071.  MOV  AX, 4F02h                       ; load function code
  3072.  INT  67h                             ; call the memory manager
  3073.  OR   AH, AH                          ; check EMM status
  3074.  JNZ  emm_err_handler                 ; jump to error handler
  3075.                                       ; on error
  3076.  MOV  size_of_partial_save_array, AL  ; save array size
  3077.  
  3078.  
  3079.  FUNCTION 17  MAP/UNMAP MULTIPLE HANDLE PAGES
  3080.  
  3081.  PURPOSE
  3082.  
  3083.  This function can, in a single invocation, map (or unmap) logical pages into
  3084.  as many physical pages as the system supports. Consequently, it has less
  3085.  execution overhead than mapping pages one at a time. For applications which
  3086.  do a lot of page mapping, this is the preferred mapping method.
  3087.  
  3088.  Mapping Multiple Pages
  3089.  
  3090.  The handle passed to this function determines what type of logical pages are
  3091.  being mapped. Logical pages that Function 4 and Function 27 (Allocate
  3092.  Standard Pages subfunction) allocate are referred to as pages and are 16K
  3093.  bytes. Logical pages that Function 27 (Allocate Raw Pages subfunction)
  3094.  allocates are referred to as raw pages and might not be the same size as the
  3095.  pages Function 4 and Function 27 (Allocate Standard Pages subfunction)
  3096.  allocate.
  3097.  
  3098.  Unmapping Multiple Pages
  3099.  
  3100.  This function can make specific physical pages unavailable for reading or
  3101.  writing. A logical page which is unmapped from a specific physical page
  3102.  cannot be read or written from that physical page. The logical page which is
  3103.  unavailable (unmapped) can be made available again by mapping it, or a new
  3104.  logical page, at the physical page that was unmapped. Unmapping a physical
  3105.  page is accomplished by setting the logical page it is associated with to
  3106.  FFFFh.
  3107.  
  3108.  You might unmap an entire set of mapped pages, for example, before loading
  3109.  and executing a program. This ensures that the loaded program won't be able
  3110.  to access the pages your program has mapped. However, you must save the
  3111.  mapping context before you unmap the physical pages. This enables you to
  3112.  restore it later so that you may access the memory you had mapped there. You
  3113.  can save the mapping context with Functions 8, 15, or 16. You can restore
  3114.  the mapping context with Functions 9, 15, or 16.
  3115.  
  3116.  Mapping and Unmapping Multiple Pages Simultaneously
  3117.  
  3118.  Both mapping and unmapping pages can be done in the same invocation.
  3119.  
  3120.  Mapping or unmapping no pages is not considered an error. If a request to
  3121.  map or unmap zero pages is made, nothing is done and no error is returned.
  3122.  
  3123.  Alternate Mapping and Unmapping Methods
  3124.  
  3125.  You can map or unmap pages using two methods. Both methods produce identical
  3126.  results.
  3127.  
  3128.      1.  The first method specifies both a logical page and a physical page
  3129.          at which the logical page is to be mapped. This method is an
  3130.          extension of Function 5 (Map Handle Page).
  3131.  
  3132.      2.  The second method specifies both a logical page and a corresponding
  3133.          segment address at which the logical page is to be mapped. While
  3134.          this is functionally the same as the first method, it may be easier
  3135.          to use the actual segment address of a physical page than to use a
  3136.          number which only represents its location. The memory manager
  3137.          verifies whether the specified segment address falls on the boundary
  3138.          of a mappable physical page. The manager then translates the segment
  3139.          address passed to it into the necessary internal representation to
  3140.          map the pages.
  3141.  
  3142.  
  3143.  FUNCTION 17  Logical Page/Physical Page Method
  3144.  
  3145.  CALLING PARAMETERS
  3146.  
  3147.  AX = 5000h
  3148.    Contains the Map/Unmap Multiple Handle Pages subfunction using the logical
  3149.    page/physical page method.
  3150.  
  3151.          log_to_phys_map_struct STRUC
  3152.              log_page_number    DW  ?
  3153.              phys_page_number   DW  ?
  3154.          log_to_phys_map_struct ENDS
  3155.  
  3156.  DX = handle
  3157.    Contains the EMM handle.
  3158.  
  3159.  CX = log_to_phys_map_len
  3160.    Contains the number of entries in the array. For example, if the array
  3161.    contained four pages to map or unmap, then CX would contain 4. The number
  3162.    in CX should not exceed the number of mappable pages in the system.
  3163.  
  3164.  DS:SI = pointer to log_to_phys_map array
  3165.    Contains a pointer to an array of structures that contains the information
  3166.    necessary to map the desired pages. The array is made up of the following
  3167.    two elements:
  3168.  
  3169.      .log_page_number
  3170.          The first member is a word which contains the number of the logical
  3171.          page which is to be mapped. Logical pages are numbered zero
  3172.          relative, so the number for a logical page can only range from zero
  3173.          to (maximum number of logical pages allocated to the handle - 1).
  3174.  
  3175.          If the logical page number is set to FFFFh, the physical page
  3176.          associated with it is unmapped rather than mapped. Unmapping a
  3177.          physical page makes it inaccessible for reading or writing.
  3178.  
  3179.      .phys_page_number
  3180.          The second member is a word which contains the number of the
  3181.          physical page at which the logical page is to be mapped. Physical
  3182.          pages are numbered zero relative, so the number for a physical page
  3183.          can only range from zero to (maximum number of physical pages
  3184.          supported in the system - 1).
  3185.  
  3186.  REGISTERS MODIFIED
  3187.  
  3188.  AX
  3189.  
  3190.  STATUS
  3191.  
  3192.  AH = 0        SUCCESSFUL.
  3193.    The logical pages have been mapped, or unmapped, at the specified physical
  3194.    pages.
  3195.  
  3196.  AH = 80h      NON-RECOVERABLE.
  3197.    The manager has detected a malfunction in the memory manager software.
  3198.  
  3199.  AH = 81h      NON-RECOVERABLE.
  3200.    The manager has detected a malfunction in the expanded memory hardware.
  3201.  
  3202.  AH = 83h      NON-RECOVERABLE.
  3203.    The manager couldn't find the specified EMM handle. The manager doesn't
  3204.    currently have any information pertaining to the specified EMM handle. The
  3205.    program has probably corrupted its EMM handle.
  3206.  
  3207.  AH = 84h      NON-RECOVERABLE.
  3208.    The function code passed to the manager is not defined.
  3209.  
  3210.  AH = 8Ah      RECOVERABLE.
  3211.    One or more of the mapped logical pages is out of the range of logical
  3212.    pages allocated to the EMM handle. The program can recover by attempting
  3213.    to map a logical page which is within the bounds for the specified EMM
  3214.    handle. When this error occurs, the only pages mapped were the ones valid
  3215.    up to the point that the error occurred.
  3216.  
  3217.  AH = 8Bh      RECOVERABLE.
  3218.    One or more of the physical pages is out of the range of mappable physical
  3219.    pages, or the log_to_phy_map_len exceeds the number of mappable pages in
  3220.    the system. The program can recover from this condition by attempting to
  3221.    map into memory at a physical page which is in the range of the physical
  3222.    page numbers supported by the system. When this error occurs, the only
  3223.    pages mapped were the ones valid up to the point that the error occurred.
  3224.  
  3225.  AH = 8Fh      NON-RECOVERABLE.
  3226.    The subfunction parameter is invalid.
  3227.  
  3228.  EXAMPLE
  3229.  
  3230.  log_to_phys_map            log_to_phys_map_struct ? DUP (?)
  3231.  
  3232.  emm_handle                        DW ?
  3233.  
  3234.  MOV   AX, SEG log_to_phys_map
  3235.  MOV   DS, AX
  3236.  LEA   SI, log_to_phys_map         ; DS:SI points to
  3237.                                    ; log_to_phys_map
  3238.  MOV   CX, LENGTH log_to_phys_map  ; set length field
  3239.  MOV   DX, emm_handle
  3240.  MOV   AX, 5000h                   ; load function code
  3241.  INT   67h                         ; call the memory manager
  3242.  OR    AH, AH                      ; check EMM status
  3243.  JNZ   emm_err_handler             ; jump to error handler on
  3244.                                    ; error
  3245.  
  3246.  
  3247.  FUNCTION 17  Logical Page/Segment Address Method
  3248.  
  3249.  CALLING PARAMETERS
  3250.  
  3251.  AX = 5001h
  3252.    Contains the Map/Unmap Multiple Handle Pages subfunction using the logical
  3253.    page/segment address method.
  3254.  
  3255.          log_to_seg_map_struct        STRUC
  3256.              log_page_number          DW  ?
  3257.              mappable_segment_address DW  ?
  3258.          log_to_seg_map_struct        ENDS
  3259.  
  3260.  DX = handle
  3261.    Contains the EMM handle.
  3262.  
  3263.  CX = log_to_segment_map_len
  3264.    Contains the number of entries in the array. For example, if the array
  3265.    contained four pages to map or unmap, then CX would contain four.
  3266.  
  3267.  DS:SI = pointer to log_to_segment_map array
  3268.    Contains a pointer to an array of structures that contains the information
  3269.    necessary to map the desired pages. The array is made up of the following
  3270.    elements:
  3271.  
  3272.      .log_page_number
  3273.          The first member is a word which contains the number of the logical
  3274.          pages to be mapped. Logical pages are numbered zero relative, so the
  3275.          number for a logical page can range from zero to (maximum number of
  3276.          logical pages allocated to the handle - 1).
  3277.  
  3278.          If the logical page number is set to FFFFh, the physical page
  3279.          associated with it is unmapped rather than mapped. Unmapping a
  3280.          physical page makes it inaccessible for reading or writing.
  3281.  
  3282.      .mappable_segment_address
  3283.          The second member is a word which contains the segment address at
  3284.          which the logical page is to be mapped. This segment address must
  3285.          correspond exactly to a mappable segment address. The mappable
  3286.          segment addresses are available with Function 25 (Get Mappable
  3287.          Physical Address Array)
  3288.  
  3289.  REGISTERS MODIFIED
  3290.  
  3291.  AX
  3292.  
  3293.  STATUS
  3294.  
  3295.  AH = 0        SUCCESSFUL.
  3296.    The logical pages have been mapped (or unmapped), at the specified
  3297.    physical pages.
  3298.  
  3299.  AH = 80h      NON-RECOVERABLE.
  3300.    The manager has detected a malfunction in the memory manager software.
  3301.  
  3302.  AH = 81h      NON-RECOVERABLE.
  3303.    The manager has detected a malfunction in the expanded memory hardware.
  3304.  
  3305.  AH = 83h      NON-RECOVERABLE.
  3306.    The manager could not find the specified EMM handle. The manager doesn't
  3307.    have any information pertaining to the specified EMM handle. The program
  3308.    has probably corrupted its EMM handle.
  3309.  
  3310.  AH = 84h      NON-RECOVERABLE.
  3311.    The function code passed to the manager is not defined.
  3312.  
  3313.  AH = 8Ah      RECOVERABLE.
  3314.    One or more of the logical pages to be mapped is out of the range of
  3315.    logical pages allocated to the EMM handle. The program can recover from
  3316.    this condition by mapping a logical page which is within the bounds for
  3317.    the specified EMM handle. When this error occurs, the only pages mapped or
  3318.    unmapped were the ones valid up to the point that the error occurred.
  3319.  
  3320.  AH = 8Bh      RECOVERABLE.
  3321.    One or more of the mappable segment addresses specified is not mappable,
  3322.    the segment address doesn't fall exactly on a mappable address boundary,
  3323.    or the log_to_segment_map_len exceeds the number of mappable segments in
  3324.    the system. The program can recover from this condition by mapping into
  3325.    memory on an exact mappable segment address. When this error occurs, the
  3326.    only pages mapped were the ones valid up to the point that the error
  3327.    occurred.
  3328.  
  3329.  AH = 8Fh      NON-RECOVERABLE.
  3330.    The subfunction parameter is invalid.
  3331.  
  3332.  EXAMPLE
  3333.  
  3334.  log_to_seg_map            log_to_seg_map_struct 4 DUP (?)
  3335.  
  3336.  emm_handle                      DW ?
  3337.  
  3338.  MOV  AX, SEG log_to_seg_map
  3339.  MOV  DS, AX
  3340.  LEA  SI, log_to_seg_map         ; DS:SI points to
  3341.                                  ; log_to_seg_map
  3342.  MOV  CX, LENGTH log_to_seg_map
  3343.  MOV  DX, emm_handle
  3344.  MOV  AX, 5001h                  ; load function code
  3345.  INT  67h                        ; call the memory manager
  3346.  OR   AH, AH                     ; check EMM status
  3347.  JNZ  emm_err_handler            ; jump to error handler
  3348.                                  ; on error
  3349.  
  3350.  
  3351.  FUNCTION 18  REALLOCATE PAGES
  3352.  
  3353.  PURPOSE
  3354.  
  3355.  This function allows an application program to increase or decrease
  3356.  (reallocate) the number of logical pages allocated to an EMM handle. There
  3357.  are four reallocation cases of interest:
  3358.  
  3359.      1.  A reallocation count of zero. The handle assigned to
  3360.          application remains assigned and is still available for use by the
  3361.          application. The memory manager won't reassign the handle to any
  3362.          other application. However, the handle will have any currently
  3363.          allocated pages returned to the memory manager. The application must
  3364.          invoke the Deallocate Pages function (Function 6) before returning
  3365.          to DOS, or the handle will remain assigned and no other application
  3366.          will be able to use it.
  3367.  
  3368.      2.  A reallocation count equal to the current allocation count.
  3369.          This is not treated as an error, and a SUCCESSFUL status is
  3370.          returned.
  3371.  
  3372.      3.  A reallocation count greater than the current allocation
  3373.          count. The memory manager will attempt to add new pages to
  3374.          those pages already allocated to the specified EMM handle. The
  3375.          number of new pages added is the difference between the reallocation
  3376.          count and the current allocation count. The sequence of logical
  3377.          pages allocated to the EMM handle remains continuous after this
  3378.          operation. The newly allocated pages have logical page numbers which
  3379.          begin where the previously allocated pages ended, and continue in
  3380.          ascending sequence.
  3381.  
  3382.      4.  A reallocation count less than the current allocation count.
  3383.          The memory manager will attempt to subtract some of the currently
  3384.          allocated pages and return them to the memory manager. The number of
  3385.          old pages subtracted is the difference between the current
  3386.          allocation count and the re-allocation count. The pages are
  3387.          subtracted from the end of the sequence of pages currently allocated
  3388.          to the specified EMM handle. The sequence of logical pages allocated
  3389.          to the EMM handle remains continuous after this operation.
  3390.  
  3391.  The handle determines what type of logical pages are being reallocated.
  3392.  Logical pages which were originally allocated with Function 4 or Function
  3393.  27 (Allocate Standard Pages subfunction) are called pages and are 16K
  3394.  bytes long. Logical pages which were allocated with Function 27 (Allocate
  3395.  Raw Pages subfunction) are called raw pages and might not be the same size
  3396.  as pages allocated with Function 4 or Function 27 (Allocate Standard Pages
  3397.  subfunction).
  3398.  
  3399.  CALLING PARAMETERS
  3400.  
  3401.  AH = 51h
  3402.    Contains the Reallocate Handle Pages function.
  3403.  
  3404.  DX = handle
  3405.    Contains the EMM handle.
  3406.  
  3407.  BX = reallocation_count
  3408.    Contains the total number of pages this handle should have allocated to it
  3409.    after this function is invoked.
  3410.  
  3411.  RESULTS
  3412.  
  3413.  These results are valid only if the status returned is zero.
  3414.  
  3415.  BX = number of pages allocated to handle after reallocation
  3416.    Contains the number of pages now allocated to the EMM handle after the
  3417.    pages have been added or subtracted. If the status returned is not zero,
  3418.    the value in BX is equal to the number of pages allocated to the handle
  3419.    prior to the invocation of this function. This information can be used to
  3420.    verify that the request generated the expected results.
  3421.  
  3422.  REGISTERS MODIFIED
  3423.  
  3424.  AX, BX
  3425.  
  3426.  STATUS
  3427.  
  3428.  AH = 00h      SUCCESSFUL.
  3429.    The pages specified have been added or subtracted to or from the handle
  3430.    specified.
  3431.  
  3432.  AH = 80h      NON-RECOVERABLE.
  3433.    The manager has detected a malfunction in the memory manager software.
  3434.  
  3435.  AH = 81h      NON-RECOVERABLE.
  3436.    The manager has detected a malfunction in the expanded memory hardware.
  3437.  
  3438.  AH = 83h      NON-RECOVERABLE.
  3439.    The manager could not find the specified EMM handle. The manager doesn't
  3440.    have any information pertaining to the specified EMM handle. The program
  3441.    may have corrupted its EMM handle.
  3442.  
  3443.  AH = 84h      NON-RECOVERABLE.
  3444.    The function code passed to the manager is not defined.
  3445.  
  3446.  AH = 87h      RECOVERABLE.
  3447.    The number of pages that are available in the system is insufficient for
  3448.    the new allocation request. The program can recover from this condition by
  3449.    specifying fewer pages be allocated to the EMM handle.
  3450.  
  3451.  AH = 88h      RECOVERABLE.
  3452.    The number of unallocated pages is insufficient for the new allocation
  3453.    request. The program can recover from this condition by either requesting
  3454.    again when additional pages are available or specifying fewer pages.
  3455.  
  3456.  EXAMPLE
  3457.  
  3458.  emm_handle                    DW   ?
  3459.  realloc_count                 DW   ?
  3460.  current_alloc_page_count      DW   ?
  3461.  
  3462.  MOV   DX, emm_handle          ; specify EMM handle
  3463.  MOV   BX, realloc_count       ; specify count
  3464.  MOV   AH, 51h                 ; load function code
  3465.  INT   67h                     ; call the memory manager
  3466.  OR    AH, AH                  ; check EMM status
  3467.  JNZ   emm_err_handler         ; jump to error handler
  3468.                                ; on error
  3469.  MOV   current_alloc_page_count, BX
  3470.  
  3471.  
  3472.  FUNCTION 19  GET/SET HANDLE ATTRIBUTE
  3473.  
  3474.  DESIGN CONSIDERATIONS
  3475.  
  3476.  This function is an option which will probably not be available in a typical
  3477.  expanded memory manager, system, or memory board. Most personal computer
  3478.  systems disable memory refresh signals for a considerable period during a
  3479.  warm boot. This can corrupt some of the data in memory boards, even though
  3480.  there is no problem with the design of the memory board, its operation, or
  3481.  the memory chips. This memory refresh deficiency is present in the software
  3482.  design of the ROM BIOS in most personal computer systems.
  3483.  
  3484.  The majority of memory board designs, chip types, or personal computer
  3485.  systems won't be able to support the non-volatility feature. The reason that
  3486.  this ROM BIOS deficiency is not evident in the conventional or extended
  3487.  memory area is that the ROM BIOS always initializes this area during a warm
  3488.  boot. Memory data integrity is not a problem with the conventional or
  3489.  extended memory region, because it isn't physically possible to have data
  3490.  retained there across a warm boot event──the ROM BIOS sets it to zero.
  3491.  
  3492.  Consequently, expanded memory board manufacturers should not supply this
  3493.  function unless their board can guarantee the integrity of data stored in
  3494.  the board's memory during a warm boot. Generally, this means the memory
  3495.  board has an independent memory refresh controller which does not depend on
  3496.  the system board's memory refresh.
  3497.  
  3498.  If the expanded memory manager, system, or memory board cannot support this
  3499.  feature, it should return the not supported status described in the
  3500.  function.
  3501.  
  3502.  
  3503.  FUNCTION 19  Get Handle Attribute Subfunction
  3504.  
  3505.  PURPOSE
  3506.  
  3507.  This subfunction returns the attribute associated with a handle. The
  3508.  attributes are volatile or non-volatile. Handles with non-volatile
  3509.  attributes enable the memory manager to save the contents of a handle's
  3510.  pages between warm boots. However, this function may be disabled with a user
  3511.  option or may not be supported by the memory board or system hardware.
  3512.  
  3513.  If the handle's attribute has been set to non-volatile, the handle, its name
  3514.  (if it is assigned one), and the contents of the pages allocated to the
  3515.  handle are all maintained after a warm boot.
  3516.  
  3517.  CALLING PARAMETERS
  3518.  
  3519.  AX = 5200h
  3520.    Contains the Get Handle Attribute subfunction.
  3521.  
  3522.  DX = handle
  3523.    Contains the EMM handle.
  3524.  
  3525.  RESULTS
  3526.  
  3527.  These results are valid only if the status returned is zero.
  3528.  
  3529.  AL = handle attribute
  3530.    Contains the EMM handle's attribute. The only attributes a handle may have
  3531.    are volatile or non-volatile. A value of zero indicates the handle is
  3532.    volatile. A value of one indicates that the handle is non-volatile.
  3533.  
  3534.  REGISTERS MODIFIED
  3535.  
  3536.  AX
  3537.  
  3538.  STATUS
  3539.  
  3540.  AH = 0        SUCCESSFUL.
  3541.    The handles attribute has been obtained.
  3542.  
  3543.  AH = 80h      NON-RECOVERABLE.
  3544.    The manager has detected a malfunction in the memory manager software.
  3545.  
  3546.  AH = 81h      NON-RECOVERABLE.
  3547.    The manager has detected a malfunction in the expanded memory hardware.
  3548.  
  3549.  AH = 83h      NON-RECOVERABLE.
  3550.    The manager couldn't find the specified EMM handle. The manager doesn't
  3551.    have any information pertaining to the specified EMM handle. The program
  3552.    may have corrupted its EMM handle.
  3553.  
  3554.  AH = 84h      NON-RECOVERABLE.
  3555.    The function code passed to the manager is not defined.
  3556.  
  3557.  AH = 8Fh      NON-RECOVERABLE.
  3558.    The subfunction parameter is invalid.
  3559.  
  3560.  AH = 91h      NON-RECOVERABLE.
  3561.    This feature is not supported.
  3562.  
  3563.  EXAMPLE
  3564.  
  3565.  emm_handle               DW   ?
  3566.  handle_attrib            DB   ?
  3567.  
  3568.  MOV   DX, emm_handle     ; specify EMM handle
  3569.  MOV   AX, 5200h          ; load function code
  3570.  INT   67h                ; call the memory manager
  3571.  OR    AH, AH             ; check EMM status
  3572.  JNZ   emm_err_handler    ; jump to error handler on error
  3573.  MOV   handle_attrib, AL  ; save handle attribute
  3574.  
  3575.  
  3576.  FUNCTION 19  Set Handle Attribute Subfunction
  3577.  
  3578.  PURPOSE
  3579.  
  3580.  This subfunction can be used to modify the attribute which a handle has
  3581.  associated with it. The attributes which a handle may have are volatile or
  3582.  non-volatile. The non-volatile attribute enables the EMM to save the
  3583.  contents of a handle's pages between warm boots. However, this function may
  3584.  be disabled with a user option or may not be supported by the memory board
  3585.  or system hardware.
  3586.  
  3587.  If the handle's attribute has been set to non-volatile, the handle, its name
  3588.  (if it is assigned one), and the contents of the pages allocated to the
  3589.  handle are all maintained after a warm boot.
  3590.  
  3591.  CALLING PARAMETERS
  3592.  
  3593.  AX = 5201h
  3594.    Contains the Set Handle Attribute function.
  3595.  
  3596.  DX = handle
  3597.    Contains the EMM handle.
  3598.  
  3599.  BL = new handle attribute
  3600.    Contains the handle's new attribute. A value of zero indicates that the
  3601.    handle should be made volatile. A value of one indicates that the handle
  3602.    should be made non-volatile.
  3603.  
  3604.    A volatile handle attribute instructs the memory manager to deallocate
  3605.    both the handle and the pages allocated to it after a warm boot. If all
  3606.    handles have the volatile attribute (the default attribute) at warm boot,
  3607.    the handle directory will be empty and all of expanded memory will be
  3608.    initialized to zero immediately after a warm boot.
  3609.  
  3610.  REGISTERS MODIFIED
  3611.  
  3612.  AX
  3613.  
  3614.  STATUS
  3615.  
  3616.  AH = 0        SUCCESSFUL.
  3617.    The handles attribute has been modified.
  3618.  
  3619.  AH = 80h      NON-RECOVERABLE.
  3620.    The manager has detected a malfunction in the memory manager software.
  3621.  
  3622.  AH = 81h      NON-RECOVERABLE.
  3623.    The manager has detected a malfunction in the expanded memory hardware.
  3624.  
  3625.  AH = 83h      NON-RECOVERABLE.
  3626.    The manager could not find the specified EMM handle. The manager doesn't
  3627.    have any information pertaining to the specified EMM handle. The program
  3628.    may have corrupted its EMM handle.
  3629.  
  3630.  AH = 84h      NON-RECOVERABLE.
  3631.    The function code passed to the manager is not defined.
  3632.  
  3633.  AH = 8Fh      NON-RECOVERABLE.
  3634.    The subfunction parameter is invalid.
  3635.  
  3636.  AH = 90h      NON-RECOVERABLE.
  3637.    The attribute type is undefined.
  3638.  
  3639.  AH = 91h      NON-RECOVERABLE.
  3640.    This feature is not supported.
  3641.  
  3642.  EXAMPLE
  3643.  
  3644.  emm_handle                   DW   ?
  3645.  new_handle_attrib            DB   ?
  3646.  
  3647.  MOV   DX, emm_handle         ; specify EMM handle
  3648.  MOV   BL, new_handle_attrib  ; specify the set attribute
  3649.  MOV   AX, 5201h              ; load function code
  3650.  INT   67h                    ; call the memory manager
  3651.  OR    AH, AH                 ; check EMM status
  3652.  JNZ   emm_err_handler        ; jump to error handler on error
  3653.  
  3654.  
  3655.  FUNCTION 19  Get Attribute Capability Subfunction
  3656.  
  3657.  PURPOSE
  3658.  
  3659.  This subfunction can be used to determine whether the memory manager can
  3660.  support the non-volatile attribute.
  3661.  
  3662.  CALLING PARAMETERS
  3663.  
  3664.  AX = 5202h
  3665.    Contains the Get Attribute Capability subfunction.
  3666.  
  3667.  RESULTS
  3668.  
  3669.  These results are valid only if the status returned is zero.
  3670.  
  3671.  AL = attribute capability
  3672.    Contains the attribute capability. A value of zero indicates that the
  3673.    memory manager and hardware supports only volatile handles. A value of one
  3674.    indicates that the memory manager/hardware supports both volatile and non-
  3675.    volatile handles.
  3676.  
  3677.  REGISTERS MODIFIED
  3678.  
  3679.  AX
  3680.  
  3681.  STATUS
  3682.  
  3683.  AH = 0        SUCCESSFUL.
  3684.    The attribute capability has been returned.
  3685.  
  3686.  AH = 80h      NON-RECOVERABLE.
  3687.    The manager has detected a malfunction in the memory manager software.
  3688.  
  3689.  AH = 81h      NON-RECOVERABLE.
  3690.    The manager has detected a malfunction in the expanded memory hardware.
  3691.  
  3692.  AH = 84h      NON-RECOVERABLE.
  3693.    The function code passed to the manager is not defined.
  3694.  
  3695.  AH = 8Fh      NON-RECOVERABLE.
  3696.    The subfunction parameter is invalid.
  3697.  
  3698.  EXAMPLE
  3699.  
  3700.  attrib_capability            DB  ?
  3701.  
  3702.  MOV   AX, 5202h              ; load function code
  3703.  INT   67h                    ; call the memory manager
  3704.  OR    AH, AH                 ; check EMM status
  3705.  JNZ   emm_err_handler        ; jump to error handler on error
  3706.  MOV   attrib_capability, AL  ; save attribute capability
  3707.  
  3708.  
  3709.  FUNCTION 20  GET/SET HANDLE NAME Get Handle Name Subfunction
  3710.  
  3711.  PURPOSE
  3712.  
  3713.  This subfunction gets the eight character name currently assigned to a
  3714.  handle. There is no restriction on the characters which may be used in the
  3715.  handle name (that is, anything from 00h through FFh).
  3716.  
  3717.  The handle name is initialized to ASCII nulls (binary zeros) three times:
  3718.  when the memory manager is installed, when a handle is allocated, and when a
  3719.  handle is deallocated. A handle with a name which is all ASCII nulls, by
  3720.  definition, has no name. When a handle is assigned a name, at least one
  3721.  character in the name must be a non-null character in order to distinguish
  3722.  it from a handle without a name.
  3723.  
  3724.  CALLING PARAMETERS
  3725.  
  3726.  AX = 5300h
  3727.    Contains the Get Handle Name function.
  3728.  
  3729.  DX = handle number
  3730.    Contains the EMM handle.
  3731.  
  3732.  ES:DI = pointer to handle_name array
  3733.    Contains a pointer to an eight-byte array into which the name currently
  3734.    assigned to the handle will be copied.
  3735.  
  3736.  RESULTS
  3737.  
  3738.  These results are valid only if the status returned is zero.
  3739.  
  3740.  handle_name array
  3741.    Contains the name associated with the specified handle.
  3742.  
  3743.  REGISTERS MODIFIED
  3744.  
  3745.  AX
  3746.  
  3747.  STATUS
  3748.  
  3749.  AH = 0        SUCCESSFUL.
  3750.    The handle name has been returned.
  3751.  
  3752.  AH = 80h      NON-RECOVERABLE.
  3753.    The manager has detected a malfunction in the memory manager software.
  3754.  
  3755.  AH = 81h      NON-RECOVERABLE.
  3756.    The manager has detected a malfunction in the expanded memory hardware.
  3757.  
  3758.  AH = 83h      NON-RECOVERABLE.
  3759.    The manager couldn't find the specified EMM handle. The manager doesn't
  3760.    have any information on the specified EMM handle. The program may have
  3761.    corrupted its EMM handle.
  3762.  
  3763.  AH = 84h      NON-RECOVERABLE.
  3764.    The function code passed to the manager is not defined.
  3765.  
  3766.  AH = 8Fh      NON-RECOVERABLE.
  3767.    The subfunction parameter is invalid.
  3768.  
  3769.  EXAMPLE
  3770.  
  3771.  handle_name              DB 8 DUP (?)
  3772.  emm_handle               DW   ?
  3773.  
  3774.  
  3775.  MOV   AX, SEG handle_name
  3776.  MOV   ES, AX
  3777.  LEA   DI, handle_name    ; ES:DI points to handle_name
  3778.  MOV   DX, emm_handle     ; specify EMM handle
  3779.  MOV   AX, 5300h          ; load function code
  3780.  INT   67h                ; call the memory manager
  3781.  OR    AH, AH             ; check EMM status
  3782.  JNZ   emm_err_handler    ; jump to error handler on error
  3783.  
  3784.  
  3785.  FUNCTION 20  Set Handle Name Subfunction
  3786.  
  3787.  PURPOSE
  3788.  
  3789.  This subfunction assigns an eight character name to a handle. There is no
  3790.  restriction on the characters which may be used in the handle name. The full
  3791.  range of values may be assigned to each character in a name (that is, 00h
  3792.  through FFh).
  3793.  
  3794.  At installation, all handles have their name initialized to ASCII nulls
  3795.  (binary zeros). A handle with a name consisting of all ASCII nulls has no
  3796.  name. When a handle is assigned a name, at least one character in the name
  3797.  must be a non-null character in order to distinguish it from a handle
  3798.  without a name. No two handles may have the same name.
  3799.  
  3800.  A handle can be renamed at any time by setting the handles name to a new
  3801.  value. A handle can have its name removed by setting the handle's name to
  3802.  all ASCII nulls. When a handle is deallocated, its name is removed (set to
  3803.  ASCII nulls).
  3804.  
  3805.  CALLING PARAMETERS
  3806.  
  3807.  AX = 5301h
  3808.    Contains the Set Handle Name function.
  3809.  
  3810.  DX = handle number
  3811.    Contains the EMM handle.
  3812.  
  3813.  DS:SI = pointer to handle_name
  3814.    Contains a pointer to a byte array which contains the name that is to be
  3815.    assigned to the handle. The handle name must be padded with nulls if the
  3816.    name is less than eight characters long.
  3817.  
  3818.  REGISTERS MODIFIED
  3819.  
  3820.  AX
  3821.  
  3822.  STATUS
  3823.  
  3824.  AH = 0        SUCCESSFUL.
  3825.    The handle name has been assigned.
  3826.  
  3827.  AH = 80h      NON-RECOVERABLE.
  3828.    The manager has detected a malfunction in the memory manager software.
  3829.  
  3830.  AH = 81h      NON-RECOVERABLE.
  3831.    The manager has detected a malfunction in the expanded memory hardware.
  3832.  
  3833.  AH = 83h      NON-RECOVERABLE.
  3834.    The manager couldn't find the specified EMM handle. The manager doesn't
  3835.    currently have any information pertaining to the specified EMM handle. The
  3836.    program may have corrupted its EMM handle.
  3837.  
  3838.  AH = 84h      NON-RECOVERABLE.
  3839.    The function code passed to the manager is not defined.
  3840.  
  3841.  AH = 8Fh      NON-RECOVERABLE.
  3842.    The subfunction parameter is invalid.
  3843.  
  3844.  AH = A1h      RECOVERABLE.
  3845.    A handle with this name already exists. The specified handle was not
  3846.    assigned a name.
  3847.  
  3848.  EXAMPLE
  3849.  
  3850.  handle_name              DB "AARDVARK"
  3851.  emm_handle               DW   ?
  3852.  
  3853.  MOV   AX, SEG handle_name
  3854.  MOV   DS, AX
  3855.  LEA   SI, handle_name    ; DS:SI points to handle_name
  3856.  MOV   DX, emm_handle     ; specify EMM handle
  3857.  MOV   AX, 5301h          ; load function code
  3858.  INT   67h                ; call the memory manager
  3859.  OR    AH, AH             ; check EMM status
  3860.  JNZ   emm_err_handler    ; jump to error handler on error
  3861.  
  3862.  
  3863.  FUNCTION 21  GET HANDLE DIRECTORY Get Handle Directory Subfunction
  3864.  
  3865.  PURPOSE
  3866.  
  3867.  This function returns an array which contains all active handles and the
  3868.  names associated with each. Handles which have not been assigned names have
  3869.  a default name of all ASCII nulls (binary zeros). When a handle is first
  3870.  allocated, or when all the pages belonging to a handle are deallocated (that
  3871.  is, an open handle is closed), its default name is set to ASCII nulls. It
  3872.  takes a subsequent assignment of a name for a handle to have a name after it
  3873.  has been opened. The full range of values may be assigned to each character
  3874.  in a name (that is, 00h through FFh).
  3875.  
  3876.  The number of bytes required by the array is:
  3877.  
  3878.                10 bytes * total number of handles
  3879.  
  3880.  The maximum size of this array is:
  3881.  
  3882.                (10 bytes/entry) * 255 entries = 2550 bytes.
  3883.  
  3884.  CALLING PARAMETERS
  3885.  
  3886.  AX = 5400h
  3887.    Contains the Get Handle Directory function.
  3888.  
  3889.          handle_dir_struct       STRUC
  3890.               handle_value       DW  ?
  3891.               handle_name        DB  8  DUP  (?)
  3892.          handle_dir_struct       ENDS
  3893.  
  3894.  ES:DI = pointer to handle_dir
  3895.    Contains a pointer to an area of memory into which the memory manager will
  3896.    copy the handle directory. The handle directory is an array of structures.
  3897.    There are as many entries in the array as there are open EMM handles. The
  3898.    structure consists of the following elements:
  3899.  
  3900.      .handle_value
  3901.          The first member is a word which contains the value of the open EMM
  3902.          handle.
  3903.  
  3904.      .handle_name
  3905.          The second member is an 8 byte array which contains the ASCII name
  3906.          associated with the EMM handle. If there is no name currently
  3907.          associated with the handle, it has a value of all zeros (ASCII
  3908.          nulls).
  3909.  
  3910.  RESULTS
  3911.  
  3912.  These results are valid only if the status returned is zero.
  3913.  
  3914.  handle_dir
  3915.    Contains the handle values and handle names associated with each handle
  3916.    value.
  3917.  
  3918.  AL = number of entries in the handle_dir array
  3919.    Contains the number of entries in the handle directory array. This is also
  3920.    the same as the number of open handles. For example, if only one handle is
  3921.    active, AL will contain a one.
  3922.  
  3923.  REGISTERS MODIFIED
  3924.  
  3925.  AX
  3926.  
  3927.  STATUS
  3928.  
  3929.  AH = 0        SUCCESSFUL.
  3930.    The handle directory has been returned.
  3931.  
  3932.  AH = 80h      NON-RECOVERABLE.
  3933.    The manager has detected a malfunction in the memory manager software.
  3934.  
  3935.  AH = 81h      NON-RECOVERABLE.
  3936.    The manager has detected a malfunction in the expanded memory hardware.
  3937.  
  3938.  AH = 84h      NON-RECOVERABLE.
  3939.    The function code passed to the manager is not defined.
  3940.  
  3941.  AH = 8Fh      NON-RECOVERABLE.
  3942.    The subfunction parameter is invalid.
  3943.  
  3944.  EXAMPLE
  3945.  
  3946.  handle_dir                 handle_dir_struct 255 DUP (?)
  3947.  
  3948.  num_entries_in_handle_dir          DB ?
  3949.  
  3950.  MOV  AX, SEG handle_dir
  3951.  MOV  ES, AX
  3952.  LEA  DI, handle_dir                ; ES:DI points to handle_dir
  3953.  MOV  AX, 5400h                     ; load function code
  3954.  INT  67h                           ; call the memory manager
  3955.  OR   AH, AH                        ; check EMM status
  3956.  JNZ  emm_err_handler               ; jump to error handler on
  3957.                                     ; error
  3958.  MOV  num_entries_in_handle_dir, AL ; save number of entries
  3959.  
  3960.  
  3961.  FUNCTION 21  Search for Named Handle Subfunction
  3962.  
  3963.  PURPOSE
  3964.  
  3965.  This subfunction searches the handle name directory for a handle with a
  3966.  particular name. If the named handle is found, this subfunction returns the
  3967.  handle number associated with the name. At the time of installation, all
  3968.  handles have their names initialized to ASCII nulls. A handle with a name
  3969.  which is all ASCII nulls has, by definition, no name. When a handle is
  3970.  assigned a name, at least one character in the name must be a non-null
  3971.  character in order to distinguish it from a handle without a name.
  3972.  
  3973.  CALLING PARAMETERS
  3974.  
  3975.  AX = 5401h
  3976.    Contains the Search for Named Handle subfunction.
  3977.  
  3978.  DS:SI = handle_name
  3979.    Contains a pointer to an 8-byte string that contains the name of the
  3980.    handle be searched for.
  3981.  
  3982.  RESULTS
  3983.  
  3984.  These results are valid only if the status returned is zero.
  3985.  
  3986.  DX = value of named handle
  3987.    The value of the handle which matches the handle name specified.
  3988.  
  3989.  REGISTERS MODIFIED
  3990.  
  3991.  AX, DX
  3992.  
  3993.  STATUS
  3994.  
  3995.  AH = 0        SUCCESSFUL.
  3996.    The handle value for the named handle has been found.
  3997.  
  3998.  AH = 80h      NON-RECOVERABLE.
  3999.    The manager has detected a malfunction in the memory manager software.
  4000.  
  4001.  AH = 81h      NON-RECOVERABLE.
  4002.    The manager has detected a malfunction in the expanded memory hardware.
  4003.  
  4004.  AH = 84h      NON-RECOVERABLE.
  4005.    The function code passed to the manager is not defined.
  4006.  
  4007.  AH = 8Fh      NON-RECOVERABLE.
  4008.    The subfunction parameter is invalid.
  4009.  
  4010.  AH = A0h      RECOVERABLE.
  4011.    No corresponding handle could be found for the handle name specified.
  4012.  
  4013.  AH = A1h      NON-RECOVERABLE.
  4014.    A handle found had no name (all ASCII nulls).
  4015.  
  4016.  EXAMPLE
  4017.  
  4018.  named_handle                  DB  'AARDVARK'
  4019.  named_handle_value            DW  ?
  4020.  
  4021.  MOV   AX, SEG named_handle
  4022.  MOV   DS, AX
  4023.  LEA   SI, named_handle        ; DS:SI points to named_handle
  4024.  MOV   AX, 5401h               ; load function code
  4025.  INT   67h                     ; call the memory manager
  4026.  OR    AH, AH                  ; check EMM status
  4027.  JNZ   emm_err_handler         ; jump to error handler on error
  4028.  MOV   named_handle_value, DX  ; save value of named handle
  4029.  
  4030.  
  4031.  FUNCTION 21  Get Total Handles Subfunction
  4032.  
  4033.  PURPOSE
  4034.  
  4035.  This subfunction returns the total number of handles that the memory manager
  4036.  supports, including the operating system handle (handle value 0).
  4037.  
  4038.  CALLING PARAMETERS
  4039.  
  4040.  AX = 5402h
  4041.    Contains the Get Total Handles subfunction.
  4042.  
  4043.  RESULTS
  4044.  
  4045.  These results are valid only if the status returned is zero.
  4046.  
  4047.  BX = total_handles
  4048.    The value returned represents the maximum number of handles which a
  4049.    program may request the memory manager to allocate memory to. The value
  4050.    returned includes the operating system handle (handle value 0).
  4051.  
  4052.  REGISTERS MODIFIED
  4053.  
  4054.  AX, BX
  4055.  
  4056.  STATUS
  4057.  
  4058.  AH = 0        SUCCESSFUL.
  4059.    The total number of handles supported has been returned.
  4060.  
  4061.  AH = 80h      NON-RECOVERABLE.
  4062.    The manager has detected a malfunction in the memory manager software.
  4063.  
  4064.  AH = 81h      NON-RECOVERABLE.
  4065.    The manager has detected a malfunction in the expanded memory hardware.
  4066.  
  4067.  AH = 84h      NON-RECOVERABLE.
  4068.    The function code passed to the manager is not defined.
  4069.  
  4070.  AH = 8Fh      NON-RECOVERABLE.
  4071.    The subfunction parameter is invalid.
  4072.  
  4073.  EXAMPLE
  4074.  
  4075.  total_handles            DW     ?
  4076.  
  4077.  MOV   AX, 5402h          ; load function code
  4078.  INT   67h                ; call the memory manager
  4079.  OR    AH, AH             ; check EMM status
  4080.  JNZ   emm_err_handler    ; jump to error handler on error
  4081.  MOV   total_handles, BX  ; save total handle count
  4082.  
  4083.  
  4084.  FUNCTION 22  ALTER PAGE MAP & JUMP
  4085.  
  4086.  PURPOSE
  4087.  
  4088.  This function alters the memory mapping context and transfers control to the
  4089.  specified address. It is analogous to the FAR JUMP in the 8086 family
  4090.  architecture. The memory mapping context which existed before the invocation
  4091.  of this function is lost.
  4092.  
  4093.  Mapping no pages and jumping is not considered an error. If a request to map
  4094.  zero pages and jump is made, control is transferred to the target address,
  4095.  and this function performs a far jump.
  4096.  
  4097.  CALLING PARAMETERS
  4098.  
  4099.  AH = 55h
  4100.    Contains the Alter Page Map & Jump function.
  4101.  
  4102.          log_phys_map_struct          STRUC
  4103.              log_page_number          DW ?
  4104.              phys_page_number_seg     DW ?
  4105.          log_phys_map_struct          ENDS
  4106.  
  4107.          map_and_jump_struct          STRUC
  4108.              target_address           DD ?
  4109.              log_phys_map_len         DB ?
  4110.              log_phys_map_ptr         DD ?
  4111.          map_and_jump_struct          ENDS
  4112.  
  4113.  AL = physical page number/segment selector
  4114.    Contains a code which indicates whether the value contained in the
  4115.  
  4116.              .log_phys_map.phys_page_number_seg
  4117.  
  4118.    members are physical page numbers or are the segment address
  4119.    representation of the physical page numbers. A zero in AL indicates that
  4120.    the values are physical page numbers. A one in AL indicates that the
  4121.    values in these members are the segment address representations of the
  4122.    physical page numbers.
  4123.  
  4124.  DX = handle number
  4125.    Contains the EMM handle.
  4126.  
  4127.  DS:SI = pointer to map_and_jump structure
  4128.    Contains a pointer to a structure that contains the information necessary
  4129.    to map the desired physical pages and jump to the target address. The
  4130.    structure consists of the following elements:
  4131.  
  4132.      .target_address
  4133.          The first member is a far pointer which contains the target address
  4134.          to which control is to be transferred. The address is represented in
  4135.          segment:offset format. The offset portion of the address is stored
  4136.          in the low portion of the double word.
  4137.  
  4138.      .log_phys_map_len
  4139.          The second member is a byte which contains the number of entries in
  4140.          the array of structures which immediately follows it. The array is
  4141.          as long as the application developer needs to map the desired
  4142.          logical pages into physical pages. The number of entries cannot
  4143.          exceed the number of mappable pages in the system.
  4144.  
  4145.      .log_phys_map_ptr
  4146.          The third member is a pointer to an array of structures which
  4147.          contain the logical page numbers and physical pages or segment
  4148.          address at which they are to be mapped. Each entry in the array of
  4149.          structures contains the following two elements:
  4150.  
  4151.      .log_page_number
  4152.          The first member of this structure is a word which contains the
  4153.          number of the logical page to be mapped.
  4154.  
  4155.      .phys_page_number_seg
  4156.          The second member of this structure is a word which contains either
  4157.          the physical page number or the segment address representation of
  4158.          the physical page number at which the previous logical page number
  4159.          is to be mapped. The value passed in AL determines the type of
  4160.          representation.
  4161.  
  4162.  REGISTERS MODIFIED
  4163.  
  4164.  AX
  4165.  
  4166.  ────────────────────────────────────────────────────────────────────────────
  4167.  NOTE:
  4168.    Values in registers which don't contain required parameters maintain the
  4169.    values across the jump. The values in registers (with the exception of AX)
  4170.    and the flag state at the beginning of the function are still in the
  4171.    registers and flags when the target address is reached.
  4172.  ────────────────────────────────────────────────────────────────────────────
  4173.  
  4174.  STATUS
  4175.  
  4176.  AH = 0        SUCCESSFUL.
  4177.    Control has been transferred to the target address.
  4178.  
  4179.  AH = 80h      NON-RECOVERABLE.
  4180.    The manager has detected a malfunction in the memory manager software.
  4181.  
  4182.  AH = 81h      NON-RECOVERABLE.
  4183.    The manager has detected a malfunction in the expanded memory hardware.
  4184.  
  4185.  AH = 83h      NON-RECOVERABLE.
  4186.    The manager could not find the specified EMM handle. The manager does not
  4187.    currently have any information pertaining to the specified EMM handle. The
  4188.    program may have corrupted its EMM handle.
  4189.  
  4190.  AH = 84h      NON-RECOVERABLE.
  4191.    The function code passed to the manager is not defined.
  4192.  
  4193.  AH = 8Ah      RECOVERABLE.
  4194.    One or more of the logical pages to map into a corresponding physical page
  4195.    is out of the range of logical pages which are allocated to the EMM
  4196.    handle. The program can recover from this condition by mapping a logical
  4197.    page which is within the bounds for the EMM handle.
  4198.  
  4199.  AH = 8Bh      RECOVERABLE.
  4200.    One or more of the physical pages is out of the range of allowable
  4201.    physical pages, or the log_phys_map_len exceeds the number of mappable
  4202.    pages in the system. Physical page numbers are numbered zero relative. The
  4203.    program can recover from this condition by mapping into memory at a
  4204.    physical page which is in the range of supported physical pages.
  4205.  
  4206.  AH = 8Fh      RECOVERABLE.
  4207.    The subfunction parameter is invalid.
  4208.  
  4209.  EXAMPLE
  4210.  
  4211.  log_phys_map             log_phys_map_struct (?) DUP (?)
  4212.  
  4213.  map_and_jump             map_and_jump_struct (?)
  4214.  
  4215.  emm_handle                      DW ?
  4216.  phys_page_or_seg_mode           DB ?
  4217.  
  4218.  MOV  AX, SEG map_and_jump
  4219.  MOV  DS, AX
  4220.  LEA  SI, map_and_jump           ; DS:SI points to
  4221.                                  ; map_and_jump
  4222.  MOV  DX, emm_handle
  4223.  MOV  AH, 55h                    ; load function code
  4224.  MOV  AL, phys_page_or_seg_mode  ; specify physical page
  4225.                                  ; or segment mode
  4226.  INT  67h                        ; call memory manager
  4227.  OR   AH, AH                     ; check EMM status
  4228.  JNZ  emm_err_handler            ; jump to error handler
  4229.                                  ; on error
  4230.  
  4231.  
  4232.  FUNCTION 23  ALTER PAGE MAP CALL Alter Page Map & Call Subfunction
  4233.  
  4234.  PURPOSE
  4235.  
  4236.  This subfunction saves the current memory mapping context, alters the
  4237.  specified memory mapping context, and transfers control to the specified
  4238.  address. It is analogous to the FAR CALL in the 8086 family architecture.
  4239.  Just as a return from a FAR CALL restores the original value in the code
  4240.  segment register, this subfunction restores the state of the specified
  4241.  mapping context after the return.
  4242.  
  4243.  There is no explicit expanded memory subfunction which emulates a return
  4244.  from a FAR CALL. However, this facility is implicitly available through the
  4245.  standard return from a FAR CALL. The following paragraphs describe how this
  4246.  works:
  4247.  
  4248.  After this function is invoked, unless an error is detected, the memory
  4249.  manager will transfer control to the address specified. If an error occurs,
  4250.  the memory manager returns immediately with the error code in the AH
  4251.  register. Otherwise, the memory manager pushes on the stack information
  4252.  which enables it to restore the mapping context after the return.
  4253.  
  4254.  When the called procedure wants to return to the calling procedure, it
  4255.  simply issues a standard FAR RETURN. The memory manager traps this return,
  4256.  restores the specified mapping context, and returns to the calling
  4257.  procedure. The memory manager also returns a status from a SUCCESSFUL return
  4258.  just as it does for all functions.
  4259.  
  4260.  Developers using this subfunction must make allowances for the additional
  4261.  stack space this subfunction will use.
  4262.  
  4263.  CALLING PARAMETERS
  4264.  
  4265.  AH = 56h
  4266.    Contains the Alter Page Map & Call function.
  4267.  
  4268.          log_phys_map_struct        STRUC
  4269.              log_page_number        DW ?
  4270.              phys_page_number_seg   DW ?
  4271.          log_phys_map_struct        ENDS
  4272.  
  4273.          map_and_call_struct        STRUC
  4274.              target_address         DD ?
  4275.              new_page_map_len       DB ?
  4276.              new_page_map_ptr       DD ?
  4277.              old_page_map_len       DB ?
  4278.              old_page_map_ptr       DD ?
  4279.              reserved               DW  4 DUP (?)
  4280.          map_and_call_struct        ENDS
  4281.  
  4282.  AL = physical page number/segment selector
  4283.    Contains a code which indicates whether the value contained in the
  4284.  
  4285.              .new_page_map.phys_page_number_seg
  4286.              .old_page_map.phys_page_number_seg
  4287.  
  4288.    members are physical pages numbers or are the segment address
  4289.    representation of the physical page numbers. A value of zero in AL
  4290.    indicates that the values in these members are physical page numbers. A
  4291.    value of one in AL indicates that the values in these members are the
  4292.    segment address representations of the physical page numbers.
  4293.  
  4294.  DX = handle number
  4295.    Contains the EMM handle.
  4296.  
  4297.  DS:SI = pointer to map_and_call structure
  4298.    Contains a pointer to a structure which contains the information necessary
  4299.    to map the desired physical pages and call the target address. The
  4300.    structure members are described here:
  4301.  
  4302.      .target_address
  4303.          The first member is a far pointer which contains the target address
  4304.          to which control is to be transferred. The address is represented in
  4305.          segment:offset format. The offset portion of the address is stored
  4306.          in the low portion of the pointer. The application must supply this
  4307.          value.
  4308.  
  4309.      .new_page_map_len
  4310.          The second member is a byte which contains the number of entries in
  4311.          the new mapping context to which new_page_map_ptr points. This
  4312.          number cannot exceed the number of mappable pages in the system.
  4313.  
  4314.      .new_page_map_ptr
  4315.          The third member is a far pointer that points to an array of
  4316.          structures which contains a list of the logical page numbers and the
  4317.          physical page numbers/segments at which they are to be mapped
  4318.          immediately after the call. The contents of the new array of
  4319.          structures are described at the end of the map_and_call structure.
  4320.  
  4321.      .old_page_map_len
  4322.          The fourth member is a byte which contains the number of entries in
  4323.          the old mapping context to which old_page_map_ptr points. This
  4324.          number cannot exceed the number of mappable pages in the system.
  4325.  
  4326.      .old_page_map_ptr
  4327.          The fifth member is a far pointer that points to an array of
  4328.          structures which contains a list of the logical page numbers and the
  4329.          physical page numbers/segments at which they are to be mapped
  4330.          immediately after the return. The contents of the old array of
  4331.          structures are described at the end of the map_and_call structure.
  4332.  
  4333.      .reserved
  4334.          The sixth member is reserved for use by the memory manager.
  4335.  
  4336.  Each entry in the old and new array of structures contains two elements:
  4337.  
  4338.      .log_page_number
  4339.          The first member of this structure is a word which contains a
  4340.          logical page number which is to be mapped at the succeeding physical
  4341.          page number/segment immediately after the CALL (in the case of the
  4342.          new array of structures) or after the RETURN (in the case of the old
  4343.          array of structures).
  4344.  
  4345.      .phys_page_number_seg
  4346.          The second member of this structure is a word which contains either
  4347.          the physical page number or the segment address representation of
  4348.          the physical page number/segment at which the preceding logical page
  4349.          is to be mapped immediately after the CALL (in the case of the new
  4350.          array of structures) or after the RETURN (in the case of the old
  4351.          array of structures).
  4352.  
  4353.  REGISTERS MODIFIED
  4354.  
  4355.  AX
  4356.  
  4357.  ────────────────────────────────────────────────────────────────────────────
  4358.  NOTE:
  4359.    Values in registers which don't contain required parameters maintain the
  4360.    values across the call. The values in registers (with the exception of AX)
  4361.    and the flag state at the beginning of the function are still in the
  4362.    registers and flags when the target address is reached.
  4363.  ────────────────────────────────────────────────────────────────────────────
  4364.  
  4365.  STATUS
  4366.  
  4367.  AH = 0        SUCCESSFUL.
  4368.    Control has been transferred to the target address.
  4369.  
  4370.  AH = 80h      NON-RECOVERABLE.
  4371.    The manager has detected a malfunction in the memory manager software.
  4372.  
  4373.  AH = 81h      NON-RECOVERABLE.
  4374.    The manager has detected a malfunction in the expanded memory hardware.
  4375.  
  4376.  AH = 83h      NON-RECOVERABLE.
  4377.    The manager couldn't find the specified EMM handle. The manager doesn't
  4378.    have any information pertaining to the specified EMM handle. The program
  4379.    may have corrupted its EMM handle.
  4380.  
  4381.  AH = 84h      NON-RECOVERABLE.
  4382.    The function code passed to the manager is not defined.
  4383.  
  4384.  AH = 8Ah      RECOVERABLE.
  4385.    One or more of the logical pages to map into a corresponding physical page
  4386.    is out of the range of logical pages which are allocated to the EMM
  4387.    handle. The program can recover from this condition by mapping a logical
  4388.    page which is within the bounds for the EMM handle.
  4389.  
  4390.  AH = 8Bh      RECOVERABLE.
  4391.    One or more of the physical pages is out of the range of allowable
  4392.    physical pages, or you've specified more physical pages than exist in the
  4393.    system. Physical page numbers are numbered zero relative. The program can
  4394.    recover from this condition by mapping a physical page which is in the
  4395.    range from zero to three.
  4396.  
  4397.  AH = 8Fh      NON-RECOVERABLE.
  4398.    The subfunction parameter is invalid.
  4399.  
  4400.  EXAMPLE
  4401.  
  4402.  new_page_map             log_phys_map_struct (?) DUP (?)
  4403.  
  4404.  old_page_map             log_phys_map_struct (?) DUP (?)
  4405.  
  4406.  map_and_call             map_and_call_struct (?)
  4407.  
  4408.  emm_handle                      DW ?
  4409.  phys_page_or_seg_mode           DB ?
  4410.  
  4411.  MOV  AX, SEG map_and_call
  4412.  MOV  DS, AX
  4413.  LEA  SI, map_and_call           ; DS:SI points to
  4414.                                  ; map_and_call
  4415.  MOV  DX, emm_handle             ; specify EMM handle
  4416.  MOV  AH, 56h                    ; load function code
  4417.  MOV  AL, phys_page_or_seg_mode  ; specify physical
  4418.                                  ; page or segment mode
  4419.  INT  67h                        ; control is actually
  4420.                                  ; transferred to the called
  4421.                                  ; procedure at this point
  4422.  OR   AH, AH                     ; check EMM status
  4423.  JNZ  emm_err_handler            ; jump to error handler
  4424.                                  ; on error
  4425.  
  4426.  
  4427.  FUNCTION 23  Get Page Map Stack Space Size Subfunction
  4428.  
  4429.  PURPOSE
  4430.  
  4431.  Since the Alter Page Map & Call function pushes additional information onto
  4432.  the stack, this subfunction returns the number of bytes of stack space the
  4433.  function requires.
  4434.  
  4435.  CALLING PARAMETERS
  4436.  
  4437.  AX = 5602h
  4438.    Contains the Get Page Map Stack Space Size subfunction.
  4439.  
  4440.  RESULTS
  4441.  
  4442.  These results are valid only if the status returned is zero.
  4443.  
  4444.  BX = stack space required
  4445.    Contains the number of bytes which the Alter Page Map & Call function will
  4446.    require. In other words, BX contains the number (including the return
  4447.    address) which has to be added to the stack pointer to remove all elements
  4448.    from the stack.
  4449.  
  4450.  REGISTERS MODIFIED
  4451.  
  4452.  AX, BX
  4453.  
  4454.  STATUS
  4455.  
  4456.  AH = 0        SUCCESSFUL.
  4457.    The size of the array has been returned.
  4458.  
  4459.  AH = 80h      NON-RECOVERABLE.
  4460.    The manager has detected a malfunction in the memory manager software.
  4461.  
  4462.  AH = 81h      NON-RECOVERABLE.
  4463.    The manager has detected a malfunction in the expanded memory hardware.
  4464.  
  4465.  AH = 84h      NON-RECOVERABLE.
  4466.    The function code passed to the manager is not defined.
  4467.  
  4468.  AH = 8Fh      NON-RECOVERABLE.
  4469.    The subfunction parameter is invalid.
  4470.  
  4471.  EXAMPLE
  4472.  
  4473.  stack_space_reqd            DW ?
  4474.  
  4475.  MOV   AX, 5602h             ; load function code
  4476.  INT   67h                   ; call the memory manager
  4477.  OR    AH, AH                ; check EMM status
  4478.  JNZ   emm_err_handler       ; jump to error handler on error
  4479.  MOV   stack_space_reqd, BX  ; save required stack size count
  4480.  
  4481.  
  4482.  FUNCTION 24  MOVE/EXCHANGE MEMORY REGION Move Memory Region Subfunction
  4483.  
  4484.  PURPOSE
  4485.  
  4486.  This subfunction copies a region of memory in the following memory
  4487.  source/destination combinations.
  4488.  
  4489.    ■  conventional memory to conventional memory
  4490.    ■  conventional memory to expanded memory
  4491.    ■  expanded memory to conventional memory
  4492.    ■  expanded memory to expanded memory
  4493.  
  4494.  You do not have to save and restore the expanded memory mapping context to
  4495.  perform these move operations. The current mapping context is maintained
  4496.  throughout this operation.
  4497.  
  4498.  The length of the region is limited by the amount of expanded memory
  4499.  allocated to the handles specified. However, in most practical applications,
  4500.  the region length will be considerably smaller. A region length of zero is
  4501.  not an error, and no move will be performed.
  4502.  
  4503.  A region length which exceeds 16K bytes is not an error. In this case the
  4504.  function assumes that a group of logical pages is the target for the move.
  4505.  The logical page specified represents the first logical page in which the
  4506.  move will take place. If the region length exceeds 16K bytes, or if the
  4507.  region is less than 16K bytes but spans logical pages, there must be
  4508.  sufficient logical pages remaining after the first logical page for the
  4509.  entire region to fit.
  4510.  
  4511.  If your application needs to save a region of conventional memory in
  4512.  expanded memory, you can move it without having to perform a save or restore
  4513.  of the current mapping context. The memory manager maintains the context. A
  4514.  move of up to 1M byte may be performed, although practical lengths are
  4515.  substantially less than this value.
  4516.  
  4517.  If the source and destination handles are identical, the source and
  4518.  destination regions are tested for overlap before the move. If they overlap,
  4519.  the move direction is chosen so that the destination region receives an
  4520.  intact copy of the source region. A status will be returned indicating that
  4521.  this overlap has occurred.
  4522.  
  4523.  CALLING PARAMETERS
  4524.  
  4525.  AX = 5700h
  4526.    Contains the Move Memory Region function.
  4527.  
  4528.          move_source_dest_struct    STRUC
  4529.               region_length         DD  ?
  4530.               source_memory_type    DB  ?
  4531.               source_handle         DW  ?
  4532.               source_initial_offset DW  ?
  4533.               source_initial_seg_page    DW  ?
  4534.               dest_memory_type      DB  ?
  4535.               dest_handle           DW  ?
  4536.               dest_initial_offset   DW  ?
  4537.               dest_initial_seg_page DW  ?
  4538.          move_source_dest_struct    ENDS
  4539.  
  4540.  DS:SI = pointer to exchange_source_dest structure
  4541.    Contains a pointer to a data structure which contains the source and
  4542.    destination information for the exchange. The structure members are
  4543.    described here:
  4544.  
  4545.      .region_length
  4546.          The first member is a double word which specifies the length of the
  4547.          memory region (in bytes) to be moved.
  4548.  
  4549.      .source_memory_type
  4550.          The second member is a byte which specifies the type of memory where
  4551.          the source region resides. A value of zero indicates that the source
  4552.          region resides in conventional memory (excluding the page frame
  4553.          segment). A value of one indicates that the source region resides in
  4554.          expanded memory.
  4555.  
  4556.      .source_handle
  4557.          If the source region resides in expanded memory, the third member is
  4558.          a word which specifies the handle number associated with the source
  4559.          memory region. If the source region resides in conventional memory,
  4560.          this variable has no meaning and should be set to zero for future
  4561.          compatibility.
  4562.  
  4563.      .source_initial_offset
  4564.          The fourth member is a word which specifies the offset within the
  4565.          source region from which to begin the move.
  4566.  
  4567.          If the source region resides in expanded memory, the
  4568.          source_initial_offset is relative to the beginning of the 16K
  4569.          logical page. Because the offset is relative to the beginning of a
  4570.          16K expanded memory page, it may only take on values between 0000h
  4571.          and 3FFFh.
  4572.  
  4573.          If the source region resides in conventional memory, the
  4574.          source_initial_offset is a word which specifies the offset, relative
  4575.          to the beginning of the source segment, from which to begin the
  4576.          move. Because the offset is relative to the beginning of a 64K-byte
  4577.          conventional memory segment, it may take on values between 0000h and
  4578.          FFFFh.
  4579.  
  4580.      .source_initial_seg_page
  4581.          The fifth member is a word which specifies the initial segment or
  4582.          logical page number within the source region from which to begin the
  4583.          move.
  4584.  
  4585.          If the source region resides in expanded memory, the value specifies
  4586.          the logical page within the source region from which to begin the
  4587.          move.
  4588.  
  4589.          If the source region resides in conventional memory, the
  4590.          source_initial_seg_page specifies the initial segment address within
  4591.          conventional memory from which to begin the move.
  4592.  
  4593.      .dest_memory_type
  4594.          The sixth member is a byte which specifies the type of memory where
  4595.          the destination region resides. A value of zero indicates
  4596.          conventional memory; a value of one indicates expanded memory.
  4597.  
  4598.      .dest_handle
  4599.          If the destination region resides in expanded memory, the seventh
  4600.          member is a word which specifies the handle number associated with
  4601.          the destination memory region. If the destination region resides in
  4602.          conventional memory, this variable has no meaning and should be set
  4603.          to zero for future compatibility.
  4604.  
  4605.      .dest_initial_offset
  4606.          The eighth member is a word which specifies the offset within the
  4607.          destination region from which to begin the move.
  4608.  
  4609.          If the destination region resides in expanded memory, the
  4610.          dest_initial_offset is relative to the beginning of the 16K-byte
  4611.          logical page. Because the offset is relative to the beginning of a
  4612.          16K-byte expanded memory page, it may take on values between 0000h
  4613.          and 3FFFh.
  4614.  
  4615.          If the destination region resides in conventional memory, the
  4616.          dest_initial_offset is a word which specifies the offset, relative
  4617.          to the beginning of the destination segment, to begin the move.
  4618.          Because the offset is relative to the beginning of a 64K
  4619.          conventional memory segment, it may take on values between 0000h and
  4620.          FFFFh.
  4621.  
  4622.      .dest_initial_seg_page
  4623.          The ninth member is a word which specifies the initial segment or
  4624.          logical page number within the destination region from which to
  4625.          begin the move.
  4626.  
  4627.          If the destination region resides in expanded memory then the value
  4628.          specifies the logical page within the destination region from which
  4629.          to begin the exchange.
  4630.  
  4631.          If the destination region resides in conventional memory, the
  4632.          dest_initial_seg_page specifies the initial segment address within
  4633.          conventional memory from which to begin the move.
  4634.  
  4635.  REGISTERS MODIFIED
  4636.  
  4637.  AX
  4638.  
  4639.  STATUS
  4640.  
  4641.  AH = 0        SUCCESSFUL.
  4642.    The memory regions have been moved.
  4643.  
  4644.  AH = 80h      NON-RECOVERABLE.
  4645.    The manager has detected a malfunction in the memory manager software.
  4646.  
  4647.  AH = 81h      NON-RECOVERABLE.
  4648.    The manager has detected a malfunction in the expanded memory hardware.
  4649.  
  4650.  AH = 83h      NON-RECOVERABLE.
  4651.    The manager couldn't find either the source or destination EMM handles.
  4652.    The memory manager doesn't have any information on the handles specified.
  4653.    The program may have corrupted its EMM handles.
  4654.  
  4655.  AH = 84h      NON-RECOVERABLE.
  4656.    The function code passed to the manager is not defined.
  4657.  
  4658.  AH = 8Ah      NON-RECOVERABLE.
  4659.    One or more of the logical pages is out of the range of logical pages
  4660.    allocated to the source/destination handle.
  4661.  
  4662.  AH = 8Fh      NON-RECOVERABLE.
  4663.    The subfunction parameter is invalid.
  4664.  
  4665.  AH = 92h      SUCCESSFUL.
  4666.    The source and destination expanded memory regions have the same handle
  4667.    and overlap. This is valid for a move. The move has been completed and the
  4668.    destination region has a full copy of the source region. However, at least
  4669.    a portion of the source region has been overwritten by the move. Note that
  4670.    the source and destination expanded memory regions with different handles
  4671.    will never physically overlap because the different handles specify
  4672.    totally different regions of expanded memory.
  4673.  
  4674.  AH = 93h      CONDITIONALLY-RECOVERABLE.
  4675.    The length of the source or destination expanded memory region specified
  4676.    exceeds the length of the expanded memory region allocated either the
  4677.    source or destination handle. Insufficient pages are allocated to this
  4678.    handle to move a region of the size specified. The program can recover
  4679.    from this condition by allocating additional pages to the destination or
  4680.    source handle and attempting to execute the function again. However, if
  4681.    the application program allocated as much expanded memory as it thought it
  4682.    needed, this may be a program error and is not recoverable.
  4683.  
  4684.  AH = 94h      NON-RECOVERABLE.
  4685.    The conventional memory region and expanded memory region overlap. This is
  4686.    invalid, the conventional memory region cannot overlap the expanded memory
  4687.    region.
  4688.  
  4689.  AH = 95h      NON-RECOVERABLE.
  4690.    The offset within the logical page exceeds the length of the logical page.
  4691.    The initial source or destination offsets within an expanded memory region
  4692.    must be between 0000h and 3FFFh (16383 or (length of a logical page -
  4693.    1)).
  4694.  
  4695.  AH = 96h      NON-RECOVERABLE.
  4696.    Region length exceeds 1M byte.
  4697.  
  4698.  AH = 98h      NON-RECOVERABLE.
  4699.    The memory source and destination types are undefined.
  4700.  
  4701.  AH = A2h      NON-RECOVERABLE.
  4702.    An attempt was made to wrap around the 1M-byte address space of
  4703.    conventional memory during the move. The combination of source/destination
  4704.    starting address and length of the region to be moved exceeds 1M byte. No
  4705.    data was moved.
  4706.  
  4707.  EXAMPLE
  4708.  
  4709.  move_source_dest         move_source_dest_struct (?)
  4710.  
  4711.  MOV   AX, SEG move_source_dest
  4712.  MOV   DS, AX
  4713.  LEA   SI, move_source_dest  ; DS:SI points to move_source_dest
  4714.  MOV   AX, 5700h             ; load function code
  4715.  INT   67h                   ; call the memory manager
  4716.  OR    AH, AH                ; check EMM status
  4717.  JNZ   emm_err_handler       ; jump to error handler on error
  4718.  
  4719.  
  4720.  FUNCTION 24  Exchange Memory Region Subfunction
  4721.  
  4722.  PURPOSE
  4723.  
  4724.  This subfunction exchanges (using a string move) a region of memory in any
  4725.  of the following memory source/destination combinations.
  4726.  
  4727.    ■  conventional memory to conventional memory
  4728.    ■  conventional memory to expanded memory
  4729.    ■  expanded memory to conventional memory
  4730.    ■  expanded memory to expanded memory
  4731.  
  4732.  The term expanded memory region refers only to the area of memory above 640K
  4733.  bytes (9FFFFh). If a system provides mappable conventional memory, this
  4734.  function treats the mappable conventional memory regions as ordinary
  4735.  conventional memory. The contents of the source region and the destination
  4736.  region are exchanged.
  4737.  
  4738.  The exchange operation can be performed without having to save and restore
  4739.  the expanded memory mapping context. The current mapping context is
  4740.  maintained throughout this operation. The length of the region is limited to
  4741.  the amount of expanded memory allocated to the specified EMM handles. A
  4742.  length of zero is not an error; however, no exchange will be performed. A
  4743.  region length which exceeds 16K bytes is not an error. In this case the
  4744.  function assumes that a group of logical pages is the target for the
  4745.  exchange. The logical page specified represents the first logical page in
  4746.  which the exchange will take place. If the region length exceeds 16K bytes,
  4747.  or if the region is less than 16K bytes but spans logical pages, there must
  4748.  be sufficient logical pages remaining after the first logical page for the
  4749.  entire region to fit.
  4750.  
  4751.  If your application needs to exchange a region of conventional memory with
  4752.  expanded memory, you can simply exchange it with the region of interest
  4753.  without having to perform a save or restore of the current mapping context.
  4754.  An exchange of up to 1M byte may be performed, although practical lengths
  4755.  are obviously below that value. Checking is done before starting the
  4756.  exchange to prevent the possibility of overlap during the exchange
  4757.  operation. Overlapping source and destination regions for a exchange are
  4758.  invalid, and the exchange will not take place.
  4759.  
  4760.  CALLING PARAMETERS
  4761.  
  4762.  AX = 5701h
  4763.    Contains the Exchange Memory Region function.
  4764.  
  4765.          xchg_source_dest_struct    STRUC
  4766.             region_length           DD ?
  4767.             source_memory_type      DB ?
  4768.             source_handle           DW ?
  4769.             source_initial_offset   DW ?
  4770.             source_initial_seg_page DW ?
  4771.             dest_memory_type        DB ?
  4772.             dest_handle             DW ?
  4773.             dest_initial_offset     DW ?
  4774.             dest_initial_seg_page   DW ?
  4775.          xchg_source_dest_struct    ENDS
  4776.  
  4777.  DS:SI = pointer to move_source_dest structure
  4778.    Contains a pointer to the data structure which contains the source &
  4779.    destination information for the exchange. The structure members are
  4780.    described here:
  4781.  
  4782.      .region_length
  4783.          The first member is a double word which specifies the length of the
  4784.          memory region to be exchanged.
  4785.  
  4786.      .source_memory_type
  4787.          The second member is a byte which specifies the type of memory where
  4788.          the source region resides. A value of zero indicates that the source
  4789.          region resides in conventional memory. A value of one indicates that
  4790.          the source region resides in expanded memory.
  4791.  
  4792.      .source_handle
  4793.          If the source region resides in expanded memory, the third member is
  4794.          a word which specifies the handle number associated with the source
  4795.          memory region. If the source region resides in conventional memory,
  4796.          this variable has no meaning and should be set to zero for future
  4797.          compatibility.
  4798.  
  4799.      .source_initial_offset
  4800.          The fourth member is a word which specifies the offset within the
  4801.          source region from which to begin the exchange.
  4802.  
  4803.          If the source region resides in expanded memory, the
  4804.          source_initial_offset is relative to the beginning of the 16K-byte
  4805.          logical page. Because the offset is relative to the beginning of a
  4806.          16K-byte expanded memory page, it may only take on values between
  4807.          0000h and 3FFFh.
  4808.  
  4809.          If the source region resides in conventional memory, the
  4810.          source_initial_offset is a word which specifies the offset, relative
  4811.          to the beginning of the source segment, to begin the exchange at.
  4812.          Because the offset is relative to the beginning of a 64K-byte
  4813.          conventional memory segment, it may only take on values between
  4814.          0000h and FFFFh.
  4815.  
  4816.      .source_initial_seg_page
  4817.          The fifth member is a word which specifies the initial segment or
  4818.          logical page number within the source region from which to begin the
  4819.          exchange.
  4820.  
  4821.          If the source region resides in expanded memory then the value
  4822.          specifies the logical page within the source region from which to
  4823.          begin the exchange.
  4824.  
  4825.          If the source region resides in conventional memory, the
  4826.          source_initial_seg_page specifies the initial segment address within
  4827.          conventional memory from which to begin the exchange.
  4828.  
  4829.      .dest_memory_type
  4830.          The sixth member is a byte which specifies the type of memory where
  4831.          the destination region resides. A value of zero indicates that the
  4832.          destination region resides in conventional memory (excluding the
  4833.          page frame segment). A value of one indicates that the destination
  4834.          region resides in expanded memory.
  4835.  
  4836.      .dest_handle
  4837.          If the destination region resides in expanded memory, the seventh
  4838.          member is a word which specifies the handle number associated with
  4839.          the destination memory region. If the destination region resides in
  4840.          conventional memory memory, then this variable has no meaning and
  4841.          should be set to zero for future compatibility.
  4842.  
  4843.      .dest_initial_offset
  4844.          The eighth member is a word which specifies the offset within the
  4845.          destination region from which to begin the exchange.
  4846.  
  4847.          If the destination region resides in expanded memory, the
  4848.          dest_initial_offset is relative to the beginning of the 16K-byte
  4849.          logical page. Because the offset is relative to the beginning of a
  4850.          16K-byte expanded memory page, it may only take on values between
  4851.          0000h and 3FFFh.
  4852.  
  4853.          If the destination region resides in conventional memory, the
  4854.          dest_initial_offset is a word which specifies the offset, relative
  4855.          to the beginning of the destination segment, to begin the exchange
  4856.          at. Because the offset is relative to the beginning of a 64K-byte
  4857.          conventional memory segment, it may only take on values between
  4858.          0000h and FFFFh.
  4859.  
  4860.      .dest_initial_seg_page
  4861.          The ninth member is a word which specifies the initial segment or
  4862.          logical page number within the destination region from which to
  4863.          begin the exchange.
  4864.  
  4865.          If the destination region resides in expanded memory, the value
  4866.          specifies the logical page within the destination region from which
  4867.          to begin the exchange.
  4868.  
  4869.          If the destination region resides in conventional memory, the
  4870.          dest_initial_seg_page specifies the initial segment address within
  4871.          conventional memory from which to begin the exchange.
  4872.  
  4873.  REGISTERS MODIFIED
  4874.  
  4875.  AX
  4876.  
  4877.  STATUS
  4878.  
  4879.  AH = 0        SUCCESSFUL.
  4880.    The memory regions have been exchanged.
  4881.  
  4882.  AH = 80h      NON-RECOVERABLE.
  4883.    The manager has detected a malfunction in the memory manager software.
  4884.  
  4885.  AH = 81h      NON-RECOVERABLE.
  4886.    The manager has detected a malfunction in the expanded memory hardware.
  4887.  
  4888.  AH = 83h      NON-RECOVERABLE.
  4889.    The manager could not find either the source or destination EMM handles.
  4890.    The memory manager does not currently have any information pertaining to
  4891.    the handles specified. The program may have corrupted its EMM handles.
  4892.  
  4893.  AH = 84h      NON-RECOVERABLE.
  4894.    The function code passed to the manager is not defined.
  4895.  
  4896.  AH = 8Ah      NON-RECOVERABLE.
  4897.    One or more of the logical pages is out of the range of logical pages
  4898.    allocated to the source/destination handle.
  4899.  
  4900.  AH = 8Fh      NON-RECOVERABLE.
  4901.    The subfunction parameter is invalid.
  4902.  
  4903.  AH = 93h      CONDITIONALLY RECOVERABLE.
  4904.    The length of the source or destination expanded memory region specified,
  4905.    exceeds the length of the expanded memory region allocated to the source
  4906.    or destination specified EMM handle. There are insufficient pages
  4907.    allocated to this handle to exchange a region of the size specified. The
  4908.    program can recover from this condition by attempting to allocate
  4909.    additional pages to the destination or source handle and attempting to
  4910.    execute the function again. However, if the application program was
  4911.    allocated as much expanded memory as it thought it needed, this may be a
  4912.    program error and is therefore not recoverable.
  4913.  
  4914.  AH = 94h      NON-RECOVERABLE.
  4915.    The conventional memory region and expanded memory region overlap. This is
  4916.    invalid, the conventional memory region cannot overlap the expanded memory
  4917.    region.
  4918.  
  4919.  AH = 95h      NON-RECOVERABLE.
  4920.    The offset within the logical page exceeds the length of the logical page.
  4921.    The initial source or destination offsets within an expanded memory region
  4922.    must be between 0000h and 3FFFh (16383 or (length of a logical page -
  4923.    1)).
  4924.  
  4925.  AH = 96h      NON-RECOVERABLE.
  4926.    Region length exceeds 1M Byte limit.
  4927.  
  4928.  AH = 97h      NON-RECOVERABLE.
  4929.    The source and destination expanded memory regions have the same handle
  4930.    and overlap. This is invalid, the source and destination expanded memory
  4931.    regions cannot have the same handle and overlap when they are being
  4932.    exchanged. Note that the source and destination expanded memory regions
  4933.    which have different handles will never physically overlap because the
  4934.    different handles specify totally different regions of expanded memory.
  4935.  
  4936.  AH = 98h      NON-RECOVERABLE.
  4937.    The memory source and destination types are undefined.
  4938.  
  4939.  AH = A2h      NON-RECOVERABLE.
  4940.    An attempt was made to wrap around the 1M-byte address space of
  4941.    conventional memory during the exchange. The source starting address
  4942.    together with the length of the region to be exchanged exceeds 1M byte. No
  4943.    data was exchanged.
  4944.  
  4945.  EXAMPLE
  4946.  
  4947.  xchg_source_dest         xchg_source_dest_struct (?)
  4948.  
  4949.  MOV   AX, SEG xchg_source_dest
  4950.  MOV   DS, AX
  4951.  LEA   SI, xchg_source_dest  ; DS:SI points to xchg_source_dest
  4952.  MOV   AX, 5701h             ; load function code
  4953.  INT   67h                   ; call the memory manager
  4954.  OR    AH, AH                ; check EMM status
  4955.  JNZ   emm_err_handler       ; jump to error handler on error
  4956.  
  4957.  
  4958.  FUNCTION 25  GET MAPPABLE PHYSICAL ADDRESS ARRAY Get Mappable Physical
  4959.               Address Array Subfunction
  4960.  
  4961.  PURPOSE
  4962.  
  4963.  This subfunction returns an array containing the segment address and
  4964.  physical page number for each mappable physical page in a system. The
  4965.  contents of this array provide a cross reference between physical page
  4966.  numbers and the actual segment addresses for each mappable page in the
  4967.  system. The array is sorted in ascending segment order. This does not mean
  4968.  that the physical page numbers associated with the segment addresses are
  4969.  also in ascending order.
  4970.  
  4971.  CALLING PARAMETERS
  4972.  
  4973.  AX = 5800h
  4974.    Contains the Get Mappable Physical Address Array subfunction
  4975.  
  4976.          mappable_phys_page_struct    STRUC
  4977.              phys_page_segment        DW ?
  4978.              phys_page_number         DW ?
  4979.          mappable_phys_page_struct    ENDS
  4980.  
  4981.  ES:DI = mappable_phys_page
  4982.    Contains a pointer to an application-supplied memory area where the memory
  4983.    manager will copy the physical address array. Each entry in the array is a
  4984.    structure containing two members:
  4985.  
  4986.      .phys_page_segment
  4987.          The first member is a word which contains the segment address of the
  4988.          mappable physical page associated with the physical page number
  4989.          following it. The array entries are sorted in ascending segment
  4990.          address order.
  4991.  
  4992.      .phys_page_number
  4993.          The second member is a word which contains the physical page number
  4994.          which corresponds to the previous segment address. The physical page
  4995.          numbers are not necessarily in ascending order.
  4996.  
  4997.      Example 1
  4998.          An expanded memory board has its page frame starting at address
  4999.          C0000h and has no mappable conventional memory. For this
  5000.          configuration, physical page 0 corresponds to segment address C000h,
  5001.          physical page 1 corresponds to segment address C400h, etc. The array
  5002.          would contain the following data (in this order):
  5003.  
  5004.          C000h, 00h
  5005.          C400h, 01h
  5006.          C800h, 02h
  5007.          CC00h, 03h
  5008.  
  5009.      Example 2
  5010.          An expanded memory board has a large page frame starting at address
  5011.          C0000h and has mappable conventional memory from 90000h through
  5012.          9FFFFh. For this configuration, physical page 0 corresponds to
  5013.          segment address C000h, physical page 1 corresponds to segment
  5014.          address C400h, etc. The array would contain the following data in
  5015.          the order specified. Note that the expanded memory region always has
  5016.          the lowest numerically valued physical page numbers.
  5017.  
  5018.          9000h, 0Ch
  5019.          9400h, 0Dh
  5020.          9800h, 0Eh
  5021.          9C00h, 0Fh
  5022.          C000h, 00h
  5023.          C400h, 01h
  5024.          C800h, 02h
  5025.          CC00h, 03h
  5026.          D000h, 04h
  5027.          D400h, 05h
  5028.          D800h, 06h
  5029.          DC00h, 07h
  5030.          E000h, 08h
  5031.          E400h, 09h
  5032.          E800h, 0Ah
  5033.          EC00h, 0Bh
  5034.  
  5035.  RESULTS
  5036.  
  5037.  These results are valid only if the status returned is zero.
  5038.  
  5039.  CX = number of entries in the mappable_phys_page
  5040.    Multiply this number by (SIZE mappable_phys_page_struct) to determine the
  5041.    number of bytes the physical page address array requires.
  5042.  
  5043.  REGISTERS MODIFIED
  5044.  
  5045.  AX, CX
  5046.  
  5047.  STATUS
  5048.  
  5049.  AH = 0        SUCCESSFUL.
  5050.    The hardware configuration array has been returned.
  5051.  
  5052.  AH = 80h      NON-RECOVERABLE.
  5053.    The manager has detected a malfunction in the memory manager software.
  5054.  
  5055.  AH = 81h      NON-RECOVERABLE.
  5056.    The manager has detected a malfunction in the expanded memory hardware.
  5057.  
  5058.  AH = 84h      NON-RECOVERABLE.
  5059.    The function code passed to the manager is not defined.
  5060.  
  5061.  AH = 8Fh      NON-RECOVERABLE.
  5062.    The subfunction parameter is invalid.
  5063.  
  5064.  EXAMPLE
  5065.  
  5066.  mappable_phys_page       mappable_phys_page_struct (?)
  5067.  
  5068.  MOV  AX, SEG mappable_phys_page
  5069.  MOV  ES, AX
  5070.  LEA  DI, mappable_phys_page        ; ES:DI points to
  5071.                                     : mappable_phys_page
  5072.  MOV  AX, 5800h                     ; load function code
  5073.  INT  67h                           ; call the memory
  5074.                                     ; manager
  5075.  OR   AH, AH                        ; check EMM status
  5076.  JNZ  emm_err_handler               ; jump to error handler
  5077.                                     ; on error
  5078.  MOV  mappable_page_entry_count, CX ; save mappable
  5079.                                     ; page entry count
  5080.  
  5081.  
  5082.  FUNCTION 25  Get Mappable Physical Address Array Entries Subfunction
  5083.  
  5084.  PURPOSE
  5085.  
  5086.  This subfunction gets the number of entries which will be required for the
  5087.  array the first subfunction returns.
  5088.  
  5089.  CALLING PARAMETERS
  5090.  
  5091.  AX = 5801h
  5092.    Contains the Get Physical Page Address Array Entry Count subfunction. This
  5093.    subfunction returns a word which represents the number of entries in the
  5094.    array returned by the previous subfunction. This number also represents
  5095.    the number of mappable physical pages in a system.
  5096.  
  5097.  RESULTS
  5098.  
  5099.  These results are valid only if the status returned is zero.
  5100.  
  5101.  CX = number of entries in the mappable_phys_page
  5102.    Multiply this number by (SIZE mappable_phys_page_struct) to determine the
  5103.    number of bytes the physical page address array will require.
  5104.  
  5105.  REGISTERS MODIFIED
  5106.  
  5107.  AX, CX
  5108.  
  5109.  STATUS
  5110.  
  5111.  AH = 0        SUCCESSFUL.
  5112.    The physical page address array has been returned.
  5113.  
  5114.  AH = 80h      NON-RECOVERABLE. .
  5115.    The manager has detected a malfunction in the memory manager software.
  5116.  
  5117.  AH = 81h      NON-RECOVERABLE.
  5118.    The manager has detected a malfunction in the expanded memory hardware.
  5119.  
  5120.  AH = 84h      NON-RECOVERABLE.
  5121.    The function code passed to the manager is not defined.
  5122.  
  5123.  AH = 8Fh      NON-RECOVERABLE.
  5124.    The subfunction parameter is invalid.
  5125.  
  5126.  EXAMPLE
  5127.  
  5128.  mappable_page_entry_count            DW ?
  5129.  
  5130.  MOV   AX, 5801h                      ; load function code
  5131.  INT   67h                            ; call memory manager
  5132.  OR    AH, AH                         ; check EMM status
  5133.  JNZ   emm_err_handler                ; jump to error handler
  5134.                                       ; on error
  5135.  MOV   mappable_page_entry_count, CX  ; save mappable
  5136.                                       ; page entry count
  5137.  
  5138.  
  5139.  FUNCTION 26  GET EXPANDED MEMORY HARDWARE INFORMATION Get Hardware
  5140.               Configuration Array Subfunction
  5141.  
  5142.  ────────────────────────────────────────────────────────────────────────────
  5143.  NOTE:
  5144.    This function is for use by operating systems only. This function can be
  5145.    disabled at any time by the operating system. Refer to Function 30 for a
  5146.    description of how an operating system does this.
  5147.  ────────────────────────────────────────────────────────────────────────────
  5148.  
  5149.  PURPOSE
  5150.  
  5151.  This subfunction returns an array containing expanded memory hardware
  5152.  configuration information for use by an operating system/environment.
  5153.  
  5154.  CALLING PARAMETERS
  5155.  
  5156.  AX = 5900h
  5157.    Contains the Get Hardware Configuration Array subfunction.
  5158.  
  5159.          hardware_info_struct       STRUC
  5160.             raw_page_size           DW ?
  5161.             alternate_register_sets DW ?
  5162.             context_save_area_size  DW ?
  5163.             DMA_register_sets       DW ?
  5164.             DMA_channel_operation   DW ?
  5165.          hardware_info_struct       ENDS
  5166.  
  5167.  ES:DI = hardware_info
  5168.    Contains a pointer to a memory area that the operating system supplies
  5169.    where the memory manager will copy expanded memory hardware information.
  5170.    The structure contains these five members:
  5171.  
  5172.      .raw_page_size
  5173.          The first member is a word which contains the size of a raw mappable
  5174.          physical page in paragraphs (16 bytes). LIM standard pages are
  5175.          always 16K bytes. However, other implementations of expanded memory
  5176.          boards do not necessarily comply with this standard and can emulate
  5177.          a 16K-byte page by mapping in multiple smaller pages. This member
  5178.          specifies the size of a mappable physical page viewed from the
  5179.          hardware implementation level.
  5180.  
  5181.      .alternate_register_sets
  5182.          The second member is a word which specifies the number of alternate
  5183.          mapping register sets. The additional mapping register sets are
  5184.          termed alternate mapping register sets in this document.
  5185.  
  5186.          All expanded memory boards have at least one set of hardware
  5187.          registers to perform the logical to physical page mapping. Some
  5188.          expanded memory boards have more than one set of these mapping
  5189.          registers. This member specifies how many of these alternate mapping
  5190.          register sets exist (beyond the one set that all expanded memory
  5191.          boards have) on the expanded memory boards in the system. If an
  5192.          expanded memory card has only one set of mapping registers (that is,
  5193.          no alternate mapping register sets) this member has a value of
  5194.          zero.
  5195.  
  5196.      .context_save_area_size
  5197.          The third member is a word which contains the storage requirements
  5198.          for the array required to save a mapping context. The value returned
  5199.          in this member is exactly the same as that returned by Function 15
  5200.          (Get Size of Page Map Save Array subfunction).
  5201.  
  5202.      .DMA_channels
  5203.          The fourth member is a word which contains the number of register
  5204.          sets that can be assigned to DMA channels. These DMA register sets,
  5205.          although similar in use to alternate register sets, are for DMA
  5206.          mapping and not task mapping.
  5207.  
  5208.          If the expanded memory hardware does not support DMA register sets,
  5209.          care must be taken when DMA is taking place.
  5210.  
  5211.          In a multitasking operating system, when one task is waiting for DMA
  5212.          to complete, it is useful to be able to switch to another task.
  5213.          However, if the DMA is taking place in memory that the second task
  5214.          will need to remap, remapping would be disastrous.
  5215.  
  5216.          If the expanded memory hardware can detect when DMA is occurring,
  5217.          the OS/E should allow task switches and remapping during DMA. If no
  5218.          special support for DMA is available, no remapping should be done
  5219.          when DMA is in progress.
  5220.  
  5221.      .DMA_channel_operation
  5222.          The fifth member is a word which specifies a special case for the
  5223.          DMA register sets. A value of zero specifies that the DMA register
  5224.          sets behave as described in Function 28. A value of one specifies
  5225.          that the expanded memory hardware has only one DMA register set. In
  5226.          addition, if any channel is mapped through this register set, then
  5227.          all channels are mapped through it. For LIM standard boards, this
  5228.          value is zero.
  5229.  
  5230.  RESULTS
  5231.  
  5232.  These results are valid only if the status returned is zero.
  5233.  
  5234.  hardware_info
  5235.    Contains the expanded memory hardware specific information described
  5236.    above.
  5237.  
  5238.  REGISTERS MODIFIED
  5239.  
  5240.  AX
  5241.  
  5242.  STATUS
  5243.  
  5244.  AH = 0        SUCCESSFUL.
  5245.    The hardware configuration array has been returned.
  5246.  
  5247.  AH = 80h      NON-RECOVERABLE.
  5248.    The manager has detected a malfunction in the memory manager software.
  5249.  
  5250.  AH = 81h      NON-RECOVERABLE.
  5251.    The manager has detected a malfunction in the expanded memory hardware.
  5252.  
  5253.  AH = 84h      NON-RECOVERABLE.
  5254.    The function code passed to the manager is not defined.
  5255.  
  5256.  AH = 8Fh      NON-RECOVERABLE.
  5257.    The subfunction parameter is invalid.
  5258.  
  5259.  AH = A4h      NON-RECOVERABLE.
  5260.    Access to this function has been denied by the operating system. The
  5261.    function cannot be used at this time.
  5262.  
  5263.  EXAMPLE
  5264.  
  5265.  hardware_info            hardware_info_struct (?)
  5266.  
  5267.  MOV   AX, SEG hardware_info
  5268.  MOV   ES, AX
  5269.  LEA   DI, hardware_info  ; ES:DI points to hardware_info
  5270.  MOV   AX, 5900h          ; load function code
  5271.  INT   67h                ; call the memory manager
  5272.  OR    AH, AH             ; check EMM status
  5273.  JNZ   emm_err_handler    ; jump to error handler on error
  5274.  
  5275.  
  5276.  FUNCTION 26  Get Unallocated Raw Page Count Subfunction
  5277.  
  5278.  PURPOSE
  5279.  
  5280.  The Get Unallocated Raw Page Count subfunction returns the number of
  5281.  unallocated non-standard length mappable pages as well as the total number
  5282.  of non-standard length mappable pages in expanded memory to the operating
  5283.  system.
  5284.  
  5285.  One variety of expanded memory board has a page size which is a sub-multiple
  5286.  of 16K bytes. An expanded memory page which is a sub-multiple of 16K is
  5287.  termed a raw page. An operating system may deal with mappable physical page
  5288.  sizes which are sub-multiples of 16K bytes.
  5289.  
  5290.  If the expanded memory board supplies pages in exact multiples of 16K bytes,
  5291.  the number of pages this function returns is identical to the number
  5292.  Function 3 (Get Unallocated Page Count) returns. In this case, there is no
  5293.  difference between a page and a raw page.
  5294.  
  5295.  CALLING PARAMETERS
  5296.  
  5297.  AX = 5901h
  5298.    Contains the Get Unallocated Raw Page Count subfunction.
  5299.  
  5300.  RESULTS
  5301.  
  5302.  These results are valid only if the status returned is zero.
  5303.  
  5304.  BX = unallocated raw pages
  5305.    The number of raw pages that are currently available for use.
  5306.  
  5307.  DX = total raw pages
  5308.    The total number of raw pages in expanded memory.
  5309.  
  5310.  REGISTERS MODIFIED
  5311.  
  5312.  AX, BX, DX
  5313.  
  5314.  STATUS
  5315.  
  5316.  AH = 0        SUCCESSFUL.
  5317.    The manager has returned the number unallocated raw pages and the number
  5318.    of total raw pages in expanded memory.
  5319.  
  5320.  AH = 80h      NON-RECOVERABLE.
  5321.    The manager detected a malfunction in the memory manager software.
  5322.  
  5323.  AH = 81h      NON-RECOVERABLE.
  5324.    The manager detected a malfunction in the expanded memory hardware.
  5325.  
  5326.  AH = 84h      NON-RECOVERABLE.
  5327.    The function code passed to the memory manager is not defined.
  5328.  
  5329.  AH = 8Fh      NON-RECOVERABLE.
  5330.    The subfunction parameter is invalid.
  5331.  
  5332.  EXAMPLE
  5333.  
  5334.  unalloc_raw_pages            DW ?
  5335.  total_raw_pages              DW ?
  5336.  
  5337.  MOV   AX, 5901h              ; load function code
  5338.  INT   67h                    ; call the memory manager
  5339.  OR    AH, AH                 ; check EMM status
  5340.  JNZ   emm_err_handler        ; jump to error handler on error
  5341.  MOV   unalloc_raw_pages, BX  ; save unallocated raw page
  5342.                               ; count
  5343.  MOV   total_raw_pages, DX    ; save total raw page count
  5344.  
  5345.  
  5346.  FUNCTION 27  ALLOCATE STANDARD/RAW PAGES Allocate Standard Pages Subfunction
  5347.  
  5348.  PURPOSE
  5349.  
  5350.  The Allocate Standard Pages subfunction allocates the number of standard
  5351.  size (16K bytes) pages that the operating system requests and assigns a
  5352.  unique EMM handle to these pages. The EMM handle owns these pages until the
  5353.  operating system deallocates them. This subfunction allows you to allocate
  5354.  zero pages to a handle, unlike Function 4 (Allocate Pages).
  5355.  
  5356.  ────────────────────────────────────────────────────────────────────────────
  5357.  NOTE:
  5358.    This note affects expanded memory manager implementers and operating
  5359.    system developers only. Applications should not use the following
  5360.    characteristic of the memory manager. An application violating this rule
  5361.    will be incompatible with future versions of Microsoft's operating systems
  5362.    and environments.
  5363.  
  5364.    To be compatible with this specification, an expanded memory manager will
  5365.    provide a special handle which is available to the operating system only.
  5366.    This handle will have a value of 0000h and will have a set of pages
  5367.    allocated to it when the expanded memory manager driver installs. The
  5368.    pages that the memory manager will automatically allocate to handle 0000h
  5369.    are those that backfill conventional memory. Typically, this backfill
  5370.    occurs between addresses 40000h (256K) and 9FFFFh (640K). However, the
  5371.    range can extend below and above this limit if the hardware and memory
  5372.    manager have the capability.
  5373.  
  5374.    An operating system won't have to invoke Function 27 to obtain this
  5375.    handle because it can assume the handle already exists and is available
  5376.    for use immediately after the expanded memory device driver installs. When
  5377.    an operating system wants to use this handle, it uses the special handle
  5378.    value of 0000h. The operating system will be able to invoke any EMM
  5379.    function using this special handle value. To allocate pages to this
  5380.    handle, the operating system need only invoke Function 18 (Reallocate
  5381.    pages).
  5382.  
  5383.    There are two special cases for this handle:
  5384.  
  5385.      1.  Function 27 (Allocate Standard Pages). This function must never
  5386.          return zero as a handle value. Applications must always invoke
  5387.          Function 27 to allocate pages and obtain a handle which identifies
  5388.          the pages which belong to it. Since Function 27 never returns a
  5389.          handle value of zero, an application will never gain access to this
  5390.          special handle.
  5391.  
  5392.      2.  Function 6 (Deallocate Pages). If the operating system uses it to
  5393.          deallocate the pages which are allocated to this handle, the pages
  5394.          the handle owns will be returned to the manager for use. But the
  5395.          handle will not be available for reassignment. The manager should
  5396.          treat a deallocate pages function request for this handle the same
  5397.          as a reallocate pages function request, where the number of pages to
  5398.          reallocate to this handle is zero.
  5399.  ────────────────────────────────────────────────────────────────────────────
  5400.  
  5401.  CALLING PARAMETERS
  5402.  
  5403.  AX = 5A00h
  5404.    Contains the Allocate Standard Pages subfunction.
  5405.  
  5406.  BX = num_of_standard_pages_to_alloc
  5407.    Contains the number of standard pages the operating system wants to
  5408.    allocate.
  5409.  
  5410.  RESULTS
  5411.  
  5412.  These results are valid only if the status returned is zero.
  5413.  
  5414.  DX = handle
  5415.    Contains a unique EMM handle. The operating system must use this EMM
  5416.    handle as a parameter in any function that requires it. Up to 255 handles
  5417.    may be obtained. (Both Function 27 and Function 4 must share the same
  5418.    255 handles).
  5419.  
  5420.    For all functions using this handle, the length of the physical and
  5421.    logical pages allocated to it are standard length (that is, 16K bytes).
  5422.  
  5423.  REGISTERS MODIFIED
  5424.  
  5425.  AX, DX
  5426.  
  5427.  STATUS
  5428.  
  5429.  AH = 0        SUCCESSFUL. The manager has allocated the pages to
  5430.    an assigned EMM raw handle.
  5431.  
  5432.  AH = 80h      NON-RECOVERABLE. The manager detected a
  5433.    malfunction in the memory manager software.
  5434.  
  5435.  AH = 81h      NON-RECOVERABLE. The manager detected a
  5436.    malfunction in the expanded memory hardware.
  5437.  
  5438.  AH = 84h      NON-RECOVERABLE.
  5439.    The function code passed to the memory manager is not defined.
  5440.  
  5441.  AH = 85h      RECOVERABLE.
  5442.    All EMM handles are being used.
  5443.  
  5444.  AH = 87h      RECOVERABLE.
  5445.    There aren't enough expanded memory pages present in the system to satisfy
  5446.    the operating system's request.
  5447.  
  5448.  AH = 88h      RECOVERABLE.
  5449.    There aren't enough unallocated pages to satisfy the operating system's
  5450.    request.
  5451.  
  5452.  AH = 8Fh      NON-RECOVERABLE.
  5453.    The subfunction parameter is invalid.
  5454.  
  5455.  EXAMPLE
  5456.  
  5457.  num_of_standard_pages_to_alloc  DW ?
  5458.  emm_handle                      DW ?
  5459.  
  5460.  MOV  BX, num_of_standard_pages_to_alloc
  5461.  MOV  AX, 5A00h                  ; load function code
  5462.  INT  67h                        ; call the memory manager
  5463.  OR   AH, AH                     ; check EMM status
  5464.  JNZ  emm_err_handler            ; jump to error handler
  5465.                                  ; on error
  5466.  MOV  emm_handle, DX             ; save handle
  5467.  
  5468.  
  5469.  FUNCTION 27  Allocate Raw Pages Subfunction
  5470.  
  5471.  PURPOSE
  5472.  
  5473.  The Allocate Raw Pages subfunction allocates the number of non-standard size
  5474.  pages that the operating system requests and assigns a unique EMM handle to
  5475.  these pages. The EMM handle owns these pages until the operating system
  5476.  deallocates them. This function allows you to allocate zero pages to a
  5477.  handle, unlike Function 4 (Allocate Pages).
  5478.  
  5479.  A hardware vendor may design an expanded memory board that has a page size
  5480.  which is a sub-multiple of 16K bytes. A physical page which is a sub-
  5481.  multiple of 16K is termed a raw page. The operating system may deal with
  5482.  page sizes which are sub-multiples of 16K bytes. The memory manager must
  5483.  treat any function using a handle with raw pages allocated to it by Allocate
  5484.  Raw Pages differently than it does a handle that has normal 16K-byte pages
  5485.  allocated to it.
  5486.  
  5487.  Handles which are assigned using Function 4 (Allocate pages) or Function
  5488.  27 (Allocate Standard Pages subfunction) must have pages which are 16K
  5489.  bytes──this is the length of a standard expanded memory page. If the
  5490.  expanded memory board hardware is not able to supply 16K-byte pages, the
  5491.  memory manager must emulate pages which are 16K bytes combining multiple
  5492.  non-standard size pages to form a single 16K-byte page.
  5493.  
  5494.  Handles which are assigned using Function 27 (Allocate Raw Pages) are
  5495.  called raw handles. All logical pages allocated to a raw handle may have a
  5496.  non-standard length (that is, not 16K bytes). However, once the operating
  5497.  system has allocated a number of raw pages to a handle, it is the
  5498.  responsibility of the memory manager to recognize that raw handle as one
  5499.  that has non-standard size pages allocated to it. The memory manager must
  5500.  identify these handles and treat all functions which use handles which have
  5501.  non-standard page lengths differently. The logical page length becomes the
  5502.  length of the non-standard size page for any raw handle that Function 27
  5503.  assigns.
  5504.  
  5505.  ────────────────────────────────────────────────────────────────────────────
  5506.  NOTE:
  5507.    This note affects expanded memory manager implementers and operating
  5508.    system developers only. Applications should not use the following
  5509.    characteristic of the memory manager. An application violating this rule
  5510.    will be incompatible with future versions of Microsoft's operating systems
  5511.    and environments.
  5512.  
  5513.    To be compatible with this specification, an expanded memory manager will
  5514.    provide a special handle which is available to the operating system only.
  5515.    This handle will have a value of 0000h and will have a set of pages
  5516.    allocated to it when the expanded memory manager driver installs. The
  5517.    pages that the memory manager will automatically allocate to handle 0000h
  5518.    are those that backfill conventional memory. Typically, this backfill
  5519.    occurs between addresses 40000h (256K) and 9FFFFh (640K). However, the
  5520.    range can extend below and above this limit if the hardware and memory
  5521.    manager have the capability.
  5522.  
  5523.    An operating system won't have to invoke Function 27 to obtain this
  5524.    handle because it can assume the handle already exists and is available
  5525.    for use immediately after the expanded memory device driver installs. When
  5526.    an operating system wants to use this handle, it uses the special handle
  5527.    value of 0000h. The operating system will be able to invoke any EMM
  5528.    function using this special handle value. To allocate pages to this
  5529.    handle, the operating system need only invoke Function 18 (Reallocate
  5530.    pages).
  5531.  
  5532.    There are two special cases for this handle:
  5533.  
  5534.      1.  Function 27 (Allocate Raw Pages). This function must never return
  5535.          zero as a handle value. Applications must always invoke Function 27
  5536.          to allocate pages and obtain a handle which identifies the pages
  5537.          which belong to it. Since Function 27 never returns a handle value
  5538.          of zero, an application will never gain access to this special
  5539.          handle.
  5540.  
  5541.      2.  Function 6 (Deallocate Pages). If the operating system uses it to
  5542.          deallocate the pages which are allocated to this special handle, the
  5543.          pages the handle owns will be returned to the manager for use. But
  5544.          the handle will not be available for reassignment. The manager
  5545.          should treat a deallocate pages function request for this handle the
  5546.          same as a reallocate pages function request, where the number of
  5547.          pages to reallocate to this handle is zero.
  5548.  ────────────────────────────────────────────────────────────────────────────
  5549.  
  5550.  CALLING PARAMETERS
  5551.  
  5552.  AX = 5A01h
  5553.    Contains the Allocate Raw Pages subfunction.
  5554.  
  5555.  BX = num_of_raw_pages_to_alloc
  5556.    Contains the number of raw pages the operating system wants to allocate.
  5557.  
  5558.  RESULTS
  5559.  
  5560.  These results are valid only if the status returned is zero.
  5561.  
  5562.  DX = raw handle
  5563.    Contains a unique EMM raw handle. The operating system must use this EMM
  5564.    raw handle as a parameter in any function that requires it. Up to 255
  5565.    handles may be obtained. (Both Function 4 and Function 27 must share the
  5566.    same 255 handles).
  5567.  
  5568.    For all functions using this raw handle, the length of the physical and
  5569.    logical pages allocated to it may be non-standard (that is, not 16K
  5570.    bytes).
  5571.  
  5572.  REGISTERS MODIFIED
  5573.  
  5574.  AX, DX
  5575.  
  5576.  STATUS
  5577.  
  5578.  AH = 0        SUCCESSFUL. The manager has allocated the raw
  5579.    pages to an assigned EMM raw handle.
  5580.  
  5581.  AH = 80h      NON-RECOVERABLE. The manager detected a
  5582.    malfunction in the memory manager software.
  5583.  
  5584.  AH = 81h      NON-RECOVERABLE. The manager detected a
  5585.    malfunction in the expanded memory hardware.
  5586.  
  5587.  AH = 84h      NON-RECOVERABLE.
  5588.    The function code passed to the memory manager is not defined.
  5589.  
  5590.  AH = 85h      RECOVERABLE.
  5591.    All EMM handles are being used.
  5592.  
  5593.  AH = 87h      RECOVERABLE.
  5594.    There aren't enough expanded memory raw pages present in the system to
  5595.    satisfy the operating system's request.
  5596.  
  5597.  AH = 88h      RECOVERABLE.
  5598.    There aren't enough unallocated raw pages to satisfy the operating
  5599.    system's request.
  5600.  
  5601.  AH = 8Fh      NON-RECOVERABLE.
  5602.    The subfunction parameter is invalid.
  5603.  
  5604.  EXAMPLE
  5605.  
  5606.  num_of_raw_pages_to_alloc       DW ?
  5607.  emm_raw_handle                  DW ?
  5608.  
  5609.  MOV  BX, num_of_raw_pages_to_alloc
  5610.  MOV  AX, 5A01h                  ; load function code
  5611.  INT  67h                        ; call the memory manager
  5612.  OR   AH, AH                     ; check EMM status
  5613.  JNZ  emm_err_handler            ; jump to error handler
  5614.                                  ; on error
  5615.  MOV  emm_raw_handle, DX         ; save raw handle
  5616.  
  5617.  
  5618.  FUNCTION 28  ALTERNATE MAP REGISTER SET
  5619.  
  5620.  ────────────────────────────────────────────────────────────────────────────
  5621.  NOTE:
  5622.    This function is for use by operating systems only. The operating system
  5623.    can disable this function at any time. Refer to Function 30 for a
  5624.    description of how an operating system can enable or disable this
  5625.    function.
  5626.  ────────────────────────────────────────────────────────────────────────────
  5627.  
  5628.  DESIGN CONSIDERATIONS
  5629.  
  5630.  The hardware support for the entire set of subfunctions described is
  5631.  generally not present on every expanded memory board from every vendor of
  5632.  expanded memory board products. For some of the subfunctions, software
  5633.  emulation is provided. For other subfunctions, a certain protocol in their
  5634.  use must be observed. The subfunctions for which this is most crucial are
  5635.  those which address system DMA capabilities.
  5636.  
  5637.  System DMA Capabilities & Expanded Memory Support of DMA
  5638.  
  5639.  In a multitasking operating system, when one task is waiting for DMA to
  5640.  complete, it is useful to be able to switch to another task. This
  5641.  specification describes a capability which may be designed into expanded
  5642.  memory boards to provide DMA into memory regions which may be mapped out
  5643.  while the DMA is occurring. For expanded memory boards that do not provide
  5644.  this, it is crucial to understand that while DMA is in progress into a
  5645.  region of mappable memory, the memory mapping context cannot be
  5646.  changed. That is, all DMA action must be complete before any remapping of
  5647.  pages can be done.
  5648.  
  5649.  Expanded Memory Support of DMA Register Sets
  5650.  
  5651.  Expanded memory boards which have DMA registers sets could support DMA into
  5652.  a region of mappable memory while the memory mapping context is being
  5653.  switched. It is important to realize that these DMA register sets are
  5654.  separate from the alternate map register sets. An example of how an OS/E
  5655.  might use DMA registers sets follows:
  5656.  
  5657.  Example 1
  5658.  
  5659.      1.  Allocate a DMA register set.
  5660.      2.  Get current register set.
  5661.      3.  Set the DMA register set.
  5662.      4.  Map in the memory desired.
  5663.      5.  Get the DMA register set.
  5664.      6.  Set the original register set.
  5665.      7.  Assign the desired DMA channel to the DMA register set.
  5666.  
  5667.  The preceding set of calls makes all DMA accesses for the desired DMA
  5668.  channel get mapped through the current DMA register set regardless of the
  5669.  current register set. In other words, the DMA register set overrides the
  5670.  current mapping register set for DMA operations on the DMA channel
  5671.  specified. A DMA channel that is not assigned to a DMA register set has all
  5672.  its DMA operations mapped through the current mapping register set.
  5673.  
  5674.  
  5675.  FUNCTION 28  Get Alternate Map Register Set Subfunction
  5676.  
  5677.  ────────────────────────────────────────────────────────────────────────────
  5678.  NOTE:
  5679.    This function is for use by operating systems only. The operating system
  5680.    can disable this function at any time. Refer to Function 30 for a
  5681.    description of how an operating system can enable or disable this
  5682.    function.
  5683.  ────────────────────────────────────────────────────────────────────────────
  5684.  
  5685.  PURPOSE
  5686.  
  5687.  The subfunction does one of two things depending on the map register set
  5688.  which is active at the time this function is invoked:
  5689.  
  5690.      1.  If the preceding Set Alternate Map Register Set call was done with
  5691.          the alternate map register set equal to zero (BL = 0), these points
  5692.          apply:
  5693.  
  5694.          a. The context save area pointer saved within EMM by the Set
  5695.             Alternate Map Register Set subfunction is returned by this call.
  5696.             This pointer is always returned for boards which do not supply
  5697.             alternate mapping register sets.
  5698.  
  5699.          b. If the context save area pointer returned is not equal to zero,
  5700.             this subfunction copies the contents of the mapping registers on
  5701.             each expanded memory board in the system into the save area
  5702.             specified by the pointer. The format of this save area is the
  5703.             same as that returned by Function 15 (Get Page Map subfunction).
  5704.             This is intended to simulate getting an alternate map register
  5705.             set. Note that the memory manager does not allocate the space for
  5706.             the context: the operating system must do so.
  5707.  
  5708.          c. If the context save area pointer returned is equal to zero, this
  5709.             subfunction does not copy the contents of the mapping registers
  5710.             on each expanded memory board in the system into the save area
  5711.             specified by the pointer.
  5712.  
  5713.          d. The context save area pointer must have been initialized by a
  5714.             previous Set Alternate Map Register Set call. Note that the value
  5715.             of the context save area pointer saved within EMM is zero
  5716.             immediately after installation.
  5717.  
  5718.          e. The context save area must be initialized by a previous Get Page
  5719.             Map call (Function 15).
  5720.  
  5721.      2.  If the preceding Set Alternate Map Register Set call was done with
  5722.          the alternate map register set greater than zero (BL > 0), then the
  5723.          number of the alternate map register set which is in use at the time
  5724.          that this function is invoked is returned. The context save area
  5725.          pointer is not returned in this case.
  5726.  
  5727.  CALLING PARAMETERS
  5728.  
  5729.  AX = 5B00h
  5730.    Contains the Get Alternate Map Register Set subfunction.
  5731.  
  5732.  RESULTS
  5733.  
  5734.  These results are valid only if the status returned is zero.
  5735.  
  5736.  IF (BL <> 0) current active alternate map register set number
  5737.    Contains the alternate map register set which was active at the time that
  5738.    this function was invoked.
  5739.  
  5740.  ES:DI         Unaffected.
  5741.  
  5742.  IF (BL = 0)
  5743.    Indicates that a pointer to an area which contains the state of all the
  5744.    map registers on all boards in the system, and any additional information
  5745.    necessary to restore the boards to their original state, has been
  5746.    returned.
  5747.  
  5748.  ES:DI = pointer to a map register context save area
  5749.    Contains a pointer to an operating system supplied context save area. The
  5750.    pointer is in standard segment:offset format. This pointer is always
  5751.    returned if the expanded memory hardware does not supply alternate mapping
  5752.    register sets.
  5753.  
  5754.    The operating system first passes this pointer to the memory manager
  5755.    whenever it invokes a Set Alternate Map Register Set subfunction (the
  5756.    description follows). If the OS/E invokes this function before invoking a
  5757.    Set Alternate Map Register Set subfunction, this function returns a
  5758.    pointer value of zero. The OS/E must have allocated the space for the save
  5759.    area. However, the OS must request that the memory manager initialize the
  5760.    contents of this save area before it contains any useful information.
  5761.  
  5762.    The OS/E must initialize the save area it has allocated by invoking
  5763.    Function 15 (Get Page Map subfunction). After the OS/E has done this, the
  5764.    save area will contain the state of all the map registers on all boards in
  5765.    the system. The save area will also contain any additional information
  5766.    necessary to restore the boards to their original state when the operating
  5767.    system invokes a Set Alternate Map Register Set subfunction.
  5768.  
  5769.  REGISTERS MODIFIED
  5770.  
  5771.  AX, BX, ES:DI
  5772.  
  5773.  STATUS
  5774.  
  5775.  AH = 0        SUCCESSFUL.
  5776.    The manager got the alternate map register set.
  5777.  
  5778.  AH = 80h      NON-RECOVERABLE.
  5779.    The manager detected a malfunction in the memory manager software.
  5780.  
  5781.  AH = 81h      NON-RECOVERABLE.
  5782.    The manager detected a malfunction in the expanded memory hardware.
  5783.  
  5784.  AH = 84h      NON-RECOVERABLE.
  5785.    The function code passed to the memory manager is not defined.
  5786.  
  5787.  AH = 8Fh      NON-RECOVERABLE.
  5788.    The subfunction parameter is invalid.
  5789.  
  5790.  AH = A4h      NON-RECOVERABLE.
  5791.    The operating system denied access to this function. The function cannot
  5792.    be used at this time.
  5793.  
  5794.  EXAMPLE
  5795.  
  5796.  alt_map_reg_set                     DB ?
  5797.  context_save_area_ptr_seg           DW ?
  5798.  context_save_area_ptr_offset        DW ?
  5799.  
  5800.  MOV  AX, 5B00h                      ; load function code
  5801.  INT  67h                            ; call the memory manager
  5802.  OR   AH, AH                         ; check EMM status
  5803.  JNZ  emm_err_handler                ; jump to error handler
  5804.                                      ; on error
  5805.  MOV  alt_map_reg_set, BL
  5806.  TEST BL, BL
  5807.  JNZ  no_ptr_returned
  5808.  MOV  context_save_area_ptr_seg, ES  ; save pointer values
  5809.  MOV  context_save_area_ptr_offset,  DI
  5810.  no_ptr_returned:
  5811.  
  5812.  
  5813.  FUNCTION 28  Set Alternate Map Register Set Subfunction
  5814.  
  5815.  ────────────────────────────────────────────────────────────────────────────
  5816.  NOTE:
  5817.    This function is for use by operating systems only. The operating system
  5818.    can disable this function at any time. Refer to Function 30 for a
  5819.    description of how an operating system can enable or disable this
  5820.    function.
  5821.  ────────────────────────────────────────────────────────────────────────────
  5822.  
  5823.  PURPOSE
  5824.  
  5825.  The subfunction does one of two things, depending on the map register set
  5826.  specified:
  5827.  
  5828.      1.  If the alternate map register set specified is zero, map register
  5829.          set zero is activated. If the map register context restore area
  5830.          pointer is not equal to zero, the contents of the restore area
  5831.          pointed to by ES:DI are copied into register set zero on each
  5832.          expanded memory board in the system. If the pointer is equal to
  5833.          zero, the contents are not copied.
  5834.  
  5835.          Regardless of its value, the map register context restore area
  5836.          pointer is saved within the memory manager. It will be used during
  5837.          the Get Alternate Map Register Set subfunction.
  5838.  
  5839.          The operating system must supply the pointer to the area. This
  5840.          subfunction is intended to simulate setting an alternate map
  5841.          register set. Note that the operating system must allocate the space
  5842.          for the context. The memory manager saves the context save area
  5843.          pointer internally.
  5844.  
  5845.      2.  If the alternate map register set specified is not zero, the
  5846.          alternate map register set specified is activated. The restore area,
  5847.          which the operating system is pointing to, is not used.
  5848.  
  5849.  CALLING PARAMETERS
  5850.  
  5851.  AX = 5B01h
  5852.    Contains the Set Alternate Map subfunction.
  5853.  
  5854.  BL = new alternate map register set number
  5855.    Contains the number of the alternate map register set which is to be
  5856.    activated.
  5857.  
  5858.      If BL <> 0
  5859.          A pointer to a map register context restore area is not required and
  5860.          the contents of ES:DI are unaffected and ignored. The alternate map
  5861.          register set specified in BL is activated if the board supports it.
  5862.  
  5863.      If BL = 0
  5864.          A pointer to an area which contains the state of all the map
  5865.          registers on all boards in the system, and any additional
  5866.          information necessary to restore the boards to their original state,
  5867.          has been passed in ES:DI.
  5868.  
  5869.  ES:DI = pointer to a map register context restore area
  5870.    Contains a pointer to an OS/E supplied map register context restore area.
  5871.    The pointer is in standard segment:offset format. This pointer must always
  5872.    be passed if the expanded memory hardware does not supply alternate
  5873.    mapping register sets.
  5874.  
  5875.    The memory manager must save this pointer whenever the OS/E invokes this
  5876.    function. The OS/E must have allocated the space for the restore area.
  5877.    Additionally, the contents of this restore area must have been initialized
  5878.    by the memory manager before it will contain any useful information. The
  5879.    OS/E initializes the restore area it has allocated by invoking Function
  5880.    15 (Get Page Map subfunction). After the OS/E has done this, the restore
  5881.    area will contain the state of the map registers on all boards in the
  5882.    system, and any additional information necessary to restore the boards to
  5883.    their original state when the operating system invokes a Set Alternate
  5884.    Map Register Set subfunction.
  5885.  
  5886.  REGISTERS MODIFIED
  5887.  
  5888.  AX
  5889.  
  5890.  STATUS
  5891.  
  5892.  AH = 0        SUCCESSFUL.
  5893.    The manager set the alternate map register set.
  5894.  
  5895.  AH = 80h      NON-RECOVERABLE.
  5896.    The manager detected a malfunction in the memory manager software.
  5897.  
  5898.  AH = 81h      NON-RECOVERABLE.
  5899.    The manager detected a malfunction in the expanded memory hardware.
  5900.  
  5901.  AH = 84h      NON-RECOVERABLE.
  5902.    The function code passed to the memory manager is not defined.
  5903.  
  5904.  AH = 8Fh      NON-RECOVERABLE.
  5905.    The subfunction parameter is invalid.
  5906.  
  5907.  AH = 9Ah      NON-RECOVERABLE.
  5908.    Alternate map register sets are supported, but the alternate map register
  5909.    set specified is not supported.
  5910.  
  5911.  AH = 9Ch      NON-RECOVERABLE.
  5912.    Alternate map register sets are not supported, and the alternate map
  5913.    register set specified is not zero.
  5914.  
  5915.  AH = 9Dh      NON-RECOVERABLE.
  5916.    Alternate map register sets are supported, but the alternate map register
  5917.    set specified is either not defined or not allocated.
  5918.  
  5919.  AH = A3h      NON-RECOVERABLE.
  5920.    The contents of the source array have been corrupted, or the pointer
  5921.    passed to the subfunction is invalid.
  5922.  
  5923.  AH = A4h      NON-RECOVERABLE.
  5924.    The operating system has denied access to this function. The function
  5925.    cannot be used at this time.
  5926.  
  5927.  EXAMPLE
  5928.  
  5929.  alt_map_reg_set                 DB ?
  5930.  context_restore_area_ptr_seg    DW ?
  5931.  context_restore_area_ptr_offset DW ?
  5932.  
  5933.  MOV  AX, 5B01h                  ; load function code
  5934.  MOV  BL, alt_map_reg_set
  5935.  TEST BL, BL
  5936.  JZ   no_ptr_passed
  5937.  
  5938.  MOV  ES, context_restore_area_ptr_seg
  5939.  MOV  DI, context_restore_area_ptr_offset
  5940.  
  5941.  no_ptr_passed:
  5942.  
  5943.  INT  67h                        ; call the memory manager
  5944.  OR   AH, AH                     ; check EMM status
  5945.  JNZ  emm_err_handler            ; jump to error handler
  5946.                                  ; on error
  5947.  
  5948.  
  5949.  FUNCTION 28  Get Alternate Map Save Array Size Subfunction
  5950.  
  5951.  ────────────────────────────────────────────────────────────────────────────
  5952.  NOTE:
  5953.    This function is for use by operating systems only. The operating system
  5954.    can disable this function at any time. Refer to Function 30 for a
  5955.    description of how an operating system can enable or disable this
  5956.    function.
  5957.  ────────────────────────────────────────────────────────────────────────────
  5958.  
  5959.  PURPOSE
  5960.  
  5961.  This subfunction returns the storage requirements for the map register
  5962.  context save area referenced by the other subfunctions.
  5963.  
  5964.  CALLING PARAMETERS
  5965.  
  5966.  AX = 5B02h
  5967.    Contains the Get Alternate Map Save Array Size subfunction.
  5968.  
  5969.  RESULTS
  5970.  
  5971.  These results are valid only if the status returned is zero.
  5972.  
  5973.  DX = size_of_array
  5974.    Contains the number of bytes that will be transferred to the memory area
  5975.    supplied by an operating system whenever an operating system requests the
  5976.    Get, Set, or Get and Set subfunction.
  5977.  
  5978.  REGISTERS MODIFIED
  5979.  
  5980.  AX, DX
  5981.  
  5982.  STATUS
  5983.  
  5984.  AH = 0        SUCCESSFUL.
  5985.    The manager has returned the array size.
  5986.  
  5987.  AH = 80h      NON-RECOVERABLE.
  5988.    The manager detected a malfunction in the memory manager software.
  5989.  
  5990.  AH = 81h      NON-RECOVERABLE.
  5991.    The manager detected a malfunction in the expanded memory hardware.
  5992.  
  5993.  AH = 84h      NON-RECOVERABLE.
  5994.    The function code passed to the memory manager is not defined.
  5995.  
  5996.  AH = 8Fh      NON-RECOVERABLE.
  5997.    The subfunction parameter is invalid.
  5998.  
  5999.  AH = A4h      NON-RECOVERABLE.
  6000.    The operating system has denied access to this function. The function
  6001.    cannot be used at this time.
  6002.  
  6003.  EXAMPLE
  6004.  
  6005.  size_of_array            DW ?
  6006.  
  6007.  MOV   AX, 5B02h          ; load function code
  6008.  INT   67h                ; call the memory manager
  6009.  OR    AH, AH             ; check EMM status
  6010.  JNZ   emm_err_handler    ; jump to error handler on error
  6011.  MOV   size_of_array, DX  ; save size of array
  6012.  
  6013.  
  6014.  FUNCTION 28  Allocate Alternate Map Register Set Subfunction
  6015.  
  6016.  ────────────────────────────────────────────────────────────────────────────
  6017.  NOTE:
  6018.    This function is for use by operating systems only. The operating system
  6019.    can disable this function at any time. Refer to Function 30 for a
  6020.    description of how an operating system can enable or disable this
  6021.    function.
  6022.  ────────────────────────────────────────────────────────────────────────────
  6023.  
  6024.  PURPOSE
  6025.  
  6026.  The Allocate Alternate Map Register Set subfunction gets the number of an
  6027.  alternate map register set for an operating system if an alternate map
  6028.  register set is currently available for use. If the hardware does not
  6029.  support alternate map register sets, an alternate map register set number of
  6030.  zero will be returned.
  6031.  
  6032.  The alternate map register set allocated may be referred to by this number
  6033.  when using the Get or Set Alternate Map Register Set subfunctions. The
  6034.  operating system can use these subfunctions to switch map contexts very
  6035.  rapidly on expanded memory boards with alternate map register sets.
  6036.  
  6037.  This subfunction copies the currently active alternate map register sets
  6038.  contents into the newly allocated alternate map register set's mapping
  6039.  registers. This is done so that when the OS/E performs a Set Alternate Map
  6040.  Register Set subfunction the memory mapped before the allocation of the new
  6041.  alternate map will be available for reading and writing. This function does
  6042.  not actually change the alternate map register set in use, but in addition
  6043.  to allocating a new alternate map register set, it prepares the new
  6044.  alternate map register set for a subsequent Set Alternate Map Register Set
  6045.  subfunction.
  6046.  
  6047.  CALLING PARAMETERS
  6048.  
  6049.  AX = 5B03h
  6050.    Contains the Allocate Alternate Map Register Set subfunction.
  6051.  
  6052.  RESULTS
  6053.  
  6054.  These results are valid only if the status returned is zero.
  6055.  
  6056.  BL = alternate map register set number
  6057.    Contains the number of an alternate map register set. If there are no
  6058.    alternate map register sets supported by the hardware, a zero will be
  6059.    returned. In this case, the Get Alternate Map function (Function 28)
  6060.    should be invoked in order to obtain a pointer to a map register context
  6061.    save area. The OS/E must supply this save area. The save area is necessary
  6062.    because the hardware doesn't support alternate map register sets.
  6063.  
  6064.  REGISTERS MODIFIED
  6065.  
  6066.  AX, BX
  6067.  
  6068.  STATUS
  6069.  
  6070.  AH = 0        SUCCESSFUL.
  6071.    The manager has returned the array size.
  6072.  
  6073.  AH = 80h      NON-RECOVERABLE.
  6074.    The manager detected a malfunction in the memory manager software.
  6075.  
  6076.  AH = 81h      NON-RECOVERABLE.
  6077.    The manager detected a malfunction in the expanded memory hardware.
  6078.  
  6079.  AH = 84h      NON-RECOVERABLE.
  6080.    The function code passed to the memory manager is not defined.
  6081.  
  6082.  AH = 8Fh      NON-RECOVERABLE.
  6083.    The subfunction parameter is invalid.
  6084.  
  6085.  AH = 9Bh      NON-RECOVERABLE.
  6086.    Alternate map register sets are supported. However, all alternate map
  6087.    register sets are currently allocated.
  6088.  
  6089.  AH = A4h      NON-RECOVERABLE.
  6090.    The operating system has denied access to this function. The function
  6091.    cannot be used at this time.
  6092.  
  6093.  EXAMPLE
  6094.  
  6095.  alt_map_reg_num            DB ?
  6096.  
  6097.  MOV   AX, 5B03h            ; load function code
  6098.  INT   67h                  ; call the memory manager
  6099.  OR    AH, AH               ; check EMM status
  6100.  JNZ   emm_err_handler      ; jump to error handler on error
  6101.  MOV   alt_map_reg_num, BL  ; save number of
  6102.                             ; alternate map register set
  6103.  
  6104.  
  6105.  FUNCTION 28  Deallocate Alternate Map Register Set Subfunction
  6106.  
  6107.  ────────────────────────────────────────────────────────────────────────────
  6108.  NOTE:
  6109.    This function is for use by operating systems only. The operating system
  6110.    can disable this function at any time. Refer to Function 30 for a
  6111.    description of how an operating system can enable or disable this
  6112.    function.
  6113.  ────────────────────────────────────────────────────────────────────────────
  6114.  
  6115.  PURPOSE
  6116.  
  6117.  The Deallocate Alternate Map Register Set subfunction returns the alternate
  6118.  map register set to the memory manager for future use. The memory manager
  6119.  may reallocate the alternate map register set when needed.
  6120.  
  6121.  This subfunction also makes the mapping context of the alternate map
  6122.  register specified unavailable for reading or writing (unmapping). This
  6123.  protects the pages previously mapped in an alternate map register set by
  6124.  making them inaccessible. Note that the current alternate map register set
  6125.  cannot be deallocated. This makes all memory which was currently mapped into
  6126.  conventional and expanded memory inaccessible.
  6127.  
  6128.  CALLING PARAMETERS
  6129.  
  6130.  AX = 5B04h
  6131.    Contains the Deallocate Alternate Map Register Set subfunction.
  6132.  
  6133.  BL = alternate register set number
  6134.    Contains the number of the alternate map register set to deallocate. Map
  6135.    register set zero cannot be allocated or deallocated. However, if
  6136.    alternate map register set zero is specified and this subfunction is
  6137.    invoked, no error will be returned. The function invocation is ignored in
  6138.    this case.
  6139.  
  6140.  REGISTERS MODIFIED
  6141.  
  6142.  AX
  6143.  
  6144.  STATUS
  6145.  
  6146.  AH = 0        SUCCESSFUL.
  6147.    The manager has returned the array size.
  6148.  
  6149.  AH = 80h      NON-RECOVERABLE.
  6150.    The manager detected a malfunction in the memory manager software.
  6151.  
  6152.  AH = 81h      NON-RECOVERABLE.
  6153.    The manager detected a malfunction in the expanded memory hardware.
  6154.  
  6155.  AH = 84h      NON-RECOVERABLE.
  6156.    The function code passed to the memory manager is not defined.
  6157.  
  6158.  AH = 8Fh      NON-RECOVERABLE.
  6159.    The subfunction parameter is invalid.
  6160.  
  6161.  AH = 9Ch      NON-RECOVERABLE.
  6162.    Alternate map register sets are not supported and the alternate map
  6163.    register set specified is not zero.
  6164.  
  6165.  AH = 9Dh      NON-RECOVERABLE.
  6166.    Alternate map register sets are supported, but the alternate map register
  6167.    set specified is either not defined or not allocated.
  6168.  
  6169.  AH = A4h      NON-RECOVERABLE.
  6170.    The operating system has denied access to this function. The function
  6171.    cannot be used at this time.
  6172.  
  6173.  EXAMPLE
  6174.  
  6175.  alternate_map_reg_set           DB ?
  6176.  
  6177.  MOV  BL, alternate_map_reg_set  ; specify alternate map
  6178.                                  ; register set
  6179.  MOV  AX, 5B04h                  ; load function code
  6180.  INT  67h                        ; call the memory manager
  6181.  OR   AH, AH                     ; check EMM status
  6182.  JNZ  emm_err_handler            ; jump to error handler
  6183.                                  ; on error
  6184.  
  6185.  
  6186.  FUNCTION 28  Allocate DMA Register Set Subfunction
  6187.  
  6188.  ────────────────────────────────────────────────────────────────────────────
  6189.  NOTE:
  6190.    This function is for use by operating systems only. The operating system
  6191.    can disable this function at any time. Refer to Function 30 for a
  6192.    description of how an operating system can enable or disable this
  6193.    function.
  6194.  ────────────────────────────────────────────────────────────────────────────
  6195.  
  6196.  PURPOSE
  6197.  
  6198.  The Allocate DMA Register Set subfunction gets the number of a DMA register
  6199.  set for an OS/E, if a DMA register set is currently available for use. If
  6200.  the hardware does not support DMA register sets, a DMA register set number
  6201.  of zero will be returned.
  6202.  
  6203.  In a multitasking operating system, when one task is waiting for DMA to
  6204.  complete, it is useful to be able to switch to another task. However, if the
  6205.  DMA is being mapped through the current register set, the switching cannot
  6206.  occur. That is, all DMA action must be complete before any remapping of
  6207.  pages can be done.
  6208.  
  6209.  The operating system would initiate a DMA operation on a specific DMA
  6210.  channel using a specific alternate map register set. This alternate map
  6211.  register set would not be used again, by the operating system or an
  6212.  application, until after the DMA operation is complete. The operating system
  6213.  guarantees this by not changing the contents of the alternate map register
  6214.  set, or allowing an application to change the contents of the alternate map
  6215.  register set, for the duration of the DMA operation.
  6216.  
  6217.  CALLING PARAMETERS
  6218.  
  6219.  AX = 5B05h
  6220.    Contains the Allocate DMA Register Set subfunction.
  6221.  
  6222.  RESULTS
  6223.  
  6224.  These results are valid only if the status returned is zero.
  6225.  
  6226.  BL = DMA register set number
  6227.    Contains the number of a DMA register set. If there are no DMA register
  6228.    sets supported by the hardware, a zero will be returned.
  6229.  
  6230.  REGISTERS MODIFIED
  6231.  
  6232.  AX, BX
  6233.  
  6234.  STATUS
  6235.  
  6236.  AH = 0        SUCCESSFUL.
  6237.    The manager has allocated the DMA register set.
  6238.  
  6239.  AH = 80h      NON-RECOVERABLE.
  6240.    The manager detected a malfunction in the memory manager software.
  6241.  
  6242.  AH = 81h      NON-RECOVERABLE.
  6243.    The manager detected a malfunction in the expanded memory hardware.
  6244.  
  6245.  AH = 84h      NON-RECOVERABLE.
  6246.    The function code passed to the memory manager is not defined.
  6247.  
  6248.  AH = 8Fh   NON-RECOVERABLE.
  6249.    The subfunction parameter is invalid.
  6250.  
  6251.  AH = 9Bh   NON-RECOVERABLE.
  6252.    DMA register sets are supported. However, all DMA register sets are
  6253.    currently allocated.
  6254.  
  6255.  AH = A4h      NON-RECOVERABLE.
  6256.    Access to this function has been denied by the operating system. The
  6257.    function cannot be used at this time.
  6258.  
  6259.  EXAMPLE
  6260.  
  6261.  DMA_reg_set_number              DB ?
  6262.  
  6263.  MOV  AX, 5B05h                  ; load function code
  6264.  INT  67h                        ; call memory manager
  6265.  OR   AH, AH                     ; check EMM status
  6266.  JNZ  emm_err_handler            ; jump to error handler
  6267.                                  ; on error
  6268.  MOV  DMA_reg_set_number, BL     ; save number of DMA
  6269.                                  ; register set
  6270.  
  6271.  
  6272.  FUNCTION 28  Enable DMA On Alternate Map Register Set Subfunction
  6273.  
  6274.  ────────────────────────────────────────────────────────────────────────────
  6275.  NOTE:
  6276.    This function is for use by operating systems only. The operating system
  6277.    can disable this function at any time. Refer to Function 30 for a
  6278.    description of how an operating system can enable or disable this
  6279.    function.
  6280.  ────────────────────────────────────────────────────────────────────────────
  6281.  
  6282.  PURPOSE
  6283.  
  6284.  This subfunction allows DMA accesses on a specific DMA channel to be
  6285.  associated with a specific alternate map register set. In a multitasking
  6286.  operating system, when a task is waiting for the completion of DMA, it is
  6287.  useful to be able to switch to another task until the DMA operation
  6288.  completes.
  6289.  
  6290.  Any DMA on the specified channel will go through the specified DMA register
  6291.  set regardless of the current register set. If a DMA channel is not assigned
  6292.  to a DMA register set, DMA for that channel will be mapped through the
  6293.  current register set.
  6294.  
  6295.  CALLING PARAMETERS
  6296.  
  6297.  AX = 5B06h
  6298.    Contains the Enable DMA on Alternate Map Register Set subfunction.
  6299.  
  6300.  BL = DMA register set number
  6301.    Contains the number of the alternate map register set to be used for DMA
  6302.    operations on the DMA channel specified by DL. If the alternate map
  6303.    register set specified is zero, no special action will be taken on DMA
  6304.    accesses for the DMA channel specified.
  6305.  
  6306.  DL = DMA channel number
  6307.    Contains the DMA channel which is to be associated with the DMA map
  6308.    register set specified in BL.
  6309.  
  6310.  REGISTERS MODIFIED
  6311.  
  6312.  AX
  6313.  
  6314.  STATUS
  6315.  
  6316.  AH = 0        SUCCESSFUL.
  6317.    The manager has enabled DMA on the DMA register set and the DMA channel
  6318.    specified.
  6319.  
  6320.  AH = 80h      NON-RECOVERABLE.
  6321.    The manager detected a malfunction in the memory manager software.
  6322.  
  6323.  AH = 81h      NON-RECOVERABLE.
  6324.    The manager detected a malfunction in the expanded memory hardware.
  6325.  
  6326.  AH = 84h      NON-RECOVERABLE.
  6327.    The function code passed to the memory manager is not defined.
  6328.  
  6329.  AH = 8Fh      NON-RECOVERABLE.
  6330.    The subfunction parameter is invalid.
  6331.  
  6332.  AH = 9Ah      NON-RECOVERABLE.
  6333.    Alternate DMA register sets are supported, but the alternate DMA register
  6334.    set specified is not supported.
  6335.  
  6336.  AH = 9Ch      NON-RECOVERABLE.
  6337.    Alternate DMA register sets are not supported, and the DMA register set
  6338.    specified is not zero.
  6339.  
  6340.  AH = 9Dh      NON-RECOVERABLE.
  6341.    DMA register sets are supported, but the DMA register set specified is
  6342.    either not defined or not allocated.
  6343.  
  6344.  AH = 9Eh      NON-RECOVERABLE.
  6345.    Dedicated DMA channels are not supported.
  6346.  
  6347.  AH = 9Fh      NON-RECOVERABLE.
  6348.    Dedicated DMA channels are supported. But the DMA channel specified is not
  6349.    supported.
  6350.  
  6351.  AH = A4h      NON-RECOVERABLE.
  6352.    The operating system has denied access to this function. The function
  6353.    cannot be used at this time.
  6354.  
  6355.  EXAMPLE
  6356.  
  6357.  alt_map_reg_set          DB ?
  6358.  DMA_channel_num          DB ?
  6359.  
  6360.  MOV   BL, alt_map_reg_set
  6361.  MOV   DL, DMA_channel_num
  6362.  MOV   AX, 5B06h          ; load function code
  6363.  INT   67h                ; call the memory manager
  6364.  OR    AH, AH             ; check EMM status
  6365.  JNZ   emm_err_handler    ; jump to error handler on error
  6366.  
  6367.  
  6368.  FUNCTION 28  Disable DMA On Alternate Map Register Set Subfunction
  6369.  
  6370.  ────────────────────────────────────────────────────────────────────────────
  6371.  NOTE:
  6372.    This function is for use by operating systems only. The operating system
  6373.    can disable this function at any time. Refer to Function 30 for a
  6374.    description of how an operating system can enable or disable this
  6375.    function.
  6376.  ────────────────────────────────────────────────────────────────────────────
  6377.  
  6378.  PURPOSE
  6379.  
  6380.  This subfunction disables DMA accesses for all DMA channels which were
  6381.  associated with a specific alternate map register set.
  6382.  
  6383.  CALLING PARAMETERS
  6384.  
  6385.  AX = 5B07h
  6386.    Contains the Disable DMA on Alternate Map Register Set subfunction.
  6387.  
  6388.  BL = alternate register set number
  6389.    Contains the number of the DMA register set for which all operations are
  6390.    to be disabled. If the alternate map register set specified is zero, no
  6391.    action will be taken.
  6392.  
  6393.  REGISTERS MODIFIED
  6394.  
  6395.  AX
  6396.  
  6397.  STATUS
  6398.  
  6399.  AH = 0        SUCCESSFUL.
  6400.    The manager has returned the array size.
  6401.  
  6402.  AH = 80h      NON-RECOVERABLE.
  6403.    The manager detected a malfunction in the memory manager software.
  6404.  
  6405.  AH = 81h      NON-RECOVERABLE.
  6406.    The manager detected a malfunction in the expanded memory hardware.
  6407.  
  6408.  AH = 84h      NON-RECOVERABLE.
  6409.    The function code passed to the memory manager is not defined.
  6410.  
  6411.  AH = 8Fh      NON-RECOVERABLE.
  6412.    The subfunction parameter is invalid.
  6413.  
  6414.  AH = 9Ah      NON-RECOVERABLE.
  6415.    Alternate DMA register sets are supported, but the alternate DMA register
  6416.    set specified is not supported.
  6417.  
  6418.  AH = 9Ch      NON-RECOVERABLE.
  6419.    Alternate DMA register sets are not supported, and the DMA register set
  6420.    specified is not zero.
  6421.  
  6422.  AH = 9Dh      NON-RECOVERABLE.
  6423.    DMA register sets are supported, but the DMA register set specified is
  6424.    either not defined or not allocated.
  6425.  
  6426.  AH = 9Eh      NON-RECOVERABLE.
  6427.    Dedicated DMA channels are not supported.
  6428.  
  6429.  AH = 9Fh      NON-RECOVERABLE.
  6430.    Dedicated DMA channels are supported, but the DMA channel specified is not
  6431.    supported.
  6432.  
  6433.  AH = A4h      NON-RECOVERABLE.
  6434.    The operating system has denied access to this function. The function
  6435.    cannot be used at this time.
  6436.  
  6437.  EXAMPLE
  6438.  
  6439.  DMA_reg_set              DB ?
  6440.  
  6441.  MOV   BL, DMA_reg_set
  6442.  MOV   AX, 5B07h          ; load function code
  6443.  INT   67h                ; call the memory manager
  6444.  OR    AH, AH             ; check EMM status
  6445.  JNZ   emm_err_handler    ; jump to error handler on error
  6446.  
  6447.  
  6448.  FUNCTION 28  Deallocate DMA Register Set Subfunction
  6449.  
  6450.  ────────────────────────────────────────────────────────────────────────────
  6451.  NOTE:
  6452.    This function is for use by operating systems only. The operating system
  6453.    can disable this function at any time. Refer to Function 30 for a
  6454.    description of how an operating system can enable or disable this
  6455.    function.
  6456.  ────────────────────────────────────────────────────────────────────────────
  6457.  
  6458.  PURPOSE
  6459.  
  6460.  The Deallocate DMA Register Set subfunction deallocates the specified DMA
  6461.  register set.
  6462.  
  6463.  CALLING PARAMETERS
  6464.  
  6465.  AX = 5B08h
  6466.    Contains the Deallocate DMA Register Set subfunction.
  6467.  
  6468.  BL = DMA register set number
  6469.    Contains the number of the DMA register set which should not be used for
  6470.    DMA operations any longer. The DMA register set would have been previously
  6471.    allocated and enabled for DMA operations on a specific DMA channel. If the
  6472.    DMA register set specified is zero, no action will be taken.
  6473.  
  6474.  REGISTERS MODIFIED
  6475.  
  6476.  AX
  6477.  
  6478.  STATUS
  6479.  
  6480.  AH = 0        SUCCESSFUL.
  6481.    The manager has deallocated the DMA register set.
  6482.  
  6483.  AH = 80h      NON-RECOVERABLE.
  6484.    The manager detected a malfunction in the memory manager software.
  6485.  
  6486.  AH = 81h      NON-RECOVERABLE.
  6487.    The manager detected a malfunction in the expanded memory hardware.
  6488.  
  6489.  AH = 84h      NON-RECOVERABLE.
  6490.    The function code passed to the memory manager is not defined.
  6491.  
  6492.  AH = 8Fh      NON-RECOVERABLE.
  6493.    The subfunction parameter is invalid.
  6494.  
  6495.  AH = 9Ch      NON-RECOVERABLE.
  6496.    DMA register sets are not supported, and the DMA register set specified is
  6497.    not zero.
  6498.  
  6499.  AH = 9Dh      NON-RECOVERABLE.
  6500.    DMA register sets are supported, but the DMA register set specified is
  6501.    either not defined or not allocated.
  6502.  
  6503.  AH = A4h      NON-RECOVERABLE.
  6504.    The operating system has denied access to this function. The function
  6505.    cannot be used at this time.
  6506.  
  6507.  EXAMPLE
  6508.  
  6509.  DMA_reg_set_num          DB  ?
  6510.  
  6511.  MOV   DMA_reg_set_num, BL
  6512.  MOV   AX, 5B08h          ; load function code
  6513.  INT   67h                ; call memory manager
  6514.  OR    AH, AH             ; check EMM status
  6515.  JNZ   emm_err_handler    ; jump to error handler on error
  6516.  
  6517.  
  6518.  FUNCTION 29  PREPARE EXPANDED MEMORY HARDWARE FOR WARM BOOT
  6519.  
  6520.  PURPOSE
  6521.  
  6522.  This function prepares the expanded memory hardware for an impending warm
  6523.  boot. This function assumes that the next operation that the operating
  6524.  system performs is a warm boot of the system. In general, this function will
  6525.  effect the current mapping context, the alternate register set in use, and
  6526.  any other expanded memory hardware dependencies which need to be initialized
  6527.  at boot time. If an application decides to map memory below 640K, the
  6528.  application must trap all possible conditions
  6529.  leading to a warm boot and invoke this function before performing the warm
  6530.  boot itself.
  6531.  
  6532.  CALLING PARAMETERS
  6533.  
  6534.  AH = 5Ch
  6535.    Contains the Prepare for Warmboot function.
  6536.  
  6537.  REGISTERS MODIFIED
  6538.  
  6539.  AX
  6540.  
  6541.  STATUS
  6542.  
  6543.  AH = 0        SUCCESSFUL.
  6544.    The manager has prepared the expanded memory hardware for a warm boot.
  6545.  
  6546.  AH = 80h      NON-RECOVERABLE.
  6547.    The manager detected a malfunction in the memory manager software.
  6548.  
  6549.  AH = 81h      NON-RECOVERABLE.
  6550.    The manager detected a malfunction in the expanded memory hardware.
  6551.  
  6552.  AH = 84h      NON-RECOVERABLE.
  6553.    The function code passed to the memory manager is not defined.
  6554.  
  6555.  EXAMPLE
  6556.  
  6557.  MOV   AH, 5Ch            ; load function code
  6558.  INT   67h                ; call the memory manager
  6559.  OR    AH, AH             ; check EMM status
  6560.  JNZ   emm_err_handler    ; jump to error handler on error
  6561.  
  6562.  
  6563.  FUNCTION 30  ENABLE/DISABLE OS/E FUNCTION SET FUNCTIONS Enable OS/E Function
  6564.               Set Subfunction
  6565.  
  6566.  ────────────────────────────────────────────────────────────────────────────
  6567.  NOTE:
  6568.    This function is for use by operating systems only. The operating system
  6569.    can disable this function at any time.
  6570.  ────────────────────────────────────────────────────────────────────────────
  6571.  
  6572.  PURPOSE
  6573.  
  6574.  This subfunction provides an OS/E with the ability to enable all programs or
  6575.  device drivers to use the OS/E specific functions. The capability is
  6576.  provided only for an OS/E which manages regions of mappable conventional
  6577.  memory and cannot permit programs to use any of the functions which affect
  6578.  mappable conventional memory regions, but must be able to use these
  6579.  functions itself. When an OS/E disables these functions and a program
  6580.  attempts to use them, the memory manager returns a status to the program
  6581.  indicating that the OS/E has denied the program access to the function. In
  6582.  other words, the functions will not work when disabled. However, all
  6583.  programs may use them when enabled.
  6584.  
  6585.  The OS/E (Operating System/Environment) functions this subfunction enables
  6586.  are:
  6587.  
  6588.    Function 26. Get Expanded Memory Hardware Information.
  6589.    Function 28. Alternate Map Register Sets.
  6590.    Function 30. Enable/Disable Operating System Functions.
  6591.  
  6592.  It appears contradictory that the OS/E can re-enable these functions when
  6593.  the function which re-enables them is itself disabled. An overview of the
  6594.  process follows.
  6595.  
  6596.  The memory manager enables all the OS/E specific functions, including this
  6597.  one, when it is loaded. The OS/E gets exclusive access to these functions by
  6598.  invoking either of the Enable/Disable OS/E Function Set subfunctions before
  6599.  any other software does.
  6600.  
  6601.  On the first invocation of either of these subfunctions, the memory manager
  6602.  returns an access_key which the OS/E must use in all future invocations of
  6603.  either of these subfunctions. The memory manager does not require the
  6604.  access_key on the first invocation of the Enable/Disable OS/E Function Set
  6605.  subfunctions.
  6606.  
  6607.  On all subsequent invocations, the access_key is required for either the
  6608.  Enable or Disable OS/E Function Set subfunctions. Since the access_key is
  6609.  returned only on the first invocation of the Enable/Disable OS/E Function
  6610.  Set subfunctions, and presumably the OS/E is the first software to invoke
  6611.  this function, only the OS/E obtains a copy of this key. The memory manager
  6612.  must return an access key with a random value, a fixed value key defeats the
  6613.  purpose of providing this level of security for an OS/E.
  6614.  
  6615.  CALLING PARAMETERS
  6616.  
  6617.  AX = 5D00h
  6618.    Contains the Enable OS/E Function Set subfunction.
  6619.  
  6620.  BX,CX = access_key
  6621.    Required on all function invocations after the first. The access_key value
  6622.    returned by the first function invocation is required.
  6623.  
  6624.  RESULTS
  6625.  
  6626.  These results are valid only if the status returned is zero.
  6627.  
  6628.  BX,CX = access_key
  6629.    Returned only on the first function invocation, the memory manager returns
  6630.    a random valued key which will be required thereafter for the execution of
  6631.    this function. On all invocations after the first, this key is not
  6632.    returned. Neither BX or CX is affected after the first time this function
  6633.    is invoked.
  6634.  
  6635.  REGISTERS MODIFIED
  6636.  
  6637.  AX, BX, CX
  6638.  
  6639.  STATUS
  6640.  
  6641.  AH = 0        SUCCESSFUL.
  6642.    The operating system function set has been enabled.
  6643.  
  6644.  AH = 80h      NON-RECOVERABLE.
  6645.    The manager detected a malfunction in the memory manager software.
  6646.  
  6647.  AH = 81h      NON-RECOVERABLE.
  6648.    The manager detected a malfunction in the expanded memory hardware.
  6649.  
  6650.  AH = 84h      NON-RECOVERABLE.
  6651.    The function code passed to the memory manager is not defined.
  6652.  
  6653.  AH = 8Fh      NON-RECOVERABLE.
  6654.    The subfunction parameter is invalid.
  6655.  
  6656.  AH = A4h      NON-RECOVERABLE.
  6657.    The operating system has denied access to this function. The function
  6658.    cannot be used at this time. The value of the key which was passed to this
  6659.    function does not entitle the program to execute this function.
  6660.  
  6661.  EXAMPLE
  6662.  
  6663.  First invocation
  6664.  
  6665.  access_key               DW 2 DUP (?)
  6666.  
  6667.  MOV   AX, 5D00h          ; load function code
  6668.  INT   67h                ; call the memory manager
  6669.  OR    AH, AH             ; check EMM status
  6670.  JNZ   emm_err_handler    ; jump to error handler on error
  6671.  MOV   access_key[0], BX
  6672.  MOV   access_key[2], CX
  6673.  
  6674.  
  6675.  All invocations after the first
  6676.  
  6677.  access_key               DW 2 DUP (?)
  6678.  
  6679.  MOV   BX, access_key[0]
  6680.  MOV   CX, access_key[2]
  6681.  MOV   AX, 5D00H          ; load function code
  6682.  INT   67h                ; call the memory manager
  6683.  OR    AH, AH             ; check EMM status
  6684.  JNZ   emm_err_handler    ; jump to test handler on error
  6685.  
  6686.  
  6687.  FUNCTION 30  Disable OS/E Function Set Subfunction
  6688.  
  6689.  ────────────────────────────────────────────────────────────────────────────
  6690.  NOTE:
  6691.    This function is for use by operating systems only. The operating system
  6692.    can disable this function at any time.
  6693.  ────────────────────────────────────────────────────────────────────────────
  6694.  
  6695.  PURPOSE
  6696.  
  6697.  This subfunction provides an OS/E with the ability to disable all programs
  6698.  or device drivers from using the OS/E specific functions. The capability is
  6699.  provided only for an OS/E which manages regions of mappable conventional
  6700.  memory and cannot permit programs to use any of the functions which would
  6701.  affect mappable conventional memory regions. When an OS/E disables these
  6702.  functions and a program attempts to use them, the memory manager returns a
  6703.  status to the program indicating that the OS/E has denied the program access
  6704.  to the function. In other words, the functions will not work when disabled.
  6705.  
  6706.  The OS/E (Operating System) functions which are disabled by this subfunction
  6707.  are:
  6708.  
  6709.    Function 26. Get Expanded Memory Hardware Information.
  6710.    Function 28. Alternate Map Register Sets.
  6711.    Function 30. Enable/Disable Operating System Functions.
  6712.  
  6713.  CALLING PARAMETERS
  6714.  
  6715.  AX = 5D01h
  6716.    Contains the Disable OS/E Function Set subfunction.
  6717.  
  6718.  BX,CX = access_key
  6719.    Required on all function invocations after the first. The access_key value
  6720.    returned by the first function invocation is required.
  6721.  
  6722.  RESULTS
  6723.  
  6724.  These results are valid only if the status returned is zero.
  6725.  
  6726.  BX,CX = access_key
  6727.    Returned only on the first function invocation, the memory manager returns
  6728.    a random valued key which will be required thereafter for the execution of
  6729.    this function. On all invocations after the first, this key is not
  6730.    returned. Neither BX nor CX is affected after the first time this function
  6731.    is invoked.
  6732.  
  6733.  REGISTERS MODIFIED
  6734.  
  6735.  AX, BX, CX
  6736.  
  6737.  STATUS
  6738.  
  6739.  AH = 0        SUCCESSFUL.
  6740.    The operating system function set has been disabled.
  6741.  
  6742.  AH = 80h      NON-RECOVERABLE.
  6743.    The manager detected a malfunction in the memory manager software.
  6744.  
  6745.  AH = 81h      NON-RECOVERABLE.
  6746.    The manager detected a malfunction in the expanded memory hardware.
  6747.  
  6748.  AH = 84h      NON-RECOVERABLE.
  6749.    The function code passed to the memory manager is not defined.
  6750.  
  6751.  AH = 8Fh      NON-RECOVERABLE.
  6752.    The subfunction parameter is invalid.
  6753.  
  6754.  AH = A4h      NON-RECOVERABLE.
  6755.    The operating system has denied access to this function. The function
  6756.    cannot be used at this time. The value of the key which was passed to this
  6757.    function does not entitle the program to execute this function.
  6758.  
  6759.  EXAMPLE
  6760.  
  6761.  First Function invocation
  6762.  
  6763.  access_key               DW 2 DUP (?)
  6764.  
  6765.  MOV   AX, 5D01h          ; load function code
  6766.  INT   67h                ; call the memory manager
  6767.  OR    AH, AH             ; check EMM status
  6768.  JNZ   emm_err_handler    ; jump to error handler on error
  6769.  MOV   access_key[0], BX
  6770.  MOV   access_key[2], CX
  6771.  
  6772.  All invocations after the first
  6773.  
  6774.  access_key               DW 2 DUP (?)
  6775.  
  6776.  MOV   BX, access_key[0]
  6777.  MOV   CX, access_key[2]
  6778.  MOV   AX, 5D01h          ; load function code
  6779.  INT   67h                ; call the memory manager
  6780.  OR    AH, AH             ; check EMM status
  6781.  JNZ   emm_err_handler    ; jump to error handler on error
  6782.  
  6783.  
  6784.  FUNCTION 30  Return Access Key Subfunction
  6785.  
  6786.  ────────────────────────────────────────────────────────────────────────────
  6787.  NOTE:
  6788.    This function is for use by operating systems only. The operating system
  6789.    can disable this function at any time.
  6790.  ────────────────────────────────────────────────────────────────────────────
  6791.  
  6792.  PURPOSE
  6793.  
  6794.  This subfunction provides an OS/E with the ability to return the access key
  6795.  to the memory manager. Returning the access key to the memory manager places
  6796.  the memory manager in the state it is in at installation time (regarding the
  6797.  use of the OS/E function set and the access key). That is, access to the
  6798.  OS/E function set is enabled. Upon execution of the next enable/disable OS/E
  6799.  function set subfunction, the access key will once again be returned.
  6800.  
  6801.  CALLING PARAMETERS
  6802.  
  6803.  AX = 5D02h
  6804.    Contains the Return Access Key subfunction.
  6805.  
  6806.  BX,CX = access_key
  6807.    Required on all function invocations. The access_key value returned by the
  6808.    first function invocation of the enable or disable subfunctions is
  6809.    required.
  6810.  
  6811.  REGISTERS MODIFIED
  6812.  
  6813.  AX
  6814.  
  6815.  STATUS
  6816.  
  6817.  AH = 0        SUCCESSFUL.
  6818.    The access key has been returned to the memory manager.
  6819.  
  6820.  AH = 80h      NON-RECOVERABLE.
  6821.    The manager detected a malfunction in the memory manager software.
  6822.  
  6823.  AH = 81h      NON-RECOVERABLE.
  6824.    The manager detected a malfunction in the expanded memory hardware.
  6825.  
  6826.  AH = 84h      NON-RECOVERABLE.
  6827.    The function code passed to the memory manager is not defined.
  6828.  
  6829.  AH = 8Fh      NON-RECOVERABLE.
  6830.    The subfunction parameter is invalid.
  6831.  
  6832.  AH = A4h      NON-RECOVERABLE.
  6833.    Access to this function has been denied by the operating system. The
  6834.    function cannot be used at this time. The value of the key which was
  6835.    passed to this function does not entitle the program to execute this
  6836.    function.
  6837.  
  6838.  EXAMPLE
  6839.  
  6840.  access_key               DW 2 DUP (?)
  6841.  
  6842.  MOV   BX, access_key[0]
  6843.  MOV   CX, access_key[2]
  6844.  MOV   AX, 5D02h          ; load function code
  6845.  INT   67h                ; call the memory manager
  6846.  OR    AH, AH             ; check EMM status
  6847.  JNZ   emm_err_handler    ; jump to error handler on error
  6848.  
  6849.  
  6850.  
  6851.  APPENDIX A  FUNCTION AND STATUS CODE CROSS REFERENCE TABLES
  6852.  
  6853.  This appendix contains two cross reference tables: one lists this function
  6854.  codes and the status codes they return; the other lists the status codes and
  6855.  the functions that return them.
  6856.  
  6857.  Table A-1  Function and Status Code Cross Reference
  6858.  
  6859. ╓┌───────────┌──────────────────────┌────────────────────────────────────────╖
  6860.  Function    Status                 Description
  6861.  
  6862.   40h       00h, 80h, 81h, 84h     Get memory manager status.
  6863.  
  6864.   41h       00h, 80h, 81h, 84h     Get Page Frame Segment Address.
  6865.  
  6866.   42h       00h, 80h, 81h, 84h     Get Unallocated Page Count.
  6867.  
  6868.   43h       00h, 80h, 81h, 84h     Allocate Pages.
  6869.  Function    Status                 Description
  6870.  43h       00h, 80h, 81h, 84h     Allocate Pages.
  6871.              85h, 87h, 88h
  6872.  
  6873.   44h       00h, 80h, 81h, 83h     Map/Unmap Handle Page.
  6874.              84h, 8Ah, 8Bh
  6875.  
  6876.   45h       00h, 80h, 81h, 83h     Deallocate Pages.
  6877.              84h, 86h
  6878.  
  6879.   46h       00h, 80h, 81h, 84h     Get EMM Version.
  6880.  
  6881.   47h       00h, 80h, 81h, 83h     Save Page Map.
  6882.              84h, 8Ch, 8Dh
  6883.  
  6884.   48h       00h, 80h, 81h, 83h     Restore Page Map.
  6885.              84h, 8Eh
  6886.  
  6887.   49h                              Reserved
  6888.  
  6889.   4Ah                              Reserved
  6890.  Function    Status                 Description
  6891.  4Ah                              Reserved
  6892.  
  6893.   4Bh       00h, 80h, 81h, 84h     Get EMM Handle Count.
  6894.  
  6895.   4Ch       00h, 80h, 81h, 83h     Get EMM Handle Pages.
  6896.              84h
  6897.  
  6898.   4Dh       00h, 80h, 81h, 84h     Get All EMM Handle Pages.
  6899.  
  6900.  4E00h      00h, 80h, 81h, 84h     Get Page Map.
  6901.              8Fh
  6902.  
  6903.  4E01h      00h, 80h, 81h, 84h     Set Page Map.
  6904.              8Fh, A3h
  6905.  
  6906.  4E02h      00h, 80h, 81h, 84h     Get & Set Page Map.
  6907.              8Fh, A3h
  6908.  
  6909.  4E03h      00h, 80h, 81h, 84h     Get Size of Page Map Save Array.
  6910.              8Fh
  6911.  Function    Status                 Description
  6912.             8Fh
  6913.  
  6914.  4F00h      00h, 80h, 81h, 84h     Get Partial Page Map
  6915.              8Bh, 8Fh, A3h
  6916.  
  6917.  4F01h      00h, 80h, 81h, 84h     Set Partial Page Map
  6918.              8Fh, A3h
  6919.  
  6920.  4F02h      00h, 80h, 81h, 84h     Get Size of Partial Page Map Array
  6921.              8Bh, 8Fh
  6922.  
  6923.  5000h      00h, 80h, 81h, 83h     Map/Unmap Multiple Handle Pages
  6924.              84h, 8Ah, 8Bh, 8Fh     (physical page number mode)
  6925.  
  6926.  5001h      00h, 80h, 81h, 83h     Map/Unmap Multiple Handle Pages
  6927.              84h, 8Ah, 8Bh, 8Fh      (segment address mode)
  6928.  
  6929.   51h       00h, 80h, 81h, 83h     Reallocate Pages.
  6930.              84h, 87h, 88h
  6931.  
  6932.  Function    Status                 Description
  6933. 
  6934.  5200h      00h, 80h, 81h, 83h     Get Handle Attribute.
  6935.              84h, 8Fh, 91h
  6936.  
  6937.  5201h      00h, 80h, 81h, 83h     Set Handle Attribute.
  6938.              84h, 8Fh, 90h, 91h
  6939.  
  6940.  5202h      00h, 80h, 81h, 84h     Get Handle Attribute Capability
  6941.              8Fh
  6942.  
  6943.  5300h      00h, 80h, 81h, 83h     Get Handle Name.
  6944.              84h, 8Fh
  6945.  
  6946.  5301h      00h, 80h, 81h, 83h     Set Handle Name.
  6947.              84h, 8FH, A1h
  6948.  
  6949.  5400h      00h, 80h, 81h, 84h     Get Handle Directory.
  6950.              8Fh
  6951.  
  6952.  5401h      00h, 80h, 81h, 84h     Search for Named Handle.
  6953.  Function    Status                 Description
  6954. 5401h      00h, 80h, 81h, 84h     Search for Named Handle.
  6955.              8Fh, A0h, A1h
  6956.  
  6957.  5402h      00h, 80h, 81h, 84h     Get Total Handles.
  6958.              8Fh
  6959.  
  6960.  5500h      00h, 80h, 81h, 83h     Alter Page Map & Jump. (Physical
  6961.              84h, 8Ah, 8Bh, 8Fh     page mode.)
  6962.  
  6963.  5501h      00h, 80h, 81h, 83h     Alter Page Map & Jump. (Segment
  6964.              84h, 8Ah, 8Bh, 8Fh     address mode.)
  6965.  
  6966.  5600h      00h, 80h, 81h, 83h     Alter Page Map & Call. (Physical
  6967.              84h, 8Ah, 8Bh, 8Fh     page mode.)
  6968.  
  6969.  5601h      00h, 80h, 81h, 83h     Alter Page Map & Call. (Segment
  6970.              84h, 8Ah, 8Bh, 8Fh     address mode)
  6971.  
  6972.  5602h      00h, 80h, 81h, 84h     Get Alter Page Map & Call Stack
  6973.              8Fh                    Space Size.
  6974.  Function    Status                 Description
  6975.             8Fh                    Space Size.
  6976.  
  6977.  5700h      00h, 80h, 81h, 83h     Move Memory Region.
  6978.              84h, 8Ah, 8Fh, 92h
  6979.              93h, 94h, 95h, 96h
  6980.              98h, A2h
  6981.  
  6982.  5701h      00h, 80h, 81h, 83h     Exchange Memory Region.
  6983.              84h, 8Ah, 8Fh, 93h
  6984.              94h, 95h, 96h, 97h
  6985.              98h, A2h
  6986.  
  6987.  5800h      00h, 80h, 81h, 84h     Get Mappable Physical Address
  6988.              8Fh                    Array.
  6989.  
  6990.  5801h      00h, 80h, 81h, 84h     Get Mappable Physical Address
  6991.              8Fh                    Array Entries.
  6992.  
  6993.  5900h      00h, 80h, 81h, 84h     Get Expanded Memory Hardware
  6994.              8Fh, A4h                    Information.
  6995.  Function    Status                 Description
  6996.             8Fh, A4h                    Information.
  6997.  
  6998.  5901h      00h, 80h, 81h, 84h     Get Unallocated Raw Page Count.
  6999.              8Fh
  7000.  
  7001.  5A00h      00h, 80h, 81h, 84h     Allocate Standard Pages.
  7002.              85h, 87h, 88h, 8Fh
  7003.  
  7004.  5A01h      00h, 80h, 81h, 84h     Allocate Raw Pages.
  7005.              85h, 87h, 88h, 8Fh
  7006.  
  7007.  5B00h      00h, 80h, 81h, 84h     Get Alternate Map Register Set.
  7008.              8Fh, A4h
  7009.  
  7010.  5B01h      00h, 80h, 81h, 84h     Set Alternate Map Register Set.
  7011.              8Fh, 9Ah, 9Ch, 9Dh
  7012.              A3h, A4h
  7013.  
  7014.  5B02h      00h, 80h, 81h, 84h     Get Alternate Map Save Array
  7015.              8Fh, A4h               Size.
  7016.  Function    Status                 Description
  7017.             8Fh, A4h               Size.
  7018.  
  7019.  5B03h      00h, 80h, 81h, 84h     Allocate Alternate Map Register
  7020.              8Fh, 9Bh, A4h          Set.
  7021.  
  7022.  5B04h      00h, 80h, 81h, 84h     Deallocate Alternate Map
  7023.              8Fh, 9Ch, 9Dh, A4h     Register Set.
  7024.  
  7025.  5B05h      00h, 80h, 81h, 84h     Allocate DMA Register Set.
  7026.              8Fh, 9Bh, A4h
  7027.  
  7028.  5B06h      00h, 80h, 81h, 84h     Enable DMA on Alternate Map
  7029.              8Fh, 9Ah, 9Ch, 9Dh     Register Set.
  7030.              9Eh, 9Fh, A4h
  7031.  
  7032.  5B07h      00h, 80h, 81h, 84h     Disable DMA on Alternate Map
  7033.              8Fh, 9Ah, 9Ch, 9Dh     Register Set.
  7034.              9Eh, 9Fh, A4h
  7035.  
  7036.  5B08h      00h, 80h, 81h, 84h     Deallocate DMA Register Set.
  7037.  Function    Status                 Description
  7038. 5B08h      00h, 80h, 81h, 84h     Deallocate DMA Register Set.
  7039.              8Fh, 9Ch, 9Dh, A4h
  7040.  
  7041.   5Ch       00h, 80h, 81h, 84h     Prepare Expanded Memory
  7042.                                     Hardware for Warmboot.
  7043.  
  7044.  5D00h      00h, 80h, 81h, 84h     Enable Operating System
  7045.              8Fh, A4h               Function Set.
  7046.  
  7047.  5D01h      00h, 80h, 81h, 84h     Disable Operating System
  7048.              8Fh, A4h               Function Set.
  7049.  
  7050.  5D02h      00h, 80h, 81h, 84h     Return Operating System
  7051.              8Fh, A4h               Access Key.
  7052.  
  7053.  
  7054.  Table A-2  Status and Function Code Cross Reference
  7055.  
  7056. ╓┌───────────┌──────────────────────┌────────────────────────────────────────╖
  7057.  Status      Function               Description
  7058.  Status      Function               Description
  7059.  
  7060.    00h       All                    The function completed normally.
  7061.  
  7062.    80h       All                    The memory manager has detected a
  7063.                                     malfunction in the expanded memory
  7064.                                     software. A condition has been detected
  7065.                                     which would not have occurred if the
  7066.                                     memory manager had been operating
  7067.                                     correctly.
  7068.  
  7069.    81h       All                    The memory manager has detected a
  7070.                                     malfunction in the expanded memory
  7071.                                     hardware. A condition has been detected
  7072.                                     which would not occur if the memory
  7073.                                     hardware were working correctly.
  7074.                                     Diagnostics should be run on the expanded
  7075.                                     memory system to determine the source of
  7076.                                     the problem.
  7077.  
  7078.    82h       None                   This error code is not returned in
  7079.  Status      Function               Description
  7080.   82h       None                   This error code is not returned in
  7081.                                     version 3.2 of the memory manager or
  7082.                                     above. In earlier versions of the memory
  7083.                                     manager this code meant a "busy" status.
  7084.                                     This status indicated that the memory
  7085.                                     manager was already processing an
  7086.                                     expanded memory request when the current
  7087.                                     request was made and is unable to process
  7088.                                     another request. In versions 3.2 of the
  7089.                                     memory manager and above, the memory
  7090.                                     manager is never "busy" and can always
  7091.                                     honor requests.
  7092.  
  7093.    83h       44h, 45h, 47h, 48h The memory manager can not find
  7094.              4Ch, 5000h, 5001h   the handle specified. The program
  7095.              51h, 5200h, 5201h   has probably corrupted its specified
  7096.              5300h, 5301h         handle. The memory manager does
  7097.              5500h, 5501h         not have any information pertaining
  7098.              5600h, 5601h         to the specified handle. The program
  7099.              5700h, 5701h         has probably corrupted its handle.
  7100.  Status      Function               Description
  7101.             5700h, 5701h         has probably corrupted its handle.
  7102.  
  7103.    84h       All                    The function code passed to the manager
  7104.                                     is not currently defined. Function codes
  7105.                                     in the range 40h through 5Eh are
  7106.                                     currently defined.
  7107.  
  7108.    85h       43h, 5A00h, 5A01h   No handles are currently available. All
  7109.                                     assignable handles are currently in use.
  7110.                                     The program may re-request the assignment
  7111.                                     of a handle in the hope that another
  7112.                                     program has released a handle. The
  7113.                                     maximum number of handles that may be
  7114.                                     supported is 255.
  7115.  
  7116.    86h       45h                   A mapping context restoration error has
  7117.                                     been detected. This error occurs when a
  7118.                                     program attempts to return a handle and
  7119.                                     there is still a "mapping context" on the
  7120.                                     context stack for the indicated handle. A
  7121.  Status      Function               Description
  7122.                                    context stack for the indicated handle. A
  7123.                                     program can recover from this error by
  7124.                                     restoring the mapping context before
  7125.                                     returning the handle.
  7126.  
  7127.    87h       43h, 51h, 5A00h     The number of total pages that are
  7128.              5A01h                 available in the system is insufficient
  7129.                                     to honor the request. The program can
  7130.                                     recover from this condition by requesting
  7131.                                     fewer pages.
  7132.  
  7133.    88h       43h, 51h, 5A00h     The number of unallocated pages
  7134.              5A01h                 currently available is insufficient to
  7135.                                     honor the allocation request. The program
  7136.                                     can recover from this condition by
  7137.                                     reposting the request or by requesting
  7138.                                     fewer pages.
  7139.  
  7140.    89h       None                   This error code is not returned in
  7141.                                     version 4.0 of the memory manager or
  7142.  Status      Function               Description
  7143.                                    version 4.0 of the memory manager or
  7144.                                     above. In earlier versions of the memory
  7145.                                     manager, this code indicated that zero
  7146.                                     pages could not be assigned to a handle.
  7147.                                     This is no longer an error condition.
  7148.  
  7149.    8Ah       44h, 5000h, 5001h   The logical page to map into memory
  7150.              5500h, 5501h         is out of the range of logical pages
  7151.              5600h, 5601h         which are allocated to the handle.
  7152.              5700h, 5701h         The program can recover from this
  7153.                                     condition by attempting to map a logical
  7154.                                     page which is within the bounds for the
  7155.                                     handle.
  7156.  
  7157.    8Bh       44h, 4F00h, 4F02h   One or more of the physical pages
  7158.              5000h, 5001h         is out of the range of allowable
  7159.              5600h, 5601h         physical pages. Physical page numbers
  7160.              5500h, 5501h         are numbered zero relative. The program
  7161.                                     can recover from this condition by
  7162.                                     mapping at a physical page which is in
  7163.  Status      Function               Description
  7164.                                    mapping at a physical page which is in
  7165.                                     the range from zero to three.
  7166.  
  7167.    8Ch       47h                   The mapping register context save area is
  7168.                                     full. The program can recover from this
  7169.                                     condition by attempting to save the
  7170.                                     mapping registers again.
  7171.  
  7172.    8Dh       47h                   The mapping register context stack
  7173.                                     already has a context associated with the
  7174.                                     handle. The program has attempted to save
  7175.                                     the mapping register context when there
  7176.                                     was already a context for the handle on
  7177.                                     the stack. The program can recover from
  7178.                                     this condition by not attempting to save
  7179.                                     the context again (this assumes the
  7180.                                     mapping register context on the stack for
  7181.                                     the handle is correct).
  7182.  
  7183.    8Eh       48h                   The mapping register context stack does
  7184.  Status      Function               Description
  7185.   8Eh       48h                   The mapping register context stack does
  7186.                                     not have a context associated with the
  7187.                                     handle. The program has attempted to
  7188.                                     restore the mapping register context when
  7189.                                     there was no context for the handle on
  7190.                                     the stack. The program can recover from
  7191.                                     this condition by not attempting to
  7192.                                     restore the context again (this assumes
  7193.                                     the current mapping register context is
  7194.                                     correct).
  7195.  
  7196.    8Fh       All functions          The subfunction parameter passed to the
  7197.              requiring              function is not defined.
  7198.              subfunction codes
  7199.  
  7200.    90h       5201h                 The attribute type is undefined.
  7201.  
  7202.    91h       5200h, 5201h         The system configuration does not support
  7203.                                     non-volatility.
  7204.  
  7205.  Status      Function               Description
  7206. 
  7207.    92h       5700h                 The source and destination expanded
  7208.                                     memory regions have the same handle and
  7209.                                     overlap. This is valid for a move. The
  7210.                                     move has been completed and the
  7211.                                     destination region has a full copy of the
  7212.                                     source region. However, at least a
  7213.                                     portion of the source region has been
  7214.                                     overwritten by the move. Note that the
  7215.                                     source and destination expanded memory
  7216.                                     regions with different handles will never
  7217.                                     physically overlap because the different
  7218.                                     handles specify totally different regions
  7219.                                     of expanded memory.
  7220.  
  7221.    93h       5700h, 5701h         The length of the specified source or
  7222.                                     destination expanded memory region
  7223.                                     exceeds the length of the expanded memory
  7224.                                     region allocated to the specified source
  7225.                                     or destination handle. There are
  7226.  Status      Function               Description
  7227.                                    or destination handle. There are
  7228.                                     insufficient pages allocated to this
  7229.                                     handle to move/exchange a region of the
  7230.                                     size specified. The program can recover
  7231.                                     from this condition by attempting to
  7232.                                     allocate additional pages to the
  7233.                                     destination or source handle or by
  7234.                                     reducing the specified length. However,
  7235.                                     if the application program has allocated
  7236.                                     as much expanded memory as it thought it
  7237.                                     needed, this may be a program error and
  7238.                                     is therefore not recoverable.
  7239.  
  7240.    94h       5700h, 5701h         The conventional memory region and
  7241.                                     expanded memory region overlap. This is
  7242.                                     invalid, the conventional memory region
  7243.                                     cannot overlap the expanded memory
  7244.                                     region.
  7245.  
  7246.    95h       5700h, 5701h         The offset within the logical page
  7247.  Status      Function               Description
  7248.   95h       5700h, 5701h         The offset within the logical page
  7249.                                     exceeds the length of the logical page.
  7250.                                     The initial source or destination offsets
  7251.                                     within an expanded memory region must be
  7252.                                     between 0 and the (length of a logical
  7253.                                     page - 1) or 16383 (3FFFh).
  7254.  
  7255.    96h       5700h, 5701h         Region length exceeds 1M-byte limit.
  7256.  
  7257.    97h       5701h                 The source and destination expanded
  7258.                                     memory regions have the SAME handle AND
  7259.                                     overlap. This is invalid; the source and
  7260.                                     destination expanded memory regions
  7261.                                     cannot have the same handle and overlap
  7262.                                     when they are being exchanged. Note that
  7263.                                     the source and destination expanded
  7264.                                     memory regions with different handles
  7265.                                     will never physically overlap because the
  7266.                                     different handles specify totally
  7267.                                     different regions of expanded memory.
  7268.  Status      Function               Description
  7269.                                    different regions of expanded memory.
  7270.  
  7271.    98h       5700h, 5701h         The memory source and destination types
  7272.                                     are undefined/not supported.
  7273.  
  7274.    9Ah       5B01h, 5B06h         Alternate map register sets are
  7275.              5B07h                 supported, but the alternate map register
  7276.                                     set specified is not supported.
  7277.  
  7278.    9Bh       5B03h, 5B05h         Alternate map/DMA register sets are
  7279.                                     supported. However, all alternate map/DMA
  7280.                                     register sets are currently allocated.
  7281.  
  7282.    9Ch       5B01h, 5B04h         Alternate map/DMA register sets are not
  7283.              5B06h, 5B07h         supported, and the alternate map/DMA
  7284.              5B08h                 register set specified is not zero.
  7285.  
  7286.    9Dh       5B01h, 5B04h         Alternate map/DMA register sets are
  7287.              5B06h, 5B07h         supported, but the alternate map
  7288.              5B08h                 register set specified is not defined,
  7289.  Status      Function               Description
  7290.             5B08h                 register set specified is not defined,
  7291.                                     not allocated, or is the currently
  7292.                                     allocated map register set.
  7293.  
  7294.    9Eh       5B06h, 5B07h         Dedicated DMA channels are not supported.
  7295.  
  7296.    9Fh       5B06h, 5B07h         Dedicated DMA channels are supported. But
  7297.                                     the DMA channel specified is not
  7298.                                     supported.
  7299.  
  7300.    A0h       5401h                 No corresponding handle value could be
  7301.                                     found for the handle name specified.
  7302.  
  7303.    A1h       5301h, 5401h         A handle with this name already exists.
  7304.                                     The specified handle was not assigned a
  7305.                                     name.
  7306.  
  7307.    A2h       5700h, 5701h         An attempt was made to "wrap around" the
  7308.                                     1M-byte address space during the
  7309.                                     move/exchange. The source starting
  7310.  Status      Function               Description
  7311.                                    move/exchange. The source starting
  7312.                                     address together with the length of the
  7313.                                     region to be moved/exchanged exceeds 1M-
  7314.                                     byte. No data was moved/exchanged.
  7315.  
  7316.    A3h       4E01h, 4E02h         The contents of the data structure
  7317.              4F00h, 4F01h         passed to the function have either been
  7318.              5B01h                 corrupted or are meaningless.
  7319.  
  7320.    A4h       5900h, 5B00h         The operating system has denied access
  7321.              5B01h, 5B02h         to this function. The function cannot
  7322.              5B03h, 5B04h         be used at this time.
  7323.              5B05h, 5B06h
  7324.              5B07h, 5B08h
  7325.              5D00h, 5D01h
  7326.              5D02h
  7327.  
  7328.  
  7329.  APPENDIX B  TESTING FOR THE PRESENCE OF THE EXPANDED MEMORY MANAGER
  7330.  
  7331.  Before an application program can use the Expanded Memory Manager, it must
  7332.  determine whether DOS has loaded the manager. This appendix describes two
  7333.  methods your program can use to test for the presence of the memory manager
  7334.  and how to choose the correct one for your situation.
  7335.  
  7336.  The first method uses the DOS "open handle" technique; the second method
  7337.  uses the DOS "get interrupt vector" technique.
  7338.  
  7339.  
  7340.  WHICH METHOD SHOULD YOUR PROGRAM USE?
  7341.  
  7342.  The majority of application programs can use either the "open handle" or the
  7343.  "get interrupt vector" method. However, if your program is a device driver
  7344.  or if it interrupts DOS during file system operations, you must use only the
  7345.  "get interrupt vector" method.
  7346.  
  7347.  Device drivers execute from within DOS and can't access the DOS file system;
  7348.  programs that interrupt DOS during file system operations have a similar
  7349.  restriction. During their interrupt processing procedures, they can't access
  7350.  the DOS file system because another program may be using the system. Since
  7351.  the "get interrupt vector" method doesn't require the DOS file system, you
  7352.  must use it for these types of programs.
  7353.  
  7354.  
  7355.  THE "OPEN HANDLE" TECHNIQUE
  7356.  
  7357.  Most application programs can use the DOS "open handle" technique to test
  7358.  for the presence of the memory manager. This section describes how to use
  7359.  the technique and gives an example.
  7360.  
  7361.  ───────────────────────────────────────────────────────────────────────────
  7362.  CAUTION:
  7363.    Don't use this technique if your program is a device driver or if it
  7364.    interrupts DOS during file system operations. Use the "get interrupt
  7365.    vector" technique described later in this chapter.
  7366.  ───────────────────────────────────────────────────────────────────────────
  7367.  
  7368.  Using The "Open Handle" Technique
  7369.  
  7370.  This section describes how to use the DOS "open handle" technique to test
  7371.  for the presence of the memory manager. Follow these steps in order:
  7372.  
  7373.    1.  Issue an "open handle" command (DOS function 3Dh) in "read only"
  7374.        access mode (register AL = 0). This function requires your program to
  7375.        point to an ASCII string which contains the path name of the file or
  7376.        device in which you're interested (register set DS:DX contains the
  7377.        pointer). In this case the file is actually the name of the memory
  7378.        manager.
  7379.  
  7380.        You should format the ASCII string as follows:
  7381.  
  7382.        ASCII_device_name   DB   "EMMXXXX0", 0
  7383.  
  7384.        The ASCII codes for the capital letters EMMXXXX0 are terminated by a
  7385.        byte containing a value of zero.
  7386.  
  7387.    2.  If DOS returns no error status code, skip Steps 3 and 4 and go to Step
  7388.        5. If DOS returns a "Too many open files" error status code, go to
  7389.        Step 3. If DOS returns a "File/Path not found" error status code, skip
  7390.        Step 3 and go to Step 4.
  7391.  
  7392.    3.  If DOS returns a "Too many open files" (not enough handles), status
  7393.        code, your program should invoke the "open file" command before it
  7394.        opens any other files. This will guarantee that at least one file
  7395.        handle will be available to perform the function without causing this
  7396.        error.
  7397.  
  7398.        After the program performs the "open file" command, it should perform
  7399.        the test described in Step 6 and close the "file handle" (DOS function
  7400.        3Eh). Don't keep the manager "open" after this status test is
  7401.        performed since "manager" functions are not available thru DOS. Go to
  7402.        Step 6.
  7403.  
  7404.    4.  If DOS returns a "File/Path not found", the memory manager is not
  7405.        installed. If your application requires the memory manager, the user
  7406.        will have to reboot the system with a disk containing the memory
  7407.        manager and the appropriate CONFIG.SYS file before proceeding.
  7408.  
  7409.    5.  If DOS doesn't return an error status code you can assume that either
  7410.        a device with the name EMMXXXX0 is resident in the system, or a file
  7411.        with this name is on disk in the current disk drive. Go to Step 6.
  7412.  
  7413.    6.  Issue an "I/O Control for Devices" command (DOS function 44h) with a
  7414.        "get device information" command (register AL = 0h). DOS function 44h
  7415.        determines whether EMMXXXX0 is a device or a file.
  7416.  
  7417.        You must use the file handle (register BX) which you obtained in Step
  7418.        1 to access the "EMM" device.
  7419.  
  7420.        This function returns the "device information" in a word (register
  7421.        DX). Go to step 7.
  7422.  
  7423.    7.  If DOS returns any error status code, you should assume that the
  7424.        memory manager device driver is not installed. If your application
  7425.        requires the memory manager, the user will have to reboot the system
  7426.        with a disk containing the memory manager and the appropriate
  7427.        CONFIG.SYS file before proceeding.
  7428.  
  7429.    8.  If DOS didn't return an error status, test the contents of bit 7
  7430.        (counting from 0) of the "device information" word (register DX) the
  7431.        function returned. Go to Step 9.
  7432.  
  7433.    9.  If bit 7 of the "device information" word contains a zero, then
  7434.        EMMXXXX0 is a file, and the memory manager device driver is not
  7435.        present. If your application requires its presence, the user will have
  7436.        to reboot the system with a disk containing the memory manager and the
  7437.        appropriate CONFIG.SYS file before proceeding.
  7438.  
  7439.        If bit 7 contains a one, then EMMXXXX0 is a device. Go to Step 10.
  7440.  
  7441.    10. Issue an "I/O Control for Devices" command (DOS function 44h) with a
  7442.        "get output status" command (register AL = 7h).
  7443.  
  7444.        You must use the file handle you obtained in Step 1 to access the
  7445.        "EMM" device (register BX). Go to Step 11.
  7446.  
  7447.    11. If the expanded memory device driver is "ready," the memory manager
  7448.        passes a status value of "0FFh" in register AL. The status value is
  7449.        "00h" if the device driver is "not ready."
  7450.  
  7451.        If the memory manager device driver is "not ready" and your
  7452.        application requires its presence, the user will have to reboot the
  7453.        system with a disk containing the memory manager and the appropriate
  7454.        CONFIG.SYS file before proceeding.
  7455.  
  7456.        If the memory manager device driver is "ready", go to Step 12.
  7457.  
  7458.    12. Issue a "Close File Handle" command (DOS function 3Eh) to close the
  7459.        expanded memory device driver. You must use the file handle you
  7460.        obtained in Step 1 to close the "EMM" device (register BX)
  7461.  
  7462.  An Example of the "Open Handle" Technique
  7463.  
  7464.  The following procedure is an example of the "open handle" technique
  7465.  outlined in the previous section.
  7466.  
  7467.  ;----------------------------------------------------------------;
  7468.  ;    The following procedure tests for the presence of the EMM   ;
  7469.  ;    in the system. It returns the CARRY FLAG SET if the EMM is  ;
  7470.  ;    present. If the EMM is not present, this procedure returns  ;
  7471.  ;    the CARRY FLAG CLEAR.                                       ;
  7472.  ;----------------------------------------------------------------;
  7473.  
  7474.  first_test_for_EMM  PROC  NEAR
  7475.  PUSH  DS
  7476.  PUSH  CS
  7477.  POP   DS
  7478.  MOV  AX, 3D00h                     ; issue "device open" in
  7479.  LEA  DX, ASCII_device_name         ; "read only" mode
  7480.  INT  21h
  7481.  JC   first_test_for_EMM_error_exit ; test for error
  7482.                                     ; during "device open"
  7483.  MOV  BX, AX                        ; get the "file
  7484.                                     ; handle" returned by DOS
  7485.  MOV  AX, 4400h                     ; issue "IOCTL
  7486.  INT  21h                           ; "get device info"
  7487.  JC   first_test_for_EMM_err_exit   ; test for error
  7488.                                     ; during "get device info"
  7489.  TEST DX, 0080h                     ; test to determine
  7490.  JZ   first_test_for_EMM_err_exit   ; ASCII_device_name
  7491.                                     ; is a device or a file
  7492.  MOV  AX, 4407h                     ; issue "IOCTL"
  7493.  INT  21h
  7494.  JC   first_test_for_EMM_error_exit ; test for error
  7495.                                     ; during "IOCTL"
  7496.  PUSH   AX                          ; save "IOCTL" status
  7497.  MOV  AH, 3Eh                       ; issue "close
  7498.  INT  21h                           ; file handle"
  7499.  POP  AX                            ; restore "IOCTL" status
  7500.  CMP  AL, 0FFh                      ; test for "device
  7501.  JNE  first_test_for_EMM_error_exit ; ready" status
  7502.                                     ; returned by the driver
  7503.  first_test_for_EMM_exit:
  7504.  POP  DS                            ; EMM is present
  7505.  STC                                ; in the system
  7506.  RET
  7507.  
  7508.  first_test_for_EMM_error_exit:
  7509.  POP  DS                            ; EMM is NOT present
  7510.  CLC                                ; in the system
  7511.  RET
  7512.  ASCII_device_name  DB  "EMMXXXX0", 0
  7513.  first_test_for_EMM ENDP
  7514.  
  7515.  The "Get Interrupt Vector" Technique
  7516.  
  7517.  Any type of program can use the DOS "get interrupt vector" technique to test
  7518.  for the presence of the memory manager. This section describes how to use
  7519.  the technique and gives an example.
  7520.  
  7521.  ───────────────────────────────────────────────────────────────────────────
  7522.  CAUTION:
  7523.    Be sure to use this technique (and not the "open handle technique) if your
  7524.    program is a device driver or if it interrupts DOS during file system
  7525.    operations.
  7526.  ───────────────────────────────────────────────────────────────────────────
  7527.  
  7528.  Using the "Get Interrupt Vector" Technique
  7529.  
  7530.  This section describes how to use the DOS "get interrupt vector" technique
  7531.  to test for the presence of the memory manager. Follow these steps in
  7532.  order:
  7533.  
  7534.    1.  Issue a "get vector" command (DOS function 35h) to obtain the contents
  7535.        of interrupt vector array entry number 67h (addresses 0000:019C thru
  7536.        0000:019F).
  7537.  
  7538.        The memory manager uses this interrupt vector to perform all manager
  7539.        functions. The Offset portion of this interrupt service routine
  7540.        address is stored in the word located at address 0000:019Ch; the
  7541.        Segment portion is stored in the word located at address 0000:019Eh.
  7542.  
  7543.    2.  Compare the "device name field" with the contents of the ASCII string
  7544.        which starts at the address specified by the segment portion of the
  7545.        contents of interrupt vector address 67h and a fixed offset of 000Ah.
  7546.        If DOS loaded the memory manager at boot time this name field will
  7547.        have the name of the device in it.
  7548.  
  7549.        Since the memory manager is implemented as a character device driver,
  7550.        its program origin is 0000h. Device drivers are required to have a
  7551.        "device header" located at the program origin. Within the "device
  7552.        header" is an 8 byte "device name field." For a character mode device
  7553.        driver this name field is always located at offset 000Ah within the
  7554.        device header. The device name field contains the name of the device
  7555.        which DOS uses when it references the device.
  7556.  
  7557.        If the result of the "string compare" in this technique is positive,
  7558.        the memory manager driver is present.
  7559.  
  7560.  An Example of the "Get Interrupt Vector" Technique
  7561.  
  7562.  The following procedure is an example of the "get interrupt vector"
  7563.  technique outlined in the previous section.
  7564.  
  7565.  ;----------------------------------------------------------------;
  7566.  ;    The following procedure tests for the presence of the EMM   ;
  7567.  ;    in the system. It returns the CARRY FLAG SET if the EMM is  ;
  7568.  ;    present. If the EMM is not present, this procedure returns  ;
  7569.  ;    the CARRY FLAG CLEAR.                                       ;
  7570.  ;----------------------------------------------------------------;
  7571.  
  7572.  second_test_for_EMM             PROC    NEAR
  7573.  PUSH DS
  7574.  PUSH CS
  7575.  POP  DS
  7576.  MOV  AX, 3567h                  ; issue "get interrupt
  7577.                                  ; vector"
  7578.  INT  21h
  7579.  MOV  DI, 000Ah                  ; use the SEGMENT in ES
  7580.                                  ; returned by DOS, place
  7581.                                  ; the "device name field"
  7582.                                  ; OFFSET in DI
  7583.  LEA  SI, ASCII_device_name      ; place the OFFSET of the
  7584.                                  ; device name string in SI,
  7585.                                  ; the SEGMENT is already
  7586.                                  ; in DS
  7587.  MOV  CX, 8                      ; compare the name strings
  7588.  CLD
  7589.  REPE   CMPSB
  7590.  JNE  second_test_for_EMM_error_exit
  7591.  second_test_for_EMM_exit:
  7592.  POP  DS                         ; EMM is present in
  7593.  STC                             ; the system
  7594.  RET
  7595.  second_test_for_EMM_error_exit:
  7596.  POP  DS                         ; EMM is NOT present
  7597.  CLC                             ; in the system
  7598.  RET
  7599.  ASCII_device_name               DB "EMMXXXX0"
  7600.  second_test_for_EMM             ENDP
  7601.  
  7602.  
  7603.  
  7604.  APPENDIX C  EXPANDED MEMORY MANAGER IMPLEMENTATION GUIDELINES
  7605.  
  7606.  In addition to the functional specification, the expanded memory manager
  7607.  should provide certain resources. The following guidelines are provided so
  7608.  required resources are present in expanded memory managers which comply with
  7609.  this version of the LIM specification.
  7610.  
  7611.    ■   The amount of expanded memory supported:
  7612.        Up to a maximum of 32M bytes of expanded memory should be supported.
  7613.  
  7614.    ■   The number of handles supported:
  7615.        The maximum number expanded memory handles provided should be 255, the
  7616.        minimum should be 64.
  7617.  
  7618.    ■   Handle Numbering:
  7619.        Although a handle is a word quantity, there is a maximum of 255
  7620.        handles, including the operating system handle. This specification
  7621.        defines the handle word as follows: the low byte of the word is the
  7622.        actual handle value, the high byte of the handle is set to 00 by the
  7623.        memory manager. Previous versions of this specification did not
  7624.        specify the value of handles.
  7625.  
  7626.    ■   New handle type: Handles versus Raw Handles:
  7627.        The difference between a raw handle and a regular handle is slight. If
  7628.        you use Function 27 to "Allocate raw pages to a handle", what is
  7629.        returned in DX is termed a raw handle. The raw handle does not
  7630.        necessarily refer to 16K-byte pages. Instead it refers to the "raw"
  7631.        page size, which depends on the expanded memory hardware.
  7632.  
  7633.        An application program can use Function 26 to find the raw page size,
  7634.        and by using the raw handle Function 27 returns, it can access them
  7635.        with the finer resolution that a particular expanded memory board may
  7636.        allow.
  7637.  
  7638.        On the other hand, applications which use Function 4 to "allocate
  7639.        pages to handle" receive a handle which always refers to 16K-byte
  7640.        pages. On expanded memory boards with smaller raw pages, the EMM
  7641.        driver will allocate and maintain the number of raw pages it takes to
  7642.        create a single composite 16K-byte page. The difference between the
  7643.        expanded memory boards raw page size and the 16K-byte LIM page size is
  7644.        transparent to the application when it is using a handle obtained with
  7645.        Function 4.
  7646.  
  7647.        The memory manager must differentiate between pages allocated to
  7648.        handles and pages allocated to raw handles. The meaning of a call to
  7649.        the driver changes depending on whether a handle or a raw handle is
  7650.        passed to the memory manager. If, for example, a handle is passed to
  7651.        Function 18 (Reallocate), the memory manager will increase or
  7652.        decrease the number of 16K-byte pages allocated to the handle. If
  7653.        Function 18 is passed a raw handle, the memory manager will increase
  7654.        or decrease the number of raw (non-16K-byte) pages allocated to the
  7655.        raw handle. For LIM standard boards, there is no difference between
  7656.        pages and raw pages.
  7657.  
  7658.    ■   The system Raw Handle (Raw Handle = 0000):
  7659.        For expanded memory boards that can remap the memory in the lower
  7660.        640K-byte address space, managing the pages of memory which are used
  7661.        to fill in the lower 640K can be a problem. To solve this problem, the
  7662.        memory manager will create a raw handle with a value of 0000 when DOS
  7663.        loads the manager. This raw handle is called the system handle.
  7664.  
  7665.        At power up, the memory manager will allocate all of the pages that
  7666.        are mapped into the lower 640K bytes to the system handle. These pages
  7667.        should be mapped in their logical order. For example, if the system
  7668.        board supplies 256K bytes of RAM, and the 384K bytes above it is
  7669.        mappable, the system handle should have its logical page zero mapped
  7670.        into the first physical page at 256K, its logical page one mapped into
  7671.        the next physical page, and so on.
  7672.  
  7673.        The system handle should deal with raw pages. To release some of these
  7674.        pages so application programs can use them, an operating system could
  7675.        decrease the number of pages allocated to the system handle with the
  7676.        "Reallocate" function. Invoking the "Deallocate" function would
  7677.        decrease the system handle to zero size, but it must not deallocate
  7678.        the raw handle itself. The "Deallocate" function treats the system
  7679.        handle differently than it treats other raw handles. If the operating
  7680.        system can ever be "exited" (for example, the way Windows can be
  7681.        exited), it must increase the size of the system handle back to what
  7682.        is needed to fill 640K and map these logical pages back into physical
  7683.        memory before returning to DOS.
  7684.  
  7685.        There are two functional special cases for this handle:
  7686.  
  7687.          -  The first special case deals with Function 4 (Allocate Pages).
  7688.             This function must never return zero as a handle value.
  7689.             Applications must always invoke Function 4 to allocate pages and
  7690.             obtain a handle which identifies its pages. Since Function 4 will
  7691.             never return a handle value of zero, an application will never
  7692.             gain access to this special handle.
  7693.  
  7694.          -  The second special case deals with Function 6 (Deallocate
  7695.             Pages). If the operating system uses Function 6 to deallocate the
  7696.             pages which are allocated to the system handle, the pages will be
  7697.             returned to the manager for use, but the handle will not be
  7698.             available for reassignment. The manager should treat a
  7699.             "deallocate pages" function request for this handle the same as a
  7700.             "reallocate pages" function request, where the number of pages to
  7701.             reallocate to this handle is zero.
  7702.  
  7703.    ■   Terminate and Stay Resident (TSR) Program Cooperation
  7704.        In order for TSR's to cooperate with each other and with other
  7705.        applications, TSR's must follow this rule: a program may only remap
  7706.        the DOS partition it lives in. This rule applies at all times, even
  7707.        when no expanded memory is present.
  7708.  
  7709.    ■   Accelerator Cards
  7710.        To support generic accelerator cards, the support of Function 34, as
  7711.        defined by AST, is encouraged.
  7712.  
  7713.  
  7714.  APPENDIX D  OPERATING SYSTEM/ENVIRONMENT USE OF FUNCTION 28
  7715.  
  7716.  All expanded memory boards have a set of registers that "remember" the
  7717.  logical to physical page mappings. Some boards have extra (or alternate)
  7718.  sets of these mapping registers. Because no expanded memory board can supply
  7719.  an infinite number of alternate map register sets, this specification
  7720.  provides a way to simulate them using Function 28 (Alternate Map Register
  7721.  Set).
  7722.  
  7723.  EXAMPLES
  7724.  
  7725.  For the examples in this section, assume the hardware supports alternate map
  7726.  register sets. First Windows is brought up, then "Reversi" is started. Then
  7727.  control is switched back to the MS-DOS Executive. For this procedure, here
  7728.  are the calls to the expanded memory manager:
  7729.  
  7730.  Example 1
  7731.  
  7732.  Allocate alt reg set          ; Start up the MS-DOS
  7733.  (for the MS-DOS executive)    ; Executive
  7734.  
  7735.  Set alt reg set
  7736.  (for MS-DOS Executive)
  7737.  
  7738.  Allocate alt reg set          ; Start up Reversi
  7739.  (for Reversi)
  7740.  
  7741.  Set alt reg set
  7742.  (for Reversi)
  7743.  
  7744.  Map pages
  7745.  (for Reversi)
  7746.  
  7747.  Set alt reg set               ; Switch back to MS-DOS
  7748.  (for MS-DOS Executive)        ; Executive
  7749.  
  7750.  Notice this procedure needed no "get" calls because the register set
  7751.  contained all the information needed to save a context. However, using "Get"
  7752.  calls would have no ill effects:
  7753.  
  7754.  Example 2
  7755.  
  7756.  Allocate alt reg set     ; Start up MS-DOS
  7757.  (for MS-DOS Executive)   ; Executive
  7758.  
  7759.  Set alt reg set
  7760.  (for MS-DOS Executive)
  7761.  
  7762.  Get alt reg set
  7763.  (for MS-DOS Executive)
  7764.  
  7765.  Allocate alt reg set     ; Start up Reversi
  7766.  (for Reversi)
  7767.  
  7768.  Set alt reg set
  7769.  (for Reversi)
  7770.  
  7771.  Map pages
  7772.  (for Reversi)
  7773.  
  7774.  Get alt reg set
  7775.  (for Reversi)
  7776.  
  7777.  Set alt reg set          ; Switch back to MS-DOS
  7778.  (for MS-DOS Executive)   ; Executive
  7779.  
  7780.  The important point to follow is that a Set must always precede a Get. The
  7781.  model of Set then Get is the inverse of what interrupt handlers use, which
  7782.  is Get then Set (Get the old map context and Set the new one). Another
  7783.  crucial point is that an alternate map register set must have the current
  7784.  mapping when allocated; otherwise, the Set will create chaos.
  7785.  
  7786.  What happens if this is simulated in software? The same Set and Get model
  7787.  applies. The main difference is where the context is saved.
  7788.  
  7789.  Since the allocate call is dynamic and there is no limit on the number of
  7790.  sets allocated, the OS/E must supply the space required. Device drivers
  7791.  cannot allocate space dynamically, since the request would fail. If the
  7792.  Allocate register set call returns a status indicating the alternate map
  7793.  register sets aren't supported, the OS/E must allocate space for the
  7794.  context. It must also initialize the context using Function 15. At that
  7795.  point it can do the Set, passing a pointer to the map context space. On the
  7796.  Get call, the EMM driver is to return a pointer to the same context space.
  7797.  
  7798.  Example 3
  7799.  
  7800.  Allocate alt reg set            ; Start up MS-DOS
  7801.  (for the MS-DOS executive)      ; Executive
  7802.  
  7803.  Get Page Map
  7804.  (for the MS-DOS executive)
  7805.  
  7806.  Set alt reg set
  7807.  (for MS-DOS Executive)
  7808.  
  7809.  Allocate alt reg set            ; Start up Reversi
  7810.  (for Reversi)
  7811.  
  7812.  Set alt reg set
  7813.  (for Reversi)
  7814.  
  7815.  Map pages
  7816.  (for Reversi)
  7817.  
  7818.  Get Page Map
  7819.  (for Reversi)
  7820.  
  7821.  Set alt reg set                 ; Switch back to MS-DOS
  7822.  (for MS-DOS Executive)          ; Executive
  7823.  
  7824.  
  7825.  
  7826.  GLOSSARY
  7827.  
  7828.  The following terms are used frequently in this specification:
  7829.  
  7830.  Allocate
  7831.    To reserve a specified amount of expanded memory pages.
  7832.  
  7833.  Application Program
  7834.    An application program is the program you write and your customer uses.
  7835.    Some categories of application software are word processors, database
  7836.    managers, spreadsheet managers, and project managers.
  7837.  
  7838.  Conventional memory
  7839.    The memory between 0 and 640K bytes, address range 00000h thru 9FFFFh.
  7840.  
  7841.  Deallocate
  7842.    To return previously allocated expanded memory to the memory manager.
  7843.  
  7844.  EMM
  7845.    See Expanded Memory Manager.
  7846.  
  7847.  Expanded memory
  7848.    Expanded memory is memory outside DOS's 640K-byte limit (usually in the
  7849.    range of C0000h through EFFFFH).
  7850.  
  7851.  Expanded Memory Manager (EMM)
  7852.    A device driver that controls the interface between DOS application
  7853.    programs and expanded memory.
  7854.  
  7855.  Extended memory
  7856.    The 15M-byte address range between 100000h thru FFFFFFh available on an
  7857.    80286 processor when it is operating in protected virtual address mode.
  7858.  
  7859.  Handle
  7860.    A value that the EMM assigns and uses to identify a block of memory
  7861.    requested by an application program. All allocated logical pages are
  7862.    associated with a particular handle.
  7863.  
  7864.  Logical Page
  7865.    The EMM allocates expanded memory in units (typically 16K-bytes) called
  7866.    logical pages.
  7867.  
  7868.  Mappable Segment
  7869.    A 16K-byte region of memory which can have a logical page mapped at it.
  7870.  
  7871.  Map Registers
  7872.    The set of registers containing the current mapping context of the EMM
  7873.    hardware.
  7874.  
  7875.  Mapping
  7876.    The process of making a logical page of memory appear at a physical page.
  7877.  
  7878.  Mapping context
  7879.    The contents of the mapping registers at a specific instant. This context
  7880.    represents a map state.
  7881.  
  7882.  Page Frame
  7883.    A collection of 16K-byte contiguous physical pages from which an
  7884.    application program accesses expanded memory.
  7885.  
  7886.  Page Frame Base Address
  7887.    A page frame base address is the location (in segment format) of the first
  7888.    byte of the page frame.
  7889.  
  7890.  Physical Page
  7891.    A physical page is the range of memory addresses occupied by a single 16K-
  7892.    byte page.
  7893.  
  7894.  Raw Page
  7895.    The smallest unit of mappable memory that an expanded memory board can
  7896.    supply.
  7897.  
  7898.  Resident Application Program
  7899.    A resident application program is loaded by DOS, executes, and remains
  7900.    resident in the system after it returns control to DOS. This type of
  7901.    program occupies memory and is usually invoked by the operating system, an
  7902.    application program, or the hardware. Some examples of resident
  7903.    application programs are RAM disks, print spoolers, and "pop-up" desktop
  7904.    programs.
  7905.  
  7906.  Status code
  7907.    A code that an EMM function returns which indicates something about the
  7908.    result of running the function. Some status codes indicate whether the
  7909.    function worked correctly and others may tell you something about he
  7910.    expanded memory hardware or software.
  7911.  
  7912.  Transient Application Program
  7913.    A transient application program is loaded by DOS, executes, and doesn't
  7914.    remain in the system after it returns control to DOS. After a transient
  7915.    application program returns control to DOS, the memory it used is
  7916.    available for other programs.
  7917.  
  7918.  Unmap
  7919.    To make a logical page inaccessible for reading or writing.
  7920.  
  7921.  
  7922.  
  7923.  INDEX
  7924.  
  7925.  Aliasing
  7926.  Allocate
  7927.  Allocate Pages Function
  7928.  Allocate Standard/Raw Pages Function
  7929.  Alter Page Map & Call Function
  7930.  Alter Page Map & Jump Function
  7931.  Alternate Map Register Set Function
  7932.  
  7933.  Conventional memory
  7934.  
  7935.  Deallocate Pages Function
  7936.  Deallocating
  7937.  
  7938.  EMM   See Expanded Memory Manager
  7939.  EMM Functions
  7940.       Function  1. Get Status
  7941.       Function  2. Get Page Frame Address
  7942.       Function  3. Get Unallocated Page Count
  7943.       Function  4. Allocate Pages
  7944.       Function  5. Map/Unmap Handle Page
  7945.       Function  6. Deallocate Pages
  7946.       Function  7. Get Version
  7947.       Function  8. Save Page Map
  7948.       Function  9. Restore Page Map
  7949.       Function 10. Reserved
  7950.       Function 11. Reserved
  7951.       Function 12. Get Handle Count
  7952.       Function 13. Get Handle Pages
  7953.       Function 14. Get All Handle Pages
  7954.       Function 15. Get/Set Page Map
  7955.       Function 16. Get/Set Partial Page Map
  7956.       Function 17. Map/Unmap Multiple Handle Pages
  7957.       Function 18. Reallocate Pages
  7958.       Function 19. Get/Set Handle Attribute
  7959.       Function 20. Get/Set Handle Name
  7960.       Function 21. Get Handle Directory
  7961.       Function 22. Alter Page Map & Jump
  7962.       Function 23. Alter Page Map & Call
  7963.       Function 24. Move/Exchange Memory Region
  7964.       Function 25. Get Mappable Physical Address Array
  7965.       Function 26. Get Expanded Memory Hardware Information
  7966.       Function 27. Allocate Standard/Raw Pages
  7967.       Function 28. Alternate Map Register Set
  7968.       Function 29. Prepare Expanded Memory Hardware Warmboot
  7969.       Function 30. Enable/Disable OS/E Function Set Function
  7970.       Summary tables
  7971.  Enable/Disable OS/E Function Set Function
  7972.  Expanded Memory
  7973.       How it Works
  7974.       Writing programs that use it
  7975.  Expanded Memory Manager (EMM)
  7976.       Testing for the presence of
  7977.       Implementation Guidelines
  7978.  
  7979.  Function Codes
  7980.  
  7981.  Get All Handle Pages Function
  7982.  Get Expanded Memory Hardware Information Function
  7983.  Get Handle Count Function
  7984.  Get Handle Directory Function
  7985.  Get Handle Pages Function
  7986.  Get Mappable Physical Address Array Function
  7987.  Get Page Frame Address Function
  7988.  Get/Set Handle Attribute Function
  7989.  Get/Set Handle Name Function
  7990.  Get/Set Page Map Function
  7991.  Get/Set Partial Page Map Function
  7992.  Get Status Function
  7993.  Get Unallocated Page Count Function
  7994.  Get Version Function
  7995.  
  7996.  Handle
  7997.       Using
  7998.       Attributes
  7999.  
  8000.  LIM
  8001.  Logical Page
  8002.  
  8003.  Mappable Segment
  8004.  Map Registers
  8005.  Mapping
  8006.  Mapping context
  8007.  Map/Unmap Handle Page Function
  8008.  Map/Unmap Multiple Handle Pages Function
  8009.  Move/Exchange Memory Region Function
  8010.  
  8011.  OS/E Function Set Functions Function
  8012.  
  8013.  Page Frame
  8014.  Physical Page
  8015.  Prepare Expanded Memory Hardware Warmboot Function
  8016.  
  8017.  Raw Page
  8018.  Reallocate Pages
  8019.  Restore Page Map Function
  8020.  
  8021.  Save Page Map Function
  8022.  Status Codes
  8023.  
  8024.  Unmapping
  8025.  
  8026.  Writing Programs
  8027.       What Every Program Must Do
  8028.       Advanced Programming
  8029.       Programming Guidelines
  8030.       Examples
  8031.