//SprintInstall.Sr - last modified: August 14, 1979 3:09 PM

// SprintInstall.Bcpl -- Spruce Printer Installation and Initialization
// errors 250
//get "Spruce.d" made dictionary too big
get "SpruceInLdOutLd.d"// InLd/OutLd messages for spooler <-> service communication
//
get "SprucePrinters.d"
//
get "Sprucedoc.d"
//
get "Sprucefont.d"
//
get "Spruceband.d"
get "spruceMisc.d"
get "SpruceFiles.d"
get "AltoFileSys.d"
get "Disks.d"
get "Streams.d"
get "SysDefs.d"
get "BcplFiles.d"
// incoming procedure
external
[
SprintInstall
]
// outgoing procedures
external
[
// Sprint
Sprint

// SpruceCheck
CheckPoint
InitCheckZone
OpenCheckPointFile
RestoreFromCheckPoint

// SpruceInUtil
StatusOf31s

// SpruceFiles
CreateSpruceFile
InitSpruceFile
ResetSpruceFile
WindowCreateStream
WindowReadBlock
WindowSetPage

// SpruceUtils, Res, Errors
CreateFPRD
FSGetX; FSInit; FSPut
LoadBase
Overlay
Scream
SpruceError
SwappedOut

// Other Spruce
CursorChar
EarOn
PollEther
Ticker
SetupFrameFinishProc

// Packages
ByteBlt
FindInterruptMask
InitializeInterrupt
PutTemplate

// OS
Closes
FileLength
GetCompleteFa
InitializeZone
Junta
MoveBlock
MyFrame
OpenFileFromFp
Zero
// statics
dsp
earMask
earStack
inMsg
inPacket
lenOut
lvSwatContextProc
lvUserFinishProc
MinorVersion
numActiveOverlays
outMsg
outPacket
OverlayBottom
overLayout
OverlayTable
OverlayTop
ovNum
PermanentBottom
RunFile
savedSCP
SprintSavedUFP
SprintUserFinishProc
sprintFPRD
SpruceZone
statusOf31s
sysDisk
TFSSwatContextProc
tickMask
tickStack
Version
]

structure IST: [ blank word 10; NewMask word ] // *** dependent on standard Interrupt package

manifest lenSysDisk = (size DSK/16)+lKDHeader
static STACKSize = 950
// presumed enough September 18, 1978

//-----------------------------------------------------------------
structure Port:
//-----------------------------------------------------------------
[
net byte
host byte
socket↑1,2 word
]
manifest lenPort = size Port/16

//-----------------------------------------------------------------
structure Pup: //basic raw pup
//-----------------------------------------------------------------
[
length word
blank byte
type byte
blank word 2
blank word lenPort
sPort: @Port
words↑1,266 word //actual length varies
//checksum word //for documentation only--actual position varies
]
manifest pupOvBytes = 22 // Pup overhead (header + checksum)
manifest pupOvWords = pupOvBytes/2
// ------------------------------------------------------
let SprintInstall(layout, runCfa) be
// ------------------------------------------------------

//
Sprint installation involves activities before and after a Junta to eliminate much of the operating
// system. Pre-Junta activities include creation of RunFile and CheckPointFile as SpruceFiles, creating
// the overlay structures, creating the Sprint.Boot file to and from which the printer program swaps, and
// saving all that away in the checkpoint file for subsequent access. Much of the hassle has to do with
// saving information as memory is mangled on both ends by Overlay (and LoadBase, which calls it), by
// the checkpoint routines, and by the Junta itself.

[
// Set up memory
OverlayTable=SprintInstall+1
// Cannibalism!
overLayout = OverlayTable+20
OverlayBottom = overLayout+10*lenOVLayout+1 //10 is the number of overlays
OverlayTop=@#335 // for now
PermanentBottom = MyFrame()-STACKSize
@#335 = PermanentBottom
SprintSavedUFP=@lvUserFinishProc
@lvUserFinishProc = SprintUserFinishProc
SetupFrameFinishProc()
savedSCP = @lvSwatContextProc
@lvSwatContextProc = TFSSwatContextProc
SpruceZone = InitializeZone(OverlayTop+1,
4300)
let Palloc(z, sz) = valof [ z!2 = z!2-sz; resultis z!2 ]
// should be InitcheckZone() ???
let cpZone = vec 3; cpZone!0 = Palloc; cpZone!1 = Scream; cpZone!2 = PermanentBottom

// Build the overlay tables from information in the run file
RunFile = CreateSpruceFile(runCfa, 0, 0, 0, cpZone) // only need map, after this process is done
unless RunFile do SpruceError(250)
let numPages = RunFile>>SPruceFile.numPages
InitSpruceFile(RunFile, 1, 3)
let st = WindowCreateStream(RunFile, ksTypeReadOnly)
ovNum=1
numActiveOverlays = 0
let pn = runCfa>>CFA.fa.pageNumber
until pn>numPages do // test succeeds when done or if no overlays
[
WindowSetPage(st, pn)
let v=vec 15; WindowReadBlock(st, v, 16)
if v!2 ne 1 % v!5 ne pn-1 then SpruceError(251)
OverlayTable!ovNum=pn; ovNum=ovNum+1
pn=pn+(v!4 + 255)/256
]
Closes(st); ResetSpruceFile(RunFile)
OverlayTable!ovNum=pn
// Terminator

// Clear initialization routine statics
let auxInstRout = SprintInstallAux
// Static soon to go away
let relocP=layout>>BLV.relPairTable
for p=1 to (relocP!0)*2 by 2 do @(relocP!p) = SwappedOut

//|| No overlays present ||
LoadBase()
// Fetch base overlay
//|| OVBase, OVInit present ||
CursorChar($B)
PutTemplate(dsp,"Spruce Printing Program, Version $D.$D*N", Version, MinorVersion)

// Get Checkpoint file set up, save the few valuable things off
OpenCheckPointFile(runCfa)
// initialize, save cfa in Run File layout vector if necessary
RunFile = CreateSpruceFile(runCfa) // rebuild, for saving in checkpoint
sprintFPRD = CreateFPRD("Sprint.Boot", true)
unless sprintFPRD do SpruceError(255)
CheckPoint(LEVInstallationStatics, LEVInstallationStatics)
CheckPoint(LEVInitialStatics, LEVInitialStatics) // just to clear it
OverlayBottom = OverlayBottom+3
statusOf31s = StatusOf31s() // temporarily -- will be replaced by (compatible) Spooler version
Junta(levBFSbase, auxInstRout) // = SprintInstallAux
]
// ------------------------------------------------------
and SprintInstallAux() be
// ------------------------------------------------------

//
Called after Junta -- nothing exists except saved sysDisk and the code and OS levels that are
// left. The job is to prepare the Sprint environment prior to an OutLd (in Sprint()) that will save the
// preparations pending the first printing invocation from the spooler. After restoring the pre-junta
// information, allocate some permanent communication structures, prepare a "canned" status packet for
// responding to remote requests while printing, allocate interrupt channels for the "ear" code that does
// the responding, and call Sprint() to OutLd and finish. Spooler will InLd to start printing. Again, the
// hair is due to memory changes -- Checkpoint routines rebuild SpruceZone, and code just before
// Sprint() call releases initialization code, removing overlays so that they can be refetched to lower
// locations.

[
// OverlayTop, OverlayBottom are set correctly for initialization -- OVBase is resident, but too high
// in memory. Prepare memory for Restore from Checkpoint
PermanentBottom=MyFrame()-STACKSize
@#335=PermanentBottom
compileif DebugSw then [ Zero(PermanentBottom, STACKSize-5) ]
sysDisk = 0 // OpenCheckPointFile will recreate it
unless OpenCheckPointFile(false) do SpruceError(258)
SpruceZone = InitCheckZone() // more permanent structures!
inMsg = FSGetX(20, SpruceZone, 0) // 19 = lInLdMessage // super-permanent
outMsg = FSGetX(20, SpruceZone, 0) // 19 = lInLdMessage // super-permanent
inPacket = FSGetX(20) // Ether "Ear" input buffer
outPacket = FSGetX(2+10+1+27+1, SpruceZone, 0) // encaps, header, code, checksum, message
lenOut = 2+10+1+27+1
outPacket!0 = EarOn(0) // just get own host value, be sure ether’s off
outPacket!1 = #1000 // type Pup
let o = lv outPacket!2
o>>Pup.length = 20+2+54+2 // Header, code, string, checksum
o>>Pup.type = #201
o>>Pup.sPort.net = 3 // ~~ can this be 0? or get from spooler
o>>Pup.sPort.host = outPacket!0
o>>Pup.sPort.socket↑2 = #21
o>>Pup.words↑1 = 3 // Spooling and Busy
ByteBlt(lv o>>Pup.words↑2,0,"Spruce is Spooling and Busy (printing);*Navailable soon",1,54)
o>>Pup.words↑29 = -1
// no checksum, for now (ever?)
earStack = FSGetX(30)
// plenty
tickStack = FSGetX(40)
earMask = InitializeInterrupt(earStack, 30, FindInterruptMask(1), PollEther)
tickMask = InitializeInterrupt(tickStack, 40, FindInterruptMask(earMask), Ticker)
// ** IST structure dependent on standard Interrupt package!!
tickStack>>IST.NewMask = earMask-1 // disable ear whenever Ticker runs
RestoreFromCheckPoint(LEVInstallationStatics, LEVInstallationStatics)
InitSpruceFile(RunFile) // reset disk structure
//|| OVBase, OVInit ||
Overlay(0, 1)
// Delete all overlays
//|| No Overlays ||
OverlayTop = OverlayBottom

Sprint()
// Start the system
]

// DCS, July 25, 1977 9:07 PM, created from old SpruceInstall and SproullInstall
//
and SproullInit
// July 28, 1977 9:21 AM, retrieve RunFile, etc., before first OutLd
// July 28, 1977 9:37 AM, add inMsg assignment
// July 29, 1977 3:07 PM, repair many File initialization bugs, avoid default damage
// August 28, 1977 7:40 AM, Spruce->Sprint
// September 2, 1977 4:22 PM, add ether "ear" init
// October 10, 1977 2:55 PM, add Version printout during installation
// January 20, 1978 1:27 PM, accommodate new, more flexible overlay structure
// March 8, 1978 9:04 AM, try larger stack size to avoid Kanji printdoc error overflow
// March 10, 1978 9:09 AM, use LoadBase
// May 11, 1978 6:38 PM, set up interrupt mask, context
// September 15, 1978 3:04 PM, accommodate new checkpoint, version, file creation stuff
// September 18, 1978 9:40 AM, improvements in run file handling
// September 25, 1978 9:25 AM, fix the "Break at 0" mystery bug -- alloc. perm. structs to perm. stg.
// October 15, 1978 4:25 PM, redo file creation for fast files
// October 29, 1978 4:21 PM, recreate sysDisk after Junta via OpenCheckPointFile
// December 6, 1978 10:35 AM add capacity for printer specific overlays
// April 25, 1979 11:26 AM change InLdOutLd.d to SpruceInLdOutLd.d, add bcplFiles.d
// August 14, 1979 3:09 PM, wrong code was in o>>Pup.words↑1
//