.TITLE IMPMUX - IMP PORT EXPANDER .INSRT ../../mos/moscnf-1.sml .INSRT ../../mos/mosmac.sml .INSRT ../../mos/mostbl.sml .INSRT imxtbl.sml .ENABL ISD .GLOBL $IMPMX ;PORT EXPANDER ENTRY POINT .GLOBL PRTTBL ;PORT VECTOR TABLE .GLOBL MBTBL ;MATCH BLOCK TABLE .GLOBL NCPPRT ;NCP PORT NUMBER .GLOBL GWTAB ;IN GATEWAY TABLE .GLOBL $TRACE ;TRACE ENQUEUEING ROUTINE .GLOBL $NOUT ;NUMBER OUTPUT ROUTINE .GLOBL TRCFLG ;PACKET TRACING ENABLE FLAG .GLOBL MSGFLG ;STATUS MSG PRINTING FLAG .GLOBL MSGCNT ;MAX NUMBER OF QUEUED MESSAGES .GLOBL IMP.UP,IMP.DN,IMP.IN ;IMP HANDLERS .GLOBL HST.UP,HST.DN,HST.IN ;HOST HANDLERS .GLOBL NETID ;NETWORK ADDRESS $CNFIG $DFIOR ;DEFINE I/O REQUEST BLOCK SW.MON = 1 ;MONITORING ENABLED SW.DBG = 0 ;DEBUGGING IN PROGRESS ANET = 12 ;NET NUMBER OF ARPANET PRT = %5 ;PORT TABLE ADDRESS CCB = %4 ;CONNECTION BLOCK ADDRESS MDB = CCB ;MATCH DESCRIPTOR BLOCK ENTRY PKT = %3 ;PACKET ADDRESS IORB = %2 ;IORB ADDR OP.PRT = 17 ;PORT INDICATOR (LOW 4 BITS OF OPC) OP.IN = 0*20 ;1822 INPUT COMPLETE OPCODE OP.OUT = 1*20 ;1822 OUTPUT COMPLETE OPCODE OP.TIM = 2*20 ;TIMER SIGNAL OPCODE .PAGE .SBTTL INITIALIZATION $IMPMX: MOV #STATS,R1 ;GET ADDR OF STATISTICS AREA MOV -2(R1),R0 ; AND ITS LENGTH 1$: CLR (R1)+ ;CLEAR EVENT COUNTERS $LOOP R0,1$ ; ; RESET THE CCB HASH TABLE ; MOV #CCBTBL,CCB ;GET ADDR OF CCB HASH TABLE MOV -2(CCB),R0 ;LENGTH OF TABLE IS -2 ENTRY 2$: CLR (CCB)+ ;RESET HASH TABLE ENTRIES $LOOP R0,2$ ; ; INITIALIZE THE PORT TABLES ; MOV #PRTTBL,R4 ;GET POINTER TO PORT TABLE MOV (R4)+,R1 ; AND NUMBER OF PORTS 3$: MOV (R4)+,PRT ;GET PORT TABLE ADDR $PUSH PRT ADD #PT.FLG,PRT ;ADVANCE TO FLAG FIELD MOV #/2,R0 ;LENGTH OF SCRATCH AREA 4$: CLR (PRT)+ ;CLEAR PORT TABLE $LOOP R0,4$ $POP PRT MOV #PT.OFL!PT.ERR!PT.DWN!PT.WD,PT.FLG(PRT) ;ASSUME PORT DOWN TST PT.IN(PRT) ;INPUT DEVICE DEFINED? BEQ 5$ ;IF NOT, SKIP TST PT.OUT(PRT) ;OUTPUT DEVICE DEFINED? BEQ 5$ ;IF NOT, SKIP BIC #PT.OFL,PT.FLG(PRT) ;MARK PORT AS ON-LINE 5$: $LOOP R1,3$ CLR IMPPRT ;RESET ID OF THE IMP PORT ; ; START TIMER GOING ; $STIME #OP.TIM,#0,#60.*3 .PAGE .SBTTL IMPMUX MAIN LOOP ; ; ONCE EVERYTHING HAS BEEN INITIALIZED, JUST WAIT FOR SIGNALS AND ; DISPATCH BASED ON OPCODE. ; WAITLP: $WAIT ;WAIT FOR ANY SIGNAL BIC #^C377,R0 ;CLEAR PID CMP R0,#OP.TIM ;VALID SIGNAL? BHI 1$ ;IF NOT, ERROR ASR R0 ;CONVERT TO TABLE INDEX ASR R0 ASR R0 JSR PC,@HNDTBL(R0) ;AND CALL HANDLER ROUTINE BR WAITLP 1$: BUGHLT HNDTBL: .WORD PRT.IN ;1822 INPUT HANDLER .WORD PRT.OT ;1822 OUTPUT HANDLER .WORD TIMER ;TIMER SIGNAL HANDLER .PAGE .SBTTL PRT.IN - 1822 PORT INPUT ROUTINE ; ; A MESSAGE HAS BEEN RECEIVED OVER SOME 1822 PORT. USE THE LOW 4 BITS OF ; THE OPCODE AS THE PORT NUMBER AND GET A POINTER TO THE PORT TABLE. ; IF THE TRANSFER IS IN ERROR, CALL THE ERROR HANDLER FOR THAT PORT. ; TWO ERROR HANDLERS ARE CURRENTLY DEFINED: "FOR AN IMP" AND "FOR A HOST". ; IF THE TRANSFER IS IN ERROR (HOST/IMP DOWN) THEN CLEAR THE UP-COUNTER ; (PT.UPC), MARK THE PORT AS BEING DOWN, IGNORE THE PACKET, AND RE-ISSUE A ; READ. ; ; IF THE PACKET IS RECEIVED OK, CALL THE HANDLER ROUTINE TO PROCESS THE ; THE PACKET. CURRENTLY SUPPORTED ARE "FROM IMP" AND "FROM HOST" HANDLERS. ; ; WHEN HANDLING ROUTINE RETURNS (EITHER ERROR OR RECEIVED HANDLER), THE ; THE DISPOSITION OF THE PACKET ARE INDICATED BY THE CONTENTS OF THE ; IORB POINTER: ; IORB = 0 - THEN PACKET HAS BEEN HANDLED INTERNALLY. RE-ISSUE A ; READ REQUEST ON THIS PORT USING A NEW IORB & PACKET. ; IORB # 0 - THEN PACKET WAS HANDLED, BUT A NEW READ REQUEST CAN ; REUSE THE IORB & PACKET BUFFER. ; ; IF A NEW READ SHOULD NOT BE DONE OF THIS PORT, THE PT.BLK FLAG WILL ; BE SET ON RETURN FROM THE HANDLERS. ; ; ; CALLED WITH: R1 - ADDRESS OF IORB ; ; RETURNS WITH: R0-R5 - CLOBBERED ; PRT.IN: MOV R1,IORB ;SAVE IORB POINTER MOVB IROPC(IORB),R0 ;GET OPCODE BIC #^COP.PRT,R0 ;CLEAR GARBAGE, LEAVING PORT NUMBER BEQ 6$ ;PORT NUMBER 0 IS AN ERROR CMP R0,PRTTBL ;VALID PORT NUMBER? BHI 6$ ;IF NOT, ERROR ASL R0 ;CONVERT TO TABLE INDEX MOV PRTTBL(R0),PRT ;GET PORT TABLE ADDRESS TST IRSTA(IORB) ;CHECK TRANSFER STATUS BMI 5$ ;IF ERROR, PORT IS NOW DOWN BIT #PT.WD,PT.FLG(PRT) ;CHECK PORT STATUS BNE 7$ ;IF WAS DOWN, INIT PORT HARDWARE MOV IRUVA(IORB),PKT ;GET PACKET ADDRESS CALL @PT.RCV(PRT) ;HANDLE MESSAGE OVER THIS PORT ; ; NOW CHECK THE DISPOSITION OF THE PACKET ; BIT #PT.BLK,PT.FLG(PRT) ;PORT BLOCKED? BNE 4$ ;IF SO, JUST EXIT (PKT HAS BEEN Q'D) TST IORB ;HAS PACKET BEEN DISPOSED OF? BNE 3$ ;IF NOT, RE-USE SAME IORB & PACKET $AVS #PKTLEN+IORBL ;ELSE, ALLOCATE REPLACEMENT PACKET ; R2 = NEW PACKET ADDR JSR PC,INITRB ;INITIALIZE THE I/O REQUEST BLOCK 3$: $SIO IORB ;INITIATE I/O 4$: RTS PC ;AND RETURN ; ; IF THE PORT IS DOWN, INDICATE THAT IN THE PORT TABLE ; 5$: BIT #PT.DWN,PT.FLG(PRT) ;WAS PORT UP? BNE 11$ ;IF NOT, SKIP INC PT.DN(PRT) ;IF UP, COUNT THE TRANSISTIONS CALL @PT.NRY(PRT) ;CALL PORT DOWN ROUTINE 11$: BIS #PT.DWN!PT.WD!PT.ERR,PT.FLG(PRT) ;INDICATE PORT DOWN $FVS #PKTLEN+IORBL,IORB ;RELEASE THE PACKET ;DROP ALL OTHER HOST LINES TO ; REFLECT IMP STATUS CLR IORB ;INDICATE PACKET RELEASED BR 4$ ;AND EXIT W/ PORT BLOCKED 6$: BUGHLT ; ; IF THE PORT IS DOWN BUT THE I/O REQUEST COMPLETED W/O ERRORS, ASSUME THAT ; THE PORT IS COMING UP. MARK THE PORT AS "WAS DOWN" ; 7$: $PUSH IORB MOV #ERRMSG,IORB ;SET ADDR OF ERROR MSG TEMPLATE CALL SNDCPY ;SEND COPY OF THE ERROR MESSAGE $POP IORB BIT #PT.DWN,PT.FLG(PRT) ;PORT BEEN INITIALIZED? BEQ 8$ ;IF SO, SKIP CALL @PT.INI(PRT) ;PORT COMING UP, CALL INIT ROUTINE 8$: BIC #PT.WD,PT.FLG(PRT) ;AND CLEAR "WAS DOWN" FLAG BR 3$ .PAGE .SBTTL IMP PORT HANDLER ROUTINES .SBTTL IMP.UP - IMP PORT INITIALIZER ROUTINE ; ; TO INITIALIZE THE IMP PORT, WE MUST SEND 4 NOP MESSAGES AND CLEAR THE ; IMPDWN IMP-DOWN FLAG ; ; CALLED WITH: PRT - ADDR OF PORT TABLE ; IMP.UP: $PUSH R0,IORB BIC #PT.DWN,PT.FLG(PRT) ;RESET DOWN FLAG INC PT.UP(PRT) ;COUNT TRANSISTIONS MOV #4,R0 ;SEND 4 NOP MESSAGES 1$: MOV #NOPMSG,IORB ;GET ADDR OF NOP TEMPLATE CALL SNDCPY ;SEND A COPY OF THE NOP MSG $LOOP R0,1$ .IF NE, SW.MON MOV #MSGUP,R0 CALL MTYPE ;OUTPUT "UP" MESSAGE .ENDC MOV PT.ID(PRT),IMPPRT ;SET IMP PORT ID $POP IORB,R0 RTS PC .PAGE .SBTTL IMP.DN - IMP PORT DOWN HANDLER ; ; A TRANFER FROM THE IMP HAS TERMINATED IN AN ERROR. COUNT THE NUBER OF ; TRANSISTIONS OF THE READY LINE AND IF MONITORING IS ENABLED, SIGNAL THE ; MONITORING PROCESS TO OUTPUT THE "IMP NOT READY" STATUS MESSAGE. MARK ; THE PORT AS CURRENTLY DOWN, AND SET THE "WAS DOWN" AND "ERROR" FLAGS. ; ; ; CALLED WITH: PRT - POINTER TO PORT TABLE ; IMP.DN: .IF NE, SW.MON ;IF MONITORING MOV #MSGDN,R0 CALL MTYPE ;OUTPUT "NOT READY" MSG .ENDC RET .PAGE .SBTTL IMP.IN - IMP MESSAGE INPUT HANDLER ; ; A MESSAGE FROM AN IMP HAS BEEN RECEIVED. HANDLE THE MESSAGE BY JUMPING ; THROUGH A DISPATCH TABLE INDEXED BY MESSAGE TYPE. THE ACTIONS ARE: ; ; TYPE 0 (REGULAR MESSAGE) - THE MESSAGE IS DISPATCHED TO THE ; APPROPRIATE HOST PORT BY LOOKING AT THE ; IMBEDDED INTERNET HEADER. ; ; TYPE 1 (ERROR IN LEADER) - LOG AND DISCARD. ; ; TYPE 2 (IMP GOING DOWN) - BROADCAST THIS MESSAGE TO ALL HOST PORTS ; ; TYPE 3 (UNCONTROLLED) - HANDLE SAME AS TYPE 0 ; ; TYPE 4 (NOP) - DISCARD ; ; TYPE 5 (RFNM) - USE THE SUB-LINK OF THE MESSAGE TO ; DISPATCH THE RFNM TO THE APPROPRIATE PORT ; AND DECREMENT THE COORESPONDING CCB PACKET ; OUTSTANDING COUNTER ; ; TYPE 6 (DEAD HOST INFO) - SEND THIS PACKET TO ALL HOSTS AWAITING ; DEAD HOST STATUS INFORMATION FOR THIS ; PARTICULAR HOST ; ; TYPE 7 (DESTINATION DEAD) - USE THE SUB-LINK TO DESPATCH TO THE ; APPROPRIATE PORT. IN ADDITION, IF ; SUBTYPE 1, INDICATE THE PORT IS AWAITING ; INFO ON HOST STATUS (TYPE 6 MSG) ; ; TYPE 8 (ERROR IN DATA) - LOG AND DISCARD ; ; TYPE 9 (INCOMPLETE TRANSMISSION) - HANDLE SAME AS TYPE 5 ; ; TYPE 10 (INTERFACE RESET) - RESET ALL DATA STRUCTURES AND BRING UP ; ALL HOST PORTS ; ; ; CALLED WITH: IORB - ADDRESS OF IORB ; PRT - ADDRESS OF PORT TABLE ; PKT - ADDR OF PACKET ; ; RETURNS WITH: IORB - ADDRESS OF IORB/DISPOSITION FLAG ; IMP.IN: CMPB AH.FMT(PKT),#17 ;96-BIT LEADER FORMAT PACKET? BNE 1$ ;IF NOT, IGNORE MOVB AH.TYP(PKT),R0 ;GET MESSAGE TYPE BIC #^C17,R0 ;CLEAR OTHER GARBAGE ASL R0 ;CONVERT TO WORD INDEX MOV PRT,R1 ;GET ADDR OF PORT TABLE ADD R0,R1 ;ADD IN MESSAGE TYPE OFFSET INC PT.RC(R1) ;COUNT # OF RCV MESSAGES PER TYPE CALL @IMPTBL(R0) ;AND CALL APPROPRIATE ROUTINE 1$: RET IMPTBL: .WORD ITYP0 ;TYPE 0 - REGULAR MESSAGES .WORD ITYP1 ;TYPE 1 - ERROR IN LEADER .WORD ITYP2 ;TYPE 2 - IMP GOING DOWN .WORD ITYP3 ;TYPE 3 - UNCONTROLLED PACKET .WORD ITYP4 ;TYPE 4 - NOP .WORD ITYP5 ;TYPE 5 - RFNM .WORD ITYP6 ;TYPE 6 - DEAD HOST STATUS .WORD ITYP7 ;TYPE 7 - DESTINATION DEAD .WORD ITYP8 ;TYPE 8 - ERROR IN DATA .WORD ITYP9 ;TYPE 9 - INCOMPLETE TRANSMISSION .WORD ITYP10 ;TYPE 10 - INTERFACE RESET .WORD 1$ ;INVALID TYPE .WORD 1$ ;INVALID TYPE .WORD 1$ ;INVALID TYPE .WORD 1$ ;INVALID TYPE .WORD 1$ ;INVALID TYPE 1$: BUGHLT .PAGE .SBTTL ITYP0 AND ITYP3 - HANDLE DATA MESSAGES ; ; WHEN A TYPE 0 OR TYPE 3 MESSAGE IS RECEIVED, FIRST CHECK THE MESSAGE'S ; LINK NUMBER. IF THE MSG IS NOT ON AN INTERNET LINK, THEN SEND THE MSG TO ; THE PORT THAT RECEIVES ALL NON-INET TRAFFIC (PORT INDEX IS IN NCPPRT) ; ; CALLED WITH: IORB - ADDRESS OF INPUT IORB ; PKT - ADDRESS OF PACKET HEADER ; PRT - ADDRESS OF INPUT PORT TABLE ; ; RETURNS WITH: IORB - DISPOSITION OF PACKET ; ITYP0: ITYP3: $PUSH PRT,IORB ;SAVE INPUT PORT NUMBER MOV #1,R1 ;SET LOOP COUNTER CMPB AH.LNK(PKT),#155. ;ON ONE OF THE INET LINKS? BLO 1$ ;IF NOT, SEND TO NCP PORT CMPB AH.LNK(PKT),#158. BLOS 2$ ;IF SO, SEARCH MATCH BLOCKS 1$: MOV NCPPRT,PRT ;GET NCP PORT INDEX BR 4$ ;SEND TO THAT PORT 2$: CMP IRBX(IORB),#OH.LEN+AH.LEN ;INET HEADER PRESENT? BLO 6$ ;IF NOT, DISCARD MOV #MBTBL,MDB ;GET ADDRESS OF MATCH BLOCK TABLE MOV -2(MDB),R1 ; AND NUMBER OF ENTRIES MOV PKT,R2 ;R2 - INET ADDR POINTER ADD #AH.LEN,R2 ;ADVANCE TO INET HEADER CMPB (R2),#IH.VAL ;NEW OR OLD FORMAT HEADER? BLO 3$ ;IF OLD FORMAT, SKIP ADD #IH.DN,R2 ;ELSE, ADVANCE POINTER TO ADDR FIELD 3$: MOV (R2),R0 ;GET DESTINATION NET & TCP HI IDS BIC MB.MSK(MDB),R0 ;AND IN MASK CMP MB.CMP(MDB),R0 ;A MATCH? BNE 5$ ;IF NOT, ADVANCE TO NEXT MOV 2(R2),R0 ;GET TCP ID BIC MB.MSK+2(MDB),R0 CMP MB.CMP+2(MDB),R0 ;A MATCH? BNE 5$ ;IF NOT, ADVANCE TO NEXT MOV MB.PRT(MDB),PRT ;GET PORT ID 4$: ASL PRT ;CONVERT TO WORD INDEX BEQ 7$ ;IF ZERO, DISCARD PACKET MOV PRTTBL(PRT),PRT ;CONVERT INDEX TO ADDRESS BIT #PT.DWN!PT.OFL,PT.FLG(PRT) ;OUTPUT PORT DOWN OR OFFLINE? BNE 5$ ;IF SO, CONTINUE SEARCH CMPB MSGCNT,PT.PKO(PRT) ;LARGE NUMBER OF OUTPUT I/O PENDING? BLOS 5$ ;IF SO, SKIP .IF NE, SW.MON MOV #MSGSND,R1 ;INDICATE SENT TO HOST CALL TRACE ;AND TRACE THE PACKET .ENDC MOV (SP),IORB ;RECOVER INPUT IORB JSR PC,SNDPKT ;SEND DATA PKT TO PROPER HOST CLR (SP) ;INDICATE THAT PACKET WAS HANDLED 6$: $POP IORB,PRT ;RECOVER INPUT PORT NUMBER & IORB RET ;AND RETURN 5$: ADD #MB.LEN,MDB ;ADVANCE TO NEXT ENTRY $LOOP R1,3$ ;AND CHECK IT 7$: .IF NE, SW.MON CLR PRT ;NO OUTPUT PORT MOV #MSGFSH,R1 ;INDICATE PKT DISCARDED CALL TRACE .ENDC BR 6$ ;AND DISCARD PACKET .PAGE .SBTTL ITYP1 - ERROR IN LEADER ITYP1: .IF NE, SW.MON MOV #MSGIT1,R0 CALL MTYPE ;OUTPUT "ERROR IN LEADER" MESSAGE .ENDC RET .PAGE .SBTTL ITYP2 - IMP GOING DOWN ITYP2: .IF NE, SW.MON ;IF MONITORING MOV #MSGIT2,R0 CALL MTYPE ;OUTPUT "IMP GOING DOWN" MSG .ENDC RET ;TEMPORARILY JUST DISCARD .SBTTL ITYP4 - NOP ITYP4: RTS PC ;DISCARD NOPS .PAGE .SBTTL ITYP5 - REQUEST FOR NEXT MESSAGE ; ; A RESPONSE TO A TRANSMITTED MESSAGE HAS BEEN RECEIVED (EITHER A RFNM, ; DESTINATION DEAD, OR INCOMPLETE TRANSMISSION). SEARCH THE OUTSTANDING ; MESSAGE LIST TO IDENTIFY THE HOST WHICH SHOULD GET THIS RESPONSE. ; ; CALLED WITH: IORB - ADDR OF IORB ; PKT - ADDR OF PACKET ; PRT - ADDR OF INPUT PORT TABLE ; ITYP5: ;RFNMS ITYP7: ;DESTINATION DEAD ITYP9: ;INCOMPLETE TRANSMISSIONS $PUSH PRT ;SAVE INPUT PORT NUMBER CALL FNDCCB ;SEARCH FOR CONNECTION BLOCK ; => CCB = CONNECTION BLOCK TST CCB ;CONNECTION BLOCK FOUND? BEQ 3$ ;NOPE, MUST BE AN ERROR TSTB CB.CNT(CCB) ;MESSAGE OUTSTANDING? BEQ 3$ ;IF NOT, ERROR DECB CB.CNT(CCB) ;DECREMENT MSGS OUTSTANDING COUNTER MOVB AH.SBL(PKT),R0 ;GET SUB-LINK FIELD BIC #^C360,R0 ;CLEAR SUB-TYPE, LEAVING SUB LINK ASR R0 ASR R0 ASR R0 ASR R0 ADD #2,R0 ;CHANGE SUB-LINK TO PORT ID BEQ 3$ ;IF ZERO, ERROR CMP R0,PRTTBL ;VERIFY PORT NUMBER IN MSG BHI 3$ ;IF TOO LARGE, ERROR BICB #360,AH.SBL(PKT) ;CLEAR SUB LINK FIELD ASL R0 ;CONVERT TO PORT INDEX MOV PRTTBL(R0),PRT ;GET ADDR OF OUTPUT PORT TABLE DECB PT.PKI(PRT) ;RFNM RECEIVED, DECRREMENT COUNTER JSR PC,SNDPKT ;SEND REPONSE TO HOST TST CB.BLK(CCB) ;ANY PORTS BLOCKED WAITING FOR RFNM? BEQ 2$ ;IF NOT, EXIT MOV CCB,R2 ;GET CCB ADDR ADD #CB.BLK,R2 ; CALCULATE BLOCKED QUEUE HEAD JSR PC,DEQ ;GET AN ELEMENT ; => R0 = ADDR OF BLOCKED IORB MOV R0,R1 ;SIGNAL OURSELVES, IORB ADDR AS DATA MOVB IROPC(R0),R0 ;GET SIGNAL OPCODE BIC #^COP.PRT,R0 ; AND CLEAR GARBAGE CMP R0,PRTTBL ;VALID PORT NUMBER? BHI 4$ ;IF NOT, ERROR ASL R0 ;CONVERT TO INDEX MOV PRTTBL(R0),PRT ;GET PORT TABLE ADDRESS BIC #PT.BLK,PT.FLG(PRT) ;PORT NO LONGER BLOCKED .IF NE, SW.MON MOV #MSGUNB,R0 ;GET "INTERFACED UNBLOCKED" MSG CALL MTYPE .ENDC $SGNLI #0,IROPC(R1),R1 ;SIMULATE PACKET INPUT 2$: CLR IORB ;INDICATE PACKET HANDLED $POP PRT ;RECOVER INPUT PORT NUMBER RTS PC 3$: .IF NE, SW.MON MOV #MSGRFN,R0 ;GET "INTERFACED UNBLOCKED" MSG CALL MTYPE .ENDC BR 2$ 4$: BUGHLT .PAGE .SBTTL ITYP6 - DEAD HOST STATUS ITYP6: RTS PC ;TEMPORARILY DISCARD .PAGE .SBTTL ITYP8 - ERROR IN DATA ITYP8: .IF NE, SW.MON MOV #MSGIT8,R0 CALL MTYPE ;OUTPUT "ERROR IN DATA" MESSAGE .ENDC RET .PAGE .SBTTL ITYP10 - INTERFACE RESET ITYP10: ;RESET ALL DATA STRUCTURES RTS PC .PAGE .SBTTL HOST PORT HANDLERS .SBTTL HST.UP - INITIALIZE A HOST PORT ; ; CALLED WITH: PRT - ADDR OF PORT TABLE ; HST.UP: $PUSH R0,IORB BIC #PT.DWN,PT.FLG(PRT) ;RESET DOWN FLAG INC PT.UP(PRT) ;COUNT TRANSISTIONS MOV #3,R0 ;SEND 3 NOP MESSAGES 1$: MOV #NOPMSG,IORB ;GET ADDR OF NOP TEMPLATE CALL SNDCPY ;SEND A COPY OF THE NOP MSG $LOOP R0,1$ MOV #RSTMSG,IORB ;GET ADDR OF RESET MSG TEMPLATE CALL SNDCPY ;SEND A COPY OF THE RESET .IF NE, SW.MON MOV #MSGUP,R0 CALL MTYPE ;OUTPUT "UP" MESSAGE .ENDC $POP IORB,R0 RET .PAGE .SBTTL HST.DN - HANDLE HOST NOT READY ERROR HST.DN: .IF NE, SW.MON MOV #MSGDN,R0 CALL MTYPE ;OUTPUT "NOT READY" MESSAGE .ENDC RET .PAGE .SBTTL HST.IN - A MESSAGE HAS BEEN RECEIVED FROM A HOST ; ; A MESSAGE HAS BEEN RECEIVED FROM AN ATTACHED HOST. IF IT IS AN ; UNCONTROLLED MESSAGE, FORWARD IMMEDIATELY TO THE IMP. IF IT IS ; A REGULAR MESSAGE, SEARCH THE CONNECTION BLOCKS LOOKING FOR A MATCH. ; IF NO CCB IS FOUND, ALLOCATE A NEW ONE. IF THE NUMBER OF MESSAGES ; OUTSTANDING ON THE CONNECTION IS LESS THAN 8, PUT THE PORT NUMBER ; INDICATOR INTO SUB-LINK FIELD OF THE MESSAGE AND OUTPUT THE MESSAGE TO ; THE IMP. IF THE NUMBER OF MESSAGES OUTSTANDING IS GREATER THAN OR EQUAL ; TO 8, ENQUEUE THE IORB ONTO THE "BLOCKED" LINKED LIST. IT WILL BE SENT ; WHEN A RFNM IS RECEIVED AND THE OUTSTANDING COUNT IS LESS THAN 8. THE ; HOST PORT WILL BE BLOCKED UNTIL THE MESSAGE IS SENT. ; ; CALLED WITH: IORB - ADDR OF IORB ; PRT - ADDR OF INPUT PORT TABLE ; PKT - ADDR OF PACKET ; HST.IN: TST PT.TYP(PRT) ;LNI? BEQ 17$ MOV PKT,R0 ;HANG ON TO POINTER ADD #LN.LEN,R0 ;MAKE IT POINT TO IN HDR ADD #2,PKT ;1822 HDR ONE WORD SMALLER MOV PKT,IRUVA(IORB) ;POINT IORB THAT WAY SUB #2,IRBX(IORB) ;MAKE LENGTH AGREE MOVB IH.DN(R0),R1 ;GET NET NUMBER BIC #177400,R1 ;FUCKING PDP-11 MOVB CMPB R1,#ANET ;FOR ARPANET? BEQ 13$ ;YES, GET ON WITH ACT TSTB R1 ;ILLEGAL ADDR? BEQ 11$ ;YEP, STEP ON CMPB R1,@#GWTAB ;NET NUMBER I DON'T KNOW ABOUT? BHI 11$ ;YEP, BARF ASL R1 ;WORD INDEX TSTB GWTAB(R1) ;DOES HE HAVE A GATEWAY? BNE 13$ ;YEP, PROCESS .IF NE, SW.MON MOV #MSGNG,R0 ;SAY NO GATEWAY .ENDC BR 12$ 11$: .IF NE, SW.MON MOV #MSGBN,R0 ;SAY BAD NET .ENDC 12$: .IF NE, SW.MON CALL MTYPE MOV #MSGRCV,R1 ;AND LET HIM KNOW WHO CULPRIT IS INC TRCFLG ;FORCE TRACE CALL TRACE DEC TRCFLG ;RESTORE NORMAL STATE .ENDC RET 13$: MOVB #17,AH.FMT(PKT) ;NOW CONSTRUCT 96 BIT LEADER CLRB AH.NET(PKT) CLRB AH.FLG(PKT) CLRB AH.TYP(PKT) ;TYPE 0 (DATA) MESSAGE CLRB AH.HND(PKT) CMPB IH.DN(R0),#ANET ;FOR ARPANET? BNE 14$ ;NO, PUT IN GWAY'S ADDR MOVB IH.DTH(R0),AH.HST(PKT) ;NOW HIS DEST MOVB IH.DT+1(R0),AH.IMP+1(PKT) BR 15$ 14$: MOVB GWTAB+1(R1),AH.HST(PKT) MOVB GWTAB(R1),AH.IMP+1(PKT) 15$: CLRB AH.IMP(PKT) MOVB #233,AH.LNK(PKT) ;SHOULD SPREAD LOAD, BUT.. CLRB AH.SBL(PKT) CLR AH.ML(PKT) BR DOPKT 17$: CMPB AH.FMT(PKT),#17 ;96-BIT LEADER FORMAT? BNE BADMSG ;IF NOT, DISCARD CLRB AH.IMP(PKT) ;CLEAR LOGICAL HOST FIELD DOPKT: MOVB AH.TYP(PKT),R0 ;GET PACKET TYPE BIC #^C17,R0 ASL R0 ;CONVERT TO WORD INDEX ADD PRT,R0 ;CALCULATE ADDR OF PKT TYPE COUNTER INC PT.RC(R0) ;AND BUMP COUNTER FOR THIS PKT TYPE CMPB AH.TYP(PKT),#4 ;NOP PACKET? BEQ 3$ ;IF SO, DISCARD TSTB AH.TYP(PKT) ;CHECK PACKET TYPE BNE INVMSG ;DISCARD ALL CONTROL MESSAGES CMPB AH.SBL(PKT),#3 ;SUB-TYPE 3 UNCONTROLLED TRAFFIC? BEQ 2$ ;IF SO, SEND TO IMP DIRECTLY INCB PT.PKI(PRT) ;INDICATE AWAITING FOR 1 MORE RFNM CALL FNDCCB ;FIND MATCHING CCB TST CCB ;ANY FOUND? BNE 1$ ;IF SO, SKIP CALL INICCB ;ELSE, ALLOCATE AND INITIALIZE ONE 1$: CLRB CB.IDL(CCB) ;RESET IDLE FLAG CMPB CB.CNT(CCB),#8. ;CHECK NUMBER OF MSGS OUTSTANDING BHIS 4$ ;IF TOO MANY, BLOCK INTERFACE INCB CB.CNT(CCB) ;BUMP COUNT 2$: MOV PT.ID(PRT),R0 ;GET PORT ID SUB #2,R0 ;CHANGE FROM 0 - MAX-1 ASL R0 ASL R0 ASL R0 ASL R0 ;MOVE TO HIGH NIBBLE BICB #360,AH.SBL(PKT) ;CLEAR SUB-LINK FIELD BISB R0,AH.SBL(PKT) ;SET PORT NUMBER IN SUB-LINK .IF NE, SW.MON MOV #MSGRCV,R1 ;INDICATE PKR RECEIVED FROM HOST CALL TRACE .ENDC $PUSH PRT ;SAVE INPUT PORT MOV IMPPRT,R0 ASL R0 MOV PRTTBL(R0),PRT ;GET IMP PORT ADDR JSR PC,SNDPKT ;SEND THE PACKET CLR IORB ;INDICATE PACKET DISPATCHED $POP PRT ;RECOVER INPUT PORT 3$: RET 4$: TST PT.TYP(PRT) ;LNI? BEQ 5$ ;IF SO, PUT PACKET BACK THE WAY IT WAS SUB #2,PKT ;1822 HDR ONE WORD SMALLER MOV PKT,IRUVA(IORB) ;POINT IORB THAT WAY ADD #2,IRBX(IORB) ;MAKE LENGTH AGREE 5$: INC PT.BC(PRT) ;COUNT # OF TIMES INTERFACE BLOCKED .IF NE, SW.MON MOV #MSGBLK,R0 ;GET "INTERFACED BLOCKED" MSG CALL MTYPE .ENDC MOV IORB,R0 MOV CCB,R2 ;GET CCB ADDR ADD #CB.BLK,R2 ;CALCULATE ADDR OF BLOCKED IORB QUEUE JSR PC,ENQ ;ENQUEUE IORB ON BLOCKED QUEUE BIS #PT.BLK,PT.FLG(PRT) ;INDICATE PORT BLOCKED RET ;AND THEN RETURN BADMSG: .IF NE, SW.MON MOV #MSGBAD,R0 ;GET "OLD-STYLE LEADER RECEIVED" MSG CALL MTYPE ;OUTPUT MESSAGE .ENDC RET ;AND DISCARD INVMSG: .IF NE, SW.MON MOV #MSGINV,R0 ;GET "INVALID MSG TYPE" MSG CALL MTYPE ;OUTPUT MESSAGE .ENDC RET ;AND DISCARD .PAGE .SBTTL PRT.OT - 1822 PORT OUTPUT COMPLETION ; ; WHEN THE OUTPUT IS COMPLETED ON A PORT, THE IORB AND PACKET CAN BE ; RETURNED TO THE STORAGE POOL. ; ; ENTERED WITH: R1 - ADDR OF IORB ; PRT.OT: MOVB IROPC(R1),R0 ;GET OPCODE BIC #^COP.PRT,R0 ;CLEAR GARBAGE, LEAVING PORT NUMBER BEQ 1$ ;IF 0, ERROR CMP R0,PRTTBL ;VALIS PORT NUMBER? BHI 1$ ;IF NOT, ERROR ASL R0 MOV PRTTBL(R0),PRT ;GET PORT TABLE ADDRESS DECB PT.PKO(PRT) ;INDICATE OUTPUT COMPLETE MOV R1,R2 $FVS #PKTLEN+IORBL,R2 ;RELEASE PACKET BUFFER RTS PC 1$: BUGHLT