TITLE SCASER - SYSTEM COMMUNICATIONS ARCHITECTURE SERVICE V37 SUBTTL JOSEPH A. DZIEDZIC/JAD 05-JAN-88 SEARCH F,S,SCAPRM,MACSYM,BTSPRM $RELOC $XHIGH PURGEACS ;PURGE DEFAULT (TOPS-10) AC NAMES T20SYM ;SWITCH TO TOPS-20 AC NAMES ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1984,1986,1988. ;ALL RIGHTS RESERVED. .CPYRT<1984,1988> XP VSCASR,37 ;VERSION NUMBER FOR GLOB AND MAP ;BASED ON TOPS-20 "SCAMPI" MODIFIED TO SUPPORT MULTIPLE PATHS SCASER:!ENTRY SCASER ;LOAD IF LIBRARY SEARCH SUBTTL PARAMETERS KLPX9==602033 ;TOPS-20 ERROR CODE SUBTTL TABLE X TABLEX: ;Connect FLD(.BSCNP,X.BSTAT)+FLD(.CSCSE,X.CSTAT) ;Closed X.ERR ;Listening X.ERR ;Connect_sent X.ERR ;Connect_received X.ERR ;Connect_ACK X.ERR ;Accept_sent X.ERR ;Reject_sent X.ERR ;Open X.ERR ;Disconnect_sent X.ERR ;Disconnect_rec X.ERR ;Disconnect_ACK X.ERR ;disconnect_match ;Listen FLD(.CSLIS,X.CSTAT) ;Closed 0 ;Listening X.ERR ;Connect_sent X.ERR ;Connect_received X.ERR ;Connect_ACK X.ERR ;Accept_sent X.ERR ;Reject_sent X.ERR ;Open X.ERR ;Disconnect_sent X.ERR ;Disconnect_rec X.ERR ;Disconnect_ACK X.ERR ;disconnect_match ;Accept X.ERR ;Closed X.ERR ;Listening X.ERR ;Connect_sent FLD(.BSACP,X.BSTAT) ;Connect_received X.ERR ;Connect_ACK X.ERR ;Accept_sent X.ERR ;Reject_sent X.ERR ;Open X.ERR ;Disconnect_sent X.ERR ;Disconnect_rec X.ERR ;Disconnect_ACK X.ERR ;disconnect_match ;Reject X.ERR ;Closed X.ERR ;Listening X.ERR ;Connect_sent FLD(.BSRPN,X.BSTAT) ;Connect_received X.ERR ;Connect_ACK X.ERR ;Accept_sent X.ERR ;Reject_sent X.ERR ;Open X.ERR ;Disconnect_sent X.ERR ;Disconnect_rec X.ERR ;Disconnect_ACK X.ERR ;disconnect_match ;Disconnect 0 ;Closed (no change) FLD(.CSCLO,X.CSTAT) ;Listening FLD(.CSCLO,X.CSTAT) ;Connect_sent FLD(.BSRPN,X.BSTAT)+FLD(.CSRJS,X.CSTAT) ;Connect_received FLD(.CSCLO,X.CSTAT) ;Connect_ACK FLD(.CSCLO,X.CSTAT) ;Accept_sent FLD(.CSCLO,X.CSTAT) ;Reject_sent FLD(.BSDPN,X.BSTAT)+FLD(.CSDSE,X.CSTAT) ;Open 0 ;Disconnect_sent (no change) FLD(.BSDPN,X.BSTAT)+FLD(.CSDMC,X.CSTAT) ;Disconnect_rec 0 ;Disconnect_ACK (no change) 0 ;Disconnect_match (no change) SUBTTL Table Y ;For each block state, this table provides the op code to send and the ;new connection state ; * * * * ;Disagrees with corporate spec when block state is connect_pending. We ;have already set the connection state to .CSCSE in order to ensure that ;if a connection's state is "closed", the sysap never expects to hear ;about it again. If this is not changed, there is potential for the sysap ;to call SC.DIS between the time that the connection state is set and ;the message is actually sent. That sets the state to closed. We can't ;change it to connect_sent when the message is finally sent, because ;we'd lose track of the fact that the sysap had closed it. ; * * * * TABLEY: 0 ;Not used 0 ;Free (1) 0 ;Allocate (2) ; FLD(.STORQ,Y.OP)+FLD(.CSCSE,Y.STAT) ;Connect_pending (3) FLD(.STORQ,Y.OP) ;Connect_pending (3) FLD(.STARQ,Y.OP)+FLD(.CSACS,Y.STAT) ;Accept_pending (4) FLD(.STRRQ,Y.OP)+FLD(.CSRJS,Y.STAT) ;Reject_pending (5) FLD(.STCRQ,Y.OP) ;Credit_pending (state doesn't change) (6) FLD(.STDRQ,Y.OP) ;Disconnect_pending (state already set) (7) YSIZE==:.-TABLEY SUBTTL Table Z ;This table indicates, for a given op code, the length of its message, ;the priority for sending it, and the expected response. TABLEZ: FLD(.LNORQ,Z.LEN)+FLD(KLPMED,Z.PRI)+FLD(.STORS,Z.RSP) ;Connect_req FLD(.LNORS,Z.LEN)+FLD(KLPMED,Z.PRI) ;CONNECT_RSP FLD(.LNARQ,Z.LEN)+FLD(KLPMED,Z.PRI)+FLD(.STARS,Z.RSP) ;ACCEPT_REQ FLD(.LNARS,Z.LEN)+FLD(KLPMED,Z.PRI) ;ACCEPT_RSP FLD(.LNRRQ,Z.LEN)+FLD(KLPMED,Z.PRI)+FLD(.STRRS,Z.RSP) ;REJECT_REQ FLD(.LNRRS,Z.LEN)+FLD(KLPMED,Z.PRI) ;REJECT_RSP FLD(.LNDRQ,Z.LEN)+FLD(KLPDRG,Z.PRI)+FLD(.STDRS,Z.RSP) ;DISCONNECT_REQ FLD(.LNDRS,Z.LEN)+FLD(KLPMED,Z.PRI) ;DISCONNECT_RSP FLD(.LNCRQ,Z.LEN)+FLD(KLPHI,Z.PRI)+FLD(.STCRS,Z.RSP) ;CREDIT_REQ FLD(.LNCRS,Z.LEN)+FLD(KLPMED,Z.PRI) ;CREDIT_RSP SUBTTL Table K ;This table indicates, for a given incoming op code and current state ;of a connection, whether the event is legal, and if it is, what the new ;state and returned op code should be TABLEK: ;Received Connect_req FLD(.STORS,K.OP) ;Closed FLD(.STORS,K.OP)+FLD(.CSCRE,K.STAT) ;Listening K.ERR ;Connect request was sent (CONNECT_SENT) K.ERR ;Connect request was received (CONNECT_REC) K.ERR ;Connect response was received (CONNECT_ACK) K.ERR ;Accept request was sent (ACCEPT_SENT) K.ERR ;Reject request was sent (REJECT_SENT) K.ERR ;Connection is open (OPEN) K.ERR ;Disconnect request was sent (DISCONNECT_SENT) K.ERR ;Disconnect request received (DISCONNECT_REC) K.ERR ;Disconnect response received (DISCONNECT_ACK) K.ERR ;Waiting for disconnect response (DISCONNECT_MATCH) ;Received connect_response FLD(.CSCLO,K.STAT) ;Closed K.ERR ;Listening FLD(.CSCAK,K.STAT)+K.CHK ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect response was received (CONNECT_ACK) K.ERR ;Accept request was sent (ACCEPT_SENT) K.ERR ;Reject request was sent (REJECT_SENT) K.ERR ;Connection is open (OPEN) K.ERR ;Disconnect request was sent (DISCONNECT_SENT) K.ERR ;Disconnect request received (DISCONNECT_REC) K.ERR ;Disconnect response received (DISCONNECT_ACK) K.ERR ;Waiting for disconnect response (DISCONNECT_MATCH) ;Received accept-request FLD(.STARS,K.OP)+FLD(.CSCLO,K.STAT) ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received FLD(.STARS,K.OP)+FLD(.CSOPN,K.STAT) ;Connect_ACK K.ERR ;Accept_sent K.ERR ;Reject_sent K.ERR ;Open K.ERR ;Disconnect_sent K.ERR ;Disconnect_rec K.ERR ;Disconnect_ACK K.ERR ;disconnect_match ;Received accept_response FLD(.STDRQ,K.OP)+FLD(.CSCLO,K.STAT) ;CLosed (special case *) K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect_ACK FLD(.CSOPN,K.STAT)+K.CHK ;Accept_sent K.ERR ;Reject_sent K.ERR ;Open K.ERR ;Disconnect_sent K.ERR ;Disconnect_rec K.ERR ;Disconnect_ACK K.ERR ;disconnect_match ;Received reject_request FLD(.STRRS,K.OP)+FLD(.CSCLO,K.STAT) ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received FLD(.STRRS,K.OP)+FLD(.CSCLO,K.STAT) ;Connect_ACK K.ERR ;Accept_sent K.ERR ;Reject_sent K.ERR ;Open K.ERR ;Disconnect_sent K.ERR ;Disconnect_rec K.ERR ;Disconnect_ACK K.ERR ;disconnect_match ;Received reject_response FLD(.CSCLO,K.STAT) ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect_ACK K.ERR ;Accept_sent FLD(.CSCLO,K.STAT)+K.CHK ;Reject_sent K.ERR ;Open K.ERR ;Disconnect_sent K.ERR ;Disconnect_rec K.ERR ;Disconnect_ACK K.ERR ;disconnect_match ;Received disconnect_request FLD(.STDRS,K.OP)+FLD(.CSCLO,K.STAT) ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect_ACK K.ERR ;Accept_sent K.ERR ;Reject_sent FLD(.STDRS,K.OP)+FLD(.CSDRE,K.STAT) ;Open FLD(.STDRS,K.OP)+FLD(.CSDMC,K.STAT) ;Disconnect_sent K.ERR ;Disconnect_rec FLD(.STDRS,K.OP)+FLD(.CSCLO,K.STAT) ;Disconnect_ACK K.ERR ;disconnect_match ;received disconnect_response FLD(.CSCLO,K.STAT) ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect_ACK K.ERR ;Accept_sent K.ERR ;Reject_sent K.ERR ;Open FLD(.CSDAK,K.STAT)+K.CHK ;Disconnect_sent K.ERR ;Disconnect_rec K.ERR ;Disconnect_ACK FLD(.CSCLO,K.STAT)+K.CHK ;disconnect_match ;Received credit_request FLD(.STCRS,K.OP) ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect_ACK K.ERR ;Accept_sent K.ERR ;Reject_sent FLD(.STCRS,K.OP) ;Open FLD(.STCRS,K.OP) ;Disconnect_sent K.ERR ;Disconnect_rec FLD(.STCRS,K.OP) ;Disconnect_ACK K.ERR ;disconnect_match ;Received credit_response 0 ;Closed K.ERR ;Listening K.ERR ;Connect_sent K.ERR ;Connect_received K.ERR ;Connect_ACK K.ERR ;Accept_sent K.ERR ;Reject_sent K.CHK ;Open 0 ;Disconnect_sent K.CHK ;Disconnect_rec 0 ;Disconnect_ACK 0 ;disconnect_match SUBTTL Tables for state machine ;Table X - used when sysap calls SCA. For each event, provides new connection ;and block state. Also allows checking for invalid state DEFSTR X.ERR,TABLEX,0,1 ;Error flag DEFSTR X.BSTAT,TABLEX,17,17 ;New block state DEFSTR X.CSTAT,TABLEX,35,18 ;New connection state ;In some cases, the connection state is set when the request is sent, ;rather than when the sysap calls SCA. EV.CON==:0 ;SC.CON EV.LIS==:1 ;SC.LIS EV.ACC==:2 ;SC.ACC EV.REJ==:3 ;SC.REJ EV.DIS==:4 ;SC.DIS ;DEFSTRs for table Y. For each block state, provides op code to ;send and new connection state DEFSTR (Y.OP,TABLEY,17,18) DEFSTR (Y.STAT,TABLEY,35,18) ;Defstrs for table Z. For each op code to be sent, provides length, priority, ;and expected response DEFSTR Z.LEN,TABLEZ,17,18 DEFSTR Z.PRI,TABLEZ,20,3 DEFSTR Z.RSP,TABLEZ,35,15 ;Defstrs for table K. For each incoming packet, provides op code of response ;and new connection state. Also allows checking for protocol violations DEFSTR (K.ERR,TABLEK,0,1) DEFSTR (K.CHK,TABLEK,1,1) DEFSTR (K.OP,TABLEK,17,16) DEFSTR (K.STAT,TABLEK,35,18) SUBTTL INITIALIZATION ;ROUTINE TO INITIALIZE THE WORLD OF SCA. ;CALL: ; PUSHJ P,SCA ;RETURN: ; CPOPJ ALWAYS $XSENT (SC.INI::) ;EXTENDED HIGH SEG ROUTINE PUSHJ P,SAVPQ## ;SAVE ALL THE REGISTERS SETZM MFQCNT ;ZERO FREE QUEUE BUFFER COUNT SETZM TOPMFQ ;ZERO THE FLINK FOR THE FREE QUEUE XMOVEI T1,TOPMFQ ;GET A POINTER TO THE FLINK MOVEM T1,BOTMFQ ;INIT BLINK AS A POINTER TO FLINK SETZM DFQCNT ;ZERO DATAGRAM QUEUE BUFFER COUNT SETZM TOPDFQ ;ZERO THE FLINK FOR THE DATAGRAM QUEUE XMOVEI T1,TOPDFQ ;GET A POINTER TO THE FLINK MOVEM T1,BOTDFQ ;INIT BLINK AS A POINTER TO FLINK SETZM TOPDC ;ZERO THE FLINK FOR THE "DON'T CARE" QUEUE XMOVEI T1,TOPDC ;GET A POINTER TO THE FLINK MOVEM T1,BOTDC ;INIT BLINK AS A POINTER TO FLINK MOVEI T1,1 ;GET A PAGE PUSHJ P,PGRSKD## ; OF RESIDENT SPACE BUG. (HLT,SCANPC,SCASER,SOFT,,,) PUSH P,T1 ;SAVE ITS ADDRESS A BIT MOVE T2,T1 ;MOVE THE ADDRESS TO THE PROPER AC AOS T3,T1 ;GET ADDRESS +1 MOVEI T1,PG.BDY ;NUMBER OF WORDS TO MOVE SETZM (T2) ;ZERO THE FIRST ONE EXTEND T1,[XBLT] ;ZERO THE REMAINDER POP P,T1 ;GET PAGE ADDRESS BACK MOVEM T1,CIDTAB ;SAVE THE ADDRESS OF THE CID TABLE ADDI T1,PAGSIZ/2 ;POINT TO HALFWAY THROUGH THE TABLE MOVEM T1,UBTTAB ;SAVE AS ADDRESS OF THE UNIQUENESS TABLE RDTIME T1 ;READ TIME BASE (SUITABLE RANDOM NUMBER) LSH T2,^L-1-14 ;STRIP HIGH ORDER BITS LEAVING LOW LSH T2,-^L-1 ; BITS MODULO CONNECT-ID TABLE LENGTH AOS T2 ;MAKE IT IN RANGE 1-C%CIDL MOVEM T2,NXTIDX ;SAVE AS NEXT INDEX INTO CID TABLE SETZM CIDRFL ;NOT DOING CIDTAB RECYCLING YET SETONE UBITS,T1 ;SET ALL BITS IN THE UNIQUENESS BITS FIELD LSH T1,- ;RIGHT JUSTIFY SAID BITS MOVEM T1,UNQBTS ;STORE AS THE UNIQUENESS BITS AOS UNQBTS ;INIT AS ONE MORE THAN THE FIRST UNIQUENESS BITS SETZM UNQRFL ;NOT DOING CID BITS RECYCLING YET ;SET BUFFER THRESHOLDS AND SET INITIAL BUFFER LEVELS IFN FTOPS10,< MOVEI T1,M.CPU## ;NUMBER OF CPUS IN CONFIGURATION IMULM T1,DGTRSH ;ADJUST DATAGRAM THRESHOLD ON A PER-CPU BASIS IMULM T1,MGTRSH ;DITTO FOR MESSAGE THRESHOLD >; END IFN FTOPS10 SETZM PBCNT ;ZERO COUNT OF PATHS ONLINE PUSHJ P,SC.SBT ;SET MSG AND DG BUFFER THRESHOLDS MOVE T1,MINMSG ;GET MINIMUM NUMBER OF MSG BUFFERS IDIVI T1,C%MGPG ;MAKE NUMBER OF BUFFERS INTO NUMBER OF PAGES SKIPE T2 ;IS THERE A REMAINDER? AOS T1 ;YES, ROUND UP PUSHJ P,PGRSKD## ;GET THE BUFFER SPACE PUSHJ P,SCADIE ;IF WE CAN'T INIT, DIE MOVX T2,C%MGSZ ;GET THE BUFFER SIZE WE DESIRE PUSHJ P,SC.BBF ;BREAK THE SPACE INTO BUFFER-SIZED PIECES MOVEM T1,TOPMFQ ;SET UP THE POINTER TO THE TOP OF THE FREE QUEUE MOVEM T2,BOTMFQ ; AND THE POINTER TO THE BOTTOM OF THE FREE QUEUE ADDM T3,MFQCNT ;UPDATE THE COUNT OF BUFFERS IN THE QUEUE ADDM T3,TOTMGB ; AND THE TOTAL NUMBER OF BUFFERS CREATED MOVE T1,MINDG ;GET MINIMUM NUMBER OF DG BUFFERS IDIVI T1,C%DGPG ;MAKE NUMBER OF BUFFERS INTO NUMBER OF PAGES SKIPE T2 ;IS THERE A REMAINDER? AOS T1 ;YES, ROUND UP PUSHJ P,PGRSKD## ;GET THE BUFFER SPACE PUSHJ P,SCADIE ;IF WE CAN'T INIT, DIE MOVX T2,C%DGSZ ;GET THE BUFFER SIZE WE DESIRE PUSHJ P,SC.BBF ;BREAK THE SPACE INTO BUFFER-SIZED PIECES MOVEM T1,TOPDFQ ;SET UP THE POINTER TO THE TOP OF THE FREE QUEUE MOVEM T2,BOTDFQ ; AND THE POINTER TO THE BOTTOM OF THE FREE QUEUE ADDM T3,DFQCNT ;UPDATE THE COUNT OF BUFFERS IN THE QUEUE ADDM T3,TOTDGB ; AND THE TOTAL NUMBER OF BUFFERS CREATED ;SET UP THE SOFTWARE INCARNATION NUMBER PUSHJ P,BTAVAL## ;IS THE BOOTSTRAP AVAILABLE? TDZA T1,T1 ;NO, NO BIG DEAL, USE ZERO AOS T1,.BTSIN(T2) ;YES, BUMP AND GET NEW INCARNATION NUMBER MOVEM T1,SCASIN ;SAVE FOR FUTURE REFERENCE ;ALLOCATE THE NOTIFICATION TABLE MOVEI T1,1 ;WE ONLY NEED ONE BUFFER PUSHJ P,SC.ABF ;ALLOCATE ONE BUG. (HLT,SCANBN,SCASER,SOFT,,,) MOVEM T1,NOTTAB ;SAVE THE ADDRESS OF THE LIST ;CALL THE INITIALIZATION ROUTINE OF THE VARIOUS SYSAP'S MOVSI P1,-C%SYTL ;-VE LENGTH OF THE TABLE SKIPE INITAB(P1) ;IS THERE AN ENTRY FOR THIS INDEX? PUSHJ P,@INITAB(P1) ;YES, CALL THE ROUTINE AOBJN P1,.-2 ;LOOP FOR THE REMAINDER POPJ P, ;RETURN ;TABLE OF MONITOR SYSAP'S TO INITIALIZE DURING SCA INITIALIZATION. INITAB: IFIW MSCINI## ;MSCP DISK INTERFACE IFIW SCSINI## ;THE SCS. UUO C%SYTL==.-INITAB ;LENGTH OF INITIALIZATION TABLE ;A GENERAL BUG. FOR ERRORS DURING INITIALIZATION SCADIE: BUG. (HLT,SCACCI,SCASER,SOFT,,,) JRST SCADIE ;IN CASE SOMEONE TRIES TO CONTINUE ;A GENERAL BUG. FOR ERRORS WHICH "SHOULD NEVER HAPPEN" BUG. (HLT,SCAFOO,SCASER,SOFT,,,) SUBTTL SYSAP NOTIFICATION REQUEST ;ROUTINE CALLED BY A SYSAP TO ADD AN ENTRY TO THE NOTIFICATION TABLE. ;CALL: ; BLCAL. (SS.SNA,) ; ;WHERE: ; SS.ADR - ADDRESS OF ROUTINE TO CALL ; ;RETURN: ; CPOPJ ON ERRORS ; CPOPJ1 ON SUCCESS $XBSUB (SC.SNA::,) SAVEAC ;FREE UP A PAIR OF AC'S MOVE T1,NOTTAB ;GET THE ADDRESS OF THE NOTIFICATION TABLE MOVX T2,C%MGSZ-1 ;GET ITS SIZE MOVE T3,SS.ADR ;GET THE CALLER'S RECALL ADDRESS CIOFF ;PREVENT RACES SNA.01: SKIPN 0(T1) ;LOOK FOR AN OPEN SLOT IN THE TABLE JRST SNA.02 ;FOUND ONE SOSLE T2 ;ANY ROOM LEFT IN TABLE? AOJA T1,SNA.01 ;YES, LOOP FOR REMAINDER CION ;GIVE UP THE INTERLOCK BUG. (CHK,SCANLF,SCASER,SOFT,,,) RETBAD (.SCNRT) ;ERROR RETURN SNA.02: MOVEM T3,0(T1) ;SAVE THE ADDRESS IN THE TABLE ;LOOP OVER ALL PATH BLOCKS GIVING AN ONLINE CALLBACK FOR THOSE ;VC'S WHICH ARE OPEN. DO THIS WITH SCA INTERLOCK TO PREVENT ;MULTIPLE ONLINE CALLBACKS. MOVSI P1,-C%PBLL ;LENGTH OF PATH BLOCK LIST SNA.03: SKIPN P5,PBLIST(P1) ;IS THERE A PATH BLOCK HERE? JRST SNA.04 ;NO IFN FTMP,< MOVE T1,.PBCPU(P5) ;YES, WHICH CPU DOES IT LIVE ON? CAME T1,.CPCPN## ;"THIS" CPU? JRST SNA.04 ;NO >; END IFN FTMP LOAD T1,PBVCST,(P5) ;GET VC STATE CAIE T1,VC.OPN ;IS VC OPEN? JRST SNA.04 ;NO MOVX T1,.SSNCO ;SAY WHY WE ARE CALLING LOAD T2,PBPBI,(P5) ;GET THE PATH BLOCK INDEX PUSHJ P,@SS.ADR ;CALL THE SYSAP SNA.04: AOBJN P1,SNA.03 ;LOOP FOR REMAINING PATH BLOCKS PJRST CINPJ1 ;GIVE UP THE INTERLOCK AND SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL CONNECTION MANAGEMENT - CONNECT ;ROUTINE TO ALLOCATE A CONNECTION BLOCK AND REQUEST A CONNECTION. ;CALL: ; BLCAL. (SC.CON,) ; ;WHERE: ; SS.SPN - ADDRESS OF SOURCE PROCESS NAME ; SS.DPN - ADDRESS OF DESTINATION PROCESS NAME ; SS.PBI - PATH BLOCK INDEX OF PATH TO USE ; SS.MSC - MINIMUM SEND CREDIT ; SS.MRC - MINIMUM RECEIVE CREDIT ; SS.ADR - ADDRESS OF ROUTINE TO CALL ON CONDITION CHANGES ; SS.SID - SIX BITS OF CONNECT ID SET BY THE SYSAP ; SS.DTA - (OPTIONAL) ADDRESS OF SYSAP CONNECTION DATA ; SS.BFR - NUMBER OF BUFFERS TO QUEUE FOR MESSAGE RECEPTION ; SS.DGB - NUMBER OF DATAGRAM BUFFERS TO QUEUE ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ CONNECT ID $XBSUB (SC.CON::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS SKIPLE P5,SS.PBI ;GET PATH BLOCK INDEX CAIL P5,C%PBLL ;CHECK FOR INVALID RETBAD (.SCIPI) ;ERROR SKIPN P5,PBLIST-1(P5) ;GET PATH BLOCK ADDRESS RETBAD (.SCIPI) ;ERROR ;ALLOCATE A CONNECTION BLOCK AND INITIALIZE WITH COMMON DATA MOVE T1,SS.SID ;GET THE SYSAP CID BITS PUSHJ P,SC.ACB ;ALLOCATE AND INITIALIZE A CONNECTION BLOCK RETBAD () ;ERROR, PASS ALONG ERROR CODE MOVEM P5,.CBPBK(P1) ;STORE PATH BLOCK ADDRESS IN CB MOVEI T1,EV.CON ;EVENT IS CONNECT CALL PUSHJ P,SC.OUT ;GET NEW CONNECTION/BLOCK STATES BUG. (HLT,SCACFO,SCASER,SOFT,,,) DMOVE P2,T1 ;SAVE NEW STATES FOR LATER ;STORE ADDRESS FOR CALLING THE SYSAP INTO THE CONNECTION BLOCK MOVE T1,SS.ADR ;GET CONDITION CHANGE CALL ADDRESS MOVEM T1,.CBADR(P1) ;STORE ;CREDIT THRESHOLDS MOVE T1,SS.MSC ;GET THE MINIMUM SEND CREDIT STOR T1,CBMNSC,(P1) ;STORE ;STORE SOURCE AND DESTINATION PROCESS NAMES AND CONNECTION DATA MOVE T1,SS.SPN ;GET THE ADDRESS OF THE SOURCE PROCESS NAME MOVE T2,SS.DPN ; AND THE DESTINATION PROCESS NAME MOVE T3,SS.DTA ; AND THE ADDRESS OF THE CONNECTION DATA PUSHJ P,SC.SDM ;MOVE THE STRINGS AND DATA INTO THE CONNECT BLOCK ;STORE THE INITIAL NUMBER OF BUFFERS TO BE QUEUED MOVE T1,SS.BFR ;NUMBER OF MESSAGE BUFFERS STOR T1,CBIMB,(P1) ;STORE MOVE T1,SS.DGB ;NUMBER OF DATAGRAM BUFFERS STOR T1,CBIDB,(P1) ;STORE ;STORE THE CONNECTION STATE SKIPE P3 ;IF WE NEED TO CHANGE IT, STOR P3,CBCNST,(P1) ; STORE NEW STATE PUSHJ P,SC.LOK ;LOCK THE CONNECTION BLOCK ;LINK THE CONNECTION BLOCK ONTO THE PATH BLOCK LIST PUSHJ P,SC.LCB ;LINK THE CB JRST CON.E1 ;VC IS CLOSED, RETURN ERROR MOVE P3,.CBSCI(P1) ;GET THE CONNECT ID WHILE BLOCK IS LOCKED ;SEND THE REQUEST NOW, OR QUEUE IT FOR LATER SKIPN T1,P2 ;GET THE NEW BLOCK STATE JRST CON.02 ;NO CHANGE, SKIP THIS PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK PUSHJ P,SC.SNM ;SEND THE MESSAGE IF POSSIBLE SKIPA ;SKIP OVER CALL TO SC.ULK ;LOAD UP THE RETURNED DATA AND RETURN TO CALLER CON.02: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK MOVE T1,P3 ;GET THE SOURCE CONNECT ID JRST CPOPJ1## ;SKIP RETURN ;HERE WHEN VC IS CLOSED; DON'T OPEN THE CONNECTION CON.E1: MOVE P3,T1 ;SAVE THE ERROR CODE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK PUSHJ P,SC.RCB ;RELEASE THE CONNECTION BLOCK MOVE T1,P3 ;GET THE ERROR CODE BACK RETBAD () ;PASS ERROR ALONG TO CALLER ENDBS. ;END OF BLSUB. RANGE SUBTTL CONNECTION MANAGEMENT - LISTEN ;ROUTINE TO LISTEN FOR A CONNECTION. ;CALL: ; BLCAL. (SC.LIS,) ; ;WHERE: ; SS.SPN - ADDRESS OF SOURCE PROCESS NAME ; SS.DPN - ADDRESS OF DESTINATION PROCESS NAME ; SS.PBI - PATH BLOCK INDEX OF PATH TO USE ; SS.ADR - ADDRESS OF ROUTINE TO CALL ON CONDITION CHANGES ; SS.SID - SIX BITS OF CONNECT ID SET BY THE SYSAP ; SS.MSC - MINIMUM SEND CREDIT ; SS.MRC - MINIMUM RECEIVE CREDIT ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ CONNECT ID ; ;A ZERO IN SS.DPN AND -1 IN SS.PBI INDICATES A CONNECT FROM ANYONE IS ;ACCEPTABLE. A BYTE POINTER IN SS.DPN AND A PBI IN SS.PBI INDICATE ;A LISTEN FOR A PARTICULAR NODE ON A PARTICULAR PATH. $XBSUB (SC.LIS::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS SKIPE P5,SS.PBI ;GET PATH BLOCK INDEX (ALLOW -1 HERE) CAIL P5,C%PBLL ;CHECK FOR INVALID RETBAD (.SCIPI) ;ERROR JUMPG P5,LIS.01 ;PROCEED IF PBI SPECIFIED CAME P5,[-1] ;LISTEN TO ANYONE? RETBAD (.SCIPI) ;NO, ERROR SETZ P5, ;GET THE "DON'T CARE" PBI LIS.01: SKIPN P5,PBLIST-1(P5) ;GET PATH BLOCK ADDRESS RETBAD (.SCIPI) ;ERROR ;ALLOCATE A CONNECTION BLOCK AND INITIALIZE WITH COMMON DATA MOVE T1,SS.SID ;GET THE SYSAP CID BITS PUSHJ P,SC.ACB ;ALLOCATE A CONNECTION BLOCK RETBAD () ;ERROR, PASS ALONG ERROR CODE MOVEM P5,.CBPBK(P1) ;STORE PATH BLOCK ADDRESS IN CB MOVEI T1,EV.LIS ;EVENT IS LISTEN CALL PUSHJ P,SC.OUT ;GET NEW CONNECTION/BLOCK STATES BUG. (HLT,SCALFO,SCASER,SOFT,,,) DMOVE P2,T1 ;SAVE NEW STATES ;STORE ADDRESS FOR CALLING THE SYSAP INTO THE CONNECTION BLOCK MOVE T1,SS.ADR ;GET CONDITION CHANGE CALL ADDRESS MOVEM T1,.CBADR(P1) ;STORE ;CREDIT THRESHOLDS MOVE T1,SS.MSC ;GET MINIMUM SEND CREDIT STOR T1,CBMNSC,(P1) ;STORE ;MOVE THE SOURCE AND DESTINATION PROCESS NAMES MOVE T1,SS.SPN ;GET THE ADDRESS OF THE SOURCE PROCESS NAME MOVE T2,SS.DPN ; AND THE DESTINATION PROCESS NAME SETZ T3, ;THERE IS NO CONNECTION DATA ON A LISTEN PUSHJ P,SC.SDM ;MOVE THE STRINGS INTO THE CONNECT BLOCK ;STORE THE CONNECTION STATE SKIPE P3 ;IF WE NEED TO CHANGE IT, STOR P3,CBCNST,(P1) ; STORE NEW STATE PUSHJ P,SC.LOK ;LOCK THE CONNECTION BLOCK ;LINK THE CONNECTION BLOCK ONTO THE PATH BLOCK LIST PUSHJ P,SC.LCB ;LINK THE CONNECTION BLOCK JRST LIS.E1 ;VC IS CLOSED MOVE P3,.CBSCI(P1) ;GET THE CONNECT ID WHILE BLOCK IS LOCKED ;SEND THE REQUEST NOW, OR QUEUE IT FOR LATER JUMPL P5,LIS.02 ;SKIP THIS STUFF FOR "DON'T CARE" LISTENER SKIPN T1,P2 ;GET THE NEW BLOCK STATE JRST LIS.02 ;NO CHANGE, SKIP THIS PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK PUSHJ P,SC.SNM ;SEND THE MESSAGE IF POSSIBLE SKIPA ;SKIP OVER CALL TO SC.ULK ;LOAD UP THE RETURNED DATA AND RETURN TO CALLER LIS.02: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK MOVE T1,P3 ;GET SOURCE CONNECT ID JRST CPOPJ1## ;SKIP RETURN ;HERE ON AN ERROR RETURN FROM SC.LCB LIS.E1: MOVE P3,T1 ;SAVE THE ERROR CODE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK PUSHJ P,SC.RCB ;RETURN THE CONNECTION BLOCK MOVE T1,P3 ;GET THE ERROR CODE BACK RETBAD () ;PASS ERROR ALONG TO CALLER ENDBS. ;END OF BLSUB. RANGE SUBTTL CONNECTION MANAGEMENT - ACCEPT ;ROUTINE TO ACCEPT A REQUEST FOR A CONNECTION. ;CALL: ; BLCAL. (SC.ACC,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.DTA - ADDRESS OF INITIAL CONNECTION DATA (OR ZERO) ; SS.BFR - NUMBER OF BUFFERS TO BE QUEUED FOR MESSAGE RECEPTION ; SS.DGB - NUMBER OF BUFFERS TO QUEUE FOR DATAGRAM RECEPTION ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.ACC::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET THE CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR MOVEI T1,EV.ACC ;EVENT IS ACCEPT CALL PUSHJ P,SC.OUT ;GET NEW CONNECTION/BLOCK STATES RETBAD (,) ;PASS ALONG THE ERROR DMOVE P2,T1 ;SAVE NEW STATES ;STORE OPTIONAL DATA TO BE SENT TO THE OTHER END SKIPN T2,SS.DTA ;IS THERE ANY DATA TO MOVE? JRST ACC.01 ;NO MOVX T1,C%CDLW ;YES, GET ITS LENGTH IN WORDS XMOVEI T3,.CBDTA(P1) ;DESTINATION ADDRESS IN CB EXTEND T1,[XBLT] ;COPY THE DATA ;STORE THE INITIAL NUMBER OF BUFFERS TO BE QUEUED ACC.01: MOVE T1,SS.BFR ;NUMBER OF MESSAGE BUFFERS STOR T1,CBIMB,(P1) ;STORE MOVE T1,SS.DGB ;NUMBER OF DATAGRAM BUFFERS STOR T1,CBIDB,(P1) ;STORE ;STORE THE CONNECTION STATE SKIPE P3 ;IF WE NEED TO CHANGE IT, STOR P3,CBCNST,(P1) ; STORE NEW STATE ;SEND THE REQUEST NOW, OR QUEUE IT FOR LATER SKIPN T1,P2 ;GET THE NEW BLOCK STATE JRST ACC.02 ;NO CHANGE, SKIP THIS PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK PUSHJ P,SC.SNM ;SEND THE MESSAGE IF POSSIBLE JRST CPOPJ1## ;SKIP RETURN ACC.02: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL CONNECTION MANAGEMENT - REJECT ;ROUTINE TO REJECT A CONNECTION REQUEST. ;CALL: ; BLCAL. (SC.REJ,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.RJR - REJECT REASON CODE ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.REJ::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR ;SEE IF THE CURRENT STATE IS CORRECT, AND GET NEW CONNECTION AND BLOCK STATES MOVEI T1,EV.REJ ;EVENT IS REJECT CALL PUSHJ P,SC.OUT ;SORT OUT THE CONNECT/BLOCK STATES RETBAD (,) ;PASS ALONG THE ERROR ;COPY CALLER'S REASON INTO THE CONNECTION BLOCK MOVE T3,SS.RJR ;GET THE REJECT REASON STOR T3,CBSDRE,(P1) ;STORE IN CB ;STORE CONNECTION AND BLOCK STATES AND SEND MESSAGE, IF ANY SKIPE T2 ;SKIP IF NO STATE CHANGE STOR T2,CBCNST,(P1) ; ELSE STORE NEW CONNECT STATE JUMPE T1,REJ.01 ;JUMP IF THERE ISN'T A NEW BLOCK STATE PUSHJ P,SC.SCA ;SET THE NEW BLOCK STATE AND QUEUE MESSAGE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK PUSHJ P,SC.SNM ;SEND THE MESSAGE IF POSSIBLE JRST CPOPJ1## ;SKIP RETURN REJ.01: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL CONNECTION MANAGEMENT - DISCONNECT ;ROUTINE TO CLOSE A CONNECTION. ;CALL: ; BLCAL. (SC.DIS,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.DIR - DISCONNECT REASON ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.DIS::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS CIOFF ;DON'T LET STATE CHANGE UNTIL WE CAN LOCK CB MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CSC ;CHECK FOR VALIDITY RETBAD (,) ;PASS ALONG THE ERROR ;SEE IF THE CURRENT STATE IS CORRECT, AND GET NEW CONNECTION AND BLOCK STATES MOVEI T1,EV.DIS ;EVENT IS DISCONNECT CALL PUSHJ P,SC.OUT ;SORT OUT THE CONNECT/BLOCK STATES RETBAD (,) ;PASS ALONG THE ERROR DMOVE P2,T1 ;SAVE NEW STATES ;COPY CALLER'S REASON INTO THE CONNECTION BLOCK MOVE T1,SS.DIR ;GET THE DISCONNECT REASON STOR T1,CBSDRE,(P1) ;STORE IN CB ;WE'VE DONE ALL WE CAN IF SOMEONE HAS THE CB LOCKED MOVX T1,CB.DIS ;SET THIS BIT IF WE HAVE TO WAIT PUSHJ P,SC.HNR ;SEE IF LOCK IS LOCKED JRST CINPJ1 ;AT INTERRUPT LEVEL AND SOMEONE HAS THE LOCK ;WE GOT THE LOCK. IF THE OLD STATE WAS "LISTEN" INDICATE PROTOCOL COMPLETE LOAD T1,CBCNST,(P1) ;GET CONNECT STATE CAIE T1,.CSLIS ;LISTEN? JRST DIS.01 ;NO MOVEI T1,.CSCLO ;FORCE ITS STATE TO "CLOSED" STOR T1,CBCNST,(P1) ;... PUSHJ P,SC.PTC ;DECLARE PROTOCOL COMPLETE JRST CINPJ1 ;TURN PI'S BACK ON AND SKIP RETURN ;STORE CONNECTION AND BLOCK STATES AND SEND MESSAGE, IF ANY DIS.01: SKIPE P3 ;SKIP IF NO STATE CHANGE STOR P3,CBCNST,(P1) ; ELSE STORE NEW CONNECT STATE SKIPN T1,P2 ;IS THERE A NEW BLOCK STATE? PJRST CINPJ1 ;NO, TURN PI'S BACK ON AND SKIP RETURN PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE CION ;TURN PI'S BACK ON PUSHJ P,SC.SNM ;SEND THE MESSAGE IF POSSIBLE JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE ;ROUTINE TO FINISH FUNCTION OF SC.DIS WHEN UNLOCKING A CONNECTION BLOCK. ;CALL: ; P1/ ADDRESS OF CONNECTION BLOCK ; P5/ ADDRESS OF PATH BLOCK ; PUSHJ P,SC.FN2 ;RETURN: ; CPOPJ ALWAYS ;THIS ROUTINE IS CALLED WHEN THE OWNER OF A CONNECTION BLOCK IS ABOUT TO ;UNLOCK IT AND THE CB.DIS BIT WAS SET. THE CB IS STILL LOCKED, AND WE ;RETURN IT IN THAT CONDITION. SINCE THE BLOCK IS STILL LOCKED, WE DON'T ;CALL SC.SNM, BUT INSTEAD SET A BIT SO THE UNLOCKER WILL DO SO. SC.FN2: MOVX T1,CB.DIS ;GET THE BIT ANDCAM T1,.CBFLG(P1) ;SHOW THIS HAS COMPLETED ;IF OLD STATE WAS "LISTEN", INDICATE PROTOCOL IS COMPLETE LOAD T1,CBCNST,(P1) ;GET OLD STATE CAIE T1,.CSLIS ;LISTENING? JRST FN2.01 ;NO MOVEI T1,.CSCLO ;FORCE ITS STATE TO "CLOSED" STOR T1,CBCNST,(P1) ;... PUSHJ P,SC.PTC ;DECLARE PROTOCOL COMPLETE PJRST SC.SRB ;SET REAP BIT AND RETURN ;CONNECTION STATE MAY HAVE CHANGED SINCE SC.DIS WAS FIRST CALLED. ;MAKE SURE A DISCONNECT IS STILL LEGAL, AND GET NEW STATES. FN2.01: MOVEI T1,EV.DIS ;EVENT IS DISCONNECT CALL PUSHJ P,SC.OUT ;GET NEW STATES BUG. (HLT,SCAFN2,SCASER,SOFT,,,) ;STORE CONNECTION AND BLOCK STATES. IF NEW BLOCK STATE IS NON-ZERO, ;WE WANT TO SEND A DISCONNECT_REQUEST. QUEUE THE BLOCK, AND FLAG THE ;UNLOCK CODE TO CALL SC.SNM. SKIPE T2 ;ZERO MEANS NO CHANGE STOR T2,CBCNST,(P1) ;STORE NEW CONNECTION STATE JUMPE T1,CPOPJ## ;RETURN IF NO NEW STATE PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE MOVX T1,CB.SNM ;INDICATE CALL TO SC.SNM WAS DEFERRED IORM T1,.CBFLG(P1) ;... POPJ P, ;RETURN SUBTTL DATAGRAM SERVICE - SEND DATAGRAM ;ROUTINE TO SEND A DATAGRAM. ;CALL: ; BLCAL. (SC.SDG,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.FLG - FLAG WORD ; SS.LDG - LENGTH OF DATAGRAM ; SS.ADG - ADDRESS OF DATAGRAM ; SS.PRI - PRIORITY FOR PACKET SEND ; SS.PTH - PATH TO SEND THE PACKET ON ; 0 - AUTO PATH SELECT ; 1 - PATH A ; 2 - PATH B ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.SDG::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR LOAD T1,CBCNST,(P1) ;GET THE CONNECT STATE CAIE T1,.CSOPN ;IS THE CONNECTION OPEN? RETBAD (.SCSWS,) ;NO, RETURN AN ERROR MOVE T1,SS.LDG ;GET THE LENGTH OF THE DATAGRAM MOVX T2,F.SPM ;GET THE HIGH DENSITY FLAG TDNE T2,SS.FLG ;IS IT SET IN CALLER'S FLAGS? JRST SDG.01 ;YES ADDI T1,C%OVHD ;ADD OVERHEAD SIZE IN BYTES CAILE T1,C%BYTD ;IS THE DATAGRAM LARGER THAN I CAN SEND? RETBAD (.SCPTL,) ;YES, GIVE AN ERROR JRST SDG.02 ;CONTINUE SDG.01: ADDI T1,C%OVHW ;ADD OVERHEAD SIZE IN WORDS CAILE T1,C%WORD ;IS THE DATAGRAM LARGER THAN I CAN SEND? RETBAD (.SCPTL,) ;YES, GIVE AN ERROR SDG.02: MOVEM T1,SS.LDG ;STORE FOR LATER PPD CALL ;ADD THE SCA HEADER TO THE MESSAGE WE HAVE BEEN PASSED MOVE P2,SS.ADG ;GET ADDRESS IN STANDARD REGISTER SETZRO MH$CDT,(P2) ;ZERO THE CREDIT FIELD MOVEI P3,.STADG ;MESSAGE TYPE = DATAGRAM STOR P3,MH$MSG,(P2) ;STORE MOVE T1,.CBDCI(P1) ;GET DESTINATION CONNECT ID MOVEM T1,.MHDCI(P2) ;STORE MOVE T1,.CBSCI(P1) ;GET SOURCE CONNECT ID MOVEM T1,.MHSCI(P2) ;STORE ;IF THE SYSAP WANTS THE BUFFER BACK, COUNT THIS AMONG ITS QUEUED BUFFERS MOVX T1,F.RTB ;PACKET RETURN STATUS FLAG TDNE T1,SS.FLG ;IS SCA GETTING THIS PACKET BACK? AOSA .CBNPO(P1) ;YES, INCREMENT COUNT OF OUTSTANDING PACKETS AOS .CBDGR(P1) ;NO, COUNT THIS AS QUEUED FOR INCOMING DATAGRAM ;CALL THE PORT DRIVER WITH THE DATA PUSHJ P,SC.ROU ;SWAP THE HEADER FOR OUTPUT LOAD T1,PBPBI,(P5) ;GET PATH BLOCK INDEX BLCAL. (PPDSDG##,) ;SEND THE PACKET JRST SDG.E1 ;HANDLE PPD FAILURE AOS SNDTAB(P3) ;INCREMENT SEND COUNT FOR THIS TYPE OF PACKET PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SUCCESS SDG.E1: MOVX T2,F.RTB ;DID WE BUMP THE PENDING PACKET COUNT? TDNN T2,SS.FLG ;... JRST SDG.E2 ;NO SOSGE .CBNPO(P1) ;YES, PACKET SEND FAILED, FIX COUNT BUG. (HLT,SCANP1,SCASER,SOFT,<.CBNPO has gone negative>,,) JRST SDG.E3 ;JOIN COMMON EXIT SDG.E2: MOVEI T1,1 ;NO, WE COUNTED THIS AS QUEUED FOR INPUT PUSHJ P,SC.ALD ;GET A BUFFER FROM SCA JRST SDG.E3 ;COULDN'T LOAD T2,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDQDB##,) ;GIVE THE BUFFERS TO THE PPD SDG.E3: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR ENDBS. ;END OF BLSUB. RANGE SUBTTL MESSAGE SERVICE - SEND MESSAGE ;ROUTINE TO SEND A MESSAGE. ;CALL: ; BLCAL. (SC.SMG,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.FLG - FLAG WORD ; SS.LMG - LENGTH OF MESSAGE ; SS.AMG - ADDRESS OF MESSAGE ; SS.PRI - PRIORITY FOR PACKET SEND ; SS.TSH - SEND CREDIT THRESHOLD ; SS.PTH - PATH TO SEND THE PACKET ON ; 0 - AUTO PATH SELECT ; 1 - PATH A ; 2 - PATH B ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.SMG::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK THE CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR LOAD T1,CBCNST,(P1) ;GET THE CONNECT STATE CAIE T1,.CSOPN ;IS THE CONNECTION OPEN? RETBAD (.SCSWS,) ;NO, RETURN AN ERROR MOVE T1,SS.LMG ;GET THE LENGTH OF THE MESSAGE MOVX T2,F.SPM ;GET THE HIGH DENSITY FLAG TDNE T2,SS.FLG ;IS IT SET IN CALLER'S FLAGS? JRST SMG.01 ;YES ADDI T1,C%OVHD ;ADD OVERHEAD SIZE IN BYTES CAILE T1,C%BYTM ;IS THE MESSAGE LARGER THAN I CAN SEND? RETBAD (.SCPTL,) ;YES, GIVE AN ERROR JRST SMG.02 ;CONTINUE SMG.01: ADDI T1,C%OVHW ;ADD OVERHEAD SIZE IN WORDS CAILE T1,C%WORM ;IS THE MESSAGE LARGER THAN I CAN SEND? RETBAD (.SCPTL,) ;YES, GIVE AN ERROR SMG.02: MOVEM T1,SS.LMG ;STORE FOR LATER PPD CALL SOS T1,.CBSCD(P1) ;DECREMENT SEND CREDIT CAML T1,SS.TSH ;DO WE HAVE MORE THAN THRESHOLD? JRST SMG.03 ;YES AOS .CBSCD(P1) ;NO, PUT IT BACK WHERE WE FOUND IT MOVX T1,CB.NNC ;SET THE FLAG TO NOTIFY ON CREDIT GAIN IORM T1,.CBFLG(P1) ;... RETBAD (.SCNEC,) ;RETURN WITH ERROR CODE SMG.03: CIOFF ;PREVENT RACES MOVX T1,F.RTB ;DOES THE SYSAP WANT HIS BUFFER BACK? TDNE T1,SS.FLG ;... JRST SMG.04 ;YES AOS T2,.CBPRC(P1) ;NO, INCREMENT PENDING RECEIVE CREDIT SKIPG T2 ;HAD WE BEEN WAITING TO CANCEL SOME? AOS .CBRTC(P1) ;YES, COUNT THIS AS RECEIVE CREDIT SMG.04: SKIPG T2,.CBPRC(P1) ;IS PENDING RECEIVE CREDIT NOW POSITIVE? JRST [SETZ T2, ;NO, NO CREDIT IN THE PACKET JRST SMG.05] ;CONTINUE ADDM T2,.CBRCD(P1) ;YES, ADD THIS INTO RECEIVE CREDIT SETZM .CBPRC(P1) ;IT'S NO LONGER PENDING SMG.05: CION ;OK TO INTERRUPT ;ADD THE SCA HEADER TO THE MESSAGE WE HAVE BEEN PASSED ;CREDIT COUNT STILL IN T2 MOVE P2,SS.AMG ;GET ADDRESS IN STANDARD REGISTER STOR T2,MH$CDT,(P2) ;STORE THE CREDIT COUNT MOVEI P3,.STAMG ;MESSAGE TYPE = MESSAGE STOR P3,MH$MSG,(P2) ;STORE MOVE T1,.CBDCI(P1) ;GET DESTINATION CONNECT ID MOVEM T1,.MHDCI(P2) ;STORE MOVE T1,.CBSCI(P1) ;GET SOURCE CONNECT ID MOVEM T1,.MHSCI(P2) ;STORE ;IF THE SYSAP WANTS THE BUFFER BACK, COUNT THIS AMONG ITS QUEUED BUFFERS MOVX T1,F.RTB ;PACKET RETURN STATUS FLAG TDNE T1,SS.FLG ;IS SCA GETTING THIS PACKET BACK? AOS .CBNPO(P1) ;YES, INCREMENT COUNT OF OUTSTANDING PACKETS ;CALL THE PORT DRIVER WITH THE DATA PUSHJ P,SC.ROU ;SWAP THE HEADER FOR OUTPUT LOAD T1,PBPBI,(P5) ;GET PATH BLOCK INDEX BLCAL. (PPDSMS##,) ;SEND THE PACKET JRST SMG.E1 ;HANDLE PPD FAILURE AOS SNDTAB(P3) ;BUMP THE SENT MESSAGE COUNT ;WE MAY HAVE INCREMENT RETURN_CREDIT. IF SO, RECLAIM A BUFFER. PUSHJ P,SC.GCB ;GET A CANCELED BUFFER, IF ANY PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SUCCESS ;HERE ON AN ERROR FROM THE PORT DRIVER SMG.E1: AOS .CBSCD(P1) ;WE DIDN'T USE THE SEND CREDIT AFTER ALL CIOFF ;PREVENT RACES LOAD T2,MH$CDT,(P2) ;GET CREDIT FIELD BACK FROM THE PACKET ADDM T2,.CBPRC(P1) ;TURN IT BACK INTO PENDING CREDIT MOVNS T2 ;GET NEGATIVE COUNT ADDM T2,.CBRCD(P1) ;UPDATE THE CREDIT COUNT IN THE CB CION ;OK TO INTERRUPT MOVX T2,F.RTB ;DID WE BUMP THE PENDING PACKET COUNT? TDNN T2,SS.FLG ;... JRST SMG.E2 ;NO SOSGE .CBNPO(P1) ;YES, PACKET SEND FAILED, FIX THE COUNT BUG. (HLT,SCANP2,SCASER,SOFT,<.CBNPO has gone negative>,,) JRST SMG.E3 ;JOIN COMMON EXIT SMG.E2: MOVEI T1,1 ;WE COUNTED THIS AS QUEUED FOR INPUT PUSHJ P,SC.ABF ;GET A BUFFER FROM SCA JRST SMG.E3 ;ERROR LOAD T2,PBPBI,(P5) ;GET PATH BLOCK INDEX BLCAL. (PPDQMB##,) ;GIVE THE BUFFER TO THE PORT SMG.E3: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR ENDBS. ;END OF BLSUB. RANGE SUBTTL DATAGRAM SERVICE - RECEIVE DATAGRAM ;ROUTINE TO QUEUE BUFFERS FOR DATAGRAM RECEPTION. ;CALL: ; BLCAL. (SC.RDG,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.NUM - NUMBER OF BUFFERS TO QUEUE IF SS.ADR IS ZERO ; IGNORED IF SS.ADR IS NON-ZERO ; SS.ADR - ADDRESS OF THE BUFFER TO QUEUE ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.RDG::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET THE CONNECTION ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK THE CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR MOVEI T2,1 ;ASSUME CALLER IS SUPPLYING THE BUFFER SKIPE T1,SS.ADR ;IS THERE A BUFFER WE NEED TO QUEUE? JRST RDG.01 ;YES MOVE T1,SS.NUM ;GET THE NUMBER THEY DESIRE PUSHJ P,SC.ALD ;ALLOCATE THEM RETBAD (,) ;IT WAS A NICE TRY SKIPA ;DON'T ZERO FLINK RDG.01: SETZM (T1) ;ENSURE LINK TO NEXT BUFFER IS ZERO PUSHJ P,SC.QDB ;QUEUE THE BUFFERS TO THE PORT PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL MESSAGE SERVICE - RECEIVE MESSAGE ;ROUTINE TO QUEUE BUFFERS FOR MESSAGE RECEPTION. ;CALL: ; BLCAL. (SC.RMG,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.NUM - NUMBER OF BUFFERS TO QUEUE IF SS.ADR IS ZERO ; IGNORED IF SS.ADR IS NON-ZERO ; SS.ADR - ADDRESS OF THE BUFFER TO QUEUE ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.RMG::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET THE USER'S CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK THE CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR MOVEI T2,1 ;ASSUME CALLER IS SUPPLYING THE BUFFER SKIPE T1,SS.ADR ;IS THERE A BUFFER WE NEED TO QUEUE? JRST RMG.01 ;YES MOVE T1,SS.NUM ;GET THE NUMBER THEY DESIRE PUSHJ P,SC.ABF ;ALLOCATE THEM RETBAD (,) ;IT WAS A NICE TRY SKIPA ;DON'T ZERO FLINK RMG.01: SETZM (T1) ;ENSURE LINK TO NEXT BUFFER IS ZERO ;IF WE HAD BEEN WAITING TO CANCEL SOME BUFFERS, INCREMENT RETURN CREDIT ;FOR AS MANY BUFFERS AS POSSIBLE MOVE P3,T2 ;SAVE THE NUMBER OF BUFFERS LOAD T2,PBPBI,(P5) ;GET PATH BLOCK INDEX BLCAL. (PPDQMB##,) ;GIVE THE BUFFER TO THE PORT CIOFF ;PREVENT RACES MOVE T2,.CBPRC(P1) ;SAVE CURRENT PENDING RECEIVE CREDIT ADDM P3,.CBPRC(P1) ;UPDATE TO INCLUDE ANY NEW BUFFERS JUMPGE T2,RMG.02 ;IF ALWAYS POSITIVE, NOTHING ELSE TO DO SKIPG .CBPRC(P1) ;PREVIOUSLY NEGATIVE, IS IT STILL? JRST [ADDM P3,.CBRTC(P1) ;YES, RECLAIM ALL THE BUFFERS, THEN JRST RMG.02] ;CONTINUE MOVMS T2 ;NO, TAKE ONLY THE NUMBER WE WANTED ADDM T2,.CBRTC(P1) ;... ;WE MAY WANT TO SEND A CREDIT_REQUEST. SC.CDT WILL QUEUE THE CONNECTION ;BLOCK TO THE PATH BLOCK WORK QUEUE IF WE NEED TO SEND THE REQUEST. IF ;SO, WE MUST CALL SC.SNM TO DO THE SENDING AFTER WE UNLOCK THE CONNECTION ;BLOCK. RMG.02: CION ;OK TO INTERRUPT PUSHJ P,SC.GCB ;GET CANCELED BUFFER, IF ANY SETO P3, ;ASSUME WE'LL NEED TO SEND SOMETHING PUSHJ P,SC.CDT ;QUEUE CREDIT REQUEST IF NEEDED SETZ P3, ;DON'T NEED TO SEND A MESSAGE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK SKIPE P3 ;SKIP IF WE DON'T NEED TO SEND A MESSAGE PUSHJ P,SC.SNM ;SEND NEXT MESSAGE JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL DATAGRAM SERVICE - CANCEL RECEIVE DATAGRAM ;ROUTINE TO DEQUEUE A DATAGRAM BUFFER. ;CALL: ; BLCAL. (SC.CRD,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.NUM - NUMBER OF BUFFERS TO DEQUEUE ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.CRD::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR SKIPE T1,SS.NUM ;GET NUMBER OF BUFFERS DESIRED JRST CRD.01 ;GO GET THEM PUSHJ P,SC.ULK ;NOTHING TO DO, UNLOCK CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN CRD.01: SOSL .CBDGR(P1) ;DECREMENT COUNT OF QUEUED BUFFERS JRST CRD.02 ;MORE LEFT, CONTINUE AOS .CBDGR(P1) ;DIDN'T HAVE ENOUGH, RESTORE COUNT RETBAD (.SCNEB,) ;RETURN FAILURE CRD.02: LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDDDB##,) ;DEQUEUE A DATAGRAM BUFFER RETBAD (,) ;PASS ALONG THE ERROR PUSHJ P,SC.RLD ;RETURN THE BUFFER TO THE SCA POOL SOSLE SS.NUM ;DECREMENT COUNT TO DEQUEUE JRST CRD.01 ;MORE TO DO, LOOP TO DEQUEUE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL MESSAGE SERVICE - CANCEL RECEIVE MESSAGE ;ROUTINE TO DEQUEUE A MESSAGE BUFFER. ;CALL: ; BLCAL. (SC.CRM,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.NUM - NUMBER OF BUFFERS TO DEQUEUE ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.CRM::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR MOVN T1,SS.NUM ;GET -VE NUMBER OF BUFFERS JUMPN T1,CRM.01 ;JUMP IF WE NEED MORE PUSHJ P,SC.ULK ;NOTHING TO DO, UNLOCK CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ;DECREMENT PENDING RECEIVE CREDIT BY THE NUMBER THE SYSAP WANTS BACK. ;IF WE HAD A POSITIVE COUNT, WE CAN CLAIM SOME (MAYBE ALL) OF THE ;BUFFERS WITHOUT ASKING PERMISSION. CRM.01: CIOFF ;PREVENT RACES MOVE T2,.CBPRC(P1) ;SAVE CURRENT PENDING RECEIVE COUNT ADDM T1,.CBPRC(P1) ;DECREMENT IT BY NUMBER DESIRED JUMPLE T2,CRM.02 ;IF ALREADY NEGATIVE, CAN'T RECLAIM ANY SKIPGE .CBPRC(P1) ;DID WE HAVE ENOUGH ALREADY PENDING? JRST [ADDM T2,.CBRTC(P1) ;NO, CLEAM THE ONES WE HAD PENDING JRST CRM.02] ;CONTINUE MOVE T1,SS.NUM ;YES, GET NUMBER WE WANTED ADDM T1,.CBRTC(P1) ; AND COUNT ALL AS RETURN CREDIT ;WE MAY NEED TO SEND A CREDIT_REQUEST. IF SO, SC.CD5 WILL QUEUE ;THE PACKET. WE MUST CAUSE IT TO BE SENT AFTER UNLOCKING THE ;CONNECTION BLOCK. CRM.02: CION ;OK TO INTERRUPT PUSHJ P,SC.GCB ;GET CANCELED BUFFER, IF ANY SETO P3, ;ASSUME WE'LL NEED TO SEND SOMETHING PUSHJ P,SC.CD5 ;QUEUE CREDIT REQUEST IF NEEDED SETZ P3, ;DON'T NEED TO SEND A MESSAGE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK SKIPE P3 ;SKIP IF WE DON'T NEED TO SEND A MESSAGE PUSHJ P,SC.SNM ;SEND THE NEXT MESSAGE JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL DMA SERVICE - MAP A BUFFER ;ROUTINE TO DEFINE A BUFFER FOR THE PORT TO USE. ;CALL: ; BLCAL. (SC.MAP,) ; ;WHERE: ; SS.BLK - ADDRESS OF FIRST ENTRY IN A CHAIN OF BUFFER DESCRIPTOR BLOCKS ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ BUFFER NAME $CSUB ;ENTRY POINT SC.MAP::PJRST PPDMAP## ;CALLING CONVENTIONS ARE THE SAME FOR PPDMAP SUBTTL DMA SERVICE - UNMAP A BUFFER ;ROUTINE TO UNMAP A NAMED BUFFER. ;CALL: ; BLCAL. (SC.UMP,) ; ;WHERE: ; SS.NAM - BUFFER NAME RETURNED BY A CALL TO SC.MAP ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $CSUB ;ENTRY POINT SC.UMP::PJRST PPDUMP## ;CALLING CONVENTIONS ARE THE SAME FOR PPDUMP SUBTTL DMA SERVICE - REQUEST DATA ;ROUTINE TO REQUEST THE START OF DATA TRANSMISSION BY A REMOTE PORT. ;CALL: ; BLCAL. (SS.REQ,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.SNM - SENDER'S BUFFER NAME ; SS.RNM - RECEIVER'S BUFFER NAME ; SS.SOF - BYTE OFFSET INTO SENDER'S BUFFER ; SS.ROF - BYTE OFFSET INTO RECEIVER'S BUFFER ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.REQ::,) SETO T1, ;INDICATE REQUEST JRST SC.SNR ;JOIN COMMON CODE SUBTTL DMA SERVICE - SEND DATA ;ROUTINE TO SEND BLOCK DATA FROM A NAMED BUFFER. ;CALL: ; BLCAL. (SS.REQ,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.SNM - SENDER'S BUFFER NAME ; SS.RNM - RECEIVER'S BUFFER NAME ; SS.SOF - BYTE OFFSET INTO SENDER'S BUFFER ; SS.ROF - BYTE OFFSET INTO RECEIVER'S BUFFER ; ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS $XBSUB (SC.SND::,) SETZ T1, ;INDICATE SEND SC.SNR: PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE P3,T1 ;SAVE SEND/REQUEST FLAG MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR LOAD T1,CBCNST,(P1) ;GET THE CONNECT STATE CAIE T1,.CSOPN ;IS THE CONNECTION OPEN? RETBAD (.SCSWS,) ;NO, GIVE AN ERROR ;DON'T SEND IF WE DON'T HAVE ENOUGH SEND CREDIT SOS T1,.CBSCD(P1) ;DECREMENT SEND CREDIT CAIL T1,1 ;DO WE HAVE MORE THAN THE THRESHOLD? JRST SNR.01 ;YES AOS .CBSCD(P1) ;NO, PUT IT BACK MOVX T1,CB.NNC ;INDICATE WAITING FOR CREDIT NOTIFY IORM T1,.CBFLG(P1) ;... RETBAD (.SCNEC,) ;RETURN "NOT ENOUGH CREDIT" ;SEND/REQUEST THE DATA SNR.01: JUMPN P3,SNR.02 ;JUMP IF REQUEST BLCAL. (PPDSND##,) JRST SNR.E1 ;ERROR JRST SNR.03 ;SUCCESS SNR.02: BLCAL. (PPDREQ##,) JRST SNR.E1 ;ERROR SNR.03: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ;HERE IF SEND FAILED; CAN ONLY HAPPEN IF VC CLOSED SNR.E1: AOS .CBSCD(P1) ;BUMP THE CREDIT, WE DIDN'T SEND AFTER ALL PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR ENDBS. ;END OF BLSUB. RANGE SUBTTL STATE POLLING - CONNECT STATE POLL ;ROUTINE TO RETURN THE STATUS OF A CONNECTION. ;CALL: ; BLCAL. (SC.CSP,) ; ;WHERE: ; SS.CID - CONNECT ID ; SS.ADR - ADDRESS OF BLOCK IN WHICH TO RETURN DATA ; ;RETURN: ; CPOPJ ON ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ CONNECT ID ; T2/ ADDRESS OF BLOCK IN WHICH DATA WAS RETURNED $XBSUB (SC.CSP::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE T1,SS.CID ;GET CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK CONNECTION BLOCK RETBAD () ;PASS ALONG THE ERROR MOVE T1,SS.ADR ;GET ADDRESS OF WHERE TO RETURN DATA LOAD T2,CBCNST,(P1) ;GET THE CONNECT STATE STOR T2,CDCST,(T1) ;STORE MOVE T2,.CBDCI(P1) ;GET THE DESTINATION CONNECT ID MOVEM T2,.CDDCI(T1) ;STORE DMOVE T2,.CBDPN(P1) ;GET FIRST AND SECOND WORD OF DESTINATION NAME DMOVEM T2,.CDDPN(T1) ;STORE DMOVE T2,.CBDPN+2(P1) ;GET THIRD AND FOURTH WORD OF DESTINATION NAME DMOVEM T2,.CDDPN+2(T1) ;STORE MOVE T2,.CBPBK(P1) ;GET PATH BLOCK ADDRESS LOAD T2,PBDPN,(T2) ;GET NODE NUMBER MOVEM T2,.CDNOD(T1) ;STORE LOAD T2,CBDDRE,(P1) ;GET DESTINATION DISCONNECT REASON STOR T2,CDDREA,(T1) ;STORE LOAD T2,CBSDRE,(P1) ;GET SOURCE DISCONNECT REASON STOR T2,CDSREA,(T1) ;STORE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK MOVE T2,T1 ;COPY BLOCK ADDRESS TO T2 MOVE T1,SS.CID ;GET CONNECT ID JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL CONFIGURATION SERVICES - RETURN DESTINATION CONNECT ID ;ROUTINE TO RETURN THE DESTINATION CONNECT ID FOR A CONNECTION. ;CALL: ; BLCAL. (SC.DCI,) ; ;WHERE: ; SS.CID - SOURCE CONNECT ID ; ;RETURN: ; CPOPJ ALWAYS $XBSUB (SC.DCI::,) SAVEAC ;SAVE THE AC'S SC.CAL TROUNCES MOVE T1,SS.CID ;GET THE CONNECT ID PUSHJ P,SC.CAL ;CHECK VALIDITY AND LOCK BLOCK RETBAD () ;RETURN FAILURE MOVE T1,.CBDCI(P1) ;GET THE DESTINATION CONNECT ID PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL CONFIGURATION SERVICES ;ROUTINE TO RETURN CONFIGURATION INFORMATION FOR A SYSTEM. ;CALL: ; BLCAL. (SC.RSB,) ; ;WHERE: ; SS.SBI - SYSTEM BLOCK INDEX ; ;RETURN: ; CPOPJ ON ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ ADDRESS OF RETURNED CONFIGURATION BLOCK ;NOTE: IT IS THE CALLER'S RESPONSIBILITY TO RETURN THE SPACE ;USED BY THE CONFIGURATION BLOCK (I.E., CALL GIVSWS). $XBSUB (SC.RSB::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED AC'S WE USE HERE SKIPLE T1,SS.SBI ;GET THE CALLER'S SBI, CHECK FOR -VE OR ZERO CAIL T1,C%SBLL ;OR OUT OF RANGE RETBAD (.SCISI) ;ERROR SKIPN P4,SBLIST-1(T1) ;GET SYSTEM BLOCK ADDRESS RETBAD (.SCISI) ;ERROR MOVEI T2,.RSLEN ;LENGTH OF THE BLOCK PUSHJ P,GETSWS## ;GET THE SPACE RETBAD () ;NO FREE CORE, ERROR MOVE P1,T1 ;COPY ADDRESS OF BLOCK TO A SAFER AC LOAD T1,SBPBI,(P4) ;GET FIRST PATH BLOCK INDEX STOR T1,RSPBI,(P1) ;STORE LOAD T1,SBDPC,(P4) ;GET DESTINATION PORT COUNT STOR T1,RSDPC,(P1) ;STORE LOAD T1,SBDPN,(P4) ;GET THE DESTINATION PORT NUMBER STOR T1,RSDPN,(P1) ;STORE MOVEI T1,.RSBLE-.RSDSA ;NUMBER OF WORDS TO MOVE XMOVEI T2,.SBDSA(P4) ;SOURCE ADDRESS XMOVEI T3,.RSDSA(P1) ;DESTINATION ADDRESS EXTEND T1,[XBLT] ;MOVE THE DATA MOVE T1,P1 ;GET THE BLOCK ADDRESS WHERE ADVERTISED JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE ;ROUTINE TO RETURN CONFIGURATION INFORMATION FOR A PATH. ;CALL: ; BLCAL. (SC.RPB,) ; ;WHERE: ; SS.PBI - PATH BLOCK INDEX ; ;RETURN: ; CPOPJ ON ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ ADDRESS OF RETURNED CONFIGURATION BLOCK ;NOTE: IT IS THE CALLER'S RESPONSIBILITY TO RETURN THE SPACE ;USED BY THE CONFIGURATION BLOCK (I.E., CALL GIVSWS). $XBSUB (SC.RPB::,) PUSHJ P,SAVP## ;SAVE THE PRESERVED AC'S WE USE HERE SKIPLE T1,SS.PBI ;GET THE CALLER'S PBI, CHECK FOR -VE OR ZERO CAIL T1,C%PBLL ;OR OUT OF RANGE RETBAD (.SCIPI) ;ERROR SKIPN P5,PBLIST-1(T1) ;GET PATH BLOCK ADDRESS RETBAD (.SCIPI) ;ERROR MOVEI T2,.RPLEN ;LENGTH OF BLOCK WE DESIRE PUSHJ P,GETSWS## ;GET THE SPACE RETBAD () ;NO FREE SPACE, ERROR MOVE P1,T1 ;COPY ADDRESS TO SAFER AC LOAD T1,PBVCST,(P5) ;GET VIRTUAL CIRCUIT STATE STOR T1,RPVCST,(P1) ;STORE LOAD T1,PBDPN,(P5) ;GET DESTINATION PORT NUMBER STOR T1,RPDPN,(P1) ;STORE LOAD T1,PBNPI,(P5) ;GET NEXT PATH BLOCK INDEX STOR T1,RPNPI,(P1) ;STORE LOAD T1,PBSBI,(P5) ;GET SYSTEM BLOCK INDEX STOR T1,RPSBI,(P1) ;STORE MOVEI T1,4 ;NUMBER OF WORDS OF PORT CHARACTERISTICS XMOVEI T2,.PBDPC(P5) ;SOURCE ADDRESS XMOVEI T3,.RPDPC(P1) ;DESTINATION ADDRESS EXTEND T1,[XBLT] ;MOVE THE DATA MOVE T1,P1 ;GET THE BLOCK ADDRESS WHERE ADVERTISED JRST CPOPJ1## ;SKIP RETURN ENDBS. ;END OF BLSUB. RANGE SUBTTL ENTRY FROM PORT DRIVER - NODE ONLINE ;ROUTINE CALLED BY THE PHYSICAL PORT DRIVER WHEN A NODE COMES ONLINE. ;CALL: ; BLCAL. (SC.ONL,) ; ;WHERE: ; SS.PBI - PATH BLOCK INDEX OF NODE ONLINE ; ;RETURN: ; CPOPJ ALWAYS $XBSUB (SC.ONL::,) PUSHJ P,SAVP## ;SAVE THE P REGISTERS SKIPLE T1,SS.PBI ;CHECK FOR VALID PBI CAIL T1,C%PBLL ;... XCT SCAFOO ;INVALID PBI? SKIPN P5,PBLIST-1(T1) ;GET THE PATH BLOCK ADDRESS XCT SCAFOO ;DUH? SETZM .PBFLG(P5) ;CLEAR ANY RESIDUAL FLAGS SETZM .PBTIM(P5) ;INDICATE WE HAVE NOT SPOKEN TO THE PB YET ;SEE IF THERE ARE ENOUGH BUFFERS AROUND OR IF WE NEED MORE. ;ALSO UPDATE THE MINIMUM NUMBER OF BUFFERS WE SHOULD HAVE. AOS T1,PBCNT ;COUNT ONLINE PATHS CAILE T1,C%PBLL ;SANITY CHECK THE RESULT XCT SCAFOO ;DUH? PUSHJ P,SC.SBT ;SET BUFFER THRESHOLDS BASED ON NEW PATH COUNT MOVE T1,MINMSG ;NUMBER OF MESSAGE BUFFERS WE SHOULD HAVE MOVE T2,MINDG ;NUMBER OF DATAGRAM BUFFERS WE SHOULD HAVE CAMG T1,MFQCNT ;DO WE HAVE ENOUGH MESSAGE BUFFERS? CAMLE T2,DFQCNT ;YES, DO WE HAVE ENOUGH DATAGRAM BUFFERS? AOS CIBUF ;ASK SC.DEF TO RUN ;ALLOCATE A BUFFER FOR INCOMING MESSAGES (GIVE TO THE PORT), AND ;A BUFFER FOR OUTGOING MESSAGES (QUEUE TO PATH BLOCK). MOVEI T1,1 ;GET ONE BUFFER PUSHJ P,SC.ABF ; FOR THE OUTBOUND BUFFER JRST ONL.E1 ;ERROR MOVEM T1,.PBOBB(P5) ;STORE ITS ADDRESS MOVEI T1,1 ;GET ANOTHER MESSAGE BUFFER PUSHJ P,SC.ABF ;ALLOCATE IT JRST ONL.E1 ;NOT AVAILABLE, DIE BLCAL. (PPDQMB##,) ;QUEUE THE MESSAGE BUFFERS IFN FTINFO,< PUSHJ P,PTHONL ;TELL CTY PATH IS ONLINE >; END IFN FTINFO ;LOOP OVER ENTRIES IN THE NOTIFICATION TABLE TELLING EVERYONE A ;NEW PATH HAS COME ONLINE. MOVE P1,NOTTAB ;GET THE ADDRESS OF THE NOTIFICATION TABLE ONL.01: SKIPN 0(P1) ;IS THERE AN ENTRY? POPJ P, ;NO, WE ARE DONE MOVX T1,.SSNCO ;REASON = NODE CAME ONLINE MOVE T2,SS.PBI ;GET THE PATH BLOCK INDEX PUSHJ P,@0(P1) ;CALL THE SYSAP ABOUT THIS NEW NODE JFCL ;CATCH SILLY SKIP RETURNS AOJA P1,ONL.01 ;LOOP FOR THE REMAINING SYSAP'S ONL.E1: BUG. (HLT,SCASCQ,SCASER,SOFT,,,) SUBTTL ENTRY FROM PORT DRIVER - NODE OFFLINE ;ROUTINE CALLED BY THE PHYSICAL PORT DRIVER WHEN A NODE GOES OFFLINE. ;CALL: ; BLCAL. (SC.ERR,) ; ;WHERE: ; SS.PBI - PATH BLOCK INDEX ; ;RETURN: ; CPOPJ ALWAYS $XBSUB (SC.ERR::,) PUSHJ P,SAVP## ;SAVE THE P REGISTRS SKIPLE T1,SS.PBI ;CHECK FOR VALID PBI CAIL T1,C%PBLL ;... XCT SCAFOO ;FOO SKIPN P5,PBLIST-1(T1) ;GET THE PATH BLOCK ADDRESS XCT SCAFOO ;FOO CIOFF ;PREVENT RACES ;SEE IF WE ALREADY COUNTED THIS PATH AS GOING OFFLINE. IF NOT, SET ;THE FLAG SAYING WE DID, AND DECREMENT THE COUNT OF PATHS ONLINE. MOVX T1,PB.OFL ;GET THE OFFLINE FLAG TDNN T1,.PBFLG(P5) ;HAS THIS PATH BEEN MARKED OFFLINE? JRST ERR.01 ;NO LOAD T1,PBDPN,(P5) ;YES, GET NODE NUMBER BUG. (CHK,SCAOF2,SCASER,SOFT,,<>,) CION ;OK TO INTERRUPT JRST ERR.09 ;LET PPD OPEN THE VC AGAIN ERR.01: IORM T1,.PBFLG(P5) ;SET THE FLAG FOR LATER SOSL PBCNT ;DECREMENT THE ONLINE PATH COUNT JRST ERR.02 ;ALL IS WELL BUG. (CHK,SCANSC,SCASER,SOFT,,,) SETZM PBCNT ;TRY TO RECOVER ;LOOP OVER ALL CONNECTIONS ON THE PB AND MARK THEM AS CLOSED. ERR.02: SKIPN P1,.PBFCB(P5) ;GET THE ADDRESS OF THE FIRST CB JRST ERR.06 ;NO CONNECTS TO MARK ERR.03: MOVX T1,CB.CVC ;INDICATE VC WAS CLOSED IORM T1,.CBFLG(P1) ;... MOVX T1,CB.ERR ;IS THE CB LOCKED? PUSHJ P,SC.HNR ;... JRST [AOS .PBCLC(P5) ;YES, COUNT ANOTHER LOCKED CB JRST ERR.05] ;SKIP TO NEXT LOAD T2,CBCNST,(P1) ;GET CURRENT STATE MOVEI T1,.CSCLO ;NEW STATE WILL BE "CLOSED" STOR T1,CBCNST,(P1) ;STORE AS NEW CONNECT STATE CAIN T2,.CSCLO ;WAS IT ALREADY CLOSED? JRST ERR.04 ;YES MOVX T1,.SSPBC ;GET THE NOTIFICATION CODE MOVE T2,.CBSCI(P1) ;GET SOURCE CONNECT ID PUSHJ P,@.CBADR(P1) ;NOTIFY THE SYSAP OF THE DISASTER ERR.04: SETZM .CBRQC(P1) ;WE'LL NEVER GET CREDIT_RESPONSE NOW SO ; CLEAR THIS SO WE CAN REAP PUSHJ P,SC.PTC ;DECLARE PROTOCOL AS COMPLETE ERR.05: SKIPE P1,.CBANB(P1) ;IS THERE A NEXT CONNECT BLOCK JRST ERR.03 ;YES, LOOP FOR IT ERR.06: PUSHJ P,SC.SBT ;SET NEW BUFFER THRESHOLDS BASED ON ACTIVE PATHS ;IF THERE WERE PENDING CONNECT_REQUEST OR ACCEPT_REQUEST MESSAGES THAT ;REQUIRED BUFFERS, THIS PATH MAY HAVE BEEN MARKED AS STUCK. THESE MESSAGES ;WILL NO LONGER BE SENT. CLEAR THE "STUCK" BIT, AND GET RID OF THE QUEUE ;OF CONNECTION BLOCKS NEEDED TO SEND REQUESTS. MOVE T1,SS.PBI ;GET PATH BLOCK INDEX MOVE T1,BITTBL##(T1) ;GET THE BIT ANDCAM T1,PBSTUK ;AND SHOW THIS PATH IS NO LONGER STUCK ON BUFFERS XMOVEI T1,.PBTWQ(P5) ;GET THE TOP OF THE WORK QUEUE MOVEM T1,.PBBWQ(P5) ;INIT TAIL AS POINTER TO HEAD SETZM .PBTWQ(P5) ;INIT HEAD AS ZERO CION ;OK TO DIDDLE STUFF AGAIN IFN FTINFO,< PUSHJ P,PTHOFL ;TELL THE CTY >; END IFN FTINFO ;WHEN PATH CAME ONLINE WE GOT 2 BUFFERS FROM THE SCA POOL FOR SENDING ;AND RECEIVING SCS CONTROL MESSAGES. GIVE THEM BACK TO SCA NOW. SETZ P2, ;GET A ZERO EXCH P2,.PBOBB(P5) ;IS THE OUTBOUND BUFFER STILL AROUND? JUMPE P2,ERR.07 ;NO MOVE T1,P2 ;YES, GET ITS ADDRESS PUSHJ P,SC.RBF ;RETURN IT TO THE SCA POOL ERR.07: BLCAL. (PPDDMB##,) ;DEQUEUE A MESSAGE BUFFER JRST ERR.08 ;COULDN'T, TELL THE POOR BLOKE PUSHJ P,SC.RBF ;RETURN THE BUFFER TO SCA JUMPN P2,ERR.09 ;DID WE HAVE AN OUTBOUND BUFFER? BLCAL. (PPDDMB##,) ;DEQUEUE A MESSAGE BUFFER JRST ERR.08 ;COULDN'T, TELL THE POOR BLOKE PUSHJ P,SC.RBF ;RETURN THE BUFFER TO SCA JRST ERR.09 ;SKIP PAST THE ERROR ;THE PORT RAN OUT OF BUFFERS. IN THEORY, WE PUT TWO BUFFERS ON THE QUEUE ;WHEN THIS PATH CAME ONLINE, SO WE SHOULD BE ABLE TO TAKE TWO OFF. ERR.08: LOAD T1,PBDPN,(P5) ;GET THE DESTINATION NODE BUG. (CHK,SCANMB,SCASER,SOFT,,<>,) ;THE -20 GIVES EVERYONE A .SSPBC CALLBACK HERE WITH A CID OF ZERO. ERR.09: SKIPN .PBCLC(P5) ;ANY LOCKED CONNECTIONS? JRST ERR.10 ;NO, SO OK TO OPEN THE VC MOVX T1,PB.OVC ;INDICATE WAITING TO OPEN IORM T1,.PBFLG(P5) ;... POPJ P, ;RETURN ERR.10: BLCAL. (PPDOVC##,) ;ASK PPD TO OPEN THE VC POPJ P, ;RETURN ENDBS. ;END OF BLSUB. RANGE ;ROUTINE TO FINISH FUNCTION OF SC.ERR WHEN UNLOCKING A CONNECTION BLOCK. ;CALL: ; P1/ ADDRESS OF CONNECTION BLOCK ; P5/ ADDRESS OF PATH BLOCK ; PUSHJ P,SC.FN1 ;RETURN: ; CPOPJ ALWAYS SC.FN1: MOVX T1,CB.ERR ;GET THE BIT ANDCAM T1,.PBFLG(P5) ;SHOW THIS HAS COMPLETED LOAD T2,CBCNST,(P1) ;GET CURRENT STATE MOVEI T1,.CSCLO ;NEW STATE WILL BE "CLOSED" STOR T1,CBCNST,(P1) ;STORE AS NEW STATE CAIN T2,.CSCLO ;WAS IT ALREADY CLOSED? JRST FN1.01 ;YES MOVX T1,.SSPBC ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID CIOFF ;MAKE SURE SYSAP IS NOT INTERRUPTED PUSHJ P,@.CBADR(P1) ;NOTIFY THE SYSAP OF THE DISASTER CION ;OK TO INTERRUPT AGAIN FN1.01: PJRST SC.PTC ;DECLARE PROTOCOL COMPLETE AND RETURN SUBTTL ENTRY FROM PORT DRIVER - DMA OPERATION COMPLETE ;HERE WHEN THE PORT NOTICED THAT A DMA OPERATION HAS COMPLETED. ;CALL: ; BLCAL. () ; ;WHERE: ; SS.BNM - BUFFER NAME ; SS.CID - CONNECT ID ; ;RETURN: ; CPOPJ ALWAYS $XBSUB (SC.DMA::,) PUSHJ P,SAVE1## ;SAVE P1 MOVE T1,SS.CID ;GET THE CONNECT ID PUSHJ P,SC.CSC ;CHECK FOR VALIDITY POPJ P, ;ERROR LOAD T1,CBCNST,(P1) ;GET THE CONNECT STATE CAIE T1,.CSOPN ;IS IT OPEN? POPJ P, ;NO, IGNORE IT AOS .CBSCD(P1) ;GIVE BACK THE CREDIT WE TOOK AT THE START MOVX T1,.SSDMA ;SAY WHY WE ARE CALLING MOVE T2,SS.CID ;GET THE CONNECT ID MOVE T3,SS.BNM ;GET THE BUFFER NAME PUSHJ P,@.CBADR(P1) ;NOTIFY SYSAP OF HIS DMA COMPLETION ;WE'VE JUST INCREMENTED SEND CREDIT. IF THE SYSAP HAD BEEN TOLD ;"NOT ENOUGH CREDITS" ON A PREVIOUS ATTEMPT AT SENDING, WE NEED ;TO TELL HIM TO TRY AGAIN. MOVX T1,CB.NNC ;DOES SYSAP NEED NOTIFICATION? TDNN T1,.CBFLG(P1) ;... POPJ P, ;NO, RETURN NOW ANDCAM T1,.CBFLG(P1) ;YES, BUT IT DOESN'T ANY LONGER MOVX T1,.SSCIA ;SAY WHY WE ARE CALLING MOVE T2,SS.CID ;GET THE CONNECT ID MOVE T3,.CBSCD(P1) ;SHOW THE SEND CREDIT MOVE T4,.CBRCD(P1) ;SHOW THE RECEIVE CREDIT PJRST @.CBADR(P1) ;CALL THE SYSAP AND RETURN SUBTTL ENTRY FROM PORT DRIVER - MESSAGE AVAILABLE INTERRUPT ;ROUTINE CALLED FROM THE PPD WHEN IT HAS A MESSAGE IT DECIDED SCA ;NEEDS TO SEE. THE VARIOUS TYPES WHICH GET HERE ARE: ; 1. APPLICATION DATAGRAMS (PASSED TO SYSAP) ; 2. APPLICATION MESSAGES (PASSED TO SYSAP) ; 3. SCA CONTROL MESSAGES (PROCESSED BY SCASER) ;CALL: ; BLCAL. (SC.INT,) ; ;WHERE: ; SS.PBI - PATH BLOCK INDEX ; SS.PKT - PACKET ADDRESS ; SS.LEN - PACKET LENGTH ; SS.FLG - FLAGS ; ;RETURN: ; CPOPJ ALWAYS $XBSUB (SC.INT::,) PUSHJ P,SAVP## ;SAVE THE P REGISTERS SKIPLE T1,SS.PBI ;CHECK FOR VALID PBI CAIL T1,C%PBLL ;... XCT SCAFOO ;FOO SKIPN P5,PBLIST-1(T1) ;GET THE PATH BLOCK ADDRESS XCT SCAFOO ;FOO MOVE P2,SS.PKT ;GET PACKET ADDRESS PUSHJ P,SC.RIN ;SWAP THE HEADER BYTES MOVE T2,SS.FLG ;GET THE FLAGS TXNN T2,F.RSP ;IS THIS A REMOTE PACKET? JRST INT.RP ;YES ;BUFFER IS BEING RETURNED AFTER A SEND. RETURN IT TO THE POOL ;OR GIVE IT TO THE SYSAP. LOAD T3,MH$MSG,(P2) ;GET THE PACKET TYPE CAIE T3,.STADG ;IS THIS AN APPLICATION DATAGRAM CAIN T3,.STAMG ; OR MESSAGE? JRST INT.MS ;HANDLE THE RETURN OF A SYSAP BUFFER ;BUFFER HAD BEEN SENT BY SCA. THIS SHOULD NEVER HAPPEN. MOVE T1,P2 ;GET THE PACKET ADDRESS PJRST SC.RBF ;RETURN THE BUFFER AND RETURN TO PPD ;HERE TO RETURN A LOCALLY GENERATED SYSAP MESSAGE BUFFER TO ITS OWNER INT.MS: $LDCID P1,.MHSCI(P2) ;GET THE CB ADDRESS FROM THE CID SOSGE .CBNPO(P1) ;DECREMENT THE COUNT OF OUTSTANDING PACKETS BUG. (HLT,SCANP3,SCASER,SOFT,<.CBNPO has gone negative>,,) MOVX T1,.SSMSC ;TELL THE SYSAP WHY WE ARE CALLING MOVE T2,.MHSCI(P2) ;INDICATE WHICH CONNECTION MOVE T3,P2 ;GET THE PACKET ADDRESS PJRST @.CBADR(P1) ;CALL THE SYSAP ABOUT HIS BUFFER AND RETURN TO PPD ;HERE ON A REMOTELY GENERATED PACKET. THE MESSAGE HANDLERS ARE ;CALLED WITH THE FOLLOWING AC'S SET UP: ; ; T1/ FLAGS ; T2/ PACKET LENGTH ; P1/ CB ADDRESS ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ;ALL MESSAGE HANDLERS RETURN CPOPJ ALWAYS INT.RP: MOVE T1,DATE## ;GET NOW MOVEM T1,.PBTIM(P5) ;STORE WHEN LAST MESSAGE WAS RECEIVED MOVX T1,PB.TMG ;CLEAR TIMED MESSAGE FLAG ANDCAM T1,.PBFLG(P5) ;... MOVE T1,SS.FLG ;GET THE FLAGS MOVE T2,SS.LEN ;GET THE PACKET LENGTH LOAD T3,MH$MSG,(P2) ;GET THE MESSAGE TYPE CAIL T3,.STLST ;IS THE PACKET ONE WE KNOW ABOUT? JRST INT.E1 ;NO AOS RECTAB(T3) ;COUNT THE MESSAGE WE JUST RECEIVED PJRST @DSPTAB(T3) ;DISPATCH BASED ON MESSAGE TYPE AND RETURN ;HERE WHEN A BAD MESSAGE WAS RECEIVED FROM THE REMOTE SCA. INT.E1: LOAD T1,PBDPN,(P5) ;GET THE DESTINATION NODE NUMBER MOVE T2,.CBSCI(P1) ;GET CONNECT ID BUG. (CHK,SCABMT,SCASER,SOFT,,<,,>,) PJRST SC.CVC ;CLOSE THE VC AND RETURN ENDBS. ;END OF BLSUB. RANGE ;DISPATCH TABLE FOR RECEIVED PACKETS DSPTAB: $DISPA ;GENERATE THE DISPATCH TABLE SUBTTL MESSAGE HANDLERS - CONNECT REQUEST SC.ORQ: PUSHJ P,SC.INC ;DO CHECK ON VC CLOSED JRST SC.RIB ;IGNORE THIS PACKET PUSHJ P,SC.SCM ;SEARCH FOR A CONNECTION MATCH JRST ORQ.NM ;NO MATCH, SAY SO ;COPY DATA FROM THE PACKET INTO THE CONNECTION BLOCK LOAD T1,MH$CDT,(P2) ;GET THE CREDIT FROM THE MESSAGE HADER MOVEM T1,.CBSCD(P1) ;STORE AS SEND CREDIT MOVE T1,.MHSCI(P2) ;GET THE SOURCE CONNECT ID MOVEM T1,.CBDCI(P1) ;STORE IN CB AS DESTINATION CONNECT ID LOAD T1,MH$MCR,(P2) ;GET THE MINIMUM CREDIT FROM THE MESSAGE HEADER STOR T1,CBMNRC,(P1) ;STORE MOVEI T1,C%PNLW ;NUMBER OF WORDS TO MOVE XMOVEI T2,.MGSPN(P2) ;SOURCE XMOVEI T3,.CBDPN(P1) ;DESTINATION EXTEND T1,[XBLT] ;MOVE THE DESTINATION PROCESS NAME MOVEI T1,C%PNLW ;NUMBER OF WORDS TO MOVE XMOVEI T2,.MGSDT(P2) ;SOURCE XMOVEI T3,.CBDTA(P1) ;DESTINATION EXTEND T1,[XBLT] ;MOVE THE CONNECTION DATA ;BUILD A CONNECT_RESPONSE MOVEI T1,.CMCMT ;GET THE "MATCH" STATUS STOR T1,MH$STS,(P2) ;STORE IN MESSAGE MOVEI T1,.STORS ;GET THE CONNECT_RESPONSE MESSAGE TYPE PUSHJ P,SC.RSP ;SEND THE RESPONSE JRST SC.RIB ;FAILED, RETURN BUFFER TO FREE QUEUE ;UPDATE CONNECTION STATE TO CONNECT_RECEIVED MOVEI T1,.CSCRE ;GET THE CONNECT_RECEIVED STATE STOR T1,CBCNST,(P1) ;SET THE NEW STATE ;NOW TELL THE SYSAP SOMEONE CONNECTED TO HIS LISTEN MOVX T1,.SSCTL ;TELL THE REASON MOVE T2,.CBSCI(P1) ;SOURCE CONNECT ID XMOVEI T3,.CBDTA(P1) ;POINT TO THE CONNECTION DATA PJRST @.CBADR(P1) ;CALL THE SYSAP AND RETURN ;HERE IF WE DIDN'T FIND A MATCH FOR THE PROCESS NAME. BUILD THE ;RESPONSE HERE BECAUSE WE WANT TO ZERO THE SOURCE CONNECT ID AND ;THE STANDARD ROUTINE WON'T LIKE THAT. ORQ.NM: SETZRO MH$CDT,(P2) ;ZERO THE CREDIT FIELD OF THE MESSAGE HEADER MOVEI T1,.STORS ;GET THE CONNECT_RSP MESSAGE TYPE STOR T1,MH$MSG,(P2) ;STORE MOVE T1,.MHSCI(P2) ;GET THE SOURCE CONNECT ID MOVEM T1,.MHDCI(P2) ;"RETURN TO SENDER ..." SETZM .MHSCI(P2) ; "ADDRESS UNKNOWN ..." SETZRO MH$MCR,(P2) ;ZERO MINIMUM CREDIT FIELD FOR SAFETY MOVEI T1,.CMCNM ;SAY WE FOUND NO CONNECTION MATCH STOR T1,MH$STS,(P2) ;PUT THE STATUS INFO IN THE MESSAGE HEADER PUSHJ P,SC.PAK ;SEND THE RESPONSE JRST SC.RIB ;FAILED, RETURN BUFFER TO THE FREE QUEUE POPJ P, ;RETURN SUBTTL MESSAGE HANDLERS - CONNECT RESPONSE SC.ORS: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND RETURN ;IF STATE WE CLOSED, OUR END DISCONNECTED AFTER REQUESTING CONNECTION. ;DON'T NEED TO UPDATE STATE. IF OTHER SIDE SAID "MATCH", WAIT FOR THE ;ACCEPT OF REJECT TO COME IN. IF IT SAID "NO MATCH", WE'RE DONE. LOAD T2,CBCNST,(P1) ;GET THE OLD STATE LOAD T3,MH$STS,(P2) ;GET THE MATCH/NO MATCH CODE CAIE T2,.CSCLO ;WAS IT CLOSED ALREADY? JRST ORS.01 ;NO CAIE T3,.CMCMT ;IT WAS CLOSED, IS THIS A MATCH? PUSHJ P,SC.PTC ;NO, END OF PROTOCOL, THEN JRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER ;HERE WHEN STATE WASN'T CLOSED; THIS IS THE NORMAL CASE. IF THE OTHER ;SIDE SAID "NO MATCH", TELL THE SYSAP THE CONNECTION FAILED, AND MARK ;PROTOCOL COMPLETE. OTHERWISE, UPDATE THE STATE AND WAIT FOR THE ACCEPT ;OR REJECT. ORS.01: CAIE T3,.CMCMT ;NOT CLOSED, IS THIS A MATCH? JRST ORS.02 ;NO MOVE T2,.MHSCI(P2) ;GET SOURCE CONNECT ID FROM PACKET MOVEM T2,.CBDCI(P1) ;STORE AS DESTINATION CONNECT ID STOR T1,CBCNST,(P1) ;STORE AS THE NEW CONNECTION STATE JRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER ORS.02: MOVEI T1,.CSCLO ;NO MATCH, NEW STATE IS CLOSED STOR T1,CBCNST,(P1) ;STORE THE NEW STATE MOVX T1,.SSCRA ;SAY WHY WE ARE CALLING THE SYSAP MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID SETZ T3, ;SAY WE WERE REJECTED LOAD T4,MH$STS,(P2) ;GET REASON CODE FOR REJECTION PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP PUSHJ P,SC.PTC ;DECLARE PROTOCOL COMPLETE JRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER SUBTTL MESSAGE HANDLERS - ACCEPT REQUEST SC.ARQ: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT MOVE P4,T1 ;SAVE NEW STATE MOVE P3,T2 ;SAVE OPCODE OF RESPONSE ;IF THE CONNECTION IS CURRENTLY CLOSED, THE SYSAP CHANGED ITS MIND ;AFTER SENDING A CONNECT_REQUEST. LOAD T1,CBCNST,(P1) ;IF THE CURRENT STATE IS CLOSED, WE WANT TO CAIN T1,.CSCLO ; TO SEND AN ACCEPT_RESPONSE WITH THE JRST ARQ.NG ; "NO MATCH" CODE ;COPY DATA FROM THE PACKET INTO THE CONNECT BLOCK ;THE NEXT TWO LINES ARE REQUIRED TO TALK TO VMS - THE CONNECT ID ;THEY SEND US WITH THE CONNECT_RESPONSE ISN'T USEFUL. FOR NOW, ;THE COPY THAT REMAINS IN SC.ORS IN CASE THERE'S SOMETHING WRONG ;WITH THIS NEW APPROACH. MOVE T1,.MHSCI(P2) ;GET SOURCE CONNECT ID MOVEM T1,.CBDCI(P1) ;STORE IN CONNECT BLOCK LOAD T1,MH$CDT,(P2) ;GET THE CREDIT FIELD ADDM T1,.CBSCD(P1) ;UPDATE THE SEND CREDIT LOAD T1,MH$MCR,(P2) ;GET THE MINIMUM CREDIT STOR T1,CBMNRC,(P1) ;STORE AS MINIMUM RECEIVE CREDIT MOVEI T1,C%SDTW ;NUMBER OF WORDS TO MOVE XMOVEI T2,.MGSDT(P2) ;SOURCE ADDRESS OF CONNECT DATA XMOVEI T3,.CBDTA(P1) ;DESTINATION ADDRESS OF CONNECT DATA EXTEND T1,[XBLT] ;MOVE THE CONNECT DATA ;BUILD AND SEND THE ACCEPT_RESPONSE MESSAGE MOVX T1,.CMCMT ;GET THE UNIVERSAL MATCH CODE STOR T1,MH$STS,(P2) ;STORE MOVE T1,P3 ;GET THE OPCODE PUSHJ P,SC.RSP ;SEND THE RESPONSE JRST SC.RIB ;FAILED, RETURN THE BUFFER TO THE FREE QUEUE ;SET NEW STATE STOR P4,CBCNST,(P1) ;STORE CONNECTION STATE RETURNED ABOVE ;NOTIFY THE SYSAP ABOUT WHAT HAS HAPPENED MOVX T1,.SSCRA ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID SETO T3, ;INDICATE CONNECTION ACCEPTED XMOVEI T4,.CBDTA(P1) ;GET THE ADDRESS OF THE CONNECTION DATA PJRST @.CBADR(P1) ;CALL THE SYSAP AND RETURN ;SEND ACCEPT_RESPONSE BECAUSE OUR SIDE DISCONNECTED. ARQ.NG: MOVE T1,P3 ;GET THE OPCODE FOR ACCEPT_RSP LOAD T2,CBSDRE,(P1) ;GET SYSAP'S REASON FOR DISCONNECTING STOR T2,MH$STS,(P2) ;STORE AS THE STATUS PUSHJ P,SC.RSP ;SEND THE RESPONSE JRST SC.RIB ;FAILED, RETURN THE BUFFER TO THE FREE QUEUE PJRST SC.PTC ;DECLARE PROTOCL COMPLETE AND RETURN SUBTTL MESSAGE HANDLERS - ACCEPT RESPONSE SC.ARS: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE & OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT LOAD T2,CBCNST,(P1) ;GET OLD CONNECT STATE LOAD T3,MH$STS,(P2) ;GET THE STATUS WORD FROM THE PACKET CAIE T2,.CSCLO ;WAS IT CLOSED? JRST ARS.02 ;NO CAIE T3,.CMCMT ;IS THE STATUS MATCH? JRST ARS.01 ;NO MOVEI T1,.BSDPN ;YES, NEW BLOCK STATE IS DISCONNECT_PENDING PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE PJRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER ARS.01: PUSHJ P,SC.PTC ;DECLARE PROTOCOL COMPLETE PJRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER ;HERE WHEN STATE WAS NOT CLOSED (NORMAL CASE). IF MATCH, TELL THE ;SYSAP IT'S OK TO SEND DATA. IF NO MATCH, THE OTHER SIDE CHANGED ;ITS MIND. TELL THE SYSAP AND DECLARE PROTOCOL COMPLETE. ARS.02: CAIE T3,.CMCMT ;MATCH? JRST ARS.03 ;NO STOR T1,CBCNST,(P1) ;STORE NEW CONNECTION STATE MOVX T1,.SSOSD ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET SOURCE CONNECT ID PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP PJRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER ARS.03: MOVX T1,.CSCLO ;GET THE CLOSED STATE STOR T1,CBCNST,(P1) ;STORE AS THE NEW STATE MOVX T1,.SSRID ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET SOURCE CONNECT ID PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP PUSHJ P,SC.PTC ;DECLARE PROTOCOL COMPLETE PJRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER SUBTTL MESSAGE HANDLERS - REJECT REQUEST SC.RRQ: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT MOVE P3,T1 ;SAVE NEW STATE FOR LATER ;GET REASON FOR REJECTION FROM THE PACKET AND STORE IN THE CB LOAD T1,MH$STS,(P2) ;GET THE REJECT REASON STOR T1,CBDDRE,(P1) ;STORE ;BUILD THE RESPONSE IN THE BUFFER WE HAVE FROM THE REJECT_REQUEST MOVE T1,T2 ;GET OPCODE RETURNED ABOVE PUSHJ P,SC.RSP ;SEND THE RESPONSE JRST SC.RIB ;FAILED, RETURN THE BUFFER TO THE FREE QUEUE ;POKE THE SYSAP WITH ITS RESPONSE TO OUR CONNECT. LOAD T1,CBCNST,(P1) ;GET CURRENT CONNECT STATE CAIN T1,.CSCLO ;CLOSED? PJRST SC.PTC ;YES, SYSAP DOESN'T WANT TO KNOW ANYMORE STOR P3,CBCNST,(P1) ;STORE NEW CONNECT STATE MOVX T1,.SSCRA ;WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID SETZ T3, ;INDICATE THE CONNECTION WAS REJECTED LOAD T4,CBDDRE,(P1) ;GET THE REASON FOR THE REJECT PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP PJRST SC.PTC ;DECLARE PROTOCOL COMPLETE AND RETURN SUBTTL MESSAGE HANDLERS - REJECT RESPONSE SC.RRS: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT ;SET NEW STATE STOR T1,CBCNST,(P1) ;SET STATE AS RETURNED ABOVE PUSHJ P,SC.PTC ;DECLARE PROTOCOL COMPLETE JRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER SUBTTL MESSAGE HANDLERS - DISCONNECT REQUEST SC.DRQ: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT MOVE P3,T1 ;SAVE NEW STATE ;COPY REASON FOR DISCONNECT FROM PACKET TO CONNECT BLOCK LOAD T1,MH$STS,(P2) ;GET THE DISCONNECT REASON STOR T1,CBDDRE,(P1) ;STORE IN CB ;SEND A DISCONNECT_RSP MOVE T1,T2 ;GET OPCODE AS RETURNED ABOVE PUSHJ P,SC.RSP ;SEND THE RESPONSE JRST SC.RIB ;FAILED, RETURN THE BUFFER TO THE FREE QUEUE ;HONOR THE CB LOCK. IT IT'S LOCKED, SET A FLAG, SO WHEN THE OWNER ;UNLOCKS THE BLOCK THIS FUNCTION WILL BE COMPLETED. MOVX T1,CB.DRQ ;GET THE FLAG PUSHJ P,SC.HNR ;HONOR THE LOCK POPJ P, ;NOTHING ELSE WE CAN DO NOW ;STORE NEW STATE AS RETURNED ABOVE. STOR P3,CBCNST,(P1) ;STORE NEW STATE ;IF THE NEW STATE IS DISCONNECT_RECEIVED, PREVIOUS STATE WAS OPEN. ;THIS MEANS THE OTHER SIDE INITIATED THE DISCONNECT. CAIN P3,.CSDRE ;IS THE STATE DISCONNECT RECEIVED? JRST DRQ.01 ;YES, GO HANDLE THAT ;HERE WHEN NEW STATE IS NOT DISCONNECT_RECEIVED. IF NEW STATE IS CLOSED, ;PROTOCOL IS COMPLETE. THIS HAPPENS WHEN WE INITIATE THE DISCONNECTION, ;AND THE OTHER SIDE RESPONDS WITH A DISCONNECT_REQUEST. CAIN P3,.CSCLO ;IS THE NEW STATE CLOSED? PUSHJ P,SC.PTC ;YES, DECLARE PROTOCOL COMPLETE POPJ P, ;RETURN ;HERE WHEN NEW STATE IS DISCONNECT_RECEIVED. CORPORATE SCA SPEC SAYS ;THE SYSAP SHOULD BE REQUIRED TO DO A DISCONNECT. WE FAKE IT BY SETTING ;THE STATE AND SENDING THE MESSAGE. SET THE STATE BEFORE CALLING THE ;SYSAP, SO IF THE SYSAP DOES A SC.DIS BEFORE RETURNING WE WON'T SEND ;TWO DISCONNECT_REQUESTS. DRQ.01: MOVEI T1,.CSDMC ;NEW CONNECTION STATE IS DISCONNECT_MATCH STOR T1,CBCNST,(P1) ;STORE NEW STATE ;TELL THE SYSAP THE OTHER SIDE HUNG UP MOVX T1,.SSRID ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID LOAD T3,CBDDRE,(P1) ;GET THE REASON FROM THE PACKET STATUS FIELD PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP ;SET BLOCK STATE TO DISCONNECT_PEND TO CAUSE DISCONNECT_REQUEST TO BE SENT MOVEI T1,.BSDPN ;NEW BLOCK STATE PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE PJRST SC.SNM ;SEND NEXT MESSAGE IF POSSIBLE AND RETURN ;ROUTINE TO FINISH FUNCTION OF SC.DRQ WHEN UNLOCKING A CONNECTION BLOCK. ;CALL: ; P1/ ADDRESS OF CONNECTION BLOCK ; P5/ ADDRESS OF PATH BLOCK ; PUSHJ P,SC.FN3 ;RETURN: ; CPOPJ ALWAYS SC.FN3: CIOFF ;PREVENT RACES MOVX T1,CB.DRQ ;GET THE BIT ANDCAM T1,.CBFLG(P1) ;SHOW THIS HAS COMPLETED MOVEI T1,.STDRQ ;OPCODE IS DISCONNECT_REQUEST IMULI T1,MXCNST ;COMPUTE OFFSET IN THE TABLE LOAD T2,CBCNST,(P1) ;GET THE CONNECT STATE ADDI T1,-1(T2) ;STATES START AT 1 MOVE T2,TABLEK(T1) ;GET THE FLAGS TXNE T2,K.ERR ;WE CAN'T HANDLE PROTOCOL VIOLATION HERE BUG. (HLT,SCAFN3,SCASER,SOFT,,,) LOAD T1,K.STAT,(T1) ;GET NEW STATE STOR T1,CBCNST,(P1) ;STORE THE NEW CONNECTION STATE ;IF THE NEW STATE IS DISCONNECT_RECEIVED, PREVIOUS STATE WAS OPEN. ;THIS MEANS THE OTHER SIDE INITIATED THE DISCONNECT. CAIN T1,.CSDRE ;IS THE STATE DISCONNECT_RECEIVED? JRST FN3.01 ;YES, GO HANDLE THAT ;HERE WHEN NEW STATE IS NOT DISCONNECT_RECEIVED. IF NEW STATE IS ;CLOSED, PROTOCOL IS COMPLETE. THIS HAPPENS WHEN WE INITIATE THE ;DISCONNECTION, AND THE OTHER SIDE RESPONDS WITH A DISCONNECT_REQUEST. CAIN T1,.CSCLO ;IS THE NEW STATE CLOSED? PUSHJ P,SC.PTC ;YES, INDICATE PROTOCOL IS COMPLETE PJRST CIONPJ ;RESTORE INTERRUPTS AND RETURN ;HERE WHEN NEW STATE IS DISCONNECT_RECEIVED. CORPORATE SCA SPEC SAYS ;THE SYSAP SHOULD BE REQUIRED TO DO A DISCONNECT. WE FAKE IT BY SETTING ;THE STATE AND SENDING THE MESSAGE. SET THE STATE BEFORE CALLING THE ;SYSAP, SO IF THE SYSAP DOES A SC.DIS BEFORE RETURNING WE WON'T SEND ;TWO DISCONNECT_REQUESTS. FN3.01: MOVEI T1,.CSDMC ;NEW STATE IS DISCONNECT_MATCH STOR T1,CBCNST,(P1) ;STORE IT ;TELL THE SYSAP THE OTHER SIDE HUNG UP. MOVX T1,.SSRID ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET SOURCE CONNECT ID LOAD T3,CBDDRE,(P1) ;RETURN REASON FROM PACKET STATUS FIELD PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP ;SET BLOCK STATE TO DISCONNECT_PENDING TO CAUSE DISCONNECT_REQUEST TO BE SENT MOVEI T1,.BSDPN ;NEW BLOCK STATE PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE MOVX T1,CB.SNM ;INDICATE CALL TO SC.SNM DEFERRED IORM T1,.CBFLG(P1) ;... PJRST CIONPJ ;RESTORE INTERRUPTS AND RETURN SUBTTL MESSAGE HANDLERS - DISCONNECT RESPONSE SC.DRS: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT STOR T1,CBCNST,(P1) ;STORE THE NEW CONNECT STATE ;IF NEW STATE IS CLOSED, THIS IS A CONFIRMATION OF OUR DISCONNECT_REQUEST. ;EARLIER WE HAD RECEIVED A DISCONNECT_REQUEST AND SENT A DISCONNECT_RESPONSE. ;IF NOT, THE OTHER SIDE STILL NEEDS TO SEND A DISCONNECT_REQUEST. CAIN T1,.CSCLO ;IS THE STATE CLOSED? PUSHJ P,SC.PTC ;YES, DECLARE PROTOCOL COMPLETE JRST SC.SAR ;GO SEND NEXT SCS CONTROL MESSAGE, RETURN BUFFER SUBTTL MESSAGE HANDLERS - CREDIT REQUEST SC.CRQ: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT MOVE P3,T2 ;SAVE OPCODE OF RESPONSE LOADE T1,MH$CDT,(P2) ;GET THE CREDIT FIELD FROM THE MESSAGE HEADER JUMPGE T1,CRQ.01 ;JUMP IF WE ARE GIVING BACK CREDIT ;HERE WHEN THE OTHER SIDE IS WITHDRAWING CREDIT. DON'T ALLOW THIS IF ;SEND CREDIT IS ALREADY BELOW THE MINIMUM, AND DON'T ALLOW IT TO GO ;BELOW THE MINIMUM. LOAD T2,CBMNSC,(P1) ;GET MINIMUM SEND CREDIT SUB T2,.CBSCD(P1) ;COMPUTE -(SEND CREDIT - MINIMUM SEND CREDIT) JUMPLE T2,[SETZ T1, ;IF BELOW MINIMUM, DON'T REDUCE IT JRST CRQ.01] ;SEND THE RESPONSE CAMLE T2,T1 ;REQUEST TOO LARGE? MOVE T1,T2 ;YES, REDUCE ONLY TO MINIMUM SEND CREDIT ;HERE TO SEND THE RESPONSE CRQ.01: ADDM T1,.CBSCD(P1) ;ADD THIS BACK INTO SEND CREDIT STOR T1,MH$CDT,(P2) ;PUT THE CREDIT AMOUNT BACK INTO THE HEADER EXCH T1,P3 ;GET OPCODE, SAVE CREDIT VALUE PUSHJ P,SC.RS2 ;SEND THE RESPONSE, DON'T ZERO CREDIT JRST [MOVNS P3 ;GET NEGATIVE OF CREDIT ADDM P3,.CBSCD(P1) ;RESTORE CREDIT TO PREVIOUS VALUE JRST SC.RIB] ;RETURN THE BUFFER TO THE FREE QUEUE ;IF THE SYSAP HAS TRIED TO SEND A MESSAGE AND FAILED BECAUSE OF LACK ;OF SEND CREDIT, WE NEED TO NOTIFY IT THAT CREDIT HAS BEEN GIVEN TO ;IT. NOTE WE MUST CLEAR THE BEFORE THE CALL TO THE SYSAP. JUMPLE P3,CPOPJ## ;IF NOT ADDING CREDIT, WE'RE DONE LOAD T1,CBCNST,(P1) ;GET THE CONNECTION STATE MOVX T2,CB.NNC ;NEEDS CREDIT NOTIFY BIT TDNE T2,.CBFLG(P1) ;DOES SYSAP NEED NOTIFICATION? CAIE T1,.CSOPN ;YES, IS CONNECTION OPEN? POPJ P, ;NO, RETURN NOW ANDCAM T2,.CBFLG(P1) ;CLEAR THE FLAG BEFORE CALLING SYSAP MOVX T1,.SSCIA ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET SOURCE CONNECT ID MOVE T3,.CBSCD(P1) ;SHOW THE SEND CREDIT MOVE T4,.CBRCD(P1) ;SHOW THE RECEIVE CREDIT PJRST @.CBADR(P1) ;CALL THE SYSAP AND RETURN SUBTTL MESSAGE HANDLERS - CREDIT RESPONSE SC.CRS: PUSHJ P,SC.INC ;CHECK VALIDITY, GET STATE AND OPCODE JRST SC.RIB ;RETURN THE BUFFER AND QUIT ;GET THE CREDIT FROM THE MESSAGE AND FIGURE OUT WHAT IS REQUIRED LOADE P3,MH$CDT,(P2) ;GET THE CREDIT FIELD FROM THE MESSAGE HEADER SKIPL .CBRQC(P1) ;WERE WE TRYING TO GET CREDIT BACK? JRST CRS.01 ;NO MOVM T2,P3 ;GET THE NUMBER WE WERE ALLOWED ADDM T2,.CBRTC(P1) ;ADD INTO RETURN CREDIT JRST CRS.02 ;CONTINUE CRS.01: CAMN P3,.CBRQC(P1) ;DO WE AGREE WITH THE OTHER END? JRST CRS.02 ;YES LOAD T1,PBDPN,(P5) ;GET THE NODE NUMBER MOVE T2,.CBSCI(P1) ;GET THE CONNECT ID BUG. (CHK,SCAQQQ,SCASER,SOFT,,<,>,) CRS.02: ADDM P3,.CBRCD(P1) ;UPDATE THE RECEIVE CREDIT SETZM .CBRQC(P1) ;IF NEGATIVE, DON'T LET SC.RCB DEQUEUE ; BECAUSE THEY ARE COUNTED IN RETURN_CREDIT SETZM .CBPND(P1) ;INDICATE NO CREDIT_REQUEST PENDING PUSHJ P,SC.CD1 ;QUEUE CREDIT REQUEST IF NEEDED JFCL ;DON'T CARE WHETHER QUEUED OR NOT PUSHJ P,SC.GCB ;GET CANCELED BUFFERS, IF ANY PJRST SC.SAR ;GO SEND THE NEXT MESSAGE SUBTTL COMMON EXIT FOR INCOMING SCS CONTROL MESSAGES ;ROUTINE TO HANDLE A RESPONSE RECEIVED. THIS IS THE PACKET RESERVED ;FOR OUTGOING MESSAGES FOR THE PATH BLOCK OF INTEREST. USE IT TO ;SEND THE NEXT MESSAGE, OR QUEUE IT TO THE PATH BLOCK FOR THE NEXT ;TIME IT WANTS TO SEND A REQUEST. ;CALL: ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.SAR ;RETURN: ; CPOPJ ALWAYS SC.SAR: MOVEM P2,.PBOBB(P5) ;STORE THE BUFFER ADDRESS PJRST SC.SNM ;SEND NEXT SCS CONTROL MESSAGE ;ROUTINE TO RETURN BUFFER TO THE PORT. THIS HAPPENS WHEN THE PACKET ;ARRIVES AFTER THE VC HAS ALREADY BEEN CLOSED. ;CALL: ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.RIB ;RETURN: ; CPOPJ ALWAYS SC.RIB: SETZM (P2) ;CLEAR FLINK OF PACKET LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDQMB##,) ;RETURN THE BUFFER TO PORT'S FREE QUEUE POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - PROCESS INCOMING PACKET ;ROUTINE TO PROCESS AN INCOMING PACKET. ;CALL: ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.INC ;RETURN: ; CPOPJ ON ERROR ; CPOPJ1 ON SUCCESS WITH: ; T1/ NEW STATE ; T2/ OPCODE OF RESPONSE ; P1/ CB ADDRESS SC.INC: SAVEAC ;SAVE AN AC LOAD T1,PBVCST,(P5) ;GET THE VC STATE CAIE T1,VC.OPN ;IS IT OPEN? POPJ P, ;NO LOAD P3,MH$MSG,(P2) ;GET THE OPCODE CAIN P3,.STORQ ;SPECIAL CASE FOR CONNECT_REQ JRST CPOPJ1## ;SKIP RETURN ;SEE WHETHER WE KNOW ABOUT THE CONNECT ID MOVE T1,.MHDCI(P2) ;GET DESTINATION CONNECT ID PUSHJ P,SC.CSC ;CHECK FOR VALIDITY JRST INC.02 ;NOT VALID, GO HANDLE THE PROBLEM ;SEE WHETHER THIS EVENT IS EXPECTED GIVEN THE CURRENT STATE IMULI P3,MXCNST ;COMPUTE OFFSET IN THE TABLE BASED LOAD T1,CBCNST,(P1) ; ON THE CURRENT CONNECT STATE ADDI P3,-1(T1) ;(STATES START AT 1) MOVE T1,TABLEK(P3) ;GET THE TABLE ENTRY TXNE T1,K.ERR ;IF UNEXPECTED, GO HANDLE THE ERROR JRST INC.04 ;... TXNN T1,K.CHK ;WANT TO CHECK THIS RESPONSE? JRST INC.01 ;NO LOAD T1,MH$MSG,(P2) ;YES, GET OPCODE LOAD T2,CBEXPR,(P1) ;GET EXPECTED RESPONSE CAMN T1,T2 ;MATCH? JRST INC.01 ;YES LOAD T3,PBDPN,(P5) ;GET DESTINATION NODE MOVE T4,.CBSCI(P1) ;GET SOURCE CONNECT ID BUG. (CHK,SCAUXR,SCASER,SOFT,,<,,,>,) JRST INC.07 ;GO CLOSE THE VC INC.01: LOAD T1,K.STAT,(P3) ;IT'S LEGAL, GET NEW STATE LOAD T2,K.OP,(P3) ; AND OPCODE TO SEND JRST CPOPJ1## ;SKIP RETURN INC.02: LOAD T1,PBDPN,(P5) ;GET THE NODE MOVE T2,.MHDCI(P2) ;GET DESTINATION CONNECT ID LOAD T3,MH$MSG,(P2) ;GET THE OPCODE BUG. (CHK,SCANOC,SCASER,SOFT,,<,,>,) JRST INC.07 ;SKIP THE NEXT ERROR INC.04: LOAD T1,PBDPN,(P5) ;GET THE DESTINATION NODE MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID LOAD T3,MH$MSG,(P2) ;GET THE OPCODE LOAD T4,CBCNST,(P1) ;GET THE CONNECT STATE BUG. (CHK,SCAPER,SCASER,SOFT,,<,,,>,) INC.07: PJRST SC.CVC ;CLOSE THE VC AND RETURN SUBTTL MESSAGE HANDLERS - APPLICATION DATAGRAM/MESSAGE ;CALL: ; T1/ FLAGS ; T2/ LENGTH (BYTES IF INDUSTRY COMPATIBLE, WORDS IF HIGH DENSITY) ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS SC.ADG: SC.AMG: LOAD T3,PBVCST,(P5) ;GET VC STATE CAIE T3,VC.OPN ;OPEN? JRST AMD.07 ;NO, RETURN THE BUFFER AND QUIT ;SAVE FLAGS AND PACKET LENGTH ANDX T1,C%FLGM ;KEEP JUST THE FLAG BITS MOVE P3,T1 ;SAVE FLAGS MOVE P4,T2 ;SAVE LENGTH ;CHECK FOR ERROR CASES - INVALID CID OR INVALID STATE MOVE T1,.MHDCI(P2) ;GET THE DESTINATION CONNECT ID PUSHJ P,SC.CSC ;CHECK FOR VALIDITY JRST AMD.06 ;NO, CLOSE THE VC LOAD T1,CBCNST,(P1) ;GET THE CONNECT STATE CAIN T1,.CSOPN ;IS THE CONNECTION OPEN? JRST AMD.01 ;YES, PROCEED CAIE T1,.CSDAK ;ARE WE IN THE MIDDLE OF SENDING CAIN T1,.CSDSE ; OR RECEIVING A DISCONNECT? JRST AMD.07 ;YES, IT'S OK, RETURN THE BUFFER AND QUIT JRST AMD.06 ;NO, SHOULDN'T BE GETTING A PACKET NOW ;WE ARE HAPPY TO BE RECEIVING THIS PACKET AMD.01: MOVEM P4,.MHPKL(P2) ;STORE PACKET LENGTH WHERE SYSAP EXPECTS IT MOVE T2,.MHDCI(P2) ;GET THE DESTINATION CONNECT ID MOVE T3,P2 ;SYSAP WANTS ADDRESS OF PACKET LOAD P4,MH$MSG,(P2) ;GET THE MESSAGE TYPE CAIE P4,.STAMG ;APPLICATION MESSAGE? JRST AMD.02 ;NO SOS .CBRCD(P1) ;YES, DECREMENT RECEIVE CREDIT LOAD T1,MH$CDT,(P2) ;GET CREDIT FROM PACKET ADDM T1,.CBSCD(P1) ;UPDATE OUR SEND CREDIT MOVE P2,T1 ;SAVE THE CREDIT *** P2 NO LONGER POINTS AT PACKET *** MOVX T1,.SSMGR ;SAY WHY WE ARE CALLING MOVE T4,[MCSEC1+SC.RBF] ;ADDRESS OF BUFFER-RETURN ROUTINE JRST AMD.03 ;GO CALL THE SYSAP AMD.02: SOSGE .CBDGR(P1) ;DATAGRAM, DO WE HAVE A BUFFER QUEUED? JRST AMD.05 ;NO, HAVE TO DROP THIS ONE ON THE FLOOR MOVX T1,.SSDGR ;SAY WHY WE ARE CALLING MOVE T4,[MCSEC1+SC.RLD] ;ADDRESS OF BUFFER-RETURN ROUTINE AMD.03: IOR T4,P3 ;INCLUDE THE FLAGS PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP CAIE P4,.STAMG ;WAS THIS A MESSAGE? POPJ P, ;NO, ALL DONE ;THIS WAS A MESSAGE. IF THE REMOTE SYSAP INCREASED OUR SEND CREDIT, ;AND OUR SYSAP NEEDS TO BE TOLD, DO IT NOW. MOVX T1,CB.NNC ;"WAITING FOR CREDIT NOTIFY" FLAG TDNE T1,.CBFLG(P1) ;SYSAP WAITING FOR CREDIT? SKIPN P2 ;YES, DID WE GET ANY? JRST AMD.04 ;NO, DON'T NOTIFY THEN ANDCAM T1,.CBFLG(P1) ;CLEAR THE FLAG MOVX T1,.SSCIA ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET SOURCE CONNECTION ID MOVE T3,.CBSCD(P1) ;SEND CREDIT MOVE T4,.CBRCD(P1) ;RECEIVE CREDIT PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP ;IF THIS PUSHED OUR RECEIVE CREDIT UNDER THE MINIMUM, NOTIFY THE ;SYSAP THAT LITTLE CREDIT IS LEFT. AMD.04: MOVE T1,.CBPRC(P1) ;GET PENDING RECEIVE CREDIT MOVE T2,.CBRCD(P1) ; AND THE RECEIVE CREDIT ADD T1,T2 ;GET THE TOTAL LOAD T2,CBMNRC,(P1) ;GET THE MINIMUM RECEIVE CREDIT SUB T1,T2 ;DIFFERENCE BETWEEN THE TWO JUMPG T1,CPOPJ## ;RETURN IF CREDIT LEFT MOVM T3,T1 ;GET THE POSITIVE NUMBER OF BUFFER TO GET AOS T3 ;PLUS ONE JUST TO HAVE AN EXTRA AROUND MOVX T1,.SSLCL ;SAY WHY WE ARE CALLING MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID PJRST @.CBADR(P1) ;CALL THE SYSAP AND RETURN ;HAVE TO DROP THIS DATAGRAM AS THERE WAS NO BUFFER QUEUED FOR IT AMD.05: MOVX T1,.SSDDG ;GET CALLBACK REASON CODE MOVE T2,.MHDCI(P2) ;GET DESTINATION CONNECT ID PUSHJ P,@.CBADR(P1) ;CALL THE SYSAP AOS .CBCDD(P1) ;COUNT ANOTHER ONE DROPPED AOS .CBDGR(P1) ;RESTORE THE COUNT THAT WE DECREMENTED JRST AMD.07 ;RETURN THE BUFFER ;THE PACKET SHOULDN'T HAVE COME. CLOSE THE VC. AMD.06: PUSHJ P,SC.CVC ;CLOSE THE VC ;RETURN THE BUFFER TO THE PORT AMD.07: SETZM (P2) ;CLEAR FLINK IN PACKET LOAD T2,MH$MSG,(P2) ;GET OPCODE LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX CAIE T2,.STAMG ;MESSAGE? JRST AMD.08 ;NO BLCAL. (PPDQMB##,) ;QUEUE A MESSAGE BUFFER POPJ P, ;RETURN AMD.08: BLCAL. (PPDQDB##,) ;QUEUE A DATAGRAM BUFFER POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - ONCE PER TICK/SECOND PROCESSING ;ROUTINE CALLED ONCE PER TICK ON ALL CPUS TO PERFORM PERIODIC ;PROCESSING. ;CALL: ; PUSHJ P,SC.TIC ;RETURN: ; CPOPJ ALWAYS $XSENT (SC.TIC::) ;EXTENDED ENTRY POINT SKPCPU (0) ;IS THIS THE BOOT CPU? JRST TIC.01 ;NO PUSHJ P,SC.DEF ;HANDLE DEFERRED BUFFER REQUESTS PUSHJ P,SC.ALM ;HANDLE MEMORY ALLOCATION REQUESTS TIC.01: SKIPE SCAREP ;DO WE NEED TO REAP CONNECTION BLOCKS? PUSHJ P,SC.RAP ;YES POPJ P, ;RETURN ;ROUTINE CALLED ONCE PER SECOND ON ALL CPUS TO PERFORM PERIODIC ;PROCESSING. ;CALL: ; PUSHJ P,SC.SEC ;RETURN: ; CPOPJ ALWAYS $XSENT (SC.SEC::) ;EXTENDED ENTRY POINT PUSHJ P,SC.IDL ;DO IDLE CHATTER POPJ P, ;RETURN SUBTTL PERIODIC FUNCTIONS - IDLE CHATTER ;ROUTINE TO HANDLE IDLE CHATTER. IF A REMOTE NODE HAS NOT SENT US A ;PACKET LATELY WE WILL SEND IT A CREDIT REQUEST OVER AN OPEN CONNECT. ;(THUS IF THERE ARE NO OPEN CONNECTIONS THEN THERE IS NO IDLE CHATTER.) ;CALL: ; PUSHJ P,SC.IDL ;RETURN: ; CPOPJ ALWAYS SC.IDL: PUSHJ P,SAVP## ;SAVE THE PRESERVED AC'S CIOFF ;PREVENT RACES SKPCPU (0) ;ON THE BOOT CPU? SKIPA T1,TMGPBI ;NO, DON'T INCREMENT PBI AOS T1,TMGPBI ;GET THE NEXT PBI WE SHOULD LOOK AT CAIL T1,C%PBLL ;HAVE WE GONE OFF THE END OF THE WORLD? SETZB T1,TMGPBI ;YES, RESET TO FIRST ONE CION ;OK TO INTERRUPT SKIPN P5,PBLIST(T1) ;IS THERE A PATH BLOCK THERE? POPJ P, ;NO IFN FTMP,< MOVE T1,.PBCPU(P5) ;YES, IS IT ON THIS CPU? CAME T1,.CPCPN## ;... POPJ P, ;NO >; END IFN FTMP LOAD T1,PBVCST,(P5) ;GET VC STATE CAIE T1,VC.OPN ;IS IT OPEN? POPJ P, ;NO SKIPN .PBFCB(P5) ;ARE THERE ANY CONNECTIONS? POPJ P, ;NO SKIPN T1,.PBTIM(P5) ;HAS THIS NODE EVER SPOKEN TO US? POPJ P, ;NO SUB T1,DATE## ;YES, HOW LONG AGO DID IT? CAMLE T1,TMGTIM ;TIME TO POKE IT IN THE SIDE? POPJ P, ;NO ;IT'S BEEN A WHILE SINCE WE LAST HEARD FROM THIS NODE. IF WE ALREADY ;SENT A TIMED MESSAGE THE LAST TIME WE CAME THROUGH HERE, GIVE UP ON ;IT AND CLOSE THE VC. OTHERWISE, GO SEND A TIMED MESSAGE. MOVX T1,PB.TMG ;HAS A TIMED MESSAGE BEEN SENT? TDNN T1,.PBFLG(P5) ;... JRST IDL.01 ;NO AOS TMGCNT ;YES, COUNT ANOTHER ONE BITING THE DUST LOAD T1,PBDPN,(P5) ;GET THE NODE NUMBER BUG. (INF,SCATMO,SCASER,SOFT,,<>,) PJRST SC.CVC ;CLOSE THE VC AND RETURN ;FIND A CONNECTION ON THIS PATH BLOCK WHICH IS FULLY OPEN. IF A NODE ;GOES OFFLINE WHILE WE'RE DOING THIS, ALL ATTEMPTS AT SENDING WILL FAIL ;BECAUSE CONNECTION STATE WILL BE CLOSED FOR EACH CB. IDL.01: SKIPN P1,.PBFCB(P5) ;GET ADDRESS OF FIRST CONNECTION BLOCK POPJ P, ;ALL CONNECTIONS ARE GONE, ALL DONE ;TRY THIS CONNECTION BLOCK; IF THE STATE IS OK, SEND A CREDIT_REQUEST IDL.02: PUSHJ P,SC.LOK ;LOCK THE CONNECTION BLOCK SETO P3, ;ASSUME WE'LL NEED TO SEND A MESSAGE PUSHJ P,SC.CD7 ;QUEUE CREDIT REQUEST IF POSSIBLE SETZ P3, ;DON'T NEED TO SEND A MESSAGE AFTER ALL PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JUMPE P3,IDL.03 ;JUMP IF WE DON'T NEED TO SEND A MESSAGE PUSHJ P,SC.SNM ;SEND THE NEXT MESSAGE MOVX T1,PB.TMG ;SET THE TIMED MESSAGE FLAG IORM T1,.PBFLG(P5) ;... POPJ P, ;RETURN IDL.03: SKIPN P1,.CBANB(P1) ;IS THERE ANOTHER CONNECTION BLOCK? POPJ P, ;NO, RETURN JRST IDL.02 ;YES, TRY IT SUBTTL PERIODIC FUNCTIONS - REAP OLD CONNECTIONS ;ROUTINE TO REAP CONNECTION BLOCKS WHICH HAVE THE REAP BIT SET. ;CALL: ; PUSHJ P,SC.RAP ;RETURN: ; CPOPJ ALWAYS SC.RAP: SAVEAC ;SAVE SOME AC'S SETZ Q1, ;START WITH FIRST PATH BLOCK RAP.01: SKIPN Q2,PBLIST(Q1) ;IS THERE A PATH BLOCK THERE? JRST RAP.04 ;NO, TRY FOR NEXT ONE IFN FTMP,< MOVE T1,.PBCPU(Q2) ;GET CPU NUMBER CAME T1,.CPCPN## ;ON OUR CPU? JRST RAP.04 ;NO, SKIP THIS >; END IFN FTMP MOVE P1,.PBFCB(Q2) ;GET THE POINTER TO THE FIRST CB JUMPE P1,RAP.04 ;TRY NEXT ONE IF NO CONNECTIONS RAP.02: MOVE Q2,.CBANB(P1) ;GET ADDRESS OF NEXT CB MOVX T1,CB.RAP ;GET THE REAP BIT TDNN T1,.CBFLG(P1) ;SHOULD THIS CONNECTION BE REAPED? JRST RAP.03 ;NO ; SKIPN .CBNPO(P1) ;ANY PACKETS STILL ON THE COMMAND QUEUE? PUSHJ P,SC.RCB ;REAP THE CONNECT DATA RAP.03: SKIPE P1,Q2 ;IS THERE ANOTHER BLOCK? JRST RAP.02 ;YES, LOOP RAP.04: CAIGE Q1,C%PBLL-1 ;PAST THE END? AOJA Q1,RAP.01 ;NO, TRY NEXT ;NOW DO THE DON'T CARE QUEUE RAP.05: CIOFF ;PREVENT RACES RAP.06: SKIPN P1,TOPDC ;GET FIRST CONNECTION JRST CIONPJ ;NONE, RESTORE INTERRUPTS AND RETURN RAP.07: MOVX T1,CB.RAP ;GET THE REAP BIT TDNN T1,.CBFLG(P1) ;SHOULD THIS CONNECTION BE REAPED? JRST RAP.08 ;NO CION ;ALLOW INTERRUPTS AGAIN PUSHJ P,SC.RCB ;RETURN THE CONNECTION DATA JRST RAP.05 ;START OVER RAP.08: MOVE P1,.CBANB(P1) ;GET THE ADDRESS OF THE NEXT CB JUMPN P1,RAP.07 ;JUMP IF MORE TO CHECK PJRST CIONPJ ;DONE, RESTORE INTERRUPTS AND RETURN SUBTTL SCA SUPPORT ROUTINES - RELEASE A CONNECTION BLOCK ;ROUTINE TO DEALLOCATE A CONNECTION BLOCK. ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SC.RCB ;RETURN: ; CPOPJ ALWAYS SC.RCB: SAVEAC ;SAVE AN AC OR THREE CIOFF ;PREVENT RACES MOVE P5,.CBPBK(P1) ;GET THE PATH BLOCK ADDRESS JUMPL P5,RCB.04 ;JUMP IF A "DON'T CARE" LISTENER PUSHJ P,SC.RSQ ;REMOVE THIS CONNECTION BLOCK FROM QUEUE CION ;OK TO INTERRUPT ;REMOVE CID TABLE ENTRIES FOR THIS CB MOVE T1,.CBSCI(P1) ;GET THE SOURCE CONNECT ID LOAD T4,INDEX,T1 ;GET THE INDEX INTO CIDTAB MOVE T1,T4 ;GET A COPY ADD T1,CIDTAB ;ADD IN ADDRESS OF CID TABLE SETZM (T1) ;ZERO THE ADDRESS OF THE CB IN TABLE ;GET BUFFERS BACK FROM THE MESSAGE FREE QUEUE LOAD P2,PBPBI,(P5) ;GET PATH BLOCK INDEX FOR PPD MOVE Q1,.CBRCD(P1) ;GET TOTAL RECEIVE CREDIT ADD Q1,.CBPRC(P1) ;ADD THE PENDING CREDITS ADD Q1,.CBRQC(P1) ;AND NUMBER OF CREDITS OUTSTANDING IN CDT_REQ ADD Q1,.CBRTC(P1) ;ADD CANCELED BUFFERS NOT YET DEQUEUED JUMPE Q1,RCB.02 ;IF NOTHING TO DEQUEUE, TRY FOR DATAGRAMS RCB.01: BLCAL. (PPDDMB##,) ;DEQUEUE A MESSAGE BUFFER JRST RCB.02 ;HMM, NO MESSAGE BUFFERS LEFT PUSHJ P,SC.RBF ;RETURN THE BUFFER TO SCA SOJG Q1,RCB.01 ;LOOP FOR ANY REMAINING ;GET BUFFERS BACK FROM THE DATAGRAM FREE QUEUE RCB.02: MOVE Q1,.CBDGR(P1) ;GET THE NUMBER OF DATAGRAMS QUEUED JUMPE Q1,RCB.05 ;JUMP IF NOTHING TO DEQUEUE RCB.03: BLCAL. (PPDDDB##,) ;DEQUEUE A DATAGRAM BUFFER JRST RCB.05 ;HMM, NO DATAGRAM BUFFERS LEFT PUSHJ P,SC.RLD ;RETURN THE BUFFER TO SCA SOJG Q1,RCB.03 ;LOOP FOR ANY REMAINING JRST RCB.05 ;GO KILL THE BUFFER ;HERE WHEN DELETING AN ENTRY FROM THE DON'T CARE LISTEN QUEUE RCB.04: PUSHJ P,SC.RDQ ;REMOVE IT FROM THE DON'T CARE QUEUE CION ;OK TO INTERRUPT ;GIVE BACK THE CB AND WE'RE DONE RCB.05: MOVX T1,CB.RAP ;GET THE REAP BIT TDNN T1,.CBFLG(P1) ;WAS IT SET? JRST RCB.06 ;NO SOSGE SCAREP ;YES, COUNT DOWN REAP COUNT SETZM SCAREP ;WENT TOO FAR, RESET TO ZERO RCB.06: MOVE T1,P1 ;GET THE CB ADDRESS IN T1 PUSHJ P,SC.RBF ;RETURN THE BUFFER SETZ P1, ;ERASE ALL KNOWLEDGE OF IT POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - MARK CONNECTION BLOCK REAPABLE ;ROUTINE TO MARK A CONNECTION BLOCK AS REAPABLE. ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SC.SRB ;RETURN: ; CPOPJ ALWAYS $XSENT (SC.SRB::) MOVX T1,CB.RAP ;GET THE REAP BIT TDNE T1,.CBFLG(P1) ;ALREADY SET? POPJ P, ;YES IORM T1,.CBFLG(P1) ;NO, SET IT AOS SCAREP ;BUMP THE REAP COUNT POPJ P, ;RETURN SUBTTL SCA BUFFER MANAGEMENT - ALLOCATE DEFERRED BUFFERS ;ROUTINE CALLED FROM THE CLOCK LEVEL CODE TO ALLOCATE DEFERRED ;BUFFERS IF ANY NEEDED BY CONNECTIONS WAITING FOR BUFFERS BEFORE ;SENDING A CONNECT_REQUEST OR ACCEPT_REQUEST MESSAGE. ;CALL: ; PUSHJ P,SC.DEF ;RETURN: ; CPOPJ ALWAYS SC.DEF: SKIPE PBSTUK ;ANY NEED TO DO THIS? SKIPE MDPAGS ;YES, MEMORY ALLOCATOR ALREADY CRANKED UP? POPJ P, ;RETURN, DON'T NEED (OR WANT) TO PUSHJ P,SAVP## ;SAVE PRESERVED REGISTERS DEF.01: SKIPE P1,PBSTUK ;STUCK ON BUFFERS ANYWHERE? JFFO P1,.+2 ;FIND FIRST PATH BLOCK INDEX WHICH IS STUCK POPJ P, ;NO SKIPN P5,PBLIST-1(P2) ;GET PATH BLOCK ADDRESS XCT SCAFOO ;FOO MOVE T1,BITTBL##(P2) ;GET THE BIT ANDCAM T1,PBSTUK ;CLEAR IT SETZ P3, ;CLEAR RECORD OF FIRST CB FOUND DEF.02: PUSHJ P,SC.RWQ ;REMOVE NEXT ENTRY FROM WORK QUEUE JRST DEF.04 ;END OF THE LIST LOAD T1,CBCNST,(P1) ;GET CONNECTION STATE CAIN T1,.CSCLO ;IS IT CLOSED? JRST DEF.03 ;YES, NO NEED TO CREATE BUFFERS PUSHJ P,SC.BF2 ;TRY TO CREATE SOME BUFFERS JRST DEF.05 ;STILL SHORT ON MEMORY MOVX T1,CB.SOB ;GET THE FLAG ANDCAM T1,.CBFLG(P1) ;CLEAR IT SKIPN P3 ;HAVE WE RECORDED FIRST MOVED BLOCK? MOVE P3,P1 ;NO, DO SO NOW PUSHJ P,SC.AWQ ;PUT IT ON THE END OF THE QUEUE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST DEF.02 ;GET NEXT CONNECTION FOR THIS PATH DEF.03: SETZRO ,(P1) ;DON'T NEED BUFFERS NOW MOVX T1,CB.SOB ;CLEAR THE FLAG ANDCAM T1,.CBFLG(P1) ;... PUSHJ P,SC.PTC ;FINISHED WITH THIS CB PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST DEF.02 ;GET NEXT CONNECTION FOR THIS PATH DEF.04: PUSHJ P,SC.SNM ;SEE IF WE CAN SEND ANYTHING NOW JRST DEF.01 ;SEE IF MORE TO DO ;HERE WHEN WE COULDN'T CREATE BUFFERS - DETERMINE HOW MUCH WE NEED ;FOR THIS CONNECTION AND GET THE MEMORY ALLOCATOR RUNNING. DEF.05: SKIPN DINITF## ;DON'T TRY THIS TYPE OF ALLOCATION DURING ONCE SKIPE MDPAGS ;ALREADY DONE THIS FOR SOME CB? JRST DEF.08 ;YES, WE CAN'T HAVE TWO REQUESTS OUTSTANDING LOAD T1,CBIMB,(P1) ;GET NUMBER OF MESSAGE BUFFERS JUMPE T1,DEF.06 ;JUMP IF NONE IDIVI T1,C%MGPG ;NUMBER PER PAGES SKIPN T2 ;IF A REMAINDER, ROUND UP SKIPN T1 ;OR IF LESS THAN A FULL PAGE, AOS T1 ;ASK FOR AT LEAST ONE PAGE HRLM T1,MDPAGS ;STORE COUNT OF PAGES REQUIRED DEF.06: LOAD T1,CBIDB,(P1) ;GET NUMBER OF DATAGRAM BUFFERS JUMPE T1,DEF.07 ;JUMP IF NONE IDIVI T1,C%DGPG ;NUMBER PER PAGES SKIPN T2 ;IF A REMAINDER, ROUND UP SKIPN T1 ;OR IF LESS THAN A FULL PAGE, AOS T1 ;ASK FOR AT LEAST ONE PAGE HRRM T1,MDPAGS ;STORE COUNT OF PAGES REQUIRED DEF.07: HLRZ T1,MDPAGS ;GET NUMBER OF MESSAGE PAGES HRRZ T2,MDPAGS ;GET NUMBER OF DATAGRAM PAGES ADD T1,T2 ;TOTAL NUMBER REQUIRED HRLI T1,(MS.SCA) ;SECTION TO ALLOCATE FROM XMOVEI T2,ALM.03 ;WHO TO CALL WHEN ALLOCATION COMPLETES PUSHJ P,GETCLP## ;QUEUE A REQUEST DEF.08: SKIPN P3 ;HAVE WE RECORDED FIRST MOVED BLOCK? MOVE P3,P1 ;NO, DO SO NOW PUSHJ P,SC.AWQ ;PUT IT ON THE END OF THE QUEUE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK MOVE T1,BITTBL##(P2) ;GET BIT FOR THIS PATH AGAIN IORM T1,PBSTUK ;SHOW WE'RE STUCK ON BUFFERS (AGAIN) POPJ P, ;TRY AGAIN NEXT TICK SUBTTL SCA BUFFER MANAGEMENT - ALLOCATE MEMORY FOR BUFFERS ;ROUTINE CALLED FROM THE CLOCK LEVEL CODE TO ALLOCATE MEMORY IF ;MEMORY IS NEEDED. ;CALL: ; PUSHJ P,SC.ALM ;RETURN: ; CPOPJ ALWAYS SC.ALM: SKIPE CIBUF ;TIME TO ALLOCATE MEMORY? SKIPE MDPAGS ;YES, ALREADY REQUESTED IT? POPJ P, ;RETURN, DON'T NEED (OR WANT) TO ;CHECK FOR MESSAGE BUFFER ALLOCATION MOVE T1,MINMSG ;GET MINIMUM MESSAGE THRESHOLD CAMGE T1,MFQCNT ;DO WE HAVE ENOUGH CURRENTLY? JRST ALM.01 ;YES, CHECK DATAGRAM BUFFERS SUB T1,MFQCNT ;WE NEED MORE, SEE HOW MANY IDIVI T1,C%MGPG ;SEE HOW MANY PAGES ARE NEEDED SKIPN T2 ;IF A REMAINDER, ROUND UP SKIPN T1 ;OR IF LESS THAN A FULL PAGE, AOS T1 ;ASK FOR AT LEAST ONE PAGE HRLM T1,MDPAGS ;STORE COUNT OF PAGES REQUIRED ;CHECK FOR DATAGRAM BUFFER ALLOCATION ALM.01: MOVE T1,MINDG ;GET MINIMUM DATAGRAM THRESHOLD CAMGE T1,DFQCNT ;DO WE HAVE ENOUGH CURRENTLY? JRST ALM.02 ;YES, SEE IF WE HAD ASKED FOR MESSAGE SPACE SUB T1,DFQCNT ;WE NEED MORE, SEE HOW MANY IDIVI T1,C%DGPG ;SEE HOW MANY PAGES ARE NEEDED SKIPN T2 ;IF A REMAINDER, ROUND UP SKIPN T1 ;OR IF LESS THAN A FULL PAGE, AOS T1 ;ASK FOR AT LEAST ONE PAGE HRRM T1,MDPAGS ;STORE COUNT OF PAGES REQUIRED ;NOW SEE IF ANY PAGES ARE REQUIRED, AND FIRE UP THE CLOCK LEVEL ;MEMORY ALLOCATION ROUTINE IF SO ALM.02: HLRZ T1,MDPAGS ;GET NUMBER OF MESSAGE PAGES HRRZ T2,MDPAGS ;GET NUMBER OF DATAGRAM PAGES ADD T1,T2 ;TOTAL NUMBER REQUIRED JUMPE T1,ALM.06 ;CHECK AGAIN LATER IF NOTHING REQUIRED SKIPE DINITF## ;INITIALIZATION STILL GOING ON? JRST ALM.IN ;YES HRLI T1,(MS.SCA) ;SECTION TO ALLOCATE FROM XMOVEI T2,ALM.03 ;WHO TO CALL WHEN ALLOCATION COMPLETES PJRST GETCLP## ;QUEUE UP A REQUEST AND RETURN ;WE PREVIOUSLY ASKED FOR MEMORY ALLOCATION, AND IT HAS NOW COMPLETED ALM.03: PUSHJ P,SAVE1## ;SAVE P1 MOVE P1,T1 ;ADDRESS OF WHERE PAGES WERE ALLOCATED ;BREAK UP PAGES OBTAINED INTO MESSAGE BUFFERS HLRZ T2,MDPAGS ;GET NUMBER OF MESSAGE BUFFER PAGES REQUESTED JUMPE T2,ALM.04 ;JUMP IF NO MESSAGE BUFFER PAGES WERE REQUESTED MOVE T1,P1 ;GET VIRTUAL ADDRESS OF FIRST PAGE PUSHJ P,SC.CPC ;CREATE A PAGE CHAIN MOVE T1,P1 ;GET VIRTUAL ADDRESS OF FIRST PAGE MOVX T2,C%MGSZ ;GET BUFFER SIZE PUSHJ P,SC.BBF ;BREAK INTO BUFFERS CIOFF ;PREVENT RACES MOVEM T1,@BOTMFQ ;LINK THESE NEW BUFFERS ONTO THE FREE QUEUE MOVEM T2,BOTMFQ ;... ADDM T3,MFQCNT ;UPDATE THE FREE COUNT ADDM T3,TOTMGB ; AND THE TOTAL NUMBER OF BUFFERS CREATED CION ;OK TO INTERRUPT AGAIN HLRZ T1,MDPAGS ;GET NUMBER OF MESSAGE BUFFER PAGES LSH T1,P2WLSH ;CONVERT TO WORDS ADD P1,T1 ;GET VIRTUAL ADDRESS OF DATAGRAM BUFFER PAGES ;BREAK UP PAGES OBTAINED INTO DATAGRAM BUFFERS ALM.04: HRRZ T2,MDPAGS ;GET NUMBER OF DATAGRAM BUFFER PAGES REQUESTED JUMPE T2,ALM.05 ;JUMP IF NO DATAGRAM BUFFER PAGES WERE REQUESTED MOVE T1,P1 ;GET VIRTUAL ADDRESS OF FIRST PAGE PUSHJ P,SC.CPC ;CREATE A PAGE CHAIN MOVE T1,P1 ;GET VIRTUAL ADDRESS OF FIRST PAGE MOVX T2,C%DGSZ ;GET BUFFER SIZE PUSHJ P,SC.BBF ;BREAK INTO BUFFERS CIOFF ;PREVENT RACES MOVEM T1,@BOTDFQ ;LINK THESE NEW BUFFERS ONTO THE FREE QUEUE MOVEM T2,BOTDFQ ;... ADDM T3,DFQCNT ;UPDATE THE FREE COUNT ADDM T3,TOTDGB ; AND THE TOTAL NUMBER OF BUFFERS CREATED CION ;OK TO INTERRUPT AGAIN ALM.05: SETZM MDPAGS ;WE'VE ALLOCATED OUR MEMORY, CLEAR THIS VARIABLE ALM.06: SETZM CIBUF ;NO LONGER NEED TO ALLOCATE MEMORY POPJ P, ;RETURN ALM.IN: PUSHJ P,PGRSKD## ;ASK FOR THE NECESSARY PAGES PUSHJ P,SCADIE ;CAN'T, DIE JRST ALM.03 ;CONTINUE SUBTTL SCA SUPPORT ROUTINES - CREATE A PAGE CHAIN ;ROUTINE TO CREATE A PAGE CHAIN FOR SC.BBF TO TAKE APART. ;CALL: ; T1/ VIRTUAL ADDRESS OF FIRST PAGE ; T2/ NUMBER OF PAGES IN CHAIN ; PUSHJ P,SC.CPC ;RETURN: ; CPOPJ ALWAYS SC.CPC: SETZM (T1) ;CLEAR LINK TO NEXT PAGE SOJLE T2,CPOPJ## ;RETURN WHEN DONE XMOVEI T3,PAGSIZ(T1) ;GET ADDRESS OF NEXT PAGE MOVEM T3,0(T1) ;LINK THAT PAGE TO THIS PAGE MOVE T1,T3 ;GET NEXT PAGE ADDRESS JRST SC.CPC ;LOOP SUBTTL SCA SUPPORT ROUTINES - SET BLOCK STATE AND QUEUE MESSAGE ;ROUTINE TO SET NEW BLOCK STATE AND QUEUE A MESSAGE TO BE SENT. ;CALL: ; T1/ NEW STATE ; P1/ CB ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.SCA ;RETURN: ; CPOPJ ALWAYS SC.SCA: LOAD T2,CBBKST,(P1) ;GET THE BLOCK STATE JUMPE T2,SCA.01 ;JUMP IF ZERO LOAD T3,PBDPN,(P5) ;GET DESTINATION NODE BUG. (CHK,SCASBN,SCASER,SOFT,,<,,>,) STOR T1,CBBKST,(P1) ;SET STATE AS REQUESTED POPJ P, ; BUT DON'T TRY TO QUEUE IT AGAIN SCA.01: STOR T1,CBBKST,(P1) ;SET STATE AS REQUESTED PUSHJ P,SC.AWQ ;ADD THE CB TO THE WORK QUEUE POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - SEND NEXT SCS CONTROL MESSAGE ;ROUTINE TO SEND THE NEXT SCS CONTROL MESSAGE FOR THIS PATH BLOCK IF ;THE BUFFER IS AVAILABLE AND THERE'S A WAITING CONNECTION BLOCK. IF ;THE CB REQUIRES BUFFERS, CREATES THEM IF POSSIBLE, OTHERWISE MOVES ;THE CB TO THE END OF THE QUEUE AND TRIES THE NEXT ONE. ;CALL: ; P5/ PBK ADDRESS ; PUSHJ P,SC.SNM ;RETURN: ; CPOPJ ALWAYS SC.SNM: SKIPN .PBTWQ(P5) ;IS THERE A CB THAT NEEDS SOMETHING? POPJ P, ;NO, NOTHING TO DO PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS SETZ P2, ;PREPARE TO CLEAR THE BUFFER ADDRESS EXCH P2,.PBOBB(P5) ;GET OUTBOUND BUFFER ADDRESS JUMPE P2,CPOPJ## ;IF NOT AVAILABLE, RETURN SETZ P3, ;INITIALIZE ADDRESS OF FIRST CB MOVED ;HERE WHEN BUFFER IS AVAILABLE, AND THERE'S SOMETHING TO BE DONE ;REMOVE FIRST ENTRY FROM WORK QUEUE SNM.01: PUSHJ P,SC.RWQ ;GET AND LOCK NEXT ENTRY JRST SNM.06 ;THERE ISN'T ONE ;BLOCK STATE SHOULDN'T BE ZERO - COMPLAIN IF IT IS LOAD T1,CBBKST,(P1) ;GET THE BLOCK STATE JUMPN T1,SNM.02 ;OK IF NOT ZERO LOAD T1,PBDPN,(P5) ;GET NODE NUMBER MOVE T2,.CBSCI(P1) ;GET CONNECT ID LOAD T3,CBCNST,(P1) ;GET CONNECT STATE BUG. (CHK,SCAEEE,SCASER,SOFT,,,) PUSHJ P,SC.PTC ;ALLOW REAPER TO GET THIS BLOCK PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST SNM.01 ;LOOK FOR ANOTHER ENTRY ;THIS PROBABLY ISN'T NECESSARY BUT DO IT ANYWAY. ;IF THE "REAP" BIT IS ON, WE SHOULDN'T BE SENDING ANY REQUESTS. SNM.02: MOVX T1,CB.RAP ;ARE WE READY TO REAP THIS BLOCK? TDNN T1,.CBFLG(P1) ;... JRST SNM.03 ;NO LOAD T1,PBDPN,(P5) ;GET THE NODE NUMBER MOVE T2,.CBSCI(P1) ;GET THE CONNECT ID BUG. (CHK,SCARBS,SCASER,SOFT,,,) PUSHJ P,SC.PTC ;FINISH OFF THIS BLOCK PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK JRST SNM.01 ;DO THE NEXT ENTRY ;IF THIS CONNECTION BLOCK IS ALREADY STUCK ON BUFFERS, MOVE IT TO THE ;END OF THE QUEUE. SNM.03: MOVX T1,CB.SOB ;GET "STUCK ON BUFFERS" FLAG TDNE T1,.CBFLG(P1) ;ARE WE STUCK ON BUFFERS? JRST SNM.05 ;YES, MOVE IT TO THE END OF THE QUEUE ;GET ANY BUFFERS THAT WE WANT, IF POSSIBLE PUSHJ P,SC.BF1 ;ALLOCATE BUFFERS IF WE NEED THEM JRST SNM.05 ;COULDN'T GET THEM ALL ;WE'VE GOT THE BUFFERS WE WANTED, OR DIDN'T WANT ANY. CREATE ;THE MESSAGE AND SEND IT. PUSHJ P,SC.RQS ;BUILD PACKET, SET NEW STATE, AND SEND IT JRST SNM.04 ;COULDN'T SEND IT PJRST SC.ULK ;SUCCESS, UNLOCK CONNECTION BLOCK AND RETURN ;SEND FAILED. VC MUST HAVE GONE AWAY, SO GIVE THE BUFFER TO THE PORT SNM.04: PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX SETZM (P2) ;CLEAR FLINK IN PACKET BLCAL. (PPDQMB##,) ;GIVE BUFFER TO PORT POPJ P, ;RETURN ;HERE WHEN WE COULDN'T GET THE BUFFERS NEEDED OR CONNECTION BLOCK ;WAS ALREADY STUCK. MARK THE CB AS "STUCK ON BUFFERS" SO WE CAN ;FIX THINGS AT CLOCK LEVEL. MARK THE PATH BLOCK TOO. SNM.05: MOVX T1,CB.SOB ;GET THE FLAG IORM T1,.CBFLG(P1) ;MARK CB AS STUCK ON BUFFERS SKIPN P3 ;IS THIS THE FIRST BLOCK MOVED TO END? MOVE P3,P1 ;YES, RECORD IT PUSHJ P,SC.AWQ ;ADD THIS CB TO THE WORK QUEUE PUSHJ P,SC.ULK ;UNLOCK THE CONNECTION BLOCK LOAD T1,PBPBI,(P5) ;GET PATH BLOCK INDEX MOVE T1,BITTBL##(T1) ;GET THE BIT IORM T1,PBSTUK ;MARK PATH BLOCK AS STUCK JRST SNM.01 ;SEE IF ANYTHING ELSE TO DO ;HERE WHEN ALL THE CONNECTION BLOCKS THAT ARE LEFT REQUIRE BUFFERS ;OR THERE AREN'T ANY BLOCKS. WE HAVE TO KEEP THE BUFFER WE HAD ;PLANNED TO USE FOR THE MESSAGE AND REUSE IT LATER. SNM.06: CIOFF ;PREVENT RACES LOAD T1,PBVCST,(P5) ;GET VC STATE CAIE T1,VC.OPN ;IS VC OPEN? JRST SNM.07 ;NO MOVEM P2,.PBOBB(P5) ;YES, RETURN BUFFER TO PATH BLOCK CION ;OK TO INTERRUPT AGAIN SKIPE PBSTUK ;IS A PATH BLOCK STUCK? AOS CIBUF ;ASK SC.DEF TO RUN POPJ P, ;RETURN SNM.07: CION ;OK TO INTERRUPT AGAIN LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX SETZM (P2) ;CLEAR FLINK IN PACKET BLCAL. (PPDQMB##,) ;GIVE THE PACKET BACK TO THE PORT POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - ADD AN ENTRY TO THE WORK QUEUE ;ROUTINE TO ADD AN ENTRY TO THE WORK QUEUE. ;CALL: ; P1/ CB ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.AWQ ;RETURN: ; CPOPJ ALWAYS SC.AWQ: CIOFF ;PREVENT RACES LOAD T1,PBVCST,(P5) ;GET VC STATE CAIE T1,VC.OPN ;IS VC OPEN? PJRST CIONPJ ;NO, DON'T TRY TO SEND MOVE T1,.PBBWQ(P5) ;GET LAST ENTRY IN WORK QUEUE XMOVEI T2,.PBTWQ(P5) ;GET HEAD OF QUEUE CAMN T1,T2 ;EMPTY IF EQUAL JRST [MOVEM P1,.PBTWQ(P5) ;MAKE THIS BE THE FIRST JRST .+2] ;CONTINUE MOVEM P1,.CBNWQ(T1) ;MAKE OLD LAST POINT TO THIS MOVEM P1,.PBBWQ(P5) ;MAKE THIS BE THE LAST PJRST CIONPJ ;INTERRUPTS ON AND RETURN SUBTTL SCA SUPPORT ROUTINES - REMOVE ENTRY FROM WORK QUEUE ;ROUTINE TO REMOVE AN ENTRY FROM A PATH BLOCK WORK QUEUE. ;CALL: ; P3/ ADDRESS OF CONNECTION BLOCK TO STOP AT ; P5/ PATH BLOCK ADDRESS ; PUSHJ P,SC.RWQ ;RETURN: ; CPOPJ IF NO MORE ENTRIES ; CPOPJ1 WITH ENTRY AVAILABLE AND LOCKED WITH: ; P1/ ADDRESS OF CONNECTION BLOCK ; P3/ UPDATED IF NECESSARY SC.RWQ: CIOFF ;PREVENT RACES RWQ.01: SKIPN P1,.PBTWQ(P5) ;GET FIRST ENTRY ON QUEUE JRST RWQ.04 ;QUEUE EMPTY CAMN P1,P3 ;HAVE WE FOUND THIS BUFFER BEFORE? JRST RWQ.04 ;YES, WE'RE FINISHED WITH THIS PATH BLOCK SKIPE T1,.CBNWQ(P1) ;POINT TO THE SECOND ENTRY JRST RWQ.02 ;THERE IS ANOTHER XMOVEI T2,.PBTWQ(P5) ;THIS IS THE END, MAKE TAIL MOVEM T2,.PBBWQ(P5) ; POINT TO HEAD RWQ.02: MOVEM T1,.PBTWQ(P5) ;MAKE HEAD POINT TO NEXT OR ZERO SETZM .CBNWQ(P1) ;INDICATE NO LONGER ON QUEUE MOVX T1,CB.SNM ;SEE IF WE HAVE TO DEFER PUSHJ P,SC.LAH ;GET THE LOCK IF POSSIBLE JRST RWQ.03 ;WE HAVE TO DEFER PJRST CINPJ1 ;INTERRUPTS BACK ON AND SKIP RETURN ;HERE WHEN THE CONNECTION BLOCK WAS LOCKED. MOVE IT TO THE END OF THE ;LIST AND CONTINUE LOOKING FOR A USABLE ENTRY. RWQ.03: SKIPN P3 ;HAVE WE RECORDED FIRST MOVED BLOCK? MOVE P3,P1 ;NO, THIS IS IT, THEN PUSHJ P,SC.AWQ ;MOVE IT TO THE END OF THE QUEUE JRST RWQ.01 ;TRY FOR THE NEXT ENTRY ;HERE WHEN WE'RE AT THE END OF THE LIST, OR IT'S EMPTY RWQ.04: SETZ P1, ;BE SAFE PJRST CIONPJ ;INTERRUPTS BACK ON AND RETURN SUBTTL SCA SUPPORT ROUTINES - ALLOCATE A CONNECTION BLOCK ;ROUTINE TO ALLOCATE AND INITIALIZE A CONNECTION BLOCK. ;CALL: ; T1/ SYSAP BITS TO BE PLACED IN CI ; PUSHJ P,SC.ACB ;RETURN: ; CPOPJ IF ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 IF SUCCESS WITH: ; P1/ CONNECTION BLOCK ADDRESS SC.ACB: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,SYBITS ;SAVE SYSAP CID BITS ;CREATE AND STORE THE CONNECTION-ID PUSHJ P,SC.FNI ;GET THE NEXT AVAILABLE INDEX RETBAD (.SCFNE) ;NO MORE, RETURN ERROR SETZ T4, ;START WITH ZERO STOR T1,INDEX,T4 ;STORE INDEX MOVEM T1,IDX ;SAVE THE INDEX PUSHJ P,SC.FUB ;GET THE UNIQUENESS BITS TO USE FOR CID STOR T2,UBITS,T4 ;STORE THE UNIQUE BITS MOVEM T2,UBTS ;SAVE THEM MOVE T2,SYBITS ;GET SYSAP BITS BACK AGAIN STOR T2,SID,T4 ;STORE THESE BITS IN THE CID MOVEM T4,CID ;SAVE THE NEWLY CREATED CONNECT ID MOVEI T1,1 ;WE ONLY WANT ONE BUFFER PUSHJ P,SC.ABF ;ALLOCATE IT RETBAD () ;PASS ERROR ALONG TO CALLER MOVE P1,T1 ;COPY CONNECTION BLOCK ADDRESS TO STANDARD AC MOVE T4,CID ;GET THE CREATED CID BACK MOVEM T4,.CBSCI(P1) ;STORE THE CONNECT ID IN THE CONNECTION BLOCK MOVE T1,IDX ;GET THE INDEX BACK AGAIN ADD T1,CIDTAB ;ADD THE BASE ADDRESS OF THE CB ADDRESS TABLE MOVEM P1,(T1) ;STORE CB ADDRESS IN THE TABLE MOVE T1,IDX ;GET THE INDEX AGAIN ADD T1,UBTTAB ;ADD THE BASE ADDRESS OF THE UNIQUESS BITS TABLE MOVE T2,UBTS ;GET THE BITS MOVEM T2,(T1) ;STORE THE UNIQUENESS BITS ;INIT JSYS QUEUE POINTERS SETZM .CBTMQ(P1) ;ZERO FLINK FOR MESSAGE QUEUE XMOVEI T2,.CBTMQ(P1) ;GET ADDRESS OF HEAD MOVEM T2,.CBBMQ(P1) ;INIT BLINK TO POINT AT HEAD SETZM .CBTDQ(P1) ;ZERO FLINK FOR DATAGRAM QUEUE XMOVEI T2,.CBTDQ(P1) ;GET ADDRESS OF HEAD MOVEM T2,.CBBDQ(P1) ;INIT BLINK TO POINT AT HEAD SETZM .CBTXQ(P1) ;ZERO FLINK FOR DATA REQUEST QUEUE XMOVEI T2,.CBTXQ(P1) ;GET ADDRESS OF HEAD MOVEM T2,.CBBXQ(P1) ;INIT BLINK TO POINT AT HEAD SETZM .CBTEQ(P1) ;ZERO FLINK FOR EVENT QUEUE XMOVEI T2,.CBTEQ(P1) ;GET ADDRESS OF HEAD MOVEM T2,.CBBEQ(P1) ;INIT BLINK TO POINT AT HEAD SETZM .CBTBQ(P1) ;ZERO FLINK FOR BUFFER QUEUE XMOVEI T2,.CBTBQ(P1) ;GET ADDRESS OF HEAD MOVEM T2,.CBBBQ(P1) ;INIT BLINK TO POINT TO HEAD MOVEI T2,.CSCLO ;INITIAL STATE IS "CLOSED" STOR T2,CBCNST,(P1) ;SET THAT IN CONNECTION BLOCK JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCA SUPPORT ROUTINES - FIND NEXT INDEX ;ROUTINE TO FIND THE NEXT INDEX INTO THE CID TABLES. ;CALL: ; PUSHJ P,SC.FNI ;RETURN: ; CPOPJ IF NO FREE SLOTS ; CPOPJ1 IF SUCCESS WITH: ; T1/ NEXT AVAILABLE INDEX SC.FNI: MOVEI T3,C%CIDL ;INIT COUNT OF ENTRIES SEARCHED FNI.01: SOSL T1,NXTIDX ;TRY FOR THE NEXT INDEX JRST FNI.02 ;MORE TO GO MOVEI T1,C%CIDL-1 ;FAILED, TIME TO RECYCLE MOVEM T1,NXTIDX ;INIT NXTIDX TO HIGHEST CIDTAB ENTRY AOS CIDRFL ;INDICATE CIDTAB RECYCLING FNI.02: MOVE T2,T1 ;GET A COPY WE CAN PLAY WITH ADD T2,CIDTAB ;ADD IN THE OFFSET TO THE CID ADDRESS TABLE SKIPN (T2) ;IS THERE AN ENTRY THERE? JRST CPOPJ1## ;NO, SKIP RETURN SOJN T3,FNI.01 ;IF WE HAVEN'T CHECKED ENTIRE CIDTAB, LOOP POPJ P, ;TABLE IS FULL, NON-SKIP RETURN SUBTTL SCA SUPPORT ROUTINES - FIND UNIQUENESS BITS ;ROUTINE TO FIND THE NEXT UNIQUENESS BITS FOR A CID. ;CALL: ; T1/ INDEX INTO CIDTAB OF CID BEING FORMED ; PUSHJ P,SC.FUB ;RETURN: ; CPOPJ ALWAYS WITH: ; T2/ NEXT UNIQUENESS BITS TO USE FOR CID SC.FUB: SOSLE T2,UNQBTS ;TRY FOR THE NEXT IDENTIFIER JRST FUB.01 ;MORE TO GO SETONE UBITS,T2 ;TIME TO RECYCLE, SET ALL BITS IN THE FIELD LSH T2,- ;RIGHT JUSTIFY SAID BITS MOVEM T2,UNQBTS ;STORE AS THE UNIQUENESS BITS AOS UNQRFL ;INDICATE RECYCLING FUB.01: SKIPN UNQRFL ;ARE WE IN RECYCLE MODE FOR THE BITS? POPJ P, ;NO, RETURN SUCCESS ADD T1,UBTTAB ;OBTAIN ADDRESS OF OLD ENTRY CAME T2,(T1) ;ARE THE OLD AND NEW UNIQUENESS BITS EQUAL? POPJ P, ;NO, SO USE THEM SOSLE T2 ;YES, MAKE NEW BITS DIFFERENT, STILL VALID? POPJ P, ;YES, USE THEM SETONE UBITS,T2 ;SET ALL BITS IN THE FIELD LSH T2,- ;RIGHT JUSTIFY SAID BITS POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - LINK A CONNECTION BLOCK ;ROUTINE TO LINK A NEW CONNECTION BLOCK TO THE LIST OF CONNECTION ;BLOCKS HANGING OFF A PATH BLOCK. ;CALL: ; P1/ CONNECTION BLOCK ADDRESS ; P5/ PATH BLOCK ADDRESS ; PUSHJ P,SC.LCB ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS SC.LCB: CIOFF ;PREVENT RACES JUMPL P5,LCB.DC ;SPECIAL CASE FOR "DON'T CARE" LISTENERS LOAD T1,PBVCST,(P5) ;GET STATUS OF THE CONNECTION CAIE T1,VC.OPN ;IS IT OPEN? RETBAD (KLPX9,) ;NO, DON'T TRY TO LINK SKIPN .CBANB(P1) ;IS THERE A CURRENT FORWARD LINK? SKIPE .CBAPB(P1) ;OR A CURRENT BACKWARD LINK? SKIPA ;YES JRST LCB.01 ;NO LOAD T1,PBDPN,(P5) ;GET THE DESTINATION NODE NUMBER MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID BUG. (CHK,SCASSS,SCASER,SOFT,,<,>,) PUSHJ P,SC.RQS ;DEQUEUE CONNECTION BLOCK FROM CURRENT QUEUE LCB.01: MOVE T2,.PBLCB(P5) ;GET THE POINTER TO CURRENT LAST XMOVEI T3,.PBFCB(P5) ;GET THE ADDRESS OF THE FLINK CAME T2,T3 ;IS THERE ANYTHING ON THE LIST? MOVEM T2,.CBAPB(P1) ;YES, LINK THIS BLOCK TO THAT MOVEM P1,@.PBLCB(P5) ;LINK THE NEW BLOCK MOVEM P1,.PBLCB(P5) ;... PJRST CINPJ1 ;INTERRUPTS BACK ON AND SKIP RETURN ;HERE TO LINK "DON'T CARE" LISTENERS TOGETHER LCB.DC: MOVE T1,BOTDC ;GET THE LAST BUFFER ON THE QUEUE MOVEM P1,@BOTDC ;LINK THIS TO THE END OF THE QUEUE XMOVEI T3,TOPDC ;GET THE ADDRESS OF THE TOP POINTER CAMN T1,T3 ;IS PREVIOUS CB THE TOP POINTER? SETZ T1, ;YES, MAKE IT ZERO INSTEAD MOVEM T1,.CBAPB(P1) ;MAKE THIS CB POINT TO THE PREVIOUS ONE MOVEM P1,BOTDC ;NOW SHOW IT AS THE END OF THE QUEUE PJRST CINPJ1 ;INTERRUPTS BACK ON AND SKIP RETURN SUBTTL SCA SUPPORT ROUTINES - DEQUEUE A CONNECTION BLOCK ;ROUTINE TO DEQUEUE A CONNECTION BLOCK FROM ITS CURRENT QUEUE ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SC.RSQ ;RETURN: ; CPOPJ ALWAYS ; ;CALLER MUST CIOFF BEFORE SC.RSQ SC.RSQ: MOVE T1,.CBANB(P1) ;GET FORWARD POINTER MOVE T2,.CBAPB(P1) ;GET BACKWARD POINTER MOVE T3,.CBPBK(P1) ;GET THE PATH BLOCK ADDRESS SKIPN T1 ;IS THERE A NEXT? SKIPE T2 ;OR A PREVIOUS? JRST RSQ.01 ;YES, NOT LAST ENTRY XMOVEI T4,.PBFCB(T3) ;GET POINTER TO HEAD OF CB QUEUE MOVEM T4,.PBLCB(T3) ;SET BLINK TO POINT AT HEAD SETZM .PBFCB(T3) ;CLEAR FLINK POPJ P, ;RETURN RSQ.01: SKIPE T1 ;IS THERE A NEXT LINK? MOVEM T2,.CBAPB(T1) ;YES, UPDATE POINTER TO PREVIOUS OF NEXT SKIPE T2 ;IS THERE A PREVIOUS LINK? MOVEM T1,.CBANB(T2) ;YES, UPDATE POINTER TO NEXT OF PREVIOUS SKIPN T1 ;IS THERE A NEXT? MOVEM T2,.PBLCB(T3) ;NO, DELETED LAST, UPDATE QUEUE BLINK SKIPN T2 ;IS THERE A PREVIOUS? MOVEM T1,.PBFCB(T3) ;NO, DELETED FIRST, UPDATE QUEUE FLINK POPJ P, ;RETURN ;ROUTINE TO DEQUEUE A CONNECTION BLOCK FROM THE "DON'T CARE" QUEUE. ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SC.RDQ ;RETURN: ; CPOPJ ALWAYS SC.RDQ: MOVE T1,.CBANB(P1) ;GET THE ADDRESS OF THE NEXT CB MOVE T2,.CBAPB(P1) ;GET THE ADDRESS OF THE PREVIOUS CB SKIPN T1 ;IS THERE A NEXT ENTRY? SKIPE T2 ;OR A PREVIOUS ENTRY? JRST RDQ.01 ;YES, NOT THE LAST ENTRY XMOVEI T1,TOPDC ;NO, THIS IS THE LAST CB ON THE QUEUE MOVEM T1,BOTDC ;INIT TAIL AS POINTER TO HEAD SETZM TOPDC ;INIT HEAD AS ZERO POPJ P, ;RETURN RDQ.01: SKIPE T1 ;IS THERE A NEXT ENTRY? MOVEM T2,.CBAPB(T1) ;YES, UPDATE PREVIOUS OF NEXT CB SKIPE T2 ;IS THERE A PREVIOUS ENTRY? MOVEM T1,.CBANB(T2) ;YES, UPDATE NEXT OF PREVIOUS CB SKIPN T1 ;WAS THERE A NEXT ENTRY? MOVEM T2,BOTDC ;NO, UPDATE THE QUEUE BLINK SKIPN T2 ;WAS THERE A PREVIOUS ENTRY? MOVEM T1,TOPDC ;NO, UPDATE THE QUEUE FLINK POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - SEARCH FOR CONNECTION MATCH ;ROUTINE TO SEARCH THE CONNECTION BLOCKS FOR A MATCH BETWEEN ;A LOCAL LISTEN AND A DESTINATION CONNECT REQUEST. ;CALL: ; P2/ ADDRESS OF MESSAGE ; P5/ PBK ADDRESS ; PUSHJ P,SC.SCM ;RETURN: ; CPOPJ IF NO MATCH ; CPOPJ1 IF MATCH WITH: ; P1/ CB ADDRESS SC.SCM: PUSHJ P,SAVQ## ;SAVE Q1-Q3 SETZ Q1, ;START WITH FIRST PATH BLOCK SCM.01: SKIPN Q2,PBLIST(Q1) ;IS THERE A PATH BLOCK HERE? JRST SCM.04 ;NO, TRY FOR NEXT ONE IFN FTMP,< MOVE T1,.PBCPU(Q2) ;GET CPU NUMBER CAME T1,.CPCPN## ;ON OUR CPU? JRST SCM.04 ;NO, SKIP THIS ONE >; END IFN FTMP SKIPA P1,.PBFCB(Q2) ;GET THE POINTER TO THE FIRST CB AND SKIP SCM.02: MOVE P1,.CBANB(P1) ;GET POINTER TO NEXT CB JUMPE P1,SCM.04 ;JUMP IF AT THE END LOAD T1,CBCNST,(P1) ;GET THE CONNECTION STATE CAIE T1,.CSLIS ;IS THE STATE LISTEN? JRST SCM.02 ;NO, TRY NEXT CB SKIPGE .CBPBK(P1) ;IS THIS A DON'T CARE LISTENER? ; JRST SCM.03 ;YES, DON'T CHECK NODE NUMBER BUG. (HLT,SCADLL,SCASER,SOFT,,,) CAME Q2,.CBPBK(P1) ;IS THIS THE ASSOCIATED PATH BLOCK? JRST SCM.02 ;NO, TRY NEXT CB SCM.03: SKIPN .MGDPN(P2) ;IS THERE A REQUESTED PROCESS NAME? SKIPE .CBDPN(P1) ;AND DO WE CARE WHO WE TALK TO? SKIPA ;WE CARE, DO REGULAR NAME CHECKING JRST CPOPJ1## ;WE DON'T CARE, THEREFORE WE HAVE A MATCH XMOVEI T1,.CBSPN(P1) ;POINT TO OUR NAME FOR ME XMOVEI T2,.MGDPN(P2) ;POINT TO THE REMOTE'S NAME FOR ME PUSHJ P,SC.C4S ;DO THE STRINGS MATCH? JRST SCM.02 ;NO XMOVEI T1,.CBDPN(P1) ;POINT TO CB'S DESTINATION PROCESS NAME XMOVEI T2,.MGSPN(P2) ;AND SOURCE PROCESS NAME FROM CONNECT REQUEST PUSHJ P,SC.C4S ;DO THE STRINGS MATCH? JRST SCM.02 ;NO JRST CPOPJ1## ;WE HAVE A MATCH SCM.04: CAIGE Q1,C%PBLL-1 ;PAST THE END? AOJA Q1,SCM.01 ;NO, TRY NEXT ;NO MATCH ON PB LISTS, TRY THE "DON'T CARE" QUEUE SKIPA P1,TOPDC ;GET ADDRESS OF FIRST CB ON DON'T CARE QUEUE SCM.05: MOVE P1,.CBANB(P1) ;GET NEXT CB ON THE QUEUE JUMPE P1,CPOPJ## ;NONE, YOU LOSE LOAD T1,CBCNST,(P1) ;GET THE CONNECTION STATE CAIE T1,.CSLIS ;IS THE STATE LISTEN? JRST SCM.05 ;NO, TRY NEXT CB SKIPN .MGDPN(P2) ;IS THERE A REQUESTED PROCESS NAME? SKIPE .CBDPN(P1) ;AND DO WE CARE WHO WE TALK TO? SKIPA ;WE CARE, DO REGULAR NAME CHECKING JRST SCM.06 ;WE DON'T CARE, THEREFORE WE HAVE A MATCH XMOVEI T1,.CBSPN(P1) ;POINT TO OUR NAME FOR ME XMOVEI T2,.MGDPN(P2) ;POINT TO THE REMOTE'S NAME FOR ME PUSHJ P,SC.C4S ;DO THE STRINGS MATCH? JRST SCM.05 ;NO SKIPN .CBDPN(P1) ;DO WE CARE WHO WE TALK TO? JRST SCM.06 ;NO, THEN WE HAVE A MATCH XMOVEI T1,.CBDPN(P1) ;POINT TO CB'S DESTINATION PROCESS NAME XMOVEI T2,.MGSPN(P2) ;AND SOURCE PROCESS NAME FROM CONNECT REQUEST PUSHJ P,SC.C4S ;DO THE STRINGS MATCH? JRST SCM.05 ;NO ;WE FOUND A MATCH, DELINK US FROM THE DON'T CARE QUEUE AND PUT US ON THE ;CB LIST FOR THE PB WE HAVE FOUND A HOME WITH. SCM.06: MOVEM P5,.CBPBK(P1) ;MAKE SURE WE KNOW WHICH PATH BLOCK PUSHJ P,SC.RDQ ;REMOVE CB FROM DON'T CARE QUEUE SETZM .CBANB(P1) ;ZERO LINKS OF CB WE JUST DEQUEUED SETZM .CBAPB(P1) ;... PUSHJ P,SC.LCB ;LINK THIS CB ON PB QUEUE BUG. (HLT,SCACLB,SCASER,SOFT,,,) JRST CPOPJ1## ;SKIP RETURN SUBTTL SCA SUPPORT ROUTINES - COMPARE FOUR-WORD STRINGS ;ROUTINE TO COMPARE TWO FOUR-WORD STRINGS. THE STRINGS ARE ALWAYS ;PADDED OUT TO THEIR FULL FOUR-WORD SIZE, SO THIS ROUTINE CAN USE ;FULL WORD COMPARES VERSUS ILDBS. ;CALL: ; T1/ ADDRESS OF ONE STRING ; T2/ ADDRESS OF ANOTHER STRING ; PUSHJ P,SC.C4S ;RETURN: ; CPOPJ IF STRINGS DON'T MATCH ; CPOPJ1 IF STRINGS DO MATCH SC.C4S: MOVE T3,0(T1) ;GET THE FIRST WORD CAME T3,0(T2) ;DO THEY MATCH? POPJ P, ;NO, RETURN MOVE T3,1(T1) ;GET THE SECOND WORD CAME T3,1(T2) ;DO THEY MATCH? POPJ P, ;NO, RETURN MOVE T3,2(T1) ;GET THE THIRD WORD CAME T3,2(T2) ;DO THEY MATCH? POPJ P, ;NO, RETURN MOVE T3,3(T1) ;GET THE FOURTH WORD CAMN T3,3(T2) ;DO THEY MATCH? AOS (P) ;YES, SET FOR SKIP RETURN POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - CID SANITY CHECK ;ROUTINE TO CHECK THE VALIDITY OF A CONNECT ID. ;CALL: ; T1/ CONNECT ID TO CHECK ; PUSHJ P,SC.CSC ;RETURN: ; CPOPJ IF NO MATCH FOR CONNECTION ID ; CPOPJ1 IF MATCH WITH: ; T1/ CONNECT ID ; P1/ CONNECTION BLOCK ADDRESS ; P5/ PATH BLOCK ADDRESS $CSUB ;ENTRY POINT SC.CSC::TDZA P1,P1 ;FLAG = 0 MEANS WE DON'T WANT TO LOCK CB SC.CAL: SETO P1, ;FLAG = -1 MEANS WE WANT TO LOCK CB CIOFF ;PREVENT RACES LOAD T2,INDEX,T1 ;GET THE INDEX FROM THE CID MOVE T3,T2 ;SAVE A COPY CAIL T2,C%CIDL ;IS IT WITHIN RANGE? JRST CSC.E1 ;NO ADD T2,CIDTAB ;ADD THE OFFSET TO THE CID TABLE SKIPN T2,(T2) ;GET THE ENTRY JRST CSC.E1 ;NONE LOAD T4,UBITS,T1 ;GET UNIQUENESS BITS MOVE T2,T3 ;GET A COPY OF THE INDEX ADD T2,UBTTAB ;ADD THE OFFSET TO THE UNIQUENESS TABLE MOVE T2,(T2) ;GET THE BITS CAME T2,T4 ;DO WE HAVE A MATCH? JRST CSC.E1 ;NO ADD T3,CIDTAB ;YES, T3 = CID TABLE BASE ADDRESS + INDEX MOVE T3,(T3) ;GET THE CONNECTION BLOCK ADDRESS EXCH T3,P1 ;PUT IT IN P1 AND RETRIEVE ENTRY FLAG SKIPE T3 ;WANT TO LOCK? PUSHJ P,SC.LOK ;YES, LOCK THE CONNECTION BLOCK MOVE P5,.CBPBK(P1) ;GET THE PATH BLOCK ADDRESS JRST CINPJ1 ;INTERRUPTS BACK ON AND SKIP RETURN CSC.E1: RETBAD (.SCIID,) ;RETURN AN ERROR $XHIGH SUBTTL CONNECTION MANAGEMENT UTILITY ROUTINES - SEND CREDIT_REQUEST ;ROUTINE TO SEND A CREDIT_REQUEST MESSAGE IF NECESSARY. ;CALL: ; P1/ CONNECTION BLOCK ADDRESS ; P5/ PATH BLOCK ADDRESS ; PUSHJ P,SC.CD? ;RETURN: ; CPOPJ IF DIDN'T SEND A MESSAGE ; CPOPJ1 IF SENT A MESSAGE ; ;FOUR ENTRY POINTS: ; SC.CDT - WHEN SYSAP QUEUES BUFFER FOR MESSAGE RECEPTION ; SC.CD1 - WHEN CREDIT_RESPONSE ARRIVES ; SC.CD5 - WHEN SYSAP TAKES A BUFFER BACK ; SC.CD7 - IDLE CHATTER ; ;IF THIS ROUTINE TAKES THE SKIP RETURN THE CALLER MUST CALL SC.SNM AFTER ;UNLOCKING THE CONNECTION BLOCK. SC.CDT: SKIPG T1,.CBPRC(P1) ;GIVE UP IF PENDING RECEIVE CREDIT POPJ P, ; IS NOT POSITIVE JRST SC.CD3 ;GO CHECK ON RECEIVE CREDIT ;HERE WHEN CREDIT_RESPONSE ARRIVES. WE MAY HAVE WANTED TO SEND ANOTHER ;ONE EARLIER, BUT ONLY ONE CAN BE OUTSTANDING AT A TIME. SEND IT IF ;PENDING RECEIVE CREDIT IS NEGATIVE, OR IF PENDING RECEIVE CREDIT IS ;POSITIVE AND RECEIVE CREDIT IS .LT. MINIMUM RECEIVE CREDIT. SC.CD1: SKIPGE T1,.CBPRC(P1) ;SEND IF PENDING RECEIVE CREDIT IS NEGATIVE JRST CDT.01 ;... JUMPE T1,CPOPJ## ;DON'T SEND IF THERE'S NO CHANGE ;SEND IF RECEIVE CREDIT .LT. MINIMUM RECEIVE CREDIT OR IF PENDING ;RECEIVE CREDIT IS GETTING LARGE. SC.CD3: LOAD T2,CBMNRC,(P1) ;SEND IF RECEIVE CREDIT IS BELOW CAMLE T2,.CBRCD(P1) ; THE MINIMUM JRST CDT.01 ;... CAIGE T1,C%MBCR ;SEND IF PENDING IS GETTING LARGE POPJ P, ;DON'T SEND JRST CDT.01 ;SEND ;HERE WHEN SYSAP TAKES A BUFFER BACK. SEND ONLY IF PENDING RECEIVE ;CREDIT IS NEGATIVE. SC.CD5: SKIPL .CBPRC(P1) ;SEND IF PENDING RECEIVE CREDIT IS NEGATIVE POPJ P, ;DON'T SEND JRST CDT.01 ;SEND ;HERE FOR IDLE CHATTER (ALWAYS SEND) SC.CD7: JRST CDT.01 ;SEND ;HERE BECAUSE CREDIT VALUES SUGGEST SENDING A CREDIT_REQUEST. SEE IF ;THE STATE OF THE CONNECTION WILL ALLOW IT. CDT.01: LOAD T1,CBCNST,(P1) ;GET THE STATE CAIE T1,.CSOPN ;CONNECTION OPEN? POPJ P, ;NO, DON'T SEND A CREDIT REQUEST NOW SETO T1, ;INDICATE CREDIT REQUEST IS PENDING EXCH T1,.CBPND(P1) ;GET THE OLD VALUE JUMPL T1,CPOPJ## ;RETURN IF ONE ALREADY PENDING LOAD T1,CBBKST,(P1) ;GET THE BLOCK STATE JUMPE T1,CDT.02 ;GO IF BLOCK STATE IS ZERO LOAD T1,PBDPN,(P5) ;GET NODE NUMBER MOVE T2,.CBSCI(P1) ;GET CONNECT ID LOAD T3,CBBKST,(P1) ;GET BLOCK STATE BUG. (CHK,SCACSC,SCASER,SOFT,,<,,>,) SETZM .CBPND(P1) ;WE'RE NOT DOING A CREDIT REQUEST AFTER ALL POPJ P, ;RETURN CDT.02: MOVEI T1,.BSCRP ;SET BLOCK STATE TO CREDIT PENDING PUSHJ P,SC.SCA ;SET BLOCK STATE AND QUEUE MESSAGE JRST CPOPJ1## ;SKIP RETURN SUBTTL SCA SUPPORT ROUTINES - RECLAIM BUFFERS ;ROUTINE TO RECLAIM BUFFERS ACCORDING TO RETURN_CREDIT FIELD OF ;CONNECT BLOCK. ;CALL: ; P1/ CB ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.GCB ;RETURN: ; CPOPJ ALWAYS SC.GCB: SAVEAC ;SAVE AN AC SETZ P3, ;GET A ZERO EXCH P3,.CBRTC(P1) ;GET OLD VALUE AND ZERO IT JUMPE P3,CPOPJ## ;NOTHING TO DO IF ALREADY ZERO GCB.01: LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDDMB##,) ;DEQUEUE A MESSAGE BUFFER JRST GCB.E1 ;ERROR PUSHJ P,SC.RBF ;RETURN THE BUFFER TO SCA SOJG P3,GCB.01 ;LOOP FOR ANY MORE POPJ P, ;RETURN GCB.E1: LOAD T1,PBDPN,(P5) ;GET THE NODE NUMBER MOVE T2,.CBSCI(P1) ;GET THE SOURCE CONNECT ID BUG. (CHK,SCACRB,SCASER,SOFT,,<,>,) POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - CLOSE A VIRTUAL CIRCUIT ;ROUTINE TO CLOSE A VIRTUAL CIRCUIT. ;CALL: ; P5/ PBK ADDRESS ; PUSHJ P,SC.CVC ;RETURN: ; CPOPJ ALWAYS SC.CVC: LOAD T1,PBDPN,(P5) ;GET THE NODE NUMBER BUG. (INF,SCACVC,SCASER,SOFT,,<>,) LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDCVC##,) ;CALL THE PORT DRIVER POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - MOVE STRINGS AND DATA TO CB ;ROUTINE TO MOVE THE SOURCE PROCESS NAME, THE DESTINATION PROCESS NAME, ;AND THE CONNECTION DATA FROM THE SYSAP'S ARGUMENTS INTO THE CONNECT ;BLOCK. THE ADDRESSES PROVIDED FOR DESTINATION NAME AND CONNECTION ;DATA MAY BE ZERO, BUT THE SOURCE NAME MAY NEVER BE ZERO. ;CALL: ; T1/ ADDRESS OF SOURCE PROCESS NAME ; T2/ ADDRESS OF DESTINATION PROCESS NAME (OR ZERO) ; T3/ ADDRESS OF CONNECTION DATA (OR ZERO) ; P1/ CB ADDRESS ; PUSHJ P,SC.SDM ;RETURN: ; CPOPJ ALWAYS SC.SDM: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,DPN ;SAVE THE ADDRESS OF THE DESTINATION NAME MOVEM T3,DATA ; AND THE ADDRESS OF THE CONNECTION DATA ;MOVE THE SOURCE PROCESS NAME MOVE T2,T1 ;ADDRESS OF SOURCE PROCESS NAME MOVX T1,C%PNLW ;LENGTH OF PROCESS NAME IN WORDS XMOVEI T3,.CBSPN(P1) ;DESTINATION ADDRESS IN CB EXTEND T1,[XBLT] ;MOVE THE SOURCE PROCESS NAME ;MOVE THE DESTINATION PROCESS NAME SKIPN T2,DPN ;IS THERE ONE TO MOVE? JRST SDM.01 ;NO, CHECK FOR CONNECTION DATA MOVX T1,C%PNLW ;LENGTH OF PROCESS NAME IN WORDS XMOVEI T3,.CBDPN(P1) ;DESTINATION ADDRESS IN CB EXTEND T1,[XBLT] ;MOVE THE SOURCE PROCESS NAME ;MOVE THE CONNECTION DATA SDM.01: SKIPN T2,DATA ;IS THERE ANY DATA TO MOVE? POPJ P, ;NO, RETURN MOVX T1,C%CDLW ;LENGTH OF CONNECTION DATA IN WORDS XMOVEI T3,.CBDTA(P1) ;DESTINATION ADDRESS IN CB EXTEND T1,[XBLT] ;MOVE THE CONNECTION DATA POPJ P, ;RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCA SUPPORT ROUTINES - HANDLE CALL FROM SYSAP ;ROUTINE TO HANDLE A CALL FROM THE SYSAP FOR CONNECTION MANAGEMENT ;FUNCTIONS. ;CALL: ; T1/ EVENT CODE ; P1/ CB ADDRESS ; PUSHJ P,SC.OUT ;RETURN: ; CPOPJ ON ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ NEW BLOCK STATE (ZERO IF NO CHANGE) ; T2/ NEW CONNECTION STATE (ZERO IF NO CHANGE) SC.OUT: MOVE T4,T1 ;SAVE THE EVENT IMULI T4,MXCNST ;COMPUTE TABLE INDEX LOAD T2,CBCNST,(P1) ;GET THE CONNECT STATE ADDI T4,-1(T2) ;STATES START AT 1 MOVE T2,TABLEX(T4) ;GET THE FLAGS TXNE T2,X.ERR ;IS EVENT LEGAL FOR CURRENT STATE? RETBAD (.SCSWS) ;NO, RETURN "WRONG STATE" ERROR LOAD T1,X.BSTAT,(T4) ;GET NEW BLOCK STATE LOAD T2,X.CSTAT,(T4) ;GET NEW CONNECTION STATE JRST CPOPJ1## ;SKIP RETURN SUBTTL SCA SUPPORT ROUTINES - SEND RESPONSE ;ROUTINE TO SEND A RESPONSE (IF NEEDED) TO AN INCOMING PACKET. ;CALL: ; T1/ OPCODE ; P1/ CB ADDRESS ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.RSP ;RETURN: ; CPOPJ ON ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS SC.RSP: SETZRO MH$CDT,(P2) ;CLEAR THE CREDIT FIELD SC.RS2: STOR T1,MH$MSG,(P2) ;STORE OPCODE MOVE T2,.MHSCI(P2) ;GET SOURCE CONNECT ID MOVEM T2,.MHDCI(P2) ;STORE AS THE RECEIVER'S CID MOVE T2,.CBSCI(P1) ;GET OUR SOURCE CONNECT ID MOVEM T2,.MHSCI(P2) ;STORE IN PACKET AS SENDING CID PUSHJ P,@SCMKPK(T1) ;STORE OPCODE-SPECIFIC DATA PJRST SC.PAK ;SEND THE PACKET AND RETURN SUBTTL SCA SUPPORT ROUTINES - SEND AN SCS CONTROL MESSAGE ;ROUTINE TO SEND AN SCS CONTROL MESSAGE. ;CALL: ; P1/ CB ADDRESS ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.RQS ;RETURN: ; CPOPJ ON ERROR ; CPOPJ1 ON SUCCESS SC.RQS: LOAD T1,CBBKST,(P1) ;GET THE BLOCK STATE LOAD T4,Y.OP,(T1) ;GET OPCODE TO BE SENT STOR T4,MH$MSG,(P2) ;STORE IT IN THE PACKET MOVE T1,.CBDCI(P1) ;GET DESTINATION CONNECT ID MOVEM T1,.MHDCI(P2) ;STORE MOVE T1,.CBSCI(P1) ;GET SOURCE CONNECT ID MOVEM T1,.MHSCI(P2) ;STORE PUSHJ P,@SCMKPK(T4) ;FILL IN OPCODE-SPECIFIC DATA LOAD T1,CBBKST,(P1) ;GET THE BLOCK STATE BACK LOAD T1,Y.STAT,(T1) ;GET THE NEW CONNECTION STATE SKIPE T1 ;UNLESS NO CHANGE DESIRED, STOR T1,CBCNST,(P1) ; STORE NEW CONNECT STATE LOAD T1,MH$MSG,(P2) ;GET THE OPCODE LOAD T1,Z.RSP,(T1) ;GET THE EXPECTED RESPONSE SKIPE T1 ;IF ONE IS EXPECTED, STOR T1,CBEXPR,(P1) ; STORE EXPECTED RESPONSE SETZRO CBBKST,(P1) ;INDICATE NOTHING IS PENDING PUSHJ P,SC.PAK ;SEND THE PACKET POPJ P, ;ERROR SETZRO CBBKST,(P1) ;INDICATE NOTHING IS PENDING JRST CPOPJ1## ;SKIP RETURN ;DISPATCH TABLE FOR ROUTINE TO FILL IN OPCODE-SPECIFIC DATA SCMKPK: IFIW SC.MOQ ;CONNECT_REQUEST IFIW SC.MOS ;CONNECT_RESPONSE IFIW SC.MAQ ;ACCEPT_REQUEST IFIW SC.MAS ;ACCEPT_RESPONSE IFIW SC.MRQ ;REJECT_REQUEST IFIW SC.MRS ;REJECT_RESPONSE IFIW SC.MDQ ;DISCONNECT_REQUEST IFIW SC.MDS ;DISCONNECT_RESPONSE IFIW SC.MCQ ;CREDIT_REQUEST IFIW SC.MCS ;CREDIT_RESPONSE SUBTTL SCA SUPPORT ROUTINES - FILL IN RESPONSE DATA ;ROUTINES CALLED BY SC.RSP TO FILL IN OPCODE-SPECIFIC DATA. ;CALL: ; P1/ CB ADDRESS ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ;RETURN: ; CPOPJ ALWAYS ;CONNECT_RESPONSE SC.MOS: SETZRO MH$MCR,(P2) ;MINIMUM CREDIT FIELD MUST BE ZERO POPJ P, ;RETURN ;ACCEPT_RESPONSE SC.MAS: POPJ P, ;RETURN ;REJECT_RESPONSE SC.MRS: POPJ P, ;RETURN ;DISCONNECT_RESPONSE SC.MDS: POPJ P, ;RETURN ;CREDIT_RESPONSE SC.MCS: POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - FILL IN REQUEST DATA ;ROUTINES CALLED BY SC.RSQ TO FILL IN OPCODE-SPECIFIC DATA. ;CALL: ; P1/ CB ADDRESS ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ;RETURN: ; CPOPJ ALWAYS ;CONNECT_REQUEST SC.MOQ: PUSHJ P,SC.SCF ;STORE CREDIT FIELD IN PACKET SETZM .MHDCI(P2) ;WE DON'T KNOW THE DESTINATION'S CID JRST MAQ.01 ;JOIN WITH ACCEPT_REQUEST CODE ;ACCEPT_REQUEST SC.MAQ: PUSHJ P,SC.SCF ;STORE CREDIT FIELD IN PACKET MAQ.01: LOAD T1,CBMNSC,(P1) ;GET THE MINIMUM SEND CREDIT STOR T1,MH$MCR,(P2) ;STORE ;MOVE THE DESTINATION PROCESS NAME MOVEI T1,C%PNLW ;NUMBER OF WORDS TO MOVE XMOVEI T2,.CBDPN(P1) ;SOURCE ADDRESS XMOVEI T3,.MGDPN(P2) ;DESTINATION ADDRESS EXTEND T1,[XBLT] ;MOVE THE DESTINATION PROCESS NAME ;MOVE THE SOURCE PROCESS NAME MOVEI T1,C%PNLW ;NUMBER OF WORDS TO MOVE XMOVEI T2,.CBSPN(P1) ;SOURCE ADDRESS XMOVEI T3,.MGSPN(P2) ;DESTINATION ADDRESS EXTEND T1,[XBLT] ;MOVE THE SOURCE PROCESS NAME ;MOVE THE INITIAL CONNECTION DATA MOVEI T1,C%CDLW ;NUMBER OF WORDS TO MOVE XMOVEI T2,.CBDTA(P1) ;SOURCE ADDRESS XMOVEI T3,.MGSDT(P2) ;DESTINATION ADDRESS EXTEND T1,[XBLT] ;MOVE THE CONNECTION DATA POPJ P, ;RETURN ;MAKE A REJECT_REQUEST SC.MRQ: ;FALL INTO SC.MDQ ;MAKE A DISCONNECT_REQUEST SC.MDQ: SETZRO MH$CDT,(P2) ;CREDIT FIELD MUST BE ZERO LOAD T1,CBSDRE,(P1) ;GET THE REASON FOR DISCONNECTING STOR T1,MH$STS,(P2) ;STORE SETZRO MH$MCR,(P2) ;MINIMUM CREDIT FIELD MUST BE ZERO POPJ P, ;RETURN ;MAKE A CREDIT_REQUEST SC.MCQ: PJRST SC.SCF ;STORE CREDIT FIELD IN PACKET AND RETURN SUBTTL SCA SUPPORT ROUTINES - SEND A MESSAGE ;ROUTINE TO SEND A MESSAGE. ;CALL: ; P2/ PACKET ADDRESS ; P5/ PBK ADDRESS ; PUSHJ P,SC.PAK ;RETURN: ; CPOPJ ON ERROR WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS SC.PAK: STKVAR ;ALLOCATE SOME STACK STORAGE LOAD T1,MH$MSG,(P2) ;GET THE OPCODE MOVEM T1,OPCODE ;SAVE IT FOR LATER LOAD T2,Z.LEN,(T1) ;GET LENGTH OF THIS MESSAGE PUSHJ P,SC.ROU ;BYTE SWAP THE PACKET HEADER FOR OUTPUT LOAD T3,Z.PRI,(T1) ;GET PRIORITY FOR THIS OPCODE LOAD T4,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDSMS##,) ;SEND THE PACKET (NO FLAGS) RETBAD () ;PASS ALONG THE ERROR MOVE T1,OPCODE ;RESTORE THE OPCODE AOS SNDTAB(T1) ;INCREMENT SEND COUNT JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCA SUPPORT ROUTINES - SET CREDIT FIELD IN PACKET ;ROUTINE TO STORE THE CREDIT FIELD IN THE PACKET AND ADJUST PENDING ;RECEIVE CREDIT. ;CALL: ; P1/ CB ADDRESS ; P2/ PACKET ADDRESS ; PUSHJ P,SC.SCF ;RETURN: ; CPOPJ ALWAYS SC.SCF: CIOFF ;PREVENT RACES LOAD T1,MH$MSG,(P2) ;GET THE MESSAGE TYPE CAIE T1,.STCRQ ;IS IT A CREDIT_REQUEST? JRST SCF.01 ;NO MOVE T1,.CBPRC(P1) ;GET PENDING RECEIVE CREDIT MOVEM T1,.CBRQC(P1) ;STORE AS REQUEST_CREDIT JRST SCF.02 ;CONTINUE SCF.01: MOVE T1,.CBPRC(P1) ;GET THE PENDING RECEIVE CREDIT ADDM T1,.CBRCD(P1) ;UPDATE THE RECEIVE CREDIT SCF.02: STOR T1,MH$CDT,(P2) ;STORE THE CREDIT FIELD SETZM .CBPRC(P1) ;ZERO THE PENDING RECEIVE CREDIT PJRST CIONPJ ;INTERRUPTS BACK ON AND RETURN SUBTTL SCA SUPPORT ROUTINES - DECLARE PROTOCOL COMPLETE ;ROUTINE TO DECLARE PROTOCOL COMPLETE. CALLED WHEN WE BELIEVE ;THERE SHOULD BE NO MORE OUTPUT SENT TO A NODE AND WE DON'T ;EXPECT ANY INPUT FROM IT. ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SC.PTC ;RETURN: ; CPOPJ ALWAYS SC.PTC: MOVX T1,CB.PTC ;GET THE PROTOCOL COMPLETE FLAG IORM T1,.CBFLG(P1) ;SET IN FLAGS WORD SETZRO CBBKST,(P1) ;CLEAR THE BLOCK STATE MOVX T1,CB.JSY ;GET THE JSYS CONNECTION FLAG TDNE T1,.CBFLG(P1) ;WAS THIS A JSYS CONNECTION? POPJ P, ;YES, CAN'T REAP NOW PJRST SC.SRB ;SET REAP BIT AND RETURN SUBTTL SCA BUFFER MANAGEMENT - QUEUE BUFFERS TO PPD ;ROUTINE TO QUEUE A (CHAIN OF) DATAGRAM BUFFER(S) TO THE PPD. ;CALL: ; T1/ ADDRESS OF FIRST BUFFER ; T2/ NUMBER OF BUFFERS ; P5/ PBK ADDRESS ; PUSHJ P,SC.QDB ;RETURN: ; CPOPJ ALWAYS SC.QDB: PUSH P,T2 ;SAVE THE COUNT LOAD T3,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDQDB##,) ;GIVE THE BUFFERS TO THE PPD POP P,T1 ;RESTORE COUNT ADDM T1,.CBDGR(P1) ;UPDATE DATAGRAM CREDIT POPJ P, ;RETURN ;ROUTINE TO QUEUE A (CHAIN OF) MESSAGE BUFFER(S) TO THE PPD. ;CALL: ; T1/ ADDRESS OF FIRST BUFFER ; T2/ NUMBER OF BUFFERS ; P5/ PBK ADDRESS ; PUSHJ P,SC.QMB ;RETURN: ; CPOPJ ALWAYS SC.QMB: PUSH P,T2 ;SAVE THE COUNT LOAD T3,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDQMB##,) ;GIVE THE BUFFERS TO THE PPD POP P,T1 ;RESTORE COUNT ADDM T1,.CBPRC(P1) ;UPDATE PENDING RECEIVE CREDIT POPJ P, ;RETURN SUBTTL SCA BUFFER MANAGEMENT - RETURN BUFFERS TO FREE POOL ;ROUTINE TO RETURN A CHAIN OF DATAGRAM BUFFERS TO THE FREE POOL. ;CALL: ; T1/ ADDRESS OF BUFFER LIST ; PUSHJ P,SC.MRD ;RETURN: ; CPOPJ ALWAYS SC.MRD: SAVEAC ;SAVE AN AC MRD.01: MOVE Q1,(T1) ;GET ADDRESS OF THE NEXT BUFFER PUSHJ P,SC.RLD ;RETURN A DATAGRAM SKIPE T1,Q1 ;WAS THERE A NEXT BUFFER? JRST MRD.01 ;YES, KEEP RETURNING POPJ P, ;RETURN ;ROUTINE TO RETURN A CHAIN OF MESSAGE BUFFERS TO THE FREE POOL. ;CALL: ; T1/ ADDRESS OF BUFFER LIST ; PUSHJ P,SC.MRM ;RETURN: ; CPOPJ ALWAYS SC.MRM: SAVEAC ;SAVE AN AC MRM.01: MOVE Q1,(T1) ;GET ADDRESS OF THE NEXT BUFFER PUSHJ P,SC.RBF ;RETURN A MESSAGE SKIPE T1,Q1 ;WAS THERE A NEXT BUFFER? JRST MRM.01 ;YES, KEEP RETURNING POPJ P, ;RETURN SUBTTL BUFFER MANAGEMENT ROUTINES - GET BUFFERS FOR SC.SNM OR SC.DEF ;ROUTINES TO GET BUFFERS FOR SC.SNM OR SC.DEF. SINCE TOPS-10 CAN'T ;HANDLE CREATING PAGES BY FAULTING THEM IN SC.BF2 IS ESSENTIALLY AN ;ELABORATE NO-OP. WE MIGHT BE ABLE TO CHECK NUMBER OF FREE PAGES ;IN CORE AND PERHAPS ALLOCATE FROM THAT POOL SOMEDAY. ;CALL: ; P1/ CONNECTION BLOCK ADDRESS ; P5/ PATH BLOCK ADDRESS ; PUSHJ P,SC.BF1 (IF CAN'T CREATE BUFFERS) ; PUSHJ P,SC.BF2 (IF CAN CREATE BUFFERS) ;RETURN: ; CPOPJ IF FAILED TO CREATE BUFFERS ; CPOPJ1 ON SUCCESS SC.BF1: TDZA T1,T1 ;CAN'T CREATE BUFFERS SC.BF2: SETO T1, ;CAN CREATE BUFFERS PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS MOVE P2,T1 ;SAVE THE FLAG LOAD T1,CBIMB,(P1) ;GET THE NUMBER OF MESSAGE BUFFERS NEEDED JUMPE T1,BFX.02 ;NONE, GO CHECK FOR DATAGRAM BUFFERS PUSHJ P,SC.ABF ;TRY TO GET THEM FROM SCA'S POOL SKIPA ;FAILED, HAVE TO CREATE THEM JRST BFX.01 ;SUCCEEDED, GIVE THEM TO THE PORT ;HERE IF WE DIDN'T HAVE ENOUGH BUFFERS IN SCA'S POOL. JUMPE P2,CPOPJ## ;RETURN IF WE CAN'T CREATE THEM LOAD T1,CBIMB,(P1) ;GET THE NUMBER OF BUFFERS AGAIN PUSHJ P,SC.CMG ;CREATE THE MESSAGE BUFFERS POPJ P, ;FAILED, TRY FOR DATAGRAMS ADDM T3,TOTMGB ;ADD TO TOTAL NUMBER OF MESSAGE BUFFERS CREATED ;SC.CMG MAY HAVE CREATED MORE THAN WE NEEDED. IF SO, MAKE A CHAIN OF THE ;EXTRA BUFFERS AND RETURN TO SCA'S POOL. LOAD P4,CBIMB,(P1) ;THE NUMBER WE WANTED CAMN P4,T3 ;SAME AS THE NUMBER CREATED? JRST BFX.01 ;YES, QUEUE THE BUFFER CHAIN IMMEDIATELY ;WE GOT MORE THAN WE WANTED. MAKE A CHAIN OF THE DESIRED NUMBER. MOVE P3,T1 ;SAVE THE ADDRESS OF THE BUFFER CHAIN MOVE T2,T1 ;INITIALIZE THE LOOP MOVE T3,T2 ;SAVE THE ADDRESS OF THE PREVIOUS BUFFER MOVE T2,(T2) ;GET THE ADDRESS OF THE NEXT BUFFER SOJG P4,.-2 ;LOOP FOR THE NUMBER DESIRED SETZM (T3) ;ZERO THE FORWARD POINTER OF THE LAST REQ'D BUFFER ;RETURN THE EXCESS BUFFERS CREATED BY SC.CMG TO THE SCA FREE POOL MOVE T1,T2 ;GET THE ADDRESS OF THE CURRENT BUFFER PUSHJ P,SC.MRM ;RETURN MESSAGES TO FREE POOL MOVE T1,P3 ;GET THE ADDRESS OF THE BUFFER CHAIN ;QUEUE THE BUFFERS TO THE PORT QUEUE BFX.01: LOAD T2,CBIMB,(P1) ;GET THE NUMBER OF BUFFERS IN THE CHAIN PUSHJ P,SC.QMB ;GIVE THEM TO THE PORT SETZRO CBIMB,(P1) ;NO LONGER NEED TO ASK FOR THESE BUFFERS ;HANDLE DATAGRAMS BFX.02: LOAD T1,CBIDB,(P1) ;GET NUMBER OF DATAGRAM BUFFERS TO CREATE JUMPE T1,CPOPJ1## ;NONE, NOTHING ELSE TO DO PUSHJ P,SC.ALD ;ALLOCATE THE DATAGRAMS FROM SCA'S POOL SKIPA ;FAILED, HAVE TO CREATE THEM JRST BFX.03 ;SUCCEEDED, GIVE THEM TO THE PORT ;DIDN'T HAVE ENOUGH IN SCA'S POOL. CREATE THEM. JUMPE P2,CPOPJ## ;RETURN IF CAN'T CREATE THEM LOAD T1,CBIDB,(P1) ;GET THE NUMBER NEEDED PUSHJ P,SC.CDG ;CREATE THE DATAGRAMS POPJ P, ;FAILED ADDM T3,TOTDGB ;ADD TO TOTAL DATAGRAM BUFFERS CREATED ;SC.CDG MAY HAVE CREATED MORE THAN WE NEEDED. IF SO, MAKE A CHAIN OF THE ;EXTRA BUFFERS AND RETURN TO SCA'S POOL. LOAD P4,CBIDB,(P1) ;NUMBER WE WANTED CAMN P4,T3 ;SAME AS THE NUMBER CREATED? JRST BFX.03 ;YES, QUEUE THE BUFFER CHAIN IMMEDIATELY ;WE GOT MORE THAN WE WANTED. MAKE A CHAIN OUT OF THE DESIRED NUMBER. MOVE P3,T1 ;SAVE THE ADDRESS OF THE BUFFER CHAIN MOVE T2,T1 ;INITIALIZE FOR LOOP MOVE T3,T2 ;SAVE THE ADDRESS OF THE PREVIOUS BUFFER MOVE T2,(T2) ;GET THE ADDRESS OF THE NEXT BUFFER SOJG P4,.-2 ;LOOP UNTIL WE HAVE THE NUMBER REQUESTED SETZM (T3) ;ZERO THE FLINK OF THE LAST REQ'D BUFFER ;RETURN THE EXCESS BUFFERS CREATED BY SC.CDG TO THE SCA FREE POOL MOVE T1,T2 ;GET THE ADDRESS OF THE CURRENT BUFFER PUSHJ P,SC.MRD ;RETURN DATAGRAMS TO FREE POOL MOVE T1,P3 ;GET THE ADDRESS OF THE BUFFER CHAIN ;HERE WHEN WE ARE READY TO QUEUE THE BUFFERS TO THE PORT QUEUE BFX.03: LOAD T2,CBIDB,(P1) ;GET THE NUMBER OF DATAGRAMS REQUESTED PUSHJ P,SC.QDB ;QUEUE THE DATAGRAM BUFFERS SETZRO CBIDB,(P1) ;NO LONGER NEED TO ASK FOR THESE BUFFERS JRST CPOPJ1## ;SKIP RETURN SUBTTL SCA SUPPORT ROUTINES - SET BUFFER THRESHOLD ;ROUTINE TO SET THE BUFFER THRESHOLDS BASED ON THE NUMBER OF ;PATHS CURRENTLY ONLINE. ;CALL: ; PUSHJ P,SC.SBT ;RETURN: ; CPOPJ ALWAYS ;UPDATES MINMSG WITH NEW MESSAGE BUFFER THRESHOLD ;UPDATES MINDG WITH NEW DATAGRAM BUFFER THRESHOLD SC.SBT: MOVE T1,PBCNT ;GET CURRENT NUMBER OF ONLINE PATHS IMUL T1,MBPP ;MULTIPLY BY THRESHOLD PER PATH ADD T1,MGTRSH ;ADD THE THRESHOLD WE MUST HAVE AROUND MOVEM T1,MINMSG ;UPDATE THE MINIMUM MESSAGE BUFFER COUNT MOVE T1,PBCNT ;GET CURRENT NUMBER OF ONLINE PATHS IMUL T1,DBPP ;MULTIPLY BY THRESHOLD PER PATH ADD T1,DGTRSH ;ADD THE THRESHOLD WE MUST HAVE AROUND MOVEM T1,MINDG ;UPDATE THE MINIMUM DATAGRAM BUFFER COUNT POPJ P, ;RETURN SUBTTL SCA BUFFER MANAGEMENT - ALLOCATE LONG DATAGRAM BUFFERS ;ROUTINE TO OBTAIN LONG DATAGRAM BUFFERS FROM SCA. WHEN YOU WISH TO ;RECEIVE A LONG DATAGRAM YOU MUST QUEUE A BUFFER OBTAINED FROM HERE. ;CALL: ; T1/ NUMBER OF BUFFERS DESIRED ;RETURN: ; CPOPJ IF COULDN'T ALLOCATE DESIRED NUMBER OF BUFFERS ; CPOPJ1 IF SUCCESS WITH: ; T1/ ADDRESS OF FIRST BUFFER IN THE CHAIN ; T2/ NUMBER OF BUFFERS RETURNED ; T3/ ADDRESS OF ROUTINE TO CALL TO RETURN BUFFERS ;NOTE: IF THE CALLER SETS T1 NEGATIVE (KLPSER) THEY ARE INDICATING THEY ;WISH TO OVER-RIDE THE THRESHOLD CHECK. THIS IS NORMALLY DONE ONLY WHEN ;THE KLIPA IS BEING INITIALIZED. $XSENT (SC.ALD::) ;EXTENDED ENTRY POINT MOVM T2,T1 ;GET A (POSITIVE) COPY WE CAN WORK WITH CIOFF ;PREVENT RACES SUB T2,DFQCNT ;NUMBER LEFT AFTER SATISFYING THIS REQUEST JUMPG T2,ALD.04 ;IF MORE THAN WE HAVE AVAILABLE, REFUSE REQUEST MOVMS T2 ;GET THE MAGNITUDE SKIPL T1 ;SKIP IF OVER-RIDING THRESHOLD CHECK CAML T2,DGTRSH ;WILL THERE BE ENOUGH LEFT OVER AFTER REQUEST? JRST ALD.01 ;YES, DO THE WORK SKIPE DINITF## ;INITIALIZATION? JRST ALD.01 ;YES CAML T1,LRGREQ ;IS THIS A SMALL REQUEST? JRST ALD.04 ;NO, REFUSE THE LARGE REQUEST AOS DBUST ;COUNT ANOTHER SMALL REQUEST BUSTING THRESHOLD ;HERE TO HONOR THE REQUEST ALD.01: STKVAR ;ALLOCATE SOME STACK STORAGE MOVMS T1 ;JUST GET MAGNITUDE MOVEM T1,NUMBUF ;SAVE THE NUMBER OF BUFFERS REQUESTED MOVE T4,T1 ;WORKING COPY OF THE REQUEST SIZE SKIPN T1,TOPDFQ ;IS THERE A FIRST BUFFER? JRST ALD.05 ;NO, FREE COUNT WAS INCORRECT MOVE T2,T1 ;START BUFFER LOOP WITH ADDRESS OF FIRST BUFFER SOJLE T4,ALD.02 ;IF NO MORE BUFFERS, FIX UP COUNT AND POINTERS SKIPE T2,(T2) ;ON TO THE NEXT BUFFER JRST .-2 ;LOOP FOR MORE ENTRIES JRST ALD.05 ;NO ENTRY, FREE COUNT WAS INCORRECT ;HERE WHEN WE KNOW ENOUGH BUFFERS ARE AVAILABLE FOR THE REQUEST. ;T1/ ADDRESS OF FIRST BUFFER T2/ ADDRESS OF LAST BUFFER ALD.02: SKIPE T3,(T2) ;GET THE ADDRESS OF THE NEW FIRST BUFFER JRST ALD.03 ;THERE ARE BUFFERS LEFT XMOVEI T4,TOPDFQ ;NO NEXT BUFFER, GET POINTER TO TOP OF QUEUE MOVEM T4,BOTDFQ ;INIT THE BLINK AS POINTER TO FLINK AOS CIBUF ;ASK SC.DEF TO RUN ALD.03: MOVEM T3,TOPDFQ ;SAVE THE NEW QUEUE FLINK SETZM (T2) ;CLEAR FLINK IN LAST BUFFER MOVN T3,NUMBUF ;GET THE NUMBER OF BUFFERS ISSUED ADDM T3,DFQCNT ;ACCOUNT FOR THESE IN BUFFER COUNTS MOVE T3,MINDG ;NUMBER OF BUFFERS WE SHOULD HAVE AROUND CAML T3,DFQCNT ;ARE THERE ENOUGH BUFFERS AROUND? AOS CIBUF ;ASK SC.DEF TO RUN CION ;OK TO INTERRUPT AGAIN MOVE T2,NUMBUF ;RETURN THE NUMBER OF BUFFERS CREATED MOVE T3,[MCSEC1+SC.RLD] ;TELL CALLER HOW TO RETURN THEM JRST CPOPJ1## ;SKIP RETURN ;HERE TO REFUSE THE REQUEST. DO SOME BOOKKEEPING FIRST. ALD.04: MOVMS T1 ;GET THE MAGNITUDE ADD T1,ASRDR ;ADD CURRENT AVERAGE SIZE TO NEW REQUEST SKIPE RDRCNT ;DON'T AVERAGE IF THIS IS THE FIRST TIME THROUGH IDIVI T1,2 ;TAKE THE AVERAGE OF THE TWO MOVEM T1,ASRDR ;UPDATE THE AVERAGE SIZE OF REFUSED REQUEST AOS RDRCNT ;INCREMENT THE NUMBER OF REFUSED REQUESTS RETBAD (.SCNEB,) ;RETURN AN ERROR ;HERE WHEN THE FREE COUNT WAS INCORRECT (WE HAD LESS BUFFERS THAN ;THE FREE COUNT CLAIMED). ALD.05: AOS CIBUF ;ASK SC.DEF TO RUN AOS NDBCNT ;COUNT THIS EVENT AOS RDRCNT ;INCREMENT THE NUMBER OF REFUSED REQUESTS MOVE T1,NUMBUF ;GET THE REQUEST SIZE AGAIN ADD T1,ASRDR ;ADD CURRENT AVERAGE SIZE TO NEW REQUEST IDIVI T1,2 ;TAKE THE AVERAGE OF THE TWO MOVEM T1,ASRDR ;UPDATE THE AVERAGE SIZE OF REFUSED REQUEST ;NOW FIX THE BUFFER COUNT SETZ T2, ;START AT ZERO SKIPN T1,TOPDFQ ;IS THE QUEUE EMPTY? JRST ALD.06 ;YES AOS T2 ;COUNT THE INITIAL BUFFER SKIPE T1,(T1) ;IS THERE A NEXT BUFFER? AOJA T2,.-1 ;YES, CONTINUE TO COUNT BUFFERS MOVEM T2,DFQCNT ;SAVE THE NEW CORRECT COUNT RETBAD (.SCNEB,) ;RETURN AN ERROR ;HERE WHEN QUEUE WAS EMPTY ALD.06: XMOVEI T1,TOPDFQ ;GET A POINTER TO THE QUEUE FLINK MOVEM T1,BOTDFQ ;INIT THE QUEUE TAIL POINTER SETZM TOPDFQ ;INIT THE QUEUE HEAD POINTER SETZM DFQCNT ;MAKE THE COUNT CORRECT RETBAD (.SCNEB,) ;RETURN AN ERROR SUBTTL SCA BUFFER MANAGEMENT - ALLOCATE BUFFERS ;ROUTINE TO OBTAIN MESSAGE BUFFERS FROM SCA. WHEN YOU WISH TO SEND ;OR RECEIVE A MESSAGE YOU MUST OBTAIN THE BUFFER FROM HERE. ;CALL: ; T1/ NUMBER OF BUFFERS DESIRED ; PUSHJ P,SC.ABF ;RETURN: ; CPOPJ IF COULDN'T ALLOCATE DESIRED NUMBER OF BUFFERS ; CPOPJ1 IF SUCCESS WITH: ; T1/ ADDRESS OF FIRST BUFFER IN THE CHAIN ; T2/ NUMBER OF BUFFERS RETURNED ; T3/ ADDRESS OF ROUTINE TO CALL TO RETURN BUFFERS $XSENT (SC.ABF::) ;EXTENDED ENTRY POINT MOVE T2,T1 ;GET A COPY WE CAN WORK WITH CIOFF ;PREVENT RACES SUB T2,MFQCNT ;NUMBER LEFT AFTER SATISFYING THIS REQUEST JUMPG T2,ABF.04 ;IF MORE THAN WE HAVE AVAILABLE, REFUSE REQUEST MOVMS T2 ;GET THE MAGNITUDE CAML T2,MGTRSH ;WILL THERE BE ENOUGH LEFT OVER AFTER REQUEST? JRST ABF.01 ;YES, DO THE WORK SKIPE DINITF## ;INITIALIZATION? JRST ABF.01 ;YES CAML T1,LRGREQ ;IS THIS A SMALL REQUEST? JRST ABF.04 ;NO, REFUSE THE LARGE REQUEST AOS MBUST ;COUNT ANOTHER SMALL REQUEST BUSTING THRESHOLD ;HERE TO HONOR THE REQUEST ABF.01: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,NUMBUF ;SAVE THE NUMBER OF BUFFERS REQUESTED MOVE T4,T1 ;WORKING COPY OF THE REQUEST SIZE SKIPN T1,TOPMFQ ;IS THERE A FIRST BUFFER? JRST ABF.05 ;NO, FREE COUNT WAS INCORRECT MOVE T2,T1 ;START BUFFER LOOP WITH ADDRESS OF FIRST BUFFER SOJLE T4,ABF.02 ;IF NO MORE BUFFERS, FIX UP COUNT AND POINTERS SKIPE T2,(T2) ;ON TO THE NEXT BUFFER JRST .-2 ;LOOP FOR MORE ENTRIES JRST ABF.05 ;NO ENTRY, FREE COUNT WAS INCORRECT ;HERE WHEN WE KNOW ENOUGH BUFFERS ARE AVAILABLE FOR THE REQUEST. ;T1/ ADDRESS OF FIRST BUFFER T2/ ADDRESS OF LAST BUFFER ABF.02: SKIPE T3,(T2) ;GET THE ADDRESS OF THE NEW FIRST BUFFER JRST ABF.03 ;THERE ARE BUFFERS LEFT XMOVEI T4,TOPMFQ ;NO NEXT BUFFER, GET POINTER TO TOP OF QUEUE MOVEM T4,BOTMFQ ;INIT THE BLINK AS POINTER TO FLINK AOS CIBUF ;ASK SC.DEF TO RUN ABF.03: MOVEM T3,TOPMFQ ;SAVE THE NEW QUEUE FLINK SETZM (T2) ;CLEAR FLINK IN LAST BUFFER MOVN T3,NUMBUF ;GET THE NUMBER OF BUFFERS ISSUED ADDM T3,MFQCNT ;ACCOUNT FOR THESE IN BUFFER COUNTS MOVE T3,MINMSG ;NUMBER OF BUFFERS WE SHOULD HAVE AROUND CAML T3,MFQCNT ;ARE THERE ENOUGH BUFFERS AROUND? AOS CIBUF ;ASK SC.DEF TO RUN CION ;OK TO INTERRUPT MOVE T2,NUMBUF ;RETURN THE NUMBER OF BUFFERS CREATED MOVE T3,[MCSEC1+SC.RBF] ;TELL CALLER HOW TO RETURN THEM JRST CPOPJ1## ;SKIP RETURN ;HERE TO REFUSE THE REQUEST. DO SOME BOOKKEEPING FIRST. ABF.04: ADD T1,ASRMR ;ADD CURRENT AVERAGE SIZE TO NEW REQUEST SKIPE RMRCNT ;DON'T AVERAGE IF THIS IS THE FIRST TIME THROUGH IDIVI T1,2 ;TAKE THE AVERAGE OF THE TWO MOVEM T1,ASRMR ;UPDATE THE AVERAGE SIZE OF REFUSED REQUEST AOS RMRCNT ;INCREMENT THE NUMBER OF REFUSED REQUESTS RETBAD (.SCNEB,) ;RETURN AN ERROR ;HERE WHEN THE FREE COUNT WAS INCORRECT (WE HAD LESS BUFFERS THAN ;THE FREE COUNT CLAIMED). ABF.05: AOS CIBUF ;ASK SC.DEF TO RUN AOS NMBCNT ;COUNT THIS EVENT AOS RMRCNT ;INCREMENT THE NUMBER OF REFUSED REQUESTS MOVE T1,NUMBUF ;GET THE REQUEST SIZE AGAIN ADD T1,ASRMR ;ADD CURRENT AVERAGE SIZE OF NEW REQUEST IDIVI T1,2 ;TAKE THE AVERAGE OF THE TWO MOVEM T1,ASRMR ;UPDATE THE AVERAGE SIZE OF REFUSED REQUEST ;NOW FIX THE BUFFER COUNT SETZ T2, ;START AT ZERO SKIPN T1,TOPMFQ ;IS THE QUEUE EMPTY? JRST ABF.06 ;YES AOS T2 ;COUNT THE INITIAL BUFFER SKIPE T1,(T1) ;IS THERE A NEXT BUFFER? AOJA T2,.-1 ;YES, CONTINUE TO COUNT BUFFERS MOVEM T2,MFQCNT ;SAVE THE NEW CORRECT COUNT RETBAD (.SCNEB,) ;RETURN AN ERROR ;HERE WHEN QUEUE WAS EMPTY ABF.06: XMOVEI T1,TOPMFQ ;GET A POINTER TO THE QUEUE FLINK MOVEM T1,BOTMFQ ;INIT THE QUEUE TAIL POINTER SETZM TOPMFQ ;INIT THE QUEUE HEAD POINTER SETZM MFQCNT ;MAKE THE COUNT CORRECT RETBAD (.SCNEB,) ;RETURN AN ERROR SUBTTL BUFFER MANAGEMENT ROUTINES - CREATE MESSAGE/DATAGRAM BUFFERS ;ROUTINE TO CREATE MESSAGE OR DATAGRAM BUFFERS. IT IS INTENDED TO ;BE CALLED DURING "PROCESS CONTEXT" WHICH DOESN'T EXIST IN TOPS-10. ;SOMEDAY THIS ROUTINE MIGHT BE CLEVER ENOUGH TO GRAB FREE PAGES FROM ;PAGTAB BUT FOR NOW JUST GIVE UP UNLESS IN INITIALIZATION. ;CALL: ; T1/ NUMBER OF BUFFERS TO CREATE ; PUSHJ P,SC.CMG/SC.CDG ;RETURN: ; CPOPJ ON ERRORS WITH: ; T1/ ERROR CODE ; CPOPJ1 ON SUCCESS WITH: ; T1/ ADDRESS OF FIRST BUFFER ; T2/ ADDRESS OF LAST BUFFER ; T3/ NUMBER OF BUFFERS RETURNED ; ;NOTE: SINCE THE NUMBER OF BUFFERS IS ROUNDED UP TO AN INTEGRAL ;DIVISOR OF A PAGE WE MAY CREATE MORE BUFFERS THAN REQUESTED. THE ;CALLER SHOULD GIVE BACK THE EXTRA BUFFERS IT DOESN'T WANT. SC.CMG: TDZA T2,T2 ;CLEAR THE DATAGRAM FLAG SC.CDG: SETO T2, ;SET THE DATAGRAM FLAG SAVEAC ;SAVE SOME AC'S STKVAR ;ALLOCATE SOME STACK STORAGE DMOVE T3,[EXP C%MGSZ,C%MGPG] ;ASSUME MESSAGE BUFFERS SKIPE T2 ;REALLY WANT DATAGRAM BUFFERS? DMOVE T3,[EXP C%DGSZ,C%DGPG] ;YES, USE DIFFERENT VARIABLES MOVEM T3,BUFSZ ;SAVE BUFFER SIZE MOVEM T4,NUMPPG ;SAVE NUMBER OF BUFFERS PER PAGE MOVE Q1,T1 ;GET THE REQUEST SIZE IN BUFFERS IDIV Q1,NUMPPG ;NUMBER OF PAGES TO REQUEST SKIPE Q2 ;ANY REMAINDER? AOS Q1 ;YES, ROUND UP THE PAGE COUNT MOVE T1,Q1 ;GET THE NUMBER OF PAGES TO CREATE IMUL T1,NUMPPG ;FIND THE TOTAL NUMBER OF BUFFERS WE'LL CREATE MOVEM T1,NUMBUF ;SAVE FOR RETURN TO CALLER MOVE T1,Q1 ;GET THE NUMBER OF PAGES DESIRED PUSHJ P,PGRSKD## ;CREATE THE SPACE POPJ P, ;NICE TRY MOVE T2,BUFSZ ;GET THE SIZE OF A BUFFER AOS (P) ;SET FOR SKIP RETURN PJRST SC.BBF ;BREAK THE PAGES INTO BUFFERS AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCA BUFFER MANAGEMENT - BREAK MEMORY INTO BUFFERS ;ROUTINE TO BREAK A CHAIN OF PAGES INTO A CHAIN OF MESSAGE BUFFERS. ;CALL: ; T1/ ADDRESS OF FIRST PAGE IN CHAIN ; T2/ BUFFER SIZE ; PUSHJ P,SC.BBF ;RETURN: ; CPOPJ ALWAYS WITH: ; T1/ ADDRESS OF FIRST BUFFER IN CHAIN ; T2/ ADDRESS OF LAST BUFFER IN CHAIN ; T3/ NUMBER OF BUFFERS CREATED SC.BBF: PUSHJ P,SAVE2## ;SAVE P1 AND P2 TRVAR ;ALLOCATE A WORD OF STACK STORAGE ADDI T2,C%BINV ;ADD INVISIBLE SPACE SIZE TO BUFFER SIZE MOVEM T2,BUFSIZ ;SAVE THE ALLEGED BUFFER SIZE MOVE P1,T1 ;SAVE THE CALLERS LIST POINTER ADDI T1,C%BINV ;CREATE THE INVISIBLE BUFFER AREA MOVE T2,T1 ;FOR INIT, TAIL IS SAME AS HEAD POINTER SETZ P2, ;INIT THE COUNT AT ZERO MOVEI T3,PAGSIZ ;GET THE SIZE OF A PAGE MOVE P1,(P1) ;GET THE ADDRESS OF THE NEXT PAGE MOVE T4,T1 ;INIT NEXT ADDRESS AS FIRST ADDRESS BBF.01: CAMG T3,BUFSIZ ;HAVE WE RUN OUT OF ROOM IN THIS PAGE? JRST BBF.02 ;YES, DO THE NEXT PAGE AOS P2 ;COUNT THIS BUFFER IN THE TOTAL MOVE T2,T4 ;UPDATE THE TAIL POINTER MOVE T4,BUFSIZ ;GET THE SIZE OF A BUFFER ADD T4,T2 ;MAKE IT THE ADDRESS OF THE NEXT BUFFER MOVEM T4,(T2) ;LINK IT ONTO THE LIST SUB T3,BUFSIZ ;UPDATE PAGE SPACE COUNTER JRST BBF.01 ;LOOP OVER THE WHOLE PAGE BBF.02: SETZM (T2) ;ZERO NEXT POINTER IN CASE WE'RE DONE JUMPE P1,BBF.03 ;WE'RE DONE IF NO NEXT PAGE TO DO MOVE T4,P1 ;GET ADDRESS OF NEXT PAGE ADDI T4,C%BINV ;CREATE THE INVISIBLE SPACE MOVEM T4,(T2) ;LINK LAST PAGE TO NEW PAGE MOVE P1,(P1) ;GET THE ADDRESS OF THE NEXT PAGE MOVEI T3,PAGSIZ ;RESET THE PAGE SPACE COUNTER JRST BBF.01 ;AND BREAK THIS PAGE INTO BUFFERS BBF.03: MOVE T3,P2 ;GET THE COUNT OF BUFFERS IN T3 POPJ P, ;RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCA BUFFER MANAGEMENT - RETURN A BUFFER ;ROUTINE TO RETURN A BUFFER OBTAINED BY A CALL TO SC.ABF. ;CALL: ; T1/ ADDRESS OF BUFFER ; PUSHJ P,SC.RBF ;RETURN: ; CPOPJ ALWAYS $XSENT (SC.RBF::) ;EXTENDED ENTRY POINT MOVE T4,T1 ;SAVE THE ADDRESS OF THE BUFFER MOVE T2,T1 ;THIS IS THE START ADDRESS SUBI T2,C%BINV ;MOVE BACK TO THE START OF THE INVISIBLE AREA MOVE T3,T2 ;DESTINATION ADDRESS TO T3 AOS T3 ;... MOVX T1,-1 ;NUMBER OF WORDS TO ZERO SETZM (T2) ;CLEAR THE FIRST WORD EXTEND T1,[XBLT] ;CLEAR THE REMAINDER CIOFF ;PREVENT RACES MOVEM T4,@BOTMFQ ;LINK THIS BUFFER AT THE END OF THE LIST MOVEM T4,BOTMFQ ;STORE THE NEW FREE QUEUE BOTTOM POINTER SETZM (T4) ;MAKE SURE THE FLINK OF LAST BUFFER IS ZERO AOS MFQCNT ;UPDATE THE BUFFER COUNT PJRST CIONPJ ;INTERRUPTS BACK ON AND RETURN SUBTTL SCA BUFFER MANAGEMENT - RETURN A LONG DATAGRAM BUFFER ;ROUTINE TO RETURN A LONG DATAGRAM BUFFER OBTAINED BY A CALL TO SC.ALD. ;CALL: ; T1/ ADDRESS OF BUFFER ; PUSHJ P,SC.RLD ;RETURN: ; CPOPJ ALWAYS $XSENT (SC.RLD::) ;EXTENDED ENTRY POINT MOVE T4,T1 ;SAVE THE ADDRESS OF THE BUFFER MOVE T2,T1 ;THIS IS THE START ADDRESS SUBI T2,C%BINV ;MOVE BACK TO THE START OF THE INVISIBLE AREA MOVE T3,T2 ;DESTINATION ADDRESS TO T3 AOS T3 ;... MOVX T1,-1 ;NUMBER OF WORDS TO ZERO SETZM (T2) ;CLEAR THE FIRST WORD EXTEND T1,[XBLT] ;CLEAR THE REMAINDER CIOFF ;PREVENT RACES MOVEM T4,@BOTDFQ ;LINK THIS BUFFER AT THE END OF THE LIST MOVEM T4,BOTDFQ ;STORE THE NEW FREE QUEUE BOTTOM POINTER SETZM (T4) ;MAKE SURE THE FLINK OF LAST BUFFER IS ZERO AOS DFQCNT ;UPDATE THE BUFFER COUNT PJRST CIONPJ ;INTERRUPTS BACK ON AND RETURN SUBTTL SCA SUPPORT ROUTINES - BYTE SWAP HEADERS ;ROUTINE TO PERFORM MAGIC ON THE PACKET HEADER WORDS. SINCE THE ;VAX AND THE 11'S HAVE THEIR NUMBERS BACKWARD WE MUST SWAP THE ;ORDER OF THE BYTES THAT GO OUT AND COME IN FROM THESE SYSTEMS. ;SWAP BYTES IN AN INCOMING MESSAGE. ;CALL: ; P2/ PACKET ADDRESS ;RETURN: ; CPOPJ ALWAYS SC.RIN: SAVEAC ;DON'T SMASH ANY AC'S MOVE T1,.MHTYP(P2) ;GET THE MESSAGE TYPE WORD LDB P1,[POINT 1,T1,24] ;GET -11 STYLE SIGN BIT PUSHJ P,SC.ISW ;SWAP THE BYTES INTO -10 FORMAT SKIPE P1 ;WAS THE NUMBER OF CREDITS NEGATIVE? TXO T1,3B1 ;YES, LIGHT THE BITS TO MAKE THIS A -10 -VE NUMBER MOVEM T1,.MHTYP(P2) ;PUT IT BACK LOAD T1,MH$MSG,(P2) ;GET THE MESSAGE TYPE CAIE T1,.STADG ;IS THIS AN APPLICATION DATAGRAM CAIN T1,.STAMG ; OR MESSAGE? POPJ P, ;YES, SKIP STATUS AND MINIMUM CREDIT WORD MOVE T1,.MHSTS(P2) ;NO, GET STATUS WORD PUSHJ P,SC.ISW ;SWAP THE BYTES INTO -10 FORMAT MOVEM T1,.MHSTS(P2) ;PUT IT BACK POPJ P, ;RETURN ;SWAP THE BYTES IN AN OUTGOING MESSAGE. ;CALL: ; P2/ PACKET ADDRESS ; PUSHJ P,SC.ROU ;RETURN: ; CPOPJ ALWAYS SC.ROU: PUSHJ P,SAVT## ;SAVE THE T REGISTERS LOAD T1,MH$MSG,(P2) ;GET THE MESSAGE TYPE CAIE T1,.STADG ;IS THIS AN APPLICATION DATAGRAM CAIN T1,.STAMG ; OR MESSAGE? JRST ROU.01 ;YES, SKIP STATUS AND MINIMUM CREDIT WORD MOVE T1,.MHSTS(P2) ;GET THE STATUS WORD PUSHJ P,SC.OSW ;SWAP THE BYTES INTO -11 FORMAT MOVEM T1,.MHSTS(P2) ;PUT IT BACK ROU.01: MOVE T1,.MHTYP(P2) ;GET THE CREDIT AND MESSAGE TYPE WORD SKIPGE T1 ;IS IT NEGATIVE? TXZ T1,3B1 ;YES, TURN OFF EXTRANEOUS SIGN BITS PUSHJ P,SC.OSW ;SWAP THE BYTES INTO -11 FORMAT MOVEM T1,.MHTYP(P2) ;PUT IT BACK POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - SWAP WORD FROM 11 TO 10 FORMAT ;ROUTINE TO SWAP A WORD FROM 11 TO 10 FORMAT. ;CALL: ; T1/ WORD TO BE SWAPPED ; PUSHJ P,SC.ISW ;RETURN: ; CPOPJ ALWAYS WITH: ; T1/ WORD WITH BYTES SWAPPED ; ;INPUT FORMAT: ; 2 16-BIT HALF WORDS, LEFT JUSTIFIED ; ; !=======================================================! ; ! B (LSB) ! B (MSB) ! A (LSB) ! A (MSB) ! IGN ! ; !=======================================================! ; 0 7 8 15 16 23 24 31 32 35 ; ;WHERE A AND B ARE THE HALF WORDS, AND LSB ARE THE LEAST SIGNIFICANT ;BITS AND MSB ARE THE MOST SIGNIFICANT BITS. ; ;THE CONTENTS OF BITS 32 THROUGH 35 ARE IGNORED. ; ;OUTPUT FORMAT: ; 2 18-BIT HALF WORDS ; ; !=======================================================! ; !X! BYTE A (MSB+LSB) !X! BYTE B (MSB +LSB) ! ; !=======================================================! ; 0 2 17 20 35 ; ;X DENOTES THE 2 BIT FIELD WITHIN EACH HALFWORD THAT WILL ALWAYS BE ZERO. SC.ISW: LDB T2,EA$MSB ;BYTE A, MSB LDB T3,EA$LSB ;BYTE A, LSB LDB T4,EB$MSB ;BYTE B, MSB LSH T1,-^D28 ;MOVE BYTE B, LSB INTO ITS POSITION FOR THE 10 DPB T4,TB$MSB ;NOW REPLACE THE BYTES IN THEIR 10 POSITIONS DPB T3,TA$LSB ;. . . DPB T2,TA$MSB ;. . . POPJ P, ;DONE SUBTTL SCA SUPPORT ROUTINES - SWAP WORD FROM 10 TO 11 FORMAT ;ROUTINE TO SWAP A WORD FROM 10 TO 11 FORMAT. ;CALL: ; T1/ WORD TO SWAP ; PUSHJ P,SC.OSW ;RETURN: ; CPOPJ ALWAYS WITH: ; T1/ WORD WITH BYTES SWAPPED ; ;INPUT FORMAT: ; 2 18-BIT HALF WORDS ; ; !=======================================================! ; ! BYTE A (MSB+LSB) ! BYTE B (MSB +LSB) ! ; !=======================================================! ; 0 17 18 35 ; ;OUTPUT FORMAT: ; 2 16-BIT HALF WORDS, LEFT JUSTIFIED ; ; !=======================================================! ; ! B (LSB) ! B (MSB) ! A (LSB) ! A (MSB) ! IGN ! ; !=======================================================! ; 0 7 8 15 16 23 24 31 32 35 ; ;WHERE A AND B ARE THE HALF WORDS, AND LSB ARE THE LEAST SIGNIFICANT BITS ;AND MSB ARE THE MOST SIGNIFICANT BITS. SC.OSW: LDB T2,TA$MSB ;GET TEN BYTE A, MSB LDB T3,TA$LSB ;TEN BYTE A, LSB LDB T4,TB$MSB ;TEN BYTE B, MSB LSH T1,^D28 ;MOVE TEN BYTE B, LSB INTO CORRECT POSITION DPB T4,EB$MSB ;ELEVEN BYTE B, MSB DPB T3,EA$LSB ;ELEVEN BYTE A, LSB DPB T2,EA$MSB ;ELEVEN BYTE A, MSB POPJ P, ;DONE SUBTTL SCA SUPPORT ROUTINES - BUFFER MANAGEMENT INTERLOCKING ;ROUTINE TO INTERLOCK ACCESS TO SCA BUFFER MANAGEMENT. ;CALLED DIRECTLY OR VIA EXPANSION OF CIOFF MACRO. $CSUB ;ENTIRE ROUTINE IN HIGH SEG SC.POF::CONO PI,PI.OFF ;TURN OFF THE PI SYSTEM WHILE TESTING .CPSCA AOSE .CPSCA## ;BUMP LEVEL OF NESTING JRST [CONO PI,PI.ON ;JUST NESTING, RETURN, ALREADY HAVE INTERLOCK POPJ P,] ;... CONI PI,.CPSCP## ;SAVE CHANNEL ENABLES CONO PI,PI.ON+DSKPIF## ;TURN PI SYSTEM BACK ON BUT LEAVE DSKCHN OFF IFN FTMP,< SKIPGE INTLSC## ;GIVE OTHER CPUS A CHANCE AOSE INTLSC## ;WAIT FOR THE SYSTEM-WIDE INTERLOCK JRST .-2 ;WAIT APRID INTOSC## ;INFORM THE WORLD WHO OWNS THIS >; END IFN FTMP POPJ P, ;RETURN ;ROUTINE TO ALLOW ACCESS TO SCA BUFFER MANAGEMENT AFTER ;IT HAS BEEN INTERLOCKED. CALED DIRECTLY OR VIA EXPANSION ;OF CION MACRO SC.PON::PUSH P,T1 ;SAVE A REGISTER SOSL T1,.CPSCA## ;DECREMENT LEVEL OF NESTING, SEE IF DONE PJRST TPOPJ## ;STILL NESTING, JUST RETURN EXCH T1,.CPSCP## ;GET CHANNEL ENABLE STATES ANDI T1,177 ;KEEP JUST THE CHANNELS WHICH WERE ON TRO T1,PI.TNP ;TURN THEM BACK ON EXCH T1,.CPSCP## ;RESTORE T1 AND SAVE ARGUMENT FOR CONO PI, IFN FTMP,< SETOM INTOSC## ;CLEAR INTERLOCK OWNER EXCH T1,INTLSC## ;RESET THE INTERLOCK SKIPGE T1 ;MAKE SURE IT WAS OWNED STOPCD .,CPU,SIU, ;++ SCA INTERLOCK UNOWNED >; END IFN FTMP CONO PI,@.CPSCP## ;PUT THE PI SYSTEM BACK THE WAY IT WAS PJRST TPOPJ## ;RESTORE T1 AND RETURN ;GLOBAL ROUTINES TO RETURN CI INTERLOCK CINPJ1::AOS (P) ;SET FOR SKIP RETURN CIONPJ::CION ;GIVE UP INTERLOCK POPJ P, ;RETURN $XHIGH ;BACK TO EXTENDED HIGH SEG SUBTTL CONNECTION BLOCK LOCKING ROUTINES ;ROUTINE TO LOCK A CONNECTION BLOCK. ;CALL: ; P1/ CONNECTION BLOCK ADDRESS ; PUSHJ P,SC.LOK ;RETURN: ; CPOPJ ALWAYS ; ;PRESERVES ALL ACS. SC.LOK: CONSZ PI,PI.IPA ;ANY PI'S IN PROGRESS? POPJ P, ;YES, NO NEED TO LOCK? AOS .CBLCK(P1) ;INCREMENT THE LOCK POPJ P, ;RETURN ;ROUTINE TO LOCK A CONNECTION BLOCK IF POSSIBLE. ;CALL: ; T1/ BIT TO BE SET IF BLOCK IS LOCKED ; P1/ CONNECTION BLOCK ADDRESS ; PUSHJ P,SC.LAH ;RETURN: ; CPOPJ IF ALREADY LOCKED ; CPOPJ1 IF WE LOCKED THE BLOCK SC.LAH: CONSZ PI,PI.IPA ;ANY PI'S IN PROGRESS? JRST SC.HNR ;YES, USE INTERRUPT LEVEL ROUTINE AOS .CBLCK(P1) ;INCREMENT THE LOCK JRST CPOPJ1## ;SKIP RETURN ;ROUTINE TO LOCK A CONNECTION BLOCK AT INTERRUPT LEVEL IF POSSIBLE. ;CALL: ; T1/ BIT TO BE SET IF BLOCK IS LOCKED ; P1/ CONNECTION BLOCK ADDRESS ; PUSHJ P,SC.HNR ;RETURN: ; CPOPJ IF ALREADY LOCKED ; CPOPJ1 IF WE LOCKED THE BLOCK SC.HNR: SKIPN .CBLCK(P1) ;IS IT LOCKED? JRST CPOPJ1## ;NO, WE CAN PROCEED IORM T1,.CBFLG(P1) ;YES, LIGHT THE BIT POPJ P, ;RETURN SUBTTL CONNECTION BLOCK UNLOCKING ROUTINE ;ROUTINE TO UNLOCK A CONNECTION BLOCK. ;CALL: ; P1/ CONNECTION BLOCK ADDRESS ; PUSHJ P,SC.ULK ;RETURN: ; CPOPJ ALWAYS ; ;PRESERVES T1 BECAUSE ERROR CODES ARE OFTEN PASSED IN T1. SC.ULK: CONSZ PI,PI.IPA ;ANY PI'S IN PROGRESS? POPJ P, ;YES, NO NEED TO UNLOCK SAVEAC ;SAVE SOME AC'S WE'LL NEED MOVE T1,.CBLCK(P1) ;WHAT'S THE CURRENT VALUE OF THE LOCK? CAIG T1,1 ;QUIT IF IT'S NOT 1 JRST ULK.01 ;PROCEED SOS .CBLCK(P1) ;DECREMENT IT POPJ P, ;RETURN ULK.01: SKIPG T1 ;MAKE SURE IT'S NOT NEGATIVE BUG. (HLT,SCAILC,SCASER,SOFT,,,) ;CURRENT VALUE IS 1. WE WILL BE THE LAST UNLOCKER. SEE WHAT SORTS ;OF THINGS HAVE BEEN DEFERRED, AND CALL THE APPROPRIATE ROUTINES. ;EACH PROCESSING ROUTINE CLEARS ITS BIT. IF THE BIT GETS SET AGAIN ;WHILE WE'RE IN HERE, WE WILL DETECT THAT. SETZB P3,P4 ;INITIALIZE FLAGS MOVE P5,.CBPBK(P1) ;GET ADDRESS OF PATH BLOCK ;SEE IF ANYTHING HAPPENED WHILE WE HAD THIS LOCKED. ULK.02: CIOFF ;PREVENT RACES MOVX T1,CB.DEF ;ANYTHING DEFERRED? TDNN T1,.CBFLG(P1) ;... JRST ULK.05 ;NO CION ;OK TO INTERRUPT ;TEST AND HANDLE EACH POSSIBLE EVENT MOVX T1,CB.ERR ;NODE OFFLINE? TDNN T1,.CBFLG(P1) ;... JRST ULK.03 ;NO SETO P4, ;YES, INDICATE WE HAD DEFERRED NODE OFFLINE PUSHJ P,SC.FN1 ;DO WHAT'S LEFT TO BE DONE JRST ULK.04 ;PROCEED ULK.03: MOVX T1,CB.DIS ;SYSAP WANTED DISCONNECT? TDNE T1,.CBFLG(P1) ;... PUSHJ P,SC.FN2 ;YES, FINISH THAT MOVX T1,CB.DRQ ;DISCONNECT_REQUEST DEFERRED? TDNE T1,.CBFLG(P1) ;... PUSHJ P,SC.FN3 ;YES, FINISH THAT ULK.04: MOVX T1,CB.SNM ;NEED TO SEND A CONNECTION MANAGEMENT REQUEST? TDNN T1,.CBFLG(P1) ;... JRST ULK.02 ;NO, SEE IF ANYTHING NEW HAS COME UP ANDCAM T1,.CBFLG(P1) ;YES, INDICATE NO LONGER DEFERRED SETO P3, ;REMEMBER THIS JRST ULK.02 ;SEE IF ANYTHING NEW HAS COME UP ;NOTHING LEFT TO DO, UNLOCK THE BLOCK ULK.05: SOSE .CBLCK(P1) ;UNLOCK THE CONNECTION BLOCK BUG. (HLT,SCALCC,SCASER,SOFT,,,) CION ;OK TO INTERRUPT ;IF WE HAD WANTED TO SEND A CONNECTION MANAGEMENT REQUEST, DO IT SKIPE P3 ;DID WE WANT TO? PUSHJ P,SC.SNM ;YES, SEND NEXT MESSAGE IF THERE'S ONE ;IF THIS BLOCK'S NODE HAD GONE OFFLINE, WE HAVE PUT OFF RE-OPENING ;THE VC BECAUSE OF THE LOCKED CB. IF THIS IS THE LAST ONE TO BE ;UNLOCKED, OPEN THE VC NOW. JUMPE P4,CPOPJ## ;RETURN IF WE DIDN'T HAVE A DEFERRED NODE OFFLINE SOSE .PBCLC(P5) ;DECREMENT PATH BLOCK COUNT OF LOCKED CB'S POPJ P, ;STILL HAVE MORE TO GO MOVX T1,PB.OVC ;NO LONGER WAITING TO OPEN ANDCAM T1,.PBFLG(P5) ;... LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX BLCAL. (PPDOVC##,) ;LET PPD OPEN THE VC POPJ P, ;RETURN SUBTTL SCA SUPPORT ROUTINES - OPERATOR NOTIFICATION ;ROUTINES TO NOTIFY THE OPERATOR WHEN A PATH CHANGES STATE. ;CALL: ; P5/ PBK ADDRESS ; PUSHJ P,PTHONL/PTHOFL ;RETURN: ; CPOPJ ALWAYS IFN FTINFO,< PTHONL: TDZA T1,T1 ;FLAG ONLINE MESSAGE PTHOFL: MOVEI T1,400000 ;FLAG OFFLINE SKIPE DINITF## ;ARE WE OUT OF DISK ONCE-ONLY CODE? POPJ P, ;NO, DON'T MESS UP THE CTY LOAD T2,PBDPN,(P5) ;GET DESTINATION PORT (CI NODE) NUMBER DPB T2,[POINT 8,T1,26] ;STORE NODE NUMBER IFN FTMP,< MOVE T2,.CPCPN## ;OUR CPU NUMBER DPB T2,[POINT 3,T1,35] ;STORE THAT TOO >; END IFN FTMP XJRST [MCSEC1+PTHSE0] ;MUST EXECUTE REMAINDER IN SECTION 0/1 $HIGH PTHSE0: PUSHJ P,SSEC0## ;LEAVE SECTION 1 MOVE T2,[PTHMSG,,1] ;CANT TYPE ON PI LEVEL SYSPIF ; SO WAIT TILL NEXT TICK PUSHJ P,SKPCLQ## ;ROOM IN CLOCK QUEUE FOR MESSAGE? JRST PTHSE1 ;NO, PROBABLY LOTS OF ERRORS, LET IT GO IDPB T2,CLOCK## ;SET SO WE WILL TELL OPR IDPB T1,CLOCK## ;SAVE DATA (PATH BLOCK ADDRESS) SETOM CLKNEW## ;INDICATE NEW ENTRY PTHSE1: SYSPIN ;ALLOW INTERRUPTS POPJ P, ;RETURN ;HERE AT CLOCK LEVEL - DATA ITEM (FLAG/NODE NBR/CPU) IS IN T1 PTHMSG: PUSHJ P,SAVE1## ;FREE UP P1 MOVE P1,T1 ;SAVE DATA ITEM PUSHJ P,TTYERO## ;SET UP TO PRINT ON OPERATOR'S TERMINAL PUSHJ P,INLMES## ;START THE MESSAGE ASCIZ /%% CI node / ;START THE MESSAGE LDB T1,[POINT 8,P1,26] ;FETCH NODE NUMBER PUSHJ P,RADX10## ;PRINT IT IFN FTMP,< PUSHJ P,INLMES## ;IDENTIFY WHICH CPU ASCIZ / on CPU/ ;... LDB T3,[POINT 3,P1,35] ;FETCH CPU NUMBER ADDI T3,"0" ;CONVERT TO ASCII PUSHJ P,COMTYO## ;... >; END IFN FTMP PUSHJ P,INLMES## ;ADD A SPACE, ETC. ASCIZ /: / ;... TRNN P1,400000 ;OFFLINE FLAG SET? SKIPA T1,[[ASCIZ /Online/]] ;NO MOVEI T1,[ASCIZ /Offline/] ;YES PUSHJ P,CONMES## ;PRINT IT PUSHJ P,INLMES## ;MORE NOISE ASCIZ / at / ;... PUSHJ P,PRDTIM## ;PRINT DATE/TIME PJRST CRLF## ;END THE LINE AND RETURN $XHIGH ;BACK TO EXTENDED HIGH SEGMENT >; END IFN FTINFO SUBTTL MISCELLANEOUS BYTE POINTERS ;BYTE POINTERS TO -10 FORMAT 8-BIT BYTES TA$LSB: POINT 8,T1,17 ;TEN BYTE A, LSB TA$MSB: POINT 8,T1,9 ;TEN BYTE A, MSB TB$LSB: POINT 8,T1,35 ;TEN BYTE B, LSB TB$MSB: POINT 8,T1,27 ;TEN BYTE B, MSB ;BYTE POINTERS TO -11 FORMAT 8-BIT BYTES EA$LSB: POINT 8,T1,23 ;ELEVEN BYTE A, LSB EA$MSB: POINT 8,T1,31 ;ELEVEN BYTE A, MSB EB$LSB: POINT 8,T1,7 ;ELEVEN BYTE B, LSB EB$MSB: POINT 8,T1,15 ;ELEVEN BYTE B, MSB SUBTTL IMPURE STORAGE $LOW EXP -1 ;FLAG FOR "DON'T CARE" LISTENERS PBLIST::BLOCK C%PBLL ;PATH BLOCK LIST ARRAY SBLIST::BLOCK C%SBLL ;SYSTEM BLOCK LIST ARRAY MFQCNT: BLOCK 1 ;FREE QUEUE BUFFER COUNT TOPMFQ: BLOCK 1 ;FREE QUEUE FLINK BOTMFQ: BLOCK 1 ;FREE QUEUE BLINK DFQCNT: BLOCK 1 ;DATAGRAM FREE QUEUE BUFFER COUNT TOPDFQ: BLOCK 1 ;DATAGRAM FREE QUEUE FLINK BOTDFQ: BLOCK 1 ;DATAGRAM FREE QUEUE BLINK TOPDC: BLOCK 1 ;DON'T CARE QUEUE FLINK BOTDC: BLOCK 1 ;DON'T CARE QUEUE BLINK CIDTAB::BLOCK 1 ;ADDRESS OF CONNECT-ID TABLE CIDRFL: BLOCK 1 ;NUMBER OF TIMES CIDTAB HAS BEEN RECYCLED UBTTAB: BLOCK 1 ;ADDRESS OF UNIQUENESS TABLE UNQRFL: BLOCK 1 ;NUMBER OF TIMES CID BITS HAVE BEEN RECYCLED NXTIDX: BLOCK 1 ;NEXT INDEX INTO UNIQUENESS TABLE UNQBTS: BLOCK 1 ;UNIQUENESS BITS SCASIN::BLOCK 1 ;SOFTWARE INCARNATION NUMBER NOTTAB: BLOCK 1 ;ADDRESS OF NOTIFICATION TABLE SNDTAB: BLOCK .STLST ;SEND COUNT INDEXED BY MESSAGE TYPE RECTAB: BLOCK .STLST ;RECEIVE COUNT INDEXED BY MESSAGE TYPE TMGCNT: BLOCK 1 ;NUMBER OF PATHS KILLED DUE TO IDLE CHATTER TMGPBI: EXP -1 ;CURRENT PATH BLOCK UNDER CONSIDERATION TMGTIM: EXP -C%TMGT ;TIMEOUT PERIOD PBCNT: BLOCK 1 ;NUMBER OF ONLINE PATHS MBPP: EXP C%MBPP ;MINIMUM MESSAGE BUFFERS PER PATH BLOCK DBPP: EXP C%DBPP ;NUMBER OF DATAGRAM BUFFERS PER PATH BLOCK MINMSG: BLOCK 1 ;MINIMUM NUMBER OF MESSAGE BUFFERS WE SHOULD HAVE MINDG: BLOCK 1 ;MINIMUM NUMBER OF DATAGRAM BUFFERS WE SHOULD HAVE NMBCNT: BLOCK 1 ;NUMBER OF TIMES WE RAN OUT OF MESSAGE BUFFERS NDBCNT: BLOCK 1 ;NUMBER OF TIMES WE RAN OUT OF DATAGRAM BUFFERS TOTMGB: BLOCK 1 ;TOTAL NUMBER OF MESSAGE BUFFERS CREATED TOTDGB: BLOCK 1 ;TOTAL NUMBER OF DATAGRAM BUFFERS CREATED MBUST: BLOCK 1 ;NUMBER OF TIMES A SMALL REQUEST WAS HONORED ; EVEN THOUGH WE WERE UNDER MESSAGE THRESHOLD DBUST: BLOCK 1 ;NUMBER OF TIMES A SMALL REQUEST WAS HONORED ; EVEN THOUGH WE WERE UNDER DATAGRAM THRESHOLD DMRCNT: BLOCK 1 ;NUMBER OF MESSAGE BUFFER REQUESTS DEFERRED DDRCNT: BLOCK 1 ;NUMBER OF DATAGRAM BUFFER REQUESTS DEFERRED RMRCNT: BLOCK 1 ;NUMBER OF MESSAGE BUFFER REQUESTS REFUSED RDRCNT: BLOCK 1 ;NUMBER OF DATAGRAM BUFFER REQUESTS REFUSED ASRMR: BLOCK 1 ;AVERAGE SIZE OF REFUSED MESSAGE REQUEST ASRDR: BLOCK 1 ;AVERAGE SIZE OF REFUSED DATAGRAM REQUEST LRGREQ: EXP C%LGRQ ;BUFFER REQUESTS OF LESS THAN THIS SIZE ARE ; CONSIDERED SMALL REQUESTS MGTRSH: EXP C%MGTR ;MINIMUM MESSAGE BUFFER THRESHOLD DGTRSH: EXP C%DGTR ;MINIMUM DATAGRAM BUFFER THRESHOLD IFN FTOPS10,< ;THIS IS ELSEWHERE IN TOPS-20 CIBUF: BLOCK 1 ;NON-ZERO IF MEMORY ALLOCATOR SHOULD RUN SCAREP: BLOCK 1 ;NON-ZERO IF REAPER NEEDS TO RUN >; END IFN FTOPS10 MDPAGS: BLOCK 1 ;NUMBER OF MESSAGE,,DATAGRAM PAGES REQUESTED OF ; THE MEMORY ALLOCATOR PBSTUK: BLOCK 2 ;BITS FOR PATHS STUCK ON BUFFERS SUBTTL THE END $XHIGH ;BACK TO EXTENDED HIGH SEGMENT SCAEND::!END