Trailing-Edge
-
PDP-10 Archives
-
BB-EV84A-SM_1985
-
monitor-sources/ipcidv.mac
There are 5 other files named ipcidv.mac in the archive. Click here to see a list.
; UPD ID= 2086, SNARK:<6.1.MONITOR>IPCIDV.MAC.12, 3-Jun-85 14:45:13 by MCCOLLUM
;TCO 6.1.1406 - Update copyright notice.
; UPD ID= 1748, SNARK:<6.1.MONITOR>IPCIDV.MAC.11, 12-Apr-85 11:30:30 by PAETZOLD
;TCO 6.1.1319 - Fix intitialization problem
; UPD ID= 1599, SNARK:<6.1.MONITOR>IPCIDV.MAC.10, 7-Mar-85 15:40:56 by PAETZOLD
;Document BUGxxx's
; UPD ID= 1574, SNARK:<6.1.MONITOR>IPCIDV.MAC.9, 26-Feb-85 17:18:42 by PAETZOLD
;Document BUGxxx's
; UPD ID= 1452, SNARK:<6.1.MONITOR>IPCIDV.MAC.8, 1-Feb-85 14:19:47 by LOMARTIRE
;Add new symbols to describe the priority used by SC.SDG
; UPD ID= 1417, SNARK:<6.1.MONITOR>IPCIDV.MAC.7, 29-Jan-85 11:37:14 by PAETZOLD
;TCO 6.1.1158 - Decrease scheduler latency when requesting INTFRK from interrupt context.
;More TCO 6.1.1100 - Reset NETON if NTLADR uninitialized.
; UPD ID= 1250, SNARK:<6.1.MONITOR>IPCIDV.MAC.6, 1-Jan-85 14:29:57 by PAETZOLD
;TCO 6.1.1100 - Verify local host number on initialization and enforce compliance.
; UPD ID= 1100, SNARK:<6.1.MONITOR>IPCIDV.MAC.5, 19-Nov-84 15:34:17 by GLINDELL
;Fix race in connection algorithm
;Do not 'CIPDNS' if connection to remote is not open
; UPD ID= 1062, SNARK:<6.1.MONITOR>IPCIDV.MAC.4, 13-Nov-84 09:07:21 by LOMARTIRE
;Use new sending priority symbols in SC.SDG calls
; UPD ID= 1034, SNARK:<6.1.MONITOR>IPCIDV.MAC.3, 12-Nov-84 15:23:58 by PAETZOLD
;TCO 6.1041 - Move ARPANET to XCDSEC
; UPD ID= 1011, SNARK:<6.1.MONITOR>IPCIDV.MAC.2, 9-Nov-84 08:41:30 by PRATT
;TCO 6.1.1030 - Interface Multinet to SCA
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985.
;ALL RIGHTS RESERVED.
SEARCH ANAUNV,PROLOG,SCAPAR,NIPAR,PHYPAR
SALL
.DIRECTIVE FLBLST
TTITLE (IPCIDV,IPCIDV,< - Internet CI Interface>)
SUBTTL SCA Connection algorithm
COMMENT \
There is a IPCIDV connection state associated with each of the 16 ports
on the CI. The states are:
OFF TCP/CI has not been enabled, i.e. CIOPEN has not been called.
DOWN The remote port is known to be down.
CONNECT The remote port is known to be up, and we have initiated an
active connect.
LISTEN The remote port is known to be up, and we are listening for
an incoming connect request.
ACCEPT We have accepted an incoming connect request, and we are now
waiting for an 'OK to send data' message before going to RUN
state.
RUN A connection is established with the remote port, and data
transfer is allowed.
There is always a listener outstanding. It listens to incoming connect
requests from all remote ports.
The NODINI will initiate a connection to a remote node. It is called in
three different cases:
(i) by CIOPEN when TCP/CI is enabled.
(ii) by 'remote port came online' callback. SCA will issue this callback
when a remote port becomes available after having been unreachable
(DOWN).
(iii) when the remote initiated a disconnect of a connection.
NODINI assumes the port state to be down. If the remote port is
available, it issues an active connect request and moves the state to
CONNECT. From now on, SCA callbacks take over.
We will get a "connect request response" to the CONNECT we sent out. If
the remote port accepted, we can move our port state to RUN.
Now look at the other port: it receives an incoming connect request.
This translates into a "connect to listen" callback. The remote port
will accept and move its state to ACCEPT. Soon after, another callback
from SCA will inform the remote IPCIDV that "it is ok to send data",
and the remote can go to RUN. The connection is established.
The complication is that it is likely for both ends to try to connect
to each other at the same time. Two active connect requests can be in
transition at the same time. One of the two connections need to be
disconnected. The backoff code is in the "connect to listen" callback
routine. If we already are in CONNECT state (i.e. we have an
outstanding connect request) then we will reject a connection if the
remotes port number is lower than our own.
\
SUBTTL Definitions
;Special AC definitions
CID==Q1 ;CID holds connect ID
PT==Q2 ;PT keeps port number
SRV==Q3 ;type of service
NCT==P1 ;address of our nct
RID==P3 ;request id (buffer address)
;Internal error codes for debugging
CI.NKL==620001 ;No KLIPA present in system
CI.NLP==620002 ;Not allowed to transmit to Local Port
CI.NRE==620003 ;No resources
CI.SDG==620004 ;SCA Send datagram failed
CI.NRU==620005 ;Port not in RUN state
CI.NBA==620007 ;CIGRBF couldn't get a buffer
CI.BTL==620010 ;Buffer too long on transmit
;Miscellaneous definitions
CI.HOP==.NBLD1 ;Routing adress is kept in the leader
DEFSTR CINOD,CI.HOP,35,4 ;CI node # is built into the internet adr
NDGBUF==4 ;# of SCA buffers to post (4 is a guess)
XSWAPCD
SCANAM: ASCI8(<TCP$IPCI >) ;SCA process name
SUBTTL Local storage
;The PRT BEGSTR contains information about each port
BEGSTR PT
FIELD OWN,1 ;Set if this is local port
FIELD HOS,1 ;Set if this port is hostile, i.e. not TOPS-20
FILLER 1
HWORD STA ;Port state (DOWN,CONNECT,LISTEN,ACCEPT,RUN)
ENDSTR
IFN <PT.LEN - 1>,<PRINTX ?BEGSTR PT is not 1 word long>
;Storage
RS(PRTTAB,C%SBLL) ;Each word is in form of PT BEGSTR
RS(CIDTBL,C%SBLL) ;Each word keeps the connect ID (CID)
RS(KLPON,1) ;Non-zero if KLIPA interface is present
RS(OURPRT,1) ;Our KLIPA port number
SUBTTL Port States and Macros
;These are the port states (stored in PTSTA in PRTTAB)
.PSOFF==0 ;Closed (or not OPENed)
.PSDOWN==1 ;Remote port not available
.PSCONNECT==2 ;Connect outstanding to remote
.PSLISTEN==3 ;Listen outstanding
.PSACCEPT==4 ;Accept, waiting for SCA .SCOSD callback
.PSRUN==5 ;Run, data may be transmitted
;The GETSTATE macro loads the port connect state into the AC argument
DEFINE GETSTATE (A) <
LOAD A,PTSTA,+PRTTAB(PT)
>
;The CHKSTATE macro skips if the port connect state is equal to the
; state given as argument
DEFINE CHKSTATE (A) <
LOAD CX,PTSTA,+PRTTAB(PT)
CAIE CX,.PS'A
>
;The NEWSTATE macro sets the port connect state to a new value
DEFINE NEWSTATE (A) <
MOVX CX,.PS'A
STOR CX,PTSTA,+PRTTAB(PT)
>
SUBTTL SCA Callback Dispatch
;SCA callbacks
XXXSEC==<XCDSEC,,0>
XRESCD
SCADSP: TABBEG .SSDGR,.SSDMA,<XXXSEC!SCAUC> ;Unknown callbacks bugchk
TABENT .SSDGR,<XXXSEC!SCADGR> ;Datagram received
TABENT .SSPBC,<XXXSEC!SCAPBC> ;Port broke connection
TABENT .SSCTL,<XXXSEC!SCACTL> ;Connection to listen
TABENT .SSCRA,<XXXSEC!SCACRA> ;Connection response available
TABENT .SSMSC,<XXXSEC!SCAMSC> ;Datagram/message send complete
TABENT .SSDDG,<XXXSEC!R> ;Datagram dropped
TABENT .SSLCL,<XXXSEC!R> ;Little credit left
TABENT .SSNCO,<XXXSEC!SCANCO> ;Node came online
TABENT .SSOSD,<XXXSEC!SCAOSD> ;Ok to send data
TABENT .SSRID,<XXXSEC!SCARID> ;Remote initiated disconnect
TABENT .SSCIA,<XXXSEC!R> ;Credit is available
TABEND
SUBTTL Initialization and Background Service
;CIPINI - INITIALIZATION
;
; Called from MNTINI when initializing all of the networks known
; to Multinet.
;
; NCT/ NCT address
;
; Returns + 1 always
XSWAPCD
CIPINI::MOVEM NCT,CIPNCT ;SAVE OUR NCT FOR THE CALLBACK ROUTINE
SETZM HSTGDM(NCT) ;CANCEL GOING DOWN MESSAGES
RET
;CIPSRV - BACKGROUND SERVICE FOR IPCI
;
; Called by the Internet fork to provide background processing
; for IPCIDV.
;
; Returns + 1 always
CIPSRV::SKIPE INTON ;CAN'T DO ANYTHING UNTIL INTERNET INIT'D
SKIPN CIPON ;OR UNTIL WE'RE INIT'D
RET
CALL CIPGIB ;GET SOME BUFFERS IF NEEDED
RET
SUBTTL Multinet Restart Service
;CIPRST - RESTART
;
; Call here when we want to open the Internet comm over the CI.
;
; NCT/ NCT address
;
; Returns + 1 always
XSWAPCD
CIPRST::SKIPN INTON ;HAS INTERNET BEEN INITIALIZED ?
RET ;NO. NOT READY YET.
SKIPG T1,NTLADR(NCT) ;SEE IF WE HAVE HOST NUMBER YET
RET ;NO. NOT READY YEST.
TXZ T1,<^-<377>> ;TURN OFF UNWANTED BITS
SKIPN T2,CHNTAB+KLPRH2 ;GET THE CDB ADDRESS
JRST CIPRSE ;NO CDB
JE <CS.CIP>,CDBSTS(T2),CIPRSE ;IF NOT A CI WE ARE ALL DONE
MOVE T2,CDBNOD(T2) ;GET OUR CI NODE NUMBER
CAME T1,T2 ;LOW ORDER HOST NUMBER SAME AS CI NODE NUMBER?
JRST CIPRSE ;NO
SETZM NTTOUT(NCT) ;CLEAR OUTPUT HUNG TIMEOUT
CALL CIPGIB ;GET A BUNCH OF BUFFERS
CALL CIOPEN ;GO DO THE OPEN
JRST CRSTER ;COULDN'T
SETOM CIPON ;INTERFACE IS READY
AOS NTSTCH(NCT) ;CAUSE CHANGE IN STATE TO BE NOTED
GTAD
MOVEM T1,NTXUPP(NCT) ;SAVE TIME WHEN IT CAME UP
SETOM NTRDY(NCT) ;INDICATE FULLY UP
SETOM NTORDY(NCT) ;ALLOW OUTPUT
CALL INTUP ;INTERFACE IS UP
CALL CIPSTO ;START OUTPUT IF NEEDED
AOS JB0FLG ;NOTE NETWORK CHANGE
RET
;Here to handle errors during restart
CRSTER: MOVEM T1,CIPERR ;SAVE THE ERROR
CALL CIPHNG ;HANDLE IT
RET
CIPRSE: ;HERE WHEN NO CI OR ADR DOES NOT EXIST
BUG.(INF,CIPBAD,IPCIDV,SOFT,<IP Host number conflicts with CI Node Number.>,<<T1,HOST>,<T2,QODE>>,<
Cause: The low order octet of the local internet host address for the CI
interface (from the SYSTEM:INTERNET.ADDRESS file) disagrees with the
systems CI node number.
Action: Fix the SYSTEM:INTERNET.ADDRESS file.
>)
CIPRSX:
SETZM NETON(P1) ;MAKE SURE WE DO NOT TRY TO START AGAIN
RET ;AND RETURN
SUBTTL Multinet Status Checking and Header Building
;CIPSTA - STATUS CHECK
;
; This routine is called from Multinet to check the status of
; the KLIPA.
;
; NCT/ NCT address
;
; Returns + 1 on error
; + 2 on success
XSWAPCD
CIPSTA::CALL CISTS ;GO GET THE STATUS
SKIPA ;ERROR DETECTED
RETSKP
CIPHNG: SETOM NTERRF(NCT) ;YES, FLAG AN ERROR
SETZM NTRDY(NCT) ;MAKE THE NETWORK NOT READY
MOVE T1,TODCLK ;GET TIME NOW
ADDI T1,^D60*^D1000 ;TIMEOUT IN ONE MINUTE
MOVEM T1,NTTOUT(NCT) ;SET INTERFACE HUNG TIMEOUT
RET
;CIPHDR - BUILD HEADER
;
; Called from Multinet to build a header for the local transport
; layer. In our case, the only essential information is the host
; number of the next node which can route the packet.
;
; T1/ local address to send to
; T2/ address of buffer
; NCT/ NCT address
;
; Returns + 1 always
XSWAPCD
CIPHDR::MOVEM T1,CI.HOP(T2) ;STORE DESTINATION ADDRESS
RET
SUBTTL Multinet Output Service
;CIPSTO - START OUTPUT
;
; Called to send an output buffer.
;
; NCT/ NCT address
; NTIOBO/ pointer to the list of internet buffers to send
; NTIOBI/ tail end of the list
;
; Returns +1 always
XRESCD
CIPSTO::SAVEAC <RID>
CIPOS1: SKIPN RID,NTIOBO(NCT) ;ANY INTERNET OUTPUT WAITING?
RET ;NO
NOSKED ;NO INTERRUPTIONS FROM OTHER FORKS
LOAD T2,NBQUE,(RID) ;GET ITS SUCCESSOR
JUMPN T2,CIPOS2 ;JUMP IF NOT LAST ONE
SETZM NTIOBI(NCT) ;YES. MAKE QUEUE NULL
SKIPA
CIPOS2: SETSEC T2,INTSEC ;PLACE IN PROPER SECTION
MOVEM T2,NTIOBO(NCT) ;UPDATE OUTPUT POINTER
SETZRO NBQUE,(RID) ;DEQUEUE BUFFER FROM ITS OLD CHAIN
OKSKED ;ALLOW INTERRUPTS AGAIN
CALL CISNDP ;NO. SEND TO SCA
RETBAD ;ERROR
SETZM NTTOUT(NCT) ;CLEAR OUTPUT HUNG TIMEOUT
JRST CIPOS1 ;TRY FOR MORE
;CISNDP - SEND PACKET VIA SCA
;
; NCT/ NCT address
; RID/ address of buffer
;
; Returns + 1 on error
; + 2 on success
XSWAPCD
CISNDP: XMOVEI T2,-LCLPKT(RID) ;POINT TO RIGHT LOCATION TO PICK UP PIDH
LOAD T3,PIDH,(T2) ;GET THE DESTINATION HOST #
CAMN T3,NTLADR(NCT) ;DESTINED FOR US ?
JRST CILCAL ;YES
LOAD T1,CINOD,(RID) ;GET THE ROUTING ADDRESS
XMOVEI T2,MAXLDR(RID) ;POINT AT DATA PORTION OF BUFFER
XMOVEI T3,-LCLPKT(RID) ;POINT TO RIGHT LOCATION TO PICK UP LENGTH
LOAD T3,PIPL,(T3) ;GET PACKET LENGTH
CALL CISEND ;GO SEND IT
JRST CISND1 ;GO HANDLE ERROR
CALLRET CIRELB ;GO RELEASE BUFFER
SUBTTL Local Loopback Service
;CILCAL - LOCAL LOOPBACK
;
; Called from CISNDP to handle a message to ourself. We reserve
; a input buffer and copy the IP packet into it, queue it, and
; release the old packet. This routine is needed because the
; SCA does not allow us to send to ourself.
;
; RID/ address of the outgoing IP packet
; NCT/ address of the NCT
;
; Returns via CIRELB
XSWAPCD
CILCAL: STKVAR <BFA>
CALL CIGRBF ;GET A BUFFER TO USE
JRST CISND1 ;DIDN'T GET A BUFFER
MOVEM T2,BFA ;SAVE THE NEW BUFFER ADDRESS
XMOVEI T2,-LCLPKT(RID) ;POINT AT PACKET HEADER BEGINNING
LOAD T1,PIPL,(T2) ;HEADER LENGTH IN BYTES
ADDI T1,3+PKTELI*4 ;PACKET SIZE IN BYTES, ROUNDED UP
ASH T1,-2 ;PACKET SIZE IN FULL WORDS
XMOVEI T2,MAXLDR(RID) ;POINT TO BEGINNING OF BUFFER
MOVE T3,BFA ;DESTINATION IS THE POSTED RCV BUFFER'S
ADDI T3,MAXLDR ; DATA AREA
CALL XBLTA ;COPY IP HEADERS
MOVE T2,BFA ;POINT AT RCV BUFFER
CALL CIDGRC ;GIVE THE BUFFER TO INTERNET
CALLRET CIRELB ;RELEASE OLD BUFFER
ENDSV.
;Here to release the current output buffer
XSWAPCD
CISND1: SKIPA T3,T1 ;WANT THE ERROR STATUS
CIRELB: SETZ T3, ;DON'T WANT ANY ERROR STATUS
MOVE T1,RID ;GET BUFFER ADDRESS
MOVE T2,T1 ;COPY FOR INDEXING
PIOFF
EXCH T1,INTNFB ;PUT ON FREE LIST
STOR T1,NBQUE,(T2) ;HANG OLD LIST OFF OF THIS NEW HEAD
PION
AOS INTFLG ;GET INTERNET GATEWAY TO NOTICE IT
SKIPN T1,T3 ;NO, GET THE CHANNEL STATUS
RETSKP ;NO ERRORS DETECTED
CDSERR: AOS CIOCNT ;BUMP THE OUTPUT ERROR COUNT
CAIE T1,CI.NRU ;If 'not in RUN state' then dont bugcheck
BUG.(INF,CIPDNS,IPCIDV,SOFT,<Datagram not sent>,<<T1,ERROR>>,<
Cause: The internet SCA interface attempted to queue a buffer to SCA
and the buffer was refused.
>)
MOVEM T1,CIPERR
RETBAD
SUBTTL Shutdown and Error Routines
;CIPKIL - SHUTDOWN
;
; Called from MNETDV to shut down both Internet and ARP
; communications with SCA.
;
; NCT/ NCT address
;
; Returns + 1 always (T1 IS PRESERVED)
XSWAPCD
CIPKIL::MOVE T1,NTRDY(NCT) ;RECORD IF ANYTHING CHANGED
IOR T1,NTORDY(NCT)
SETZM NTTOUT(NCT) ;CLEAR OUTPUT HUNG TIMEOUT
JUMPE T1,CIPKLD ;NOTHING CHANGED SO EXIT QUIETLY
SETZM NTRDY(NCT) ;CI OFF
SETZM NTORDY(NCT) ;OUTPUT OFF
AOS NTSTCH(NCT) ;JUST CHANGED STATE
AOS JB0FLG ;NOTE THE NETWORK CHANGE
CALL CICLS ;CLOSE THE CI
SETZM CIPON ;INTERNET NOT ON ANYMORE
CIPKLD: RET
SUBTTL Buffer Management
;CIPGIB - GET INPUT BUFFERS.
;
; Called from the Internet fork to get a bunch of input buffers
; to be used for incoming IP packets over the CI.
;
; Returns + 1 always
XRESCD
CIPGIB: MOVE T1,CIPNFI ;NUMBER OF FREE INPUT BUFFERS
CIPGB1: CAML T1,CIPNIB ;BELOW DESIRED LEVEL?
RET ;NO - DO NOTHING
MOVE T1,MAXWPM ;GET ENOUGH ROOM
CALL GETNIB ;GET A BUFFER
JUMPE T1,CIPGB3 ;ZERO ADDRESS, NONE AVAILABLE
SETZRO PKTFLG,(T1) ;CLEAR ALL INTERNAL CONTROL FLAGS
SETONE PFSIZ,(T1) ;INDICATE IT'S A FULL SIZE PACKET
XMOVEI T2,LCLPKT(T1) ;GET POINTER TO LOCAL HEADERS
MOVE T3,MAXWPM ;MAX WORDS
STOR T3,NBBSZ,(T2) ;SAVE AS BUFFER SIZE
SETZRO NBQUE,(T2)
CALL INTLKB ;MAKE SURE BUFFER IS RESIDENT
MOVE T1,T2
PIOFF
EXCH T2,CIPFRI ;ADD TO LIST OF FREE INPUT BUFFERS
STOR T2,NBQUE,(T1) ;OLD LIST IS SUCCESSOR OF THIS BUF
AOS T1,CIPNFI ;BUMP THE COUNT TO MATCH
PION
JRST CIPGB1 ;SEE IF ENOUGH
CIPGB3: ;HERE WHEN NO BUFFERS AVAILABLE
MOVE T1,CIPNFI ;GET NUMBER OF BUFFERS AVAILABLE
CAIGE T1,NCIPTH ;BELOW THE THRESHOLD LEVEL ?
BUG.(CHK,CIPNBA,IPCIDV,SOFT,<No IPCI input buffers available.>,<<T1,BFRCNT>>,<
Cause: The internet SCA interface was unable to assign any buffers from
the internet free space manager. This should be a temporary condition.
>)
RET
SUBTTL Receive Buffer Handling
;CIGRBF - get receive buffer
;
;CI driver will call this routine when it has received a SCA datagram
; and needs an IP buffer to copy the message to.
;
;Call: <no arguments>
; CALL CIGRBF
; +1 return/ no buffers available
; +2 return/ T2/ address of resident buffer (need not be physically
; contiguous)
; T3/ # of bytes in buffer
;Context: Interrupt (SCA)
XRESCD
CIGRBF: PIOFF
SOSL T1,CIPNFI ;COUNT DOWN NUMBER OF FREE INTERNET BUFS
SKIPN T2,CIPFRI ;GET POINTER TO BUFFER TO USE
IFNSK.
AOS CIPNFI ;DON'T HAVE BUFFERS. DON'T LET IT GO NEGATIVE
PION
MOVE T2,CIPFRI ;MAKE SURE WE GET POINTER
BUG.(CHK,CIPBLP,IPCIDV,SOFT,<IPCIDV input buffer list problem>,<<T1,CNT>,<T2,BFR>>,<
Cause: The internet SCA interface requested a buffer for an incoming datagram
and none were available.
>)
RETBAD <CI.NBA> ;SET THE ERROR CODE AND RETURN
ENDIF.
LOAD T1,NBQUE,(T2) ;NEXT INTERNET FREE BUFFER
SETSEC T1,INTSEC ;YES SO SET THE SECTION NUMBER
SETZRO NBQUE,(T2) ;CLEAR LIST POINTER
MOVEM T1,CIPFRI ;BECOMES HEAD OF LIST
PION
ADDI T2,MAXLDR ;POINT PAST HEADER AREA
MOVE T3,INTXPB ;GET SIZE OF INTERNET PACKET
ADDI T3,4 ;ADD IN CRC
RETSKP
SUBTTL SCA Datagram Received Service
;CIDGRC - receive datagram
;
;CI driver will call this routine when it has received a message and copied
; it into an IP buffer
;
;Call: T1/ node # (of source)
; T2/ buffer address
; T3/ # of bytes
; CALL CIDGRC
; +1 return always
;Context: Interrupt (SCA)
XRESCD
CIDGRC: PIOFF ;DON'T ALLOW US TO BE INTERRUPTED
SUBI T2,MAXLDR ;POINT AT HEADER AREA
MOVE T3,INTIBI ;QUEUE FOR INTERNET GATEWAY
JUMPN T3,CBDRQ1
MOVEM T2,INTIBO ;ONLY THIS ITEM
SKIPA
CBDRQ1: STOR T2,NBQUE,(T3)
MOVEM T2,INTIBI ;NEW POINTER
AOS INTFLG ;CAUSE INTERNET TO NOTICE IT.
AOS PSKD1 ;AND CAUSE THE SCHED TO NOTICE IF SYSTEM IDLE
PION
RET
SUBTTL CISTS - Check status of CI
;CISTS - Check status of CI
;
;Call: <no arguments>
; CALL CISTS
; +1 error return with CI.NKL (No KLIPA present) in T1
; +2 success return: CI interface is available
EXTERN SC.PRT
CISTS=SC.PRT ;SC.PRT does exactly this
SUBTTL CIOPEN - Open CI for traffic
;CIOPEN - Open CI for Internet traffic
;
;Call: <no arguments>
; CALL CIOPEN
; +1 error return with error code in T1
; +2 success return
XSWAPCD
CIOPEN: SKIPE KLPON ;ALREADY ON ?
RET
SAVEAC <P1,CID,PT>
SETZ PT, ;Initialize the port table
DO.
SETZM PRTTAB(PT) ;Clear port table entry
NEWSTATE DOWN ;Set initial state to "DOWN"
CAIGE PT,<C%SBLL-1> ;Done all ports yet?
AOJA PT,TOP. ; -no, initialize next
ENDDO.
CALL SC.PRT ;Get local port number
RETBAD (CI.NKL) ; -no KLIPA, return error
MOVEM T1,OURPRT ;Save our port number
SETONE PTOWN,+PRTTAB(T1) ;Flag "own" flag for this port
;Now post a promiscuous listen
CALL DOLIS ;Post a listener
RETBAD (CI.NRE) ; -return "no resources"
;Set online address so we get notified if new nodes come online
BLCAL. (<@[MSEC1,,SC.SOA]>,<[XADDR. SCACBK]>) ;Set callback address
RETBAD (CI.NRE)
;Loop over all nodes, and see if we should try to connect
SETZ PT, ;PT is node index
DO.
CALL NODINI ;Initialize this node
CAIGE PT,<C%SBLL-1> ;Done all nodes?
AOJA PT,TOP. ; -no, go to the next
ENDDO.
SETOM KLPON ;Flag CI present
RETSKP
SUBTTL SCA Remote Node Connection Initialization
XRESCD
NODINI: ;(try to) initialize a remote node
STKVAR <CBADR>
MOVE T1,[XWD .RESP1,.RDLEN] ;Priority,,length
MOVEI T2,.RESGP ;Pool
CALL ASGRES ;Assign space
RET ; -failed
MOVEM T1,CBADR ;Save address of block
BLCAL. (<@[MSEC1,,SC.RCD]>,<PT,T1>) ;Read configuration
IFNSK. ; -not there
MOVE T1,CBADR ; Get address of block
CALLRET RELRES ; and return deallocating it
ENDIF.
MOVE T1,CBADR ;Get address of block
CALL NODIN1 ;Call coroutine to do the work
MOVE T1,CBADR ;Retrieve configuration block address
CALLRET RELRES ; and return the block and return
ENDSV.
NODIN1: LOAD T2,RDVCST,(T1) ;Get VC state
LDB T3,[POINT PKSID,.RDPCH(T1),PKPID] ;Get remote system ID
CAIN T3,ID.KL ;Is it a friendly system?
IFSKP. ; -no,
SETONE PTHOS,+PRTTAB(PT) ; Set the hostile bit
RET ; and return
ENDIF.
;Coming here we want to try to connect if the remote is available
CAIE T2,VC.OPN ;Is VC state OPEN?
RET
CALLRET DOCONN ; and do the connect
;DOLIS - post a promiscuous listen
XRESCD
DOLIS: BLCAL. (<@[MSEC1,,SC.LIS]>,<[XADDR. SCANAM],[XADDR. SCANAM],[-1],[XADDR. SCACBK],[0],[0],[0]>)
RET
RETSKP
;DOCONN - do an active connect
XRESCD
DOCONN: CIOFF ;Protect from state changes
CHKSTATE DOWN ;Verify that we believe remote is down
JRST DOCON1 ; -no, go do CION and RET
BLCAL. (<@[MSEC1,,SC.CON]>,<[XADDR. SCANAM],[XADDR. SCANAM],PT,[0],[0],[XADDR. SCACBK],[0],[0],[0],[NDGBUF]>)
IFSKP. ;Success
NEWSTATE CONNECT ; so new state is CONNECT
ELSE. ;On error return
CAIE T1,KLPX9 ; VC closed
CAIN T1,SCSISB ; or remote not available?
IFNSK.
NEWSTATE DOWN ; -yes, move state to DOWN
ELSE.
NEWSTATE LISTEN ; -no, move state to LISTEN
ENDIF.
ENDIF.
DOCON1: CION ;Done with sensitive code
RET
SUBTTL CISEND - Send datagram
;CISEND - send datagram
;
;Call: T1/ node #
; T2/ buffer address
; T3/ # of bytes to transmit
; CALL CISEND
; +1 return on error with error code in T1
; +2 return on success
XSWAPCD
CISEND: SKIPN KLPON ;Make sure KLIPA is on
RETBAD (CI.NKL) ; -return 'no KLIPA'
SAVEAC <P1,P2,CID,PT>
MOVE PT,T1 ;Port number to PT
CHKSTATE RUN ;Is it RUN state?
RETBAD (CI.NRU) ; -no, return error
CAXLE T3,<C%BYTD-C%OVHD> ;Make sure supplied buffer isnt too large
RETBAD (CI.BTL) ; -it was, return error
MOVE CID,CIDTBL(PT) ;Get CID for connection
DMOVE P1,T2 ;Move T2,T3 to P1,P2
MOVX T1,1 ;Get one buffer
CALL SC.ALD ; from SCA pool
RETBAD (CI.NRE) ; -return "no resources"
;Copy the IP buffer into the SCA buffer
MOVE T2,P1 ;Move IP buffer address into T2
MOVE P1,T1 ;And save SCA buffer address in P1
MOVEI T1,3(P2) ;Get # of bytes to transmit + 3
ASH T1,-2 ; to make into words
XMOVEI T3,.MHUDA(P1) ;And SCA buffer address to T3
EXTEND T1,[XBLT] ;XBLT into the buffer
;Send the datagram
BLCAL. (<@[MSEC1,,SC.SDG]>,<CID,[F.RTB],P2,P1,[IPCPRI],[0]>)
RETBAD (CI.SDG)
RETSKP
SUBTTL CICLS - Close CI
;CICLS - close CI
;
;Call: <no arguments>
; CALL CICLS
; +1 return on error with error code in T1
; +2 return on success
XRESCD
CICLS: SAVEAC <CID,PT>
;Step through all ports and disconnect any connections
SETZ PT, ;PT is port number
DO.
CIOFF ;Protect from callbacks that may move state to
; RUN
GETSTATE T1 ;Get current state into T1
NEWSTATE OFF ; and move state to OFF
CION ;Let in interrupts again
CAIE T1,.PSRUN ;Was this port in RUN
CAIN T1,.PSACC ; or in ACCEPT state?
IFNSK.
BLCAL. (<@[MSEC1,,SC.DIS]>,<CIDTBL(PT),[0]>) ;Disconnect
JFCL
ENDIF.
CAIGE PT,<C%SBLL-1> ;Done all ports?
AOJA PT,TOP. ; -no, go to next one
ENDDO.
SETZM KLPON ;CLEAR THE ON FLAG
RETSKP ;Return success
SUBTTL SCACBK - SCA Callback Entry Point
XRESCD
SCACBK: ;Called on SCA callbacks
SAVEAC <CID,PT> ;Save preserved ACs
CALL @SCADSP(T1) ;Call service routine
RET ;Always single return
CID2PN: ;Convert CID to port number
MOVE T1,CID
CALL SC.NOD ;Call SCA to do this
MOVE PT,T2 ;Node # is returned in T1
RET
SCAUC: ;Unexpected callback
BUG. (CHK,IPSCBV,IPCIDV,SOFT,<SCA passed an illegal callback function>,<<T1,CODE>,<T2,ARG1>,<T3,ARG2>>,<
Cause: SCA gave the internet SCA interface a callback with an unknown function
code.
>)
RET
SUBTTL SCADGR - Datagram Received Callback
;Call: T2/ address of datagram buffer
; T3/ CID
; T4/ flags
; CALL SCADGR
; +1 return always
;Ac usage:
; P1/ SCA buffer address
; P2/ SCA packet length
; P4/ flags
; P5/ IP buffer address
XRESCD
SCADGR: SAVEP
MOVE P1,T3 ;SCA buffer address
MOVE P2,.MHPKL(P1) ;SCA packet length
SUBI P2,C%OVHD ; minus overhead bytes
MOVE P4,T4 ;Flags
MOVE CID,T2 ;Get CID
CALL CID2PN ;CID =) port #
;is port in RUN state?
CHKSTATE RUN ;RUN?
CALLRET RDGBUF ; -no, return SCA buffer and return
TXNN P4,F.SPM ;Industry compatible mode?
CALL CIGRBF ; -yes, get IP buffer
CALLRET RDGBUF ; -no to any or both, return buffer
MOVE P5,T2 ;Save IP buffer address
CAMGE T3,P2 ;IP buffer big enough?
CALLRET RDGBUF ; -no, (should probably bugcheck)
;Copy SCA buffer to IP buffer
MOVEI T1,3(P2) ;Get # of SCA bytes + 3
ASH T1,-2 ; and make into words
XMOVEI T2,.MHUDA(P1) ;Get SCA buffer address
MOVE T3,P5 ; and IP buffer address
EXTEND T1,[XBLT] ; and move the data
CALL RDGBUF ;Return the SCA buffer
;Call IP to process incoming packet
MOVE T1,PT ;Port #
MOVE T2,P5 ;IP buffer address
MOVE T3,P2 ;# of bytes
CALL CIDGRC ;Call "received datagram"
RET ;Return to SCA
RDGBUF: ;Put a SCA buffer back on free queue
BLCAL. (<@[MSEC1,,SC.RDG]>,<CID,[0],P1>) ;Recycle buffer to free queue
BUG. (CHK,IPNFRB,IPCIDV,SOFT,<Failed to recycle buffer>,,<
Cause: The internet SCA interface attempted to return a buffer to SCA and
the buffer was refused.
>)
RET
SUBTTL SCAPBC - Port broke connection
;Call: T2/ CID
; CALL SCAPBC
; +1 return always
XRESCD
SCAPBC: SKIPL CID,T2 ;Get CID and test for unsolicited (T2 eq -1)
IFSKP. ; -unsolicited
MOVE PT,T3 ; so get port # from T3
ELSE. ; -real pbc
CALL CID2PN ; so get port number from CID
ENDIF.
NEWSTATE DOWN ;Move state to DOWN in all cases
RET
SUBTTL SCACTL - Connect to listen
;Call: T2/ CID
; T3/ address of connetion data
; CALL SCACTL
; +1 return always
XRESCD
SCACTL: MOVE CID,T2 ;Move CID into place
CALL CID2PN ; and make port number
CALL DOLIS ;Post a new listener since the old one is gone
JFCL ; -too bad...
CHKSTATE LISTEN ;In LISTEN state
SKIPA ; -no,
JRST DOACC ;-yes, do accept
CHKSTATE CONNECT ;In CONNECT state
JRST DOREJ ; -no, go reject
CAML PT,OURPRT ;-yes, remotes port number lower than ours?
JRST DOREJ ; -no, reject
DOACC: ;All set, accept
BLCAL.(<@[MSEC1,,SC.ACC]>,<CID,[0],[0],[NDGBUF]>)
IFNSK.
BUG. (CHK,IPACFA,IPCIDV,SOFT,<SCA ACCEPT failed>,,<
Cause: The internet SCA interface attempted to accept a connection and
failed.
>)
ELSE.
NEWSTATE ACCEPT ;Move state to ACCEPT
ENDIF.
RET ;All sone
DOREJ: BLCAL.(<@[MSEC1,,SC.REJ]>,<CID,[0]>)
JFCL
RET
SUBTTL SCACRA - Connection response available
;Call: T2/ CID
; T3/ -1 if accepted, 0 if rejected
; CALL SCACRA
; +1 return always
XRESCD
SCACRA: MOVE CID,T2 ;Get connect ID
CALL CID2PN ; and get port #
CHKSTATE CONNECT ;Are we in CONNECT state?
IFNSK. ; -no,
SKIPN T3 ; Were we accepted?
IFSKP. ; -yes,
BLCAL.(<@[MSEC1,,SC.DIS]>,<CID,[0]>) ; disconnect connection
JFCL
ENDIF.
ELSE. ; -yes, port in CONNECT state
SKIPN T3 ; Were we accepted?
IFSKP. ; -yes, good news
MOVEM CID,CIDTBL(PT) ;Save CID
NEWSTATE RUN
ELSE.
NEWSTATE LISTEN ; -no, bad news
ENDIF.
ENDIF.
RET
SUBTTL Misc. SCA callbacks.
;Call: T2/ CID
; T3/ address of buffer
; CALL SCAMSC
; +1 return always
XRESCD
SCAMSC: MOVE T1,T3 ;Get buffer
CALLRET SC.RLD ; and return it to SCA
;Call: T2/ # of node that just came online
; CALL SCANCO
; +1 return always
SCANCO: MOVE PT,T2 ;NODINI expects node in PT
CALLRET NODINI ;Try to iniitializa node that came online
;Call: T2/ CID
; CALL SCAOSD
; +1 return always
SCAOSD: MOVE CID,T2 ;Get connect ID
CALL CID2PN ; and make port number of it
CHKSTATE ACCEPT ;ACCEPT state?
IFSKP.
MOVEM CID,CIDTBL(PT) ;Save CID
NEWSTATE RUN ; -yes, then move to RUN
ELSE.
BLCAL.(<@[MSEC1,,SC.DIS]>,<CID,[0]>) ; -no, then disconnect
JFCL
ENDIF.
RET
;Call: T2/ CID
; CALL SCARID
; +1 return always
SCARID: MOVE CID,T2 ;Get connect ID
CALL CID2PN ; and get port number
GETSTATE T1 ;Get port state
CAIE T1,.PSRUN ;RUN or
CAIN T1,.PSACCEPT ; ACCEPT?
IFNSK. ; -yes,
BLCAL.(<@[MSEC1,,SC.DIS]>,<CID,[0]>) ; disconnect
JFCL
ENDIF.
NEWSTATE DOWN ;Reset state
CALL NODINI ;Reinitialize connection with remote
RET
SUBTTL End of Module
TNXEND
END