home *** CD-ROM | disk | FTP | other *** search
- /* This is file VALLOC.C */
- /*
- ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
- **
- ** This file is distributed under the terms listed in the document
- ** "copying.dj", available from DJ Delorie at the address above.
- ** A copy of "copying.dj" should accompany this file; if not, a copy
- ** should be available from where this file was obtained. This file
- ** may not be distributed without a verbatim copy of "copying.dj".
- **
- ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
- ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
- /* Bugs in large memory usage (both RAM & virtual) fixed Greg Galperin 2AUG93 */
-
- /*
- Note: The functions here assume that memory is never really freed, just
- reused through page_out, unless we're exiting or running another
- program. In either case, we don't need to keep track of what's freed
- since it's all going anyway. Thus, vfree() is empty and the rest of the
- routines are relatively simple. Note that VCPI may blow you up if you
- try to be clever in here.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <dos.h>
-
- #include "gotypes.h"
- #include "valloc.h"
- #include "xms.h"
- #include "mono.h"
- #include "vcpi.h"
- #include "utils.h"
- #include "paging.h"
- #include "stubinfo.h"
- #include "proginfo.h"
- #include "control.h"
- #include "mswitch.h"
-
- #define VA_FREE 0
- #define VA_USED 1
-
- #define DOS_PAGE 256 /* 1MB / 4KB = 256 Pages */
-
- extern char use_DPMI;
-
- int valloc_initted = 0;
- static word8 map[4096]; /* Expanded/Extended paged, allocated with VA_1M */
-
- word32 mem_avail, mem_used; /* Kbytes */
-
- static unsigned pn_lo_first, pn_lo_last, pn_hi_first, pn_hi_last;
- static unsigned pn_lo_next, pn_hi_next;
- static unsigned vcpi_flush_ok = 0;
- static char use_vcpi = 0;
-
- extern int debug_mode;
- extern word16 vcpi_installed; /* If VCPI is installed, set this not Zero */
- extern word32 far *vcpi_pt;
-
- void valloc_update_status(void)
- {
- char buf[20];
- int i;
- if (!valloc_initted)
- return;
- sprintf(buf, "%6ldk", mem_avail);
- for (i=0; i<7; i++)
- poke(screen_seg, (i+70)*2, buf[i] | 0x0a00);
- sprintf(buf, "%6ldk", mem_used);
- for (i=0; i<7; i++)
- poke(screen_seg, (i+62)*2, buf[i] | 0x0a00);
- }
-
-
- emb_handle_t emb_handle=-1;
-
- void
- xms_free(void)
- {
- if(use_xms && emb_handle != -1)
- {
- xms_unlock_emb(emb_handle);
- xms_emb_free(emb_handle);
- emb_handle = -1;
- }
- }
-
- void
- xms_alloc_init(void)
- {
- xms_extended_info *x = xms_query_extended_memory();
- emb_off_t linear_base;
- emb_size_K_t emb_size;
- emb_size = x->max_free_block;
- emb_handle = xms_emb_allocate(emb_size);
- linear_base = xms_lock_emb(emb_handle);
- pn_hi_first = (word16)((linear_base + 4095)/4096);
- pn_hi_last = (word16)((linear_base + emb_size * 1024L)/4096 - 1);
- if (cpumode())
- {
- fprintf(stderr, "\nGo32 error: Using XMS switches the CPU into V86 mode.\n");
- fprintf(stderr, "If you are using QEMM, add the `on' parameter to the entry\n");
- fprintf(stderr, "in your CONFIG.SYS file. See the FAQ for details.\n\n");
- xms_free();
- if (!show_memory_info)
- exit(1);
- }
- }
-
-
- static int valloc_lowmem_page;
- static unsigned lol;
-
- void valloc_init(void)
- {
- word32 left_lo, left_hi;
- unsigned char far *vdisk;
- int has_vdisk=1;
- unsigned free_pages;
- unsigned i;
- struct REGPACK r;
-
- if (valloc_initted)
- return;
-
- if (vcpi_installed)
- {
- pn_hi_first = 0;
- pn_hi_last = vcpi_maxpage();
- i = vcpi_capacity();
- if ( i )
- {
- use_vcpi = 1;
- if (show_memory_info)
- fprintf(stderr, "VCPI (Expanded) memory available: %ld Kb\n", i * 4L);
- }
- else if(use_xms)
- {
- xms_alloc_init(); /* Try XMS allocation */
- if (show_memory_info)
- fprintf(stderr, "XMS memory available: %ld Kb\n", ((word32)pn_hi_last-pn_hi_first) * 4);
- }
- prog_info.run_mode = _GO32_RUN_MODE_VCPI;
- }
- else if (use_xms)
- {
- xms_alloc_init(); /* Try XMS allocation */
- if (show_memory_info)
- fprintf(stderr, "XMS memory available: %ld Kb\n", ((word32)pn_hi_last-pn_hi_first) * 4);
- prog_info.run_mode = _GO32_RUN_MODE_XMS;
- }
- else
- {
- /*
- ** int 15/vdisk memory allocation
- */
- r.r_ax = 0x8800; /* get extended memory size */
- intr(0x15, &r);
- pn_hi_last = r.r_ax / 4 + 255;
-
- /* get ivec 19h, seg only */
- vdisk = (unsigned char far *)(*(long far *)0x64L & 0xFFFF0000L);
- for (i=0; i<5; i++)
- if (vdisk[i+18] != "VDISK"[i])
- has_vdisk = 0;
- if (has_vdisk)
- {
- pn_hi_first = ( (vdisk[46]<<4) | (vdisk[45]>>4) );
- if (vdisk[44] | (vdisk[45]&0xf))
- pn_hi_first ++;
- }
- else
- pn_hi_first = 256;
- if (show_memory_info)
- fprintf(stderr, "Extended memory available: %ld Kb\n", ((word32)pn_hi_last-pn_hi_first) * 4);
- prog_info.run_mode = _GO32_RUN_MODE_RAW;
- }
-
- r.r_ax= 0x4800; /* get real memory size */
- r.r_bx = 0xffff;
- intr(0x21, &r); /* lol == size of largest free memory block */
-
- lol = r.r_bx;
- /* printf("max pages is %u\n", lol); */
- if (lol < 8*256)
- {
- fprintf(stderr, "Error: not enough memory to run go32!\n");
- exit(1);
- }
-
- free_pages = (unsigned)(stub_info.free_conventional_memory / 16);
- /* printf("free pages desired is %u\n", free_pages); */
- if (lol - 8*256 > free_pages)
- {
- lol -= free_pages;
- /* printf("subtracting, lol now %u\n", lol); */
- }
- else
- {
- lol = 8*256;
- /* printf("best we can do is %u\n", lol); */
- }
-
- r.r_ax = 0x4800;
- r.r_bx = lol;
- /* printf("go32 uses %u para", lol); */
- intr(0x21, &r); /* get the block */
- /* printf(" at %x, %d, %x\n", r.r_ax, r.r_flags, r.r_bx); */
- pn_lo_first = (r.r_ax+0xFF) >> 8; /* lowest real mem 4K block */
- pn_lo_last = ((r.r_ax+lol-0x100)>>8); /* highest real mem 4K block */
- if (r.r_flags & 1)
- {
- fprintf(stderr, "Error: could not allocate memory for go32\n");
- exit(1);
- }
-
- valloc_lowmem_page = r.r_ax;
-
- pn_lo_next = pn_lo_first;
- pn_hi_next = pn_hi_first;
-
- memset(map, 0, 4096);
- vcpi_flush_ok = 1;
-
- mem_used = 0;
- left_lo = ((long)pn_lo_last - pn_lo_first + 1)*4;
- left_hi = (use_vcpi)? vcpi_capacity()*4:((long)pn_hi_last-pn_hi_first+1)*4;
- mem_avail = left_lo + left_hi;
-
- if (debug_mode)
- fprintf(stderr, "%ld Kb conventional, %ld Kb %s - %ld Kb total RAM available\n",
- left_lo, left_hi,
- use_DPMI ? "dpmi" : use_vcpi ? "expanded" : use_xms ? "XMS" : "extended",
- mem_avail);
-
- if (topline_info)
- valloc_update_status();
-
- valloc_initted = 1;
- }
-
- void valloc_shrink_rmem(int pages)
- {
- if (pn_lo_last - pn_lo_next > pages)
- {
- struct REGPACK r;
- /* printf("Changing allocation down %d pages from %d ", pages, lol); */
- lol -= pages * 256;
- r.r_ax = 0x4a00; /* modify real memory size */
- r.r_bx = lol;
- r.r_es = valloc_lowmem_page;
- /* printf("to %d (0x%04x)\n", lol, valloc_lowmem_page); */
- intr(0x21, &r);
- }
- /* else
- {
- printf("most avail pages is %d (wanted %d)\n", pn_lo_last - pn_lo_next, pages);
- } */
- }
-
- void valloc_uninit(void)
- {
- struct REGPACK r;
- if (!valloc_initted)
- return;
-
- r.r_es = valloc_lowmem_page; /* free the block we allocated */
- r.r_ax = 0x4900;
- intr(0x21, &r);
-
- xms_free();
- valloc_initted = 0;
- }
-
- unsigned valloc(where)
- {
- unsigned pn;
- if (!valloc_initted)
- valloc_init();
- switch (where)
- {
- case VA_640:
- if (pn_lo_next <= pn_lo_last)
- {
- mem_avail -= 4;
- mem_used += 4;
- if (topline_info)
- valloc_update_status();
- return pn_lo_next++;
- }
-
- pn = page_out(VA_640);
- if (pn != 0xffff)
- {
- return pn;
- }
- fprintf(stderr, "Error: out of conventional memory\n");
- exit(1);
- case VA_1M:
- if (use_vcpi)
- {
- if ((pn = vcpi_alloc()) != 0)
- {
- mem_avail -= 4;
- mem_used += 4;
- if (topline_info)
- valloc_update_status();
- map[pn>>3] |= 1 << (pn&7);
- return pn;
- }
- }
- else
- {
- if (pn_hi_next <= pn_hi_last)
- {
- mem_avail -= 4;
- mem_used += 4;
- if (topline_info)
- valloc_update_status();
- return pn_hi_next++;
- }
- }
- /* Difference is -1 when there are no pages left, so
- use signed compare. */
- if ((signed)pn_lo_last-(signed)pn_lo_next > 3) /* save last four for VA_640 */
- {
- mem_avail -= 4;
- mem_used += 4;
- if (topline_info)
- valloc_update_status();
- return (word16)(vcpi_pt[pn_lo_next++] >> 12);
- }
-
- pn = page_out(VA_1M);
- if (pn != 0xffff)
- {
- return pn;
- }
- fprintf(stderr, "Error: out of extended memory\n");
- exit(1);
- }
- return 0;
- }
-
- void vfree_640()
- {
- struct REGPACK r;
-
- r.r_es = valloc_lowmem_page; /* free the block we allocated */
- r.r_ax = 0x4900;
- intr(0x21, &r);
- }
-
- void vrecover_640()
- {
- struct REGPACK r;
-
- r.r_ax= 0x4800; /* get real memory size */
- r.r_bx = 0xffff;
- intr(0x21, &r); /* lol == size of largest free memory block */
-
- if (lol != r.r_bx)
- {
- fprintf(stderr, "Error: unable to realloc conventional memory (wrong size)\n");
- exit(1);
- }
- r.r_ax = 0x4800;
- intr(0x21, &r); /* get the block */
- if (r.r_ax != valloc_lowmem_page)
- {
- fprintf(stderr, "Error: unable to realloc conventional memory (wrong address)\n");
- exit(1);
- }
- pn_lo_next = pn_lo_first;
- }
-
- void vfree(void)
- {
- mem_avail += 4;
- mem_used -= 4;
- if (topline_info)
- valloc_update_status();
- }
-
- void vcpi_flush(void) /* only called on exit */
- {
- word16 pn;
-
- if (!vcpi_flush_ok || !use_vcpi)
- return; /* Not Initaialized Map[] */
- for(pn = pn_hi_first; pn <= pn_hi_last; pn++)
- if (map[pn>>3] & (1 << (pn&7)))
- vcpi_free(pn);
- }
-
- unsigned valloc_max_size(void)
- {
- return (unsigned)((mem_avail + mem_used) / 4);
- }
-
- unsigned valloc_used(void)
- {
- return (unsigned)(mem_used / 4);
- }
-