// IfsInitSwap.bcpl -- IFS swappable initialization
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified June 25, 1981 7:07 PM by Taft
get "Ifs.decl"
get "IfsRs.decl"
get "IfsDirs.decl"
get "AltoFileSys.d"
get "IfsInit.decl"
get "Pup0.decl"
get "Pup1.decl"
external
[
// outgoing procedures
InitIFSPart3; FreeStackEvent
// incoming procedures
MakeFree; OpenIFSPart2; CreateIFSPart2; IFSError; CheckDirectory
InitPupLevel1; PupChecksum; IfsPupChecksum; InitRSMgr; InitXMOverlays
InitFtpServ; InitTelnet; InitMail; InitMiscellaneous; InitEventMgr
InitAllocSpy; InitVMemSpy; InitBackup; InitPrintError; InitLeaf; InitPress
InitMemoryError
CreateOFT; DestroyOFT; SetAllocation
OpenVFile; IFSOpenFile; PositionPage; Closes; MoveBlock; SetBlock; Usc
CallersFrame; AddToZone; Allocate; Free; Zero; ReadCalendar
InitializeContext; Enqueue; ExtractSubstring
CreateEvent; InstallSysParams; FreePointer; VFileReadPage; VFileWritePage
// outgoing statics
infoVMD
// incoming statics
sysZone; bigZone; smallZone; ifsCtxQ; primaryIFS; system
numVMemBufs; numPBIs; lenJobT; dPSIB
CtxRunning; rtpStackSize; isb; monthNames; numOvXMPages
leafPresent; leafEnabled; spyBuffer
]
static [ infoVMD ]
manifest
[
stkLim = 335b
cursorBitMap = 431b
]
//----------------------------------------------------------------------------
let InitIFSPart3() be
//----------------------------------------------------------------------------
// This procedure will be called in as an overlay. It cuts up the resident
// initialization code into vmem buffers, finishes opening the primary file
// system, calls swappable initialization in other modules, and arranges to
// turn the remaining stack into vmem buffers.
// Much of this initialization is very delicate, and it is crucial that
// it be done in the correct order.
[
// Set up dummy context in which we pretend to run (for access checks, etc.)
let saveCtxRunning = CtxRunning
let v = vec lenRSCtx; CtxRunning = v
Zero(v, lenRSCtx)
CtxRunning>>RSCtx.userInfo = system
// Finish opening (or creating) primary file system.
// I hope we have enough VMem buffers to do this now!
if isb>>ISB.creatingPrimary then CreateIFSPart2(primaryIFS)
let ec = nil
unless OpenIFSPart2(primaryIFS, lv ec) do IFSError(ec)
// Verify that the directory is well-formed
if isb>>ISB.verifyTree then CheckDirectory(primaryIFS)
// Open the <System>Info file
OpenSystemInfo()
// Now, at last, we can decide how to carve up the remaining
// resident initialization, move code into XM, etc., which is not possible
// until we can look at SysParam.enableLeaf in the Info file.
leafEnabled = VFileReadPage(infoVMD, spPage)>>SysParams.enableLeaf
if leafEnabled then leafPresent = true // can also be forced by /L switch
// Prepare to discard leaf resident code if Leaf is not to be present
unless leafPresent do
[
let lenLeafResident = isb>>ISB.pcI - isb>>ISB.pcL
isb>>ISB.pcI = isb>>ISB.pcL
isb>>ISB.initStart = isb>>ISB.initStart - lenLeafResident
if spyBuffer ne 0 then spyBuffer = spyBuffer - lenLeafResident
]
// InitIFSPart3 (cont'd)
// Attempt to load overlays into extended memory.
// If this is successful it will consume some of the storage
// formerly occupied by initialization code, updating isb>>ISB.initStart.
InitXMOverlays()
// Determine how many VMem buffers are potentially available, and let
// InitRSMgr decide how many jobs can be supported and how much
// additional space must be given up for zones and PBIs.
let potentialVMemBufs = numVMemBufs +
(isb>>ISB.bigZoneBot - isb>>ISB.initStart) rshift logStdPageLength
if isb>>ISB.residentCodeXM then
potentialVMemBufs = potentialVMemBufs - 1 + // -1 for breakage
(isb>>ISB.pcI - isb>>ISB.pcX) rshift logStdPageLength
InitEventMgr()
InitRSMgr(potentialVMemBufs) // must follow InitEventMgr -- calls CreateEvent
// Turn additional space over to the zones
if isb>>ISB.smallZoneIncr ne 0 then
[
AddToZone(smallZone, isb>>ISB.initStart, isb>>ISB.smallZoneIncr)
isb>>ISB.initStart = isb>>ISB.initStart + isb>>ISB.smallZoneIncr
]
if isb>>ISB.bigZoneIncr ne 0 then
[
// round up to next page boundary, since scraps will go to bigZone anyway
let newFree = ((isb>>ISB.initStart + isb>>ISB.bigZoneIncr) %
(1 lshift logStdPageLength -1)) +1
AddToZone(bigZone, isb>>ISB.initStart, newFree - isb>>ISB.initStart)
isb>>ISB.initStart = newFree
]
// Turn the remaining initialization code into vMem buffers.
MakeFree(bigZone, isb>>ISB.initStart, isb>>ISB.bigZoneBot-isb>>ISB.initStart)
// If we moved resident code into XM, turn it into free storage as well.
// Must do this after the preceding MakeFree to avoid the AddToZone bug.
if isb>>ISB.residentCodeXM then
MakeFree(bigZone, isb>>ISB.pcX, isb>>ISB.pcI - isb>>ISB.pcX)
// Initialize Pup package, with routing table big enough to cope with
// simultaneous connections from many networks.
InitPupLevel1(sysZone, ifsCtxQ, numPBIs, 0,
(leafPresent? lenJobT+2, lenJobT+15))
PupChecksum = IfsPupChecksum //install microcoded checksum routine
// Limit allocation of rendezvous and transient unregistered sockets.
// (Registered sockets' allocations are managed by DistributedPBIs.)
SetAllocation(dPSIB - offset PupSoc.psib/16, 6, 5, 5)
// Extra RTP stack space needed to handle overlay faults.
// Even more space needed with Extended Emulator, since RTPFSM references
// a large table.
rtpStackSize = (numOvXMPages gr 0? 300, 180)
// InitIFSPart3 (cont'd)
// Execute all other swappable initialization
InitTimeIO()
InitAllocSpy()
InitVMemSpy()
InitTelnet()
InitMiscellaneous() // must follow OpenSystemInfo -- uses infoVMD
InitPress() // must follow OpenSystemInfo -- uses infoVMD
InitBackup() // must follow OpenSystemInfo -- uses infoVMD
InitFtpServ()
InitMail() // must follow OpenSystemInfo and InitFtpServ
if leafPresent then
[
InitLeaf()
// primaryIFS must have a bigger OFT if Leaf is present.
// n.b. this depends on there being no open files at this time!
unless DestroyOFT(primaryIFS) do IFSError(ecCantDestroyOFT)
CreateOFT(primaryIFS, 128) // must be power of 2
]
InstallSysParams(true) // must follow all of the Init routines above
InitPrintError()
InitMemoryError()
// Record starting time and Ifs.run creation time
let sp = VFileWritePage(infoVMD, spPage)
ReadCalendar(lv sp>>SysParams.ifsStartTime)
MoveBlock(lv sp>>SysParams.runFileCreated, lv isb>>ISB.runFileCreated, 2)
// Create an event to free up all of the remaining stack.
isb>>ISB.stkBase = @stkLim
isb>>ISB.stkLength = CallersFrame()-isb>>ISB.stkBase-2
CreateEvent(FreeStackEvent)
@stkLim = CallersFrame()-1
CtxRunning = saveCtxRunning
// Change cursor to 'IFS'
MoveBlock(cursorBitMap, table
[
0; 0; 0; 0; 71706b; 21011b; 21010b; 21606b
21001b; 21011b; 71006b; 0; 77777b; 0; 0; 0
], 16)
]
//----------------------------------------------------------------------------
and FreeStackEvent(ecb) be
//----------------------------------------------------------------------------
[
MakeFree(bigZone, isb>>ISB.stkBase, isb>>ISB.stkLength)
Free(sysZone, ecb)
FreePointer(lv isb>>ISB.xepTable)
Free(sysZone, isb)
]
//---------------------------------------------------------------------------
and OpenSystemInfo() be
//---------------------------------------------------------------------------
[
let name = "<System>Info!1"
infoVMD = OpenVFile(name, systemInfoPages)
if infoVMD eq 0 then
[
let str = IFSOpenFile(name, 0, modeWrite)
if str eq 0 then IFSError(ecCreateEssentialFile)
PositionPage(str, systemInfoPages)
Closes(str)
infoVMD = OpenVFile(name, systemInfoPages)
if infoVMD eq 0 then IFSError(ecTridentFile, name)
]
]
//---------------------------------------------------------------------------
and InitTimeIO() be // make legal constant string for modified IfsTimeIO
//---------------------------------------------------------------------------
monthNames = ExtractSubstring("x*007January*000*000*010February*000*005March*000*000*000*000*005April*000*000*000*000*003May*000*000*000*000*000*000*004June*000*000*000*000*000*004July*000*000*000*000*000*006August*000*000*000*011September*007October*000*000*010November*000*010December*000") +1