Dec 072017
 
Version independent C interface to LIM EMS functions.
File EMSLIB.ZIP from The Programmer’s Corner in
Category C Source Code
Version independent C interface to LIM EMS functions.
File Name File Size Zip Size Zip Type
EMSLIB.DOC 23885 6967 deflated
EMSLIB.H 3734 1036 deflated
EMSLIBC.OBJ 8694 5067 deflated
EMSLIBL.OBJ 8720 5083 deflated
EMSLIBM.OBJ 8741 5097 deflated
EMSLIBS.OBJ 8715 5072 deflated
EMSTEST.C 5779 1524 deflated

Download File EMSLIB.ZIP Here

Contents of the EMSLIB.DOC file


EMSLIB
Version-independent C Interface to LIM EMS Functions
for LIM EMS versions 3.0 and higher
EMSLIB version 2.15
by James W. Birdsall
05/28/91


1. INTRODUCTION
---------------

EMSLIB provides a high-level interface to LIM EMS control functions for
common operations such as allocating, mapping, and freeing EMS, and copying
data to and from EMS. More exotic functions are not included. The interface
has been made independent of the version of the EMS driver as far as possible,
so that parameters and returned data are always in the same format, but the
EMS call most appropriate to the EMS version implemented by the driver is
used. EMS versions 3.0 and higher are supported, although versions above 4.0
will be treated as version 4.0.

1.1 LEGALESE
------------

EMSLIB is not in the public domain. It is copyright 1991 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 here {EMSLIB.DOC, EMSLIBS.OBJ, EMSLIBC.OBJ,
EMSLIBM.OBJ, EMSLIBL.OBJ, EMSTEST.C, EMSLIB.H} intact and
unmodified.

You may use the object files in programs for your own use. You
may not redistribute programs linked with these object files.

Payment of the $5 shareware registration fee grants the following
additional permissions:

You may obtain the source to EMSLIB, upon request. You may modify
the source as necessary for use in your programs. However, you may
not redistribute either the original or modified source.

You may redistribute programs linked with either the original
object files, or object files generated from source you have
modified, without royalty.

The contents of this archive, and all other related files, information,
and services are provided as-is. While every effort has been made to ensure
that the files, information, and services are accurate and correct, the
author cannot be held liable for damages arising out of the use of or
inability to use this product.

Information on contacting the author is provided at the end of this
file.


2. USE
------

EMSLIB is provided as an object file for maximum flexibility. It is
written in Turbo Assembler 2.5, to be compatible with Borland C++ 2.0. Since
Borland C++ has the same calling conventions as Turbo C(++), EMSLIB is
compatible with Turbo C(++).
According to the documentation for Microsoft C 6.0, the calling
conventions used by MSC are essentially the same. EMSLIB should be compatible
with MSC also, but extensive testing has not been done. What tests could
be performed worked.

EMSLIB is provided for small, medium, compact, and large models. The model
for which the object is intended is indicated by the last letter of the
filename proper, which is the same as the first letter of the model. For
example, EMSLIBL.OBJ is the large-model object. The small object should
probably work with the tiny model, and the large object with the huge model,
but these have not been tested.

To use EMSLIB, choose the appropriate object for the model in which the
rest of your program is compiled, and include that object. Consult your
compiler documentation for how to link in objects. If you are using the
command-line compiler to compile and/or link, simply place the full name
of the EMSLIB object on the command line. If you are linking manually (using
LINK, TLINK, et al.), simply place EMSLIB in with the names of the other
object files being linked.

An example program, EMSTEST.C, has been included. To use it, simply
compile it in whatever memory model you choose and link it with the
appropriate EMSLIB object for that memory model. For example, using the
Borland C++ command-line compiler, the following command would compile
EMSTEST.C in the medium model and link it with EMSLIBM.OBJ:

bcc -mm emstest.c emslibm.obj

Users of Turbo C(++) can simply substitute "tcc" for "bcc". The following
two commands perform the same function, but demonstrate using TLINK
directly:

bcc -mm -c emstest.c
tlink c0m emstest emslibm, emstest, , cm

Again, users of Turbo C(++) can simply substitute "tcc" for "bcc". TLINK is
the same for both packages. The files "c0m" and "cm" on the TLINK command
line are the standard medium-model startup object and medium-model library,
respectively.


3. GENERAL CONSIDERATIONS
-------------------------

EMSLIB provides a set of functions which are intended to be orthogonal
with the standard C functions malloc()/free(), and the Turbo C function
coreleft(). It also provides functions to allow more direct manipulation of
EMS.

One point that cannot be stressed sufficiently is that the library
initialization function EMMlibinit() _must_ be called before any other
EMSLIB calls are made. Failure to do so can result in undefined behavior
or crash. One of the important things that EMMlibinit() does is determine
whether there is an EMS driver in the system at all.

All files which call EMSLIB functions should #include the file EMSLIB.H.
This file defines the return and error code symbols shown in section 5,
declares the global variables provided by EMSLIB, and provides prototypes
for the EMSLIB functions.


4. LIBRARY FACILITIES
---------------------

4.1 GLOBAL VARIABLES
--------------------

EMSLIB provides the following global variables, as shown in the header
file EMSLIB.H:

4.1.1 _EMMerror
---------------

_EMMerror is an unsigned char which contains the EMS driver error
code from the last EMS driver call. If there was no error, it will be 0.
A list of error code values and symbolic values is in section 5.

4.1.2 _EMMversion
-----------------

_EMMversion is an unsigned char which contains the EMS version that the
EMS driver implements. It is in packed BCD format. For example, if the EMS
version is 4.0, the value of _EMMversion will be 0x40. If the EMS version
is 3.2, the value of _EMMversion will be 0x32.

4.1.3 emslib_vers_vers, emslib_vers_date, emslib_vers_time
----------------------------------------------------------

These variables are null-terminated strings containing information about
the name and version of the library, the date of compilation, and the time
of compilation, respectively.

4.2 FUNCTIONS
-------------

All functions set the variable _EMMerror. If the function completed
successfully, _EMMerror is set to 0. If there was an error, _EMMerror is
set to the appropriate error code. Thus, it is always possible to check
the value of _EMMerror after a function call to check for errors. However,
many functions also indicate success or error by their return value. Those
functions where the return value may be ambiguous are noted, and it is
recommended that _EMMerror be checked instead of the return value.

4.2.1 EMMlibinit()
------------------

int EMMlibinit(void)

This function initializes the library. It _must_ be called before any
other EMSLIB calls are made. It returns 0 on success, EMMOOPS if there was
an EMS driver error, or NOEMM if an EMS driver was not detected. Detection
of the EMS driver relies on DOS services, so this library cannot be used
in a device driver as it stands. If you need this library for a device driver,
buy the source (it's cheap) and modify EMSlibinit() to use another method
of detection. The method used was chosen because it is more reliable than
the other method, which is typically only good for device drivers.

4.2.2 EMMgetversion()
---------------------

int EMMgetversion(void)

This function returns the EMS version implemented by the EMS driver. It
is in packed BCD format, the same as in the global variable EMMversion (see
above). On error, this function returns EMMOOPS and the global variable
_EMMerror will be set to an EMS error code. _EMMerror is set to 0 otherwise.

4.2.3 EMMcoreleft()
-------------------

unsigned long EMMcoreleft(void)

This function returns the amount of EMS memory available, in bytes.
Since each EMS page is 16384 bytes long, division of the returned value by
16384 (equivalent to shifting the value right by 14 bits) yields the number
of EMS pages free.
The value of _EMMerror should be checked after calling this function.
If an error occurred, _EMMerror will be set to the error code. If the function
completed successfully, _EMMerror will be 0.

4.2.4 EMMalloc()
----------------

int EMMalloc(unsigned long bytes)
bytes -- number of bytes to allocate

This function allocates EMS memory. It takes the given number of bytes and
rounds upward to the next multiple of 16384 (one page) and allocates that
number of pages. It returns the EMS handle assigned by the EMS driver.
The value of _EMMerror should be checked after calling this function.
If an error occurred, _EMMerror will be set to the error code. If the
function completed successfully, _EMMerror will be 0.
Note that EMS cannot be allocated in units smaller than a page. Requesting
one byte will allocate a whole page; 16385 bytes will allocate two pages.
Requesting zero bytes allocates one page. If you wish to allocate zero pages,
which is only possible with EMS versions 4.0 and up, you must use the
EMMallocpages() function.

4.2.5 EMMfree()
---------------

int EMMfree(int handle)
handle -- EMS handle to free

This function accepts an EMS handle obtained from the EMMalloc() or
EMMallocpages() functions, or directly from the EMS driver, and releases
it and any EMS pages allocated to it. If an error occurred, EMMfree() returns
EMMOOPS and _EMMerror will be set to the error code. If the function
completed successfully, EMMfree() returns 0 and _EMMerror will be 0.

4.2.6 EMMgetnumframe()
----------------------

int EMMgetnumframe(void)

This function returns the number of EMS frames available. For EMS version
below 4.0, this will always be 3. For EMS versions 4.0 and above, it will be
3 or more. If an error occured, EMMOOPS is returned and _EMMerror is set to
the error code. If the function completed successfully, the number of EMS
frames is returned and _EMMerror is 0.

4.2.7 EMMgetframeaddr()
-----------------------

int EMMgetframeaddr(frameinfo *buffer)
buffer -- pointer to array of structures in which frame information
is returned

This function returns the segment addresses of all the EMS frames.
The argument buffer is a pointer to an array of frameinfo structures;
it is assumed to be large enough to contain information about all the
frames. The number of frameinfo structures needed can be obtained with the
EMMgetnumframe() function.
Each frameinfo structure contains the number of the frame and the
segment address of the frame. Look in the header file for the precise
format of the structure. The information is returned in whatever order
the EMS driver provides it; typically, it is sorted by address rather than
frame number. Do NOT assume that the first element in the array contains
information for frame 0!
If an error occurred, EMMOOPS is returned and _EMMerror is set to the error
code. If the function completed successfully, 0 is returned and _EMMerror is
0.

4.2.8 EMMgetsinfraddr()
-----------------------

unsigned int EMMgetsinfraddr(int frame)
frame -- number of frame whose address is desired

This function returns the segment address of a particular EMS frame.
The argument frame is the number of the particular frame. The value of
_EMMerror should be checked after calling this function. If an error
occurred, _EMMerror will be set to an error code. If the function completed
successfully, _EMMerror will be 0.

4.2.9 EMMallocpages()
---------------------

int EMMallocpages(int pages)
pages -- number of EMS pages to allocate

This function allocates the requested number of standard EMS pages (16384
bytes each) and returns the handle assigned by the EMS driver. The value of
_EMMerror should be checked after calling this function. If an error
occurred, _EMMerror will be set to an error code. If the function completed
successfully, _EMMerror will be 0.

4.2.10 EMMmappage()
-------------------

int EMMmappage(int frameno, int handle, int logpage)
frameno -- frame into which to map
handle -- handle of logical page to map
logpage -- logical page number to map into frame frameno

This function allows manual control over EMS page mapping. It allows
mapping of any logical page belonging to any handle into any of the EMS
frames. If an error occurred, EMMOOPS is returned and _EMMerror will be set
to an error code. If the function completed successfully, 0 is returned and
_EMMerror is 0.

4.2.11 EMMcopyto()
------------------

int EMMcopyto(unsigned long copylen, unsigned char far *source,
int handle, unsigned long foffset)
copylen -- number of bytes to be copied
source -- far pointer to source in conventional memory
handle -- EMS handle to which to copy
foffset -- offset, in bytes, into pages owned by handle

This function allows painless copying from conventional memory to EMS.
All mapping, calculation of addresses, etc., is handled by the function.
Areas larger than 64K can be copied without special treatment.
Copylen bytes of data are copied, from the conventional memory area pointed
to by source (which must be a far pointer; a near pointer can be converted
to a far pointer with a cast when the function is called, if necessary).
These bytes are put in the EMS pages owned by handle, starting at byte offset
foffset. This feature allows the EMS memory owned by handle to be treated
as a linear area, rather than a collection of pages. To convert an offset
to page/page-offset, divide the offset by the size of a page (16384 bytes).
The page is the quotient and the page-offset the remainder. Offsets 0 through
16383 are in page 0; offsets 16384 through 32767 are in page 1, etc.
If an error occurred, EMMOOPS is returned and _EMMerror is set to an error
code. If the function completed successfully, 0 is returned and _EMMerror is
0.

4.2.12 EMMcopyfrom()
--------------------

int EMMcopyfrom(unsigned long copylen, int handle, unsigned long foffset,
unsigned char far *dest)
copylen -- number of bytes to be copied
handle -- EMS handle from which to copy
foffset -- offset, in bytes, into pages owned by handle
dest -- far pointer to destination in conventional memory

This function is the mirror image of EMMcopyto(). It allows painless
copying to conventional memory from EMS. All mapping, calculation of addresses,
etc., is handled by the function. Copies longer than 64K are possible
without special treatment.
Copylen bytes of data are copied, from the EMS pages owned by handle,
starting at byte offset foffset. These bytes are put in the conventional
memory area pointed to by dest (which must be a far pointer; a near pointer
can be converted to a far pointer with a cast when the function is called,
if necessary). Byte offsets in EMS pages are as for EMMcopyto(), see above.
If an error occurred, EMMOOPS is returned and _EMMerror is set to an
error code. If the function completed successfully, 0 is returned and
_EMMerror is 0.

4.2.13 EMMsetname()
-------------------

int EMMsetname(int handle, char *name)
handle -- EMS handle to be named
name -- pointer to 8-character buffer holding name

This function allows the assignment of an eight-character name to an
EMS handle. It only works with EMS versions 4.0 and up; under lower versions,
it returns an error. Version independency has been abandoned in this case
because the main purpose of assigning a name to an EMS handle is to allow
several different programs to recognize shared data. While EMSLIB could
implement a naming function within itself, the names would be internal to
the program assigning the name, defeating the purpose of assigning a name in
the first place.
If an error occurred, EMMOOPS is returned and _EMMerror is set to an
error code. If the function completed successfully, 0 is returned and
_EMMerror is 0.

4.2.14 EMMgetname()
-------------------

int EMMgetname(int handle, char *name)
handle -- EMS handle being queried
name -- pointer to 8-character buffer in which name is returned

This function returns the name, if any, assigned to an EMS handle. Real
names are only implemented in EMS versions 4.0 and up. Under lower versions,
this function fills the name buffer with nulls ('\0'), which is the return
under versions 4.0 and up when the handle does not have a name assigned to
it. The buffer pointed to by name must be at least eight characters long.
If an error occurred, EMMOOPS is returned and _EMMerror is set to an error
code. If the function completed successfully, 0 is returned and _EMMerror is 0.


5. ERROR CODES
--------------

This section is a list of the error codes to which the global variable
_EMMerror may be set, and the values and meanings thereof.

5.1 INTERNAL CODES
------------------

Internal codes indicate an error in EMSLIB itself.

NAME VALUE MEANING
---- ----- -------
EMM_BADVERS 0x40 Bad EMS version, below 3.0.

EMM_BADOFFSET 0x41 Offset plus copy length runs off last
EMS page owned by handle.

EMM_NOFRAME 0x42 Could not find segment address of frame
used for EMMcopyto() and EMMcopyfrom() --
internal error!

5.2 EMS DRIVER CODES
--------------------

These codes are defined in the EMS specification and are returned by
the EMS driver. They are saved in _EMMerror by EMSLIB without alteration.

NAME VALUE MEANING
---- ----- -------
EMM_SOFTERROR 0x80 Internal error exists in EMS driver (can
indicate corrupted memory image of driver)

EMM_HARDERROR 0x81 Malfunction in expanded memory hardware

EMM_BUSY 0x82 EMS driver is busy

EMM_BADHANDLE 0x83 Invalid EMS handle

EMM_UNIMP 0x84 Function not defined

EMM_NOFREEHAN 0x85 No free EMS handles

EMM_CONTEXTERR 0x86 Error in save or restore of mapping context

EMM_WAYTOOBIG 0x87 Tried to allocate more pages than physically
exist in system; no pages allocated

EMM_TOOBIG 0x88 Tried to allocate more pages than currently
available; no pages allocated

EMM_TOOSMALL 0x89 Cannot allocate 0 pages

EMM_BADLOGPAGE 0x8A Requested logical page is outside range of
pages owned by handle

EMM_BADFRAMENO 0x8B Illegal frame number in mapping request

EMM_HSTATESAVFULL 0x8C Page-mapping hardware-state save area full

EMM_MSTATESAVFULL 0x8D Mapping-context save failed; save area
already contains context associated with
specified handle

EMM_MSTATERESTERR 0x8E Mapping-context restore failed; save area
does not contain context for specified
handle

EMM_UNIMPSUB 0x8F Subfunction parameter not defined

EMM_BADATTRIB 0x90 Attribute type not defined

EMM_NOFEATURE 0x91 Feature not supported

EMM_SRCOVERWRITE 0x92 Source and destination memory regions have
same handle nad overlap; requested move
was performed, but part of the source region
was overwritten

EMM_BADLENGTH 0x93 Copy length longer than actual length

EMM_CONEMSOVERLAP 0x94 Conventional memory region and expanded
memory region overlap

EMM_OFFPAGE 0x95 Specified offset outside logical page

EMM_TOOLONG 0x96 Copy length exceeds one megabyte

EMM_EMSEMSOVERLAP 0x97 Source and destination memory regions have
same handle and overlap; exchange cannot be
performed

EMM_LOST 0x98 Memory source and destination types
undefined

EMM_UNUSED 0x99 This error code is currently unused

EMM_BADALTREG 0x9A Alternate map or DMA register sets are
supported, but specified alternate register
set is not supported

EMM_NOFREEALTREG 0x9B Alternate map or DMA register sets are
supported, but all alternate register sets
are currently allocated

EMM_NOALTREG 0x9C Alternate map or DMA register sets are not
supported, specified alternate register
set is not 0

EMM_BADALTREG2 0x9D Alternate map or DMA register sets are
supported, but the alternate register set
specified is not defined or not allocated

EMM_NODEDDMA 0x9E Dedicated DMA channels are not supported

EMM_BADDEDDMA 0x9F Dedicated DMA channels are supported, but
specified DMA channel is not supported

EMM_UNKNAME 0xA0 Handle for specified name not found

EMM_NAMETAKEN 0xA1 Handle with same name already exists

EMM_ADDRWRAP 0xA2 Memory address wraps; sum of source or
destination region base address and length
exceeds one megabyte

EMM_BADPTR 0xA3 Invalid pointer passed to function, or
contents of source array corrupted

EMM_FORBIDDENFUNC 0xA4 Access to function denied by operating
system

6. THE END
----------

Technical support via email is available from the following addresses:

INTERNET:
First choice (the following are alternate addresses for the same place):
[email protected]
[email protected]
[email protected]
[email protected]
uunet!uw-coco!amc-gw!picarefy!support

Second choice:
[email protected]

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


 December 7, 2017  Add comments

Leave a Reply