home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-30 | 59.6 KB | 1,702 lines |
-
- The
- EMS TOOLKIT
- for C developers
-
-
-
-
-
-
-
-
-
-
-
- Copyright (c) 1989 Intel Corporation. All rights reserved.
- Intel Corporation, 5200 NE Elam Young Parkway, Hillsboro, OR 97124
-
-
- First Edition December, 1989
-
-
- DISCLAIMER
- Intel Corporation assumes no responsibility for errors that may appear in
- this manual. Nor does Intel make any commitment to update the
- information contained in this manual.
-
- Intel and Above are trademarks of Intel Corporation.
-
-
-
-
- LIMITED WARRANTY
- Intel Corporation excludes any and all implied warranties, including
- warranties of merchantability and fitness for a particular purpose. Intel
- makes no warranty of representation, either express or implied, with
- respect to this software, its quality, performance, merchantability, or
- fitness for a particular purpose. Intel shall not have any liability for
- special, incidental, or consequential damages arising out of or resulting
- from the use or modification of this software. This software is provided as
- is.
-
-
- USE OF PROGRAM PRODUCT You may use the Program Product on any one IBM or
- compatible personal computer, and copy the Object Code into any
- machine-readable form for your use of the Program Product; You may modify
- the Program Product material and/or merge or incorporate it into any
- general use software program of your development except for a utility
- program of similar nature to the Program Product. You may freely reproduce
- any such program of your development; however, the merged or incorporated
- part of the Program Product will continue to be subject to all other
- provisions of this agreement.
-
-
-
- CONTENTS
-
-
- CHAPTER 1. GETTING STARTED
- How to use this book 1-2
- What's on the disks? 1-3
- Which library should I use? 1-5
- Requirements 1-7
- Installing the software 1-7
-
- CHAPTER 2. MEMLIB: LIBRARY FOR C DEVELOPERS
- Compiling and linking MEMLIB 2-3
- Suggested sequence for using MEMLIB functions 2-4
- MEMLIB functions list 2-5 -- 2-31
-
- CHAPTER 3. EMMLIB: LIBRARY FOR ASSEMBLY LANGUAGE AND C DEVELOPERS
- EMMLIB functions grouped by operation 3-3
- EMMLIB functions in alphabetical order 3-7
-
- APPENDIX A. EXAMPLE PROGRAM
-
- APPENDIX B. ERROR MESSAGES
-
- APPENDIX C. TECHNICAL INFORMATION ABOUT MEMLIB
- How MEMLIB provides access to expanded memory C-1
- How MEMLIB keeps track of expanded memory C-2
- How MEMLIB allocates expanded memory C-2
- Algorithms C-4
-
-
-
- Chapter 1
- GETTING STARTED
-
- This manual describes the toolkit for the Lotus-Intel-Microsoft Expanded
- Memory Specification (EMS). The toolkit offers experienced Microsoft C
- developers a quick and easy way to use expanded memory in their application
- programs.
-
- If you are writing programs in some other Microsoft language (Fortran,
- Pascal, etc.), you may still be able to use the toolkit. Read the
- mixed-language programming section in the Microsoft manual to find out how
- tomake calls to C from your language.
-
- The toolkit includes the following libraries:
-
- MEMLIB A set of C functions that perform the "housekeeping"
- necessary to access and store data in expanded memory. When you
- use MEMLIB, you won't need to worry about page frame size,
- 16K-byte boundaries, or interfacing with an assembly language
- device driver. See Chapter 2.
-
- EMMLIB A set of C-callable assembly language functions that call
- the EMS driver directly. See Chapter 3.
-
- These libraries allow you to use the full functionality of EMS without
- spending countless hours writing assembly language programs.
-
- This manual supplements the Lotus-Intel-Microsoft Expanded Memory
- Specification manual (also referred to as the EMS manual). The LIM
- specification defines the software interface between an application
- program and the expanded memory used by the program.
-
- How to use this book
- --------------------
- This manual explains the features and operation of the EMS Toolkit
- libraries. Once you are familiar with the libraries and how to use
- them, you can use this book as a quick reference for function names,
- parameters, and error messages.
-
- Here's what you'll find in each chapter of the manual: Chapter 1 -- Getting
- Started: This is the chapter you're reading now. Besides introducing you
- to the EMS Toolkit, this chapter lists the contents of the Intel diskettes,
- offers suggestions for which library to use, and tells you how to install
- the software.
-
- Chapter 2 -- MEMLIB: Library for C Developers This chapter describes
- how the MEMLIB library works, how to write code to use MEMLIB, and how to
- compile and link MEMLIB. The last section (which makes up the bulk of this
- chapter) describes each of the MEMLIB functions in detail.
-
- Chapter 3 -- EMMLIB: Library for Assembly Language and C Developers
- Chapter 3 describes the EMMLIB library and how it works, and describes how
- to compile and link EMMLIB. This chapter also includes lists of EMMLIB
- functions, and tells you how to get more information about each one.
-
- Appendix A -- Example Progra: This short example program
- demonstrates how to use MEMLIB to store and access data in expanded memory.
-
- Appendix B -- Error Messages: This appendix lists the error messages
- you may incur from MEMLIB, and suggests corrective actions.
-
- Appendix C -- Technical Information About MEMLIB: This appendix explains
- the more technical aspects of how MEMLIB allocates and frees expanded
- memory. You don't need to know this information to use MEMLIB.
-
- What's on the disks?
- --------------------
- The EMS Toolkit package includes four diskettes. You'll need disks 1, 2
- and 3 to use either of the toolkit libraries. If you are an assembly
- language developer and want to use expanded memory to execute code, you may
- want to use disk 4. Disk 4 contains examples for assembly language
- programmers only. (You don't need disk 4 to use MEMLIB or EMMLIB.)
-
- The Intel EMS Toolkit diskettes contain the following files:
-
- Disk 1
- Filename Description
- MEMLIB.C MEMLIB source code (functions)
- MEMLIB.H MEMLIB include file (function prototypes)
- MEMINTRL.C MEMLIB source code (internal MEMLIB utilities)
- ERRORS.H MEMLIB error messages
- EMMLIB.LIB EMM large-model library of C interface routines
- EMMLIB.H EMMLIB include file
-
- Disk 2
- Filename Description
- SAMPLE.C Short sample program using MEMLIB functions
- SAMPLE.MAK "make" file for use with SAMPLE.C program
- ROLODEX.C More detailed sample program using MEMLIB and EMMLIB
- ROLODEX.H Header file for use with ROLODEX.C
- ROLODEX.DAT Data file for ROLODEX.C
- ROLODEX.MAK "make" file for use with ROLODEX.C program
- EMMLIB <DIR> Directory containing EMMLIB function files
-
- Disk 3
- Filename Description
- EMMLIB <DIR> Directory containing the rest of the EMMLIB function
- files and other EMMLIB support files
-
- Disk 4
- Filename Description
- LOADCODE.ASM Sample assembly language program that demonstrates how
- to execute code from expanded memory
- HELLO.ASM Sample code the LOADCODE.ASM will execute
- LOADCODE.MAK "make" file for LOADCODE.ASM
-
-
- Which library should I use?
- ---------------------------
- The way in which your application will use expanded memory determines
- which library you should use.
- o If you are writing code in C and you want to store data in
- expanded memory, you can use MEMLIB; it offers routines to do this
- quickly and easily.
- o If you understand the Lotus-Intel-Microsoft Expanded Memory
- Specification and want to make expanded memory calls directly from C,
- you must use EMMLIB. For example, if you want to use named handles for
- the blocks of expanded memory you allocate, you need to use EMMLIB.
- o If you want to use expanded memory for more complex uses such as
- executing code, you must write your program in assembly language and
- make EMS function calls directly.
-
- Requirements
- ------------
- The functions in the EMS Toolkit libraries assume a few things about
- your computer's environment.
- +
- o Both MEMLIB and EMMLIB assume that Microsoft C version 5.1 and its
- "include" files are available on your system.
- o MEMLIB assumes that you are using a C "large-memory-model." EMMLIB
- allows you to use any size memory model.
- o The sample "make" files assume that the Microsoft utility MAKE.EXE
- is available; that the source code, header files, and EMMLIB.LIB are
- in one directory; and that the EMMLIB function files are in a
- subdirectory named \EMMLIB. Intel recommends that you install the
- MEMLIB files and your application's source code in the same
- subdirectory.
-
-
- Installing the software
- -----------------------
- The following sequence is the way we suggest you install the EMS
- Toolkit software. For this example, suppose the application source code is
- kept a subdirectory named \APP.
- 1 Insert Intel Toolkit diskette 1 into drive A.
-
- 2 At the DOS prompt, type the following:
- XCOPY A:\*.* C:\APP /s
-
- 3 Repeat the first two steps with diskettes 2 and 3.
-
- This command will copy the contents of the Intel disks to the \APP
- directory on drive C.
-
- /s means that all files in subdirectories below A:\ will be copied,
- and will keep the same directory structure. (If you'd like more
- information about the XCOPY command, refer to a DOS manual.)
-
-
-
- Chapter 2
- MEMLIB: LIBRARY FOR C DEVELOPERS
-
-
- MEMLIB is a set of functions that allow developers to manage expanded
- memory similar to the way they manage conventional memory with C.
- MEMLIB functions look and act like some of the more familiar C functions
- (malloc and free, for example).
-
- MEMLIB's internal structure does the "housekeeping" necessary to access and
- store data in expanded memory. When you use MEMLIB, you won't need to
- worry about page frame size, 16K-byte boundaries, or interfacing with an
- assembly language device driver.
-
- MEMLIB lets you allocate and access any size block of memory up to 64K
- bytes. It tracks available free memory, and uses a "best fit"
- algorithm to allocate new blocks.
-
- When you use MEMLIB, you just make a few C calls, and the libraries do
- the rest.
- Your application makes a call to MEMLIB, and MEMLIB in turn calls
- the EMMLIB library to access expanded memory. EMMLIB then translates
- the C calls into assembly language, and passes the calls on to the EMS
- driver.
-
-
- Compiling and linking MEMLIB
- ----------------------------
- Because MEMLIB uses EMMLIB calls to perform its functions, you must
- link and compile both libraries when you use MEMLIB. (The toolkit includes
- a previously made EMMLIB.LIB file to use with MEMLIB.) You can compile
- and link either with "make" (a Microsoft C utility) or manually.
-
- Using the "make" file
- ---------------------
- The easiest way to compile and link a number of interdependent modules
- is to use a "make" file. A "make" file lists all of the modules and
- their dependencies in a single file.
-
- A "make" file for a program called "SAMPLE" to use MEMLIB should
- contain the following lines.
-
- (contents of the file sample.mak)
- memlib.obj: memlib.c memlib.h errors.h emmlib.h
- CL /C /AL memlib.c
-
- sample.obj: sample.c memlib.h errors.h
- CL /C /AL sample.c
-
- sample.exe: sample.obj memlib.obj
- link sample memlib,,, emmlib.lib
-
- To use the "make" file, type the following line at the DOS prompt:
- make sample.mak
-
- If you change any file, just run the "make" file again to recompile
- and relink.
-
-
- Compile and link manually
- -------------------------
- Use the following command to compile the MEMLIB library:
- CL /C /AL memlib.c
-
- Use the following command to link MEMLIB to a program called "SAMPLE":
- LINK sample memlib, sample, nul, emmlib.lib
-
-
- Suggested sequence for using MEMLIB functions
- ---------------------------------------------
- MEMLIB functions provide a convenient way for your application to
- store data in expanded memory. To use expanded memory (and MEMLIB) most
- effectively, your application should follow this sequence of actions:
-
- 1. Allocate memory efmalloc allocates a block of expanded memory
- and returns a token (a block ID) to the application.
-
- 2. Access memory seteptrs uses the token returned by efmalloc to
- access the blocks you allocated. Also set1eptr,
- set2eptrs, set3eptrs.
-
- 3. Free memory effree frees previously allocated blocks of memory.
- Also effreeall.
-
- The other MEMLIB functions are provided for more specialized uses.
- You don't need to use them to store data in expanded memory.
-
- **CAUTION** Be sure to check the error codes that MEMLIB returns. If
- you try to allocate and use expanded memory when EMM isn't
- installed, you may lose data or overwrite some other area of
- memory. To learn more about MEMLIB's error codes, read
- Appendix B.
-
- The next section describes all of the MEMLIB functions in detail. Each
- description includes the purpose of the function, the calling sequence to
- use, and a short example program.
-
- The functions are listed in alphabetical order for easy reference. Below is
- a complete list of the functions grouped according to the operations they
- perform. To learn about a particular function, turn to the specified page.
-
-
- Function Page
- Allocating Memory
- efmalloc 2-10
-
- Accessing Memory
- seteptrs 2-24
- set1eptr 2-28
- set2eptrs 2-30
- set3eptrs 2-32
-
- Freeing Memory
- effree 2-6
- effreeall 2-8
-
- Other
- ememavl 2-12
- ememmax 2-14
- emsize 2-16
- push_context 2-21
- pop_context 2-18
-
- This is all you need to begin using MEMLIB to get expanded memory for your
- application program. If you would like more detailed information about how
- MEMLIB works, read Appendix C, Technical Information about MEMLIB.
-
-
- EFFREE
- ------
-
- PURPOSE
- The effree function frees a block of memory that efmalloc had allocated.
- Effree is analogous to the standard C function free.
-
- **CAUTION** The expanded memory manager (MEMLIB) is NOT a part of DOS.
- MEMLIB will not automatically free your allocated blocks when
- you exit your application. Your application should free all
- blocks during any kind of exit, including <CTL><BREAK> or
- other error conditions. (See Function 6, effreeall.)
-
- CALLING SEQUENCE
- unsigned int status;
- status = effree (token);
-
- unsigned int token The token that efmalloc returned when it
- allocated that block of memory. (input)
-
- STATUS
- PASSED (zero) The block is now free.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int token;
- unsigned int status;
-
- status = efmalloc (100, &token);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = effree (token);
- if (status == PASSED)
- /* Token is free, continue normal code */
- else
- /* error condition */
-
-
-
- EFFREEALL
- ---------
-
- PURPOSE
- The effreeall function frees all expanded memory blocks, pages, and
- handles effreeallallocated by your application. Effreeall is a convenient
- function to use when you are ending your application.
-
- **CAUTION** The expanded memory manager (MEMLIB) is NOT a part of DOS.
- MEMLIB will not automatically free your allocated blocks when
- you exit your application. Your application should free all
- blocks during any kind of exit, including <CTL><BREAK> or
- other error conditions.
-
- CALLING SEQUENCE
- unsigned int status;
- status = effreeall ( );
-
- STATUS
- PASSED (zero) All blocks, handles, and pages are now free.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int status;
- ...
- status = effreeall();
- if (status == PASSED)
- printf ("effreeall() successful");
- else
- /* error condition */
-
-
-
- EFMALLOC
- --------
-
- PURPOSE
- The efmalloc function is analogous to the standard C function malloc.
- In the same way that malloc allocates conventional memory, the efmalloc
- function allocates a block of memory from expanded memory pool. You can
- allocate up to 64K bytes with a call to efmalloc.
-
- There is one significant difference between malloc and efmalloc. A
- call to malloc allocates memory and returns a pointer, giving you access to
- that memory. Efmalloc allocates memory, but doesn't return a pointer.
-
- Here's why: You can't access expanded memory the same way you access
- conventional memory. You have to map a block of expanded memory into
- the page frame before you can access it. Once you've mapped in a block,
- you get a pointer to that block. With MEMLIB, you access a block using
- the seteptrs function (also set1eptr, set2eptrs, and set3eptrs). See the
- seteptrs function for more information about accessing expanded memory.
-
- **NOTE** You must use the effree (or effreeall) function to free a block of
- memory allocated with efmalloc.
-
- CALLING SEQUENCE
- unsigned int status;
- status = efmalloc (size, &token);
-
- unsigned int size The size (in bytes) desired for the memory
- block. The size must be greater than zero.
- (input)
- unsigned int token An identifier assigned to the memory block
- you've allocated. The token identifies that
- memory block in subsequent calls to other
- functions such as set1eptr. (output)
-
- STATUS
- PASSED (zero) The memory manager has allocated the block as
- expanded memory.
- error (non-zero value) See Appendix B for descriptions of error
- codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int size;
- unsigned int status;
- unsigned int token;
-
- size = 100 * sizeof(int);
- status = efmalloc (size, &token);
- if (status == PASSED)
- /* Continue normal code. We have allocated */
- /* space to store 100 integer values. */
- else
- /* error condition */
-
-
- EMEMAVL
- -------
-
- PURPOSE
- The ememavl function computes the amount (in bytes) of expanded memory
- available in your computer. The amount returned by ememavl is the total of
- all expanded memory available -- it is not the largest contiguous block of
- expanded memory (see ememmax).
-
- CALLING SEQUENCE
- unsigned int status;
- status = ememavl (&size)
- unsigned long size The amount of expanded memory (in bytes)
- ememavl returns (output)
-
- STATUS
- PASSED (zero) The memory manager has returned the total amount of
- expanded memory.
-
- error (non-zero value) See Appendix B for descriptions of the error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int status;
- unsigned long size;
-
- status = ememavl (&size);
- if (status == PASSED)
- printf ("Exp. memory avail. = %lu bytes \n",
- size);
- else
- /* error condition */
-
-
- EMEMMAX
- -------
-
- PURPOSE
- The ememmax function returns the size (in bytes) of the largest usable
- ememmaxblock of expanded memory. Because blocks of free memory can be
- fragmented, this amount may be smaller than the total amount of free
- expanded memory.
-
- CALLING SEQUENCE
- unsigned int status;
- status = ememmax (&size);
-
- unsigned int size The number of bytes in the largest usable block of
- expanded memory. (output)
-
- STATUS
- PASSED (zero) The memory manager has returned the size of the
- largest usable block.
- error (non-zero value) See Appendix B for descriptions of the error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int status;
- unsigned int size;
-
- status = ememmax (&size);
- if (status == PASSED)
- printf ("Largest block available = %u bytes \n",
- size);
- else
- /* error condition */
-
-
- EMSIZE
- ------
-
- PURPOSE
- The emsize function computes the size of a previously allocated block
- of expanded memory. Identify the block using the token that efmalloc
- returned emsizeafter allocating it.
-
- CALLING SEQUENCE
- unsigned int status;
- status = emsize (token, &size);
-
- unsigned int token Identifier for the block. (input)
- unsigned int size The size of the block (in bytes). (output)
-
- STATUS
- PASSED (zero) The token was valid; the size is computed.
- error (non-zero value) See Appendix B for descriptions of error
- codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int status;
- unsigned int token;
- unsigned int size;
-
- status = efmalloc (200, &token);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = emsize (token, &size)
- if (status == PASSED)
- printf ("Size of block = %u bytes \n", size);
- else
- /* error condition */
-
-
- POP_CONTEXT
- -----------
-
- PURPOSE
- The pop_context function restores the context saved by the
- push_context function.
-
- **NOTE** When you call pop_context, you lose access to the blocks that
- were mapped in at the time of the call.
-
- CALLING SEQUENCE
- unsigned int status;
- status = pop_context( );
-
- STATUS
- PASSED (zero) The context of block ( ) is restored.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int status;
- unsigned int token1;
- unsigned int token2;
- void *pointer1;
- void *pointer2;
-
- status = efmalloc (100, &token1);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = efmalloc (200, &token2);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = set1eptr (token1, &pointer1);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = push_context();
- if (status != PASSED)
- /* error condition */
- else
- /* save context for block 1 */
- status = set1eptr (token2, &pointer2);
- if (status != PASSED)
- /* error condition */
- else
- /* context for block 2 is active -- */
- /* can't access block 1 */
- ...
- status = pop_context();
- if (status != PASSED)
- /* error condition */
- else
- /* context for block 1 is active -- */
- /* can't access block 2 */
-
-
- PUSH_CONTEXT
- ------------
-
- PURPOSE
- The push_context function provides a convenient way to make the context of
- a mapped block available for later use. The context tells MEMLIB which
- blocks are mapped into which physical pages. Push_context saves the
- context, making it easy to restore access to whatever block(s) were mapped
- in at the time of the call to push_context.
-
- Restore the context you've "pushed" using the pop_context function
- (see Function 12).
-
- CALLING SEQUENCE
- unsigned int status;
- status = push_context( );
-
- STATUS
- PASSED (zero) The memory manager has pushed the context of the
- block onto a stack.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- **NOTE** To save a context, MEMLIB needs to allocate a small amount of
- conventional memory. MEMLIB allocates this memory dynamically--
- allocating just enough memory to save the context at the time of
- the call (usually less than 20 bytes).
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int status;
- unsigned int token1;
- unsigned int token2;
- void *pointer1;
- void *pointer2;
-
- status = efmalloc (100, &token1);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = efmalloc (200, &token2);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = set1eptr (token1, &pointer1);
- ...
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = push_context();
- if (status != PASSED)
- /* error condition */
- else
- /* save context for block 1 */
- ...
- status = set1eptr (token2, &pointer2);
- if (status != PASSED)
- /* error condition */
- else
- /* context for block 2 is active -- */
- /* can't access block 1 */
- ...
- status = pop_context();
- if (status != PASSED)
- /* error condition */
- else
- /* context for block 1 is active -- */
- /* can't access block 2 */
-
-
- SETEPTRS
- --------
-
- PURPOSE
- The seteptrs function attempts to gain access to the blocks you specify.
- Seteptrs then returns pointers to those blocks. Use this function if you
- need access to more than three blocks at once. Use set1eptr, set2eptrs,
- or set3eptrs to access 1, 2, or 3 blocks of memory.
-
- You can access all allocated blocks, but not necessarily all at the same
- time. You can access only that memory which is mapped into the page frame.
- Each expanded memory page is 16K, so if your page frame is 64K bytes, it
- will hold four pages, and any four blocks of 16K or less can be mapped in
- at one time. (EMS page frames are guaranteed to be at least 64K bytes.)
-
- If the combined size of all memory blocks you allocate during your
- program's execution is less than the size of your page frame, you can
- access all of the blocks at once.
-
- For a more detailed description of page frames, read Chapter 1 in the EMS
- manual.
-
- **NOTE** Seteptrs will unmap any pages that were mapped in before the call
- to seteptrs. If you want to call seteptrs, but want to regain access to a
- block that had been mapped in before the call, use the push_context
- function (before you call seteptrs). See push_context.
-
- CALLING SEQUENCE
- unsigned int status;
- status = seteptrs (num_blocks, tokens, pointers);
-
- unsigned int num_blocks The number of blocks you want to
- access. (input)
- unsigned int tokens[num_blocks] An array of tokens that efmalloc
- returned when it allocated the
- memory blocks. (input)
- void *pointers[num_blocks] The array of pointers seteptrs
- returns. Pointer[i] will point to
- the block of memory identified by
- token[i]. (output)
-
- STATUS
- PASSED (zero) You can gain access to all of the specified blocks.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- unsigned int tokens[2];
- /* Set array size for the number of blocks */
- /* you wish to allocate (in this case, 2) */
- void far *pointers[2];
- unsigned int status;
-
- status = efmalloc (200, &token[0]);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = efmalloc (600, &token[1]);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = seteptrs (2, tokens, pointers)
- if (status == PASSED)
- /* blocks are mapped in -- use */
- /* pointers to reference them */
- else
- /* error condition */
-
-
- SET1EPTR
- --------
-
- PURPOSE
- The set1eptr function provides access to a single block of memory by
- calling seteptrs. (This is a convenience routine for programmers who don't
- want to declare the arrays required by seteptrs.)
-
- CALLING SEQUENCE
- unsigned int status;
- status = set1eptr (token, &pointer);
-
- unsigned int token The token that efmalloc returned when it
- allocated that block of memory. (input)
- void *pointer The pointer that set1eptr returns to the
- application. (output)
-
- STATUS
- PASSED (zero) You have access to the block.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- void *pointer;
- unsigned int token;
- unsigned int status;
-
- status = efmalloc (500, &token);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = set1eptr (token, &pointer);
- if (status == PASSED)
- /* You have access to that block. Use */
- /* the pointer as the block's reference. */
- else
- /* error condition */
-
-
- SET2EPTRS
- ---------
-
- PURPOSE
- The set2eptrs function provides access to two blocks of expanded memory by
- calling seteptrs. (This is a convenience routine for programmers who don't
- want to declare the arrays required by seteptrs.)
-
- CALLING SEQUENCE
- unsigned int status;
- status = set2eptrs (token1, token2, &pointer1, &pointer2);
-
- unsigned int token1 The token efmalloc returned when it allocated
- the first block of memory. (input)
- unsigned int token2 The token efmalloc returned when it allocated
- the second block of memory. (input)
- void *pointer1 The pointer to the first block that set2eptrs
- returns. (output)
- void *pointer2 The pointer to the second block that set2eptrs
- returns. (output)
-
- STATUS
- PASSED (zero) You have access to these two blocks.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- void *pointer1;
- void *pointer2;
- unsigned int token1;
- unsigned int token2;
- unsigned int status;
-
- status = efmalloc (500, &token1);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = efmalloc (900, &token2);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = set2eptrs (token1, token2, &pointer1, &pointer2);
- if (status == PASSED)
- /* You have access to these blocks. */
- /* Use the pointers as references. */
- else
- /* error condition */
-
-
- SET3EPTRS
- ---------
-
- PURPOSE
- The set3eptrs function provides access to three blocks of expanded memory
- by calling seteptrs. (This is a convenience routine for programmers who
- don't want to declare the arrays required by seteptrs.)
-
- CALLING SEQUENCE
- unsigned int status;
- status = set3eptrs (token1, token2, token3, &pointer1, &pointer2, &pointer3);
-
- unsigned int token1 The token efmalloc returned when it allocated
- the first block of memory. (input)
- unsigned int token2 The token efmalloc returned for the second
- block. (input)
- unsigned int token3 The token efmalloc returned for the third
- block. (input)
- void *pointer1 The pointer to the first block that set3eptrs
- returns. (output)
- void *pointer2 The pointer to the second block that set3eptrs
- returns. (output)
- void *pointer3 The pointer to the third block. (output)
-
- STATUS
- PASSED (zero) You can gain access to these three blocks.
- error (non-zero value) See Appendix B for descriptions of error codes.
-
- EXAMPLE
- #include "memlib.h"
- #include "errors.h"
-
- void *pointer1;
- void *pointer2;
- void *pointer3;
- unsigned int token1;
- unsigned int token2;
- unsigned int token3;
- unsigned int status;
-
- status = efmalloc (500, &tok1);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = efmalloc (900, &tok2);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- set3eptrs status = efmalloc (300, &tok3);
- if (status != PASSED)
- /* error condition */
- else
- /* continue normal code */
- ...
- status = set3eptrs (token1, token2, token3,
- &pointer1, &pointer2, &pointer3);
- if (status == PASSED)
- /* Blocks are allocated; use pointers as references */
- else
- /* error condition */
-
-
-
-
- Chapter 3
- EMMLIB: LIBRARY FOR ASSEMBLY LANGUAGE
- AND C DEVELOPERS
-
-
- EMMLIB is a collection of assembly language functions that call EMS
- functions directly. This library provides full EMS capability to C
- programmers; EMMLIB performs all of the functions listed in the
- Lotus-Intel-Microsoft Expanded Memory Specification.
-
- If you want to use expanded memory for more complex uses such as named
- handles, alternate register sets, or page aliasing, then you will need the
- advanced functions available from EMMLIB.
-
- **NOTE** LIM-EMS is a powerful and complex specification. The EMMLIB
- routines are designed to allow high level languages to use the full power
- of EMM directly; the routines are not designed to simplify the
- specification.
-
-
- The LIM specification has approximately 30 functions, and most of these
- functions have subfunctions. EMMLIB provides C-callable routines for all
- of the functions and subfunctions (a total of 59). The EMMLIB functions
- are described in comment headers in the .ASM files on the Intel diskettes.
- Each filename includes the number of the EMS function corresponding to the
- EMMLIB function.
-
- Table 3-1 is a list of the functions available in EMMLIB, grouped according
- to the operations they perform. The table includes the name of the
- function, the file containing the code and description, and the
- corresponding function number from EMS.
-
- Table 3-2 lists the functions in alphabetical order, and includes cross
- references to the filename and corresponding EMS function.
-
- For a detailed description of a function, read the <Filename> file using
- any text editor, or read the description of the corresponding assembly
- language function <EMS Function No.> in the EMS manual.
-
- For example, to map in a couple of pages of expanded memory, you could use
- the map_unmap_pages function. To learn how to use this function, you would
- read either file EMMLIB23.ASM or the description of Function 17 in the EMS
- manual.
-
- **NOTE** EMMLIB.H is a header file that provides your C code with all of
- the "typedefs", function prototypes, and "#defines" that you need to call
- the EMMLIB functions. Be sure to include this file when you use any EMMLIB
- function.
-
-
- Table 3-1 EMMLIB Functions grouped by operation
-
- ______________________________________________________________
-
- Function Name Filename EMS Function No.
- _____________________________________________________________
- presence, status, and version
- EMM_installed EMM01-B.ASM 1
- get_EMM_status EMM01-A.ASM 1
- get_EMM_version EMM07-A.ASM 7
-
- memory allocation
- get_unalloc_page_count EMM03-A.ASM 3
- get_alloc_page_count EMM03-B.ASM 3
- get_total_page_count EMM03-C.ASM 3
- alloc_pages EMM04-A.ASM 4
- dealloc_pages EMM06-A.ASM 6
- realloc_pages EMM18-A.ASM 18
- get_unalloc_raw_page_count EMM26-A.ASM 26
- get_alloc_raw_page_count EMM26-B.ASM 26
- get_total_raw_page_count EMM26-C.ASM 26
- alloc_std_pages EMM27-A.ASM 27
- alloc_raw_pages EMM27-B.ASM 27
-
- mappable memory region information
- get_page_frame_seg EMM02-A.ASM 2
- get_mappable_conv_regions EMM25-A.ASM 25
- get_mappable_exp_regions EMM25-A.ASM 25
- get_mappable_regions EMM25-A.ASM 25
- get_mappable_conv_region_count EMM25-A.ASM 25
- get_mappable_exp_region_count EMM25-A.ASM 25
- get_page_frame_count EMM25-A.ASM 25
- get_mappable_region_count EMM25-C.ASM 25
-
- memory mapping
- map_unmap_page EMM05-A.ASM 5
- map_unmap_pages EMM17-A.ASM 17
-
- memory mapping context
- save_context EMM08-A.ASM 8
- restore_context EMM09-A.ASM 9
- get_context EMM15-A.ASM 15
- set_context EMM15-B.ASM 15
- get_set_context EMM15-C.ASM 15
- get_context_size EMM15-D.ASM 15
- get_partial_context EMM16-A.ASM 16
- get_partial_context_size EMM16-C.ASM 16
- set_partial_context EMM16-B.ASM 16
-
- memory movement and exchange
- move_memory_region EMM24-A.ASM 24
- xchg_memory_region EMM24-B.ASM 24
-
- handle management
- get_handle_count EMM12-A.ASM 12
- get_handle_pages EMM13-A.ASM 13
- get_all_handles_pages EMM14-A.ASM 14
- get_handle_attrib EMM19-A.ASM 19
- set_handle_attrib EMM19-B.ASM 19
- get_attrib_capability EMM19-C.ASM 19
- get_handle_name EMM20-A.ASM 20
- set_handle_name EMM20-B.ASM 20
- get_handle_dir EMM21-A.ASM 21
- search_handle_name EMM21-B.ASM 21
- get_total_handles EMM21-C.ASM 21
-
- program flow control
- alter_map_jump EMM22-A.ASM 22
- alter_map_call EMM23-A.ASM 23
- get_alter_map_call_stack_size EMM23-B.ASM 23
-
- Operating System only
- enable_OS_fcns EMM30-A.ASM 30
- disable_OS_fcns EMM30-B.ASM 30
- return_OS_access_key EMM30-C.ASM 30
- get_hw_info EMM26-D.ASM 26
- get_alt_reg_set EMM28-A.ASM 28
- set_alt_reg_set EMM28-B.ASM 28
- get_alt_context_size EMM28-C.ASM 28
- alloc_alt_reg_set EMM28-D.ASM 28
- dealloc_alt_reg_set EMM28-E.ASM 28
- alloc_DMA_reg_set EMM28-F.ASM 28
- enable_DMA_reg_set EMM28-G.ASM 28
- disable_DMA_reg_set EMM28-H.ASM 28
- dealloc_DMA_reg_set EMM28-I.ASM 28
- prep_EMM_warmboot EMM29-A.ASM 29
- _____________________________________________
-
-
-
-
-
- Table 3-2 EMMLIB Functions in alphabetical order
- ________________________________________________________________
-
- Function Name Filename EMS Function No.
- _________________________________________________________________
-
- alloc_alt_reg_set EMM28-D.ASM 28
- alloc_DMA_reg_set EMM28-F.ASM 28
- alloc_pages EMM04-A.ASM 4
- alloc_std_pages EMM27-A.ASM 27
- alloc_raw_pages EMM27-B.ASM 27
- alter_map_jump EMM22-A.ASM 22
- alter_map_call EMM23-A.ASM 23
-
- dealloc_alt_reg_set EMM28-E.ASM 28
- dealloc_DMA_reg_set EMM28-I.ASM 28
- dealloc_pages EMM06-A.ASM 6
- disable_DMA_reg_set EMM28-H.ASM 28
- disable_OS_fcns EMM30-B.ASM 30
-
- EMM_installed EMM01-B.ASM 1
- enable_DMA_reg_set EMM28-G.ASM 28
- enable_OS_fcns EMM30-A.ASM 30
-
- get_all_handles_pages EMM14-A.ASM 14
- get_alloc_page_count EMM03-B.ASM 3
- get_alloc_raw_page_count EMM26-B.ASM 26
- get_alt_context_size EMM28-C.ASM 28
- get_alter_map_call_stack_size EMM23-B.ASM 23
- get_alt_reg_set EMM28-A.ASM 28
- get_attrib_capability EMM19-C.ASM 19
-
- get_context EMM15-A.ASM 15
- get_context_size EMM15-D.ASM 15
- get_EMM_status EMM01-A.ASM 1
- get_EMM_version EMM07-A.ASM 7
- get_handle_count EMM12-A.ASM 12
- get_handle_pages EMM13-A.ASM 13
- get_handle_attrib EMM19-A.ASM 19
- get_handle_name EMM20-A.ASM 20
- get_handle_dir EMM21-A.ASM 21
- get_hw_info EMM26-D.ASM 26
-
- get_mappable_conv_regions EMM25-A.ASM 25
- get_mappable_conv_region_count EMM25-A.ASM 25
- get_mappable_exp_regions EMM25-A.ASM 25
- get_mappable_exp_region_count EMM25-A.ASM 25
- get_mappable_regions EMM25-B.ASM 25
- get_mappable_region_count EMM25-C.ASM 25
- get_page_frame_count EMM25-A.ASM 25
- get_page_frame_seg EMM02-A.ASM 2
-
- get_partial_context EMM16-A.ASM 16
- get_partial_context_size EMM16-C.ASM 16
- get_set_context EMM15-C.ASM 15
- get_total_handles EMM21-C.ASM 21
- get_total_page_count EMM03-C.ASM 3
- get_total_raw_page_count EMM26-C.ASM 26
- get_unalloc_page_count EMM03-A.ASM 3
- get_unalloc_raw_page_count EMM26-A.ASM 26
-
- map_unmap_page EMM05-A.ASM 5
- map_unmap_pages EMM17-A.ASM 17
- move_memory_region EMM24-A.ASM 24
-
- prep_EMM_warmboot EMM29-A.ASM 29
-
- realloc_pages EMM18-A.ASM 18
- restore_context EMM09-A.ASM 9
- return_OS_access_key EMM30-C.ASM 30
-
- save_context EMM08-A.ASM 8
- search_handle_name EMM21-B.ASM 21
- set_alt_reg_set EMM28-B.ASM 28
- set_context EMM15-B.ASM 15
- set_handle_attrib EMM19-B.ASM 19
- set_handle_name EMM20-B.ASM 20
- set_partial_context EMM16-B.ASM 16
-
- xchg_memory_region EMM24-B.ASM 24
- _________________________________________________________
-
-
-
-
- Appendix A
- EXAMPLE PROGRAM
-
- /* The intent of this example program is to show how to store and */
- /* manipulate data in expanded memory using the C Memory Manager -- */
- /* MEMLIB. */
- /* */
- /* This example shows what developers need to do in order to manipulate */
- /* expanded memory in their own applications by using MEMLIB routines. */
- /* For a more detailed program that uses a doubly linked list data */
- /* structure, see the ROLODEX.C program. */
- /* */
- /* This program follows a seven-step algorithm: */
- /* 1. Check the total amount of expanded memory available. */
- /* 2. Find the largest contiguous block of free expanded memory. */
- /* 3. Allocate expanded memory for two strings. */
- /* 4. Calculate the size of the block allocated for the first string. */
- /* 5. Print the two strings. */
- /* 6. Manipulate the data by appending one string to the other. */
- /* 7. Print the new string. */
- /**************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
-
- /**************************************************************************/
- /* The two header files below contain the function prototypes for */
- /* MEMLIB routines and the error messages specific to MEMLIB. Keep in */
- /* mind that MEMLIB calls EMMLIB functions, so you may get an error code */
- /* relating to EMS. (EMS codes are explained in Table A-2 in the */
- /* EMS manual.) You must include these two headers for any application */
- /* that will use MEMLIB. If you are going to use any EMMLIB calls */
- /* directly, you must also include "emmlib.h." */
- /**************************************************************************/
-
- #include "memlib.h"
- #include "errors.h"
- #define PASSED 0 /* If the MEMLIB call was successful */
- /* it will return a zero. */
- #define MAX_STRING_SIZE 255
- void abort (unsigned short); /* If we encounter any errors, we */
- /* call this function to "clean up." */
- void main()
- {
- unsigned short status; /* The status after a MEMLIB call. */
- char *string1; /* Our first data item. */
- char *string2; /* Our second data item. */
- unsigned int token1; /* The identifier to our first */
- /* block of expanded memory. */
- unsigned int token2; /* The identifier to our second */
- /* block of expanded memory. */
- unsigned int max_block_size; /* The size of the largest */
- /* allocatable contiguous block. */
- unsigned int size; /* The size of one of our blocks. */
- unsigned long max_exp_mem; /* The amount of expanded mem avail. */
-
- /***********************************************/
- /* See how much total expanded memory we have. */
- /***********************************************/
-
- status = ememavl (&max_exp_mem);
- if (status != PASSED)
- {
- printf ("Unable to obtain total expanded memory size.\n");
- abort (status);
- }
- else
- printf ("Total expanded memory available: %lu\n", max_exp_mem);
-
- /*************************************************/
- /* Get the size of the largest contiguous block. */
- /*************************************************/
-
- status = ememmax (&max_block_size);
- if (status != PASSED)
- {
- printf ("Unable to obtain the largest contiguous block.\n");
- abort (status);
- }
- else
- printf ("Largest contiguous block: %u\n\n", max_block_size);
-
- /*********************************************/
- /* Allocate the memory and check for errors. */
- /*********************************************/
-
- status = efmalloc (MAX_STRING_SIZE, &token1);
- if (status != PASSED)
- {
- printf ("Unable to allocate first block.\n");
- abort (status);
- }
- else
- printf ("Allocated space for the first block.\n");
-
- status = efmalloc (MAX_STRING_SIZE, &token2);
- if (status != PASSED)
- {
- printf ("Unable to allocate second block.\n");
- abort (status);
-
- else
- printf ("Allocated space for the second block.\n\n");
-
- /********************************/
- /* Check the size of block one. */
- /********************************/
-
- status = emsize (token1, &size);
- if (status != PASSED)
- {
- printf ("Unable to obtain size for block %u\n", token1);
- abort (status);
- }
- else
- printf ("Size of block %u is %u\n\n", token1, size);
-
- /***********************************************/
- /* Map in the two blocks, checking for errors. */
- /***********************************************/
-
- status = set2eptrs (token1, token2, & (char *) string1, & (char *)string2);
- if (status != PASSED)
- {
- printf ("Unable to map in the two blocks.\n");
- abort (status);
- }
- else
- printf ("Blocks mapped in.\n\n");
-
- printf ("Putting data in expanded memory.\n\n");
-
- /*********************************************/
- /* Store values in expanded memory using the */
- /* pointers given to us from set2eptrs(). */
- /*********************************************/
-
- strcpy (string1, "'What if life is an illusion and nothing exists?'");
- strcpy (string2, "'In that case, I definitely overpaid for my carpet.'
- --Woody Allen");
-
- printf ("String1: %s\n", string1);
- printf ("String2: %s\n\n", string2);
-
- /**************************************************/
- /* Still using the pointers, manipulate the data. */
- /**************************************************/
-
- printf ("Manipulating data in expanded memory.\n");
-
- strcat (string1, string2);
-
- printf ("String1: %s\n\n", string1);
-
- /**************************************************************/
- /* Free all expanded memory we've allocated. If effreeall() */
- /* is unsuccessful, we don't want to call abort() because */
- /* abort() would just call effreeall() again. */
- /**************************************************************/
-
- status = effreeall();
- if (status != PASSED)
- {
- printf ("Unable to free memory.\n");
- printf ("ERROR %X\n", status);
- exit (2);
- }
- else
- printf ("Expanded memory freed.\n");
- }
-
- /****************************************************************************/
- /* Aborts the program with an error message. Effreeall() frees all */
- /* pages, blocks, and handles associated with this application. It is */
- /* imperative that you release all the expanded memory you've allocated */
- /* before exiting, so that other applications can use this memory. If */
- /* you don't, you'll have to reboot to recover the lost memory. Notice */
- /* also that a call to effreeall() checks the EMM status. In case that */
- /* call fails, you'll get an error condtion back to let you know the */
- /* memory was not freed. */
- /* */
- /* You should always call effreeall() before aborting your program, even */
- /* if you get an error before allocating any memory. Effreeall() will free */
- /* the handles and memory that MEMLIB allocated when it was initialized. */
- /****************************************************************************/
-
- void abort (status)
- unsigned short status;
- {
- printf ("ERROR %X\n", status);
- status = effreeall();
- if (status != PASSED)
- {
- printf ("ERROR %X from effreeall().\n");
- printf ("Expanded memory not freed.\n");
- }
- exit (1);
- }
-
-
-
-
- Appendix B
- MEMLIB ERROR MESSAGES
-
- This appendix lists the MEMLIB error codes that may appear when you are
- running your application. The codes are listed in numerical order. Each
- error code description includes:
- o the hexadecimal number of the error code
- o a one-line description of the error
- o a short explanation of why the error message appeared
- o what you should do to correct the error
-
- Because MEMLIB makes calls to EMMLIB functions, you may see messages other
- than those listed here. Each EMMLIB error message includes a hexadecimal
- code number used by the Expanded Memory Specification (EMS). To find out
- more about these errors, look up the code number in Table A-2, "Status and
- Function Code Cross Reference," in the EMS manual.
-
- Error:
-
- 0xD0 INVALID_TOKEN
-
- cause The token that the MEMLIB routine received did not represent
- an allocated block of memory.
-
- action Each time efmalloc allocates a block of memory, it returns a
- token unique to that block. Use this token when referring to
- a particular block.
-
-
- 0xD1 NOT_ENOUGH_UNALLOCATED_PAGES
-
- cause Your computer does not have enough free expanded memory.
- MEMLIB requires at least 1 page (16K bytes) for its internal
- directory, and assumes that you'll need at least 1 more page
- to store data for your application.
-
- action You need more expanded memory. Add more memory to your Above
- Board, buy a Piggyback Option, or buy another Above Board.
-
-
- 0xD2 TOO_MANY_DIRECTORY_ENTRIES
-
- cause You requested more separate blocks of memory than the MEMLIB
- directory can handle. The maximum number of directory
- entries available is 65535.
-
- action Try requesting a few larger blocks instead of many small blocks.
-
- 0xD3 REQUEST_FOR_ZERO_LENGTH_BLOCK
-
- cause You tried to allocate a 0K-byte block of memory.
-
- action When you use efmalloc, make sure the size parameter is greater
- than zero.
-
- 0xD4 CANNOT_MAP_ALL_BLOCKS
-
- cause The blocks you attempted to access can't all be mapped into the
- page frame at the same time.
-
- action Try accessing fewer blocks at a time. See the NOTE at the
- beginning of the seteptrs function for more information on
- the number of memory blocks you can access.
-
- 0xD5 MAX_PUSH_CONTEXTS_EXCEEDED
-
- cause MEMLIB has a set maximum number of contexts it will "push"
- onto a stack, and you have exceeded that maximum.
- (See Function 11 for more information about contexts.)
-
- action You can either pop some of the contexts before pushing any
- more, or you can change the maximum default. In the
- MEMINTRL.C file you'll find a #define called
- MAX_CONTEXTS_AVAILABLE. Increase this number, then recompile
- MEMLIB.
-
- 0xD6 MALLOC_FAILURE
-
- cause When you tried to push a context, MEMLIB could not find enough
- open conventional memory to hold the context.
-
- action Use the pop_context function to release the contexts you have
- already pushed.
- If you haven't called push_context previously but get this
- error, you don't have enough free conventional memory to use
- the push_context function. Unless you can free some of your
- computer's conventional memory, don't call push_context or
- pop_context.
-
-
- 0xD7 NO_CONTEXT_AVAILABLE_TO_POP
-
- cause You attempted to call pop_context before calling push_context,
- or you tried to pop a context you had popped already.
-
- action Use the push_context function before using pop_context.
-
-
- 0xD8 ERROR_REALLOCATING_PAGES
-
- cause Efmalloc could not allocate the block of memory you requested
- because your computer doesn't have enough free expanded memory.
-
- action Allocate a smaller block of memory, add more memory to your
- Above Board, or buy another.
-
-
- 0xD9 NOT_INITIALIZED
-
- cause You called a function that was designed to be called by another
- function, not by your application.
-
- action Limit your MEMLIB function calls to the functions listed in
- this manual.
-
-
-
- Appendix C
- TECHNICAL INFORMATION ABOUT MEMLIB
-
- This appendix explains in detail how MEMLIB provides access to expanded
- memory, how it keeps track of expanded memory, how it allocates memory, and
- the algorithms it uses. You don't need this information to use MEMLIB with
- your application program. It's provided for your information only.
-
- If you'd like more information about how expanded memory works, read
- Chapter 1 in the EMS manual.
-
-
- How MEMLIB provides access to expanded memory
- ---------------------------------------------
-
- You can have up to 32M bytes of expanded memory in your computer, and
- MEMLIB can provide access to all of it.
-
- Expanded memory is divided into logical pages. Each logical page is 16K
- bytes.
-
- To access a block of expanded memory, MEMLIB needs to map in the logical
- page that the block uses. MEMLIB can map only a limited number of these
- pages into the EMS page frame at one time.
-
- For example, if your page frame is 64K bytes, four logical pages can be
- mapped into it. You can access four memory blocks at the same time if the
- size of each block is 16K bytes or less. However, accessing five blocks at
- once may be impossible, because the blocks might use five different logical
- pages (five pages won't fit in the page frame).
-
- How MEMLIB keeps track of expanded memory
- -----------------------------------------
-
- The expanded memory manager, MEMLIB, is based on a directory structure.
- Each directory entry consists of four fields:
-
- unsigned int token (0xFFFF = free, otherwise = allocated)
- unsigned int size (size [in bytes] of this block)
- unsigned short offset (the offset into the first logical page of
- this block)
- int logical_page[4] (pages used)
-
- Blocks less than or equal to 16K bytes will use one logical page; 16 - 32K,
- two pages; 32 - 48K, three pages; and 48 - 64K, four pages.
-
- This directory is stored in expanded memory that MEMLIB allocates when
- needed.
-
-
- How MEMLIB allocates expanded memory
- ------------------------------------
-
- To allocate memory, MEMLIB attempts to reuse as much deallocated memory as
- possible before allocating any new blocks.
-
- When a block of memory is freed, MEMLIB checks all other freed blocks to
- see if they fall immediately before or after that block. If there are any
- adjacent free blocks, MEMLIB combines the blocks into one larger block.
- When a user requests a block of memory, MEMLIB checks all free blocks and
- gives the user the smallest free block bigger than the size requested (best
- fit). Any leftover memory is put into another free block.
-
- EXAMPLE:
- A user makes an efmalloc request for a 6K block. MEMLIB allocates
- logical page 1 from EMM, and creates two directory entries: one to
- the 6K block and one to the 10K free block.
-
- Next, the user makes another efmalloc request, this time for an 11K
- block. 11K won't fit in the 10K free block in logical page 1, and
- will overlap into the next logical page if assigned to page 1 at all.
- MEMLIB allocates an entirely new logical page, page 2. Again, it
- creates one directory entry to point to the allocated block, and
- another entry to point to the 5K of free memory (4).
-
-
-
- Algorithms
- ----------
-
- When a user requests a block of memory (efmalloc), Intel uses the following
- algorithm:
-
- (C pseudo code)
-
- do
- if (exact fit)
- allocate block
- else
- check for best fit
- while ((not exact fit) and (not last directory entry))
- if (not exact fit)
- if (best fit)
- allocate block
- set directory entry for remainder
- else
- request page from expanded memory manager
- if request = OK
- allocate block
- else
- return NOT_ENOUGH_UNALLOCATED_PAGES error
-
-
- To free a block of memory (effree), we use this algorithm:
-
- do
- if (contiguous free block)
- combine into one free block
- while (not last directory entry)
- if (no allocated pages found)
- deallocate all pages /* prepare for program termination */
-
-
- When mapping in blocks of memory (seteptrs), we use the following algorithm:
-
- for (i = 0, i < number of requested blocks; i++)
- if (logical pages needed for block i are already mapped)
- OK = true
- else
- if (pages need for block i will fit)
- OK = true
- map in pages needed
- else
- return CANNOT_MAP_ALL_BLOCKS error
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-