; 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() ;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 , ;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== XRESCD SCADSP: TABBEG .SSDGR,.SSDMA, ;Unknown callbacks bugchk TABENT .SSDGR, ;Datagram received TABENT .SSPBC, ;Port broke connection TABENT .SSCTL, ;Connection to listen TABENT .SSCRA, ;Connection response available TABENT .SSMSC, ;Datagram/message send complete TABENT .SSDDG, ;Datagram dropped TABENT .SSLCL, ;Little credit left TABENT .SSNCO, ;Node came online TABENT .SSOSD, ;Ok to send data TABENT .SSRID, ;Remote initiated disconnect TABENT .SSCIA, ;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 ,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,,<,>,< 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 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 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,,<>,< 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,,<>,< 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: ; 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,,<,>,< Cause: The internet SCA interface requested a buffer for an incoming datagram and none were available. >) RETBAD ;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: ; 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: ; CALL CIOPEN ; +1 error return with error code in T1 ; +2 success return XSWAPCD CIOPEN: SKIPE KLPON ;ALREADY ON ? RET SAVEAC SETZ PT, ;Initialize the port table DO. SETZM PRTTAB(PT) ;Clear port table entry NEWSTATE DOWN ;Set initial state to "DOWN" CAIGE PT, ;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, ;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 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]>,) ;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 MOVE PT,T1 ;Port number to PT CHKSTATE RUN ;Is it RUN state? RETBAD (CI.NRU) ; -no, return error CAXLE T3, ;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]>,) RETBAD (CI.SDG) RETSKP SUBTTL CICLS - Close CI ;CICLS - close CI ; ;Call: ; CALL CICLS ; +1 return on error with error code in T1 ; +2 return on success XRESCD CICLS: SAVEAC ;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]>,) ;Disconnect JFCL ENDIF. CAIGE PT, ;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 ;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,,<,,>,< 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]>,) ;Recycle buffer to free queue BUG. (CHK,IPNFRB,IPCIDV,SOFT,,,< 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]>,) IFNSK. BUG. (CHK,IPACFA,IPCIDV,SOFT,,,< 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]>,) 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]>,) ; 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]>,) ; -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]>,) ; disconnect JFCL ENDIF. NEWSTATE DOWN ;Reset state CALL NODINI ;Reinitialize connection with remote RET SUBTTL End of Module TNXEND END