home *** CD-ROM | disk | FTP | other *** search
- XMSIF
- C Interface to XMS Functions
- XMSIF version 1.42
- by James W. Birdsall
- 11/14/92
-
-
- 0. CONTENTS
- -----------
-
- 0. CONTENTS
- I. INTRODUCTION
- I.1 WHAT IS SUPPORTED
- I.2 COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
- II. COMPILING AND LINKING WITH THE LIBRARIES
- II.1 WITH C
- II.2 WITH C++
- II.3 XMSTEST, THE EXAMPLE PROGRAM
- III. PROGRAMMING WITH XMSIF
- III.1 INITIALIZING THE LIBRARY
- III.2 ORDINARY USE
- III.3 TIPS ON USING EMBS
- III.4 TIPS ON USING UMBS
- III.5 OTHER TIPS
- III.6 FUNCTION GROUPINGS
- IV. LIBRARY REFERENCE
- IV.1 GLOBAL VARIABLES
- IV.2 EMB FUNCTIONS
- IV.3 UMB FUNCTIONS
- V. ERROR CODES
- V.1 INTERNAL ERRORS
- V.2 XMS DRIVER ERRORS
- VI. THE END
- VI.1 ACKNOWLEDGEMENTS
-
-
- I. INTRODUCTION
- ---------------
-
- XMSIF provides a high-level interface to XMS control functions for
- common operations such as allocating and freeing XMS extended memory
- blocks (EMBs) and upper memory blocks (UMBs), and copying data to and
- from EMBs. A raw interface to the driver has been included to allow more
- convenient access to driver functions not otherwise supported.
-
- XMSIF is written in assembly language for speed and assembled with
- Borland's Turbo Assembler (TASM) 2.5. The source code is not compatible
- with the Microsoft Assembler (MASM).
-
- I.1 WHAT IS SUPPORTED
- ---------------------
-
- XMSIF expressly supports the Microsoft eXtended Memory Specification
- (XMS) version 2.0. Versions below 2.0 are not supported. Versions above
- 2.0 are supported as 2.0.
-
- XMSIF supports tiny, small, medium, compact, large, and huge memory
- models. The small model library supports both tiny and small models, so
- no library is provided specifically for tiny model.
-
- XMSIF supports any version of Turbo C, Turbo C++, or Borland C++, in
- both C and C++ modes, and Microsoft C 6.00/A and C/C++ 7.0. XMSIF has
- been tested with Borland C++ 2.0, Turbo C 2.0, Microsoft C 6.00A, and
- Microsoft C/C++ 7.0 in all of the supported memory models. XMSIF should
- work with earlier versions of Microsoft C and any other MS-DOS C
- compiler that 1) uses compatible parameter passing and return methods
- and 2) can use standard-format libraries.
-
- I.2 COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
- -----------------------------------------------
-
- XMSIF is not in the public domain. All the files are copyright 1991,
- 1992 by James W. Birdsall, all rights reserved. Permission is granted to
- do the following:
-
- You may freely redistribute this archive, so long as it contains
- all the files listed in the file MANIFEST, intact and
- unmodified.
-
- You may use the libraries in programs for your own use. You may
- not distribute programs linked with these libraries.
-
- Payment of the $5 shareware registration fee ($50 for commercial use)
- grants the following license, in addition to the permissions listed
- above:
-
- You may request the source to XMSIF. You may modify the source
- as necessary for use in your programs. However, you may not
- redistribute either the original or modified source. There is no
- additional charge for source.
-
- You may distribute programs linked with either the original
- libraries or libraries generated from source you have modified,
- without royalty, provided you (a) do not alter or remove
- copyright notices contained therein and (b) you indemnify, hold
- harmless, and defend the author from and against any claims or
- lawsuits, including attorney's fees, that arise or result from
- the use or distribution of your software product.
-
- For the purposes of this license, commercial use is defined as use by an
- incorporated entity in a software product that is regarded as the
- product of the corporation, no matter how the software product is
- distributed, but only if 100 or more copies of the product are expected
- to be made.
-
- Registered users will also receive update notices and bug reports,
- and are entitled to use future versions without further payment.
-
- The contents of the distribution archive, and all other related
- files, information, and services are provided "as is" and without
- warranty. To the extent permitted by applicable law, the author
- disclaims all warranties, express or implied, including but not limited
- to, any implied warranty of merchantability or fitness for a particular
- purpose. While effort has been made to ensure that the files, information,
- and services are accurate and correct, the author shall not be liable
- for damages arising out of the use of or inability to use this product,
- including but not limited to, loss of profit, data, or use of this
- software, or special, incidental, or consequential damages or other
- similar claims, even if the author has been specifically advised of the
- possibility of such damages. Some states do not allow the exclusion of
- incidental or consequential damages, so the foregoing limitation may not
- apply to you.
-
- Information on contacting the author is provided at the end of this
- file.
-
-
- II. COMPILING AND LINKING WITH THE LIBRARIES
- --------------------------------------------
-
- This section describes how to use the XMSIF libraries with your
- programs.
-
- XMSIF is provided as Borland/Microsoft standard library files.
- Libraries are provided for small, medium, compact, large, and huge
- memory models (tiny model uses the small model library). The model for
- which a library is intended is indicated by the last letter of the
- filename proper, which is the same as the first letter for the model.
- For example, XMSIFL.LIB is the large model library.
-
- II.1 WITH C
- -----------
-
- To use XMSIF in C programs, you must #include the file XMSIF.H in
- every source file that calls XMSIF functions, accesses XMSIF global
- variables, or uses #defined constants provided by XMSIF.
-
- The procedures for linking XMSIF with the rest of your program vary
- according to the compiler and method you are using. In general, you must
- include the appropriate library (the library corresponding to the memory
- model in which you have compiled the rest of your program) in the link.
-
- If you are compiling in the Integrated Development Environment of
- Turbo/Borland C[++], you should include the name of the appropriate
- library in the project file for your program. For example, if you are
- working in the compact memory model, you should include XMSIFC.LIB in
- your project file.
-
- If you are using a command-line compiler (bcc, tcc, or cl) to compile
- and link, simply place the full name of the appropriate XMSIF library on
- the command line. For example, "bcc -mc foo.c xmsifc.lib" will compile
- the file "foo.c" in the compact model and link it with xmsifc.lib.
-
- If you are linking manually (using TLINK or LINK), place the name of
- the appropriate library in with the other libraries. For example,
- tlink c0c.obj foo.obj, foo.exe, foo.map, cc.lib xmsifc.lib
- or
- link foo.obj, foo.exe, foo.map, xmsifc.lib ;
- will link the object "foo.obj" with the appropriate startup object and
- standard library (LINK automatically includes the startup object and
- standard library, so it is not necessary to explicitly include them) and
- the compact model XMSIF library.
-
- II.2 C++
- --------
-
- To use XMSIF in C++ programs, you must #include the file XMSIF.HPP in
- every file that calls XMSIF functions, accesses XMSIF global variables,
- or uses #defined constants provided by XMSIF. Be careful to include
- XMSIF.HPP instead of XMSIF.H. If you include the wrong one, you will
- probably see "undefined symbol" errors when linking.
-
- Otherwise, the procedures for using XMSIF with C++ programs are the
- same as for using it with C programs.
-
- II.3 XMSTEST, THE EXAMPLE PROGRAM
- ---------------------------------
-
- A large and complete example program and tester, XMSTEST, has been
- included in this distribution. It can be compiled in any of the
- supported memory models, with either Borland or Microsoft compilers.
-
- The test program has four source files: XMSTEST.C, XMSTEST2.C,
- XMSTEST3.C, and TESTUTIL.C, and two header files: XMSTEST.H and
- TESTUTIL.H. When compiling in tiny model with Borland compilers, an
- additional source file, STACK.ASM, is needed. STACK.OBJ, which is
- STACK.ASM pre-assembled, has been included for those who do not have
- assemblers.
-
- Example makefiles have been included for Borland and Microsoft
- compilers. EXMAKEBC is the example makefile for Borland C++ 2.0,
- EXMAKETC is the example makefile for Turbo C[++], and EXMAKEMS is the
- example makefile for Microsoft C. Complete instructions for making the
- example program and using the example makefiles are included at the
- beginning of each makefile. More information about the program is also
- included at the beginning of XMSTEST.C.
-
- XMSTEST requires a single free EMB of at least 81,920 bytes in order
- to perform the copy-function tests. It requires at least one free UMB in
- order to perform all the UMB-function tests. If your system does not
- support UMBs, XMSTEST will note this fact and skip inappropriate
- UMB-function tests. If your system does support UMBs but none are free,
- XMSTEST will assume that your system does not support UMBs and will also
- skip inappropriate UMB-function tests. XMSTEST also requires at least
- 165,000 bytes of available conventional memory to run.
-
- XMSTEST may require the command-line parameters "-q" or "-w" to run
- on your system. A full explanation of these parameters and what they do
- may be found at the beginning of XMSTEST.C.
-
-
- III. PROGRAMMING WITH XMSIF
- ---------------------------
-
- This section describes how to make XMSIF calls in your program, and
- details various tricks and tips which you may find useful.
-
- III.1 INITIALIZATION
- --------------------
-
- The library initialization function XMMlibinit() _must_ be called
- before any other XMSIF calls are made. All other XMSIF functions are
- guaranteed to fail if called before XMMlibinit(). XMMlibinit()
- determines whether an XMS driver is present and sets up various internal
- and global variables necessary to the functioning of XMSIF.
-
-
- III.2 ORDINARY USE
- ------------------
-
- XMSIF provides several sets of functions. First, there is a set of
- functions which are intended to be orthogonal with the standard C
- functions malloc() and free(), and the Borland/Turbo C[++] function
- coreleft(), for EMBs. These functions are XMMalloc(), XMMfree(),
- XMMcoreleft(), and XMMallcoreleft().
-
- Second, there is a group of functions for copying data to and from
- EMBs. These functions are XMMcopyto(), XMMcopyfrom(), _XMMcopy(),
- XMMicopyto(), XMMicopyfrom(), and _XMMicopy().
-
- Third, there is a group of miscellaneous functions: XMMlibinit(),
- XMMgetversion(), and XMMrawcall().
-
- Finally, there is a set of functions which are intended to be
- orthogonal with the standard C functions malloc() and free(), and the
- Borland/Turbo C[++] function coreleft(), for UMBs. These functions are
- UMBalloc(), UMBfree(), UMBcoreleft(), and UMBallcoreleft(). For details
- on these functions and all the others listed above, see section IV.2.
-
- To use EMBs (Extended Memory Blocks), first it is necessary to
- allocate some. This is done with XMMalloc(), which takes a size in bytes
- and returns a handle which will be used to reference the allocated
- memory. EMBs are subject to fragmentation problems; it is not possible
- to allocate with XMMalloc() more extended memory than is in the largest
- free block. The size of the largest free block, in bytes, is returned by
- XMMcoreleft(). The total of all free EMBs is returned by
- XMMallcoreleft(). Other considerations about using EMBs are discussed in
- section III.3 below.
-
- The only way to get data to or from an EMB is via the XMS driver's
- copying functions. The XMSIF copying functions provide handy interfaces
- to the underlying driver functions and provide extra processing to
- remove some of the limitations on the driver functions (such as the
- inability to copy an odd number of bytes).
-
- The miscellaneous functions listed above initialize XMSIF
- (XMMlibinit(), see section III.1), return the XMS version implemented by
- the driver (XMMgetversion()), and allow programs to call the driver more
- directly, specifying values for all the relevant registers
- (XMMrawcall()).
-
- Finally, to use UMBs (Upper Memory Blocks, which may exist in unused
- spaces between 640K and 1M), first it is necessary to allocate one (or
- more). This is done with UMBalloc(), which takes a size in bytes and
- returns a far pointer to the UMB. UMBs are subject to fragmentation
- problems; it is not possible to allocate with UMBalloc() more memory
- than is in the largest free block. The size of the largest free block,
- in bytes, is returned by UMBcoreleft(). The total of all free UMBs is
- returned by UMBallcoreleft(). Other problems with using UMBs are
- discussed in section III.4 below. Since UMBs can be accessed directly,
- no copying functions are provided for them.
-
- Many functions return a status directly. For those functions, a
- return value of 0 indicates success and a return value of XMMOOPS
- indicates failure. The global variable _XMMerror contains an error code
- which gives further information on why the function failed, or has value
- 0 if the function succeeded. Many functions return some other value
- instead of a status code (0 or XMMOOPS). In these cases, the value of
- _XMMerror should be checked upon return. The recommended method of
- error-checking is indicated for each function in section IV.2 below.
-
- III.3 TIPS ON USING EMBS
- ------------------------
-
- As mentioned above, EMBs are subject to fragmentation problems, and
- the limit on allocation is the size of the largest free block. This has
- some interesting side effects. For one, there is no single measure of
- free extended memory. In some cases, the size of the largest free block
- will be most useful, in other cases, the total of all free blocks. Thus,
- both XMMcoreleft() and XMMallcoreleft() are provided. But a consequence
- of having multiple measures is that allocations may change the values in
- unanticipated ways. For example, while any allocation will change the
- total of all free blocks, it may or may not change the size of the
- largest free block depending on the size of the allocation request and
- the allocation strategy followed by the XMS driver. For example, if the
- allocation request is small enough to fit into a smaller free block, the
- XMS driver may perform the allocation from the smaller block, leaving
- the size of the largest free block unchanged. Or it may always perform
- allocations from the largest free block, in which case the size of the
- largest free block will change. In summary, do not depend on the size of
- the largest free block changing when you allocate extended memory.
-
- Furthermore, not all XMS drivers behave in exactly the same way.
- While writing XMSTEST, I observed distinct differences between QEMM 5.12
- and HIMEM.SYS 2.77. The most obvious difference is that when allocating
- under QEMM, the total of all free blocks drops by the size of the
- allocation rounded up to the nearest 16K, instead of the size rounded up
- to the nearest 1K (the minimum allocation unit for EMBs). This is
- probably related to QEMM's support of EMS, which has a minimum
- allocation unit of 16K. XMSTEST's -q parameter is a direct response to
- this difference in behavior. In summary, do not depend on the total of
- all free blocks changing by the amount you think it will.
-
- Finally, there are some speed considerations when using EMBs. For
- maximum speed, copy the largest blocks you can. Each copy of an even
- number of bytes makes one call to the XMS driver. Each copy of an odd
- number of bytes makes two calls to the XMS driver. And each copy of a
- single byte requires no fewer than three calls to the XMS driver in
- order to reliably copy the desired byte without corrupting surrounding
- data (remember that the XMS driver itself can only copy even numbers of
- bytes). To get a good idea of relative speeds of various sizes of
- copies, run XMSTEST -- it performs some speed tests, returning times in
- ticks (at 18.2 ticks per second). Large copies may be hundreds of times
- faster than small copies. If you have to make lots of small copies, try
- using the interval copy functions (_XMMicopy() et al.). They make the
- same number of calls to the XMS driver, but the loops are tightly coded
- in assembly and are marginally faster than performing the same loop
- yourself. And, as a last consideration, note that different XMS drivers
- may be faster or slower. Results from XMSTEST showed that QEMM was
- roughly 40% faster than HIMEM.SYS.
-
- III.4 TIPS ON USING UMBS
- ------------------------
-
- It is probably better not to use UMBs if there isn't a powerful
- reason to do so. UMBs are not present on many systems, may be all used
- on other systems, and some XMS drivers have buggy UMB support functions.
-
- UMBs are blocks of memory between 640K (the top of conventional
- memory) and 1M (in general, the top of memory addressable in real mode).
- Systems based on the 80286 do not have UMBs unless there is special
- hardware support on the motherboard or elsewhere. Even if the hardware
- support is present, an XMS driver is also required to provide the UMB
- management functions. Systems based on the 80386 and up do not require
- the hardware support, but do require a driver (such as QEMM, EMM386.SYS,
- 386-to-the-Max, etc.) which uses the processor's on-board memory mapping
- capability to make extended memory appear between 640K and 1M, in unused
- holes between video memory, ROMs, and anything else inhabiting that
- space. Then they may require a separate XMS driver to actually provide
- the UMB management functions. QEMM and 386-to-the-Max include XMS
- drivers within themselves; EMM386.SYS requires HIMEM.SYS.
-
- Even if the system has the requisite support and drivers, UMBs may
- not be available to your application. DOS 5.0, for example, depending on
- the configuration, may allocate all UMBs to itself.
-
- Lastly, some XMS drivers have buggy UMB support functions. While
- testing XMSIF, I discovered that QEMM 5.12 may return a random error
- code when there are no more free UMBs. In fact, it may not return an
- error code at all -- it may leave the contents of that register
- untouched. Various measures to combat this problem have been taken
- within XMSIF with sufficient success that XMSTEST can perform the
- UMB-function tests under QEMM 5.12 correctly, but other XMS drivers may
- have other bugs. In summary, I would advise that you avoid the use of
- UMBs unless there is a powerful reason to do so, and even then your
- program should be ready to deal with error returns or unusual results.
-
- III.5 OTHER TIPS
- ----------------
-
- Neither EMBs nor UMBs are deallocated automatically when a program
- exits. If the program does not deallocate EMBs or UMBs that it has
- allocated, those EMBs and/or UMBs are stuck, not available to any other
- program until the machine is rebooted. Under normal circumstances, it is
- easy enough to free EMBs and UMBs when they are no longer needed.
- However, an emergency exit due to the user hitting control-break or due
- to a hardware error (e.g. the famous "Abort, Retry, Fail?") can cause
- EMBs or UMBs to become stuck unless your program takes special measures
- to intercept these errors and perform cleanup before exiting. There are
- a number of ways to do this and they vary from compiler to compiler.
- Look for functions named things like ctrlbrk(), harderr(), and signal().
-
- If you are copying array elements, XMMicopyto(), XMMicopyfrom(), or
- _XMMicopy() may be more efficient. These functions allow copying of
- elements of fixed size which are separated by gaps also of fixed size.
- For example, if you have an array of integers and wish to copy all the
- even-indexed elements (a[0], a[2], a[4], etc.), these functions are
- faster than calling a standard copying function (XMMcopyto(),
- XMMcopyfrom(), or _XMMcopy()) from within a loop.
-
- III.6 FUNCTION GROUPING
- -----------------------
-
- The XMSIF functions have been arranged in the library in such a way
- as to reduce the number of unnecessary functions linked into your
- program. There are currently two groups:
-
- FUNCTIONS VARIABLES
- --------- ---------
- GROUP 1: XMMlibinit(), XMMgetversion(), _XMMerror, _XMMversion,
- XMMcoreleft(), XMMallcoreleft(), _xmsif_vers_vers,
- XMMalloc(), XMMfree(), _XMMcopy(), _xmsif_vers_date,
- _XMMicopy(), XMMrawcall() _xmsif_vers_time
-
- GROUP 2: UMBcoreleft(), UMBallcoreleft(), none
- UMBalloc(), UMBfree()
-
- If your program references any of the functions or variables in a group,
- all the functions and variables in that group will be linked in. Note
- that group one will always be linked, since it contains XMMlibinit(),
- which all XMSIF-using programs must call.
-
-
- IV. LIBRARY REFERENCE
- ---------------------
-
- IV.1 GLOBAL VARIABLES
- ---------------------
-
- _XMMerror
- ---------
-
- unsigned char const _XMMerror;
-
- _XMMerror contains the error code from the last XMSIF call. If the
- call succeeded, _XMMerror will be 0. If the call failed because the XMS
- driver returned an error, _XMMerror contains the error code returned by
- the XMS driver. If the call failed because XMSIF detected an error
- internally, _XMMerror contains an internal error code. A list of error
- code values, their meanings, and #defined constants for them is in
- section V.
-
- _XMMversion
- -----------
-
- unsigned int const _XMMversion;
-
- _XMMversion contains the XMS version implemented by the XMS driver in
- packed BCD format. For example, if the XMS version is 2.0, the value of
- _XMMversion will be 0x0200. The high byte of _XMMversion represents two
- digits to the left of the decimal point (one digit per nibble) and the
- low byte represents two digits to the right of the decimal point (again,
- one digit per nibble). This value is the same as that returned by
- XMMgetversion().
-
- xmsif_vers_vers, xmsif_vers_date, xmsif_vers_time
- -------------------------------------------------
-
- char const xmsif_vers_vers[];
- char const xmsif_vers_date[];
- char const xmsif_vers_time[];
-
- These are null-terminated strings containing information about the
- name and version of the library, the date of assembly, and the time of
- assembly, respectively.
-
- IV.2 EMB FUNCTIONS
- ------------------
-
- _XMMcopy() - copy data
- ----------
-
- int _XMMcopy(unsigned long clen,
- int shan, unsigned long soff,
- int dhan, unsigned long doff);
- int XMMcopyfrom(unsigned long clen,
- int handle, unsigned long soff,
- unsigned char far *dest);
- int XMMcopyto(unsigned long clen,
- unsigned char far *src,
- int handle, unsigned long doff);
-
- _XMMcopy() allows painless copying from conventional memory to an
- EMB, from an EMB to conventional memory, from one EMB to another, or
- even from one point in conventional memory to another. Areas larger than
- 64K can be copied without special treatment. Clen bytes of data are
- copied. If shan is nonzero, it is assumed to be the handle of an EMB,
- and soff is treated as a byte offset into the EMB owned by shan. If shan
- is zero, soff is treated as a segment:offset far pointer to conventional
- memory. The pair of shan and soff indicate where the data is to be
- copied from (the source). Dhan and doff work similarly, but indicate
- where the data is to be copied to (the destination).
- This function returns 0 on success or XMMOOPS on error. The specific
- error may be determined from _XMMerror. If clen is 0, the function
- returns immediately without error.
-
- XMMcopyfrom() is a macro which provides a convenient interface to
- _XMMcopy() for copying data from an EMB to conventional memory. Clen
- bytes of data are copied. Handle is the handle of an EMB, and soff is a
- byte offset into the EMB owned by handle. The pair of handle and soff
- indicate where the data is to be copied from. Dest is a far pointer to
- conventional memory and indicates where the data is to be copied to. The
- returns are the same as for _XMMcopy().
-
- XMMcopyto() is a macro which provides a convenient interface to
- _XMMcopy() for copying data to an EMB from conventional memory. Clen
- bytes of data are copied. Src is a far pointer to conventional memory
- and indicates where the data is to be copied from. Handle is the handle
- of an EMB, and doff is a byte offset into the EMB owned by handle. The
- pair of handle and doff indicate where the data is to be copied to. The
- returns are the same as for _XMMcopy().
-
- _XMMicopy() - copy data by intervals
- -----------
-
- int _XMMicopy(unsigned long nelem, int elsize,
- unsigned int sskip, int shan, unsigned long soff,
- int dhan, unsigned long doff, unsigned int dskip);
- int XMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
- int handle, unsigned long soff,
- unsigned char far *dest);
- int XMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
- unsigned char far *src,
- int handle, unsigned long doff);
-
- _XMMicopy() allows painless copying of array elements from
- conventional memory to an EMB, from an EMB to conventional memory, from
- one EMB to another, or even from one point in conventional memory to
- another. Calculation of addresses, skipping of unwanted elements, etc.,
- are all handled by the function. Elements spread across more than 64K
- or totalling more than 64K in length can be copied without special
- treatment.
- Nelem elements are copied, each of which is elsize bytes long. If
- shan is nonzero, it is assumed to be the handle of an EMB, and soff is
- treated as a byte offset into the EMB owned by shan. If shan is zero,
- soff is treated as a segment:offset far pointer to conventional memory.
- The pair of shan and soff indicate where the data is to be copied from
- (the source). Dhan and doff work similarly, but indicate where the data
- is to be copied to (the destination). Sskip and dskip indicate the
- number of bytes between elements in the source and destination,
- respectively.
- If nelem or elsize is zero, the function returns immediately without
- error. If nelem is one, _XMMcopy() is called internally. Elsize must be
- in the range 0 through 16384, or the function will return with error
- XMM_ELTOOBIG (in _XMMerror). Sskip and dskip must both be in the range 0
- through 32768, or the function will return with error XMM_SKTOOBIG (in
- _XMMerror).
- This function returns 0 on success or XMMOOPS on error. The specific
- error may be determined from _XMMerror.
-
- XMMicopyfrom() is a macro which provides a more convenient interface
- to _XMMicopy() for copying data from an EMB to conventional memory with
- sskip equal to dskip. Nelem elements are copied, each of which is elsize
- bytes long. Handle is the handle of an EMB, and soff is a byte offset
- into the EMB owned by handle. The pair of handle and soff indicate where
- the data is to be copied from. Dest is a far pointer to conventional
- memory and indicates where the data is to be copied to. Byteskip is the
- number of bytes between elements, the same for both source and
- destination. The returns are the same as for _XMMicopy().
-
- XMMicopyto() is a macro which provides a more convenient interface
- to _XMMicopy() for copying data to an EMB from conventional memory with
- sskip equal to dskip. Nelem elements are copied, each of which is elsize
- bytes long. Src is a far pointer to conventional memory and indicates
- where the data is to be copied from. Handle is the handle of an EMB, and
- doff is a byte offset into the EMB owned by handle. The pair of handle
- and doff indicate where the data is to be copied to. Byteskip is the
- number of bytes between elements, the same for both source and
- destination. The returns are the same as for _XMMicopy().
-
- XMMallcoreleft() - get total of all free EMBs
- ----------------
-
- unsigned long XMMallcoreleft(void);
- unsigned long XMMcoreleft(void);
-
- XMMallcoreleft() returns the total size of all free EMBs, in bytes.
- Note that when all EMBs have been allocated, the driver itself returns
- an error (0xA0, XMM_NOFREEX). This behavior is masked by
- XMMallcoreleft() -- if there are no free EMBs, XMMallcoreleft() returns
- 0L, not an error. _XMMerror should be checked after calling this
- function.
-
- XMMcoreleft() returns the size of the largest free EMB, in bytes.
- Note that when all EMBs have been allocated, the driver itself returns
- an error (0xA0, XMM_NOFREEX). This behavior is masked by XMMcoreleft() --
- if there are no free EMBs, XMMcoreleft() returns 0L, not an error.
- _XMMerror should be checked after calling this function.
-
- XMMalloc() - allocate EMB
- ----------
-
- int XMMalloc(unsigned long bytes);
-
- This function allocates an EMB. It takes the given number of bytes
- and rounds it up to the nearest kilobyte, then allocates an EMB that
- many kilobytes in size. It returns the EMB handle assigned by the XMS
- driver. _XMMerror should be checked after calling this function.
- Note that EMBs cannot be allocated in units smaller than a kilobyte
- (1024 bytes). Requesting one byte will allocate 1K; 1025 bytes will
- allocate 2K. Requesting zero bytes allocates a handle but no memory.
- Note that it is not possible to allocate in one XMMalloc() call more
- extended memory than is in the largest free EMB. This is a limitation of
- the XMS driver. See section III.3 above for more information on EMB
- allocation limitations.
-
- XMMcopyfrom() - copy data from EMB
- -------------
-
- int XMMcopyfrom(unsigned long clen,
- int handle, unsigned long soff,
- unsigned char far *dest);
-
- See _XMMcopy().
-
- XMMcopyto() - copy data to EMB
- -----------
-
- int XMMcopyto(unsigned long clen,
- unsigned char far *src,
- int handle, unsigned long doff);
-
- See _XMMcopy();
-
-
- XMMcoreleft() - get size of largest free EMB
- -------------
-
- unsigned long XMMcoreleft(void);
-
- See XMMallcoreleft().
-
- XMMfree() - deallocate an EMB
- ---------
-
- int XMMfree(int handle);
-
- This function accepts an EMB handle (as returned by XMMalloc() or
- otherwise obtained from the XMS driver) and releases it and the EMB
- associated with it (if any). This function returns 0 on success or
- XMMOOPS on error. The specific error may be determined from _XMMerror.
-
- XMMgetversion() - obtain XMS version implemented by XMS driver
- ---------------
-
- int XMMgetversion(void);
-
- This function returns the XMS version implemented by the XMS driver.
- The version number is in packed BCD format as in the global variable
- _XMMversion, and is in fact the same value. _XMMerror should be checked
- after calling this function.
-
- XMMicopyfrom() - copy data by intervals from EMB
- --------------
-
- int XMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
- int handle, unsigned long soff,
- unsigned char far *dest);
-
- See _XMMicopy().
-
- XMMicopyto() - copy data by intervals to EMB
- ------------
-
- int XMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
- unsigned char far *src,
- int handle, unsigned long doff);
-
- See _XMMicopy().
-
- XMMlibinit() - initialize XMSIF
- ------------
-
- int XMMlibinit(void);
-
- XMMlibinit() initializes XMSIF. Any other XMSIF function will return
- with error XMM_NOINIT (in _XMMerror) if called before XMMlibinit() has
- been called. This function returns 0 on success, XMMOOPS on error, or
- NOXMM if no XMS driver is detected. The specific error may be determined
- from _XMMerror.
-
- XMMrawcall() - call XMS driver directly
- ------------
-
- int XMMrawcall(struct XMMregs *regs);
-
- This function is a raw interface directly to the XMS driver. The
- XMMregs structure has fields for the AX, BX, DX, SI, and DS registers,
- which are the only registers used as parameters for calls to the XMS
- driver. The values in the structure are placed in the appropriate
- registers before the XMS driver is called, and the registers are copied
- back into the structure after the XMS driver call returns. Check XMSIF.H
- or XMSIF.HPP for the exact format of the XMMregs structure.
- Since the XMS specification provides a uniform error indication for
- all XMS calls, XMMrawcall() is able to determine if the call performed
- caused an error. It returns 0 on success or XMMOOPS on error. The
- specific error may be determined from _XMMerror; the error code can also
- be found in the low byte of the regBX field of the XMMregs structure.
-
- IV.3 UMB FUNCTIONS
- ------------------
-
- UMBallcoreleft() - get total of all free UMBs
- ----------------
-
- unsigned long UMBallcoreleft(void);
- unsigned long UMBcoreleft(void);
-
- UMBallcoreleft() returns the total size of all free UMBs, in bytes.
- Note that when all UMBs have been allocated, the driver itself returns
- an error (0xB1, UMB_NOFREEUMB). This behavior is masked by
- UMBallcoreleft() -- if there are no free UMBs, UMBallcoreleft() returns
- 0L, not an error. If the XMS driver does not support UMBs at all, it
- returns an error (0x80, XMM_UNIMP). This is also masked by
- UMBallcoreleft(). Again, 0L will be returned, not an error. _XMMerror
- should be checked after calling this function.
-
- UMBcoreleft() returns the size of the largest free UMB, in bytes.
- Note that when all UMBs have been allocated, the driver itself returns
- an error (0xB1, UMB_NOFREEUMB). This behavior is masked by UMBcoreleft() --
- if there are no free UMBs, UMBcoreleft() returns 0L, not an error. If
- the XMS driver does not support UMBs at all, it returns an error (0x80,
- XMM_UNIMP). This is also masked by UMBallcoreleft(). Again, 0L will be
- returned, not an error. _XMMerror should be checked after calling this
- function.
-
- UMBalloc() - allocate UMB
- ----------
-
- void far *UMBalloc(unsigned long bytes, unsigned long *finalsize);
-
- This function allocates an UMB. It takes the given number of bytes
- and rounds it up to the nearest multiple of 16, then allocates a UMB
- that many bytes in size. The actual size in bytes of the UMB allocated
- is returned in the unsigned long pointed to by finalsize. UMBalloc()
- returns a far pointer to the UMB; this pointer should be cast to a type
- other than void before being used to access the UMB. _XMMerror should be
- checked after calling this function.
- Note that UMBs cannot be allocated in units smaller than a paragraph
- (16 bytes). Requesting one byte will allocate 16; 17 bytes will allocate
- 32.
- Note that it is not possible to allocate in one UMBalloc() call more
- extended memory than is in the largest free UMB. This is a limitation of
- the XMS driver. See section III.4 above for more information on UMB
- allocation limitations.
-
- UMBcoreleft() - get size of largest free UMB
- -------------
-
- unsigned long UMBcoreleft(void);
-
- See UMBallcoreleft().
-
- UMBfree() - deallocate an UMB
- ---------
-
- int UMBfree(void far *handle);
-
- This function accepts a pointer to a UMB (as returned by UMBalloc())
- and releases that UMB. If the pointer has been modified, UMBfree()
- attempts to return it to canonical form before calling the XMS driver.
- However, for maximum reliability, UMBfree() should be called with an
- unmodified copy of the pointer returned by UMBalloc(). This function
- returns 0 on success or UMBOOPS on error. The specific error may be
- determined from _XMMerror.
-
-
- V. ERROR CODES
- --------------
-
- This section is a list of the error codes to which the global
- variable _XMMerror may be set, and the values and meanings thereof.
-
- V.1 INTERNAL ERRORS
- -------------------
-
- Internal codes indicate an error detected by XMSIF itself.
-
- NAME VALUE MEANING
- ---- ----- -------
- XMM_NOINIT 0x40 XMMlibinit() must be called before any
- other XMSIF function can be called.
-
- XMM_UMBHUGE 0x41 Size of UMB requested is larger than
- XMS driver can handle (maximum UMB
- request size is 1M).
-
- XMM_BADPTR 0x42 The UMB pointer passed to UMBfree()
- is corrupt.
-
- XMM_ELTOOBIG 0x43 The element size passed to XMMicopyto(),
- XMMicopyfrom(), or _XMMicopy() is too big.
-
- XMM_SKTOOBIG 0x44 The skip size passed to XMMicopyto(),
- XMMicopyfrom(), or _XMMicopy() is too big.
-
- V.2 XMS DRIVER ERRORS
- ---------------------
-
- These codes are defined in the XMS specification and are returned by
- the XMS driver. They are saved in _XMMerror by XMSIF without alteration.
-
- NAME VALUE MEANING
- ---- ----- -------
- XMM_UNIMP 0x80 Function is not implemented
-
- XMM_VDISK 0x81 VDISK device driver was detected
-
- XMM_A20ERROR 0x82 A20 error occurred
-
- XMM_GENERROR 0x83 General driver error occurred
-
- XMM_UNRECERROR 0x84 Unrecoverable driver error occurred
-
- XMM_NOHMA 0x90 HMA (High Memory Area) does not exist
-
- XMM_HMAUSED 0x91 HMA already allocated
-
- XMM_HMATOOBIG 0x92 Request to allocate HMA denied because
- amount of HMA requested is less than
- minimum parameter given to XMS driver
- on its command line
-
- XMM_HMANOALLOC 0x93 HMA is not allocated
-
- XMM_A20STILLEN 0x94 A20 line is still enabled
-
- XMM_NOFREEX 0xA0 All EMBs (Extended Memory Blocks) are
- allocated
-
- XMM_NOFREEXHAN 0xA1 No free EMB handles
-
- XMM_BADXHAN 0xA2 EMB handle is invalid
-
- XMM_BADSRCHAN 0xA3 Source EMB handle is invalid
-
- XMM_BADSRCOFF 0xA4 Source offset in EMB is beyond end of EMB
-
- XMM_BADDESTHAN 0xA5 Destination EMB handle is invalid
-
- XMM_BADDESTOFF 0xA6 Destination offset in EMB is beyond end
- of EMB
-
- XMM_BADLENGTH 0xA7 Length is invalid
-
- XMM_COPYOVERLAP 0xA8 Overlap in copy request is invalid
-
- XMM_PARITY 0xA9 Parity error was detected
-
- XMM_NOLOCK 0xAA EMB is not locked
-
- XMM_LOCKED 0xAB EMB is locked
-
- XMM_TOOMANYLOCKS 0xAC EMB lock count overflowed
-
- XMM_LOCKFAIL 0xAD EMB lock failed
-
- XMM_UMBSMALLER 0xB0 UMB (Upper Memory Block) of size requested
- is not available; however, a smaller UMB
- is available
-
- XMM_NOFREEUMB 0xB1 All UMBs are allocated
-
- XMM_BADUMBHAN 0xB2 UMB handle (same as segment address of
- start of UMB) is invalid
-
-
- VI. THE END
- -----------
-
- Technical support via email is available from the following addresses:
-
- INTERNET:
- First choice (the following are alternate addresses for the same place):
- support@picarefy.com
- picarefy!support@amc.com
- picarefy!support@netcom.com
- picarefy!support@halcyon.com
- amc-gw!picarefy!support@coco.ms.washington.edu
- halcyon!picarefy!support@sumax.seattleu.edu
- uunet!uw-coco!amc-gw!picarefy!support
-
- Second choice:
- jwbirdsa@amc.com
-
- COMPUSERVE:
- 71261,1731
-
- AMERICA ON-LINE:
- GreenTiger
-
- GENIE:
- J.BIRDSALL2
-
- Registrations should be sent to:
-
- James W. Birdsall
- 11112 NE 124 LN #D204
- Kirkland, WA 98034
-
- If you have an email address on any of the networks listed above,
- please include it when registering, especially if you are requesting
- source code. It is much easier to send the source code by email. Also,
- please specify what sort of archive (ZIP, ZOO, ARC, LZH, ARJ, UNIX shar)
- you can handle most easily.
-
- NOTE: IF YOU DO NOT PROVIDE AN EMAIL ADDRESS, YOU WILL ONLY RECEIVE
- MAJOR VERSION UPDATES. YOU WILL NOT RECEIVE MINOR VERSIONS. PLEASE
- PROVIDE AN EMAIL ADDRESS IF YOU HAVE ANY WAY OF DOING SO.
-
- VI.1 ACKNOWLEDGEMENTS
- ---------------------
-
- Thanks to Bob Parsons of Parsons Technology Inc. for some good suggestions
- on the documentation and for providing the original C++ header file.
-
-