Trailing-Edge
-
PDP-10 Archives
-
BB-X140B-BB_1986
-
10,7/703mon/scaser.mac
There are 3 other files named scaser.mac in the archive. Click here to see a list.
TITLE SCASER - SYSTEM COMMUNICATIONS ARCHITECTURE SERVICE V24
SUBTTL JOSEPH A. DZIEDZIC/JAD 21 JAN 86
SEARCH F,S,SCAPRM,MACSYM
$RELOC
$HIGH
PURGEACS ;PURGE DEFAULT (TOPS-10) AC NAMES
T20SYM ;SWITCH TO TOPS-20 AC NAMES
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
.CPYRT<1984,1986>
;COPYRIGHT (C) 1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;BASED ON TOPS-20 "SCAMPI" MODIFIED TO SUPPORT MULTIPLE PATHS
XP VSCASR,24 ;VERSION NUMBER FOR GLOB AND MAP
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
SC.INI::SE1ENT ;RUN IN NON-ZERO SECTION
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,<No page for CID table>,,)
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,PGSIZ-1 ;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,PGSIZ/2 ;POINT TO HALFWAY THROUGH THE TABLE
MOVEM T1,UBTTAB ;SAVE AS ADDRESS OF THE UNIQUENESS TABLE
MOVX T1,C%CIDL ;INIT NXTIDS AS ONE MORE THAN HIGHEST INDEX
MOVEM T1,NXTIDX ;...
SETZM CIDRFL ;NOT DOING CIDTAB RECYCLING YET
SETONE UBITS,T1 ;SET ALL BITS IN THE UNIQUENESS BITS FIELD
LSH T1,-<C%RMBU> ;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,CPUN## ;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
;ALLOCATE THE NOTIFICATION TABLE
MOVEI T1,1 ;WE ONLY NEED ONE BUFFER
PUSHJ P,SC.ABF ;ALLOCATE ONE
BUG. (HLT,SCANBN,SCASER,SOFT,<No buffer for notification table>,,)
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,<Cannot complete initialization>,,)
JRST SCADIE ;IN CASE SOMEONE TRIES TO CONTINUE
;A GENERAL BUG. FOR ERRORS WHICH "SHOULD NEVER HAPPEN"
BUG. (HLT,SCAFOO,SCASER,SOFT,<Oh foo!>,,)
SUBTTL SYSAP NOTIFICATION REQUEST
;ROUTINE CALLED BY A SYSAP TO ADD AN ENTRY TO THE NOTIFICATION TABLE.
;CALL:
; BLCAL. (SS.SNA,<SS.ADR>)
;
;WHERE:
; SS.ADR - ADDRESS OF ROUTINE TO CALL
;
;RETURN:
; CPOPJ ON ERRORS
; CPOPJ1 ON SUCCESS
SC.SNA::BLSUB. (<SS.ADR>)
SAVEAC <P1,P5> ;FREE UP A PAIR OF AC'S
SE1ENT ;ENSURE WE RUN IN NZS
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,<Notice table full>,,)
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,<SS.SPN,SS.DPN,SS.PBI,SS.MSC,SS.MRC,SS.ADR,SS.SID,SS.DTA,SS.BFR,SS.DGB>)
;
;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
SC.CON::BLSUB. (<SS.SPN,SS.DPN,SS.PBI,SS.MSC,SS.MRC,SS.ADR,SS.SID,SS.DTA,SS.BFR,SS.DGB>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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,<SC.CON received failure from SC.OUT>,,)
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,<SS.SPN,SS.DPN,SS.PBI,SS.ADR,SS.SID,SS.MSC,SS.MRC>)
;
;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.
SC.LIS::BLSUB. (<SS.SPN,SS.DPN,SS.PBI,SS.ADR,SS.SID,SS.MSC,SS.MRC>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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,<SC.LIS received failure from SC.OUT>,,)
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,<SS.CID,SS.DTA,SS.BFR,SS.DGB>)
;
;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
SC.ACC::BLSUB. (<SS.CID,SS.DTA,SS.BFR,SS.DGB>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (,<PUSHJ P,SC.ULK>) ;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,<SS.CID,SS.RJR>)
;
;WHERE:
; SS.CID - CONNECT ID
; SS.RJR - REJECT REASON CODE
;
;RETURN:
; CPOPJ ON ERRORS WITH:
; T1/ ERROR CODE
; CPOPJ1 ON SUCCESS
SC.REJ::BLSUB. (<SS.CID,SS.RJR>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (,<PUSHJ P,SC.ULK>) ;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,<SS.CID,SS.DIR>)
;
;WHERE:
; SS.CID - CONNECT ID
; SS.DIR - DISCONNECT REASON
;
;RETURN:
; CPOPJ ON ERRORS WITH:
; T1/ ERROR CODE
; CPOPJ1 ON SUCCESS
SC.DIS::BLSUB. (<SS.CID,SS.DIR>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (,<CION>) ;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 (,<CION>) ;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
MOVX T1,CB.RAP ;MARK AS REAPABLE
IORM T1,.CBFLG(P1) ; (IN CASE JSYS CONNECTION)
SETOM SCAREP ;HAVE REAPER RUN NEXT TICK
POPJ P, ;NOTHING MORE TO DO
;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,<Can't complete deferred call to SC.DIS>,,)
;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,<SS.CID,SS.FLG,SS.LDG,SS.ADG,SS.PRI,SS.PTH>)
;
;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
SC.SDG::BLSUB. (<SS.CID,SS.FLG,SS.LDG,SS.ADG,SS.PRI,SS.PTH>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (.SCFWS,<PUSHJ P,SC.ULK>) ;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,<PUSHJ P,SC.ULK>) ;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,<PUSHJ P,SC.ULK>) ;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##,<T1,P2,SS.LDG,SS.FLG,SS.PRI,SS.PTH>) ;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##,<T2,T1>) ;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,<SS.CID,SS.FLG,SS.LMG,SS.AMG,SS.PRI,SS.TSH,SS.PTH>)
;
;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
SC.SMG::BLSUB. (<SS.CID,SS.FLG,SS.LMG,SS.AMG,SS.PRI,SS.TSH,SS.PTH>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (.SCFWS,<PUSHJ P,SC.ULK>) ;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,<PUSHJ P,SC.ULK>) ;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,<PUSHJ P,SC.ULK>) ;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,<PUSHJ P,SC.ULK>) ;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##,<T1,P2,SS.LMG,SS.FLG,SS.PRI,SS.PTH>) ;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##,<T2,T1>) ;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,<SS.CID,SS.NUM,SS.ADR>)
;
;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
SC.RDG::BLSUB. (<SS.CID,SS.NUM,SS.ADR>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (,<PUSHJ P,SC.ULK>) ;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,<SS.CID,SS.NUM,SS.ADR>)
;
;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
SC.RMG::BLSUB. (<SS.CID,SS.NUM,SS.ADR>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (,<PUSHJ P,SC.ULK>) ;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##,<T2,T1>) ;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,<SS.CID,SS.NUM>)
;
;WHERE:
; SS.CID - CONNECT ID
; SS.NUM - NUMBER OF BUFFERS TO DEQUEUE
;
;RETURN:
; CPOPJ ON ERRORS WITH:
; T1/ ERROR CODE
; CPOPJ1 ON SUCCESS
SC.CRD::BLSUB. (<SS.CID,SS.NUM>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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,<PUSHJ P,SC.ULK>) ;RETURN FAILURE
CRD.02: LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX
BLCAL. (PPDDDB##,<T1>) ;DEQUEUE A DATAGRAM BUFFER
RETBAD (,<PUSHJ P,SC.ULK>) ;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,<SS.CID,SS.NUM>)
;
;WHERE:
; SS.CID - CONNECT ID
; SS.NUM - NUMBER OF BUFFERS TO DEQUEUE
;
;RETURN:
; CPOPJ ON ERRORS WITH:
; T1/ ERROR CODE
; CPOPJ1 ON SUCCESS
SC.CRM::BLSUB. (<SS.CID,SS.NUM>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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,<SS.BLK>)
;
;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
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,<SS.NAM>)
;
;WHERE:
; SS.NAM - BUFFER NAME RETURNED BY A CALL TO SC.MAP
;
;RETURN:
; CPOPJ ON ERRORS WITH:
; T1/ ERROR CODE
; CPOPJ1 ON SUCCESS
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,<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
;
;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
SC.REQ::BLSUB. (<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
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,<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
;
;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
SC.SND::BLSUB. (<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
SETZ T1, ;INDICATE SEND
SC.SNR: PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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 (.SCFWS,<PUSHJ P,SC.ULK>) ;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,<PUSHJ P,SC.ULK>) ;RETURN "NOT ENOUGH CREDIT"
;SEND/REQUEST THE DATA
SNR.01: JUMPN P3,SNR.02 ;JUMP IF REQUEST
BLCAL. (PPDSND##,<SS.SNM,SS.RNM,SS.SOF,SS.ROF,SS.CID>)
JRST SNR.E1 ;ERROR
JRST SNR.03 ;SUCCESS
SNR.02: BLCAL. (PPDREQ##,<SS.SNM,SS.RNM,SS.SOF,SS.ROF,SS.CID>)
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,<SS.CID,SS.ADR>)
;
;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
SC.CSP::BLSUB. (<SS.CID,SS.ADR>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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,<SS.CID>)
;
;WHERE:
; SS.CID - SOURCE CONNECT ID
;
;RETURN:
; CPOPJ ALWAYS
SC.DCI::BLSUB. (<SS.CID>)
SAVEAC <P1,P5> ;SAVE THE AC'S SC.CAL TROUNCES
SE1ENT ;ENSURE WE RUN IN NZS
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,<SS.SBI>)
;
;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).
SC.RSB::BLSUB. (<SS.SBI>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED AC'S WE USE HERE
SE1ENT ;ENSURE WE RUN IN NZS
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,<SS.PBI>)
;
;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).
SC.RPB::BLSUB. (<SS.PBI>)
PUSHJ P,SAVP## ;SAVE THE PRESERVED AC'S WE USE HERE
SE1ENT ;ENSURE WE RUN IN NZS
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,<SS.PBI>)
;
;WHERE:
; SS.PBI - PATH BLOCK INDEX OF NODE ONLINE
;
;RETURN:
; CPOPJ ALWAYS
SC.ONL::BLSUB. (<SS.PBI>)
PUSHJ P,SAVP## ;SAVE THE P REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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##,<SS.PBI,T1>) ;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,<SCA credit queue failed>,,)
SUBTTL ENTRY FROM PORT DRIVER - NODE OFFLINE
;ROUTINE CALLED BY THE PHYSICAL PORT DRIVER WHEN A NODE GOES OFFLINE.
;CALL:
; BLCAL. (SC.ERR,<SS.PBI>)
;
;WHERE:
; SS.PBI - PATH BLOCK INDEX
;
;RETURN:
; CPOPJ ALWAYS
SC.ERR::BLSUB. (<SS.PBI>)
PUSHJ P,SAVP## ;SAVE THE P REGISTRS
SE1ENT ;ENSURE WE RUN IN NZS
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,<Duplicate offline for a node>,<<T1,NODE>>,)
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,<Negative path count>,,)
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##,<SS.PBI>) ;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##,<SS.PBI>) ;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,<Can't return SCS control message buffer>,<<T1,NODE>>,)
;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##,<SS.PBI>) ;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. (<SS.BNM,SS.CID>)
;
;WHERE:
; SS.BNM - BUFFER NAME
; SS.CID - CONNECT ID
;
;RETURN:
; CPOPJ ALWAYS
SC.DMA::BLSUB. (<SS.BNM,SS.CID>)
PUSHJ P,SAVE1## ;SAVE P1
SE1ENT ;ENSURE WE RUN IN NZS
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,<SS.PBI,SS.PKT,SS.LEN,SS.FLG>)
;
;WHERE:
; SS.PBI - PATH BLOCK INDEX
; SS.PKT - PACKET ADDRESS
; SS.LEN - PACKET LENGTH
; SS.FLG - FLAGS
;
;RETURN:
; CPOPJ ALWAYS
SC.INT::BLSUB. (<SS.PBI,SS.PKT,SS.LEN,SS.FLG>)
PUSHJ P,SAVP## ;SAVE THE P REGISTERS
SE1ENT ;ENSURE WE RUN IN NZS
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,<Bad message type from remote node>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>>,)
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,<Can't complete deferred call to SC.DRQ>,,)
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,<Unexpected credit field in credit_request>,<<T1,NODE>,<T2,CID>>,)
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##,<T1,P2>) ;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 <P3> ;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,<Unexpected response>,<<T3,NODE>,<T4,CID>,<T1,OPCODE>,<T2,EXPCTD>>,)
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,<Received packet and connection block doesn't exist>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>>,)
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,<Protocol error>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>,<T4,STATE>>,)
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
XMOVEI T4,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
XMOVEI T4,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##,<T1,P2>) ;QUEUE A MESSAGE BUFFER
POPJ P, ;RETURN
AMD.08: BLCAL. (PPDQDB##,<T1,P2>) ;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
SC.TIC::SE1ENT ;RUN IN NZS
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
SC.SEC::SE1ENT ;RUN IN NZS
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,<SCA timed out remote node>,<<T1,NODE>>,)
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 <Q1,Q2,P1> ;SAVE SOME AC'S
SETZM SCAREP ;REMEMBER WE'VE RUN
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 <Q1,P2,P5> ;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##,<P2>) ;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##,<P2>) ;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: 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 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 <CBIMB,CBIDB>,(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## ;ASK FOR THE SPACE 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 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,PGSIZ(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,<Block state already non-zero>,<<T3,NODE>,<T2,OLDSTA>,<T1,NEWSTA>>,)
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,<Block state is zero when trying to send connection management request>,,)
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,<Reap bit is set when block state is non-zero>,,)
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##,<T1,P2>) ;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##,<T1,P2>) ;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 <SYBITS,IDX,UBTS,CID> ;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
SKIPN CIDRFL ;ARE WE IN RECYCLE MODE?
JRST FNI.01 ;NO, TRY FOR ANOTHER INDEX
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,-<C%RMBU> ;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,-<C%RMBU> ;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,<CION>) ;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,<Connect block already linked>,<<T1,NODE>,<T2,CID>>,)
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,<Dont care listener linked to CB>,,)
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,<Incoming connection request on closed VC>,,)
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
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,<CION>) ;RETURN AN ERROR
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,<Can't send credit request>,<<T1,NODE>,<T2,CID>,<T3,STATE>>,)
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 <P3> ;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##,<T1>) ;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,<Can't reclaim buffers>,<<T1,NODE>,<T2,CID>>,)
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,<Virtual circuit closure requested>,<<T1,NODE>>,)
LOAD T1,PBPBI,(P5) ;GET THE PATH BLOCK INDEX
BLCAL. (PPDCVC##,<T1>) ;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 <DPN,DATA> ;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 <OPCODE> ;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##,<T4,P2,T2,[0],T3,[0]>) ;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
MOVX T2,CB.RAP ;GET THE REAP BIT
IORM T2,.CBFLG(P1) ;WE CAN REAP IT NEXT TICK
SETOM SCAREP ;START REAPER NEXT TICK
POPJ P, ;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##,<T3,T1>) ;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##,<T3,T1>) ;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 <Q1> ;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 <Q1> ;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.
SC.ALD::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 <NUMBUF> ;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
XMOVEI T3,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,<CION>) ;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,<CION>) ;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,<CION>) ;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
SC.ABF::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 <NUMBUF> ;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
XMOVEI T3,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,<CION>) ;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,<CION>) ;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,<CION>) ;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
SKIPN CORLOC## ;CAN WE DO IT?
POPJ P, ;NO, NICE TRY
SAVEAC <Q1,Q2,P4,P5> ;SAVE SOME AC'S
STKVAR <BUFSZ,NUMPPG,NUMBUF> ;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 <BUFSIZ> ;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,PGSIZ ;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,PGSIZ ;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
SC.RBF::SE1ENT ;MAKE SURE WE RUN IN NZS
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,<C%BINV+C%MGSZ>-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
SC.RLD::SE1ENT ;MAKE SURE WE RUN IN NZS
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,<C%BINV+C%DGSZ>-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 <T1,T2,T3,T4,P1> ;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.
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
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 <T1,P3,P4,P5> ;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,<Illegal lock count in connection block>,,)
;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,<Connection block lock count has changed>,,)
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##,<T1>) ;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: SKIPA T1,[[ASCIZ /Online/]] ;GET TEXT
PTHOFL: MOVEI T1,[ASCIZ /Offline/] ;GET TEXT
LOAD T2,PBDPN,(P5) ;GET DESTINATION PORT NUMBER
SKIPE DINITF## ;ARE WE OUT OF DISK ONCE-ONLY CODE?
POPJ P, ;NO, DON'T MESS UP THE CTY
PUSHJ P,SAVPQ## ;SAVE ALL THE REGISTERS WE MIGHT STEP ON
DMOVE P1,T1 ;COPY ARGUMENTS
PUSHJ P,SSEC0## ;ENTER SECTION ZERO
PUSHJ P,TTYERO## ;SET UP TO PRINT ON OPERATOR'S TERMINAL
PUSHJ P,INLMES## ;START THE MESSAGE
ASCIZ /%% CI node / ;START THE MESSAGE
MOVE T1,P2 ;GET NODE NUMBER
PUSHJ P,RADX10## ;PRINT IT
IFN FTMP,<
PUSHJ P,INLMES## ;IDENTIFY WHICH CPU
ASCIZ / on CPU/ ;...
MOVE T3,.CPCPN## ;GET CPU NUMBER
ADDI T3,"0" ;CONVERT TO ASCII
PUSHJ P,COMTYO## ;...
>; END IFN FTMP
PUSHJ P,INLMES## ;ADD A SPACE, ETC.
ASCIZ /: / ;...
MOVE T1,P1 ;GET TEXT ADDRESS
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
>; 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
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
$HIGH
SUBTTL THE END
SCAEND::!END