.TITLE RTRRSX MA ROUTER RSX VERSION .IDENT /1.6/ ; ; This is the code for the MA_ROUTER RSX version. ; ; UPDATES: ; ; 03/12/87 D. LUECK VERSION 1.1 ; Added support to translate a logical node name into ; an actual node name used for the service. ; ; 03/17/87 D. LUECK VERSION 1.2 ; Added support to log all state changes (i.e. connect/disconnect) ; to the queue (message id NET_STATUS). ; ; 05/18/87 D. LUECK VERSION 1.3 ; Added support to reject a connect request if accept of the connect ; request results in a bad I/O status. ; ; 06/08/87 D. LUECK VERSION 1.4 ; Added additional support for V1.3 implementation. The reject of ; a connect request in V1.3 did not work properly. A network message ; buffer was added to each NRB defined in the database to save the connect ; block received in the mail buffer by GND$. The accept connection ; AST routine did not have a valid temporary link address in the connect ; block to reject the connect request -- probably lost when GND$ dequeued ; another network message into the same mail buffer. ; ; 06/09/87 D. LUECK VERSION 1.5 ; The invalid temporary link address mentioned in V1.4 change was caused ; by passing a connect block size of 0 to REJECT. Although a save buffer ; was not needed to save the connect block, it was retained to avoid ; any future problems. ; ; 10/08/87 D. LUECK VERSION 1.6 ; Added retry counter to 'read message from queue' function in routine ; GETOUT. The counter uses the last two bits (14 and 15) of word ; NID.ST in the routing database. This counter was added because ; the test for messages in a queue (M.CNT offset in queue listhead) ; indicated at least one message, but a 'no messages in queue' error ; (IE.EOF) was returned from the QUEACP when a read was attempted. No ; reason for the error could be detected at this time and the affected ; queue does not appear to be corrupted. ; ; ; SYSTEM MACROS ; .MCALL WTLO$ ; WAIT FOR LOGICAL OR OF EVENT FLAGS .MCALL SETF$ ; SET SINGLE EVENT FLAG .MCALL MRKT$ ; MARK TIME .MCALL CMKT$S ; CANCEL MARK TIME REQUEST .MCALL WTSE$S ; WAIT FOR SINGLE EVENT FLAG .MCALL GTIM$ ; GET SYSTEM TIME .MCALL SETF$S ; SET SINGLE EVENT FLAG .MCALL RDAF$ ; READ ALL EVENT FLAGS .MCALL QIOSY$ ; DEFINE ALL THE FUNCTION CODES .MCALL WTSE$S ; WAIT FOR SINGLE EVENT FLAG .MCALL CLEF$S ; CLEAR EVENT FLAG .MCALL SRDA$S ; SPECIFY RECIEVE DATA AST .MCALL DIR$ ; DIRECTIVE CALL .MCALL QIO$ ; QIO CALL .MCALL QIOW$ ; QIO AND WAIT CALL .MCALL ASTX$S ; AST EXIT .MCALL SREX$S ; SPECIFY REQUESTED EXIT AST .MCALL RQST$ ; RUN A TASK .MCALL ATRG$ ; ATTACH TO REGION .MCALL CRAW$ ; CREATE ADDRESS WINDOW .MCALL DTRG$S ; DETACH REGION .MCALL SVTK$S ; SPECIFY SST VECTOR TABLE .MCALL SNPBK$ ; ALLOCATE SNAPSHOT DUMP CONTROL BLOCK .MCALL SNAP$ ; GENERATE SNAPSHOT DUMP .MCALL EXIT$S ; TASK EXIT .MCALL ALUN$ ; ASSIGN LOGICAL UNIT NUMBER .MCALL DSAR$S ; DISABLE AST RECOGNITION .MCALL ENAR$S ; ENABLE AST RECOGNITION ; ; EQUATES ; ;DEBUG=1 ; DEFINE SYMBOL TO PRINT DEBUG MESSAGES ; ICO=1 ; CONSOLE DEVICE IZQ=2 ; QUEUE DEVICE DRIVER INET=3 ; NETWORK MESSAGES ; LUNS 4... TO N+3 WHERE N= NUMBER OF NODES ARE THE ; LUNS ASSIGNED TO THE TASK ON THE REMOTE NODES ; ; EVENT FLAGS ; NETEFN=5 ; EVENT FLAG TO SET WHEN NETWORK MESSAGE (NOT NORMAL ; TASK TO TASK MESSAGE) CONEFN=6 ; EVENT FLAG TO SET WHEN CONSOLE I/O COMPLETE SNPEFN=7 ; EVENT FLAG TO SYNCHRONIZE SST HANDLER AND PMD WAKEFN=8. ; WAKE UP EVENT FLAG QUEEFN=9. ; USED FOR ACCESSING THE QUEUE MRKEFN=10. ; USED BY MARK TIME DIRECTIVE WATEFN=11. ; USED BY TASK FOR QIO'S THAT ARE TO COMPLETE SYNCHRONOUSLY ; ; ; QUEUE FILE MACROS (QUEUE.MLB) ; .MCALL HDRDEF ; MESSAGE HEADER OFFSETS .MCALL QHDDEF ; QUEUE HEADER OFFSETS .MCALL MIDDEF ; MESSAGE ID LIST HEAD DEFINITIONS .MCALL RTRHED ; ROUTER DATABASE HEADER DEFINITIONS .MCALL NRBDEF ; DEFINE NRB OFFSETS .MCALL OUTDEF ; OUTPUT BUFFER OFFSETS .MCALL RSPDEF ; RESPONSE BUFFER OFFSETS .MCALL EVTDEF ; EVENT QUEUE ENTRY DEFINITONS .MCALL MGHDEF ; MESSAGE DEFINITION BETWEEN ROUTERS .MCALL STADEF ; CONNECT/DISCONNECT MESSAGE OFFSETS ; ; NETWORK MACROS ; .MCALL CNBDF$ ; CONNECT BLOCK DEFINITIONS .MCALL SPAW$ ; SPECIFY NETWORK MESSAGES AST .MCALL GLNW$ ; GET LOCAL NETWORK INFORMATION .MCALL OPNW$ ; OPEN LUN TO NETWORK .MCALL GNDW$ ; GET NETWORK DATA .MCALL NETDF$ ; NETWORK SYMBOLIC OFFSETS .MCALL ACC$S ; ACCEPT CONNECT REQUEST .MCALL REJ$S ; REJECT CONNECT REQUEST .MCALL REC$ ; RECEIVE DATA OVER NETWORK LOGICAL LINK .MCALL SND$ ; SEND DATA OVER NETWORK LOGICAL LINK .MCALL CON$ ; CONNECT REQUEST .MCALL DSC$S ; DISCONNECT LOGICAL LINK .MCALL DSC$ ; ; INVOKE SOME OF THE MACROS TO DEFINE OFFSETS ; QIOSY$ NETDF$ CNBDF$ ; .LIST ME HDRDEF QHDDEF MIDDEF RTRHED NRBDEF OUTDEF RSPDEF EVTDEF MGHDEF STADEF .NLIST ME .PAGE .PSECT $DATA,D,CON,LCL,REL ; ; DIRECTIVES AND THE LIKE ; ; ; DPB'S TO CREATE AND MAP REGION FOR OUR QUEUE HEADER ; CRWND: CRAW$ WDB ; CREATE ADDRESS WINDOW ; ; WINDOW DESCRIPTOR BLOCK ; WDB: .BYTE 0 ; UNUSED .BYTE 6 ; W.NAPR APR (6) .WORD 0 ; W.NBAS RETURN V. A. OR WINDOW .WORD 0 ; W.NSIZ DESIRED SIZE OF WINDOW IN 32W BLOCKS .WORD 0 ; W.NRID TASK REGION ID (FROM CREATE REGION) .WORD 0 ; W.NOFF OFFSET TO START MAP .WORD 0 ; W.NLEN LENGTH TO BE MAPPED IN 32W BLOCKS .WORD WS.RED!WS.MAP!WS.UDS ; W.NSTS STATUS ; WS.MAP= IF WINDOW IS TO BE MAPPED ; WS.RED= READ ACCESS ; WS.UDS= CREATE WINDOW IN USER "D" SPACE ; ATREG: ATRG$ RDB ; ATTACH REGION ; ; REGIONS DESCRIPTOR BLOCK ; RDB: .WORD 0 ; R.GID RETURNDED ID TO THE CREATED REGION .WORD 0 ; R.GSIZ SIZE OF REGION TO CREATE IN 32W BLOCKS .RAD50 /QUEHED/ ; R.GNAM NAME OF REGION .WORD 0,0 ; R.GPAR PARTITION NAME (0= OUR PARTITION) .WORD RS.RED!RS.DEL ; R.GSTS STATUS .WORD 010400 ; R.GPRO PROTECTION, ALLOW ONLY OWNER AND SYSTEM FULL ; ACCESS, REST READ ACCESS .PAGE ; ; SST TRAP VECTOR FOR "SVTK$S" MACRO CALL ; SSTVEC: .WORD ODDSST ; ODD ADDRESS OR NONEXISTENT MEMORY .WORD MEMSST ; MEMORY PROTECT VIOLATION .WORD TBTSST ; T-BIT TRAP OR EXECUTION OF A BPT INSTRUCTION .WORD IOTSST ; EXECUTION OF AN IOT INSTRUCTION .WORD RESSST ; EXECUTION OF A RESERVED INSTRUCTION .WORD EMTSST ; EXECUTION OF A NON-RSX EMT INSTRUCTION .WORD TRPSST ; EXECUTION OF A TRAP INSTRUCTION .WORD FLTSST ; FLOATING POINT EXCEPTION ; ; ; DEFINE AND ALLOCATE THE SNAPSHOT CONTROL BLOCK ; SNPSHT: SNPBK$ LB,0,SC.HDR!SC.LUN!SC.STK!SC.WRD!SC.BYT,SNPEFN,100. ; ; THE FOLLOWING GLOBAL SYMBOL IS DEFINED BY THE ROUTING DATABASE ; AND IS THEN LINKED IN WITH THIS IMAGE. IT IS A SAVE GUARD ; AGAINST INCOMPATABLE ROUTING DATABASES AND TASKBUILDS WITH ; THIS TASK. ; DBSID: .WORD RTRDID ; SEE RTRDBS FOR RTRDID DEFINITIONS ; ; TELL NETWORK THAT WE WANT UNSOLICITED MESSAGES ; SPAW: SPAW$ INET,NETEFN,NETSTA,CONAST, GLNW: GLNW$ INET,NETEFN,NETSTA,, ; LOCAL: .BLKW 4 ; LOCAL NODE NAME AND DEFAULT NSP SEGMENT SIZE .ASCII /RTRRSX/ ; RESPONSE BUFFER FOR A CONNECT .EVEN ; NETSTA: .WORD 0,0 ; NETWORK STATUS ; OPNW: ; OPEN LUN TO NETOWRK OPNW$ INET,NETEFN,NETSTA,, ; 3 MINUTE DISCONECT ; GNDW: GNDW$ INET,NETEFN,NETSTA,,,NT.TYP ; GET ANY MESSAGE REQEST: RQST$ FNDSRV ; RUN TASK 'FNDSRV' RETRY: MRKT$ WAKEFN,1,2 ; MARK TIME FOR 1 SECOND TIMER: MRKT$ WAKEFN,1,4,NRTAST ; MARK TIME 1 HOUR CONTIM: MRKT$ WAKEFN,15.,3,CNTAST ; MARK TIME 15 MINUTES CONTM2: MRKT$ WAKEFN,2,3,CNTAST ; MARK TIME 2 MINUTES ; ; NETWORK MAIL BUFFER ; MAIL: .BLKB N.CBL+30 ; SIZE OF MAIL PLUS ROOM ; FOR SOME OPTIONAL POOP MLEN=.-MAIL ; ; CONNECT/DISCONNECT STATUS MESSAGE WRITTEN TO QUEUE ; STAMSG: .BLKB SM.LEN STAFLG: .WORD 0 ; STATUS MESSAGE MSG ID FOUND FLAG STAMID: .ASCII /NET_STATUS / ; STATUS MESSAGE MSG ID NAME STASTA: .WORD 0,0 ; WRITE STATUS MESSAGE TO QUEUE QIO STATUS ; ; NETWORK MESSAGE TYPE TABLE AND JUMP TABLE ; FOR DISPOSEING OF EACH TYPE OF NETWORK MESSAGE ; TYPTBL: .BYTE NT.CON ; CONNECT .BYTE NT.INT ; INTERRUPT .BYTE NT.DSC ; DISCONNECT .BYTE NT.ABT ; USER ABORT .BYTE NT.ABO ; NETWORK ABORT TYPCNT=.-TYPTBL .EVEN ; ; SUBROUTINE TO HANDLE EACH TYPE OF NETWORK MESSAGE ; NOTE: THEY ARE IN REVERSE ORDER FROM ABOVE (BECAUSE OF JSR INSTRUCTION) ; TYPJMP: .WORD ABOMSG .WORD ABTMSG .WORD DSCMSG .WORD INTMSG .WORD CONMSG ; ASTCNT: .WORD 0 ; ; EVENT QUEUE DISPOSE TABLE ; ENTTYP: .WORD EVTCON ; EVENT= CONNECTION COMPLETE .WORD EVTRSP ; EVENT= RETRY ALLOCATING RESPONSE BUFFER AFTER ; MARK TIME COMPLETES .WORD EVTNRT ; EVENT= MARK MSG ID'S AS ROUTABLE .WORD CONFAL ; EVENT= CONNECTION FAILURE .WORD CONTRY ; EVENT= TRY CONNECTING TO REMOTES .WORD EVTDIS ; EVENT= DISCONNECT COMPLETE ENTCNT=<.-ENTTYP>/2 ; NUMBER OF EVENTS .EVEN ; ; SUBROUTINE LIST FOR EACH EVENT ; NOTE: IN REVERSE ORDER FROM ABOVE (BECAUSE OF JSR INSTRUCTION) ; ENTJMP: .WORD DISCMP ; DISCONNECT COMPLETE .WORD CONNOD ; TIME TO ATTEMT A CONNECT .WORD CNFALS ; CONNECTION FAILURE .WORD NRTENB ; TIME TO MARK MSG ID'S AS ROUTABLE .WORD RERSP ; RETRY RESPONSE BUFFER ALLOCATION .WORD CONCMP ; CONNECT COMPLETE ; ; READ DATA FROM NETWORK QIO ; REDNET: REC$ ,NETEFN,,REDAST, ; BUFFER, LENGTH, LUN, AND ; BUFFER SIZE FILLED IN LATER ; ; WRITE DATA TO NETWORK QIO ; WRTNET: SND$ ,NETEFN,,WRRAST, ; BUFFER, LENGTH, LUN, AND ; BUFFER SIZE FILLED IN LATER SNDNET: SND$ ,NETEFN,,WROAST, ; BUFFER, LENGTH, LUN, AND ; BUFFER SIZE FILLED IN LATER ; ; CONNECT REQUEST ; CONREQ: CON$ ,NETEFN,,CNLAST,<,N.RQL> .PAGE ; ; QIOS TO THE QUEUE DRIVER/ACP ; WRTQUE: ; WRITE TO THE QUEUE (ROUTER ENTRY) QIO$ IO.WVB+1,IZQ,QUEEFN,,,WRQAST,<> REDQUE: ; READ FROM THE QUEUE QIOW$ IO.RVB,IZQ,WATEFN,,,<> RNAQUE: ; BACKUP RNA QIO$ IO.RNA,IZQ,QUEEFN,,,RNAAST,<,16.> ACKQUE: ; ACKNOWLEGE A READ FROM THE QUEUE QIO$ IO.ACW,IZQ,QUEEFN,,,ACKAST,<,16.> ; ; CONNECT A MESSAGE ID TO QUEUE ; CONQUE: QIOW$ IO.ACR,IZQ,WATEFN,,QUESTA,,<,16.,WAKEFN> ; QUESTA: .BLKW 2 ; CONNECT TO QUEUE STATUS ; QINIT: QIO$ IO.DAC,IZQ,,,,, ; RESID: QIOW$ IO.RNA,IZQ,WATEFN,,,,<,16.> ; BACKUP RNA FOR ID AND WAIT ; (USED WHEN NEW CONNECTION MADE) DISCQ: QIO$ IO.KIL,IZQ,,,,, ; KILL ALL PENDING I/O TO ZQ0: WRTSTA: QIOW$ IO.WVB,IZQ,WATEFN,,STASTA,, ; QIO TO WRITE CONNECT/DISCONNECT ; STATUS MESSAGE TO QUEUE .PAGE ; ; LINKAGE TO THE ROUTING DATABASE COMMON ; .PSECT ARTRHD,RW,D,OVR,REL,GBL RTRHED: .PSECT NRBS,D,OVR,RW,REL,GBL .PSECT OUTBUF,D,RW,REL,OVR,GBL .PSECT RSPBUF,D,RW,REL,OVR,GBL .PSECT UNSBUF,D,RW,REL,OVR,GBL .PAGE ; ; SET UP SST VECTOR ; .PSECT $CODE,RO,I,CON,REL START: SVTK$S #SSTVEC,#8. ; DEFINE SST VECTOR BCC 5$ ; SST DIRECTIVE SUCCESSFUL MOV #"01,ERRNUM ; STORE ERROR NUMBER CALL DSWMSG ; LOG STATUS EXIT$S ; CAN'T CONTINUE ; ; ATTACH TO THE REGION ; 5$: DIR$ #ATREG ; ATTACH TO THE REGION BCC 10$ ; ATTACH OK? MOV #"02,ERRNUM ; ERORR NUMBER, FOR OUTPUT MESSAGE CALL DSWMSG ; LOG THE MESSAGE EXIT$S ; FATAL ERROR 10$: MOV RDB+R.GSIZ,WDB+W.NSIZ ; SET SIZE OF WINDOW MOV RDB+R.GID,WDB+W.NRID ; COPY REGION ID DIR$ #CRWND ; CREATE THE WINDOW BCC 20$ ; EVERYTHING OK? MOV #"03,ERRNUM ; ERROR NUMBER FOR OUTPUT MESSAGE CALL DSWMSG ; LOG ERROR EXIT$S ; FATAL ERROR 20$: MOV #"04,ERRNUM ; LOG SUCCESSFUL STATUS MOV RDB+R.GSIZ,ERRSTA ; STATUS TO BE ENCODED CALL MESGW ; LOG ERROR ; ; VALIDATE OUR ROUTING DATABASE ; CMP DBSID,RTRHED+HD.ID ; DO DATABASES MATCH? BEQ 25$ ; YES, GO LINK DBS WITH QUEUE MOV #"05,ERRNUM ; LOG THE ERROR MOV DBSID,ERRSTA ; COPY OUR VERSION CALL MESGW ; LOG ERROR MESSAGE EXIT$S ; CAN'T CONTINUE ; ; MAKE SURE DATABASE HAS NOT BEEN ACCESSED SINCE INSTALLED FROM DISK ; 25$: TST RTRHED+HD.STR ; WAS DATABASE ACCESSED? BEQ 30$ ; NO, SO OK MOV #"54,ERRNUM ; ERROR NUMBER CLR ERRSTA ; NO STATUS CALL MESGW ; LOG ERROR MESSAGE EXIT$S ; CAN'T CONTINUE 30$: INC RTRHED+HD.STR ; MARK DATABASE AS HAVING BEEN ACCESSED ; DIR$ #QINIT ; SET UP EXIT POOP FOR QUEUE BCC INIDS ; A-OK? MOV #"50,ERRNUM ; ERROR NUMBER CALL DSWMSG ; LOG ERROR EXIT$S .PAGE ; ; DATABASE INITIALIZATION FOR THE RTRRSX TASK. ; THE FOLLOWING ARE DONE: ; ; 1) SCAN ALL OF THE NRB'S AND CLEAR THE STATUS WORD ; ; 2) FOR ALL MESSAGE ID'S THAT ARE ROUTED TO THE ; NODE SPECIFIED BY THIS NRB, FIND THE MESSAGE ; ID IN THE QUEUE. IF NOT IN QUEUE, SIMPLY ; CLEAR THE LINK TO THE QUEUE MESSAGE ID LIST HEAD ; AND LOG THE ERROR. ; ; ; LOOP LOOKING AT EACH NRB ; INIDS: MOV RTRHED+HD.NCT,R1 ; NUMBER OF NRB'S DEFINED MOV RTRHED+HD.NRB,R5 ; NRB BEGINNING THREAD MOV #140000+Q.KSIZ,-(SP) ; WHERE MESSAGE ID LIST HEADS START ; (RIGHT AFTER THE QUEUE HEADER) 10$: MOV N.IDS(R5),-(SP) ; NUMBER OF MESSAGE ID'S ; ROUTED TO THIS NODE BEQ 105$ ; NONE ROUTED, ONLY RECEIVED ; MOV R5,R3 ; COPY NRB ADD #N.IDXL,R3 ; POINT TO MESSAGE ID LIST MOV R3,-(SP) ; SAVE INDEX TO ID LIST ; ; SCAN THE QUEUE LOOKING FOR THE MESSAGE ID IN THE QUEUE ; 30$: MOV @#<140000 ! Q.IDC>,R0 ; GET NUMBER OF ID'S IN QUEUE ; ; LOOP FOR EACH ID IN QUEUE ; 40$: MOV (SP),R3 ; GET CURRENT NRB MESG. ID LIST PTR. MOV 4(SP),R2 ; ID LHD. TO COMPARE IN QUEUE ADD #M.MID,R2 ; POINT TO THE ID NAME IN LHD. MOV #M.IDSIZ/2,R4 ; SIZE OF A MESSAGE ID IN WORDS ADD #NID.NM,R3 ; POINT TO THE ACTUAL ASCII ID NAME ; IN ID LIST HEAD 50$: CMP (R3)+,(R2)+ ; MATCH? BNE 80$ ; NO SOB R4,50$ ; YES, SO FAR ; ; MATCH COMPLETELY, STORE ADDRESS TO MESSAGE ID LIST ; HEAD IN THE QUEUE ; MOV (SP),R2 ; GET MESSAGE ID NRB LIST PTR. MOV 4(SP),NID.IX(R2) ; STORE ADDRESS TO ENTRY IN QUEUE CLR NID.ST(R2) ; CLEAR STATUS WORD ; ; CONNECT THE MESSAGE IT TO THE QUEUE ; MOV R2,CONQUE+Q.IOPL ; ADDRESS OF NRBID ADD #NID.NM,CONQUE+Q.IOPL ; ADD OFFSET TO ACTUAL MESSAGE ID DIR$ #CONQUE ; CONNECT MESSAGE ID TO QUEUE BCC 55$ ; DIRECTIVE ACCEPTED MOV #"34,ERRNUM ; NO CALL DSWMSG ; LOG IT DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; EXIT 55$: CMPB #IS.SUC,QUESTA ; STATUS GOOD? BEQ 60$ ; YES MOVB QUESTA,ERRSTA BIS #177400,ERRSTA ; SIGN EXTEND STATUS MOV #"35,ERRNUM ; ERROR CALL MESGW DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; EXIT ; ; FOUND OR NOT, POINT TO NEXT MESSAGE ID IN NRB ID LIST ; 60$: MOV #140000+Q.KSIZ,4(SP) ; RESET THE QUEUE SEARCH POINTER DEC 2(SP) ; DECREMENT NUMBER THAT HAVE TO LOOK FOR BEQ 100$ ; THIS NRB, ALL DONE THIS NRB? ADD #NID.LN,(SP) ; UPDATE NRB ID LIST POINTER BR 30$ ; GO SEE IF WE CAN FIND THIS ID IN QUEUE ; ; MESSAGE ID'S DON'T MATCH, UPDATE TO NEXT MESSAGE ID IN QUEUE OR ELSE ; MESSAGE ID IS NOT IN THE QUEUE ; 80$: ADD #M.LEN,4(SP) ; ADD SIZE OF A MESSAGE ID LISTHEAD DEC R0 BEQ 85$ JMP 40$ ; LOOP FOR NUMBER ID'S IN QUEUE ; ; CAN'T FIND THE MESSAGE ID IN THE QUEUE ; 85$: MOV #M.IDSIZ/2,R4 ; NUMBER WORDS IN MESSAGE ID MOV #ASCXTA,R2 ; BUFFER FOR LOGGING MOV #NID.NM,R3 ; OFFSET IN NBR ID LIST TO ID NAME ADD (SP),R3 ; ADD CURRENT ID LIST ELEMENT ADDR. 90$: MOV (R3)+,(R2)+ ; COPY ID THAT WASN'T FOUND FOR LOG SOB R4,90$ CLR ERRSTA MOV #"26,ERRNUM ; MESSAGE ID NOT FOUND ERROR NUMBER CALL MESGW ; LOG THE ERROR BR 60$ ; GO CHECK NEXT ID IN NRB ID LIST ; ; DONE THIS NRB, CHECK NEXT ; 100$: TST (SP)+ ; POP OFF THE NRB ID LIST POINTER 105$: ; <--- if the NRB didn't have any id's at all MOV N.LNK(R5),R5 ; POINT TO NEXT NRB TST (SP)+ ; POP OFF NUMBER IDS THIS NRB DEC R1 BEQ 110$ JMP 10$ ; GO CHECK NEXT NODE 110$: TST (SP)+ ; POP OFF ADDRESS OF THE FIRST ; MESSAGE ID LHD. IN THE QUEUE ; ALL DONE .PAGE ; ; CONNECT A LUN FOR THE UNSOLICITED NETWORK MESSAGES ; ININET: DIR$ #OPNW ; OPEN LUN TO NETWORK BCC 25$ ; DIRECTIVE ACCEPTED? MOV #"06,ERRNUM CALL DSWMSG ; LOG THE ERROR DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; FATAL 25$: CMPB #IS.SUC,NETSTA ; WAS STATUS SUCCESSFUL? BEQ 30$ ; YES MOVB NETSTA,R0 ; GET STATUS MOV R0,ERRSTA ; STORE FOR LOG MOV #"11,ERRNUM ; ERROR NUMBER CALL MESGW ; LOG MESSAGE DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; FATAL ERROR 30$: DIR$ #SPAW ; SPECIFY NETWORK MESSAGES AST'S BCC 40$ ; DIRECTIVE ACCEPTED? MOV #"07,ERRNUM CALL DSWMSG ; LOG ERROR DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; ; SEE IF STATUS GOOD TOO ; 40$: CMPB #IE.NDA,NETSTA ; NO DATA IN QUEUE? BEQ 50$ ; OK CMPB #IS.SUC,NETSTA ; WAS IT SUCCESSFUL? BEQ 50$ ; YES MOVB NETSTA,R0 ; SIGN EXTEND MOV #"08,ERRNUM MOV R0,ERRSTA CALL MESGW ; LOG ERROR DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; FATAL ; ; GET OUR LOCAL NODE INFORMATION ; 50$: DIR$ #GLNW ; GET LOCAL NODE INFORMATION BCC 60$ ; DIRECTIVE ACCEPTED? MOV #"09,ERRNUM CALL DSWMSG ; LOG ERROR DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; FATAL ; 60$: TSTB NETSTA ; GOOD I/O STATUS? BPL 70$ ; YES MOVB NETSTA,R0 MOV R0,ERRSTA MOV #"10,ERRNUM CALL MESGW ; LOG ERROR DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; FATAL .PAGE ; ; ALREADY TO GO ; 70$: MOV LOCAL,ASCXTA ; COPY NODE NAME FOR OUR OUTPUT MOV LOCAL+2,ASCXTA+2 MOV LOCAL+4,ASCXTA+4 ; MOV LOCAL,RTRHED+HD.NOD MOV LOCAL+2,RTRHED+HD.NOD+2 MOV LOCAL+4,RTRHED+HD.NOD+4 MOV #"14,ERRNUM ; ERROR NUMBER CLR ERRSTA ; NO STATUS CALL MESGW ; MESSAGE WITH ASCII ; ; ATTEMPT TO CONNECT ALL REMOTE NODES WITH AN NRB. AST'S ARE DISABLED ; SINCE THE 'CONNOD' ROUTINE PUSHES STATUS MESSAGES INTO THE MESSAGE ; QUEUE WHICH MUST BE DONE AT AST LOCKOUT. ; DSAR$S ; DISABLE AST RECOGNITION CALL CONNOD ENAR$S ; ENABLE AST RECOGNITION ; ; THIS CODE PROCESSES OF ALL EVENTS THAT OCCURRED SINCE THE ; WAKEUP EVENT FLAG WAS SET. AFTER FINISHING, IT WAITS FOR ANOTHER ; EVENT TO SET THE WAKEUP EVENT FLAG. THIS CODE RUNS ENTIRELY IN ; AN AST LOCKOUT STATE. ; 80$: CLEF$S #WAKEFN ; CLEAR WAKEUP EFN DSAR$S ; DISABLE AST RECOGNITION WHILE PROCESSING ; EVENTS THAT WERE QUEUED .IF DF,DEBUG MOV #"99,-(SP) ; WAKEUP DEBUG MESSAGE MOV ASTCNT,-(SP) CLR -(SP) MOV #WAKEUP,-(SP) MOV #6,-(SP) CALL PSHERR ; QUEUE MESSAGE .ENDC ; 85$: CALL REMQUE BCS 110$ MOV #ENTTYP,R3 ; TABLE OF POSSIBLE ENTRIES MOV #ENTCNT,R2 ; NUMBER OF POSSIBLE ENTRIES 90$: CMP (R3)+,R1 ; IS IT THIS ENTRY? BNE 100$ ; NO ; ; GO TAKE CARE OF THE DESIRED EVENT ; ASL R2 ; CHANGE FROM BYTE TO WORD INDEX JSR PC,@ENTJMP-2(R2) ; GO HANDLE EVENT BR 85$ ; GO SEE IF ANY MORE EVENTS 100$: SOB R2,90$ ; CHECK REST OF THE POSSIBLE EVENTS 110$: CALL GETOUT ; GO SEE IF ANY MESSAGES FOR ROUTING ENAR$S ; ENABLE AST RECOGNITION, ALL EVENTS QUEUED ; WERE PROCESSED WTSE$S #WAKEFN ; WAIT FOR SOMETHING TO HAPPEN BR 80$ .page ; ; This subroutine connects each NRB if it is not ; currently connected and a remote has not requested a ; connection. ; ; If neither the Primary or Secondary node is selected, ; then the Primary node is selected and copied into ; N.CUR. If the primary node name is a logical node name, ; the Secondary node is always selected. The connect block ; is constructed and an attempt to connect is made. ; ; CONNOD: MOV RTRHED+HD.NCT,R0 ; NUMBER OF NODES TO CONNECT MOV RTRHED+HD.NRB,R5 ; POINT TO FIRST NRB 5$: BIT #NS.AVL ! NS.CPN ! NS.RCN, N.STS(R5) ; OK TO CONNECT BEQ 10$ ; TRY TO CONNECT JMP 60$ ; CAN'T CONNECT RIGHT NOW ; ; ATTEMPT TO BUILD THE CONNECT BLOCK ; ; CHECK IF PRIMARY NODE NAME IS A LOGICAL NODE NAME ; 10$: BIT #NS.LND,N.STS(R5) ; IS PRIMARY NODE NAME A LOGICAL NODE ; NAME? BEQ 20$ ; NO BIT #NS.NOD,N.STS(R5) ; IS CURRENT ACTUAL (SERVICE) NODE ; NAME PRESENT FOR LOGICAL NODE NAME BNE 30$ ; YES, CONNECT TO SECONDARY DIR$ #REQEST ; RUN TASK 'FNDSRV' BCC 12$ ; DIRECTIVE OK CMP #IE.ACT,$DSW ; IS TASK ALREADY ACTIVE BNE 11$ ; NO, LOG ERROR JMP 60$ ; TASK ACTIVE, NO NEED TO RUN AGAIN 11$: MOV #"55,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; NO SECOND STATUS CLR -(SP) ; NO NODE NAME DISPLAYED CLR -(SP) CALL PSHERR ; QUEUE MESSAGE 12$: TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BEQ 15$ ; NO CMKT$S ,#CNTAST ; CANCEL CONNECT ATTEMPT MARK TIME 15$: DIR$ #CONTM2 ; ISSUE MARK TIME BCC 17$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.PRI,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE CLR RTRHED+HD.CTM ; CLEAR CONNECT TIMER ACTIVE FLAG JMP 60$ 17$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG JMP 60$ 20$: BIT #NS.PRI,N.STS(R5) ; IS PRIMARY SELECTED? BNE 30$ ; YES, THEN GO SELECT SECONDARY THIS TIME ; ; SELECT PRIMARY NODE ; BIC #NS.SEC,N.STS(R5) ; CLEAR SECONDARY NODE BIS #NS.CPN ! NS.PRI,N.STS(R5) ; SELECT AS PRIMARY ; AND MARK LOCAL CONNECT ; IN PROGRESS MOV #N.PRI,R1 ; POINT TO PRIMARY BR 50$ ; GO TO COMMON CONNECT CODE ; ; SELECT SECONDARY NODE ; 30$: BIC #NS.PRI,N.STS(R5) ; CLEAR PRIMARY NODE BIS #NS.CPN ! NS.SEC, N.STS(R5) ; SELECT AS SECONDARY ; AND MARK LOCAL CONNECT ; IN PROGRESS MOV #N.SEC,R1 ; POINT TO SECONDARY NODE NAME .PAGE ; ; CONNECT NODE ; 50$: ADD R5,R1 ; R1 NOW POINTS TO DESIRED NODE TO BUILD ; NCB CONNECT BLOCK MOV #N.CUR,R2 ; FILL IN CURRENT NODE NAME ADD R5,R2 ; ADD START OF NRB ; MOV #N.NCB+N.RND,R3 ; NETWORK CONNECT BLOCK (REMOTE NODE NAME) ADD R5,R3 ; ADD START OF NRB ; MOV (R1),(R3)+ ; COPY TO NCB MOV (R1)+,(R2)+ ; COPY TO CURRENT NODE NAME MOV (R1),(R3)+ ; COPY TO NCB MOV (R1)+,(R2)+ ; COPY TO CURRENT NODE NAME MOV (R1),(R3)+ ; COPY TO NCB MOV (R1)+,(R2)+ ; COPY TO CURRENT NODE NAME ; MOV N.LUN(R5),CONREQ+Q.IOLU ; COPY LOGICAL UNIT NAME MOV N.ISAC(R5),CONREQ+Q.IOSB ; I/O STATUS BLOCK ADDRESS MOV #N.NCB,CONREQ+Q.IOPL ADD R5,CONREQ+Q.IOPL ; NCB FOR CONNECT DIR$ #CONREQ ; REQUEST THE CONNECTION BCC 60$ ; DIRECTIVE ACCEPTED? BIC #NS.CPN,N.STS(R5) ; CLEAR LOCAL CONNECT IN PROGRESS MOV #"45,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) MOV R5,-(SP) ; POINT TO NODE NAME IN NRB ADD #N.CUR,(SP) MOV #6,-(SP) ; NBR BYTES IN NODE NAME CALL PSHERR ; QUEUE MESSAGE ; ; START TIMER FOR LATER RETRY ; TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BNE 60$ ; YES DIR$ #CONTIM ; ISSUE MARK TIME BCC 53$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 60$ 53$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG 60$: MOV N.LNK(R5),R5 ; NEXT NRB ADDRESS DEC R0 BEQ 65$ JMP 5$ ; TRY TO CONNECT THIS NODE 65$: RETURN .PAGE ; ; CONNECTION AST. ; If the connection was successful, then mark the ; NRB with link available status and push an event that ; denotes that. This will also trigger a scan to see if ; there is any work. ; ; 0(SP)= I/O STATUS BLOCK (MUST BE POPPED) ; CNLAST: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET I/O STATUS BLOCK ADDRESS SUB #N.IOSC,R5 ; NORMALIZE TO START OF NRB BIC #NS.CPN,N.STS(R5) ; CLEAR LOCAL CONNECT IN PROGRESS TSTB N.IOSC(R5) ; GOOD STATUS? BPL 10$ ; YES ; ; BAD CONNECT STATUS ; BIS #NS.DWN,N.STS(R5) ; FLAG AS DOWN TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BNE 5$ ; YES DIR$ #CONTIM ; ISSUE MARK TIME BCC 3$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 5$ 3$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG 5$: MOV R5,-(SP) ; PASS NRB MOV #CONFAL,-(SP) ; ERROR CALL PSHENT ; PUSH AN EVENT MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ASTX$S ; EXIT AST ; ; CONNECT COMPLETE ; 10$: BIS #NS.AVL,N.STS(R5) ; FLAG NODE AS AVAILABLE BIC #NS.DWN,N.STS(R5) ; CLEAR DOWN FLAG MOVB N.IOSC(R5),N.STAM(R5) ; SAVE CONNECT STATUS MOV R5,-(SP) ; CONNECT COMPLETE MOV #EVTCON,-(SP) ; PUSH ENTRY "CONNECT COMPLETE" CALL PSHENT MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ASTX$S ; EXIT AST .PAGE ; ; CONNECT FAILURE STATUS ; ; Simply log the error. ; ; R5= NRB OF NODE ; N.IOSC(R5) SHOULD PROBABLY STILL CONTAIN THE STATUS ; ; CNFALS: MOV #"46,-(SP) ; ERROR NUMBER MOVB N.IOSC(R5),-(SP) ; I/O ERROR BIS #177400,(SP) ; MAKE NEGATIVE MOVB N.IOSC+2(R5),-(SP) ; SECOND STATUS WORD BIC #177400,(SP) ; MAKE POSITIVE MOV R5,-(SP) ; POINT TO NODE NAME IN NRB ADD #N.CUR,(SP) MOV #6,-(SP) ; NBR BYTES IN NODE NAME CALL PSHERR ; QUEUE MESSAGE RETURN .PAGE ; ; CONNECT TIMER HAS EXPIRED. QUEUE AN EVENT TO ATTEMPT CONNECTING ; TO ALL REMOTE NODES AGAIN. ; 0(SP)= EVENT FLAG NUMBER (MUST BE POPPED) ; CNTAST: CLR RTRHED+HD.CTM ; CLEAR CONNECT TIMER ACTIVE FLAG CLR -(SP) ; NO PARAMETER TO SAVE MOV #CONTRY,-(SP) ; PUSH ENTRY "ATTEMPT TO CONNECT" CALL PSHENT TST (SP)+ ; POP EFN ASTX$S ; EXIT AST .PAGE ; ; CONNECT TO NETWORK FOR NETWORK MAIL AST ROUTINE. THIS OCURRS ONLY ; ONCE WHEN THE CONNECTION IS FIRST ATTEMPTED. ; (SP)= I/O STATUS BLOCK ADDRESS ; SECOND WORD OF THE I/O STATUS BLOCK WILL CONTAIN THE NUMBER ; OF NETWORK MESSAGES ALREADY PENDING. ; CONAST: .IF DF,DEBUG MOV #"CA,-(SP) MOV #-1,-(SP) CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD CLR -(SP) ; NO ADDRESS CLR -(SP) ; NO BYTE COUNT CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE .ENDC ; INC ASTCNT MOV R0,-(SP) ; SAVE A REGISTER MOV 2(SP),R0 ; GET I/O STATUS BLOCK TST 2(R0) ; ANY MESSAGES? BNE 10$ ; YES MOV (SP),2(SP) ; MOV SAVE R0 ON TOP OF I/O STATUS BLOCK TST (SP)+ ; POP EXTRA COPY OF R0 MOV (SP)+,R0 ; RESTORE R0 ASTX$S ; EXIT AST 10$: MOV (SP),2(SP) ; MOVE SAVED R0 DOWN TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS BR SPAST2 ; GO READ THE MESSAGES .page ; ; NETWORK MESSAGES AST ROUTINE ; When the network has a network message (not a message from some ; other router), then this routine is called. The type of the ; message is returned in the higher byte of the status block as follows: ; ; .BLKB 1 (IS.SUC, have a network message ; IE.NDA, if no more messages) ; .BLKB type is: ; NT.CON= Network connection requested ; NT.INT= Interrupt message ; NT.DSC= User disconnect notice ; NT.ABT= User abort notice ; NT.ABO= Network abort notice ; ; .BLKB 1 ; number of words in connect block if NT.CON ; ; number of bytes in optional message if NT.INT, ; NT.DSC, or NT.ABT ; ; reason for network abort if NT.ABO ; ; .BLKB 1 ; access verification and priv code if NT.CON ; ; LUN if NT.INT, NT.DSC, NT.ABO, or NT.ABT ; ; ; NOTE: THERE IS NOTHING ON THE STACK WHEN THIS AST IS ENVOKED. ; THE STATUS IS ONLY AFTER DOING THE GET NETWORK DATA. SPAAST: .IF DF,DEBUG MOV #"SA,-(SP) MOV #-1,-(SP) CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD CLR -(SP) ; NO ADDRESS CLR -(SP) ; NO BYTE COUNT CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE .ENDC INC ASTCNT MOV R0,-(SP) ; SAVE AT LEAST ONE REGISTER SPAST2: DIR$ #GNDW ; GET NETWORK DATA (ANY MESSAGE TYPE) BCC 10$ ; DIRECTIVE ACCEPTED? MOV #"38,-(SP) ; PUSH ERROR NUMBER MOVB $DSW,R0 ; SIGN EXTEND ERROR MOV R0,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD CLR -(SP) ; NO ADDRESS CLR -(SP) ; NO BYTE COUNT CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 5$: MOV (SP)+,R0 ; RESTORE R0 ASTX$S ; EXIT AST ; 10$: TSTB NETSTA ; IS STATUS CODE POSTIVE (IS.SUC or IS.DAO)? BPL 20$ ; YES, THEN MUST BE A GOOD READ MESSAGE CMPB #IE.NDA,NETSTA ; QUEUE EMPTY? BEQ 5$ ; YES, THEN COMPLETE MOV #"23,-(SP) ; ERROR NUMBER MOVB NETSTA,R0 ; SIGN EXTEND THE ERROR CODE MOV R0,-(SP) ; STORE FOR A LOG CLR -(SP) CLR -(SP) ; NO ADDRESS CLR -(SP) ; NO BYTE COUNT CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR SPAST2 ; GO SEE IF ANY MORE MESSAGES .PAGE ; ; HAVE A VALID NETWORK MESSAGE, DISPOSE OF BY LOOKING AT THEY TYPE ; 20$: MOV #70$,-(SP) ; FAKE RETURN ADDRESS CALL $SAVAL ; SAVE ALL REGISTERS MOV #TYPCNT,R1 MOV #TYPTBL,R2 30$: CMPB (R2)+,NETSTA+1 ; SEE IF MATCH ON TYPE BEQ 40$ ; FOUND MATCH SOB R1,30$ ; SEE IF NEXT ; ; NOT A VALID TYPE, LOG AND IGNORE ; MOV #"12,-(SP) ; ERROR NUMBER MOVB NETSTA+1,R0 ; PRINT THE MESSAGE TYPE MOV R0,-(SP) ; STORE FOR LOG CLR -(SP) CLR -(SP) ; NO ADDRESS CLR -(SP) ; NO BYTE COUNT CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 50$ ; DISPOSE OF AST ; 40$: ASL R1 ; MAKE OFFSET JSR PC,@TYPJMP-2(R1) ; GO TO CORRECT MESSAGE TYPE 50$: RETURN ; RESTORE REGISTERS (WILL RETURN TO 70$ WITH ; REGISTERS RESTORED) 70$: BR SPAST2 ; GO SEE IF ANY MORE NETWORK DATA .PAGE ; ; CONNECT MESSAGE ; ; Offset N.SND is the node that is requesting a connection with us in ; the MAIL buffer from the network. If we can find the node in our ; routing database, accept the connection, else reject the connection. ; Also if we are currently trying to connect, then also reject the ; connection. ; CONMSG: MOV RTRHED+HD.NRB,R5 ; GET THREAD TO NRB'S MOV RTRHED+HD.NCT,R2 ; NUMBER OF NRB'S TO SCAN 10$: CMP MAIL+N.SND,N.PRI(R5) ; SEE IF PRIMARY NODE BNE 20$ ; NOPE CMP MAIL+N.SND+2,N.PRI+2(R5) BNE 20$ CMP MAIL+N.SND+4,N.PRI+4(R5) BEQ 60$ ; NODE IS PRIMARY NODE 20$: CMP MAIL+N.SND,N.SEC(R5) ; SEE IF SECONDARY NODE BNE 40$ ; NOPE CMP MAIL+N.SND+2,N.SEC+2(R5) BNE 40$ CMP MAIL+N.SND+4,N.SEC+4(R5) BEQ 70$ ; NODE IS SECONDARY NODE 40$: MOV N.LNK(R5),R5 ; GET NEXT NRB IN THREAD SOB R2,10$ ; CHECK ALL NRB'S ; ; NRB NOT FOUND; SINCE NODE REQUESTING CONNECTION MAY HAVE A LOGICAL ; NODE NAME IN THE DATABASE, RUN TASK 'FNDSRV', SET CONNECT TIMER, AND ; REJECT CONNECTION. ; DIR$ #REQEST ; RUN TASK 'FNDSRV' BCC 45$ ; DIRECTIVE OK CMP #IE.ACT,$DSW ; IS TASK ALREADY ACTIVE BEQ 50$ ; YES, NO NEED TO RUN AGAIN MOV #"55,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; NO SECOND STATUS CLR -(SP) ; NO NODE NAME DISPLAYED CLR -(SP) CALL PSHERR ; QUEUE MESSAGE 45$: TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BEQ 47$ ; NO CMKT$S ,#CNTAST ; CANCEL CONNECT ATTEMPT MARK TIME 47$: DIR$ #CONTM2 ; ISSUE MARK TIME BCC 48$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.PRI,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE CLR RTRHED+HD.CTM ; CLEAR CONNECT TIMER ACTIVE FLAG BR 50$ 48$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG ; ; NRB NOT FOUND, DISALLOW THE CONNECTION AND LOG THE FACT ; 50$: MOV #"24,-(SP) ; ERROR NUMBER CLR -(SP) ; NO STATUS CLR -(SP) MOV #MAIL+N.SND,-(SP) ; POINTER TO NODE NAME WANTING ; CONNECTION MOV #6,-(SP) ; NUMBER OF BYTES IN NODE NAME CALL PSHERR ; STORE IN OUR EVENT QUEUE ; ; REJECT CONNECTION ; 55$: MOVB NETSTA+2,R1 ; NUMBER BYTES IN MAIL CONNECT BLOCK MOV R5,R3 ; COPY NRB ADD #N.IOSU,R3 ; POINT TO I/O STATUS BLOCK REJ$S #INET,#NETEFN,R3,#RJAST1,<#MAIL,R1> BCC 58$ ; DIRECTIVE ACCEPTED MOV #"18,-(SP) ; ERROR NUMBER MOVB $DSW,R0 ; SIGN EXTEND ERROR MOV R0,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV #MAIL+N.SND,-(SP) ; POINTER TO NODE NAME WANTING ; CONNECTION MOV #6,-(SP) ; NUMBER OF BYTES IN NODE NAME CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 58$: RETURN .PAGE ; ; FOUND NODE IN OUR DATABASE, ACCEPT UNLESS WE ARE ALREADY ; ATTEMPTING TO CONNECT. ; ; PRIMARY NODE ; 60$: BIT #NS.CPN,N.STS(R5) ; LOCAL CONNECT PENDING? BNE 55$ ; YES, THEN DON'T ALLOW EITHER BIC #NS.SEC,N.STS(R5) ; CLEAR SECONDARY NODE BIS #NS.PRI,N.STS(R5) ; SET PRIMARY BR 80$ ; ; SECONDARY NODE ; 70$: BIT #NS.CPN,N.STS(R5) ; LOCAL CONNECT PENDING? BNE 55$ ; YES, THEN DON'T ALLOW EITHER BIC #NS.PRI,N.STS(R5) ; CLEAR PRIMARY NODE BIS #NS.SEC,N.STS(R5) ; SET SECONDARY NODE BIT #NS.LND,N.STS(R5) ; IS THE PRIMARY NODE NAME A LOGICAL ; NODE NAME? BEQ 80$ ; NO BIS #NS.NOD,N.STS(R5) ; SET THE LOGICAL NAME TRANSLATED ; FLAG SINCE REMOTE REQUEST OK 80$: ; ; ACTUALLY ACCEPT THE CONNECTION ; MOV MAIL+N.SND,N.CUR(R5) ; COPY ACTUAL CURRENT NODE NAME MOV MAIL+N.SND+2,N.CUR+2(R5) MOV MAIL+N.SND+4,N.CUR+4(R5) MOVB NETSTA+2,R1 ; NUMBER BYTES IN MAIL CONNECT BLOCK MOV #MAIL,R2 ; GET START ADDRESS OF NETWORK MAIL BUFFER MOV R5,R3 ; GET ADDRESS OF NRB ADD #N.MBX,R3 ; POINT TO START OF CONNECT BLOCK SAVE BUFFER 85$: MOVB (R2)+,(R3)+ ; SAVE CONNECT BLOCK SOB R1,85$ MOVB NETSTA+2,R1 ; GET NUMBER OF BYTES IN CONNECT BLOCK MOV R5,R2 ; COPY NRB ADD #N.IOSU,R2 ; POINT TO I/O STATUS BLOCK MOV R5,R3 ; GET ADDRESS OF SAVE BUFFER ADD #N.MBX,R3 .IF DF,DEBUG MOV #"CR,-(SP) MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE MESSAGE FOR LOGGING .ENDC ACC$S N.LUN(R5),#NETEFN,R2,#ACCAST, BCC 90$ ; DIRECTIVE ACCEPTED? MOV #"17,-(SP) ; ERROR NUMBER MOVB $DSW,R0 ; SIGN EXTEND ERROR MOV R0,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 90$: RETURN .PAGE ; ; INTERRUPT MESSAGE (DON'T EXPECT ANY) ; INTMSG: MOV #"19,-(SP) MOV #-1,-(SP) CLR -(SP) CLR -(SP) CLR -(SP) CALL PSHERR RETURN ; ; ANY TIME A DISCONNECT MESSAGE, ABORT MESSAGE, OR NETWORK ABORT MESSAGE ; IS RECEIVED, AN ATTEMPT WILL BE MADE TO DISCONNECT THE LOGICAL LINK ; (PROBABLY DISCONNECTED ALREADY BY REMOTE), THE NODE SENDING THE MESSAGE ; WILL BE MARKED 'NOT AVAILABLE', AND A TIMER WILL BE STARTED TO TRY ; A LATER RECONNECT TO THE NODE. ; ; USER DISCONNECT MESSAGE ; DSCMSG: CALL NETMSG ; GET NODE NAME MOV #"20,-(SP) ; ERROR NUMBER CLR -(SP) ; NO STATUS CLR -(SP) MOV R5,-(SP) ; POINTER TO NODE NAME MOV R2,-(SP) ; NUMBER BYTES IN NODE NAME CALL PSHERR ; PUT IN MESSAGE QUEUE RETURN ; ; USER ABORT MESSAGE ; ABTMSG: CALL NETMSG ; GET NODE NAME MOV #"21,-(SP) ; ERROR NUMBER CLR -(SP) ; NO STATUS CLR -(SP) MOV R5,-(SP) ; POINTER TO NODE NAME MOV R2,-(SP) ; NUMBER BYTES IN NODE NAME CALL PSHERR ; PUT IN MESSAGE QUEUE RETURN ; ; NETWORK ABORT MESSAGE ; ABOMSG: CALL NETMSG ; GET NODE NAME MOV #"22,-(SP) ; ERROR NUMBER MOVB NETSTA+2,-(SP) ; STATUS BIC #177400,(SP) CLR -(SP) ; NO SECOND STATUS MOV R5,-(SP) ; POINTER TO NODE NAME MOV R2,-(SP) ; NUMBER BYTES IN NODE NAME CALL PSHERR ; PUT IN MESSAGE QUEUE RETURN ; ; HANDLE USER DISCONNECT, USER ABORT, OR NETWORK ABORT MESSAGE ; RECEIVED FROM REMOTE. ; NETMSG: MOV RTRHED+HD.NRB,R5 ; POINTER TO FIRST NRB MOV RTRHED+HD.NCT,R2 ; NUMBER OF NRB'S TO SCAN MOVB NETSTA+3,R0 ; MOVE LUN OVER WHICH THE NETWORK 5$: ; MESSAGE WAS RECEIVED CMP N.LUN(R5),R0 ; SEE IF MATCH WITH LUN IN NRB BEQ 10$ ; MATCH, NRB ADDRESS OF NODE ; SENDING MESSAGE IN R5 MOV N.LNK(R5),R5 ; POINT TO NEXT NRB SOB R2,5$ ; CHECK NEXT NRB CLR R5 ; DIDN'T FIND LUN IN ANY NRB ; DON'T LOG ANY NODE NAME CLR R2 ; NO BYTE COUNT RETURN 10$: DSC$S N.LUN(R5),#NETEFN ; ALSO TRY TO DISCONNECT FROM ; THIS END, DON'T CARE ABOUT STATUS BCC 20$ ; DIRECTIVE ACCEPTED MOV #"51,-(SP) ; ERROR NUMBER MOVB $DSW,R0 ; SIGN EXTEND ERROR MOV R0,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 20$: BIC #NS.AVL ! NS.CPN ! NS.RCN ! NS.NOD,N.STS(R5) ; MARK NOT AVAILABLE BIS #NS.DWN,N.STS(R5) ; MARK DOWN TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BNE 30$ ; YES DIR$ #CONTIM ; ISSUE MARK TIME TO TRY CONNECT LATER BCC 25$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 30$ 25$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG 30$: MOV #1,N.STAM(R5) ; SAVE CONNECT STATUS MOV R5,-(SP) ; NRB ADDRESS MOV #EVTDIS,-(SP) ; PUSH EVENT "DISCONNECT COMPLETE" CALL PSHENT ADD #N.CUR,R5 ; POINT TO CURRENT NODE NAME IN NRB SO THAT ; IT CAN BE LOGGED MOV #6,R2 ; NUMBER BYTES TO LOG RETURN .PAGE ; ; THIS AST ROUTINE IS CALLED AFTER AN ACCEPT LOGICAL LINK HAS BEEN ; COMPLETED. ; ; 0(SP)= I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; ACCAST: INC ASTCNT MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET I/O STATUS BLOCK ADDRESS SUB #N.IOSU,R5 ; CHANGE TO NRB ADDRESS .IF DF,DEBUG MOV #"AA,-(SP) MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE ERROR FOR LOGGING .ENDC TSTB N.IOSU(R5) ; GOOD STATUS? BMI 20$ ; NO. BIS #NS.AVL,N.STS(R5) ; YES, FLAG AS AVAILABLE BIC #NS.DWN,N.STS(R5) ; CLEAR POSSIBLE DOWN BIS #NS.RCN,N.STS(R5) ; MARK AS REMOTE CONNECTING MOVB N.IOSU(R5),N.STAM(R5) ; SAVE CONNECT STATUS MOV R5,-(SP) ; STORE NRB MOV #EVTCON,-(SP) ; EVENT IS NODE CONNECTED CALL PSHENT 10$: MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS ASTX$S ; EXIT AST ; ; ERROR WHILE ACCEPTING THE CONNECTION. ATTEMPT TO REJECT CONNECTION. ; 20$: MOV R3,-(SP) ; SAVE R3,R2,R1 MOV R2,-(SP) MOV R1,-(SP) MOV #"16,-(SP) ; ERROR NUMBER MOVB N.IOSU(R5),-(SP) ; I/O STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LOG MOV #MLEN,R1 ; DEFAULT SIZE OF NETWORK MAILBOX IN BYTES, ; COULD NOT USE SIZE IN BYTE 1 OF 'NETSTA' ; SINCE COULD HAVE BEEN DESTROYED. MOV R5,R2 ; COPY NRB ADD #N.IOSU,R2 ; POINT TO I/O STATUS BLOCK MOV R5,R3 ; GET ADDRESS OF CONNECT REQUEST SAVE BUFFER ADD #N.MBX,R3 REJ$S #INET,#NETEFN,R2,#RJAST2, BCC 21$ ; DIRECTIVE ACCEPTED MOV #"18,-(SP) ; ERROR NUMBER MOVB $DSW,R0 ; SIGN EXTEND ERROR MOV R0,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES IN NODE NAME CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 21$: MOV (SP)+,R1 ; RESTORE R1,R2,R3 MOV (SP)+,R2 MOV (SP)+,R3 BR 10$ ; GO TAKE CARE OF REST .PAGE ; ; THIS AST ROUTINE IS CALLED AFTER A REJECT OF A CONNECTION REQUEST ; BECAUSE THE NODE REQUESTING THE CONNECTION WAS NOT DEFINED IN THE ; DATABASE. ; ; 0(SP)= I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; RJAST1: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET I/O STATUS BLOCK ADDRESS SUB #N.IOSU,R5 ; CHANGE TO NRB ADDRESS MOV #"15,-(SP) CLR -(SP) ; NO STATUS TSTB N.IOSU(R5) ; STATUS GOOD BPL 10$ MOV N.IOSU(R5),(SP) ; BAD I/O STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE 10$: CLR -(SP) MOV #MAIL+N.SND,-(SP) ; POINTER TO NODE NAME WANTING ; CONNECTION MOV #6,-(SP) ; NUMBER OF BYTES IN NODE NAME CALL PSHERR ; QUEUE ERROR FOR LOGGING MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS ASTX$S ; EXIT AST .PAGE ; ; THIS AST ROUTINE IS CALLED AFTER A REJECT OF A CONNECTION REQUEST ; BECAUSE AN ATTEMPT TO ACCEPT THE REQUEST RESULTED IN A BAD I/O ; STATUS. IF THE BAD ACCEPT WAS CAUSED BY A LINK ALEADY ESTABLISHED ; ON THE LUN, A DISCONNECT IS ALSO DONE. IF NOT, A TIMER IS SET ; SO THAT A LINK MAY BE ATTEMPTED LATER. ; ; 0(SP)= I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; RJAST2: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET I/O STATUS BLOCK ADDRESS SUB #N.IOSU,R5 ; CHANGE TO NRB ADDRESS MOV #"15,-(SP) CLR -(SP) ; NO STATUS TSTB N.IOSU(R5) ; STATUS GOOD BPL 10$ MOV N.IOSU(R5),(SP) ; BAD I/O STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE 10$: CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NAME OF NODE WANTING CONNECTION MOV #6,-(SP) ; NUMBER OF BYTES IN NODE NAME CALL PSHERR ; QUEUE ERROR FOR LOGGING BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS NODE AVAILABLE FOR ; DISCONNECT BNE 20$ ; NO CALL DISCNT ; DISCONNECT 15$: MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS ASTX$S ; EXIT AST 20$: TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BNE 25$ ; YES DIR$ #CONTIM ; ISSUE MARK TIME BCC 23$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 25$ 23$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG 25$: BR 15$ ; EXIT AST .PAGE ; ; ; CONNECTION COMPLETE TO A NODE ; R1= EVTCON ; R5= NRB ADDRESS ; ; LOG THE SUCCESSFUL EVENT, WRITE THE STATUS MESSAGE TO THE QUEUE, ; MARK THE NRB AS ON LINE, HANG A READ ON THE REMOTE NODE. ; CONCMP: MOV #"25,-(SP) ; ERROR NUMBER CLR -(SP) ; NO STATUS CLR -(SP) MOV R5,-(SP) ; POINT TO NODE NAME IN NRB ADD #N.CUR,(SP) MOV #6,-(SP) ; NBR BYTES IN NODE NAME CALL PSHERR ; QUEUE MESSAGE ; ; WRITE CONNECT STATUS MESSAGE TO QUEUE ; TST STAFLG ; DOES MESSAGE ID EXIST BNE 10$ ; NO, DON'T ATTEMPT TO QUEUE MOV #STAMSG,R0 ; GET ADDRESS OF STATUS MESSAGE BUFFER MOV #1,SM.UD(R0) ; FLAG AS CONNECT CALL WRTSTS ; WRITE CONNECT STATUS TO QUEUE ; ; BACKUP ANY OUTSTANDING MESSAGE IDS THAT WERE TRANSMITTED TO ; THE REMOTE NODE BUT WE NEVER RECEIVED AN ACKNOWLEGE TO. WILL ; PUT THEM BACK ON THE QUEUE AND RESEND WHEN AVAILABLE. ; 10$: MOV N.IDS(R5),R1 ; NUMBER OF MESSAGE ID'S BEQ 35$ ; NO MESSAGES ROUTED TO NODE CONNECTING MOV R5,R4 ; COPY NRB ADD #N.IDXL,R4 ; POINT TO THE NRB ID LIST 15$: TST NID.RA(R4) ; OUTSTANDING RNA? BEQ 30$ ; NO MOV R4,RESID+Q.IOPL ; MESSAGE ID BUFFER ADD #NID.NM,RESID+Q.IOPL ; OF ID TO DO THE BACKUP RNA ON DIR$ #RESID ; BACK UP THE RNA BCC 20$ ; ALL OK? (ONLY CHECK DIRECTIVE AS THE ; STATUS COULD BE BAD ANYWAY) MOV #"13,ERRNUM ; ERROR NUMBER CALL DSWMSG ; LOG ERROR DIR$ #DISCQ ; KILL PENDING I/O EXIT$S ; SHOULDN'T HAPPEN 20$: CLR NID.RA(R4) ; NO LONGER ANY OUTSTANDING RNA 30$: ADD #NID.LN,R4 ; POINT TO NEXT RNA SOB R1,15$ ; LOOP UNTIL ALL HAVE BEEN RESET ; ; POST A READ ON THIS NODE ; 35$: CALL POSRED RETURN .PAGE ; ; POST A READ ON THE NODE WHOSE NRB IS PASSED. ; THIS ROUTINE IS CALLED TO POST A READ ON THE NODE WHEN A ; CONNECTION IS FIRST MADE TO THAT NODE. THE TASK IS NOT ; PROCESSING AN AST. ; R5 = NRB ADDRESS ; ; POSRED: .IF DF,DEBUG MOV #"PR,-(SP) MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LOG .ENDC BIT #NS.AVL,N.STS(R5) ; IS THE NODE AVAILABLE? BNE 10$ ; YES RETURN ; NO, THEN DONE ; 10$: MOV R1,-(SP) ; SAVE R1 MOV N.LUN(R5),REDNET+Q.IOLU ; UNIT NUMBER MOV N.IBSA(R5),REDNET+Q.IOSB ; I/O STATUS BLOCK MOV N.ULNK(R5),R1 ; ADDRESS OF UNSOLICITED BUFFER HEADER MOV (R1)+,REDNET+Q.IOPL+2 ; SIZE OF UNSOLICITED BUFFER MOV R1,REDNET+Q.IOPL ; READ BUFFER ADDRESS DIR$ #REDNET ; POST THE READ BCC 20$ ; ALL A OK, LET AST HANDLE REST MOV #"27,-(SP) ; ERROR NUMBER MOVB $DSW,R1 ; SIGN EXTEND ERROR MOV R1,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 20$ ; NO CALL DISCNT ; DISCONNECT NODE 20$: MOV (SP)+,R1 ; RESTORE R1 RETURN .PAGE ; ; POST A READ ON THE NODE WHOSE NRB IS PASSED. ; THIS ROUTINE IS CALLED TO POST A READ WHENEVER THE TASK ; IS PROCESSING AN AST. ; R5 = NRB ADDRESS ; ; POSRD1: .IF DF,DEBUG MOV #"P1,-(SP) MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LOG .ENDC BIT #NS.AVL,N.STS(R5) ; IS THE NODE AVAILABLE? BNE 10$ ; YES RETURN ; NO, THEN DONE ; 10$: MOV R1,-(SP) ; SAVE R1 MOV N.LUN(R5),REDNET+Q.IOLU ; UNIT NUMBER MOV N.IBSA(R5),REDNET+Q.IOSB ; I/O STATUS BLOCK MOV N.ULNK(R5),R1 ; ADDRESS OF UNSOLICITED BUFFER HEADER MOV (R1)+,REDNET+Q.IOPL+2 ; SIZE OF UNSOLICITED BUFFER MOV R1,REDNET+Q.IOPL ; READ BUFFER ADDRESS DIR$ #REDNET ; POST THE READ BCC 20$ ; ALL A OK, LET AST HANDLE REST MOV #"27,-(SP) ; ERROR NUMBER MOVB $DSW,R1 ; SIGN EXTEND ERROR MOV R1,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 20$ ; NO CALL DISCNT ; DISCONNECT NODE 20$: MOV (SP)+,R1 ; RESTORE R1 RETURN .PAGE ; ; NETWORK READ AST ; This routine is called when a network read is complete. ; The information on the stack is: ; 0(SP) I/O STATUS BLOCK (MUST BE POPPED) ; 2(SP) DSW ; 4(SP) PC PRIOR TO AST ; 6(SP) PS PRIOR TO AST ; 10(SP) EVENT FLAG MASK WORD ; ; I/O STAUS BLOCK: ; .BLKB STATUS ; .BLKB Unused ; .BLKW TRANSFER COUNT ; REDAST: TSTB @(SP) ; GOOD STATUS? BPL 10$ ; YES ; ; BAD I/O STATUS ; MOV R5,-(SP) ; SAVE A REGISTER MOV 2(SP),R5 ; GET I/O STATUS BLOCK SUB #N.IOSB,R5 ; POINT TO BEGINNING OF NRB MOV #"28,-(SP) MOV N.IOSB(R5),-(SP) ; I/O STATUS BIS #177400,(SP) ; SIGN EXTEND CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE ERROR FOR LOG BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 5$ ; NO CALL DISCNT ; DISCONNECT NODE 5$: MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ASTX$S ; ; GOOD READ STATUS ; DEPENDING ON THE TYPE OF MESSAGE, THIS MESSAGE COULD ; EITHER BE A ROUTER TO ROUTER PROTOCOL MESSAGE OR A ; DATA MESSAGE ; 10$: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET I/O STATUS BLOCK SUB #N.IOSB,R5 ; POINT TO NRB .IF DF,DEBUG MOV #"DD,-(SP) MOV #-1,-(SP); ; JUST LOG IT FOR NOW MOV N.IOSB+2(R5),-(SP) ; NUMBER OF BYTES RECEIVED MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LOG .ENDC MOV #200$,-(SP) ; FAKE RETURN ADDRESS CALL $SAVAL ; SAVE REGISTERS .PAGE ; ; CHECK LINK SEQUNCE NUMBER OF MESSAGE JUST RECEIVED ; MOV N.ULNK(R5),R1 ; GET ADDRESS OF INPUT BUFFER TST (R1)+ ; SKIP OVER BUFFER SIZE TST N.SEQ(R5) ; ZERO, THEN MUST BE FIRST MESSAGE, ACCEPT BEQ 30$ ; ANYTHING MOV N.SEQ(R5),R2 ; GET OLD LINK SEQUENCE NUMBER INC R2 ; SHOULD BE ONE MORE CMP #10000.,R2 ; TIME TO WRAP BNE 20$ ; NO MOV #1,R2 ; YES, RESET TO ONE 20$: CMP R2,MG.LSQ(R1) ; ARE THEY EQUAL BEQ 30$ ; YES ; ; LOST A MESSAGE OR SOMETHING, OR ELSE REBOOT ON REMOTE SYSTEM, ETC. ; ; LOG FACT AND ACCEPT THE NEW LINK SEQUENCE NUMBER ; SUB MG.LSQ(R1),R2 ; GET DIFFERENCE BMI 25$ ; ALREADY NEGATIVE? NEG R2 ; NO, THEN MAKE NEGATIVE 25$: MOV #"29,-(SP) ; ERROR NUMBER MOV R2,-(SP) ; DIFFERENCE IN LINK SEQUNCE NUMBER CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; STORE IN QUEUE FOR LATER LOGGING 30$: MOV MG.LSQ(R1),N.SEQ(R5) ; NO MATTER WHAT ACCEPT NEW SEQ. NO. ; ; FIND OUT IF THE MESSAGE IS A ROUTER TO ROUTER MESSAGE OR A NEW ; MESSAGE TO BE QUEUED. ; TST MG.SIZ+H.TYPE(R1) ; SEE IF ROUTER MESSAGE (IE: < 0) BMI 60$ ; ROUTER MESSAGE ; ; NOT A ROUTER MESSAGE, THEN USE OUR SPECIAL ENTRY TO WRITE ; AN ENTRY INTO THE QUEUE VIA A QIO. WE WILL USE THE SAME ; I/O STATUS BLOCK AS FOR A READ AS WE WON'T BE POSTING ANOTHER ; READ UNTIL WE FINISH WITH THE WRITE TO THE QUEUE ANYWAY. ; MOV N.IBSA(R5),WRTQUE+Q.IOSB ; I/O STATUS BLOCK MOV R1,WRTQUE+Q.IOPL ; MESSAGE BUFFER ADDRESS OF MESG ADD #MG.SIZ,WRTQUE+Q.IOPL ; JUST RECIEVED. SKIP ROUTER INFO MOV N.IOSB+2(R5),WRTQUE+Q.IOPL+2 ; TOTAL SIZE OF MESSAGE SUB #MG.SIZ,WRTQUE+Q.IOPL+2 ; NOT WRITING HEADER MOV R1,WRTQUE+Q.IOPL+4 ; MESSAGE ID BUFFER ADD #MG.MID,WRTQUE+Q.IOPL+4 ; ADDRESS IN ROUTER HEADER MOV MG.SIZ+H.TYPE(R1),WRTQUE+Q.IOPL+10 ; TYPE OF MESSAGE DIR$ #WRTQUE ; WRITE IT TO THE QUEUE BCC 40$ ; WRITE OK?, IF YES WAIT FOR AST MOV #"30,-(SP) ; ERROR NUMBER MOVB $DSW,R2 ; SIGN EXTEND ERROR MOV R2,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MEG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 40$ ; NO CALL DISCNT ; DISCONNECT NODE 40$: RETURN .PAGE ; ; ROUTER MESSAGE FROM REMOTE NODE, ONE OF THE FOLLOWING: ; -1= ACKNOWLEGE ; -2= REMOTE MESSAGE ID FULL ; -3= REMOTE NODE DOES NOT KNOW OF THE MESSAGE ID ; 60$: ; CMP #-1,MG.SIZ+H.TYPE(R1) ; IS THIS AN ACKNOWLEGE BNE 70$ ; NO ; ; ACKNOWLEGE OF A PREVIOUSLY WRITTEN MESSAGE TO THE REMOTE. IE, THE ; REMOTE NODE HAS SUCCESSFULLY QUEUED THE MESSAGE AND NOW IS TELLING ; US THAT IT CAN BE REMOVED. TO DO THIS: ; ; DO A WRITE TO THE QUEUE WITH AN ACKNOWLEGE WITH THE RNA. ; (THE INDEX THAT WAS PASSED TO THE REMOTE ROUTER SHOULD ; POINT TO MESSAGE ID ENTRY IN THE NRB ID LIST FOLLOWED BY ; THE RNA THAT WAS RECEIVED FROM THE QUEUE). ; MOV MG.IDX(R1),R3 ; GET OUR INDEX (ADDRESS OF NRBID ENTRY) CMP NID.RA(R3),MG.RNA(R1) ; DOES THE RNA IN MESSAGE MATCH OURS BEQ 65$ ; YES MOV #"32,-(SP) ; ERROR CODE MOV MG.RNA(R1),-(SP) ; STORE FOR LOGGING CLR -(SP) MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MSG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; LOG ERROR LATER, IGNORE REST ; OF THE PROCESSING, MAYBE DISCONNECT?? RETURN 65$: MOV N.IBSA(R5),ACKQUE+Q.IOSB ; I/O STATUS BLOCK MOV R1,ACKQUE+Q.IOPL ; MESSAGE ID BUFFER ADD #MG.MID,ACKQUE+Q.IOPL ; POINT TO MESSAGE ID MOV 2(R3),ACKQUE+Q.IOPL+4 ; RNA DIR$ #ACKQUE ; ACKNOWLEGE THE MESSAGE BCC 67$ ; ALL OK. MOV #"33,-(SP) ; ERROR NUMBER MOVB $DSW,R2 ; SIGN EXTEND ERROR MOV R2,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MSG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 67$: RETURN 70$: CMP #-2,MG.SIZ+H.TYPE(R1) ; IS THIS A REMOTE MESSAGE ID QUEUE FULL BEQ 80$ ; YES CMP #-3,MG.SIZ+H.TYPE(R1) ; IS THIS A REMOTE MESSAGE ID UNLNOWN BNE 90$ ; NO ; ; REMOTE MESSAGE ID QUEUE IS FULL OR REMOTE NODE DOSEN'T KNOW OF ; THIS MESSAGE ID. ; MARK THE MESSAGE ID AS NOT ROUTABLE, BACKUP THE ; RNA POINTER, AND START A TIMER FOR A LATER TRY. ; THE RNAAST WILL POST ANOTHER READ WHEN IT IS COMPLETE. ; 80$: .IF DF,DEBUG MOV #"NR,-(SP) MOV #-1,-(SP); ; JUST LOG IT FOR NOW CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR .ENDC MOV MG.IDX(R1),R3 ; GET OUR INDEX (ADDRESS OF NRBID ENTRY) BIS #NIS.RT,NID.ST(R3) ; MARK AS NOT ROUTABLE TST RTRHED+HD.NRT ; IS TIMER ACTIVE BNE 83$ ; YES DIR$ #TIMER ; ISSUE MARK TIME BCC 82$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,R2 ; SIGN EXTEND ERROR MOV R2,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MSG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 83$ 82$: INC RTRHED+HD.NRT ; SET NOT ROUTABLE TIMER ACTIVE FLAG 83$: MOV N.IBSA(R5),RNAQUE+Q.IOSB ; I/O STATUS BLOCK MOV R1,RNAQUE+Q.IOPL ; MESSAGE ID BUFFER ADD #MG.MID,RNAQUE+Q.IOPL ; POINT TO MESSAGE ID DIR$ #RNAQUE ; PUT MESSAGE BACK ON QUEUE THE MESSAGE BCC 85$ ; ALL OK. MOV #"44,-(SP) ; ERROR NUMBER MOVB $DSW,R2 ; SIGN EXTEND ERROR MOV R2,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MSG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 85$: RETURN ; 90$: MOV #"31,-(SP) ; INVALID ROUTER TYPE MESSAGE MOV MG.SIZ+H.TYPE(R1),-(SP) ; STORE THE INVALID TYPE CODE CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; CALL TO PLACE IN QUEUE TO BE LOGGED RETURN ; ; AST EXIT (REGISTERS RESTORED BY $SAVAL, ONLY ; SAVED R5 AND I/O STATUS BLOCK LEFT TO BE POPPED. ; 200$: MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ASTX$S .PAGE ; ; MSG ID'S NOT ROUTABLE TIMER HAS EXPIRED. QUEUE AN EVENT TO SET ALL ; MSG ID'S IN EACH NRB AS ROUTABLE. ; 0(SP) = EVENT FLAG NUMBER (MUST BE POPPED) ; NRTAST: CLR -(SP) ; NO PARAMETER TO SAVE MOV #EVTNRT,-(SP) ; PUSH ENTRY "ATTEMPT TO CONNECT" CALL PSHENT TST (SP)+ ; POP EFN ASTX$S ; EXIT AST ; ; ; MARK ALL MSG ID'S IN EACH NRB AS ROUTABLE. CLEAR THE NOT ROUTABLE ; TIMER FLAG SO THAT A TIMER CAN BE STARTED WHEN A MSG ID BECOMES NOT ; ROUTABLE. ; NRTENB: .IF DF,DEBUG MOV #"ER,-(SP) ; DEBUG MOV #-1,-(SP) CLR -(SP) CLR -(SP) CLR -(SP) CALL PSHERR .ENDC MOV RTRHED+HD.NCT,R1 ; NUMBER OF NRB'S DEFINED MOV RTRHED+HD.NRB,R5 ; NRB BEGINNING THREAD 10$: MOV N.IDS(R5),R2 ; NUMBER OF MSG ID'S THIS NRB BEQ 50$ ; NO MSG ID'S THIS NRB MOV R5,R3 ; COPY NRB ADDRESS ADD #N.IDXL,R3 ; POINT TO FIRST MSG ID LIST 20$: BIC #NIS.RT,NID.ST(R3) ; MARK AS ROUTABLE ADD #NID.LN,R3 ; POINT TO NEXT MSG ID LIST SOB R2,20$ ; NEXT MSG ID IN NRB 50$: MOV N.LNK(R5),R5 ; GET LINK TO NEXT NRB SOB R1,10$ ; NEXT NRB CLR RTRHED+HD.NRT ; INDICATE MARK TIME EXPIRED AND ; ALL MSG ID'S MARKED ROUTABLE RETURN .PAGE ; ; A MESSAGE FROM A REMOTE NODE HAS BEEN QUEUED. ; THE QIO FOR THIS AST WAS CAUSED WHEN A READ COMPLETED ; FROM THE REMOTE NODE AND IT WAS A DATA MESSAGE AND NOT ; A ROUTER MESSAGE (IE: THE MESSAGE HAD TO BE QUEUED). IF ; ALL IS WELL, THEN SEND BACK A ROUTER RESPONSE MESSAGE TO THE ; REMOTE NODE AND POST ANOTHER READ FOR THAT NODE. IF A RESPONSE ; BUFFER IS NOT AVAILABLE, AN EVENT IS QUEUED AND A TIMER IS STARTED. ; WHEN THE TIMER EXPIRES, THIS ROUTINE WILL NOT BE ENTERED AT ; AST LEVEL. ; ; AT AST LEVEL: 0(SP) = I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; WRQAST: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; ADDRESS OF NRB I/O STATUS BLOCK SUB #N.IOSB,R5 ; POINT TO START OF NRB MOV #RETN,-(SP) ; FAKE RETURN ADDRESS CALL $SAVAL ; SAVE ALL REGISTERS ; ; ENTER HERE WHEN TIMER (ISSUED WHEN A RESPONSE BUFFER WAS NOT ; AVAILABLE) EXPIRES. ; RERSP: TSTB N.IOSB(R5) ; WAS QUEUE SUCCESSFUL BPL 50$ ; YES .IF DF,DEBUG MOV #"NQ,-(SP) ; DEBUG MOV N.IOSB(R5),-(SP) BIS #177400,(SP) ; SIGN EXTEND CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR .ENDC CALL ALLRSP ; ALLOCATE RESPONSE BUFFER BCC 40$ ; ABLE TO ALLOCATE JMP NOALL ; COULD NOT ALLOCATE A BUFFER 40$: MOV #-3,R.BUF+MG.SIZ+H.TYPE(R4) ; PUT TYPE IN RESPONSE BUFFER CMPB #IE.NDR,N.IOSB(R5) ; QUEUE FULL ERROR? BNE 60$ ; NO MOV #-2,R.BUF+MG.SIZ+H.TYPE(R4) ; PUT TYPE IN RESPONSE BUFFER BR 60$ 50$: .IF DF,DEBUG MOV #"WQ,-(SP) ; DEBUG MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LOG .ENDC CALL ALLRSP ; ALLOCATE RESPONSE BUFFER BCS NOALL MOV #-1,R.BUF+MG.SIZ+H.TYPE(R4) ; PUT TYPE IN RESPONSE BUFFER ; ; FILL IN RESPONSE BUFFER AND ISSUE THE QIO TO SEND THE RESPONSE TO ; THE REMOTE NODE. ; 60$: MOV N.OSEQ(R5),R1 ; GET OUTBOUND LINK SEQ. NUMBER INC R1 ; INCREMENT IT MOV R1,N.OSEQ(R5) ; UPDATE IT CMP #9999.,R1 ; TIME TO WRAP? BNE 62$ ; NO CLR N.OSEQ(R5) ; YES, RESET SO WILL BE ONE AGAIN NEXT TIME 62$: MOV R1,R.BUF+MG.LSQ(R4) ; STORE IN ROUTER MESSAGE PORTION MOV N.ULNK(R5),R1 ; POINT TO INPUT BUFFER TST (R1)+ ; SKIP OVER THE BYTE COUNT OF THE BUFFER MOV MG.RNA(R1),R.BUF+MG.RNA(R4) ; RNA MOV MG.IDX(R1),R.BUF+MG.IDX(R4) ; INDEX ; ; MESSAGE ID ; MOV #MG.MID,R3 ; OFFSET TO MESSAGE ID IN RECV. BUFFER ADD R1,R3 ; RELOCATE BY ADDING RECV. BUFFER MOV #R.BUF+MG.MID,R2 ; OFFSET TO MESSAGE ID IN RESP. BUFFER ADD R4,R2 ; RELOCATE BY ADDING RESPONSE BUF ADDR. MOV R4,-(SP) ; SAVE R4 MOV #M.IDSIZ/2,R4 ; MSG ID SIZE IN WORDS 65$: MOV (R3)+,(R2)+ ; FILL MSG ID IN RSP BUFFER SOB R4,65$ ; LOOP UNTIL ENTIRE MSG IN IN BUFFER MOV (SP)+,R4 ; RESTORE RSP BUFFER PTR IN R4 ; ; SOURCE NODE NAME ; MOV RTRHED+HD.NOD,R.BUF+MG.SIZ+H.SNM(R4) MOV RTRHED+HD.NOD+2,R.BUF+MG.SIZ+H.SNM+2(R4) MOV RTRHED+HD.NOD+4,R.BUF+MG.SIZ+H.SNM+4(R4) ; ; DESTINATION NODE NAME ; MOV MG.SIZ+H.SNM(R1),R.BUF+MG.SIZ+H.DNM(R4) MOV MG.SIZ+H.SNM+2(R1),R.BUF+MG.SIZ+H.DNM+2(R4) MOV MG.SIZ+H.SNM+4(R1),R.BUF+MG.SIZ+H.DNM+4(R4) ; ; OFF QUEUE TIME ; MOV MG.SIZ+H.OFQT(R1),R.BUF+MG.SIZ+H.OFQT(R4) MOV MG.SIZ+H.OFQT+2(R1),R.BUF+MG.SIZ+H.OFQT+2(R4) MOV MG.SIZ+H.OFQT+4(R1),R.BUF+MG.SIZ+H.OFQT+4(R4) MOV MG.SIZ+H.OFQT+6(R1),R.BUF+MG.SIZ+H.OFQT+6(R4) ; ; SETUP FOR SEND QIO ; MOV N.LUN(R5),WRTNET+Q.IOLU ; UNIT NUMBER MOV R4,WRTNET+Q.IOSB ADD #R.IOSB,WRTNET+Q.IOSB ; RSP BUFFER I/O STATUS BLOCK MOV R4,WRTNET+Q.IOPL ADD #R.BUF,WRTNET+Q.IOPL ; ADDRESS OF RESPONSE BUFFER MOV RTRHED+HD.RSZ,WRTNET+Q.IOPL+2 ; SIZE OF RESPONSE BUFFER DIR$ #WRTNET ; DO THE WRITE TO THE NETWORK BCC 68$ ; ALL A OK, LET AST HANDLE REST MOV #"48,-(SP) ; ERROR NUMBER MOVB $DSW,R1 ; SIGN EXTEND ERROR MOV R1,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE CALL DEARSP ; DEALLOCATE RESPONSE BUFFER BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 68$ ; NO CALL DISCNT ; DISCONNECT NODE RETURN ; IF REGISTERS SAVED, RESTORE REGISTERS AND ; RETURN AT RETN 68$: CALL POSRD1 ; POST ANOTHER READ ON THIS NODE RETURN ; IF REGISTERS SAVED, RESTORE REGISTERS AND ; RETURN AT RETN RETN: MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ASTX$S ; ; COULD NOT ALLOCATE A RESPONSE BUFFER. PUSH ENTRY IN QUEUE AND ISSUE ; A MARK TIME TO TRY AGAIN. ; NOALL: .IF DF,DEBUG MOV #"NA,-(SP) ; DEBUG MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR .ENDC MOV R5,-(SP) ; SAVE NRB ADDRESS MOV #EVTRSP,-(SP) ; EVENT IS RETRY ALLOCATING RSP BUFFER CALL PSHET2 ; QUEUE EVENT BUT DON'T WAKEUP DIR$ #RETRY ; ISSUE MARK TIME BCC 110$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,R1 ; SIGN EXTEND ERROR MOV R1,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 110$: RETURN ; IF REGISTERS SAVED, RESTORE REGISTERS AND ; RETURN AT RETN .PAGE ; ; This subroutine scans the routing database to see ; if there are any messages that can be routed. The ; criteria that is used is: ; 1) There are output buffers available ; (HD.BFR .NE. 0) ; 2) The Message ID existed when the router ; was started up (done during database ; initialization). ; 3) The node that the message is to be routed ; to is available ((IE: N.STS .AND. N.AVL) .NE. 0) ; 4) The message count is for the message id is ; non zero and there is not an outstanding ; RNA message. ; ; If a message is selected, then a read and wait from the Queue ; is performed and the RNA pointer is stored in the ; NRBID NB.RNA. The message header and is filled in ; and the message is transmitted to the network. ; ; This routine is called with ast's disabled. ; GETOUT: MOV RTRHED+HD.NBL,R5 ; GET NRB TO LOOK FOR MOV RTRHED+HD.NCT,R0 ; NUMBER OF NODES 10$: MOV N.OIDS(R5),R1 ; START SCAN WHERE WE LEFT OFF LAST TIME MOV N.IDS(R5),R4 ; NUMBER OF ID'S BEQ 35$ ; NO MESAGES ROUTED TO THIS NODE ; ; LOOP HERE FOR EACH MESSAGE ID ROUTED TO THIS NODE ; 15$: TST RTRHED+HD.BFR ; ANY OUTPUT BUFFERS? BNE 20$ ; YES MOV R5,RTRHED+HD.NBL ; SAVE LAST SCANNED NODE MOV R1,N.OIDS(R5) ; SAVE LAST SCANNED MESSAGE ID RETURN ; 20$: BIT #NS.AVL,N.STS(R5) ; IS LINK AVAILABLE BEQ 35$ ; NO, THEN SKIP THIS NODE ; ; LOOP HERE FOR EACH ID IN THE NRB ; 30$: TST (R1) ; TIME TO RECYCLE THE NRBID LIST ; ID LIST TERMINATED WITH A NULL ENTRY BNE 31$ ; NO MOV R5,R1 ; POINTER TO NRBID LIST ADD #N.IDXL,R1 ; STARTS RIGHT AFTER THE NRB 31$: MOV NID.IX(R1),R2 ; DID WE FIND THIS ID DURING ; DATABASE INITITIALZATION BEQ 33$ ; NO. ; TST M.RNA(R2) ; IS THERE AN OUTSTANDING RNA BNE 33$ ; YES, THEN DON'T NEED TO LOOK FURTHER TST M.CNT(R2) ; ARE THERE ANY MESSAGES BEQ 33$ ; NO BIT #NIS.RT,NID.ST(R1) ; IS THIS MSG ID MARKED ROUTABLE BEQ 39$ ; YES, GO TRY TO OUTPUT IT .PAGE ; ; DONE WITH A NRBID ; 33$: ADD #NID.LN,R1 ; POINT TO NEXT NRBID SOB R4,15$ ; LOOP UNTIL DONE WITH ALL NRBIDS MOV R5,R1 ; SCANNED WHOLE NRB, POINT TO ADD #N.IDXL,R1 ; BEGINNING OF LIST AGAIN MOV R1,N.OIDS(R5) ; SAVE FOR NEXT SCAN THROUGH ; ; DONE WITH A NRB ; 35$: MOV N.LNK(R5),R5 ; GET FORWARD POINTER SOB R0,10$ ; LOOP UNTIL ALL HAVE BEEN SCANNED MOV R5,RTRHED+HD.NBL ; SAVE LAST SCANNED NODE RETURN ; ; WE HAVE A NODE WITH MESSAGES AND WE HAVE BUFFERS AVAILABLE ; TO OUTPUT THE MESSAGE. ; 39$: MOV R4,-(SP) ; SAVE NRBID COUNTER CALL ALLBUF ; ALLOCATE A BUFFER BCC 40$ ; IT SHOULD ALLOCATE!!! MOV #"40,ERRNUM ; ERROR NUMBER CLR ERRSTA ; NO STATUS CALL MESGW ; WE WANT TO LOG IOT ; DO AN IOT SO WILL FAULT AND GET PMD .PAGE ; ; R4= BUFFER TO WRITE INTO ; 40$: MOV R4,REDQUE+Q.IOSB ; I/O STATUS BLOCK ADDRESS ADD #O.IOSB,REDQUE+Q.IOSB ; IN BUFFER JUST ALLOCATED MOV R4,REDQUE+Q.IOPL ADD #O.BUF+MG.SIZ,REDQUE+Q.IOPL ; SKIP OVER LINKS AND RTR HDR. MOV R1,REDQUE+Q.IOPL+4 ; NRBID ADDRESS ADD #NID.NM,REDQUE+Q.IOPL+4 ; POINT TO MESSAGE ID NAME MOV RTRHED+HD.OSZ,REDQUE+Q.IOPL+2 ; SIZE OF THE BUFFERS SUB #MG.SIZ,REDQUE+Q.IOPL+2 ; NEED SPACE FOR ROUTER INFO. DIR$ #REDQUE ; DO THE READ BCC 55$ ; DIRECTIVE OK? MOV #"41,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) MOV R1,-(SP) ; POINT TO MSG ID NAME IN NRB ADD #NID.NM,(SP) MOV #16.,-(SP) ; NBR BYTES IN MSG ID NAME CALL PSHERR ; QUEUE MESSAGE 50$: CALL DEABUF ; DEALLOCATE THE BUFFER ADD #40000,NID.ST(R1) ; INCREMENT RETRY COUNTER, ; LAST TWO BITS OF NID.ST (V1.6) BCC 52$ ; NO CARRY OUT OF BIT 15, ; TRY NEXT TIME (V1.6) CLR NID.IX(R1) ; WON'T TRY THIS MESSAGE ; AGAIN!!! 52$: MOV (SP)+,R4 ; RESTORE NRBID COUNTER BR 33$ ; GO HANDLE REST FOR THIS NODE 55$: CMPB #IS.SUC,O.IOSB(R4) ; GOOD STATUS? BEQ 60$ ; YES MOV #"42,-(SP) ; NO, LOG THE ERROR MOVB O.IOSB(R4),-(SP) ; GET ERROR CODE FOR LOGGING BIS #177400,(SP) ; EXTEND THE ERROR CODE CLR -(SP) MOV R1,-(SP) ; POINT TO MSG ID NAME IN NRB ADD #NID.NM,(SP) MOV #16.,-(SP) ; NBR BYTES IN MSG ID NAME CALL PSHERR ; QUEUE MESSAGE BR 50$ ; COMMON ERROR PROCESSING .PAGE ; ; WRITE THE MESSAGE TO THE NETWORK, FILLING THE ; ROUTING DATABASE HEADER AND THE NORMAL HEADER ; ; R5= NRB ; R4= OUTPUT BUFFER ; 60$: BIC #140000,NID.ST(R1) ; CLEAR RETRY COUNTER BITS (V1.6) MOV R1,-(SP) MOV N.OSEQ(R5),R1 ; GET OUTBOUND LINK SEQ. NUMBER INC R1 ; INCREMENT IT MOV R1,N.OSEQ(R5) ; UPDATE IT CMP #9999.,R1 ; TIME TO WRAP? BNE 70$ ; NO CLR N.OSEQ(R5) ; YES, RESET SO WILL BE ONE AGAIN NEXT TIME 70$: MOV R1,O.BUF+MG.LSQ(R4) ; STORE IN ROUTER MESSAGE PORTION MOV (SP),R1 ; GET SAVED NRBID ADDRESS MOV R1,O.BUF+MG.IDX(R4) ; STORE NRBID INDEX MOV O.IOSB+2(R4),O.BUF+MG.RNA(R4) ; STORE RNA MOV O.IOSB+2(R4),NID.RA(R1) ; STORE IN NRBID TOO ; ; MOVE IN THE MESG ID ; MOV NID.NM(R1),O.BUF+MG.MID(R4) MOV NID.NM+2(R1),O.BUF+MG.MID+2(R4) MOV NID.NM+4(R1),O.BUF+MG.MID+4(R4) MOV NID.NM+6(R1),O.BUF+MG.MID+6(R4) MOV NID.NM+10(R1),O.BUF+MG.MID+10(R4) MOV NID.NM+12(R1),O.BUF+MG.MID+12(R4) MOV NID.NM+14(R1),O.BUF+MG.MID+14(R4) MOV NID.NM+16(R1),O.BUF+MG.MID+16(R4) ; ; MOVE IN OUR NODE NAME ; MOV RTRHED+HD.NOD,O.BUF+MG.SIZ+H.SNM(R4) MOV RTRHED+HD.NOD+2,O.BUF+MG.SIZ+H.SNM+2(R4) MOV RTRHED+HD.NOD+4,O.BUF+MG.SIZ+H.SNM+4(R4) ; ; MOVE IN TARGET NODE NAME ; MOV N.CUR(R5),O.BUF+MG.SIZ+H.DNM(R4) MOV N.CUR+2(R5),O.BUF+MG.SIZ+H.DNM+2(R4) MOV N.CUR+4(R5),O.BUF+MG.SIZ+H.DNM+4(R4) ; ; NOW DO A QIO TO THE NETWORK WITH THE MESSAGE ; THE BYTE COUNT OF THE MESSAGE IS IN THE MESSAGE ; HEADER PLUS OUR ROUTER HEADER SIZE (MG.SIZ) AND ; H.LEN. ; MOV O.BUF+MG.SIZ+H.LEN(R4),R1 ; GET SIZE OF MESSAGE PART ADD #H.SIZ+MG.SIZ,R1 ; TOTAL SIZE TO BE WRITTEN TO NETWORK MOV R1,SNDNET+Q.IOPL+2 ; STORE IN QIO MOV R4,SNDNET+Q.IOPL ; BUFFER ADDRESS ADD #O.BUF,SNDNET+Q.IOPL ; ADD OFFSET TO START OF BUFFER MOV N.LUN(R5),SNDNET+Q.IOLU ; LOGICAL UNIT NUMBER MOV #O.IOSB,SNDNET+Q.IOSB ; I/O STATUS BLOCK OFFSET ADD R4,SNDNET+Q.IOSB ; RELOCATE TO AN ADRESS DIR$ #SNDNET ; DO THE OUTPUT BCC 80$ ; A OK? MOV #"43,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) MOV R5,-(SP) ; POINT TO NODE NAME IN NRB ADD #N.CUR,(SP) MOV #6,-(SP) ; NBR BYTES IN NODE NAME CALL PSHERR ; QUEUE MESSAGE CALL DEABUF ; DEALLOCATE THE BUFFER BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 75$ ; NO CALL DISCNT ; DISCONNECT NODE 75$: MOV (SP)+,R1 ; RESTORE R1 MOV (SP)+,R4 ; RESTORE R4 JMP 35$ ; GO HANDLE NEXT NRB 80$: MOV (SP)+,R1 ; RESTORE R1 MOV (SP)+,R4 ; RESTORE R4 JMP 33$ .PAGE ; ; A READ BUT NOT ACKNOWLEGED POINTER HAS BEEN REPLACED ON THE ; QUEUE. THE QIO FOR THIS READ WAS PROBABLY ENVOKED WHEN ; A RESPONSE FROM THE REMOTE COMPUTER SHOWED THAT THE REMOTE ; COMPUTER WAS FULL, OR DIDN'T KNOW OF THE MESSAGE ID ; ; SINCE WE COULDN'T HAVE THE NETWORK POOPING ON OUR BUFFER, ; WE HAD TO WAIT UNTIL THE QUEACP FINISHED WITH THE BACKUP RNA ; BEFORE WE POST ANOTHER READ. WHICH IS WHAT WE HAVE TO DO ; HERE. ; ; 0(SP) = I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; RNAAST: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; I/O STATUS BLOCK ADDRESS SUB #N.IOSB,R5 ; POINT TO NRB TSTB N.IOSB(R5) ; RNA SUCCESSFUL? BPL 10$ ; YES MOV R1,-(SP) ; SAVE R1 MOV #"36,-(SP) ; FLAG BAD STATUS MOV N.IOSB(R5),-(SP) BIS #177400,(SP) ; SIGN EXTEND CLR -(SP) MOV N.ULNK(R5),R1 ; INPUT BUFFER ADDRESS TST (R1)+ ; SKIP BUFFER SIZE MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MSG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LATER LOGGING CALL POSRD1 ; POST ANOTHER READ MOV (SP)+,R1 ; RESTORE R1 MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP IOSB ADDRESS ASTX$S ; 10$: .IF DF,DEBUG MOV #"RN,-(SP) ; DEBUG MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEU FOR LATER LOGGING .ENDC CALL POSRD1 ; POST ANOTHER READ MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS SETF$S #WAKEFN ; WAKE UP MAINLINE TO SEE IF MORE ; MESSAGES CAN GO OUT ASTX$S .PAGE ; ; A remote computer liked what we sent it and we were ; acknowleging the message to the queue. But we couldn't ; allow the network to destroy our read buffer until ; the QUEACP finished acknowleging the message. All ; we have to do here is post another read. ; ; 0(SP) = I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; ACKAST: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; I/O STATUS BLOCK ADDRESS SUB #N.IOSB,R5 ; POINT TO NRB TSTB N.IOSB(R5) ; RNA SUCCESSFUL? BPL 10$ ; YES MOV R1,-(SP) ; SAVE R1 MOV #"37,-(SP) ; FLAG BAD STATUS MOV N.IOSB(R5),-(SP) BIS #177400,(SP) ; SIGN EXTEND CLR -(SP) MOV N.ULNK(R5),R1 ; INPUT BUFFER ADDRESS TST (R1)+ ; SKIP BUFFER SIZE MOV R1,-(SP) ADD #MG.MID,(SP) ; ADDRESS OF MSG ID NAME MOV #16.,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE FOR LATER LOGGING CALL POSRD1 ; POST ANOTHER READ MOV (SP)+,R1 ; RESTORE R1 MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP IOSB ADDRESS ASTX$S ; 10$: .IF DF,DEBUG MOV #"AK,-(SP) ; DEBUG MOV #-1,-(SP) CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEU FOR LATER LOGGING .ENDC CALL POSRD1 ; POST ANOTHER READ MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS SETF$S #WAKEFN ; ALL DONE, SEE IF MORE TO GO OUT ASTX$S .PAGE ; ; WRITE TO NETWORK QIO AST ; ; Deallocate the response buffer. If there was a QIO error, push ; an entry for later logging. Also, post another read on this node. ; ; 0(SP) = I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; WRRAST: MOV R5,-(SP) ; SAVE R5 MOV R4,-(SP) ; SAVE R4 MOV 4(SP),R4 ; GET I/O STAUS BLOCK ADDRESS SUB #R.IOSB,R4 ; CHANGE TO RESPONSE BUFFER STARTING ADDRESS MOV R.NRB(R4),R5 ; GET THE NRB ADDRESS CMPB #IS.SUC,R.IOSB(R4) ; GOOD STATUS BEQ 20$ ; YES MOV #"47,-(SP) ; ERROR NUMBER MOVB R.IOSB(R4),-(SP) BIS #177400,(SP) ; SIGN EXTEND STATUS CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE SO WILL LOG BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 20$ ; NO CALL DISCNT ; DISCONNECT NODE 20$: CALL DEARSP ; DEALLOCATE RESPONSE BUFFER MOV (SP)+,R4 ; RESTORE R4 MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS ASTX$S ; EXIT THE AST .PAGE ; ; WRITE TO NETWORK QIO AST ; ; Deallocate the output buffer. If there was a QIO error, push ; an entry for later logging. ; ; 0(SP) = I/O STATUS BLOCK ADDRESS (MUST BE POPPED) ; WROAST: MOV R5,-(SP) ; SAVE R5 MOV R4,-(SP) ; SAVE R4 MOV 4(SP),R4 ; GET I/O STATUS BLOCK ADDRESS SUB #O.IOSB,R4 ; CHANGE TO OUTPUT BUFFER STARTING ADDRESS MOV O.NRB(R4),R5 ; GET THE NRB ADDRESS CMPB #IS.SUC,O.IOSB(R4) ; GOOD STATUS BEQ 20$ ; YES MOV #"39,-(SP) ; ERROR NUMBER MOVB O.IOSB(R4),-(SP) BIS #177400,(SP) ; SIGN EXTEND STATUS CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE SO WILL LOG BIT #NS.DPN ! NS.DWN,N.STS(R5) ; IS THE NODE AVAILABLE TO ; DICONNECT? (COULD HAVE ; ALREADY BEEN DICONNECTED) BNE 20$ ; NO CALL DISCNT ; DISCONNECT NODE 20$: CALL DEABUF MOV (SP)+,R4 ; RESTORE R4 MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP I/O STATUS BLOCK ADDRESS ASTX$S ; EXIT THE AST .PAGE ; ; ; DISCONNECT THE LOGICAL LINK TO NODE ; R5 = NRB ADDRESS OF NODE TO DISCONNECT ; DISCNT: MOV R0,-(SP) ; SAVE R0 MOV R5,R0 ; NRB ADDRESS ADD #N.IOSC,R0 ; ADDRESS OF I/O STATUS BLOCK BIS #NS.DPN,N.STS(R5) ; MARK DISCONNECT PENDING DSC$S N.LUN(R5),#NETEFN,R0,#DISAST ; DICONNECT LOGICAL LINK BCC 20$ ; DIRECTIVE ACCEPTED BIC #NS.DPN,N.STS(R5) ; CLEAR DISCONNECT PENDING MOV #"51,-(SP) ; ERROR NUMBER MOVB $DSW,R0 ; SIGN EXTEND ERROR MOV R0,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE 20$: MOV (SP)+,R0 ; RESTORE R0 RETURN .PAGE ; ; DISCONNECT COMPLETE AST ; 0(SP) = I/O STATUS BLOCK ADDRESS ; DISAST: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET IOSB ADDRESS SUB #N.IOSC,R5 ; POINT TO START OF NRB TSTB N.IOSC(R5) ; GOOD STATUS? BPL 10$ ; YES BIC #NS.DPN,N.STS(R5) ; CLEAR DISCONNECT PENDING MOV #"52,-(SP) ; ERROR NUMBER MOVB N.IOSC(R5),-(SP); STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP IOSB ADDRESS ASTX$S 10$: BIC #NS.AVL ! NS.CPN ! NS.RCN ! NS.NOD,N.STS(R5) ; MARK NOT AVAILABLE BIS #NS.DWN,N.STS(R5) ; MARK DOWN BIC #NS.DPN,N.STS(R5) ; CLEAR DISCONNECT PENDING TST RTRHED+HD.CTM ; IS CONNECT TIMER ACTIVE BNE 30$ ; YES DIR$ #CONTIM ; ISSUE MARK TIME TO TRY CONNECT LATER BCC 25$ ; DIRECTIVE OK MOV #"49,-(SP) ; ERROR NUMBER MOVB $DSW,-(SP) ; DIRECTIVE STATUS BIS #177400,(SP) ; MAKE SURE NEGATIVE CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE BR 30$ 25$: INC RTRHED+HD.CTM ; SET CONNECT TIMER ACTIVE FLAG 30$: MOVB N.IOSC(R5),N.STAM(R5) ; SAVE DISCONNECT STATUS MOV R5,-(SP) ; NRB ADDRESS MOV #EVTDIS,-(SP) ; PUSH EVENT "DISCONNECT COMPLETE" CALL PSHENT MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; POP IOSB ADDRESS ASTX$S .PAGE ; ; ; DISCONNECT FROM NODE COMPLETE ; R1 = EVTDIS ; R5 = NRB ADDRESS ; ; LOG THE EVENT AND WRITE THE STATUS MESSAGE ; TO THE QUEUE. ; DISCMP: MOV #"53,-(SP) ; SUCCESSFUL DISCONNECT CLR -(SP) ; NO STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ; ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE ; ; WRITE CONNECT STATUS MESSAGE TO QUEUE ; TST STAFLG ; DOES MESSAGE ID EXIST BNE 10$ ; NO, DON'T ATTEMPT TO QUEUE MOV #STAMSG,R0 ; GET ADDRESS OF STATUS MESSAGE BUFFER CLR SM.UD(R0) ; FLAG AS DISCONNECT CALL WRTSTS ; WRITE DISCONNECT STATUS TO QUEUE 10$: RETURN .PAGE ; ; WRITE CONNECT/DISCONNECT MESSAGE TO 'NET_STATUS' MSG ID IN QUEUE ; R0 = ADDRESS OF CONNECT/DISCONNECT MSG BUFFER ; R5 = ADDRESS OF NRB ; WRTSTS: MOV N.PRI(R5),SM.PRI(R0) ; MOVE IN PRIMARY NODE NAME MOV N.PRI+2(R5),SM.PRI+2(R0) MOV N.PRI+4(R5),SM.PRI+4(R0) MOV N.SEC(R5),SM.SEC(R0) ; MOVE IN SECONDARY NODE NAME MOV N.SEC+2(R5),SM.SEC+2(R0) MOV N.SEC+4(R5),SM.SEC+4(R0) MOV N.STAM(R5),SM.IOS(R0) ; MOVE IN THE STATUS MOV N.STS(R5),SM.STS(R0) ; MOVE IN NRB STATUS WORD CLR SM.STS+2(R0) ; CLEAR SECOND WORD (NOT USED) DIR$ #WRTSTA ; DO THE QIO BCC 5$ ; DIRECTIVE OK MOV #"56,-(SP) ; ERROR NUMBER MOVB $DSW,R1 ; SIGN EXTEND ERROR MOV R1,-(SP) ; STORE ERROR STATUS CLR -(SP) ; CLEAR SECOND ERROR STATUS WORD MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; PUT ERROR IN MESSAGE QUEUE INC STAFLG ; SET FLAG SO THAT NO MORE ATTEMPTS ; TO QUEUE STATUS WILL BE MADE RETURN 5$: TSTB STASTA ; CHECK QIO STATUS BPL 10$ ; STATUS OK MOV #"57,-(SP) ; ERROR NUMBER MOV STASTA,-(SP) ; I/O STATUS BIS #177400,(SP) ; SIGN EXTEND CLR -(SP) MOV R5,-(SP) ADD #N.CUR,(SP) ; ADDRESS OF NODE NAME MOV #6,-(SP) ; NUMBER OF BYTES TO MOVE CALL PSHERR ; QUEUE ERROR FOR LOG INC STAFLG ; SET FLAG SO THAT NO MORE ATTEMPTS ; TO QUEUE STATUS WILL BE MADE 10$: RETURN .PAGE .PSECT $DATA,D,CON,LCL,REL ; ; EVENT QUEUE ; INSPTR: .WORD QUEUE ; INSERT POINTER REMPTR: .WORD QUEUE ; REMOVAL POINTER QUECNT: .WORD 0 ; NUMBER OF ENTRIES IN QUEUE QUESIZ=20. ; NUMBER OF ENTRIES ; QUEUE: .REPT QUESIZ .BLKW 2 ; TWO WORDS PER ENTRY .ENDR QUEEND=. ; ; ; This subroutine is responsible for pushing a single ; event into our event queue. ; ; calling sequence is: ; ; (sp)= return address ; 02(sp)= Entry type ; 04(sp)= entry parameter ; ; NOTE: AST MUST BE DISABLED OR CALLED FROM AN AST ROUTINE ; ; return is with the stack cleaned up and all registers preserved. ; .PSECT $CODE,RO,I,CON,REL PSHENT: SETF$S #WAKEFN ; SET NETWORK WAKE UP EVENT FLAG PSHET2: ; ENTRY TO NOT CAUSE A WAKEUP CMP #QUESIZ,QUECNT ; ROOM STILL LEFT IN QUEUE? BLE 40$ ; NO ; ; STORE ENTRY IN QUEUE ; MOV R0,-(SP) ; SAVE REGISTERS MOV R1,-(SP) MOV INSPTR,R0 ; WHERE TO INSERT CMP #QUEEND,R0 ; TIME TO WRAP QUEUE BNE 20$ ; NO MOV #QUEUE,R0 ; RESET TO BEGINNING OF QUEUE ; 20$: MOV 6(SP),(R0)+ ; MOVE ENTRY TYPE MOV 10(SP),(R0)+ ; MOVE ENTRY PARAMETER MOV R0,INSPTR ; UPDATE INSERT POINTER INC QUECNT ; UPDATE COUNTER MOV (SP)+,R1 ; RESTORE OUR REGISTERS MOV (SP)+,R0 40$: MOV (SP),4(SP) ; MOVE RETURN ADDRESS DOWN OVER ENTRY PARMETER CMP (SP)+,(SP)+ ; OLD RETURN ADDR. AND ENTRY TYPE RETURN .PAGE ; ; This subroutine is responsible for removing an entry from the ; event queue. The calling sequence is: ; ; CALL REMQUE ; ; On return, if carry is clear, then have an entry. ; R0= destroyed ; R1= entry type ; R5= entry parameter ; ; else carry is set in which case the queue was empty. ; REMQUE: TST QUECNT BNE 10$ ; HAVE AN ENTRY SEC ; NO ENTRY RETURN ; 10$: MOV REMPTR,R0 ; GET REMOVAL POINTER MOV (R0)+,R1 ; TYPE MOV (R0)+,R5 ; ENTRY PARAMETER CMP #QUEEND,R0 ; PAST END OF QUEUE? BNE 20$ ; NO MOV #QUEUE,R0 ; YES, RESET TO BEGINNING 20$: DEC QUECNT ; DECREMENT NUMBER IN QUEUE MOV R0,REMPTR ; POINT TO NEXT AVAILABLE CLC RETURN .PAGE .PSECT $DATA,D,CON,LCL,REL ; ; MESSAGE QUEUE ; INSPTE: .WORD ERRQUE ; INSERT POINTER REMPTE: .WORD ERRQUE ; REMOVAL POINTER EQUECT: .WORD 0 ; NUMBER OF ENTRIES IN QUEUE EQUESZ=20. ; NUMBER OF ENTRIES ; ERRQUE: .REPT EQUESZ .BLKB 22. ; 22 BYTES PER ENTRY .ENDR EQUEEN=. ; ; ; This subroutine is responsible for pushing a status message ; into our message queue if the console QIO busy flag is set. ; If the busy flag is not set, the message is logged without ; being queued. ; ; calling sequence is: ; ; (sp)= return address ; 02(sp)= status type ; 04(sp)= error status word 1 (0 if no status) ; 06(sp)= error status word 2 (0 if no status) ; 10(sp)= address of extra ASCII to log (0 if none to log) ; 12(sp)= number of extra ASCII characters to log (0 if none to log) ; ; NOTE: AST MUST BE DISABLED OR CALLED FROM AN AST ROUTINE ; ; return is with the stack cleaned up and all registers preserved. ; .PSECT $CODE,RO,I,CON,REL PSHERR: ; ; STORE ENTRY IN QUEUE ; MOV R0,-(SP) ; SAVE REGISTERS MOV R1,-(SP) MOV R2,-(SP) TST BUSY ; IS A CONSOLE QIO STILL PENDING? BNE 10$ ; YES, QUEUE MESSAGE JMP LOGMSG ; LOG MESSAGE WITHOUT QUEUEING 10$: CMP #EQUESZ,EQUECT ; ROOM STILL LEFT IN QUEUE? BLE 37$ ; NO, CLEAN STACK AND EXIT MOV INSPTE,R0 ; WHERE TO INSERT CMP #EQUEEN,R0 ; TIME TO WRAP QUEUE BNE 20$ ; NO MOV #ERRQUE,R0 ; RESET TO BEGINNING OF QUEUE 20$: MOV 20(SP),(R0)+ ; MOVE TYPE MOV 16(SP),(R0)+ ; MOVE STATUS WORD 1 MOV 14(SP),(R0)+ ; MOVE STATUS WORD 2 MOV 12(SP),R2 ; ADDRESS OF EXTRA ASCII TO BE QUEUED BEQ 32$ ; ZERO, NOTHING TO MOVE MOV 10(SP),R1 ; NUMBER OF BYTES TO MOVE 30$: MOVB (R2)+,(R0)+ ; MOVE EXTRA ASCII TO QUEUE SOB R1,30$ 32$: MOV 10(SP),R1 ; CALCULATE NUMBER BYTES TO FILL SUB #16.,R1 ; WITH SPACES NEG R1 BEQ 36$ ; NOTHING TO FILL WITH SPACES 35$: MOVB #' ,(R0)+ ; FILL REST WITH SPACES SOB R1,35$ 36$: MOV R0,INSPTE ; UPDATE INSERT POINTER INC EQUECT ; UPDATE COUNTER 37$: MOV (SP)+,R2 ; RESTORE OUR REGISTERS MOV (SP)+,R1 MOV (SP)+,R0 MOV (SP),12(SP) ; MOVE RETURN ADDRESS DOWN OVER TYPE ADD #12,SP ; POP STACK TO RETURN ADDRESS RETURN ; ; CONSOLE QIO IS NOT PENDING. LOG MESSAGE WITHOUT QUEUEING. ; LOGMSG: INC BUSY ; SET CONSOLE QIO PENDING FLAG MOV #ASCXTA,R0 ; PLACE FOR EXTRA ASCII MOV 20(SP),ERRNUM ; MOVE TYPE MOV 16(SP),ERRSTA ; MOVE STATUS WORD 1 MOV 14(SP),ERRSTA+2 ; MOVE STATUS WORD 2 MOV 12(SP),R2 ; ADDRESS OF EXTRA ASCII TO BE QUEUED BEQ 32$ ; ZERO, NOTHING TO MOVE MOV 10(SP),R1 ; NUMBER OF BYTES TO MOVE 30$: MOVB (R2)+,(R0)+ ; MOVE EXTRA ASCII TO QUEUE SOB R1,30$ 32$: MOV 10(SP),R1 ; CALCULATE NUMBER BYTES TO FILL SUB #16.,R1 ; WITH SPACES NEG R1 BEQ 36$ ; NOTHING TO FILL WITH SPACES 35$: MOVB #' ,(R0)+ ; FILL REST WITH SPACES SOB R1,35$ 36$: CALL MESG ; LOG MESSAGE MOV (SP)+,R2 ; RESTORE OUR REGISTERS MOV (SP)+,R1 MOV (SP)+,R0 MOV (SP),12(SP) ; MOVE RETURN ADDRESS DOWN OVER TYPE ADD #12,SP ; POP STACK TO RETURN ADDRESS RETURN .PAGE ; ; This subroutine is responsible for removing an entry from the ; status message queue. The calling sequence is: ; ; CALL REMERR ; REMERR: TST EQUECT ; IS THERE A MESSAGE IN QUEUE? BNE 10$ ; YES, SEE IF MESSAGE CAN BE SENT TO CONSOLE RETURN 10$: INC BUSY ; SET QIO PENDING FLAG MOV REMPTE,R0 ; GET REMOVAL POINTER MOV #ASCXTA,R2 ; EXTRA ASCII ADDRESS IN R2 MOV (R0)+,ERRNUM ; STATUS TYPE MOV (R0)+,ERRSTA ; STATUS WORD 1 MOV (R0)+,ERRSTA+2 ; STATUS WORD 2 MOV #8.,R1 ; NUMBER OF WORDS IN EXTRA ASCII 15$: MOV (R0)+,(R2)+ ; MOVE WORD SOB R1,15$ CMP #EQUEEN,R0 ; PAST END OF QUEUE? BNE 20$ ; NO MOV #ERRQUE,R0 ; YES, RESET TO BEGINNING 20$: DEC EQUECT ; DECREMENT NUMBER IN QUEUE MOV R0,REMPTE ; POINT TO NEXT AVAILABLE CALL MESG ; LOG MESSAGE RETURN .PAGE ; ; ; SUBROUTINE 'ALLBUF' WILL ALLOCATE AN OUTPUT BUFFER. ; ; RECEIVES: R5 -- ADDRESS OF NRB ; RETURNS: R4 -- ADDRESS OF OUTPUT BUFFER ; C=0 IF OUTPUT BUFFER WAS ALLOCATED ; C=1 IF ALLOCATION FAILED ; ALLBUF: TST RTRHED+HD.BFR ; SEE IF THERE IS A FREE BUFFER BNE 10$ ; THERE IS SEC ; SET CARRY TO INDICATE ALLOCATION ; FAILURE RETURN ; 10$: MOV RTRHED+HD.OCT,R3 ; TOTAL NUMBER OF BUFFERS AVAILABLE MOV RTRHED+HD.BLS,R4 ; ADDRESS OF FIRST BUFFER TO CHECK 15$: TST O.NRB(R4) ; SEE IF THE POINTER TO THE NRB IS ; ZERO INDICATING A FREE BUFFER BEQ 20$ ; NOT IN USE MOV O.LNK(R4),R4 ; LOAD POINTER TO NEXT BUFFER SOB R3,15$ ; CHECK NEXT BUFFER SEC ; SET CARRY TO INDICATE ALLOCATION ; FAILURE (SHOULD NOT HAPPEN SINCE ; FREE COUNTER WAS NOT ZERO) RETURN ; 20$: MOV R5,O.NRB(R4) ; STORE POINTER TO NRB TO ALLOCATE ; BUFFER DEC RTRHED+HD.BFR ; DECREMENT FREE COUNTER CLC ; CLEAR CARRY TO INDICATE SUCCESS RETURN ; ; ; ; ; SUBROUTINE 'DEABUF' WILL DEALLOCATE AN OUTPUT BUFFER. ; ; RECEIVES: R4 -- ADDRESS OF BUFFER TO DEALLOCATE ; DEABUF: CLR O.NRB(R4) ; ZERO POINTER TO NRB TO FREE BUFFER MOV R4,RTRHED+HD.BLS ; POINT NEXT POSSIBLE FREE BUFFER TO ; THIS BUFFER INC RTRHED+HD.BFR ; INCREMENT FREE COUNTER CMP #1,RTRHED+HD.BFR ; DID FREE COUNT GO FROM 0 TO 1 BNE 10$ ; NO SETF$S #WAKEFN ; HAVE 1 FREE OUTPUT BUFFER NOW, ; SET WAKEUP EFN TO SCAN FOR ; MORE WORK TO SEND 10$: RETURN ; ; ; ; ; SUBROUTINE 'ALLRSP' WILL ALLOCATE A RESPONSE BUFFER. ; ; RECEIVES: R5 -- ADDRESS OF NRB ; RETURNS: R4 -- ADDRESS OF RESPONSE BUFFER ; C=0 IF RESPONSE BUFFER WAS ALLOCATED ; C=1 IF ALLOCATION FAILED ; ALLRSP: TST RTRHED+HD.RFR ; SEE IF THERE IS A FREE BUFFER BNE 10$ ; THERE IS SEC ; SET CARRY TO INDICATE ALLOCATION ; FAILURE RETURN ; 10$: MOV RTRHED+HD.RCT,R3 ; TOTAL NUMBER OF BUFFERS AVAILABLE MOV RTRHED+HD.RLS,R4 ; ADDRESS OF FIRST BUFFER TO CHECK 15$: TST R.NRB(R4) ; SEE IF THE POINTER TO THE NRB IS ; ZERO INDICATING A FREE BUFFER BEQ 20$ ; NOT IN USE MOV R.LNK(R4),R4 ; LOAD POINTER TO NEXT BUFFER SOB R3,15$ ; CHECK NEXT BUFFER SEC ; SET CARRY TO INDICATE ALLOCATION ; FAILURE (SHOULD NOT HAPPEN SINCE ; FREE COUNTER WAS NOT ZERO) RETURN ; 20$: MOV R5,R.NRB(R4) ; STORE POINTER TO NRB TO ALLOCATE ; BUFFER DEC RTRHED+HD.RFR ; DECREMENT FREE COUNTER CLC ; CLEAR CARRY TO INDICATE SUCCESS RETURN ; ; ; ; ; SUBROUTINE 'DEARSP' WILL DEALLOCATE A RESPONSE BUFFER. ; ; RECEIVES: R4 -- ADDRESS OF BUFFER TO DEALLOCATE ; DEARSP: CLR R.NRB(R4) ; ZERO POINTER TO NRB TO FREE BUFFER MOV R4,RTRHED+HD.RLS ; POINT NEXT POSSIBLE FREE BUFFER TO ; THIS BUFFER INC RTRHED+HD.RFR ; INCREMENT FREE COUNTER RETURN .PAGE .PSECT $DATA,D,CON,LCL,REL ; ; QIO'S TO WRITE TO CONSOLE DEVICE ; CONSWT: QIOW$ IO.WLB,ICO,CONEFN,,CONSTS,, CONSOL: QIO$ IO.WLB,ICO,CONEFN,,CONSTS,LOGAST, CONSTS: .WORD 1,0 ; CONSOLE QIO STATUS BUSY: .WORD 0 ; I/O IN PROGRESS FLAG ; ; DPB TO GET THE CURRENT SYSTEM TIME ; TIME: GTIM$ TIMBUF TIMBUF: .BLKW 8. ; BUFFER TO GET CURRENT TIME AND DATE WAKEUP: .ASCII /WAKEUP/ ; FOR DEBUG WAKEUP MESSAGE .EVEN ; ; CONSOLE DEVICE MESSAGE ; LGMESG: .BYTE 012,015 ; SOME CARRIAGE RETURNS .BYTE 006 ; A BELL .EVEN MSGTIM: ; TIME STAMP TO MESSAGE .ASCII /YY-MM-DD / .ASCII /HH:MM:SS / .ASCII / RTRRSX ROUTER ERROR: / .EVEN ERRNUM: .WORD 0 ; ASCII ERROR NUMBER .ASCII / STATUS: / .EVEN ASCSTA: .ASCII / / ; WORD 0 OF STATUS BLOCK .ASCII / / .ASCII / / .ASCII / / ; SEPARATE STATUS BLOCK WORDS .EVEN ASCST2: .ASCII / / ; WORD 1 OF STATUS BLOCK .ASCII / / .ASCII / / .EVEN ASCXTA: .ASCII / / ; SOME EXTRA ASCII IF DESIRED .ASCII / / ; SOME EXTRA ASCII IF DESIRED .ASCII / / ; SOME EXTRA ASCII IF DESIRED .ASCII / / ; SOME EXTRA ASCII IF DESIRED .BYTE 012,015,006,006 ; LINE FEEDS, CARRIAGE RETURNS, BELLS .EVEN CSMGL=.-LGMESG .PAGE ; ; MESSAGE OUTPUT SUBROUTINE ; ; ERROR DESCRIPTION ; ; 01 Unable to set up SST vector ; 02 Unable to attach to QUEHED region ; 03 Unable to map the QUEHED region ; 04 Successful map to QUEHED, status= size ; 05 Routing database not consistent with one linked with task ; 06 Assign lun to network failure ; 07 Specify network AST directive failure ; 08 Specify network AST I/O status failure ; 09 Get local node information directive failure ; 10 Get local node information status failure ; 11 Assign lun to network bad i/o status ; 12 Unknown network message type received (type is status) ; 13 Bad directive status while backing up RNA when link est. ; 14 Good connect to the network. Local node name is printed ; 15 Connection requested by remote node was rejected by this node ; 16 Node connection accept attempt failed for a remote node ; 17 Bad directive status while attempting to accept connection ; 18 Bad directive status while attempting to reject connection ; 19 Interupt network message received ; 20 User disconnect network message received ; 21 User abort network message received ; 22 Network abort network message received ; 23 Get network data bad I/O status ; 24 Remote request for a node not in routing database ; 25 Connect complete to node printed ; 26 Mesg. ID was not found in Queue, Mesg. ID will not be routed ; 27 Bad directive status while posting a read for node ; 28 Read from network with bad I/O status ; 29 Link sequence number in error by delta value ; 30 Write to queue directive status error ; 31 Invalid router to router type message received ; 32 RNA received from the remote computer does not match ours ; 33 Bad directive status on ACK Write QIO to the Queue ; 34 Bad directive status while connecting to msg id in queue. ; 35 Bad I/O status while connecting to msg id in queue ; 36 Backup RNA to queue I/O status error ; 37 Ack message to queue I/O status error ; 38 Get network data bad directive status ; 39 Write to network with bad status (output buffer) ; 40 Unable to allocate an output buffer, IOT will be issued ; 41 Directive error while reading a message id from queue ; 42 Bad I/O status while reading from queue, message marked not ; routable ; 43 Bad directive status while writing to network ; 44 Bad directive status on RNA QIO to the Queue ; 45 Connect request bad directive status ; 46 Connect request failure for node, possible network status: ; 47 Write to network with bad status (response buffer) ; 48 Bad directive status while writing response to network ; 49 Bad directive status issuing mark time ; 50 Bad directive status while initing queue access ; 51 Bad directive status while disconnecting ; 52 Bad I/O status while disconnecting ; 53 Disconnect complete, disconnected node logged ; 54 Routing database wasn't initialized properly (i.e. was accessed ; since last installed from disk) ; 55 Bad directive status while attempting to activate task ; 56 Bad directive status while writing connect/disconnect status ; message to queue ; 57 Bad I/O status while writing connect/disconnect status message ; to queue ; ; ; DEBUG DESCRIPTION ; ; CA Connect to network for network mail ast routine ; SA Receive network mail (AST) ; CR Accept connect request from remote node ; AA Accept connect request QIO from remote node complete ; PR Post a read on remote node when connect just made ; P1 Post a read on remote node when in AST state ; DD Received a message from remote node ; NR Message not routable to remote node; remote responded that ; it could not queue message. ; ER Not routable timer expired; mark all msg ids routable ; NQ Message received from remote node could not be queued; send ; response to remote. ; WQ Message received from remote node was queued successfully; ; send response to remote. ; NA Response buffer could not be allocated ; RN A message read but not acknowledged by remote has been requeued. ; AK A message has been acknowledged successfully by the remote. ;%%%%%%%%%%% ; ; ERROR STATUS TO BE ENCODED INTO THE MESSAGE BEFORE OUTPUT ; ERRSTA: .WORD 0,0 ; .PSECT $CODE,RO,I,CON,REL ; ; THIS ROUTINE WILL ISSUE A QIO TO THE CONSOLE AND WAIT FOR IT TO COMPLETE. ; IT IS ONLY USED TO LOG FATAL ERROR MESSAGES SINCE THE TASK MUST WAIT ; FOR THE QIO TO COMPLETE BEFORE IT EXITS. ; DSWMSG: ; ENTRY WHERE DSW IS THE STATUS, R0 ; IS DESTROYED MOVB $DSW,R0 ; SIGN EXTEND THE ERROR CODE MOV R0,ERRSTA ; STORE STATUS MESGW: MOV R0,-(SP) ; SAVE REGISTERS MOV R1,-(SP) MOV R2,-(SP) CALL FORMAT ; FORMAT MESSAGE DIR$ #CONSWT ; OUTPUT MESSAGE TO CONSOLE DEVICE AND WAIT MOV #16.,R1 ; BLANK OUT ASCII EXTENSION (16 BYTES) MOV #ASCXTA,R2 10$: MOVB #' ,(R2)+ ; BLANK OUT ASCII EXTENSION SOB R1,10$ MOV (SP)+,R2 ; RESTORE OUR REGISTERS MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; ; THIS ROUTINE WILL ISSUE A QIO TO THE CONSOLE AND CONTINUE. ALL NON-FATAL ; ERRORS MUST USE THIS ROUTINE SO THAT THE TASK DOES NOT WAIT FOREVER IF ; THE QIO DOESN'T COMPLETE (CONSOLE OUT OF PAPER, ETC.) ; MESG: CALL FORMAT ; FORMAT MESSAGE DIR$ #CONSOL ; OUTPUT MESSAGE TO CONSOLE DEVICE AND WAIT RETURN ; ; ; QIO TO THE CONSOLE PRINTER HAS COMPLETED. RESET THE BUSY FLAG AND ; CHECK FOR MORE MESSAGES TO LOG. ; ; 0(SP) = ADDRESS OF I/O STATUS BLOCK ; LOGAST: MOV R0,-(SP) ; SAVE REGISTERS MOV R1,-(SP) MOV R2,-(SP) CLR BUSY ; RESET BUSY FLAG CALL REMERR ; CHECK FOR ANOTHER MESSAGE IN QUEUE TO LOG MOV (SP)+,R2 ; RESTORE OUR REGISTERS MOV (SP)+,R1 MOV (SP)+,R0 TST (SP)+ ; POP IOSB ADDRESS OFF STACK ASTX$S ; ; ; THIS ROUTINE FORMATS THE MESSAGE LOGGED ON THE CONSOLE ; FORMAT: DIR$ #TIME ; GET CURRENT SYSTEM TIME MOV #TIMBUF,R1 ; DATE PARAMETERS MOV #MSGTIM,R0 ; WHERE TO ENCODE TIME CALL $DAT ; COVNERT DATE MOVB #' ,(R0)+ ; STORE INTERVENING SPACE MOV #TIMBUF+6,R1 ; TIME PARAMETERS MOV #3,R2 ; WANT HH:MM:SS CALL $TIM ; CONVERT TIME ; MOV #" ,ASCSTA ; BLANK OUT MOV #" ,ASCSTA+2 MOV #" ,ASCSTA+4 TST ERRSTA ; IS STATUS ZERO? BEQ 2$ ; YES, NO STATUS TO LOG MOV #ASCSTA,R0 ; PLACE FOR ASCII MOV ERRSTA,R1 ; BINARY TO CONVERT ; ; MOV #<10.!400!020000>,R2 ; CONVERSION PARAMETERS CALL $CBTA ; CALL TO CONVERT BINARY ASCII ; ; 2$: MOV #" ,ASCST2 ; BLANK OUT MOV #" ,ASCST2+2 MOV #" ,ASCST2+4 TST ERRSTA+2 ; IS SECOND STATUS WORD=0 BEQ 5$ ; DON'T LOG IT MOV #ASCST2,R0 ; PLACE FOR ASCII MOV ERRSTA+2,R1 ; BINARY TO CONVERT ; ; MOV #<10.!400!020000>,R2 ; CONVERSION PARAMETERS CALL $CBTA ; CALL TO CONVERT BINARY ASCII CLR ERRSTA+2 ; CLEAR STATUS ; 5$: RETURN .PAGE ; ; SYNCHRONOUS SYSTEM TRAP ROUTINES ; ; THE COMMON SST ROUTINE CREATES A SNAP DUMP OF THE TASK STACK ; AND THE ROUTER DATABASE REGION. THE EXACT ; SST IS IDENTIFIED BY AN ERROR CODE THAT APPEARS ON THE STACK ; ALONG WITH SST DEPENDENT PARAMETERS. ; ; THE STACK IN THE SNAP DUMP CONTAINS THE FOLLOWING ; (SP) = R5 WHEN SST OCCURRED ; 2(SP) = R4 WHEN SST OCCURRED ; 4(SP) = R3 WHEN SST OCCURRED ; 6(SP) = R2 WHEN SST OCCURRED ; 10(SP) = R1 WHEN SST OCCURRED ; 12(SP) = R0 WHEN SST OCCURRED ; 14(SP) = SST CODE ; ; ; ODD ADDRESS OR NONEXISTENT MEMORY ; 14(SP) = SST CODE 'OD' ; 16(SP) = PC WHEN SST OCCURRED ; 20(SP) = PSW WHEN SST OCCURRED ; ODDSST: MOV #"OD,-(SP) ; PUSH ODD ADDRESS CODE 'OD' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; MEMORY PROTECT VIOLATION ; 14(SP) = SST CODE 'ME' ; 16(SP) = MMR1 (INSTRUCTION BACKUP REGISTER) ; 20(SP) = MMR2 (VIRTUAL PC OF FAULTY INSTRUCTION) ; 22(SP) = MMR0 (MEMORY PROTECT STATUS) ; 24(SP) = PC WHEN SST OCCURRED ; 26(SP) = PSW WHEN SST OCCURRED MEMSST: MOV #"ME,-(SP) ; PUSH MEMORT PROTECT CODE 'ME' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; T-BIT TRAP OR EXECUTION OF A BPT INSTRUCTION ; 14(SP) = SST CODE 'TB' ; 16(SP) = PC WHEN SST OCCURRED ; 20(SP) = PSW WHEN SST OCCURRED TBTSST: MOV #"TB,-(SP) ; PUSH T-BIT CODE 'TB' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; EXECUTION OF AN IOT INSTRUCTION ; 14(SP) = SST CODE 'IO' ; 16(SP) = PC WHEN SST OCCURRED ; 20(SP) = PSW WHEN SST OCCURRED IOTSST: MOV #"IO,-(SP) ; PUSH IOT CODE 'IO' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; EXECUTION OF A RESERVED INSTRUCTION ; 14(SP) = SST CODE 'RE' ; 16(SP) = PC WHEN SST OCCURRED ; 20(SP) = PSW WHEN SST OCCURRED RESSST: MOV #"RE,-(SP) ; PUSH RESERVED INSTRUCTION CODE 'RE' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; EXECUTION OF A NON-RSX EMT INSTRUCTION ; 14(SP) = SST CODE 'EM' ; 16(SP) = EMT CODE TIMES 2 ; 20(SP) = PC WHEN SST OCCURRED ; 22(SP) = PSW WHEN SST OCCURRED EMTSST: MOV #"EM,-(SP) ; PUSH EMT CODE 'EM' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; EXECUTION OF A TRAP INSTRUCTION ; 14(SP) = SST CODE 'TR' ; 16(SP) = TRAP CODE TIMES 2 ; 20(SP) = PC WHEN SST OCCURRED ; 22(SP) = PSW WHEN SST OCCURRED TRPSST: MOV #"TR,-(SP) ; PUSH TRAP CODE 'TR' ON STACK JMP COMSST ; ENTER COMMON ROUTINE ; ; FLOATING POINT EXCEPTION ; 14(SP) = SST CODE 'FL' ; 16(SP) = PC WHEN SST OCCURRED ; 20(SP) = PSW WHEN SST OCCURRED FLTSST: MOV #"FL,-(SP) ; PUSH FLOAT EXCEPTION CODE 'FL' ON STACK ; COMSST: MOV R0,-(SP) ; SAVE STATE OF REGISTERS WHEN SST MOV R1,-(SP) ; OCCURRED MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV R5,-(SP) MOV RDB+R.GSIZ,R1 ; GET 'QUEHED' SIZE IN 32 WORD BLOCKS ASH #6,R1 ; CHANGE TO NUMBER OF BYTES ADD #137776,R1 ; MERGE IN APR6 MAPPING MOV #117776,R2 ; ROUTING DATABASE MAPPED BY APRS 2,3,4 SNAP$ ,,,#140000,R1,#40000,R2 ; GENERATE SNAP DUMP; QUEUE HEADER AND DATABASE EXIT$S ; EXIT TASK .END START