// PupAlImpInit.bcpl -- Alto Imp driver initialization
// Copyright Xerox Corporation 1983

// Last modified August 22, 1983  2:06 PM by Taft

get "Pup0.decl"
get "PupAlImp.decl"

external
[
// Outgoing procedures
InitAltoImp; DestroyAltoImp

// Incoming procedures
EncapsulateImpPup; SendImpPacket; ResetImpInterface
ImpInputInterrupt; ImpOutputInterrupt; ImpProcess; ImpPupFilter; ImpFinish
InitializeInterrupt; DestroyInterrupt; FindInterruptMask; InitializeContext
Allocate; Free; Zero; Enqueue; Unqueue; FalsePredicate; Dismiss

// Incoming statics
impNDB; savedImpUFP; ndbQ; pbiIQ; lvUserFinishProc
]

manifest
[
lenIntStack = 75
lenProcStack = 75
]

//----------------------------------------------------------------------------
let InitAltoImp(zone, ctxQ) be
//----------------------------------------------------------------------------
[
impNDB = Allocate(zone, lenImpNDB)
Zero(impNDB, lenImpNDB)

// Set up Imp Control Block
let icb = Allocate(zone, lenICB, false, true)  // even word
impNDB>>ImpNDB.icb = icb
Zero(icb, lenICB)

// See if an Imp interface exists
ResetImpInterface(false)
if icb>>ICB.controlPost eq 0 then
  [ Free(zone, icb); Free(zone, impNDB); impNDB = 0; return ]

impNDB>>ImpNDB.encapsulatePup = EncapsulateImpPup
impNDB>>ImpNDB.level0Transmit = SendImpPacket
impNDB>>ImpNDB.destroy = DestroyAltoImp
impNDB>>ImpNDB.level0Stats = FalsePredicate
impNDB>>ImpNDB.netType = netTypeArpa
impNDB>>ImpNDB.zone = zone
impNDB>>ImpNDB.ctxQ = ctxQ
impNDB>>ImpNDB.pupPF.predicate = ImpPupFilter
impNDB>>ImpNDB.pupPF.queue = pbiIQ
Enqueue(lv impNDB>>ImpNDB.pfQ, lv impNDB>>ImpNDB.pupPF)
Enqueue(ndbQ, impNDB)

// Initialize interrupts
icb>>ICB.inputChanMask = InitializeInterrupt(Allocate(zone, lenIntStack),
 lenIntStack, FindInterruptMask(#400), ImpInputInterrupt)
icb>>ICB.outputChanMask = InitializeInterrupt(Allocate(zone, lenIntStack),
 lenIntStack, FindInterruptMask(#400), ImpOutputInterrupt)

// Initialize Imp housekeeping process
impNDB>>ImpNDB.ctx = InitializeContext(Allocate(zone, lenProcStack), lenProcStack,
 ImpProcess)
Enqueue(ctxQ, impNDB>>ImpNDB.ctx)

savedImpUFP = @lvUserFinishProc
@lvUserFinishProc = ImpFinish

// Initialize hardware
ResetImpInterface(true)
]

//----------------------------------------------------------------------------
and DestroyAltoImp() be
//----------------------------------------------------------------------------
// Shuts off the Imp interface and returns all allocated storage.
[
let icb = impNDB>>ImpNDB.icb
ResetImpInterface(false)
DestroyInterrupt(icb>>ICB.inputChanMask)
DestroyInterrupt(icb>>ICB.inputChanMask)
Unqueue(impNDB>>ImpNDB.ctxQ, impNDB>>ImpNDB.ctx)
Free(impNDB>>ImpNDB.zone, impNDB>>ImpNDB.ctx)
Free(impNDB>>ImpNDB.zone, impNDB>>ImpNDB.icb)
Unqueue(ndbQ, impNDB)
Free(impNDB>>ImpNDB.zone, impNDB)
impNDB = 0

// Try to get rid of ImpFinish -- this is possible only if ImpFinish was the
// last userFinishProc queued.
if @lvUserFinishProc eq ImpFinish then
  [ @lvUserFinishProc = savedImpUFP; savedImpUFP = -1 ]
]