home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 October
/
VPR9710A.ISO
/
BENCH
/
DJ1SRC_K
/
105
/
PAGING.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-02
|
23KB
|
912 lines
/* This is file PAGING.C */
/*
** Copyright (C) 1991 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 */
/* 1997/05/01 modified by Kimio Itoh(kitoh@nn.iij4u.or.jp)
for reduce binary size and for dead code elimination.
and merged paging.c, valloc.c and dalloc.c
*/
/* History:112,12 */
#include "build.h"
static unsigned dalloc(void);
static void __pascal dfree(unsigned);
static void __pascal dwrite(word8 * buf, unsigned block);
static void __pascal dread(word8 * buf, unsigned block);
static unsigned __pascal valloc(int where);
static void __pascal vfree(unsigned);
static int page_out(void);
#if DEBUGGER
#define MAX_PAGING_NUM 1
#else
#define MAX_PAGING_NUM 4
#endif
extern word32 __pascal ptr2linear(void far * ptr);
static CLIENT client; /* VCPI Change Mode Structure */
word32 abs_client; /* _DS * 16L + &client */
far32 vcpi_entry;
static SYS_TBL int_descriptor;
static SYS_TBL gbl_descriptor;
extern word16 vcpi_installed; /* VCPI Installed Flag */
extern near protect_entry();
extern TSS *utils_tss;
extern int debug_mode;
static word16 mem_avail;
extern long header_offset;
typedef struct AREAS {
word32 first_addr;
word32 last_addr;
word32 foffset; /* corresponding to first_addr; -1 = zero fill only */
} AREAS;
#define MAX_AREA 8
static AREAS areas[MAX_AREA];
#if TOPLINEINFO
static char achar[MAX_AREA] = "tdbmsg?e";
#endif
typedef enum {
A_text,
A_data,
A_bss,
A_arena,
A_stack,
A_vga,
A_syms,
A_emu
} AREA_TYPES;
static aout_f;
static emu_f;
static word32 far *pd = 0;
word32 far *graphics_pt;
extern word32 graphics_pt_lin;
static word8 paging_buffer[4096 * MAX_PAGING_NUM];
/* VCPI Get Interface */
static void __pascal link_vcpi(word32 far * dir, word32 far * table)
{
vcpi_entry.selector = g_vcpicode * 8;
vcpi_entry.offset32 = get_interface(table, &gdt[g_vcpicode]);
if (vcpi_entry.offset32 == ULONG_MAX) {
printf("CAUTION !!!! This EMS driver used address 1B0000H.\n"
"This memory area is broken by handle_screen_swap().\n");
exit(1);
}
int_descriptor.limit_16 = sizeof(idt);
int_descriptor.base_32 = ptr2linear(idt);
gbl_descriptor.limit_16 = sizeof(gdt);
gbl_descriptor.base_32 = ptr2linear(gdt);
client.page_table = (word32) dir >> 12;
client.gdt_address = ptr2linear(&gbl_descriptor);
client.idt_address = ptr2linear(&int_descriptor);
client.ldt_selector = 0;
client.tss_selector = g_ctss * 8;
client.entry_eip = (word16) protect_entry;
client.entry_cs = g_rcode * 8;
abs_client = ptr2linear(&client);
}
static void __pascal handle_screen_swap(word32 far * pt)
{
struct REGPACK r;
int have_mono, have_color, have_graphics, save, new, i;
have_mono = have_color = have_graphics = 0;
r.r_ax = 0x1200;
r.r_bx = 0xff10;
r.r_cx = 0xffff;
intr(0x10, &r);
if (r.r_cx == 0xffff)
pokeb(0x40, 0x84, 24); /* the only size for CGA/MDA */
save = peekb(screen_seg, 0);
pokeb(screen_seg, 0, ~save);
new = peekb(screen_seg, 0);
pokeb(screen_seg, 0, save);
if (new == ~save)
have_color = 1;
save = peekb(0xb000, 0);
pokeb(0xb000, 0, ~save);
new = peekb(0xb000, 0);
pokeb(0xb000, 0, save);
if (new == ~save)
have_mono = 1;
r.r_ax = 0x0f00;
intr(0x10, &r);
if ((r.r_ax & 0xff) > 0x07)
have_graphics = 1;
if (have_graphics && have_mono)
have_color = 1;
else if (have_graphics && have_color)
have_mono = 1;
for (i = 0; i < 16; i++)
pt[0x1b0 + i] = pt[0xb0 + i];
if (have_color && !have_mono) {
for (i = 0; i < 8; i++)
pt[0x1b0 + i] = pt[0xb8 + i];
return;
}
if (have_mono && !have_color) {
for (i = 0; i < 8; i++)
pt[0x1b8 + i] = pt[0xb0 + i];
return;
}
if ((biosequip() & 0x0030) == 0x0030) { /* mono mode, swap! */
for (i = 0; i < 8; i++) {
pt[0x1b0 + i] ^= pt[0x1b8 + i];
pt[0x1b8 + i] ^= pt[0x1b0 + i];
pt[0x1b0 + i] ^= pt[0x1b8 + i];
}
return;
}
}
void __pascal paging_set_file(char *fname)
{
word32 far *pt;
FILEHDR filehdr;
AOUTHDR aouthdr;
SCNHDR scnhdr[3];
GNU_AOUT gnu_aout;
int i;
aout_f = open(fname, O_RDONLY | O_BINARY);
if (aout_f == -1) {
printf("Can't open file <%s>\n", fname);
exit(1);
}
#if TOPLINEINFO
for (i = 0; fname[i]; i++)
poke(screen_seg, i * 2 + 10, fname[i] | 0x0700);
#endif
lseek(aout_f, header_offset, 0);
read(aout_f, &filehdr, sizeof(filehdr));
if (filehdr.f_magic != 0x14c) {
lseek(aout_f, header_offset, 0);
read(aout_f, &gnu_aout, sizeof(gnu_aout));
a_tss.tss_eip = gnu_aout.entry;
aouthdr.tsize = gnu_aout.tsize;
aouthdr.dsize = gnu_aout.dsize;
aouthdr.bsize = gnu_aout.bsize;
} else {
read(aout_f, &aouthdr, sizeof(aouthdr));
a_tss.tss_eip = aouthdr.entry;
read(aout_f, scnhdr, sizeof(scnhdr));
}
a_tss.tss_cs = g_acode * 8;
a_tss.tss_ds = a_tss.tss_es = a_tss.tss_fs = a_tss.tss_gs = a_tss.tss_ss = g_adata * 8;
a_tss.tss_esp = 0x7ffffffcL;
if (filehdr.f_magic == 0x14c) {
areas[0].first_addr = aouthdr.text_start + ARENA;
areas[0].foffset = scnhdr[0].s_scnptr + header_offset;
areas[0].last_addr = areas[0].first_addr + aouthdr.tsize;
} else if (filehdr.f_magic == 0x10b) {
areas[0].first_addr = ARENA;
if (a_tss.tss_eip >= 0x1000) /* leave space for null reference */
areas[0].first_addr += 0x1000; /* to cause seg fault */
areas[0].foffset = header_offset;
areas[0].last_addr = areas[0].first_addr + aouthdr.tsize + 0x20;
}
#if DEBUGGER
else if (filehdr.f_magic == 0x107) {
struct stat sbuf;
fstat(aout_f, &sbuf);
areas[0].first_addr = ARENA;
areas[0].foffset = 0x20 + header_offset;
areas[0].last_addr = sbuf.st_size + ARENA - 0x20;
} else {
struct stat sbuf;
fstat(aout_f, &sbuf);
areas[0].first_addr = ARENA;
areas[0].foffset = header_offset;
areas[0].last_addr = sbuf.st_size + ARENA;
}
#else
else {
printf("Unknown file type %#x (%#o)\n", filehdr.f_magic, filehdr.f_magic);
exit(-1);
}
#endif
#if DEBUGGER
if (debug_mode)
printf("%ld+%ld+%ld = %ld\n",
aouthdr.tsize, aouthdr.dsize, aouthdr.bsize,
aouthdr.tsize + aouthdr.dsize + aouthdr.bsize);
#endif
if (filehdr.f_magic == 0x14c) {
areas[1].first_addr = aouthdr.data_start + ARENA;
areas[1].foffset = scnhdr[1].s_scnptr + header_offset;
} else {
areas[1].first_addr = (areas[0].last_addr + 0x3fffffL) & ~0x3fffffL;
areas[1].foffset = ((aouthdr.tsize + 0x20 + 0xfffL) & ~0xfffL) + header_offset;
}
areas[1].last_addr = areas[1].first_addr + aouthdr.dsize - 1;
areas[2].first_addr = areas[1].last_addr + 1;
areas[2].last_addr = areas[2].first_addr + aouthdr.bsize - 1;
areas[3].first_addr = areas[2].last_addr;
areas[3].last_addr = areas[3].first_addr;
areas[4].first_addr = 0x50000000L;
areas[4].last_addr = 0x8fffffffL;
areas[5].first_addr = 0xe0000000L;
areas[5].last_addr = 0xe03fffffL;
areas[A_syms].first_addr = 0xa0000000L;
areas[A_syms].last_addr = 0xafffffffL;
areas[2].foffset = areas[3].foffset = areas[4].foffset = areas[5].foffset = areas[A_syms].foffset = ULONG_MAX;
pd = MK_FP(valloc(VA_640) << 8, 0);
pt = MK_FP(valloc(VA_640) << 8, 0);
for (i = 0; i < 1024; i++)
pd[i] = 0;
if (vcpi_installed) {
link_vcpi(pd, pt); /* Get VCPI Page Table */
for (i = 0; i < 1024; i++)
if (pt[i] & PT_P)
pt[i] |= PT_I;
} else {
for (i = 0; i < 256; i++)
pt[i] = ((unsigned long)i << 12) | PT_P | PT_W | PT_I;
for (; i < 1024; i++)
pt[i] = 0;
}
pd[0] = pd[0x3c0] = ((word32) pt >> 12) | PT_P | PT_W | PT_I;
/* map 0-1M 1:1 */
/* map also to 0xF0000000 */
handle_screen_swap(pt);
graphics_pt = MK_FP(valloc(VA_640) << 8, 0);
graphics_pt_lin = ptr2linear(graphics_pt);
for (i = 0; i < 1024; i++)
graphics_pt[i] = 0x000a0000L | ((i * 4096L) & 0xffffL) | PT_W | PT_U;
pd[0x380] = ((word32) graphics_pt >> 12) | PT_P | PT_W | PT_U;
c_tss.tss_cr3 = a_tss.tss_cr3 = o_tss.tss_cr3 = i_tss.tss_cr3 = p_tss.tss_cr3 = f_tss.tss_cr3 = (word32) pd >> 12;
}
#if TOPLINEINFO
static __pascal update_status(int c, int col)
{
int r = peek(screen_seg, 2 * 79);
poke(screen_seg, 2 * col, c);
return r;
}
#endif
word32 __pascal paging_brk(word32 b)
{
word32 r = (areas[3].last_addr - ARENA + 7) & ~7;
areas[3].last_addr = b + ARENA;
return r;
}
word32 paging_sbrk(int32 b)
{
word32 r = (areas[3].last_addr - ARENA + 7) & ~7;
areas[3].last_addr = r + b + ARENA;
return r;
}
int __pascal page_is_valid(word32 vaddr)
{
int a;
for (a = 0; a < MAX_AREA; a++)
if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
return 1;
if (vaddr >= 0xf000000L)
return 1;
return 0;
}
int page_in(void)
{
TSS *old_util_tss;
word32 far *pt;
word32 vaddr, cnt32;
word32 eaddr, vtran, vcnt, zaddr;
int pdi, pti, pn, a, count;
unsigned dblock;
#if TOPLINEINFO
int old_status;
#endif
old_util_tss = utils_tss;
utils_tss = &f_tss;
vaddr = tss_ptr->tss_cr2;
for (a = 0; a < MAX_AREA; a++)
if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
goto got_area;
printf("Segmentation Violation referencing address %#lx\n", tss_ptr->tss_cr2 - ARENA);
return 1;
got_area:
vaddr &= 0xFFFFF000L; /* points to beginning of page */
if ((a == 2) & (vaddr < areas[a].first_addr)) { /* bss, but data too */
a = 1; /* set to page in data */
}
#if TOPLINEINFO
old_status = update_status(achar[a] | 0x0a00, 78);
#endif
pdi = (word16) (vaddr >> 22);
if (!(pd[pdi] & PT_P)) { /* put in an empty page table if required */
pn = valloc(VA_640);
pt = MK_FP(pn << 8, 0);
pd[pdi] = ((word32) pn << 12) | PT_P | PT_W | PT_I | PT_S;
for (pti = 0; pti < 1024; pti++)
pt[pti] = PT_W | PT_S;
} else
pt = (word32 far *) ((pd[pdi] & ~0xFFF) << 12);
pti = (word16) (vaddr >> 12) & 0x3ff;
if (pt[pti] & PT_P) {
utils_tss = old_util_tss;
#if TOPLINEINFO
update_status(old_status, 78);
#endif
return 0;
}
count = MAX_PAGING_NUM;
if (count > mem_avail / 4)
count = mem_avail / 4;
if (pti + count > 1024)
count = 1024 - pti;
if (vaddr + count * 4096L > areas[a].last_addr + 4096L)
count = (int)((areas[a].last_addr - vaddr + 4095) / 4096);
if (count < 1)
count = 1;
zaddr = eaddr = ULONG_MAX;
vtran = vaddr;
vcnt = 0;
for (; count; count--, pti++, vaddr += 4096) {
if (pt[pti] & PT_P)
break;
dblock = (unsigned)(pt[pti] >> 12);
pn = valloc(VA_1M);
pt[pti] &= 0xfffL & ~(word32) (PT_A | PT_D | PT_C);
pt[pti] |= ((word32) pn << 12) | PT_P;
if (pt[pti] & PT_I) {
dread(paging_buffer, dblock);
dfree(dblock);
memput(vaddr, paging_buffer, 4096);
} else {
if (areas[a].foffset != ULONG_MAX) {
if (eaddr == ULONG_MAX) {
eaddr = areas[a].foffset + (vaddr - areas[a].first_addr);
vtran = vaddr;
}
cnt32 = areas[a].last_addr - vaddr + 1;
if (cnt32 > 4096)
cnt32 = 4096;
else
zaddr = vaddr;
vcnt += cnt32;
} else
zero32(vaddr);
pt[pti] |= PT_I;
}
}
if (eaddr != ULONG_MAX) {
int cur_f, rsize;
if (a == A_emu)
cur_f = emu_f;
else
cur_f = aout_f;
lseek(cur_f, eaddr, 0);
rsize = read(cur_f, paging_buffer, (size_t) vcnt);
if (rsize < vcnt)
memset(paging_buffer + rsize, 0, (size_t) (vcnt - rsize));
if (zaddr != ULONG_MAX)
zero32(zaddr);
memput(vtran, paging_buffer, (size_t) vcnt);
}
utils_tss = old_util_tss;
#if TOPLINEINFO
update_status(old_status, 78);
#endif
return 0;
}
static last_po_pdi = 0;
static last_po_pti = 0;
static int page_out(void)
{ /* return 1 if paged out, 0 if not */
unsigned start_pdi, start_pti, dblock, pn;
word32 far *pt, v;
#if TOPLINEINFO
int old_status;
old_status = update_status('>' | 0x0a00, 79);
#endif
start_pdi = last_po_pdi;
start_pti = last_po_pti;
pt = (word32 far *) ((pd[last_po_pdi] & ~0xFFF) << 12);
do {
if ((pd[last_po_pdi] & (PT_P | PT_S)) == (PT_P | PT_S)) {
if ((pt[last_po_pti] & (PT_P | PT_S)) == (PT_P | PT_S)) {
pn = (unsigned)(pt[last_po_pti] >> 12);
dblock = dalloc();
v = ((word32) last_po_pdi << 22) | ((word32) last_po_pti << 12);
memget(v, paging_buffer, 4096);
dwrite(paging_buffer, dblock);
pt[last_po_pti] &= 0xfff & ~PT_P; /* no longer present */
pt[last_po_pti] |= (long)dblock << 12;
vfree(pn);
#if TOPLINEINFO
update_status(old_status, 79);
#endif
return 1;
}
} else /* imagine we just checked the last entry */
last_po_pti = 1023;
if (++last_po_pti == 1024) {
last_po_pti = 0;
if (++last_po_pdi == 1024)
last_po_pdi = 0;
pt = (word32 far *) ((pd[last_po_pdi] & ~0xFFF) << 12);
}
} while ((start_pdi != last_po_pdi) || (start_pti != last_po_pti));
#if TOPLINEINFO
update_status(old_status, 79);
#endif
return 0;
}
static unsigned pd_dblock;
static int valloc_initted = 0;
void page_out_everything(void)
{
int pdi;
unsigned ptb;
void far *fp;
while (page_out());
for (pdi = 0; pdi < 1024; pdi++)
if (pd[pdi]) {
ptb = dalloc();
fp = (void far *)((pd[pdi] & ~0xFFF) << 12);
movedata(FP_SEG(fp), FP_OFF(fp), _DS, FP_OFF(paging_buffer), 4096);
dwrite(paging_buffer, ptb);
vfree((unsigned)(pd[pdi] >> 12));
pd[pdi] = (pd[pdi] & (0xFFF & ~PT_P)) | ((word32) ptb << 12);
}
movedata(FP_SEG(pd), 0, _DS, FP_OFF(paging_buffer), 4096);
pd_dblock = dalloc();
dwrite(paging_buffer, pd_dblock);
vfree(FP_SEG(pd) >> 8);
xms_free();
}
void page_in_everything(void)
{
int pdi;
unsigned pta, ptb;
valloc_initted = 0;
pd = MK_FP(valloc(VA_640) << 8, 0);
dread(paging_buffer, pd_dblock);
dfree(pd_dblock);
movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pd), 0, 4096);
for (pdi = 0; pdi < 1024; pdi++)
if (pd[pdi]) {
pta = valloc(VA_640);
ptb = (unsigned)(pd[pdi] >> 12);
dread(paging_buffer, ptb);
dfree(ptb);
movedata(_DS, FP_OFF(paging_buffer), pta << 8, 0, 4096);
pd[pdi] = (pd[pdi] & 0xFFF) | ((word32) pta << 12) | PT_P;
}
graphics_pt = (word32 far *) ((pd[0x380] & ~0xfff) << 12);
graphics_pt_lin = ptr2linear(graphics_pt);
}
int __fastcall emu_install(char *filename)
{
GNU_AOUT eh;
areas[A_emu].first_addr = EMU_TEXT + ARENA;
areas[A_emu].last_addr = areas[A_emu].first_addr - 1;
areas[A_emu].foffset = 0;
if (!filename)
return 0;
emu_f = open(filename, O_RDONLY | O_BINARY);
if (emu_f == -1) {
printf("Can't open 80387 emulator file <%s>\n", filename);
return 0;
}
read(emu_f, &eh, sizeof(eh));
areas[A_emu].last_addr += eh.tsize + eh.dsize + eh.bsize + 0x20;
return 1;
}
/* This is file VALLOC.C */
#define VA_FREE 0
#define VA_USED 1
#define DOS_PAGE 256 /* 1MB / 4KB = 256 Pages */
static word8 map[4096];
static word16 mem_used;
static word16 left_lo, left_hi;
static unsigned pn_lo_first, pn_lo_last, pn_hi_first, pn_hi_last;
static unsigned vcpi_flush_ok = 0;
#if TOPLINEINFO
static void valloc_update_status(void)
{
char buf[20];
int i;
if (!valloc_initted)
return;
sprintf(buf, "%5dk", mem_avail);
for (i = 0; i < 6; i++)
poke(screen_seg, (i + 70) * 2, buf[i] | 0x0a00);
sprintf(buf, "%5dk", mem_used);
for (i = 0; i < 6; i++)
poke(screen_seg, (i + 62) * 2, buf[i] | 0x0a00);
}
#endif
static void __pascal vset(unsigned i, int b)
{
register unsigned o, m;
m = 1 << (i & 7);
o = i >> 3;
if (b && !(map[o] & m)) {
#if TOPLINEINFO
mem_avail -= 4;
mem_used += 4;
valloc_update_status();
#endif
map[o] |= m;
} else if (map[o] & m) {
#if TOPLINEINFO
mem_avail += 4;
mem_used -= 4;
valloc_update_status();
#endif
map[o] &= ~m;
}
}
static int __pascal vtest(unsigned i)
{
register unsigned m;
m = 1 << (i & 7);
return map[i >> 3] & m;
}
static 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);
#if DEBUGGER
printf("XMS memory freed\n");
#endif
}
}
static void xms_alloc_init(void)
{
xms_extended_info *x = xms_query_extended_memory();
emb_off_t linear_base;
emb_size_K_t emb_size;
#if DEBUGGER
printf("XMS driver detected\n");
#endif
emb_size = x->max_free_block;
emb_handle = xms_emb_allocate(emb_size);
linear_base = xms_lock_emb(emb_handle);
pn_hi_first = (unsigned)((linear_base + 4095) / 4096);
pn_hi_last = pn_hi_first + emb_size / 4 - 1;
}
static void valloc_init(void)
{
unsigned char far *vdisk;
int has_vdisk = 1;
unsigned long vdisk_top;
unsigned i, lol;
struct REGPACK r;
if (vcpi_installed) {
pn_hi_first = 32767;
pn_hi_last = DOS_PAGE;
} else if (use_xms)
xms_alloc_init(); /* Try XMS allocation */
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) {
vdisk_top = vdisk[46] * 65536L + vdisk[45] * 256 + vdisk[44];
pn_hi_first = (unsigned)((vdisk_top + 4095) / 4096);
} else
pn_hi_first = 256;
}
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;
r.r_ax = 0x4800;
intr(0x21, &r); /* get the block */
pn_lo_first = (r.r_ax + 0xFF) >> 8; /* lowest real mem 4K block */
pn_lo_last = (r.r_ax + lol - 1) >> 8; /* highest real mem 4K block */
r.r_es = r.r_ax; /* free the block just allocated */
r.r_ax = 0x4900; /* because Turbo Debugger won't if we don't */
intr(0x21, &r);
mem_avail = 0;
for (i = 0; i < DOS_PAGE / 8; i++)
map[i] = 0xff; /* DOS Area */
for (; i < 4096; i++)
map[i] = (vcpi_installed) ? 0x00 : 0xff; /* Extened Memory Area */
for (i = pn_lo_first; i <= pn_lo_last; i++)
vset(i, VA_FREE);
for (i = pn_hi_first; i <= pn_hi_last; i++)
vset(i, VA_FREE);
vcpi_flush_ok = 1;
mem_used = 0;
left_lo = (pn_lo_last - pn_lo_first + 1) * 4;
left_hi = (vcpi_installed) ? vcpi_capacity() * 4 : (pn_hi_last - pn_hi_first + 1) * 4;
if (vcpi_installed)
mem_avail = left_lo + left_hi;
/* mem_avail = (pn_lo_last-pn_lo_first+1)*4 + (pn_hi_last-pn_hi_first+1)*4; */
#if DEBUGGER
if (debug_mode)
printf("%d Kb conventional, %d Kb extended - %d Kb total RAM available\n", left_lo, left_hi, mem_avail);
#endif
#if TOPLINEINFO
valloc_update_status();
#endif
valloc_initted = 1;
}
static unsigned __pascal valloc(where)
{
unsigned pn;
if (!valloc_initted)
valloc_init();
switch (where) {
case VA_640:
more_640:
for (pn = pn_lo_first; pn <= pn_lo_last; pn++)
if (vtest(pn) == VA_FREE) {
left_lo -= 4;
vset(pn, VA_USED);
return pn;
}
page_out();
goto more_640;
case VA_1M:
more_1m:
if (vcpi_installed) {
pn = vcpi_alloc();
if (pn) {
left_hi -= 4;
if (pn < pn_hi_first)
pn_hi_first = pn;
if (pn > pn_hi_last)
pn_hi_last = pn;
vset(pn, VA_USED);
return pn;
}
} else
for (pn = pn_hi_first; pn <= pn_hi_last; pn++)
if (vtest(pn) == VA_FREE) {
left_hi -= 4;
vset(pn, VA_USED);
return pn;
}
for (pn = pn_lo_first; pn <= pn_lo_last; pn++)
if (vtest(pn) == VA_FREE) {
left_lo -= 4;
vset(pn, VA_USED);
return pn;
}
page_out();
goto more_1m;
}
return 0;
}
static void __pascal vfree(unsigned pn)
{
if ((vcpi_installed) && (pn >= DOS_PAGE))
vcpi_free(pn);
vset(pn, VA_FREE);
}
void vcpi_flush(void)
{
word16 pn;
if (!vcpi_flush_ok)
return; /* Not Initaialized Map[] */
for (pn = pn_hi_first; pn <= pn_hi_last; pn++)
if (vtest(pn))
vcpi_free(pn);
#if DEBUGGER
printf("VCPI memory freed\n");
#endif
}
/* This is file DALLOC.C */
#define DA_FREE 0
#define DA_USED 1
#define MAX_DBLOCK 32760 /* 4095 * 8 -> 128 Mb */
static int dalloc_initted = 0;
static word8 dmap[4096];
static first_avail, last_avail;
static int dfile = -1;
#if TOPLINEINFO
static disk_used = 0;
#endif
static void __pascal dset(unsigned i, int b)
{
register unsigned o, m;
m = 1 << (i & 7);
o = i >> 3;
if (b)
dmap[o] |= m;
else
dmap[o] &= ~m;
}
static int dtest(unsigned i)
{
register unsigned m;
m = 1 << (i & 7);
return dmap[i >> 3] & m;
}
static char dfilename[80];
void dalloc_init(void)
{
int i;
char *tmp;
tmp = getenv("GO32TMP");
if (!tmp)
tmp = getenv("GCCTMP");
if (!tmp)
tmp = getenv("TMP");
if (!tmp)
tmp = getenv("TEMP");
if (!tmp)
tmp = "/";
i = strlen(tmp) - 1;
if ((tmp[i] == '/') || (tmp[i] == '\\'))
tmp[i] = '\0';
sprintf(dfilename, "%s/page%04x.386", tmp, _CS);
dfile = open(dfilename, O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IWRITE | S_IREAD);
if (dfile == -1) {
printf("Fatal! cannot open swap file %s\n", dfilename);
exit(1);
}
memset(dmap, 0, 4096);
first_avail = last_avail = 0;
dalloc_initted = 1;
}
void dalloc_uninit(void)
{
if (dfile == -1)
return;
close(dfile);
unlink(dfilename);
}
static unsigned dalloc(void)
{
#if TOPLINEINFO
char buf[8];
int i;
#endif
unsigned pn;
if (!dalloc_initted)
dalloc_init();
for (pn = first_avail; pn <= MAX_DBLOCK; pn++)
if (dtest(pn) == DA_FREE) {
dset(pn, DA_USED);
first_avail = pn + 1;
#if TOPLINEINFO
if (pn >= last_avail)
last_avail = pn + 1;
disk_used++;
sprintf(buf, "%5dk", disk_used * 4);
for (i = 0; i < 6; i++)
poke(screen_seg, (54 + i) * 2, buf[i] | 0x0c00);
#endif
return pn;
}
printf("Fatal: out of swap space!\n");
return 0;
}
static void __pascal dfree(unsigned pn)
{
#if TOPLINEINFO
char buf[8];
int i;
#endif
dset(pn, DA_FREE);
if (pn < first_avail)
first_avail = pn;
#if TOPLINEINFO
disk_used--;
sprintf(buf, "%5dk", disk_used * 4);
for (i = 0; i < 6; i++)
poke(screen_seg, (54 + i) * 2, buf[i] | 0x0c00);
#endif
}
static void __pascal dwrite(word8 * buf, unsigned block)
{
lseek(dfile, (long)block * 4096L, 0);
if (write(dfile, buf, 4096) < 4096) {
printf("Fatal! disk full writing to swap file\n");
exit(1);
}
}
static void __pascal dread(word8 * buf, unsigned block)
{
lseek(dfile, (long)block * 4096L, 0);
read(dfile, buf, 4096);
}