home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / EMSIF24.ZIP / EMSIF.DOC next >
Text File  |  1993-06-27  |  58KB  |  1,259 lines

  1.                                  EMSIF
  2.           Version-independent C Interface to LIM EMS Functions
  3.                   for LIM EMS versions 3.0 and higher
  4.                            EMSIF version 2.4
  5.                           by James W. Birdsall
  6.                                 06/27/93
  7.  
  8.  
  9. 0. CONTENTS
  10. -----------
  11.  
  12.    0.     CONTENTS
  13.    I.     INTRODUCTION
  14.     I.1    WHAT IS SUPPORTED
  15.     I.2    COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
  16.    II.    USING EMSIF
  17.     II.1   COMPILING AND LINKING WITH THE LIBRARIES
  18.     II.2   EMSTEST, THE EXAMPLE PROGRAM
  19.    III.   PROGRAMMING WITH EMSIF
  20.     III.1  INITIALIZING THE LIBRARY
  21.     III.2  ORDINARY USE
  22.     III.3  FRAME CACHING AND ALIASING
  23.     III.4  SAVE/RESTORE
  24.     III.5  OTHER TIPS
  25.     III.6  FUNCTION GROUPING
  26.    IV.    LIBRARY REFERENCE
  27.     IV.1   GLOBAL VARIABLES
  28.     IV.2   FUNCTIONS
  29.    V.     ERROR CODES
  30.     V.1    INTERNAL ERRORS
  31.     V.2    EMS DRIVER ERRORS
  32.    VI.    THE END
  33.     VI.1   ACKNOWLEDGEMENTS
  34.     VI.2   TRADEMARKS
  35.  
  36.  
  37. I. INTRODUCTION
  38. ---------------
  39.  
  40.    EMSIF provides a high-level interface to LIM EMS control functions
  41. for common operations such as allocating, mapping, and freeing EMS, and
  42. copying data to and from EMS. The interface has been made independent of
  43. the EMS version implemented by the EMS driver as far as possible, so
  44. that parameters and returned data are always in the same format, but the
  45. EMS call most appropriate to the EMS version implemented by the driver
  46. is used.
  47.  
  48.    EMSIF is written in assembly language for speed and compactness and
  49. assembled with Borland's Turbo Assembler (TASM) 2.5. The source code is
  50. not compatible with the Microsoft Assembler (MASM).
  51.  
  52.  I.1 WHAT IS SUPPORTED
  53.  ---------------------
  54.  
  55.    EMSIF expressly supports the Lotus-Intel-Microsoft (LIM) Expanded
  56. Memory Specification (EMS) versions 3.0, 3.2, and 4.0. Versions above
  57. 4.0 are supported as 4.0. Versions below 3.0 are not supported.
  58. Save/restore is not supported under version 3.0, and assigning names to
  59. EMS handles and unmapping logical pages are only supported under version
  60. 4.0. These exceptions to version-independence are due to limitations of
  61. the unsupported versions; the necessary services are not available from
  62. the driver.
  63.  
  64.    EMSIF supports tiny, small, medium, compact, large, and huge memory
  65. models. The small model library supports both tiny and small models, so
  66. no library is provided specifically for tiny model.
  67.  
  68.    EMSIF supports any version of Turbo C, Turbo C++, or Borland C++, in
  69. both C and C++ modes, and Microsoft C 6.00 and above. This version of
  70. EMSIF has been tested with Borland C++ 2.0, Turbo C 2.0, Microsoft C 7.0
  71. and 8.0 (in Microsoft Visual C++ 1.0) in all of the supported memory
  72. models. EMSIF should work with earlier versions of Microsoft C and any
  73. other C compiler that 1) uses compatible parameter passing and return
  74. methods and 2) can use standard-format libraries.
  75.  
  76.  I.2 COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
  77.  -----------------------------------------------
  78.  
  79.    EMSIF is not in the public domain. All the files are copyright 1991,
  80. 1992, 1993 by James W. Birdsall, all rights reserved. Permission is
  81. granted to do the following:
  82.  
  83.         You may freely redistribute this archive, so long as it contains
  84.         all the files listed in the file MANIFEST, intact and
  85.         unmodified.
  86.  
  87.         You may use the libraries in programs for your own use. You may
  88.         not distribute programs linked with these libraries.
  89.  
  90.    Payment of the $5 shareware registration fee ($50 for commercial use)
  91. grants the following license, in addition to the permissions listed
  92. above:
  93.  
  94.         You may request the source to EMSIF. You may modify the source
  95.         as necessary for use in your programs. However, you may not
  96.         redistribute either the original or modified source.
  97.  
  98.         You may distribute programs linked with either the original
  99.         libraries or libraries generated from source you have modified,
  100.         without royalty, provided you (a) do not alter or remove
  101.         copyright notices contained therein and (b) you indemnify, hold
  102.         harmless, and defend the author from and against any claims or
  103.         lawsuits, including attorney's fees, that arise or result from
  104.         the use or distribution of your software product. 
  105.  
  106. For the purposes of this license, commercial use is defined as use by an
  107. incorporated entity in a software product that is regarded as the
  108. product of the corporation, no matter how the software product is
  109. distributed, but only if 100 or more copies of the product are expected
  110. to be made.
  111.  
  112.    The contents of the distribution archive, and all other related
  113. files, information, and services are provided "as is" and without
  114. warranty. To the extent permitted by applicable law, the author
  115. disclaims all warranties, express or implied, including but not limited
  116. to, any implied warranty of merchantability or fitness for a particular
  117. purpose. While effort has been made to ensure that the files, information,
  118. and services are accurate and correct, the author shall not be liable
  119. for damages arising out of the use of or inability to use this product,
  120. including but not limited to, loss of profit, data, or use of this
  121. software, or special, incidental, or consequential damages or other
  122. similar claims, even if the author has been specifically advised of the
  123. possibility of such damages. Some states do not allow the exclusion of
  124. incidental or consequential damages, so the foregoing limitation may not
  125. apply to you.
  126.  
  127.    Information on contacting the author is provided at the end of this
  128. file.
  129.  
  130.  
  131. II. USING EMSIF
  132. ---------------
  133.  
  134.    This section describes how to use the EMSIF libraries with your
  135. programs.
  136.  
  137.  II.1 COMPILING AND LINKING WITH THE LIBRARIES
  138.  ---------------------------------------------
  139.  
  140.    EMSIF is provided as Borland/Microsoft standard library files.
  141. Libraries are provided for small, medium, compact, large, and huge
  142. memory models (tiny model uses the small model library). The model for
  143. which a library is intended is indicated by the last letter of the
  144. filename proper, which is the same as the first letter for the model.
  145. For example, EMSIFL.LIB is the large model library.
  146.  
  147.    To use EMSIF, you must #include the file EMSIF.H in every source file
  148. that calls EMSIF functions, accesses EMSIF global variables, or uses
  149. #defined constants provided by EMSIF. The same EMSIF.H file supports
  150. both C and C++.
  151.  
  152.    The procedures for linking EMSIF with the rest of your program vary
  153. according to the compiler and method you are using. In general, you must
  154. include the appropriate library (the library corresponding to the memory
  155. model in which you have compiled the rest of your program) in the link.
  156.  
  157.    If you are compiling in the Integrated Development Environment of
  158. Turbo/Borland C[++] or Microsoft Visual C++, include the name of the
  159. appropriate library in the project file for your program. For example,
  160. if you are working in the compact memory model, include EMSIFC.LIB in
  161. your project file.
  162.  
  163.    If you are using a command-line compiler (bcc, tcc, or cl) to compile
  164. and link, simply place the full name of the appropriate EMSIF library on
  165. the command line. For example, "bcc -mc foo.c emsifc.lib" will compile
  166. the file "foo.c" in the compact model and link it with emsifc.lib.
  167.  
  168.    If you are linking manually (using TLINK or LINK), place the name of
  169. the appropriate library in with the other libraries. For example,
  170.         tlink c0c.obj foo.obj, foo.exe, foo.map, cc.lib emsifc.lib
  171. or
  172.         link foo.obj, foo.exe, foo.map, emsifc.lib ;
  173. will link the object "foo.obj" with the appropriate startup object and
  174. standard library (LINK automatically includes the startup object and
  175. standard library, so it is not necessary to explicitly include them) and
  176. the compact model EMSIF library.
  177.  
  178.  II.2 EMSTEST, THE EXAMPLE PROGRAM
  179.  ---------------------------------
  180.  
  181.    A large and complete example program and tester, EMSTEST, has been
  182. included in this distribution. It can be compiled in any of the
  183. supported memory models (although tiny model for all compilers and
  184. compact model for Microsoft compilers require some contortions to do
  185. so), with either Borland or Microsoft compilers.
  186.  
  187.    The test program has four source files: EMSTEST.C, EMSTEST2.C,
  188. EMSTEST3.C, and TESTUTIL.C; and two header files: EMSTEST.H and
  189. TESTUTIL.H. When compiling in tiny model with Borland compilers, an
  190. additional file, STACK.OBJ, is needed. STACK.ASM, which is the source
  191. for STACK.OBJ, has been included for completeness.
  192.  
  193.    Example makefiles have been included for Borland and Microsoft
  194. compilers. EXMAKEBC is the example makefile for Borland C++ 2.0,
  195. EXMAKETC is the example makefile for Turbo C[++], and EXMAKEMS is the
  196. example makefile for Microsoft C. Complete instructions for making the
  197. example program and using the example makefiles are included at the
  198. beginning of each makefile. More information about the program is also
  199. included at the beginning of EMSTEST.C.
  200.  
  201.    EMSTEST requires at least eight pages (128K) of available expanded
  202. memory and at least 200,000 bytes of available conventional memory to
  203. run.
  204.  
  205.  
  206. III. PROGRAMMING WITH EMSIF
  207. ----------------------------
  208.  
  209.    This section describes how to make EMSIF calls in your program, and
  210. details various tricks and tips which you may find useful.
  211.  
  212.  III.1 INITIALIZATION
  213.  --------------------
  214.  
  215.    The library initialization function EMMlibinit() _must_ be called
  216. before any other EMSIF calls are made. All other EMSIF functions are
  217. guaranteed to fail if called before EMMlibinit(). EMMlibinit()
  218. determines whether an EMS driver is present and sets up various internal
  219. and global variables necessary to the functioning of EMSIF.
  220.  
  221.  III.2 ORDINARY USE
  222.  ------------------
  223.  
  224.    EMSIF provides several sets of functions. First, there is a set of
  225. functions which are intended to be orthogonal with the standard C
  226. functions malloc(), free(), and realloc(), and the Borland/Turbo C[++]
  227. function coreleft(). These functions are EMMalloc(), EMMfree(),
  228. EMMrealloc(), and EMMcoreleft().
  229.  
  230.    Second, there is a group of functions for copying data to and from
  231. expanded memory. These functions allow you to treat allocated blocks of
  232. expanded memory pages as linear memory, hiding the details of page
  233. mapping. These functions are EMMcopyto(), EMMcopyfrom(), EMMicopyto(),
  234. EMMicopyfrom(), _EMMicopyto(), and _EMMicopyfrom().
  235.  
  236.    Third, there is a group of low-level functions which allow more
  237. direct access to EMS driver calls. These functions are EMMallocpages(),
  238. EMMreallocpages(), EMMgetframeaddr(), EMMgetnumframe(),
  239. EMMgetsinfraddr(), EMMmappage(), and EMMunmapframe(). With these
  240. functions it is possible to duplicate the copying functions or access
  241. expanded memory in other ways. Calls to these functions can be mixed
  242. with calls to copying functions without trouble, except as noted in
  243. section IV.2 for EMS versions below 4.0.
  244.  
  245.    Fourth, there is a group of miscellaneous functions: EMMgetname(),
  246. EMMsetname(), EMMgetversion(), EMMsave(), and EMMrestore().
  247.  
  248.    Finally, there is a group of functions which affect only the
  249. operation of EMSIF itself: _EMMenc(), _EMMdisc(), _EMMinval(),
  250. EMMlibinit(), and EMMsrinit(). For details on all the functions listed
  251. above, see section IV.2.
  252.  
  253.    To use expanded memory, first it is necessary to allocate some. This
  254. can be done with either EMMalloc(), which takes a size in bytes, or
  255. EMMallocpages(), which allocates EMS pages directly. Both return a
  256. handle which will be used to reference the allocated memory.
  257.  
  258.    To access the expanded memory, you can either use the copying
  259. functions or access it directly. The copying functions are pretty
  260. self-explanatory, so they will not be discussed further here. Accessing
  261. expanded memory directly is more complicated. First, it is necessary to
  262. determine the addresses of the EMS page frames. EMS page frames 0
  263. through 3 are available under all EMS versions and are intended for
  264. general use. While EMS version 4.0 implementations may provide
  265. additional page frames, they are intended for use by multitaskers such
  266. as Quarterdeck DESQview and Microsoft Windows. These additional page
  267. frames may appear anywhere, even in the middle of your program. Use them
  268. only with great caution. To obtain the addresses of all page frames, use
  269. EMMgetframeaddr(). To obtain the address of a single page frame, use
  270. EMMgetsinfraddr(). The addresses returned by both these functions are
  271. segment addresses and must be converted to far pointers before actually
  272. being used.
  273.  
  274.    Having decided which page frame or frames you wish to use, and
  275. determined the necessary addresses, it is then necessary to map EMS
  276. logical pages into the page frame(s). This is accomplished with
  277. EMMmappage(). Once this is done, you can then access any byte in that
  278. logical page (which is 16384 bytes long) using the far pointer created
  279. earlier. Mapping a logical page into a page frame into which another
  280. logical page has already been mapped causes the original logical page to
  281. be displaced by the new logical page. A logical page may be mapped in
  282. any number of times (although "aliasing" -- having one mapped into
  283. multiple page frames simultaneously -- may cause unexpected results),
  284. and a page frame can have logical pages mapped into it any number of
  285. times (but only the last one mapped is accessible in that page frame).
  286. Under EMS 4.0, it is possible to remove the logical page currently
  287. mapped into a frame with EMMunmapframe(), leaving no page mapped into
  288. that frame.
  289.  
  290.    Eventually, when you are done using the EMS, use EMMfree() to
  291. deallocate it.
  292.  
  293.    The miscellaneous functions listed above allow you to determine the
  294. EMS version supported by the driver (EMMgetversion()), to associate a
  295. string name with an EMS handle and retrieve the name associated with an
  296. EMS handle (EMMsetname()/EMMgetname()), and save and restore EMS page
  297. mappings (EMMsave()/EMMrestore()). More information on the last is
  298. available in section III.4.
  299.  
  300.    The internal functions _EMMenc(), _EMMdisc(), and _EMMinval() are
  301. discussed in section III.3 below. EMMlibinit() has already been
  302. discussed, in section III.1, and EMMsrinit() is discussed in section
  303. III.4 below.
  304.  
  305.    Many functions return a status directly. For those functions, a
  306. return value of 0 indicates success and a return value of EMMOOPS
  307. indicates failure. The global variable _EMMerror contains an error code
  308. which gives further information on why the function failed, or has value
  309. 0 if the function succeeded. Many functions return some other value
  310. instead of a status code (0 or EMMOOPS). In these cases, the value of
  311. _EMMerror should be checked upon return. The recommended method of
  312. error-checking is indicated for each function in section IV.2 below.
  313.  
  314.  III.3 FRAME CACHING AND ALIASING
  315.  --------------------------------
  316.  
  317.    Aliasing occurs when one logical page is mapped into multiple page
  318. frames. This can cause a variety of problems if the EMS implementation
  319. does not support aliasing well. Frequently, data written to the page in
  320. one frame will not be visible in other frames to which that page is
  321. mapped. At least one common implementation displays this problem.
  322.  
  323.    Frame caching is a technique used by EMSIF to attempt to speed up the
  324. copying functions. By keeping track of the handle and logical page
  325. number mapped into page frame 2, the copying functions can avoid
  326. unnecessary calls to the page-mapping functions.
  327.  
  328.    However, frame caching has a variety of problems. First, it assumes
  329. that all EMS mapping activity will be performed via EMSIF, so that an
  330. accurate record of the contents of frame 2 can be kept. If you are using
  331. another third-party library that also uses EMS, then obviously there is
  332. mapping activity that is not performed via EMSIF, and frame caching will
  333. cause the copying functions to malfunction. Worse, there are some
  334. EMS-using disk caches and ramdisks which do not properly restore the EMS
  335. page mapping, so apparently unrelated activity such as file access can
  336. cause the copying functions to malfunction. Because of these risks,
  337. frame caching is off by default.
  338.  
  339.    The second major problem is due to aliasing; if the copying functions
  340. leave the last logical page accessed mapped into page frame 2, attempts
  341. to access that logical page by mapping it into some other page frame may
  342. produce incorrect data. Hence, for EMS versions that have unmapping
  343. capability, the copying functions unmap the last logical page accessed
  344. just before returning. This means that frame caching is not possible
  345. across calls to the copying functions, only within single calls.
  346.  
  347.    Frame caching is off by default. To check the current setting, inspect
  348. the global variable _EMMframecache. If it is nonzero, frame caching is
  349. on; if it is 0, frame caching is off. The state of frame caching is
  350. changed via the functions _EMMenc() (enable caching) and _EMMdisc()
  351. (disable caching).
  352.  
  353.  III.4 SAVE/RESTORE
  354.  ------------------
  355.  
  356.    Interactions with other libraries using EMS can pose problems. If the
  357. other library assumes that the EMS mapping will not change between calls
  358. to it, then almost any EMSIF activity at all will interfere with the
  359. other library. This is why save/restore capability was added to EMSIF.
  360. Note that save/restore only works with EMS versions 3.2 and up. EMS
  361. version 3.0 has a save/restore capability so radically different from
  362. that in versions 3.2 and up that it cannot be consolidated under the
  363. same interface. If you use save/restore in your program, you give up
  364. compatibility with EMS version 3.0; fortunately 3.0 is extremely rare
  365. these days.
  366.  
  367.    The EMS specification (for versions 3.2 and up) includes calls to
  368. save the current EMS mapping to a buffer in memory, and restore a
  369. mapping from such a buffer. EMSIF's save/restore functions are an
  370. interface to these calls. Before any save/restore calls can be made,
  371. EMMsrinit() must be called to initialize save/restore. It takes a single
  372. parameter, which is a pointer to a function used to allocate save
  373. buffers. Malloc() may be passed in any memory model, but any other
  374. function with the same prototype may be used. Note that the passed
  375. function will never be required to allocate more that 255 bytes in one
  376. call.
  377.  
  378.    Having initialized save/restore, you can call EMMsave() to save a
  379. mapping and EMMrestore() to restore one. The pointer returned by
  380. EMMsave() is the value returned by an internal call to the function
  381. which was passed to EMMsrinit(), and may be freed when necessary with
  382. whatever function would ordinarily be called; for example, if malloc()
  383. was passed to EMMsrinit(), then pointers returned by EMMsave() may be
  384. passed to free(). Note that EMMrestore() does not free save buffers. You
  385. must free them yourself.
  386.  
  387.    To avoid interference with libraries which assume that the EMS
  388. mapping will not change, simply call EMMsave() after calls to that
  389. library, and call EMMrestore() with the pointer returned by the last
  390. EMMsave() before the next call to that library. Note that EMMrestore()
  391. invalidates the frame cache, if frame caching is enabled.
  392.  
  393.    Save/restore can also be used to quickly alternate between several
  394. complex mappings. Having established a mapping, save it with EMMsave().
  395. Then, when you need it again, a call to EMMrestore() will restore it
  396. quickly and easily. A given mapping may be restored from the same buffer
  397. any number of times.
  398.  
  399.  III.5 OTHER TIPS
  400.  ----------------
  401.  
  402.    Expanded memory is not deallocated automatically when a program
  403. exits. If the program does not deallocate expanded memory it has
  404. allocated, that expanded memory is stuck, not available to any other
  405. program until the machine is rebooted. Under normal circumstances, it is
  406. easy enough to free expanded memory when it is no longer needed.
  407. However, an emergency exit due to the user hitting control-break or due
  408. to a hardware error (e.g. the famous "Abort, Retry, Fail?") can cause
  409. expanded memory to become stuck unless your program takes special
  410. measures to intercept these errors and perform cleanup before exiting.
  411. There are a number of ways to do this and they vary from compiler to
  412. compiler. Look for functions such as ctrlbrk(), harderr(), and signal().
  413.  
  414.    If you are copying array elements, _EMMicopyto()/_EMMicopyfrom() or
  415. EMMicopyto()/EMMicopyfrom() may be more efficient. These functions allow
  416. copying of elements of fixed size which are separated by gaps also of
  417. fixed size. For example, if you have an array of integers and wish to
  418. copy all the even-indexed elements (a[0], a[2], a[4], etc.), these
  419. functions are far faster than calling a standard copying function
  420. (EMMcopyto() or EMMcopyfrom()) from within a loop. While the performance
  421. improvement varies from machine to machine, the smallest speed increase
  422. that I have seen is seven times, ranging up to over twenty times on a
  423. fast machine with frame caching off.
  424.  
  425.  III.6 FUNCTION GROUPING
  426.  -----------------------
  427.  
  428.    The EMSIF functions have been arranged in the library in such a way
  429. as to reduce the number of unnecessary functions linked into your
  430. program. There are currently five groups:
  431.  
  432.                 FUNCTIONS                               VARIABLES
  433.                 ---------                               ---------
  434. GROUP 1:        EMMlibinit(), EMMgetversion(),          _EMMerror, _EMMversion,
  435.                 EMMgetnumframe(), EMMgetsinfraddr(),    _EMMframecache,
  436.                 EMMgetframeaddr(), EMMmappage(),        emsif_vers_vers,
  437.                 EMMunmapframe()                         emsif_vers_date,
  438.                                                         emsif_vers_time
  439.  
  440. GROUP 2:        EMMcoreleft(), EMMallocpages(),         none
  441.                 EMMalloc(), EMMreallocpages(),
  442.                 EMMrealloc(), EMMfree()
  443.  
  444. GROUP 3:        EMMcopyto(), EMMcopyfrom(),             none
  445.                 _EMMicopyto(), _EMMicopyfrom(),
  446.                 _EMMenc(), _EMMdisc()
  447.  
  448. GROUP 4:        EMMsrinit(), EMMsave(), EMMrestore()    none
  449.  
  450. GROUP 5:        EMMgetname(), EMMsetname()              none
  451.  
  452. If your program references any of the functions or variables in a group,
  453. all the functions and variables in that group will be linked in. Note
  454. that group one will always be linked, since it contains EMMlibinit(),
  455. which all EMSIF-using programs must call.
  456.  
  457.  
  458. IV. LIBRARY REFERENCE
  459. ---------------------
  460.  
  461.  IV.1 GLOBAL VARIABLES
  462.  ---------------------
  463.  
  464.   _EMMerror
  465.   ---------
  466.  
  467.    unsigned char const _EMMerror;
  468.  
  469.    _EMMerror contains the error code from the last EMSIF call. If the
  470. call succeeded, _EMMerror will be 0. If the call failed because the EMS
  471. driver returned an error, _EMMerror contains the error code returned by
  472. the EMS driver. If the call failed because EMSIF detected an error
  473. internally, _EMMerror contains an intenal error code. A list of error
  474. code values, their meanings, and #defined constants for them is in
  475. section V.
  476.  
  477.   _EMMframecache
  478.   --------------
  479.  
  480.    unsigned char const _EMMframecache;
  481.  
  482.    _EMMframecache is a flag which indicates whether frame caching is
  483. enabled or not. A nonzero value indicates that frame caching is enabled,
  484. and 0 indicates that frame caching is disabled. See section III.3 for a
  485. discussion of frame caching.
  486.  
  487.   _EMMversion
  488.   -----------
  489.  
  490.    unsigned char const _EMMversion;
  491.  
  492.    _EMMversion contains the EMS version implemented by the EMS driver in
  493. packed BCD format. For example, if the EMS version is 4.0, the value of
  494. _EMMversion will be 0x40. If _EMMversion is 0x32, the EMS version is
  495. 3.2. This value is the same as that returned by EMMgetversion().
  496.  
  497.   emsif_vers_vers, emsif_vers_date, emsif_vers_time
  498.   -------------------------------------------------
  499.  
  500.    char const emsif_vers_vers[];
  501.    char const emsif_vers_date[];
  502.    char const emsif_vers_time[];
  503.  
  504.    These are null-terminated strings containing information about the
  505. name and version of the library, the date of assembly, and the time of
  506. assembly, respectively.
  507.  
  508.  IV.2 FUNCTIONS
  509.  --------------
  510.  
  511.   _EMMdisc() - disable frame caching
  512.   ----------
  513.  
  514.    void _EMMdisc(void);
  515.    void _EMMenc(void);
  516.    void _EMMinval(void);
  517.  
  518.    _EMMdisc() disables frame caching, invalidates the current cache
  519. contents, and sets _EMMframecache to zero. _EMMerror should be checked
  520. after calling this function. It is not an error to call this function
  521. when frame caching is already disabled.
  522.  
  523.    _EMMenc() enables frame caching, invalidates the current cache
  524. contents, and sets _EMMframecache to a nonzero value. _EMMerror should
  525. be checked after calling this function. It is not an error to call this
  526. function when frame caching is already enabled; however, the current
  527. cache contents will still be invalidated.
  528.  
  529.    _EMMinval() is a macro (in C) or inline function (in C++) that
  530. invalidates the current cache contents if frame caching is enabled, or
  531. has no effect if frame caching is disabled. The frame caching status is
  532. not changed. _EMMerror should be checked afterwards.
  533.  
  534.    For more information on frame caching, see section III.3.
  535.  
  536.   _EMMenc() - enable frame caching
  537.   ---------
  538.  
  539.    void _EMMenc(void);
  540.  
  541.    See _EMMdisc();
  542.  
  543.   _EMMicopyfrom() - copy data by intervals from EMS
  544.   ---------------
  545.  
  546.    int _EMMicopyfrom(unsigned long nelem, int elsize,
  547.                      unsigned int srcskip, int handle, unsigned long foffset,
  548.                      unsigned char far *dest, unsigned int destskip);
  549.    int _EMMicopyto(unsigned long nelem, int elsize,
  550.                    unsigned int srcskip, unsigned char far *source,
  551.                    int handle, unsigned long foffset, unsigned int destskip);
  552.  
  553.    _EMMicopyfrom() allows painless copying of array elements from
  554. expanded memory to conventional memory. EMS mapping, calculation of
  555. addresses, skipping of unwanted elements, etc., are all handled by the
  556. function. Elements spread across more than 64K and/or totalling more than
  557. 64K in length can be copied without special treatment.
  558.    Nelem elements are copied, each of which is elsize bytes long. The
  559. elements are copied from the EMS pages owned by handle, starting at byte
  560. offset foffset and with srcskip bytes between elements, to conventional
  561. memory starting at dest with destskip bytes between elements. Dest must
  562. be a far pointer; a near pointer can be converted to a far pointer with
  563. a cast when the function is called. Foffset is converted as in
  564. EMMcopyfrom().
  565.    If nelem or elsize is zero, the function returns immediately without
  566. error. Elsize must be in the range 0 through 16384, or the function will
  567. return with error EMM_ELTOOBIG (in _EMMerror). Byteskip must be in the
  568. range 0 through 32768, or the function will return with error
  569. EMM_SKTOOBIG.
  570.    This function returns 0 on success or EMMOOPS on error. The specific
  571. error may be determined from _EMMerror.
  572.  
  573.    _EMMicopyto() allows painless copying of array elements from
  574. conventional memory to expanded memory. EMS mapping, calculation of
  575. addresses, skipping of unwanted elements, etc., are all handled by the
  576. function. Elements spread across more than 64K and/or totalling more than
  577. 64K in length can be copied without special treatment.
  578.    Nelem elements are copied, each of which is elsize bytes long. The
  579. elements are copied from conventional memory starting at source with
  580. srcskip bytes between elements, to the EMS pages owned by handle, starting
  581. at byte offset foffset and with destskip bytes between elements. Source
  582. must be a far pointer; a near pointer can be converted to a far pointer
  583. with a cast when the function is called. Foffset is converted as in
  584. EMMcopyfrom().
  585.    If nelem or elsize is zero, the function returns immediately without
  586. error. Elsize must be in the range 0 through 16384, or the function will
  587. return with error EMM_ELTOOBIG (in _EMMerror). Byteskip must be in the
  588. range 0 through 32768, or the function will return with error
  589. EMM_SKTOOBIG.
  590.    This function returns 0 on success or EMMOOPS on error. The specific
  591. error may be determined from _EMMerror.
  592.  
  593.    For EMS versions below 4.0, these functions leave the last logical
  594. page accessed mapped into page frame 2 because there is no unmapping
  595. service. This can cause trouble if you map that logical page into
  596. another page frame in an EMS implementation that does not support
  597. aliasing properly. If you must mix calls to EMMmappage() and the copying
  598. functions, it is recommended that for versions below 4.0 you map some
  599. other logical page into page frame 2 before mapping the desired page.
  600. Alternatively, using page frame 2 to access logical pages is guaranteed
  601. to work properly except for logical pages which you have explicitly
  602. mapped elsewhere.
  603.  
  604.   _EMMicopyto() - copy data by intervals to EMS
  605.   -------------
  606.  
  607.    int _EMMicopyto(unsigned long nelem, int elsize,
  608.                    unsigned int srcskip, unsigned char far *source,
  609.                    int handle, unsigned long foffset, unsigned int destskip);
  610.  
  611.  
  612.    See _EMMicopyfrom().
  613.  
  614.   _EMMinval() - invalidate frame cache contents
  615.   -----------
  616.  
  617.    void _EMMinval(void);
  618.  
  619.    See _EMMdisc().
  620.  
  621.   EMMalloc() - allocate EMS
  622.   ----------
  623.  
  624.    int EMMalloc(unsigned long bytes);
  625.    int EMMallocpages(int pages);
  626.  
  627.    EMMalloc() allocates EMS memory. It takes the given number of bytes
  628. and allocates the smallest number of pages which contain that many
  629. bytes. It returns the EMS handle assigned by the EMS driver. _EMMerror
  630. should be checked after calling this function.
  631.    Note that EMS cannot be allocated in units smaller than a page (16384
  632. bytes). Requesting one byte will allocate a whole page; 16385 bytes will
  633. allocate two pages. Requesting zero bytes allocates one page.
  634.  
  635.    EMMallocpages() allocates EMS memory by pages directly. It returns
  636. the EMS handle assigned by the EMS driver. _EMMerror should be checked
  637. after calling this function. It is possible to allocate 0 pages with
  638. this function, but only under EMS version 4.0; under earlier versions,
  639. allocating 0 pages is an error.
  640.  
  641.    See also EMMrealloc() and EMMreallocpages().
  642.  
  643.   EMMallocpages() - allocate EMS by pages
  644.   ---------------
  645.  
  646.    int EMMallocpages(int pages);
  647.  
  648.    See EMMalloc().
  649.  
  650.   EMMcopyfrom() - copy data from EMS
  651.   -------------
  652.  
  653.    int EMMcopyfrom(unsigned long copylen,
  654.                    int handle, unsigned long foffset,
  655.                    unsigned char far *dest);
  656.    int EMMcopyto(unsigned long copylen,
  657.                  unsigned char far *source,
  658.                  int handle, unsigned long foffset);
  659.  
  660.    EMMcopyfrom() allows painless copying of blocks of data from expanded
  661. memory to conventional memory. All mapping, calculation of addresses,
  662. etc., is handled by the function. Copies longer than 64K are possible
  663. without special treatment.
  664.    Copylen bytes of data are copied, from the EMS pages owned by handle,
  665. starting at byte offset foffset, to the conventional memory area pointed
  666. to by dest. Dest must be a far pointer; a near pointer can be converted
  667. to a far pointer with a cast when the function is called. Foffset ia
  668. converted to a logical page number and offset within that page by
  669. dividing by the size of a page (16384 bytes). The quotient is the page
  670. number and the remainder is the offset within that page. Offsets 0
  671. through 16383 are in page 0; offsets 16384 through 32767 are in page 1,
  672. etc. This feature allows you to treat expanded memory blocks as linear
  673. memory rather than a collection of pages.
  674.    This function returns 0 on success or EMMOOPS on error. The specific
  675. error may be determined from _EMMerror. If copylen is 0, the function
  676. returns immediately without error.
  677.  
  678.    EMMcopyto() is the mirror image of EMMcopyfrom(). It allows painless
  679. copying of blocks of data from conventional memory to expanded memory.
  680. All mapping, calculation of addresses, etc., is handled by the function.
  681. Copies longer than 64K are possible without special treatment.
  682.    Copylen bytes of data are copied, from the conventional memory area
  683. pointed to by source, to the EMS pages owned by handle, starting at byte
  684. offset foffset. Foffset is converted as in EMMcopyfrom().
  685.    This function returns 0 on success or EMMOOPS on error. The specific
  686. error may be determined from _EMMerror. If copylen is 0, the function
  687. returns immediately without error.
  688.  
  689.    For EMS versions below 4.0, these functions leave the last logical
  690. page accessed mapped into page frame 2 because there is no unmapping
  691. service. This can cause trouble if you map that logical page into
  692. another page frame in an EMS implementation that does not support
  693. aliasing properly. If you must mix calls to EMMmappage() and the copying
  694. functions, it is recommended that for versions below 4.0 you map some
  695. other logical page into page frame 2 before mapping the desired page.
  696. Alternatively, using page frame 2 to access logical pages is guaranteed
  697. to work properly except for logical pages which you have explicitly
  698. mapped elsewhere.
  699.  
  700.    See also EMMicopyto(), EMMicopyfrom(), _EMMicopyto(), and
  701. _EMMicopyfrom().
  702.  
  703.   EMMcopyto() - copy data to EMS
  704.   -----------
  705.  
  706.    int EMMcopyto(unsigned long copylen,
  707.                  unsigned char far *source,
  708.                  int handle, unsigned long foffset);
  709.  
  710.    See EMMcopyfrom().
  711.  
  712.   EMMcoreleft() - get amount of free EMS
  713.   -------------
  714.  
  715.    unsigned long EMMcoreleft(void);
  716.  
  717.    This function returns the amount of EMS memory available, in bytes.
  718. To determine the number of EMS pages available, divide the returned
  719. value by 16384. _EMMerror should be checked after calling this function.
  720.  
  721.   EMMfree() - deallocate EMS
  722.   ---------
  723.  
  724.    int EMMfree(int handle);
  725.  
  726.    This function accepts an EMS handle (as returned by EMMalloc(),
  727. EMMallocpages(), EMMrealloc(), or EMMreallocpages() or otherwise
  728. obtained from the EMS driver) and releases it and any EMS pages
  729. allocated to it.
  730.    This function returns 0 on success or EMMOOPS on error. The specific
  731. error may be determined from _EMMerror.
  732.  
  733.   EMMgetframeaddr() - get EMS page frame segment addresses
  734.   -----------------
  735.  
  736.    int EMMgetframeaddr(frameinfo *buffer);
  737.    int EMMgetnumframe(void);
  738.    unsigned int EMMgetsinfraddr(int frame);
  739.  
  740.    EMMgetframeaddr() returns the segment addresses of all the EMS page
  741. frames. Buffer is a pointer to an array of frameinfo structures; this
  742. array is assumed to be large enough to contain information about all the
  743. frames. The number of frameinfo structures needed can be determined with
  744. the EMMgetnumframe() function described below.
  745.    Each frameinfo structure contains the number and the segment address
  746. of a frame. Check EMSIF.H or EMSIF.HPP for the exact format of the
  747. frameinfo structure. The information is returned in whatever order the
  748. EMS driver provides it, which is typically sorted by address rather than
  749. frame number. Do NOT just assume that the first element in the array
  750. contains information for frame 0! The segment addresses returned must be
  751. converted to far pointers (using MK_FP() or your compiler's equivalent)
  752. before they can be used to access memory.
  753.    This function returns 0 on success or EMMOOPS on error. The specific
  754. error may be determined from _EMMerror.
  755.  
  756.    EMMgetnumframe() returns the number of EMS page frames present in the
  757. system. For EMS versions below 4.0, this will always be 4. For EMS
  758. version 4.0, it will be at least 4.
  759.    _EMMerror should be checked after calling this function.
  760.  
  761.    EMMgetsinfraddr() returns the segment address of a particular EMS
  762. page frame. This address must be converted to a far pointer (using
  763. MK_FP() or your compiler's eqivalent) before it can be used to access
  764. memory.
  765.    Note that this function calls EMMgetframeaddr() internally and
  766. allocates a temporary buffer for it on the stack. Therefore, depending
  767. on how many page frames the system has, this function may require many
  768. bytes of stack space. There is an absolute top limit of 60 page frames
  769. in a system, so not more than 60 * sizeof(frameinfo) bytes will ever be
  770. needed.
  771.    _EMMerror should be checked after calling this function.
  772.  
  773.   EMMgetname() - obtain string name associated with an EMS handle
  774.   ------------
  775.  
  776.    int EMMgetname(int handle, char *name);
  777.    int EMMsetname(int handle, char *name);
  778.  
  779.    EMMgetname() returns (as a null-terminated string) the name, if any,
  780. assigned to an EMS handle. Real names are only implemented in EMS
  781. version 4.0. Under earlier versions, this function fills the name buffer
  782. with nulls ('\0'), which is also the return under version 4.0 when no
  783. name has been associated with the given handle. The buffer pointed to by
  784. name must be at least nine characters long (since an EMS name may be up
  785. to eight characters long and there must be room for a terminating null).
  786.    This function returns 0 on success or EMMOOPS on error. The specific
  787. error may be determined from _EMMerror.
  788.  
  789.    EMMsetname() allows the association of a name up to eight characters
  790. long with an EMS handle. It only works for EMS version 4.0; under
  791. earlier versions, it returns the error EMM_BADVERS. Version independence
  792. has been abandoned in this case because the main purpose of associating
  793. a name with an EMS handle is to allow several different programs to
  794. recognize shared data. While EMSIF could implement a naming function
  795. within itself, the names would not be visible outside the program
  796. assigning the name, defeating the purpose of doing so in the first
  797. place.
  798.    This function returns 0 on success or EMMOOPS on error. The specific
  799. error may be determined from _EMMerror.
  800.  
  801.   EMMgetnumframe() - obtain number of EMS page frames
  802.   ----------------
  803.  
  804.    int EMMgetnumframe(void);
  805.  
  806.    See EMMgetframeaddr().
  807.  
  808.   EMMgetsinfraddr() - get segment address of one EMS page frame
  809.   -----------------
  810.  
  811.    unsigned int EMMgetsinfraddr(int frame);
  812.  
  813.    See EMMgetframeaddr().
  814.  
  815.   EMMgetversion() - obtain EMS version implemented by EMS driver
  816.   ---------------
  817.  
  818.    int EMMgetversion(void);
  819.  
  820.    This function returns the EMS version implemented by the EMS driver.
  821. The version number is in packed BCD format as in the global variable
  822. _EMMversion, and is in fact the same value. _EMMerror should be checked
  823. after calling this function.
  824.  
  825.   EMMicopyfrom() - copy data by intervals from EMS
  826.   --------------
  827.  
  828.    int EMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
  829.                     int handle, unsigned long foffset,
  830.                     unsigned char far *dest);
  831.    int EMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
  832.                   unsigned char far *source,
  833.                   int handle, unsigned long foffset);
  834.  
  835.    EMMicopyfrom() is a macro (in C) or inline function (in C++) which
  836. calls _EMMicopyfrom(). It allows painless copying of array elements from
  837. expanded memory to conventional memory. EMS mapping, calculation of
  838. addresses, skipping of unwanted elements, etc., are all handled by the
  839. function. Elements spread across more than 64K and/or totalling more
  840. than 64K in length can be copied without special treatment.
  841.    Nelem elements are copied, each of which is elsize bytes long, with
  842. byteskip bytes between elements at both source and destination. The
  843. elements are copied from the EMS pages owned by handle, starting at byte
  844. offset foffset, to conventional memory starting at dest. Dest must be a
  845. far pointer; a near pointer can be converted to a far pointer with a cast
  846. when the function is called. Foffset is converted as in EMMcopyfrom().
  847.    If nelem or elsize is zero, the function returns immediately without
  848. error. Elsize must be in the range 0 through 16384, or the function will
  849. return with error EMM_ELTOOBIG (in _EMMerror). Byteskip must be in the
  850. range 0 through 32768, or the function will return with error
  851. EMM_SKTOOBIG.
  852.    This function returns 0 on success or EMMOOPS on error. The specific
  853. error may be determined from _EMMerror.
  854.  
  855.    EMMicopyto() is a macro (in C) or inline function (in C++) which
  856. calls _EMMicopyto(). It allows painless copying of array elements from
  857. conventional memory to expanded memory. EMS mapping, calculation of
  858. addresses, skipping of unwanted elements, etc., are all handled by the
  859. function. Elements spread across more than 64K and/or totalling more
  860. than 64K in length can be copied without special treatment.
  861.    Nelem elements are copied, each of which is elsize bytes long, with
  862. byteskip bytes between elements at both source and destination. The elements
  863. are copied from conventional memory starting at source, to the EMS pages
  864. owned by handle, starting at byte offset foffset. Source must be a far
  865. pointer; a near pointer can be converted to a far pointer with a cast when
  866. the function is called. Foffset is converted as in EMMcopyfrom().
  867.    If nelem or elsize is zero, the function returns immediately without
  868. error. Elsize must be in the range 0 through 16384, or the function will
  869. return with error EMM_ELTOOBIG (in _EMMerror). Byteskip must be in the
  870. range 0 through 32768, or the function will return with error
  871. EMM_SKTOOBIG.
  872.    This function returns 0 on success or EMMOOPS on error. The specific
  873. error may be determined from _EMMerror.
  874.  
  875.    For EMS versions below 4.0, these functions leave the last logical
  876. page accessed mapped into page frame 2 because there is no unmapping
  877. service. This can cause trouble if you map that logical page into
  878. another page frame in an EMS implementation that does not support
  879. aliasing properly. If you must mix calls to EMMmappage() and the copying
  880. functions, it is recommended that for versions below 4.0 you map some
  881. other logical page into page frame 2 before mapping the desired page.
  882. Alternatively, using page frame 2 to access logical pages is guaranteed
  883. to work properly except for logical pages which you have explicitly
  884. mapped elsewhere.
  885.  
  886.   EMMicopyto() - copy data by intervals to EMS
  887.   ------------
  888.  
  889.    int EMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
  890.                   unsigned char far *source,
  891.                   int handle, unsigned long foffset);
  892.  
  893.    See EMMicopyfrom().
  894.  
  895.   EMMlibinit() - initialize EMSIF
  896.   ------------
  897.  
  898.    int EMMlibinit(void);
  899.  
  900.    EMMlibinit() initializes EMSIF. Any other EMSIF function will return
  901. with error EMM_NOINIT (in _EMMerror) if called before EMMlibinit() has
  902. been called. This function returns 0 on success, EMMOOPS on error, or
  903. NOEMM if no EMS driver is detected. If EMMOOPS is returned, the specific
  904. error may be determined from _EMMerror. Note that EMSIF will not
  905. initialize if the EMS driver claims that fewer than four EMS page frames
  906. exist, since that is a violation of the EMS specification and the driver
  907. may have other anomalies that EMSIF does not know how to handle.
  908.    Detection of the EMS driver relies on DOS services, so this library
  909. cannot be used in a device driver as it stands. If you need this library
  910. for a device driver or other program that cannot access DOS services,
  911. you can buy the source (it's cheap) and easily modify EMMlibinit() to
  912. use another method of detection. There are no other calls to DOS
  913. services in EMSIF. The method used was chosen for its reliability;
  914. there is another method, suitable for use in device drivers, which is
  915. not as reliable and typically is useful _only_ for device drivers.
  916.  
  917.   EMMmappage() - map an EMS logical page into an EMS page frame
  918.   ------------
  919.  
  920.    int EMMmappage(int frameno, int handle, int logpage);
  921.    int EMMunmapframe(int frameno);
  922.  
  923.    EMMmappage() maps a logical page into an EMS page frame so that it
  924. can be accessed. The logical page logpage belonging to handle is mapped
  925. into page frame number frameno.
  926.    This function returns 0 on success or EMMOOPS on error. The specific
  927. error may be determined from _EMMerror.
  928.  
  929.    EMMunmapframe() unmaps the logical page currently mapped into page
  930. frame number frameno, if any, leaving nothing mapped into that page
  931. frame. This function only works under EMS versions 4.0 and up; version
  932. independence has been abandoned in this case because earlier versions do
  933. not provide this functionality and there is no good way to fake it.
  934. EMMunmapframe() places EMM_BADVERS in _EMMerror if the EMS version is
  935. below 4.0.
  936.    This function returns 0 on success or EMMOOPS on error. The specific
  937. error may be determined from _EMMerror.
  938.  
  939.   EMMrealloc() - change size of an allocated block of EMS
  940.   ------------
  941.  
  942.    int EMMrealloc(int handle, unsigned long bytes);
  943.    int EMMreallocpages(int handle, int pages);
  944.  
  945.    EMMrealloc() adjusts the size of the previously allocated EMS block
  946. referenced by handle to be the smallest number of pages which contain
  947. the given number of bytes, and returns an EMS handle which may or may
  948. not be different from the old handle. If it is different, the old handle
  949. is invalid. The contents of the block are preserved as far as possible.
  950. If the new size is smaller, the contents of the block are truncated; if
  951. larger, the additional bytes at the end of the block are undefined.
  952.    If the new number of pages is the same as that currently allocated to
  953. the handle, EMMrealloc() returns immediately without error. EMMrealloc()
  954. works best under EMS versions 4.0 and up, where an actual reallocation
  955. service is available. Under earlier versions, EMSIF allocates a new
  956. block and copies the contents of the old block, meaning that there must
  957. be enough free EMS to allocate a new block of the desired size. If there
  958. is not enough free EMS, the old block is left intact.
  959.    _EMMerror should be checked after calling this function.
  960.  
  961.    EMMreallocpages() adjusts the size of the previously allocated EMS
  962. block referenced by handle to be the given number of pages, and returns
  963. an EMS handle which may or may not be different from the old handle. If
  964. it is different, the old handle is invalid. The contents of the block
  965. are preserved as far as possible. If the new size is smaller, the
  966. contents of the block are truncated; if larger, the contents of the
  967. additional pages at the end of the block are undefined.
  968.    If the new number of pages is the same as that currently allocated to
  969. the handle, EMMreallocpages() returns immediately without error.
  970. EMMreallocpages() works best under EMS versions 4.0 and up, where an
  971. actual reallocation service is available. Under earlier versions, EMSIF
  972. allocates a new block and copies the contents of the old block, meaning
  973. that there must be enough free EMS to allocate a new block of the
  974. desired size. If there is not enough free EMS, the old block is left
  975. intact.
  976.    _EMMerror should be checked after calling this function.
  977.  
  978.   EMMreallocpages() - change size of an allocated block of EMS
  979.   -----------------
  980.  
  981.    int EMMreallocpages(int handle, int pages);
  982.  
  983.    See EMMrealloc().
  984.  
  985.   EMMrestore() - restore an EMS mapping from a save buffer
  986.   ------------
  987.  
  988.    int EMMrestore(void *saveblock);
  989.    void *EMMsave(void);
  990.    int EMMsrinit(void *(*mallocfunc)(size_t));
  991.  
  992.    EMMrestore() restores an EMS mapping that has earlier been saved in a
  993. save buffer with a call to EMMsave(). The contents of the frame cache
  994. are invalidated, since the format of the contents of the save buffer
  995. varies from one EMS driver to the next and it is thus not possible to
  996. determine what will be mapped into the cached frame when the restore is
  997. done. EMMrestore() does not deallocate the save buffer.
  998.    This function returns 0 on success or EMMOOPS on error. The specific
  999. error may be determined from _EMMerror. It is an error if this function
  1000. is called before EMMsrinit() has been called.
  1001.  
  1002.    EMMsave() allocates a save buffer (see EMMsrinit(), below) and saves
  1003. the current EMS mapping into it. The current EMS mapping is not changed,
  1004. nor are the contents of the frame cache invalidated. This function
  1005. returns the pointer returned by the allocation function (see below).
  1006.    _EMMerror should be checked after calling this function. It is an
  1007. error if this function is called before EMMsrinit() has been called.
  1008.  
  1009.    EMMsrinit() initializes the save/restore capability of EMSIF. It
  1010. takes a pointer to a memory-allocation function which is used by
  1011. EMMsave() to allocate save buffers. Malloc() is compatible in all memory
  1012. models, but any function which works the same way (returns a void
  1013. pointer of the size normal for the memory model (near or far), takes a
  1014. single parameter of type size_t which is the number of bytes to
  1015. allocate, and returns NULL (0) if the memory cannot be allocated) can
  1016. also be used. Note that the function will never be required to allocate
  1017. more than 255 bytes in one call.
  1018.    EMMsrinit() will fail to initialize and return EMM_BADVERS if the EMS
  1019. version is 3.0. Since it did not initialize, EMMsave() and EMMrestore()
  1020. will not work either.
  1021.    _EMMerror should be checked after calling this function.
  1022.  
  1023.    For more information on frame caching and suggestions on using
  1024. save/restore, see sections III.3 and III.4 respectively.
  1025.  
  1026.   EMMsave() - save an EMS mapping into a save buffer
  1027.   ---------
  1028.  
  1029.    void *EMMsave(void);
  1030.  
  1031.    See EMMrestore().
  1032.  
  1033.   EMMsetname() - associate string name with an EMS handle
  1034.   ------------
  1035.  
  1036.    int EMMsetname(int handle, char *name);
  1037.  
  1038.    See EMMgetname().
  1039.  
  1040.   EMMsrinit() - initialize save/restore
  1041.   -----------
  1042.  
  1043.    int EMMsrinit(void *(*mallocfunc)(size_t));
  1044.  
  1045.    See EMMrestore().
  1046.  
  1047.   EMMunmapframe() - remove logical page mapped into a page frame
  1048.   ---------------
  1049.  
  1050.    int EMMunmapframe(int frameno);
  1051.  
  1052.    See EMMmappage().
  1053.  
  1054.  
  1055. V. ERROR CODES
  1056. --------------
  1057.  
  1058.    This section is a list of the error codes to which the global variable
  1059. _EMMerror may be set, and the values and meanings thereof.
  1060.  
  1061.  V.1 INTERNAL ERRORS
  1062.  -------------------
  1063.  
  1064.    Internal codes indicate an error detected by EMSIF itself.
  1065.  
  1066.    NAME                 VALUE     MEANING
  1067.    ----                 -----     -------
  1068.    EMM_BADVERS           0x40     Bad EMS version, earlier than 3.0.
  1069.  
  1070.    EMM_BADOFFSET         0x41     Offset plus copy length runs off last
  1071.                                   EMS page owned by handle.
  1072.  
  1073.    EMM_NOFRAME           0x42     Could not find segment address of page frame
  1074.                                   used for copying functions (frame 2).
  1075.  
  1076.    EMM_NOINIT            0x43     EMMlibinit() must be called before any
  1077.                                   other EMSIF function can be called.
  1078.  
  1079.    EMM_FEWFRAMES         0x44     The EMS driver claims that there are fewer
  1080.                                   than four page frames.
  1081.  
  1082.    EMM_NOSR              0x45     EMMsrinit() must be called before
  1083.                                   EMMsave() or EMMrestore() can be called.
  1084.  
  1085.    EMM_MEMNULL           0x46     The save/restore memory allocation
  1086.                                   function (the one passed to EMMsrinit())
  1087.                                   returned NULL.
  1088.  
  1089.    EMM_ELTOOBIG          0x47     The element size passed to EMMicopyto()
  1090.                                   or EMMicopyfrom() is too big.
  1091.  
  1092.    EMM_SKTOOBIG          0x48     The skip size passed to EMMicopyto()
  1093.                                   or EMMicopyfrom() is too big.
  1094.  
  1095.  V.2 EMS DRIVER ERRORS
  1096.  ---------------------
  1097.  
  1098.    These codes are defined in the EMS specification and are returned by
  1099. the EMS driver. They are saved in _EMMerror by EMSIF without alteration.
  1100.  
  1101.    NAME                 VALUE     MEANING
  1102.    ----                 -----     -------
  1103.    EMM_SOFTERROR         0x80     Internal error exists in EMS driver (can
  1104.                                   indicate corrupted memory image of driver)
  1105.  
  1106.    EMM_HARDERROR         0x81     Malfunction in expanded memory hardware
  1107.  
  1108.    EMM_BUSY              0x82     EMS driver is busy
  1109.  
  1110.    EMM_BADHANDLE         0x83     Invalid EMS handle
  1111.  
  1112.    EMM_UNIMP             0x84     Function not defined
  1113.  
  1114.    EMM_NOFREEHAN         0x85     No free EMS handles
  1115.  
  1116.    EMM_CONTEXTERR        0x86     Error in save or restore of mapping context
  1117.  
  1118.    EMM_WAYTOOBIG         0x87     Tried to allocate more pages than physically
  1119.                                   exist in system; no pages allocated
  1120.  
  1121.    EMM_TOOBIG            0x88     Tried to allocate more pages than currently
  1122.                                   available; no pages allocated
  1123.  
  1124.    EMM_TOOSMALL          0x89     Cannot allocate 0 pages
  1125.  
  1126.    EMM_BADLOGPAGE        0x8A     Requested logical page is outside range of
  1127.                                   pages owned by handle
  1128.  
  1129.    EMM_BADFRAMENO        0x8B     Illegal frame number in mapping request
  1130.  
  1131.    EMM_HSTATESAVFULL     0x8C     Page-mapping hardware-state save area full
  1132.  
  1133.    EMM_MSTATESAVFULL     0x8D     Mapping-context save failed; save area
  1134.                                   already contains context associated with
  1135.                                   specified handle
  1136.  
  1137.    EMM_MSTATERESTERR     0x8E     Mapping-context restore failed; save area
  1138.                                   does not contain context for specified
  1139.                                   handle
  1140.  
  1141.    EMM_UNIMPSUB          0x8F     Subfunction parameter not defined
  1142.  
  1143.    EMM_BADATTRIB         0x90     Attribute type not defined
  1144.  
  1145.    EMM_NOFEATURE         0x91     Feature not supported
  1146.  
  1147.    EMM_SRCOVERWRITE      0x92     Source and destination memory regions have
  1148.                                   same handle and overlap; requested move
  1149.                                   was performed, but part of the source region
  1150.                                   was overwritten
  1151.  
  1152.    EMM_BADLENGTH         0x93     Copy length longer than actual length
  1153.  
  1154.    EMM_CONEMSOVERLAP     0x94     Conventional memory region and expanded
  1155.                                   memory region overlap
  1156.  
  1157.    EMM_OFFPAGE           0x95     Specified offset outside logical page
  1158.  
  1159.    EMM_TOOLONG           0x96     Copy length exceeds one megabyte
  1160.  
  1161.    EMM_EMSEMSOVERLAP     0x97     Source and destination memory regions have
  1162.                                   same handle and overlap; exchange cannot be
  1163.                                   performed
  1164.  
  1165.    EMM_LOST              0x98     Memory source and destination types
  1166.                                   undefined
  1167.  
  1168.    EMM_UNUSED            0x99     This error code is currently unused
  1169.  
  1170.    EMM_BADALTREG         0x9A     Alternate map or DMA register sets are
  1171.                                   supported, but specified alternate register
  1172.                                   set is not supported
  1173.  
  1174.    EMM_NOFREEALTREG      0x9B     Alternate map or DMA register sets are
  1175.                                   supported, but all alternate register sets
  1176.                                   are currently allocated
  1177.  
  1178.    EMM_NOALTREG          0x9C     Alternate map or DMA register sets are not
  1179.                                   supported, specified alternate register
  1180.                                   set is not 0
  1181.  
  1182.    EMM_BADALTREG2        0x9D     Alternate map or DMA register sets are
  1183.                                   supported, but the alternate register set
  1184.                                   specified is not defined or not allocated
  1185.  
  1186.    EMM_NODEDDMA          0x9E     Dedicated DMA channels are not supported
  1187.  
  1188.    EMM_BADDEDDMA         0x9F     Dedicated DMA channels are supported, but
  1189.                                   specified DMA channel is not supported
  1190.  
  1191.    EMM_UNKNAME           0xA0     Handle for specified name not found
  1192.  
  1193.    EMM_NAMETAKEN         0xA1     Handle with same name already exists
  1194.  
  1195.    EMM_ADDRWRAP          0xA2     Memory address wraps; sum of source or
  1196.                                   destination region base address and length
  1197.                                   exceeds one megabyte
  1198.  
  1199.    EMM_BADPTR            0xA3     Invalid pointer passed to function, or
  1200.                                   contents of source array corrupted
  1201.  
  1202.    EMM_FORBIDDENFUNC     0xA4     Access to function denied by operating
  1203.                                   system
  1204.  
  1205. VI. THE END
  1206. -----------
  1207.  
  1208.    Technical support via email is available from the following addresses:
  1209.  
  1210.    INTERNET:
  1211.       The following are alternate addresses for the same place:
  1212.          support@picarefy.com
  1213.          picarefy!support@amc.com
  1214.          picarefy!support@netcom.com
  1215.          uunet!netcom!picarefy!support
  1216.  
  1217.    COMPUSERVE:
  1218.       71261,1731
  1219.  
  1220.    GENIE:
  1221.       J.BIRDSALL2
  1222.  
  1223.    Registrations should be sent to:
  1224.  
  1225.    (until 7/10/93)
  1226.       James W. Birdsall
  1227.       11112 NE 124 LN #D204
  1228.       Kirkland, WA 98034
  1229.  
  1230.    (after 7/10/93)
  1231.       11106 NE 125 LN #J203
  1232.       Kirkland, WA 98034
  1233.  
  1234.    If you have an email address on any of the networks listed above,
  1235. please include it when registering, especially if you are requesting
  1236. source code. It is much easier to send the source code by email. Also,
  1237. please specify what sort of archive (ZIP, ZOO, ARC, LZH, ARJ, UNIX shar)
  1238. you can handle most easily.
  1239.  
  1240.  VI.1 ACKNOWLEDGEMENTS
  1241.  ---------------------
  1242.  
  1243.    Thanks to Bob Parsons of Parsons Technology Inc. for some good suggestions
  1244. on the documentation and for providing the original C++ header file.
  1245.  
  1246.    Thanks to Jim Gomes of WordPerfect Inc. for suggesting that I unify
  1247. the C and C++ headers.
  1248.  
  1249.  VI.2 TRADEMARKS
  1250.  ---------------
  1251.  
  1252.    MS-Windows is a trademark of the Microsoft Corporation.
  1253.  
  1254.    DESQview is a trademark of Quarterdeck Office Systems.
  1255.  
  1256.    Any other trademarks in this document are property of their
  1257. respective holders.
  1258.  
  1259.