TITLE SCSUUO - SCS. UUO SUPPORT V24 SUBTTL JOSEPH A. DZIEDZIC/JAD 17-DEC-85 SEARCH F,S,ICHPRM,KLPPRM,SCAPRM,MACSYM $RELOC $HIGH T20SYM ;SWITCH TO TOPS-20 AC NAMES ;(NEEDED FOR INTERFACE TO SCASER) ;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,1986 ;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. ;ALL RIGHTS RESERVED. XP VSCSUU,24 ;VERSION NUMBER FOR GLOB AND MAP SCSUUO:!ENTRY SCSUUO ;LOAD IF LIBRARY SEARCH ;NOTE ON ACCUMULATOR USAGE: ; ;DON'T USE Q1 - Q3 UNLESS YOU WANT TO STEP ON W, M, OR U. KLPSER ;USES Q2 AS THE PCB ADDRESS REGISTER. INTERNALLY WE WILL USE P6 ;TO AVOID STEPPING ON M. THIS IS THE ONLY AC DIFFERING BETWEEN ;KLPSER/SCASER AND SCSUUO. SUBTTL UUO ERROR RETURN DEFINITIONS ERCODX ERRNPV,SSNPV% ;NOT PRIVILEGED ERCODX ERRIFC,SSIFC% ;ILLEGAL FUNCTION CODE ERCODX ERRARG,SSARG% ;BAD ARGUMENT LIST LENGTH ERCODX ERRACR,SSACR% ;ADDRESS CHECK READING ARGUMENTS ERCODX ERRACS,SSACS% ;ADDRESS CHECK STORING DATA ERCODX ERRCPN,SSCPN% ;CPU NUMBER OUT OF RANGE ERCODX ERRNPC,SSNPC% ;NO CI PORT ON SPECIFIED CPU ERCODX ERRNNK,SSNNK% ;CPU'S CI NODE NUMBER NOT KNOWN ERCODX ERRINN,SSINN% ;INVALID CI NODE NUMBER ERCODX ERRNFC,SSNFC% ;NO FREE CORE ERCODX ERRVNO,SSVNO% ;VIRTUAL CIRCUIT NOT OPEN ERCODX ERRICI,SSICI% ;INVALID CONNECT ID ERCODX ERRRQE,SSRQE% ;RECEIVE QUEUE EMPTY ERCODX ERRNBQ,SSNBQ% ;NO BUFFER QUEUED FOR PACKET RECEPTION ERCODX ERRRCF,SSRCF% ;REJECT CONNECTION FAILED ERCODX ERRDCF,SSDCF% ;DISCONNECT CONNECTION FAILED ERCODX ERRNFB,SSNFB% ;NO FREE BUFFERS TO SEND PACKET ERCODX ERRQBF,SSQBF% ;QUEUE BUFFERS FAILED ERCODX ERRCBF,SSCBF% ;CANCEL BUFFERS FAILED ERCODX ERRPSF,SSPSF% ;PACKET SEND FAILED ERCODX ERRDQE,SSDQE% ;DATA ENTRY QUEUE EMPTY ERCODX ERREQE,SSEQE% ;EVENT QUEUE EMPTY ERCODX ERRCRB,SSCRB% ;CAN'T REMOVE BUFFER FROM DATABASE ERCODX ERRCUB,SSCUB% ;CAN'T UNMAP BUFFER ERCODX ERRNSB,SSNSB% ;NO SUCH BUFFER NAME ERCODX ERRTMS,SSTMS% ;TOO MANY BUFFER SEGMENT DESCRIPTORS ERCODX ERRIDM,SSIDM% ;ILLEGAL DATA MODE ERCODX ERRSCP,SSSCP% ;SEGMENT CROSSES PAGE BOUNDARY ERCODX ERRSTL,SSSTL% ;SEGMENT TOO LONG (GREATER THAN 1 PAGE) SUBTTL FORMAT OF PROCESS QUEUE BLOCK ;THE PROCESS QUEUE BLOCK CONTAINS VARIOUS QUEUES ON WHICH MESSAGE ;BUFFERS, EVENT BLOCKS, CONNECTION BLOCKS, AND ETC. ARE QUEUED. ;THE PROCESS QUEUE BLOCK (PQB) IS ALWAYS POINTED TO BY AC P3. PHASE 0 ;DEFINE AS OFFSETS SCSTMQ:!BLOCK 1 ;TOP OF MESSAGE QUEUE SCSBMQ:!BLOCK 1 ;BOTTOM OF MESSAGE QUEUE SCSTDQ:!BLOCK 1 ;TOP OF DATAGRAM QUEUE SCSBDQ:!BLOCK 1 ;BOTTOM OF DATAGRAM QUEUE SCSTXQ:!BLOCK 1 ;TOP OF DMA TRANSFER COMPLETE QUEUE SCSBXQ:!BLOCK 1 ;BOTTOM OF DMA TRANSFER COMPLETE QUEUE SCSTEQ:!BLOCK 1 ;TOP OF EVENT BLOCK QUEUE SCSBEQ:!BLOCK 1 ;BOTTOM OF EVENT BLOCK QUEUE SCSTCQ:!BLOCK 1 ;TOP OF CONNECTION BLOCK QUEUE SCSBCQ:!BLOCK 1 ;BOTTOM OF CONNECTION BLOCK QUEUE SCSTXN:!BLOCK 1 ;TOP OF DMA BUFFER NAME QUEUE SCSBXN:!BLOCK 1 ;BOTTOM OF DMA BUFFER NAME QUEUE PQBLEN:! ;LENGTH OF PROCESS QUEUE BLOCK DEPHASE SUBTTL INITIALIZATION ;HERE FROM SCASER TO INITIALIZE THE SCS. UUO INTERFACE. SCSINI::SETZM SCSTIQ ;ZERO FLINK OF INTERRUPT LEVEL PACKET QUEUE XMOVEI T1,SCSTIQ ;SET BLINK MOVEM T1,SCSBIQ ; AS POINTER TO FLINK BLCAL. (SC.SNA##,<<.,SCSINT>>) ;TELL SCA ABOUT THIS ADDRESS STOPCD CPOPJ##,DEBUG,SCSCIS ;++CAN'T INITIALIZE SCS. UUO INTERFACE POPJ P, ;ALL DONE, RETURN SUBTTL SCS. UUO - DISPATCH ;HERE FROM UUOCON ON AN SCS. UUO. T1 CONTAINS THE CONTENTS OF THE ;USER'S ACCUMULATOR. SCS:: MOVE M,T1 ;GET ADDRESS OF ARGUMENT BLOCK PUSHJ P,SXPCS## ;SET UP FOR EXTENDED GETWRDS JRST ERRACR ;ADDRESS CHECK PUSHJ P,GETEWD## ;GRAB THE FIRST WORD OF USER'S ARGUMENT BLOCK JRST ERRACR ;ADDRESS CHECK MOVE P1,T1 ;SAVE FOR A WHILE LDB P4,[POINTR T1,SS.FNC] ;GET FUNCTION CODE IN P4 HRRES P4 ;EXTEND THE SIGN CAML P4,[MINFCN] ;LOWER THAN LOWEST? CAILE P4,MAXFCN ;GREATER THAN GREATEST? JRST ERRIFC ;NO, GIVE ERROR MOVSI T1,JP.POK ;PRIVILEGE BIT REQUIRED MOVSI T2,DF.UPV ;UNPRIVILEGED FUNCTION? TDNN T2,FCNTAB(P4) ;... PUSHJ P,PRVBIT## ;NO, MAKE SURE PRIVILEGED SKIPA T1,M ;GET ADDRESS OF USER'S ARGUMENT BLOCK AND SKIP JRST ERRNPV ;GIVE AN ERROR LDB T2,[POINTR P1,SS.LEN] ;GET LENGTH OF ARGUMENT BLOCK PUSHJ P,ARNGE## ;SEE IF LEGAL FOR I/O JRST ERRACR ;ADDRESS CHECK JRST ERRACS ;ADDRESS CHECK SKIPE P3,.PDSCS##(W) ;GET ADDRESS OF PROCESS QUEUE BLOCK JRST SCS.1 ;THERE IS ONE MOVSI T1,DF.NPB ;DOES THIS FUNCTION REQUIRE A PQB? TDNE T1,FCNTAB(P4) ;... JRST SCS.1 ;NO, SO DON'T BOTHER PUSHJ P,GETPQB ;TRY TO GET A PQB JRST ERRNFC ;NO FREE CORE SCS.1: MOVE T1,P1 ;GET FIRST WORD OF ARGUMENT BLOCK BACK LDB P1,[POINTR T1,SS.LEN] ;GET LENGTH OF ARGUMENT BLOCK SOJLE P1,ERRARG ;MUST HAVE AT LEAST 2 ARGUMENTS LDB P2,[POINTR T1,SS.CPU] ;GET POSSIBLE CPU ARGUMENT HRRZ T1,FCNTAB(P4) ;GET DISPATCH ADDRESS TXO T1,IFIW ;MAKE A LOCAL INDIRECT WORD PJRST (T1) ;DISPATCH TO PROCESSING ROUTINE ;ALL FUNCTIONS ARE DISPATCHED TO WITH THE FOLLOWING DATA IN THE AC'S: ; ; P1 - LENGTH OF ARGUMENT LIST EXCLUDING FUNCTION WORD ; P2 - CPU NUMBER (ALWAYS LOADED FROM FUNCTION WORD, BUT MAY ; NOT ALWAYS BE APPLICABLE) ; P3 - ADDRESS OF PROCESS QUEUE BLOCK ; M - ADDRESS OF USER'S ARGUMENT BLOCK ;DISPATCH FLAGS FOR SCS. UUO FUNCTIONS DF.UPV==(1B0) ;JOB NEED NOT BE PRIVILEGED DF.NPB==(1B1) ;FUNCTION DOES NOT REQUIRE A PQB ;FUNCTION CODE DISPATCH TABLE FOR SCS. UUO ZZ==. ;ADDRESS OF MINIMUM FUNCTION ;CUSTOMER FUNCTIONS GO HERE FCNTAB: EXP SCSCON ;(0) REQUEST A CONNECTION EXP SCSLIS ;(1) LISTEN FOR A CONNECTION EXP SCSREJ ;(2) REJECT A CONNECTION REQUEST EXP SCSDIS ;(3) DISCONNECT AND CLOSE A CONNECTION EXP SCSSDG ;(4) SEND A DATAGRAM EXP SCSQRD ;(5) QUEUE DATAGRAM BUFFERS EXP SCSSMG ;(6) SEND MESSAGE EXP SCSQRM ;(7) QUEUE MESSAGE BUFFERS XWD DF.NPB,SCSCSP ;(10) CONNECT STATE POLL XWD DF.UPV+DF.NPB,SCSRCD ;(11) RETURN CONFIGURATION DATA EXP SCSSTS ;(12) RETURN CONNECTION STATUS EXP SCSRMG ;(13) RECEIVE A MESSAGE EXP SCSMAP ;(14) MAP A BUFFER FOR DMA OPERATIONS EXP SCSUMP ;(15) UNMAP A MAPPED BUFFER EXP SCSSND ;(16) SEND DATA TO REMOTE HOST EXP SCSREQ ;(17) REQUEST DATA DELIVERY EXP ERRIFC ;(20) ADD INTERRUPT CHANNELS EXP ERRIFC ;(21) EXP SCSRDG ;(22) RECEIVE DATAGRAM EXP SCSACC ;(23) ACCEPT CONNECTION EXP SCSGDE ;(24) GET DATA REQUEST COMPLETE QUEUE ENTRY EXP SCSEVT ;(25) GET EVENT QUEUE ENTRY EXP SCSCRD ;(26) CANCEL DATAGRAM RECEPTION EXP SCSCRM ;(27) CANCEL MESSAGE RECEPTION XWD DF.UPV+DF.NPB,SCSGLN ;(30) GET LOCAL NODE NUMBER EXP ERRIFC ;(31) EXP ERRIFC ;(32) EXP ERRIFC ;(33) EXP ERRIFC ;(34) XWD DF.UPV+DF.NPB,SCSRBS ;(35) RETURN MINIMUM BUFFER SIZES XWD DF.UPV+DF.NPB,SCSRPS ;(36) RETURN PATH STATUS MINFCN==ZZ-FCNTAB ;MINIMUM LEGAL FUNCTION NUMBER MAXFCN==.-FCNTAB-1 ;MAXIMUM LEGAL FUNCTION NUMBER SUBTTL SCS. UUO - CONNECT ;*** WARNING - THE STKVAR AT SCSCON MUST MATCH THAT AT SCSLIS EXACTLY ;AS THESE TWO FUNCTIONS SHARE COMMON ERROR PROCESSING ROUTINES WHICH ;EXPECT THE ORDER OF THE STKVAR ARGUMENTS TO BE IDENTICAL. SCSCON: STKVAR SETZM DATADR ;ZERO THE POINTER TO CONNECTION DATA SETZM STRADR ;DITTO FOR STRING STORAGE CAIGE P1,.SQRCI ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO PUSHJ P,CPUPCB ;TRANSLATE CPU ARGUMENT INTO PCB POPJ P, ;ERROR, CODE ALREADY STORED EXCTUX ;GET THE NODE NUMBER SKIPL T1 ;CHECK FOR VALIDITY CAIL T1,MAXNDS ;... JRST ERRINN ;INVALID NODE NUMBER ADD T1,P6 ;OFFSET PCB ADDRESS BY NODE NUMBER SKIPN P5,.PCPBK(T1) ;GET PATH BLOCK ADDRESS JRST ERRVNO ;ERROR PUSHJ P,SCSUNM ;MOVE PROCESS NAMES INTO MONITOR SCRATCH STORAGE JRST ERRACR ;ADDRESS CHECK MOVEM T1,SPN ;SAVE THE POINTER TO SOURCE PROCESS NAME MOVEM T2,DPN ; AND DESTINATION PROCESS NAME MOVEM T3,STRADR ; AND ADDRESS OF FREE SPACE MOVEM T4,STRRET ; AND ROUTINE TO RETURN FREE SPACE EXCTUX ;GET POINTER TO CONNECTION DATA JRST CON.01 ;NONE SUPPLIED, PROCEED PUSHJ P,SCSUDM ;MOVE THE DATA INTO MONITOR SCRATCH STORAGE JRST LISACR ;ADDRESS CHECK MOVEM T1,DATADR ;SAVE THE POINTER TO CONNECTION DATA MOVEM T2,DATRET ; AND ROUTINE TO RETURN SPACE CON.01: SETZM MSGBUF ;ZERO MESSAGE BUFFER COUNT EXCTUX ;ANY MESSAGE BUFFERS? JRST CON.02 ;NO MOVX T2,C%MGSZ ;GET SIZE OF A MESSAGE BUFFER PUSHJ P,SCSCUB ;COUNT USER BUFFERS AND ADDRESS CHECK THEM JRST LISACR ;ADDRESS CHECK MOVEM T3,MSGBUF ;STORE NUMBER OF BUFFERS IN THE CHAIN CON.02: SETZM DGBUF ;ZERO DATAGRAM BUFFER COUNT EXCTUX ;ANY DATAGRAM BUFFERS? JRST CON.03 ;NO MOVX T2,C%DGSZ ;GET SIZE OF A DATAGRAM BUFFER PUSHJ P,SCSCUB ;COUNT USER BUFFERS AND ADDRESS CHECK THEM JRST LISACR ;ADDRESS CHECK MOVEM T3,DGBUF ;STORE NUMBER OF BUFFERS IN THE CHAIN CON.03: EXCTUX ;GET CID BITS FROM USER LOAD T2,PBPBI,(P5) ;GET PBI BLCAL. (SC.CON##,,T1,DATADR,MSGBUF,DGBUF>) JRST LISERR ;ERROR UMOVEM T1,.SQRCI(M) ;STORE RETURNED CONNECT ID MOVEM T1,CID ;SAVE FOR LATER SKIPE T1,DATADR ;ANY CONNECTION DATA? PUSHJ P,@DATRET ;YES, RETURN THE SPACE SKIPE T1,STRADR ;ANY STRING SPACE? PUSHJ P,@STRRET ;YES, RETURN THE SPACE $LDCID P1,CID ;GET CONNECTION BLOCK ADDRESS PUSHJ P,SCSCBI ;INIT THE CB WITH JSYS DATA PUSHJ P,SCSLCB ;LINK THIS CB ONTO THIS JOB'S CB QUEUE SKIPN MSGBUF ;ANY MESSAGE BUFFERS? JRST CON.04 ;NO UMOVE T1,.SQAMC(M) ;GET POINTER TO FIRST BUFFER MOVX T2,.BDFMG ;PUT IT ON THE MESSAGE BUFFER LIST PUSHJ P,SCSXUB ;LINK THIS CHAIN ONTO CB JRST LISACR ;ADDRESS CHECK CON.04: SKIPN DGBUF ;ANY DATAGRAM BUFFERS? JRST CPOPJ1## ;NO, SKIP RETURN UMOVE T1,.SQADC(M) ;GET POINTER TO FIRST BUFFER MOVX T2,.BDFDG ;PUT IT ON THE DATAGRAM BUFFER LIST PUSHJ P,SCSXUB ;LINK THIS CHAIN ONTO CB JRST LISACR ;ADDRESS CHECK JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - LISTEN ;*** WARNING - THE STKVAR AT SCSCON MUST MATCH THAT AT SCSLIS EXACTLY ;AS THESE TWO FUNCTIONS SHARE COMMON ERROR PROCESSING ROUTINES WHICH ;EXPECT THE ORDER OF THE STKVAR ARGUMENTS TO BE IDENTICAL. SCSLIS: STKVAR SETZM DATADR ;ZERO THE POINTER TO CONNECTION DATA SETZM STRADR ;DITTO FOR STRING STORAGE CAIGE P1,.SQLCI ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO PUSHJ P,CPUPCB ;TRANSLATE CPU NUMBER INTO PCB POPJ P, ;ERROR, CODE ALREADY STORED SETO P5, ;ASSUME A "DON'T CARE" LISTENER EXCTUX ;GET THE NODE NUMBER CAMN T1,[-1] ;IS IT A "DON'T CARE" LISTEN? JRST LIS.01 ;YES SKIPL T1 ;CHECK FOR VALIDITY CAIL T1,MAXNDS ;... JRST ERRINN ;INVALID NODE NUMBER ADD T1,P6 ;OFFSET PCB ADDRESS BY NODE NUMBER SKIPN P5,.PCPBK(T1) ;GET PATH BLOCK ADDRESS JRST ERRVNO ;ERROR LIS.01: PUSHJ P,SCSUNM ;MOVE PROCESS NAMES INTO MONITOR SCRATCH STORAGE JRST ERRACR ;ADDRESS CHHECK MOVEM T1,SPN ;SAVE THE POINTER TO SOURCE PROCESS NAME MOVEM T2,DPN ; AND DESTINATION PROCESS NAME MOVEM T3,STRADR ; AND ADDRESS OF FREE SPACE MOVEM T4,STRRET ; AND ROUTINE TO RETURN FREE SPACE SKIPL T1,P5 ;IS THIS A "DON'T CARE" LISTEN? LOAD T1,PBPBI,(P5) ;NO, GET PATH BLOCK INDEX EXCTUX ;GET CID BITS BLCAL. (SC.LIS##,,T2,[0],[0]>) JRST LISERR ;ERROR UMOVEM T1,.SQLCI(M) ;STORE RETURNED CONNECT ID MOVEM T1,CID ;SAVE FOR LATER MOVE T1,STRADR ;GET THE ADDRESS OF THE STRING SPACE PUSHJ P,@STRRET ;RETURN THE SPACE $LDCID P1,CID ;GET THE CB ADDRESS FOR THE CID PUSHJ P,SCSCBI ;INITIALIZE THE CONNECTION BLOCK PUSHJ P,SCSLCB ;LINK THIS NEW CB ONTO FORK CB QUEUE JRST CPOPJ1## ;SKIP RETURN LISACR: MOVEI T1,SSACR% ;GET ERROR CODE LISERR: MOVEM T1,ERRCOD ;SAVE IT SKIPE T1,DATADR ;ANY CONNECTION DATA? PUSHJ P,@DATRET ;YES, RETURN THE SPACE SKIPE T1,STRADR ;ANY STRING SPACE? PUSHJ P,@STRRET ;YES, RETURN THE SPACE MOVE T1,ERRCOD ;GET ERROR CODE BACK PJRST STOTAC## ;STORE ERROR CODE AND RETURN ENDSV. ;END STACK VARIABLE FROM SCSCON SUBTTL SCS. UUO - RECEIVE DATAGRAM/MESSAGE SCSRDG: TDZA T1,T1 ;INDICATE WE ARE DOING DATAGRAM SCSRMG: SETO T1, ;INDICATE WE ARE DOING MESSAGE CAIGE P1,.SQLRP ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO SAVEAC ;SAVE AN AC STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,MSGFLG ;SAVE ENTRY FLAG XMOVEI Q1,MSG ;ASSUME WE ARE DOING MESSAGES SKIPN MSGFLG ;GOOD GUESS? XMOVEI Q1,DG ;NO SETZM USRBUF ;ZERO SOME ERROR RECOVERY VARIABLES SETZM PAKADR ;... UMOVE T1,.SQCID(M) ;GET CONNECT ID CAMN T1,[-1] ;DO WE WANT FIRST FOR CONNECTION OR CONTEXT? JRST RDG.01 ;FIRST FOR CONTEXT PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR SKIPN T1,@.TOPCQ(Q1) ;ARE THERE ANY PACKETS QUEUED FOR THIS CONNECT? JRST ERRRQE ;NO, ERROR MOVEM T1,PAKADR ;SAVE THE ADDRESS OF THE PACKET JRST RDG.02 ;CONTINUE RDG.01: SKIPN T1,@.TOPFQ(Q1) ;IS THERE A PACKET WAITING FOR THIS CONTEXT? JRST ERRRQE ;NO MOVEM T1,PAKADR ;SAVE THE ADDRESS OF THE PACKET MOVE T1,.MECID(T1) ;GET THE CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR UMOVEM T1,.SQCID(M) ;LET THEM KNOW WHO PACKET WAS FOR RDG.02: SKIPG @.JBUFF(Q1) ;ARE THERE BUFFERS QUEUED? JRST ERRNBQ ;NO MOVE T1,PAKADR ;GET THE PACKET ADDRESS BACK MOVE T2,Q1 ;POINT TO THE LIST POINTERS PUSHJ P,SCSDEQ ;DEQUEUE THE BUFFER FROM THE QUEUES MOVX T1,.BDFMG ;ASSUME DOING MESSAGES SKIPN MSGFLG ;GOOD GUESS? MOVX T1,.BDFDG ;NO, DATAGRAMS PUSHJ P,SCSGUB ;GET A USER DATAGRAM BUFFER ADDRESS JRST RDGNBQ ;NEED TO RETURN THIS BUFFER MOVEM T1,USRBUF ;STORE USER BUFFER ADDRESS UMOVEM T1,.SQARB(M) ;RETURN THE ADDRESS OF THE DATA MOVE T4,PAKADR ;GET ADDRESS OF THE PACKET LOAD T1,MELEN,(T4) ;GET THE LENGTH OF THE DATAGRAM MOVE T2,.METYP(T4) ;GET PACKET FLAGS TXNE T2,F.SPM ;HIGH DENSITY MODE? SUBI T1,.MHLNW ;YES, ACCOUNT FOR PACKET HEADER TXNN T2,F.SPM ;INDUSTRY COMPATIBLE MODE? SUBI T1,.MHLNB ;YES, ACCOUNT FOR PACKET HEADER MOVEM T1,LEN ;SAVE LENGTH UMOVEM T1,.SQLRP(M) ;RETURN TO THE USER TXNE T2,F.SPM ;INDUSTRY COMPATIBLE? JRST RDG.03 ;NO, NO EXTRA BYTES TO ZERO IDIVI T1,4 ;CONVERT TO LENGTH IN WORDS JUMPE T2,RDG.03 ;JUMP IF NO REMAINDER ADDI T1,1 ;ROUND UP TO EVEN NUMBER OF WORDS IMULI T2,^D8 ;GET NUMBER OF BITS TO CLEAR MOVNI T2,-1(T2) ;NEGATE NUMBER OF BITS AND SUBTRACT ONE MOVX T3,1B0 ;GET LEFT-MOST BIT ASH T3,(T2) ;MAKE A MASK MOVE T2,PAKADR ;GET PACKET ADDRESS ADDI T2,.MHUDA-1(T1) ;OFFSET TO LAST WORD OF USER DATA ANDM T3,(T2) ;CLEAR EXCESS BITS IN LAST WORD RDG.03: MOVE T2,PAKADR ;GET SOURCE ADDRESS ADDI T2,.MHUDA ;DON'T MOVE THE HEADER MOVE T3,USRBUF ;ADDRESS OF USER'S BUFFER PUSHJ P,SCSDMU ;MOVE DATA TO USER SPACE JRST RDGACS ;ERROR MOVE T1,PAKADR ;GET PACKET ADDRESS AGAIN LOAD T3,MEFLG,(T1) ;GET THE FLAGS EXCTXU ;STORE FOR USER SKIPN MSGFLG ;DOING MESSAGES? PUSHJ P,SC.RLD## ;NO, DATAGRAM, RETURN IT SKIPE MSGFLG ;DOING MESSAGES? PUSHJ P,SC.RBF## ;NO, MESSAGE, RETURN IT LOAD T1,PBDPN,(P5) ;GET PATH BLOCK ADDRESS EXCTXU ;STORE FOR USER IFN FTPI,< PUSHJ P,SCSSIG ;SIGNAL ANOTHER INTERRUPT IF NECESSARY >; END IFN FTPI JRST CPOPJ1## ;SKIP RETURN ;HERE ON ERROR RDGNBQ: SKIPA T1,[SSNBQ%] ;GET ERROR CODE AND SKIP RDGACS: MOVEI T1,SSACS% ;GET ERROR CODE RDGERR: MOVEM T1,ERRCOD ;SAVE ERROR CODE SKIPN T1,USRBUF ;IS THERE A USER BUFFER TO WORRY ABOUT? JRST RDGER2 ;NO MOVX T2,.BDFMG ;ASSUME MESSAGE SKIPN MSGFLG ;GOOD GUESS? MOVX T2,.BDFDG ;NO, DATAGRAM PUSHJ P,SCSLUB ;RE-LINK USER BUFFER JFCL ;ERROR RDGER2: SKIPN T1,PAKADR ;DID WE DEQUEUE A PACKET? JRST RDGER3 ;NO MOVE T2,Q1 ;POINT TO THE 4-WORD LIST HEADER BLOCK PUSHJ P,SCSLFQ ;PUT ON BEGINNING OF QUEUE RDGER3: MOVE T1,ERRCOD ;GET ERROR CODE PJRST STOTAC## ;STORE ERROR CODE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - REJECT SCSREJ: CAIGE P1,.SQREJ ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR UMOVE T2,.SQREJ(M) ;GET REJECT REASON FROM USER BLCAL. (SC.REJ##,) ;DO THE REJECT JRST ERRRCF ;ERROR PUSHJ P,SCSCBD ;DONE WITH CONNECT, DELETE JSYS DATA JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - DISCONNECT SCSDIS: CAIGE P1,.SQDIS ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR LOAD T1,CBJCH,(P1) ;GET THE JCH CAME T1,.CPJCH## ;DOES THIS JOB/CONTEXT OWN IT? JRST ERRICI ;ERROR UMOVE T1,.SQCID(M) ;GET CONNECT ID AGAIN UMOVE T2,.SQDIS(M) ;GET DISCONNECT REASON FROM USER BLCAL. (SC.DIS##,) ;DO THE DISCONNECT JRST ERRDCF ;ERROR PUSHJ P,SCSCBD ;DONE WITH CONNECT, DELETE JSYS DATA JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - SEND DATAGRAM/MESSAGE SCSSDG: TDZA T1,T1 ;INDICATE WE ARE DOING DATAGRAM SCSSMG: SETO T1, ;INDICATE WE ARE DOING MESSAGE CAIGE P1,.SQFLG ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,MSGFLG ;SAVE THE ENTRY TYPE SETZM BUFADR ;INIT THE BUFFER ADDRESS AS ZERO UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR MOVEM T1,CID ;SAVE THE CID FOR LATER MOVEI T1,1 ;ASK FOR A PACKET BUFFER SKIPN MSGFLG ;DOING MESSAGE SEND? JRST SDG.01 ;NO, REQUEST A DATAGRAM BUFFER PUSHJ P,SC.ABF## ;ASK SCASER FOR A MESSAGE BUFFER JRST ERRNFB ;ERROR MOVX T2,JH%DGB ;INDICATE THIS IS A MESSAGE BUFFER ANDCAM T2,.JHFLG(T1) ;... JRST SDG.02 ;CONTINUE SDG.01: PUSHJ P,SC.ALD## ;ASK SCASER FOR A DATAGRAM BUFFER JRST ERRNFB ;ERROR MOVX T2,JH%DGB ;INDICATE THIS IS A DATAGRAM BUFFER IORM T2,.JHFLG(T1) ;... SDG.02: MOVEM T1,BUFADR ;SAVE ADDRESS OF BUFFER UMOVE T2,.SQAPT(M) ;GET USER ADDRESS OF PACKET TEXT MOVEM T2,.JHAUB(T1) ;STORE THE ADDRESS OF THE USER BUFFER UMOVE T1,.SQLPT(M) ;GET LENGTH OF PACKET UMOVE T2,.SQFLG(M) ;GET FLAGS WORD TXNE T2,SC%MOD ;IS THIS A HIGH DENSITY PACKET? JRST SDG.03 ;YES ADDI T1,3 ;NO, ROUND UP BYTE COUNT LSH T1,-2 ;CONVERT BYTE COUNT TO WORD COUNT SDG.03: MOVX T3, ;ASSUME A MESSAGE SKIPN MSGFLG ;GOOD GUESS? MOVX T3, ;NO CAMLE T1,T3 ;IS THE TEXT TOO LONG? JRST SDGSTL ;YES MOVE T3,BUFADR ;GET THE ADDRESS OF THE MONITOR BUFFER MOVE T2,.JHAUB(T3) ;ADDRESS OF USER BUFFER ADDI T3,.MHUDA ;OFFSET TO TEXT AREA IN BUFFER PUSHJ P,SCSDUM ;MOVE THE DATA FROM USER TO MONITOR JRST SDGACS ;ERROR MOVX T2,F.RTB ;START WITH JUST THE RETURN BUFFER FLAG UMOVE T3,.SQFLG(M) ;GET FLAGS WORD AGAIN TXNE T3,SC%MOD ;IS THIS A HIGH DENSITY PACKET? TXO T2,F.SPM ;YES LOAD T3,SC%OPS,T3 ;GET OPTIONAL PATH SPEC UMOVE T4,.SQLPT(M) ;GET LENGTH OF PACKET SKIPN MSGFLG ;DOING MESSAGE SEND? JRST SDG.04 ;NO BLCAL. (SC.SMG##,) JRST SDGERR ;ERROR JRST CPOPJ1## ;SKIP RETURN SDG.04: BLCAL. (SC.SDG##,) JRST SDGERR ;ERROR JRST CPOPJ1## ;SKIP RETURN SDGSTL: SKIPA T1,[SSSTL%] ;GET ERROR CODE AND SKIP SDGACS: MOVEI T1,SSACS% ;GET ERROR CODE SDGERR: MOVEM T1,ERRCOD ;SAVE ERROR CODE SKIPN T1,BUFADR ;IS THERE A BUFFER OWNED? JRST SDGER2 ;NO SKIPN MSGFLG ;DATAGRAM? PUSHJ P,SC.RLD## ;YES SKIPE MSGFLG ;MESSAGE? PUSHJ P,SC.RBF## ;YES SDGER2: MOVE T1,ERRCOD ;GET ERROR CODE BACK PJRST STOTAC## ;STORE ERROR CODE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - QUEUE DATAGRAM/MESSAGE BUFFERS SCSQRD: TDZA T1,T1 ;INDICATE WE ARE DOING DATAGRAM SCSQRM: SETO T1, ;INDICATE WE ARE DOING MESSAGE CAIGE P1,.SQAFB ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,QRMFLG ;SAVE ENTRY TYPE FLAG UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR MOVEM T1,CID ;SAVE THE CID FOR LATER UMOVE T1,.SQAFB(M) ;GET THE ADDRESS OF THE FIRST BUFFER MOVX T2,C%MGSZ ;ASSUME THEY'RE QUEUEING MESSAGE BUFFERS SKIPN QRMFLG ;GOOD GUESS? MOVX T2,C%DGSZ ;NO, GET THE SIZE FOR DATAGRAMS PUSHJ P,SCSCUB ;COUNT AND ADDRESS CHECK USER BUFFERS JRST ERRACR ;ADDRESS CHECK MOVE P2,T3 ;SAVE COUNT FOR A MOMENT UMOVE T1,.SQAFB(M) ;GET ADDRESS OF USER BUFFER AGAIN MOVX T2,.BDFMG ;ASSUME THEY'RE QUEUEING MESSAGE BUFFERS SKIPN QRMFLG ;GOOD GUESS? MOVX T2,.BDFDG ;NO, THEY'RE DATAGRAM BUFFERS PUSHJ P,SCSXUB ;LINK THESE BUFFERS INTO DATABASE POPJ P, ;ERROR SKIPN QRMFLG ;DOING DATAGRAMS? JRST QRD.01 ;YES BLCAL. (SC.RMG##,) ;QUEUE BUFFERS FOR THIS CONNECTION JRST ERRQBF ;ERROR JRST CPOPJ1## ;SUCCESS QRD.01: BLCAL. (SC.RDG##,) ;QUEUE BUFFERS FOR THIS CONNECTION JRST ERRQBF ;ERROR JRST CPOPJ1## ;SUCCESS ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - CANCEL BUFFERS SCSCRM: TDZA T1,T1 ;SET THE MESSAGE FLAG SCSCRD: SETO T1, ;SET THE DATAGRAM FLAG CAIGE P1,.SQADB ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,CRDFLG ;SAVE THE ENTRY FLAG UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR MOVEM T1,CID ;SAVE CONNECT ID FOR LATER UMOVE T1,.SQADB(M) ;GET ADDRESS OF THE BUFFER TO RETURN PUSHJ P,SCSRUB ;REMOVE THE BUFFER FROM THE DATABASE POPJ P, ;ERROR SKIPN CRDFLG ;ARE WE DOING DATAGRAMS? JRST CRM.01 ;NO, CANCEL A MESSAGE BLCAL. (SC.CRD##,) ;CANCEL ONE DATAGRAM JRST ERRCBF ;ERROR SOS .CBDGJ(P1) ;ONE LESS DATAGRAM QUEUED JRST CPOPJ1## ;SKIP RETURN CRM.01: BLCAL. (SC.CRM##,) ;CANCEL ONE MESSAGE JRST ERRCBF ;ERROR SOS .CBMGJ(P1) ;ONE LESS MESSAGE QUEUED JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - CONNECT STATE POLL SCSCSP: CAIGE P1,.SQREA ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR LOAD T1,CBCNST,(P1) ;GET CONNECT STATE UMOVEM T1,.SQCST(M) ;STORE IT MOVE T1,.CBDCI(P1) ;GET DESTINATION CONNECT ID UMOVEM T1,.SQDCI(M) ;STORE IT MOVE T1,.CBPBK(P1) ;ADDRESS OF PATH BLOCK LOAD T1,PBDPN,(T1) ;GET DESTINATION NODE NUMBER UMOVEM T1,.SQNOD(M) ;STORE IT LOAD T1,CBDDRE,(P1) ;GET DESTINATION DISCONNECT REASON LOAD T2,CBSDRE,(P1) ;GET SOURCE DISCONNECT REASON HRL T1,T2 ;COMBINE IN T1 UMOVEM T1,.SQREA(M) ;STORE IT UMOVE T1,.SQBDN(M) ;GET BYTE POINTER TO RETURN PROCESS NAME TLC T1,-1 ;SEE IF A GENERIC BYTE POINTER TLCE T1,-1 ;... JRST CSP.01 ;NO, USE WHAT USER SUPPLIED HLL T1,M ;MAKE A SECTION LOCAL TLO T1,610000 ; ONE-WORD GLOBAL BYTE POINTER CSP.01: MOVE P2,T1 ;SAVE THE BYTE POINTER ACROSS CALL TO PRNGE MOVX T2,C%PNMN ;LENGTH OF PROCESS NAME IN BYTES PUSHJ P,PRNGE## ;SEE IF LEGAL TO STORE IN THAT BUFFER JRST ERRACS ;ILLEGAL ADDRESS JRST ERRACS ;ILLEGAL FOR I/O MOVX T1,C%PNMN ;LENGTH OF PROCESS NAME IN BYTES MOVE T2,[POINT 8,.CBDPN(P1)] ;BYTE POINTER TO PROCESS NAME CSP.02: ILDB T3,T2 ;GET A BYTE EXCTXU ;STORE THE BYTE SOJG T1,CSP.02 ;LOOP FOR THE WHOLE THING JRST CPOPJ1## ;NOW SKIP RETURN SUBTTL SCS. UUO - RETURN CONFIGURATION DATA SCSRCD: CAIGE P1,.SQLPN ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO EXCTUX ;GET CONNECT ID JRST RCD.01 ;CONNECT ID IS ZERO, USE OPTIONAL NODE NUMBER PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR JRST RCD.02 ;CONTINUE RCD.01: PUSHJ P,CPUPCB ;TRANSLATE CPU ARGUMENT INTO PCB POPJ P, ;ERROR, CODE ALREADY STORED EXCTUX ;GET NODE NUMBER, CHECK FOR VALIDITY CAIL T1,MAXNDS ;... JRST ERRINN ;INVALID NODE NUMBER ADD T1,P6 ;OFFSET PCB ADDRESS BY NODE NUMBER SKIPN P5,.PCPBK(T1) ;GET PATH BLOCK ADDRESS JRST ERRVNO ;ERROR RCD.02: LOAD P4,PBSBI,(P5) ;GET SYSTEM BLOCK INDEX SKIPN P4,SBLIST##-1(P4) ;GET THE SYSTEM BLOCK ADDRESS JRST ERRVNO ;ERROR LOAD T1,SBDPN,(P4) ;GET DESTINATION PORT NUMBER LOAD T2,PBVCST,(P5) ;GET VIRTUAL CIRCUIT STATE HRL T1,T2 ;COMBINE IN T1 UMOVEM T1,.SQVCS(M) ;STORE IT DMOVE T1,.SBDSA(P4) ;GET TWO WORDS OF SYSTEM ADDRESS EXCTXU ;STORE THEM LOAD T1,SBMXDG,(P4) ;GET MAXIMUM DATAGRAM SIZE UMOVEM T1,.SQMDD(M) ;STORE IT LOAD T1,SBMXMG,(P4) ;GET MAXIMUM MESSAGE SIZE UMOVEM T1,.SQMDM(M) ;STORE IT MOVE T1,.SBDST(P4) ;GET DESTINATION SOFTWARE TYPE UMOVEM T1,.SQDST(M) ;STORE IT MOVE T1,.SBDSV(P4) ;GET DESTINATION SOFTWARE VERSION UMOVEM T1,.SQDSV(M) ;STORE IT DMOVE T1,.SBDSE(P4) ;GET TWO WORDS OF DESTINATION SOFTWARE EDIT EXCTXU ;STORE THEM MOVE T1,.SBDHT(P4) ;GET DESTINATION HARDWARE TYPE UMOVEM T1,.SQDHT(M) ;STORE IT DMOVE T1,.SBDHV(P4) ;GET TWO WORDS OF DESTINATION HARDWARE VERSION EXCTXU ;STORE THEM MOVE T1,.SBDHV+2(P4) ;GET THIRD WORD OF DESTINATION HARDWARE VERSION UMOVEM T1,.SQDHV+2(M) ;STORE IT DMOVE T1,.SBNNM(P4) ;GET TWO WORDS OF DESTINATION NODE NAME EXCTXU ;STORE THEM MOVE T1,.PBDPC(P5) ;GET DESTINATION PORT CHARACTERISTICS UMOVEM T1,.SQPCW(M) ;STORE IT MOVEI T1,KLPICH ;RH20 CHANNEL FOR THE KLIPA UMOVEM T1,.SQLPN(M) ;STORE IT JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - RETURN STATUS OF CONNECT SCSSTS: CAIGE P1,.SQSBR ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR LOAD T1,CBCNST,(P1) ;GET THE CONNECTION STATE SKIPE .CBTMQ(P1) ;ANY MESSAGES PENDING? TXO T1,SC%MSA ;YES SKIPE .CBTDQ(P1) ;ANY DATAGRAMS AVAILABLE? TXO T1,SC%DGA ;YES SKIPE .CBTXQ(P1) ;ANY DATA REQUESTS PENDING? TXO T1,SC%DTA ;YES SKIPE .CBTEQ(P1) ;AN EVENT PENDING? TXO T1,SC%EVA ;YES UMOVEM T1,.SQFST(M) ;STORE IT MOVE T1,.CBPBK(P1) ;GET PATH BLOCK ADDRESS LOAD T1,PBDPN,(T1) ;GET DESTINATION NODE NUMBER UMOVEM T1,.SQSBR(M) ;STORE IT JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - MAP A BUFFER SCSMAP: CAIGE P1,.SQBNA+.SQBAD+1 ;ROOM IN ARGUMENT BLOCK JRST ERRARG ;NO PUSHJ P,CPUPCB ;TRANSLATE CPU ARGUMENT INTO PCB POPJ P, ;ERROR, CODE ALREADY STORED MOVEI T1,-.SQBNA(P1) ;GET USER LENGTH MINUS OVERHEAD CAILE T1,/<.SQBAD+1> ;MORE SEGMENTS THAN WE CAN HANDLE? JRST ERRTMS ;TOO MANY SEGMENTS LSH T1,-1 ;CONVERT TO NUMBER OF SEGMENT DESCRIPTORS MOVE P1,T1 ;SAVE COUNT IN P1 MOVE P2,M ;COPY ADDRESS OF ARGUMENT BLOCK ADDI P2,.SQBNA+1 ;OFFSET TO FIRST USER SEGMENT DESCRIPTOR ;WHAT ABOUT CROSSING SECTION BOUNDARIES HERE? IS THERE A BETTER WAY ;TO INCREMENT THE ADDRESS? STKVAR ;ALLOCATE SOME STACK STORAGE MOVEI T1,1 ;ASK FOR A DATAGRAM BUFFER PUSHJ P,SC.ALD## ; TO USE FOR THE MAP DESCRIPTOR BLOCK JRST ERRNFC ;NOT AVAILABLE MOVEM T1,FBADDR ;SAVE HERE FOR LATER USE MOVE P4,T1 ;COPY HERE FOR IMMEDIATE USE UMOVE T1,.SQXFL(M) ;GET THE USERS FLAGS ANDX T1,MD%FLG ;KEEP ONLY THE DEFINED ONES TXO T1,SQ%WRT ;SET THE WRITABLE BIT ALWAYS MOVEM T1,.MDFLG(P4) ;STORE FLAGS/MODE IN DESCRIPTOR BLOCK LOAD T1,MD%DMD,T1 ;GET THE BUFFER MODE CAILE T1,MD%DHD ;IS IT A LEGAL VALUE? JRST MAPIDM ;NO MOVEM T1,MODE ;SAVE MODE FOR LATER ADDI P4,.MDSSD ;OFFSET TO FIRST DESCRIPTOR BLOCK MAP.01: UMOVE T3,.SQBLN(P2) ;GET LENGTH OF SEGMENT JUMPE T3,MAP.04 ;ZERO LENGTH MEANS END OF DESCRIPTORS MOVEM T3,.MDLEN(P4) ;STORE LENGTH IN DESCRIPTOR MOVE T1,MODE ;GET THE MODE CAIN T1,MD%DIC ;IS IT INDUSTRY COMPATIBLE? JRST MAP.02 ;YES LSH T3,1 ;NO, CONVERT NIBBLES TO WORDS IDIVI T3,^D9 ;(MULTIPLY BY 2/9) SKIPE T4 ;A REMAINDER? ADDI T3,1 ;YES, ADD ONE TO THE WORD COUNT JRST MAP.03 ;CONTINUE MAP.02: LSH T3,-2 ;CONVERT BYTE COUNT TO WORD COUNT MAP.03: MOVEM T3,WRDLEN ;SAVE NUMBER OF WORDS IN SEGMENT CAILE T3,PGSIZ ;BLOCK LONGER THAN ONE PAGE? JRST MAPSTL ;YES UMOVE T1,.SQBAD(P2) ;GET ADDRESS OF SEGMENT MOVE T2,T3 ;COPY LENGTH PUSHJ P,ARNGE## ;SEE IF WRITABLE JFCL ;YES JRST MAPACS ;ERROR EXCTUU ;GET THE PHYSICAL ADDRESS TXNE T1,MP.BAD ;BAD MAPPING? JRST MAPSCP ;YES, ASSUME THEY PASSED US GARBAGE TXZ T1,MP.NAD ;CLEAR NON-ADDRESS BITS MOVE T2,T1 ;COPY THE PHYSICAL ADDRESS ANDI T2,PG.BDY## ;KEEP ONLY THE PAGE OFFSET ADD T2,T3 ;ADD THE LENGTH OF THE SEGMENT CAILE T2,PGSIZ ;MORE THAN A PAGE IN LENGTH? JRST MAPSCP ;YES MOVEM T1,.MDADR(P4) ;SAVE SEGMENT ADDRESS ADDI P4,.MDLSD ;POINT AT NEXT SEGMENT DESCRIPTOR ADDI P2,.SQBAD+1 ;... SOJG P1,MAP.01 ;LOOP FOR OTHER SEGMENTS ;CALL SCA TO MAP THIS BUFFER MAP.04: BLCAL. (SC.MAP##,) ;DO THE REAL WORK JRST MAPERR ;ERROR UMOVEM T1,.SQBNA(M) ;TELL USER THE BUFFER NAME PUSHJ P,SCSAXN ;ADD THE NAME TO THE CONTEXT'S DATABASE JRST MAPNFC ;ERROR MOVE T1,FBADDR ;GET THE BUFFER ADDRESS PUSHJ P,SC.RLD## ;RETURN IT TO SCA JRST CPOPJ1## ;SKIP RETURN ;HERE ON ERRORS MAPSCP: MOVEI T1,SSSCP% ;GET ERROR CODE JRST MAPERR ;JOIN COMMON CODE MAPSTL: SKIPA T1,[SSSTL%] ;GET ERROR CODE AND SKIP MAPACS: MOVEI T1,SSACS% ;GET ERROR CODE JRST MAPERR ;JOIN COMMON CODE MAPIDM: SKIPA T1,[SSIDM%] ;GET ERROR CODE AND SKIP MAPNFC: MOVEI T1,SSNFC% ;GET ERROR CODE MAPERR: MOVEM T1,ERRCOD ;SAVE ERROR CODE MOVE T1,FBADDR ;GET THE BUFFER ADDRESS PUSHJ P,SC.RLD## ;RETURN IT TO SCA MOVE T1,ERRCOD ;GET THE ERROR CODE PJRST STOTAC## ;STORE IT AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - UNMAP A BUFFER SCSUMP: CAIGE P1,.SQNAM ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO PUSHJ P,CPUPCB ;TRANSLATE CPU ARGUMENT INTO PCB POPJ P, ;ERROR, CODE ALREADY STORED STKVAR ;ALLOCATE SOME STACK STORAGE UMOVE T1,.SQNAM(M) ;GET THE BUFFER NAME MOVEM T1,BUFNAM ;SAVE IT PUSHJ P,SCSFXN ;SEE IF WE HAVE SUCH A BUFFER NAME JRST ERRNSB ;ERROR MOVE T1,BUFNAM ;GET BUFFER NAME AGAIN PUSHJ P,SCSDXN ;REMOVE IT FROM THE DATABASE JRST ERRCRB ;ERROR JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - SEND/REQUEST DATA SCSREQ: TDZA T1,T1 ;INDICATE THIS IS A REQUEST SCSSND: SETO T1, ;INDICATE THIS IS A SEND CAIGE P1,.SQOFS ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,SNDFLG ;SAVE ENTRY TYPE FLAG UMOVE T1,.SQCID(M) ;GET CONNECTION ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR MOVEM T1,CID ;SAVE FOR LATER UMOVE T1,.SQSNM(M) ;GET NAME OF BUFFER TO SEND UMOVE T2,.SQRNM(M) ;GET NAME OF BUFFER TO RECEIVE EXCTUX ;GET SEND BUFFER OFFSET EXCTUX ;GET RECEIVE BUFFER OFFSET SKIPN SNDFLG ;ARE WE DOING A SEND? JRST REQ.01 ;NO BLCAL. (SC.SND##,) JRST ERRPSF ;ERROR JRST CPOPJ1## ;SKIP RETURN REQ.01: BLCAL. (SC.REQ##,) JRST ERRPSF ;ERROR JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - ACCEPT CONNECTION SCSACC: CAIGE P1,.SQCDA ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR ;ALLOCATE SOME STACK STORAGE SETZM DATADR ;ZERO ADDRESS OF CONNECTION DATA UMOVE T1,.SQCID(M) ;GET CONNECT ID PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR MOVEM T1,CID ;SAVE FOR LATER UMOVE T1,.SQCDA(M) ;GET THE ADDRESS OF THE CONNECTION DATA JUMPE T1,ACC.01 ;JUMP IF NO USER CONNECTION DATA PUSHJ P,SCSUDM ;MOVE THE USER CONNECT DATA JRST ERRACR ;ADDRESS CHECK MOVEM T1,DATADR ;SAVE THE ADDRESS OF THE CONNECT DATA MOVEM T2,DATRET ; AND THE ROUTINE TO RETURN FREE SPACE ACC.01: BLCAL. (SC.ACC##,) ;DO THE ACCEPT JRST ACCERR ;ERROR SKIPE T1,DATADR ;ANY USER CONNECTION DATA? PUSHJ P,@DATRET ;YES, RETURN IT JRST CPOPJ1## ;SKIP RETURN ACCERR: MOVEM T1,ERRCOD ;SAVE THE ERROR CODE SKIPE T1,DATADR ;ANY USER CONNECTION DATA? PUSHJ P,@DATRET ;YES, RETURN IT MOVE T1,ERRCOD ;GET ERROR CODE BACK PJRST STOTAC## ;STORE ERROR CODE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - GET DATA QUEUE ENTRY SCSGDE: CAIGE P1,.SQBID ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR ;ALLOCATE A WORD OF STACK STORAGE UMOVE T1,.SQCID(M) ;GET THE CONNECT ID CAMN T1,[-1] ;WANT NEXT FOR THE CONTEXT? JRST GDE.01 ;YES PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR SKIPN T1,.CBTXQ(P1) ;IS THERE ANYTHING ON THE QUEUE? JRST ERRDQE ;NO JRST GDE.02 ;CONTINUE GDE.01: SKIPN T1,SCSTXQ(P3) ;ANYTHING ON CONTEXT QUEUE? JRST ERRDQE ;NO $LDCID P1,.MECID(T1) ;GET CB ADDRESS FROM CID GDE.02: XMOVEI T2,XFER ;POINT TO THE BLOCK PUSHJ P,SCSDEQ ;DEQUEUE THE BUFFER MOVE T2,.DMNAM(T1) ;GET THE BUFFER NAME FROM THE BLOCK UMOVEM T2,.SQBID(M) ;GIVE IT TO THE USER PUSHJ P,RELRES ;RETURN THE FREE SPACE IFN FTPI,< PUSHJ P,SCSSIG ;SIGNAL ANOTHER INTERRUPT IF NECESSARY >; END IFN FTPI JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - GET EVENT QUEUE ENTRY SCSEVT::CAIGE P1,.SQEVT ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO STKVAR MOVEM P1,USRLEN ;SAVE LENGTH OF BLOCK UMOVE T1,.SQCID(M) ;GET THE CONNECT ID CAMN T1,[-1] ;FOR CONTEXT OR CONNECTION? JRST EVT.01 ;CONTEXT PUSHJ P,CHKCID ;CHECK THE CID JRST ERRICI ;ERROR SKIPN T1,.CBTEQ(P1) ;IS THERE ANYTHING ON THE QUEUE? JRST ERREQE ;NO JRST EVT.02 ;PROCEED EVT.01: SKIPN T1,SCSTEQ(P3) ;IS THERE SOMETHING ON THE CONTEXT QUEUE? JRST ERREQE ;NO EVT.02: MOVEM T1,EVTADR ;SAVE ADDRESS OF EVENT BLOCK LOAD T3,EBLEN,(T1) ;GET LENGTH OF BLOCK SUBI T3,.EBDAT ;DON'T COUNT THE OVERHEAD AREA CAML T3,USRLEN ;IS THERE ROOM IN USER'S BLOCK FOR THIS EVENT? JRST ERRARG ;NO XMOVEI T2,EVT ;POINT TO THE EVENT BLOCK $LDCID P1,.MECID(T1) ;GET CB ADDRESS MOVE P5,.CBPBK(P1) ;GET PBK ADDRESS LOAD T4,PBDPN,(P5) ;GET DESTINATION NODE UMOVEM T4,.SQESB(M) ;STORE FOR USER EVT.03: PUSHJ P,SCSDEQ ;DEQUEUE THIS ENTRY LOAD T4,EBCOD,(T1) ;GET THE CODE FROM THE BLOCK MOVEM T4,EVTCOD ;SAVE IT UMOVEM T4,.SQEVT(M) ;RETURN TO USER MOVE T4,.MECID(T1) ;GET CID FROM THE BLOCK UMOVEM T4,.SQCID(M) ;RETURN TO USER LOAD T3,EBLEN,(T1) ;GET THE LENGTH BLOCK SUBI T3,.EBDAT ;DON'T COUNT THE OVERHEAD JUMPE T3,EVT.04 ;QUIT IF NO DATA TO MOVE MOVE T2,T1 ;SOURCE ADDRESS FOR XLBT MOVE T1,T3 ;LENGTH OF DATA TO MOVE MOVE T3,M ;GET ADDRESS OF USER'S BLOCK ADDI T2,.EBDAT ;OFFSET SOURCE TO JUST EVENT DATA ADDI T3,.SQDTA ;OFFSET TO DATA AREA IN USER BLOCK PUSHJ P,SCSDMU ;MOVE DATA TO THE USER JRST EVTERR ;ERROR EVT.04: MOVE T1,EVTCOD ;GET THE EVENT CODE CAIN T1,.SEPBC ;DID THE VC CLOSE? JRST EVT.05 ;YES CAIE T1,.SERID ;IS THIS A REMOTE DISCONNECT? CAIN T1,.SECRR ;OR A CONNECT REJECTION? EVT.05: PUSHJ P,SCSCBD ;YES, CLEAN UP JSYS CONNECTION DATA MOVE T1,EVTADR ;GET ADDRESS OF THE BLOCK PUSHJ P,RELRES ;RETURN THE SPACE IFN FTPI,< PUSHJ P,SCSSIG ;SIGNAL ANOTHER INTERRUPT IF NECESSARY >; END IFN FTPI JRST CPOPJ1## ;SKIP RETURN ;HERE ON ERROR EVTERR: PUSHJ P,EVT.04 ;HANDLE MOST OF THE WORK JRST ERRACS ;THEN GIVE AN ADDRESS CHECK ERROR ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SCS. UUO - GET LOCAL NODE NUMBER SCSGLN: CAIGE P1,.SQLNN ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO PUSHJ P,CPUPCB ;TRANSLATE CPU ARGUMENT INTO A PCB ADDRESS POPJ P, ;ERROR, CODE ALREADY STORED MOVX T1,ST.DED ;SEE IF PORT IS DEAD TDNN T1,.PCSTS(P6) ;IF SO, GIVE AN ERROR HERE SKIPGE T1,.PCONN(P6) ;GET NODE NUMBER, SKIP IF KNOWN JRST ERRNNK ;NODE NUMBER NOT KNOWN UMOVEM T1,.SQLNN(M) ;STORE IT JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - RETURN BUFFER SIZES SCSRBS: CAIGE P1,.SQLDG ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO MOVX T1, ;GET THE SIZE OF A MESSAGE BUFFER UMOVEM T1,.SQLMG(M) ;STORE IT MOVX T1, ;GET THE SIZE OF A DATAGRAM BUFFER UMOVEM T1,.SQLDG(M) ;STORE IT JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS. UUO - RETURN PATH STATUS SCSRPS: CAIGE P1,.SQRPS ;ROOM IN ARGUMENT BLOCK? JRST ERRARG ;NO PUSHJ P,CPUPCB ;TRANSLATE CPU ARGUMENT INTO A PCB ADDRESS POPJ P, ;ERROR, CODE ALREADY STORED EXCTUX ;GET NODE NUMBER, CHECK FOR VALIDITY CAIL T1,MAXNDS ;... JRST ERRINN ;INVALID NODE NUMBER ADD P6,T1 ;OFFSET PCB ADDRESS BY CI NODE NUMBER MOVE P6,.PCRIS(P6) ;GET STATUS OF PATHS TO THAT NODE TXNN P6,RI.PAO ;PATH A OPEN? TLZA T1,-1 ;NO, CLEAR LH OF T1 AND SKIP HRLI T1,1 ;YES, SET A FLAG TXNN P6,RI.PBO ;PATH B OPEN? TRZA T1,-1 ;NO, CLEAR RH OF T1 AND SKIP HRRI T1,1 ;YES, SET A FLAG UMOVEM T1,.SQRPS(M) ;STORE IT JRST CPOPJ1## ;SKIP RETURN SUBTTL SCS INTERRUPT NOTIFICATION ;ROUTINE CALLED WHEN SCS DETERMINES THE SYSAP SHOULD BE TOLD ABOUT ;A CHANGE IN THE STATE OF ONE OF HIS CONNECTIONS, ETC. SEE THE ;VARIOUS .SS??? NOTIFICATION DEFINITIONS IN SCAPRM. ;CALL: ; T1/ REASON ; T2 - T4/ REASON DEPENDENT DATA ; PUSHJ P,SCSINT ;RETURN: ; CPOPJ ALWAYS ;ENTRIES IN THE DISPATCH TABLE FLAGGED WITH "*" ARE CALLED ;WITH THE CONNECT ID IN T2. SCSINT: PUSHJ P,SAVPQ## ;SAVE THE "PRESERVED" SCASER REGISTERS CAILE T1,.SSAFT ;A CODE WE KNOW OF? STOPCD .,STOP,SCSNOR, ;++NOTIFICATION CODE OUT OF RANGE JRST @SINDSP(T1) ;DISPATCH BASED ON REASON SINDSP: IFIW SINDGR ;(0) DATAGRAM RECEIVED * IFIW SINMGR ;(1) MESSAGE RECEIVED * IFIW SINPBC ;(2) PORT BROKE CONNECTION * IFIW SINCTL ;(3) CONNECT TO LISTEN * IFIW SINCRA ;(4) CONNECTION RESPONSE AVAILABLE * IFIW SINPSC ;(5) PACKET SEND COMPLETE * IFIW CPOPJ## ;(6) DATAGRAM DROPPED * IFIW SINLCL ;(7) LITTLE CREDIT LEFT * IFIW SINONL ;(10) NODE CAME ONLINE IFIW SINOSD ;(11) OK TO SEND DATA * IFIW SINRID ;(12) REMOTE INITIATED DISCONNECT * IFIW SINCIA ;(13) CREDIT IS AVAILABLE * IFIW SINDMA ;(14) DMA TRANSFER COMPLETE * IF2,,> SUBTTL INTERRUPT NOTIFICATION - NODE(PATH) ONLINE ;ROUTINE CALLED WHEN A NODE(PATH) HAS COME ONLINE. ;CALL: ; T1/ .SSNCO ; T2/ PATH BLOCK INDEX ; PUSHJ P,SINONL ;RETURN: ; CPOPJ ALWAYS ;NOTE THAT WE DO NOT GET CALLED HERE FOR CONNECTIONS, ONLY FOR ;SCSUUO'S CALL TO SC.SNA. THEREFORE, WE DON'T HAVE A CONNECT ID, ;AND MUST INSTEAD LOOP THROUGH ALL JOBS GIVING THEM AN ONLINE ;INTERRUPT IF THEY ARE PSI'ING ON SCS EVENTS. SINONL: POPJ P, ;RETURN SUBTTL INTERRUPT NOTIFICATION - MESSAGE/DATAGRAM RECEIVED ;ROUTINE CALLED WHEN A MESSAGE/DATAGRAM HAS BEEN RECEIVED. ;CALL: ; T1/ .SSDGR OR .SSMGR ; T2/ CONNECT ID ; T3/ PACKET ADDRESS ; T4/ FLAGS FROM PPD ; PUSHJ P,SINDGR/SINMGR ;RETURN: ; CPOPJ ALWAYS SINDGR: TDZA T1,T1 ;INDICATE DATAGRAM ENTRY SINMGR: SETO T1, ;INDICATE MESSAGE ENTRY EXCH T1,T3 ;GET PACKET ADDRESS WHERE EXPECTED MOVEM T2,.MECID(T1) ;STORE CONNECT ID ANDX T4,C%FLGM ;KEEP JUST THE FLAGS IORM T4,.METYP(T1) ;STORE IN BLOCK MOVX T2,.ETMSG ;ASSUME DOING MESSAGES SKIPN T3 ;GOOD GUESS? MOVX T2,.ETDG ;NO, DATAGRAMS MOVE T3,.MHPKL(T1) ;GET PACKET LENGTH STOR T3,MELEN,(T1) ;STORE IT PJRST SCSQUE ;QUEUE UP BLOCK AND RETURN SUBTTL INTERRUPT NOTIFICATION - PORT BROKE CONNECTION ;ROUTINE CALLED WHEN A VC TO A REMOTE NODE HAS BEEN BROKEN. ;CALL: ; T1/ NOTIFICATION CODE ; T2/ CONNECT ID ; PUSHJ P,SINPBC ;RETURN: ; CPOPJ ALWAYS SINPBC: STKVAR ;ALLOCATE A WORD OF STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEI T1,C%PBCL ;LENGTH OF BLOCK NEEDED PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,.SEPBC ;GET EVENT TYPE STOR T2,EBCOD,(T1) ;STORE IN BLOCK MOVEI T2,C%PBCL ;LENGTH OF BLOCK STOR T2,EBLEN,(T1) ;STORE IN BLOCK MOVE T2,CID ;GET CONNECT ID MOVEM T2,.MECID(T1) ;STORE IN BLOCK MOVX T2,.ETEVT ;GET BLOCK TYPE PJRST SCSQUE ;QUEUE BLOCK AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - CONNECT TO LISTEN ;ROUTINE CALLED WHEN A CONNECTION WAS REQUESTED TO A LISTENER. ;CALL ; T1/ .SSCTL ; T2/ CONNECT ID ; T3/ POINTER TO CONNECTION DATA SINCTL: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEM T3,CDATA ;SAVE POINTER TO CONNECTION DATA MOVX T1,C%CTLL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%CTLL ;LENGTH STOR T2,EBLEN,(T1) ;STORE IN BLOCK MOVX T2,.SECTL ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T3,CDATA ;GET THE POINTER TO CONNECTION DATA MOVE T4,T1 ;MAKE THE BLOCK ADDRESS THE DESTINATION ADDI T4,.EBDAT ;ADD THE OFFSET TO THE DATA PORTION MOVX T2,C%DTLW ;LENGTH OF DATA IN WORDS EXTEND T2,[XBLT] ;TRANSFER THE DATA MOVE T2,CID ;GET THE CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - CONNECT RESPONSE AVAILABLE ;ROUTINE CALLED WHEN A CONNECT REPONSE HAS BECOME AVAILABLE. ;CALL: ; T1/ .SSCRA ; T2/ CONNECT ID ; T3/ -1 IF ACCEPTED, 0 IF REJECTED ; T4/ REJECT REASON OR POINTER TO CONNECTION DATA SINCRA: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEM T4,RJTADR ;SAVE REJECT REASON/DATA ADDRESS JUMPE T3,CRA.01 ;JUMP IF CONNECTION WAS REJECTED MOVX T1,C%CRAL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%CRAL ;LENGTH STOR T2,EBLEN,(T1) ;STORE IN BLOCK MOVX T2,.SECRA ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVE T3,RJTADR ;ADDRESS OF CONNECTION DATA XMOVEI T4,.EBDAT(T1) ;DESTINATION ADDRESS MOVX T2,C%DTLW ;LENGTH OF DATA IN WORDS EXTEND T2,[XBLT] ;TRANSFER THE DATA MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ;HERE IF CONNECTION REJECTED CRA.01: MOVX T1,C%CRRL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%CRRL ;LENGTH STOR T2,EBLEN,(T1) ;STORE IN BLOCK MOVX T2,.SECRR ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVE T2,RJTADR ;REJECT REASON MOVEM T2,.EBDAT(T1) ;STORE MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - OK TO SEND DATA ;ROUTINE CALLED WHEN A CONNECTION IS FULLY OPEN AND IT IS OK ;TO SEND DATA. ;CALL: ; T2/ CONNECT ID ; PUSHJ P,SINOSD ;RETURN: ; CPOPJ ALWAYS SINOSD: STKVAR ;ALLOCATE A WORD OF STACK STORAGE MOVEM T2,CID ;SAVE THE CONNECT ID MOVX T1,C%OSDL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%OSDL ;LENGTH STOR T2,EBLEN,(T1) ;STORE MOVX T2,.SEOSD ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - REMOTE INITIATED DISCONNECT ;ROUTINE CALLED WHEN THE REMOTE NODE HAS INITIATED A DISCONNECT. ;CALL: ; T2/ CONNECT ID ; PUSHJ P,SINRID ;RETURN: CPOPJ ALWAYS SINRID: STKVAR ;ALLOCATE A WORD OF STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVX T1,C%RIDL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%RIDL ;LENGTH STOR T2,EBLEN,(T1) ;STORE MOVX T2,.SERID ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - CREDIT IS AVAILABLE ;ROUTINE CALLED WHEN CREDIT BECOMES AVAILABLE. ;CALL: ; T2/ CONNECT ID ; T3/ SEND CREDIT ; T4/ RECEIVE CREDIT ; PUSHJ P,SINCIA ;RETURN: ; CPOPJ ALWAYS SINCIA: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEM T3,SCDT ; AND SEND CREDIT MOVEM T4,RCDT ; AND RECEIVE CREDIT MOVX T1,C%CIAL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%CIAL ;LENGTH STOR T2,EBLEN,(T1) ;STORE MOVX T2,.SECIA ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVE T2,SCDT ;GET SEND CREDIT MOVEM T2,.EBDAT(T1) ;STORE AS FIRST WORD OF DATA MOVE T2,RCDT ;GET RECEIVE CREDIT MOVEM T2,.EBDAT+1(T1) ;STORE AS SECOND WORD OF DATA MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - DMA TRANSFER COMPLETE ;ROUTINE CALLED WHEN A DMA TRANSFER COMPLETES. ;CALL: ; T2/ CONNECT ID ; T3/ BUFFER NAME ; PUSHJ P,SINDMA ;RETURN: ; CPOPJ ALWAYS SINDMA: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEM T3,BUFNAM ;SAVE BUFFER NAME MOVX T1,.DMLEN ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,.DMLEN ;LENGTH STOR T2,MELEN,(T1) ;STORE MOVE T2,BUFNAM ;BUFFER NAME MOVEM T2,.DMNAM(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVX T2,.ETDMA ;GET THE BLOCK TYPE PJRST SCSQUE ;QUEUE UP BLOCK AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - PACKET SEND COMPLETE ;ROUTINE CALLED WHEN A PACKET SEND COMPLETES. ;CALL: ; T2/ CONNECT ID ; T3/ BUFFER ADDRESS ; PUSHJ P,SINPSC ;RETURN: ; CPOPJ ALWAYS SINPSC: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEM T3,BUFADR ;SAVE THE BUFFER ADDRESS $LDCID P1,T2 ;GET CONNECTION BLOCK ADDRESS MOVX T1,CB.RAP ;IS THIS AN ABORTED CONNECTION? TDNE T1,.CBFLG(P1) ;... JRST PSC.01 ;YES MOVX T1,C%MSCL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%MSCL ;LENGTH STOR T2,EBLEN,(T1) ;STORE MOVX T2,.SEMSC ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVE T3,BUFADR ;GET BUFFER ADDRESS MOVE T2,.JHAUB(T3) ;GET ADDRESS OF USER BUFFER MOVEM T2,.EBDAT(T1) ;STORE AS FIRST DATA WORD MOVX T2,.ETEVT ;BLOCK TYPE PUSHJ P,SCSQUE ;QUEUE THE BLOCK PSC.01: MOVE T1,BUFADR ;GET BUFFER ADDRESS PJRST SCSRET ;RETURN THE BUFFER AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL INTERRUPT NOTIFICATION - LITTLE CREDIT LEFT ;ROUTINE CALLED WHEN CREDIT HAS DROPPED BELOW THE THRESHOLD. ;CALL: ; T2/ CONNECT ID ; T3/ NUMBER OF BUFFERS NEEDED ; PUSHJ P,SINLCL ;RETURN: ; CPOPJ ALWAYS SINLCL: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T2,CID ;SAVE CONNECT ID MOVEM T3,SHRTBF ;SAVE NUMBER OF BUFFERS NEEDED MOVX T1,C%LCLL ;LENGTH OF BLOCK PUSHJ P,ASGRES ;ASK FOR THE SPACE POPJ P, ;ERROR MOVX T2,C%LCLL ;LENGTH STOR T2,EBLEN,(T1) ;STORE MOVX T2,.SELCL ;EVENT CODE STOR T2,EBCOD,(T1) ;STORE MOVE T2,CID ;CONNECT ID MOVEM T2,.MECID(T1) ;STORE MOVE T2,SHRTBF ;GET NUMBER OF BUFFERS NEEDED MOVEM T2,.EBDAT(T1) ;STORE AS FIRST WORD OF DATA MOVX T2,.ETEVT ;BLOCK TYPE PJRST SCSQUE ;QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - QUEUE EVENT BLOCK ;ROUTINE TO QUEUE AN EVENT BLOCK TO THE INTERRUPT LEVEL QUEUE. ;CALL: ; T1/ BLOCK ADDRESS ; T2/ BLOCK TYPE ; PUSHJ P,SCSQUE ;RETURN: ; CPOPJ ALWAYS ;AS SCSINT HAS SAVED P'S & Q'S NO SAVE WILL BE DONE HERE. SCSQUE: SETZM .MEANC(T1) ;ZERO OLD LINK POINTERS SETZM .MEAPC(T1) ;... SETZM .MEANF(T1) ;... SETZM .MEAPF(T1) ;... STOR T2,METYP,(T1) ;STORE TYPE IN BLOCK $LDCID P1,.MECID(T1) ;GET CB ADDRESS LOAD T2,CBJCH,(P1) ;GET OWNING CONTEXT STOR T2,MEJCH,(T1) ;STORE IN EVENT BLOCK ;WHILE A BLOCK IS ON THE INTERRUPT LEVEL QUEUE, THE .MEANC AND .MEAPC ;WORDS WILL BE USED TO LINK BLOCKS ON THE QUEUE. CIOFF ;PREVENT RACES SKIPN SCSTIQ ;ANY ENTRIES ON THE QUEUE? JRST QUE.01 ;NO MOVE T2,SCSBIQ ;YES, GET ADDRESS OF LAST ENTRY MOVEM T2,.MEAPC(T1) ;UPDATE THE BACKWARD LINK IN ENTRY TO BE ADDED QUE.01: MOVEM T1,@SCSBIQ ;LINK THIS ENTRY MOVEM T1,SCSBIQ ;UPDATE BLINK PJRST CIONPJ## ;TURN INTS BACK ON AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - CLOCK LEVEL PACKET DEQUEUEING ;ROUTINE CALLED FROM CLOCK LEVEL TO REMOVE PACKETS FROM THE INTERRUPT ;LEVEL PACKET QUEUE AND QUEUE THEM TO A JOB'S CONTEXT QUEUE. ;CALL: ; PUSHJ P,SCSCLK ;RETURN: ; CPOPJ ALWAYS SCSCLK::SKPCPU (0) ;BOOT CPU? POPJ P, ;NO, QUIT SE1ENT ;ENTER SECTION 1 PUSHJ P,SAVPQ## ;SAVE THE AC'S WE WILL BE USING STKVAR ;ALLOCATE SOME STACK STORAGE CLK.01: SKIPN T1,SCSTIQ ;IS THERE AN ENTRY HERE? POPJ P, ;NO, QUIT JRST CLK.03 ;CONTINUE CLK.02: SKIPN T1,NXTENT ;A NEXT ENTRY? JRST CLK.01 ;NO, CHECK TOP OF QUEUE ONCE MORE CLK.03: MOVEM T1,BLKADR ;SAVE ADDRESS OF CURRENT BLOCK MOVE T2,.MEANC(T1) ;GET ADDRESS OF NEXT ENTRY MOVEM T2,NXTENT ;SAVE LOAD T1,MEJCH,(T1) ;GET JCH FOR THIS ENTRY PUSHJ P,CTXVAL## ;VALIDATE IT JRST CLK.05 ;NON-EXISTANT CONTEXT, DELETE THIS BLOCK SKIPA ;CURRENT CONTEXT FOR JOB, SKIP JRST CLK.02 ;NOT CURRENT CONTEXT, CHECK NEXT ANDI T1,JOBMSK## ;GET A JOB NUMBER MOVE J,T1 ;COPY HERE FOR CALL TO FNDPDB PUSHJ P,FNDPDB## ;FIND PDB JRST CLK.02 ;NO PDB (?), CHECK NEXT MOVE P3,.PDSCS##(W) ;GET ADDRESS OF PROCESS QUEUE BLOCK MOVE T1,BLKADR ;GET ADDRESS OF ENTRY $LDCID P1,.MECID(T1) ;GET CB ADDRESS PUSHJ P,SCSDEB ;DEQUEUE THE EVENT BLOCK LOAD T2,METYP,(T1) ;GET EVENT TYPE SKIPLE T2 ;CHECK FOR INVALID TYPES CAILE T2,EVTMAX ;... STOPCD CLK.02,DEBUG,SCSBEB, ;++BAD EVENT BLOCK MOVE T2,[EXP MSG,DG,EVT,XFER]-1(T2) ;GET ADDRESS OF LIST POINTER BLOCK MOVE Q1,.TOPCQ(T2) ;POINTER TO CB QUEUE TOP POINTER XMOVEI Q1,@Q1 ;TURN INDEX INTO CB INTO A REAL ADDRESS MOVE Q2,.BOTCQ(T2) ;POINTER TO CB QUEUE BOTTOM POINTER XMOVEI Q2,@Q2 ;TURN INDEX INTO CB INTO A REAL ADDRESS TXO Q2,1B1 ;SET THE GLOBAL INDIRECT BIT SETZM .MEANC(T1) ;THERE IS NO NEXT BUFFER SETZM .MEAPC(T1) ; AND FOR NOW ASSUME THERE IS NO PREVIOUS MOVE T3,(Q2) ;GET THE CURRENT LAST ENTRY CAME T3,Q1 ;IS THIS A POINTER TO THE QUEUE HEADER POINTER? MOVEM T3,.MEAPC(T1) ;NO, UPDATE THE PREVIOUS POINTER OF NEW ENTRY MOVEM T1,@Q2 ;LINK THIS ENTRY ONTO THE END OF THE QUEUE MOVEM T1,(Q2) ;AND UPDATE THE TAIL POINTER MOVE Q1,.TOPFQ(T2) ;POINTER TO CONTEXT QUEUE TOP POINTER XMOVEI Q1,@Q1 ;TURN INDEX INTO PQB INTO A REAL ADDRESS MOVE Q2,.BOTFQ(T2) ;POINTER TO CONTEXT QUEUE BOTTOM POINTER XMOVEI Q2,@Q2 ;TURN INDEX INTO PQB INTO A REAL ADDRESS SETZM .MEANF(T1) ;THERE IS NO NEXT BUFFER SETZM .MEAPF(T1) ; AND FOR NOW ASSUME THERE IS NO PREVIOUS MOVE T3,(Q2) ;GET ADDRESS OF CURRENT LAST ENTRY CAMN T3,Q1 ;IS THIS A POINTER TO THE FLINK? JRST [MOVEM T1,(Q1) ;YES, UPDATE THE CONTEXT QUEUE FLINK JRST CLK.04] ;CONTINUE MOVEM T3,.MEAPF(T1) ;NO, UPDATE LINK TO PREVIOUS OF NEW ENTRY MOVEM T1,.MEANF(T3) ;UPDATE NEXT FIELD OF PREVIOUS ENTRY CLK.04: MOVEM T1,(Q2) ;UPDATE CONTEXT QUEUE BLINK SIGNAL C$SCS ;SIGNAL SCS EVENT JFCL ;USER NOT ENABLED? JRST CLK.02 ;LOOK FOR MORE BLOCKS ;HERE WHEN AN EVENT BLOCK WAS QUEUED TO A CONTEXT WHICH NO LONGER ;EXISTS. DEQUEUE IT AND RETURN IT AS APPROPRIATE. CLK.05: MOVE T1,BLKADR ;GET ADDRESS OF ENTRY PUSHJ P,SCSDEB ;DEQUEUE THE EVENT BLOCK LOAD T2,METYP,(T1) ;GET EVENT TYPE SKIPLE T2 ;CHECK FOR INVALID TYPES CAILE T2,EVTMAX ;ONE WE KNOW OF? STOPCD CLK.02,DEBUG,SCSUET, ;++UNKNOWN EVENT TYPE PUSHJ P,@RETBLK-1(T2) ;CALL APPROPRIATE ROUTINE JRST CLK.02 ;TRY FOR ANOTHER ENTRY RETBLK: IFIW SC.RBF## ;.ETMSG IFIW SC.RLD## ;.ETDG IFIW RELRES ;.ETEVT IFIW RELRES ;.ETDMA EVTMAX==.-RETBLK ;MAXIMUM EVENT TYPE ENDSV. ;END OF STACK VARIABLE RANGE ;ROUTINE TO DEQUEUE AN EVENT BLOCK FROM THE INTERRUPT LEVEL ;QUEUE. CALLED ONLY BY SCSCLK. ;CALL: ; T1/ ADDRESS OF ENTRY ; PUSHJ P,SCSDEB ;RETURN: ; CPOPJ ALWAYS SCSDEB: CIOFF ;PREVENT RACES MOVE T2,.MEANC(T1) ;GET ADDRESS OF NEXT ENTRY SKIPN T3,.MEAPC(T1) ;GET ADDRESS OF PREVIOUS ENTRY SKIPE T2 ;ANYTHING LEFT ON QUEUE? JRST DEB.01 ;YES SETZM SCSTIQ ;NO, RE-INITIALIZE THE QUEUE XMOVEI T2,SCSTIQ ;INIT BLINK MOVEM T2,SCSBIQ ; AS POINTER TO FLINK JRST DEB.02 ;CONTINUE DEB.01: SKIPE T2 ;IS THERE A NEXT ENTRY? MOVEM T3,.MEAPC(T2) ;YES, UPDATE PREVIOUS ENTRY POINTER SKIPN T2 ;IS THERE A NEXT ENTRY? MOVEM T3,SCSBIQ ;NO, UPDATE TAIL POINTER SKIPE T3 ;IS THERE A PREVIOUS ENTRY? MOVEM T2,.MEANC(T3) ;YES, UPDATE NEXT POINTER OF PREVIOUS SKIPN T3 ;IS THERE A PREVIOUS ENTRY? MOVEM T2,SCSTIQ ;NO, UPDATE HEAD POINTER DEB.02: CION ;ALLOW INTERRUPTS POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - JOB/CONTEXT KILLED ;ROUTINE CALLED WHEN A CONTEXT IS KILLED. DELETE ANY INTERESTING STUFF. ;CALL: ; J/ JOB NUMBER ; PUSHJ P,SCSLGO ;RETURN: ; CPOPJ ALWAYS SCSPOP::! ;UNTIL THIS NEEDS TO DO SOMETHING DIFFERENT SCSRST::! ;DITTO SCSLGO::PUSHJ P,FNDPDS## ;SET UP PDB FOR JOB SE1ENT ;ENTER SECTION 1 PUSHJ P,SAVP## ;SAVE AC'S WE WILL SMASH SKIPN P3,.PDSCS##(W) ;CONTEXT DOING SCS? POPJ P, ;NO, THAT WAS EASY CIOFF ;PREVENT RACES SKIPE P1,SCSTCQ(P3) ;ANYTHING CONNECTIONS FOR THIS CONTEXT? PUSHJ P,KILCLP ;YES, LOOP TO KILL THEM PUSHJ P,SCSCXN ;DELETE ANY DMA RESOURCES OWNED SETZM .PDSCS##(W) ;CLEAR POINTER TO PQB CION ;OK TO INTERRUPT AGAIN MOVE T1,P3 ;COPY ADDRESS OF PQB PJRST RELRES ;RETURN THE SPACE AND RETURN ;ROUTINE TO LOOP OVER ALL CONNECTIONS OWNED BY A CONTEXT AND ;DELETE (DISCONNECT) THEM. ;CALL: ; P1/ POINTER TO FIRST CB ; PUSHJ P,KILCLP ;RETURN: ; CPOPJ ALWAYS KILCLP: LOAD T1,CBJCH,(P1) ;GET CONTEXT NUMBER OF CONNECT PUSHJ P,CTXVAL## ;IS IT CURRENT? JRST KILCL1 ;NON-EXISTANT? SKIPA ;CURRENT JRST KILCL1 ;NON-CURRENT MOVX T1,CB.KIL ;LIGHT THE BIT IN THE CB IORM T1,.CBFLG(P1) ;... PUSHJ P,SCSCBD ;DELETE JSYS CB DATA FROM THIS CB MOVE T1,.CBSCI(P1) ;GET THE CONNECT ID MOVE P1,.CBJNB(P1) ;GET NEXT CB FOR JOB/CONTEXT BLCAL. (SC.DIS##,) ;ABORT THE CONNECTION JFCL ;OH WELL JUMPN P1,KILCLP ;LOOP IF ANOTHER CB JRST KILCL2 ;ALL DONE KILCL1: MOVE P1,.CBJNB(P1) ;GET NEXT CB FOR JOB/CONTEXT JUMPN P1,KILCLP ;LOOP IF ANOTHER CB KILCL2: XMOVEI T1,SCSTCQ(P3) ;RE-INIT QUEUE HEADER MOVEM T1,SCSBCQ(P3) ;... SETZM SCSTCQ(P3) ;AS IF IT MATTERS POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - COUNT USER BUFFERS ;ROUTINE TO CHASE A BUFFER CHAIN AND RETURN A COUNT OF THE NUMBER ;OF BUFFERS IN THE CHAIN. IT ALSO ADDRESS CHECKS THE BUFFERS. ;CALL: ; T1/ STARTING BUFFER ADDRESS ; T2/ SIZE OF BUFFER ; PUSHJ P,SCSCUB ;RETURN: ; CPOPJ IF ADDRESS CHECK ; CPOPJ1 IF VALID BUFFER CHAIN WITH: ; T3/ NUMBER OF BUFFERS IN THE CHAIN SCSCUB: SETZ T3, ;INITIALIZE THE COUNT CUB.01: PUSHJ P,ARNGE## ;HOW NICE THAT THE ARGUMENTS ARE READY FOR A ; CALL TO ARNGE! POPJ P, ;ADDRESS CHECK POPJ P, ;ILLEGAL FOR I/O AOS T3 ;COUNT THE BUFFER CAILE T3,C%MXBF ;HAVE WE EXCEEDED THE MAXIMUM NUMBER OF BUFFERS? POPJ P, ;YES, PRETEND LIKE ADDRESS CHECK FOR NOW EXCTUX ;GET LINK TO NEXT BUFFER IN CHAIN JRST CUB.01 ;LOOP FOR OTHERS JRST CPOPJ1## ;SKIP RETURN SUBTTL SUPPORT ROUTINES - LINK BUFFER CHAIN ;ROUTINE TO LINK A BUFFER CHAIN TO THE CONNECTION BLOCK. ;CALL: ; T1/ ADDRESS OF FIRST BUFFER IN USER SPACE ; T2/ OFFSET INTO BSD FOR LINKING THESE BUFFERS ; P1/ ADDRESS OF CONNECT BLOCK ; PUSHJ P,SCSXUB ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSXUB: SAVEAC ;FREE UP SOME AC'S DMOVE Q1,T1 ;COPY THE ARGUMENTS SOMEWHERE PERMANENT XUB.01: PUSHJ P,SCSLUB ;LINK THIS BUFFER POPJ P, ;ERROR EXCTUX ;GET LINK TO NEXT BUFFER IN CHAIN JRST CPOPJ1## ;DONE, SKIP RETURN DMOVE T1,Q1 ;POINT AT CURRENT BUFFER JRST XUB.01 ;LOOP ;ROUTINE TO MOVE SOURCE AND DESTINATION PROCESS NAMES FROM USER ;MEMORY INTO SCRATCH MONITOR SPACE. THIS ROUTINE EXPECTS A SPECIFIC ;ARGUMENT BLOCK FORMAT (COMMON TO .SSCON AND .SSLIS). ;CALL: ; M/ ADDRESS OF USER ARGUMENTS ; PUSHJ P,SCSUNM ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS WITH: ; T1/ ADDRESS OF SOURCE PROCESS NAME ; T2/ ADDRESS OF DESTINATION PROCESS NAME (OR ZERO IF NONE) ; T3/ ADDRESS OF FREE SPACE BLOCK USED ; T4/ ADDRESS OF ROUTINE TO CALL TO RETURN FREE SPACE SCSUNM: SAVEAC (Q1) ;FREE UP AN AC STKVAR ;ALLOCATE SOME STACK STORAGE SETZM DPN ;INIT POINTER TO DESTINATION PROCESS NAME MOVEI T1,C%PNLW*2 ;AMOUNT OF SPACE WE NAME PUSHJ P,ASGRES ;GET THE SPACE FOR THE EVENT BLOCK POPJ P, ;ERROR MOVE Q1,T1 ;SAVE ADDRESS FOR LATER UMOVE T1,.SQSPN(M) ;GET ADDRESS OF SOURCE PROCESS NAME JUMPE T1,UNMERR ;JUMP IF NO POINTER MOVEM Q1,SPN ;SAVE ADDRESS OF SOURCE PROCESS NAME MOVX T2, ;BUILD BYTE POINTER WE CAN USE MOVX T3,C%PNMN ;LENGTH OF THE STRING PUSHJ P,SCSSUM ;MOVE THE STRING JRST UNMERR ;ERROR UMOVEM T1,.SQSPN(M) ;UPDATE POINTER FOR LATER USE UMOVE T1,.SQDPN(M) ;GET ADDRESS OF DESTINATION PROCESS NAME JUMPE T1,UNM.02 ;JUMP IF NOTHING SPECIFIED XMOVEI T2,C%PNLW(Q1) ;ADDRESS OF DESTINATION NAME MOVEM T2,DPN ;SAVE THE POINTER MOVX T2, ;BUILD BYTE POINTER WE CAN USE MOVX T3,C%PNMN ;LENGTH OF THE STRING PUSHJ P,SCSSUM ;MOVE THE STRING JRST UNMERR ;ERROR UMOVEM T1,.SQDPN(M) ;UPDATE POINTER FOR LATER USE UNM.02: MOVE T1,SPN ;RETURN ARGUMENTS AS PROMISED MOVE T2,DPN ;... MOVE T3,Q1 ;ADDRESS OF FREE SPACE XMOVEI T4,RELRES ;ROUTINE TO RETURN FREE SPACE JRST CPOPJ1## ;SKIP RETURN ;HERE ON ERROR UNMERR: EXCH T1,Q1 ;SAVE ERROR IN Q1, GET ADDRESS IN T1 PUSHJ P,RELRES ;GIVE UP THE SPACE MOVE T1,Q1 ;GET THE ERROR CODE BACK POPJ P, ;RETURN ENDSV. ;END OF STACK VARIABLE RANGE ;ROUTINE TO MOVE CONNECTION DATA FROM USER MEMORY INTO SCRATCH MONITOR ;SPACE. ;CALL: ; T1/ BASE ADDRESS OF CONNECTION DATA IN USER SPACE ; PUSHJ P,SCSUDM ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS WITH: ; T1/ MONITOR ADDRESS OF CONNECTION DATA ; T2/ ADDRESS OF ROUTINE TO CALL TO RETURN FREE SPACE SCSUDM: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,USRDAT ;SAVE THE ADDRESS OF THE USER DATA MOVX T1,C%DTLW ;LENGTH OF BLOCK PUSHJ P,ASGRES ;GET THE SPACE POPJ P, ;ERROR MOVEM T1,DATADR ;SAVE ADDRESS OF DATA MOVE T3,T1 ;MAKE THIS THE DESTINATION ADDRESS MOVX T1,C%DTLW ;LENGTH IN WORDS MOVE T2,USRDAT ;USER ADDRESS PUSHJ P,SCSDUM ;MOVE THE DATA JRST UDMERR ;ERROR MOVE T1,DATADR ;GET THE ADDRESS OF THE SPACE XMOVEI T2,RELRES ;ROUTINE TO RETURN SPACE JRST CPOPJ1## ;SKIP RETURN ;HERE ON ERROR UDMERR: EXCH T1,DATADR ;SAVE ERROR CODE, GET FREE SPACE ADDRESS PUSHJ P,RELRES ;FREE IT UP MOVE T1,DATADR ;GET ERROR CODE BACK POPJ P, ;RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - CONNECT BLOCK INITIALIZATION ;ROUTINE TO INITIALIZE THE CONNECT BLOCK WITH REQUIRED DATA. ;CALL: ; P1/ ADDRESS OF BLOCK ; PUSHJ P,SCSCBI ;RETURN: ; CPOPJ ALWAYS SCSCBI: MOVX T1,CB.JSY ;INDICATE CB IS FOR JSYS CONNECT IORM T1,.CBFLG(P1) ;... MOVE T1,.CPJCH## ;JCH OF OWNING CONTEXT STOR T1,CBJCH,(P1) ;STORE IN CB MOVE T1,.CPJOB## ;JOB OF OWNING CONTEXT STOR T1,CBJOB,(P1) ;STORE IN CB POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - LINK CB ONTO CONTEXT CB QUEUE ;ROUTINE TO LINK A CB ONTO THE CB QUEUE OF A CONTEXT. ;CALL: ; P1/ CB ADDRESS ; P3/ PQB ADDRESS ; PUSHJ P,SCSLCB ;RETURN: ; CPOPJ ALWAYS SCSLCB: MOVE T1,SCSBCQ(P3) ;GET ADDRESS OF LAST ENTRY ON THE QUEUE XMOVEI T2,SCSTCQ(P3) ; AND THE ADDRESS OF THE TOP OF QUEUE POINTER CAMN T1,T2 ;IS THE QUEUE EMPTY? JRST LCB.01 ;YES MOVEM T1,.CBJPB(P1) ;NO, UPDATE PREVIOUS POINTER OF NEW CB ADDI T1,.CBJNB ; AND OFFSET TO THE FORWARD POINTER OF LAST LCB.01: MOVEM P1,(T1) ;LINK NEW BUFFER ONTO THE CONTEXT CB QUEUE MOVEM P1,SCSBCQ(P3) ; AND UPDATE THE QUEUE BLINK POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - DELETE JSYS CB DATA ;ROUTINE TO DELETE JSYS DATA FROM A CONNECTION BLOCK. BUFFERS ;ON THE PORT QUEUES WILL BE RETURNED BY SC.RAP. ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SCSCBD ;RETURN: ; CPOPJ ALWAYS SCSCBD: XMOVEI T1,.CBTMQ(P1) ;POINT TO TOP OF THE QUEUE XMOVEI T2,.CBBMQ(P1) ; AND THE BOTTOM XMOVEI T3,SC.RBF## ; WHO TO CALL TO RETURN BUFFERS XMOVEI T4,MSG ; AND THE 4-WORD BLOCK PUSHJ P,SCSGPR ;RETURN THE PACKETS XMOVEI T1,.CBTDQ(P1) ;POINT TO TOP OF THE QUEUE XMOVEI T2,.CBBDQ(P1) ; AND THE BOTTOM XMOVEI T3,SC.RLD## ; WHO TO CALL TO RETURN BUFFERS XMOVEI T4,DG ; AND THE 4-WORD BLOCK PUSHJ P,SCSGPR ;RETURN THE PACKETS XMOVEI T1,.CBTXQ(P1) ;POINT TO TOP OF THE QUEUE XMOVEI T2,.CBBXQ(P1) ; AND THE BOTTOM XMOVEI T3,RELRES ; WHO TO CALL TO RETURN BUFFERS XMOVEI T4,XFER ; AND THE 4-WORD BLOCK PUSHJ P,SCSGPR ;RETURN THE PACKETS XMOVEI T1,.CBTEQ(P1) ;POINT TO TOP OF THE QUEUE XMOVEI T2,.CBBEQ(P1) ; AND THE BOTTOM XMOVEI T3,RELRES ; WHO TO CALL TO RETURN BUFFERS XMOVEI T4,EVT ; AND THE 4-WORD BLOCK PUSHJ P,SCSGPR ;RETURN THE PACKETS XMOVEI T1,.CBTBQ(P1) ;POINT TO TOP OF THE QUEUE XMOVEI T2,.CBBBQ(P1) ; AND THE BOTTOM PUSHJ P,SCSCBS ;CLEAN UP ANY BSDS THAT ARE AROUND PUSHJ P,SCSRCB ;RETURN CB FROM OWNING CONTEXT CB QUEUE JFCL ;ERROR MOVX T1,CB.JSY ;TURN OFF THE JSYS FLAG BIT ANDCAB T1,.CBFLG(P1) ;... TXNN T1,CB.PTC ;IS PROTOCOL COMPLETE? POPJ P, ;NO, RETURN MOVX T1,CB.RAP ;YES, SET THE REAP FLAG IORM T1,.CBFLG(P1) ;... SETOM SCAREP## ;TELL SCASER TO RUN THE REAPER POPJ P, ;AND RETURN SUBTTL SUPPORT ROUTINES - LINK PACKET TO FRONT OF QUEUE ;THIS ROUTINE LINKS A MONITOR PACKET ONTO THE FRONT OF THE CONTEXT ;AND CB QUEUES. ;CALL: ; T1/ ADDRESS OF PACKET ; T2/ ADDRESS OF 4-WORD LIST HEADER ; P1/ CB ADDRESS ; PUSHJ P,SCSLUB ;RETURN: ; CPOPJ ALWAYS SCSLFQ: MOVE T3,@.TOPFQ(T2) ;GET THE ADDRESS OF THE FIRST ON CONTEXT QUEUE MOVEM T3,.MEANF(T1) ;LINK NEW BUFFER AT THE FRONT SETZM .MEAPF(T1) ;MAKE BACKWARD LINK BE ZERO MOVEM T1,@.TOPFQ(T2) ;UPDATE THE QUEUE FLINK MOVE T3,@.TOPCQ(T2) ;GET ADDRESS OF FIRST BUFFER ON CB QUEUE MOVEM T3,.MEANC(T1) ;LINK NEW BUFFER AT THE FRONT SETZM .MEAPC(T1) ;MAKE BACKWARD LINK BE ZERO MOVEM T1,@.TOPCQ(T2) ;UPDATE THE QUEUE FLINK POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - REMOVE CB FROM OWNING CONTEXT CB QUEUE ;ROUTINE TO REMOVE A CB FROM THE OWNING CONTEXT'S LIST OF CB'S. ;CALL: ; P1/ ADDRESS OF CONNECT BLOCK ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSRCB: LOAD T1,CBJCH,(P1) ;GET OWNING JCH CAME T1,.CPJCH## ;IS IT FOR THE CURRENT JOB/CONTEXT? POPJ P, ;NO XMOVEI T3,SCSTCQ(P3) ;GET ADDRESS OF QUEUE FLINK XMOVEI T4,SCSBCQ(P3) ;GET ADDRESS OF QUEUE BLINK MOVE T1,.CBJNB(P1) ;GET FORWARD POINTER FROM CB SKIPN T2,.CBJPB(P1) ;IS THERE A PREVIOUS POINTER? SKIPE T1 ;OR A FORWARD POINTER? JRST RCB.01 ;YES XMOVEI T1,SCSTCQ(P3) ;GET ADDRESS OF QUEUE FLINK MOVEM T1,(T4) ;REINIT BLINK AS POINTER TO FLINK SETZM (T3) ;REINIT FLINK AS ZERO JRST CPOPJ1## ;SKIP RETURN RCB.01: SKIPN T1 ;IS THERE A NEXT CB? MOVEM T2,(T4) ;NO, UPDATE QUEUE BLINK WITH POINTER TO PREVIOUS SKIPE T1 ;IS THERE A NEXT CB? MOVEM T2,.CBJPB(T1) ;YES, UPDATE ITS PREVIOUS POINTER SKIPN T2 ;IS THERE A PREVIOUS CB? MOVEM T1,(T3) ;NO, UPDATE QUEUE FLINK SKIPE T2 ;IS THERE A PREVIOUS CB? MOVEM T1,.CBJNB(T2) ;YES, UPDATE ITS NEXT POINTER JRST CPOPJ1## ;SKIP RETURN SUBTTL SUPPORT ROUTINES - ADD DMA BUFFER NAME ;ROUTINE TO ADD A BUFFER NAME TO THE DMA NAME DATABASE. ;CALL: ; T1/ BUFFER NAME ; P3/ PQB ADDRESS ; PUSHJ P,SCSAXN ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSAXN: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,BUFNAM ;SAVE BUFFER NAME MOVX T1,.XNLEN ;LENGTH OF THE BLOCK PUSHJ P,ASGRES ;GET THE SPACE POPJ P, ;ERROR MOVE T2,BUFNAM ;GET BUFFER NAME MOVEM T2,.XNNAM(T1) ;SAVE BUFFER NAME AOS (P) ;SET FOR SKIP RETURN PJRST SCSLXN ;LINK ENTRY ONTO QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - DELETE DMA BUFFER NAME ;ROUTINE TO DELETE A BUFFER NAME FROM THE DMA NAME DATABASE. ;CALL: ; T1/ BUFFER NAME ; P3/ PQB ADDRESS ; PUSHJ P,SCSDXN ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSDXN: STKVAR ;ALLOCATE A WORD OF STACK STORAGE MOVEM T1,BUFNAM ;SAVE BUFFER NAME FOR A BIT XMOVEI T1,SCSTXN(P3) ;GET ADDRESS OF QUEUE FLINK DXN.01: SKIPN T1,.XNNXT(T1) ;IS THERE ANOTHER ENTRY ON THE QUEUE? POPJ P, ;NO, INVALID BUFFER NAME MOVE T2,.XNNAM(T1) ;GET THE BUFFER NAME FROM THE ENTRY CAME T2,BUFNAM ;DOES IT MATCH? JRST DXN.01 ;NO, LOOP AOS (P) ;SET FOR SKIP RETURN PJRST SCSRXN ;REMOVE THE ENTRY FROM THE QUEUE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - FIND BUFFER NAME ;ROUTINE TO DETERMINE IF A BUFFER NAME IS CURRENTLY OWNED. ;CALL: ; T1/ BUFFER NAME ; P3/ PQB ADDRESS ; PUSHJ P,SCSFXN ;RETURN: ; CPOPJ IF BUFFER NOT OWNED ; CPOPJ1 IF BUFFER OWNED SCSFXN: STKVAR ;ALLOCATE A WORD OF STACK STORAGE MOVEM T1,BUFNAM ;SAVE BUFFER NAME XMOVEI T1,SCSTXN(P3) ;GET ADDRESS OF QUEUE FLINK FXN.01: SKIPN T1,.XNNXT(T1) ;IS THERE A NEXT ENTRY? POPJ P, ;NO, BUFFER NAME NOT OWNED MOVE T2,.XNNAM(T1) ;GET BUFFER NAME CAME T2,BUFNAM ;DOES IT MATCH? JRST FXN.01 ;NO, LOOP JRST CPOPJ1## ;YES, SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - CLEAN A BUFFER NAME LIST ;ROUTINE TO CLEAN THE BUFFER NAME LIST. ;CALL: ; P3/ PQB ADDRESS ; PUSHJ P,SCSCXN ;RETURN: ; CPOPJ ALWAYS SCSCXN: PUSHJ P,SAVE1## ;SAVE P1 XMOVEI P1,SCSTXN(P3) ;GET ADDRESS OF QUEUE FLINK MOVE P1,.XNNXT(P1) ;GET ADDRESS OF FIRST ENTRY CXN.01: JUMPE P1,CPOPJ## ;RETURN AT END MOVE T1,.XNNXT(P1) ;GET ADDRESS OF NEXT ENTRY EXCH T1,P1 ;SAVE NEXT IN P1, GET CURRENT IN T1 PUSHJ P,SCSRXN ;RETURN THE ENTRY JRST CXN.01 ;LOOP FOR OTHERS SUBTTL SUPPORT ROUTINES - LINK ENTRY ONTO DMA DATABASE ;ROUTINE TO ADD AN ENTRY TO A DMA BUFFER NAME LIST. ;CALL: ; T1/ ENTRY ADDRESS ; P3/ PQB ADDRESS ; PUSHJ P,SCSLXN ;RETURN: ; CPOPJ ALWAYS SCSLXN: SKIPE SCSTXN(P3) ;IS THERE ANYTHING ON THE LIST? JRST LXN.01 ;YES MOVEM T1,SCSTXN(P3) ;SET UP THE FLINK MOVEM T1,SCSBXN(P3) ;SET UP THE BLINK SETZM .XNNXT(T1) ;CLEAR LINKS SETZM .XNPRV(T1) ;... POPJ P, ;RETURN LXN.01: MOVE T4,SCSBXN(P3) ;GET ADDRESS OF LAST ENTRY MOVEM T1,.XNNXT(T4) ;LINK THIS TO LAST MOVEM T1,SCSBXN(P3) ;SET UP BLINK SETZM .XNNXT(T1) ;CLEAR FLINK MOVEM T4,.XNPRV(T1) ;SET UP BLINK POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - REMOVE ENTRY FROM DMA DATABASE ;ROUTINE TO REMOVE AN ENTRY FROM A DMA NAME LIST. ;CALL: ; T1/ ENTRY ADDRESS ; P3/ PQB ADDRESS ; PUSHJ P,SCSRXN ;RETURN: ; CPOPJ ALWAYS SCSRXN: PUSHJ P,SAVE1## ;SAVE P1 STKVAR ;ALLOCATE A WORD OF STACK STORAGE MOVEM T1,ENTADR ;SAVE ADDRESS OF ENTRY MOVE T1,.XNNAM(T1) ;GET BUFFER NAME BLCAL. (SC.UMP##,) ;TELL SCASER TO UNMAP THIS BUFFER JFCL ;ERROR RETURN, STILL REMOVE FROM DATABASE XMOVEI T1,SCSTXN(P3) ;GET ADDRESS OF QUEUE FLINK XMOVEI T2,SCSBXN(P3) ;GET ADDRESS OF QUEUE BLINK MOVE P1,ENTADR ;GET ADDRESS OF ENTRY BEING REMOVED MOVE T3,.XNNXT(P1) ;GET THE FORWARD LINK MOVE T4,.XNPRV(P1) ;GET THE BACKWARD LINK SKIPN T3 ;IS THERE A FORWARD LINK? SKIPE T4 ;AND NO BACKWARD LINK? JRST RXN.01 ;OTHER ENTRIES ON THE QUEUE SETZM (T1) ;LAST ENTRY ON THE QUEUE, ZERO FLINK MOVEM T1,(T2) ;INIT BLINK AS POINTER TO FLINK MOVE T1,P1 ;GET THE ENTRY ADDRESS PJRST RELRES ;RETURN THE SPACE AND RETURN RXN.01: SKIPN T3 ;IS THERE A FORWARD LINK? MOVEM T4,(T2) ;NO, LAST ENTRY, UPDATE QUEUE BLINK SKIPE T3 ;IS THERE A FORWARD LINK? MOVEM T4,.XNPRV(T3) ;YES, UPDATE BLINK OF NEXT ENTRY SKIPN T4 ;IS THERE A PREVIOUS ENTRY? MOVEM T3,(T1) ;NO, LAST ENTRY, UPDATE QUEUE FLINK SKIPE T4 ;IS THERE A PREVIOUS ENTRY? MOVEM T3,.XNNXT(T4) ;YES, UPDATE ENTRY FLINK MOVE T1,P1 ;GET ENTRY ADDRESS PJRST RELRES ;RETURN THE SPACE AND RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - GENERAL PACKET RETURN ;ROUTINE TO RETURN A SET OF PACKETS/BLOCKS LINKED WITH A STANDARD ;QUEUE HEADER. THE HEADER IS THE ONE USED BY THE SCS. UUO TO QUEUE ;EVERYTHING IT HANGS OFF THE CONNECT BLOCK. ;CALL: ; T1/ QUEUE FLINK ; T2/ QUEUE BLINK ; T3/ ADDRESS OF ROUTINE TO RETURN BLOCK IN T1 ; T4/ ADDRESS OF 4-WORD LIST HEADER BLOCK (IF ONE) ; P1/ CB ADDRESS ; PUSHJ P,SCSGPR ;RETURN: ; CPOPJ ALWAYS SCSGPR: SAVEAC ;FREE UP AN AC STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T3,RTNADR ;SAVE THE RETURN ROUTINE ADDRESS MOVEM T4,BLKADR ;AND THE 4-WORD BLOCK ADDRESS SKIPN Q1,(T1) ;ANYTHING AT ALL ON THE QUEUE? POPJ P, ;NO, RETURN GPR.01: MOVE T1,Q1 ;GET THE ADDRESS OF THE CURRENT ENTRY MOVE Q1,(Q1) ;GET THE ADDRESS OF THE NEXT ENTRY SKIPE T2,BLKADR ;IS THERE A 4-WORD BLOCK ADDRESS? PUSHJ P,SCSDEQ ;YES, DEQUEUE THE PACKET/BLOCK PUSHJ P,@RTNADR ;RETURN THE FREE SPACE JUMPN Q1,GPR.01 ;JUMP IF MORE TO DO POPJ P, ;RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - CLEAN UP A BSD QUEUE ;ROUTINE TO CLEAN UP THE ENTRIES ON A BSD QUEUE. NOTE THAT THIS ;ROUTINE SHOULD BE MERGED WITH A GENERAL QUEUE CLEANING ROUTINE. ;CALL: ; P1/ CB ADDRESS ; PUSHJ P,SCSCBS ;RETURN: ; CPOPJ ALWAYS SCSCBS: SAVEAC ;FREE UP AN AC SKIPN T1,.CBTBQ(P1) ;IS THERE SOMETHING HERE? POPJ P, ;NO, RETURN CBS.01: MOVE Q1,.BDNXT(T1) ;GET THE ADDRESS OF THE NEXT ENTRY PUSHJ P,SC.RLD## ;RETURN THE DATAGRAM SKIPE T1,Q1 ;IS THERE ANOTHER BLOCK TO RETURN? JRST CBS.01 ;YES XMOVEI T1,.CBTBQ(P1) ;GET A POINTER TO TOP OF QUEUE MOVEM T1,.CBBBQ(P1) ;INIT BLINK AS POINTER TO FLINK SETZM .CBTBQ(P1) ;INIT FLINK AS ZERO POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - MOVE DATA FROM MONITOR TO USER ;ROUTINE TO MOVE A BLOCK OF WORDS FROM MONITOR SPACE INTO USER SPACE. ;CALL: ; T1/ LENGTH IN WORDS OF BLOCK ; T2/ ADDRESS OF SOURCE BLOCK IN EXEC SPACE ; T3/ ADDRESS OF DESTINATION BLOCK IN USER SPACE ; PUSHJ P,SCSDMU ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSDMU: EXCH T2,T3 ;SWAP ARGUMENTS FOR CALL TO ARNGE EXCH T1,T2 ;... PUSHJ P,ARNGE## ;SEE IF LEGAL ADDRESSES POPJ P, ;ADDRESS CHECK POPJ P, ;ILLEGAL FOR I/O EXCH T1,T2 ;PUT ARGUMENTS BACK AS THEY WERE EXCH T2,T3 ;... XBLTXU T1 ;XBLT THE DATA OVER JRST CPOPJ1## ;SKIP RETURN SUBTTL SUPPORT ROUTINES - MOVE DATA FROM USER TO MONITOR ;ROUTINE TO MOVE A BLOCK OF WORDS FROM USER SPACE INTO MONITOR SPACE. ;CALL: ; T1/ LENGTH IN WORDS OF BLOCK ; T2/ ADDRESS OF SOURCE BLOCK IN USER SPACE ; T3/ ADDRESS OF DESTINATION BLOCK IN EXEC SPACE ; PUSHJ P,SCSDUM ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSDUM: EXCH T1,T2 ;SWAP ARGUMENTS FOR CALL TO ARNGE PUSHJ P,ARNGE## ;ADDRESS CHECK IT POPJ P, ;ADDRESS CHECK POPJ P, ;ILLEGAL FOR I/O EXCH T1,T2 ;PUT ARGUMENTS BACK THE WAY THEY SHOULD BE XBLTUX T1 ;XBLT THE DATA OVER JRST CPOPJ1## ;SKIP RETURN ;ROUTINE TO MOVE A STRING FROM USER SPACE TO MONITOR SPACE. ;CALL: ; T1/ BYTE POINTER TO SOURCE STRING ; T2/ BYTE POINTER TO DESTINATION STRING ; T3/ MAXIMUM LENGTH OF THE STRING ; PUSHJ P,SCSSUM ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSSUM: PUSHJ P,SAVE1## ;SAVE AN AC MOVE P1,T3 ;SAVE LENGTH OF STRING TLC T1,-1 ;SEE IF GENERIC BYTE POINTER TLCE T1,-1 ;... JRST SUM.01 ;NO, USE WHAT USER SUPPLIED HLL T1,M ;MAKE A SECTION LOCAL TLO T1,610000 ; ONE-WORD GLOBAL BYTE POINTER SUM.01: EXCTUX ;GET A BYTE FROM THE USER STRING ERJMP CPOPJ## ;HANDLE ADDRESS CHECK JUMPE T4,SUM.02 ;JUMP IF NULL BYTE (SEE IF PADDING NEEDED) IDPB T4,T2 ;STORE BYTE IN MONITOR SPACE JUMPE P1,SUM.01 ;IF NO MAXIMUM COUNT LOOP UNTIL NULL SOJG T3,SUM.01 ;HAVE A BYTE COUNT, LOOP IF MORE ALLOWED JRST CPOPJ1## ;SKIP RETURN SUM.02: JUMPE P1,CPOPJ1## ;IF NO MAXIMUM COUNT NO PADDING REQUIRED JUMPE T3,CPOPJ1## ;RETURN IF NO PADDING REQUIRED MOVEI T4," " ;GET A SPACE IDPB T4,T2 ;STORE BYTE IN MONITOR SPACE SOJG T3,.-1 ;LOOP FOR NECESSARY PAD CHARACTERS JRST CPOPJ1## ;SKIP RETURN SUBTTL SUPPORT ROUTINES - DEQUEUE A BUFFER FROM QUEUES ;ROUTINE TO DEQUEUE A BUFFER FROM THE QUEUES IT IS ON. ;CALL: ; T1/ ADDRESS OF PACKET ; T2/ ADDRESS OF 4-WORD LIST HEADER BLOCK ; P1/ ADDRESS OF CB (OR -1 IF NO CB ENTRY) ; PUSHJ P,SCSDEQ ; CPOPJ ALWAYS WITH: ; T1/ ADDRESS OF PACKET SCSDEQ: PUSHJ P,SAVQ## ;FREE UP SOME AC'S TO USE JUMPL P1,DEQ.03 ;IF A CONTEXT ONLY ENTRY, SKIP CB STUFF MOVE T3,.MEANC(T1) ;GET NEXT CONNECTION ENTRY SKIPN T4,.MEAPC(T1) ;IS THERE A PREVIOUS ENTRY? SKIPE T3 ;OR A NEXT? JRST DEQ.01 ;YES XMOVEI T3,@.TOPCQ(T2) ;GET THE ADDRESS OF THE TOP OF THE QUEUE MOVEM T3,@.BOTCQ(T2) ;INIT TAIL POINTER AS POINTER TO HEAD SETZM @.TOPCQ(T2) ;INIT HEAD POINTER AS ZERO JRST DEQ.02 ;PROCEED DEQ.01: SKIPE T3 ;IS THERE A NEXT ENTRY? MOVEM T4,.MEAPC(T3) ;YES, UPDATE PREVIOUS ENTRY POINTER SKIPN T3 ;IS THERE A NEXT ENTRY? MOVEM T4,@.BOTCQ(T2) ;NO, UPDATE THE TAIL POINTER SKIPE T4 ;IS THERE A PREVIOUS ENTRY? MOVEM T3,.MEANC(T4) ;YES, UPDATE NEXT POINTER OF PREVIOUS SKIPN T4 ;IS THERE A PREVIOUS ENTRY? MOVEM T3,@.TOPCQ(T2) ;NO, UPDATE THE HEAD POINTER DEQ.02: MOVX T3,CB.KIL ;SEE IF CONTEXT WITH CONNECT IS DEAD TDNE T3,.CBFLG(P1) ;IS THE CONTEXT ALREADY GONE? POPJ P, ;YES, RETURN DEQ.03: MOVE Q1,.TOPFQ(T2) ;GET ADDRESS OF THE CONTEXT QUEUE TOP MOVE Q2,.BOTFQ(T2) ;GET ADDRESS OF THE CONTEXT QUEUE BOTTOM MOVE T3,.MEANF(T1) ;GET THE NEXT ENTRY SKIPN T4,.MEAPF(T1) ;IS THERE A PREVIOUS ENTRY? SKIPE T3 ; AND NO NEXT? JRST DEQ.04 ;NO XMOVEI T3,@Q1 ;GET THE ADDRESS OF THE TOP OF THE QUEUE MOVEM T3,@Q2 ;INIT TAIL POINTER AS POINTER TO HEAD SETZM @Q1 ;INIT HEAD POINTER AS ZERO POPJ P, ;ALL DONE DEQ.04: SKIPE T3 ;IS THERE A NEXT ENTRY? MOVEM T4,.MEAPF(T3) ;YES, UPDATE PREVIOUS ENTRY IN NEXT SKIPN T3 ;IS THERE A NEXT ENTRY? MOVEM T4,@Q2 ;NO, UPDATE THE TAIL POINTER IN THE PQB SKIPE T4 ;IS THERE A PREVIOUS ENTRY? MOVEM T3,.MEANF(T4) ;YES, UPDATE NEXT POINTER OF PREVIOUS SKIPN T4 ;IS THERE A PREVIOUS ENTRY? MOVEM T3,@Q1 ;NO, UPDATE THE HEADER POINTER IN THE PQB POPJ P, ;RETURN SUBTTL SUPPORT ROUTINES - MAKE A BSD ;THIS ROUTINE CREATES A BSD AND LINKS ONTO THE CB BSD LIST. ;CALL: ; P1/ ADDRESS OF CONNECTION BLOCK ; PUSHJ P,SCSMBS ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS WITH: ; T1/ ADDRESS OF NEW BSD ; P1/ ADDRESS OF CONNECTION BLOCK SCSMBS: MOVEI T1,1 ;ASK FOR A DATAGRAM BUFFER PUSHJ P,SC.ALD## ;... POPJ P, ;NOT AVAILABLE XMOVEI T2,.BDFMG(T1) ;ADDRESS OF FIRST MESSAGE POINTER MOVEM T2,.BDLMG(T1) ;INIT MESSAGE TAIL AS POINTER TO HEAD SETZM .BDFMG(T1) ;ZERO THE MESSAGE ENTRY HEAD XMOVEI T2,.BDFDG(T1) ;ADDRESS OF FIRST DATAGRAM POINTER MOVEM T2,.BDLDG(T1) ;INIT DATAGRAM TAIL AS POINTER TO HEAD SETZM .BDFDG(T1) ;ZERO THE DATAGRAM ENTRY HEAD MOVX T4,C%NBSD ;GET THE NUMBER OF ENTRIES IN A BSD MOVE T2,T1 ;COPY BSD ADDRESS ADDI T2,.BDBDB ;OFFSET TO FIRST SLOT ADDRESS MOVEM T2,.BDFFD(T1) ;STORE AS ADDRESS OF FIRST FREE ENTRY MOVE T3,T2 ;DON'T SMASH THE POINTER TO LAST ENTRY MBS.01: ADDI T3,.BBLEN ;ADD THE OFFSET TO THE NEXT ENTRY MOVEM T3,(T2) ;LINK ON THIS NEXT ENTRY MOVE T2,T3 ;MOVE TO THE NEXT BUFFER SOJG T4,MBS.01 ;LOOP FOR THE ENTIRE BSD MOVEM T3,.BDLFD(T1) ;STORE THE LIST TAIL POINTER SETZM (T3) ;ENSURE A NULL LAST ENTRY POINTER MOVEM T1,@.CBBBQ(P1) ;LINK THIS NEW BSD ONTO THE END OF THE QUEUE MOVEM T1,.CBBBQ(P1) ;AND UPDATE THE TAIL POINTER JRST CPOPJ1## ;SKIP RETURN SUBTTL SUPPORT ROUTINES - LINK ON USER BUFFER ;ROTINE TO LINK A USER BUFFER ADDRESS INTO A BSD FOR THE CURRENT ;CONNECTION. ;CALL: ; T1/ USER ADDRESS OF BUFFER ; T2/ OFFSET IN BSD TO DESIRED FLINK ; P1/ CB ADDRESS ; PUSHJ P,SCSLUB ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSLUB: STKVAR ;ALLOCATE SOME STACK STORAGE MOVEM T1,BUFADR ;SAVE USER BUFFER ADDRESS MOVEM T2,BSDOFS ;AND THE BSD OFFSET SKIPE T3,.CBTBQ(P1) ;ARE THERE ANY BSDS ON THIS CONNECT? JRST LUB.02 ;YES, DON'T NEED TO CREATE ONE LUB.01: PUSHJ P,SCSMBS ;CREATE A BSD POPJ P, ;ERROR MOVE T3,T1 ;PUT BSD ADDRESS WHERE EXPECTED MOVE T2,BSDOFS ;RESTORE THE BSD OFFSET MOVE T1,BUFADR ; AND THE USER BUFFER ADDRESS LUB.02: SKIPE T4,.BDFFD(T3) ;IS THERE A FREE ENTRY IN THE BSD? JRST LUB.03 ;YES SKIPE T3,.BDNXT(T3) ;IS THERE ANOTHER BSD ON THE CHAIN? JRST LUB.02 ;YES, SEE IF IT HAS A FREE ENTRY JRST LUB.01 ;NO, CREATE A NEW BSD LUB.03: ADD T2,T3 ;CALCULATE ADDRESS OF QUEUE FLINK MOVEM T1,.BBUVA(T4) ;STORE USER ADDRESS IN BSD ENTRY MOVE T1,.BBNXT(T4) ;GET ADDRESS OF NEXT BUFFER MOVEM T1,.BDFFD(T3) ;DELETE THIS ENTRY FROM THE FREE QUEUE SETZM .BBNXT(T4) ;ZERO THE FORWARD LINK OF NEW ENTRY JUMPN T1,LUB.04 ;JUMP IF ANY ENTRIES LEFT XMOVEI T1,.BDFFD(T3) ;GET ADDRESS OF FREE QUEUE FLINK MOVEM T1,.BDLFD(T3) ;INIT BLINK AS POINTER TO FLINK LUB.04: MOVEM T4,@.BDF2B(T2) ;LINK THIS BUFFER ONTO THE END OF THE QUEUE MOVEM T4,.BDF2B(T2) ; AND UPDATE THE QUEUE BLINK MOVE T2,BSDOFS ;GET THE BSD OFFSET CAIN T2,.BDFDG ;NEW DATAGRAM? AOS .CBDGJ(P1) ;YES, INCREMENT COUNT OF JSYS DATAGRAM BUFFERS CAIN T2,.BDFMG ;NEW MESSAGE? AOS .CBMGJ(P1) ;YES, INCREMENT COUNT OF JSYS MESSAGE BUFFERS JRST CPOPJ1## ;SKIP RETURN ENDSV. ;END OF STACK VARIABLE RANGE SUBTTL SUPPORT ROUTINES - GET USER BUFFER ;ROUTINE TO OBTAIN A USER BUFFER. ;CALL: ; T1/ OFFSET INTO BSD INDICATING PACKET TYPE ; P1/ ADDRESS OF CONNECTION BLOCK ; PUSHJ P,SCSGUB ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS WITH: ; T1/ ADDRESS OF BUFFER SCSGUB: SKIPN T2,.CBTBQ(P1) ;ANY BSDS ON THE CB? POPJ P, ;NO, RETURN PUSHJ P,SAVQ## ;FREE UP SOME AC'S MOVE Q1,T2 ;SAVE THE BSD ADDRESS MOVE Q2,T2 ;ANOTHER COPY MOVE Q3,T1 ;SAVE THE BSD OFFSET ADD Q2,T1 ;MAKE A FLINK ADDRESS GUB.01: SKIPN T4,(Q2) ;GET ADDRESS OF FIRST PACKET ENTRY JRST GUB.06 ;NONE IN THIS BSD, TRY THE NEXT ONE SKIPE .BBNXT(T4) ;ONLY ENTRY ON QUEUE? JRST GUB.02 ;NO SETZM (Q2) ;YES, SET FIRST ENTRY ADDRESS TO ZERO MOVEM Q2,.BDF2B(Q2) ;POINT BLINK AT FLINK JRST GUB.03 ;CONTINUE GUB.02: MOVE T1,.BBNXT(T4) ;GET ADDRESS OF NEXT ENTRY MOVEM T1,(Q2) ;MAKE IT THE FIRST GUB.03: SKIPE .BDFFD(Q1) ;ANY ENTRIES IN FREE QUEUE? JRST GUB.04 ;NO MOVEM T4,.BDLFD(Q1) ;YES, UPDATE LAST FREE ENTRY POINTER SETZM .BBNXT(T4) ;SET END OF QUEUE TO ZERO JRST GUB.05 ;CONTINUE GUB.04: MOVE T1,.BDFFD(Q1) ;GET ADDRESS OF FIRST ENTRY MOVEM T1,.BBNXT(T4) ;MAKE NEW ENTRY POINT TO THE PREVIOUS ENTRY GUB.05: MOVE T1,.BBUVA(T4) ;GET USER ADDRESS OF BUFFER CAIN Q3,.BDFDG ;DID WE GET A DATAGRAM? SOS .CBDGJ(P1) ;YES, DECREMENT JSYS BUFFER COUNT CAIN Q3,.BDFMG ;DID WE GET A MESSAGE? SOS .CBMGJ(P1) ;YES, DECREMENT JSYS BUFFER COUNT JRST CPOPJ1## ;SKIP RETURN GUB.06: SKIPN Q1,.BDNXT(Q1) ;IS THERE A NEXT BSD? POPJ P, ;NO, ERROR MOVE Q2,Q1 ;GET NEW BSD ADDRESS ADD Q2,T1 ;ADD IN FLINK OFFSET JRST GUB.01 ;LOOP FOR MORE SUBTTL SUPPORT ROUTINES - REMOVE USER BUFFER ;ROUTINE TO REMOVE A USER BUFFER ENTRY FROM THE BSD SET. ;CALL: ; T1/ USER BUFFER ADDRESS (TO BE REMOVED) ; T2/ OFFSET INTO BSD FOR BUFFER TYPE ; P1/ ADDRESS OF CONNECTION BLOCK ; PUSHJ P,SCSRUB ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS SCSRUB: SKIPN T3,.CBTBQ(P1) ;ANY BSDS ON THIS CONNECTION? POPJ P, ;NO, ERROR SAVEAC ;SAVE AN AC RUB.01: SETZ Q1, ;SET INITIAL BACK POINTER TO ZERO MOVE T4,T3 ;BUILD OFFSET TO FIRST BUFFER ADD T4,T2 ; BY ADDING OFFSET TO BSD ADDRESS SKIPN T4,(T4) ;IS THERE A FIRST ENTRY? JRST RUB.03 ;NO, TRY NEXT BSD RUB.02: CAMN T1,.BBUVA(T4) ;THIS THE ONE WE WANT? JRST RUB.04 ;YES MOVE Q1,T4 ;SAVE ADDRESS OF CURRENT BUFFER SKIPE T4,.BBNXT(T4) ;IS THERE A NEXT BUFFER? JRST RUB.02 ;YES, CHECK THAT ONE RUB.03: SKIPN T3,.BDNXT(T3) ;IS THERE A NEXT BSD? POPJ P, ;NO, ERROR JRST RUB.01 ;TRY NEXT BSD RUB.04: SETZM .BBUVA(T4) ;ZERO USER BUFFER ADDRESS SKIPN Q1 ;WAS THERE A PREVIOUS ENTRY? SKIPE T1,.BBNXT(T4) ;OR A NEXT ENTRY? SKIPA ;YES, QUEUE ISN'T EMPTY JRST RUB.06 ;QUEUE IS EMPTY ADD T2,T3 ;GET ADDRESS OF BUFFER FLINK SKIPN Q1 ;IS THERE A PREVIOUS? MOVEM T1,(T2) ;NO, UPDATE FLINK TO NEW FIRST SKIPN T1 ;IS THERE A NEXT ENTRY? MOVEM Q1,.BDF2B(T2) ;NO NEXT, UPDATE BLINK FOR LAST NEW ENTRY SKIPE Q1 ;IS THERE A PREVIOUS? MOVEM T1,.BDNXT(Q1) ;YES, POINT IT TO THE NEXT ENTRY RUB.05: MOVEM T4,@.BDLFD(T3) ;LINK BUFFER ONTO FREE QUEUE MOVEM T4,.BDLFD(T3) ;UPDATE THE BLINK JRST CPOPJ1## ;SKIP RETURN RUB.06: MOVE T1,T3 ;GET ADDRESS OF BSD ADD T1,T2 ;GET ADDRESS OF FLINK MOVEM T1,.BDF2B(T1) ;STORE FLINK ADDRESS IN BLINK SETZM (T1) ;INIT FLINK AS ZERO JRST RUB.05 ;PUT ENTRY ON QUEUE AND RETURN SUBTTL SUPPORT ROUTINES - RETURN BUFFER ;ROUTINE CALLED TO RETURN BUFFERS TO THE SCA POOL. ;CALL: ; T1/ BUFFER ADDRESS ; PUSHJ P,SCSRET ;RETURN: ; CPOPJ ALWAYS SCSRET: MOVX T2,JH%DGB ;IS THIS A DATAGRAM BUFFER? TDNN T2,.JHFLG(T1) ;... PJRST SC.RBF## ;NO, RETURN MESSAGE BUFFER PJRST SC.RLD## ;YES, RETURN DATAGRAM BUFFER SUBTTL TEMPORARY ROUTINES ;HERE UNTIL DEFINED SOMEWHERE ELSE ;ROUTINE TO OBTAIN RESIDENT FREE SPACE. ;CALL: ; T1/ NUMBER OF WORDS DESIRED ; PUSHJ P,ASGRES ;RETURN: ; CPOPJ IF NOT AVAILABLE ; CPOPJ1 IF AVAILABLE WITH: ; T1/ ADDRESS OF SPACE ASGRES: MOVEI T2,1(T1) ;ADD AN EXTRA WORD, MOVE TO T2 PUSH P,T2 ;SAVE LENGTH PUSHJ P,GETSWS## ;GET FROM SCA FREE POOL JRST T2POPJ## ;SORRY POP P,T2 ;RESTORE LENGTH MOVEM T2,0(T1) ;SAVE LENGTH AS FIRST WORD SUBI T2,2 ;NUMBER OF WORDS TO ZERO AOS T3,T1 ;BUMP ADDRESS, COPY TO T3 ; (SKIP OUR LENGTH WORD) XMOVEI T4,1(T3) ;DESTINATION ADDRESS SETZM (T3) ;ZERO FIRST WORD EXTEND T2,[XBLT] ;ZERO REMAINDER JRST CPOPJ1## ;SKIP RETURN ;ROUTINE TO RETURN RESIDENT FREE SPACE. ;CALL: ; T1/ ADDRESS OF SPACE TO RETURN ; PUSHJ P,RELRES ;RETURN: ; CPOPJ ALWAYS RELRES: MOVE T2,-1(T1) ;GET LENGTH WE STUFFED HERE EARLIER EXCH T1,T2 ;SWAP SO WE HAVE LENGTH IN T1, ADDRESS IN T2 SOJA T2,GIVSWS## ;ACCOUNT FOR THE WORD WE SWIPED EARLIER, ; RETURN THE SPACE TO SCA FREE POOL AND RETURN SUBTTL MISCELLANEOUS ROUTINES ;ROUTINE TO CHECK A CID AND GET ON THE PROPER CPU. ;CALL: ; T1/ CONNECT ID ; PUSHJ P,CHKCID ;RETURN: ; CPOPJ IF ERROR ; CPOPJ1 IF SUCCESS WITH: ; T1/ CONNECT ID ; P1/ CBK ADDRESS ; P5/ PBK ADDRESS CHKCID: PUSHJ P,SC.CSC## ;FIRST CHECK THE CID FOR VALIDITY POPJ P, ;ERROR ;RETURNS P1=CBK ADDRESS, P5=PBK ADDRESS IFN FTMP,< MOVE T1,.PBCPU(P5) ;GET CPU NUMBER PUSHJ P,ONCPUS## ;GET ON THAT CPU POPJ P, ;CPU IS DOWN >; END IFN FTMP MOVE T1,.CBSCI(P1) ;GET SOURCE CONNECT ID JRST CPOPJ1## ;SKIP RETURN ;ROUTINE TO OBTAIN A PROCESS QUEUE BLOCK WHEN NONE HAS PREVIOUSLY ;EXISTED FOR THIS CONTEXT. ;CALL: ; W/ PDB ADDRESS ; PUSHJ P,GETPQB ;RETURN: ; CPOPJ IF NO FREE CORE ; CPOPJ1 IF SUCCESS WITH: ; P3/ PQB ADDRESS GETPQB: MOVEI T1,PQBLEN ;LENGTH OF THE BLOCK PUSHJ P,ASGRES ;GET SOME FREE SPACE POPJ P, ;NO FREE CORE, RETURN MOVE P3,T1 ;COPY TO STANDARD REGISTER SETZM SCSTMQ(P3) ;ZERO HEAD POINTER XMOVEI T1,SCSTMQ(P3) ;INIT BLINK MOVEM T1,SCSBMQ(P3) ; AS POINTER TO FLINK SETZM SCSTDQ(P3) ;ZERO HEAD POINTER XMOVEI T1,SCSTDQ(P3) ;INIT BLINK MOVEM T1,SCSBDQ(P3) ; AS POINTER TO FLINK SETZM SCSTXQ(P3) ;ZERO HEAD POINTER XMOVEI T1,SCSTXQ(P3) ;INIT BLINK MOVEM T1,SCSBXQ(P3) ; AS POINTER TO FLINK SETZM SCSTEQ(P3) ;ZERO HEAD POINTER XMOVEI T1,SCSTEQ(P3) ;INIT BLINK MOVEM T1,SCSBEQ(P3) ; AS POINTER TO FLINK SETZM SCSTCQ(P3) ;ZERO HEAD POINTER XMOVEI T1,SCSTCQ(P3) ;INIT BLINK MOVEM T1,SCSBCQ(P3) ; AS POINTER TO FLINK SETZM SCSTXN(P3) ;ZERO HEAD POINTER XMOVEI T1,SCSTXN(P3) ;INIT BLINK MOVEM T1,SCSBXN(P3) ; AS POINTER TO FLINK MOVEM P3,.PDSCS##(W) ;STORE ADDRESS IN PDB JRST CPOPJ1## ;SKIP RETURN ;ROUTINE TO RETURN A PCB ADDRESS GIVEN A CPU NUMBER. CALLED ;BY FUNCTIONS WHICH ACCEPT A CPU NUMBER ARGUMENT. ;CALL: ; P2/ CPU NUMBER ; PUSHJ P,CPUPCB ;RETURN: ; CPOPJ IF NO PCB AFTER CALLING ERRNPC ; CPOPJ1 WITH: ; P6/ PCB ADDRESS ;*** DO I LIKE THE CPU NUMBER = 6/7 HACK FOR THE CPU WE'RE RUNNING ON? CPUPCB: CAIN P2,6 ;SPECIAL CODE FOR "THIS" CPU? MOVE P2,.CPCPN## ;YES, SUBSTITUTE "THIS" CPU NUMBER SKIPL P6,P2 ;RANGE CHECK CPU ARGUMENT CAIL P2,CPUN## ;... JRST ERRCPN ;CPU NUMBER OUT OF RANGE LSH P6,.CPSOF## ;OFFSET FROM CPU0'S CDB SKIPG .C0OK##(P6) ;SKIP IF CPU NOT RUNNING SKIPN P6,.C0PCB##(P6) ;GET ADDRESS OF PCB AND SKIP JRST ERRNPC ;NO PORT ON CPU (OR CPU NOT RUNNING) JRST CPOPJ1## ;SKIP RETURN SUBTTL SOFTWARE INTERRUPT SUPPORT ;ROUTINE TO RETURN THE INTERRUPT STATUS WORD. CALLED FROM PSISER ;WHEN GRANTING AN SCS PSI EVENT. ;CALL: ; J/ JOB NUMBER ; PUSHJ P,SCSPSI ;RETURN: ; CPOPJ ALWAYS WITH: ; T2/ INTERRUPT STATUS WORD IFN FTPI,< SCSPSI::SE1ENT ;RUN IN NZS PUSHJ P,SAVJW## ;SAVE W (J COMES ALONG FOR THE RIDE) SETZ T2, ;START WITH A BIG FAT ZERO PUSHJ P,FNDPDB## ;FIND PDB FOR JOB POPJ P, ;THAT'S ODD SKIPN T1,.PDSCS##(W) ;GET POINTER TO PROCESS QUEUE BLOCK POPJ P, ;THAT'S ODD TOO! SKIPE SCSTMQ(T1) ;ANYTHING ON MESSAGE QUEUE? TXO T2,SC%MSA ;YES SKIPE SCSTDQ(T1) ;ANYTHING ON DATAGRAM QUEUE? TXO T2,SC%DGA ;YES SKIPE SCSTXQ(T1) ;ANYTHING ON DMA XFER QUEUE? TXO T2,SC%DTA ;YES SKIPE SCSTEQ(T1) ;ANYTHING ON EVENT QUEUE? TXO T2,SC%EVA ;YES POPJ P, ;RETURN >; END IFN FTPI ;ROUTINE TO GENERATE ANOTHER SOFTWARE INTERRUPT WHEN AN EVENT BLOCK ;OR A MESSAGE/DATAGRAM IS REMOVED FROM THE CONTEXT QUEUE. ;CALL: ; P3/ PQB ADDRESS ; PUSHJ P,SCSSIG ;RETURN: ; CPOPJ ALWAYS, INTERRUPT SIGNALLED IF NECESSARY IFN FTPI,< SCSSIG: SKIPE SCSTMQ(P3) ;ANYTHING ON MESSAGE QUEUE? JRST SIG.01 ;YES SKIPE SCSTDQ(P3) ;ANYTHING ON DATAGRAM QUEUE? JRST SIG.01 ;YES SKIPE SCSTXQ(P3) ;ANYTHING ON DMA XFER QUEUE? JRST SIG.01 ;YES SKIPN SCSTEQ(P3) ;ANYTHING ON EVENT QUEUE? POPJ P, ;NO, SO NO NEED FOR ANOTHER INTERRUPT SIG.01: PUSH P,J ;SAVE J MOVE J,.CPJOB## ;MAKE SURE J CONTAINS THE JOB NUMBER SIGNAL C$SCS ;SIGNAL SCS EVENT JFCL ;USER NOT ENABLED? PJRST JPOPJ## ;RESTORE J AND RETURN >; END IFN FTPI SUBTTL QUEUE HEADER BLOCKS MSG: IFIW .CBTMQ(P1) ;(.TOPCQ) TOP OF CB MESSAGE QUEUE IFIW .CBBMQ(P1) ;(.BOTCQ) BOTTOM OF CB MESSAGE QUEUE IFIW SCSTMQ(P3) ;(.TOPFQ) TOP OF CONTEXT MESSAGE QUEUE IFIW SCSBMQ(P3) ;(.BOTFQ) BOTTOM OF CONTEXT MESSAGE QUEUE IFIW .CBMGJ(P1) ;(.JBUFF) COUNT OF JSYS MESSAGE BUFFERS DG: IFIW .CBTDQ(P1) ;(.TOPCQ) TOP OF CB DATAGRAM QUEUE IFIW .CBBDQ(P1) ;(.BOTCQ) BOTTOM OF CB DATAGRAM QUEUE IFIW SCSTDQ(P3) ;(.TOPFQ) TOP OF CONTEXT DATAGRAM QUEUE IFIW SCSBDQ(P3) ;(.BOTFQ) BOTTOM OF CONTEXT DATAGRAM QUEUE IFIW .CBDGJ(P1) ;(.JBUFF) COUNT OF JSYS DATAGRAM BUFFERS XFER: IFIW .CBTXQ(P1) ;(.TOPCQ) TOP OF CB DMA XFER QUEUE IFIW .CBBXQ(P1) ;(.BOTCQ) BOTTOM OF CB DMA XFER QUEUE IFIW SCSTXQ(P3) ;(.TOPFQ) TOP OF CONTEXT DMA XFER QUEUE IFIW SCSBXQ(P3) ;(.BOTFQ) BOTTOM OF CONTEXT DMA XFER QUEUE 0 ;(.JBUFF) NO COUNTER OF JSYS MESSAGE BUFFERS EVT: IFIW .CBTEQ(P1) ;(.TOPCQ) TOP OF CB EVENT QUEUE IFIW .CBBEQ(P1) ;(.BOTCQ) BOTTOM OF CB EVENT QUEUE IFIW SCSTEQ(P3) ;(.TOPFQ) TOP OF CONTEXT EVENT QUEUE IFIW SCSBEQ(P3) ;(.BOTFQ) BOTTOM OF CONTEXT EVENT QUEUE 0 ;(.JBUFF) NO COUNTER OF JSYS MESSAGE BUFFERS SUBTTL IMPURE STORAGE $LOW SCSTIQ: BLOCK 1 ;POINTER TO TOP OF INTERRUPT LEVEL PACKET QUEUE SCSBIQ: BLOCK 1 ;POINTER TO BOTTOM OF QUEUE $HIGH SUBTTL THE END SCSEND::!END