1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-02 01:30:40 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

2587 lines
86 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE SCSUUO - SCS. UUO SUPPORT V34
SUBTTL JOSEPH A. DZIEDZIC/JAD 8 SEP 87
SEARCH F,S,DEVPRM,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 BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1984,1988>
XP VSCSUU,34 ;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.
$CSENT (SCSINI::) ;GLOBAL ENTRY POINT
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
PUSHJ P,SCSSIG ;SIGNAL ANOTHER INTERRUPT IF NECESSARY
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
LDB T1,[POINT 3,KDBCNO(P6),9] ;GET RH20 NUMBER
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,PAGSIZ ;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,PAGSIZ ;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
PUSHJ P,SCSSIG ;SIGNAL ANOTHER INTERRUPT IF NECESSARY
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
PUSHJ P,SCSSIG ;SIGNAL ANOTHER INTERRUPT IF NECESSARY
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::
;ONLY GETS CALLED ON THE BOOT CPU
; SKPCPU (0) ;BOOT CPU?
; POPJ P, ;NO, QUIT
SKIPN SCSTIQ ;AVOID SE1ENT AND SAVING ACS IF NO ENTRIES
POPJ P, ;GET OUT QUICK
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,M.CPU## ;...
JRST ERRCPN ;CPU NUMBER OUT OF RANGE
IMULI P6,.CPLEN## ;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
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
;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
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
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