// Pup1Init.bcpl - Level 1 initialization and destruction // Copyright Xerox Corporation 1979, 1980, 1981 // Last modified November 21, 1981 11:40 AM by Taft get "Pup0.decl" get "Pup1.decl" get "PupRoute.decl" external [ // outgoing procedures InitPupLevel1; DestroyPupLevel1 // incoming procedures Enqueue; Dequeue; Unqueue; PupLevel1; InitializeContext; Max; SetTimer Allocate; Free; Noop; SysErr; CallSwat; Zero; DefaultArgs OpenLevel1Socket; CloseLevel1Socket; CompletePup; GetPBI; ReleasePBI GatewayListener; InitForwarder; LocateNet HLookup; HInsert; HDelete; HEnumerate; Call0; Call1; Call2; Call3 RTLookup; RTEnumerate; RTInsert; RTDelete InitAltoEther; InitAltoEIA; InitAltoComProc; InitAltoImp; InitAltoPRU InitNovaEther; InitNovaMCA; InitNovaImp; InitNovaSLA // incoming statics ndbQ; pbiFreeQ; pbiIQ; pbiTQ; socketQ; gatewayIQ; pupRT; dPSIB pupZone; pupCtxQ; lenPBI; lenPup; maxPupDataBytes; pupLevel1Ctx numNets; gatewayListenerSoc; socketSequence ] static [ listenerCtx ] //---------------------------------------------------------------------------- let InitPupLevel1(zone, ctxQ, numPBI, pupDataBytes, numRTE; numargs na) be //---------------------------------------------------------------------------- [ DefaultArgs(lv na, -3, defaultPupDataBytes, 9) // define some defaults and other constants pupZone = zone pupCtxQ = ctxQ maxPupDataBytes = pupDataBytes lenPup = (pupOvBytes+pupDataBytes)/2 lenPBI = lenPBIOverhead+lenPup // level one Queues -- DestroyPupLevel1 knows that pbiIQ is first let level1Qs = Allocate(zone, 10); Zero(level1Qs, 10) pbiIQ = level1Qs // level 1 raw pup input queue pbiTQ = level1Qs+2 // level 1 default transmitted queue socketQ = level1Qs+4 // level 1 socket list pbiFreeQ = level1Qs+6 // empty pbi queue ndbQ = level1Qs+8 // net data block queue gatewayIQ = pbiFreeQ // changed by gateway init code // free packet buffer queue for i = 1 to numPBI do Enqueue(pbiFreeQ, Allocate(zone, lenPBI)) // Initialize all connected network interfaces compileif numAltoEther ge 1 then [ InitAltoEther(zone, ctxQ, 0) ] compileif numAltoEther ge 2 then [ InitAltoEther(zone, ctxQ, 1) ] compileif numAltoEther ge 3 then [ InitAltoEther(zone, ctxQ, 2) ] compileif numAltoComProc ge 1 then [ InitAltoComProc(zone, ctxQ) ] compileif numAltoEIA ge 1 then [ InitAltoEIA(zone, ctxQ) ] compileif numAltoImp ge 1 then [ InitAltoImp(zone, ctxQ) ] compileif numAltoPRU ge 1 then [ InitAltoPRU(zone, ctxQ) ] compileif numNovaEther ge 1 then [ InitNovaEther(zone, ctxQ, #73) ] compileif numNovaEther ge 2 then [ InitNovaEther(zone, ctxQ, #63) ] compileif numNovaEther ge 3 then [ InitNovaEther(zone, ctxQ, #53) ] compileif numNovaMCA ge 1 then [ InitNovaMCA(zone, ctxQ, #6) ] compileif numNovaMCA ge 2 then [ InitNovaMCA(zone, ctxQ, #46) ] compileif numNovaImp ge 1 then [ InitNovaImp(zone, ctxQ) ] compileif numNovaSLA ge 1 then [ InitNovaSLA(zone, ctxQ) ] // InitPupLevel1 (cont'd) // Find out how many networks there are numNets = 0 let ndb = ndbQ!0 while ndb ne 0 do [ numNets = numNets+1; ndb = ndb!0 ] if numNets eq 0 then SysErr(0, ecNoNetworkInterface) // Set up default pup socket info block dPSIB = Allocate(zone, lenPSIB) let pbiAlloc = Max(numPBI-numNets, 2) dPSIB>>PSIB.numTPBI = pbiAlloc // Allow socket all PBIs dPSIB>>PSIB.maxTPBI = pbiAlloc // except one per net dPSIB>>PSIB.maxIPBI = pbiAlloc-1 dPSIB>>PSIB.numIPBI = pbiAlloc-1 dPSIB>>PSIB.maxOPBI = pbiAlloc-1 dPSIB>>PSIB.numOPBI = pbiAlloc-1 dPSIB>>PSIB.doChecksum = true SetTimer(lv socketSequence, 0) // randomize default socket numbers // initialize "Hash table" access HLookup, HInsert, HDelete, HEnumerate = Call0, Call1, Call2, Call3 // Set up routing table numRTE = numRTE+numNets // add one entry per directly-connected net let n = lenRT + numRTE*lenRTQI pupRT = Allocate(zone, n); Zero(pupRT, n) pupRT>>HTP.lookup = RTLookup pupRT>>HTP.enumerate = RTEnumerate pupRT>>HTP.insert = RTInsert pupRT>>HTP.delete = RTDelete for i = 0 to numRTE-1 do [ let rtqi = pupRT+lenRT+i*lenRTQI rtqi>>RTQI.rte.net = rtFreeEntry Enqueue(lv pupRT>>RT.head, rtqi) ] LocateNet(0) // Insert entry for net 0 and request routing probe HInsert(pupRT, 0)>>RTE.ndb = ndbQ!0 // Default network is first on ndbQ // Fire up background processes pupLevel1Ctx = InitializeContext(Allocate(zone, 175), 175, PupLevel1) Enqueue(ctxQ, pupLevel1Ctx) listenerCtx = InitializeContext(Allocate(zone, 160), 160, GatewayListener) Enqueue(ctxQ, listenerCtx) // Open a socket for GatewayListener process gatewayListenerSoc = Allocate(zone, lenPupSoc) let portAdr = table [ 0; 0; psRouteInfo ] OpenLevel1Socket(gatewayListenerSoc, portAdr, portAdr) InitForwarder(numPBI) ] //---------------------------------------------------------------------------- and DestroyPupLevel1() be //---------------------------------------------------------------------------- // Destroys Pup package level 1 and level 0 and returns all allocated storage. [ Unqueue(pupCtxQ, pupLevel1Ctx); Free(pupZone, pupLevel1Ctx) Unqueue(pupCtxQ, listenerCtx); Free(pupZone, listenerCtx) // Close all sockets to release any PBIs on their IQs -- but we know nothing // about PBIs hung onto by higher-level protocols (e.g., RTP, BSP). while socketQ!0 ne 0 do CloseLevel1Socket(socketQ!0) // Destroy the level 0 drivers in reverse order of their creation // so their userFinishProcs have a chance to unwind properly. while ndbQ!0 ne 0 do (ndbQ!1)>>NDB.destroy(ndbQ!1) ndbQ = 0 while pbiIQ!0 ne 0 do Free(pupZone, Dequeue(pbiIQ)) // all the PBIs while pbiTQ!0 ne 0 do Free(pupZone, Dequeue(pbiTQ)) while pbiFreeQ!0 ne 0 do Free(pupZone, Dequeue(pbiFreeQ)) Free(pupZone, pbiIQ) // all the level1Qs Free(pupZone, dPSIB) Free(pupZone, pupRT) Free(pupZone, gatewayListenerSoc) ]