//PupAlEIAInit.bcpl - Alto initialization for EIA interface // Code can be thrown away after use // Companion to PupAlEIAb.bcpl and PupAlEIAa.bcpl // Copyright Xerox Corporation 1979, 1980 // Last modified March 9, 1980 6:22 PM by Taft get "Pup0.decl" get "PupAlEIA.decl" external [ //outgoing procedures InitAltoEIA //incoming procedures EncapsulateEIAPup; SendEIAPacket; SendEIAStats EIAPupFilter; EIARoutingFilter; StartEIAR EIAInterrupt; EIAProcess; EIAFinishProc; EIASwatContextProc InitializeContext; InitializeInterrupt; FindInterruptMask Allocate; Dequeue; Enqueue; SetBlock; Zero; SetTimer; Dismiss; Noop //outgoing statics eiaNDB; eiaLT; savedEIAFinishProc; eiaMcLoaded //incoming statics ndbQ; pbiIQ; pbiFreeQ; lenPup lvUserFinishProc ] static [ eiaNDB; eiaLT; savedEIAFinishProc; eiaMcLoaded ] //---------------------------------------------------------------------------- let InitAltoEIA(zone, ctxQ) be //---------------------------------------------------------------------------- //zone is where to get storage from //ctxQ is the context list on which to queue the interface process [ unless eiaMcLoaded return //no microcode structure Vers: [ eng bit 4; build bit 4; mc bit 8 ] if (table [ #61014; #1401 ])()<<Vers.eng ne 3 return //must be Alto II XM @eiaControl = swi; if @eiaStatus eq 0 return //no EIA board let foo = @eiaData //re sync the interface savedEIAFinishProc = @lvUserFinishProc @lvUserFinishProc = EIAFinishProc //build a Network Data Block for this network, whatever it is. eiaNDB = Allocate(zone, lenEIANDB) Zero(eiaNDB, lenEIANDB) //standard part of NDB eiaNDB>>NDB.encapsulatePup = EncapsulateEIAPup eiaNDB>>NDB.level0Transmit = SendEIAPacket eiaNDB>>NDB.level0Stats = SendEIAStats eiaNDB>>NDB.destroy = Noop // not implemented yet eiaNDB>>NDB.netType = netTypeSLA eiaNDB>>NDB.deviceNum = 0 eiaNDB>>NDB.pupPF.predicate = EIAPupFilter eiaNDB>>NDB.pupPF.queue = pbiIQ Enqueue(lv eiaNDB>>NDB.pfQ, lv eiaNDB>>NDB.pupPF) //EIA line control blocks for line = 0 to maxLine do [ let lcb = lv eiaNDB>>EIANDB.lcb↑line lcb>>LCB.line = line SetTimer(lv lcb>>LCB.rTimer, 0) ] //internal routing table SetBlock(lv eiaNDB>>EIANDB.rt, -1, maxHost) eiaNDB>>EIANDB.rPF.predicate = EIARoutingFilter eiaNDB>>EIANDB.rPF.queue = lv eiaNDB>>EIANDB.rIQ Enqueue(lv eiaNDB>>NDB.pfQ, lv eiaNDB>>EIANDB.rPF) Enqueue(ndbQ, eiaNDB) //set up interface process Enqueue(ctxQ, InitializeContext(Allocate(zone, 150), 150, EIAProcess)) //EIA interface microcode Line Table // the +2 is for the CRC table pointer and a blank to pad to an even address eiaLT = Allocate(zone, lenEIALT+2, false, true) Zero(eiaLT, lenEIALT+2) //in particular all states = throwAway eiaLT = eiaLT+2 EIASwatContextProc() //must wait until eiaLT has been allocated //CRC table let crcTable = Allocate(zone, 256) eiaLT!-1 = crcTable for entry = 0 to 255 do [ let crc = 0 let value = entry for power = 0 to 7 do test (value & 1) eq 0 ifso value = value rshift 1 ifnot [ crc = crc xor (120001B rshift (7 - power)) value = (value rshift 1) xor 120001B ] crcTable!entry = crc ] //Assign an interrupt channel let intMask = InitializeInterrupt(Allocate(zone, 120), 120, FindInterruptMask(1), EIAInterrupt) //Enable the EIA microcode (table [ mcEnableEIA; #1401 ])(eiaLT) //Discover how many EIA boards are really plugged in. //We can handle up to maxLine lines, but if there are fewer boards // we can avoid wasting a pbi under receivers that don't exist. for line = 0 to maxLine do @eiaControl = swi % line lshift 9 //Wait a wile for the interrupts to settle out... Dismiss(1) //waits for 40 ms. //eiaLT>>EIALT.eiaLTE↑line.status will be non zero for boards that exist. //EIA Line Command Blocks for line = 0 to maxLine do [ let lcb = lv eiaNDB>>EIANDB.lcb↑line if eiaLT>>EIALT.eiaLTE↑line.status eq 0 then [ lcb>>LCB.state = slaLineMissing loop ] eiaLT>>EIALT.eiaLTE↑line.exists = true let eiaLCB = Allocate(zone, lenEIALCB, false, true) Zero(eiaLCB, lenEIALCB) lcb>>LCB.iEIALCB = eiaLCB eiaLCB>>EIALCB.intMask = intMask eiaLCB = Allocate(zone, lenEIALCB, false, true) Zero(eiaLCB, lenEIALCB) lcb>>LCB.oEIALCB = eiaLCB eiaLCB>>EIALCB.intMask = intMask //Set up the hardware for reception. let line000 = line lshift 9 @eiaControl = initIF % 410B % line000 //talking to data set, fdx, (9600) @eiaControl = reset % #200 % line000 //clear rx & tx @eiaControl = initRT % #700 % line000 //8 bits, no parity, synchronous @eiaControl = initRG % 26B % line000 //syn character is 26b @eiaControl = initRG % 777B % line000 //fill character is 377b @eiaControl = reset % #100 % line000 //start rx //Put the EIA microcode into BiSync state. let eiaLTE = lv eiaLT>>EIALT.eiaLTE↑line eiaLTE>>EIALTE.iState = stateBiSyncInput eiaLTE>>EIALTE.oState = stateBiSyncOutput //Start the receiver. lcb>>LCB.iPBI = Dequeue(pbiFreeQ) if lcb>>LCB.iPBI ne 0 then StartEIAR(lcb) ] ]