home *** CD-ROM | disk | FTP | other *** search
- /*
- ** VMEM - a virtual memory manager for the Amiga operating system
- **
- ** Version 0.1 ⌐1990 by Edward Hutchins
- ** Based in part on the SetCPU program by Dave Haynie
- ** Authors:
- **
- ** Edward Hutchins: eah1@cec1.wustl.edu
- ** Loren Rittle: l-rittle@uiuc.edu
- **
- ** Revisions:
- ** 10/29/91 cleaned up code somewhat - Ed.
- ** 12/19/91 made the spy faster with SpyPenCache - Ed.
- ** 12/19/91 code released as freeware under the GNU general public license - Ed.
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 1, or (at your option)
- ** any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- **
- */
-
- #include "vmem.h"
-
- /*
- ** typedefs and defines
- */
-
- #define VMEM_VERSION "0.4" /* vmem version */
- #define VMEM_NAME "virtual memory" /* memory pool name */
- #define VMEM_BASE 0x01000000 /* virt mem base addr */
- #define VMEM_PRI 20 /* allocation priority */
- #define DEF_SWAP_FILE_NAME "work:.VMEM_PAGES" /* should be SYS: */
- #define DEF_NUMFRAMES 0x80 /* 1M of frames */
- #define DEF_NUMPAGES 0x200 /* 4M of virt mem */
- #define INITIAL_SHIFT 5 /* 5 + 14 + 13 == 32 */
- #define PAGE_SIZE 0x2000 /* 8k pages */
- #define PAGE_SIZE_MASK 0x1FFF /* mask off 8k */
- #define PAGE_SIZE_INDEX 13 /* 8k page offset bits */
- #define PAGE_TABLE_INDEX 14 /* TIA index bits */
- #define PAGE_TABLE_MIN 0x800 /* 16M of 8k pages */
- #define PAGEDAEMON_PRI 50 /* VERY high priority */
- #define AGEING_PERIOD 100000 /* 0.1 second */
- #define FASTPUB (MEMF_FAST | MEMF_PUBLIC) /* fast public memory */
-
- /* spy stuff */
- #define WIDTH 320
- #define HEIGHT 32
- #define DEPTH 3
- #define MAX_PEN 8
-
- /*
- ** globals
- */
-
- struct ExecBase *ExecBase;
- struct GfxBase *GfxBase;
- struct IntuitionBase *IntuitionBase;
- struct Window *window;
- struct RastPort *RP;
-
- UWORD NumFrames = DEF_NUMFRAMES; /* number of frames */
- UWORD NumPages = DEF_NUMPAGES; /* number of pages */
- CPTR ROMBase; /* ROMs mapped to this RAM */
- CPTR FrameBase; /* frame table */
- PFRAME_DESC FrameTable; /* frame descriptors */
- PPD_SHORT PageTable; /* page table */
- CPTR SysBusErrHandler; /* default bus fault vector */
- ULONG SwapFile; /* handle to swap file */
- ULONG PageDaemonSig; /* daemon's signal */
- struct Task *PageDaemonTask; /* the pager (us for now) */
- struct MemHeader *FastMemHeader; /* public memory area */
- struct MinList PageFaultList; /* queue faults here */
- char SwapFileName[80]; /* swap file name */
- WORD PendingPageFaults; /* page faults to be served */
-
- /* this will break once NumPages gets parsed from the command line... */
- BYTE SpyPenCache[PAGE_TABLE_MIN + DEF_NUMPAGES];
-
- #define VMEM_LENGTH (NumPages * PAGE_SIZE) /* virt mem size */
- #define VMEM_END (VMEM_BASE + VMEM_LENGTH) /* end of virt mem */
-
- /* get a frame index from a page address */
- #define PAGE_TO_FRAME(pd) ((((pd)&PD_ADDR_MASK)-(ULONG)FrameBase)/PAGE_SIZE)
-
- /*
- ** locals
- */
-
- UWORD ctable[] =
- {0x0000, 0x0222, 0x0630, 0x0f00, 0x000f, 0x0070, 0x0304, 0x0740 };
-
- /* spy pen types (map to colors above) */
- enum { PEN_UNUSED, PEN_VIRT, PEN_INVALID, PEN_MOD,
- PEN_USED, PEN_WP, PEN_CI, PEN_FRAME };
-
- /*
- ** We don't need any termination routines
- */
-
- VOID MemCleanup(VOID) {}
-
- /*
- ** AllocBlocks - allocate memory aligned by lBound+1
- */
-
- static void *AllocBlocks( ULONG lSize, ULONG lBound )
- {
- void *mem, *aligned;
-
- if (!(mem = AllocMem( lSize + lBound, FASTPUB ))) return( NULL );
- Forbid();
- aligned = (void *)(((ULONG)mem + lBound) & ~(lBound));
- FreeMem( mem, lSize + lBound );
- mem = AllocAbs( lSize, aligned );
- Permit();
- return( mem );
- }
-
- /*
- ** AllocVMem - find the fast memory list, allocate needed physical space
- */
-
- BOOL AllocVMem(VOID)
- {
- ULONG FrameSize = NumFrames * PAGE_SIZE;
- ULONG FrameTableSize = NumFrames * sizeof(FRAME_DESC);
- ULONG PageTableSize = (PAGE_TABLE_MIN + NumPages) * sizeof(PD_SHORT);
- BOOL bSuccess = FALSE;
-
- /* prevent mucking about with the MemLists */
- Disable();
-
- /* find a fast+public memory MemHeader for the fault nodes */
- /* note: this works because lh_Head and ln_Succ are the same */
- FastMemHeader = (struct MemHeader *)&(ExecBase->MemList);
- if (FastMemHeader == NULL)
- {
- Enable();
- goto BailOut;
- }
-
- for (;;)
- {
- FastMemHeader = (struct MemHeader *) FastMemHeader->mh_Node.ln_Succ;
- if (FastMemHeader == NULL) goto BailOut;
- if ((FastMemHeader->mh_Attributes & FASTPUB) == FASTPUB) break;
- }
-
- Enable();
-
- /* allocate in this order to minimize fragging */
- if (!(FrameBase = (CPTR)AllocBlocks( FrameSize, PAGE_SIZE_MASK )))
- goto BailOut;
-
- if (!(ROMBase = (CPTR)AllocBlocks( ROMSIZE, PAGE_SIZE_MASK )))
- goto BailOut;
-
- /* the !@#%!&* CRP needs to be aligned to 16-byte boundaries */
- if (!(PageTable = (PPD_SHORT)AllocBlocks( PageTableSize, 15 )))
- goto BailOut;
-
- if (!(FrameTable = (PFRAME_DESC)AllocBlocks( FrameTableSize, 15 )))
- goto BailOut;
-
- bSuccess = TRUE;
-
- /* come here to bomb */
- BailOut:
- return (bSuccess);
- }
-
- /*
- ** SetPageTableFlags - set flags in the page table over a range of addresses
- */
-
- VOID SetPageTableFlags(ULONG begad, ULONG endad, ULONG Flags)
- {
- while (begad < endad)
- {
- PageTable[begad / PAGE_SIZE] |= Flags;
- begad += PAGE_SIZE;
- }
- }
-
- /*
- ** ClearPageTableFlags - clear flags in the page table over a range of addresses
- */
-
- VOID ClearPageTableFlags(ULONG begad, ULONG endad, ULONG Flags)
- {
- while (begad < endad)
- {
- PageTable[begad / PAGE_SIZE] &= ~Flags;
- begad += PAGE_SIZE;
- }
- }
-
- /*
- ** This routine creates the Fast ROM and sets up memory.
- **
- ** Address:
- ** 31 23 15 7 0
- ** +------+--------------+----------+
- ** | IS 5 | TIA 14 | PS 13 | 13 bits = 8K pages
- ** +------+--------------+----------+
- **
- ** First 5 bits of logical address -> shifted into the bit bucket
- ** next 14 bits of logical address -> index into PageTable (level A)
- ** last 13 bits of logical address -> offset into page
- */
-
- BOOL CreatePageTable(VOID)
- {
- ULONG i, myCRP[2], myTC;
-
- #if defined(DEBUG)
- printf("AllocVMem()\n");
- #endif
-
- /* allocate all needed memory */
- if (!AllocVMem()) return (FALSE);
-
- #if defined(DEBUG)
- printf("CopyMemQuick()\n");
- #endif
-
- /* Here I set up the ROM, as quickly as possible! */
- CopyMemQuick((ULONG *)ROMBASE, (ULONG *)ROMBase, ROMSIZE);
-
- #if defined(DEBUG)
- printf("Translation setup...\n");
- #endif
-
- /* transparent translation of existing address space... */
- for (i = 0x00000000; i < ROMBASE; i += PAGE_SIZE)
- {
- PageTable[i / PAGE_SIZE] = PD_ADDR(i) | PD_DT_PAGE;
- }
-
- /* ...except re-map the ROM image and write protect it... */
- for (i = ROMBASE; i < 0x00FFFFFF; i += PAGE_SIZE)
- {
- PageTable[i / PAGE_SIZE] = PD_ADDR(ROMBase + (i - ROMBASE)) | PD_WP | PD_DT_PAGE;
- }
-
- /* ...as well as the physical memory containing the ROM image */
- SetPageTableFlags( (ULONG)ROMBase, (ULONG)ROMBase + ROMSIZE, PD_WP );
-
- /*
- ** cache-inhibit chip memory and custom registers
- **
- ** $00000000
- ** | 2M chip memory, cache inhibit
- ** $001FFFFF
- ** $00200000
- ** | 8M fast ram, public
- ** $00BFFFFF
- ** $00A00000
- ** | 2M reserved area, cache inhibit anyway
- ** $00BFFFFF
- ** $00C00000
- ** | 1M fast (slow really) ram on some machines, public
- ** $00CFFFFF
- ** $00D00000
- ** | 2M custom chip area, cache inhibit
- ** $00F7FFFF
- ** $00F80000
- ** | 256K system rom area (part mapped to FASTROM)
- ** $00FFFFFF
- ** $01000000
- ** | (up to) 16M virtual memory area
- ** $01FFFFFF
- */
-
- /* set up cache-inhibit */
- SetPageTableFlags(0x00000000, 0x001FFFFF, PD_CI);
- SetPageTableFlags(0x00A00000, 0x00BFFFFF, PD_CI);
- SetPageTableFlags(0x00D00000, 0x00F7FFFF, PD_CI);
-
- /* map the first of the virtual pages to the available frames */
- for (i = 0; i < NumFrames; ++i)
- {
- FrameTable[i].Age = 0;
- FrameTable[i].PageIndex = PAGE_TABLE_MIN + i;
- PageTable[PAGE_TABLE_MIN + i] = PD_ADDR(FrameBase + (i * PAGE_SIZE)) | PD_DT_PAGE;
- }
-
- /* clear out the rest of virtual memory to invalid status */
- for (i = NumFrames; i < NumPages; ++i)
- {
- PageTable[PAGE_TABLE_MIN + i] = PD_DT_INVALID;
- }
-
- /*
- ** Now I have to set up the MMU. The CPU Root Pointer tells the MMU about
- ** the table I've set up, and the Translation Control register will turn
- ** the thing on. Note that the first half of the CRP is control data, the
- ** second the address of my table.
- */
-
- #if defined(DEBUG)
- printf("CRP and TC Setup...\n");
- #endif
-
- Disable();
- SetTC(0);
- myCRP[0] = CRP_LIMIT(PAGE_TABLE_MIN + NumPages - 1) | CRP_SG | CRP_DT_V4BYTE;
- myCRP[1] = (ULONG) PageTable;
- SetCRP(myCRP);
- myTC = TC_ENB | TC_IS(INITIAL_SHIFT) | TC_TIA(PAGE_TABLE_INDEX) |
- TC_TIB(0) | TC_TIC(0) | TC_TID(0) | TC_PS(PAGE_SIZE_INDEX);
- SetTC(myTC);
- Enable();
-
- return (TRUE);
- }
-
- /*
- ** AddVirtMem - add the virtual memory to the system free list
- */
-
- VOID AddVirtMem(VOID)
- {
- static char VirtMemName[] = VMEM_NAME;
-
- /* the page table better have a valid descriptor for the first page... */
- AddMemList(VMEM_LENGTH, MEMF_FAST, VMEM_PRI, VMEM_BASE, VirtMemName);
- }
-
- /*
- ** ShowFrameTableAges - show the page age table
- */
-
- VOID ShowFrameTableAges(VOID)
- {
- PFRAME_DESC pFrame = &FrameTable[0];
- PFRAME_DESC pFrameEnd = &FrameTable[NumFrames];
- PFRAME_DESC pOldest = pFrame;
- UWORD FrameIndex = 0;
-
- while (pFrame < pFrameEnd)
- {
- printf("%d(%4.4x,%4.4x) ", FrameIndex, pFrame->Age, pFrame->PageIndex);
- if (FrameIndex % 4 == 0) printf("\n");
- ++FrameIndex, ++pFrame;
- }
- printf("\n\n");
- }
-
- /*
- ** AgeFrameTable - age the frame table
- */
-
- VOID AgeFrameTable(VOID)
- {
- PFRAME_DESC pFrame = &FrameTable[0];
- PFRAME_DESC pFrameEnd = &FrameTable[NumFrames];
-
- Disable();
- while (pFrame < pFrameEnd)
- {
- PPD_SHORT pTbl = &PageTable[pFrame->PageIndex];
- if (*pTbl & PD_USED)
- {
- *pTbl &= ~PD_USED;
- pFrame->Age /= 2;
- }
- else if (pFrame->Age < AGE_MAX) ++(pFrame->Age);
- ++pFrame;
- }
- Enable();
- }
-
- /*
- ** CreateSwapFile - open and allocate the swap file
- **
- ** Call AFTER AllocVMem is done
- */
-
- BOOL CreateSwapFile(VOID)
- {
- ULONG Offset, SizeNeeded = NumPages * PAGE_SIZE;
- ULONG BuffSize = NumFrames * PAGE_SIZE;
- BOOL bSuccess = FALSE;
-
- #if defined(DEBUG)
- printf("opening file, ");
- #endif
-
- /* get an exclusive lock on this file */
- SwapFile = Open(SwapFileName, MODE_OLDFILE);
- if (SwapFile == 0)
- {
- SwapFile = Open(SwapFileName, MODE_NEWFILE);
- if (SwapFile == 0) return (FALSE);
- }
-
- /* make sure the file is at least big enough */
- if (Seek(SwapFile, 0, OFFSET_END) == -1) goto Abort;
- if ((Offset = Seek(SwapFile, 0, OFFSET_CURRENT)) == -1) goto Abort;
-
- /* is it already big enough? */
- if (Offset >= SizeNeeded)
- {
- bSuccess = TRUE;
- goto Abort;
- }
-
- #if defined(DEBUG)
- printf("clearing buffer, ");
- #endif
-
- /* clear out the buffer */
- {
- char *p = FrameBase;
- char *e = FrameBase + BuffSize;
- while (p < e) *p++ = '\0';
- }
-
- SizeNeeded -= Offset;
-
- #if defined(DEBUG)
- printf("writing (%ld) ", SizeNeeded);
- #endif
-
- while (SizeNeeded > BuffSize)
- {
- if (Write(SwapFile, FrameBase, BuffSize) != BuffSize) goto Abort;
- SizeNeeded -= BuffSize;
-
- #if defined(DEBUG)
- printf(". ");
- #endif
- }
-
- if (Write(SwapFile, FrameBase, SizeNeeded) == SizeNeeded) bSuccess = TRUE;
-
- Abort:
-
- #if defined(DEBUG)
- printf("closing\n");
- #endif
-
- Close(SwapFile);
- return (bSuccess);
- }
-
- /*
- ** StealPage - choose the oldest page and discard it, return it's index
- */
-
- UWORD StealPage(VOID)
- {
- PFRAME_DESC pFrame = &FrameTable[0];
- PFRAME_DESC pFrameEnd = &FrameTable[NumFrames];
- PFRAME_DESC pOldest = pFrame;
- UWORD Wage = WAGE(pOldest);
- UWORD FrameIndex;
- PD_SHORT pd;
-
- Disable();
-
- /* find the oldest page */
- while (++pFrame < pFrameEnd) if (WAGE(pFrame) > Wage)
- {
- pOldest = pFrame;
- Wage = WAGE(pOldest);
- }
-
- FrameIndex = (((ULONG) pOldest - (ULONG) FrameTable) / sizeof(FRAME_DESC));
-
- /* mark the stolen page as invalid */
- pd = PageTable[pOldest->PageIndex];
- PageTable[pOldest->PageIndex] = PD_DT_INVALID;
-
- Enable();
-
- /* if the stolen page has been modified, we need to save it */
- if (pd & PD_MOD)
- {
- ULONG FrameOffset = FrameIndex * PAGE_SIZE;
- ULONG PageOffset = (pOldest->PageIndex * PAGE_SIZE) - VMEM_BASE;
-
- if ((SwapFile = Open(SwapFileName, MODE_OLDFILE)) == 0)
- {
- #if defined(DEBUG)
- printf("StealPage open file failed! (%s)\n", SwapFileName);
- #endif
- Alert(-1L, 1);
- }
- Seek(SwapFile, PageOffset, OFFSET_BEGINNING);
- Write(SwapFile, FrameBase + FrameOffset, PAGE_SIZE);
- Close(SwapFile);
-
- #if defined(DEBUG_PAGING)
- printf("page %d (%lx) swapped out, ", pOldest->PageIndex, PageOffset);
- #endif
- }
-
- return (FrameIndex);
- }
-
- /*
- ** LockPage - check if a page is swapped in, and lock it if so
- */
-
- BOOL LockPage(CPTR Address)
- {
- PD_SHORT pd;
-
- if (Address < VMEM_BASE) return (TRUE);
-
- pd = PageTable[Address / PAGE_SIZE];
-
- /* the page is swapped out, so swap it in later */
- if ((pd & PD_DT_MASK) == PD_DT_INVALID) return (FALSE);
-
- /* hopefully we won't get paged out right away */
- FrameTable[PAGE_TO_FRAME(pd)].Age = 0;
- return (TRUE);
- }
-
- /*
- ** LoadPage - load a swapped out page, stealing unlocked pages only
- */
-
- VOID LoadPage(CPTR Address)
- {
- UWORD PageIndex = Address / PAGE_SIZE;
- ULONG PageOffset = (PageIndex * PAGE_SIZE) - VMEM_BASE;
- UWORD FrameIndex;
- ULONG FrameOffset;
-
- /* has this page already been fixed? */
- if ((PageTable[PageIndex] & PD_DT_MASK) == PD_DT_PAGE) return;
-
- FrameOffset = (FrameIndex = StealPage()) * PAGE_SIZE;
-
- if ((SwapFile = Open(SwapFileName, MODE_OLDFILE)) == 0)
- {
- #if defined(DEBUG)
- printf("LoadPage open file failed! (%s)\n", SwapFileName);
- #endif
- Alert(-1L, 2);
- }
- Seek(SwapFile, PageOffset, OFFSET_BEGINNING);
- Read(SwapFile, FrameBase + FrameOffset, PAGE_SIZE);
- Close(SwapFile);
-
- #if defined(DEBUG_PAGING)
- printf("page %d (%lx) swapped in\n", PageIndex, PageOffset);
- #endif
-
- FrameTable[FrameIndex].Age = 0;
- FrameTable[FrameIndex].PageIndex = PageIndex;
- PageTable[PageIndex] = PD_ADDR(FrameBase + FrameOffset) | PD_DT_PAGE;
- }
-
- /*
- ** CorrectPageFault - lock and load all needed pages, signal task to restart
- */
-
- BOOL CorrectPageFault(VOID)
- {
- PFaultNode FaultNode;
- CPTR Faults[4]; /* Data Fault (LSB and MSB), stage B, stage C */
- UWORD FaultCount = 0;
- UWORD Format;
- UWORD PPF;
- static UWORD OldFormat = 0;
- static UWORD SSW = 0;
- UWORD bDiff = FALSE;
-
- Disable();
- FaultNode = (PFaultNode) RemHead((struct List *) & PageFaultList);
- Enable();
- if (!FaultNode) return (FALSE);
-
- Format = FaultNode->Fault.S.VectorOffset & SF_FORMAT_MASK;
-
- #if defined(DEBUG)
- PPF = --PendingPageFaults;
- if (PPF)
- printf("PPF=%d ", PPF);
- if (Format != OldFormat)
- OldFormat = Format, bDiff = TRUE;
- if (FaultNode->Fault.S.SpecialStatusReg != SSW)
- SSW = FaultNode->Fault.S.SpecialStatusReg, bDiff = TRUE;
- if (bDiff)
- printf("Format [%4.4x] SSW = %4.4x\n", OldFormat, SSW);
- #endif
-
- /* Data Fault is the same for both long and short frames */
- if (!LockPage(FaultNode->Fault.S.DataCycleFaultAddr))
- Faults[FaultCount++] = FaultNode->Fault.S.DataCycleFaultAddr;
-
- /* check LSB of Data Fault */
- if (!LockPage(FaultNode->Fault.S.DataCycleFaultAddr + 3))
- Faults[FaultCount++] = FaultNode->Fault.S.DataCycleFaultAddr + 3;
-
- if (Format == SSF_FORMAT)
- {
- /* stage B address is PC+4, stage C is PC+2 */
- if (!LockPage(FaultNode->Fault.S.PC + 4))
- Faults[FaultCount++] = FaultNode->Fault.S.PC + 4;
- if (!LockPage(FaultNode->Fault.S.PC + 2))
- Faults[FaultCount++] = FaultNode->Fault.S.PC + 2;
- }
- else /* must be LSF_FORMAT */
- {
- /* stage B address is in stack frame, stage C is at B-2 */
- if (!LockPage(FaultNode->Fault.L.StageBAddress))
- Faults[FaultCount++] = FaultNode->Fault.L.StageBAddress;
- if (!LockPage(FaultNode->Fault.L.StageBAddress - 2))
- Faults[FaultCount++] = FaultNode->Fault.L.StageBAddress - 2;
- }
-
- /* load all faulted pages */
- while (FaultCount--) LoadPage(Faults[FaultCount]);
-
- /* wake up the sleeping task (it does the rest) */
- Signal(FaultNode->FaultedTask, 1 << FaultNode->RestartSigNum);
- return (TRUE);
- }
-
- /*
- ** ShowUsage - explain VMEM
- */
-
- VOID ShowUsage(VOID)
- {
- printf("\2330;33mVMem " VMEM_VERSION " ⌐1990 by Edward Hutchins\2330m\n");
- printf("Usage: VMem [-f <swapfile>] [-p <phys pages>] [-v <virt pages>]\n");
- printf("Note: the default swap file is " DEF_SWAP_FILE_NAME "\n");
- }
-
- /*
- ** Spy - spy on memory usage
- */
-
- void Spy(void)
- {
- UWORD totalpages = PAGE_TABLE_MIN + NumPages;
- WORD xoff = WIDTH - totalpages / 16;
- while (1)
- {
- UWORD i = totalpages;
- while (i--)
- {
- PD_SHORT pd = PageTable[i];
- BYTE pen;
-
- if (i < PAGE_TABLE_MIN)
- {
- PageTable[i] &= ~(PD_MOD | PD_USED);
- pen = PEN_UNUSED;
- }
- else pen = PEN_VIRT;
- if ((pd & PD_DT_MASK) == PD_DT_INVALID) pen = PEN_INVALID;
- else if (pd & PD_MOD) pen = PEN_MOD;
- else if (pd & PD_USED) pen = PEN_USED;
- else if (pd & PD_WP) pen = PEN_WP;
- else if (pd & PD_CI) pen = PEN_CI;
- if (pen != SpyPenCache[i])
- {
- SetAPen(RP, SpyPenCache[i] = pen);
- WritePixel(RP, 80 + (i / 16), 8 + (i & 15));
- }
- }
- }
- }
-
- /*
- ** SetupSpy - create the spy task
- */
-
- void SetupSpy(void)
- {
- if (!(window = OpenScrn(WIDTH, HEIGHT, DEPTH, 0, 0))) return;
- /* sig = 1 << (window->UserPort->mp_SigBit); */
- LoadRGB4(ViewPortAddress(window), ctable, MAX_PEN);
- RP = window->RPort;
- SetRast(RP, PEN_FRAME);
- CreateTask ("VMEM Spy", -1L, Spy, 4096);
- }
-
- /*
- ** OpenLibs - open the needed libraries
- */
-
- void OpenLibs( void )
- {
- /* we need to open this for some reason */
- ExecBase = (struct ExecBase *) OpenLibrary("exec.library", 0);
- if (!ExecBase) exit( 20 );
-
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
- if (!GfxBase) exit( 20 );
-
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
- if (!IntuitionBase) exit( 20 );
- }
-
- /*
- ** main - VMEM main entry point
- */
-
- int main(int argc, char *argv[])
- {
- ULONG cacr, cpu, fpu, mmu = 0;
- struct MsgPort *AgePort = NULL;
- struct timerequest *TimerReq = NULL;
- ULONG AgeSig;
- ULONG Signals;
- UBYTE DaemonSigNum;
-
- OpenLibs();
-
- #if defined(DEBUG)
- printf("This is the debugging version of VMEM\n\n");
- #endif
-
- /* If they're just asking for help */
- if (argc >= 2 && argv[1][0] == '?')
- {
- ShowUsage();
- exit(0);
- }
-
- /* get the system setup */
- cpu = GetCPUType();
- fpu = GetFPUType();
- mmu = GetMMUType();
-
- /* trap silly users */
- if (cpu < 68020 || !mmu)
- {
- printf("Sorry, your system doesn't have the balls for VMEM!\n");
- exit(0);
- }
-
- /* allocate the paging daemon's signal */
- if ((DaemonSigNum = AllocSignal(-1)) == -1) goto Abort;
-
- /* allocate the ageing timer port */
- AgePort = CreatePort(NULL, 0);
- if (AgePort == NULL) goto Abort;
- TimerReq = (PTIMER_REQ) CreateExtIO(AgePort, sizeof(TIMER_REQ));
- if (TimerReq == NULL) goto Abort;
- if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)TimerReq, 0)) goto Abort;
-
- /* parse arguments someday... */
- strcpy(SwapFileName, DEF_SWAP_FILE_NAME);
-
- #if 0
- if (argc > 1)
- {
- for (i = 1; i < argc; ++i)
- {
- }
- }
- #endif
-
- /* set up both the instruction and data caches */
- cacr = (CACR_INST | CACR_DATA) << CACR_WALLOC;
- cacr |= (CACR_INST | CACR_DATA) << CACR_BURST;
- cacr |= (CACR_INST | CACR_DATA) << CACR_CLEAR;
- cacr |= (CACR_INST | CACR_DATA) << CACR_ENABLE;
- SetCACR(cacr);
-
- #if defined(DEBUG)
- printf("MMU Check\n");
- #endif
-
- /* see if someone's using the MMU already */
- if (GetTC() & TC_ENB) printf("MMU already in use, resetting...\n");
-
- #if defined(DEBUG)
- printf("CreatePageTable()\n");
- #endif
-
- /* create the low-level paging tables and set up the MMU */
- if (!CreatePageTable())
- {
- printf("Error: not enough physical memory\n");
- goto Abort;
- }
-
- #if defined(DEBUG)
- printf("CreateSwapFile()\n");
- #endif
-
- /* open the swap file and make sure it's big enough */
- if (!CreateSwapFile())
- {
- printf("Error: failed to create swap file\n");
- goto Abort;
- }
-
- /* initialize misc variables */
- NewList((struct List *) & PageFaultList);
- PageDaemonTask = FindTask(NULL);
- PageDaemonSig = 1 << DaemonSigNum;
- AgeSig = 1 << AgePort->mp_SigBit;
-
- /* queue a timer request to get us started */
- TimerReq->tr_node.io_Command = TR_ADDREQUEST;
- TimerReq->tr_time.tv_secs = 0;
- TimerReq->tr_time.tv_micro = AGEING_PERIOD;
- SendIO((struct IORequest *) TimerReq);
-
- /*
- ** The point of no return...
- */
-
- SetupSpy();
-
- SetTaskPri(PageDaemonTask, PAGEDAEMON_PRI);
-
- #if defined(DEBUG)
- printf("InsertFaultHandler()\n");
- #endif
-
- InsertFaultHandler();
-
- #if defined(DEBUG)
- printf("AddVirtMem()\n");
- #endif
-
- AddVirtMem();
-
-
- /*
- ** This task never exits (system failure would result)
- */
-
- #if defined(DEBUG)
- printf("Waiting on %lx\n", PageDaemonSig | AgeSig);
- #endif
-
- for (;;)
- {
- Signals = Wait(PageDaemonSig | AgeSig);
-
- if (Signals & AgeSig)
- {
- #if defined(DEBUG_AGEING)
- static int nCnt = 0;
- if (nCnt++ % 50 == 0) ShowFrameTableAges();
- #endif
-
- GetMsg(AgePort);
- AgeFrameTable();
- TimerReq->tr_node.io_Command = TR_ADDREQUEST;
- TimerReq->tr_time.tv_secs = 0;
- TimerReq->tr_time.tv_micro = AGEING_PERIOD;
- SendIO((struct IORequest *) TimerReq);
- }
-
- if (Signals & PageDaemonSig) while (CorrectPageFault()) ;
- }
-
- Abort: /* we only come here if there was a problem */
- if (DaemonSigNum != -1) FreeSignal(DaemonSigNum);
- if (AgePort) DeletePort(AgePort);
- if (TimerReq) DeleteExtIO((struct IORequest *) TimerReq);
- exit(30);
- }
-