mirror of
https://github.com/PDP-10/stacken.git
synced 2026-03-01 17:26:38 +00:00
6630 lines
215 KiB
Plaintext
6630 lines
215 KiB
Plaintext
;TITLE SCLINK - Session Control Layer Control for DECnet-36
|
||
|
||
|
||
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
|
||
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
|
||
;
|
||
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976,1986,1988.
|
||
;ALL RIGHTS RESERVED.
|
||
|
||
SUBTTL V.Brownell & W.Nichols/Tarl
|
||
SEARCH D36PAR,SCPAR,MACSYM
|
||
SALL
|
||
|
||
ENTRY SCTL,SCTINI
|
||
|
||
IFN FTOPS10,<
|
||
.CPYRT<1976,1988>
|
||
> ;END IFN FTOPS10
|
||
|
||
IFN FTOPS20,<
|
||
SEARCH PROLOG
|
||
TTITLE SCLINK,,< - Session Control Layer for DECnet-36>
|
||
>
|
||
|
||
IFN FTOPS10,<
|
||
SEARCH F,S
|
||
TITLE SCLINK - Session Control Layer Control for DECnet-36
|
||
$RELOC
|
||
>
|
||
|
||
D36SYM ;SET UP D36 SPECIFIC PARAMETERS
|
||
XRESCD ;Start in extended resident code
|
||
|
||
SUBTTL Table of Contents
|
||
|
||
|
||
; Table of Contents for SCLINK
|
||
;
|
||
;
|
||
; Section Page
|
||
; 1. Table of Contents. . . . . . . . . . . . . . . . . . . 2
|
||
; 2. Definitions
|
||
; 2.1. Internal References . . . . . . . . . . . . . 3
|
||
; 2.2. External References . . . . . . . . . . . . . 4
|
||
; 2.3. Accumulators. . . . . . . . . . . . . . . . . 6
|
||
; 2.4. Node name/number database . . . . . . . . . . 7
|
||
; 2.5. Loopback node block . . . . . . . . . . . . . 8
|
||
; 3. Macros
|
||
; 3.1. Code-Generating
|
||
; 3.1.1. IFxSTATE . . . . . . . . . . . . . . 9
|
||
; 3.1.2. NEWSTATE . . . . . . . . . . . . . . 10
|
||
; 4. SCTINI - Session Control Initialization. . . . . . . . 11
|
||
; 5. SCTPSQ - Grant a PSI interrupt . . . . . . . . . . . . 12
|
||
; 6. SCTSTM - Check Active Connect Timers for Expiration. . 13
|
||
; 7. SCTSEC - Once-a-second service for SCLINK. . . . . . . 14
|
||
; 8. SCTRFJ - Request Second Service for a Link . . . . . . 15
|
||
; 9. SCTL's Interlock
|
||
; 9.1. Queuing Version . . . . . . . . . . . . . . . 16
|
||
; 9.2. Waiting Version . . . . . . . . . . . . . . . 17
|
||
; 9.3. Flag Version. . . . . . . . . . . . . . . . . 18
|
||
; 10. SCTULK - SCTL's Interlock
|
||
; 10.1. Unlock Checks . . . . . . . . . . . . . . . . 19
|
||
; 11. NSP.
|
||
; 11.1. Function Dispatch Table . . . . . . . . . . . 20
|
||
; 11.2. Wait Check Tables
|
||
; 11.2.1. Definitons . . . . . . . . . . . . . 21
|
||
; 11.3. Wait check tables
|
||
; 11.3.1. "Before" NSP. table. . . . . . . . . 22
|
||
; 11.3.2. "After" NSP. table . . . . . . . . . 23
|
||
; 11.3.3. Routines . . . . . . . . . . . . . . 24
|
||
; 11.4. SCTNSF - The Entry to SCLINK from SCMUUO. . . 25
|
||
; 11.5. NSFRE - REset all links . . . . . . . . . . . 31
|
||
; 11.6. NSFEA - Enter Active State. . . . . . . . . . 32
|
||
; 11.7. NSFEP - Enter Passive State . . . . . . . . . 35
|
||
; 11.8. NSFRI - Read Connect Information. . . . . . . 36
|
||
; 11.9. NSFAC - Accept the Connect. . . . . . . . . . 37
|
||
; 11.10. NSFRJ - Reject the Connect. . . . . . . . . . 39
|
||
; 11.11. NSFRC - Read Connect Confirm Information. . . 40
|
||
; 11.12. NSFSD - Synchronous Disconnect. . . . . . . . 41
|
||
; 11.13. NSFAB - Abort and Release . . . . . . . . . . 43
|
||
; 11.14. NSFRD - Read Disconnect Data. . . . . . . . . 44
|
||
; 11.15. NSFRL - Release the Channel . . . . . . . . . 45
|
||
; 11.16. NSFRS - Read the Channel Status . . . . . . . 46
|
||
; 11.17. NSFIS - Send Interrupt Data . . . . . . . . . 47
|
||
; 11.18. NSFIR - Receive Interrupt Data. . . . . . . . 49
|
||
; 11.19. NSFDS - Send Normal Data. . . . . . . . . . . 51
|
||
; 11.20. NSFDR - Receive Normal Data . . . . . . . . . 55
|
||
; 11.21. NSFSQ - Set Quotas and Goals. . . . . . . . . 57
|
||
; 11.22. NSFRQ - Read Quotas and Goals . . . . . . . . 58
|
||
; 11.23. NSFJS - Set Job Quotas and Goals. . . . . . . 59
|
||
; 11.24. NSFJR - Read Job Quotas and Goals . . . . . . 60
|
||
; 11.25. NSFPI - Set PSI Reason Mask . . . . . . . . . 61
|
||
; 12. RETFLW - Return current flow controls. . . . . . . . . 62
|
||
; 13. SNDDRQ - Send Data Requests. . . . . . . . . . . . . . 63
|
||
; 14. RLSLNK - Release a Link. . . . . . . . . . . . . . . . 64
|
||
; 15. LLINKS Calls
|
||
; 15.1. Entry Vector Table. . . . . . . . . . . . . . 65
|
||
; 15.2. SCTRIB - Reserve Input Buffer . . . . . . . . 66
|
||
; 15.3. SCTUCG - Uncongestion Call. . . . . . . . . . 67
|
||
; 15.4. SCTLCI - Connect Initiate Call. . . . . . . . 68
|
||
; 15.5. The Vectored Call Entry Point SCTL. . . . . . 71
|
||
; 15.6. SCCCR - Connect Confirmed call from NSP . . . 72
|
||
; 15.7. SCDIR - Disconnect Initiate received call . . 73
|
||
; 15.8. SCDCR - Disconnect Confirm received call. . . 74
|
||
; 15.9. SCODN - Output done call. . . . . . . . . . . 75
|
||
; 15.10. SCSEG - Segment received call . . . . . . . . 76
|
||
; 15.11. SCDRQ - Data request received call. . . . . . 77
|
||
; 15.12. SCNCF - No confidence in port call. . . . . . 78
|
||
; 15.13. SCNRS - No resources call . . . . . . . . . . 79
|
||
; 15.14. SCCLS - Close Completed call. . . . . . . . . 80
|
||
; 15.15. SCNLK - No link call. . . . . . . . . . . . . 81
|
||
; 15.16. SCNCM - No communication call . . . . . . . . 82
|
||
; 15.17. SCNRN - Not in Run State call . . . . . . . . 83
|
||
; 15.18. SCCAK - Got a Connect ACK . . . . . . . . . . 84
|
||
; 16. Subroutines
|
||
; 16.1. CHKABO - Check SLABO flag . . . . . . . . . . 85
|
||
; 16.2. CHKPPN - Check self PPN for validity. . . . . 86
|
||
; 16.3. FREMSG - Free a message block . . . . . . . . 87
|
||
; 16.4. CONBUF - Invoke Conservative Buffering. . . . 88
|
||
; 16.5. FNDSLB - Find SLB given a channel number. . . 89
|
||
; 16.6. FNDSBI - Find SLB from SLBid. . . . . . . . . 90
|
||
; 16.7. FRESLB - Deallocate a SLB . . . . . . . . . . 91
|
||
; 16.8. FRECBP - Free Connect Block . . . . . . . . . 92
|
||
; 16.9. CDMCBP - Copy User Data from Message Block. . 93
|
||
; 16.10. CPMSCB - Copy User Data from Message Block. . 94
|
||
; 16.11. FRESJB - Deallocate a SJB . . . . . . . . . . 95
|
||
; 16.12. MAKSLB - Create a SLB, filling in defaults. . 96
|
||
; 16.13. MAKSJB - Create a SJB, filling in defaults. . 98
|
||
; 16.14. SCSSTS/CHKSTS - Set Status & Inform PSISER. . 99
|
||
; 16.15. SCTWKQ - Queue a Link for later call to SCTPSQ 101
|
||
; 16.16. SLBMAT - Pattern match connect to passive SLBs 102
|
||
; 16.17. CDBMAT - Match Two Connect Blocks . . . . . . 103
|
||
; 16.18. STRMAT - Pattern Matcher. . . . . . . . . . . 106
|
||
; 16.19. STPTMR - Stop the Connect Initiate Timer. . . 107
|
||
; 16.20. STRTMR - Start the Connect Initiate Timer . . 108
|
||
; 16.21. TMRREJ - Send a Reject with Reason RSNNRO . . 109
|
||
; 16.22. BLDCTX - Build connect message. . . . . . . . 110
|
||
; 16.23. PRSCTX - Parse a connect message. . . . . . . 114
|
||
; 16.24. CPYS2M - Copy string block to message segment 118
|
||
; 16.25. CPYM2S - Copy message data to string block. . 119
|
||
; 16.26. SCTGSS - Get segment size for a destination . 120
|
||
; 16.27. SCTCSS - Check segment size for a destination 121
|
||
; 17. Node name/number database
|
||
; 17.1. Initialize. . . . . . . . . . . . . . . . . . 122
|
||
; 17.2. Lock/unlock database. . . . . . . . . . . . . 123
|
||
; 17.3. Add a node. . . . . . . . . . . . . . . . . . 124
|
||
; 17.4. Address to name . . . . . . . . . . . . . . . 125
|
||
; 17.5. Name to address . . . . . . . . . . . . . . . 126
|
||
; 17.6. Name to NO block. . . . . . . . . . . . . . . 127
|
||
; 17.7. Default area #. . . . . . . . . . . . . . . . 128
|
||
; 17.8. Hash routine. . . . . . . . . . . . . . . . . 129
|
||
; 17.9. Get a bucket. . . . . . . . . . . . . . . . . 130
|
||
; 17.10. SCTANL - Add a loopback node name . . . . . . 131
|
||
; 17.11. SCTN2L - Convert name to loop circ. . . . . . 132
|
||
; 17.12. SCTL2N - Convert loopback circuit . . . . . . 132
|
||
; 17.13. SCTCKL - Check for loopback node. . . . . . . 132
|
||
; 18. Network management
|
||
; 18.1. Dispatch. . . . . . . . . . . . . . . . . . . 133
|
||
; 18.2. SET parameter . . . . . . . . . . . . . . . . 134
|
||
; 18.3. CLEAR parameter . . . . . . . . . . . . . . . 134
|
||
; 18.4. READ parameter. . . . . . . . . . . . . . . . 134
|
||
; 18.5. Return list of entity ids . . . . . . . . . . 135
|
||
; 18.6. Map node address to node name . . . . . . . . 136
|
||
; 18.7. Map node name to node address . . . . . . . . 136
|
||
; 18.8. Check loopback node name. . . . . . . . . . . 136
|
||
; 18.9. Event
|
||
; 18.9.1. Invalid message. . . . . . . . . . . 137
|
||
; 18.9.2. CSSE event . . . . . . . . . . . . . 138
|
||
; 19. Local SCTL Storage . . . . . . . . . . . . . . . . . . 139
|
||
; 20. End of SCLINK. . . . . . . . . . . . . . . . . . . . . 140
|
||
|
||
SUBTTL Definitions -- Internal References
|
||
|
||
;These are the routines and variables in SCLINK that are referenced
|
||
; by other modules
|
||
|
||
;Initialization
|
||
INTERN SCTINI ;Initialize SCLINK
|
||
|
||
;Calls from higher layers
|
||
INTERN SCTPSQ ;Grant PSI to user
|
||
INTERN SCTWKQ ;Queue a link to SCTPSQ
|
||
INTERN SCTSEC ;Once-a-second service
|
||
INTERN SCTLCW ;Process level interlock grabber
|
||
INTERN SCTNSF ;Session control function entry point
|
||
|
||
IFN FTOPS20 <
|
||
INTERN SCTLOK ;Session control interlock
|
||
>
|
||
|
||
;Calls from LLINKS
|
||
INTERN SCTRIB ;Reserve input buffer
|
||
INTERN SCTUCG ;Congestion
|
||
INTERN SCTLCI ;Connect initiate
|
||
INTERN SCTL ;LLINKS entry point in general
|
||
|
||
;Network management
|
||
INTERN SCLNMX ;NTMAN entry point
|
||
INTERN SCTLNL ;Loopback node name list
|
||
INTERN SCTINT ;Incoming timer
|
||
INTERN SCTOTT ;Outgoing timer
|
||
INTERN LEVT.0 ;LCG event parameter 0
|
||
|
||
;SJB routines
|
||
INTERN FRESJB ;Free a SJB
|
||
INTERN MAKSJB ;Allocate a SJB
|
||
INTERN CHKSJB ;Check an SJB for SLBs
|
||
|
||
;Node name and address mapping
|
||
INTERN SCTAND ;Add or delete a node
|
||
INTERN SCTA2N ;Map a node address to a name
|
||
INTERN SCTN2A ;Map a node name to an address
|
||
INTERN SCTNDC ;# of local nodes defined (for JNTMAN)
|
||
|
||
;Loopback nodes
|
||
INTERN SCTN2L ;Map node name to loopback node
|
||
INTERN SCTCKL ;Check for existance of loopback node
|
||
|
||
SUBTTL Definitions -- External References
|
||
|
||
;These are the external references to the D36COM library of routines.
|
||
|
||
EXT DNGNBF ;GET TOTAL NUMBER OF BUFFERS IN SYSTEM
|
||
|
||
EXT DNGINI ;INITIALIZE FOR INPUT (DGXYBY)
|
||
EXT DNPINI ;INITIALIZE FOR OUTPUT (DPXYBY)
|
||
EXT DNPINR ;REINITIALIZE FOR OUTPUT (DPXYBY)
|
||
|
||
EXT DNP1BY ;PUT ONE BYTE IN MESSAGE
|
||
EXT DNP2BY ;PUT TWO BYTES IN MESSAGE
|
||
EXT DNPEBY ;PUT AN EXTENSIBLE BYTE IN MESSAGE
|
||
|
||
EXT DNG1BY ;GET ONE BYTE FROM MESSAGE
|
||
EXT DNG2BY ;GET TWO BYTES FROM MESSAGE
|
||
EXT DNGEBY ;GET EXTENSIBLE BYTE FROM MESSAGE
|
||
|
||
EXT DNGMSG ;GET DECNET-36 MESSAGE BLOCK
|
||
EXT DNFMSG ;FREE MESSAGE BLOCK
|
||
EXT DNMINI ;REUSE A MESSAGE BLOCK
|
||
|
||
EXT DNLENG ;GET THE MESSAGE LENGTH
|
||
EXT DNSLNG ;FIND THE SEGMENT LENGTH
|
||
|
||
EXT DNGWDS ;GET SOME WORDS
|
||
EXT DNGWDP ;Get some words in process context
|
||
EXT DNGWDZ ;GET SOME ZEROED WORDS
|
||
EXT DNGWZP ;Get som zeroed words in process context
|
||
EXT DNFWDS ;FREE SOME WORDS
|
||
EXT DNSWDS ;SMEAR SOME WORDS
|
||
|
||
EXT DNBKBY ;GO BACKWARDS SOME BYTES
|
||
EXT DNSKBY ;SKIP SOME BYTES
|
||
|
||
EXT DNSMRK ;SET MARK IN MESSAGE
|
||
EXT DNGMRK ;POSITION AT MARK IN MESSAGE
|
||
|
||
EXT DNLMSS ;LINK MESSAGE SEGMENT INTO MESSAGE BLOCK
|
||
|
||
EXT DNCPYW ;COPY WORDS WITH BLT OR XBLT
|
||
|
||
EXT DNCM2U ;COPY MESSAGE TO USER BUFFER (TOPS-10)
|
||
EXT DNCU2M ;COPY USER BUFFER TO MESSAGE (TOPS-10)
|
||
EXT DNCM2B ;COPY MESSAGE TO MONITOR BUFFER
|
||
EXT DNCB2M ;COPY MONITOR BUFFER TO MESSAGE
|
||
|
||
EXT DNGTIM ;GET CURRENT TIME IN MS
|
||
|
||
EXT DCNTSB ;TOTAL SYSTEM BUFFERS, USED AND UNUSED
|
||
EXT DCNCON ;NON-ZERO IF SYSTEM IS CONGESTED
|
||
EXT DCNRSB ;RESERVED BUFFERS, MODIFIED UNDER D36OFF
|
||
; TO PROTECT AGAINST SCTRIB CALL FROM LLINKS
|
||
EXT DCNRHT ;HIGH TIDE FOR DCNRSB
|
||
EXT DCNRIF ;INPUT RESERVATION FAILURES
|
||
EXT DCNROF ;OUTPUT RESERVATION FAILURES
|
||
|
||
EXT NTPARM ;Network management parameter processing
|
||
|
||
EXT EVPBYT ;Network management event parameter output
|
||
EXT EVP2BT ; " " " " "
|
||
EXT TIMBAS ;Fractions of a second for time computation
|
||
|
||
;Entries into NSP.
|
||
|
||
EXT NSP ;THE MAIN ENTRY TO NSP
|
||
EXT NSPINI ;INITIALIZATION ROUTINE FOR NSP
|
||
EXT NSPEVT ;SIGNAL AN NSP-LEVEL EVENT, USING EVENT MACRO
|
||
; FROM SCPAR.UNV
|
||
|
||
;Entry into ROUTER.
|
||
|
||
;Calls to ROUTER violate the layering. However, it is necessary to
|
||
; ask ROUTER for the maximum buffer sizes to a given destination node in order
|
||
; to implement 'big buffers' on the NI.
|
||
|
||
EXT RTRGBS ;Get maximum buffer size for a node
|
||
EXT RTRCBS ;Check maximum buffer size for a node
|
||
|
||
;Here are some external references to system things.
|
||
|
||
EXT RTN ;RETURN
|
||
EXT RSKP ;SKIP RETURN
|
||
|
||
EXT EV96.0 ;Determines whether CSSE event 96.0 is logged
|
||
|
||
IFN FTOPS10,<
|
||
EXT BITTBL ;TABLE OF BIT POSITIONS
|
||
BITS==BITTBL ;SCLINK USES BITS TABLE
|
||
>; END IFN FTOPS10
|
||
|
||
IFN FTOPS20,<
|
||
EXT ASGVAS ;Assign virtual address space
|
||
>
|
||
;Externals for TOPS10 interlock management
|
||
|
||
IFN FTOPS10,< ;EXTERNAL FOR SMP INTERLOCK BREAKER
|
||
EXT SCTLOK ;INTERLOCK WORD
|
||
EXT SCTLKO ;INTERLOCK OWNER WORD
|
||
>
|
||
|
||
;External data.
|
||
|
||
EXT %SCHDR ;MAX LENGTH OF HEADERS BELOW SCTL
|
||
EXT RTRBSZ ;CELL CONTAINING ROUTER'S BUFFER SIZE
|
||
EXT IBBLK ;DECnet initialization block
|
||
EXT RTRHOM ;CELL CONTAINING ROUTER'S HOME AREA
|
||
EXT RTRMXN ;MAXIMUM NODE ADDRESS IN AREA
|
||
EXT %SCP2Q ;"PHASE II" QUOTA
|
||
EXT %SCINT ;DEFAULT INCOMING TIMER VALUE
|
||
EXT %SCOTT ;DEFAULT OUTGOING TIMER VALUE
|
||
EXT %RTMXN ;MAX-NODES
|
||
SUBTTL Definitions -- Accumulators
|
||
|
||
;These are some local AC defintions for Session Control.
|
||
|
||
SL=FREE1 ;SL POINTS TO THE CURRENT SC LINK BLOCK
|
||
SA=FREE2 ;SA POINTS TO THE ARGUMENT BLOCK
|
||
PURGE FREE1,FREE2 ;WE DON'T NEED THIS SYMBOL ANYMORE
|
||
|
||
SUBTTL Definitions -- Node name/number database
|
||
|
||
;Calculate number of buckets in database.
|
||
IFN FTOPS20,<
|
||
SCNHSZ==^D223 ;Hash table size
|
||
>; END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
SCNHSZ==^D509 ;Hash table size (largest prime less than 512)
|
||
MAPBAS==777,,000000 ;Base Pseudo address used in pseudo map
|
||
>; END IFN FTOPS10
|
||
NRNOPB==^D3 ;Nodes per bucket
|
||
|
||
;The LDAREA macro extracts an area # from a node address
|
||
DEFINE LDAREA(DST,SRC) <
|
||
LDB DST,[POINTR(SRC,RN%ARE)]
|
||
>
|
||
|
||
;The STAREA macro stores an area # into a node address
|
||
DEFINE STAREA(SRC,DST) <
|
||
DPB SRC,[POINTR(DST,RN%ARE)]
|
||
>
|
||
|
||
;The LDNOD macro extracts a local node index from a node address
|
||
DEFINE LDNODE(DST,SRC) <
|
||
LDB DST,[POINTR(SRC,RN%NOD)]
|
||
>
|
||
|
||
;The BEGSTR BU defines a bucket
|
||
BEGSTR BU
|
||
WORD NXT ;Pointer to next bucket
|
||
WORD NO1,<NO.LEN * NRNOPB>
|
||
ENDSTR
|
||
|
||
;The BEGSTR NO defines a single node in a bucket
|
||
BEGSTR NO ;Represents a single node
|
||
WORD NAM ;Node name
|
||
WORD ADR ;Node address
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- Loopback node block
|
||
|
||
BEGSTR LN
|
||
WORD NXT ;PTR TO NEXT LOOPBACK NODE BLOCK
|
||
WORD NAM ;LOOPBACK NODE NAME
|
||
WORD CIR ;LOOPBACK CIRCUIT
|
||
ENDSTR
|
||
|
||
SUBTTL Macros -- Code-Generating -- IFxSTATE
|
||
|
||
;Use: AC/ One of the .NSSxx state codes
|
||
;
|
||
;a) IFSTATE AC,<OP,CC,RJ>
|
||
; executed if match found
|
||
;b) IFSTATE AC,<OP,CC,RJ>,LABEL (Go there if match found)
|
||
|
||
DEFINE IFSTATE(AC,STATES,GLABEL),<IFST1(AC,<STATES>,<GLABEL>,N,GE,L)>
|
||
|
||
|
||
;Use: AC/ One of the .NSSxx state codes
|
||
;
|
||
;a) IFNSTATE AC,<OP,CC,RJ>
|
||
; executed if match NOT found
|
||
;b) IFNSTATE AC,<OP,CC,RJ>,LABEL (Go there if match NOT found)
|
||
|
||
DEFINE IFNSTATE(AC,STATES,GLABEL),<IFST1(AC,<STATES>,<GLABEL>,E,L,GE)>
|
||
|
||
DEFINE IFST1(AC,STATES,GLABEL,MOD1,MOD2,MOD3),<
|
||
ZZ==0
|
||
ZZCNT==0
|
||
IRP STATES,<ZZ==ZZ ! 1B<.NSS'STATES>
|
||
ZZCNT==ZZCNT+1>
|
||
IFE ZZCNT-1,<
|
||
CAI'MOD1 AC,.NSS'STATES
|
||
IFNB <GLABEL>,<
|
||
IFIDN <GLABEL>,<RTN>,<RET>
|
||
IFDIF <GLABEL>,<RTN>,<JRST GLABEL>
|
||
>>
|
||
IFG ZZCNT-1,< ;;IF MORE THAN ONE STATE TESTED
|
||
MOVX CX,ZZ
|
||
ROT CX,(AC)
|
||
IFB <GLABEL>,< SKIP'MOD2 CX >
|
||
IFNB <GLABEL>,< JUMP'MOD3 CX,GLABEL >
|
||
>
|
||
PURGE ZZCNT,ZZ
|
||
>
|
||
SUBTTL Macros -- Code-Generating -- NEWSTATE
|
||
|
||
;NEWSTATE will change the state of the link and call SCSSTS to tell
|
||
;PSISER to possibly let the user know about the change.
|
||
|
||
DEFINE NEWSTATE(suffix),<
|
||
MOVX T1,.NSS'suffix ;;SET UP STATE
|
||
CALL SCSSTS ;;LET PSISER KNOW ABOUT IT
|
||
TRACE SC,New State: suffix
|
||
>
|
||
SUBTTL SCTCCR - Compute Core Requirements
|
||
|
||
;SCTCCR computes SCLINK's core requirements.
|
||
;Call:
|
||
; PUSHJ P,SCTCCR
|
||
;Returns:
|
||
; T1/ Size of SCLINK core
|
||
|
||
IFN FTOPS10,<
|
||
SCTCCR::OPSTR <MOVE T1,>,IBMXA,+IBBLK ;NUMBER OF NODES IN AREA
|
||
ADDI T1,1 ;AND AN EXTRA WORD FOR NODE 0
|
||
ADD T1,SCTMPS ;AND SIZE OF PSEUDO MAP
|
||
RET ;AND RETURN
|
||
>; END IFN FTOPS10
|
||
SUBTTL SCTINI - Session Control Initialization
|
||
|
||
;SCTINI - Session Control Initialization
|
||
;
|
||
; Call:
|
||
; IBBLK filled in
|
||
;
|
||
; Return:
|
||
; RET ;COULDN'T INITIALIZE DUE TO RESOURCE FAILURE
|
||
; RETSKP ;INITIALIZED
|
||
;
|
||
; Uses: T1-T4
|
||
;
|
||
; Context:
|
||
; Process
|
||
|
||
XSWAPCD
|
||
SCTINI: TRACE SC,<Initializing Session Control>
|
||
|
||
;Initialize node name/number database, then call NSP to initialize itself
|
||
; and ROUTER
|
||
CALL SCTNIN ;Initialize node name/number database
|
||
RET ; -failed, return error
|
||
CALLRET NSPINI ;NSP, you can fly now!
|
||
|
||
XRESCD ;Back to resident code
|
||
|
||
SUBTTL SCTPSQ - Grant a PSI interrupt
|
||
|
||
;SCTPSQ - Grant a PSI interrupt for user
|
||
;
|
||
; Call: T1/ SJB Pointer
|
||
;
|
||
; Return:
|
||
; RET ;IF NOTHING IN QUEUE
|
||
; RETSKP ;IF FOUND AN SLB QUEUED
|
||
; T1+T2/ STRUCTURE PS, SEE SCPAR
|
||
;
|
||
; Uses:
|
||
;Note that this routine is not under the interlock
|
||
|
||
;Note that if we use T5 or T6 in this routine, we have to save
|
||
;them for caller.
|
||
|
||
XRENT SCTPSQ ;Run in extended resident code
|
||
|
||
D36OFF ;#AVOID PROBLEMS WITH SLPSI FLAG
|
||
DEQUE T4,SJ.PSQ(T1),SL.NXP,SCTPQ1 ;#ANYTHING ON THE PSI Q?
|
||
SETZRO SLPSI,(T4) ;#NOT ON THE PSI Q ANY MORE
|
||
D36ON
|
||
|
||
IF1,IFN PS.MOR,<PRINTX SCTPSQ needs PSMOR to be in T1>
|
||
|
||
MOVE T3,T1 ;GET POINTER TO SJB
|
||
LOAD T1,SLSST,(T4) ;NO INTERLOCK, DON'T CALL CHKSTS
|
||
STOR T1,PSSTS,+T1 ;STORE FOR CALLER (IN T2)
|
||
TMNE QHBEG,+SJ.PSQ(T3) ;MORE SLBS ON PSI Q?
|
||
TXO T1,PSMOR ;YES, SET THE MORE FLAG FOR CALLER
|
||
LOAD T3,SLCHN,(T4) ;GET CHANNEL NUMBER
|
||
STOR T3,PSCHN,+T1
|
||
LOAD T3,SLPSM,(T4) ;GET PSI MASK
|
||
STOR T3,PSPSM,+T1
|
||
|
||
RETSKP ;SUCCESS RETURN
|
||
|
||
|
||
;Here if DEQUE found nothing
|
||
|
||
SCTPQ1: D36ON
|
||
RET
|
||
SUBTTL SCTSTM - Check Active Connect Timers for Expiration
|
||
|
||
;SCTSTM - Check active connect timers for expiration
|
||
;
|
||
; Call:
|
||
; With nothing special
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCTSTM: SAVEAC <SA,SL,P1,P2> ;SAVE THE JOB AND LINK BLOCK POINTERS
|
||
LOAD SA,QHBEG,+SCTSJQ ;POINT TO THE FIRST SJB
|
||
TRNA
|
||
SCTST1: LOAD SA,SJNXT,(SA) ;GET THE NEXT SJB IN LIST
|
||
JUMPE SA,RTN ;NO MORE, JUST RETURN
|
||
JE SJCTA,(SA),SCTST1 ;IF THERE ARE NO TIMERS ACTIVE FOR JOB
|
||
; JUST LOOK AT THE NEXT GUY
|
||
LOAD P1,SJCHC,(SA) ;GET THE COUNT OF ENTRIES IN SLB TABLE
|
||
LOAD P2,SJCHT,(SA) ;POINT TO THE SLB TABLE
|
||
|
||
SCTST2: SKIPN SL,(P2) ;DO WE HAVE AN SLB?
|
||
JRST SCTST3 ;NO, CHECK THE NEXT ONE
|
||
JN <SLFSL,SLLBC>,(SL),SCTST3 ;YES, IGNORE IF ALREADY CLOSING
|
||
LOAD T1,SLSTA,(SL) ;GET THE STATE
|
||
IFSTATE T1,CR,SCTST4 ;CHECK THE INCOMING CONNECT TIMER
|
||
IFSTATE T1,CS,SCTST5 ;CHECK THE OUTGOING CONNECT TIMER
|
||
|
||
SCTST3: ADDI P2,1 ;INCREMENT SLB POINTER
|
||
SOJG P1,SCTST2 ;ANY MORE LEFT?
|
||
JRST SCTST1 ;NO, CHECK THE NEXT JOB
|
||
|
||
;Here with a SLB in CR state. Check the incoming timer for expiration.
|
||
|
||
SCTST4: CALL DNGTIM ;GET THE CURRENT TIME
|
||
OPSTR <SUB T1,>,SLCTM,(SL) ;FIND TIME SINCE TIMER STARTED
|
||
CAMGE T1,SCTINT ;HAS IT EXPIRED?
|
||
JRST SCTST3 ;NO, LOOK AT NEXT SLB
|
||
CALL TMRREJ ;YES, SEND REJECT
|
||
JRST SCTST3 ;ALLOCATION FAILURE, LEAVE TIMER RUNNING
|
||
CALLRET SCTST6 ;REJECT, STOP TIMERS AND CHECK THE NEXT ONE
|
||
|
||
;Here with a SLB in CS state. Check the outgoing timer for expiration.
|
||
|
||
SCTST5: CALL DNGTIM ;GET THE CURRENT TIME
|
||
OPSTR <SUB T1,>,SLCTM,(SL) ;FIND TIME SINCE TIMER STARTED
|
||
CAMGE T1,SCTOTT ;HAS OUTGOING TIMER EXPIRED?
|
||
JRST SCTST3 ;NO, LOOK AT NEXT SLB
|
||
MOVX T1,RSNNRO ;YES, GET 'NO RESPONSE FROM OBJECT' REASON CODE
|
||
STOR T1,SLRSN,(SL) ;STORE REASON FOR INTERESTED CALLER
|
||
NEWSTATE RJ ;TELL USER LINK IS REJECTED
|
||
SCTST6: CALL STPTMR ;STOP THE TIMERS
|
||
JRST SCTST3 ; AND CHECK THE NEXT ONE
|
||
|
||
SUBTTL SCTSEC - Once-a-second service for SCLINK
|
||
|
||
;SCTSEC - Once-a-second service for Session Control
|
||
;
|
||
; Once a second the following things are checked:
|
||
; connect timers
|
||
; slb's that can be freed
|
||
;
|
||
; Call:
|
||
; with nothing, every second
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRESCD
|
||
SCTSEC:
|
||
|
||
IFN FTOPS10 <
|
||
SEC1 ;RUN ALL OUR JUNK IN SECTION 1
|
||
>
|
||
SAVEAC <MB,MS,T5,T6,SL,SA,P1,P2>
|
||
SETOM SCTJFF ;TELL SCTULK WE NEED SECOND SERVICE
|
||
CALLRET SCTLCF ;GET INTERLOCK, CALL SCTSES
|
||
|
||
|
||
SCTSES: SKIPE SCTCTA ;ARE THERE ANY OUTSTANDING CONNECTS?
|
||
CALL SCTSTM ;SCAN FOR RUNNING CONNECT TIMERS
|
||
|
||
;We must not continue processing after getting a no-resources return
|
||
;because the procedure which gave that return put the current port
|
||
;back on the second-request queue. If we were to continue along that
|
||
;queue, we would visit that port over and over forever.
|
||
|
||
SCTSS1:!DEQUE SL,SCTJFQ,SL.JFQ,RTN ;RETURN WHEN Q EMPTY
|
||
SETZRO SLJFR,(SL) ;NO LONGER ON THE SECOND-REQ Q
|
||
TMNN SLFSL,(SL) ;SKIP IF SLB NEEDS TO BE FREED
|
||
Repeat 0,< ;See comment below and at SNDDRQ
|
||
JRST SCTSS2 ;NO, SEE IF WE NEED DRQ CHECK
|
||
>
|
||
Repeat 1,<
|
||
JRST SCTSS1 ;Should never happen, but if! just loop back
|
||
>
|
||
CALL SCTSFR ;YES, GET RID OF IT
|
||
CALLRET SCTRFJ ;LEAVE, REQUESTING SERVICE AGAIN
|
||
JRST SCTSS1 ; AND CHECK THE NEXT CHANNEL
|
||
|
||
;This code to resend DRQ is commented out since it is never used.
|
||
; See comment at SNDDRQ for more information
|
||
|
||
Repeat 0,<
|
||
|
||
SCTSS2: OPSTR <SKIPE T1,>,SLDRR,(SL) ;ARE THERE ANY DATA REQUESTS?
|
||
CALL SCTJDR ;YES, RESEND THE DATA REQUESTS
|
||
CALLRET SCTRFJ ;LEAVE, REQUESTING SERVICE AGAIN
|
||
JRST SCTSS1 ;GET NEXT SLB THAT NEEDS SERVICE
|
||
|
||
>
|
||
|
||
;Here to free an SLB that we are finished with
|
||
|
||
SCTSFR: JN SLBSY,(SL),RTN ;CAN'T FREE IT NOW, TRY LATER
|
||
CALL FRESLB ;CLEAN UP THAT ONE.
|
||
RETSKP ;SUCCESS
|
||
|
||
Repeat 0,<
|
||
|
||
;Here with a SLB that needs to have DRQs resent.
|
||
|
||
SCTJDR: TXZ T2,MBOTH ;ON THE NORMAL SUB-LINK
|
||
CALL SNDDRQ ;SEND THOSE DATA REQUESTS
|
||
RET ;CAN'T, LET CALLER HANDLE THIS
|
||
SETZRO SLDRR,(SL) ;WE SENT THE DATA REQUESTS
|
||
RETSKP ; AND RETURN
|
||
|
||
> ;End repeat 0
|
||
|
||
SUBTTL SCTRFJ - Request Second Service for a Link
|
||
|
||
;SCTRFJ - Request Second Service for a Link
|
||
;
|
||
; Call:
|
||
; SL/ The SLB for which service is requested
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH ALL TEMP ACS SMASHED
|
||
;
|
||
; Uses: T1
|
||
|
||
SCTRFJ: MOVX T1,SLJFR ;GET QUEUED-FOR-SERVICE FLAG
|
||
TDNE T1,SL.JFR(SL) ;ALREADY QUEUED?
|
||
RET ;YES, DON'T Q AGAIN
|
||
IORM T1,SL.JFR(SL) ;NO, WILL BE NOW THOUGH
|
||
ENDQUE SL,SCTJFQ,SL.JFQ,T1
|
||
RET
|
||
SUBTTL SCTL's Interlock -- Queuing Version
|
||
|
||
;SCTLCQ - Interlock routine for interrupt level callers
|
||
;
|
||
; Call:
|
||
; T1/ Address of processor to call with the interlock
|
||
; MB/ Pointer to Message Block with arguments stored
|
||
; or zero if called from SCTJIF
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH ALL TEMP ACS SMASHED
|
||
;
|
||
; Uses: T1
|
||
;
|
||
;If it could not get the interlock, it queues the message block with its
|
||
;arguments. When the interlock is given up, the queue is checked and
|
||
;if it has a message on it, it will service it.
|
||
|
||
SCTLCQ: STOR T1,MBPRC,(MB) ;SAVE THE PROCESSING PROCEDURE
|
||
|
||
D36OFF ;GET GLOBAL INTERLOCK FOR ENDQUE BELOW
|
||
AOSN SCTLOK ;TEST AND SET THE INTERLOCK
|
||
JRST SCTLQ1 ;GO PROCESS, NOW THAT WE HAVE THE LOCK
|
||
|
||
;Here when we have to queue the message and dismiss.
|
||
|
||
ENDQUE MB,SCTPRQ,MB.NXT,T1 ;QUEUE THE MESSAGE
|
||
D36ON ;TURN INTERLOCK OFF
|
||
RET
|
||
|
||
;Here to process the message now.
|
||
|
||
SCTLQ1: APRID SCTLKO ;SET THE OWNER OF THE INTERLOCK
|
||
IFN FTOPS20,<
|
||
CONSO PI,1B<DLSCHN+^D20> ;AT DTE PI LEVEL?
|
||
CSKED ;NO, ASSURE WE GET THROUGH THIS QUICKLY
|
||
>;END IFN FTOPS20 ;MUSTN'T CALL CSKED AT INTERRUPT LEVEL
|
||
D36ON ;TURN INTERLOCK OFF
|
||
LOAD T1,MBAR1,(MB) ;GET THE FIRST ARGUMENT
|
||
LOAD T2,MBAR2,(MB) ; SECOND
|
||
LOAD T3,MBAR3,(MB) ; THIRD
|
||
OPSTR <CALL @>,MBPRC,(MB) ;GET THE PROCESSOR
|
||
|
||
CALLRET SCTULK ;DO THE UNLOCK CHECKS
|
||
SUBTTL SCTL's Interlock -- Waiting Version
|
||
|
||
;SCTLCW - Interlock routine for process level callers
|
||
;
|
||
; Call:
|
||
; T1/ Address of processor to call with the interlock
|
||
; MB/ Pointer to Message Block with arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH ALL TEMP ACS SMASHED
|
||
;
|
||
; Uses: T1
|
||
;
|
||
;This version of the interlock will spin on SCTLOK until it is freed.
|
||
;This is to be called only from process level, thus it will only spin
|
||
;if another process or interrupt level user has it on another processor.
|
||
;It will not fight with any other process level users on this processor
|
||
;since only one can be active on any one processor at any one time.
|
||
;
|
||
;Note that SCTLOK must be uncached if this is a multiprocessor system.
|
||
|
||
SCTLCW:
|
||
SAVEAC <MB,SA> ;TEMPORARY UNTIL AC-TRASHING BUG FOUND.
|
||
|
||
;Even though we don't really have to store the routine address in
|
||
;the message block here, we do because its a convenient debugging tool.
|
||
|
||
STOR T1,MBPRC,(MB) ;SAVE THE PROCESSING PROCEDURE
|
||
|
||
IFN FTOPS10,<
|
||
SCTLW1: SKIPGE SCTLOK ;TEST INTERLOCK TO SEE IF WE HAVE A CHANGE
|
||
AOSE SCTLOK ;TEST AND SET THE INTERLOCK
|
||
JRST SCTLW1 ;ITS LOCKED, SPIN UNTIL ITS FREED
|
||
APRID SCTLKO ;SET THE OWNER OF THE INTERLOCK
|
||
>;END IFN FTOPS10 ; CAN ONLY BE COMPETING WITH ANOTHER
|
||
; PROCESSOR ON TOPS10
|
||
IFN FTOPS20,<
|
||
SCTLW1: CSKED ;ASSURE WE GET THROUGH THIS QUICKLY
|
||
AOSN SCTLOK ;TEST AND SET THE INTERLOCK
|
||
JRST SCTLW3 ;ITS OK, GO USE IT
|
||
ECSKED ;NO, UNDO THE CSKED ABOVE.
|
||
SKIPE INSKED ;IN USE, ARE WE AT SCHEDULAR LEVEL?
|
||
JRST SCTLW2 ;YES
|
||
MOVE T1,[MSEC1,,SCTLWB] ;No, set up scheduler test
|
||
MDISMS ;WAIT FOR COMPETING PROCESS TO FINISH
|
||
JRST SCTLW1 ;OK, LETS TRY AGAIN
|
||
|
||
;Must run in section 1 since the data structure used to keep the scheduler
|
||
; test routine is currently only 18-bits wide.
|
||
RESCD
|
||
SCTLWB: SKIPL SCTLOK ;IS SESSION CONTROL LOCK FREE YET?
|
||
JRST (T4) ;NO, SLEEP ON
|
||
JRST 1(T4) ;YES, WAKE UP FORK
|
||
XRESCD
|
||
|
||
SCTLW2: BUG.(CHK,SCTBWK,SCLINK,SOFT,<SCTNSF call from sched without lock>,,<
|
||
|
||
Cause: The DECnet entry point SCTNSF has been called from scheduler
|
||
level when the Session Control interlock was locked.
|
||
|
||
Action: All scheduler level routines which call SCTNSF should first
|
||
check SCTLOK. If SCTLOK is not -1, then the caller should
|
||
wait for the next scheduler cycle before calling SCTNSF.
|
||
Inspect the stack to find out who the offender is.
|
||
|
||
>)
|
||
RET ;LET CALLER WORRY ABOUT NO DECNET ACTION
|
||
|
||
SCTLW3:
|
||
>;END IFN FTOPS20
|
||
|
||
;Here to process the message now.
|
||
|
||
LOAD T1,MBAR1,(MB) ;GET THE FIRST ARGUMENT
|
||
LOAD T2,MBAR2,(MB) ; SECOND
|
||
LOAD T3,MBAR3,(MB) ; THIRD
|
||
OPSTR <CALL @>,MBPRC,(MB) ;GET THE PROCESSOR
|
||
|
||
CALLRET SCTULK ;DO THE UNLOCK CHECKS
|
||
SUBTTL SCTL's Interlock -- Flag Version
|
||
|
||
;SCTLCF - Interlock routine for Flagged Routines
|
||
;
|
||
; Call:
|
||
; T1/ Address of processor to call with the interlock
|
||
; SCTJFF or SCTUCF set non-zero for SCTULK
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH ALL TEMP ACS SMASHED
|
||
;
|
||
; Uses: T1
|
||
;
|
||
|
||
SCTLCF:
|
||
|
||
;We have no message block here, so we cannot store any processor
|
||
;address. Caller has set a SCTxxF flag instead.
|
||
;
|
||
;All we have to do here is call the unlocker, for it will check
|
||
;the Service flags SCTJFF and SCTUCF.
|
||
;
|
||
IFN FTOPS20,<
|
||
CONSO PI,1B<DLSCHN+^D20> ;AT DTE PI LEVEL?
|
||
CSKED ;NO, ASSURE WE GET THROUGH THIS QUICKLY
|
||
>;END IFN FTOPS20 ;MUSTN'T CALL CSKED AT INTERRUPT LEVEL
|
||
AOSE SCTLOK ;TEST AND SET THE INTERLOCK
|
||
IFN FTOPS20,<
|
||
IFNSK.
|
||
CONSO PI,1B<DLSCHN+^D20> ;NOT FREE, LEAVE NOW. AT DTE PI LEVEL?
|
||
ECSKED ;NO, UNDO CSKED FROM ABOVE.
|
||
RET ;LEAVE.
|
||
ENDIF.
|
||
>;END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
RET ;NOT FREE, LEAVE NOW
|
||
>;END IFN FTOPS10
|
||
APRID SCTLKO ;SET THE OWNER OF THE INTERLOCK
|
||
CALLRET SCTULK ;AND DO THE UNLOCK CHECKS.
|
||
SUBTTL SCTULK - SCTL's Interlock -- Unlock Checks
|
||
|
||
;SCTULK - All interlock routines call SCTULK to unlock
|
||
;
|
||
; Call:
|
||
; No args in registers
|
||
; Called with the Session Control Interlock still on
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH ALL TEMP ACS SMASHED
|
||
;
|
||
; Uses: T1
|
||
;
|
||
|
||
SCTULK: SAVEAC <MB,MS,SL> ;SAVE SOME ACS
|
||
|
||
;It is OK to have the window between SKIPE SCTJFF and SETZM SCTJFF
|
||
;since the worst that can happen is that we lose a second interrupt.
|
||
;If we are so close to the next second when we respond to the last one
|
||
;that we fall into the window, its just as well not to introduce more
|
||
;overhead by closing the window!
|
||
|
||
SCTUL1: SETZ T1, ;LOAD UP A ZERO TO TO TURN FLAG OFF
|
||
EXCH T1,SCTJFF ;NEED TO DO
|
||
SKIPE T1 ; CLOCK LEVEL STUFF?
|
||
CALL SCTSES ;YES, GIVE SECOND SERVICE
|
||
|
||
SETZ T1, ;LOAD UP A ZERO TO TO TURN FLAG OFF
|
||
EXCH T1,SCTUCF ;NEED TO DEAL WITH
|
||
SKIPE T1 ; CONGESTION RELIEF?
|
||
CALL SCIUCG ;YES, DO SO
|
||
|
||
D36OFF ;TURN OF THE INTERRUPTS
|
||
DEQUE MB,SCTPRQ,MB.NXT,SCTUL2 ;DEQUEUE MSG FROM PROCESS Q
|
||
D36ON ;UNDO THE D36OFF
|
||
|
||
LOAD T1,MBAR1,(MB) ;GET THE FIRST ARGUMENT
|
||
LOAD T2,MBAR2,(MB) ; SECOND
|
||
LOAD T3,MBAR3,(MB) ; THIRD
|
||
OPSTR <CALL @>,MBPRC,(MB) ;GET THE PROCESSOR
|
||
JRST SCTUL1 ;PROCESS THE NEXT ONE
|
||
|
||
SCTUL2: SETOM SCTLKO ;CLEAR THE INTERLOCK OWNER
|
||
SETOM SCTLOK ;TURN OFF THE INTERLOCK
|
||
D36ON ;UNDO THE D36OFF
|
||
IFN FTOPS20,<
|
||
CONSO PI,1B<DLSCHN+^D20> ;AT DTE PI LEVEL?
|
||
ECSKED ;NO, UNDO THE CSKED WE DID BEFORE
|
||
>;END IFN FTOPS20 ;MUSTN'T CALL ECSKED AT INTERRUPT LEVEL
|
||
RET ; AND RETURN
|
||
SUBTTL NSP. -- Function Dispatch Table
|
||
|
||
;Define some macros to set up the dispatch table for the NSP. UUO functions.
|
||
|
||
DEFINE INIDSP(PREFIX,LABEL,START<0>,FSTNAM<MN>),<
|
||
PREFIX''FSTNAM==START
|
||
%%%CTR==START-1
|
||
|
||
DEFINE DSP(NAME),<
|
||
%%%CTR==%%%CTR+1 ;;INCREMENT THE COUNTER
|
||
IFN <%%%CTR-PREFIX''NAME>,<
|
||
PRINTX ?Function PREFIX''NAME in SCLINK not in
|
||
PRINTX ? the same order as in SCPAR.UNV
|
||
PASS2
|
||
END>
|
||
|
||
IFIW <LABEL''NAME & 777777>> ;;ENTRY POINT FOR INDIRECT CALL
|
||
|
||
DEFINE ENDDSP(MAXNAM<MX>),<
|
||
PREFIX''MAXNAM==%%%CTR>
|
||
>
|
||
|
||
;This is the table which is used to find the entry vector to for a specific
|
||
;NSP. function. Symbols are also defined in the for .NSFxx for each of the
|
||
;function types.
|
||
|
||
NSFNT: ;START OF THE TABLE
|
||
|
||
INIDSP .NSF,NSF,0
|
||
DSP RE ;RESET ALL CHANNELS
|
||
DSP EA ;ENTER ACTIVE STATE
|
||
DSP EP ;ENTER PASSIVE STATE
|
||
DSP RI ;READ CONNECT INFORMATION
|
||
DSP AC ;ACCEPT THE CONNECT
|
||
DSP RJ ;REJECT THE CONNECT
|
||
DSP RC ;READ CONNECT CONFIRM INFORMATION
|
||
DSP SD ;SYNCHRONOUS DISCONNECT
|
||
DSP AB ;ABORT
|
||
DSP RD ;READ DISCONNECT DATA
|
||
DSP RL ;RELEASE THE CHANNEL
|
||
DSP RS ;READ THE CHANNEL STATUS
|
||
DSP IS ;SEND INTERRUPT DATA
|
||
DSP IR ;RECEIVE INTERRUPT DATA
|
||
DSP DS ;SEND NORMAL DATA
|
||
DSP DR ;RECEIVE NORMAL DATA
|
||
DSP SQ ;SET QUOTAS
|
||
DSP RQ ;READ QUOTAS
|
||
DSP JS ;SET JOB QUOTAS
|
||
DSP JR ;READ JOB QUOTAS
|
||
DSP PI ;SET PSI REASON MASK
|
||
ENDDSP
|
||
SUBTTL NSP. -- Wait Check Tables -- Definitons
|
||
|
||
;The following definitions are for the wait check tables. The tables
|
||
;are used to find out if session control should wait for a condition
|
||
;when the user has set the NS.WAI bit. Each table is indexed by
|
||
;function number and returns in T1 a value which means one of:
|
||
|
||
XP CW.ERR,0 ;GIVE THE USER A UNEXPECTED STATE ERROR
|
||
XP CW.NWA,1 ;DON'T BOTHER WAITING
|
||
XP CW.WAI,2 ;WAIT FOR SOME MORE TIME
|
||
XP CW.SAT,3 ;WAIT FOR SATISFYING COND BEFORE PROCEEDING
|
||
XP CW.DAT,4 ;WAIT FOR MORE DATA TO BE SENT
|
||
|
||
BEGSTR CF ;SEE CHKFOR, BELOW
|
||
FIELD IFI,1 ;THE SIGN BIT IS RESERVED FOR IFIW FLG
|
||
FILLER 11 ;ROOM FOR SOME FUNCTION FLAGS
|
||
FIELD CHN,1 ;SET IF A CHANNEL IS REQ'D FOR THIS FCN
|
||
HWORD TST ;LOCAL ADDRESS OF TESTER FUNCTION
|
||
ENDSTR
|
||
|
||
XP CHNREQ,1 ;CHANNEL REQUIRED FOR FUNCTION
|
||
XP NOCHAN,0 ;NO CHANNEL REQ'D
|
||
|
||
|
||
;Define some macros to set up the table.
|
||
|
||
DEFINE INITAB(START<0>),<
|
||
%%%CTR==START-1
|
||
|
||
DEFINE CHKFOR(func,reqchn,tester),<
|
||
%%%CTR==%%%CTR+1
|
||
|
||
IFN <%%%CTR-.NSF'func>,<
|
||
PRINTX ?NSP. Function .NSF'func in SCLINK not in
|
||
PRINTX ? the same order as in SCPAR.UNV
|
||
PASS2
|
||
END>
|
||
|
||
;;The following doubtful format is designed to prevent MACRO from
|
||
;;going Polish and thus encountering its bugs.
|
||
IFIW reqchn,tester ;SEE BEGSTR CF, ABOVE
|
||
>
|
||
|
||
DEFINE ENDTAB,<
|
||
PURGE CHKFOR,...TST
|
||
>>
|
||
|
||
;CHKSTA checks for one of STATES, returning successfully if in WAISTA
|
||
;and the wait bit is off.
|
||
|
||
DEFINE CHKSTA(SUCSTA,WAISTA),<[IFSTATE T2,<SUCSTA>,NOWAIT
|
||
IFNB <WAISTA>,< IFSTATE T2,<WAISTA>,WAITMORE >
|
||
JRST BLEWIT]
|
||
>
|
||
|
||
;CHKSTE checks for one of STATES, returning an error if in WAISTA
|
||
;and the wait bit is off.
|
||
|
||
DEFINE CHKSTE(SUCSTA,WAISTA),<[ IFSTATE T2,<SUCSTA>,NOWAIT
|
||
IFNB <WAISTA>,< JE SAWAI,(SA),BLEWIT
|
||
IFSTATE T2,<WAISTA>,WAITMORE >
|
||
JRST BLEWIT]
|
||
>
|
||
|
||
;CHKBIT checks for on of the .NSxxx status bits.
|
||
;CONDSTATES are conditional states, in which we will allow a data or
|
||
;interrupt read only if there is something queued now, else the state
|
||
;is illegal. We don't want the poor user who sets the wait bit to hang
|
||
;in DR or DC state forever!
|
||
|
||
DEFINE CHKBIT(BIT,STATES,CONDSTATES),<[
|
||
IFB <STATES>,<PRINTX ?No STATE(s) declared for CHKBIT macro>
|
||
IFB <CONDSTATES>,IFNSTATE T2,<STATES>,BLEWIT
|
||
IFNB <CONDSTATES>,IFNSTATE T2,<STATES,CONDSTATES>,BLEWIT
|
||
TXNE T1,NS'BIT
|
||
JRST NOWAIT
|
||
IFNB <CONDSTATES>,IFNSTATE T2,<STATES>,BLEWIT
|
||
JRST WAITMORE]
|
||
>
|
||
SUBTTL NSP. -- Wait check tables -- "Before" NSP. table
|
||
|
||
;The following is the wait table which is checked before the NSP.
|
||
;function is called. This table is indexed by function type and
|
||
;returns CW.xxx as explained above.
|
||
|
||
;*Note* The macro seems to rely on the address argument not going
|
||
; polish. As SCLINK now runs in section 6, this may happen if you
|
||
; change anything below, including moving any of the routines (for
|
||
; instance NOWAIT) to another psects. Beware!
|
||
|
||
SCTWTB:
|
||
|
||
INITAB
|
||
CHKFOR RE,NOCHAN,NOWAIT
|
||
CHKFOR EA,NOCHAN,NOWAIT
|
||
CHKFOR EP,NOCHAN,NOWAIT
|
||
IFN FTOPS10,<CHKFOR RI,CHNREQ,CHKSTE(CR,CW)> ;SUCCESS STATE,WAITMORE STATE
|
||
IFN FTOPS20,<CHKFOR RI,CHNREQ,NOWAIT>
|
||
CHKFOR AC,CHNREQ,CHKSTA(CR) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR RJ,CHNREQ,CHKSTA(CR) ;SUCCESS STATE,WAITMORE STATE
|
||
IFN FTOPS10,<CHKFOR RC,CHNREQ,CHKSTE(RN,CS)> ;ERROR IF CS STATE AND NS.WAI=0
|
||
IFN FTOPS20,<CHKFOR RC,CHNREQ,NOWAIT>
|
||
CHKFOR SD,CHNREQ,CHKSTA(RN) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR AB,CHNREQ,CHKSTA(RN) ;SUCCESS STATE,WAITMORE STATE
|
||
IFN FTOPS10,<CHKFOR RD,CHNREQ,CHKSTA(<DR,RJ>)> ;SUCCESS STATE,WAITMORE STATE
|
||
IFN FTOPS20,<CHKFOR RD,CHNREQ,NOWAIT>
|
||
CHKFOR RL,CHNREQ,NOWAIT
|
||
CHKFOR RS,CHNREQ,NOWAIT
|
||
CHKFOR IS,CHNREQ,CHKBIT(IDR,<CS,RN>)
|
||
CHKFOR IR,CHNREQ,CHKBIT(IDA,<CS,RN,DS>,<DR,DC>)
|
||
CHKFOR DS,CHNREQ,CHKBIT(NDR,<CS,RN>)
|
||
CHKFOR DR,CHNREQ,CHKBIT(NDA,<CS,RN,DS>,<DR,DC>)
|
||
CHKFOR SQ,CHNREQ,NOWAIT
|
||
CHKFOR RQ,CHNREQ,NOWAIT
|
||
CHKFOR JS,CHNREQ,NOWAIT
|
||
CHKFOR JR,CHNREQ,NOWAIT
|
||
CHKFOR PI,CHNREQ,NOWAIT
|
||
ENDTAB
|
||
SUBTTL NSP. -- Wait check tables -- "After" NSP. table
|
||
|
||
;The following is the wait table which is checked after the NSP. function
|
||
;is called. This table is indexed by function type and returns CW.xxx
|
||
|
||
;*Note* See comment at SCTWTB about changing the table
|
||
|
||
SCTWTA:
|
||
|
||
INITAB
|
||
CHKFOR RE,NOCHAN,NOWAIT
|
||
CHKFOR EA,CHNREQ,CHKSTA(RN,CS) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR EP,CHNREQ,CHKSTA(CR,CW) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR RI,CHNREQ,NOWAIT
|
||
CHKFOR AC,CHNREQ,CHKSTA(RN) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR RJ,CHNREQ,NOWAIT
|
||
CHKFOR RC,CHNREQ,CHKSTA(RN,CS) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR SD,CHNREQ,CHKSTA(DC,DS) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR AB,CHNREQ,CHKSTA(DC,DS) ;SUCCESS STATE,WAITMORE STATE
|
||
CHKFOR RD,CHNREQ,NOWAIT
|
||
CHKFOR RL,CHNREQ,NOWAIT
|
||
CHKFOR RS,CHNREQ,NOWAIT
|
||
CHKFOR IS,CHNREQ,NOWAIT
|
||
CHKFOR IR,CHNREQ,NOWAIT
|
||
CHKFOR DS,CHNREQ,WAITDAT
|
||
CHKFOR DR,CHNREQ,WAITSAT
|
||
CHKFOR SQ,CHNREQ,NOWAIT
|
||
CHKFOR RQ,CHNREQ,NOWAIT
|
||
CHKFOR JS,CHNREQ,NOWAIT
|
||
CHKFOR JR,CHNREQ,NOWAIT
|
||
CHKFOR PI,CHNREQ,NOWAIT
|
||
ENDTAB
|
||
SUBTTL NSP. -- Wait check tables -- Routines
|
||
|
||
;The following routines perform the correct action for the function. They
|
||
;are dispatched to by the "before" and "after" tables.
|
||
|
||
;Don't wait any longer.
|
||
|
||
NOWAIT: MOVX T1,CW.NWA
|
||
RET
|
||
|
||
;Error (possibly expected) occured.
|
||
|
||
BLEWIT: MOVX T1,CW.ERR
|
||
RET
|
||
|
||
;Wait some more.
|
||
|
||
WAITMO: MOVX T1,CW.WAI
|
||
RET
|
||
|
||
;Loop to do it again.
|
||
|
||
WAITSAT:
|
||
MOVX T1,CW.SAT
|
||
RET
|
||
|
||
;Wait if we are to get more data.
|
||
|
||
WAITDAT:
|
||
MOVX T1,CW.DAT
|
||
RET
|
||
SUBTTL NSP. -- SCTNSF - The Entry to SCLINK from SCMUUO
|
||
|
||
;SCTNSF - Perform a NSP. UUO function
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to Message Block in SA format (See BEGSTR SA in D36PAR)
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH SJERR CONTAINING A ZERO FOR SUC.
|
||
; ; AND A NON-ZERO ERROR CODE FOR FAILURES
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;We return the updated user arguments in the SJB (or error code on a
|
||
;failure).
|
||
;
|
||
;Note: It is assumed that SCJSYS, or whatever equivalent, has range
|
||
;and privilege checked all of the user arguments. The arguments are
|
||
;all in either the SAB portion of the message block or in internal
|
||
;blocks pointed to by the SAB (SACBP and SASBP).
|
||
|
||
XRENT SCTNSF
|
||
|
||
SAVEAC <MB,MS,SL,SA,T5,T6,P1,P2> ;SAVE ALMOST ALL ACS
|
||
SKIPG SA,T1 ;DID HE SUPPLY A MESSAGE BLOCK?
|
||
SCERR %NEABE,SCTNIE,<No argument block>
|
||
SETZRO SAERR,(SA) ;INITIALIZE THE ERROR LOCATION
|
||
|
||
LOAD T1,SAAFN,(SA) ;GET THE FUNCTION
|
||
CAIL T1,.NSFMN ;RANGE CHECK
|
||
CAILE T1,.NSFMX ; THE FUNCTION CODE
|
||
SCERR %NEILF,SCTNIE,<Illegal function>
|
||
;...
|
||
;...
|
||
|
||
;The code on this page and the following page is a series of coroutines. The
|
||
;Session Control interlock will only interlock a whole routine (to reduce the
|
||
;possibility of interlock screwups). The routines on this page call
|
||
;coroutines on the following page (only) via the Session Control interlock.
|
||
|
||
;We start on this page, not owning the Session Control interlock. The first
|
||
;interlocked coroutine called is SCTNIS (Setup). SCTNIS will do what it can,
|
||
;then, when it needs to do something outstide of the Session Control
|
||
;interlock, it will put the address of one of the labels on this page into
|
||
;MBPRC,(SA) and then RET. The RET takes us back to SCTULK (Session Control
|
||
;unlock) where we process any Session Control requests which may have been
|
||
;queued. Then control returns to this page after the original coroutine call.
|
||
;Each of the coroutines on this page has OPSTR <CALLRET @>,MBPRC,(SA) after
|
||
;its call the the Session Control interlock.
|
||
|
||
;Control leaves this page either via a coroutine call to an interlocked
|
||
;routine on the next page or by a RET to SCTNSF's caller.
|
||
|
||
MOVE MB,SA ;INTERLOCK ROUTINE NEEDS MB SET UP
|
||
XMOVEI T1,SCTNIS ;INTERLOCKED SETUP ROUTINE
|
||
CALL SCTLCW ;CALL INTERLOCKED SETUP ROUTINE
|
||
OPSTR <CALLRET @>,MBPRC,(SA) ;CALL COROUTINE CHOSEN BY SCTNIS
|
||
|
||
;Here to HIBER without the interlock before calling the BEFORE-function
|
||
;coroutine (again).
|
||
|
||
SCTNS1: LOAD T1,SASJB,(SA) ;PASS PTR TO SJB IN T1 TO @SAHBA(SA)
|
||
LOAD T2,SAACH,(SA) ;PASS CHANNEL # IN T2
|
||
MOVE T3,SA ;PASS SAB ADDR IN T3 (SIGH)
|
||
OPSTR <CALL @>,SAHBA,(SA) ;CALL THE HIBER'ER
|
||
MOVE MB,SA ;MB MUST BE SET UP FOR INTERLOCK
|
||
XMOVEI T1,SCTNIB ;CALL THE "BEFORE" INTERLOCKED PROCESS
|
||
CALL SCTLCW ; AFTER WE GET THE INTERLOCK
|
||
OPSTR <CALLRET @>,MBPRC,(SA) ;CALL COROUTINE CHOSEN BY SCTNIB
|
||
|
||
;Here to HIBER without the interlock before calling the AFTER-function
|
||
;coroutine (again).
|
||
|
||
SCTNS2: LOAD T1,SASJB,(SA) ;PASS PTR TO SJB IN T1 TO @SAHBA(SA)
|
||
LOAD T2,SAACH,(SA) ;PASS CHANNEL # IN T2
|
||
MOVE T3,SA ;PASS SAB ADDR IN T3 (SIGH)
|
||
OPSTR <CALL @>,SAHBA,(SA) ;CALL THE HIBER'ER
|
||
MOVE MB,SA ;MB MUST BE SET UP FOR INTERLOCK
|
||
XMOVEI T1,SCTNIA ;CALL THE "AFTER" INTERLOCKED PROCESS
|
||
CALL SCTLCW ; AFTER WE GET THE INTERLOCK
|
||
OPSTR <CALLRET @>,MBPRC,(SA) ;CALL COROUTINE CHOSEN BY SCTNIA
|
||
|
||
;Here to give up the interlock and call the system schedular to give others
|
||
;a chance between segments of a long message.
|
||
|
||
SCTNS3:
|
||
IFN FTOPS10,<
|
||
MCALL (RG,MSEC1,INTLVL##) ;ARE WE AT UUO LEVEL?
|
||
MCALL (RG,MSEC1,SCDCHK##) ;YES, LET OTHER USERS HAVE A CHANCE
|
||
>; END IFN FTOPS10
|
||
MOVE MB,SA ;MB MUST BE SET UP FOR INTERLOCK
|
||
XMOVEI T1,SCTNIB ;CALL THE "BEFORE" PROCESS AGAIN
|
||
CALL SCTLCW ; AFTER WE GET THE INTERLOCK
|
||
OPSTR <CALLRET @>,MBPRC,(SA) ;CALL COROUTINE CHOSEN BY SCTNIB
|
||
;All of these routines have the interlock. These routines may only go
|
||
;back to non-interlocked code by the return address in MBPRC.
|
||
|
||
;Setup the SLB.
|
||
|
||
SCTNIS: LOAD T1,SAAFN,(SA) ;GET THE FUNCTION CODE
|
||
SETO SL, ;ASSUME WE HAVE NO SLB (-1 IS 'UNASSIGNED')
|
||
JE CFCHN,+SCTWTB(T1),SCNIS1 ;IF NO CHANNEL IS REQ'D,
|
||
; LEAVE SL AS 'UNASSIGNED' (-1)
|
||
LOAD T1,SAACH,(SA) ;GET THE CHANNEL NUMBER
|
||
LOAD T2,SASJB,(SA) ;POINT TO THE JOB BLOCK
|
||
CALL FNDSLB ;FIND THE CORRESPONDING SLB
|
||
SCERR %NEBCN,SCTNIE,<Bad Channel Number>
|
||
SETONE SLBSY,(SL) ;NO ONE MAY FREE THIS SLB
|
||
LOAD T1,SLUID,(SL) ;GET THE SLB'S SERIAL NUMBER
|
||
STOR T1,SAUID,(SA) ; AND STASH IT IN THE SAB
|
||
SCNIS1: STOR SL,SASLB,(SA) ;STORE THE SLB POINTER
|
||
JRST SCNIB1 ;WE ALREADY HAVE THE INTERLOCK
|
||
|
||
;Do the BEFORE-function state checking and perform the function.
|
||
|
||
SCTNIB: LOAD SL,SASLB,(SA) ;GET POINTER TO LINK BLOCK
|
||
SCNIB1: JUMPL SL,[SETZB T1,T2 ;NO STATUS IF NO SLB (EA & EP FUNCTS)
|
||
JRST SCNIB3] ;GO SEE IF WE CAN MAKE ONE
|
||
LOAD T1,SLUID,(SL) ;IS THIS SLB POINTER
|
||
OPSTR <CAMN T1,>,SAUID,(SA) ; STALE ?
|
||
JRST SCNIB2 ;NO. CONTINUE
|
||
SETO SL, ;YES. LOSE THIS POINTER.
|
||
SCERR %NEBCN,SCTNIE,<Bad Channel Number> ;FAIL.
|
||
SCNIB2: LOAD T1,SLSST,(SL) ;GET CURRENT LINK STATUS
|
||
LOAD T2,NSSTA,+T1 ;PUT JUST THE STATE IN T2
|
||
SCNIB3: LOAD T3,SAAFN,(SA) ;GET THE FUNCTION BACK
|
||
CALL @SCTWTB(T3) ;SEE IF WE SHOULD WAIT A WHILE
|
||
CALLRET @.+1(T1) ;BRANCH ON SCTWTB'S RETURN CODE
|
||
IFIW <SCTNIU&777777> ;CW.ERR - ERROR RETURN TO MONUSER
|
||
IFIW <SCNIB4&777777> ;CW.NWA - NO WAIT, GO DO FUNCTION
|
||
IFIW <SCNIB5&777777> ;CW.WAI - WAIT IF MONUSER SO REQUESTED
|
||
|
||
;Here to call the function processor
|
||
|
||
SCNIB4: LOAD T1,SAAFN,(SA) ;GET THE FUNCTION TYPE
|
||
CALL @NSFNT(T1) ;CALL FUNCTION PROCESSOR
|
||
JRST SCTNIE ;REPORT THE ERROR IF NEEDED
|
||
STOR SL,SASLB,(SA) ;SAVE THE POSSIBLY NEW SLB FOR AFTER CHECKING
|
||
JRST SCNIA1 ;DON'T GET INTERLOCK, WE HAVE IT
|
||
|
||
;Here when function not yet complete to see if we should wait
|
||
|
||
SCNIB5: TMNN SAWAI,(SA) ;MONUSER ASK US TO WAIT FOR FCN COMPLETION?
|
||
JRST SCTNIX ;NO, RETURN TO MONUSER NOW
|
||
XMOVEI T2,SCTNS1 ;YES, DO OUR HIBER
|
||
STOR T2,MBPRC,(SA) ;STORE COROUTINE ADDRESS
|
||
RET ;BACK TO NON-INTERLOCKED CODE
|
||
;Here to do the AFTER-function checking.
|
||
|
||
SCTNIA: LOAD SL,SASLB,(SA) ;GET POINTER TO LINK BLOCK
|
||
SCNIA1: JUMPL SL,SCTNX1 ;IF WE DON'T HAVE A SLB, JUST LEAVE
|
||
|
||
;Note that none of the NSFxx routines call CHKSTS when they change
|
||
;a status other than the link state, because they assume that we will
|
||
;call CHKSTS from here.
|
||
|
||
CALL CHKSTS ;UPDATE SLB'S LINK STATUS WORD
|
||
LOAD T1,SLSST,(SL) ;GET CURRENT LINK STATUS
|
||
LOAD T2,NSSTA,+T1 ;PUT JUST THE STATE IN T2
|
||
LOAD T3,SAAFN,(SA) ;GET THE FUNCTION CODE BACK
|
||
CALL @SCTWTA(T3) ;SEE IF WE SHOULD WAIT A WHILE
|
||
CALLRET @.+1(T1) ;BRANCH ON ANSWER FROM SCTWTA
|
||
IFIW <SCTNIU&777777> ;CW.ERR - ERROR RETURN REQUIRED
|
||
IFIW <SCTNIX&777777> ;CW.NWA - FCN COMPLETE, RETURN TO MONUSER
|
||
IFIW <SCNIA2&777777> ;CW.WAI - FCN NOT COMPLETE, WAIT
|
||
IFIW <SCNIA3&777777> ;CW.SAT - CHECK FOR I/O SATISFIED
|
||
IFIW <SCNIA4&777777> ;CW.DAT - BRIEF PAUSE BETWEEN MSG SEGMENTS
|
||
|
||
;Here if function not yet complete, see if we have to wait
|
||
|
||
SCNIA2: TMNN SAWAI,(SA) ;DID MONUSER ASK TO WAIT FOR FCN TO COMPLETE?
|
||
JRST SCTNIX ;NO, RETURN TO USER NOW
|
||
XMOVEI T1,SCTNS2 ;YES, POINT TO HIBER ROUTINE, OUT-OF-INTERLOCK
|
||
STOR T1,MBPRC,(SA) ;TELL CO-ROUTINE WHERE TO GO TO HIBER
|
||
RET ; AND RETURN TO TO HIBER
|
||
|
||
;Here to see if .NSFDR function is complete, wait if so requested
|
||
|
||
SCNIA3: TMNN SAWAI,(SA) ;MONUSER WANT US TO WAIT FOR I/O COMPLETE?
|
||
JRST SCTNIX ;NO, RETURN TO MONUSER NOW
|
||
TMNN SASAT,(SA) ;YES, IS THE I/O SATISFIED YET?
|
||
JRST SCNIB2 ;NO, GO BACK AND TRY AGAIN
|
||
JRST SCTNIX ;YES, RETURN TO MONUSER NOW
|
||
|
||
;Here to free the Session Control interlock briefly between message segments
|
||
;so that we don't keep the lock too long when sending long messages.
|
||
|
||
SCNIA4: TMNE SASAT,(SA) ;I/O SATISFIED YET?
|
||
JRST SCTNIX ;YES, RETURN TO CALLER NOW
|
||
LOAD T1,SLSST,(SL) ;NO, CAN WE SEND ANOTHER SEGMENT
|
||
TXNE T1,NSNDR ; NOW? (ONLY NORMAL DATA CAN HAVE MULT SEGS)
|
||
JRST SCNIA5 ;YES
|
||
TMNN SAWAI,(SA) ;NO, USER WANT TO BLOCK?
|
||
JRST SCTNIX ;NO, RETURN TO USER NOW
|
||
JRST SCNIB2 ;YES, GET BEFORE PROCESSOR TO BLOCK
|
||
|
||
SCNIA5: XMOVEI T1,SCTNS3 ;RELEASE INTERLOCK A BIT
|
||
STOR T1,MBPRC,(SA) ; THEN DO THE NEXT SEGMENT
|
||
RET ;RETURN FROM THE SCTL INTERLOCK
|
||
|
||
;Here to exit with the normal return.
|
||
|
||
SCTNIX: SETZRO SAAST,(SA) ;START WITH NO STATUS SO THAT A RESET
|
||
; FUNCTION WILL RETURN A ZERO AS STATUS
|
||
JUMPL SL,SCTNX1 ;IF WE DON'T HAVE AN SLB, PUNT
|
||
LOAD T1,SLSST,(SL) ;GET CURRENT LINK STATUS
|
||
STOR T1,SAAST,(SA) ;STORE STATUS FOR USER AS WE LEAVE
|
||
SETZRO SLBSY,(SL) ;WE'RE DONE WITH SLB NOW, IF NEED BE
|
||
; IT MAY BE FREED
|
||
SCTNX1: XMOVEI T1,RTN ;JUST RETURN WHEN DONE
|
||
STOR T1,MBPRC,(SA) ;STORE THAT AS THE PROCEDURE
|
||
RET ;RETURN TO OTHER CO-ROUTINE
|
||
;Here to report the Unexpected State errors. We will give the error
|
||
;based upon the state that was unexpected.
|
||
|
||
SCTNIU: CALL CHKSTS ;UPDATE SLB'S LINK STATUS WORD
|
||
LOAD T1,SLSST,(SL) ;GET CURRENT LINK STATUS
|
||
LOAD T2,NSSTA,+T1 ;GET THE STATE
|
||
IFSTATE T2,<DR,RJ>,SCTNIR ;IF WE'RE IN DR OR RJ GIVE REASON ERROR
|
||
; MESSAGE
|
||
ADJBP T2,ERRSBP ;INDEX INTO UNEXPECTED STATE CODE TABLE
|
||
LDB T1,T2 ;GET THE VALUE OF THE ERROR MESSAGE
|
||
JUMPE T1,SCTNUE ;JUMP IF UNEXPECTED STATE
|
||
CALLRET SCTNIE ;REPORT THE ERROR TO USER
|
||
|
||
SCTNUE: SCERR %NEUXS,SCTNIE,<Unexpected State: Unspecified>
|
||
|
||
|
||
;Here to give the error codes which correspond to the REASON
|
||
;codes given by NSP.
|
||
|
||
SCTNIR: LOAD T3,SLRSN,(SL) ;GET THE REASON CODE NSP GAVE US
|
||
JUMPE T3,SCTNR1 ;IF REASON IS ZERO, WE HAVE TO FIGURE
|
||
;OUT ERROR BASED ON STATE
|
||
CAILE T3,RSNLEN ;IS THE REASON VALUE REASONABLE?
|
||
JRST SCTNR2 ;NO, CALL IT UNSPECIFIED
|
||
MOVE T1,ERRRBP ;GET THE REASON ERROR TABLE BYTE POINTER
|
||
ADJBP T3,T1 ;INDEX TO THE CORRECT MESSAGE
|
||
LDB T1,T3 ;GET THE VALUE OF THE ERROR MESSAGE
|
||
JUMPE T1,SCTNR2 ;IF TABLE SAYS ZERO, IT UNSPECIFIED
|
||
CALLRET SCTNIE ;RETURN THE FAILURE TO THE USER
|
||
|
||
SCTNR1: IFSTATE T2,RJ
|
||
SCERR %NERBO,SCTNIE,<Rejected by Object>
|
||
IFSTATE T2,DR
|
||
SCERR %NEDBO,SCTNIE,<Disconnected by Object>
|
||
SCTNR2: SCERR %NEREJ,SCTNIE,<Unspecified Reject Reason>
|
||
|
||
|
||
;Here with an error code in T1.
|
||
|
||
SCTNIE: SKIPN T1 ;IS THERE AN ERROR CODE?
|
||
BUG.(CHK,SCLNZE,SCLINK,SOFT,<Passing zero error code to SCMUUO>,,<
|
||
|
||
Cause: The routine that is supposed to store an error code
|
||
for the user is zero. This is an illegal value.
|
||
|
||
Action: Find who called SCTNIE with T1/ 0 and correct the caller's behavior.
|
||
|
||
>)
|
||
STOR T1,SAERR,(SA) ;STORE THE ERROR TYPE
|
||
SKIPLE SL ;DON'T UPDATE STATUS IF WE HAVE NO SLB
|
||
CALL CHKSTS ;UPDATE SLB'S LINK STATUS WORD
|
||
CALLRET SCTNIX ;FREE THE MESSAGE
|
||
;The following is the table (indexed by SC state) which contains the
|
||
;error code to give (i.e., %NSUDR = Unexpected State: Disconnect
|
||
;Received).
|
||
|
||
ERRSTB: BYTE(6) %NEUXS, %NEUCW, %NEUCR, %NEUCS, %NEURJ, %NEURN
|
||
BYTE(6) %NEUDS, %NEUDC, %NEUCF, %NEULK, %NEUCM, %NEUNR
|
||
|
||
ERRSBP: POINT 6,ERRSTB ;BYTE POINTER TO ERROR MESSAGES
|
||
|
||
|
||
;This table is indexed by reason code, with each cell corresponding to
|
||
;the correct error message to give for that reason. A zero in the
|
||
;table means "return the Unspecified Reject Reason error code".
|
||
;This should only happen when someone gives us a reason that we
|
||
;never heard of.
|
||
|
||
ERRRSB: BYTE(6) %NERES, %NEUNN, %NERNS, %NEURO, %NEIOF, %NEOTB
|
||
BYTE(6) 0, %NEABM, %NEABO, %NEINF, %NELNS, 0
|
||
BYTE(6) 0, 0, 0, 0, 0, 0
|
||
BYTE(6) 0, 0, 0, 0, 0, 0
|
||
BYTE(6) 0, 0, 0, 0, 0, 0
|
||
BYTE(6) 0, 0, 0, %NEACR, 0, 0
|
||
BYTE(6) 0, %NERNO, %NENUR, 0, %NENLK, %NEDSC
|
||
BYTE(6) %NEIMG
|
||
|
||
RSNLEN==<.-ERRRSB>*6
|
||
|
||
ERRRBP: POINT 6,ERRRSB ;BYTE POINTER TO REASON ERROR MESSAGES
|
||
SUBTTL NSP. -- NSFRE - REset all links
|
||
|
||
;NSFRE - REset all links
|
||
;
|
||
; Call:
|
||
; SA/ Pointer to Session Control Argument Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;This function is only done by the system when the user does a RESET
|
||
;UUO. There are no arguments.
|
||
|
||
NSFRE: SAVEAC SL ;PRESERVE SL FOR SCTNI*
|
||
LOAD T1,SASJB,(SA) ;GET POINTER TO SJB
|
||
LOAD P1,SJCHT,(T1) ;GET THE POINTER TO SLB TABLE
|
||
LOAD P2,SJCHC,(T1) ;GET THE COUNT OF LINKS
|
||
|
||
NSFRE1: SKIPN SL,(P1) ;IS THERE ANYTHING THERE?
|
||
JRST NSFRE2 ;NO, TRY NEXT LINK
|
||
SETZRO SLBSY,(SL) ;THIS LINK IS NO LONGER BUSY
|
||
SETZ MB, ;RESET PASSES NO MSG BLK, NO Q'D INTERLOCKS
|
||
CALL RLSLNK ;(MB)DO A RELEASE ON THIS LINK
|
||
NSFRE2: ADDI P1,1 ;POINT TO THE NEXT SLB
|
||
SOJG P2,NSFRE1 ;DO THE NEXT ONE, IF THERE ARE ANY LEFT
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL NSP. -- NSFEA - Enter Active State
|
||
|
||
;NSFEA - Enter Active State
|
||
;
|
||
; Call:
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFEA function, the function dependant arguments are:
|
||
;
|
||
; SAACH/ Returned: zero on failure, channel # on success
|
||
; SAAA1/ Ptr to connect-block
|
||
; SAAA2/ Segment Size
|
||
; SAAA3/ Flow control mode
|
||
|
||
NSFEA: TRACE SC,<Performing Enter Active (.NSFEA)>
|
||
SETZRO SAACH,(SA) ;ASSUME WE CANNOT ASSIGN A CHANNEL
|
||
CALL MAKSLB ;MAKE A SLB
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
STOR T1,SAACH,(SA) ;STORE CHANNEL NUMBER FOR MONUSER
|
||
NEWSTATE CS ;INITIAL STATE IS CONNECT SENT
|
||
|
||
; Get the Object type and if format 0, store both the source (SLSOB)
|
||
; and destination (SLDOB) object type into the SLB.
|
||
|
||
LOAD T3,SACBP,(SA) ;GET POINTER TO CONNECT BLOCK
|
||
XMOVEI T1,CB.SRC(T3) ;GET THE POINTER TO SOURCE PDB
|
||
LOAD T2,PBFOR,(T1) ;GET THE FORMAT TYPE
|
||
CAIE T2,FRM.2 ;FORMAT TYPE WITH PPN?
|
||
IFSKP.
|
||
CALL CHKPPN ;AND VERIFY THE PPN
|
||
SCERR %NEPRV,NSFEAC,<No privs to use bad PPN>
|
||
ELSE.
|
||
IFN FRM.0,<PRINTX ?FRM.0 MUST BE EQUAL TO 0>
|
||
ANDE. T2 ;IF OBJECT TYPE, STORE THE NUMBER
|
||
LOAD T2,PBOBJ,(T1) ;GET OBJECT TYPE WE CLAIM TO BE
|
||
IFN FTOPS10,<
|
||
LOAD T3,SLSJB,(SL) ;GET POINTER TO SJB
|
||
TMNN SJPRV,(T3) ;ARE WE PRIVED
|
||
CAIL T2,^D128 ;IS OBJECT TYPE PRIVED?
|
||
TRNA ;WE ARE O.K.
|
||
SCERR %NEPRV,NSFEAC,<No privs for this object type>
|
||
> ; END FTOPS10
|
||
STOR T2,SLSOB,(SL) ;SAVE SOURCE OBJ TYPE FOR SYSDPY AND THE LIKE
|
||
ENDIF.
|
||
LOAD T3,SACBP,(SA) ;GET POINTER TO CONNECT BLOCK
|
||
XMOVEI T1,CB.DST(T3) ;GET THE POINTER TO THE DEST PDB
|
||
LOAD T2,PBFOR,(T1) ;GET THE FORMAT TYPE
|
||
CAIE T2,FRM.0 ;FORM WITH JUST AN OBJECT TYPE
|
||
IFSKP.
|
||
LOAD T2,PBOBJ,(T1) ;GET THE OBJECT TYPE FROM PDB
|
||
STOR T2,SLDOB,(SL) ;SAVE DEST OBJ TYPE FOR SYSDPY AND THE LIKE
|
||
ENDIF.
|
||
LOAD T1,SAKCB,(SA) ;GET USER'S 'KEEP CONNECT BLOCK' FLAG
|
||
STOR T1,SLKCB,(SL) ;REMEMBER IT
|
||
JUMPE T1,NSFEA3 ;JUMP IF WE'RE NOT TO KEEP CONNECT BLOCK
|
||
MOVX T1,CB.LEN ;GET 'CONNECT BLOCK LENGTH' WORDS
|
||
CALL DNGWDS ;GET NON-ZEROED WORDS
|
||
SCERR %NEALF,NSFEAC,<Allocation failure>
|
||
STOR T1,SLCBP,(SL) ;SAVE POINTER TO SLB'S NEW CB
|
||
; FRESLB WILL FREE THIS CB FROM NOW ON
|
||
MOVE T2,T1 ;DESTINATION IS NEW CB
|
||
LOAD T1,SACBP,(SA) ;SOURCE IS CONNECT BLOCK FROM SAB
|
||
MOVX T3,CB.LEN ;LENGTH IS LENGTH OF A CONNECT BLOCK
|
||
CALL DNCPYW ;COPY SAB'S CB TO SLB'S CB
|
||
NSFEA3:
|
||
LOAD P1,SANAG,(SA) ;GET THE NUMBER OF ARGS USER SPECIFIED
|
||
CAIG P1,.NSAA3 ;DID USER SPECIFY THE FLOW CONTROL MODE?
|
||
JRST NSFEA4 ;NO
|
||
|
||
LOAD T1,SAAA3,(SA) ;GET THE FLOW CONTROL MODE
|
||
JUMPLE T1,NSFEA4 ;DIDN'T SPECIFY, USE THE DEFAULT
|
||
CAIL T1,NSF.C0 ;RANGE CHECK THE
|
||
CAILE T1,NSF.MX ; FLOW CONTROL MODE
|
||
SCERR %NEIFM,NSFEAC,<Illegal flow control mode>
|
||
SUBI T1,1 ;TRANSLATE FLOW CONTROL MODE INTO THE
|
||
; FCM.XX FORM THAT NSP USES
|
||
STOR T1,SLRFL,(SL) ;STORE THE FLOW CONTROL MODE
|
||
|
||
NSFEA4: SETZ T1, ;NO USER DATA NEEDED
|
||
CALL DNGMSG ;GET MESSAGE BLOCK
|
||
SCERR %NEALF,NSFEAC,<Allocation failure>
|
||
MOVE MB,T1 ;PUT MESSAGE BLOCK POINTER IN MB
|
||
|
||
MOVX T1,OA.LEN ;LENGTH OF OPEN ARGS
|
||
CALL DNGWDZ ;GET BLOCK FOR OPEN ARGS
|
||
SCERR %NEALF,NSFEAD,<Allocation failure>
|
||
;Now fill in the Open block with the arguments.
|
||
|
||
MOVE P1,T1 ;MAKE P1 POINT TO THE ARGUMENT BLOCK
|
||
STOR SL,OASCB,(P1) ;PUT ID IN OPEN ARG BLOCK
|
||
|
||
OPSTR <SKIPN T2,>,SACBP,(SA) ;GET THE CONNECT BLOCK POINTER
|
||
SCERR %NENCD,NSFEAE,<No connect block>
|
||
|
||
OPSTR <SKIPE T1,>,CBNUM,(T2) ;Get node number and check for zero
|
||
IFSKP. ;If it is zero, then its a loopback circuit
|
||
LOAD T1,CBCIR,(T2) ;Get loopback circuit ID
|
||
STOR T1,OACIR,(P1) ; and store it
|
||
LOAD T1,IBADR,+IBBLK ;Get local node number
|
||
ENDIF.
|
||
STOR T1,OANOD,(P1) ;PUT DESTINATION NODE ADDRESS IN ARG BLOCK
|
||
STOR T1,SLDNA,(SL) ; AND STORE AS DESTINATION OF THIS LINK
|
||
|
||
; LOAD T1,SLDNA,(SL)
|
||
OPSTR <SKIPN>,OACIR,(P1) ;Loopback?
|
||
IFSKP. ; -yes
|
||
MOVE T1,RTRBSZ ; Use default buffer size
|
||
SUBI T1,%SCHDR ; minus header
|
||
ELSE. ; -no,
|
||
CALL SCTGSS ; Get segment size for that destination
|
||
ENDIF.
|
||
LOAD T2,SANAG,(SA) ;Get the number of args user specified
|
||
CAIG T2,.NSAA2 ;Did the user specifiy the segment size?
|
||
IFSKP. ;Yes, use the supplied value
|
||
OPSTR <SKIPLE T2,>,SAAA2,(SA) ;Get the segment size
|
||
CAMLE T2,T1 ; is it bigger than the legal max?
|
||
IFSKP. <MOVE T1,T2> ; -no smaller, use that value
|
||
ENDIF.
|
||
STOR T1,SLSIZ,(SL) ;STORE THE SEGMENT SIZE IN SLB
|
||
|
||
LOAD T1,SLRFL,(SL) ;GET THE FLOW CONTROL MODE BACK
|
||
STOR T1,OAFLO,(P1) ;PUT IN OPEN ARG BLOCK
|
||
LOAD T2,SLGOL,(SL) ;GET THE DATA REQUEST GOAL
|
||
CAIN T1,FCM.MG ;ARE WE IN MESSAGE FLOW CONTROL?
|
||
CAIL T2,1 ;YES, IS OUR GOAL SET TO LESS THAN ONE?
|
||
TRNA ;NO, DON'T WORRY ABOUT IT
|
||
MOVEI T2,1 ;IN MSG FLOW MODE WE GOAL OF AT LEAST 1
|
||
STOR T2,SLGOL,(SL) ;REMEMBER THE GOAL WE DECIDED ON
|
||
STOR T2,OAGOL,(P1) ;TELL LLINKS ABOUT THE GOAL TOO
|
||
|
||
LOAD T1,SLSIZ,(SL) ;GET THE MAXIMUM SEGMENT SIZE
|
||
STOR T1,OASIZ,(P1) ;THAT TOO
|
||
|
||
MOVE T1,[XCDSEC,,SCTL] ;HE WANT'S OUR ENTRY VECTOR ADDRESS
|
||
STOR T1,OASCV,(P1) ;GIVE IT TO HIM
|
||
|
||
MOVE T1,P1 ;PASS ARG POINTER IN T1
|
||
MOVX T2,OA.LEN ;LENGTH OF THE OPEN ARG BLOCK
|
||
MOVX T3,NV.OPN ;FUNCTION IS OPEN A PORT
|
||
MOVE T4,MB ;POINT TO THE MESSAGE BLOCK WE ALLOCATED
|
||
CALL NSP ;ASK NSP TO OPEN A PORT
|
||
SKIPG T1 ;Did we get a port?
|
||
SCERR %NERES,NSFEAD,<Resource error>
|
||
|
||
;Now we have an open port to NSP, let's try to make it active.
|
||
|
||
STOR T1,SLPID,(SL) ;STORE THE NSPpid
|
||
|
||
MOVE T1,MB ;LET'S REUSE THE MESSAGE BLOCK
|
||
MOVEI T2,^D200 ;GET ENOUGH ROOM FOR THE CONNECT MESSAGE
|
||
CALL DNMINI ;MAKE THE MESSAGE BLOCK LIKE NEW
|
||
SCERR %NEALF,NSFEAD,<Allocation failure>
|
||
|
||
XMOVEI T1,UD.MSD(MB) ;POINT TO USER DATA PORTION OF MESSAGE
|
||
CALL DNPINI ;INITIALIZE FOR PUTTING BYTES IN MESSAGE
|
||
|
||
LOAD T1,SACBP,(SA) ;POINT TO THE CONNECT BLOCK
|
||
CALL BLDCTX ;BUILD THE CONNECT TEXT IN THE MESSAGE
|
||
SCERR %NECFE,NSFEAD,<Connect Block format error>
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid BACK AGAIN
|
||
MOVX T3,NV.ACT ;FUNCTION IS ENTER ACTIVE
|
||
MOVE T4,MB ;POINT TO MB WITH CONNECT DATA
|
||
CALL NSP ;CALL NSP TO DO THE FUNCTION
|
||
|
||
CALL STRTMR ;START THE CONNECT TIMERS
|
||
RETSKP ;GIVE A GOOD RETURN
|
||
|
||
;The following are the error returns that free up things that we have
|
||
;allocated before we got the error.
|
||
|
||
;Free an arg block, a message block and a SLB. Report "illegal function".
|
||
|
||
NSFEAE: MOVE T1,P1 ;POINT TO THE ARGUMENT BLOCK
|
||
CALL DNFWDS ; AND GO AND FREE UP THE WORDS
|
||
MOVEI T1,%NEILF ;"Illegal function"
|
||
JRST NSFEAD ;GO AND FREE MESSAGE BLOCK
|
||
|
||
;Free a message block and a SLB.
|
||
|
||
NSFEAD: SAVEAC T1 ;SAVE THE ERROR CODE
|
||
CALL FREMSG ;FREE THE MESSAGE BLOCK POINTED TO BY MB
|
||
JRST NSFEC1 ;GO AND FREE THE SLB
|
||
|
||
;Free an SLB.
|
||
|
||
NSFEAC: SAVEAC T1 ;SAVE THE ERROR CODE
|
||
NSFEC1: SETONE SLFSL,(SL) ;FREE THE SLB AFTER THE "AFTER" PROCESSING
|
||
SETZRO SAACH,(SA) ;TELL USER THERE'S NO CHANNEL OPEN
|
||
CALLRET SCTRFJ ;REQUEST SECOND SERVICE TO FREE SLB
|
||
SUBTTL NSP. -- NSFEP - Enter Passive State
|
||
|
||
;NSFEP - Enter Passive State
|
||
;
|
||
; Call:
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFEP function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to connect-block
|
||
|
||
NSFEP: TRACE SC,<Performing Enter Passive (.NSFEP)>
|
||
CALL MAKSLB ;MAKE A SLB
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
STOR T1,SAACH,(SA) ;STORE THE CHANNEL FOR USER
|
||
|
||
; Get the Object type and if format 0, store the source (SLSOB) object type
|
||
; in the SLB.
|
||
|
||
LOAD T3,SACBP,(SA) ;GET POINTER TO CONNECT BLOCK
|
||
XMOVEI T1,CB.SRC(T3) ;GET THE POINTER TO THE SOURCE PDB
|
||
LOAD T2,PBFOR,(T1) ;GET THE FORMAT TYPE
|
||
IFE. T2 ;IF FRM.0, IT HAS AN OBJECT TYPE
|
||
LOAD T2,PBOBJ,(T1) ;GET THE OBJECT TYPE FROM THE PDB
|
||
STOR T2,SLSOB,(SL) ;STORE IT IN THE SLB
|
||
ENDIF.
|
||
XMOVEI T1,CB.DST(T3) ;GET THE POINTER TO THE DEST PDB
|
||
LOAD T2,PBFOR,(T1) ;GET THE FORMAT TYPE
|
||
CAIE T2,FRM.2 ;FORMAT TYPE WITH PPN?
|
||
IFSKP.
|
||
CALL CHKPPN ;AND VERIFY THE PPN
|
||
SCERR %NEPRV,NSFEPC,<No privs to use bad PPN>
|
||
ELSE.
|
||
IFN FRM.0,<PRINTX ?FRM.0 MUST BE EQUAL TO 0>
|
||
ANDE. T2 ;IF OBJECT TYPE, STORE THE NUMBER
|
||
LOAD T3,SLSJB,(SL) ;GET POINTER TO SJB
|
||
LOAD T2,PBOBJ,(T1) ;GET OBJECT TYPE WE CLAIM TO BE
|
||
IFN FTOPS20,<
|
||
MOVE T1,CAPENB ;ARE WE PRIVED
|
||
TXNN T1,SC%WHL!SC%OPR
|
||
> ; END FTOPS20
|
||
IFN FTOPS10,<
|
||
TMNN SJPRV,(T3) ;ARE WE PRIVED
|
||
> ; END FTOPS10
|
||
CAIL T2,^D128 ;IS OBJECT TYPE PRIVED?
|
||
TRNA ;WE ARE O.K.
|
||
SCERR %NEPRV,NSFEPC,<No privs for this object type>
|
||
STOR T2,SLDOB,(SL) ;SAVE IT FOR SYSDPY AND THE LIKE
|
||
ENDIF.
|
||
|
||
;Now allocate another block for the internal connect block, so that the
|
||
;original goes back to SCLINK's caller.
|
||
|
||
NSFEP2: LOAD T1,SAKCB,(SA) ;GET USER'S 'KEEP CONNECT BLOCK' FLAG
|
||
STOR T1,SLKCB,(SL) ;REMEMBER IT
|
||
|
||
MOVX T1,CB.LEN ;LENGTH OF A INTERNAL CONNECT BLOCK
|
||
CALL DNGWDS ;GET THE WORDS
|
||
SCERR %NEALF,NSFEPC,<Allocation failure>
|
||
STOR T1,SLCBP,(SL) ;STORE THE POINTER IN THE SLB
|
||
MOVE T2,T1 ;SET IT UP IN T2 ALSO FOR DNCPYW
|
||
|
||
LOAD T1,SACBP,(SA) ;POINT TO THE CONNECT BLOCK
|
||
MOVX T3,CB.LEN ;LENGTH OF THE CONNECT BLOCK
|
||
CALL DNCPYW ;COPY THE WHOLE THING
|
||
|
||
NEWSTATE CW ;NEW STATE IS CONNECT WAIT
|
||
SETONE SLPAS,(SL) ;Flag that this link is passive
|
||
RETSKP ;RETURN WITH SUCCESS
|
||
|
||
;Here to free up the SLB after an error occured.
|
||
|
||
NSFEPC: SAVEAC T1 ;SAVE THE ERROR CODE
|
||
SETONE SLFSL,(SL) ;SAY THAT WE SHOULD FREE THE SLB
|
||
CALLRET SCTRFJ ;REQUEST SECOND SERVICE TO FREE SLB
|
||
SUBTTL NSP. -- NSFRI - Read Connect Information
|
||
|
||
;NSFRI - Read Connect Information
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRI function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to connect-block
|
||
; .NSAA2/ Maximum segment size
|
||
; .NSAA3/ Flow control mode
|
||
;
|
||
;This function can be called in any state. If we were asked to keep the
|
||
;connect in the Enter Active or Enter Passive, then .NSFRI will be able to
|
||
;return the connect block at any time, and the user data will have been
|
||
;updated with the most recently received user data from CC or DI messages.
|
||
|
||
NSFRI: TRACE SC,<Performing Read Connect Info (.NSFRI)>
|
||
SETZRO SASBP,(SA) ;ZERO THE ARGUMENTS IN
|
||
SETZRO SAAA2,(SA) ; CASE WE CAN'T
|
||
SETZRO SAAA3,(SA) ; GET THE RIGHT ANSWER
|
||
;CDMCBP WILL BUILD A CONNECT BLOCK IF NEEDED
|
||
CALL CDMCBP ;COPY ANY MESSAGE DATA TO CONNECT BLOCK
|
||
RET ;PROPOGATE ERROR RETURN, CODE IN T1
|
||
TMNN SLCBP,(SL) ;ANY DIS/CONNECT DATA TO READ?
|
||
SCERR %NENCD,RTN,<No dis/connect data to read>
|
||
|
||
|
||
JE SLKCB,(SL),NSFRI1 ;USER WANT US TO KEEP CONNECT BLOCK
|
||
|
||
;Here if we are to keep connect block, copy it for user
|
||
|
||
MOVX T1,CB.LEN ;YES, LENGTH OF AN INTERNAL CONNECT BLOCK
|
||
CALL DNGWDS ;GET NON-ZEROED WORDS
|
||
SCERR %NEALF,RTN,<Allocation Failure>
|
||
STOR T1,SACBP,(SA) ;STORE THE POINTER FOR SCJSYS
|
||
MOVE T2,T1 ;SET UP DEST POINTER FOR DNCPYW
|
||
LOAD T1,SLCBP,(SL) ;GET THE INTERNAL CB POINTED TO IN THE SLB
|
||
MOVX T3,CB.LEN ;COUNT OF WORDS TO COPY
|
||
CALL DNCPYW ;COPY CONNECT BLOCK FOR USER
|
||
JRST NSFRI2 ;CONTINUE
|
||
|
||
;Here if we are not to keep the connect block, just hand it over
|
||
|
||
NSFRI1: LOAD T1,SLCBP,(SL) ;GET THE INTERNAL CB POINTED TO IN THE SLB
|
||
SETZRO SLCBP,(SL) ;SCLINK NO LONGER OWNS THE CONNECT BLOCK
|
||
SKIPN T1 ;DO WE STILL HAVE A CONNECT BLOCK?
|
||
SCERR %NEWRS,RTN,<Function called in wrong state>
|
||
STOR T1,SACBP,(SA) ;STORE THE POINTER FOR SCMUUO
|
||
|
||
NSFRI2: LOAD P1,SANAG,(SA) ;GET THE NUMBER OF ARGUMENTS
|
||
CAIG P1,.NSAA2 ;DID HE WANT SOME OTHER ARGUMENTS?
|
||
RETSKP ;NO, JUST RETURN
|
||
|
||
LOAD T1,SLSIZ,(SL) ;YES, GET IT FROM THE SLB
|
||
STOR T1,SAAA2,(SA) ;STORE REASON CODE,,SEGMENT SIZE
|
||
|
||
CAIG P1,.NSAA3 ;HOW ABOUT THE FLOW CONTROL OPTION?
|
||
RETSKP ;NO, JUST RETURN
|
||
|
||
CALL RETFLW ;GET THE RFL,,XFL IN T1
|
||
STOR T1,SAAA3,(SA) ; AND STORE IT IN THE ARG BLOCK
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL NSP. -- NSFAC - Accept the Connect
|
||
|
||
;NSFAC - Accept the Connect
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFAC function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to user-data (which is the DATA-CTL optional response)
|
||
; .NSAA2/ Maximum segment size
|
||
; .NSAA3/ Flow control mode
|
||
|
||
NSFAC: TRACE SC,<Performing Accept Connect (.NSFAC)>
|
||
|
||
CALL STPTMR ;STOP THE CONNECT INITIATE TIMER AND FIX COUNTS
|
||
|
||
LOAD P1,SANAG,(SA) ;GET THE NUMBER OF ARGS USER SPECIFIED
|
||
CAIG P1,.NSAA2 ;DID THE USER SPECIFIY THE SEGMENT SIZE?
|
||
JRST NSFAC1 ;NO
|
||
|
||
LOAD T2,SLSIZ,(SL) ;Get the segment size that we and remote
|
||
; decided upon.
|
||
OPSTR <SKIPLE T1,>,SAAA2,(SA) ;Get the segment size user wants
|
||
CAML T1,T2 ;User's smaller?
|
||
IFSKP. <STOR T1,SLSIZ,(SL)> ; -yes, use the user's value
|
||
|
||
CAIG P1,.NSAA3 ;DID USER SPECIFY THE FLOW CONTROL MODE?
|
||
JRST NSFAC1 ;NO
|
||
|
||
LOAD T1,SAAA3,(SA) ;GET THE FLOW CONTROL MODE
|
||
JUMPLE T1,NSFAC1 ;DIDN'T SPECIFY IT, USE THE DEFAULT
|
||
CAIL T1,NSF.C0 ;RANGE CHECK THE FLOW
|
||
CAILE T1,NSF.MX ; CONTROL MODE
|
||
SCERR %NEIFM,RTN,<Illegal flow control mode>
|
||
SUBI T1,1 ;TRANSLATE FROM NSP.'S VERSION OF FLOW CONTROL
|
||
; VALUE TO NSP'S
|
||
STOR T1,SLRFL,(SL) ;STORE THE FLOW CONTROL MODE
|
||
;Allocate two message blocks, one for the accept arguments and one to
|
||
;send out data requests with.
|
||
|
||
NSFAC1: MOVX T1,^D20 ;GET ENOUGH ROOM FOR DATA-CTL
|
||
CALL DNGMSG ;GET A MESSAGE BLOCK
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE MB,T1 ;MAKE MB POINT TO THE MESSAGE BLOCK
|
||
|
||
SETZ T1, ;DON'T NEED ANY USER DATA FOR DRQ MB
|
||
CALL DNGMSG ;GET THE MESSAGE BLOCK
|
||
JRST [CALL FREMSG ;FREE THE MESSAGE BLOCK WE JUST ALLOCATED
|
||
SCERR %NEALF,RTN,<Allocation failure>] ; AND GIVE A FAILURE TO USER
|
||
MOVE P2,T1 ;SAVE THE POINTER TO THE DRQ MB
|
||
|
||
;Copy the user's DATA-CTL (in the user data area) from the user area to
|
||
;the message block.
|
||
|
||
XMOVEI T1,UD.MSD(MB) ;WE WANT TO WRITE DATA-CTL INTO USER DATA
|
||
CALL DNPINI ;INITIALIZE THE MSD
|
||
|
||
LOAD T1,SASBP,(SA) ;GET THE POINTER TO SBLOCK
|
||
CALL CPYS2M ;COPY THE DATA-CTL TO THE MESSAGE
|
||
|
||
;Now set up the accept argument block for NSP.
|
||
|
||
MOVX T1,AA.LEN ;LENGTH OF THE ACCEPT ARGUMENT BLOCK
|
||
CALL DNGWDZ ;GET THAT MANY WORDS
|
||
SCERR %NEALF,NSFACD,<Allocation failure>
|
||
|
||
LOAD T2,SLSLB,(SL) ;THE SCB ID FOR NEW PORT
|
||
STOR T2,AASCB,(T1)
|
||
|
||
LOAD T2,SLPID,(SL) ;NSP'S PORT IDENTIFIER
|
||
STOR T2,AAPID,(T1)
|
||
|
||
LOAD T3,SLRFL,(SL) ;RECEIVE FLOW CONTROL TYPE
|
||
STOR T3,AAFLO,(T1)
|
||
LOAD T2,SLGOL,(SL) ;GET THE DATA REQUEST GOAL
|
||
CAIN T3,FCM.MG ;ARE WE IN MESSAGE FLOW CONTROL?
|
||
CAIL T2,1 ;YES, IS OUR GOAL SET TO LESS THAN ONE?
|
||
TRNA ;NO, DON'T WORRY ABOUT IT
|
||
MOVEI T2,1 ;IN MSG FLOW MODE WE GOAL OF AT LEAST 1
|
||
STOR T2,SLGOL,(SL) ;REMEMBER THE GOAL WE DECIDED ON
|
||
STOR T2,AAGOL,(T1) ;TELL LLINKS ABOUT THE GOAL TOO
|
||
|
||
LOAD T2,SLSIZ,(SL) ;MAX BYTES ALLOWED IN A SEGMENT
|
||
STOR T2,AASIZ,(T1)
|
||
|
||
MOVE T2,[XCDSEC,,SCTL] ;OUT ENTRY VECTOR ADDRESS
|
||
STOR T2,AASCV,(T1) ; SO HE KNOWS WHERE TO CALL US
|
||
|
||
MOVX T2,AA.LEN ;LENGTH OF THE ARG BLOCK
|
||
MOVX T3,NV.ACC ;FUNCTION IS ACCEPT THE CONNECT
|
||
MOVE T4,MB ;SET UP T4 WITH MB POINTER
|
||
;T1 IS SET UP ALREADY WITH ARG BLOCK ADDRESS
|
||
CALL NSP ;PERFORM THE FUNCTION
|
||
|
||
NEWSTATE RN ;NEWSTATE IS CONNECT INITIATE
|
||
SETONE SLCCB,(SL) ;HAVE TO CHECK CONNECT BLOCK NOW
|
||
|
||
;Now let's send the job's input quota worth of DRQs.
|
||
|
||
MOVE MB,P2 ;POINT TO THE MB WE ALLOCATED BEFORE
|
||
|
||
TMNE SLPH2,(SL) ;SHOULD WE BE CONSERVATIVE WITH THIS FELLOW?
|
||
RETSKP ;YES, WE BETTER LEAVE NICELY
|
||
|
||
LOAD T1,SLINQ,(SL) ;GET THE INPUT QUOTA
|
||
STOR T1,QACNT,+T2 ; USE THAT AS THE DATA REQUEST COUNT
|
||
STOR T1,SSRDO,+SL.NSL(SL) ;WE KEEP COUNT OF OUTGOING DATA REQUESTS
|
||
|
||
TXZ T2,MBOTH ;ON THE NORMAL SUBLINK
|
||
CALL SNDDRM ;SEND THE DATA REQUESTS
|
||
SCERR %NERES,RTN,<Failed to get memory>
|
||
RETSKP ;RETURN SUCCESS
|
||
|
||
;Here on a error.
|
||
|
||
NSFACD: SAVEAC T1 ;SAVE THE ERROR CODE
|
||
CALLRET FREMSG ;FREE THE MESSAGE BLOCK POINTED TO BY MB
|
||
SUBTTL NSP. -- NSFRJ - Reject the Connect
|
||
|
||
;NSFRJ - Reject the Connect
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRJ function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to user-data (which is the DATA-CTL optional response)
|
||
; .NSAA2/ Reason code or zero to take default 'rejected by object'
|
||
|
||
NSFRJ: TRACE SC,<Performing Reject the Connect (.NSFRJ)>
|
||
|
||
CALL STPTMR ;STOP THE CONNECT INITIATE TIMER AND FIX COUNTS
|
||
|
||
MOVX T1,^D20 ;GET ENOUGH ROOM FOR DATA-CTL
|
||
CALL DNGMSG ;GET A MESSAGE BLOCK
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE MB,T1 ;MAKE MB POINT TO THE MESSAGE BLOCK
|
||
|
||
XMOVEI T1,UD.MSD(MB) ;WE WANT TO WRITE DATA-CTL INTO USER DATA
|
||
CALL DNPINI ;INITIALIZE THE MSD
|
||
|
||
;Put in the reason code (RSNRBO - Rejected by object).
|
||
|
||
LOAD T2,SANAG,(SA) ;GET NUMBER OF ARGUMENTS USER OFFERED
|
||
OPSTR <SKIPLE T1,>,SAAA2,(SA) ;USER SPECIFY A REASON?
|
||
CAIGE T2,4 ;YES, SANAG INCLUDE SAAA2?
|
||
MOVX T1,RSNRBO ;NO, REJECTED BY THE OBJECT
|
||
CALL DNP2BY ;PUT REASON IN THE MESSAGE
|
||
|
||
;Copy the user's DATA-CTL (in the user data area) from the user area to the
|
||
;message block.
|
||
|
||
LOAD T1,SASBP,(SA) ;GET THE POINTER TO SBLOCK
|
||
CALL CPYS2M ;COPY THE DATA-CTL TO THE MESSAGE
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid FOR NSP
|
||
MOVX T3,NV.REJ ;FUNCTION IS REJECT THE CONNECT
|
||
MOVE T4,MB ;SET UP T4 WITH MB POINTER
|
||
;T1 IS SET UP ALREADY WITH ARG BLOCK ADDRESS
|
||
CALL NSP ;PERFORM THE FUNCTION
|
||
|
||
;There is no need to change the state of the link here, as we are
|
||
;about to forget about the link. The user may possibly clean out
|
||
;his database about this link and then get the state change interrupt,
|
||
;confusing him.
|
||
|
||
SETONE SLFSL,(SL) ;SAY THAT WE SHOULD FREE THE SLB LATER
|
||
CALL SCTRFJ ;REQUEST SECOND SERVICE TO FREE SLB
|
||
RETSKP ;RETURN NICELY
|
||
SUBTTL NSP. -- NSFRC - Read Connect Confirm Information
|
||
|
||
;NSFRC - Read Connect Confirm Information
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRC function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to string block to receive data
|
||
; .NSAA2/ Segment size
|
||
; .NSAA3/ Flow control mode
|
||
|
||
NSFRC: TRACE SC,<Performing Read Connect Confirm Data (.NSFRC)>
|
||
SETZRO SASBP,(SA) ;ZERO THE ARGUMENTS IN
|
||
SETZRO SAAA2,(SA) ; CASE WE CAN'T
|
||
SETZRO SAAA3,(SA) ; GET THE RIGHT ANSWER
|
||
;CDMCBP WILL BUILD A CONNECT BLOCK IF NEEDED
|
||
CALL CDMCBP ;COPY ANY MESSAGE DATA TO CONNECT BLOCK
|
||
RET ;PROPOGATE ERROR RETURN, CODE IN T1
|
||
TMNN SLCBP,(SL) ;DO WE HAVE ANY CONNECT DATA
|
||
SCERR %NENCD,RTN,<No dis/connect data to read>
|
||
|
||
MOVX T1,SB.LEN ;GET SOME WORDS FOR THE DATA-CTL FIELD
|
||
CALL DNGWDS ;GET THEM FROM MEMORY MANAGER
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE P2,T1 ;POINTER TO STRING BLOCK
|
||
STOR P2,SASBP,(SA) ;PUT POINTER IN ARG BLOCK FOR SCMUUO
|
||
|
||
MOVEI T1,SB.LEN ;LENGTH OF STRING BLOCK IN WORDS
|
||
STOR T1,SBWDS,(P2) ;STORE LENGTH IN WORDS
|
||
LOAD P1,SLCBP,(SL) ;GET PTR TO CONNECT BLOCK
|
||
LOAD T3,CBCCT,(P1) ;LENGTH OF USER DATA
|
||
STOR T3,SBCNT,(P2) ;STORE IN STRING BLOCK
|
||
ADDI T3,3 ;ROUND UP
|
||
ASH T3,-2 ;CONVERT BYTES TO WORDS
|
||
XMOVEI T1,CB.UDA(P1) ;POINTER TO CONNECT BLOCK'S USER DATA
|
||
XMOVEI T2,SB.DAT(P2) ;POINTER TO STRING BLOCK'S DATA SECTION
|
||
CALL DNCPYW ;(T1,T2,T3)COPY USER DATA TO STRING BLOCK
|
||
|
||
JN SLKCB,(SL),NSFRC1 ;JUMP IF WE'RE TO KEEP CONNECT BLOCK
|
||
MOVE T1,P1 ;POINTER TO CONNECT BLOCK
|
||
CALL DNFWDS ;DEALLOCATE MSG BLK WHICH HAD CONNECT DATA
|
||
SETZRO SLCBP,(SL) ; AND REMEMBER WE'VE USED IT
|
||
|
||
NSFRC1: LOAD T1,SLSIZ,(SL) ;GET THE SEGMENT SIZE
|
||
STOR T1,SAAA2,(SA) ;STORE IT IN THE ARGUMENT WORD
|
||
|
||
CALL RETFLW ;GET THE FLOW CONTROL TYPES
|
||
STOR T1,SAAA3,(SA) ;STORE IN THE ARG WORD
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL NSP. -- NSFSD - Synchronous Disconnect
|
||
|
||
;NSFSD - Synchronous Disconnect
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFSD function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to user-data (which is the optional disconnect data)
|
||
; .NSAA2/ Reason code or zero for 'Disconnected by Object'
|
||
|
||
NSFSD: TRACE SC,<Performing Synchronous Disconnect (.NSFSD)>
|
||
TMNE SLOTM,(SL) ;IS THERE A PARTIALLY FILLED OUTPUT MESSAGE?
|
||
SCERR %NEWRS,RTN,<Function called in wrong state>
|
||
|
||
MOVX T1,^D20 ;GET ENOUGH ROOM FOR DATA-CTL
|
||
CALL DNGMSG ;GET A MESSAGE BLOCK
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE MB,T1 ;MAKE MB POINT TO THE MESSAGE BLOCK
|
||
|
||
;Copy the user's DATA-CTL (in the user data area) from the user area to the
|
||
;message block.
|
||
|
||
XMOVEI T1,UD.MSD(MB) ;WE WANT TO WRITE DATA-CTL INTO USER DATA
|
||
CALL DNPINI ;INITIALIZE THE MSD
|
||
|
||
LOAD T2,SANAG,(SA) ;GET NUMBER OF ARGUMENTS USER OFFERED
|
||
OPSTR <SKIPLE T1,>,SAAA2,(SA) ;USER SPECIFY A REASON?
|
||
CAIGE T2,4 ;YES, SANAG INCLUDE SAAA2?
|
||
MOVX T1,RSNDBO ;NO, REASON IS DISCONNECTED BY OBJECT
|
||
CALL DNP2BY ;PUT REASON (2 BYTES) IN MESSAGE
|
||
|
||
LOAD T1,SASBP,(SA) ;GET THE POINTER TO SBLOCK
|
||
CALL CPYS2M ;COPY THE DATA-CTL TO THE MESSAGE
|
||
;Now call NSP to do the disconnect.
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid FOR NSP
|
||
MOVX T3,NV.DSC ;FUNCTION IS DISCONNECT
|
||
MOVE T4,MB ;SET UP T4 WITH MB POINTER
|
||
CALL NSP ;PERFORM THE FUNCTION
|
||
|
||
NEWSTATE DS ;NEWSTATE IS DISCONNECT SENT
|
||
RETSKP ;DID OK
|
||
SUBTTL NSP. -- NSFAB - Abort and Release
|
||
|
||
;NSFAB - Abort and Release
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFAB function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to user-data (which is the optional disconnect data)
|
||
; .NSAA2/ Reason code or zero for 'Aborted by Object'
|
||
|
||
NSFAB: TRACE SC,<Performing Abort and Release (.NSFAB)>
|
||
|
||
MOVX T1,^D20 ;GET ENOUGH ROOM FOR DATA-CTL
|
||
CALL DNGMSG ;GET A MESSAGE BLOCK
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE MB,T1 ;MAKE MB POINT TO THE MESSAGE BLOCK
|
||
|
||
;Copy the user's DATA-CTL (in the user data area) from the user area to the
|
||
;message block.
|
||
|
||
XMOVEI T1,UD.MSD(MB) ;WE WANT TO WRITE DATA-CTL INTO USER DATA
|
||
CALL DNPINI ;INITIALIZE THE MSD
|
||
|
||
LOAD T2,SANAG,(SA) ;GET NUMBER OF ARGUMENTS USER OFFERED
|
||
OPSTR <SKIPLE T1,>,SAAA2,(SA) ;USER SPECIFY A REASON?
|
||
CAIGE T2,4 ;YES, SANAG INCLUDE SAAA2?
|
||
MOVX T1,RSNABO ;NO, REASON IS ABORTED BY OBJECT
|
||
CALL DNP2BY ;PUT THE TWO BYTES OF REASON CODE IN MSG
|
||
|
||
LOAD T1,SASBP,(SA) ;GET THE POINTER TO SBLOCK
|
||
CALL CPYS2M ;COPY THE DATA-CTL TO THE MESSAGE
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid FOR NSP
|
||
MOVX T3,NV.ABO ;FUNCTION IS DISCONNECT
|
||
MOVE T4,MB ;SET UP T4 WITH MB POINTER
|
||
CALL NSP ;PERFORM THE FUNCTION
|
||
|
||
NEWSTATE DS ;NEWSTATE IS DISCONNECT SENT
|
||
CALL STPTMR ;STOP THE CI TIMER IN CASE IT'S GOING
|
||
SETONE SLABO,(SL) ;WE HAVE TO CLOSE WHEN LINK IS FINISHED
|
||
RETSKP ;RETURN WITH GOODNESS
|
||
SUBTTL NSP. -- NSFRD - Read Disconnect Data
|
||
|
||
;NSFRD - Read Disconnect Data
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRD function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to Connect-Block
|
||
; .NSAA2/ The Disconnect Reason
|
||
|
||
NSFRD: TRACE SC,<Performing Read Disconnect Data (.NSFRD)>
|
||
SETZRO SASBP,(SA) ;ZERO THE ARGUMENTS IN
|
||
SETZRO SAAA2,(SA) ; CASE WE CAN'T GET THE RIGHT ANSWER
|
||
;CDMCBP WILL BUILD A CONNECT BLOCK IF NEEDED
|
||
CALL CDMCBP ;COPY ANY MESSAGE DATA TO CONNECT BLOCK
|
||
RET ;PROPOGATE ERROR RETURN, CODE IN T1
|
||
OPSTR <SKIPN P1,>,SLCBP,(SL) ;GET PTR TO DIS/CONNECT BLOCK
|
||
SCERR %NENCD,RTN,<No dis/connect data to read>
|
||
|
||
MOVX T1,SB.LEN ;GET SOME WORDS FOR THE DATA-CTL FIELD
|
||
CALL DNGWDS ;GET THEM FROM MEMORY MANAGER
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE P2,T1 ;POINTER TO STRING BLOCK
|
||
STOR P2,SASBP,(SA) ;PUT POINTER IN ARG BLOCK FOR SCMUUO
|
||
|
||
MOVEI T1,SB.LEN ;LENGTH OF STRING BLOCK IN WORDS
|
||
STOR T1,SBWDS,(P2) ;STORE LENGTH IN WORDS
|
||
LOAD T3,CBCCT,(P1) ;LENGTH OF USER DATA IN CONNECT BLOCK
|
||
STOR T3,SBCNT,(P2) ;STORE IN STRING BLOCK
|
||
ADDI T3,3 ;ROUND UP TO NEAREST WORD
|
||
ASH T3,-2 ;CONVERT BYTES TO WORDS
|
||
XMOVEI T1,CB.UDA(P1) ;POINTER TO CONNECT BLOCK'S USER DATA
|
||
XMOVEI T2,SB.DAT(P2) ;POINTER TO STRING BLOCK'S DATA SECTION
|
||
CALL DNCPYW ;(T1,T2,T3)COPY USER DATA TO STRING BLOCK
|
||
|
||
LOAD T1,SLRSN,(SL) ;GET THE DISCONNECT REASON CODE
|
||
STOR T1,SAAA2,(SA) ;RETURN THE REASON CODE
|
||
RETSKP ; AND GIVE THE GOOD RETURN
|
||
SUBTTL NSP. -- NSFRL - Release the Channel
|
||
|
||
;NSFRL - Release the Channel
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRL function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Ptr to user-data (which is the optional disconnect data)
|
||
|
||
NSFRL: TRACE SC,<Performing Release (.NSFRL)>
|
||
SETZ MB, ;WE HAVE NO MESSAGE BLOCK, NO Q'D INTERLOCKS
|
||
CALL RLSLNK ;(MB)RESET THE LINK (DO THE CLOSE)
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL NSP. -- NSFRS - Read the Channel Status
|
||
|
||
;NSFRS - Read the Channel Status
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRS function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ State
|
||
; .NSAA2/ Segment Size
|
||
; .NSAA3/ Flow control type
|
||
|
||
NSFRS: TRACE SC,<Performing Read Status (.NSFRS)>
|
||
LOAD P1,SANAG,(SA) ;GET NUMBER OF ARGUMENTS USER WANTED
|
||
|
||
CAIG P1,.NSAA1 ;DOES HE WANT TO KNOW SEGMENT SIZE?
|
||
RETSKP ;NO, JUST RETURN
|
||
|
||
LOAD T1,SLSIZ,(SL) ;GET THE MAX SEG SIZE WE'RE USING
|
||
STOR T1,SAAA1,(SA) ;STORE IT IN SAB ARGUMENT BLOCK
|
||
|
||
CAIG P1,.NSAA2 ;DOES HE WANT TO KNOW FLOW CONTROL TYPE?
|
||
RETSKP ;NO, JUST RETURN
|
||
|
||
CALL RETFLW ;RETURN THE FLOW CONTROL TYPES
|
||
STOR T1,SAAA2,(SA) ;STORE IT IN THE ARGUEMENT BLOCK
|
||
RETSKP ; AND RETURN SUCCESSFULLY
|
||
SUBTTL NSP. -- NSFIS - Send Interrupt Data
|
||
|
||
;NSFIS - Send Interrupt Data
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
; .NSAA1/ Ptr to user-data (which is the interrupt data to be sent)
|
||
|
||
NSFIS: TRACE SC,<Sending Interrupt Data (.NSFIS)>
|
||
|
||
TMNE SLCCB,(SL) ;SHOULD WE CHECK CONNECT BLOCK?
|
||
CALL FRECBP ;YES, GET RID OF CONNECT DATA IF WE CAN
|
||
|
||
NSFIS1: OPSTR <SKIPN P1,>,SASBP,(SA) ;POINT TO THE SBLOCK POINTER
|
||
SCERR %NEABE,RTN,<No Sblock supplied>
|
||
LOAD T1,SBCNT,(P1) ;GET THE COUNT OF BYTES
|
||
SKIPL T1 ;RANGE CHECK THE LENGTH
|
||
CAILE T1,^D16 ;IS IT WITHIN THE SPEC?
|
||
SCERR %NEIDL,RTN,<Interrupt data too long>
|
||
|
||
;...
|
||
;...
|
||
;Allocate the message block.
|
||
|
||
MOVX T1,^D16 ;GET 16 BYTES (MIGHT AS WELL GO ALL THE WAY
|
||
; SINCE THEY'RE IN THE MB ALREADY)
|
||
CALL DNGMSG ;GET THE MESSAGE BLOCK
|
||
SCERR %NEALF,NSFIS2,<Allocation failure>
|
||
MOVE MB,T1 ;SET UP MB
|
||
XMOVEI T1,UD.MSD(MB) ;SET UP TO PUT IN BYTES
|
||
CALL DNPINI ; IN THE USER SEGMENT
|
||
|
||
D36OFF ;INTERLOCK AGAINST SCTRIB CALL FROM LLINKS
|
||
JE SLOTU,(SL),NSFISO ;JUMP IF THIS WILL BE ONLY OUTPUT BUFFER NOW
|
||
MOVE T1,DCNRSB ;GET # NOW RESERVED
|
||
SKIPN DCNCON ;IS SYSTEM CONGESTED?
|
||
CAML T1,DCNTSB ;NO, IS THERE ROOM FOR ONE MORE?
|
||
JRST NSFISF ;NO, RETURN FAILURE
|
||
AOS T1,DCNRSB ;ONE MORE BUFFER RESERVED
|
||
CAMLE T1,DCNRHT ;NEW HIGH TIDE?
|
||
MOVEM T1,DCNRHT ;YES, RECORD IT
|
||
JRST NSFISA ;GOT ROOM, GO ALLOCATE
|
||
|
||
NSFISF: ;NO ROOM FOR THIS LOGICAL LINK
|
||
SETOM DCNCON ;CALL FOR CHKSTS WHEN CONGESTION FREES
|
||
D36ON ;END CRITICAL SECTION
|
||
AOS DCNROF ;INCREMENT OUTPUT RESERVATION FAILURES
|
||
CALL FREMSG ;RETURN THE MESSAGE BLOCK
|
||
JRST NSFIS2 ;SUCCEEDED IN SENDING ZERO BYTES (CONGESTION)
|
||
|
||
NSFISO: JN SLINU,(SL),NSFISA ;JUMP IF INPUT BUFF ALLOC, THAT RESERVES 1 OUT
|
||
MOVE T1,DCNRSB ;GET # ALREADY RESERVED
|
||
ADDI T1,2 ;WE INTEND TO RESERVE 2 MORE (1 IN + 1 OUT)
|
||
CAMLE T1,DCNTSB ;WILL THAT FIT IN TOTAL?
|
||
JRST NSFISF ;NO, RETURN FAILURE
|
||
MOVEM T1,DCNRSB ;YES, D36OFF MAKES THIS STORE OK
|
||
CAMLE T1,DCNRHT ;NEW HIGH TIDE?
|
||
MOVEM T1,DCNRHT ;YES, RECORD IT
|
||
NSFISA: INCR SLOTU,(SL) ;INCREMENT NUMBER OF OUTPUT BUFFERS IN USE
|
||
D36ON ;END OF CRITICAL SECTION
|
||
|
||
;Here to copy the bytes from the user's buffer into the message.
|
||
|
||
MOVE T1,P1 ;POINT TO THE SBLOCK
|
||
CALL CPYS2I ;(T1)COPY INTERRUPT DATA FROM STRING BLOCK
|
||
; TO MESSAGE
|
||
SETONE <MBBOM,MBEOM>,(MB) ;INTERRUPT MESSAGES ARE ONE SEGMENT
|
||
|
||
;Update counts
|
||
INCR SLPKS,(SL) ;# of 'packets' sent
|
||
LOAD T1,SBCNT,(P1) ;Get # of bytes in string block
|
||
OPSTRM <ADDM T1,>,SLBYS,(SL) ; and update count in SLB
|
||
|
||
;Now send the message to NSP.
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid
|
||
SETZ T2, ;T2 HAS THE DA STRUCTURE
|
||
SETONE MBOTH,(MB) ;SEND ON THE OTHER SUB-LINK
|
||
MOVX T3,NV.SEG ;FUNCTION IS SEND A SEGMENT
|
||
MOVE T4,MB ;POINT TO THE MESSAGE BLOCK
|
||
CALL NSP ;SEND INTERRUPT MESSAGE
|
||
|
||
OPSTRM <SOS>,SSXDO,+SL.OSL(SL) ;DECR COUNT OF XMT DATA REQUESTS
|
||
SETZRO SBCNT,(P1) ;TELL ASYNCHRONOUS USER WE SENT THE DATA
|
||
RETSKP ; AND RETURN SUCCESSFULLY
|
||
|
||
|
||
;Here when DNGMSG or DCNRSB fails due to congestion.
|
||
|
||
NSFIS2: LOAD T1,SLSST,(SL) ;GET LINK STATUS HALF-WORD
|
||
TXZ T1,NSNDR ! NSIDR ;NEITHER TYPE OF OUTPUT IS OK NOW
|
||
STOR T1,SLSST,(SL) ;STORE BACK SO WHEN CONGESTION IS FREED
|
||
RET ; CHKSTS WILL WAKE USER
|
||
SUBTTL NSP. -- NSFIR - Receive Interrupt Data
|
||
|
||
;NSFIR - Receive Interrupt Data
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
; .NSAA1/ Ptr to interrupt data
|
||
|
||
NSFIR: TRACE SC,<Receiving Interrupt Data (.NSFIR)>
|
||
|
||
TMNE SLCCB,(SL) ;SHOULD WE CHECK CONNECT BLOCK?
|
||
CALL FRECBP ;YES, GET RID OF CONNECT DATA IF WE CAN
|
||
|
||
MOVX T1,SB.LEN ;GET SB TO STORE THE INTERRUPT DATA
|
||
CALL DNGWDZ ; FROM MEMORY MANAGER
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
STOR T1,SASBP,(SA) ;STORE THE POINTER TO STRING BLOCK
|
||
MOVX T2,SB.LEN ;LENGTH OF STRING BLOCK IN WORDS
|
||
STOR T2,SBWDS,(T1) ;STORE LENGTH IN WORDS IN STRING BLOCK
|
||
|
||
XMOVEI T1,SL.OSL(SL) ;POINT TO THE OTHER SUB-LINK'S AREA
|
||
|
||
DEQUE MB,SS.INQ(T1),MB.NXT,NSFIR2 ;TRY TO DEQUE A MESSAGE ON INPUT Q
|
||
|
||
MOVE T1,MB ;SET UP FOR DNLENG
|
||
CALL DNLENG ;FIGURE OUT LENGTH OF MESSAGE
|
||
OPSTRM <ADDM T1,>,SLBYR,(SL) ;Update count of bytes received
|
||
CAILE T1,^D16 ;IS IT TOO LONG?
|
||
CALLRET SCEIVM ;--INVALID MESSAGE EVENT
|
||
MOVE P1,T1 ;SAVE THE LENGTH
|
||
|
||
;Now copy the data into the intermediate buffer.
|
||
|
||
MOVE T1,MB ;POINT TO THE MESSAGE BLOCK
|
||
CALL DNGINI ;SET UP TO GET IT
|
||
|
||
LOAD T1,SASBP,(SA) ;POINT TO THE INTERNAL STRING BLOCK
|
||
CALL CPYI2S ;COPY INTERRUPT DATA TO INTERNAL SB
|
||
CALLRET SCEIVM ;--INVALID MESSAGE EVENT
|
||
|
||
OPSTRM <SOS T1,>,SSRDO,+SL.OSL(SL) ;DECREMENT DATA REQUEST COUNT
|
||
OPSTR <CAML T1,>,SLINQ,(SL) ;IS NEW COUNT WITHIN QUOTA?
|
||
JRST [CALL FREMSG ;NO, CAN'T SEND ANOTHER DRQ, FREE THE MB
|
||
RETSKP] ;AND RETURN TO SCMUUO
|
||
|
||
OPSTRM <AOS>,SSRDO,+SL.OSL(SL) ;WE'RE SENDING OUT ONE DATA REQUEST
|
||
TXO T2,MBOTH ;PUT IT ON THE OTHER SUB-LINK
|
||
MOVX T1,1 ;LET'S SEND OUT ONE DATA REQUEST
|
||
CALL SNDDRM ;SEND THE DATA REQUESTS
|
||
SCERR %NEALF,RTN,<Allocation Failure>
|
||
RETSKP ;RETURN SUCCESSFULLY
|
||
|
||
;Here when there was nothing on the input queue.
|
||
|
||
NSFIR2: RETSKP ;SCTNA? WILL CALL CHKSTS FOR US
|
||
SUBTTL NSP. -- NSFDS - Send Normal Data
|
||
|
||
;NSFDS - Send Normal Data
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For .NSFDS function, the function dependant arguments are:
|
||
;
|
||
; SAAA1/ Byte count
|
||
; SAAA2/ Byte pointer to data
|
||
; SAAA3/ Optional second word of byte pointer
|
||
|
||
NSFDS: TRACE SC,<Sending Normal Data (.NSFDS)>
|
||
|
||
SETZRO SASAT,(SA) ;NOT YET SATISFIED THIS REQUEST.
|
||
TMNE SLCCB,(SL) ;SHOULD WE CHECK CONNECT BLOCK?
|
||
CALL FRECBP ;YES, GET RID OF CONNECT DATA IF WE CAN
|
||
|
||
;We only check the data requests here, not the quotas as well, because
|
||
;we may have a msg blk already allocated on the output queue.
|
||
|
||
LOAD T1,SLXFL,(SL) ;GET FLOW CONTROL TYPE
|
||
TMNN SSXDO,+SL.NSL(SL) ;ARE THERE ANY DRQS LEFT?
|
||
JUMPN T1,RSKP ;NO, RETURN NICELY UNLESS NO FLOW CTL
|
||
IF1,<IFN FCM.NO,<PRINTX ?NSFDS expects FCM.NO to be zero; it isn't>>
|
||
;Fall through to next page
|
||
;Fall through from previous page
|
||
|
||
;Here we get a message block in which to put user's data and calculate
|
||
;how much of the user's data will fit.
|
||
|
||
OPSTR <SKIPGE P1,>,SAAA1,(SA) ;GET USER'S BYTE COUNT
|
||
SCERR %NEADE,RTN,<Address Error> ;DON'T ALLOW NEGATIVE COUNT
|
||
SETZ T1, ;ASSUME NO BYTES IN SAVED MESSAGE
|
||
LOAD MB,SLOTM,(SL) ;ALREADY HAVE A MESSAGE?
|
||
JUMPE MB,NSFDS0 ;JUMP IF NOT
|
||
SETZRO SLOTM,(SL) ;YES, ITS NOT THERE ANY MORE
|
||
XMOVEI T1,UD.MSD(MB) ;REINITIALIZE FOR PUTTING BYTES INTO
|
||
CALL DNPINR ; A PARTIALLY FILLED MESSAGE BLOCK
|
||
MOVE T1,MB ;SEE HOW MANY ARE BYTES ALREADY
|
||
CALL DNLENG ; IN IT BY GETTING LENGTH
|
||
ADD P1,T1 ;ADD IN BYTES ALREADY IN MESSAGE
|
||
NSFDS0: OPSTR <SUB P1,>,SLSIZ,(SL) ;SUBTRACT SEGMENT SIZE WE'RE USING
|
||
|
||
;P1 is now:
|
||
; Negative if user data fits in segment with room to spare
|
||
; Zero if user data fits in segment exactly
|
||
; Positive if user data is too big to fit in segment
|
||
;This fact is used throughout the rest of this routine.
|
||
|
||
LOAD P2,SAAA1,(SA) ;ASSUME USER'S BUFFER WILL FIT IN SEGMENT
|
||
JUMPLE P1,NSFDS1 ;WILL IT FIT?
|
||
LOAD P2,SLSIZ,(SL) ;NO, SEND ONE SEGMENT'S WORTH
|
||
SUB P2,T1 ;P2 NOW HAS NUMBER OF BYTES WE'LL COPY
|
||
NSFDS1: JUMPN MB,NSFDS2 ;JUMP IF WE JUST DEQUEUED A MESSAGE BLOCK
|
||
|
||
;Get a message block
|
||
|
||
MOVE T1,P2 ;NUMBER OF BYTES WE'LL COPY INTO FIRST SEGMENT
|
||
TMNN SAEOM,(SA) ;IS THIS SEGMENT AN END OF MESSAGE?
|
||
LOAD T1,SLSIZ,(SL) ;NO, ALLOCATE A WHOLE SEGMENT'S WORTH SINCE
|
||
; USER WILL BE SENDING MORE IN THIS SEG
|
||
CALL DNGMSG ;(T1)GET MESSAGE BLOCK
|
||
JRST NSFDS6 ;SUCCEEDED IN SENDING ZERO BYTES (CONGESTION)
|
||
MOVE MB,T1 ;SET UP MB WITH MESSAGE BLOCK POINTER
|
||
XMOVEI T1,UD.MSD(MB) ;INITIALIZE FOR PUTTING BYTES
|
||
CALL DNPINI ; IN USER DATA PART OF MESSAGE BLOCK
|
||
|
||
D36OFF ;INTERLOCK AGAINST SCTRIB CALL FROM LLINKS
|
||
JE SLOTU,(SL),NSFDSO ;JUMP IF THIS WILL BE ONLY OUTPUT BUFFER NOW
|
||
MOVE T1,DCNRSB ;GET # NOW RESERVED
|
||
SKIPN DCNCON ;IS SYSTEM CONGESTED?
|
||
CAML T1,DCNTSB ;NO, IS THERE ROOM FOR ONE MORE?
|
||
JRST NSFDSF ;NO, RETURN FAILURE
|
||
AOS T1,DCNRSB ;ONE MORE BUFFER RESERVED
|
||
CAMLE T1,DCNRHT ;NEW HIGH TIDE?
|
||
MOVEM T1,DCNRHT ;YES, RECORD IT
|
||
JRST NSFDSA ;GOT ROOM, GO ALLOCATE
|
||
|
||
NSFDSF: ;NO ROOM FOR THIS LOGICAL LINK
|
||
SETOM DCNCON ;CALL FOR CHKSTS WHEN CONGESTION FREES
|
||
D36ON ;END CRITICAL SECTION
|
||
AOS DCNROF ;INCREMENT OUTPUT RESERVATION FAILURES
|
||
CALL FREMSG ;RETURN THE MESSAGE BLOCK
|
||
JRST NSFDS6 ;SUCCEEDED IN SENDING ZERO BYTES (CONGESTION)
|
||
|
||
NSFDSO: JN SLINU,(SL),NSFDSA ;JUMP IF INPUT BUFF ALLOC, THAT RESERVES 1 OUT
|
||
MOVE T1,DCNRSB ;GET # ALREADY RESERVED
|
||
ADDI T1,2 ;WE INTEND TO RESERVE 2 MORE (1 IN + 1 OUT)
|
||
CAMLE T1,DCNTSB ;WILL THAT FIT IN TOTAL?
|
||
JRST NSFDSF ;NO, RETURN FAILURE
|
||
MOVEM T1,DCNRSB ;YES, D36OFF MAKES THIS STORE OK
|
||
CAMLE T1,DCNRHT ;NEW HIGH TIDE?
|
||
MOVEM T1,DCNRHT ;YES, RECORD IT
|
||
NSFDSA: INCR SLOTU,(SL) ;INCREMENT NUMBER OF OUTPUT BUFFERS IN USE
|
||
D36ON ;END OF CRITICAL SECTION
|
||
NSFDS2:
|
||
|
||
;Fall through to next page
|
||
;Fall through from previous page
|
||
|
||
;Message block is now ready to receive data and P2 has the count of
|
||
;data to copy into it.
|
||
|
||
MOVE T1,P2 ;PASS # OF BYTES TO COPY TO COPIER
|
||
LOAD T2,SAAA2,(SA) ;GET BYTE POINTER
|
||
LOAD T3,SAAA3,(SA) ;GET OPTIONAL SECOND WORD OF BYTE PTR
|
||
|
||
IFN FTOPS10,<
|
||
MOVE T4,[XCDSEC,,DNCU2M] ;Assume buffer in user space
|
||
TMNE SAEVA,(SA) ;IS THAT TRUE?
|
||
>
|
||
;Note: SAEVA must be set on TOPS-20 - user mode buffers are not supported
|
||
MOVE T4,[XCDSEC,,DNCB2M] ; -no, copy from monitor buffer
|
||
CALL 0(T4) ;COPY BUFFER TO THE MESSAGE BLOCK
|
||
STOR T2,SAAA2,(SA) ;STORE UPDATED BYTE POINTER
|
||
STOR T3,SAAA3,(SA) ;OPTIONAL SECOND WORD OF BYTE PTR
|
||
|
||
SUB P2,T1 ;T1 contains count of bytes we didn't copy
|
||
SKIPLE T1 ;Any bytes not sent?
|
||
MOVE P1,T1 ;Yes, remember that
|
||
MOVN T1,P2 ;GET # OF BYTES WE COPIED
|
||
OPSTRM <ADDM T1,>,SAAA1,(SA) ;FIX USER'S COUNT OF BYTES TO SEND
|
||
|
||
TMNN SAEOM,(SA) ;IS THIS END OF MESSAGE
|
||
SKIPL P1 ; OR DID WE GET A WHOLE SEGMENTS WORTH?
|
||
JRST NSFDS3 ;YES, SEND SEGMENT TO NSP
|
||
|
||
;Here to save pointer to message so that the user can add data to it
|
||
;later. Note that in this case we allocated a whole segment when we
|
||
;allocated the message block.
|
||
|
||
SETONE SASAT,(SA) ;WE HAVE SATISFIED THIS NSFDS REQUEST
|
||
STOR MB,SLOTM,(SL) ;SAVE PTR TO PARTIALLY FILLED OUTPUT MSG
|
||
RETSKP ;RETURN SUCCESSFULLY
|
||
;Send segment to NSP.
|
||
|
||
;Set the BoM and EoM flags in the message block and remember whether
|
||
;or not this segment had EoM for figuring the next segment's BoM.
|
||
|
||
NSFDS3: MOVE T1,SL.EOM(SL) ;GET "LAST SEGMENT'S EOM" WORD
|
||
MOVX T2,MBBOM ;GET MESSAGE BLOCK'S BOM FLAG
|
||
TXOE T1,SLEOM ;LAST SEGMENT HAVE EOM? (ASSUME THIS WILL)
|
||
IORM T2,MB.BOM(MB) ;YES, THIS MUST BE FIRST SEGMENT OF NEXT MSG
|
||
JUMPG P1,NSFDS4 ;NEVER EOM IF WE'RE SEGMENTING
|
||
MOVX T2,MBEOM ;GET MESSAGE BLOCK'S EOM FLAG
|
||
TMNN SAEOM,(SA) ;IS THIS EOM?
|
||
NSFDS4: TXZA T1,SLEOM ;NO, REMEMBER THAT FOR NEXT SEGMENT
|
||
IORM T2,MB.EOM(MB) ;YES, MARK MESSAGE BLOCK WITH EOM
|
||
MOVEM T1,SL.EOM(SL) ;REMEMBER STATE OF EOM FLAG FOR NEXT TIME
|
||
|
||
;Update counts
|
||
INCR SLPKS,(SL) ;# of 'packets' sent
|
||
XMOVEI T1,UD.MSD(MB) ;Point to user MSD
|
||
CALL DNSLNG ;Get # of bytes in it
|
||
OPSTRM <ADDM T1,>,SLBYS,(SL) ; and update bytes sent
|
||
|
||
;Send the message
|
||
|
||
LOAD T1,SLPID,(SL) ;GET NSPpid
|
||
SETZ T2, ;DAOTH IS ZERO
|
||
MOVX T3,NV.SEG ;FUNCTION IS SEND A SEGMENT
|
||
MOVE T4,MB ;POINT TO MESSAGE BLOCK
|
||
CALL NSP ;DO SEND
|
||
|
||
;Determine whether or not to claim that we have satisfied the request
|
||
|
||
MOVX T1,SASAT ;PICK UP SASAT FLAG
|
||
SKIPG P1 ;MORE DATA TO SEND FOR THIS REQUEST?
|
||
IORM T1,SA.SAT(SA) ;NO, WE'VE SATISFIED THE REQUEST
|
||
|
||
;Update DRQs.
|
||
|
||
LOAD T1,SLXFL,(SL) ;GET FLOW CONTROL TYPE WE ARE USING
|
||
CAIN T1,FCM.SG ;IS IT SEGMENT?
|
||
JRST NSFDS5 ;YES, DECREMENT DATA REQUEST COUNT
|
||
|
||
SKIPG P1 ;DO WE HAVE ANY MORE SEGMENTS TO SEND LATER?
|
||
CAIE T1,FCM.MG ;NO, SAEOM MUST BE SET IF WE'RE HERE
|
||
RETSKP ;MORE SEGS TO GO OR NO FLOW CONTROL
|
||
|
||
NSFDS5: OPSTRM <SOS>,SSXDO,+SL.NSL(SL) ;DECR COUNT OF XMT DATA REQUESTS
|
||
RETSKP ; AND RETURN SUCCESS
|
||
|
||
|
||
;Here when DNGMSG fails due to congestion. We have not yet changed
|
||
;SAAA1, so the user will see that we succeeded in sending zero bytes.
|
||
|
||
NSFDS6: LOAD T1,SLSST,(SL) ;GET LINK STATUS HALF-WORD
|
||
TXZ T1,NSNDR ! NSIDR ;NEITHER TYPE OF OUTPUT IS OK NOW
|
||
STOR T1,SLSST,(SL) ;STORE BACK SO WHEN CONGESTION IS FREED
|
||
RETSKP ; CHKSTS WILL WAKE USER
|
||
SUBTTL NSP. -- NSFDR - Receive Normal Data
|
||
|
||
;NSFDR - Receive Normal Data
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING THE ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFDR function, the function dependant arguments are:
|
||
;
|
||
; SAAA1/ Byte count
|
||
; SAAA2/ Byte pointer
|
||
; SAAA3/ Optional second word of byte pointer
|
||
|
||
NSFDR: TRACE SC,<Receiving Normal Data (.NSFDR)>
|
||
|
||
SETZRO SASAT,(SA) ;NOT YET SATISFIED THIS REQUEST.
|
||
TMNE SLCCB,(SL) ;SHOULD WE CHECK CONNECT BLOCK?
|
||
CALL FRECBP ;YES, GET RID OF CONNECT DATA IF WE CAN
|
||
|
||
LOAD T1,SAFLG,(SA) ;GET THE FLAGS
|
||
TXNN T1,SA%WAI ;IS WAIT OFF
|
||
TXNN T1,SA%EOM ; AND EOM ON?
|
||
TRNA ;NO, NO DEADLY EMBRACE PROBLEM
|
||
SCERR %NEBCF,RTN,<Bad Combination of NS.xxx Flags>
|
||
|
||
XMOVEI P2,SL.NSL(SL) ;POINT TO NORMAL SUBLINK AREA
|
||
|
||
NSFDR1: LOAD MB,QHBEG,+SS.INQ(P2) ;GET THE FIRST THING ON THE INPUT QUEUE
|
||
JUMPE MB,RSKP ;THERE'S NOTHING THERE,
|
||
; SCTNI? WILL CALL CHKSTS
|
||
;Here with MB/ The Input Message
|
||
; P2/ SL.NSL(SL)
|
||
|
||
;The SASAT flag is set when a read is satisfied, that is, when we have
|
||
;read a message segment containing an End of Message flag. SASAT is
|
||
;used to tell whether to wake a user who has requested NS.WAIt. SASAT
|
||
;is for internal use only: it has no meaning to the user. We cannot use
|
||
;SAEOM for this purpose because SAEOM has meaning when passed from the
|
||
;user to us: if it is set, then we must put the next message in one
|
||
;buffer, possibly truncating data, if SAEOM is cleared by the user, we
|
||
;must keep the overflow and present it to the next read. Also, we
|
||
;consider a read satisfied if the user's buffer is filled and the
|
||
;user has not asserted SAEOM.
|
||
|
||
MOVE T1,MB ;SET UP FOR CALL TO DNLENG
|
||
CALL DNLENG ;GET THE LENGTH OF THE MESSAGE
|
||
MOVE P1,T1 ;P1 HAS LENGTH OF USER'S DATA IN MSG
|
||
|
||
MOVE T1,MB ;GET READY TO READ REST OF BYTES
|
||
CALL DNGINI ; IN THE MESSAGE
|
||
|
||
;Note that the following code does not depend on SASAT being initialized
|
||
|
||
MOVE T4,SA.FLG(SA) ;GET USER'S FLAGS BEFORE THEY'RE MODIFIED
|
||
LOAD T5,MBEOM,(MB) ;GET EOM FLAG FROM MSG BLK, T5 USED BELOW
|
||
STOR T5,SASAT,(SA) ;READ IS SATISFIED IF THIS IS EOM
|
||
; IOR IF BUFFER IS FULL, SEE BELOW
|
||
LOAD T1,SAAA1,(SA) ;GET THE LENGTH OF THE USER'S BUFFER
|
||
;
|
||
; SPR 10-34926
|
||
; If there's a negative count here, it should be because we're discarding
|
||
; DECnet messages for the user until we see EOM in an incoming message.
|
||
; This happens if the user sets the EOM bit in his arg block, but
|
||
; the incoming message is too big to fit in his buffer, and it doesn't
|
||
; have EOM set itself. We should discard bytes until we see an EOM.
|
||
; SCMUUO already checked to make sure that the user didn't give us a
|
||
; negative count to begin with.
|
||
;
|
||
SUB T1,P1 ;WILL THIS MESSAGE FIT?
|
||
JUMPE T1,NSFDR2 ;MSG FITS IN USER BUFFER EXACTLY
|
||
JUMPG T1,NSFDR3 ;MSG FITS IN USER BUFFER WITH ROOM TO SPARE
|
||
|
||
;Here if message overfills user buffer
|
||
LOAD P1,SAAA1,(SA) ;COPY ONLY WHAT FITS IN USER BUFFER
|
||
SETZ T5, ;BUFFERFUL HAS NO EOM, SINCE IT OVERFLOWED
|
||
TXNN T4,SAEOM ;USER WANT WHOLE MSG IN 1 READ?
|
||
SETZB P2,T1 ;NO, LEAVE MSG BLK FOR NEXT READ, COUNT := 0
|
||
;YES, TOSS REST OF MSG, P2 STILL PTS TO NSL
|
||
;Here if message fills or overfills user buffer
|
||
NSFDR2: MOVX T2,SASAT ;SATISFACTION FLAG
|
||
TXNN T4,SAEOM ;USER WANT WHOLE MSG IN 1 READ?
|
||
IORM T2,SA.SAT(SA) ;NO, READ IS SATISFIED SINCE BUFFER IS FULL
|
||
; WHETHER OR NOT MBEOM IS TRUE
|
||
;Here for all messages, note that count is negative if we toss overflow
|
||
|
||
NSFDR3: TXNN T4,SAEOM ;USER WANT WHOLE MSG IN 1 READ?
|
||
STOR T5,SAEOM,(SA) ;NO, STORE EOM FLAG WE'VE CALC'D HERE
|
||
|
||
STOR T1,SAAA1,(SA) ;STORE # BYTES REMAINING IN USER BFR
|
||
|
||
;We now have: P1/ Length of data to copy
|
||
; P2/ Pointer to NSL if we're to free msg blk, else 0
|
||
|
||
JUMPLE P1,NSFDRA ;IF COUNT IS NEGATIVE, DON'T COPY ANYTHING
|
||
|
||
;Update byte count in SLB
|
||
OPSTRM <ADDM P1,>,SLBYR,(SL) ;# of bytes received
|
||
|
||
;Copy the message data into the user's buffer.
|
||
|
||
MOVE T1,P1 ;NUMBER OF BYTES TO COPY FROM MSG TO USER
|
||
LOAD T2,SAAA2,(SA) ;GET THE BYTE POINTER
|
||
LOAD T3,SAAA3,(SA) ; AND OPTIONAL SECOND WORD OF BPTR
|
||
IFN FTOPS10,<
|
||
MOVE T4,[XCDSEC,,DNCM2U] ;ASSUME BUFFER IN USER SPACE
|
||
TMNE SAEVA,(SA) ;IS THAT TRUE?
|
||
>
|
||
;Note: SAEVA must be set on TOPS-20 - buffer can never be in user space
|
||
MOVE T4,[XCDSEC,,DNCM2B] ;No, copy to monitor buffer
|
||
CALL 0(T4) ;COPY MESSAGE BLOCK TO BUFFER
|
||
CALLRET SCEIVM ;--INVALID MESSAGE EVENT
|
||
STOR T2,SAAA2,(SA) ;STORE THE UPDATED BYTE POINTER
|
||
STOR T3,SAAA3,(SA) ; AND OPTIONAL SECOND WORD OF BPTR
|
||
|
||
NSFDRA: JUMPE P2,RSKP ;IF THERE'S NO PTR, WE HAVE MORE TO READ
|
||
; FROM THIS MSG, SO DON'T DEQUE MSG
|
||
; OR SEND OUT DATA REQUESTS YET
|
||
|
||
DEQUE MB,SS.INQ(P2),MB.NXT,NSFDRB ;DEQUE MSG WE WERE PEEKING AT
|
||
|
||
;Here we unreserve an appropriate number of buffers, but we don't
|
||
;reserve any again to correspond to the data requests we send, that is
|
||
;done by a call to SCTRIB from LLINKS when a message arrives.
|
||
|
||
NSFDRB: D36OFF ;PROTECT THIS CODE FROM LLINKS CALL TO SCTRIB
|
||
OPSTRM <SOS T1,>,SLINU,(SL) ;ONE LESS INPUT BUFFER USED
|
||
MOVX T2,-1 ;ASSUME WE'RE NOT FREEING LAST INPUT BUFFER
|
||
JUMPG T1,NSFDR4 ;JUMP IF THAT'S TRUE
|
||
MOVX T2,-2 ;WE ARE FREEING LAST INPUT, ASSUME NO OUTPUT
|
||
TMNE SLOTU,(SL) ;ANY OUTPUT BUFFERS RESERVED?
|
||
MOVX T2,0 ;YES, LEAVE AN INPUT BUFFER RESERVED
|
||
NSFDR4: ADDB T2,DCNRSB ;ADJUST THE RESERVED BUFFER COUNT
|
||
D36ON ;END OF CRITICAL SECTION
|
||
LOAD T1,SLINQ,(SL) ;GET THE INPUT QUOTA
|
||
OPSTRM <SOS T2,>,SSRDO,+SL.NSL(SL) ;ONE LESS REC DATA REQUEST
|
||
SUB T1,T2 ;HOW MANY REQUESTS SHOULD WE SEND NOW?
|
||
JUMPL T1,[CALL FREMSG ;IF WE DON'T HAVE ENOUGH QUOTA, CAN'T SEND
|
||
; ANOTHER DRQ, SO FREE MESSAGE BLOCK
|
||
RETSKP] ;AND RETURN TO MONITOR USER
|
||
OPSTRM <ADDM T1,>,SSRDO,+SL.NSL(SL) ;UPDATE RECEIVE DRQ COUNT
|
||
|
||
;Send the data requests to NSP.
|
||
|
||
TXZ T2,MBOTH ;(T1,T2)ON THE NORMAL SUB-LINK
|
||
CALL SNDDRM ;SEND DATA REQUESTS USING MESSAGE BLOCK
|
||
; WE CURRENTLY HAVE
|
||
SCERR %NEALF,RTN,<Allocation Failure>
|
||
RETSKP ;RETURN SUCCESSFULLY
|
||
|
||
SUBTTL NSP. -- NSFSQ - Set Quotas and Goals
|
||
|
||
;NSFSQ - Set Quotas and Goals
|
||
;Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6, P1 & MB
|
||
;
|
||
;For the .NSFSQ function, the function dependant arguments are:
|
||
; .NSAA1/ Link Quota, input + output
|
||
; .NSAA2/ % Input
|
||
; .NSAA3/ Input Goal
|
||
|
||
NSFSQ: TRACE SC,<Performing Set Link Quota (.NSFSQ)>
|
||
LOAD T1,SLSTA,(SL) ;GET LINK STATE
|
||
IFSTATE T1,<DC,LK,CM,CF,NR>,RSKP ;LEAVE QUIETLY IF IN TERMINAL STATE
|
||
LOAD P1,SANAG,(SA) ;GET NUMBER OF ARGUMENTS USER SUPPLIED
|
||
CAIG P1,.NSAA1 ;DID HE GIVE THE TOTAL QUOTA?
|
||
SCERR %NEWNA,RTN,<Wrong number of arguments>
|
||
|
||
LOAD T1,SLINQ,(SL) ;GET THE OLD QUOTA
|
||
OPSTR <ADD T1,>,SLOTQ,(SL) ;TOTAL OF INPUT + OUTPUT QUOTA
|
||
OPSTR <SKIPG>,SAAA1,(SA) ;USER SUPPLY A NEW QUOTA?
|
||
STOR T1,SAAA1,(SA) ;NO, STORE OLD QUOTA TOTAL AS DEFAULT
|
||
|
||
MOVEI T2,0 ;NO VALUE OFFERED YET
|
||
CAILE P1,.NSAA2 ;DID HE GIVE THE % INPUT?
|
||
LOAD T2,SAAA2,(SA) ;GET HIS VALUE
|
||
CAILE T2,^D100 ; AND 100
|
||
SCERR %NEPIO,RTN,<Percentage input out of bounds>
|
||
JUMPG T2,NSFSQ1 ;USER OFFER A VALUE?
|
||
MOVEI T2,^D50 ;NO, ASSUME HALF INPUT & HALF OUTPUT
|
||
STOR T2,SAAA2,(SA) ;REMEMBER PERCENTAGE WE DECIDED ON
|
||
NSFSQ1:
|
||
SETZB T1,MB ;DON'T NEED ANY USER DATA
|
||
CAIG P1,.NSAA3 ;USER SPECIFY AN INPUT GOAL?
|
||
IFSKP. ;Yes, apply default if necessary
|
||
LOAD T2,SASJB,(SA) ;Get pointer to SJB
|
||
LOAD T1,SJGOL,(T2) ;Get job goal for default
|
||
OPSTR <SKIPGE>,SAAA3,(SA) ;Verify supplied value
|
||
STOR T1,SAAA3,(SA) ;Apply default
|
||
|
||
CALL DNGMSG ;GET MESSAGE BLOCK IN CASE WE NEED IT
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
MOVE MB,T1 ;SAVE POINTER TO MSG BLK
|
||
ENDIF.
|
||
|
||
;No more error returns now
|
||
|
||
LOAD T1,SAAA1,(SA) ;GET THE LINK QUOTA
|
||
LOAD T2,SAAA2,(SA) ;GET PERCENTAGE VERIFIED ABOVE
|
||
IMUL T1,T2 ;MULTIPY LINK QUOTA BY % INPUT
|
||
IDIVI T1,^D100 ;DIVIDE BY 100. TO FIND INPUT QUOTA
|
||
STOR T1,SLINQ,(SL) ;STORE THE INPUT QUOTA IN THE SLB
|
||
LOAD T2,SAAA1,(SA) ;GET THE LINK QUOTA BACK
|
||
SUB T2,T1 ;SUBTRACT TO FIND THE OUTPUT QUOTA
|
||
STOR T2,SLOTQ,(SL) ;STORE THE OUTPUT QUOTA IN THE SLB
|
||
|
||
CAIG P1,.NSAA3 ;WAS THE GOAL SPECIFIED?
|
||
RETSKP ;USE DEFAULT THAT'S THERE ALREADY
|
||
;WE ONLY GOT MSG BLK IF WE HAVE A GOAL
|
||
LOAD T1,SLRFL,(SL) ;GET THE FLOW CONTROL TYPE
|
||
LOAD T2,SAAA3,(SA) ;GET THE INPUT GOAL
|
||
CAIN T1,FCM.MG ;ARE WE IN MESSAGE FLOW CONTROL?
|
||
CAIL T2,1 ;YES, IS OUR GOAL SET TO LESS THAN ONE?
|
||
TRNA ;NO, DON'T WORRY ABOUT IT
|
||
MOVEI T2,1 ;IN MSG FLOW MODE WE GOAL OF AT LEAST 1
|
||
STOR T2,SLGOL,(SL) ;REMEMBER THE GOAL WE DECIDED ON
|
||
|
||
;Notify NSP of the change in the goal.
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid
|
||
;T2 CARRIED DOWN FROM ABOVE
|
||
IFE. T1 ;IS THERE ONE ?
|
||
MOVE T1,MB ;NO. DON'T TELL NSP
|
||
CALL DNFMSG ; SINCE THERE IS NO PLACE
|
||
RETSKP ; TO PUT IT YET.
|
||
ENDIF.
|
||
MOVX T3,NV.GOL ;FUNCTION IS SET GOAL
|
||
MOVE T4,MB ;NSP TAKES MB POINTER IN T4
|
||
CALL NSP ;(T1,T2,T3,T4)PERFORM THE SET GOAL
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL NSP. -- NSFRQ - Read Quotas and Goals
|
||
|
||
;NSFRQ - Read Quotas and Goals
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFRQ function, the function dependant arguments are:
|
||
;
|
||
; .NSAA1/ Link Quota
|
||
; .NSAA2/ % Input
|
||
; .NSAA3/ Input Goal
|
||
|
||
NSFRQ: TRACE SC,<Performing Read Link Quota (.NSFRQ)>
|
||
|
||
LOAD T1,SLINQ,(SL) ;GET THE INPUT QUOTA
|
||
LOAD T2,SLOTQ,(SL) ; AND THE OUTPUT QUOTA
|
||
ADD T1,T2 ;TOTAL THEM UP
|
||
|
||
STOR T1,SAAA1,(SA) ;STORE IN ARG BLOCK WERE THE LINK QUOTA GOES
|
||
|
||
LOAD P1,SANAG,(SA) ;GET THE NUMBER OF ARGUMENTS USER SUPPLIED
|
||
CAIG P1,.NSAA2 ;DOES HE WANT THE %INPUT?
|
||
RETSKP ;NO, JUST GIVE GOOD RETURN
|
||
|
||
LOAD T2,SLINQ,(SL) ;Get the input quota
|
||
IMULI T2,^D100 ;Multiply by 100 to get % input
|
||
IDIV T2,T1 ; as an integer between 0 and 100.
|
||
STOR T2,SAAA2,(SA) ;Store it in argument block
|
||
|
||
CAIG P1,.NSAA3 ;DOES HE WANT THE INPUT GOAL?
|
||
RETSKP ;NO, JUST RETURN
|
||
|
||
LOAD T1,SLGOL,(SL) ;GET THE GOAL
|
||
STOR T1,SAAA3,(SA) ;PUT IT IN THE ARG BLOCK
|
||
RETSKP ; AND RETURN
|
||
SUBTTL NSP. -- NSFJS - Set Job Quotas and Goals
|
||
|
||
;NSFJS - Set Job Quotas and Goals
|
||
;
|
||
; Call:
|
||
; Never Happens: serviced in SCMUUO
|
||
;
|
||
; Return:
|
||
;
|
||
; Uses: Nothing
|
||
;
|
||
;This function is performed entirely by SCMUUO or equivalent.
|
||
|
||
NSFJS: SCERR %NEILF,RTN,<Illegal function - handled in SCMUUO>
|
||
|
||
SUBTTL NSP. -- NSFJR - Read Job Quotas and Goals
|
||
|
||
;NSFJR - Read Job Quotas and Goals
|
||
;
|
||
; Call:
|
||
; Never Happens: serviced in SCMUUO
|
||
;
|
||
; Return:
|
||
;
|
||
; Uses: Nothing
|
||
;
|
||
;This function is performed entirely by SCMUUO or equivalent.
|
||
|
||
NSFJR: SCERR %NEILF,RTN,<Illegal function - handled by SCMUUO>
|
||
|
||
SUBTTL NSP. -- NSFPI - Set PSI Reason Mask
|
||
|
||
;NSFPI - Set PSI Reason Mask
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
; SA/ Pointer to Session Control Arg Block with user arguments stored
|
||
;
|
||
; Return:
|
||
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
|
||
; RETSKP ;ALL IS WELL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;For the .NSFPI function, the function dependent arguments are:
|
||
;
|
||
; .NSAA1/ XWD 0,reason mask
|
||
|
||
NSFPI: TRACE SC,<Performing Set PSI Mask (.NSFPI)>
|
||
|
||
LOAD T1,SAAA1,(SA) ;GET .NSAA1 ARGUMENT
|
||
STOR T1,SLPSM,(SL) ;STORE THE PSI MASK FOR SCTPSI
|
||
|
||
TMNE <SLPSI,SLLBC,SLFSL>,(SL) ;PSI ALREADY PENDING OR LINK CLOSING?
|
||
RETSKP ;YES, AVOID RACE
|
||
|
||
;T1 HOLDS OLD STATUS (0),,NEW MASK
|
||
LOAD T2,SLCHN,(SL) ;THE LINK NUMBER
|
||
LOAD T5,SLSST,(SL) ;T5 PASSES STATUS CHANGES (CURRENT STATUS)
|
||
HRL T2,T5 ;T2 HOLDS NEW STATUS,,CHN NUMBER
|
||
LOAD T3,SLSJB,(SL) ;@SLWKA NEEDS T3 SET UP WITH PTR TO SJB
|
||
MOVE T4,SL ;'LINK IDENTIFIER' TO PASS TO SCTWKQ
|
||
OPSTR <SKIPE T6,>,SLWKA,(SL) ;IS THERE A WAKE ROUTINE?
|
||
CALL 0(T6) ;(T1,T2,T3,T4,T5)YES, CALL WAKE ROUTINE
|
||
|
||
RETSKP ;RETURN SUCCESSFULLY
|
||
SUBTTL RETFLW - Return current flow controls
|
||
|
||
;RETFLW - Return Receive Flow Mode,,Transmit Flow Control
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Line Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS, WITH T1 CONTAINING RFL,,XFL
|
||
;
|
||
; Uses: T1,T2
|
||
|
||
RETFLW: LOAD T1,SLRFL,(SL) ;GET THE RECEIVE FLOW CONTROL
|
||
LOAD T2,SLXFL,(SL) ;GET THE TRANSMIT FLOW CONTROL TYPE
|
||
ADDI T1,1 ;TRANSLATE TO USER'S VALUE
|
||
HRLI T1,1(T2) ;BUILD RFL,XFL
|
||
;TRANSLATE THAT ALSO
|
||
RET ; AND RETURN
|
||
SUBTTL SNDDRQ - Send Data Requests
|
||
|
||
;SNDDRQ - Send some data requests to NSP
|
||
;
|
||
; Call:
|
||
; T1/ Number of Data Requests to Send
|
||
; T2/ MBOTH set to the correct value
|
||
; (for SNDDRM:
|
||
; MB/ Pointer to Message Block)
|
||
;
|
||
; Return:
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;ON SUCCESS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
;The SNDDRQ code is commented out since there are no callers of it.
|
||
; All callers come in at the SNDDRM entry point
|
||
|
||
Repeat 0,<
|
||
|
||
SNDDRQ: SAVEAC <MB,P1,P2> ;GET OUR OWN COPY OF MB AND SAVE SOME PEAS
|
||
DMOVE P1,T1 ;PRESERVE THE ARGUMENTS
|
||
SETZ T1, ;DON'T NEED ANY USER DATA
|
||
CALL DNGMSG ;GET A MESSAGE BLOCK
|
||
RET ;COULDN'T ALLOCATE, JUST RETURN
|
||
MOVE MB,T1 ;POINT TO THE NEW MESSAGE BLOCK
|
||
CALLRET SNDDRX ;JOIN COMMON CODE
|
||
|
||
>
|
||
|
||
;This is the alternate entry for those guys which already have a message
|
||
;block.
|
||
|
||
SNDDRM: DMOVE P1,T1 ;SAVE THE COUNT AND MBOTH
|
||
MOVE T1,MB ;POINT TO THE MESSAGE BLOCK
|
||
MOVEI T2,0 ;NO USER DATA NEEDED
|
||
CALL DNMINI ;RE-INITIALIZE THE MESSAGE BLOCK
|
||
RET ;COULDN'T DO IT
|
||
|
||
SNDDRX: SETZ T2, ;BUILD THE DATA REQUEST ARG BLOCK (QA) IN T2
|
||
STOR P1,QACNT,+T2 ; USE THAT AS THE DATA REQUEST COUNT
|
||
|
||
MOVX T1,MBOTH ;GET THE "OTHER" SUBLINK FLAG
|
||
TXNE P2,MBOTH ;CALLER WANT IT SET IN MESSAGE BLOCK?
|
||
IORM T1,MB.OTH(MB) ;YES, IT WAS CLEARED BY DNMINI
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid FOR NSP
|
||
MOVX T3,NV.DRQ ;FUNCTION IS SEND DATA REQUESTS
|
||
MOVE T4,MB ;POINT TO MESSAGE BLOCK
|
||
CALL NSP ;CALL NSP AND RETURN EVENTUALLY
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL RLSLNK - Release a Link
|
||
|
||
;RLSLNK - Release a Link
|
||
;
|
||
; Call:
|
||
; MB/ Ptr to msg blk or zero if LLINKS will not have to queue NV.CLS call
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6,MB,MS
|
||
|
||
RLSLNK: JN <SLFSL,SLLBC>,(SL),RLSLN1 ;IGNORE IF LINK ALREADY BEING CLOSED
|
||
SKIPN EV96.0 ;Shall we log the CSSE event?
|
||
IFSKP. ; -yes, unfortunately
|
||
EVENT(LCG,CSE,Link close) ;Log "link close" event for CSSE
|
||
ENDIF.
|
||
CALL STPTMR ;STOP THE CI TIMER, IF IT'S GOING
|
||
JN SLPID,(SL),RLSLN2 ;JUMP IF WE HAVE A PID FROM NSP
|
||
SETONE SLFSL,(SL) ;WE HAVEN'T TOLD NSP ABOUT
|
||
; THIS LINK YET, DON'T CALL HIM NOW
|
||
CALL SCTRFJ ;REQUEST SECOND SERVICE, SLFSL WILL
|
||
; TELL IT TO FREE THE SLB
|
||
RLSLN1: SKIPN MB ;DID WE HAVE A MSG BLK?
|
||
RET ;NO, ONLY RETURN
|
||
CALLRET FREMSG ;YES, FREE IT AND RETURN
|
||
|
||
RLSLN2: LOAD T1,SLPID,(SL) ;GET THE NSPpid FROM SLB
|
||
LOAD T2,SLSLB,(SL) ;GET THIS PORT'S SLBid
|
||
MOVX T3,NV.CLS ;CLOSE FUNCTION FOR NSP
|
||
MOVE T4,MB ;NSP WANTS MSG BLK PTR IN T4 (ZERO IF RESET)
|
||
CALL NSP ;CALL NSP TO CLOSE THE PORT
|
||
SETONE SLLBC,(SL) ;LINK IS BEING CLOSED
|
||
RET ;ONLY RETURN
|
||
SUBTTL LLINKS Calls -- Entry Vector Table
|
||
|
||
;See procedure SCTL for a description of the calling sequence used to
|
||
;call SCTL.
|
||
|
||
;The offsets SV.xxx into this table are defined in D36PAR.
|
||
|
||
DEFINE SV(NAM),<
|
||
IFN .-SCFNT-SV.'NAM,< PRINTX ?SCFNT table (NAM) not in same order
|
||
PRINTX ? as SV.'NAM in D36PAR.UNV
|
||
PASS2
|
||
END>
|
||
IFIW <SC'NAM&777777>>
|
||
|
||
;These are the function codes for the calls to Session Control from
|
||
;NSP.
|
||
|
||
SCFNT: SV CCR ;CONNECT CONFIRMED CALL
|
||
SV DIR ;DISCONNECT INITIATE RECEIVED CALL
|
||
SV DCR ;DISCONNECT CONFIRM RECEIVED CALL
|
||
SV OND ;OUTPUT NOT DONE CALL
|
||
SV ODN ;OUTPUT DONE CALL
|
||
SV SEG ;SEGMENT RECEIVED CALL
|
||
SV DRQ ;DATA REQUEST RECEIVED CALL
|
||
SV NCF ;NO CONFIDENCE IN PORT CALL
|
||
SV NRS ;NO RESOURCES CALL
|
||
SV CLS ;CLOSE COMPLETED CALL
|
||
SV NLK ;NO LINK CALL
|
||
SV NCM ;NO COMMUNICATION CALL
|
||
SV NRN ;NOT IN RUN STATE
|
||
SV CAK ;GOT A CONNECT ACK
|
||
SV.MAX==.-SCFNT-1 ;THE HIGHEST RECOGNIZED ENTRY OFFSET
|
||
|
||
;The Connect Initiate call does not go
|
||
;through the vectored interface, since
|
||
;it must go to a single routine
|
||
;capable of sorting out which Session
|
||
;Control will handle the incoming
|
||
;message. the connect initiate call
|
||
;goes to the global label SCTLCI.
|
||
|
||
PURGE SV
|
||
SUBTTL LLINKS Calls -- SCTRIB - Reserve Input Buffer
|
||
|
||
;SCTRIB - Reserve Input Buffer
|
||
;
|
||
;Call: T1/ Pointer to SLB
|
||
; CALL SCTRIB
|
||
; Error Return: no input buffer has been reserved
|
||
; Normal Return: one input buffer has been reserved
|
||
;Changes T1,T2,T3,T4
|
||
|
||
;This routine and all others which reference DCNRSB must run under
|
||
;D36OFF because this routine is called from LLINKS without the SCLINK
|
||
;interlock. This routine is only called from LLINKS. It is here in
|
||
;SCLINK so that all references to the reserved buffer counter will be
|
||
;together in one module.
|
||
|
||
;The scheme here is that we want to count the buffers which are
|
||
;actually in use, plus those which are required to be reserved in
|
||
;order to prevent a deadlock. We must be sure that no logical link is
|
||
;put in the position of being having a allowed to read a message while
|
||
;being stuck not allowed to send a message. If both ends of a link
|
||
;were to be in that state, they would be in a deadly embrace.
|
||
;
|
||
;So whenever we want to commit a buffer for output (by sending it) or
|
||
;for input (by ACKing it), we must check first if we have room in the
|
||
;system pool to reserve it. If we reserve a buffer for one direction,
|
||
;then we must assure that at least one is reserved for the other
|
||
;direction.
|
||
;
|
||
;The handling of DCNRSB in SCLINK preserves the above guarantees.
|
||
;This routine is called from LLINKS when it receives a message and
|
||
;there are Session Control data requests for that message. If this
|
||
;routine returns failure, LLINKS will keep the message, unACKed, and
|
||
;will try to send it to Session Control again when the memory manager
|
||
;tells LLINKS that congestion has been relieved.
|
||
|
||
XRESCD
|
||
SCTRIB: OPSTR <CAME T1,>,SLSLB,(T1) ;IS THIS A LEGIT SLB POINTER?
|
||
BUG.(CHK,SCLRIB,SCLINK,SOFT,<Bad SCTRIB call from LLINKS>,<<T1,ADDR>>,<
|
||
|
||
Cause: LLINKS has called SCTRIB for permission to send a message to SCLINK
|
||
and has passed an invalid SLB address in T1. The data structures
|
||
for this logical link are inconsistent.
|
||
|
||
Action: Find out what is in LLINK's ELSCB and why its not an SLB pointer.
|
||
|
||
Data: ADDR - The bad SLB pointer
|
||
|
||
>,RTN)
|
||
D36OFF ;INTERLOCK AGAINST SCTRIB CALL FROM LLINKS
|
||
JE SLINU,(T1),SCTRB1 ;JUMP IF THIS WILL BE ONLY INPUT BUFFER NOW
|
||
MOVE T2,DCNRSB ;GET # NOW RESERVED
|
||
SKIPN DCNCON ;IS THE SYSTEM CONGESTED?
|
||
CAML T2,DCNTSB ;NO, CAN WE FIT ONE MORE?
|
||
JRST SCTRB3 ;NO ROOM FOR THIS LINK
|
||
AOS T2,DCNRSB ;ONE MORE BUFFER RESERVED
|
||
JRST SCTRB2 ;SUCCESS
|
||
|
||
SCTRB1: JN SLOTU,(T1),SCTRB4 ;JUMP IF OUTPUT BUFF ALLOC, THAT RESERVES 1 IN
|
||
MOVE T2,DCNRSB ;GET # ALREADY RESERVED
|
||
ADDI T2,2 ;WE INTEND TO RESERVE 2 MORE (1 IN + 1 OUT)
|
||
CAMLE T2,DCNTSB ;ENOUGH ROOM IN TOTAL SYSTEM BUFFERS?
|
||
JRST SCTRB3 ;NO, NO ROOM FOR THIS LINK
|
||
MOVEM T2,DCNRSB ;YES, D36OFF MAKES THIS STORE OK
|
||
SCTRB2: CAMLE T2,DCNRHT ;NEW HIGH TIDE?
|
||
MOVEM T2,DCNRHT ;YES, RECORD IT
|
||
SCTRB4: INCR SLINU,(T1) ;UPDATE INPUT_BUFFERS_IN_USE COUNT
|
||
D36ON ;END OF CRITICAL SECTION
|
||
RETSKP ;GOT ROOM, SUCCESS RETURN
|
||
|
||
SCTRB3: SETOM DCNCON ;CALL FOR CHKSTS WHEN CONGESTION FREES
|
||
D36ON ;END OF CRITICAL SECTION
|
||
AOS DCNRIF ;INCREMENT INPUT RESERVATION FAILURES
|
||
RET ;FAIL RETURN
|
||
SUBTTL LLINKS Calls -- SCTUCG - Uncongestion Call
|
||
|
||
;SCTUCG - LLINKS calls this routine when memory manager announces
|
||
; that congestion is relieved.
|
||
;
|
||
; Call:
|
||
; No arguments
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRESCD
|
||
SCTUCG: SAVEAC <MB,SL,SA,MS,P1,P2>
|
||
TRACE SC,Session Control told of congestion relief
|
||
|
||
SETOM SCTUCF ;NO MESSAGE BLOCK TO QUEUE HERE
|
||
CALLRET SCTLCF ;GET THE INTERLOCK, FLAG IF FAIL
|
||
|
||
;When NSFDS (data send) and NSFIS (interrupt send) fail to get a
|
||
;message block, they will both turn off both NSNDR (normal data
|
||
;requests available) and NSIDR (interrupt data requests available).
|
||
;Presumably this will only happen if the system is congested. Later,
|
||
;when the system congestion is relieved, we must tell the stalled
|
||
;links that we again have message blocks available. Since the NSxDR
|
||
;flags in the status half-word have been turned off, this call to
|
||
;CHKSTS will turn them back on again if appropriate and this will
|
||
;trigger CHKSTS to call the wake routine.
|
||
|
||
SCIUCG: LOAD SL,QHBEG,+SCTASQ ;PTR TO FIRST SLB ON ALL SLBs Q
|
||
SCIUC1: JUMPE SL,RTN ;RETURN WHEN NO MORE SLBs TO VISIT
|
||
CALL CHKSTS ;SEE IF THIS SLB NEEDS WAKING
|
||
LOAD SL,SLASQ,(SL) ;STEP TO NEXT SLB ON ALL SLBs Q
|
||
JRST SCIUC1 ;LOOP OVER ALL SLBs IN SYSTEM
|
||
SUBTTL LLINKS Calls -- SCTLCI - Connect Initiate Call
|
||
|
||
;SCTLCI - Connect Initiate Call
|
||
;
|
||
; Call:
|
||
; T1/ NSPpid for port just created
|
||
; T2/ Connect Call arguments (see BEGSTR IA in D36PAR)
|
||
; T4/ Pointer to Message Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRESCD
|
||
SCTLCI: SAVEAC <MB,SL,SA,MS,P1,P2>
|
||
TRACE SC,Connect Initiate call
|
||
MOVE MB,T4 ;SET UP THE MESSAGE BLOCK POINTER
|
||
STOR T1,MBAR1,(MB) ;STORE THE FIRST ARGUMENT
|
||
STOR T2,MBAR2,(MB) ; AND THE SECOND ONE
|
||
XMOVEI T1,SCTLC1 ;PROCESSOR TO CALL WHEN WE
|
||
CALLRET SCTLCQ ; GET THE INTERLOCK
|
||
|
||
;Now try to find a matching SLB for the incoming connect.
|
||
|
||
SCTLC1: TRACE SC,Processing Connect Initiate
|
||
|
||
MOVE T1,MB ;POINT TO THE INCOMING MESSAGE BLOCK
|
||
CALL DNGINI ;SET UP MS FOR DNGxBY ROUTINES
|
||
|
||
MOVX T1,CB.LEN ;WE HAVE TO GET A CONNECT BLOCK
|
||
CALL DNGWDZ ; TO FILL IN AND COMPARE WITH PASSIVE SLBS
|
||
JRST SCTCIR ;RESOURCE FAILURE
|
||
MOVE P1,T1 ;SAVE POINTER TO INCOMING CONNECT BLOCK
|
||
|
||
CALL PRSCTX ;PARSE THE INCOMING CONNECT DATA IN CB
|
||
JRST [ MOVE T1,P1 ;PTR TO NEW CONNECT BLK
|
||
CALL DNFWDS ;FREE NEW CONNECT BLK
|
||
CALLRET SCEIVM] ;--INVALID MESSAGE EVENT
|
||
|
||
MOVE T1,P1 ;GET THE INCOMING CONNECT BLOCK POINTER BACK
|
||
CALL SLBMAT ;FIND PASSIVE SLB TO MATCH NEW SLB
|
||
JRST [ EXCH T1,P1 ;Get pointer to new connect block and save
|
||
; return code
|
||
CALL DNFWDS ;Free the connect blk
|
||
JUMPN P1,SCTCIT ;Return 'object too busy'
|
||
CALLRET SCTCIN] ; otherwise unrecognized object error
|
||
;We have found matching SLB, lets set some parameters in the SLB and
|
||
;go into CR state.
|
||
|
||
LOAD T1,SLCBP,(SL) ;POINT TO PASSIVE CB
|
||
CALL DNFWDS ;FREE THAT UP
|
||
SETZRO SLCBP,(SL) ;LOSE PTR TO PASSIVE CB WE JUST FREED
|
||
|
||
LOAD T1,MBSRC,(MB) ;GET SOURCE NODE ADDRESS
|
||
STOR T1,SLDNA,(SL) ; AND STORE AS DESTINATION OF THIS LINK
|
||
STOR T1,CBNUM,(P1) ; and store in connect block
|
||
|
||
SCTLC2: STOR P1,SLCBP,(SL) ;PUT PTR TO ACTIVE CONNECT BLK IN SLB
|
||
; FOR .NSFRI FUNCTION
|
||
|
||
XMOVEI T1,CB.SRC(P1) ;Point to source PDB
|
||
LOAD T1,PBOBJ,(T1) ;Get remote object type
|
||
STOR T1,SLSOB,(SL) ; and store as source PDB in SLB
|
||
|
||
LOAD T1,MBAR1,(MB) ;GET THE NSPpid
|
||
STOR T1,SLPID,(SL) ;STORE IT IN THE SLB
|
||
|
||
LOAD T2,MBAR2,(MB) ;GET THE CONNECT CALL ARGUMENTS
|
||
LOAD T1,IAFLO,+T2 ;GET FLOW CONTROL TYPE FROM ARGUMENTS
|
||
STOR T1,SLXFL,(SL) ; AND STORE IT IN SLB
|
||
|
||
LOAD T1,SLDNA,(SL) ;Get destination address
|
||
LOAD T2,IASIZ,+T2 ;Get segment size specified by remote
|
||
CALL SCTCSS ;Check what segment size we should use
|
||
STOR T1,SLSIZ,(SL) ; and store the segment size ROUTER calculated
|
||
|
||
NEWSTATE CR ;CALL SCSSTS TO PUT US IN .NSSCR STATE
|
||
; AND WAKE THE USER
|
||
TMNE MBPH2,(MB) ;IS THIS CONNECT FROM A PHASE II GUY?
|
||
CALL CONBUF ;YES, SET UP FOR CONSERVATIVE BUFFERING
|
||
|
||
CALL STRTMR ;START CONNECT TIMERS & FIX TIMER COUNTS
|
||
CALLRET FREMSG ;DEALLOCATE CI MESSAGE, & RETURN TO NSP
|
||
;Here when we could not get enough resources to accept the Connect.
|
||
|
||
SCTCIR: MOVX P2,RSNRES ;NO RESOURCES ERROR CODE
|
||
JRST SCTCFN ;TO COMMON REJECT CODE
|
||
|
||
SCTCIT: MOVX P2,RSNOTB ;Object too busy code
|
||
JRST SCTCFN ; to common rejet code
|
||
|
||
SCTCIN: MOVX P2,RSNURO ;UNRECOGNIZED OBJECT REASON CODE
|
||
SCTCFN: TRACE SC,Rejecting Connect Initiate call
|
||
LOAD P1,MBAR1,(MB) ;SAVE THE NSPpid
|
||
MOVE T1,MB ;SET UP FOR DNMINI CALL
|
||
MOVEI T2,3 ;LENGTH OF USER DATA NEEDED
|
||
CALL DNMINI ;RE-INITIALIZE THE MESSAGE BLOCK WE'RE USING
|
||
RET ; Will never happen - but if, just return
|
||
XMOVEI T1,UD.MSD(MB) ;POINT TO THE USER MSD
|
||
CALL DNPINI ;INITIALIZE FOR PUTTING BYTES
|
||
|
||
MOVE T1,P2 ;GET REASON CODE
|
||
CALL DNP2BY ;PLACE IT IN THE MESSAGE
|
||
|
||
SETZ T1, ;NO DATA-CTL NEEDED
|
||
CALL DNP1BY ;PLACE IT IN
|
||
|
||
MOVE T1,P1 ;SET UP THE NSPpid
|
||
MOVX T3,NV.REJ ;REJECT THE CONNECT
|
||
MOVE T4,MB ;SET UP POINTER TO MESSAGE BLOCK
|
||
CALLRET NSP ;INFORM NSP OF FAILURE
|
||
SUBTTL LLINKS Calls -- The Vectored Call Entry Point SCTL
|
||
|
||
;SCTL - Here for all calls from NSP except Connect Initiate
|
||
;
|
||
; Call:
|
||
; T1/ SLBid
|
||
; T2/ Function specific argument
|
||
; T3/ Function Code (SV.xxx)
|
||
; T4/ Pointer to message block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRESCD
|
||
SCTL: SAVEAC <MB,MS,SA,SL> ;SAVE SOME ACS
|
||
MOVE MB,T4 ;SET UP MESSAGE BLOCK
|
||
STOR T1,MBAR1,(MB) ;STORE THE SLBid
|
||
STOR T2,MBAR2,(MB) ;STORE THE FUNCTION SPECIFIC ARGUMENT
|
||
STOR T3,MBAR3,(MB) ;STORE THE FUNCTION CODE
|
||
XMOVEI T1,SCTL1 ;ADDRESS OF PROCESSOR TO CALL AFTER WE
|
||
CALLRET SCTLCQ ; GET THE INTERLOCK
|
||
|
||
SCTL1: CALL FNDSBI ;FIND THE SLB FROM THE SLBid
|
||
CALLRET FREMSG ;NO SUCH SLBid, IGNORE THIS MSG
|
||
CALLRET @SCFNT(T3) ;DISPATCH BY FUNCTION TYPE
|
||
SUBTTL LLINKS Calls -- SCCCR - Connect Confirmed call from NSP
|
||
|
||
;SCCCR - Connect Confirmed call from NSP
|
||
;
|
||
; Call:
|
||
; T2/ Connect Initiate arguments (see BEGSTR IA in D36PAR)
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCCCR: TRACE SC,Connect confirmed call
|
||
SAVEAC P1 ;SAVE A PEA
|
||
MOVE P1,T2 ;SAVE ARGUMENT FROM NSP
|
||
|
||
CALL STPTMR ;STOP CI TIMER & DECREMENT TIMER COUNTS
|
||
|
||
LOAD T1,IAFLO,+P1 ;GET FLOW CONTROL TYPE
|
||
STOR T1,SLXFL,(SL) ;STORE TRANSMIT FLOW TYPE IN SLB
|
||
|
||
;We have to cater for a VMS crock here. Assuming that the buffer size
|
||
; is 576 bytes, VMS announces 561 bytes while TOPS-20 would pick 559 bytes.
|
||
; The reason is that VMS never uses the piggy-back field while we do do.
|
||
;
|
||
;Now, if we are an endnode and we try to connect to a remote node and we run
|
||
; with big buffers, we will probably suggest 1450 bytes. If the remote is
|
||
; not on the same NI and is a VAX it will return 561 bytes and we will accept
|
||
; that.... so we make a special test for if the remote buffer size is equal
|
||
; to our executor buffer size - %schdr + 2
|
||
LOAD T1,IASIZ,+P1 ;GET MAX BYTES ALLOWED IN MESSAGE SEGMENT
|
||
MOVE T2,RTRBSZ ;Get router buffer size
|
||
SUBI T2,<%SCHDR-2> ;Get 'VMS size'
|
||
CAMN T1,T2 ;Equal?
|
||
SUBI T1,2 ; -yes, fudge for VMS
|
||
STOR T1,SLSIZ,(SL) ;STORE THAT
|
||
|
||
TMNE MBPH2,(MB) ;WAS CC FROM A PHASE II NODE?
|
||
CALL CONBUF ;YES, USE CONSERVATIVE BUFFERING
|
||
|
||
STOR MB,SLCDM,(SL) ;SAVE CONNECT MSG FOR "NSFRC"
|
||
|
||
NEWSTATE RN ;SET NEW STATE TO CONNECT RECEIVED
|
||
SETONE SLCCB,(SL) ;HAVE TO CHECK CONNECT BLOCK NOW
|
||
|
||
;Now let's send the job's input quota worth of DRQs.
|
||
|
||
TMNE SLPH2,(SL) ;SHOULD WE BE CONSERVATIVE WITH THIS FELLOW?
|
||
RET ;LEAVE QUIETLY
|
||
|
||
MOVEI T1,0 ;DON'T NEED ANY USER DATA
|
||
CALL DNGMSG ;GET A NEW MESSAGE BLOCK
|
||
RET ; - resource error
|
||
MOVE MB,T1 ;POINT TO THE NEW MSG BLK
|
||
|
||
SETZRO MBOTH,(MB) ;SEND OUT ON THE NORMAL SUBLINK
|
||
SETZ T2, ;BUILD THE DATA REQUEST ARG BLOCK (QA) IN T2
|
||
LOAD T1,SLINQ,(SL) ;GET THE INPUT QUOTA
|
||
STOR T1,QACNT,+T2 ; USE THAT AS THE DATA REQUEST COUNT
|
||
STOR T1,SSRDO,+SL.NSL(SL) ;WE KEEP COUNT OF OUTGOING DATA REQUESTS
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid FOR NSP
|
||
MOVX T3,NV.DRQ ;FUNCTION IS SEND DATA REQUESTS
|
||
MOVE T4,MB ;POINT TO MESSAGE BLOCK
|
||
CALLRET NSP ;CALL NSP AND RETURN EVENTUALLY
|
||
SUBTTL LLINKS Calls -- SCDIR - Disconnect Initiate received call
|
||
|
||
;SCDIR - Disconnect Initiate received call from NSP
|
||
;
|
||
; Call:
|
||
; T2/ Reason Code
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
SCDIR: TRACE SC,Disconnect Initiate received call
|
||
SAVEAC P1 ;SAVE A PEA
|
||
|
||
STOR T2,SLRSN,(SL) ;ALSO STORE THE REASON FOR ERROR CODE
|
||
; PROCESSING
|
||
LOAD P1,SLSTA,(SL) ;GET THE STATE OF LINK
|
||
IFSTATE P1,CS ;IF WE WERE IN CONNECT SENT STATE,
|
||
CALL STPTMR ; STOP CI TIMERS & ADJUST TIMER CNTRS
|
||
|
||
OPSTR <SKIPE T1,>,SLCDM,(SL) ;ANY CONNECT DATA STILL THERE?
|
||
CALL DNFMSG ;YES, FREE IT NOW
|
||
STOR MB,SLCDM,(SL) ;STORE DISCONNECT MESSAGE
|
||
SETONE SLCCB,(SL) ;HAVE TO CHECK CONNECT BLOCK NOW
|
||
|
||
IFNSTATE P1,CS,SCDIR1 ;IF WE WERE IN CONNECT SENT,
|
||
NEWSTATE RJ ; SET THE STATE TO RJ
|
||
RET ; AND RETURN
|
||
|
||
;We differentiate between RJ and DR states here so that the user can
|
||
;tell from the state whether or not the link has ever been open.
|
||
|
||
SCDIR1: NEWSTATE DR ;WE GOT INTO RN STATE, SO GO INTO DR STATE
|
||
RET ;RETURN
|
||
SUBTTL LLINKS Calls -- SCDCR - Disconnect Confirm received call
|
||
|
||
;SCDCR - Disconnect Confirm received call from NSP
|
||
;
|
||
; Call:
|
||
; T2/ Reason Code
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
SCDCR: TRACE SC,Disconnect Confirm received call
|
||
SAVEAC P1
|
||
|
||
;A DC is normally received in response to our sending out a DI. In
|
||
;this case, there will be no interesting reason code and the link will
|
||
;not be in CS state, etc. Phase II nodes, or those not yet updated to
|
||
;Phase III fully, will reject a CI with a DC instead of a DI and in
|
||
;this case the only reason code we get is on that DC message.
|
||
|
||
STOR T2,SLRSN,(SL) ;ALSO STORE THE REASON FOR ERROR CODE
|
||
; PROCESSING
|
||
OPSTR <SKIPE T1,>,SLCDM,(SL) ;ANY CONNECT DATA STILL THERE?
|
||
CALL DNFMSG ;(T1) YES, FREE IT NOW
|
||
SETZRO SLCDM,(SL) ;NO DISCONNECT MESSAGE FROM A DC
|
||
|
||
LOAD P1,SLSTA,(SL) ;GET THE STATE OF LINK
|
||
IFNSTATE P1,CS,SCDCR1 ;IF WE WERE IN CONNECT SENT STATE,
|
||
CALL STPTMR ; STOP CI TIMERS & ADJUST TIMER CNTRS
|
||
NEWSTATE RJ ;GO INTO REJECT STATE
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
|
||
;Here if link was not in CS state
|
||
|
||
SCDCR1: NEWSTATE DC ;GO INTO DISCONNECT CONFIRM STATE
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
SUBTTL LLINKS Calls -- SCODN - Output done call
|
||
|
||
;SCODN - Output done call from NSP
|
||
;SCOND - Output not done call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
SCOND:!
|
||
SCODN: TRACE SC,Output done call
|
||
D36OFF ;PROTECT THIS CODE FROM LLINKS CALL TO SCTRIB
|
||
OPSTRM <SOS T1,>,SLOTU,(SL) ;DECREMENT OUTPUT BUFFERS IN USE
|
||
MOVX T2,-1 ;ASSUME WE'RE NOT FREEING LAST OUTPUT BUFFER
|
||
JUMPG T1,SCODN1 ;JUMP IF THAT'S TRUE
|
||
MOVX T2,-2 ;WE ARE FREEING LAST OUTPUT, ASSUME NO INPUT
|
||
TMNE SLINU,(SL) ;ANY INPUT BUFFERS ALLOCATED?
|
||
MOVX T2,0 ;YES, LEAVE AN OUTPUT BUFFER RESERVED
|
||
SCODN1: ADDB T2,DCNRSB ;ADJUST THE RESERVED BUFFER COUNT
|
||
D36ON ;END OF CRITICAL SECTION
|
||
CALL FREMSG ;FREE THE MESSAGE BLOCK
|
||
CALLRET CHKSTS ;GENERATE PSI INTERRUPT "OUTPUT-OK"
|
||
SUBTTL LLINKS Calls -- SCSEG - Segment received call
|
||
|
||
;SCSEG - Segment received call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCSEG: TRACE SC,Segment Received Call
|
||
|
||
XMOVEI T4,SL.NSL(SL) ;ASSUME IT'S ON THE NORMAL SUBLINK
|
||
TMNE MBOTH,(MB) ;IS IT THE OTHER SUBLINK?
|
||
XMOVEI T4,SL.OSL(SL) ;YES, POINT TO OTHER AREA
|
||
|
||
ENDQUE MB,SS.INQ(T4),MB.NXT,T1 ;QUEUE THE MESSAGE
|
||
INCR SLPKR,(SL) ;Increment # of packets received
|
||
CALLRET CHKSTS ;SEE IF THE USER NEEDS WAKING
|
||
|
||
;Note: The count of input buffers used is incremented when the data
|
||
;requests are sent out in NSFxR, so we don't have to incr now.
|
||
SUBTTL LLINKS Calls -- SCDRQ - Data request received call
|
||
|
||
;SCDRQ - Data request received call from NSP
|
||
;
|
||
; Call:
|
||
; T2/ DATA REQUEST call's arguments (see BEGSTR QA in D36PAR)
|
||
; SL/ Pointer to Session Control Link Block
|
||
; MB/ Pointer to the Message Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCDRQ: TRACE SC,Data Request Received Call
|
||
|
||
XMOVEI T4,SL.NSL(SL) ;ASSUME IT CAME FROM NORMAL SUBLINK
|
||
TMNE MBOTH,(MB) ;DID IT?
|
||
XMOVEI T4,SL.OSL(SL) ;NO, MUST BE FROM INTERRUPT SUBLINK
|
||
|
||
LOADE T1,QACNT,+T2 ;GET THE DATA REQUEST COUNT
|
||
LOADE T3,SSXDO,(T4) ;GET # OF DRQS WE HAVE NOW OUTSTANDING
|
||
ADD T3,T1 ;NEW COUNT OF DATA REQUESTS
|
||
STOR T3,SSXDO,(T4) ;STORE THE NEW DATA REQUEST COUNT
|
||
|
||
CALL CHKSTS ;SET THE STATUS, POSSIBLY GENERATING PSI
|
||
CALLRET FREMSG ;FREE THE MESSAGE BLOCK
|
||
SUBTTL LLINKS Calls -- SCNCF - No confidence in port call
|
||
|
||
;SCNCF - No confidence in port call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCNCF: TRACE SC,No confidence in port call
|
||
|
||
NEWSTATE CF ;NEW STATE IS NO CONFIDENCE
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
SUBTTL LLINKS Calls -- SCNRS - No resources call
|
||
|
||
;SCNRS - No resources call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCNRS: TRACE SC,No resources call
|
||
|
||
NEWSTATE NR ;SET THE NEW STATE TO "NO RESOURCES"
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
SUBTTL LLINKS Calls -- SCCLS - Close Completed call
|
||
|
||
;SCCLS - Close Completed call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCCLS: TRACE SC,Close Completed call
|
||
|
||
SETONE SLFSL,(SL) ;FREE THE SLB ON NEXT TICK
|
||
CALL SCTRFJ ;REQUEST SECOND SERVICE FOR THIS LINK
|
||
CALLRET FREMSG ;FREE THE MESSAGE BLOCK
|
||
SUBTTL LLINKS Calls -- SCNLK - No link call
|
||
|
||
;SCNLK - No link call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCNLK: TRACE SC,No Link call
|
||
|
||
NEWSTATE LK ;NEW STATE IS NO-LINK
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
SUBTTL LLINKS Calls -- SCNCM - No communication call
|
||
|
||
;SCNCM - No communication call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCNCM: TRACE SC,No communication call
|
||
|
||
NEWSTATE CM ;NEW STATE IS NO COMMUNICATION
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
SUBTTL LLINKS Calls -- SCNRN - Not in Run State call
|
||
|
||
;SCNRN - Not in Run State call from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCNRN: TRACE SC,Not in Run State call
|
||
;NO NEW STATE TO GO INTO HERE
|
||
CALLRET CHKABO ;(MB)CLOSE PORT IF NECESSARY
|
||
SUBTTL LLINKS Calls -- SCCAK - Got a Connect ACK
|
||
|
||
;SCCAK - Got a Connect ACK from NSP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1
|
||
;
|
||
;NSP will call us here to report a connect ACK. Using this call, we
|
||
;can determine that the CI has made it to the remote, while the remote
|
||
;user hasn't yet accepted the connect. Maybe someday we'll figure out
|
||
;what to do with this.
|
||
|
||
SCCAK: TRACE SC,Got a Connect ACK
|
||
CALLRET FREMSG
|
||
|
||
SUBTTL Subroutines -- CHKABO - Check SLABO flag
|
||
|
||
;CHKABO - Check SLABO flag, close port if need be
|
||
;
|
||
; Call:
|
||
; MB/ Pointer to a message block
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS, MESSAGE BLOCK FREED
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
|
||
CHKABO: TMNN SLABO,(SL) ;ARE WE TRYING TO CLOSE AFTER AN ABORT?
|
||
CALLRET FREMSG ;NO, FREE MSG BLK AND LEAVE
|
||
TMNE <SLFSL,SLLBC>,(SL) ;YES, HAVE WE ALREADY CLOSED LINK?
|
||
CALLRET FREMSG ;YES, FREE MSG BLK AND LEAVE
|
||
|
||
CALLRET RLSLNK ;(MB)RELEASE THE LINK AND RETURN
|
||
SUBTTL Subroutines -- CHKPPN - Check self PPN for validity
|
||
|
||
;CHKPPN - Check PPN in self port block
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to Port Block
|
||
; SL/ Pointer to SLB
|
||
; Return
|
||
; RET ;INVALID PPN AND NO PRIVS TO FAKE IT
|
||
; RETSKP ;VALID
|
||
|
||
|
||
CHKPPN:
|
||
IFN FTOPS10,<
|
||
LOAD T2,SLSJB,(SL) ;GET POINTER TO SJB
|
||
JN SJPRV,(T2),RSKP ;IF PRIVED, ALWAYS VALID
|
||
IFN <PB.USR-PB.GRP>,<PRINTX PBUSR and PBGRP must be in same word>
|
||
MOVE T1,PB.USR(T1) ;GET PPN WE CLAIM TO BE
|
||
LOAD T2,SJJOB,(T2) ;GET JOB OUR JOB NUMBER
|
||
CAME T1,JBTPPN##(T2) ;COMPARE OUR PPN WITH PPN WE CLAIM TO BE
|
||
RET ;THAT'S NOT YOU. FAIL.
|
||
RETSKP ;THAT'S YOU ALRIGHT. SUCCEED.
|
||
> ;END IFN FTOPS10
|
||
IFN FTOPS20,<
|
||
RETSKP ;SUCCEED UNTIL WE DECIDE TO CHECK
|
||
> ;END IFN FTOPS20
|
||
SUBTTL Subroutines -- FREMSG - Free a message block
|
||
|
||
;FREMSG - Free a message block
|
||
;
|
||
; Call:
|
||
; MB/ Pointer to Message Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
FREMSG: MOVE T1,MB ;POINT TO THE MESSAGE BLOCK
|
||
TRASH MB, ;CATCH A BUG
|
||
CALLRET DNFMSG ;FREE THE MESSAGE BLOCK
|
||
SUBTTL Subroutines -- CONBUF - Invoke Conservative Buffering
|
||
|
||
;CONBUF - Invoke Conservative Buffering
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to SLB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2
|
||
|
||
;If we do support Phase II, then this routine will have to be updated
|
||
;to reserve a small number of buffers (eg, 1 in + 1 out) at open time,
|
||
;and then the rest of the 'reserve' routines will have to test for
|
||
;Phase II and promise never to release this link's reservations, and
|
||
;always to use the existing reservation when reallocating.
|
||
|
||
CONBUF: BUG.(INF,SCLCBN,SCLINK,SOFT,<Phase-II buffering not implemented>,,<
|
||
|
||
Cause: Conservative buffering is not yet implemented.
|
||
We should never have a logical link open to a phase II node.
|
||
|
||
>)
|
||
SETONE SLPH2,(SL) ;MARK LINK AS A PHASE II LINK
|
||
MOVX T1,FCM.SG ;DO SEGMENT FLOW CONTROL ONLY
|
||
STOR T1,SLRFL,(SL) ;SET THE RECEIVE FLOW CONTROL TYPE
|
||
SETZRO SLGOL,(SL) ;SET THE GOAL TO ZERO
|
||
MOVX T1,SCTP2Q ;GET THE PHASE II QUOTA
|
||
STOR T1,SLINQ,(SL) ;STORE THAT AS THE INPUT QUOTA
|
||
STOR T1,SLOTQ,(SL) ; AND AS THE OUTPUT QUOTA
|
||
RET ;ONLY RETURN
|
||
SUBTTL Subroutines -- FNDSLB - Find SLB given a channel number
|
||
|
||
;FNDSLB - Find a SLB from a channel number
|
||
;
|
||
; Call:
|
||
; T1/ Channel #
|
||
; T2/ Pointer to Session Control Job Block
|
||
;
|
||
; Return:
|
||
; RET ;COUDLN'T GET IT
|
||
; RETSKP ;FOUND IT OK, SL POINTS TO IT
|
||
;
|
||
; Uses: T1,T2,T4,SL
|
||
|
||
FNDSLB: JUMPLE T1,RTN ;IF NEGATIVE OR ZERO, RETURN FAILURE
|
||
OPSTR <CAMLE T1,>,SJCHC,(T2) ;DO A QUICKIE RANGE CHECK
|
||
RET ;OUT OF BOUNDS
|
||
SOJ T1, ;OUR OFFSET IS ZERO, WHILE USER'S IS ONE
|
||
LOAD T4,SJCHT,(T2) ;GET POINTER TO SLB TABLE
|
||
ADD T4,T1 ;FIND ENTRY FOR THIS CHANNEL
|
||
SKIPN SL,(T4) ;GET THE POINTER TO IT
|
||
RET ;NO THERE, GIVE BAD RETURN
|
||
OPSTR <CAME SL,>,SLSLB,(SL) ;MAKE SURE IT POINTS TO AN SLB
|
||
BUG.(CHK,SCLSPF,SCLINK,SOFT,<SLB self pointers messed up in FNDSLB>,<<T1,CHAN>,<T2,SJBPTR>>,<
|
||
|
||
Cause: The DECnet data structures for this link are inconsistent.
|
||
If this happens more than once, submit a SPR.
|
||
|
||
Data: CHAN - The DECnet channel number
|
||
SJBPTR - Pointer to the SJB
|
||
|
||
>,RTN)
|
||
TMNE <SLFSL,SLLBC>,(SL) ;IS IT SCHEDULED FOR DESTRUCTION?
|
||
RET ;YES, DON'T LET ON THAT ITS HERE
|
||
RETSKP ;RETURN WITH SUCCESS
|
||
SUBTTL Subroutines -- FNDSBI - Find SLB from SLBid
|
||
|
||
;FNDSBI - Find SLB from a SLBid
|
||
;
|
||
; Call:
|
||
; T1/ SLBid
|
||
;
|
||
; Return:
|
||
; RET ;FAILED
|
||
; RETSKP ;SUCCESS WITH SL POINTING TO SLB
|
||
;
|
||
; Uses: T1
|
||
|
||
FNDSBI: TMNE SLFSL,(T1) ;SLB SCHEDULED FOR DESTRUCTION?
|
||
RET ;YES, TELL CALLER IT DOESN'T EXIST
|
||
SKIPE SL,T1 ;EASY ISN'T IT?
|
||
AOS (P) ;WE'RE OK
|
||
RET ;BLEW IT
|
||
SUBTTL Subroutines -- FRESLB - Deallocate a SLB
|
||
|
||
;FRESLB - Deallocate a SLB
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to SLB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
FRESLB: SAVEAC <P1,P2>
|
||
OPSTR <SKIPN P2,>,SLSJB,(SL) ;LOAD UP THE JOB BLK POINTER
|
||
BUG.(CHK,SCLSLB,SCLINK,SOFT,<SLB bad at FRESLB>,<<SL,SLBPTR>>,<
|
||
|
||
Cause: There is no Session Control Job Block (SJB) for this Session
|
||
Control Link Block (SLB). This error could have happened at
|
||
any time during the life of the link after it was actively
|
||
transferring data.
|
||
|
||
Data: SLBPTR/ pointer to the SLB that lacked a SJB pointer
|
||
|
||
>,RTN)
|
||
LOAD T1,SLCHN,(SL) ;GET THE CHANNEL NUMBER OF LINK
|
||
LOAD T4,SJCHT,(P2) ;GET POINTER TO SLB TABLE IN THE SJB
|
||
ADDI T4,-1(T1) ;FIND THE ENTRY FOR THIS CHANNEL
|
||
CAME SL,(T4) ;MAKE SURE THERE'S ONE THERE
|
||
BUG.(CHK,SCLTFS,SCLINK,SOFT,<Tried to free wrong SLB>,<<SL,SLBPTR>>,<
|
||
|
||
Cause: The channel table entry didn't point to the correct SLB.
|
||
There is an internal inconsistency in the DECnet data
|
||
structures for this link.
|
||
|
||
Action: Submit a SPR if this happens more than once.
|
||
|
||
Data: SLBPTR - Pointer to the bad SLB
|
||
|
||
>,RTN)
|
||
SETZM (T4) ;ZERO CHANNEL TABLE ENTRY
|
||
|
||
XMOVEI P1,SS.INQ+SL.NSL(SL) ;POINT TO NORMAL SUBLINK'S INPUT Q
|
||
CALL CLNQUE ;GET RID OF ALL MESSAGES ON THE QUEUE
|
||
XMOVEI P1,SS.INQ+SL.OSL(SL) ;SAME FOR OTHER SUBLINK'S INPUT Q
|
||
CALL CLNQUE
|
||
OPSTR <SKIPE T1,>,SLOTM,(SL) ;IF WE HAVE A PART FILLED OUTPUT MSG
|
||
CALL DNFMSG ; THEN FREE IT
|
||
OPSTR <SKIPE T1,>,SLCBP,(SL) ;IF WE HAVE AN INTERNAL CONNECT BLK
|
||
CALL DNFWDS ; THEN FREE IT
|
||
OPSTR <SKIPE T1,>,SLCDM,(SL) ;IF WE HAVE A DISCONNECT MSG BLK
|
||
CALL DNFMSG ; THEN FREE IT
|
||
|
||
;Here we remove any buffer reservations attached to this SLB.
|
||
|
||
D36OFF ;#KEEP LLINKS (SCTRIB CALL) OUT OF THIS
|
||
LOAD T1,SLOTU,(SL) ;#GET OUTPUT BUFFERS IN USE
|
||
LOAD T2,SLINU,(SL) ;#GET INPUT BUFFERS IN USE
|
||
SKIPG T3,T1 ;#ANY INPUT BUFFERS RESERVED?
|
||
JUMPE T2,FRESL1 ;#NO, NO RESERVATIONS IF NEITHER IN USE
|
||
ADD T3,T2 ;#GET TOTAL BUFFERS WHICH WERE IN USE
|
||
SKIPE T1 ;#WERE THERE ANY INPUTS IN USE?
|
||
SKIPN T2 ;#YES, ANY OUTPUTS?
|
||
AOS T3 ;#NO OR NO, ONE MORE WAS RESERVED FOR
|
||
MOVNS T3 ;# OTHER DIRECTION
|
||
ADDM T3,DCNRSB ;#UPDATE RESERVED BUFFER COUNT
|
||
FRESL1: D36ON ;#END CRITICAL SECTION
|
||
|
||
;Here we remove this SLB from the PSQ if it had a PSI waiting.
|
||
|
||
TMNN SLPSI,(SL) ;ON THE PSI Q?
|
||
JRST FRESL2 ;NO, NO WORRY NOW
|
||
D36OFF ;#PSI Q DOESN'T RESPECT SCT INTERLOCK
|
||
RMVQUE SL,SJ.PSQ(P2),SL.NXP,T1 ;#REMOVE SLB FROM PSI Q
|
||
D36ON ;#FINISHED WITH THE CRITICAL SECTION
|
||
FRESL2:
|
||
|
||
;Here we remove the SLB from the second request Q if need be
|
||
|
||
RMVQUE SL,SCTJFQ,SL.JFQ,T1 ;THIS IS INTERLOCKED
|
||
|
||
;Here we remove the SLB from the All SBLs Queue
|
||
|
||
RMVQUE SL,SCTASQ,SL.ASQ,T1 ;THIS IS INTERLOCKED
|
||
|
||
;Here we clean out the SLB's serial number
|
||
|
||
SETZRO SLUID,(SL)
|
||
|
||
;Here we free up the SLB's memory
|
||
|
||
MOVE T1,SL ;SET UP FOR CALL TO DNFWDS
|
||
SETZ SL, ;JUST FOR KICKS
|
||
CALLRET DNFWDS ;FREE THE WORDS AND RETURN
|
||
|
||
|
||
;Routine to clean out a queue of message blks pointed to by P1.
|
||
|
||
CLNQUE: DEQUE T1,(P1),MB.NXT,RTN ;GET NEXT MB, RETURN IF Q IS EMPTY
|
||
CALL DNFMSG ;FREE MESSAGE POINTED TO BY T1
|
||
JRST CLNQUE ;LOOP FOR NEXT ONE
|
||
SUBTTL Subroutines -- FRECBP - Free Connect Block
|
||
|
||
;FRECBP - Free Connect Block
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to SLB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
;We try to free up connect data blocks in decending order of importance.
|
||
;First, we try to get rid of a message blocks which interrupt level may have
|
||
;left for process level by copying them to connect blocks. (Interrupt level
|
||
;can't copy for fear of failing to get a connect block from free memory.)
|
||
;Whether or not we can get rid of the resulting connect block, we have freed a
|
||
;quota-controlled message block.
|
||
;Then we try to free any connect block which may be waiting, subject to the
|
||
;user's request that we keep it.
|
||
|
||
FRECBP: SETZRO SLCCB,(SL) ;DON'T NEED TO CHECK CONNECT BLK ANY MORE
|
||
TMNN SLCDM,(SL) ;ANY WAITING DIS/CONNECT DATA MESSAGE?
|
||
JRST FRECB1 ;NO
|
||
CALL CDMCBP ;YES, FREE UP MESSAGE BY COPYING IT TO CBP
|
||
JFCL ;COULDN'T WE'LL TRY AGAIN NEXT TIME
|
||
FRECB1: TMNN SLCBP,(SL) ;IS THERE A CONNECT BLOCK?
|
||
RET ;NONE THERE, LEAVE NOW
|
||
TMNE SLKCB,(SL) ;USER WANT US TO KEEP CONNECT BLOCK?
|
||
RET ;YES, DON'T RELEASE IT.
|
||
LOAD T2,SLSTA,(SL) ;GET LINK'S STATE
|
||
IFNSTATE T2,RN,RTN ;IF NOT RUN STATE, MIGHT BE DISCON DATA
|
||
LOAD T1,SLCBP,(SL) ;GET POINTER TO CONNECT BLOCK
|
||
CALL DNFWDS ;(T1) FREE THE BLOCK
|
||
SETZRO SLCBP,(SL) ;REMEMBER WE'VE LOST IT
|
||
RET ;THAT'S ALL
|
||
SUBTTL Subroutines -- CDMCBP - Copy User Data from Message Block
|
||
|
||
;CDMCBP - Copy User Data from @SLCDM to @SLCBP
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to SLB
|
||
;
|
||
; Return:
|
||
; RET ;IF INVALID MESSAGE, EVENT ALREADY CALLED
|
||
; RETSKP ;ON SUCCESS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
CDMCBP: SAVEAC <MB,MS>
|
||
OPSTR <SKIPN MB,>,SLCDM,(SL) ;ANY DISCONNECT MESSAGE?
|
||
RETSKP ;NO, NOTHING TO COPY
|
||
TMNE SLCBP,(SL) ;YES, IS THERE A CONNECT BLOCK
|
||
JRST CDMCB1 ;YES, ONE OF THEM TOO, COPY THE GOODS NOW
|
||
MOVEI T1,CB.LEN ;NO, ALLOCATE ONE FIRST
|
||
CALL DNGWDZ ;GET A ZEROED BLOCK
|
||
SCERR %NEALF,RTN,<Allocation failure>
|
||
STOR T1,SLCBP,(SL) ;STORE CONNECT BLOCK POINTER IN SLB
|
||
|
||
CDMCB1: MOVE T1,MB ;POINT TO THE MESSAGE BLOCK
|
||
CALL DNGINI ;SET UP TO GET SOME BYTES OUT
|
||
|
||
SETZRO SLCDM,(SL) ;REMEMBER WE FREED IT
|
||
CALL CPMSCB ;COPY USER DATA TO CONNECT BLOCK
|
||
RETSKP ;INVALID MESSAGE, WE'VE DONE BEST WE CAN
|
||
CALL FREMSG ;DONE WITH THE DISCONNECT MESSAGE NOW
|
||
RETSKP ;SUCCESS RETURN
|
||
SUBTTL Subroutines -- CPMSCB - Copy User Data from Message Block
|
||
|
||
;CPMSCB - Copy User Data from Message Block to Existing Connect Block
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to SLB, SLCBP points to Connect Block
|
||
; MB/ Pointer to Message Block
|
||
; MS/ Set up for D36COM message block routines to copy user data
|
||
;
|
||
; Return:
|
||
; RET ;IF INVALID MESSAGE, EVENT ALREADY CALLED
|
||
; RETSKP ;ON SUCCESS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
CPMSCB: CALL DNG1BY ;GET FIRST BYTE = LENGTH OF USER DATA
|
||
SETZ T1, ;ZERO LENGTH IF NO LENGTH BYTE PRESENT
|
||
CAIG T1,^D16 ;LONGER THAN ARCHITECTURAL LIMIT OF 16?
|
||
JRST CPMSC1 ;NO, ITS OK
|
||
MOVEI T1,^D16 ;YES, TOO LONG, TRUNCATE TO 16 BYTES
|
||
CALL CPMSC1 ; COPY WHAT WE CAN BEFORE SCEIVM FREES MSG
|
||
RET ; OOPS, INVALID MESSAGE EVENT ALREADY GIVEN
|
||
CALLRET SCEIVM ; GIVE INVALID MESSAGE EVENT
|
||
|
||
CPMSC1: LOAD T4,SLCBP,(SL) ;T4 POINTS TO CONNECT BLOCK
|
||
STOR T1,CBCCT,(T4) ;STORE LENGTH OF USER DIS/CONNECT DATA
|
||
JUMPE T1,RSKP ;SUCCESS NOW IF NO USER DATA
|
||
MOVX T2,<<POINT 8,>!1B12> ;2-WORD BYTE POINT PTR TO CONNECT BLOCK'S
|
||
XMOVEI T3,CB.UDA(T4) ; USER-CONNECT-DATA BLOCK
|
||
CALL DNCM2B ;(T1,T2,T3,MS)COPY MSG BLK TO MONITOR BUFFER
|
||
CALLRET SCEIVM ;TOO SHORT, GIVE INVALID MESSAGE EVENT
|
||
RETSKP ;JUST RIGHT, SUCCESS
|
||
SUBTTL Subroutines -- FRESJB - Deallocate a SJB
|
||
|
||
;FRESJB - Deallocate a SJB
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to SJB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
XRENT FRESJB
|
||
|
||
SAVEAC <P1,T5,T6>
|
||
SKIPN P1,T1 ;POINTER TO SJB
|
||
RET ;JUST CHECKING
|
||
CALL CHKSJB ;SEE IF THERE ARE ANY SLBs
|
||
BUG.(CHK,SCLTFJ,SCLINK,SOFT,<Freeing SJB with SLB entries existing>,<<P1,SJBPTR>>,<
|
||
|
||
Cause: FRESJB was called to free up a SJB. However, there are still active
|
||
links in use for this SJB. This should never happen, and there is
|
||
an internal inconsistency in the DECnet data structures. Submit a
|
||
SPR if this happens more than once.
|
||
|
||
Data: SJBPTR - Pointer to the SJB
|
||
|
||
>)
|
||
|
||
D36OFF ;#PROTECT THE SMP
|
||
RMVQUE P1,SCTSJQ,SJ.NXT,T1 ;#REMOVE SJB FROM LIST OF SJBS
|
||
D36ON ;#END OF CRITICAL SECTION
|
||
MOVE T1,P1 ;SET UP TO FREE SOME WORDS
|
||
CALLRET DNFWDS ;FREE THE WORDS THE SJB IS USING
|
||
SUBTTL Subroutines -- CHKSJB - Check an SJB for SLBs
|
||
|
||
;CHKSJB - Check an SJB for SLBs
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to SJB
|
||
;
|
||
; Return:
|
||
; RET ;There are SLBs associated with this SJB
|
||
; RETSKP ;No SLBs associated with this SJB
|
||
;
|
||
; Uses: T1-T2
|
||
|
||
XRENT CHKSJB
|
||
|
||
LOAD T2,SJCHC,(T1) ;GET COUNT OF SLB SLOTS
|
||
LOAD T1,SJCHT,(T1) ;AND ADDRESS OF SLB TABLE
|
||
CHKSJ1: SOJL T2,RSKP ;IF NONE LEFT, RETURN
|
||
SKIPE (T1) ;IS THERE AN SLB ADDRESS IN THIS SLOT?
|
||
RET ;YES, RETURN
|
||
AOJA T1,CHKSJ1 ;NO, CHECK NEXT ONE
|
||
SUBTTL Subroutines -- MAKSLB - Create a SLB, filling in defaults
|
||
|
||
;MAKSLB - Create a SLB, filling in defaults
|
||
;
|
||
; Call:
|
||
; T1/ Channel #
|
||
; SA/ Pointer to argument block from SCTNSF caller
|
||
;
|
||
; Return:
|
||
; RET ;ON FAILURE DUE TO ALLOCATION
|
||
; RETSKP ;SUCCESS WITH SL SET UP WITH THE SLB POINTER
|
||
; ; AND T1 CONTAINING THE CHANNEL NUMBER
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
CHTFAC==2 ;FACTOR BY WHICH NEW CHT IS LARGER THAN OLD
|
||
|
||
MAKSLB: SAVEAC <P1,P2> ;CHT POINTER, SJB POINTER
|
||
MAKSL1: LOAD P2,SASJB,(SA) ;GET POINTER TO SJB
|
||
LOAD P1,SJCHT,(P2) ;GET POINTER TO THE SLB TABLE
|
||
LOAD T3,SJCHC,(P2) ; AND THE COUNT OF ENTRIES IN THE TABLE
|
||
|
||
MAKSL2: SKIPN (P1) ;IS THERE A FREE ENTRY?
|
||
JRST MAKSL3 ;YES, GO USE IT
|
||
SOSE T3 ;ARE ANY MORE ENTRIES LEFT?
|
||
AOJA P1,MAKSL2 ;YES, LOOK AT THE NEXT ONE
|
||
|
||
;Here when we have to expand the SLB table in the SJB. We will try to make
|
||
;it twice as large as it is currently.
|
||
|
||
LOAD T1,SJCHC,(P2) ;GET THE CURRENT SIZE OF SLB TABLE
|
||
IMULI T1,CHTFAC ;CALC NEW, LARGER SIZE
|
||
;WE'LL STORE SIZE LATER, AFTER COPY
|
||
CALL DNGWDZ ;GET THAT MANY WORDS
|
||
RET ;ALLOCATION FAILURE
|
||
|
||
MOVE T2,T1 ;SET UP DEST POINTER FOR DNCPYW
|
||
OPSTRM <EXCH T1,>,SJCHT,(P2) ;STORE NEW CHT PTR, LOAD OLD CHT PTR
|
||
LOAD T3,SJCHC,(P2) ;GET THE OLD COUNT
|
||
PUSH P,T1 ;SAVE POINTER TO OLD CHT
|
||
CALL DNCPYW ;COPY THE OLD WORDS
|
||
POP P,T4 ;RESTORE POINTER TO OLD CHT FOR DEALLOCATION
|
||
|
||
LOAD T2,SJCHC,(P2) ;GET OLD CHT LENGTH
|
||
IMULI T2,CHTFAC ;CALC NEW LENGTH AGAIN
|
||
STOR T2,SJCHC,(P2) ;STORE NEW CHT LENGTH
|
||
|
||
;Deallocate the old block if it was outside of the SJB.
|
||
|
||
XMOVEI T2,SJ.SLT(P2) ;POINT TO THE SLB TABLE IN THE SJB
|
||
CAME T2,T4 ;IS THE SLB TABLE IN THE SLB?
|
||
JRST [MOVE T1,T4 ;NO, JUST FREE THE BLOCK
|
||
CALL DNFWDS ;FREE THE WORDS
|
||
JRST MAKSL1] ;MAKE THE NEW ENTRY UP
|
||
MOVE T1,T2 ;ZERO THE
|
||
ADDI T2,SLT.LN-1 ; ENTRIES IN THE SJB
|
||
SETZ T3, ; JUST TO BE SAFE
|
||
CALL DNSWDS ;SMEAR THEM
|
||
JRST MAKSL1 ; AND GO INTO THE OTHER CODE
|
||
;Here to make the new SLB.
|
||
|
||
MAKSL3: MOVX T1,SL.LEN ;LENGTH OF A SLB
|
||
CALL DNGWDZ ;GET THAT MANY WORDS
|
||
RET ;ALLOCATION FAILURE
|
||
MOVE SL,T1 ;SET UP SL WITH THE POINTER
|
||
STOR SL,SLSLB,(SL) ;STORE POINTER TO OURSELVES FOR CHECKING
|
||
STOR P2,SLSJB,(SL) ; AND POINTER TO SJB
|
||
|
||
;Initialize some of the variables.
|
||
|
||
SETONE SSOTH,+SL.OSL(SL) ;SET "OTHER SUBLINK" BIT IN OTHER SUBLINK
|
||
|
||
LOAD T1,IBFCM,+IBBLK ;Get default flow control from IB block
|
||
STOR T1,SLXFL,(SL) ;SET THE TRANSMIT FLOW CONTROL TO SEGMENT
|
||
STOR T1,SLRFL,(SL) ; AND THE RECEIVE FLOW TYPE
|
||
|
||
SETZRO SLGOL,(SL) ;START THE GOAL AT ZERO
|
||
MOVX T1,1
|
||
STOR T1,SSXDO,+SL.OSL(SL) ;SET XMT DRQS ON OTHER SUBLINK TO ONE
|
||
STOR T1,SSRDO,+SL.OSL(SL) ; ALONG WITH THE RCV DRQS
|
||
|
||
LOAD T1,SJGOL,(P2) ;GET THE JOB'S GOAL
|
||
STOR T1,SLGOL,(SL) ;STORE IT
|
||
|
||
LOAD T1,SJINQ,(P2) ;GET THE JOB'S INPUT QUOTA
|
||
STOR T1,SLINQ,(SL) ;STORE IT IN THE SLB
|
||
LOAD T1,SJOTQ,(P2) ;SAME FOR THE OUTPUT QUOTA
|
||
STOR T1,SLOTQ,(SL) ;STORE THAT IN THE SLB ALSO
|
||
|
||
MOVE T1,RTRBSZ ;Get executor bytes size
|
||
SUBI T1,%SCHDR ; and subtract size of headers below SC
|
||
STOR T1,SLSIZ,(SL) ;SET THAT UP ALSO
|
||
|
||
SETZRO SLRSN,(SL) ;ZERO THE REASON FIELD
|
||
|
||
LOAD T1,SAWKA,(SA) ;GET ADDRESS OF WAKEUP ROUTINE
|
||
STOR T1,SLWKA,(SL) ;STORE IN THE SLB
|
||
|
||
SETZRO SLPSM,(SL) ;START WITH PSI MASK DISABLED
|
||
|
||
SETONE <SLBSY,SLEOM>,(SL) ;INITIALLY THE SLB IS BUSY, SEE SCTNIA
|
||
; SLEOM INITIALLY TRUE FOR FIRST BOM
|
||
|
||
IFN FTOPS10,<
|
||
MOVE T1,SYSUTM## ;GET MILLISECONDS OF UPTIME
|
||
>;End of IFN FTOPS10
|
||
IFN FTOPS20,<
|
||
MOVE T1,TODCLK ;SET UP THE
|
||
>
|
||
STOR T1,SLUID,(SL) ; SLB'S SERIAL NUMBER
|
||
|
||
;After all errors have been avoided, store pointer in SLB table
|
||
|
||
ENDQUE SL,SCTASQ,SL.ASQ,T1 ;PUT NEW SLB ON ALL SLB QUEUE
|
||
|
||
MOVEM SL,(P1) ;SAVE POINTER TO US IN SLB TABLE
|
||
OPSTR <SUB P1,>,SJCHT,(P2) ;CALC NEW CHANNEL NUMBER
|
||
AOS T1,P1 ;MAKE CHANNEL NUMBERS START AT ONE
|
||
STOR P1,SLCHN,(SL) ;STORE IT IN THE SLB
|
||
RETSKP ; AND RETURN CHANNEL # TO USER IN T1
|
||
SUBTTL Subroutines -- MAKSJB - Create a SJB, filling in defaults
|
||
|
||
;MAKSJB - Create a SJB, filling in defaults
|
||
;
|
||
; Call, PC in section 1 if KL paging:
|
||
; T1/ DECnet "PDB" word (See PD Structure in D36PAR)
|
||
;
|
||
; Return:
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;OK, WITH T1 SET UP WITH SJB POINTER
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRENT MAKSJB
|
||
|
||
SAVEAC <P1,P2,T5,T6>
|
||
MOVE P1,T1 ;SAVE THE ARGUMENT
|
||
MOVX T1,SJ.LEN ;GET THE LENGTH OF A SJB
|
||
CALL DNGWDZ ;GET THAT MANY WORDS
|
||
RET ;ALLOCATION FAILURE
|
||
MOVE P2,T1 ;SET UP THE SJB POINTER IN P2
|
||
|
||
D36OFF ;INTERLOCK FOR SMP
|
||
ENDQUE P2,SCTSJQ,SJ.NXT,T1 ;PUT IT ON THE QUEUE OF SJB'S
|
||
D36ON ;END CRITICAL SECTION
|
||
MOVX T1,SLT.LN ;LENGTH OF VIRGINAL SLB TABLE
|
||
STOR T1,SJCHC,(P2) ;STORE THAT IN THE COUNT
|
||
XMOVEI T1,SJ.SLT(P2) ;MAKE THE SLB TABLE POINTER POINT
|
||
STOR T1,SJCHT,(P2) ; TO THE VIRGIN TABLE IN THE SJB
|
||
|
||
LOAD T1,PDGOL,+P1 ;GET THE JOB'S GOAL
|
||
STOR T1,SJGOL,(P2) ;STORE IN THE SJB
|
||
LOAD T1,PDDQT,+P1 ;GET THE DEFAULT QUOTA
|
||
OPSTR <IMUL T1,>,PDIPR,+P1 ;MULT BY INPUT % = INPUT QUOTA * 100
|
||
IDIVI T1,^D100 ; AND DIVIDE BY 100 TO FIND INPUT QUOTA
|
||
SKIPG T1 ;ASSURE INPUT
|
||
MOVEI T1,1 ; GETS AT LEAST ONE
|
||
STOR T1,SJINQ,(P2) ;STORE THE INPUT QUOTA IN SJB
|
||
LOAD T2,PDDQT,+P1 ;GET THE TOTAL QUOTA BACK
|
||
SUB T2,T1 ;SUBTRACT INPUT QUOTA
|
||
SKIPG T2 ;ASSURE OUTPUT
|
||
MOVEI T2,1 ; GETS AT LEAST ONE
|
||
STOR T2,SJOTQ,(P2) ;TO GET THE OUTPUT QUOTA
|
||
|
||
MOVE T1,P2 ;RETURN SJB POINTER IN T1
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL Subroutines -- SCSSTS/CHKSTS - Set Status & Inform PSISER
|
||
|
||
;SCSSTS/CHKSTS - Set Status & Inform PSISER
|
||
;
|
||
; Call:
|
||
; T1/ New State ;FOR SCSSTS ONLY, NO ARGS FOR CHKSTS
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;NSFDS and NSFIS use the NSNDR and NSIDR bits to determine whether they
|
||
;should send a msg, so CHKSTS is the repository of quota information.
|
||
|
||
SCSSTS: STOR T1,SLSTA,(SL) ;STORE NEW STATE (NOT PART OF SLSST)
|
||
CHKSTS: ;ALTERNATE ENTRY TO CHECK BITS ONLY
|
||
|
||
;Now build a new status word from the data contained in the SLB. The
|
||
;new status gets built in T6.
|
||
|
||
LOAD T6,SLSTA,(SL) ;GET STATE FOR STATUS HALF-WORD
|
||
MOVE T4,T6 ;SAVE THE STATE FOR LATER
|
||
|
||
;Check for input available
|
||
TMNE QHBEG,+SL.NSL+SS.INQ(SL) ;ANY NORMAL INPUT DATA AVAILABLE?
|
||
TXO T6,NSNDA ;YES, SET NORMAL DATA AVAILABLE
|
||
TMNE QHBEG,+SL.OSL+SS.INQ(SL) ;ANY OTHER INPUT DATA AVAILABLE?
|
||
TXO T6,NSIDA ;YES, SET INTERRUPT DATA AVAILABLE
|
||
|
||
;Check for output quota
|
||
IFNSTATE T4,<RN>,CHKST4 ;IF WE'RE NOT RUNNING, DON'T ALLOW SENDS
|
||
D36OFF ;PROTECT FROM SCTRIB CALL FROM LLINKS
|
||
LOAD T2,SLOTU,(SL) ;GET # OUTPUT BUFFERS CURRENTLY IN USE
|
||
TMNE SLOTM,(SL) ;Is there an output message being filled?
|
||
SOS T2 ;Yes, allow output to continue
|
||
SKIPE DCNCON ;WE ARE CONGESTED,
|
||
JUMPG T2,CHKST3 ; ALLOW ONLY 1 OUTPUT/LINK
|
||
OPSTR <CAML T2,>,SLOTQ,(SL) ;ARE WE WITHIN THE QUOTA?
|
||
JRST CHKST3 ;NO, DON'T ALLOW SENDS
|
||
MOVEI T1,1 ;ASSUME WE'RE ALREADY USING AN OUTPUT BUFFER
|
||
JUMPG T2,CHKST1 ;JUMP IF THAT'S TRUE
|
||
MOVEI T1,2 ;WE HAVE NO OUTPUT NOW, ASSUME NO INPUT
|
||
TMNE SLINU,(SL) ;ANY INPUT BUFFERS ALLOCATED?
|
||
JRST CHKST2 ;YES, AN OUTPUT BUFFER ALREADY RESERVED
|
||
CHKST1: MOVE T2,DCNTSB ;GET TOTAL SYSTEM BUFFERS
|
||
SUB T2,DCNRSB ;SUBTRACT THOSE ALREADY USED
|
||
CAMGE T2,T1 ;ENOUGH ROOM FOR A NEW REQUEST?
|
||
JRST CHKST3 ;NO, DON'T ALLOW OUTPUT
|
||
|
||
;Check for output data requests
|
||
CHKST2: LOAD T1,SLXFL,(SL) ;GET THE TRANSMIT FLOW CONTROL OPTION
|
||
TMNN SSXDO,+SL.NSL(SL) ;NORMAL DATA REQUESTS AVAILABLE?
|
||
CAIN T1,FCM.NO ;NO, PUNT UNLESS NO FLOW CONTROL
|
||
TXO T6,NSNDR ;YES, SET NORMAL DATA REQUESTED
|
||
TMNE SSXDO,+SL.OSL(SL) ;OTHER DATA REQUESTS AVAILABLE?
|
||
TXO T6,NSIDR ;YES, SET INTERRUPT DATA REQUESTED
|
||
CHKST3: D36ON ;END CRITICAL SECTION
|
||
CHKST4:
|
||
;Fall through with new status in T6
|
||
;From previous page with new status in T6
|
||
|
||
;Note that NSFPI calls the wake routine also, and any argument changes
|
||
;must be reflected there too.
|
||
|
||
LOAD T5,SLSST,(SL) ;GET OLD STATUS
|
||
STOR T6,SLSST,(SL) ;STORE NEW STATUS
|
||
SKIPN T2,T5 ;COPY OLD STATUS
|
||
RET ;FIRST CHANGE IS NEVER "INTERESTING"
|
||
TXZ T5,^-NSSTS ;LEAVE ONLY THE STATUS BITS
|
||
IOR T5,T6 ;BITS (NEW ! OLD) + NEW STATE
|
||
XOR T5,T2 ;REVEAL INTERESTING CHANGES AS ONES IN T5
|
||
JUMPE T5,RTN ;LEAVE NOW IF NO INTERESTING CHANGES
|
||
|
||
;SLPSI is no longer in the following test incase we are e blocked at PSI level.
|
||
;SCTWKQ won't signal twice.
|
||
|
||
TMNE <SLLBC,SLFSL>,(SL) ;PSI PENDING OR LINK CLOSING?
|
||
RET ;YES, AVOID RACE
|
||
|
||
;Here if the status has changed in an interesting way
|
||
;Pick up the args for the caller's wake routine
|
||
|
||
LOAD T1,SLPSM,(SL) ;THE PSI MASK FOR THIS LINK
|
||
HRL T1,T2 ;T1 HOLDS OLD STATUS,,MASK
|
||
LOAD T2,SLCHN,(SL) ;THE LINK NUMBER
|
||
HRL T2,T6 ;T2 HOLDS NEW STATUS,,CHN NUMBER
|
||
LOAD T3,SLSJB,(SL) ;@SLWKA NEEDS T3 SET UP WITH PTR TO SJB
|
||
MOVE T4,SL ;'LINK IDENTIFIER' TO PASS TO SCTWKQ
|
||
OPSTR <SKIPE T6,>,SLWKA,(SL) ;IS THERE A WAKE ROUTINE?
|
||
CALLRET 0(T6) ;(T1,T2,T3,T4,T5)YES, CALL WAKE ROUTINE
|
||
RET ;NO, JUST RETURN
|
||
SUBTTL Subroutines -- SCTWKQ - Queue a Link for later call to SCTPSQ
|
||
|
||
;SCTWKQ - Queue a Link for later call to SCTPSQ
|
||
;
|
||
; Call: T1/ Link Identifier (SLB ptr) from @SLWKA call above
|
||
;
|
||
; Return:
|
||
; RET ;Only return
|
||
;T1 = 0 on return if SLB already queued for PSI, non-zero altered
|
||
;This routine is only called by the routine whose address is in SAWKA.
|
||
|
||
XRENT SCTWKQ ;Entry point
|
||
|
||
LOAD T3,SLSJB,(T1) ;LOAD UP SJB POINTER FOR ENDQUE BELOW
|
||
MOVX T2,SLPSI ;GET THE "QUEUED ON PSQ" FLAG
|
||
D36OFF ;#THE DEQUE ROUTINE IS NOT INTERLOCKED
|
||
TDNE T2,SL.PSI(T1) ;#IS THIS SLB ALREADY QUEUED?
|
||
JRST [SETZ T1,
|
||
JRST SCTWKX]
|
||
IORM T2,SL.PSI(T1) ;#WELL, IT IS QUEUED NOW
|
||
ENDQUE T1,SJ.PSQ(T3),SL.NXP,T2 ;#QUEUE SLB FOR SCTPSQ
|
||
SCTWKX: D36ON ;#INTERRUPTS BACK ON AGAIN
|
||
RET ;ALL DONE
|
||
SUBTTL Subroutines -- SLBMAT - Pattern match connect to passive SLBs
|
||
|
||
;SLBMAT - Pattern match a connect over all passive SLBs
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to internal connect block (see BEGSTR CB in SCPAR)
|
||
;
|
||
; Return:
|
||
; RET ;COULND'T FIND MATCHING PASSIVE SLB
|
||
; RETSKP ;FOUND ONE, POINTER TO IT IN SL
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SLBMAT: SAVEAC <P1,P2>
|
||
MOVE P1,T1 ;SAVE THE POINTER TO THE CONNECT BLOCK
|
||
SETZ P2, ;No matches so far (used to distinguish
|
||
; between 'no such object' and 'object too
|
||
; busy'
|
||
LOAD SL,QHBEG,+SCTASQ ;GET PTR TO FIRST SLB ON ALL SLBs QUEUE
|
||
SLBMA1: JUMPE SL,[MOVE T1,P2 ;If no more SLB's, load return code
|
||
RET] ; and fail return
|
||
JN <SLFSL,SLLBC>,(SL),SLBMA2 ;IF LINK IS BEING CLOSED, IGNORE IT
|
||
|
||
;We try to match the connect no matter wait the link state is.
|
||
; If we get a success return we check if the state is CW. If so, all is well.
|
||
; If not, we know that we had an 'object too busy' reject instead of a
|
||
; 'no such object'.
|
||
|
||
CALL SLBMAS ;COMPARE SLB WITH RECEIVED CONNECT BLK
|
||
JRST SLBMA2 ;NO MATCH
|
||
LOAD T1,SLSTA,(SL) ;GET THE SLB'S STATE
|
||
IFSTATE T1,CW,RSKP ;IF IT'S IN CONNECT WAIT, THEN MATCH
|
||
TMNE SLPAS,(SL) ;Was this a passive task?
|
||
SETO P2, ; -yes, flag 'object too busy'
|
||
|
||
SLBMA2: LOAD SL,SLASQ,(SL) ;STEP TO NEXT SLB ON ALL SLBs Q
|
||
JRST SLBMA1 ;AND TRY IT
|
||
|
||
;Check a SLB
|
||
|
||
SLBMAS: SAVEAC <T3,T4> ;SAVE T3 AND T4 FOR A WHILE
|
||
MOVE T2,P1 ;POINT TO THE INCOMING CONNECT BLOCK
|
||
LOAD T1,SLCBP,(SL) ;POINT TO THE SLB'S CONNECT BLOCK
|
||
JUMPN T1,CDBMAT ;If there is a connect block, then go
|
||
; and check it out. CDBMAT returns +1 or +2.
|
||
;No connect block - link is not in CW state. Check if the object numbers
|
||
; match.
|
||
XMOVEI T2,CB.DST(T2) ;Point to the dest pb source
|
||
LOAD T2,PBOBJ,(T2) ;Get dest obj number
|
||
OPSTR <CAME T2,>,SLDOB,(SL) ;The same object numbers?
|
||
RET ; -no, return failure
|
||
RETSKP ;-yes, return success
|
||
|
||
SUBTTL Subroutines -- CDBMAT - Match Two Connect Blocks
|
||
|
||
;CDBMAT - Match two internal connect blocks
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to passive SLB's connect block
|
||
; T2/ Pointer to incoming connect block
|
||
;
|
||
; Return:
|
||
; RET ;THEY DON'T MATCH
|
||
; RETSKP ;FOUND A MATCH
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
CDBMAT: SAVEAC <P1,P2> ;SAVE SOME PEAS
|
||
DMOVE P1,T1 ;SAVE THE POINTERS TO THE CONNECT BLOCKS
|
||
|
||
;Try to match the destination end names with each other.
|
||
|
||
XMOVEI T5,CB.DST(P1) ;POINT TO THE DEST PB PATTERN (PASSIVE)
|
||
XMOVEI T6,CB.DST(P2) ;POINT TO THE DEST PB SOURCE
|
||
CALL CDBMTP ;COMPARE THE DEST END NAME DESCRIPTOR
|
||
RET ;NOW GIVE ERROR RETURN
|
||
|
||
;Both of the end descriptors have matched. Now let's try to match the
|
||
;remainder of the fields in the connect data. First:
|
||
|
||
;RQSTRID
|
||
|
||
LOAD T1,CBUCT,(P1) ;GET THE PASSIVE RQSTRID COUNT
|
||
XMOVEI T2,CB.UID(P1) ;POINT TO THE WORD ALIGNED RQSTRID STRING
|
||
LOAD T3,CBUCT,(P2) ;GET THE SOURCE RQSTRID COUNT
|
||
XMOVEI T4,CB.UID(P2) ;POINT TO THE WORD ALIGNED STRING
|
||
CALL STRMAT ;TRY TO MATCH THE STRING
|
||
RET ;A MISMATCH
|
||
|
||
;PASSWRD
|
||
|
||
LOAD T1,CBPCT,(P1) ;GET THE PASSIVE PASSWRD COUNT
|
||
XMOVEI T2,CB.PSW(P1) ;POINT TO THE WORD ALIGNED PASSWRD STRING
|
||
LOAD T3,CBPCT,(P2) ;GET THE SOURCE STRING COUNT
|
||
XMOVEI T4,CB.PSW(P2) ;POINT TO THE WORD ALIGNED STRING
|
||
CALL STRMAT ;TRY TO MATCH THEM
|
||
RET ;MISMATCH
|
||
|
||
;ACCOUNT
|
||
|
||
LOAD T1,CBACT,(P1) ;GET THE PASSIVE ACCOUNT COUNT
|
||
XMOVEI T2,CB.ACC(P1) ;POINT TO THE WORD ALIGNED ACCOUNT STRING
|
||
LOAD T3,CBACT,(P2) ;GET THE SOURCE STRING COUNT
|
||
XMOVEI T4,CB.ACC(P2) ;POINT TO THE WORD ALIGNED STRING
|
||
CALL STRMAT ;TRY TO MATCH THEM
|
||
RET ;MISMATCH
|
||
|
||
;USRDATA
|
||
|
||
LOAD T1,CBCCT,(P1) ;GET THE PASSIVE USER CONNECT DATA COUNT
|
||
XMOVEI T2,CB.UDA(P1) ;POINT TO THE WORD ALIGNED USER DATA STRING
|
||
LOAD T3,CBCCT,(P2) ;GET THE SOURCE STRING COUNT
|
||
XMOVEI T4,CB.UDA(P2) ;POINT TO THE WORD ALIGNED STRING
|
||
CALLRET STRMAT ;TRY TO MATCH THE STRINGS AND RETURN
|
||
;CDBMTP - Subroutine to match process descriptor blocks
|
||
;
|
||
;Call:
|
||
; T5/ Pointer to the passive (or pattern) connect block
|
||
; T6/ Pointer to the source (or incoming) connect block
|
||
|
||
CDBMTP: LOAD T1,PBOBJ,(T5) ;GET THE PASSIVE GUY'S OBJECT TYPE
|
||
OPSTR <CAME T1,>,PBOBJ,(T6) ;MUST BE THE SAME AS THE SOURCE'S
|
||
RET ;MISMATCH
|
||
|
||
;Get the format type, do a range check and dispatch.
|
||
|
||
LOAD T1,PBFOR,(T5) ;GET THE PASSIVE FORMAT TYPE
|
||
OPSTR <CAME T1,>,PBFOR,(T6) ;DOES IT MATCH?
|
||
RET ;NO, WE HAVE A MISMATCH
|
||
CAIL T1,FRM.0 ;RANGE CHECK THE
|
||
CAILE T1,FRM.MX ; FORMAT TYPE
|
||
RETSKP ; - should never happen, just RSKP
|
||
CALLRET @.+1(T1) ;DISPATCH ON FORMAT TYPE
|
||
IFIW <RSKP&777777> ;FORMAT TYPE 0
|
||
IFIW <CDBMP1&777777> ;FORMAT TYPE 1
|
||
IFIW <CDBMP2&777777> ;FORMAT TYPE 2
|
||
|
||
;Here to match format 1s. We already matched the object type, so just match
|
||
;the NAME field.
|
||
|
||
CDBMP1: LOAD T1,PBNCT,(T5) ;GET THE PASSIVE COUNT
|
||
XMOVEI T2,PB.NAM(T5) ;POINT TO THE WORD ALIGNED STRING
|
||
LOAD T3,PBNCT,(T6) ;GET THE SOURCE STRING COUNT
|
||
XMOVEI T4,PB.NAM(T6) ;POINT TO THE WORD ALIGNED STRING
|
||
CALLRET STRMAT ;TRY TO MATCH THE STRING
|
||
|
||
;Here to match format 2s. We have already matched the object type. Compare
|
||
;the GRPCODE and USRCODE fields, allowing zeroes in either field to act as
|
||
;wildcards.
|
||
|
||
CDBMP2:
|
||
|
||
IFN <PB.USR-PB.GRP>,<
|
||
IF2,<PRINTX ?GRPCODE and USRCODE must be in the same word>>
|
||
|
||
MOVE T1,PB.USR(T5) ;GET THE PASSIVE USRCODE AND GRPCODE
|
||
MOVE T2,PB.USR(T6) ; AND THE SOURCE ONE
|
||
TLNE T1,-1 ;A ZERO IN THE LEFT OF PASSIVE
|
||
TLNN T2,-1 ; OR LEFT OF SOURCE?
|
||
HLL T1,T2 ;YES, MAKE BOTH THE SAME
|
||
TRNE T1,-1 ;A ZERO IN THE RIGHT OF PASSIVE
|
||
TRNN T2,-1 ; OR RIGHT OF SOURCE?
|
||
HRR T1,T2 ;YES, MAKE BOTH THE SAME
|
||
CAME T1,T2 ;ARE THEY THE SAME?
|
||
RET ;MISMATCH
|
||
;Now try to match the DESCRPT fields.
|
||
|
||
LOAD T1,PBNCT,(T5) ;GET THE PASSIVE COUNT
|
||
XMOVEI T2,PB.NAM(T5) ;POINT TO THE WORD ALIGNED STRING
|
||
LOAD T3,PBNCT,(T6) ;GET THE SOURCE STRING COUNT
|
||
XMOVEI T4,PB.NAM(T6) ;POINT TO THE WORD ALIGNED STRING
|
||
CALLRET STRMAT ;TRY TO MATCH THE STRING
|
||
SUBTTL Subroutines -- STRMAT - Pattern Matcher
|
||
|
||
;STRMAT - Routine to perform a pattern match
|
||
;
|
||
; Call:
|
||
; T1/ Length of pattern
|
||
; T2/ Pointer to start of word aligned pattern string (not a BP)
|
||
; T3/ Length of source string
|
||
; T4/ Pointer to start of word aligned source string (not a BP)
|
||
;
|
||
; Return:
|
||
; RET ;FAILURE TO MATCH OR TOO MANY "*"S IN PATTERN
|
||
; RETSKP ;PATTERN MATCHED STRING
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;The special "pattern-matching" characters are:
|
||
;
|
||
; ? Match the next source character.
|
||
; * Match zero or more next source characters.
|
||
; ^V (Control-V) Treat the next pattern character as
|
||
; a normal character even if it is a "?" or a "*".
|
||
;
|
||
;Note: This routine uses four words of stack for every "*" contained
|
||
;within the pattern. Also note that we are assuming one word byte
|
||
;pointers. This is the same algorithm that TSKSER (in TOPS-10) uses.
|
||
;Also note that a null pattern will match anything.
|
||
|
||
P0==SL ;WE NEED ONE MORE AC
|
||
STRMAX==^D4 ;MAXIMUM LEVEL OF RECURSION
|
||
|
||
STRMAT: JUMPE T1,RSKP ;NULL PATTERN MATCHES EVERYTHING
|
||
SAVEAC <P0,P1,P2,P3>
|
||
MOVE P1,T2 ;KEEP WORD ALIGNED POINTER TO PATTERN IN P1
|
||
MOVE P2,T4 ; TO SOURCE STRING IN P2
|
||
SETZ P3, ;USE P3 AS A RECURSION COUNTER
|
||
MOVX T2,<POINT 8,(P1)> ;SET UP INDEXED BYTE POINTER TO PATTERN
|
||
MOVX T4,<POINT 8,(P2)> ; TO SOURCE STRING ALSO
|
||
MOVE P0,P ;SAVE THE STACK POINTER
|
||
ADJSP P0,4 ;THIS IS ZERO LEVEL
|
||
|
||
STRMT1: ADJSP P,4 ;SAVE THE
|
||
DMOVEM T1,-3(P) ; SOURCE AND
|
||
DMOVEM T3,-1(P) ; PATTERN DESCRIPTORS
|
||
AOJ P3, ;INCREMENT THE RECURSION COUNTER
|
||
CAILE P3,STRMAX ;ARE WE TOO FAR DOWN?
|
||
JRST STRMTF ;WE FAILED
|
||
|
||
STRMT2: SOJL T1,[SOJL T3,STRMTS ;IF BOTH STRINGS ARE NULL, RETURN SUCCESS
|
||
JRST STRMT3] ;IF SOURCE STRING TOO LONG, BACK UP
|
||
ILDB T5,T2 ;GET THE NEXT PATTERN CHARACTER
|
||
CAIN T5,"*" ;SEE IF IT'S A STAR
|
||
JRST STRMT1 ;IT IS, GO RECURSE
|
||
CAIN T5,"?" ;SEE IF IT'S A WILDCARD CHARACTER
|
||
JRST [SOJL T3,STRMTF ;IF SO, COUNT ONE SOURCE CHAR, FAIL IF NONE
|
||
IBP T4 ;SKIP OVER NEXT SOURCE CHAR
|
||
JRST STRMT2] ; AND CONTINUE MATCHING WITH NEXT CHARACTER
|
||
CAIN T5,"V"-100 ;IS IT A ^V?
|
||
JRST [SOJL T1,STRMTF ;IF SO, COUNT OFF ON PATTERN CHARACTER
|
||
ILDB T5,T2 ;GET THE NEXT "QUOTED" CHARACTER
|
||
JRST .+1] ; AND CONTINUE WITH THE MATCH
|
||
SOJL T3,STRMTF ;COUNT OFF SOURCE CHARACTER, FAIL IF NONE
|
||
ILDB T6,T4 ;GET THE NEXT SOURCE CHARACTER
|
||
CAIL T6,"A"+40 ;IS IT
|
||
CAILE T6,"Z"+40 ; LOWER CASE?
|
||
CAIA ;NO
|
||
SUBI T6,40 ;YES, MAKE UPPER CASE
|
||
CAIL T5,"A"+40 ;IS IT
|
||
CAILE T5,"Z"+40 ; LOWER CASE?
|
||
CAIA ;NO
|
||
SUBI T5,40 ;YES, MAKE UPPER CASE
|
||
XORI T5,(T6) ;COMPARE THE CHARACTERS
|
||
TRNN T5,177 ; BUT ONLY LOOK AT LOW 7 BITS
|
||
JRST STRMT2 ;IF THEY MATCH, COMPARE NEXT CHARACTERS
|
||
|
||
;Here when characters don't match.
|
||
|
||
STRMT3: CAMN P,P0 ;ARE WE AT LEVEL ZERO?
|
||
JRST STRMTF ;NO, MATCH FAILED
|
||
DMOVE T1,-3(P) ; PATTERN AND THE
|
||
DMOVE T3,-1(P) ; SOURCE
|
||
SOJL T3,STRMTF ;WE ARE PROCESSING A "*", EAT ONE MORE
|
||
IBP T4 ; SOURCE CHARACTER
|
||
DMOVEM T3,-1(P) ;REMEMBER THE UPDATED SOURCE
|
||
JRST STRMT2 ;NO TRY TO COMPARE AGAIN
|
||
|
||
;STRMTF on failure, STRMTS on success
|
||
|
||
STRMTF: SETO T6, ;WHEN T6 IS NON-ZERO, WE FAILED
|
||
TRNA ;MERGE WITH OTHER SUCCESS
|
||
STRMTS: SETZ T6, ;SIGNAL SUCCESS
|
||
ASH P3,2 ;MULTIPLY RECURSION COUNTER BY FOUR
|
||
MOVNS P3 ;NEGATE IT
|
||
ADJSP P,(P3) ;GO BACK TO TOP LEVEL
|
||
ADJSP P0,-4 ;BACK TO TOP LEVEL FROM ZERO LEVEL
|
||
IFN FTDEBUG <
|
||
CAME P,P0 ;I GET PARANOID ABOUT STACKS
|
||
BUG.(CHK,SCLSMS,SCLINK,SOFT,<STRMAT messed up the stack pointer>,,<
|
||
|
||
Cause: This BUG is for debugging purposes only and will not be present in
|
||
a production monitor.
|
||
|
||
>,RTN)
|
||
>
|
||
JUMPN T6,RTN ;GIVE BAD RETURN ON FAILURE
|
||
RETSKP ; AND GIVE SUCCESS RETURN
|
||
SUBTTL Subroutines -- STPTMR - Stop the Connect Initiate Timer
|
||
|
||
;STPTMR - Stop the Connect Initiate Timer, adjusting timer counts
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to the SLB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2
|
||
;
|
||
;This is called even when the CI timer isn't running.
|
||
|
||
STPTMR: JE SLCTM,(SL),RTN ;IF TIMER ISN'T GOING, JUST RETURN
|
||
SETZRO SLCTM,(SL) ;ZERO THE CONNECT TIMER
|
||
SOSGE SCTCTA ;DECREMENT THE GLOBAL TIMER COUNT
|
||
SETZM SCTCTA ; - went negative, should never happen, fix
|
||
LOAD T2,SLSJB,(SL) ;POINT TO THE SJB
|
||
OPSTRM <SOS T1,>,SJCTA,(T2) ;DECREMENT THE JOB'S TIMER COUNT
|
||
JUMPGE T1,RTN ;RETURN IF COUNT IS OK
|
||
SETZRO SJCTA,(T2) ; -should never happen, fix
|
||
RET
|
||
|
||
SUBTTL Subroutines -- STRTMR - Start the Connect Initiate Timer
|
||
|
||
;STRTMR - Start the Connect Initiate Timer, adjusting all timer counts
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to SLB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2
|
||
;
|
||
;It is illegal to start a CI timer that has already been started.
|
||
|
||
STRTMR: CALL DNGTIM ;GET THE CURRENT TIME
|
||
STOR T1,SLCTM,(SL) ;STORE THE CURRENT TIME
|
||
AOS SCTCTA ;INCREMENT THE GLOBAL TIMER COUNT
|
||
LOAD T1,SLSJB,(SL) ;GET POINTER TO SJB
|
||
INCR SJCTA,(T1) ;INCREMENT THE JOB'S TIMER COUNT
|
||
RET ;RETURN
|
||
SUBTTL Subroutines -- TMRREJ - Send a Reject with Reason RSNNRO
|
||
|
||
;TMRREJ - Reject a Connect with reason RSNNRO
|
||
;
|
||
; Call:
|
||
; SL/ Pointer to Session Control Link Block
|
||
;
|
||
; Return:
|
||
; RET ;ON ALLOCATION FAILURE - TRY AGAIN LATER
|
||
; RETSKP ;ON SUCCESS - STOP THE TIMER
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
TMRREJ: SAVEAC <MB,MS> ;SAVE SOME ACS
|
||
TRACE SC,<Rejecting connect due to lack of response from object>
|
||
MOVX T1,2 ;WE NEED ONLY TWO BYTES
|
||
CALL DNGMSG ;GET A MESSAGE BLOCK
|
||
RET ;COULDN'T GET IT, TRY AGAIN LATER
|
||
MOVE MB,T1 ;POINT TO THE MESSAGE BLOCK
|
||
|
||
XMOVEI T1,UD.MSD(MB) ;POINT TO THE USER DATA AREA
|
||
CALL DNPINI ;INITIALIZE TO PUT BYTES IN MESSAGE
|
||
|
||
MOVX T1,RSNNRO ;REASON IS "NO RESPONSE FROM OBJECT"
|
||
STOR T1,SLRSN,(SL) ;TELL USER THAT REASON AND
|
||
CALL DNP2BY ; PUT IT IN MESSAGE TOO
|
||
|
||
LOAD T1,SLPID,(SL) ;GET THE NSPpid
|
||
MOVX T3,NV.REJ ;FUNCTION IS REJECT
|
||
MOVE T4,MB ;POINT TO THE MESSAGE BLOCK
|
||
CALL NSP ;CALL NSP TO REJECT THE CONNECT
|
||
NEWSTATE LK ;GO INTO NO LINK STATE
|
||
SETZRO SLPID,(SL) ;NSP HAS FORGOTTEN THIS LINK DUE TO REJECT
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL Subroutines -- BLDCTX - Build connect message
|
||
|
||
;BLDCTX - Build the connect message from an internal connect block
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to the internal connect block (See BEGSTR CB in SCPRM)
|
||
;
|
||
; Return:
|
||
; RET ;RANGE CHECKING FOUND ILLEGAL CONNECT INFO
|
||
; RETSKP ;EVERYTHING'S ALRIGHT
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;Note: We are assuming that DNPINI has already been called and that we can
|
||
;just do DNPxBYs to dump bytes into the message.
|
||
|
||
BLDCTX: SAVEAC <P1,P2> ;SAVE TWO PEAS
|
||
MOVE P1,T1 ;SAVE THE POINTER TO THE CONNECT BLOCK
|
||
XMOVEI P2,CB.DST(P1) ;BUILD THE
|
||
CALL BLDCTP ; DESTINATION END USER NAME
|
||
RET ;BAD FORMAT
|
||
XMOVEI P2,CB.SRC(P1) ;BUILD THE
|
||
CALL BLDCTP ; SOURCE END USER NAME
|
||
RET ;BAD FORMAT
|
||
|
||
;Here to build the MENUVER word.
|
||
|
||
SETZB T3,T4 ;BUILD MENUVER IN T4, FLAG FOR MNRPA IN T3
|
||
OPSTR <IOR T3,>,CBUCT,(P1) ;ANY RQSTRID?
|
||
OPSTR <IOR T3,>,CBPCT,(P1) ;ANY PASSWRD?
|
||
OPSTR <IOR T3,>,CBACT,(P1) ;ANY ACCOUNT?
|
||
SKIPE T3 ;SHOULD WE SAY THOSE FIELDS ARE INCLUDED?
|
||
TXO T4,MNRPA ;YES, SET BIT
|
||
TMNE CBCCT,(P1) ;ANY USRDATA?
|
||
TXO T4,MNUSR ;YES, SET THE BIT TO INDICATE THIS
|
||
|
||
MOVX T1,SC.VER ;GET THE VERSION OF SESSION CONTROL
|
||
STOR T1,MNVER,+T4 ;STORE IT IN THE VERSION FIELD
|
||
MOVE T1,T4 ;PUT IT IN T1 FOR DNPEBY
|
||
CALL DNPEBY ;PLACE THE MENUVER EXTENSIBLE BYTE IN MESSAGE
|
||
|
||
TXNN T4,MNRPA ;WAS RQSTRID, PASSWRD OR ACCOUNT SET?
|
||
JRST BLDCT1 ;NO, DON'T INCLUDE THEM
|
||
;Now put in the User ID, Password, etc.
|
||
|
||
LOAD T1,CBUCT,(P1) ;GET THE RQSTRID BYTE COUNT
|
||
XMOVEI T2,CB.UID(P1) ;POINT TO THE STRING
|
||
CALL PUTSTR ;PUT THE STRING IN THE MESSAGE
|
||
|
||
LOAD T1,CBPCT,(P1) ;GET THE PASSWRD BYTE COUNT
|
||
XMOVEI T2,CB.PSW(P1) ;POINT TO THE PASSWORD
|
||
CALL PUTSTR ;PUT IT IN THE MESSAGE
|
||
|
||
LOAD T1,CBACT,(P1) ;GET THE ACCOUNT BYTE COUNT
|
||
XMOVEI T2,CB.ACC(P1) ;POINT TO THE ACCOUNT STRING
|
||
CALL PUTSTR ;PUT IT IN THE MESSAGE
|
||
|
||
BLDCT1: TXNN T4,MNUSR ;IS THERE ANY USRDATA?
|
||
RETSKP ;NO, JUST RETURN
|
||
|
||
LOAD T1,CBCCT,(P1) ;GET THE USRDATA BYTE COUNT
|
||
XMOVEI T2,CB.UDA(P1) ;POINT TO THE ACCOUNT STRING
|
||
CALL PUTSTR ;PUT IT IN THE MESSAGE
|
||
RETSKP ; AND RETURN
|
||
;BLDCTP - Subroutine for BLDCTX to build end user name from process block
|
||
;
|
||
; Call:
|
||
; P2/ Pointing to the process descriptor block
|
||
|
||
BLDCTP: LOAD T1,PBFOR,(P2) ;GET THE FORMAT TYPE
|
||
CAIL T1,FRM.0 ;DO SOME
|
||
CAILE T1,FRM.MX ; RANGE CHECKING
|
||
RET ;BAD CONNECT BLOCK
|
||
MOVE T4,T1 ;SEMI-PRESERVE THE FORMAT
|
||
CALL DNP1BY ;PLACE THE BYTE IN THE MESSAGE
|
||
CALL @[IFIW <BLDCP1&777777> ;DISPATCH BY THE FORMAT TYPE
|
||
IFIW <BLDCP2&777777> ;
|
||
IFIW <BLDCP4&777777>](T4) ;
|
||
RET ;ERROR RETURN
|
||
RETSKP ;SUCCESS RETURN
|
||
|
||
;Here to process a end user name format 0. This just consists
|
||
;of a non-zero one byte object type.
|
||
|
||
BLDCP1: OPSTR <SKIPN T1,>,PBOBJ,(P2) ;MUST HAVE AN OBJECT TYPE
|
||
RET ;DIDN'T - ILLEGAL CONNECT BLOCK
|
||
CALL DNP1BY ;PLACE THE OBJECT TYPE IN
|
||
RETSKP ; AND WE'RE DONE
|
||
|
||
;Here to process a end user name format 1. This format is a
|
||
;zero object type followed by a I-16 name field.
|
||
|
||
BLDCP2: JN PBOBJ,(P2),RTN ;OBJECT TYPE MUST BE ZERO
|
||
SETZ T1, ;GET A ZERO FOR THE OBJECT TYPE
|
||
CALL DNP1BY ;STORE OBJECT TYPE IN MESSAGE
|
||
MOVX T3,^D16 ;MAX LENGTH NAME IS 16 BYTES
|
||
|
||
BLDCP3: LOAD T1,PBNCT,(P2) ;GET THE COUNT OF NAME BYTES
|
||
CAMLE T1,T3 ;RANGE CHECK THE LENGTH
|
||
MOVE T1,T3 ;OOPS, OVERFLOWED, USE MAXIMUM ALLOWED LENGTH
|
||
XMOVEI T2,PB.NAM(P2) ;POINT TO THE STRING
|
||
CALL PUTSTR ;PLACE THE STRING IN THE MESSAGE
|
||
RETSKP ;RETURN SUCCESS
|
||
|
||
;Here to process a end user name format 2. This format is a zero
|
||
;object type followed by GRPCODE (1B), USRCODE (1B) and DESCRPT (I-12).
|
||
|
||
BLDCP4: JN PBOBJ,(P2),RTN ;OBJECT TYPE MUST BE ZERO
|
||
SETZ T1, ;GET A ZERO FOR THE OBJECT TYPE
|
||
CALL DNP1BY ;STORE OBJECT TYPE IN MESSAGE
|
||
LOAD T1,PBGRP,(P2) ;GET THE GROUP CODE
|
||
CALL DNP2BY ;PLACE IT IN THE MESSAGE
|
||
LOAD T1,PBUSR,(P2) ;GET THE USER CODE
|
||
CALL DNP2BY ;PLACE IT IN THE MESSAGE
|
||
MOVX T3,^D12 ;MAXIMUM LENGTH FOR THIS GUY IS 12 BYTES
|
||
JRST BLDCP3 ;MERGE WITH THE COMMON CODE
|
||
;PUTSTR - Subroutine to put a string from an internal block into a message
|
||
;
|
||
; Call:
|
||
; T1/ Length of the string
|
||
; T2/ Pointer to word aligned start of string
|
||
|
||
PUTSTR: SAVEAC <P1,P2,T4> ;THIS IS A REALLY LOCAL ROUTINE
|
||
MOVE P1,T2 ;PUT THE POINTER IN P1
|
||
MOVE T4,T1 ;PRESERVE THE LENGTH FOR A WHILE
|
||
CALL DNP1BY ;PLACE THE IMAGE COUNT IN THE STRING
|
||
MOVX P2,<POINT 8,(P1)> ;BYTE POINTER TO 8 BIT STRING
|
||
SOJGE T4,[ILDB T1,P2 ;GET THE BYTE FROM CONNECT BLOCK
|
||
CALL DNP1BY ;PLACE THE BYTE IN THE MESSAGE
|
||
JRST .] ;KEEP GOING UNTIL DONE
|
||
RET ; AND THEN RETURN
|
||
SUBTTL Subroutines -- PRSCTX - Parse a connect message
|
||
|
||
;PRSCTX - Parse a connect message into an internal connect block
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to internal connect block (See BEGSTR CB in SCPRM)
|
||
; MB/ Pointer to the Message Block
|
||
; MS/ Pointer to the current MSD
|
||
;
|
||
; Return:
|
||
; RET ;ON MESSAGE FORMAT ERROR AFTER REPORTING EVENT
|
||
; RETSKP ;SUCESS, INTERNAL CONNECT BLOCK IS FILLED
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;Note: We are assuming that DNGINI has already been called and that we can
|
||
;just do DNGxBYs to get bytes from the message.
|
||
|
||
PRSCTX: SAVEAC <P1,P2> ;SAVE A COUPLE OF PEAS
|
||
MOVE P1,T1 ;PRESERVE THE POINTER TO THE CONNECT BLOCK
|
||
XMOVEI P2,CB.DST(P1) ;POINT TO THE DESTINATION PROCESS BLOCK
|
||
CALL PRSCTP ;PARSE DSTNAME PORTION OF MESSAGE
|
||
RET ;OOPS
|
||
XMOVEI P2,CB.SRC(P1) ;POINT TO THE SOURCE PROCESS BLOCK
|
||
CALL PRSCTP ;PARSE SRCNAME PORTION OF MESSAGE
|
||
RET ;COULDN'T DO IT
|
||
|
||
;Here to look at the MENUVER field and see what to parse.
|
||
|
||
CALL DNG1BY ;GET MENUVER
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
MOVE P2,T1 ;PRESERVE IT
|
||
LOAD T1,MNVER,+P2 ;GET THE VERSION NUMBER
|
||
CAIGE T1,SC.VER ;Same or greater than ours?
|
||
RET ; - error, caller will SCEIVM
|
||
TXNN P2,MNRPA ;ARE RQSTRID, PASSWRD AND ACCOUNT COMING?
|
||
JRST PRSCT1 ;NO, CHECK FOR USRDATA
|
||
|
||
;Now read the RQSTRID, PASSWRD and the ACCOUNT.
|
||
|
||
CALL DNG1BY ;GET THE LENGTH OF THE RQSTRID
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
CAILE T1,^D39 ;IS LENGTH OK?
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
STOR T1,CBUCT,(P1) ;STORE THE BYTE COUNT
|
||
XMOVEI T2,CB.UID(P1) ;PUT THE TEXT HERE
|
||
CALL GETSTR ;DO IT
|
||
RET ;Error - Caller will handle
|
||
|
||
CALL DNG1BY ;GET THE LENGTH OF THE PASSWRD
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
CAILE T1,^D39 ;IS LENGTH OK?
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
STOR T1,CBPCT,(P1) ;STORE THE BYTE COUNT
|
||
XMOVEI T2,CB.PSW(P1) ;STORE THE TEXT IN
|
||
CALL GETSTR ; THE CONNECT BLOCK
|
||
RET ;Error - Caller will handle
|
||
|
||
CALL DNG1BY ;GET THE LENGTH OF THE ACCOUNT STRING
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
CAILE T1,^D39 ;IS LENGTH OK?
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
STOR T1,CBACT,(P1) ;STORE THE BYTE COUNT
|
||
XMOVEI T2,CB.ACC(P1) ;STORE THE ACCOUNT STRING
|
||
CALL GETSTR ; IN THE CONNECT BLOCK
|
||
RET ;Error - Caller will handle
|
||
|
||
;Now check for the USRDATA field.
|
||
|
||
PRSCT1: TXNN P2,MNUSR ;IS THERE ANY USER TEXT?
|
||
RETSKP ;NO, WE'RE DONE
|
||
|
||
CALL DNG1BY ;GET THE LENGTH OF THE USRDATA
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
CAILE T1,^D16 ;IS LENGTH OK?
|
||
RET ;ERROR, CALLER WILL CALLRET SCEIVM
|
||
STOR T1,CBCCT,(P1) ;STORE THE BYTE COUNT
|
||
XMOVEI T2,CB.UDA(P1) ;PUT THE TEXT HERE
|
||
CALL GETSTR ;DO IT
|
||
RET ;Error - Caller will handle
|
||
RETSKP ;RETURN SUCCESS
|
||
;PRSCTP - Subroutine for PRSCTX to parse end user name portion of message
|
||
;
|
||
; Call:
|
||
; P2/ Pointing to the process descriptor block
|
||
|
||
PRSCTP: CALL DNG1BY ;GET THE FORMAT TYPE
|
||
RET ;ERROR, CALLER WILL RET TO CALLRET SCEIVM
|
||
CAIL T1,FRM.0 ;RANGE CHECK
|
||
CAILE T1,FRM.MX ; THE FORMAT
|
||
RET ;ERROR, CALLER WILL RET TO CALLRET SCEIVM
|
||
STOR T1,PBFOR,(P2) ;STORE IT IN THE PD BLOCK
|
||
MOVE T4,T1 ;SORT OF PRESERVE THE FORMAT
|
||
CALL DNG1BY ;GET THE OBJECT TYPE
|
||
RET ;ERROR, CALLER WILL RET TO CALLRET SCEIVM
|
||
JRST @.+1(T4) ;DISPATCH BY FORMAT TYPE
|
||
IFIW <PRSCP1&777777> ;FORMAT TYPE 0
|
||
IFIW <PRSCP2&777777> ;FORMAT TYPE 1
|
||
IFIW <PRSCP3&777777> ;FORMAT TYPE 2
|
||
|
||
;Here to parse the end user name format 0.
|
||
|
||
PRSCP1: SKIPN T1 ;IS THERE A NON-ZERO OBJECT TYPE?
|
||
RET ;ERROR, CALLER WILL RET TO CALLRET SCEIVM
|
||
STOR T1,PBOBJ,(P2) ;YES, STORE IT
|
||
RETSKP ; AND WE'RE DONE
|
||
|
||
;Here to parse the end user name format 1.
|
||
|
||
PRSCP2: CALL DNG1BY ;GET THE IMAGE COUNT
|
||
SETZ T1, ;ASSUME NO TEXT IF NO COUNT FIELD
|
||
CAILE T1,^D16 ;IS IT OF ACCEPTABLE LENGTH?
|
||
RET ;ERROR, CALLER WILL RET TO CALLRET SCEIVM
|
||
STOR T1,PBNCT,(P2) ;STORE THE COUNT OF BYTES IN NAME
|
||
JUMPE T1,RSKP ;SUCCESS NOW IF NO STRING TO GET
|
||
XMOVEI T2,PB.NAM(P2) ;POINT TO WERE TO PUT THE STRING
|
||
CALL GETSTR ;GET THE STRING INTO THE PB
|
||
RET ;Error - Caller will handle
|
||
RETSKP ; AND WE'RE DONE
|
||
;Here to parse the end user name format 2.
|
||
|
||
PRSCP3: CALL DNG2BY ;GET THE GRPCODE
|
||
RET ;ERROR, CALLER RETS TO CALLRET SCEIVM
|
||
STOR T1,PBGRP,(P2) ;STORE IT IN THE PB
|
||
CALL DNG2BY ;GET THE USRCODE
|
||
RET ;ERROR, CALLER RETS TO CALLRET SCEIVM
|
||
STOR T1,PBUSR,(P2) ;STORE IT IN THE PB
|
||
CALL DNG1BY ;GET THE IMAGE LENGTH
|
||
SETZ T1, ;NO LENGTH FIELD, ASSUME ZERO LENGTH
|
||
CAILE T1,^D14 ;IS LENGTH OK?
|
||
RET ;ERROR, CALLER RETS TO CALLRET SCEIVM
|
||
STOR T1,PBNCT,(P2) ;STORE THE BYTE COUNT
|
||
JUMPE T1,RSKP ;SUCCESS NOW IF NO MORE STRING
|
||
XMOVEI T2,PB.NAM(P2) ;POINT TO THE NAME AREA IN THE PB
|
||
CALL GETSTR ;PLACE THE STRING IN THE PB
|
||
RET ;Error - Caller will handle
|
||
RETSKP ; AND RETURN SUCCESSFULLY
|
||
;GETSTR - Get a string from the message and place it in the connect block
|
||
;
|
||
; T1/ Byte count
|
||
; T2/ Pointer to the string area in the internal connect block
|
||
|
||
GETSTR: SAVEAC <P1,P2,FREE0>
|
||
DMOVE P1,T1 ;SAVE THE BYTE COUNT AND POINTER
|
||
MOVX FREE0,<POINT 8,(P2)> ;BYTE POINTER USING FULLWORD IN P2
|
||
SOJGE P1,[CALL DNG1BY ;GET THE BYTE
|
||
RET ;Return the error
|
||
IDPB T1,FREE0 ;STORE IN CONNECT BLOCK
|
||
JRST .] ; AND CONTINUE UNTIL WE RUN OUT
|
||
RETSKP ;RETURN
|
||
|
||
;GETSTP performs the same function but takes the data from a string.
|
||
;
|
||
; Call:
|
||
; T1/ Count
|
||
; T2/ Fullword Pointer
|
||
; T3/ String Block Address (word aligned)
|
||
;
|
||
; Return:
|
||
; RET ;WITH STRING IN BLOCK
|
||
|
||
GETSTP: SAVEAC <P1,P2> ;SAVE FOR BYTE POINTERS
|
||
DMOVE P1,[POINT 8,0(T2)
|
||
POINT 8,0(T3)];BYTE POINTERS FOR FULL WORD POINTERS
|
||
SOJGE T1,[ILDB T4,P1 ;GET A BYTE FROM STRING
|
||
IDPB T4,P2 ;PLACE IT IN THE STRING BLOCK
|
||
JRST .] ; AND CONTINUE UNTIL DONE
|
||
RET ;RETURN TO SENDER
|
||
|
||
SUBTTL Subroutines -- CPYS2M - Copy string block to message segment
|
||
|
||
;CPYS2M - Copy string block to message segment
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to SBLOCK to copy into message
|
||
; MS/ Pointer to current message segment
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;Note: CPYS2I is identical except that it doesn't put a image count into
|
||
;the message (used for interrupt data).
|
||
|
||
CPYS2M: SAVEAC P1 ;SAVE A PEA
|
||
SKIPE P1,T1 ;SAVE STRING BLOCK POINTER
|
||
LOAD T1,SBCNT,(P1) ;GET COUNT OF BYTES IN STRING
|
||
CALL DNP1BY ;PUT IMAGE COUNT IN THE MESSAGE
|
||
JUMPE P1,RTN ;IF NO STRING BLOCK, RETURN NOW
|
||
|
||
CPYS21: LOAD T1,SBCNT,(P1) ;GET THE BYTE COUNT AGAIN
|
||
MOVX T2,<<POINT 8,>!1B12> ;MAKE UP 2-WORD BYTE POINTER
|
||
XMOVEI T3,SB.DAT(P1) ;POINT TO THE DATA
|
||
CALLRET DNCB2M ;COPY STRING TO THE MESSAGE
|
||
|
||
;Here to copy interrupt data into the message block.
|
||
|
||
CPYS2I: SAVEAC P1 ;SAVE A PEA
|
||
JUMPE T1,RTN ;IF THERE'S NO DATA TO COPY, JUST RETURN
|
||
MOVE P1,T1 ;PRESERVE POINTER TO THE SBLOCK
|
||
CALLRET CPYS21 ;MERGE WITH OTHER CODE
|
||
SUBTTL Subroutines -- CPYM2S - Copy message data to string block
|
||
|
||
;CPYM2S - Copy message data to string block
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to String Block to copy into
|
||
; MS/ Pointer to current message segment
|
||
; MB/ Pointer to current message block
|
||
;
|
||
; Return:
|
||
; RET ;ON A FAILURE
|
||
; RETSKP ;SUCCESSFUL
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;Note: CPYI2S performs the same function, expcept it gets the data
|
||
;length from the remaining length of the message (used for interrupt
|
||
;data).
|
||
|
||
CPYM2S: SAVEAC <P1,P2> ;SAVE A PEA
|
||
MOVE P1,T1 ;SAVE STRING BLOCK POINTER
|
||
MOVE T1,MB ;POINT TO MESSAGE BLOCK
|
||
CALL DNLENG ;GET LENGTH OF THE MESSAGE
|
||
SOS P2,T1 ;SAVE LENGTH OF DATA IN MSG
|
||
CALL DNG1BY ;GET THE IMAGE COUNT
|
||
JRST [SETZ T1, ;IF THERE WAS NO COUNT
|
||
STOR T1,SBCNT,(P1) ; WE SHOULD RETURN A ZERO AS
|
||
RETSKP] ; BYTE COUNT IN SBLOCK
|
||
CAMLE T1,P2 ;THAT LENGTH LOOK OK?
|
||
RET ;NO, CALLER WILL CALLRET SCEIVM
|
||
|
||
CPYM21: STOR T1,SBCNT,(P1) ;STORE THE REAL COUNT
|
||
JUMPE T1,RSKP ;IF NOTHING THERE, JUST RETURN
|
||
MOVX T2,<<POINT 8,>!1B12> ;MAKE UP 2-WORD BYTE POINTER
|
||
XMOVEI T3,SB.DAT(P1) ;POINT TO THE TEXT PORTION
|
||
CALLRET DNCM2B ;COPY IT TO BUFFER AND RETURN
|
||
|
||
;Here to copy interrupt data from a message block to a string block.
|
||
|
||
CPYI2S: SAVEAC P1 ;SAVE A PEA
|
||
MOVE P1,T1 ;SAVE SBLOCK POINTER
|
||
MOVE T1,MB ;POINT TO MESSAGE BLOCK
|
||
CALL DNLENG ;GET LENGTH OF THE MESSAGE
|
||
CAILE T1,^D16 ;LEGAL INTERRUPT MSG?
|
||
RET ;NO, CALLER WILL CALLRET SCEIVM
|
||
CALLRET CPYM21 ;MERGE WITH OTHER CODE
|
||
|
||
SUBTTL Subroutines -- SCTGSS - Get segment size for a destination
|
||
|
||
;SCTGSS - get the segment size we are willing to use to a specific destination.
|
||
; Used to implement 'big buffers on the NI'.
|
||
;
|
||
; Call:
|
||
; T1/ 16-bit destination node address
|
||
; CALL SCTGSS
|
||
;
|
||
; Return:
|
||
; RET always with T1/ segment size to use
|
||
|
||
SCTGSS: CALL RTRGBS ;Get ROUTER buffer size
|
||
SUBI T1,%SCHDR ; and subtract max headers below SC
|
||
RET
|
||
|
||
SUBTTL Subroutines -- SCTCSS - Check segment size for a destination
|
||
|
||
;SCTCSS - check the segment size for a specific destination.
|
||
; Used to implement 'big buffers on the NI'
|
||
;
|
||
; Call:
|
||
; T1/ 16-bit destination node address
|
||
; T2/ the segment size the remote is willing to use
|
||
; CALL SCTCSS
|
||
;
|
||
; Return:
|
||
; RET with T1/ the segment size to use
|
||
|
||
SCTCSS: ADDI T2,%SCHDR ;Get the right value for ROUTER to compare with
|
||
CALL RTRCBS ;Ask ROUTER for value
|
||
SUBI T1,%SCHDR ; and remove header length
|
||
RET
|
||
|
||
SUBTTL Node name/number database -- Initialize
|
||
|
||
;SCTNIN - Initialize node database
|
||
; CALL SCTNIN
|
||
;
|
||
; Return:
|
||
; RET Failed to initialize
|
||
; RETSKP Success.
|
||
|
||
XSWAPCD
|
||
SCTNIN:
|
||
|
||
;The node name/number database use swappable extended section memory.
|
||
; ASGVAS is used to allocate space.
|
||
;
|
||
;At initialization time (below) the hash table and the address table
|
||
; are allocated. The layout of these are:
|
||
;
|
||
; HSHTAB ADRTAB
|
||
; ! !
|
||
; ------------------------------
|
||
; ! SCNHSZ ! RTRMXN+1 !
|
||
; ------------------------------
|
||
;
|
||
;As needed, space for the node name buckets are allocated, 1 page at
|
||
; a time. QHBUCK points to the head of free buckets:
|
||
;
|
||
; QHBUCK ---) BUNXT ---) BUNXT ---) 0
|
||
;
|
||
IFN FTOPS20,<
|
||
MOVEI T1,SCNHSZ ;Hash table size
|
||
OPSTR <ADD T1,>,IBMXA,+IBBLK ;Add max # of nodes in area
|
||
AOJ T1, ; and an extra word to offset from 0
|
||
BLCAL.(<@[MSEC1,,ASGVAS]>,<[0],T1>) ;Get unlocked extended virtual mem
|
||
BUG.(CHK,SCLVAS,SCLINK,SOFT,<Couldnt get memory>,,<
|
||
|
||
Cause: SCLINK called ASGVAS to assign virtual address space for the node
|
||
name/address database. Since the requested memory is non-resident,
|
||
this should always succeed. However, ASGVAS gave a fail return.
|
||
>,RTN) ; and return error
|
||
>; END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
CALL SCTCCR ;Get amount of core allocated
|
||
SUBI T1,1 ;Less one for XBLT count
|
||
MOVE T2,DCNVFF## ;Get starting address of core
|
||
XMOVEI T3,1(T2) ;Plus one for XBLT
|
||
SETZM (T2) ;Zero first word
|
||
CALL XBLTA## ;Zero the remainder
|
||
MOVE T1,DCNVFF## ;Get location of assigned core
|
||
>; END IFN FTOPS10
|
||
|
||
;Success return from ASGVAS, T1 has address of first location
|
||
IFN FTOPS20,<
|
||
MOVEM T1,HSHTAB ;Save hash table address
|
||
ADDI T1,SCNHSZ ;Add hash table size
|
||
>; END IFN FTOPS20
|
||
MOVEM T1,ADRTAB ;Save node address table address
|
||
IFN FTOPS10,<
|
||
OPSTR <ADD T1,>,IBMXA,+IBBLK ;Compute end of address table
|
||
ADDI T1,1 ;...
|
||
MOVEM T1,SCTMAP ;Set up pseudo map
|
||
ADD T1,SCTMPS ;Add size of pseudo map
|
||
MOVEM T1,DCNVFF## ;Update DECnet first free address
|
||
IFN FTMP,<
|
||
SNCALL (UPMM##,MCSEC1) ;Get MM for GETPHP
|
||
>; END IFN FTMP
|
||
MOVEI T3,1 ;Number of pages to allocate
|
||
SNCALL (GETPHP##,MCSEC1) ;Get a physical page
|
||
IFN FTMP,<
|
||
SNCALL (DWNMM##,MCSEC1) ;Give back MM
|
||
>; END IFN FTMP
|
||
MOVE T2,SCTMAP ;Get address of pseudo map
|
||
MOVEM T1,(T2) ;Store first entry
|
||
AOS SCTMPF ;Increment pseudo map first free
|
||
MOVX T1,MAPBAS ;Set up pseudo address of hash table
|
||
MOVEM T1,HSHTAB ;...
|
||
>; END IFN FTOPS10
|
||
|
||
;No buckets yet
|
||
SETZM QHBUCK ;Clear bucket header
|
||
|
||
;Unlock the node database
|
||
IFN FTOPS20,< UNLOCK NODLOK>
|
||
|
||
;Insert executor node name and address into database
|
||
LOAD T1,IBNAM,+IBBLK ;Get sixbit executor name
|
||
LOAD T2,IBADR,+IBBLK ; and executor address
|
||
CALLRET SCTAND ;Insert them into database and return
|
||
|
||
SUBTTL Node name/number database -- Lock/unlock database
|
||
|
||
;LOKNOD - Lock/unlock node database
|
||
;
|
||
;This is a coroutine (like a SAVEAC) that locks the node database
|
||
;
|
||
; Call: JSP CX,LOKNOD
|
||
;
|
||
; Return: forwards a +1 or +2 return
|
||
;
|
||
; Must be called in process context, without already having the lock.
|
||
|
||
LOKNOD:
|
||
IFN FTOPS10,<JRST (CX)>
|
||
IFN FTOPS20,<
|
||
PUSH P,CX ;Save PC for a little while
|
||
LOCK NODLOK ;Lock the database, wait if necessary
|
||
NOINT ;No user interrupts while we have lock
|
||
CSKED ;Go CSKED since we have a system resource
|
||
POP P,CX ;Retrieve PC
|
||
CALL 0(CX) ;Call processing routine
|
||
IFNSK. ; +1 return
|
||
UNLOCK NODLOK ; Unlock,
|
||
OKINT ; allow interrupts
|
||
ECSKED ; and exit critical section
|
||
RET ; and pass on +1 return
|
||
ELSE. ; +2 return
|
||
UNLOCK NODLOK ; Unlock
|
||
OKINT ; allow interrupts
|
||
ECSKED ; and exit critical section
|
||
RETSKP ; and pass on +2 return
|
||
ENDIF.
|
||
;Can never get here
|
||
> ;END IFN FTOPS20
|
||
|
||
SUBTTL Node name/number database -- Add a node
|
||
|
||
;SCTAND - Add a node name to the database
|
||
;
|
||
; Call: T1/ node name (in sixbit). Zero to clear
|
||
; T2/ Node address. If area # is not present, it will be
|
||
; to local area.
|
||
; CALL SCTAND
|
||
;
|
||
; Return:
|
||
; RET Name already taken, or node address out of range
|
||
; RETSKP Node name and address added to the database
|
||
|
||
XSWAPCD
|
||
SCTAND: SAVEAC <T6,P1,P2>
|
||
JSP CX,LOKNOD ;Lock node database
|
||
DMOVE P1,T1 ;Save node name and address in P1,P2
|
||
CALL CHKADR ;Check address, and default area if needed
|
||
RET ; -bad address, pass on error code
|
||
|
||
;P2 now contains a node address with area #, T6 is non-zero if area = home area
|
||
|
||
;Delete option?
|
||
JUMPE P1,SCTDND ;Go delete a node
|
||
|
||
;Check if the node already exists in the database
|
||
CALL NAM2NO ;Map node name to NO pointer
|
||
JRST SCTAN1 ; -no, go check address before adding node
|
||
|
||
;Here to change a node, T1 points to NO block
|
||
;
|
||
;Are we changing executor (not allowed unless changing to same..)
|
||
LOAD T2,NOADR,(T1) ;Get node address
|
||
OPSTR <CAME T2,>,IBADR,+IBBLK ;Executor?
|
||
IFSKP. ; -yes,
|
||
LOAD T2,NONAM,(T1) ; Get node name
|
||
OPSTR <CAME T2,>,IBNAM,+IBBLK ; Same as before?
|
||
RNMXER (NF.CWS) ; -no, not allowed, component in wrong st.
|
||
RETSKP ; -yes, say its ok
|
||
ENDIF.
|
||
|
||
;Is the node number we are replacing in the local area. If so, delete pointer
|
||
; from ADRTAB
|
||
LDAREA T3,T2 ;Get old area number
|
||
CAME T3,RTRHOM ;IS it local area?
|
||
IFSKP. ; -yes, must delete old pointer in ADRTAB
|
||
LDNODE T3,T2 ; Get local node index
|
||
ADD T3,ADRTAB ; and add in ADRTAB base address
|
||
SETZM (T3) ; and clear the link
|
||
SOS SCTNDC ; and one less local node
|
||
ENDIF.
|
||
|
||
;Now write the new node address into the tables
|
||
STOR P2,NOADR,(T1) ;Store new node address
|
||
|
||
;If we are adding to local area, update ADRTAB
|
||
SKIPN T6 ;Home area?
|
||
IFSKP. ; -yes,
|
||
LDNODE T2,P2 ; Get new local node index
|
||
ADD T2,ADRTAB ; and add address table address
|
||
IFN FTOPS10,<
|
||
CALL UMPBUC ; Compute unmapped address
|
||
>; END IFN FTOPS10
|
||
MOVEM T1,(T2) ; and store NO pointer in address table
|
||
AOS SCTNDC ; Increment # of local nodes defined
|
||
ENDIF.
|
||
|
||
;All done, return
|
||
RETSKP
|
||
|
||
;SCTAN1 - node name is not in database
|
||
SCTAN1: SKIPN T6 ;Home area?
|
||
IFSKP. ; -yes,
|
||
LDNODE T2,P2 ; Get node index
|
||
ADD T2,ADRTAB ; and get pointer into address table
|
||
SKIPE (T2) ; Entry non-zero?
|
||
RNMXER (NF.CWS) ; -yes, not allowed
|
||
ENDIF.
|
||
|
||
;Find the hash index for this node name
|
||
CALL HSHNAM ;Get the hash index
|
||
ADD T1,HSHTAB ; and make address of hash table entry
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map entry
|
||
>; END IFN FTOPS10
|
||
SKIPN (T1) ;Is there a hash chain already?
|
||
JRST SCTAN2 ; -no, go add a hash chain
|
||
|
||
;There is a hash chain, search buckets for an empty slot, or end of chain
|
||
MOVE T1,(T1) ;Point to first bucket
|
||
DO. ;LOOP over buckets
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map unmapped bucket
|
||
>; END IFN FTOPS10
|
||
XMOVEI T2,BU.NO1(T1) ; Point to first NO block in bucket
|
||
MOVX T3,NRNOPB ; # of NO blocks/bucket
|
||
DO. ; LOOP over NO blocks
|
||
OPSTR <SKIPE>,NONAM,(T2) ;Is node name clear?
|
||
IFSKP. ; -yes,
|
||
STOR P1,NONAM,(T2) ; store name
|
||
STOR P2,NOADR,(T2) ; and address
|
||
JRST SCTAN3 ; Go join common code to update ADRTAB
|
||
ENDIF.
|
||
ADDI T2,NO.LEN ; Move to next NO block
|
||
SOJG T3,TOP. ; And loop back if more to do
|
||
ENDDO.
|
||
OPSTR <SKIPN T2,>,BUNXT,(T1) ;Go to next bucket, if any
|
||
EXIT. ; -no, exit with T1/ last bucket
|
||
MOVE T1,T2 ; -yes, bucket pointer in T1
|
||
LOOP. ; and loop back
|
||
ENDDO.
|
||
|
||
;Come here of there are no more buckets, T1 points to last one
|
||
|
||
;SCTAN2 - add a hash chain, T1 has address of hash entry
|
||
SCTAN2: ASSUME BU.NXT,EQ,0
|
||
MOVE T4,T1 ;"Save" bucket pointer in T4
|
||
IFN FTOPS10,<
|
||
CALL UMPBUC ;Compute unmapped address
|
||
EXCH T1,T4 ;Save in T4
|
||
>; END IFN FTOPS10
|
||
CALL GETBUC ; and get a bucket
|
||
RNMXER (NF.RES) ; -failed (!!)
|
||
XMOVEI T2,BU.NO1(T1) ;Point to first NO block in bucket
|
||
STOR P1,NONAM,(T2) ; and store node name
|
||
STOR P2,NOADR,(T2) ; and node address
|
||
IFN FTOPS10,<
|
||
CALL UMPBUC ;Compute unmapped bucket address
|
||
EXCH T1,T4 ;Save unmapped address, get original bucket
|
||
CALL MAPBUC ;Map original bucket
|
||
EXCH T1,T4 ;Swap around again
|
||
>; END IFN FTOPS10
|
||
STOR T1,BUNXT,(T4) ;Link new bucket into chain
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ;Map new bucket again
|
||
>; END IFN FTOPS10
|
||
; JRST SCTAN3 ;Go join common code to update ADRTAB
|
||
|
||
;SCTAN3 - update address table with a new node. NO pointer in T2
|
||
SCTAN3: JUMPE T6,RSKP ;No more to do if not home area
|
||
LDNODE T1,P2 ;Get local node index
|
||
ADD T1,ADRTAB ; and add address table address
|
||
IFN FTOPS10,<
|
||
EXCH T1,T2 ;Get mapped bucket address
|
||
CALL UMPBUC ;Compute unmapped bucket address
|
||
EXCH T1,T2 ;...
|
||
>; END IFN FTOPS10
|
||
MOVEM T2,(T1) ;Store NO pointer
|
||
AOS SCTNDC ;Increment # of local nodes known
|
||
RETSKP ; and done
|
||
|
||
;SCTDND - delete a node
|
||
SCTDND: OPSTR <CAMN P2,>,IBADR,+IBBLK ;Deleting executor?
|
||
RNMXER (NF.CWS) ; -not allowed
|
||
MOVE T1,P2 ;Get node address
|
||
CALL LSCTA2N ; and map it to a name, use locked entry point
|
||
RETSKP ; -not found, no more to do
|
||
|
||
;If home area, clear pointer from ADRTAB to NO block
|
||
SKIPN T6 ;Home area?
|
||
IFSKP. ; -yes,
|
||
LDNODE T1,P2 ; Get local node index
|
||
ADD T1,ADRTAB ; and add address table address
|
||
SETZM (T1) ; and clear entry
|
||
SOS SCTNDC ; Decrement # of local nodes
|
||
ENDIF.
|
||
|
||
;Now clear node name in NO block
|
||
SETZRO NONAM,(T2) ;Clear
|
||
SETZRO NOADR,(T2) ; Might as well clear address too
|
||
RETSKP ; and done
|
||
|
||
SUBTTL Node name/number database -- Address to name
|
||
|
||
;SCTA2N - Do node address to name mapping
|
||
;
|
||
; Call: T1/ Node address. If an area # is not present, it will be
|
||
; defaulted to local area.
|
||
; CALL SCTA2N
|
||
;
|
||
; Return:
|
||
; RET The address does not have a name set
|
||
; RETSKP Node name in sixbit returned in T1, NO pointer in T2
|
||
|
||
XNENT SCTA2N
|
||
|
||
JSP CX,LOKNOD ;Lock node database
|
||
LSCTA2N: ;Entry point if already locked
|
||
SAVEAC <T6,P1,P2>
|
||
MOVE P2,T1 ;P2 has node address
|
||
CALL CHKADR ;Check address, and default area if needed
|
||
RET ; -bad address, pass on error code
|
||
|
||
;P2 now has node address with area #, T6 is non-zero if area = home area
|
||
JUMPE T6,SCTA21 ;If not local area, do it the cumbersome way..
|
||
|
||
;Verify that the node address is in range
|
||
LDNODE T1,P2 ;Get local node index
|
||
CAMLE T1,RTRMXN ;Compare with max nodes in area
|
||
RNMXER (NF.IPV) ; -bad address
|
||
|
||
;Get NO pointer from ADRTAB
|
||
ADD T1,ADRTAB ;Add address of ADRTAB
|
||
SKIPN T2,(T1) ;Is there a NO pointer
|
||
RNMXER (NF.URC) ; -no, node is not known
|
||
IFN FTOPS10,<
|
||
MOVE T1,T2 ;Get unmapped bucket address
|
||
CALL MAPBUC ;Map unmapped bucket
|
||
MOVE T2,T1 ;Get mapped address
|
||
>; END IFN FTOPS10
|
||
|
||
IFN FTDEBUG <
|
||
;Do a sanity check
|
||
OPSTR <CAME P2,>,NOADR,(T2) ;Node addresses match?
|
||
BUG.(CHK,SCLA2N,SCLINK,SOFT,<Node database inconsistent>,<<T1,NOD>>,<
|
||
|
||
Cause: The node database SCLA2N failed an internal consistency check.
|
||
|
||
Data: NOD - NO pointer in ADRTAB
|
||
|
||
>,RTN)
|
||
>
|
||
LOAD T1,NONAM,(T2) ;Get node name
|
||
RETSKP ; and return with T1 and T2
|
||
|
||
;SCTA21 - map non-local node address
|
||
SCTA21:
|
||
|
||
;T6 can be reused, not needed as flag any more
|
||
; Use T6 as hash table index
|
||
SETZ T6, ;Start at index 0
|
||
DO. ;LOOP over hash table
|
||
CAIL T6,SCNHSZ ; Done all of table?
|
||
RNMXER (NF.URC) ; -yes, no match
|
||
MOVE T1,T6 ; Move hash index to T1
|
||
ADD T1,HSHTAB ; And make hash table address
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map entry
|
||
>; END IFN FTOPS10
|
||
SKIPN T1,(T1) ; Is there a hash bucket chain?
|
||
AOJA T6,TOP. ; -no, loop back to next index
|
||
DO. ; LOOP over hash bucket chain
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map unmapped bucket
|
||
>; END IFN FTOPS10
|
||
XMOVEI T2,BU.NO1(T1) ; Pointer to first NO block for this bucket
|
||
MOVX T3,NRNOPB ; and # of NO blocks in this bucket
|
||
DO. ; LOOP over NO blocks in bucket
|
||
OPSTR <CAME P2,>,NOADR,(T2) ;Node addresses match?
|
||
IFSKP. ; -yes,
|
||
LOAD T1,NONAM,(T2) ; Get node name
|
||
RETSKP ; and return (T1 and T2)
|
||
ENDIF.
|
||
ADDI T2,NO.LEN ; -no match, go to next NO block
|
||
SOJG T3,TOP. ; -if there is any
|
||
ENDDO.
|
||
OPSTR <SKIPE T1,>,BUNXT,(T1) ;Move to next bucket
|
||
LOOP. ; and loop back
|
||
ENDDO.
|
||
AOJA T6,TOP. ; and move to next hash table entry
|
||
ENDDO.
|
||
;Will never get here
|
||
|
||
SUBTTL Node name/number database -- Name to address
|
||
|
||
;SCTN2A - Do node name to address mapping
|
||
;
|
||
; Call: T1/ Node name (in sixbit).
|
||
; CALL SCTN2A
|
||
;
|
||
; Return:
|
||
; RET No such name
|
||
; RETSKP Node address returned in T1
|
||
|
||
RESCD
|
||
SCTN2A: TOXSWAPCD
|
||
JSP CX,LOKNOD ;Lock node database
|
||
LSCTN2A: ; Already locked entry point
|
||
SAVEAC <T6,P1,P2>
|
||
MOVE P1,T1 ;P1 contains node name
|
||
CALL NAM2NO ;Map node name to NO block
|
||
RNMXER (NF.URC) ; -node name not in database
|
||
LOAD T1,NOADR,(T1) ;Get node address
|
||
RETSKP ; and return it successfully
|
||
|
||
SUBTTL Node name/number database -- Name to NO block
|
||
|
||
;NAM2NO - map a node name to NO block
|
||
;
|
||
; Call: P1/ node name (in sixbit)
|
||
; CALL NAM2NO
|
||
;
|
||
; Return:
|
||
; RET Node name not in database
|
||
; RETSKP T1/ NO pointer
|
||
|
||
NAM2NO: CALL HSHNAM ;Get a hash value from name
|
||
ADD T1,HSHTAB ;Get pointer to hash table entry
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map entry
|
||
>; END IFN FTOPS10
|
||
SKIPN T2,(T1) ;Get pointer to first bucket
|
||
RET ; -none, return error
|
||
|
||
;Hash table entry (in T1) has address of first bucket in chain
|
||
DO. ;LOOP over hash chain
|
||
IFN FTOPS10,<
|
||
MOVE T1,T2 ; Get unmapped bucket address
|
||
CALL MAPBUC ; Map unmapped bucket
|
||
MOVE T2,T1 ; Get mapped bucket address
|
||
>; END IFN FTOPS10
|
||
XMOVEI T1,BU.NO1(T2) ; Point to first NO block in bucket
|
||
MOVX T3,NRNOPB ; # of nodes/bucket
|
||
DO. ; LOOP over NO blocks
|
||
OPSTR <CAMN P1,>,NONAM,(T1) ;Node name matches?
|
||
RETSKP ; -yes, return with T1 setup
|
||
|
||
;No match, go to next NO block in bucket
|
||
ADDI T1,NO.LEN ; Move T1
|
||
SOJG T3,TOP. ; and do next NO block
|
||
ENDDO.
|
||
|
||
;Come here when one bucket is exhausted, go to next if there is any
|
||
OPSTR <SKIPE T2,>,BUNXT,(T2) ;Move to next
|
||
LOOP. ; -yes, loop and do next bucket
|
||
RET ; -no more in this chain, fail return
|
||
ENDDO.
|
||
;Will never get here
|
||
|
||
SUBTTL Node name/number database -- Default area #
|
||
|
||
;CHKADR - check node address, and default area
|
||
;
|
||
; Call: P2/ node address
|
||
; CALL CHKADR
|
||
;
|
||
; Return:
|
||
; RET Bad node address
|
||
; RETSKP P2/ node address with area #, T6 non-zero if home area
|
||
|
||
CHKADR: TXNE P2,RN%ARE ;Is there an area #?
|
||
IFSKP. ; -no, default it
|
||
MOVE T1,RTRHOM ; Get ROUTER home area
|
||
STAREA T1,P2 ; and store it
|
||
ELSE.
|
||
LDAREA T1,P2 ; Get area # if there is one
|
||
ENDIF.
|
||
SETZ T6, ;Assume not home area
|
||
CAME T1,RTRHOM ;Is it?
|
||
RETSKP ; -yes, all done
|
||
SETO T6, ;It is home area
|
||
LDNODE T1,P2 ;Get local node index
|
||
OPSTR <CAMLE T1,>,IBMXA,+IBBLK ;In range?
|
||
RNMXER (NF.IPV) ; -no, return failure
|
||
RETSKP ;-yes, all ok
|
||
|
||
SUBTTL Node name/number database -- Hash routine
|
||
|
||
; Call: T1/ Node name (in sixbit)
|
||
; CALL HSHNAM
|
||
;
|
||
; Return:
|
||
; RET Index into hash table in T1 [0..SCNHSZ-1]
|
||
;
|
||
; Note:
|
||
; May not touch T4....
|
||
|
||
|
||
XSWAPCD
|
||
HSHNAM: MOVM T1,P1 ;We know first character is alphanumeric..
|
||
IDIVI T1,SCNHSZ ;Divide by table size (prime #)
|
||
MOVE T1,T2 ;Use the modulo value
|
||
RET
|
||
|
||
SUBTTL Node name/number database -- Get a bucket
|
||
|
||
;GETBUC - get a bucket off free bucket list
|
||
;
|
||
; Call: CALL GETBUC
|
||
;
|
||
; Return:
|
||
; RET No bucket available (!!)
|
||
; RETSKP T1 contains address of bucket
|
||
|
||
XSWAPCD
|
||
GETBUC:
|
||
IFN FTOPS10,<
|
||
SAVEAC <T4,J> ;Save T4 and J
|
||
MOVE J,.CPJOB## ;Get our job number
|
||
>; END IFN FTOPS10
|
||
D36OFF ;Lock out other jobs
|
||
SKIPE T1,QHBUCK ;Get first free bucket
|
||
IFSKP. ; -none, get more space
|
||
IFN FTOPS20,<
|
||
D36ON ; Release interlock
|
||
BLCAL.(<@[MSEC1,,ASGVAS]>,<[0],[PGSIZ]>) ;Get one page for buckets
|
||
RNMXER(NF.RES) ; None, give error
|
||
MOVX T2,<PGSIZ/BU.LEN> ; Get # of buckets per page
|
||
D36OFF ; Get interlock
|
||
>; END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
GETBU1: MOVE T4,SCTMPF ; Any room in pseudo page map?
|
||
CAMGE T4,SCTMPS ; ...
|
||
JRST GETBU2 ; Yes, continue
|
||
CALL EXPMAP ; Expand it
|
||
JRST [D36ON ; Unsuccessful, release interlock
|
||
RNMXER (NF.RES)] ;And give error return
|
||
JRST GETBU1 ; And try again
|
||
GETBU2: AOS SCTMPF ; Update first free
|
||
D36ON ; Release interlock
|
||
PUSH P,T4 ; Save index into pseudo map
|
||
IFN FTMP,<
|
||
SNCALL (UPMM##,MCSEC1) ;Get MM for GETPHP
|
||
>; END IFN FTMP
|
||
MOVEI T3,1 ;Number of pages to allocate
|
||
SNCALL (GETPHP##,MCSEC1) ;Get a physical page
|
||
IFN FTMP,<
|
||
SNCALL (DWNMM##,MCSEC1) ;Give back MM
|
||
>; END IFN FTMP
|
||
MOVEI T2,<PAGSIZ##/BU.LEN> ;Get bucket count
|
||
POP P,T4 ; Restore pseudo map index
|
||
D36OFF ; Get interlock
|
||
ADD T4,SCTMAP ; Compute address of first free
|
||
MOVEM T1,(T4) ; Store physical address in pseudo map
|
||
SUB T4,SCTMAP ; Compute pseudo address
|
||
LSH T4,P2WLSH## ; ...
|
||
ADDX T4,MAPBAS ; ...
|
||
MOVE T1,T4 ; ...
|
||
>; END IFN FTOPS10
|
||
MOVE T4,QHBUCK ; Save pointer to current list
|
||
MOVEM T1,QHBUCK ; Save pointer to first bucket
|
||
MOVE T3,T1 ; Get bucket pointer into right AC for loop
|
||
DO. ; LOOP over buckets
|
||
SOJLE T2,ENDLP. ; Exit if all buckets linked
|
||
MOVE T1,T3 ; Copy pointer of current bucket
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map unmapped bucket
|
||
>; END IFN FTOPS10
|
||
ADDI T3,BU.LEN ; and move to next bucket
|
||
STOR T3,BUNXT,(T1) ; Link new bucket into old
|
||
LOOP. ; and loop
|
||
ENDDO.
|
||
IFN FTOPS10,<
|
||
MOVE T1,T3 ;Get unmapped address
|
||
CALL MAPBUC ;Map unmapped bucket address
|
||
MOVE T3,T1 ;Get mapped address
|
||
>; END IFN FTOPS10
|
||
STOR T4,BUNXT,(T3) ; Link previous list onto end of new list
|
||
MOVE T1,QHBUCK ; Get bucket header again (now non-zero)
|
||
ENDIF.
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ;Map unmapped bucket
|
||
>; END IFN FTOPS10
|
||
LOAD T2,BUNXT,(T1) ;Get link to next free bucket
|
||
MOVEM T2,QHBUCK ; and make that the new first bucket
|
||
SETZRO BUNXT,(T1) ;Clear link to next word
|
||
D36ON
|
||
RETSKP
|
||
|
||
SUBTTL Node name/number database -- Expand pseudo map
|
||
|
||
;EXPMAP - Expand pseudo map
|
||
;
|
||
;Call: CALL EXPMAP
|
||
;
|
||
;Return: RET if unable to expand map
|
||
; RETSKP on success
|
||
|
||
IFN FTOPS10,<
|
||
EXPMAP: MOVE T1,SCTMPS ;Get size of map
|
||
ADDI T1,^D20 ;Expand by 20 words
|
||
CALL DNGWDZ ;...
|
||
RET ;Can't return
|
||
MOVE T3,T1 ;Get address of new map
|
||
MOVE T2,SCTMAP ;Get address of old map
|
||
MOVE T1,SCTMPS ;Get size of old map
|
||
MOVEM T3,SCTMAP ;Store address of new map
|
||
CALL XBLTA## ;Copy old map into new map
|
||
MOVEI T1,^D20 ;Update size of new map
|
||
ADDM T1,SCTMPS ;...
|
||
RETSKP ;And return
|
||
>; END IFN FTOPS10
|
||
SUBTTL Node name/number database -- Map a bucket
|
||
|
||
;MAPBUC - Map an unmapped bucket
|
||
;
|
||
;Call: T1/ Unmapped address of bucket
|
||
; CALL MAPBUC
|
||
;
|
||
;Return: RET with T1/ Virtual address of bucket
|
||
|
||
XSWAPCD
|
||
IFN FTOPS10,<
|
||
MAPBUC: SAVEAC <T2> ;Save T2
|
||
MOVE T2,T1 ;Copy unmapped address
|
||
SUBX T2,MAPBAS ;Convert to map slot number
|
||
LSH T2,W2PLSH## ;...
|
||
ADD T2,SCTMAP ;Add address of map
|
||
MOVE T2,(T2) ;Get physical address
|
||
HRLI T2,(<PM.DCD>B2+PM.WRT+PM.PUB) ;Get mapping info
|
||
EXCH T2,.UPMP+.UMTMP ;Map in temp slot
|
||
ANDI T1,PG.BDY## ;Compute virtual address
|
||
IORI T1,.TEMP ;...
|
||
; CAME T2,.UPMP+.UMTMP ;Mapping change?
|
||
CLRPT .TEMP ;Yes, flush previous mapping
|
||
RET ;And return
|
||
>; END IFN FTOPS10
|
||
SUBTTL Node name/number database -- Compute bucket's unmapped address
|
||
|
||
;UMPBUC - Compute unmapped address of bucket
|
||
;
|
||
;Call: T1/ Mapped address of bucket
|
||
; CALL UMPBUC
|
||
;
|
||
;Return: RET with T1/ Unmapped address of bucket
|
||
|
||
IFN FTOPS10,<
|
||
UMPBUC: SAVEAC <T2,T3,T4> ;Save T2-T4
|
||
MOVE T2,.UPMP+.UMTMP ;Get mapping information
|
||
TXZ T2,PM.NAD ;Mask off non-address bits
|
||
MOVE T3,SCTMPS ;Get size of pseudo page map
|
||
MOVE T4,SCTMAP ;And address
|
||
UMPBU1: SOSGE T3 ;Adjust and check count
|
||
BUG. (CHK,SCLPMI,SCLINK,SOFT,<Node database pseudo page map inconsistent>,,,RTN)
|
||
CAME T2,(T4) ;Found the correct entry?
|
||
AOJA T4,UMPBU1 ;No, loop back
|
||
SUB T4,SCTMAP ;Compute pseudo map slot
|
||
LSH T4,P2WLSH## ;Make into pseudo address
|
||
ADDX T4,MAPBAS ;Compute unmapped address
|
||
ANDI T1,PG.BDY## ;...
|
||
IOR T1,T4 ;...
|
||
RET ;And return
|
||
>; END IFN FTOPS10
|
||
SUBTTL Node name/number database -- SCTMOV - SET MEMORY OFFLINE support
|
||
|
||
;SCTMOV - Called on SET MEMORY OFFLINE to move any affected pages
|
||
;
|
||
; Call:
|
||
; P1/ First affected page number
|
||
; P2/ Last affected page number
|
||
;
|
||
; Return:
|
||
; RET always
|
||
|
||
IFN FTOPS10,<
|
||
IFN FTLOCK,<
|
||
SCTMOV::SAVEAC <P3,P4> ;Save P3-P4
|
||
MOVE P3,SCTMPS ;Get size of pseudo map
|
||
MOVE P4,SCTMAP ;And address of pseudo map
|
||
SCTMO1: JUMPE P3,RTN ;Exit when finished checking
|
||
MOVE T1,(P4) ;Get next physical page in pseudo map
|
||
JUMPE T1,SCTMO2 ;Skip entry if zero
|
||
CAML T1,P1 ;In range being set offline?
|
||
CAMLE T1,P2 ;...
|
||
JRST SCTMO2 ;No, skip this entry
|
||
SNCALL (MOVPAG##,MCSEC1) ;Ask LOKCON to move the page
|
||
MOVEM T1,(P4) ;Store new page number
|
||
SCTMO2: AOJ P4, ;Bump pointer into pseudo map
|
||
SOJA P3,SCTMO1 ;And loop back for entire map
|
||
>; END IFN FTLOCK
|
||
>; END IFN FTOPS10
|
||
SUBTTL Node name/number database -- SCTANL - Add a loopback node name
|
||
|
||
;SCTANL - Add a loopback node name to table
|
||
;
|
||
; Call
|
||
; T1/ Node name (in sixbit). Zero to clear.
|
||
; T2/ Circuit id
|
||
;
|
||
; Return:
|
||
; RET ;NAME ALREADY TAKEN
|
||
; RETSKP ;LOOPBACK NODE CREATED
|
||
|
||
XSWAPCD
|
||
SCTANL: JSP CX,LOKNOD ;Lock node database
|
||
SAVEAC <P1,P2> ;STORAGE SPACE
|
||
DMOVE P1,T1 ;SAVE ARGUMENTS
|
||
JUMPE T1,SCTAL5 ;CLEARING?
|
||
CALL LSCTN2A ;FIND OUT IF THIS NAME ALREADY EXISTS, locked
|
||
IFNSK. ; -no,
|
||
MOVE T1,P1 ; maybe loopback node name?
|
||
CALL LSCTCKL ; so check that
|
||
RNMXER (NF.NRM) ; -yes, return "name already taken"
|
||
ENDIF.
|
||
MOVE T1,SCTLNL ;GET POINTER TO LIST OF LOOPBACK NODES
|
||
SCTAL1: JUMPE T1,SCTAL2 ;IF END OF LIST, ADD IT IN
|
||
OPSTR <CAMN P2,>,LNCIR,(T1) ;MAKE SURE CIRCUIT ID DOESN'T MATCH
|
||
RNMXER (NF.NRM) ;CIRCUIT ALREADY HAS A LOOPBACK NODE
|
||
LOAD T1,LNNXT,(T1) ;GET POINTER TO NEXT LOOPBACK NODE
|
||
JRST SCTAL1 ;AND LOOP
|
||
|
||
SCTAL2: MOVX T1,LN.LST ;GET SIZE OF BLOCK WE NEED
|
||
CALL DNGWDP ;ALLOCATE IT
|
||
RNMXER (NF.RES) ;OUT OF RESOURCES
|
||
STOR P1,LNNAM,(T1) ;SAVE LOOPBACK NAME
|
||
STOR P2,LNCIR,(T1) ;SAVE CIRCUIT ID
|
||
MOVE T2,SCTLNL ;#GET POINTER TO HEAD OF LIST
|
||
STOR T2,LNNXT,(T1) ;#STORE AS NEXT
|
||
MOVEM T1,SCTLNL ;#AND STORE POINTER TO THIS AS HEAD
|
||
RETSKP ;AND RETURN SUCCESS
|
||
|
||
SCTAL5: MOVE T1,T2 ;Get circuit ID
|
||
MOVE T2,SCTLNL ;GET POINTER TO LOOPBACK NODE LIST
|
||
MOVE T3,[MSEC1,,SCTLNL] ;PLACE TO BACK UP TO
|
||
SCTAL6: SKIPN T2 ;Skip if there is such circuit
|
||
RNMXER (NF.URC) ; -no such circuit
|
||
OPSTR <CAMN T1,>,LNCIR,(T2) ;Is this the circuit we are interested in?
|
||
JRST SCTAL7 ;YES
|
||
MOVE T3,T2 ;SAVE POINTER TO THIS BLOCK
|
||
LOAD T2,LNNXT,(T2) ;LOOK AT NEXT loop node
|
||
JRST SCTAL6 ;AND LOOP
|
||
|
||
SCTAL7: LOAD T1,LNNXT,(T2) ;GET POINTER TO NEXT BLOCK
|
||
STOR T1,LNNXT,(T3) ;SAVE IN PREDECESSOR, DELINKING THIS BLOCK
|
||
MOVE T1,T2 ;POINTER TO THIS BLOCK
|
||
CALL DNFWDS ;RETURN THE CORE
|
||
RETSKP ;AND DONE
|
||
|
||
SUBTTL Node name/number database -- SCTN2L - Convert name to loop circ
|
||
|
||
;SCTN2L - Convert name to loopback circuit
|
||
;
|
||
; Call
|
||
; T1/ Node name (in sixbit).
|
||
; Return:
|
||
; RET ;NO SUCH LOOPBACK NODE
|
||
; RETSKP, T1/ Circuit ID
|
||
|
||
RESCD
|
||
SCTN2L: TOXSWAPCD
|
||
JSP CX,LOKNOD ;Lock node database
|
||
MOVE T2,SCTLNL ;GET POINTER TO HEAD OF LOOPBACK NODE LIST
|
||
DO.
|
||
SKIPN T2 ;Skip if another node
|
||
RNMXER (NF.URC) ; -no such name
|
||
OPSTR <CAME T1,>,LNNAM,(T2) ;IS THIS THE NODE WE WANT?
|
||
IFSKP. ; -yes,
|
||
LOAD T1,LNCIR,(T2) ; Get circuit ID
|
||
RETSKP
|
||
ENDIF.
|
||
LOAD T2,LNNXT,(T2) ;NOPE, TRY FOR THE NEXT
|
||
LOOP.
|
||
ENDDO.
|
||
;Can never get here
|
||
|
||
SUBTTL Node name/number database -- SCTL2N - Convert loopback circuit
|
||
|
||
;SCTL2N - Check for existance of a loopback node name associated with a
|
||
;circuit.
|
||
;
|
||
; Call:
|
||
; T1/ circuit id (LI format)
|
||
;
|
||
; Return:
|
||
; RET No loopback name associated with circuit
|
||
; RETSKP T1/ sixbit loopback node name
|
||
|
||
XSWAPCD
|
||
SCTL2N: JSP CX,LOKNOD ;Lock node database
|
||
MOVE T2,SCTLNL ;Get pointer to header of loopback node list
|
||
DO. ;LOOP over list
|
||
SKIPN T2 ; More items in list?
|
||
RNMXER (NF.URC) ; -no, end of list, no such name
|
||
OPSTR <CAME T1,>,LNCIR,(T2) ;Circuits match?
|
||
IFSKP. ; -yes,
|
||
LOAD T1,LNNAM,(T2) ; Get loopback node name
|
||
RETSKP ; and return
|
||
ENDIF.
|
||
LOAD T2,LNNXT,(T2) ; -no, go to next loopback node
|
||
LOOP. ; and loop back
|
||
ENDDO.
|
||
;Will never get here
|
||
|
||
SUBTTL Node name/number database -- SCTCKL - Check for loopback node
|
||
|
||
;SCTCKL - Check for existance of loopback node. Meant to be used with SCTN2A,
|
||
; and thus has a reversed return sequence to indicate existance.
|
||
;
|
||
;Call
|
||
; T1/ Node name (in sixbit).
|
||
;Return
|
||
; RET ;NODE EXISTS
|
||
; RETSKP ;NODE DOESN'T EXIST
|
||
|
||
XSWAPCD
|
||
SCTCKL: JSP CX,LOKNOD ;Lock node database
|
||
LSCTCKL: ;Entry point if already locked
|
||
MOVE T2,SCTLNL ;GET POINTER TO HEAD OF LOOPBACK NODE LIST
|
||
DO. ;LOOP through list
|
||
JUMPE T2,RSKP ; Skip return at end of list
|
||
OPSTR <CAMN T1,>,LNNAM,(T2) ;IS THIS THE NODE WE WANT?
|
||
RET ;YES, DECLARE THAT IT EXISTS
|
||
LOAD T2,LNNXT,(T2) ;GET POINTER TO NEXT
|
||
LOOP. ;Do next node
|
||
ENDDO.
|
||
;Can never get here
|
||
|
||
SUBTTL Network management -- Dispatch
|
||
|
||
;SCLNMX is the entry point for all network management calls to SCLINK.
|
||
;
|
||
; Call:
|
||
; T1/ function code
|
||
; T2/ NF block address
|
||
;
|
||
; Return:
|
||
; RET Network management error code in T1
|
||
; RETSKP Operation succeded
|
||
|
||
XSWAPCD ;All of network management is swappable
|
||
|
||
;Define dispatch table
|
||
|
||
NMXFNT:
|
||
|
||
INIDSP NF.,NMX,0
|
||
DSP SET ;SET parameter
|
||
DSP CLR ;CLEAR parameter
|
||
DSP RED ;READ parameter
|
||
DSP COU ;SHOW counters
|
||
DSP SZC ;SHOW and ZERO counters
|
||
DSP RET ;Return list of entity ids
|
||
DSP A2N ;Map Node address to Node name
|
||
DSP N2A ;Map Node name to node address
|
||
DSP CET ;Check entity Id
|
||
DSP CKL ;Check loopback node
|
||
ENDDSP
|
||
|
||
ASSUME NF.CKL,EQ,NF.MAX ;Verify our dispatch table
|
||
|
||
;Network management parameter table
|
||
NODPAR:
|
||
|
||
PARAMETER(^D500,<PANRD!PADRC>,,,0,<CALL SET500>,JFCL,<CALL CLR500>,<Name>)
|
||
PARAMETER(^D501,PADRC,,,,<CALL SET501>,<CALL RED501>,<CALL CLR501>,<Circuit>)
|
||
PARAMETER(^D502,<PANRD!PADRC>,,,0,<CALL SET502>,JFCL,<CALL CLR502>,<Address>)
|
||
PARAMETER(^D510,,^D65535*TIMBAS,^D1000,%SCINT,<MOVEM T2,SCTINT>,<MOVE T2,SCTINT>,<MOVEM T2,SCTINT>,<Incoming timer>)
|
||
PARAMETER(^D511,,^D65535*TIMBAS,^D1000,%SCOTT,<MOVEM T2,SCTOTT>,<MOVE T2,SCTOTT>,<MOVEM T2,SCTOTT>,<Outgoing timer>)
|
||
|
||
NRNPAR==.-NODPAR
|
||
|
||
CIRPAR:
|
||
|
||
PARAMETER(^D400,PANST!PANCL,,,,JFCL,<CALL RED400>,JFCL,<Loopback name>)
|
||
|
||
NRCPAR==.-CIRPAR
|
||
|
||
XSWAPCD
|
||
SCLNMX: CAIL T1,NF.SET ;Range check
|
||
CAILE T1,NF.MAX ; the function code
|
||
RNMXER (NF.UFO) ;"Unrecognized function or option"
|
||
SAVEAC <P1,P2> ;Save preserved ACs
|
||
MOVE P1,T2 ;Put NF block in P1
|
||
JRST @NMXFNT(T1) ;Go to processing routine
|
||
|
||
;Unsupported function codes come here
|
||
|
||
;Session control does not maintain any counters
|
||
NMXCOU:
|
||
NMXSZC:
|
||
|
||
;Check entity ID should never be called
|
||
NMXCET:
|
||
RNMXER (NF.MPE) ;"Management program error"
|
||
|
||
SUBTTL Network management -- SET parameter
|
||
SUBTTL Network management -- CLEAR parameter
|
||
SUBTTL Network management -- READ parameter
|
||
|
||
;NMXSET - SET a network management paramater
|
||
;
|
||
; Call:
|
||
; T1/ function code
|
||
; P1/ NF block
|
||
; NFEID/ entity ID
|
||
; NFPRM/ parameter #
|
||
; NFETY/ entity type
|
||
; NFBFF/ zero
|
||
; NFBUF/ parameter value
|
||
|
||
NMXSET:
|
||
NMXCLR:
|
||
NMXRED:
|
||
MOVE P2,T1 ;Save function code
|
||
LOAD T1,NFETY,(P1) ;Get entity type
|
||
CAIE T1,.NTNOD ;NODE?
|
||
IFSKP. ; -yes,
|
||
XMOVEI T1,NODPAR ; Load node table
|
||
MOVEI T2,NRNPAR ; and its length
|
||
ELSE. ; -not NODE
|
||
CAIE T1,.NTCKT ; Is it circuit?
|
||
IFSKP. ; -yes,
|
||
XMOVEI T1,CIRPAR ; Load circuit table
|
||
MOVEI T2,NRCPAR ; and its length
|
||
ELSE. ; -neither NODE nor CIRCUIT
|
||
RNMXER (NF.URC) ; -so return error
|
||
ENDIF.
|
||
ENDIF.
|
||
MOVE T3,P2 ;Retrieve function code
|
||
CALLRET NTPARM ;Call NTPARM to do more work
|
||
|
||
;RED400 - READ circuit parameter 400
|
||
; Call:
|
||
; P1/ points to NF block
|
||
; NFEID/ circuit ID (LI format)
|
||
;
|
||
; Return:
|
||
; RET No loopback name associated with circuit
|
||
; RETSKP T1/ 0 and T2/ loopback name (sixbit)
|
||
|
||
RED400: SAVEAC <T3,T4> ;This coroutine may not touch T3 and T4
|
||
LOAD T1,NFEID,(P1) ;Get circuit ID
|
||
CALL SCTL2N ;Convert loopback circuit to name
|
||
RNMXND ; -not there, return 'no data'
|
||
MOVE T2,T1 ;Put it in T2
|
||
RNMXOK ; and return success
|
||
|
||
;SET500 - set node parameter 500 (NAME)
|
||
;CLR500 - read " " " "
|
||
;
|
||
; Call:
|
||
; NFEID/ Node address
|
||
; T2/ sixbit node name in SET case, 0 in CLEAR
|
||
;
|
||
SET500:
|
||
CLR500: SAVEAC <T3,T4> ;Must be preserved
|
||
MOVE T1,T2 ;Move node name into place
|
||
LOAD T2,NFEID,(P1) ; and node address
|
||
CALL SCTAND ;Insert/remove into table
|
||
RNMXER () ;Pass error code back up
|
||
RNMXOK ;Success return
|
||
|
||
;SET501 - set node parameter 501 (CIRCUIT)
|
||
;
|
||
; Call:
|
||
; NFEID/ node name
|
||
; T2/ circuit ID
|
||
;
|
||
SET501: SAVEAC <T3,T4> ;Must be preserved
|
||
LOAD T1,NFEID,(P1) ;Get loopback node name
|
||
CALL SCTANL ;Add loopback node name
|
||
RNMXER (NF.NRM) ; -error
|
||
RNMXOK ;Return success
|
||
|
||
;CLR501 - clear parameter 501 (CIRCUIT)
|
||
;
|
||
; Call:
|
||
; NFEID/ node name
|
||
; T2/ zero
|
||
;
|
||
CLR501: SAVEAC <T3,T4>
|
||
LOAD T1,NFEID,(P1) ;Get loopback node name to clear
|
||
XCALL (MSEC1,SCTN2L) ;Convert it to loopback circuit
|
||
RNMXND ; -not there, return 'no data'
|
||
MOVE T2,T1 ;Get circuit ID into T2
|
||
SETZ T1, ; and clear loopback node name
|
||
CALL SCTANL ;Clear loopback node name
|
||
RET ; -pass on error code
|
||
RNMXOK ;Return success
|
||
|
||
;RED501 - read parameter 501 (CIRCUIT)
|
||
;
|
||
; Call:
|
||
; NFEID/ loopback node name
|
||
;
|
||
RED501: SAVEAC <T3,T4> ;Must be preserved
|
||
LOAD T1,NFEID,(P1) ;Get node name
|
||
XCALL (MSEC1,SCTN2L) ;Convert to circuit
|
||
RNMXER (NF.NRM) ; -error
|
||
MOVE T2,T1 ;Result to T2
|
||
RNMXOK ; and return success
|
||
|
||
;SET502 - set node parameter 502 (ADDRESS)
|
||
;
|
||
; Call:
|
||
; NFEID/ node name
|
||
; T2/ node address on SET
|
||
;
|
||
SET502: SAVEAC <T3,T4>
|
||
LOAD T1,NFEID,(P1) ;Get node name
|
||
CALL SCTAND ;Add node name
|
||
RNMXER () ; Pass on error code
|
||
RNMXOK ;Return success
|
||
|
||
;CLR502 - clear node parameter 502 (ADDRESS)
|
||
;
|
||
; Call:
|
||
; NFEID/ node name
|
||
; T2/ 0
|
||
;
|
||
CLR502: SAVEAC <T3,T4> ;Must be preserved
|
||
LOAD T1,NFEID,(P1) ;Get node name
|
||
XCALL (MSEC1,SCTN2A) ;Map it to a node address
|
||
IFSKP. ; -ok,
|
||
MOVE T2,T1 ; Move node address to T2
|
||
SETZ T1, ; Clear node name to indicate clear
|
||
CALL SCTAND ; Clear
|
||
RNMXER () ; Pass on error code
|
||
ENDIF.
|
||
RNMXOK ;Return success
|
||
|
||
SUBTTL Network management -- Return list of entity ids
|
||
|
||
;NMXRET - return list of entity IDs
|
||
;
|
||
; SCLINK maintains two entity types: KNOWN NODES and LOOP NODES.
|
||
; The KNOWN nodes fall into two categories: home area and not home
|
||
; area. The arguments to NMXRET are different in each case.
|
||
;
|
||
; Common parameters are:
|
||
; P1/ address of NF block
|
||
; NFSEL/ .NTKNO or .NTLOP
|
||
; NFEID/ if NFSEL is .NTKNO then NFEID has area #
|
||
|
||
NMXRET: LOADE T1,NFSEL,(P1) ;Get selector
|
||
CAXN T1,.NTLOP ;Is it LOOP nodes?
|
||
JRST RETLOP ; -yes, go return LOOP nodes
|
||
CAXE T1,.NTKNO ;then it should be KNOWN nodes
|
||
RNMXER (NF.MPE) ; -no, management program error
|
||
LOAD T1,NFEID,(P1) ;Get area number
|
||
CAME T1,RTRHOM ;Is it local area
|
||
JRST RETOAR ; -no, return other area
|
||
; JRST RETHAR ;-yes, return home area
|
||
|
||
;RETHAR - return home area
|
||
;
|
||
; SCLINK is handed a buffer that is indexed by local node number
|
||
; The local node number is filled in if the node is KNOWN, i.e. in
|
||
; session controls node database.
|
||
;
|
||
; Call:
|
||
; NFBFF/ set
|
||
; NFUBF/ clear
|
||
; NFBUF/ buffer address
|
||
; NFBLN/ buffer length
|
||
;
|
||
; Return:
|
||
; RET/ error occurred
|
||
; RETSKP/ succeeded
|
||
|
||
RETHAR:
|
||
|
||
;Do a couple of sanity checks
|
||
LOAD T1,NFBFF,(P1) ;Get buffer flag
|
||
LOAD T2,NFUBF,(P1) ; and user flag
|
||
SKIPE T1 ;Verify buffer flag is set
|
||
SKIPE T2 ; and user buffer flag is clear
|
||
RNMXER (NF.MPE) ; otherwise "management program error"
|
||
|
||
;P2 will contain buffer address
|
||
LOAD P2,NFBUF,(P1)
|
||
|
||
;Loop from node 1 to node NFBLN, checking ADRTAB along the way
|
||
JSP CX,LOKNOD ;Lock database
|
||
LOAD T1,NFBLN,(P1) ;T1 has node index
|
||
LOAD T2,IBMXA,+IBBLK ;Get the Maximum Nodes in Area
|
||
CAMLE T1,T2 ;Is Max Area .LE. Buffer Length??
|
||
MOVE T1,T2 ;If so use Max area as index
|
||
DO. ;LOOP
|
||
MOVE T2,ADRTAB ; Get address of address table
|
||
ADD T2,T1 ; and add in current local node index
|
||
SKIPN T3,(T2) ; Is any pointer there?
|
||
IFSKP. ; -yes, that node is KNOWN
|
||
IFN FTOPS10,<
|
||
EXCH T1,T3 ;Map bucket
|
||
CALL MAPBUC ;...
|
||
EXCH T1,T3 ;...
|
||
>; END IFN FTOPS10
|
||
LOAD T3,NOADR,(T3) ; Get node address (now 16-bit format)
|
||
MOVE T4,T1 ; Get local node index
|
||
ADD T4,P2 ; and add destination buffer address
|
||
MOVEM T3,(T4) ; and store the node address
|
||
ENDIF.
|
||
SOJG T1,TOP. ; Loop back if more nodes to do
|
||
ENDDO. ; -no, all nodes done, return successfully
|
||
RETSKP
|
||
|
||
;RETOAR - return list of KNOWN nodes in areas other than home area
|
||
;
|
||
; RETOAR will write directly to a user buffer. Each node within the given
|
||
; area should be written in NICE format, i.e. 16-bit node address in two
|
||
; bytes followed by a zero byte to indicate no node name following.
|
||
;
|
||
; Since the node name/number database is organized in a way that makes
|
||
; the search for a single node number outside home area very expensive,
|
||
; another measure is taken to speed up the processing.
|
||
;
|
||
; RETOAR will process the entire area in one pass through the database,
|
||
; setting a bit in a temporary table if a specific node is there.
|
||
;
|
||
; Call:
|
||
; NFEID/ area #
|
||
; NFUBF/ set
|
||
; NFBPT/ user byte pointer
|
||
; NFBLN/ # of user bytes
|
||
;
|
||
; Return:
|
||
; RET Some error occurred
|
||
; RETSKP Success with
|
||
; NFBLN/ # of bytes written
|
||
|
||
RETOAR: SAVEAC <T5,T6> ;Need these two also
|
||
|
||
;Verify user buffer bit is set
|
||
TMNN NFUBF,(P1) ;Is it set?
|
||
RNMXER (NF.MPE) ; -no, "management program error"
|
||
|
||
;Allocate a temporary buffer to store the bit mask of KNOWN nodes in
|
||
MOVX T1,<<RN%NOD+^D36>/^D36> ;Room for all nodes in an area
|
||
CALL DNGWZP ;Get zeroed space
|
||
RNMXER (NF.RES) ; "resource failure"
|
||
MOVE P2,T1 ;Keep bit mask address in P2
|
||
|
||
;Lock node database so it doesnt change under our feet
|
||
IFN FTOPS20,<
|
||
S1XCT <LOCK NODLOK>
|
||
> ;END IFN FTOPS20
|
||
|
||
;Now go through the entire node name/number database, and check for all nodes
|
||
; in the specified area
|
||
SETZ T6, ;T6 is hash table index
|
||
DO. ;LOOP over hash table
|
||
CAIL T6,SCNHSZ ; Done all of table?
|
||
EXIT. ; -yes, pass 1 done
|
||
MOVE T1,T6 ; Hash index to T1
|
||
ADD T1,HSHTAB ; and make hash table address
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map entry
|
||
>; END IFN FTOPS10
|
||
SKIPN T1,(T1) ; Is there a bucket chain?
|
||
AOJA T6,TOP. ; -no, go to next hash index
|
||
DO. ; LOOP over hash bucket chain
|
||
IFN FTOPS10,<
|
||
CALL MAPBUC ; Map bucket
|
||
>; END IFN FTOPS10
|
||
XMOVEI T2,BU.NO1(T1) ; Pointer to first NO block in this bucket
|
||
MOVX T3,NRNOPB ; and # of NO blocks per bucket
|
||
DO. ; LOOP over bucket
|
||
LOAD T4,NOADR,(T2) ; Get node address
|
||
LDAREA T5,T4 ; and extract area number
|
||
OPSTR <CAME T5,>,NFEID,(P1) ;Do areas match?
|
||
IFSKP. ; -yes, found a KNOWN node
|
||
LDNODE T5,T4 ; Get the local node index
|
||
CALL INSNOD ; and set the corresponding bit
|
||
ENDIF.
|
||
ADDI T2,NO.LEN ; Go to next NO block
|
||
SOJG T3,TOP. ; -if there is any!
|
||
ENDDO.
|
||
OPSTR <SKIPE T1,>,BUNXT,(T1) ;Move to next bucket
|
||
LOOP. ; and loop back
|
||
ENDDO.
|
||
AOJA T6,TOP. ; and go to next hash index
|
||
ENDDO.
|
||
|
||
;Come here after 1st pass.
|
||
; The node database can now be unlocked
|
||
IFN FTOPS20,< UNLOCK NODLOK>
|
||
|
||
;The bit table has now been set up.
|
||
;
|
||
;Loop over all entries in the bit table and write corresponding node number
|
||
; to the user buffer
|
||
LOAD T1,IBMXA,+IBBLK ;Get maximum # of nodes in an area
|
||
ADDI T1,^D35 ;One bit
|
||
IDIVI T1,^D36 ; per node
|
||
MOVE T6,T1 ; gives word count in T6
|
||
SETZ T1, ;Begin at word 0
|
||
DO. ;LOOP over all words
|
||
MOVE T2,T1 ; Move index to T2
|
||
ADD T2,P2 ; and make bit table address
|
||
MOVE T3,(T2) ; Get contents of that word
|
||
JFFO T3,RETOA1 ; Find first bit set
|
||
;Come here if no bit was set, go to next word
|
||
AOJ T1, ; Increment index
|
||
CAMGE T1,T6 ; Done all?
|
||
LOOP. ; -no, loop back
|
||
EXIT. ; -yes, exit loop
|
||
|
||
RETOA1: ;Come here if some bit was set, bit # in T4
|
||
TDZ T3,BITS(T4) ; Clear bit in word
|
||
MOVEM T3,(T2) ; and write it back to bit mask
|
||
MOVE T3,T1 ; Get index
|
||
IMULI T3,^D36 ; and make into
|
||
ADD T3,T4 ; node number
|
||
CALL WRTNOD ; in order to write it to user space
|
||
IFNSK.
|
||
MOVE T1,P2 ;Get the buffer address
|
||
CALL DNFWDS ;Return space
|
||
RNMXER (NF.RES) ;And return a "Resource Error"
|
||
ENDIF.
|
||
LOOP. ; Loop back with old T1 to take care of
|
||
; next set bit in word, if any.
|
||
ENDDO.
|
||
|
||
;At this point, release the temporary buffer and return successfully
|
||
MOVE T1,P2 ;Get buffer address
|
||
CALL DNFWDS ;Return space
|
||
RETSKP ;Done successfully
|
||
|
||
;INSNOD - insert a node in bit table
|
||
;
|
||
; T5/ local node index
|
||
; P2/ bit mask address
|
||
;
|
||
;No ACs may be touched
|
||
|
||
INSNOD: SAVEAC <T1,T2>
|
||
MOVE T1,T5 ;Local node index to T1
|
||
IDIVI T1,^D36 ;Word index to T1, bit number to T2
|
||
ADD T1,P2 ;Make buffer word address
|
||
MOVE T2,BITS(T2) ;Get bit mask for node index
|
||
IORM T2,(T1) ; and OR in the node
|
||
RET ;Done
|
||
|
||
;WRTNOD - write a node to user buffer
|
||
;
|
||
; T3/ local node index
|
||
; P1/ NF block
|
||
; CALL WRTNOD
|
||
; +1 return if no more user space available
|
||
; +2 return if all is OK
|
||
;
|
||
;No ACs may be touched
|
||
|
||
WRTNOD: SAVEAC <T1,T2>
|
||
LOAD T1,NFBLN,(P1) ;Is there room
|
||
SUBI T1,3 ; for 3 more bytes
|
||
SKIPGE T1 ; ?
|
||
RET ; -no, return +1 to indicate that
|
||
STOR T1,NFBLN,(P1) ;Store new updated count
|
||
LOAD T1,NFEID,(P1) ;Get area number
|
||
STAREA T1,T3 ; and put it into node number
|
||
|
||
TOSWAPCD ;Transfer into section 1 to do PXCT
|
||
LOAD T1,NFBPT,(P1) ;Get user byte pointer
|
||
LDB T2,[POINT 8,T3,35] ;Get 1st byte
|
||
XCTBU [IDPB T2,T1] ;Give it to him
|
||
LDB T2,[POINT 8,T3,27] ;Get 2nd byte
|
||
XCTBU [IDPB T2,T1] ;Give it to him
|
||
SETZ T2, ;And a zero length of node name
|
||
XCTBU [IDPB T2,T1] ;Give it to him
|
||
TOXSWAPCD ;Exit section 1 after PXCT
|
||
|
||
STOR T1,NFBPT,(P1) ;Save the updated Byte Pointer
|
||
RETSKP ;All done
|
||
|
||
|
||
;RETLOP - return list of LOOP nodes
|
||
;
|
||
; Call:
|
||
; NFBFF/ set
|
||
; NFUBF/ clear
|
||
; NFBUF/ buffer address
|
||
; NFBLN/ # of words in buffer
|
||
;
|
||
; Return:
|
||
; RET Some error occurred
|
||
; RETSKP Succes with
|
||
; NFBLN/ # of words written
|
||
; buffer contains sixbit loop node names
|
||
|
||
RETLOP:
|
||
JSP CX,LOKNOD ;Lock node database
|
||
|
||
;Sanity checks
|
||
LOAD T1,NFBFF,(P1) ;Get buffer flag
|
||
LOAD T2,NFUBF,(P1) ; and user buffer flag
|
||
SKIPE T1 ;Verify buffer flag is set
|
||
SKIPE T2 ; and user buffer flag is clear
|
||
RNMXER (NF.MPE) ; otherwise "management program error"
|
||
|
||
;Step through list of loopback nodes
|
||
LOAD P2,NFBUF,(P1) ;Buffer address to P2
|
||
SETZ T1, ;No loop nodes found yet
|
||
MOVE T2,SCTLNL ;Get pointer to head of loopback nodes
|
||
DO. ;LOOP over chain
|
||
SKIPN T2 ; Is there any more LOOP nodes?
|
||
EXIT. ; -no, done
|
||
LOAD T3,LNNAM,(T2) ; -yes, get loopback node name
|
||
MOVE T4,T1 ; Get count word of nodes found
|
||
ADD T4,P2 ; and add in destination address
|
||
MOVEM T3,(T4) ; Store the loopback name
|
||
AOJ T1, ; One more loopback node found
|
||
LOAD T2,LNNXT,(T2) ; Go to next loopback node
|
||
LOOP. ; and loop back
|
||
ENDDO.
|
||
;Come here when there are no more loopback nodes
|
||
STOR T1,NFBLN,(P1) ;Store # of loopback nodes returned
|
||
RETSKP ; and return successfully
|
||
|
||
SUBTTL Network management -- Map node address to node name
|
||
|
||
;NMXA2N - convert from node address to node name
|
||
;
|
||
; Call:
|
||
; T1/ function code
|
||
; P1/ NF block
|
||
; NFEID/ Entity ID (node address in 16-bit format)
|
||
; NFETY/ .NTNOD
|
||
; NFBUF/ zero
|
||
;
|
||
; Return:
|
||
; RET Network management error code in T1
|
||
; RETSKP NFBUF/ Sixbit node name
|
||
|
||
SUBTTL Network management -- Map node name to node address
|
||
|
||
;NMXN2A - convert node name to node number
|
||
;
|
||
; Call:
|
||
; T1/ function code
|
||
; P1/ NF block
|
||
; NFEID/ entity ID (sixbit node name)
|
||
; NFETY/ .NTNOD
|
||
; NFBUF/ zero
|
||
;
|
||
; Return:
|
||
; RET Network management error code in T1
|
||
; RETSKP NFBUF/ 16-bit node address
|
||
|
||
NMXN2A:
|
||
NMXA2N: LOAD T2,NFETY,(P1) ;Get entity type
|
||
LOAD T3,NFBUF,(P1) ; and buffer word
|
||
CAIN T2,.NTNOD ;Verify that it is a node
|
||
SKIPE T3 ; and that buffer word is zero
|
||
RNMXER (NF.MPE) ; "Management program error"
|
||
CAIE T1,NF.A2N ;Is it address to name?
|
||
IFSKP. ; -yes
|
||
LOAD T1,NFEID,(P1) ;Get 16-bit node address
|
||
XCALL (MSEC1,SCTA2N) ;Convert it
|
||
RNMXER (NF.URC) ; "Unrecognized component"
|
||
ELSE. ; -no
|
||
LOAD T1,NFEID,(P1) ;Get sixbit node name
|
||
XCALL (MSEC1,SCTN2A) ;Convert it
|
||
RNMXER (NF.URC) ; "Unrecognized component"
|
||
ENDIF.
|
||
STOR T1,NFBUF,(P1) ;Store node name/address
|
||
RETSKP
|
||
|
||
SUBTTL Network management -- Check loopback node name
|
||
|
||
;NMXCKL - Check loopback node name
|
||
;
|
||
; Call:
|
||
; P1/ NF block address
|
||
; NFETY/ .NTNOD
|
||
; NFEID/ sixbit node name
|
||
;
|
||
; Return:
|
||
; RET Node is not a loopback node
|
||
; RETSKP Node is a loopback node
|
||
|
||
NMXCKL: LOAD T1,NFETY,(P1) ;Get entity type
|
||
CAIE T1,.NTNOD ;Verify that it is a node
|
||
RNMXER (NF.MPE) ; otherwise "management program error"
|
||
LOAD T1,NFEID,(P1) ;Get entity ID
|
||
CALL SCTCKL ;Check if it is a loopback node
|
||
RETSKP ; SCTCKL returns "wrong way" (to be fixed)
|
||
RNMXER (NF.URC) ; -no, return "unrecognized component"
|
||
|
||
XRESCD
|
||
|
||
SUBTTL Network management -- Event -- Invalid message
|
||
|
||
;SCEIVM - Report Invalid Message Event
|
||
;
|
||
; Call:
|
||
; MB/ Pointer to Message Block (which will be freed)
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS (WITH AN ERROR CODE IN T1)
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
SCEIVM: EVENT(NSP,MSG,Invalid Msg in SCTL) ;BAD MESSAGE EVENT TYPE
|
||
CALL FREMSG ;MUSTN'T FREE UNTIL AFTER EVENT MACRO
|
||
SCERR %NEIMF,RTN,<Illegal message format detected>
|
||
|
||
;T1 set up with error code by SCERR macro, which also returns via RTN
|
||
|
||
SUBTTL Network management -- Event -- CSSE event
|
||
|
||
;LEVT.0 - parameter 0 for CSSE event
|
||
|
||
XRESCD
|
||
LEVT.0:
|
||
|
||
;Fall through to LEP.0
|
||
; CALLRET LEP.0 ;Parameter 0 (all data)
|
||
|
||
;LEP.0 - LCG event paramater 0
|
||
; CM-6
|
||
; DU-2 destination object type
|
||
; DU-2 destination node address
|
||
; DU-2 packets sent
|
||
; DU-2 packets received
|
||
; DU-2 bytes sent
|
||
; DU-2 bytes received
|
||
|
||
LEP.0: SETZ T1, ;Parameter #0
|
||
CALL EVP2BT ; and output
|
||
MOVEI T1,306 ;CM-6
|
||
CALL EVPBYT
|
||
MOVEI T1,002 ;DU-2
|
||
CALL EVPBYT ; and output
|
||
LOAD T1,SLDOB,(SL) ;Get destination object #
|
||
CALL EVP2BT ; and output
|
||
MOVEI T1,002 ;DU-2
|
||
CALL EVPBYT ; and output
|
||
LOAD T1,SLDNA,(SL) ;Get destination node address
|
||
CALL EVP2BT ; and output
|
||
MOVEI T1,002 ;DU-2
|
||
CALL EVPBYT ; and output
|
||
LOAD T1,SLPKS,(SL) ;Get # of packets sent
|
||
CALL EVP2BT ; and output
|
||
MOVEI T1,002 ;DU-2
|
||
CALL EVPBYT ; and output
|
||
LOAD T1,SLPKR,(SL) ;Get # of packets received
|
||
CALL EVP2BT ; and output
|
||
MOVEI T1,002 ;DU-2
|
||
CALL EVPBYT ; and output
|
||
LOAD T1,SLBYS,(SL) ;Get # of bytes sent
|
||
CALL EVP2BT ; and output
|
||
MOVEI T1,002 ;DU-2
|
||
CALL EVPBYT ; and output
|
||
LOAD T1,SLBYR,(SL) ;Get # of bytes received
|
||
CALLRET EVP2BT ; and output and return
|
||
|
||
SUBTTL Local SCTL Storage
|
||
|
||
RESDT ;IMPURE STORAGE (non-zeroed on boot)
|
||
|
||
IFN FTOPS20,< ;TOPS10 HAS THESE IN COMMON
|
||
;Schedular level routines do "SKIPL SCTLOK/RET" before proceeding
|
||
SCTLOK: EXP -1 ;SCTL INTERLOCK, USED BY SCTLCQ & SCTLCW
|
||
SCTLKO: EXP 0 ;INTERLOCK OWNER
|
||
>
|
||
SCTJFF: BLOCK 1 ;NON-ZERO: SCTULK SHOULD CALL SECOND SERVICE
|
||
SCTUCF: BLOCK 1 ;NON-ZERO: SCTULK SHOULD CALL SCIUCG
|
||
|
||
SCTCTA: BLOCK 1 ;GLOBAL COUNT OF CI TIMERS ACTIVE
|
||
SCTSJQ: BLOCK QH.LEN ;QUEUE OF ALL SJBS
|
||
|
||
|
||
SWAPVR
|
||
IFN FTOPS10,<
|
||
SCTCOR::BLOCK 1 ;30-bit address of core for name/address map
|
||
SCTMPF: BLOCK 1 ;First free name/address pseudo page map slot
|
||
SCTMPS: EXP <<SCNHSZ+777>/PAGSIZ##>+^D20 ;Size of name/address pseudo page map
|
||
SCTMAP: BLOCK 1 ;Address of Name/address psuedo page map
|
||
>; END IFN FTOPS10
|
||
HSHTAB: BLOCK 1 ;30-bit address of node name hash table
|
||
ADRTAB: BLOCK 1 ;30-bit address of node number table
|
||
QHBUCK: BLOCK 1 ;30-bit address of first free bucket
|
||
SCTNDC: BLOCK 1 ;# of local nodes known by SCLINK (for JNTMAN)
|
||
RESDT
|
||
|
||
NODLOK: BLOCK 1 ;Lock word for node database
|
||
|
||
SCTLNL: BLOCK 1 ;LOOPBACK NODE LIST
|
||
SCTP2Q: %SCP2Q ;PHASE II QUOTA
|
||
SCTINT: %SCINT ;INCOMING TIMER EXPIRATION VALUE
|
||
SCTOTT: %SCOTT ;OUTGOING TIMER EXPIRATION VALUE
|
||
SCTJFQ: BLOCK QH.LEN ;QUEUE OF SLBS NEEDING SECOND SERVICE
|
||
SCTPRQ: BLOCK QH.LEN ;SCTL TRANSACTION QUEUE HEADER
|
||
|
||
STRCNT: BLOCK 1 ;RECURSION COUNT FOR PATTERN MATCHER
|
||
|
||
SCTASQ: BLOCK QH.LEN ;ALL-SLBs QUEUE HEADER
|
||
|
||
XRESCD ;BACK TO PURE STORAGE
|
||
SUBTTL End of SCLINK
|
||
|
||
IFN FTOPS10, .XCMSY ;XCREF THE MACSYM SYMBOLS
|
||
IFN FTOPS20, TNXEND ;TOPS-20 ENDING
|
||
|
||
IFN FTOPS10,<
|
||
RESDT
|
||
SCTLOW::!
|
||
XRESCD
|
||
>; END IFN FTOPS10
|
||
END
|