// GateControl.bcpl - Gateway Control Program
// Last modified July 2, 1983 10:28 PM by Boggs
get "SysDefs.d"
get "AltoDefs.d"
get "BcplFiles.d"
external
[
// outgoing procedures
AfterJunta; StatusCtx; TopLevel; SysErr
// incoming procedures
Junta; InitGateControl; AddToZone; ReturnFrom
CallContextList; Block; LeftCycle; MoveBlock; Zero
GateConVersion; GateConSummary; RouteSummary; TransitMatrix
EchoSummary; TimeSummary; NameSummary; BootSummary
Ws; Wss; Puts; Resets; GetString
ResetCmdMenu; CreateCmdBox; BoxProc; Free; Dequeue
Gateway; Route; Echo; Name; Boot; Time; Level0Stats
Eftp; Debugger; HaltGateway; RestartGateway
CreateRouteCtx; CreateEchoCtx; CreateGateConCtx
CreateBootCtx; CreateNameCtx; CreateTimeCtx
SetTimer; TimerHasExpired
LoadRam; InitBcplRuntime; BFSClose
EtherBoot; DisableInterrupts; StartIO
// outgoing statics
wheel; versionText
// incoming statics
lvUserFinishProc; lvIdle
sysZone; sysDisk; ctxQ; oldStatsQ
RamImage; gcNet; gcHost
]
static [ savedUFP; savedIdle; wheel; endCode; versionText ]
structure String [ length byte; char↑1,1 byte ]
//----------------------------------------------------------------------------
let GateControl(blv, upe, cfa) be
//----------------------------------------------------------------------------
[
versionText = "GateControl of 2 July 83"
let ramOk = LoadRam(RamImage) eq 0
if ramOk then InitBcplRuntime()
savedUFP = @lvUserFinishProc; @lvUserFinishProc = GCFinishProc
endCode = blv>>BLV.endCode
Junta((ramOk? levBasic, levBcpl), AfterJunta)
]
//----------------------------------------------------------------------------
and AfterJunta() be
//----------------------------------------------------------------------------
[
InitGateControl()
AddToZone(sysZone, InitGateControl, endCode-InitGateControl)
savedIdle = @lvIdle; @lvIdle = Block
//This stuff below should be in GateControlInit.
//The problem is that I run out of free storage during initialization,
// so this suff is deferred until after the initialization code has
// been reclaimed. These procedures aren't very big and they aren't
// broken out into separate initialization modules.
CreateRouteCtx()
CreateEchoCtx()
CreateGateConCtx()
CreateBootCtx()
CreateNameCtx()
CreateTimeCtx()
TopLevel()
CallContextList(ctxQ!0) repeat
]
//----------------------------------------------------------------------------
and GCFinishProc() be
//----------------------------------------------------------------------------
[
@displayListHead = 0; for i = 0 to 32000 loop
@lvIdle = savedIdle
if sysDisk ne 0 then BFSClose(sysDisk)
manifest kbInterruptBit = 1 lshift 12
@activeInterrupts = @activeInterrupts & not kbInterruptBit
@displayInterrupt = @displayInterrupt & not kbInterruptBit
@lvUserFinishProc = savedUFP
]
//----------------------------------------------------------------------------
and SysErr(p1, ec, p2, p3, p4, p5) be
//----------------------------------------------------------------------------
[
let temp = p1; p1 = ec; ec = temp
(table [ 77403b; 1401b ])("Sys.errors", lv p1)
]
//----------------------------------------------------------------------------
and StatusCtx(ctx) be // a context
//----------------------------------------------------------------------------
// ctx!3 is a box stream for the status window.
[
let lastNet, lastHost = -1, -1
[ // repeat
let sts = ctx!3
let timer = nil; SetTimer(lv timer, 250)
[
while oldStatsQ!0 ne 0 do
Free(sysZone, Dequeue(oldStatsQ))
Block()
] repeatuntil TimerHasExpired(lv timer)
Resets(sts, gcNet eq lastNet & gcHost eq lastHost) // dontClear
lastNet = gcNet; lastHost = gcHost
GateConVersion(sts)
Wss(sts, "*N*N")
EchoSummary(sts)
RouteSummary(sts)
TimeSummary(sts)
NameSummary(sts)
BootSummary(sts)
Puts(sts, $*N)
GateConSummary(sts)
Wss(sts, "*N*N")
TransitMatrix(sts)
] repeat
]
//----------------------------------------------------------------------------
and TopLevel() be
//----------------------------------------------------------------------------
[
ResetCmdMenu()
CreateCmdBox(Quit, "Quit")
CreateCmdBox(Gateway, "Gateway")
CreateCmdBox(Route, "Route")
CreateCmdBox(Echo, "Echo")
CreateCmdBox(Name, "Name")
CreateCmdBox(Boot, "Boot")
CreateCmdBox(Time, "Time")
if gcHost ne 0 then CreateCmdBox(Level0Stats, "Level0Stats")
test wheel
ifnot CreateCmdBox(Enable, "Enable")
ifso
[
CreateCmdBox(Disable, "Disable")
if gcHost ne 0 then
[
if sysDisk ne 0 then CreateCmdBox(Eftp, "EFTP")
CreateCmdBox(Debugger, "Debugger")
CreateCmdBox(HaltGateway, "Halt")
CreateCmdBox(RestartGateway, "Restart")
]
]
// 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 Enable() be
//----------------------------------------------------------------------------
[
let psw = vec 128
if GetString("*NPassword: ", psw, false) then
[
Ws("(pst)")
let encpw = 0
for i = 1 to psw>>String.length do
encpw = LeftCycle(encpw+(psw>>String.char↑i & #137) * 25035, 1)
test encpw eq 24141b
ifso
[
wheel = true
TopLevel()
]
ifnot Ws(" - incorrect password")
]
]
//----------------------------------------------------------------------------
and Disable() be
//----------------------------------------------------------------------------
[
wheel = false
TopLevel()
]
//----------------------------------------------------------------------------
and Quit() be
//----------------------------------------------------------------------------
[
ResetCmdMenu()
CreateCmdBox(TopLevel, "TopLevel")
CreateCmdBox(DMT, "DMT")
CreateCmdBox(NetExec, "NetExec")
if (@diskStatus & 40b) eq 0 then CreateCmdBox(DiskBoot, "DiskExec")
ReturnFrom(BoxProc)
]
//----------------------------------------------------------------------------
and DMT() be EtherBoot(0)
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
and NetExec() be EtherBoot(10b)
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
and DiskBoot() be
//----------------------------------------------------------------------------
[
structure KCB:
[
link word
status word
command word
headerAddress word
labelAddress word
dataAddress word
normalWakeups word
errorWakeups word
header word
diskAddress word
]
manifest lenKCB = size KCB/16
DisableInterrupts()
StartIO(3)
let kcb, data, label = vec lenKCB, vec 256, vec 8
[
Zero(kcb, lenKCB)
kcb>>KCB.command = 44100b // check header, read label, read data
kcb>>KCB.headerAddress = lv kcb>>KCB.header
kcb>>KCB.labelAddress = label
kcb>>KCB.dataAddress = data
kcb>>KCB.diskAddress = kbdAd!0 xor -1
until @diskCommand eq 0 loop
@diskCommand = kcb
while (kcb>>KCB.status & 7400b) eq 0 loop
if (kcb>>KCB.status & 7667b) eq 7400b break
] repeat
MoveBlock(402b, label, 8)
MoveBlock(1, data, 256)
@2 = kcb>>KCB.status
goto 1
]