/*
C Initialization program init1.c.
This module has two parts:
- a subroutine named init←map called by the assembly program init0.s This subroutine sets the Sparc Map and finds out the size of the memory. This has to be done wery early in order to set the Stack Pointer. *** DANGER Temporary changes the mapping of page 0 DANGER ***
- a routine named init1. The program init0.s branch to this routine after completion of its job. Any futher initialization is done here. Control is given to main at the end of init1.
*/
#include "SparcSoftcard.h"
#include "SparcSoftcardOps.h"
void debug(), initMonitor();
/* Initialize a MapEntry with flags clear and the VM space name provided. */
static void EntryInit (entryPointer, name)
SparcSoftcardOps←MapEntry *entryPointer;
SparcSoftcardOps←VMSpaceName name;
{
entryPointer->flags.readOnly = FALSE;
entryPointer->flags.referenced = FALSE;
entryPointer->flags.dirty = FALSE;
entryPointer->flags.nonCachable = FALSE;
entryPointer->flags.interrupt = FALSE;
entryPointer->vMSpace.name = name;
};
static void WritePattern (bank, pattern)
long bank, pattern;
{
SparcSoftcardOps←MapEntry entry;
long *p;
/* Set Virtual page 0 to point at the last page of the bank */
EntryInit (&entry, VMSpaceName←sparcSuperData);
entry.virtualAddressByte = 0;
entry.realAddressByte = softcardMemoryBankSizeByte * (bank + 1) - softcardPageSizeByte;
SparcSoftcardOps←WriteMapEntry(entry);
/* Store pattern in the last word and ~pattern in the previous word */
p = (long *) softcardPageSizeByte;
p--;
*p = pattern;
p--;
*p = ~ pattern;
};
static BOOLEAN ReadPattern (bank, pattern)
long bank, pattern;
{
BOOLEAN match;
SparcSoftcardOps←MapEntry entry;
long *p;
/* Set Virtual page 0 to point at the last page of the bank */
EntryInit (&entry, VMSpaceName←sparcSuperData);
entry.virtualAddressByte = 0;
entry.realAddressByte = softcardMemoryBankSizeByte * (bank + 1) - softcardPageSizeByte;
SparcSoftcardOps←WriteMapEntry(entry);
/* Compare pattern with the last word and ~pattern with the previous word */
match = TRUE;
p = (long *) softcardPageSizeByte;
p--;
if (*p != pattern) match = FALSE;
p--;
if (*p != ~ pattern) match = FALSE;
return (match);
};
static void FindMemoryConfig (memoryConfig)
BOOLEAN memoryConfig[8];
{
long i, pattern = 0x12345678;
/* For each bank of memory write a distinct pattern (inside the last words of the bank) */
for ( i = 0 ; i < 8 ; i++) {
WritePattern ( i, pattern+i );
};
/* Read them back. Look at 4 banks at a time */
for ( i = 0 ; i < 8 ; i += 4) {
/* default => no DRAM in the 4 banks */
memoryConfig[i+0] = FALSE;
memoryConfig[i+1] = FALSE;
memoryConfig[i+2] = FALSE;
memoryConfig[i+3] = FALSE;
/* 4 different patterns => 4 Mega bits DRAM => 4 banks OK */
if ((ReadPattern ( i+0, i+0+pattern) == TRUE) &&
(ReadPattern ( i+1, i+1+pattern) == TRUE) &&
(ReadPattern ( i+2, i+2+pattern) == TRUE) &&
(ReadPattern ( i+3, i+3+pattern) == TRUE)) {
memoryConfig[i+0] = TRUE;
memoryConfig[i+1] = TRUE;
memoryConfig[i+2] = TRUE;
memoryConfig[i+3] = TRUE;
};
/* 4 time the same pattern 1 Mega bits DRAM => 1 out of 4 banks OK */
if ((ReadPattern ( i+0, i+3+pattern) == TRUE) &&
(ReadPattern ( i+1, i+3+pattern) == TRUE) &&
(ReadPattern ( i+2, i+3+pattern) == TRUE) &&
(ReadPattern ( i+3, i+3+pattern) == TRUE)) {
memoryConfig[i+0] = TRUE;
memoryConfig[i+1] = FALSE;
memoryConfig[i+2] = FALSE;
memoryConfig[i+3] = FALSE;
};
};
};
static void SetSparcMap (sparcVMStartByte, softcardRMStartByte, length)
/* maps length bytes of sparc supervisor VM and DMA VM */
long sparcVMStartByte, softcardRMStartByte, length;
{
SparcSoftcardOps←MapEntry dataEntry, textEntry, dMAEntry;
long i, pageNumber;
EntryInit ( &dataEntry, VMSpaceName←sparcSuperData );
EntryInit ( &textEntry, VMSpaceName←sparcSuperProgram );
EntryInit ( &dMAEntry, VMSpaceName𡤍MA );
dataEntry.virtualAddressByte = sparcVMStartByte;
textEntry.virtualAddressByte = sparcVMStartByte;
dMAEntry.virtualAddressByte = sparcVMStartByte;
dataEntry.realAddressByte = softcardRMStartByte;
textEntry.realAddressByte = softcardRMStartByte;
dMAEntry.realAddressByte = softcardRMStartByte;
pageNumber = length / softcardPageSizeByte;
for (i = 0; i < pageNumber; i++) {
SparcSoftcardOps←WriteMapEntry(dataEntry);
SparcSoftcardOps←WriteMapEntry(textEntry);
SparcSoftcardOps←WriteMapEntry(dMAEntry);
dataEntry.virtualAddressByte += softcardPageSizeByte;
textEntry.virtualAddressByte += softcardPageSizeByte;
dMAEntry.virtualAddressByte += softcardPageSizeByte;
dataEntry.realAddressByte += softcardPageSizeByte;
textEntry.realAddressByte += softcardPageSizeByte;
dMAEntry.realAddressByte += softcardPageSizeByte;
};
};
static void SetRemainingSparcMap (sparcVMStartByte, length)
/* maps length bytes of sparc supervisor data VM to first available page */
long sparcVMStartByte, length;
{
SparcSoftcardOps←MapEntry dataEntry;
long i, pageNumber;
EntryInit ( &dataEntry, VMSpaceName←sparcSuperData );
dataEntry.virtualAddressByte = sparcVMStartByte;
dataEntry.realAddressByte = cedarMemoryExtensionSizeByte;
pageNumber = length / softcardPageSizeByte;
for (i = 0; i < pageNumber; i++) {
SparcSoftcardOps←WriteMapEntry(dataEntry);
dataEntry.virtualAddressByte += softcardPageSizeByte;
};
};
extern long init←map()
/*
This is a C subroutine to find out the memory size and initialize the map.
This subroutine returns sparcMemorySizeByte inside %o0.
All the VM pages from 0 to sparcMemorySizeByte/softcardPageSizeByte - 1 point
to distinct Real memory pages. The remaining entries of the map point at the
same place that page 0
*/
{
BOOLEAN memoryConfig[8];
int i;
long sparcMemorySizeByte, sparcVMStartByte, softcardRMStartByte, length;
FindMemoryConfig (memoryConfig);
/* Each boolean of this array is worth 8 Megabytes */
/* the loader dont know yet about all this bank staff
=> if the program is able to execute the bank 0 is here
special treatement for bank 0: needs too remove
cedarMemoryExtensionSizeByte from the usable memory size
*/
/* sets back page 0 of sparc VM */
sparcVMStartByte = 0;
softcardRMStartByte = cedarMemoryExtensionSizeByte;
length = softcardPageSizeByte;
SetSparcMap (sparcVMStartByte, softcardRMStartByte, length);
/* sets the VM for the last part of bank 0 (takes over the job of the loader) */
sparcVMStartByte = HeapStart();
/* DANGER this call will work properly only if page 0 is back to place DANGER */
softcardRMStartByte = sparcVMStartByte + cedarMemoryExtensionSizeByte;
length = softcardMemoryBankSizeByte - softcardRMStartByte;
SetSparcMap (sparcVMStartByte, softcardRMStartByte, length);
sparcVMStartByte += length;
softcardRMStartByte += length;
length = softcardMemoryBankSizeByte;
for (i = 1; i < 8; i++) {
if (memoryConfig[i] == TRUE) {
/* set subsequent parts of the VM */
SetSparcMap (sparcVMStartByte, softcardRMStartByte, length);
sparcVMStartByte += length;
};
softcardRMStartByte += length;
};
sparcMemorySizeByte = sparcVMStartByte;
/*
sets the remaining of the VM to point to "nowhere".
(in fact first page of available Real memory)
*/
length = 8 * softcardMemoryBankSizeByte - sparcVMStartByte;
SetRemainingSparcMap (sparcVMStartByte, length);
return (sparcMemorySizeByte);
};
extern void init1()
/*
This is a C subroutine finish initialization of the machine prior to run the main program.
This routine calls main(). If main returns the Sparc enters an infinite loop .
*/
{
CacheFlushAndEnable();  /* enable the cache */
InitInterrupts();     /* init interrupt package */
SetInterruptA();     /* init interrupt A */
SetInterruptB();     /* init interrupt B */
initFS();       /* init communication package */
initMonitor();     /* init monitor package */
/* any further init here */
main();
/* If ever main() comes back */
PutText(1, "\n *** Program terminated via main() ***\n");
for (;;) {
(void) debug(0);
};
};
extern void exit()
/*
Standard exit point
*/
{
PutText(1, "\n *** Program terminated via exit() ***\n");
for (;;) {
(void) debug(0);
};
};