home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / MEMLIB.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  90KB  |  1,770 lines

  1. /**********************************************************************/
  2. /*                                                                    */
  3. /*     Module:    MEMLIB.C                                            */
  4. /*                                                                    */
  5. /*     This module contains the C MEMORY MANAGER - a group of C       */
  6. /*     callable routines that manage expanded memory.  These          */
  7. /*     routines alleviate many of the housekeeping chores necessary   */
  8. /*     when dealing with expanded memory and make allocating and      */
  9. /*     freeing expanded memory look as much like allocating and       */
  10. /*     freeing conventional memory as possible.                       */
  11. /*                                                                    */
  12. /*     The routines called by an application are:                     */
  13. /*                                                                    */
  14. /*     ememavl         Approximate amount of free expanded memory     */
  15. /*     ememmax         Size of the largest contiguous free block      */
  16. /*     emsize          Size of a specified block                      */
  17. /*     efmalloc        Allocate a block of memory                     */
  18. /*     effree          Free a previously allocated block              */
  19. /*     seteptrs        Access n different blocks                      */
  20. /*     set1eptr        Access 1 block                                 */
  21. /*     set2eptrs       Access 2 blocks                                */
  22. /*     set3eptrs       Access 3 blocks                                */
  23. /*     push_context    Push the current mapping context               */
  24. /*     pop_context     Pop a mapping context                          */
  25. /*     effreeall       Frees ALL blocks                               */
  26. /*                                                                    */
  27. /**********************************************************************/
  28.   
  29. #include "memintrl.c"
  30.   
  31. /*$PAGE*/
  32. /**********************************************************************/
  33. /*                                                                    */
  34. /*     Name:    unsigned int ememavl (*size)                          */
  35. /*              unsigned long *size;                                  */
  36. /*                                                                    */
  37. /*     Description:                                                   */
  38. /*        Computes the size of expanded memory available in bytes but */
  39. /*     due to memory fragmentation, the largest useable block may be  */
  40. /*     smaller than the amount returned by this function.  See        */
  41. /*     ememmax.                                                       */
  42. /*                                                                    */
  43. /*     Parameters:                                                    */
  44. /*        output  size       The size computed.                       */
  45. /*                                                                    */
  46. /*     Results returned:                                              */
  47. /*        PASSED     The size is valid                                */
  48. /*        error      Non-zero value, see "ERRORS.H" or EMS table A-2  */
  49. /*                                                                    */
  50. /*     Calling sequence:                                              */
  51. /*     #include "memlib.h"                                            */
  52. /*     #include "errors.h"                                            */
  53. /*         ...                                                        */
  54. /*     unsigned long size;                                            */
  55. /*     unsigned int  status;                                          */
  56. /*         ...                                                        */
  57. /*     status = ememavl (&size);                                      */
  58. /*     if (status == PASSED)                                          */
  59. /*         printf("Expanded memory available = %lu \n", size);        */
  60. /*     else                                                           */
  61. /*         { error condition }                                        */
  62. /*                                                                    */
  63. /*     Calls: prepare_dir_mapping()                                   */
  64. /*            get_unalloc_page_count()                                */
  65. /*            restore_memlib_context()                                */
  66. /*            map_dir_page()                                          */
  67. /*                                                                    */
  68. /*     Called by:  Application                                        */
  69. /*                                                                    */
  70. /*     Globals referenced/modified: directory                         */
  71. /*                                  dir_page_count                    */
  72. /*                                                                    */
  73. /**********************************************************************/
  74.   
  75. unsigned int ememavl (size)
  76. unsigned long *size;
  77. {
  78.     unsigned int status;             /* The status of EMM and MEMLIB    */
  79.     unsigned int num_unalloc_pages;  /* Number of unallocated pages     */
  80.     unsigned int index;              /* Index into a directory page     */
  81.     unsigned int dir_page;           /* The directory page to map in    */
  82.     unsigned int context_saved;      /* Whether the contexted was saved */
  83.   
  84.     *size = 0;
  85.   
  86.    /**********************************************/
  87.    /* Call prepare_dir_mapping() to save context */
  88.    /* before mapping in the directory.           */
  89.    /**********************************************/
  90.   
  91.     status = prepare_dir_mapping (&context_saved);
  92.   
  93.     if (status == PASSED)
  94.     {
  95.       /********************************************************/
  96.       /* Add up the number of 16K pages that are unallocated. */
  97.       /********************************************************/
  98.   
  99.         status = get_unalloc_page_count (&num_unalloc_pages);
  100.         if (status == PASSED)
  101.         {
  102.             *size += PAGE_SIZE * (long) num_unalloc_pages;
  103.         }
  104.   
  105.       /***************************************************/
  106.       /* Go through entire directory one page at a time. */
  107.       /***************************************************/
  108.   
  109.         for (dir_page = 0; ((status == PASSED) &&
  110.             (dir_page < dir_page_count)); dir_page++)
  111.         {
  112.          /***********************************/
  113.          /* Map in the this directory page. */
  114.          /***********************************/
  115.   
  116.             status = map_dir_page (dir_page, FIRST_PHYS_PAGE);
  117.             if (status == PASSED)
  118.             {
  119.             /******************************************/
  120.             /* Add up all freed blocks for this page. */
  121.             /******************************************/
  122.   
  123.                 for (index = 0; (index < DIR_ENTRIES_PER_PAGE); index++)
  124.                 {
  125.                     if (directory[0][index].token == UNASSIGNED_TOKEN)
  126.                         *size += directory[0][index].size;
  127.                 }
  128.             }
  129.         }
  130.     }
  131.    /**************************************************************/
  132.    /* Unmap the directory - remap the pages that were in before. */
  133.    /**************************************************************/
  134.   
  135.     if (context_saved)
  136.         status = restore_memlib_context (status);
  137.   
  138.    /*************************************/
  139.    /* If some error return a size of 0. */
  140.    /*************************************/
  141.   
  142.     if (status != PASSED)
  143.         *size = 0;
  144.   
  145.     return (status);
  146.   
  147. }  /** end of ememavl **/
  148.   
  149.   
  150.   
  151. /*$PAGE*/
  152. /**********************************************************************/
  153. /*                                                                    */
  154. /*     Name:    unsigned int ememmax (*size)                          */
  155. /*              unsigned int *size;                                   */
  156. /*                                                                    */
  157. /*     Description:                                                   */
  158. /*        Computes the size of the largest block of expanded memory   */
  159. /*     that MEMLIB can allocate.                                      */
  160. /*                                                                    */
  161. /*     Parameters:                                                    */
  162. /*        output  size  The size of the largest allocatable block.    */
  163. /*                                                                    */
  164. /*     Results returned:                                              */
  165. /*        PASSED     Operation successful                             */
  166. /*        error      Non-zero value, see "ERRORS.H" or EMS table A-2  */
  167. /*                                                                    */
  168. /*     Calling sequence:                                              */
  169. /*     #include "memlib.h"                                            */
  170. /*     #include "errors.h"                                            */
  171. /*         ...                                                        */
  172. /*     unsigned int size;                                             */
  173. /*     unsigned int status;                                           */
  174. /*         ...                                                        */
  175. /*     status = ememmax (&size);                                      */
  176. /*     if (status == PASSED)                                          */
  177. /*         printf("Largest block available = %u \n", size);           */
  178. /*     else                                                           */
  179. /*         { error condition }                                        */
  180. /*                                                                    */
  181. /*     Calls: prepare_dir_mapping()                                   */
  182. /*            map_dir_page()                                          */
  183. /*            get_unalloc_page_count()                                */
  184. /*            restore_memlib_context()                                */
  185. /*                                                                    */
  186. /*     Called by:  Application                                        */
  187. /*                                                                    */
  188. /*     Globals referenced/modified: directory                         */
  189. /*                                  dir_page_count                    */
  190. /*                                                                    */
  191. /**********************************************************************/
  192.   
  193. unsigned int ememmax (size)
  194. unsigned int *size;
  195. {
  196.     unsigned int status;     /* The status of EMM and MEMLIB   */
  197.     unsigned int num_pages;  /* Number of unallocated pages    */
  198.     unsigned int page;       /* Directory page to map in       */
  199.     unsigned int index;      /* Index into a directory page    */
  200.     unsigned int saved;      /* whether the context was saved  */
  201.   
  202.    /**********************************************/
  203.    /* Call prepare_dir_mapping() to save context */
  204.    /* before mapping in the directory            */
  205.    /**********************************************/
  206.   
  207.     status = prepare_dir_mapping (&saved);
  208.   
  209.     if (status == PASSED)
  210.     {
  211.       /***************************************************************/
  212.       /* If more than 64K worth of unallocated pages, set max to     */
  213.       /* the largest allocateable block (64K-1).  Otherwise, test    */
  214.       /* the number of unallocated pages * 16K against *size.        */
  215.       /***************************************************************/
  216.   
  217.         status = get_unalloc_page_count (&num_pages);
  218.         if (status == PASSED)
  219.         {
  220.             if (num_pages >= MAX_ALLOCATABLE_PAGES)
  221.                 *size = LARGEST_ALLOCATABLE_BLOCK;
  222.             else
  223.                 *size = PAGE_SIZE * num_pages;
  224.         }
  225.     }
  226.   
  227.    /**************************************/
  228.    /* Go through all the directory pages */
  229.    /**************************************/
  230.   
  231.     for (page = 0; ((status == PASSED) &&
  232.         (page < dir_page_count)); page++)
  233.     {
  234.       /***********************************/
  235.       /* Map in the this directory page. */
  236.       /***********************************/
  237.   
  238.         status = map_dir_page (page, FIRST_PHYS_PAGE);
  239.         if (status == PASSED)
  240.         {
  241.          /********************************/
  242.          /* Find the maximum free block. */
  243.          /********************************/
  244.   
  245.             for (index = 0; index < DIR_ENTRIES_PER_PAGE; index++)
  246.             {
  247.                 if ((directory[0][index].token == UNASSIGNED_TOKEN) &&
  248.                     (directory[0][index].size > *size))
  249.                     *size = directory[0][index].size;
  250.             }
  251.         }
  252.     }
  253.   
  254.    /**************************************************************/
  255.    /* Unmap the directory - remap the pages that were in before. */
  256.    /**************************************************************/
  257.   
  258.     if (saved)
  259.         status = restore_memlib_context (status);
  260.   
  261.    /*************************************/
  262.    /* If some error return a size of 0. */
  263.    /*************************************/
  264.   
  265.     if (status != PASSED)
  266.         *size = 0;
  267.   
  268.     return (status);
  269.   
  270. }  /** end of ememmax **/
  271.   
  272. #ifdef notdef
  273.   
  274. /*$PAGE*/
  275. /**********************************************************************/
  276. /*                                                                    */
  277. /*     Name:    unsigned int emsize (token, *size)                    */
  278. /*              unsigned int token;                                   */
  279. /*              unsigned int *size;                                   */
  280. /*                                                                    */
  281. /*     Description:                                                   */
  282. /*        Returns the size, in bytes, of the allocated block of       */
  283. /*     memory identified by 'token.' (A token returned from           */
  284. /*     efmalloc).                                                     */
  285. /*                                                                    */
  286. /*     Parameters:                                                    */
  287. /*        input   token       identifies the block desired            */
  288. /*        output  size        the size, in bytes, of the block        */
  289. /*                                                                    */
  290. /*     Results returned:                                              */
  291. /*        PASSED     Operation successful                             */
  292. /*        error      Non-zero value, see "ERRORS.H" or EMS table A-2  */
  293. /*                                                                    */
  294. /*     Calling sequence:                                              */
  295. /*     #include "memlib.h"                                            */
  296. /*     #include "errors.h"                                            */
  297. /*         ...                                                        */
  298. /*     unsigned int status;                                           */
  299. /*     unsigned int token;                                            */
  300. /*     unsigned int size;                                             */
  301. /*                                                                    */
  302. /*     status = efmalloc (200, &token);                               */
  303. /*         ...                                                        */
  304. /*     status = emsize (token, &size);                                */
  305. /*     if (status == PASSED)                                          */
  306. /*         printf ("Size of block = %u bytes\n", size);               */
  307. /*                                                                    */
  308. /*     Calls: prepare_dir_mapping()                                   */
  309. /*            map_dir_page()                                          */
  310. /*            check_token()                                           */
  311. /*            restore_memlib_context()                                */
  312. /*                                                                    */
  313. /*     Called by:  Application                                        */
  314. /*                                                                    */
  315. /*     Globals referenced/modified: directory                         */
  316. /*                                                                    */
  317. /**********************************************************************/
  318.   
  319. unsigned int emsize (token, size)
  320. unsigned int token;
  321. unsigned int *size;
  322. {
  323.     unsigned int status;        /* The status of EMM and MEMLIB    */
  324.     unsigned int page;          /* Directory page to map in        */
  325.     unsigned int index;         /* The index into a directory page */
  326.     unsigned int context_saved; /* Whether the context was saved   */
  327.   
  328.    /**********************************************/
  329.    /* Call prepare_dir_mapping() to save context */
  330.    /* before mapping in the directory            */
  331.    /**********************************************/
  332.   
  333.     status = prepare_dir_mapping (&context_saved);
  334.   
  335.    /***************************/
  336.    /* Check for a valid token */
  337.    /***************************/
  338.   
  339.     if (status == PASSED)
  340.         status = check_token (token);
  341.   
  342.     if (status == PASSED)
  343.     {
  344.       /*****************************************************/
  345.       /* Set 'page' to the directory page this token is in */
  346.       /*****************************************************/
  347.   
  348.         page = token / DIR_ENTRIES_PER_PAGE;
  349.   
  350.       /**********************************************/
  351.       /* Convert the token into an index that falls */
  352.       /* within the size of a directory page        */
  353.       /**********************************************/
  354.   
  355.         index = token % DIR_ENTRIES_PER_PAGE;
  356.   
  357.       /******************************/
  358.       /* Map in this directory page */
  359.       /******************************/
  360.   
  361.         status = map_dir_page (page, FIRST_PHYS_PAGE);
  362.         if (status == PASSED)
  363.         {
  364.          /*****************************/
  365.          /* Check size for this index */
  366.          /*****************************/
  367.   
  368.             if (directory[0][index].token == token)
  369.             {
  370.                 *size = directory[0][index].size;
  371.                 status = PASSED;
  372.             }
  373.             else
  374.             {
  375.                 *size = 0;
  376.                 status = INVALID_TOKEN;
  377.             }
  378.         }
  379.     }
  380.   
  381.    /*************************************************************/
  382.    /* Unmap the directory - remap the pages that were in before */
  383.    /*************************************************************/
  384.   
  385.     if (context_saved)
  386.         status = restore_memlib_context (status);
  387.   
  388.    /************************************/
  389.    /* If some error return a size of 0 */
  390.    /************************************/
  391.   
  392.     if (status != PASSED)
  393.         *size = 0;
  394.   
  395.     return (status);
  396.   
  397. }  /** end of emsize **/
  398.   
  399. #endif
  400.   
  401. /*$PAGE*/
  402. /**********************************************************************/
  403. /*                                                                    */
  404. /*     Name:    unsigned int efmalloc (size, token);                  */
  405. /*              unsigned int size;                                    */
  406. /*              unsigned int *token;                                  */
  407. /*                                                                    */
  408. /*     Description:                                                   */
  409. /*        This function is analagous to fmalloc except it allocates a */
  410. /*     block of memory from the expanded memory pool.                 */
  411. /*                                                                    */
  412. /*     Parameters:                                                    */
  413. /*        input    size   The desired size, in bytes, of the block of */
  414. /*                        memory.                                     */
  415. /*        output   token  A tag needed for subsequent calls to the C  */
  416. /*                        Memory Manager to unquiely identify the     */
  417. /*                        block of memory allocated.                  */
  418. /*                                                                    */
  419. /*     Results returned:                                              */
  420. /*        PASSED    Operation successful                              */
  421. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  422. /*                                                                    */
  423. /*     Calling sequence:                                              */
  424. /*     #include "memlib.h"                                            */
  425. /*     #include "errors.h"                                            */
  426. /*         ...                                                        */
  427. /*     unsigned int token;                                            */
  428. /*     unsigned int size;                                             */
  429. /*     unsigned int status                                            */
  430. /*         ...                                                        */
  431. /*     size = 100;                                                    */
  432. /*     status = efmalloc (size, &token);                              */
  433. /*     if (status == PASSED)                                          */
  434. /*        { continue normal code - we have allocated space to }       */
  435. /*        { store 100 byte values                             }       */
  436. /*     else                                                           */
  437. /*        { error condition }                                         */
  438. /*                                                                    */
  439. /*     Calls: allocate_new_block()                                    */
  440. /*            check_best_fit()                                        */
  441. /*            prepare_dir_mapping()                                   */
  442. /*            restore_memlib_context()                                */
  443. /*            split_block()                                           */
  444. /*            map_dir_page()                                          */
  445. /*                                                                    */
  446. /*     Called by:  Application                                        */
  447. /*                                                                    */
  448. /*     Globals reference/modified: directory                          */
  449. /*                                 directory_map                      */
  450. /*                                                                    */
  451. /**********************************************************************/
  452.   
  453. unsigned int efmalloc (size, token)
  454. unsigned int size;
  455. unsigned int *token;
  456.   
  457. {
  458.     unsigned int found_block;       /* memory block found                */
  459.     unsigned int status;            /* Status of EMM and MEMLIB          */
  460.     unsigned int best_indexs_page;  /* best_index's dir entry's log page */
  461.     unsigned int best_indexs_index; /* best_index's index into its page  */
  462.     unsigned int best_index;        /* Index of the current best fit     */
  463.     unsigned int context_saved;     /* whether the context was saved     */
  464.     long         min_difference;    /* Minimum difference - best size    */
  465.   
  466.    /**********************************************/
  467.    /* Attempting to allocate 0 bytes is an error */
  468.    /**********************************************/
  469.   
  470.     if (size > 0)
  471.         status = PASSED;
  472.     else
  473.         status = REQUEST_FOR_ZERO_LENGTH_BLOCK;
  474.   
  475.    /**********************************************/
  476.    /* Call prepare_dir_mapping() to save context */
  477.    /* before mapping in the directory            */
  478.    /**********************************************/
  479.   
  480.     if (status == PASSED)
  481.         status = prepare_dir_mapping (&context_saved);
  482.   
  483.     if (status == PASSED)
  484.     {
  485.       /*************************************/
  486.       /* check to see if there exists a    */
  487.       /* "best size" fit in memory blocks. */
  488.       /*************************************/
  489.   
  490.         status = check_best_fit (size, &best_index, &min_difference);
  491.   
  492.       /********************************************/
  493.       /* If best_index is not an UNASSIGNED_TOKEN */
  494.       /* then we found a block.                   */
  495.       /********************************************/
  496.   
  497.         if ((status == PASSED) &&
  498.             (best_index != UNASSIGNED_TOKEN))
  499.         {
  500.             found_block = TRUE;
  501.   
  502.          /****************************************************/
  503.          /* We're going to use a free block to put our block */
  504.          /* into.  First we need to map in the free block's  */
  505.          /* (best_index) directory entry's logical page.     */
  506.          /****************************************************/
  507.   
  508.          /******************************************************************/
  509.          /* Convert best_index to its respective directory page and index. */
  510.          /******************************************************************/
  511.   
  512.             best_indexs_page  = best_index / DIR_ENTRIES_PER_PAGE;
  513.             best_indexs_index = best_index % DIR_ENTRIES_PER_PAGE;
  514.   
  515.          /***************************************/
  516.          /* Map in best_index's directory page. */
  517.          /***************************************/
  518.   
  519.             status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
  520.   
  521.   
  522.          /********************************************************/
  523.          /* If the size of the best fit that we found was 0 then */
  524.          /* what we found was an unallocated block.  Allocate a  */
  525.          /* a new block.                                         */
  526.          /********************************************************/
  527.   
  528.             if (directory[0][best_indexs_index].size == 0)
  529.                 status = allocate_new_block (size, best_index);
  530.             else
  531.             {
  532.             /******************************************************/
  533.             /* When using a previously allocated block we need to */
  534.             /* check the size and if any space is left over we    */
  535.             /* should make a new available block.                 */
  536.             /******************************************************/
  537.   
  538.                 if ((status == PASSED) &&
  539.                     (min_difference != 0))
  540.                 {
  541.                     status = split_block (best_index, size);
  542.                 }
  543.   
  544.             } /** end else **/
  545.   
  546.         }  /** end if best_index ... **/
  547.   
  548.     }   /** end if passed from prepare_dir_mapping() **/
  549.   
  550.    /********************************************************/
  551.    /* We found a block - set the token value and directory */
  552.    /* entries.  (The directory pointer (offset) is set     */
  553.    /* either in allocate_new_block or was already valid.)  */
  554.    /********************************************************/
  555.     if (status == PASSED)
  556.     {
  557.         if (found_block)
  558.         {
  559.             status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
  560.             if (status == PASSED)
  561.             {
  562.                 *token = best_index;
  563.                 directory[0][best_indexs_index].token = best_index;
  564.                 directory[0][best_indexs_index].size  = size;
  565.             }
  566.         }
  567.         else
  568.         {
  569.             *token = UNASSIGNED_TOKEN;
  570.             if (!found_block)
  571.                 status = TOO_MANY_DIRECTORY_ENTRIES;
  572.         }
  573.     }
  574.   
  575.    /*************************************************************/
  576.    /* Unmap the directory - remap the pages that were in before */
  577.    /*************************************************************/
  578.   
  579.     if (context_saved)
  580.         status = restore_memlib_context (status);
  581.   
  582.     return (status);
  583.   
  584. }  /** end efmalloc **/
  585.   
  586. /*$PAGE*/
  587. /**********************************************************************/
  588. /*                                                                    */
  589. /*     Name:  unsigned int effree (token)                             */
  590. /*            unsigned int token;                                     */
  591. /*                                                                    */
  592. /*     Description:                                                   */
  593. /*        This function frees a block of memory from expanded memory  */
  594. /*     that was allocated by efmalloc().                              */
  595. /*                                                                    */
  596. /*     Parameters:                                                    */
  597. /*        input  token  The token returned by efmalloc when this      */
  598. /*                      block was allocated.                          */
  599. /*                                                                    */
  600. /*     Results returned:                                              */
  601. /*        PASSED    Operation successful                              */
  602. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  603. /*                                                                    */
  604. /*     Calling sequence:                                              */
  605. /*     #include "memlib.h"                                            */
  606. /*     #include "errors.h"                                            */
  607. /*         ...                                                        */
  608. /*     unsigned int token;                                            */
  609. /*     unsigned int status;                                           */
  610. /*         ...                                                        */
  611. /*     status = efmalloc (100, &token);                               */
  612. /*         ...                                                        */
  613. /*     status = efree(token);                                         */
  614. /*     if (status == PASSED)                                          */
  615. /*        { continue normal code }                                    */
  616. /*     else                                                           */
  617. /*        { error condition }                                         */
  618. /*                                                                    */
  619. /*     Calls: check_if_all_blocks_free()                              */
  620. /*            check_token()                                           */
  621. /*            prepare_dir_mapping()                                   */
  622. /*            restore_memlib_context()                                */
  623. /*            search_after()                                          */
  624. /*            search_before()                                         */
  625. /*            map_dir_page()                                          */
  626. /*            effreeall()                                             */
  627. /*                                                                    */
  628. /*     Called by: Application                                         */
  629. /*                                                                    */
  630. /*     Globals referenced/modified: directory                         */
  631. /*                                  dir_start                         */
  632. /*                                                                    */
  633. /**********************************************************************/
  634.   
  635. unsigned int effree (token)
  636. unsigned int token;
  637. {
  638.     unsigned int status;             /* Status of EMM and MEMLIB           */
  639.     unsigned int all_blocks_free;    /* Whether all blocks are free or not */
  640.     unsigned int j;                  /* Looping variable                   */
  641.     unsigned int usable_entry;       /* A usuable directory entry          */
  642.     unsigned int size_mod_page_size; /* Size of a block MOD PAGE_SIZE      */
  643.     unsigned int tokens_index;       /* Token's index into its log page    */
  644.     unsigned int tokens_page;        /* Token's dir entry's logical page   */
  645.     unsigned int usable_entrys_index;/* Usable_entry's index into its page */
  646.     unsigned int usable_entrys_page; /* Usable_entry's dir entry's log page*/
  647.     unsigned int final_entrys_index; /* Final_entry's index into its page  */
  648.     unsigned int final_entrys_page;  /* Final_entry's dir entry's log page */
  649.     unsigned int final_entry;        /* Directory entry of the final       */
  650.                                     /* coalesced block                    */
  651.     unsigned int context_saved;      /* Whether the context was saved      */
  652.   
  653.    /******************************/
  654.    /* Initialize some variables. */
  655.    /******************************/
  656.   
  657.     all_blocks_free = FALSE;
  658.     context_saved   = FALSE;
  659.   
  660.    /******************************/
  661.    /* Check for an invalid token */
  662.    /******************************/
  663.   
  664.     status = check_token (token);
  665.   
  666.    /**********************************************/
  667.    /* Call prepare_dir_mapping() to save context */
  668.    /* before mapping in the directory            */
  669.    /**********************************************/
  670.     if (status == PASSED)
  671.         status = prepare_dir_mapping (&context_saved);
  672.   
  673.     if (status == PASSED)
  674.     {
  675.       /************************************************/
  676.       /* Convert token to its index and logical page. */
  677.       /************************************************/
  678.   
  679.         tokens_index = token % DIR_ENTRIES_PER_PAGE;
  680.         tokens_page  = token / DIR_ENTRIES_PER_PAGE;
  681.   
  682.       /*******************************/
  683.       /* Map in this directory page. */
  684.       /*******************************/
  685.   
  686.         status = map_dir_page (tokens_page, FIRST_PHYS_PAGE);
  687.     }
  688.   
  689.     if (status == PASSED)
  690.     {
  691.       /*************************************************/
  692.       /* If token does not identify an allocated block */
  693.       /* or if its size is zero return an error code.  */
  694.       /*************************************************/
  695.   
  696.         if ((directory[0][tokens_index].token != token) ||
  697.             (directory[0][tokens_index].size == 0))
  698.             status = INVALID_TOKEN;
  699.   
  700.         if (status == PASSED)
  701.         {
  702.          /*******************************************************/
  703.          /* Set token to UNASSIGNED_TOKEN showing freed status. */
  704.          /*******************************************************/
  705.   
  706.             directory[0][tokens_index].token = UNASSIGNED_TOKEN;
  707.   
  708.          /****************************************************/
  709.          /* If this token is less than the current starting  */
  710.          /* location then set the new starting location used */
  711.          /* when searching for free directory entries.       */
  712.          /****************************************************/
  713.   
  714.             if (token < dir_start)
  715.                 dir_start = token;
  716.   
  717.          /**********************************/
  718.          /* Check if all pages are free.   */
  719.          /* If not, try to coalesce blocks */
  720.          /**********************************/
  721.   
  722.             status = check_if_all_blocks_free (&all_blocks_free);
  723.         }
  724.         if ((status == PASSED) &&
  725.             (all_blocks_free))
  726.         {
  727.          /*****************************************/
  728.          /* We need to restore the context before */
  729.          /* the pages and handles.                */
  730.          /*****************************************/
  731.   
  732.             if (context_saved)
  733.                 status = restore_memlib_context (status);
  734.   
  735.             if (status == PASSED)
  736.             {
  737.                 context_saved = FALSE;
  738.                 status = effreeall();
  739.             }
  740.         }
  741.         else if ((status == PASSED) &&
  742.             (!all_blocks_free))
  743.         {
  744.          /*****************************************************/
  745.          /* Search for a free block of memory after this free */
  746.          /* block to coalesce into one free block.  This      */
  747.          /* makes sure that if there are a number of little   */
  748.          /* blocks that could actually be put together into   */
  749.          /* one large block that we do so.                    */
  750.          /*****************************************************/
  751.   
  752.             status = search_after (token, &final_entry, &usable_entry);
  753.   
  754.          /*******************************************************/
  755.          /* Search for a free block of memory before this block */
  756.          /* to coalesce into one free block.                    */
  757.          /*******************************************************/
  758.   
  759.             if (status == PASSED)
  760.                 status = search_before (token, &final_entry, &usable_entry);
  761.   
  762.          /**************************************************/
  763.          /* Test to see if we coalesced any blocks.  If so */
  764.          /* we need to check that the coalesced block does */
  765.          /* not overlap too many logical pages.            */
  766.          /**************************************************/
  767.   
  768.             if ((status == PASSED) &&
  769.                 (final_entry != UNASSIGNED_TOKEN))
  770.             {
  771.             /*****************************************/
  772.             /* Convert final_entry to its respective */
  773.             /* directory page and index.             */
  774.             /*****************************************/
  775.   
  776.                 final_entrys_page  = final_entry / DIR_ENTRIES_PER_PAGE;
  777.                 final_entrys_index = final_entry % DIR_ENTRIES_PER_PAGE;
  778.   
  779.             /****************************************/
  780.             /* Map in final_entry's directory page. */
  781.             /****************************************/
  782.   
  783.                 status = map_dir_page (final_entrys_page, FIRST_PHYS_PAGE);
  784.                 if (status == PASSED)
  785.                 {
  786.                /*******************************************************/
  787.                /* We can't have a block taking up more logical pages  */
  788.                /* than it needs.  We always guarantee that a block of */
  789.                /* memory take the least amount of logical pages as    */
  790.                /* possible.  If it overlaps too many blocks we need   */
  791.                /* to break it up.  Check the block final_index for    */
  792.                /* too much overlap.                                   */
  793.                /*******************************************************/
  794.   
  795.                     size_mod_page_size =
  796.                     directory[0][final_entrys_index].size % PAGE_SIZE;
  797.                     if (size_mod_page_size == 0)
  798.                         size_mod_page_size = PAGE_SIZE;
  799.   
  800.                     if ((PAGE_SIZE - directory[0][final_entrys_index].offset) <
  801.                         size_mod_page_size)
  802.   
  803.                     {
  804.                   /*********************************************************/
  805.                   /* Convert usable_block to its respective directory page */
  806.                   /* and index.  We're going to map this page into the     */
  807.                   /* second physical page.                                 */
  808.                   /*********************************************************/
  809.   
  810.                         usable_entrys_page  = usable_entry / DIR_ENTRIES_PER_PAGE;
  811.                         usable_entrys_index = usable_entry % DIR_ENTRIES_PER_PAGE;
  812.   
  813.                   /****************************************************/
  814.                   /* Map in usable_block's directory page using the   */
  815.                   /* directory_map's second array element to map this */
  816.                   /* page in at physical page one while keeping the   */
  817.                   /* block that was coalesced's directory page at     */
  818.                   /* physical page zero.                              */
  819.                   /***************************************************/
  820.   
  821.                         status = map_dir_page (usable_entrys_page, SECOND_PHYS_PAGE);
  822.   
  823.                   /*************************************************/
  824.                   /* This block overlaps too many logical pages.   */
  825.                   /* We need to break it into two pieces at a      */
  826.                   /* a logical page boundry.  Use the usable_block */
  827.                   /* set when coalescing.                          */
  828.                   /*************************************************/
  829.   
  830.                         if (status == PASSED)
  831.                         {
  832.                      /*************************************************/
  833.                      /* Set the second block's (usable_entry) size to */
  834.                      /* the size of the first piece after the first   */
  835.                      /* page boundry of the whole block.              */
  836.                      /*************************************************/
  837.   
  838.                             directory[1][usable_entrys_index].size =
  839.                             directory[0][final_entrys_index].size -
  840.                             PAGE_SIZE + directory[0][final_entrys_index].offset;
  841.   
  842.                      /**************************************/
  843.                      /* Set the offset of the second block */
  844.                      /* to start at the page boundry.      */
  845.                      /**************************************/
  846.   
  847.                             directory[1][usable_entrys_index].offset = 0;
  848.   
  849.                      /***********************************************/
  850.                      /* Set the logical pages for the second block. */
  851.                      /***********************************************/
  852.   
  853.                             for (j = 0; j < NUM_PAGES (directory[1][usable_entrys_index].size); j++)
  854.                             {
  855.                                 directory[1][usable_entrys_index].logical_page[j] =
  856.                                 directory[0][final_entrys_index].logical_page[j + 1];
  857.                             }
  858.   
  859.                      /***********************************************/
  860.                      /* Set the first block size to the amount of   */
  861.                      /* memory before the logical page boundry (the */
  862.                      /* space before the second block).             */
  863.                      /***********************************************/
  864.   
  865.                             directory[0][final_entrys_index].size -=
  866.                             directory[1][usable_entrys_index].size;
  867.                         }
  868.   
  869.                     } /** end if PAGE_SIZE ... **/
  870.   
  871.                 } /** status passed **/
  872.   
  873.             } /** end if final_index ... **/
  874.   
  875.         } /** end if check_of_all_blocks_free **/
  876.   
  877.     } /** end if status passed **/
  878.   
  879.    /*************************************************************/
  880.    /* Unmap the directory - remap the pages that were in before */
  881.    /*************************************************************/
  882.   
  883.     if ((!all_blocks_free) &&
  884.         (context_saved))
  885.         status = restore_memlib_context (status);
  886.   
  887.     return (status);
  888.   
  889. } /** end effree **/
  890.   
  891. /*$PAGE*/
  892. /**********************************************************************/
  893. /*                                                                    */
  894. /*     Name:  unsigned int seteptrs (num_blocks, token, pointer)      */
  895. /*            unsigned int num_blocks;                                */
  896. /*            unsigned int token[];                                   */
  897. /*            void far*    pointer[];                                 */
  898. /*                                                                    */
  899. /*     Description:                                                   */
  900. /*        Attempts to map all the pages required by the block(s) of   */
  901. /*     memory identified by token[].  Returns pointers to each block  */
  902. /*     that has been mapped in.  If the requested block(s) could not  */
  903. /*     mapped in then we return an error.                             */
  904. /*                                                                    */
  905. /*     Parameters:                                                    */
  906. /*        input  num_blocks          Number of blocks to get access   */
  907. /*                                   to.                              */
  908. /*        input  token[num_blocks]   An array of tokens that identify */
  909. /*                                   the blocks to be mapped in. (The */
  910. /*                                   tokens returned by efmalloc when */
  911. /*                                   the block(s) were allocated.)    */
  912. /*        output pointer[num_blocks] An array of far pointers returned*/
  913. /*                                   to the application.  Pointer[i]  */
  914. /*                                   will point to the block of       */
  915. /*                                   memory identified by token[i].   */
  916. /*                                                                    */
  917. /*     Results returned:                                              */
  918. /*        PASSED    Operation successful                              */
  919. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  920. /*                                                                    */
  921. /*     Calling sequence:                                              */
  922. /*     #include "memlib.h"                                            */
  923. /*     #include "errors.h"                                            */
  924. /*         ...                                                        */
  925. /*     void far*    pointers[2];                                      */
  926. /*     unsigned int tokens[2];                                        */
  927. /*     unsigned int status;                                           */
  928. /*         ...                                                        */
  929. /*     status = efmalloc (200, &token[0]);                            */
  930. /*     if (status != PASSED)                                          */
  931. /*        { error condition }                                         */
  932. /*     else                                                           */
  933. /*        { continue normal code }                                    */
  934. /*         ...                                                        */
  935. /*     status = efmalloc (600, &token[1]);                            */
  936. /*     if (status != PASSED)                                          */
  937. /*        { error condition }                                         */
  938. /*     else                                                           */
  939. /*        { continue normal code }                                    */
  940. /*         ...                                                        */
  941. /*     status = seteptrs (2, tokens, pointers)                        */
  942. /*     if (status == PASSED)                                          */
  943. /*       { blocks mapped in - use pointers to reference them }        */
  944. /*     else                                                           */
  945. /*       { error - a token was bad or not all blocks could fit }      */
  946. /*                                                                    */
  947. /*     Calls: map_dir_page()                                          */
  948. /*            map_unmap_pages()                                       */
  949. /*                                                                    */
  950. /*     Called by: Application                                         */
  951. /*                set1eptr()                                          */
  952. /*                set2eptrs()                                         */
  953. /*                set3eptrs()                                         */
  954. /*                                                                    */
  955. /*     Globals referenced/modified: directory                         */
  956. /*                                  app_handle                        */
  957. /*                                  directory_map                     */
  958. /*                                  num_pages_in_page_frame           */
  959. /*                                  number_pages_mapped               */
  960. /*                                  page_frame_base_address           */
  961. /*                                  pages_mapped                      */
  962. /*                                                                    */
  963. /**********************************************************************/
  964.   
  965. unsigned int seteptrs (num_blocks, token, pointer)
  966. unsigned int num_blocks;
  967. unsigned int token[];
  968. void far*    pointer[];
  969. {
  970.     unsigned int status;             /* Status of EMM & MEMLIB               */
  971.     unsigned int i;                  /* looping variable                     */
  972.     unsigned int j;                  /* looping variable                     */
  973.     unsigned int start_phys_page;    /* Starting physical page in page frame */
  974.     unsigned int log_page_match;     /* Match was found? TRUE/FALSE          */
  975.     unsigned int log_page;           /* temporarily store log page we're on  */
  976.     unsigned int current_dir_page;   /* The current directory page mapped in */
  977.     unsigned int tokens_page;        /* Token's dir entry's logical page     */
  978.     unsigned int tokens_index;       /* Token's index into its logical page  */
  979.     unsigned int num_pages_for_token;/* Number of logical pages for token's  */
  980.                                     /* block                                */
  981.     void far*    tokens_ptr;         /* pointer to token's block             */
  982.   
  983.    /*******************************/
  984.    /* Initialize local variables. */
  985.    /*******************************/
  986.   
  987.     status = PASSED;
  988.     current_dir_page = UNMAPPED;
  989.   
  990.    /***************************************/
  991.    /* Make sure all the tokens are valid. */
  992.    /***************************************/
  993.   
  994.     for (i = 0; ((status == PASSED) &&
  995.         (i < num_blocks)); i++)
  996.     {
  997.         status = check_token (token[i]);
  998.     }
  999.   
  1000.     if (status == PASSED)
  1001.     {
  1002.       /*******************************************************/
  1003.       /* Set each page in the page frame to UNMAPPED status. */
  1004.       /*******************************************************/
  1005.   
  1006.         for (i = 0; i < num_pages_in_page_frame; i++)
  1007.             pages_mapped[i].log_page = UNMAPPED;
  1008.   
  1009.         number_pages_mapped = 0;
  1010.   
  1011.       /***********************************************/
  1012.       /* For each block requested, try to map it in. */
  1013.       /***********************************************/
  1014.   
  1015.         for (i = 0; ((status == PASSED) &&
  1016.             (i < num_blocks)); i++)
  1017.         {
  1018.             tokens_page  = token[i] / DIR_ENTRIES_PER_PAGE;
  1019.             tokens_index = token[i] % DIR_ENTRIES_PER_PAGE;
  1020.   
  1021.             if (tokens_page != current_dir_page)
  1022.             {
  1023.                 current_dir_page = tokens_page;
  1024.                 status = map_dir_page (current_dir_page, FIRST_PHYS_PAGE);
  1025.             }
  1026.   
  1027.             if ((status == PASSED) &&
  1028.                 (token[i] != directory[0][tokens_index].token))
  1029.                 status = INVALID_TOKEN;
  1030.   
  1031.             if (status == PASSED)
  1032.             {
  1033.             /*********************************/
  1034.             /* Initialize variable for loop. */
  1035.             /*********************************/
  1036.   
  1037.                 start_phys_page      = 0;
  1038.                 log_page_match       = FALSE;
  1039.                 num_pages_for_token  = NUM_PAGES (directory[0][tokens_index].size);
  1040.   
  1041.             /***********************************************************/
  1042.             /* While there's potentially room to map the logical pages */
  1043.             /* need for the i'th block and it isn't already mapped in. */
  1044.             /***********************************************************/
  1045.   
  1046.                 while (((start_phys_page + num_pages_for_token)
  1047.                     <= num_pages_in_page_frame)
  1048.                     && (!log_page_match))
  1049.                 {
  1050.                /*****************************************/
  1051.                /* Assume the logical pages need for the */
  1052.                /* i'th block are already mapped in.     */
  1053.                /*****************************************/
  1054.   
  1055.                     log_page_match = TRUE;
  1056.   
  1057.                /**************************************************/
  1058.                /* Test each of the logical pages in the i'th     */
  1059.                /* block against the logical pages already mapped */
  1060.                /* in the page frame starting at start_phys_page. */
  1061.                /**************************************************/
  1062.   
  1063.                     for (j = 0; (j < num_pages_for_token); j++)
  1064.                     {
  1065.                         log_page = directory[0][tokens_index].logical_page[j];
  1066.   
  1067.                   /**********************************************/
  1068.                   /* We won't have a match if the logical page  */
  1069.                   /* we're looking for is not already mapped in */
  1070.                   /* and if the page is unmapped.               */
  1071.                   /**********************************************/
  1072.   
  1073.                         if ((log_page != pages_mapped[start_phys_page + j].log_page) &&
  1074.                             (pages_mapped[start_phys_page + j].log_page != UNMAPPED))
  1075.                             log_page_match = FALSE;
  1076.                     }
  1077.                /*************************************************/
  1078.                /* If the i'th block isn't mapped in (starting   */
  1079.                /* at start_phys_page) increment start_phys_page */
  1080.                /* and try again.                                */
  1081.                /*************************************************/
  1082.   
  1083.                     if (!log_page_match)
  1084.                         start_phys_page++;
  1085.   
  1086.                 }  /** end while **/
  1087.   
  1088.             /**************************************************/
  1089.             /* If a match was found set pages_mapped array to */
  1090.             /* include the logical pages for this block.  If  */
  1091.             /* no match was found we can't map this block     */
  1092.             /**************************************************/
  1093.   
  1094.                 if (log_page_match)
  1095.                 {
  1096.                     for (j = 0; (j < num_pages_for_token); j++)
  1097.                     {
  1098.                         pages_mapped[start_phys_page + j].log_page =
  1099.                         directory[0][tokens_index].logical_page[j];
  1100.   
  1101.                   /*************************************************/
  1102.                   /* Update pointer[i] to point to the i'th block. */
  1103.                   /* The offset of the pointer we return is equal  */
  1104.                   /* to the offset of this block within the first  */
  1105.                   /* logical page for this block.  These pointers  */
  1106.                   /* are only good modulus 16K since, for example, */
  1107.                   /* we could have allocated a block when it was   */
  1108.                   /* mapped in at phys page 0 and now want to map  */
  1109.                   /* it in at phys page 3 or some such.            */
  1110.                   /*************************************************/
  1111.   
  1112.                         FP_OFF (tokens_ptr) = directory[0][tokens_index].offset;
  1113.                         FP_SEG (tokens_ptr) = FP_SEG(page_frame_base_address) +
  1114.                         start_phys_page * OFFSET_SIZE;
  1115.                         pointer[i]          = tokens_ptr;
  1116.                     }
  1117.                 }
  1118.                 else
  1119.                     status = CANNOT_MAP_ALL_BLOCKS;
  1120.   
  1121.             } /** if status PASSED **/
  1122.   
  1123.         }  /** end for i **/
  1124.   
  1125.     }  /** end if status PASSED **/
  1126.   
  1127.    /*************************************************************/
  1128.    /* Unmap the directory - remap the pages that were in before */
  1129.    /*************************************************************/
  1130.   
  1131.     if (status == PASSED)
  1132.     {
  1133.       /*************************************/
  1134.       /* Count the number of pages to map. */
  1135.       /*************************************/
  1136.   
  1137.         number_pages_mapped = 0;
  1138.         for (i = 0; i < num_pages_in_page_frame; i++)
  1139.         {
  1140.             if (pages_mapped[i].log_page != UNMAPPED)
  1141.                 number_pages_mapped++;
  1142.         }
  1143.       /************************************/
  1144.       /* Map in all the blocks requested. */
  1145.       /************************************/
  1146.   
  1147.         status = map_unmap_pages (PHYS_PAGE_MODE, number_pages_mapped,
  1148.         pages_mapped, app_handle);
  1149.     }
  1150.     return(status);
  1151.   
  1152. } /** end seteptrs **/
  1153.   
  1154. /*$PAGE*/
  1155. /**********************************************************************/
  1156. /*                                                                    */
  1157. /*     Name:  unsigned int set1eptr (token, pointer)                  */
  1158. /*            unsigned int token;                                     */
  1159. /*            void far*    *pointer;                                  */
  1160. /*                                                                    */
  1161. /*     Description:                                                   */
  1162. /*        Convenience routine that calls seteptrs to just get access  */
  1163. /*     to one block.                                                  */
  1164. /*                                                                    */
  1165. /*     Parms Passed:                                                  */
  1166. /*        input  token     A token that identifies the block to be    */
  1167. /*                         mapped in. (The token returned by efmalloc */
  1168. /*                         when the block was allocated.)             */
  1169. /*        output pointer   A far pointer returned to the application. */
  1170. /*                         It will point to the block of memory       */
  1171. /*                         identified by token.                       */
  1172. /*                                                                    */
  1173. /*     Results returned:                                              */
  1174. /*        PASSED     Operation successful                             */
  1175. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1176. /*                                                                    */
  1177. /*     Calling sequence:                                              */
  1178. /*     #include "memlib.h"                                            */
  1179. /*     #include "errors.h"                                            */
  1180. /*         ...                                                        */
  1181. /*     void far*     pointer;                                         */
  1182. /*     unsigned int  token;                                           */
  1183. /*     unsigned int  status;                                          */
  1184. /*         ...                                                        */
  1185. /*     status = efmalloc (500, &token);                               */
  1186. /*     if (status != PASSED)                                          */
  1187. /*        { error condition }                                         */
  1188. /*     else                                                           */
  1189. /*        { continue normal code }                                    */
  1190. /*         ...                                                        */
  1191. /*     status = set1eptr(token, &pointer)                             */
  1192. /*     if (status == PASSED)                                          */
  1193. /*       { block mapped in - use pointer to reference it }            */
  1194. /*     else                                                           */
  1195. /*       { error - the token was invalid }                            */
  1196. /*                                                                    */
  1197. /*     Calls: seteptrs()                                              */
  1198. /*                                                                    */
  1199. /*     Called by: Application                                         */
  1200. /*                                                                    */
  1201. /*     Globals referenced/modified: None                              */
  1202. /*                                                                    */
  1203. /**********************************************************************/
  1204.   
  1205. unsigned int set1eptr (token, pointer)
  1206. unsigned int token;
  1207. void far*    *pointer;
  1208. {
  1209.     unsigned int tokens[1];     /* Set one array entry to pass to   */
  1210.                                /* seteptrs()                       */
  1211.     void far*    pointers[1];   /* Set one array entry to be passed */
  1212.                                /* back from seteptrs()             */
  1213.     unsigned int status;        /* Status of EMM and MEMLIB         */
  1214.   
  1215.     tokens[0] = token;
  1216.   
  1217.    /**************************************************/
  1218.    /* Call seteptrs() to map in the block identified */
  1219.    /* by token and return it pointer.                */
  1220.    /**************************************************/
  1221.   
  1222.     status = seteptrs (1, tokens, pointers);
  1223.   
  1224.     if (status == PASSED)
  1225.         *pointer = pointers[0];
  1226.   
  1227.     return (status);
  1228.   
  1229. }  /** end set1eptr **/
  1230.   
  1231.   
  1232. #ifdef notdef
  1233.   
  1234. /*$PAGE*/
  1235. /**********************************************************************/
  1236. /*                                                                    */
  1237. /*     Name:  unsigned int set2eptrs (token1, token2, pointer1,       */
  1238. /*                                      pointer2)                     */
  1239. /*            unsigned int token1;                                    */
  1240. /*            unsigned int token2;                                    */
  1241. /*            void far*    *pointer1;                                 */
  1242. /*            void far*    *pointer2;                                 */
  1243. /*                                                                    */
  1244. /*     Description:                                                   */
  1245. /*        Convenience routine that calls seteptrs to get access to    */
  1246. /*     two different blocks of memory at one time.                    */
  1247. /*                                                                    */
  1248. /*     Parameters:                                                    */
  1249. /*        input  token1    A token that identifies the first block to */
  1250. /*                         be mapped in. (The token returned by       */
  1251. /*                         efmalloc when the block was allocated.)    */
  1252. /*        input  token2    A token that identifies the second block   */
  1253. /*                         to be mapped in. (The token returned by    */
  1254. /*                         efmalloc when the block was allocated.)    */
  1255. /*        output pointer1  A far pointer returned to the application. */
  1256. /*                         It will point to the block of memory       */
  1257. /*                         identified by token1.                      */
  1258. /*        output pointer2  A far pointer returned to the application. */
  1259. /*                         It will point to the block of memory       */
  1260. /*                         identified by token2.                      */
  1261. /*                                                                    */
  1262. /*     Results returned:                                              */
  1263. /*        PASSED    Operation successful                              */
  1264. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1265. /*                                                                    */
  1266. /*     Calling sequence:                                              */
  1267. /*     #include "memlib.h"                                            */
  1268. /*     #include "errors.h"                                            */
  1269. /*         ...                                                        */
  1270. /*     void far*    ptr1;                                             */
  1271. /*     void far*    ptr2;                                             */
  1272. /*     unsigned int token1;                                           */
  1273. /*     unsigned int token2;                                           */
  1274. /*     unsigned int status;                                           */
  1275. /*         ...                                                        */
  1276. /*     status = efmalloc (500, &token1);                              */
  1277. /*     if (status != PASSED)                                          */
  1278. /*        { error condition }                                         */
  1279. /*     else                                                           */
  1280. /*        { continue normal code }                                    */
  1281. /*         ...                                                        */
  1282. /*     status = efmalloc (900, &token2);                              */
  1283. /*     if (status != PASSED)                                          */
  1284. /*        { error condition }                                         */
  1285. /*     else                                                           */
  1286. /*        { continue normal code }                                    */
  1287. /*         ...                                                        */
  1288. /*     status = set2eptrs (token1, token2, &ptr1, &ptr2);             */
  1289. /*     if (status == PASSED)                                          */
  1290. /*       { blocks mapped in - use pointers to reference them }        */
  1291. /*     else                                                           */
  1292. /*       { error - a token was invalid or blocks couldn't fit }       */
  1293. /*                                                                    */
  1294. /*     Calls: seteptrs()                                              */
  1295. /*                                                                    */
  1296. /*     Called by: Application                                         */
  1297. /*                                                                    */
  1298. /*     Globals referenced/modified: None                              */
  1299. /*                                                                    */
  1300. /**********************************************************************/
  1301.   
  1302. unsigned int set2eptrs (token1, token2, pointer1, pointer2)
  1303. unsigned int token1;
  1304. unsigned int token2;
  1305. void far*    *pointer1;
  1306. void far*    *pointer2;
  1307. {
  1308.     unsigned int tokens[2];      /* Set two array entries to pass to   */
  1309.                                 /* seteptrs()                         */
  1310.     void far*    pointers[2];    /* Set two array entries to be passed */
  1311.                                 /* back from seteptrs()               */
  1312.     unsigned int status;         /* Status of EMM and MEMLIB           */
  1313.   
  1314.     tokens[0] = token1;
  1315.     tokens[1] = token2;
  1316.   
  1317.    /***************************************************/
  1318.    /* Call seteptrs() to map in the blocks identified */
  1319.    /* by token1 and token2 and return their pointers. */
  1320.    /***************************************************/
  1321.   
  1322.     status = seteptrs (2, tokens, pointers);
  1323.   
  1324.     if (status == PASSED)
  1325.     {
  1326.         *pointer1 = pointers[0];
  1327.         *pointer2 = pointers[1];
  1328.     }
  1329.   
  1330.     return (status);
  1331.   
  1332. }  /** end set2eptrs **/
  1333.   
  1334. /*$PAGE*/
  1335. /**********************************************************************/
  1336. /*                                                                    */
  1337. /*     Name:  unsigned int set3eptrs (token1, token2, token3,         */
  1338. /*                                      pointer1, pointer2, pointer3) */
  1339. /*            unsigned int token1;                                    */
  1340. /*            unsigned int token2;                                    */
  1341. /*            unsigned int token3;                                    */
  1342. /*            void far*    *pointer1;                                 */
  1343. /*            void far*    *pointer2;                                 */
  1344. /*            void far*    *pointer3;                                 */
  1345. /*                                                                    */
  1346. /*     Description:                                                   */
  1347. /*        Convenience routine that calls seteptrs to get access to    */
  1348. /*     three different blocks of memory at one time.                  */
  1349. /*                                                                    */
  1350. /*     Parameters:                                                    */
  1351. /*        input  token1    A token that identifies the first block to */
  1352. /*                         be mapped in. (The token returned by       */
  1353. /*                         efmalloc when the block was allocated.)    */
  1354. /*        input  token2    A token that identifies the second block   */
  1355. /*                         to be mapped in. (The token returned by    */
  1356. /*                         efmalloc when the block was allocated.)    */
  1357. /*        input  token3    A token that identifies the third block to */
  1358. /*                         be mapped in. (The token returned by       */
  1359. /*                         efmalloc when the block was allocated.)    */
  1360. /*        output pointer1  A far pointer returned to the application. */
  1361. /*                         It will point to the block of memory       */
  1362. /*                         identified by token1.                      */
  1363. /*        output pointer2  A far pointer returned to the application. */
  1364. /*                         It will point to the block of memory       */
  1365. /*                         identified by token2.                      */
  1366. /*        output pointer3  A far pointer returned to the application. */
  1367. /*                         It will point to the block of memory       */
  1368. /*                         identified by token3.                      */
  1369. /*                                                                    */
  1370. /*     Results returned:                                              */
  1371. /*        PASSED    Operation successful                              */
  1372. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1373. /*                                                                    */
  1374. /*                                                                    */
  1375. /*     Calling sequence:                                              */
  1376. /*     #include "memlib.h"                                            */
  1377. /*     #include "errors.h"                                            */
  1378. /*         ...                                                        */
  1379. /*     void far*    ptr1;                                             */
  1380. /*     void far*    ptr2;                                             */
  1381. /*     void far*    ptr3;                                             */
  1382. /*     unsigned int tok1;                                             */
  1383. /*     unsigned int tok2;                                             */
  1384. /*     unsigned int tok3;                                             */
  1385. /*     unsigned int status;                                           */
  1386. /*         ...                                                        */
  1387. /*     status = efmalloc (500, &tok1);                                */
  1388. /*     if (status != PASSED)                                          */
  1389. /*        { error condition }                                         */
  1390. /*     else                                                           */
  1391. /*        { continue normal code }                                    */
  1392. /*         ...                                                        */
  1393. /*     status = efmalloc (900, &tok2);                                */
  1394. /*     if (status != PASSED)                                          */
  1395. /*        { error condition }                                         */
  1396. /*     else                                                           */
  1397. /*        { continue normal code }                                    */
  1398. /*         ...                                                        */
  1399. /*     status = efmalloc (300, &tok3);                                */
  1400. /*     if (status != PASSED)                                          */
  1401. /*        { error condition }                                         */
  1402. /*     else                                                           */
  1403. /*        { continue normal code }                                    */
  1404. /*         ...                                                        */
  1405. /*     status = set3eptrs (tok1, tok2, tok3, &ptr1, &ptr2, &ptr3);    */
  1406. /*     if (status == PASSED)                                          */
  1407. /*       { blocks mapped in - use pointers to reference them }        */
  1408. /*     else                                                           */
  1409. /*       { error - a token was invalid or blocks couldn't fit }       */
  1410. /*                                                                    */
  1411. /*     Calls: seteptrs()                                              */
  1412. /*                                                                    */
  1413. /*     Called by: Application                                         */
  1414. /*                                                                    */
  1415. /*     Globals referenced/modified: None                              */
  1416. /*                                                                    */
  1417. /**********************************************************************/
  1418.   
  1419. unsigned int set3eptrs (token1, token2, token3, pointer1, pointer2,
  1420. pointer3)
  1421. unsigned int token1;
  1422. unsigned int token2;
  1423. unsigned int token3;
  1424. void far*    *pointer1;
  1425. void far*    *pointer2;
  1426. void far*    *pointer3;
  1427. {
  1428.     unsigned int tokens[3];      /* Set three array entries to pass */
  1429.                                 /* seteptrs()                      */
  1430.     void far*    pointers[3];    /* Set three array entries to be   */
  1431.                                 /* passed back from seteptrs()     */
  1432.     unsigned int status;         /* Status of EMM and MEMLIB        */
  1433.   
  1434.     tokens[0] = token1;
  1435.     tokens[1] = token2;
  1436.     tokens[2] = token3;
  1437.   
  1438.    /*********************************************************/
  1439.    /* Call seteptrs() to map in the blocks identified by    */
  1440.    /* token1, token2, and token3 and return their pointers. */
  1441.    /*********************************************************/
  1442.   
  1443.     status = seteptrs (3, tokens, pointers);
  1444.   
  1445.     if (status == PASSED)
  1446.     {
  1447.         *pointer1 = pointers[0];
  1448.         *pointer2 = pointers[1];
  1449.         *pointer3 = pointers[2];
  1450.     }
  1451.     return (status);
  1452.   
  1453. }  /** end set3eptrs **/
  1454.   
  1455. /*$PAGE*/
  1456. /**********************************************************************/
  1457. /*                                                                    */
  1458. /*     Name:  unsigned int push_context (void)                        */
  1459. /*                                                                    */
  1460. /*     Description:                                                   */
  1461. /*        Pushes the current mapping context onto an internal stack.  */
  1462. /*     The routine pop_context() can be used to restore the context   */
  1463. /*     saved by this routine.  Note that for each push we do we must  */
  1464. /*     do a pop.                                                      */
  1465. /*                                                                    */
  1466. /*     Parameters: None                                               */
  1467. /*                                                                    */
  1468. /*     Results returned:                                              */
  1469. /*        PASSED    Operation successful                              */
  1470. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1471. /*                                                                    */
  1472. /*     Calling sequence:                                              */
  1473. /*     #include "memlib.h"                                            */
  1474. /*     #include "errors.h"                                            */
  1475. /*      ...                                                           */
  1476. /*     unsigned int status;                                           */
  1477. /*      ...                                                           */
  1478. /*     status = push_context();                                       */
  1479. /*     if (status == PASSED)                                          */
  1480. /*         { continue normal code }                                   */
  1481. /*     else                                                           */
  1482. /*         { error condition }                                        */
  1483. /*                                                                    */
  1484. /*     Calls: get_partial_context()                                   */
  1485. /*            init_exp_mem()                                          */
  1486. /*                                                                    */
  1487. /*     Called by: Application                                         */
  1488. /*                                                                    */
  1489. /*     Globals referenced/modified: context_ptrs                      */
  1490. /*                                  context_size                      */
  1491. /*                                  exp_initialized                   */
  1492. /*                                  partial_page_map                  */
  1493. /*                                  context_top                       */
  1494. /*                                                                    */
  1495. /**********************************************************************/
  1496.   
  1497. unsigned int push_context (void)
  1498. {
  1499.     unsigned int status;         /* The status of EMM and MELIB */
  1500.   
  1501.    /**************************/
  1502.    /* Assume this will pass. */
  1503.    /**************************/
  1504.   
  1505.     status = PASSED;
  1506.   
  1507.    /*************************************************************/
  1508.    /* Initialize expanded memory if we haven't already done so. */
  1509.    /*************************************************************/
  1510.   
  1511.     if (!exp_initialized)
  1512.         status = init_exp_mem();
  1513.   
  1514.     if (status == PASSED)
  1515.     {
  1516.       /**************************************/
  1517.       /* Increment our variable for keeping */
  1518.       /* track of top of our context stack. */
  1519.       /**************************************/
  1520.   
  1521.         context_top++;
  1522.   
  1523.       /***********************************************************/
  1524.       /* We have an array of pointers that keep track of the     */
  1525.       /* saved context.  Make sure we stay with our array limit. */
  1526.       /***********************************************************/
  1527.   
  1528.         if (context_top < MAX_CONTEXTS_AVAILABLE)
  1529.         {
  1530.          /***************************************************************/
  1531.          /* Allocate space in conventional memory to save this context. */
  1532.          /* Then call get_partial_page_map to do the actual save.       */
  1533.          /***************************************************************/
  1534.   
  1535.             context_ptrs[context_top] = (CONTEXT_STRUCT *) malloc (context_size);
  1536.   
  1537.          /*************************************************/
  1538.          /* Make sure we have enough conventional memory. */
  1539.          /*************************************************/
  1540.   
  1541.             if (context_ptrs[context_top] == NULL)
  1542.                 status = MALLOC_FAILURE;
  1543.             else
  1544.                 status = get_partial_context (&partial_page_map,
  1545.                 context_ptrs[context_top]);
  1546.         }
  1547.         else
  1548.             status = MAX_PUSH_CONTEXTS_EXCEEDED;
  1549.   
  1550.       /*************************************************/
  1551.       /* If status failed, reset top of context stack. */
  1552.       /*************************************************/
  1553.   
  1554.         if (status != PASSED)
  1555.             context_top--;
  1556.     }
  1557.   
  1558.     return (status);
  1559.   
  1560. } /** end push_context **/
  1561.   
  1562. /*$PAGE*/
  1563. /**********************************************************************/
  1564. /*                                                                    */
  1565. /*     Name:  unsigned int pop_context (void)                         */
  1566. /*                                                                    */
  1567. /*     Description:                                                   */
  1568. /*        Pops the last context saved by a call to push_context().    */
  1569. /*     Note that for each push we do we must do a pop.                */
  1570. /*                                                                    */
  1571. /*     Parameters: None                                               */
  1572. /*                                                                    */
  1573. /*     Results returned:                                              */
  1574. /*        PASSED    Operation successful                              */
  1575. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1576. /*                                                                    */
  1577. /*     Calling sequence:                                              */
  1578. /*     #include "memlib.h"                                            */
  1579. /*     #include "errors.h"                                            */
  1580. /*      ...                                                           */
  1581. /*     unsigned int status;                                           */
  1582. /*      ...                                                           */
  1583. /*     status = pop_context();                                        */
  1584. /*     if (status == PASSED)                                          */
  1585. /*         { continue normal code }                                   */
  1586. /*     else                                                           */
  1587. /*         { error condition }                                        */
  1588. /*                                                                    */
  1589. /*     Calls: set_partial_context()                                   */
  1590. /*            init_exp_mem()                                          */
  1591. /*                                                                    */
  1592. /*     Called by: Application                                         */
  1593. /*                                                                    */
  1594. /*     Globals referenced/modified: context_ptrs                      */
  1595. /*                                  exp_initialized                   */
  1596. /*                                  context_top                       */
  1597. /*                                                                    */
  1598. /**********************************************************************/
  1599.   
  1600. unsigned int pop_context (void)
  1601. {
  1602.     unsigned int status;         /* The status of EMM and MEMLIB) */
  1603.   
  1604.    /**************************/
  1605.    /* Assume this will pass. */
  1606.    /**************************/
  1607.   
  1608.     status = PASSED;
  1609.   
  1610.    /*************************************************************/
  1611.    /* Initialize expanded memory if we haven't already done so. */
  1612.    /*************************************************************/
  1613.   
  1614.     if (!exp_initialized)
  1615.         status = init_exp_mem();
  1616.   
  1617.     if (status == PASSED)
  1618.     {
  1619.       /********************************************/
  1620.       /* Make sure there is a context to restore. */
  1621.       /********************************************/
  1622.   
  1623.         if (context_top != NO_CONTEXTS)
  1624.         {
  1625.          /*********************************************************/
  1626.          /* Save the context using set_partial_context(), storing */
  1627.          /* the information an our stack (context_ptrs array).    */
  1628.          /*********************************************************/
  1629.   
  1630.             status = set_partial_context (context_ptrs[context_top]);
  1631.             if (status == PASSED)
  1632.   
  1633.             /**************************************************************/
  1634.             /* Free the conventional memory we used to save this context. */
  1635.             /**************************************************************/
  1636.   
  1637.                 free (context_ptrs[context_top]);
  1638.         }
  1639.         else
  1640.             status = NO_CONTEXT_AVAILABLE_TO_POP;
  1641.   
  1642.       /**********************************************/
  1643.       /* If status passed, decrement stack pointer. */
  1644.       /**********************************************/
  1645.   
  1646.         if (status == PASSED)
  1647.             if (context_top > 0)
  1648.                 context_top--;
  1649.             else
  1650.                 context_top = NO_CONTEXTS;
  1651.     }
  1652.   
  1653.     return (status);
  1654.   
  1655. } /** end pop_context **/
  1656.   
  1657. #endif
  1658.   
  1659. /*$PAGE*/
  1660. /**********************************************************************/
  1661. /*                                                                    */
  1662. /*     Name:  unsigned int effreeall (void)                           */
  1663. /*                                                                    */
  1664. /*     Description:                                                   */
  1665. /*        Frees all handles, pages and blocks.  Prepare for program   */
  1666. /*     termination.                                                   */
  1667. /*                                                                    */
  1668. /*     Parameters: None                                               */
  1669. /*                                                                    */
  1670. /*     Results returned:                                              */
  1671. /*        PASSED    Operation successful                              */
  1672. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1673. /*                                                                    */
  1674. /*     Calling sequence:                                              */
  1675. /*     #include "memlib.h"                                            */
  1676. /*     #include "errors.h"                                            */
  1677. /*                                                                    */
  1678. /*     unsigned int status;                                           */
  1679. /*      ...                                                           */
  1680. /*     status = effree();                                             */
  1681. /*     if (status == PASSED)                                          */
  1682. /*        { continue normal code }                                    */
  1683. /*     else                                                           */
  1684. /*        { error condition }                                         */
  1685. /*                                                                    */
  1686. /*     Calls: dealloc_pages()                                         */
  1687. /*            map_umap_page()                                         */
  1688. /*                                                                    */
  1689. /*     Called by: Application                                         */
  1690. /*                effree()                                            */
  1691. /*                                                                    */
  1692. /*     Globals referenced/modified: app_handle                        */
  1693. /*                                  exp_initialized                   */
  1694. /*                                  man_handle                        */
  1695. /*                                  num_pages_in_page_frame           */
  1696. /*                                  context_ptrs                      */
  1697. /*                                  context_top                       */
  1698. /*                                                                    */
  1699. /**********************************************************************/
  1700.   
  1701. unsigned int effreeall (void)
  1702. {
  1703.     unsigned int status;         /* The status of EMM and MEMLIB */
  1704.     unsigned int j;              /* Looping variable             */
  1705.   
  1706.     status = PASSED;
  1707.   
  1708.    /*****************************************************************/
  1709.    /*  If MEMLIB has not been initialized no need to free anything. */
  1710.    /*****************************************************************/
  1711.   
  1712.     if (exp_initialized)
  1713.     {
  1714.   
  1715.       /**************************************/
  1716.       /* Unmap all pages in the page frame. */
  1717.       /**************************************/
  1718.   
  1719.         for (j = 0; (status == PASSED) &&
  1720.             (j < num_pages_in_page_frame); j++)
  1721.         {
  1722.             status = map_unmap_page(j, UNMAPPED, man_handle);
  1723.         }
  1724.   
  1725.         if (status == PASSED)
  1726.         {
  1727.          /***********************************************/
  1728.          /* Deallocate the pages and handle for MEMLIB. */
  1729.          /***********************************************/
  1730.   
  1731.             status = dealloc_pages (man_handle);
  1732.         }
  1733.         if (status == PASSED)
  1734.         {
  1735.          /********************************************************/
  1736.          /* Deallocate the pages and handle for the application. */
  1737.          /********************************************************/
  1738.   
  1739.             status = dealloc_pages (app_handle);
  1740.   
  1741.          /***********************************/
  1742.          /* Reset exp_initialized to FALSE. */
  1743.          /***********************************/
  1744.   
  1745.             if (status == PASSED)
  1746.             {
  1747.                 exp_initialized = FALSE;
  1748.   
  1749.             /***********************************************/
  1750.             /* Free up all space taken by pushed contexts. */
  1751.             /***********************************************/
  1752.   
  1753.                 if (context_top != NO_CONTEXTS)
  1754.                 {
  1755.                     for (j = 0; j < context_top; j++)
  1756.                     {
  1757.                         if (context_ptrs[j] != NULL)
  1758.                             free (context_ptrs[j]);
  1759.                     }
  1760.                 }
  1761.             }
  1762.         }
  1763.     }
  1764.     return(status);
  1765.   
  1766. } /** end effreeall **/
  1767.   
  1768.   
  1769.   
  1770.