home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2MISC / CSDPMI3S.ZIP / SRC / CWSDPMI / VALLOC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-25  |  9.5 KB  |  387 lines

  1. /* Copyright (C) 1995,1996 CW Sandmann (sandmann@clio.rice.edu) 1206 Braelinn, Sugarland, TX 77479
  2. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. **
  4. ** This file is distributed under the terms listed in the document
  5. ** "copying.cws", available from CW Sandmann at the address above.
  6. ** A copy of "copying.cws" should accompany this file; if not, a copy
  7. ** should be available from where this file was obtained.  This file
  8. ** may not be distributed without a verbatim copy of "copying.cws".
  9. **
  10. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. */
  13. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <dos.h>
  19.  
  20. #include "gotypes.h"
  21. #include "valloc.h"
  22. #include "xms.h"
  23. #include "vcpi.h"
  24. #include "paging.h"
  25. #include "control.h"
  26. #include "mswitch.h"
  27.  
  28. #define NPAGEDIR CWSpar.pagedir /* In low memory * 4K, user gets 3 less, 4Mb/entry */
  29. #define MINAPPMEM CWSpar.minapp    /* Min pages extended before we use DOS memory */
  30. #define SAVEPARA CWSpar.savepar    /* If we use DOS memory for paging, amt to save */
  31. #define MINPAGEDIR 4        /* May round down, 1PD, 2PT */
  32. #define PAGE2PARA 256
  33. #define KB2PARA 64
  34.  
  35. static word8 map[4096];        /* Expanded/Extended paged by valloc() */
  36.  
  37. static word16 mem_avail;
  38. static word16 mem_used;        /* Pages, max 256Mb */
  39.  
  40. static unsigned pn_lo_first, pn_lo_last, pn_hi_first, pn_hi_last;
  41. static unsigned pn_lo_next, pn_hi_next;
  42. static char valloc_initted = 0;
  43. static char use_vcpi = 0;
  44.  
  45. static int16 emb_handle=-1;
  46.  
  47. static void xms_free(void)
  48. {
  49.   if(use_xms && emb_handle != -1) {
  50.     xms_unlock_emb(emb_handle);
  51.     xms_emb_free(emb_handle);
  52.     emb_handle = -1;
  53.   }
  54. }
  55.  
  56. static void xms_alloc_init(void)
  57. {
  58.   word32 linear_base;
  59.   word16 emb_size;
  60.   if((emb_size = xms_query_extended_memory()) != 0) {
  61.     emb_handle = xms_emb_allocate(emb_size);
  62.     linear_base = xms_lock_emb(emb_handle);
  63.     pn_hi_first = (word16)((linear_base + 4095)/4096);
  64.     pn_hi_last = (word16)((linear_base + emb_size * 1024L)/4096 - 1);
  65.   } else {
  66.     pn_hi_first = 1;
  67.     pn_hi_last = 0;
  68.   }
  69.   SHOW_MEM_INFO("XMS memory: %ld Kb",(((word32)pn_hi_last-pn_hi_first+1) * 4));
  70. }
  71.  
  72. static unsigned valloc_lowmem_page;
  73. static unsigned lol;
  74. static unsigned desired_pt;
  75. static unsigned strategy, umbstat;
  76. static unsigned mempid;
  77. static unsigned oldmempid;
  78.  
  79. static void set_umb(void)
  80. {
  81.   oldmempid = get_pid();
  82.   if(mempid) {
  83.     if(oldmempid != mempid)
  84.       set_pid(mempid);
  85.   } else
  86.     mempid = oldmempid;
  87.  
  88.   if (_osmajor >= 5) {
  89.     _AX = 0x5800;
  90.     geninterrupt(0x21);    /* Get allocation strategy */
  91.     strategy = _AX;
  92.  
  93.     _AX = 0x5802;
  94.     geninterrupt(0x21);    /* Get UMB status */
  95.     umbstat = _AX;
  96.     
  97.     _AX = 0x5801;
  98.     _BX = 0x0080;
  99.     geninterrupt(0x21);    /* Set first fit high, then low */
  100.  
  101.     _AX = 0x5803;
  102.     _BX = 0x0001;
  103.     geninterrupt(0x21);    /* Include UMB in memory chain */
  104.   }
  105. }
  106.  
  107. static void restore_umb(void)
  108. {
  109.   if (_osmajor >= 5) {
  110.     _AX = 0x5803;
  111.     _BX = umbstat;
  112.     _BH = 0;
  113.     geninterrupt(0x21);    /* Restore memory chain UMB usage */
  114.  
  115.     _AX = 0x5801;
  116.     _BX = strategy;
  117.     geninterrupt(0x21);    /* Restore allocation stragegy */
  118.   }
  119.   if(oldmempid != mempid)
  120.       set_pid(oldmempid);
  121. }
  122.  
  123. static int alloc_pagetables(int mintable, int wanttable)
  124. {
  125.   set_umb();
  126.   _AH = 0x48;        /* get real memory size */
  127.   _BX = 0xffff;
  128.   geninterrupt(0x21);    /* lol == size of largest free memory block */
  129.   lol = _BX;
  130.  
  131.   if (lol < mintable*PAGE2PARA)    /* 1 PD, 1 PT (real), 1 PT (user) */
  132.     goto mem_exit;
  133.  
  134.   if (lol > wanttable*PAGE2PARA) {    /* 8 will probably result in 5 user pt */
  135.     if (mem_avail > MINAPPMEM)            /* 256K extended */
  136.       lol = wanttable*PAGE2PARA;
  137.     else {
  138.       if (lol > wanttable*PAGE2PARA+SAVEPARA)
  139.         lol -= SAVEPARA;            /* Reserve extra DOS memory */
  140.       mem_avail += (lol >> 8) - wanttable;
  141.     }
  142.   }
  143.  
  144.   _BX = lol;
  145.   _AH = 0x48;
  146.   geninterrupt(0x21);        /* get the block */
  147.   valloc_lowmem_page = _AX;
  148.   if (_FLAGS & 1) {
  149. mem_exit:
  150.     restore_umb();
  151.     return 1;
  152.   }
  153.  
  154.   /* shrink memory to 4K align */
  155.   if (valloc_lowmem_page & 0xFF) {
  156.     lol -= (valloc_lowmem_page & 0xFF);
  157.     _ES = valloc_lowmem_page;
  158.     _BX = lol;
  159.     _AH = 0x4A;
  160.     geninterrupt(0x21);
  161.   }
  162.   restore_umb();
  163.  
  164.   pn_lo_first = (valloc_lowmem_page+0xFF) >> 8;    /* lowest real mem 4K block */
  165.   pn_lo_last = (valloc_lowmem_page+lol-0x100)>>8;    /* highest real mem 4K block */
  166.  
  167.   pn_lo_next = pn_lo_first;
  168.   return 0;
  169. }
  170.  
  171. void valloc_init(void)
  172. {
  173.   unsigned i;
  174.  
  175.   if (valloc_initted)
  176.     return;
  177.  
  178.   if (vcpi_installed) {
  179.     pn_hi_first = 0;
  180.     pn_hi_last  = vcpi_maxpage();
  181.     i = vcpi_capacity();
  182.     if (i) {
  183.       use_vcpi = 1;
  184.       SHOW_MEM_INFO("VCPI memory: %ld Kb", (i * 4L));
  185.     } else if(use_xms) {
  186.       use_vcpi = 0;    /* Just in case multiple pass with all allocated */
  187.       xms_alloc_init();    /* Use XMS memory with VCPI mode switch */
  188.     }
  189.   } else if (use_xms) {
  190.     xms_alloc_init();    /* Try XMS allocation */
  191.     if (cpumode()) {
  192.       errmsg("\nError: Using XMS switched the CPU into V86 mode.\n");
  193.       xms_free();
  194.       _exit(1);
  195.     }
  196.   } else if (mtype == PC98) { /* RAW memory not supported, 640K only */
  197.     pn_hi_first = 256;
  198.     pn_hi_last = 255;    /* Or set via memory size, how? */
  199.   } else {
  200.     /* int 15/vdisk memory allocation */
  201.     /* Bug here - we should hook int 0x15 and reduce size, but who cares? */
  202.     char has_vdisk=1;
  203.     unsigned char far *vdisk;
  204.     _AH = 0x88;        /* get extended memory size */
  205.     geninterrupt(0x15);
  206.     pn_hi_last = _AX / 4 + 255;
  207.  
  208.     /* get ivec 19h, seg only */
  209.     vdisk = (unsigned char far *)(*(long far *)0x64L & 0xFFFF0000L);
  210.     for (i=0; i<5; i++)
  211.       if (vdisk[i+18] != "VDISK"[i])
  212.         has_vdisk = 0;
  213.     if (has_vdisk) {
  214.       pn_hi_first = ( (vdisk[46]<<4) | (vdisk[45]>>4) );
  215.       if (vdisk[44] | (vdisk[45]&0xf))
  216.         pn_hi_first ++;
  217.     }
  218.     else
  219.       pn_hi_first = 256;
  220.     SHOW_MEM_INFO("Extended memory: %ld Kb", (((word32)pn_hi_last-pn_hi_first) * 4));
  221.   }
  222.   pn_hi_next = pn_hi_first;
  223.   mem_avail = (use_vcpi)? vcpi_capacity():((long)pn_hi_last-pn_hi_first+1);
  224.   
  225.   if(NPAGEDIR)                /* Specified */
  226.     desired_pt = 3 + NPAGEDIR;
  227.   else {                /* Zero means automatic */
  228.     desired_pt = 4 + (mem_avail>>10);    /* All physical mem plus 1 extra */
  229.     if(desired_pt < 8)
  230.       desired_pt = 8;
  231.   }
  232.  
  233.   mempid = 0;
  234.   if(alloc_pagetables(MINPAGEDIR, desired_pt)) {
  235.     errmsg("Error: could not allocate page table memory\n");
  236.     xms_free();
  237.     _exit(1);
  238.   }
  239.  
  240.   memset(map, 0, 4096);
  241.  
  242.   mem_used = 0;
  243.   valloc_initted = 1;
  244.   set_a20();
  245. }
  246.  
  247. static void vset(unsigned i, char b)
  248. {
  249.   unsigned o;
  250.   word8 m;
  251.   o = (unsigned)(i>>3);
  252.   m = 1<<((unsigned)i&7);
  253.   if (b)
  254.     map[o] |= m;
  255.   else
  256.     map[o] &= ~m;
  257. }
  258.  
  259. static word8 vtest(unsigned i)
  260. {
  261.   unsigned o;
  262.   word8 m;
  263.   o = (unsigned)(i>>3);
  264.   m = 1<<((unsigned)i&7);
  265.   return map[o] & m;
  266. }
  267.  
  268. static void vcpi_flush(void)        /* only called on exit */
  269. {
  270.   word16 pn;
  271.  
  272.   if (!use_vcpi)
  273.     return;            /*  Not Initaialized Map[]  */
  274.   for(pn = 0; pn <= pn_hi_last; pn++)
  275.     if (vtest(pn))
  276.       vcpi_free(pn);
  277. }
  278.  
  279. void valloc_uninit(void)
  280. {
  281.   if (!valloc_initted)
  282.     return;
  283.  
  284.   /* free the block we allocated - DOS does this
  285.   _ES = valloc_lowmem_page;
  286.   _AH = 0x49;
  287.   geninterrupt(0x21); */
  288.  
  289.   xms_free();
  290.   vcpi_flush();        /*  Deallocated VCPI Pages  */
  291.   valloc_initted = 0;
  292.   reset_a20();
  293. }
  294.  
  295. unsigned valloc_640(void)
  296. {
  297.   unsigned pn;
  298.   if (pn_lo_next <= pn_lo_last) {
  299.     return pn_lo_last--;        /* Never deallocated! */
  300.   }
  301.  
  302.   /* First try to resize current block instead of paging */
  303.   {
  304.     int failure;
  305.     set_umb();
  306.     lol += PAGE2PARA;
  307.     _ES = valloc_lowmem_page;
  308.     _BX = lol;
  309.     _AH = 0x4A;
  310.     geninterrupt(0x21);
  311.     failure = _FLAGS & 1;
  312.     restore_umb();
  313.     if(!failure)
  314.       return (valloc_lowmem_page+lol-0x100)>>8;
  315.     /* Okay, not unexpected.  Allocate a new block, we can 
  316.        hopefully resize it later if needed. */
  317.     if(!alloc_pagetables(2,2))
  318.       return pn_lo_last--;
  319.   }
  320.  
  321.   pn = page_out_640();
  322.   if (pn == 0xffff) {
  323.     errmsg("Error: could not allocate page table memory\n");
  324.     cleanup(1);
  325.   }
  326.   return pn;
  327. }
  328.  
  329. unsigned valloc(void)
  330. {
  331.   unsigned pn;
  332.   if (use_vcpi) {
  333.     if ((pn = vcpi_alloc()) != 0) {
  334.       mem_used++;
  335.       vset(pn, 1);
  336.       return pn;
  337.     }
  338.   } else {
  339.     for (pn=pn_hi_next; pn<=pn_hi_last; pn++) 
  340.       if (!vtest(pn)) {
  341.         pn_hi_next = pn+1;
  342.         mem_used++;
  343.         vset(pn, 1);
  344.         return pn;
  345.       }
  346.   }
  347.  
  348.   /* This section is only used if we are paging in 1Mb area; save for PDs */
  349.   /* Note, if VCPI memory runs out before we get mem_avail also end up here */
  350.   if (mem_used < mem_avail && pn_lo_next < 4+pn_lo_last-desired_pt) {
  351.     mem_used++;
  352.     return (word16)(vcpi_pt[pn_lo_next++] >> 12);
  353.   }
  354.  
  355.   return page_out();
  356. }
  357.  
  358. /* If we are able to find the page, return 1 */
  359. int vfree(word16 pn)
  360. {
  361.   if (vtest(pn)) {
  362.     vset(pn, 0);
  363.     if (use_vcpi)
  364.       vcpi_free(pn);
  365.     else if(pn < pn_hi_next)
  366.       pn_hi_next = pn;
  367.     mem_used--;
  368.     return 1;
  369.   } 
  370.   if (pn == vcpi_pt[pn_lo_next-1]) {
  371.     pn_lo_next--;
  372.     mem_used--;
  373.     return 1;
  374.   }
  375.   return 0;
  376. }
  377.  
  378. unsigned valloc_max_size(void)
  379. {
  380.   return (unsigned)(mem_avail);
  381. }
  382.  
  383. unsigned valloc_used(void)
  384. {
  385.   return (unsigned)(mem_used);
  386. }
  387.