// IfsInitCommon.bcpl -- IFS initialization and cleanup
// This module contains code that must be present in both the resident
// initialization and the swappable initialization.
// Copyright Xerox Corporation 1980, 1982
// Last modified September 17, 1982  9:13 AM by Taft

get "Ifs.decl"
get "IfsVMem.decl"
get "IfsInit.decl"
get "AltoDefs.d"

external
[
// outgoing procedures
MakeFree; IFSFinish

// incoming procedures
ExtendStackCall; TFSSilentBoot; CloseIFS
UnsnarfBuffers; AddToZone
SetBlock; IFSError; Usc

// incoming statics
snarfTable; numVMemBufs; primaryIFS; lvUserFinishProc; savedUFP
]

manifest
[
ecNumVMemBufs = 3
ecMakeFreeNegative = 56
]

//----------------------------------------------------------------------------
let MakeFree(zone, first, length) be
//----------------------------------------------------------------------------
// Cuts up the stretch of memory starting at 'first' into
//  vmem buffers, adding any scraps to 'zone'.
[
if length ls 0 then IFSError(ecMakeFreeNegative)
SetBlock(first, 77400B, length)  // fill region with traps, for debugging
manifest pageLength = 1 lshift logStdPageLength
manifest pageMask = (-1) lshift logStdPageLength
let last = first+length
let firstModPageLength = (first+pageLength-1) & pageMask
let lastModPageLength = last & pageMask
UnsnarfBuffers(firstModPageLength rshift logVMPageLength,
 (lastModPageLength-firstModPageLength) rshift logVMPageLength)

for i = firstModPageLength rshift logStdPageLength to
 lastModPageLength rshift logStdPageLength -1 do
   [ snarfTable!i = 0; numVMemBufs = numVMemBufs+1 ]
if numVMemBufs lshift (logStdPageLength-logVMPageLength) gr
 maxVMPages then IFSError(ecNumVMemBufs)

// Beware of the AddToZone bug: blocks that are added must not
// appear to be "inside" the existing zone, else an error will occur.
// This imposes an ordering requirement on the blocks being added.
// Ensure that the two scraps added here are successively further
// "away from" the zone to which they are being added.
if Usc(first, zone) gr 0 & firstModPageLength-first ge 10 then
   AddToZone(zone, first, firstModPageLength-first)
if last-lastModPageLength ge 10 then
   AddToZone(zone, lastModPageLength, last-lastModPageLength)
if Usc(first, zone) ls 0 & firstModPageLength-first ge 10 then
   AddToZone(zone, first, firstModPageLength-first)
]

//---------------------------------------------------------------------------
and IFSFinish() be
//---------------------------------------------------------------------------
// The last finish procedure called when a finish is done
[
if primaryIFS ne 0 then ExtendStackCall(2000, CloseDisks)
@displayListHead = 0
TFSSilentBoot()
@lvUserFinishProc = savedUFP
]

//----------------------------------------------------------------------------
and CloseDisks() be
//----------------------------------------------------------------------------
[
// We know that primaryIFS is the first one on the queue.
// Must close it last because when it is closed vmem and overlays won't work.
while primaryIFS!0 ne 0 do CloseIFS(primaryIFS!0, true)
CloseIFS(primaryIFS, true)
]