// PupAlEIAa.bcpl - PUP level -1 driver for EIA Interface // Copyright Xerox Corporation 1979 // Last modified October 1, 1978 5:07 PM get "Pup0.decl" get "PupAlEIA.decl" external [ // outgoing procedures EIAFinishProc; EIASwatContextProc; EIAInterrupt StartEIAT; StopEIAT; StartEIAR; StopEIAR // incoming procedures EIAOutputDone; EIAInputDone Enqueue; Dequeue DisableInterrupts; EnableInterrupts; DestroyInterrupt // incoming statics pbiFreeQ; lenPup; eiaNDB; eiaLT savedEIAFinishProc; lvUserFinishProc; lvSwatContextProc ] static savedEIASwatProc //---------------------------------------------------------------------------- let EIAFinishProc() be //---------------------------------------------------------------------------- [ //Disable the EIA microcode. (table [ mcEnableEIA; #1401 ])(0) DestroyInterrupt(eiaNDB>>EIANDB.lcb↑0.iEIALCB>>EIALCB.intMask) @lvUserFinishProc = savedEIAFinishProc @lvSwatContextProc = savedEIASwatProc ] //---------------------------------------------------------------------------- and EIASwatContextProc() be //---------------------------------------------------------------------------- [ let t = table [ #101005 // mov 0 0 snr ; skip if turn on #102401 // mkzero 0 0 skp ; entering. Turn off eia #020403 // lda 0 .+3 ; leaving. Turn on eia #063400 // EnableEIA #001401 // jmp 1 3 0 // -> eiaLT ] t!5 = eiaLT savedEIASwatProc = @lvSwatContextProc @lvSwatContextProc = t ] //---------------------------------------------------------------------------- and EIAInterrupt() be //---------------------------------------------------------------------------- // Control comes here when the EIA microcode interrupts. [ for line = 0 to maxLine do if eiaLT>>EIALT.eiaLTE↑line.exists then [ let lcb = lv eiaNDB>>EIANDB.lcb↑line //Check input LCBs. let eiaLCB = lcb>>LCB.iEIALCB let firmStatus = eiaLCB>>EIALCB.firmStatus if firmStatus ls 0 then [ //Dont look here again for a completed EIALCB eiaLCB>>EIALCB.firmStatus = 0 //Take care of any errors that might have occured. switchon (firmStatus & 77777B) into [ case errorNone: [ lcb>>LCB.iPBI>>PBI.packetLength = ((lenPup+1) lshift 1) - (eiaLCB>>EIALCB.byteCount & 77777B) EIAInputDone(lcb) endcase ] case errorFatal: [ StopEIAR(lcb) endcase ] case errorETX: [ lcb>>LCB.inputOverrun = lcb>>LCB.inputOverrun +1 endcase ] case errorSTX: case errorDLE: [ lcb>>LCB.lineControlError = lcb>>LCB.lineControlError +1 endcase ] case errorCRC: [ lcb>>LCB.badCRC = lcb>>LCB.badCRC +1 endcase ] ] //Restart reception of packets. if lcb>>LCB.iPBI eq 0 then lcb>>LCB.iPBI = Dequeue(pbiFreeQ) if lcb>>LCB.iPBI ne 0 then StartEIAR(lcb) ] //EIAInterrupt (cont'd) //check output LCBs. eiaLCB = lcb>>LCB.oEIALCB firmStatus = eiaLCB>>EIALCB.firmStatus if firmStatus ls 0 then [ //Dont look here again for a completed EIALCB eiaLCB>>EIALCB.firmStatus = 0 //Take care of any errors that might have occured. switchon (firmStatus & 77777B) into [ case errorFatal: StopEIAT(lcb) //fall through case errorNone: [ EIAOutputDone(lcb) endcase ] default: StartEIAT(lcb) ] ] ] ] //---------------------------------------------------------------------------- and StartEIAR(lcb) be //---------------------------------------------------------------------------- // Start EIA reception of a packet over the line represented by the LCB. // This procedure is called by InitAltoEIA to start things up, // by EIAInterrupt when an input is complete to restart reception, and // by EIAProcess to restart reception on a line that ran out of PBIs. [ DisableInterrupts() let eiaLCB = lcb>>LCB.iEIALCB //Set up to input into iPBI. eiaLCB>>EIALCB.byteCount = (lenPup+1) lshift 1 eiaLCB>>EIALCB.bytePointer = lv (lcb>>LCB.iPBI)>>EIAPBI.type eiaLCB>>EIALCB.firmStatus = 0 eiaLCB>>EIALCB.hardStatus = 0 eiaLCB>>EIALCB.partialCRC = 0 //Link the EIALCB to the line's LTE. //The microcode is always watching for this to go non-zero. eiaLT>>EIALT.eiaLTE↑(lcb>>LCB.line).iLCB = eiaLCB EnableInterrupts() ] //---------------------------------------------------------------------------- and StopEIAR(lcb) be //---------------------------------------------------------------------------- // Stop EIA reception of a packet over the line represented by the LCB. // This procedure is called by EIAProcess when it detects a dead line. [ DisableInterrupts() //Put the line in throw-away state. let eiaLTE = lv eiaLT>>EIALT.eiaLTE↑(lcb>>LCB.line) //Put the line in throw-away state, then //remove the EIALCB from the EIALTE, then //put the line back into bisync input state. eiaLTE>>EIALTE.iState = stateThrowAway eiaLTE>>EIALTE.iLCB = 0 eiaLTE>>EIALTE.iState = stateBiSyncInput EnableInterrupts() ] //---------------------------------------------------------------------------- and StartEIAT(lcb) be //---------------------------------------------------------------------------- // Start EIA transmission of a packet. [ DisableInterrupts() let eiaLCB = lcb>>LCB.oEIALCB //Set up to output from oPBI. eiaLCB>>EIALCB.byteCount = lcb>>LCB.oPBI>>PBI.packetLength eiaLCB>>EIALCB.bytePointer = lv (lcb>>LCB.oPBI)>>EIAPBI.type eiaLCB>>EIALCB.firmStatus = 0 eiaLCB>>EIALCB.hardStatus = 0 eiaLCB>>EIALCB.partialCRC = 0 eiaLT>>EIALT.eiaLTE↑(lcb>>LCB.line).oLCB = eiaLCB //Inform the EIA interface board that there is something new to do. @eiaControl = swi % (lcb>>LCB.line lshift 9) EnableInterrupts() ] //---------------------------------------------------------------------------- and StopEIAT(lcb) be //---------------------------------------------------------------------------- // Disable EIA transmission of a packet. // It is safe to call from both interrupt and non interrupt level. [ DisableInterrupts() let eiaLTE = lv eiaLT>>EIALT.eiaLTE↑(lcb>>LCB.line) //Put the line in throw-away state, then //remove the EIALCB from the EIALTE, then //put the line back into BiSync output state. eiaLTE>>EIALTE.oState = stateThrowAway eiaLTE>>EIALTE.oLCB = 0 eiaLTE>>EIALTE.oState = stateBiSyncOutput EnableInterrupts() ]