Trailing-Edge
-
PDP-10 Archives
-
bb-jr93e-bb
-
7,6/ap018/scsuuo.x18
There is 1 other file named scsuuo.x18 in the archive. Click here to see a list.
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 <SPN,DPN,CID,ERRCOD,STRRET,DATRET,STRADR,DATADR,MSGBUF,DGBUF>
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 <HLRE T1,.SQSYS(M)> ;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 <SKIPN T1,.SQCDT(M)> ;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 <SKIPN T1,.SQAMC(M)> ;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 <SKIPN T1,.SQADC(M)> ;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 <HRRZ T1,.SQSYS(M)> ;GET CID BITS FROM USER
LOAD T2,PBPBI,(P5) ;GET PBI
BLCAL. (SC.CON##,<SPN,DPN,T2,[5],[0],<.,SCSINT>,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 <SPN,DPN,CID,ERRCOD,STRRET,DATRET,STRADR,DATADR,MSGBUF,DGBUF>
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 <HLRE T1,.SQSYS(M)> ;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 <HRRZ T2,.SQSYS(M)> ;GET CID BITS
BLCAL. (SC.LIS##,<SPN,DPN,T1,<.,SCSINT>,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 <Q1> ;SAVE AN AC
STKVAR <PAKADR,USRBUF,MSGFLG,ERRCOD,LEN> ;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 <HRLM T3,.SQDFL(M)> ;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 <HRRM T1,.SQDFL(M)> ;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##,<T1,T2>) ;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##,<T1,T2>) ;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 <BUFADR,CID,MSGFLG,ERRCOD> ;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,<C%MGSZ-.MHUDA> ;ASSUME A MESSAGE
SKIPN MSGFLG ;GOOD GUESS?
MOVX T3,<C%DGSZ-.MHUDA> ;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##,<CID,T2,T4,BUFADR,[SCSPRI],[0],T3>)
JRST SDGERR ;ERROR
JRST CPOPJ1## ;SKIP RETURN
SDG.04: BLCAL. (SC.SDG##,<CID,T2,T4,BUFADR,[SCSPRI],T3>)
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 <QRMFLG,CID> ;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##,<CID,P2,[0]>) ;QUEUE BUFFERS FOR THIS CONNECTION
JRST ERRQBF ;ERROR
JRST CPOPJ1## ;SUCCESS
QRD.01: BLCAL. (SC.RDG##,<CID,P2,[0]>) ;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 <CRDFLG,CID> ;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##,<CID,[1]>) ;CANCEL ONE DATAGRAM
JRST ERRCBF ;ERROR
SOS .CBDGJ(P1) ;ONE LESS DATAGRAM QUEUED
JRST CPOPJ1## ;SKIP RETURN
CRM.01: BLCAL. (SC.CRM##,<CID,[1]>) ;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 <IDPB T3,P2> ;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 <SKIPN T1,.SQCID(M)> ;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 <SKIPL T1,.SQOND(M)> ;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 <DMOVEM T1,.SQSAD(M)> ;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 <DMOVEM T1,.SQDSE(M)> ;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 <DMOVEM T1,.SQDHV(M)> ;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 <DMOVEM T1,.SQNNM(M)> ;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,<C%DGSZ-2>/<.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 <FBADDR,ERRCOD,MODE,WRDLEN> ;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 <MAP T1,(T1)> ;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##,<FBADDR>) ;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 <BUFNAM> ;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 <SNDFLG,CID> ;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 <HLRZ T3,.SQOFS(M)> ;GET SEND BUFFER OFFSET
EXCTUX <HRRZ T4,.SQOFS(M)> ;GET RECEIVE BUFFER OFFSET
SKIPN SNDFLG ;ARE WE DOING A SEND?
JRST REQ.01 ;NO
BLCAL. (SC.SND##,<CID,T1,T2,T3,T4>)
JRST ERRPSF ;ERROR
JRST CPOPJ1## ;SKIP RETURN
REQ.01: BLCAL. (SC.REQ##,<CID,T1,T2,T3,T4>)
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 <DATADR,DATRET,ERRCOD,CID> ;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##,<CID,DATADR,[0],[0]>) ;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 <BLKADR> ;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 <EVTADR,EVTCOD,USRLEN,ERRCOD>
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,<C%MGSZ-.MHUDA> ;GET THE SIZE OF A MESSAGE BUFFER
UMOVEM T1,.SQLMG(M) ;STORE IT
MOVX T1,<C%DGSZ-.MHUDA> ;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 <SKIPL T1,.SQRPN(M)> ;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,<IFN .SSAFT-<.-SINDSP-1>,<PRINTX ?Dispatch table SINDSP out of order>>
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 <CID> ;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 <CID,CDATA> ;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 <CID,RJTADR> ;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 <CID> ;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 <CID> ;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 <CID,RCDT,SCDT> ;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 <CID,BUFNAM> ;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 <CID,BUFADR> ;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 <CID,SHRTBF> ;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 <BLKADR,NXTENT> ;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##,<T1,[0]>) ;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 <SKIPE T1,(T1)> ;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 <Q1,Q2> ;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 <SKIPN Q1,(Q1)> ;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 <SPN,DPN> ;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,<POINT 8,(Q1)> ;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,<POINT 8,C%PNLW(Q1)> ;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 <DATADR,USRDAT> ;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
PJRST SC.SRB## ;SET REAP BIT 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 <BUFNAM> ;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 <BUFNAM> ;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 <BUFNAM> ;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 <ENTADR> ;ALLOCATE A WORD OF STACK STORAGE
MOVEM T1,ENTADR ;SAVE ADDRESS OF ENTRY
MOVE T1,.XNNAM(T1) ;GET BUFFER NAME
BLCAL. (SC.UMP##,<T1>) ;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 <Q1> ;FREE UP AN AC
STKVAR <RTNADR,BLKADR> ;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 <Q1> ;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 <ILDB T4,T1> ;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 <BUFADR,BSDOFS> ;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 <Q1> ;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