SUBTTL Definitions -- Local storage
;TOPS-20 can have only one CB block, and it is statically defined here.
; In a possible future TOPS-10 implementation, the CININI should loop
; over all possible CI interfaces and build a CB block for each.
;
;Also, TOPS-20 relies on there being only 1 CB block when locating the
; CB block associated with a connection. On TOPS-10, the "XMOVEI CB,CBBLK"
; has to be replaced with something else.
;The CB block
RESVR ;Into zeroed resident storage
CBBLK: BLOCK CB.LEN
;DNACBK has the DNA callback address as supplied in the CININI call
DNACBK: BLOCK 1
;RCVBSZ has the maximum DECnet receive buffer size
RCVBSZ: BLOCK 1
;CONTIM is the connect timer, decremented by CINSEC
RESDT
CONTIM: EXP -1 ;No timer set initially
XRESCD

SUBTTL Connection management -- DNADLL -- Close data link layer port
;DNACLS closes a data link layer port
;
;Call: PB and CB are set up
; CALL DNACLS
; +1 error return, status code in T1
; +2 success return
;
;Context: Jsys or scheduler level
;
;Ac usage: CB, PB and MB may be clobbered
;Interlocking: DNACLS has to interlock between getting the old state and
; disconnecting the connection if there was one. If CIOFF was not done, DNACLS
; could assume that the status was, say, LISTEN and then set the state to
; OFF. In the window between reading LISTEN and setting state to OFF there
; could be a SCA interrupt establishing a connection.
XRESCD ;Must be resident since CIOFF is done
DNACLS: CIOFF ;Implies NOSKED too..
GETSTATE T1 ;Get current state
CALL @DNACLT(T1) ;Call transition routine
NEWSTATE OFF ;New state is OFF in all cases
CION ;No harm can be done now
RETSKP
;DNACLT is state transition vector for DNADLL Close event
DNACLT: $SDSP
$DSP(.PSOFF,<IFIW <R&777777>>,<Current state is OFF>)
$DSP(.PSLIS,<IFIW <R&777777>>,<Current state is LISTEN>)
$DSP(.PSACC,<IFIW <LOCDIS&777777>>,<Current state is ACCEPT>)
$DSP(.PSCDO,<IFIW <R&777777>>,<Current state is CDOWN>)
$DSP(.PSCUP,<IFIW <R&777777>>,<Current state is CUP>)
$DSP(.PSCSE,<IFIW <LOCDIS&777777>>,<Current state is CSENT>)
$DSP(.PSRUN,<IFIW <LOCDIS&777777>>,<Current state is RUN>)
$EDSP

SUBTTL Connection management -- SCA callback -- "Port broke connection"
;"Port broke connection" callback indicate that the connection to the remote
; node has been broken for some reason.
;
;At the callback the CID is unusable, and the connection is broken. Buffers
; outstanding for it will be cleaned when the SCA reaper runs at a future
; time.
;
;CIDLL shall activate the connection if needed, and report "port state change"
; to DNADLL if the current state was RUN.
;
;Call: CB,PB and CID set up
; CALL SCAPBC
;
;Context: Scheduler or SCA interrupt
;
;Note: there is no interlock problem since even if the callback occurred at
; scheduler level, SCA will not interrupt for the same CID (since its broken)
XRESCD
SCAPBC: GETSTATE T1 ;Get current state
JRST @SCAPBT(T1) ; and go to transition routine
;SCAPBT is the state transition vector for SCA callback "port broke connection"
SCAPBT: $SDSP
$DSP(.PSOFF,<IFIW <SCAUCB&777777>>,<Current state is OFF>)
$DSP(.PSLIS,<IFIW <SCAUCB&777777>>,<Current state is LISTEN>)
$DSP(.PSACC,<IFIW <PBCACC&777777>>,<Current state is ACCEPT>)
$DSP(.PSCDO,<IFIW <SCAUCB&777777>>,<Current state is CDOWN>)
$DSP(.PSCUP,<IFIW <PBCCUP&777777>>,<Current state is CUP>)
$DSP(.PSCSE,<IFIW <PBCCSE&777777>>,<Current state is CSENT>)
$DSP(.PSRUN,<IFIW <PBCRUN&777777>>,<Current state is RUN>)
$EDSP
;PBCACC handles ACCEPT state
;
;Move state to LISTEN
PBCACC: NEWSTATE LISTEN ;CID is disconnected, need not do any more
RET
;PBCCUP handles CUP state
;PBCCSE handles CSENT state
;
;Move state to CDOWN
PBCCUP:
PBCCSE: NEWSTATE CDOWN ;Remote is down
RET
;PBCRUN handles RUN state
;
;Signal port state change (to down) to DNADLL, and activate port
PBCRUN: MOVX T1,DI.LSC ;Port state change
LOAD T2,PBDID,(PB) ;DNADLL id
MOVX T3,LS.OFF ;Port OFF
CALL @DNACBK ;Call DNADLL at callback address
CALLRET ACTIVA ;Activate this port and return

SUBTTL Connection management -- SCA callback -- "Connection to listen"
;SCACTL is called on SCA callback "connection to listen"
;
;Call: CB, PB and CID set up
; T3/ Address of connection data from remote system
; CALL SCACTL
; +1 return always
;
;Context: SCA interrupt
XRESCD
SCACTL: STKVAR <REMDAT>
MOVEM T3,REMDAT ;Save address of remote connect data
CALL DOLIS ;Post a new promiscuous listener
JFCL ; ...
;Now get the port number for the remote end
MOVE T1,CID ;Load CID into T1 to
CALL <XENT SC.NOD> ;[7.1037] get port number into T2
;See if we are listening on this port: do we have a PB?
XMOVEI T1,CB.PRT(CB) ;Get address of port blocks
ADD T2,T1 ; add port number offset
SKIPN PB,(T2) ;Load PB and check for zero
CALLRET REJNL ; -no, no PB, reject and return
;Yes, we have a PB: are we listening?
;Note: the following section of code replaces the state transition vector
CHKSTATE LISTEN
CALLRET REJNL ; and do reject
;The only thing that can stop us now is bad connection data
MOVE T2,REMDAT ;Get address of remote connection data
LDB T1,[POINT 8,(T2),7] ; and 1st byte of connection data
CAIN T1,.CNDRP ;Check if protocol type is .CNDRP "Multidrop"
IFSKP. ; -no,
NEWSTATE OFF ; Set state to OFF
CALL REJWP ; Reject connection
MOVX T2,.CNDRP ; Get our protocol version
BUG.(INF,CINRWP,CIDLL,SOFT,<Remote supplied wrong protocol version>,<<T1,REMVER>,<T2,LOCVER>>,<
Cause: The remote port is not running the same protocol version of DECnet/CI.
This may happen if you are running DECnet/CI between two different
versions of TOPS-20, or if you are running DECnet/CI between TOPS-20
and a VMS system. DECnet/CI between TOPS-20 and VMS is not
supported.
Action: If this is caused by a VMS system, then remove the system from
your cluster or disable the CI dircuit to that system. If it is
caused by a TOPS-20 system, then you should make both systems
run the same version of the software or disable the CI circuit
between them.
Data: REMVER - The remote ends protocol version
LOCVER - The local TOPS-20 systems protocol version
>,RTN,<DB%NND>) ;[7.1210]
ENDIF.
;All ok, accept the connection
BLCAL. (<XENT SC.ACC>,<CID,[0],[0],[NDGBUF]>) ;[7.1037]Accept
IFSKP. ;If succeded,
STOR CID,PBCID,(PB)
NEWSTATE ACCEPT ; and new state is ACCEPT
ELSE. ;Accept failed
;Note: if the ACCEPT fails nothing bad can happen. State stays LISTEN,
; and no CID has been moved into the PB to confuse things
BUG.(CHK,CINACF,CIDLL,SOFT,<Accept failed>,<<T1,ERRCOD>>,<
Cause: CIDLL decided to accept an incoming connection, but the accept
call to SCA failed.
Data: ERRCOD - The error code returned by SCAMPI
>)
ENDIF.
RET ;Return
ENDSV.
;REJECT a connection with code CNRJNL "no listener"
;
REJNL: MOVX T1,CNRJNL ;Load rejection code
JRST REJECT ; and go reject
;REJECT a connection with code CNRJWP "wrong protocol version"
;
REJWP: MOVX T1,CNRJWP ;Load rejection code
; JRST REJECT ; and go reject
REJECT: BLCAL. (<XENT SC.REJ>,<CID,T1>) ;[7.1037]
JFCL ;Ignore failure to reject
RET

SUBTTL Connection management -- SCA callback -- "Connection response available"
;SCACRA is called on SCA callback "Connection response available". It is
; expected to happen while in CSENT state, and informs CIDLL whether the
; connection was accepted (go to RUN) or if it was rejected (go to OFF)
;
;Call: CB, PB and CID set up.
; T3/ -1 if accepted, 0 if rejected
; T4/ reject code, or pointer to connection data
; CALL SCACRA
; +1 return always
;
;Context: SCA interrupt
XRESCD
SCACRA: STKVAR <REMSTS,REJCOD>
MOVEM T3,REMSTS ;Save status and rejection code
MOVEM T4,REJCOD
;The following section of code implements the state transitions for SCACRA:
; if the current state is not CONNECT, then bugchk and do no more. Else process
; the connect response
CHKSTATE CSENT
BUG.(CHK,CINUEC,CIDLL,SOFT,<Unexpected connect response>,<<CID,SCACID>>,<
Cause: CIDLL received a callback from SCA stating that a connection response
was available. CIDLL was not expecting any such callback for
the port.
Data: SCACID - The connect ID
>,RTN) ; -return after the BUGCHK
;Now, if state is CSENT, then check if it was rejected. If so, go to state
; OFF and BUGINF, else go to state RUN and signal "port state change"
SKIPN REMSTS ;Rejected or accepted
IFSKP. ; -accepted!
NEWSTATE RUN ; New state is RUN
MOVX T1,DI.LSC ; Flag port state change to DNADLL
LOAD T2,PBDID,(PB) ; DNADLL id
MOVX T3,LS.ON ; New port state is ON
CALLRET @DNACBK ; Call DNADLL and return
ELSE. ; -rejected
BLCAL. (<XENT SC.DIS>,<CID,[CNDSWS]>) ;[7.1037]Disconnect "wrong state"
JFCL ; -ignore failure to disconnect
MOVE T1,REJCOD ; Get rejection code
CAIN T1,CNRJWP ; Is it wrong protocol version?
IFSKP. ; -no,
NEWSTATE CUP ; just move to CUP
ELSE. ; -yes,
NEWSTATE OFF ; new state is OFF
MOVX T1,.CNDRP ; Get our protocol version
BUG.(INF,CINRRL,CIDLL,SOFT,<Remote rejected our protocol version>,<<T1,LOCVER>>,<
Cause: The remote port does not understand the protocol version of DECnet/CI.
The other system may be running another version of TOPS-20, or the
remote system may be running VMS. DECnet/CI between TOPS-20
and VMS is not supported.
Action: If this is caused by a VMS system, then remove the system from
your cluster or disable the CI dircuit to that system. If it is
caused by a TOPS-20 system, then you should make both systems
run the same version of the software or disable the CI circuit
between them.
Data: LOCVER - TOPS-20 DECnet/CI protocol version
>)
ENDIF.
ENDIF.
RET
ENDSV.

SUBTTL Connection management -- SCA callback -- "Ok to send data"
;SCAOSD is called on SCA callback "Ok to send data". It is expected to
; occur while in ACCEPT state, and is an indication that the connection
; is established, i.e.
;
;Call: CB, PB and CID set up
; CALL SCAOSD
; +1 return always
;
;Context: SCA interrupt
XRESCD
SCAOSD: GETSTATE T1 ;Get current state
JRST @SCAOST(T1) ; and go to transition routine
;SCAOST is the state transition vector for SCA callback "Ok to send data"
SCAOST: $SDSP
$DSP(.PSOFF,<IFIW <SCAUCB&777777>>,<Current state is OFF>)
$DSP(.PSLIS,<IFIW <SCAUCB&777777>>,<Current state is LISTEN>)
$DSP(.PSACC,<IFIW <OSDACC&777777>>,<Current state is ACCEPT>)
$DSP(.PSCDO,<IFIW <SCAUCB&777777>>,<Current state is CDOWN>)
$DSP(.PSCUP,<IFIW <SCAUCB&777777>>,<Current state is CUP>)
$DSP(.PSCSE,<IFIW <SCAUCB&777777>>,<Current state is CSENT>)
$DSP(.PSRUN,<IFIW <R&777777>>,<Current state is RUN>)
$EDSP
;OSDACC is called in ACCEPT state
OSDACC: NEWSTATE RUN ;Hurrah!
MOVX T1,DI.LSC ;Tell DNADLL also "port state change"
LOAD T2,PBDID,(PB) ;DNADLL id
MOVX T3,LS.ON ;New state is ON
CALLRET @DNACBK ;Call at supplied address and return

SUBTTL Connection management -- SCA callback -- "Remote initiated disconnect"
;SCARID is called on SCA callback "remote disconnect". CIDLL will disconnect
; the port if running, notify DNADLL if so, and activate the port again.
;
;Call: CB, PB and CID set up
; CALL SCARID
; +1 return always
;
;Context: SCA interrupt
SCARID: GETSTATE T1 ;Get current state
JRST @SCARIT(T1) ; and go to transition routine
;SCARIT is the transition vector for SCA callback "Remote initiated disconnect"
SCARIT: $SDSP
$DSP(.PSOFF,<IFIW <SCAUCB&777777>>,<Current state is OFF>)
$DSP(.PSLIS,<IFIW <SCAUCB&777777>>,<Current state is LISTEN>)
$DSP(.PSACC,<IFIW <RIDACC&777777>>,<Current state is ACCEPT>)
$DSP(.PSCDO,<IFIW <SCAUCB&777777>>,<Current state is CDOWN>)
$DSP(.PSCUP,<IFIW <SCAUCB&777777>>,<Current state is CUP>)
$DSP(.PSCSE,<IFIW <RIDCSE&777777>>,<Current state is CSENT>)
$DSP(.PSRUN,<IFIW <RIDRUN&777777>>,<Current state is RUN>)
$EDSP
;RIDACC is called in ACCEPT state
RIDACC: CALL REMDIS ;Return receive buffers and disconnect
NEWSTATE LISTEN ; and new state is LISTEN
RET
;RIDCSE is called in CSENT state
RIDCSE: CALL REMDIS ;Return receive buffers and disconnect
NEWSTATE CUP ; and new state is CUP
RET
;RIDRUN is called in RUN state
RIDRUN: CALL REMDIS ;Return receive buffers and disconnect
MOVX T1,DI.LSC ;Signal port down to DNADLL
LOAD T2,PBDID,(PB) ;DNADLL id
MOVX T3,LS.OFF ;Down
CALL @DNACBK ;Call at supplied address
CALLRET ACTIVA ; and activate and return

SUBTTL Connection management -- Subroutines -- SCAUCB
;SCAUCB issues a callback "Unexpected callback function"
SCAUCB: BUG.(CHK,CINUCB,CIDLL,SOFT,<Unexpected SCA callback>,<<T1,STATE>,<CID,SCACID>,<MB,ROUADR>>,<
Cause: SCA issued a callback to DECnet/CI that was not expected in the
current state of the connection.
Data: STATE - The DECnet/CI connection state
SCACID - The connect ID for the connection in question
ROUADR - The address of the SCA callback processing routine
>,RTN) ;Return after bugcheck