home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 4
/
DATAFILE_PDCD4.iso
/
utilities
/
utilst
/
virtual
/
!Virtual
/
c
/
pager
< prev
next >
Wrap
Text File
|
1993-07-06
|
13KB
|
536 lines
#include "swis.h"
#include "swiv.h"
#include "wimp.h"
#include "virtual.h"
#include "lib.h"
#include "output.h"
#include "pager.h"
/* #define DEBUG */
void Initourmem(WKSP *w)
{
int i;
w->stacktop = (char *)alloc(STACKSIZE)+STACKSIZE;
swi(OS_ReadMemMapInfo, OUT(R0|R1), &w->pagesize, &w->numpages);
#ifndef FIXED_2MB
w->pageshift = w->pagesize == K32 ? 15 : 13;
#else
w->pageshift = 15;
if (w->pagesize == K32/2) w->pageshift = 14;
if (w->pagesize == K32/4) w->pageshift = 13;
#endif
w->numplaces = PLACE(M24);
w->ourmem = alloc(sizeof(int) * w->numplaces);
w->oldpages = alloc(sizeof(PAGEENTRY)*(w->numpages + 1));
w->newpages = alloc(sizeof(PAGEENTRY)*(w->numpages + 1));
FindPages(w);
w->nslots = 0; /* page file empty */
w->index = alloc(sizeof(int)*w->numplaces);
for ( i=PLACE(K32); i<w->numplaces; i++)
{ w->ourmem[i] = TAGLOC(ABORT, 0);
}
w->losepage = 0;
}
void SetWimpMemMap(WKSP *w)
{
int i;
#ifdef DEBUG
printf("Places %d..%d match wimp map\n",PLACE(K32),w->numourpages+PLACE(K32));
#endif
for ( i = 0; i<w->numourpages; i++ )
{ w->newpages[i].addr = ADDR(i)+K32;
w->newpages[i].access = ACCESS_READWRITE;
w->ourmem[i+PLACE(K32)] = TAGLOC(DIRTY,i);
}
for ( i=w->numourpages+PLACE(K32); i<w->numplaces; i++ )
w->ourmem[i] = TAGLOC(ABORT, 0);
for (i=0;i<w->nslots;i++)
w->index[i] = -1;
}
void Finishourmem(WKSP *w)
{
free(w->oldpages);
free(w->newpages);
free(w->ourmem);
free(w->index);
}
int SetVirtualSlot(WKSP *w, int size)
{ int i,m;
i = PLACE(K32);
m = i + PLACE(size);
#ifdef DEBUG
printf("Places %d..%d abort->zerofill\n",i,m);
#endif
for (;i<m;i++)
if (TAG(w->ourmem[i])==ABORT)
w->ourmem[i] = TAGLOC(ZERO,0);
return size;
}
void virtualmem(WKSP *w)
{
swi(OS_SetMemMapEntries, IN(R0), w->newpages);
}
void normalmem(WKSP *w)
{
swi(OS_SetMemMapEntries, IN(R0), w->oldpages);
}
/* Find us a set of pysical pages, preserving newpages[0..numourpages].addr,access */
void FindPages(WKSP *w)
{
int i;
int appspace;
int a, b;
for (i = 0; i<w->numpages ; i++)
w->oldpages[i].pagenum = i;
w->oldpages[w->numpages].pagenum = -1;
swi(OS_ReadMemMapEntries, IN(R0), w->oldpages);
swi(OS_ChangeEnvironment, IN(R0|R1)|OUT(R1), 14, 0, &appspace);
w->numourpages = PLACE(appspace - K32);
b = w->numourpages; /* We accumulate pages that must be moved out the way here */
for (i = 0; i<w->numpages; i++)
{ if (w->oldpages[i].addr < K32) /* OS workspace will get protected */
/*w->newpages[b++] = w->oldpages[i] */;
else if (w->oldpages[i].addr < appspace) /* Useable page */
{ a = PLACE(w->oldpages[i].addr-K32); /* its current place */
w->newpages[a].pagenum = i; /* it becomes our page */
}
else if (w->oldpages[i].addr < M24) /* page needs moving */
w->newpages[b++] = w->oldpages[i];
}
for (i=0; i<w->numourpages; i++)
{ w->oldpages[i].pagenum = w->newpages[i].pagenum;
w->oldpages[i].addr = ADDR(i)+K32;
w->oldpages[i].access = ACCESS_READWRITE;
}
for (i = w->numourpages; i<b; i++)
{ w->oldpages[i] = w->newpages[i];
if (w->newpages[i].addr<K32)
w->newpages[i].access = ACCESS_READONLY;
else
{ w->newpages[i].addr = DUMPADDR;
w->newpages[i].access = ACCESS_BAD;
} }
w->oldpages[b].pagenum = -1;
w->newpages[b].pagenum = -1;
}
static int pageout(WKSP *w, int page, int addr)
{
int place, Normaddr, slot;
place = PLACE(addr);
Normaddr = w->oldpages[page].addr;
slot = LOC(w->ourmem[place]);
switch (TAG(w->ourmem[place]))
{ case DIRTY:
for (slot = 0; slot<w->nslots; slot++)
if (w->index[slot] == -1)
break;
if (slot>=w->nslots)
{ w->nslots = slot+1;
#ifdef DEBUG
printf("nslots = %d\n",w->nslots);
#endif
}
swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 1, w->pagefile, Normaddr, w->pagesize, ADDR(slot));
/* FALL THROUGH */
case SAVED:
w->index[slot] = place;
w->ourmem[place] = TAGLOC(PAGED, slot);
break;
default:
printf("*** ILLEGAL page out tag page %d addr %d place %d Normaddr %d slot %d tag %d\n",
page,addr,place,Normaddr,slot,TAG(w->ourmem[place]));
RealDoOff(w);
break;
}
#ifdef DEBUG
printf("Paging place %d out from page %d to slot %d\n",place,page,slot);
#endif
return page;
}
static int findpageout(WKSP *w)
{
int addr, page;
loop:
page = w->losepage;
if (++w->losepage >= w->numourpages)
w->losepage = 0;
addr = w->newpages[page].addr;
if (addr == DUMPADDR)
return page;
if (addr & LOCKADDRBIT)
goto loop;
return pageout(w,page,addr);
}
static void pagein(WKSP *w, int page, int place, int write)
{ int Normaddr = w->oldpages[page].addr;
int slot = LOC(w->ourmem[place]);
swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, w->pagefile, Normaddr, w->pagesize, ADDR(slot));
w->newpages[page].addr = ADDR(place);
if (write)
{ w->newpages[page].access = ACCESS_READWRITE;
w->index[slot] = -1;
w->ourmem[place] = TAGLOC(DIRTY, page);
}
else
{ w->newpages[page].access = ACCESS_READONLY;
w->index[slot] = page;
w->ourmem[place] = TAGLOC(SAVED, slot);
}
#ifdef DEBUG
printf("Paging place %d in to page %d from slot %d %s",place,page,slot,write?"writeable":"readonly");
#endif
}
#ifdef FIXED_SYSTEMCALL_VERSION_FO
/*
* First page out all DIRTY places whose address is not as RISC OS expects
* Then page in all place which should be in that page.
*/
void FixMemoryPages(WKSP *w)
{
int i;
for (i = 0; i < w->numourpages; i++)
if (w->newpages[i].addr != ADDR(i) + K32 &&
w->newpages[i].access != ACCESS_BAD)
switch (TAG(w->ourmem[PLACE(w->newpages[i].addr)])) {
case DIRTY:
pageout(w, i, w->newpages[i].addr);
break;
} /* switch */
for (i = 0; i < w->numourpages; i++) {
if (w->newpages[i].addr != ADDR(i) + K32) {
switch (TAG(w->ourmem[i+PLACE(K32)])) {
case PAGED:
pagein(w, i, i + PLACE(K32), 1);
break;
case ZERO:
/*
* This page was just recieved from the wimp by a wimplsot drag.
* I'm not really sure if the tag, the place recieves here
* should be DIRTY; maybe ZERO is ok. But, to be consistent with Brian's
* code in SetWimpMemMap, all places paged in at the right page,
* get the DIRTY tag.
*/
w->ourmem[i+PLACE(K32)] = TAGLOC(DIRTY, i);
w->newpages[i].addr = ADDR(i) + K32;
w->newpages[i].access = ACCESS_READWRITE;
break;
} /* switch */
}
}
}
#endif
void SetRealMem(WKSP*w, int size)
{
int newnumourpages=PLACE(size);
int i,newslot;
if (newnumourpages<2)
newnumourpages=2;
if (newnumourpages!=w->numourpages)
#ifndef FIXED_SYSTEMCALL_VERSION_FO
{ for (i = w->numourpages; i>newnumourpages; )
{ --i;
if (w->newpages[i].addr!=DUMPADDR)
pageout(w, i, w->newpages[i].addr);
}
w->numourpages = i;
#else
{ for (i = newnumourpages; i < w->numourpages; i++)
{
if (w->newpages[i].addr!=DUMPADDR)
pageout(w, i, w->newpages[i].addr);
}
#endif
swi(Wimp_SlotSize,IN(R0|R1)|OUT(R0),ADDR(newnumourpages),-1,&newslot);
newnumourpages = PLACE(newslot);
for (i = w->numourpages; i<newnumourpages; i++)
{ w->newpages[i].addr=DUMPADDR;
w->newpages[i].access=ACCESS_BAD;
}
#ifndef FIXED_SYSTEMCALL_VERSION_FO
w->losepage = w->numourpages<i?w->numourpages:0;
w->numourpages = i;
#else
/*
* When the user drags our slotbar, we often will receive more than one
* wimp_MSETSLOT message at once. In the old code, w->losepage would then
* be set at the *end* of a big block of DUMPADDR pages. This is a waste.
* The code below ensures w->losepage is always on the first DUMPADDR page.
*/
if (w->numourpages < newnumourpages) {
for (i = 0; i < newnumourpages; i++)
if (w->newpages[i].addr == DUMPADDR) {
w->losepage = i;
break;
}
}
else
w->losepage = 0;
w->numourpages = newnumourpages;
#endif
#ifdef DEBUG
printf("numourpages=%d\n",newnumourpages);
#endif
} }
static int GetPlace(WKSP *w, int pl