Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Zortech C++ 3.0r4 - <b>the emm package</b> http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
The Emm Package

   This contains a full set of functions for allocating and using expanded
   (EMS or LIMS) memory. It is provided as an alternative to the support
   built into the compiler via the handle pointer type. For details of the
   latter refer to the chapter The Handle Pointer Type in the Compiler
   Guide. These functions are supported under real mode MS-DOS only.

   The Emm package is provided as an alternative to the __handle pointer
   system for the programmer who requires more control of the use of
   expanded memory by an application. The Emm package can be utilized at the
   same time as the __handle system but the two should be kept separate. The
   following discussion will be useful to programmers whichever system they
   intend to use.

   The current implementation only uses the facilities of EMS 3.2 to ensure
   the widest possible compatibility. Applications written using the Emm
   package or the __handle pointer system are therefore compatible with

   expanded memory managers for both EMS 3.2 and the newer EMS 4.0, as well
   as with the EMS facilities within MS-DOS 4.x.

What is an Expanded Memory System?

   Expanded memory is a system for real mode MS-DOS which gives access to up
   to 8 Mb (EMS 3.2) of bank switched memory. It is not required when using
   the ZPM or DOSX extenders. Blocks of the expanded memory are overlaid on
   a region of conventional memory, known as a page frame, and swapped in
   and out of the normal addressing space, as needed. When a block of
   expanded memory is swapped into the page frame it can be used to store
   and retrieve data just as if it were conventional memory. Data stored
   within the blocks is retained even when they are not swapped in.

   An expanded memory system normally consists of two components, an
   expansion board containing extra memory as well as some special control
   chips, and an MS-DOS device driver known as the Expanded Memory Manager
   (EMM). However, there are a number of other methods of implementing
   expanded memory. Some software only systems are designed to emulate
   expanded memory in the 16 Mb address space of 80286 based computers

   (known as extended memory). There are also systems that emulate expanded
   memory using hard disk storage. These software only systems do not
   support some of the facilities available in the hardware based
   implementations. For example, data aliasing, that is the mapping of the
   same expanded memory page to more than one physical page, cannot be
   supported. Another system which has appeared, also uses extended memory
   as expanded memory, except that the facility is built into the hardware
   of the computer, this type can sometimes support data aliasing. Finally
   the 80386 chip has the ability to manage expanded memory built in, and
   most 80386 based systems are designed to allow this.

How Expanded Memory Works

   An expanded memory system normally sets aside a page frame in the
   nominally "unused" area of 8086 address space which lies between the top
   of the video display memory (768K) and the 1 Mb address limit. In version
   3.2 of the EMS this area has a fixed length of 64 kb and is arranged to
   start at a segment boundary. Different board manufacturers use different
   absolute addresses for the start of their page frames, but this address
   is always fixed at start up either by board switches or by the device

   driver command line. (EMS version 4.0 allows the page frame to be any
   length between 64 kb and 176 kb and allows for the start of the page
   frame to be changed by software during program execution.)

   It should be noted that although the memory addresses between 768 kb and
   1 Mb are normally unused in most systems, certain hardware add ons such
   as network boards, or specialist display boards may use this address
   space and clash with EMS boards. It is sometimes possible to alleviate
   this situation by relocating the page frame, provided there is a
   sufficiently large (64 kb for EMS 3.2) free area in the 768 kb to 1 Mb
   address space that is unused.

   The page frame is normally split up into 16 kb blocks, known as physical
   pages. Thus a 64 kb page frame consists of 4 physical pages. Access to
   expanded memory is then achieved via the Expanded Memory Manager, by the
   use of hardware registers in the expanded memory board or a software
   simulation of these registers. These registers are used to "map" 16 kb
   blocks of expanded memory into the address space of the available
   physical pages. The 16 kb expanded memory page can then be accessed by
   the microprocessor reading and writing to memory addresses which are

   contained within that physical page.

   Taking the example of an Expanded Memory Manager which uses a 64 kb page
   frame starting at the hex address 1e00:0000 (in segment:offset notation).
   The EMM might be asked to map the first 16 kb block of expanded memory
   (this is known as a logical page) into the first physical page in the
   page frame. The net result of this is that the 1st logical page of
   expanded memory now has the effective address of 1e00:0000 through
   1e00:3fff. The application can then store and retrieve data from this
   block of expanded memory, as if it were any other block of memory.
   However, if the application program then requests the memory manager to
   map a different block of expanded memory into this physical page, any
   data stored to the previous page will no longer be found. The data is not
   lost, however, because any read or write operations are now affecting a
   totally different block of memory, which can be used independently of the
   first block. The application could for instance then ask for the original
   1st logical page to be mapped back not into the first physical page in
   the page frame, but into the second physical page at memory addresses
   1e00:4000 through 1e00:7fff. Any data previously stored in this page of
   expanded memory can then be retrieved using a memory address which is 16

   kb higher than that to which it was originally written.

   Obviously, with a 64 kb page frame it is possible to have more than one
   page of expanded memory mapped into the microprocessor's address space at
   any one time. The term used to describe the relationship between physical
   pages within the page frame and the logical pages which are using the
   address space of those physical pages (mapped in) is known as the mapping
   context. The mapping context is maintained for you by the Expanded Memory
   Manager once you have established it with the appropriate expanded memory
   function calls and it modifies this context when requested to by further
   function calls as your application progresses. EMS version 3.2 allows a
   maximum of 8 Mb of expanded memory to be utilized whereas version 4.0
   allows up to 32 Mb (2048 logical pages) to be made available to
   applications or the operating system.

   As mentioned previously, applications gain access to expanded memory
   through the Expanded Memory Manager. This is an MS-DOS device driver
   which is normally supplied with the expanded memory hardware, or with the
   computer if the expanded memory hardware is built in. The usual way of
   installing such a device driver is to place it in the config.sys file.

   The EMM installs itself onto one of the 8086 interrupt vectors, interrupt
   0x67 and this vector provides the application software with access to the
   Expanded Memory Manager via the 8086 instruction int. From the point of
   view of the programmer therefore, access to the EMM can be achieved
   through the standard library functions int86 and int86x. This requires
   the programmer to know exactly the register format required by the
   Expanded Memory Manager for each EMS function and also involves a speed
   penalty since int86 and int86x are general purpose functions designed to
   cope with a wide variety of different situations. Obviously, where memory
   access to data is concerned, any loss of speed can have a detrimental
   effect on the performance of an application. For these reasons the
   pre-written access functions provided in the Emm package are all hand
   coded in assembler.

   If you are using the EMM functions, it is important to note that when the
   program exits, EMM pages that are allocated are not automatically freed,
   in the same way regular allocated memory is. It is therefore important to
   find all routes by which the program can be terminated, and add in a call
   to free up and terminate use of EMM pages. The ways a program can
   terminate are:


   1. Return from main().

   2. Calling exit().

   3. Calling _exit(), _assert(), abort() or raise(SIGABRT).

   4. Ctrl-C or Ctrl-Break.

   5. Heap corruption or floating point not loaded errors from the runtime
   library.

   Case 4 can only be handled by intercepting the control break interrupt
   (0x23). Case 5 is a program crash anyway.

   The symptoms of not freeing up EMM memory are that programs run later
   will not find any available EMM pages to allocate. This will persist
   until a program is run that frees up EMM, or the system is rebooted. If
   you are using EMM via handles, this is already taken care of by the
   runtime library. Cases 1 and 2 are handled by setting up a static

   destructor. Case 4 is done by chaining into the control break interrupt.
   Case 3 is not dealt with.

   The following outline shows how a typical application might use expanded
   memory:

   1. The application tests whether an Expanded Memory Manager is installed.

   2. It determines whether there are enough expanded memory pages available
   for the application's purposes.

   3. The EMM is requested to allocate the required number of expanded
   memory (logical) pages to the application. The EMM supplies the
   application with a unique EMM handle, which the application uses to refer
   to its allocated pages.

   4. The base address of the various physical pages is obtained from the
   EMM so that the application knows which memory addresses to use to access
   the expanded memory.


   5. Some of the expanded memory (logical) pages are mapped into the
   physical pages within the page frame.

   6. Data is written to and read from these logical pages, just as though
   it were being written to or read from conventional memory.

   7. Steps 5 and 6 are repeated as necessary by the application.

   8. When the application is finished using expanded memory, it returns the
   expanded memory pages to the EMM pool before exiting (otherwise other
   applications will be unable to use this memory).

   9. The application terminates.

Example 

   #include <stdio.h>
   #include <stdlib.h>
   #include <emm.h>


   #define HANDLES 4

   /*  chkout:make sure an EMM supervisor is installed. */
   void chkout(void)
   {
       int i, version;
       float ver_no;

       if (emm_init()) {
           printf("Unable to initiate EMS driver\n");
           exit(EXIT_FAILURE);
       }

       version = emm_getversion();
       ver_no = version/16+version%16/10.0;

       printf("EMS driver detected, version %1.1f\n",ver_no);

       printf("\tlogical page\t\tsegment\n");
       for (i = 0;i < 4;i++) {

           printf("\t%d\t\t\t%lp\n",i,emm_physpage(i));
       }
       printf("\n");
   }

   /* check that allocation worked */
   void check_aloc(void)
   {
       int i, noh;
       struct emm_handle_s *hp;

       noh = emm_gethandlecount();

       if ((hp = calloc(noh, sizeof(struct emm_handle_s))) ==
               NULL) {
           printf("Insufficient Memory:function check_aloc\n");
           exit(EXIT_FAILURE);
       }

       emm_gethandlespages(hp);


       printf("\thandle no.\t\tpages\n");
       for (i = 0; i < noh; i++) {
           printf("\t%d\t\t\t%d\n",hp[i].handle,hp[i].pages);
       }
       printf("\n");
   }

   use_emm(unsigned h, int logical)
   {
       char message[128], *s;
       char far *src, far *dst;

       src = emm_physpage(0);
       dst = emm_physpage(1);

       printf("Writing string to physical page 0 at %lp\n"
                       ,src);
       sprintf(message,"Hello, from physical page 1 at %lp"
                       ,dst);

       emm_maphandle(h,logical,0);
       s = message;
       while (*s)
           *src++ = *s++;

       printf("Reading String from EMM buffer:\n");
       emm_maphandle(h,logical,1);
       s = message;
       while (*s)
           *s++ = *dst++;
       printf("Handle %d message ='%s'.\n",h,message);
   }

   int main()
   {
       unsigned i, usedp, thandle[HANDLES];

       chkout() ;

       printf("No. of active handles is %d \n"

                   ,emm_gethandlecount());

       for (i=0;i<HANDLES;i++) {
           /* Take half of what is available */
           usedp = (emm_getunalloc()+1)>>1;
           thandle[i] = emm_allocpages(usedp);
           printf("%d pages allocated to handle %d\n"
                   , usedp,thandle[i]);
       }

       printf("No. of active handles is %d \n"
                   ,emm_gethandlecount());
       printf("Total size is %d pages\n",emm_gettotal());
       printf("Free size is %d pages\n",emm_getunalloc());

       check_aloc();
       use_emm(thandle[0],0);

       for (i=0;i<HANDLES;i++) {
           emm_deallocpages(thandle[i]);

           printf("[%d] H=%d freed\n",i,thandle[i]);
       }
       printf("Total size is %d pages\n",emm_gettotal());
       printf("Free size is %d pages\n",emm_getunalloc());
       printf("Done with EMM test.\n");
       emm_term();
       return EXIT_SUCCESS;
   }





Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson