// GateConBoot.bcpl -- talks to the Boot server
// Last modified March 6, 1979 10:39 PM by Boggs
get "Pup0.decl"
get "Pup1.decl"
get "PupBootServ.decl"
external
[
// outgoing procedures
CreateBootCtx; RestartBoot; Boot; BootSummary
// incoming procedures
OpenLevel1Socket; CloseLevel1Socket
GetBuf; CompletePup; ReleasePBI
Zero; MoveBlock; ReturnFrom
Allocate; Free; Enqueue; Dequeue; Noop
InitializeContext; Block; SetTimer; TimerHasExpired
Ws; Wss; PutTemplate; UNPACKDT; WRITEUDT; Confirm
TopLevel; ResetCmdMenu; CreateCmdBox; BoxProc
SendCommand; MiscCmd
// incoming statics
dsp; sysZone; ctxQ; gcHost; oldStatsQ; wheel
]
static @bu
structure BU: // bu -> this 'global frame' for this module
[
soc word // -> PupSoc
stats word // -> Boot Server Stats block
timer word // update stats when this expires
]
manifest lenBU = size BU/16
//----------------------------------------------------------------------------
let CreateBootCtx() be
//----------------------------------------------------------------------------
[
Enqueue(ctxQ, InitializeContext(Allocate(sysZone, 150), 150, BootCtx))
bu = Allocate(sysZone, lenBU); Zero(bu, lenBU)
bu>>BU.soc = Allocate(sysZone, lenPupSoc); OpenLevel1Socket(bu>>BU.soc)
]
//----------------------------------------------------------------------------
and RestartBoot() be
//----------------------------------------------------------------------------
[
SetTimer(lv bu>>BU.timer, 0)
if bu>>BU.stats ne 0 then
[ Enqueue(oldStatsQ, bu>>BU.stats); bu>>BU.stats = 0 ]
]
//----------------------------------------------------------------------------
and Boot() be
//----------------------------------------------------------------------------
[
ResetCmdMenu()
CreateCmdBox(TopLevel, "TopLevel")
CreateCmdBox(BootDirectory, "BootDir")
if gcHost ne 0 then
[
CreateCmdBox(BootStats, "BootStats")
if wheel then
[
CreateCmdBox(BootLock, "Lock")
CreateCmdBox(BootUnlock, "Unlock")
]
]
// ResetCmdMenu destroyed the BoxQ which BoxProc is following.
// If we just return now, BoxProc will get horribly confused.
// So don't let it continue: force a return from BoxProc.
ReturnFrom(BoxProc)
]
//----------------------------------------------------------------------------
and BootSummary(stream) be
//----------------------------------------------------------------------------
[
if bu>>BU.stats ne 0 then
PutTemplate(stream, "Boot: $EUD ", lv bu>>BU.stats>>Stats.fastSends)
]
//----------------------------------------------------------------------------
and BootCtx(ctx) be //a context
//----------------------------------------------------------------------------
[
Block() repeatuntil TimerHasExpired(lv bu>>BU.timer) & gcHost ne 0
SetTimer(lv bu>>BU.timer, 1000) // 10 sec
let pbi = GetBuf(bu>>BU.soc)
pbi>>PBI.pup.dPort.socket↑2 = psMiscServ
pbi = SendCommand(pbi, ptBootStatsRequest, pupOvBytes, (bu>>BU.stats? 1, 3))
if pbi ne 0 then
[
let stats = lv pbi>>PBI.pup.words
if pbi>>PBI.pup.type eq ptBootStatsReply &
stats>>Stats.version eq bootStatsVersion then
[
if bu>>BU.stats then Enqueue(oldStatsQ, bu>>BU.stats)
let lenStatBlock = (pbi>>PBI.pup.length-pupOvBytes+1)/2
bu>>BU.stats = Allocate(sysZone, lenStatBlock)
MoveBlock(bu>>BU.stats, stats, lenStatBlock)
]
ReleasePBI(pbi)
]
] repeat
//----------------------------------------------------------------------------
and BootStats() be
//----------------------------------------------------------------------------
[
let oldStats = bu>>BU.stats
SetTimer(lv bu>>BU.timer, 0)
let timer = nil; SetTimer(lv timer, 500)
Block() repeatuntil TimerHasExpired(lv timer) % bu>>BU.stats ne oldStats
test bu>>BU.stats ne oldStats
ifso Ws("*NBoot Server stats:")
ifnot
[
Ws("*NThe Boot Server doesn't answer.")
if bu>>BU.stats ne 0 then
Ws("*NWhen last heard from its stats were:")
]
if bu>>BU.stats ne 0 then
PutTemplate(dsp, "*NDirs sent: $EUD Files Rcvd: $EUD Fast Sends: $EUD Slow sends: $EUD",
lv bu>>BU.stats>>Stats.dirsSent, lv bu>>BU.stats>>Stats.filesRcvd,
lv bu>>BU.stats>>Stats.fastSends, lv bu>>BU.stats>>Stats.slowSends)
]
//----------------------------------------------------------------------------
and BootDirectory() be
//----------------------------------------------------------------------------
[
let soc = vec lenPupSoc; OpenLevel1Socket(soc)
let pbi = GetBuf(soc)
pbi>>PBI.pup.dPort.socket↑2 = psMiscServ
pbi = SendCommand(pbi, ptBootDirRequest, pupOvBytes, 1)
if pbi then Enqueue(lv soc>>PupSoc.iQ, pbi)
let timer = nil; SetTimer(lv timer, 200) // 2 seconds
[
Block() repeatuntil soc>>PupSoc.iQ.head ne 0 % TimerHasExpired(lv timer)
let pbi = Dequeue(lv soc>>PupSoc.iQ.head); if pbi eq 0 break
if pbi>>PBI.pup.type eq ptBootDirReply then
[
let ptr = 1
while ptr ls (pbi>>PBI.pup.length-pupOvBytes)/2 do
[
let bfd = lv pbi>>PBI.pup.words↑ptr
PutTemplate(dsp, "*N$S, bfn = $UO, created ",
lv bfd>>BFD.name, bfd>>BFD.bfn)
let utv = vec 7; UNPACKDT(lv bfd>>BFD.date, utv); WRITEUDT(dsp, utv)
ptr = ptr + lenBFD + bfd>>BFD.name.length rshift 1 +1
]
]
ReleasePBI(pbi)
] repeat
CloseLevel1Socket(soc)
]
//----------------------------------------------------------------------------
and BootLock() be if Confirm("*NLock Boot server") then
//----------------------------------------------------------------------------
MiscCmd(ptBootLockRequest, ptBootLockReply, Noop)
//----------------------------------------------------------------------------
and BootUnlock() be MiscCmd(ptBootUnlockRequest, ptBootUnlockReply, Noop)
//----------------------------------------------------------------------------