Trailing-Edge
-
PDP-10 Archives
-
decnet_mcb_cusps_703a
-
10,7/703mon/scmuuo.mac
There are 3 other files named scmuuo.mac in the archive. Click here to see a list.
TITLE SCMUUO - Session Control UUO handler V104
SUBTTL W. Nichols & V. Brownell/AJR/Tarl 27 JAN 86
SEARCH D36PAR,SCPAR,MACSYM
SEARCH F,S
SALL
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1981,1986>
;COPYRIGHT (C) 1981,1984,1986
;BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
;
XP SCMUUO,104
$RELOC
XRESCD
SUBTTL Table of Contents
; Table of Contents for SCMUUO
;
;
; Section Page
; 1. Table of Contents. . . . . . . . . . . . . . . . . . . 2
; 2. Definitions
; 2.1. External References . . . . . . . . . . . . . 3
; 2.2. Accumulators. . . . . . . . . . . . . . . . . 4
; 2.3. NSP.
; 2.3.1. Functions and Arguments. . . . . . . 5
; 2.3.2. Argument Parameters. . . . . . . . . 6
; 3. SCURST - RESET call from UUOCON. . . . . . . . . . . . 8
; 4. SCUUUO
; 4.1. The NSP. UUO processor. . . . . . . . . . . . 9
; 4.2. SCUINI - Initialization . . . . . . . . . . . 11
; 4.3. SCUAFN - Read the Function Code . . . . . . . 13
; 4.4. SCURAA - Read the AAn Arguments . . . . . . . 14
; 5. Argument Readers
; 5.1. SCCCBL - Connect Block. . . . . . . . . . . . 15
; 5.2. SCCSBL - String Block . . . . . . . . . . . . 16
; 5.3. SCCARG - Integer Argument . . . . . . . . . . 17
; 5.4. SCCBCT - Byte Count . . . . . . . . . . . . . 18
; 5.5. SCCBPT - Byte pointer . . . . . . . . . . . . 19
; 5.6. SCCBUF - Buffer Checking Subr . . . . . . . . 20
; 6. Argument Writers
; 6.1. SCSCBL - Store Connect Block into User Space. 23
; 6.2. SCSSBL - Store String Block into User Space . 24
; 6.3. SCSARG, SCSBCT, SCSBPT. . . . . . . . . . . . 25
; 7. Argument Discarders
; 7.1. SCDARG, SCDCBL, SCDSBL. . . . . . . . . . . . 26
; 8. Subroutines
; 8.1. SCUHBR - Subroutine to do the HIBERs. . . . . 27
; 8.2. SCUWAK - Subroutine to do the WAKEs.. . . . . 28
; 8.3. SCTPSI - Get PSI associated variable. . . . . 29
; 8.4. SCGWRD & SCPWRD . . . . . . . . . . . . . . . 30
; 8.5. WRDTRP - The Word Troll Processor . . . . . . 31
; 8.6. GETPRO - Get process block. . . . . . . . . . 32
; 8.7. GETSTR - Get a string block . . . . . . . . . 34
; 8.8. PUTPRO - Write Process Block to User's Space. 35
; 8.9. PUTSTR - Write String Block to User's Space . 36
; 9. Impure Storage . . . . . . . . . . . . . . . . . . . . 37
; 10. End of SCMUUO. . . . . . . . . . . . . . . . . . . . . 38
SUBTTL Definitions -- External References
;ENTRY declarations for LINK
ENTRY SCUUUO ;USER UUO CALLS FROM UUOCON
ENTRY SCURST ;RESET CALL FROM UUOCON
;These are the external references to the D36COM library of routines.
EXT DNGMSG ;GET DECNET-36 MESSAGE BLOCK
EXT DNFMSG ;FREE MESSAGE BLOCK
EXT DNGWDS ;GET SOME WORDS
EXT DNGWDZ ;GET SOME ZEROED WORDS
EXT DNFWDS ;FREE SOME WORDS
EXT DNSWDS ;SMEAR SOME WORDS
EXT DNLMSS ;LINK MESSAGE SEGMENT INTO MESSAGE BLOCK
;Here are the references to SCLINK.
EXT SCTNSF ;NSP. FUNCTION PROCESSING
EXT MAKSJB ;MAKE A SJB
EXT SCTRST ;RESET AN SJB
EXT SCTWKQ ;ENQUEUE THIS SLB FOR SCTPSQ CALL
EXT SCTPSQ ;DEQUEUE NEXT SLB FOR PSI INTERRUPT
;Here are some external references to TOPS-10 things.
EXT RTN ;RETURN
EXT RSKP ;SKIP RETURN
SUBTTL Definitions -- Accumulators
;SCMUUO must use its own AC definitions, since it is the gateway
;between TOPS10's AC usage and DECnet-36's system independent AC usage.
OPDEF CALL [PUSHJ P,]
OPDEF RET [POPJ P,]
.NODDT CALL,RET
SJ=U ;(U ) PTR TO SCT JOB BLK (SEE PURGE SJ FURTHER DOWN)
MS=P4 ;(P4) POINTER TO CURRENT MSD
SA=P3 ;(P3) POINTER TO SCLINK ARGS BLOCK
R=:17 ;(R ) BECAUSE MACSYM REDEFINES THIS
CX=R ;(R ) SUPER-TEMP FOR MACROS
.SAC==CX ;(R ) DIFFERENT NAME, FOR MACROS.
;Notice that W and M correspond to DECnet-36's T5 and T6, so save
;them around calls to D36COM routines.
SUBTTL Definitions -- NSP. -- Functions and Arguments
;These are the definitions of all the NSP. functions. The format of the
;NSPFNC macro is function name followed by the three possible arguments
;of the NSP. UUO.
;
; R = Read this arg from user's block
; W = Write this arg into user's block
; P = Privileged Argument
DEFINE NSPFNS,<
NSPFNC EA,CBL(R),ARG(R),ARG(R,P) ;;ENTER ACTIVE
NSPFNC EP,CBL(R) ;;ENTER PASSIVE
NSPFNC RI,CBL(W),ARG(W),ARG(W) ;;READ CONNECT DATA
NSPFNC AC,SBL(R),ARG(R),ARG(R,P) ;;ACCEPT CONNECT
NSPFNC RJ,SBL(R),ARG(R,P) ;;REJECT CONNECT
NSPFNC RC,SBL(W),ARG(W),ARG(W) ;;READ CONFIRM INFO
NSPFNC SD,SBL(R),ARG(R,P) ;;SYNCHRONOUS DISCONNECT
NSPFNC AB,SBL(R),ARG(R,P) ;;ABORT AND RELEASE
NSPFNC RD,SBL(W),ARG(W) ;;READ DISCONNECT DATA
NSPFNC RL ;;RELEASE CHANNEL
NSPFNC RS,ARG(W),ARG(W) ;;READ STATUS
NSPFNC IS,SBL(R) ;;SEND INTERRUPT DATA
NSPFNC IR,SBL(W) ;;READ INTERRUPT DATA
NSPFNC DS,BCT(R,W),BPT(R,W) ;;SEND NORMAL DATA
NSPFNC DR,BCT(R,W),BPT(R,W) ;;READ NORMAL DATA
NSPFNC SQ,ARG(R),ARG(R),ARG(R) ;;SET QUOTAS AND GOALS
NSPFNC RQ,ARG(W),ARG(W),ARG(W) ;;READ QUOTAS AND GOALS
NSPFNC JS,ARG(R,P),ARG(R,P) ;;SET JOB QUOTAS & GOALS
NSPFNC JR,ARG(W),ARG(W) ;;READ JOB QUOTAS & GOALS
NSPFNC PI,ARG(R) ;;SET PSI REASON MASK
>
SUBTTL Definitions -- NSP. -- Argument Parameters
;Each of these macros is a possible argument to the NSP. UUO.
DEFINE ARG(A1,A2,A3),<COMBLK(<A1,A2,A3>,ARG)>
DEFINE SBL(A1,A2,A3),<COMBLK(<A1,A2,A3>,SBL)>
DEFINE CBL(A1,A2,A3),<COMBLK(<A1,A2,A3>,CBL)>
DEFINE BCT(A1,A2,A3),<COMBLK(<A1,A2,A3>,BCT)>
DEFINE BPT(A1,A2,A3),<COMBLK(<A1,A2,A3>,BPT)>
DEFINE COMBLK(FLAGS,TYPE),<
%FLG==0
IRP FLAGS,<IFNB <FLAGS>,<%FLG==%FLG!AP'FLAGS>>
EXP %FLG!AT.'TYPE>
;These are the optional parameters for any NSP. argument.
BEGSTR AP ;ARGUMENT PARAMETER DESCRIPTOR
FIELD FLG,6 ;FLAGS ASSOCIATED WITH PARAMETER
BIT P ;PRIVILIGED ARG
BIT R ;READ ARG FROM USER AT BEG OF UUO
BIT W ;WRITE ARG TO USER AT END OF UUO
HWORD DSP ;DISPATCH OFFSET BY ARG TYPE
ENDSTR
;These are the possible arguments that can be given to the NSP. UUO.
DEFINE ARGS,<
TYPE ARG ;;GENERALIZED ARGUMENT
TYPE CBL ;;CONNECT BLOCK
TYPE SBL ;;STRING BLOCK
TYPE BCT ;;BUFFER BYTE COUNT
TYPE BPT ;;BUFFER BYTE POINTER
>
;Now expand them to AT.xxx symbols.
DEFINE TYPE(ARG),<
%CNT==%CNT+1
AT.'ARG==%CNT-1>
%CNT==0
ARGS
;Now make the "check arguments" dispatch table.
DEFINE TYPE(ARG),<
IFIW SCC'ARG>
SCUCDS: ARGS
;Now make the "store arguments" dispatch table.
DEFINE TYPE(ARG),<
IFIW SCS'ARG>
SCUSDS: ARGS
;Now make the "discard arguments" dispatch table.
DEFINE TYPE(ARG),<
IFIW SCD'ARG>
SCUDDS: ARGS
;Now expand the dispatch table.
DEFINE NSPFNC(FUNC,ARG1,ARG2,ARG3),<
%CNT==%CNT+1
%ARG==0
IFN <%CNT-.NSF'FUNC>,<
PRINTX ?NSP. Function .NSF'FUNC in SCMUUO not in
PRINTX ? the same order as in SCPAR.UNV
PASS2
END>
IFNB <ARG1>,<%ARG==%ARG+1>
IFNB <ARG2>,<%ARG==%ARG+1>
IFNB <ARG3>,<%ARG==%ARG+1>
EXP [EXP %ARG ;;COUNT OF ARGUMENTS THAT ARE LEGAL
'ARG1 ;;NOTE THAT THIS LITERAL ONLY INCLUDES
'ARG2 ;; ENTRIES FOR %ARG ARGUMENTS
'ARG3]
>
%CNT==0
SCUTAB: NSPFNS
;Now get rid of all those useless symbols.
PURGE CBL,SBL,ARG,BCT,BPT,NSPFNC,NSPS
SUBTTL SCULGO - LOGOUT call from COMCON
;Routine called by COMCON when a job is killed
;
;Call:
; J/ Job number
; PUSHJ P,SCULGO
;Returns:
; CPOPJ ALWAYS
SCUPOP::
SCULGO::MCALL (RG,MSEC1,FNDPDS##) ;SET UP PDB
SKIPN .PDSJB##(W) ;JOB HAVE ANY SJB?
RET ;NO, RETURN
SEC1 ;RUN IN SECTION 1
SCULG1: MOVE T1,.PDSJB##(W) ;GET SJB POINTER
CALL CHKSJB## ;ANY SLBs ?
IFNSK.
CALL SCH1BS ;YES, SLEEP FOR A SECOND
JRST SCULG1 ;AND TRY AGAIN
ENDIF.
;
; Now it's safe to free the SJB
;
MOVE T1,.PDSJB##(W) ;GET SJB POINTER
SETZM .PDSJB##(W) ;AND CLEAR
CALLRET FRESJB## ;FREE THE SJB AND RETURN
SUBTTL SCURST - RESET call from UUOCON
;Called from the UUO handler for an NSP. UUO
;
;Call:
; J/ Job number
;
; RET ;ONLY RETURN
;
;Once the RESET gets the required message blocks, it should be quick;
;SCLINK just closes each of the NSP links, it does not abort or
;otherwise wait for a DISCONNECT sequence. SCLINK does have to wait
;for a CLOSE-COMPLETE message from LLINKS before it can relinquish
;control, since it must free up any message blocks outstanding in the
;lower layers of DECnet.
SCURST::HRRZ T1,JBTPDB##(J) ;GET POINTER TO USER'S PDB
JUMPE T1,CPOPJ## ;JUST GO AWAY IF THERE ISN'T ONE
SKIPN T2,.PDSJB##(T1) ;ANY SJB POINTER THERE?
RET ;NOTHING, LEAVE NOW
SAVEAC <SJ,SA,M,W> ;DN ROUTINES MAY SMASH (M & W)
IFN <<T4-W+1>!<T4-M+2>>,<PRINTX ?W OR M HAS MOVED. FIX THIS CODE>
MOVE SJ,T2 ;SET UP SJ WITH SJB POINTER
SEC1 ;DO DECNET IN SECTION 1
IFE FTXMON,<
DNCALL SCURSU ;DO DECNET IN DECNET CONTEXT
RET
>
;Entry point for SCUINI, J and SJ already set up
SCURSU: SETONE SJRST,(SJ) ;THIS SJB IS BEING RESET, SEE SCUINI
;Here to try the RESET (again, perhaps)
SCURS1: CALL INISAB ;GET AN INITIALIZED SA BLOCK
JRST SCURSL ;CAN'T, WAIT A WHILE AND TRY AGAIN
MOVX T1,.NSFRE ;THE RESET FUNCTION CODE
STOR T1,SAAFN,(SA) ;STORE THE FUNCTION CODE FOR SCLINK
MOVE T1,SA ;SCLINK NEEDS A MSG BLK TO QUEUE
CALL SCTNSF ;TELL SCLINK TO DO THE RESET NOW
TMNE SAERR,(SA) ;DID WE HAVE AN ERROR
JRST SCURSL ;YES, TRY AGAIN LATER
;Here when the RESET has completed
SETZRO SJRST,(SJ) ;SUCCESS, NO LONGER RESETing
CALLRET SCUFSA ;FREE THE SA BLOCK AND RETURN
;Here when the RESET must be restarted later due to allocation failure
SCURSL:
CALL SCUFSA ;FREE THE SA BLOCK
CALL SCH1BS ;SLEEP FOR 1 SECOND
JRST SCURS1 ;TRY RESET AGAIN
;
; ROUTINE TO SLEEP FOR 1 SECOND
;
SCH1BS: MOVEI T1,1 * ^D1000 ;SLEEP FOR ONE SECOND
PUSH P,F ;SAVE WHATEVER AC F IS
SETZM F ;HIBER THINKS F POINTS TO A DDB
MCALL (RG,MCSEC0,HIBER##) ;WAIT FOR SOME MEMORY
POP P,F
RET
SUBTTL SCUUUO -- The NSP. UUO processor
;Called from the UUO handler for an NSP. UUO
;
;Call:
; T1/ UUOCON sets up T1 with contents of AC
; J/ Job Number
;
; RET ;ON ERROR, ERROR CODE IN USER'S AC
; RETSKP ;ON SUCCESS, WITH FUNCTION COMPLETED
INTERNAL SCUUUO
XRENT SCUUUO
IFE FTXMON,<CALL SVDCN##> ;SWITCH TO DECNET CONTEXT
MOVE P1,T1 ;SAVE CONTENTS OF USER AC
CALL SCUINI ;SET UP SJ & SA, SET UP MSG BLK
JRST [ MCALL (RG,MCSEC0,STOTAC##) ;CAN'T GET MEMORY, ERROR CODE IN T1
RET] ;STORE CODE IN USER'S AC, ERROR RETURN
STOR M,SJMUU,(SJ) ;SAVE MUUO FOR STOTAC, ETC
MOVE M,P1 ;POINTER TO USER'S ARG BLOCK
MOVX P2,SJPRV ;GET THE PRIVILEGED-JOB FLAG
ANDCAM P2,SJ.PRV(SJ) ;ASSUME HE'S LOST ANY PRIVS
MCALL (RG,MSEC1,PRVJC##) ;PRIVILEGED JOB?
IORM P2,SJ.PRV(SJ) ;YES, REMEMBER THAT
CALL SCGWRD ;GET THE FUNCTION WORD
SCERR %NEADE,SCUUUE,<Address Error>
CALL SCPWRD ;PUT IT BACK TO CHECK WRITABILITY NOW
SCERR %NEADE,SCUUUE,<Address Error>
HRRZ W,T1 ;TELL SCGWRD THE LENGTH OF ARG BLK
CALL SCUAFN ;PROCESS THE .NSAFN ARG WORD
CALLRET SCUUUE ;PROPOGATE ERROR RETURN
CALL SCGWR1 ;GET CHANNEL NUMBER (MAYBE JOB NUMBER)
SCERR %NEADE,SCUUUE,<Address Error>
CALL SCPWRD ;PUT IT BACK TO CHECK WRITABILITY NOW
SCERR %NEADE,SCUUUE,<Address Error>
STOR T1,SAACH,(SA) ;STORE IT IN THE SA'S ARG BLOCK
CALL SCURAA ;READ THE .NSAAn ARGUMENTS FROM USER
CALLRET SCUUUE ;PROPOGATE ERROR RETURN
;Call SCLINK to perform the NSP. function.
MOVE T1,SA ;T1 POINTS TO SA STRUCTURE'S MSG BLK
CALL SCTNSF ;PERFORM THE FUNCTION
;Now store the arguments in the SA block back into the User Space.
MOVE M,P1 ;RESTORE VIRGIN M FOR SCPWRD
CALL SCUWAxx ;WRITE BACK .NSAxx AS REQUESTED
CALLRET SCUUUI ;WE HAD AN ERROR, CHECK IT
CALL SCUFSA ;FREE THE SA MESSAGE BLOCK
RETSKP ;SUCCESS RETURN
;Here to check the error code returned from SCUWAxx
SCUUUI: CAIE T1,%NEADE ;WAS ERROR AN ADDRESS ERROR?
CALLRET SCUUUE ;NO, NO PROBLEM FOR US
;Here if we had an address error after the function
;If we get here, then we let an erroneous address get through to
;SCLINK and we were very lucky not get get an IME STOPCD.
BUG. CHK,SCMAAE,SCMUUO,SOFT,<Address Check after Function Call>,,<
Cause: This BUG is not documented yet.
>
MOVX T1,%NEADE
CALLRET SCUUUE ;ERROR RETURN TO USER
;Here to deallocate internal SBlock and CBlocks and the message
;block (SA block) used to pass arguments to SCLINK.
;Give error return.
SCUUUE: LOAD M,SJMUU,(SJ) ;TELL STOTAC WHICH AC TO STORE T1 IN
MCALL (RG,MCSEC0,STOTAC##);STORE ERROR CODE IN USER'S AC
; CALLRET SCUFSA ;CALL THE NORMAL ROUTINE
;GIVE ERROR RETURN (ORED)
;Free the SA block and any of its appendages
SCUFSA: OPSTR <SKIPN SA,>,SJSAB,(SJ) ;GET POINTER TO CURRENT SA BLOCK
RET ;LEAVE IF NO SA BLOCK LEFT
OPSTR <SKIPE T1,>,SACBP,(SA) ;IS THERE A CONNECT BLOCK?
CALL DNFWDS ;YES, FREE UP THOSE WORDS
OPSTR <SKIPE T1,>,SASBP,(SA) ;IS THERE A STRING BLOCK?
CALL DNFWDS ;YES, FREE UP THOSE WORDS
MOVE T1,SA ;WE CHECKED SA ABOVE
CALL DNFWDS ;YES, FREE IT
OPSTRM <SETZB SA,>,SJSAB,(SJ) ;WE NO LONGER HAVE AN SA BLOCK
RET ;DONE
SUBTTL SCUUUO -- SCUINI - Initialization
;Here to set up SCUUUO to process an NSP. function (User Mode)
;
;Call:
; RET ;ON ERROR, ERROR CODE IN T1
; RETSKP ;ON SUCCESS
;
;Sets up SA/ Message block to pass to SCLINK
; SJ/ Pointer to SC's job block
; J/ Job Number
SCUINI: SAVEAC <P1,M,W> ;DN ROUTINES MAY SMASH M AND W
IFN <<T4-W+1>!<T4-M+2>>,<PRINTX ?W OR M HAS MOVED. FIX THIS CODE>
HRRZ P1,JBTPDB##(J) ;GET POINTER TO JOB'S PDB
JUMPE P1,[BUG. CHK,SCMNPD,SCMUUO,SOFT,<No PDB for Job>,,<
Cause: This BUG is not documented yet.
>,SCUI.A]
SKIPE SJ,.PDSJB##(P1) ;GET POINTER TO JOB'S SJB
JRST SCUI.1 ;ALREADY HAVE AN SJB, USE IT
;Here to build a SJB for a new job
MOVE T1,SCUDFT ;GET DEFAULT GOAL, QUOTAS
CALL MAKSJB ;GO MAKE AN SJB
SCUI.A: SCERR %NEALF,RTN,<Allocation failure>
MOVE SJ,T1 ;SJB POINTER RETURNED IN T1
STOR J,SJJOB,(SJ) ;SCLINK DOESN'T KNOW ABOUT J
MOVEM SJ,.PDSJB##(P1) ;STORE POINTER TO NEW SJB IN PDB
SCUI.1:
TMNE SJRST,(SJ) ;RESET IN PROGRESS?
CALL SCURSU ;MUST COMPLETE THE RESET FIRST
CALL INISAB ;SET UP AN SA BLOCK TO SEND TO SCLINK
RET ;PROPOGATE ERROR RETURN, CODE IN T1
RETSKP
;Here to set up an SAB block to pass to SCLINK
;
;Call:
; SJ/ Pointer to SC's job block
;
;Return:
; RET ;ON ERROR, ERROR CODE IN T1
; RETSKP ;ON SUCCESS
;
;Sets up SA/ Message block to pass to SCLINK
INISAB: SAVEAC <M,W> ;DN ROUTINES MAY SMASH M AND W
CALL SCUFSA ;FREE ANY LEFTOVER SA BLK & APPENDAGES
SETZM SA ;ZERO SA IN CASE OF ALLOCATION FAILURE
MOVEI T1,SA.LEN ;LENGTH OF AN SA BLOCK
CALL DNGWDS ;GET NON-ZEROED MSG BLK FOR SCLINK ARGS
SCERR %NEALF,RTN,<Allocation Failure>
MOVE SA,T1 ;SET UP SA
STOR SA,SJSAB,(SJ) ;SAVE PTR FOR WHEN WE LEAVE
;Zero some fields we expect to be zero, since block is not zeroed
SETZRO SABCT,(SA) ;SCCBxT NEEDS TO KNOW
SETZRO SABPT,(SA) ; OR NOT WE HAVE A BPT OR COUNT YET
SETZRO SASBP,(SA) ;WE HAVE NO STRING BLOCK
SETZRO SACBP,(SA) ;WE HAVE NO CONNECT BLOCK
SETZRO SAMFG,(SA) ;WE HAVE NO MONITOR FLAGS
;Fill in some fields that we always need in the SA block
STOR SJ,SASJB,(SA) ;STORE THE ADDRESS OF THE SJB
XMOVEI T1,SCUHBR ;POINT TO THE HIBER ROUTINE
STOR T1,SAHBA,(SA) ;STORE IN THE HIBER ADDRESS ARGUMENT
XMOVEI T1,SCUWAK ;GET ADDRESS OF WAKE HANDLER
STOR T1,SAWKA,(SA) ; AND TELL SCLINK ABOUT IT
RETSKP ;SUCCESS
SUBTTL SCUUUO -- SCUAFN - Read the Function Code
;Here to check the .NSAFN word, the function word of the user's args
;
;Call: T1/ The .NSAFN word
;
; RET ;ON SCERR, T1 HOLDS ERROR CODE
; RETSKP ;ON SUCCESS
SCUAFN: LOADE T3,NFSIZ,+T1 ;GET SIGNED SIZE (WORDS) OF ARG BLOCK
CAIGE T3,2 ;DO WE HAVE THE MINIMUM NUMBER OF ARGS
SCERR %NEWNA,RTN,<Wrong number of arguments>
STOR T3,SANAG,(SA) ;SAVE NUMBER OF ARGS IN ARG BLOCK
LOAD T3,NFFLG,+T1 ;GET THE FLAGS FROM THE FLAG FIELD
STOR T3,SAFLG,(SA) ;STORE THEM IN THE SA FLAG WORD
LOAD T3,NFFNC,+T1 ;THE FUNCTION CODE
SKIPLE T3 ;CHECK THAT ITS A VALID FUNCTION
CAILE T3,.NSFMX ; ON THE FUNCTION TYPE
SCERR %NEILF,RTN,<Illegal function>
STOR T3,SAAFN,(SA) ;STORE THE FUNCTION TYPE IN ARG BLOCK
RETSKP
SUBTTL SCUUUO -- SCURAA - Read the AAn Arguments
;Store any connect block or string blocks in the internal connect and
;string block format for SCLINK.
;
;Call: SA/ The message block for SA arguments
;
;Call: RET ;ON SCERR, T1 HOLDS ERROR CODE
; RETSKP ;ON SUCCESS
;
;Arguments with APR set are copied from the user's space to monitor
;buffers for SCLINK. Arguments with APW set are checked to assure that
;when we want to copy data to them after the function is complete that
;we will not find a page fault which would restart the UUO.
SCURAA: SAVEAC <M,W,P1,P2>
LOAD P2,SAAFN,(SA) ;LOAD UP THE FUNCTION CODE
MOVE P2,SCUTAB-1(P2) ;GET THE FUNCTION'S ARGUMENT TABLE
MOVE P1,0(P2) ;GET THE COUNT OF EXPECTED ARGUMENTS
LOAD T1,SANAG,(SA) ;GET THE NUMBER OF ARGUMENTS USER GAVE
CAILE P1,-2(T1) ;CHOSE SMALLER OF THE TWO
MOVEI P1,-2(T1) ; (MINUS .NSAFN AND .NSACH)
ADD P2,P1 ;POINT TO LAST ARG DESCRIPTOR
ADD M,P1 ;POINT TO LAST ARG
JUMPLE P1,RSKP ;SUCCESS IF NO ARGS TO COPY
SCURA1: TMNN <APR,APW>,(P2) ;SHOULD WE READ OR CHECK FOR WRITE?
JRST SCURA3 ;NO, SKIP PROCESSING
;YES
CALL SCGWRD ;GET THE ARGUMENT WORD INTO T1
SCERR %NEADE,RTN,<Address Error>
TMNE SJPRV,(SJ) ;YES, PRIVILEGED JOB?
JRST SCURA2 ;YES, DON'T CHECK THIS ONE
JUMPE T1,SCURA2 ;IF NOTHING SUPPLIED, DON'T PRIV CHECK
TMNE APP,(P2) ;NO, IS THIS A PRIVILEGED FUNCTION?
SCERR %NEPRV,RTN,<No Privileges to Perform Function>
SCURA2: LOAD T2,APDSP,(P2) ;GET THE DISPATCH OFFSET
CALL @SCUCDS(T2) ;CALL THE CORRECT ARGUMENT PROCESSOR
RET ;THERE WAS AN ERROR, PROPAGATE THE ERROR
XMOVEI T2,SA.AA1-1(SA) ;POINT TO FIRST AA ARGUMENT
ADD T2,P1 ;PASS STORAGE LOC TO ARG PROCESSOR
MOVEM T1,(T2) ;STORE VALUE RETURNED BY PROCESSOR
TMNE APR,(P2) ;DID WE REALLY WANT TO READ THIS?
JRST SCURA3 ;YES, ALL DONE
SETZM (T2) ;NO, JUST CHECKING FOR PAGE FAULTS
LOAD T1,APDSP,(P2) ;GET DISPATCH OFFSET AGAIN
CALL @SCUDDS(T1) ;DISCARD STRING OR CONNECT BLOCK
SCURA3: SOJ P2, ;LOOP DOWN THE ARG DESCRIPTORS
SOJ M, ;LOOP DOWN USER'S ARG LIST TOO
SOJG P1,SCURA1 ;LOOP WHILE STILL MORE ARGS
RETSKP ;SUCCESS RETURN
SUBTTL Argument Readers -- SCCCBL - Connect Block
;SCCCBL - Read the Connect-Block argument from user address space
;
; Call: T1/ Contents of argument word
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;ON RESOURCE FAILURE
; RETSKP ;ALL IS OK, WITH T1/ WORD FOR SJAAx
;
; Uses: T1-T4
;
;Note that M is the same as DECnet-36's T6, and is thus not saved
;by calls to DECnet-36 subroutines.
SCCCBL: SAVEAC <M,W,P1,P2> ;PRIVATE M AND SAVE A COUPLE OF PEAS
IFN <<T4-W+1>!<T4-M+2>>,<PRINTX ?W OR M HAS MOVED. FIX THIS CODE>
MOVE P1,T1 ;SAVE USER CBLOCK POINTER
OPSTR <SKIPE T1,>,SACBP,(SA) ;DO WE HAVE A CONNECT BLOCK?
CALL DNFWDS ;YES, GET A SHINY NEW ONE INSTEAD
MOVX T1,CB.LEN ;LENGTH OF A CONNECT BLOCK
CALL DNGWDZ ;GET A ZEROED MONITOR CONNECT BLOCK
SCERR %NERES,RTN,<Resource Error>
STOR T1,SACBP,(SA) ;STORE POINTER TO MONITOR CONNECT BLOCK
MOVE P2,T1 ;SAVE POINTER TO MONITOR CONNECT BLOCK
JUMPE P1,SCCCBX ;LEAVE IF NO USER CONNECT BLOCK
MOVE M,P1 ;SET THE NEW BASE TO GET ARGUMENTS FROM
;LENGTH
CALL SCGWRD ;GET THE LENGTH OF THE USER CBLOCK
SCERR %NEADE,RTN,<Address Error>
HRRZ W,T1 ;TELL SC?WR1 LENGTH OF ARG BLOCK
JUMPE W,SCCCBX ;LEAVE IF THE CONNECT BLOCK IS ZERO LONG
CAIL W,CBL.MN ;RANGE CHECK THE NUMBER OF ARGS
CAILE W,CBL.MX
SCERR %NECBL,RTN,<Connect block length error>
;NAME
CALL SCGWR1 ;GET THE POINTER TO THE NAME BLOCK
SCERR %NEADE,RTN,<Address Error>
CALL GETSXR ;GET THE STRING BLOCK INTO A SIXBIT WORD
SCERR %NEADE,RTN,<Address Error>
SETZRO CBCIR,(P2) ;ZERO CIRCUIT ID
SETZRO CBNUM,(P2) ;AND NODE ADDRESS
LOAD T2,SAAFN,(SA) ;GET FUNCTION CODE
CAIE T2,.NSFEA ;ENTER ACTIVE FUNCTION?
JRST SCCCB1 ;NO, SKIP NAME/ADDRESS MAPPING
STOR T1,CBNUM,(P2) ;SAVE NODE NAME IN CASE SCTN2A FAILS
CALL SCTN2A## ;DO NAME TO NODE ADDRESS TRANSLATION
JRST [ LOAD T1,CBNUM,(P2) ;GET BACK NODE NAME
CALL SCTN2L## ;TRY FOR LOOPBACK NODE NAME
SCERR %NEUKN,RTN,<Unknown node name>
STOR T1,CBCIR,(P2) ;STORE CIRCUIT ID
MOVE T1,RTRADR## ;GET OUR NODE ADDRESS
MOVE T2,RTRHOM## ;AND OUR AREA NUMBER
DPB T2,[POINTR (T1,RN%ARE)] ;BUILD COMPLETE NODE ADDRESS
JRST .+1] ;AND CONTINUE
STOR T1,CBNUM,(P2) ;SAVE FOR LATER USE
SCCCB1:
;SOURCE PROCESS BLOCK
CALL SCGWR1 ;GET THE NEXT ARG (SOURCE PROCESS BLOCK PTR)
SCERR %NEADE,RTN,<Address Error>
XMOVEI T2,CB.SRC(P2) ;PUT IT HERE
CALL GETPRO ;GET THE PROCESS BLOCK
RET ;OOPS, GOT AN ERROR
;DESTINATION PROCESS BLOCK
CALL SCGWR1 ;GET THE DESTINATION PROCESS BLOCK PTR
SCERR %NEADE,RTN,<Address Error>
XMOVEI T2,CB.DST(P2) ;PUT IT HERE
CALL GETPRO ;GET THE PROCESS BLOCK
RET ;OOPS, GOT AN ERROR
;USER ID
CALL SCGWR1 ;GET THE NEXT ARG (USER ID)
SCERR %NEADE,RTN,<Address Error>
JUMPE T1,SCCCB2 ;IS THERE A POINTER TO STRING?
XMOVEI T2,CB.UID(P2) ;YES, POINT TO ITS AREA IN THE INTERNAL CBLOCK
CALL GETSTR ;PUT IT IN
SCERR %NEADE,RTN,<Address Error>
STOR T1,CBUCT,(P2) ;ALONG WITH THE COUNT
SCCCB2:
;PASSWORD
CALL SCGWR1 ;GET THE NEXT ARG (PASSWORD)
SCERR %NEADE,RTN,<Address Error>
JUMPE T1,SCCCB3 ;SBLOCK POINTER?
XMOVEI T2,CB.PSW(P2) ;YES, PASSWORD PLACE IN CBLOCK
CALL GETSTR ;PUT IT IN MONITOR'S CBLOCK
SCERR %NEADE,RTN,<Address Error>
STOR T1,CBPCT,(P2) ;SAVE THE COUNT
SCCCB3:
;ACCOUNT
CALL SCGWR1 ;GET THE NEXT ARG (ACCOUNT STRING)
SCERR %NEADE,RTN,<Address Error>
JUMPE T1,SCCCB4 ;SBLOCK POINTER?
XMOVEI T2,CB.ACC(P2) ;ACCOUNT'S PLACE IN CBLOCK
CALL GETSTR ;PUT IT IN MONITOR'S CBLOCK
SCERR %NEADE,RTN,<Address Error>
STOR T1,CBACT,(P2) ;SAVE THE COUNT
SCCCB4:
;USER DATA
CALL SCGWR1 ;GET THE USER DATA STRING POINTER
SCERR %NEADE,RTN,<Address Error>
JUMPE T1,SCCCBX ;JUMP IF NO USER DATA OFFERED
XMOVEI T2,CB.UDA(P2) ;PUT IT HERE
MOVEI T3,UDA.MX ; WITH THIS MAX LENGTH
CALL GETST1 ; IN THE CBLOCK
SCERR %NEADE,RTN,<Address Error>
STOR T1,CBCCT,(P2) ; ALONG WITH THE COUNT
SCCCBX: LOAD T1,SACBP,(SA) ;RETRIEVE POINTER TO CONNECT BLOCK
RETSKP ;RETURN SUCCESSFULLY TO USER
SUBTTL Argument Readers -- SCCSBL - String Block
;SCCSBL - Process the String-Block argument
;
; Call:
; T1/ Contents of argument word
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;ON ERROR, CODE IN T1
; RETSKP ;SUCCESS, WITH T1 WITH VALUE FOR SJAAx
;
; Uses: T1-T4
;
;We might have blocks hanging off the SA block from last time if
;this is a restarted UUO (after a page fault). We free them and get
;new ones rather than trying to clean them up here to reduce the
;number of paths offered by this code. I assume page fault restarts
;will not happen too often, so the overhead is not significant.
SCCSBL: SAVEAC <M,W,P1,P2> ;GET PRIVATE COPY OF M AND SAVE TWO PS
MOVE P1,T1 ;SAVE THAT POINTER
OPSTR <SKIPE T1,>,SASBP,(SA) ;DO WE HAVE A STRING BLOCK
CALL DNFWDS ;YES, GET A SHINY NEW ONE
JUMPE P1,RSKP ;RETURN SUCCESS, EVEN THOUGH NOT THERE
MOVX T1,SB.LEN ;GET A STRING
CALL DNGWDS ; BLOCK, NO NEED TO ZERO IT
SCERR %NEALF,RTN,<Allocation Failure>
STOR T1,SASBP,(SA) ;SAVE THE POINTER
MOVE P2,T1 ;SAVE THE INTERNAL SBLOCK POINTER
XMOVEI T2,SB.DAT(P2) ;PLACE TO STORE THE USER'S STRING
MOVE T1,P1 ;GET THE POINTER TO USER'S SBLOCK BACK
CALL GETSTR ;STORE THE STRING IN THE SBLOCK
SCERR %NEADE,RTN,<Address Error>
STOR T1,SBCNT,(P2) ;SAVE THE COUNT
LOAD T1,SASBP,(SA) ;GET STRING BLOCK POINTER AGAIN
RETSKP ;RETURN SUCCESS TO THE USER
SUBTTL Argument Readers -- SCCARG - Integer Argument
;SCCARG - Process a random argument
;
; Call:
; T1/ Contents of argument word
; T2/ Pointer to appointed storage loc for this argument
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;COULDN'T DO IT
; RETSKP ;WITH T1 CONTAINING WHAT TO STORE IN THE
; ; USER'S ARG BLOCK
;
; Uses: T1-T4
SCCARG: RETSKP
SUBTTL Argument Readers -- SCCBCT - Byte Count
;SCCBCT - Process a byte count for a buffer
;
; Call:
; T1/ Contents of argument word
; T2/ Pointer to appointed storage loc for this argument
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;COULDN'T DO IT
; RETSKP ;WITH T1 CONTAINING WHAT TO STORE IN THE
; ; USER'S ARG BLOCK
;
; Uses: T1-T4
SCCBCT: SKIPGE T1 ;CHECK FOR NEGATIVE LENGTH
SCERR %NEADE,RTN,<Address Error> ;DON'T ALLOW, SCLINK FALLS OVER
STOR T1,SABCT,(SA) ;STORE AS THE BUFFER BYTE POINTER ALSO
TMNN SABPT,(SA) ;HAVE ASSOCIATED BYTE POINTER YET?
RETSKP ;NO, LET SCCBPT DO IT LATER
CALL SCCBUF ;CHECK THE BUFFER
RET ;ADDRESS ERROR CODE IN T1
LOAD T1,SABCT,(SA) ;GET VALUE FOR CALLER TO STORE IN SAAAx
RETSKP ;SUCCESS
SUBTTL Argument Readers -- SCCBPT - Byte pointer
;SCCBPT - Process a byte pointer for a buffer
;
; Call:
; T1/ Contents of argument word
; T2/ Pointer to appointed storage loc for this argument
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;COULDN'T DO IT
; RETSKP ;WITH T1 CONTAINING WHAT TO STORE IN THE
; ; USER'S ARG BLOCK
;
; Uses: T1-T4
;
;We don't allow indexing or indirection because we store back an incremented
;byte pointer. We would have to store a resolved (no indexing or indirection)
;pointer, because that is what CHKBPT returns and that is what we increment.
SCCBPT: STOR T1,SABPT,(SA) ;STORE AS THE BUFFER BYTE POINTER ALSO
TMNN SABCT,(SA) ;HAVE ASSOCIATED BYTE COUNT YET?
JRST SCCBP1 ;NO, LETS RESOLVE THE BYTE PTR THO
CALL SCCBUF ;CHECK THE BUFFER
RET ;ADDRESS ERROR CODE IN T1
LOAD T1,SABPT,(SA) ;GET VALUE FOR CALLER TO STORE IN SAAAx
RETSKP ;SUCCESS
;Here to resolve the user's byte pointer when we haven't got the
;buffer length yet to check the whole buffer properly.
SCCBP1: SAVEAC M ;CHKBPT SMASHES M
MOVEI T2,1 ;CHECK A 1 BYTE BUFFER
MCALL (RG,MCSEC0,CHKBPT##) ;RESOLVE USER'S INDIRECTION & INDEXING
SCERR %NEADE,RTN,<Address Error>
STOR T1,SABPT,(SA) ;STORE THE RESOLVED BYTE POINTER
RETSKP ;RETURN BYTE PTR IN T1 FOR SCLINK
SUBTTL Argument Readers -- SCCBUF - Buffer Checking Subr
;SCCBUF - Buffer Checking Subroutine for SCCBCT and SCCBPT
;
; Call:
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;ADDRESS ERROR, CODE IN T1
; RETSKP ;SUCCESS
; Restarts UUO on page fault
;
; Uses: T1-T4
;Here to address check the user's buffer
SCCBUF: SAVEAC M ;CHKBPT SMASHES M
LOAD J,SJJOB,(SJ) ;IN CASE WE HAVE A PAGE FAULT
LOAD T1,SABPT,(SA) ;GET BYTE POINTER TO USER'S BUFFER
LOAD T2,SABCT,(SA) ;GET BYTE LENGTH OF USER'S BUFFER
MCALL (RG,MCSEC0,CHKBPT##);GO ASK VMSER IF THIS BPT IS SAFE
;NOTE THAT M HAS BEEN TRASHED.
SCERR %NEADE,RTN,<Address Error>
STOR T1,SABPT,(SA) ;STORE THE RESOLVED BYTE POINTER
RETSKP ;RETURN TO CALLER
;Copy back the .NSAFN and .NSACH words to the user's arg blk
;
;Call: SA/ The message block for SA arguments
; M/ Pointer to user's arg block for SCGWRD
;
; RET ;ON ERROR, CODE IN T1
; RETSKP ;ON SUCCESS
;
;We checked before the function that there were at least 2 args
;passed, so we don't have to check again here.
SCUWAx:SAVEAC <P1,P2>
CALL SCGWRD ;GET THE FLAGS AND FUNCTION WORD
SCERR %NEADE,RTN,<Address Error>
HRRZ W,T1 ;LOAD UP LENGTH FOR SC?WR1
LOAD T2,SAFLG,(SA) ;GET SA'S FLAGS
STOR T2,NFFLG,+T1 ;REPLACE THE OLDER FLAGS
CALL SCPWRD ;PUT THE WORD BACK IN THE USER'S SPACE
SCERR %NEADE,RTN,<Address Error>
LOAD T1,SAACH,(SA) ;GET THE STATUS WORD,,CHANNEL NUMBER
OPSTR <HRL T1,>,SAAST,(SA) ;GET THE STATUS IN THE LEFT HALF
CALL SCPWR1 ;WRITE IT BACK TO USER SPACE
SCERR %NEADE,RTN,<Address Error>
OPSTR <SKIPE T1,>,SAERR,(SA) ;DID WE GET A FAILURE?
RET ;ERROR RETURN, CODE IN T1
;Fall through to next page
; to copy .NSAA1, .NSAA2 and .NSAA3 as requested
;From previous page
;Here to copy .NSAA1, .NSAA2 and .NSAA3 as requested
LOAD P2,SAAFN,(SA) ;LOAD UP THE FUNCTION CODE
MOVE P2,SCUTAB-1(P2) ;GET THE FUNCTION'S ARGUMENT TABLE
MOVE P1,0(P2) ;GET THE COUNT OF EXPECTED ARGUMENTS
LOAD T1,SANAG,(SA) ;GET THE NUMBER OF ARGUMENTS USER GAVE
CAIL P1,-2(T1) ;CHOSE SMALLER OF THE TWO
MOVEI P1,-2(T1) ; (MINUS .NSAFN AND .NSACH)
ADD P2,P1 ;POINT TO LAST ARG DESCRIPTOR
ADD M,P1 ;POINT TO LAST ARG
JUMPLE P1,RSKP ;SUCCESS IF NO ARGS TO COPY
SCUWA1: TMNN APW,(P2) ;SHOULD WE WRITE THIS ARG?
JRST SCUWA2 ;NO, SKIP WRITE PROCESSOR
CALL SCGWRD ;GET THE NEXT USER ARGUMENT
SCERR %NEADE,RTN,<Address Error>
MOVE T2,T1 ;PUT THE ARGUMENT IN T2
XMOVEI T1,SA.AA1-1(SA) ;POINT TO ARGUMENTS IN ARG BLOCK
ADD T1,P1 ;GET THE ONE WE'RE LOOKING AT
MOVE T1,(T1) ;GET THE CONTENTS OF SAAAx
LOAD T3,APDSP,(P2) ;GET THE DISPATCH OFFSET
CALL @SCUSDS(T3) ;CALL THE CORRECT ARGUMENT PROCESSOR
RET ;PROPOGATE ERROR RETURN
CALL SCPWRD ;PLACE THE WORD BACK
SCERR %NEADE,RTN,<Address Error>
SCUWA2: SOJ P2, ;LOOP DOWN THE ARG DESCRIPTORS
SOJ M, ;LOOP DOWN USER'S ARG LIST TOO
SOJG P1,SCUWA1 ;LOOP WHILE STILL MORE ARGS
RETSKP ;SUCCESS RETURN
SUBTTL Argument Writers -- SCSCBL - Store Connect Block into User Space
;SCSCBL - Give user a connect block back
;
; Call:
; T1/ Contents of SAAAx after SCLINK
; T2/ Contents of user argument
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;ON AN ADDRESS FAILURE
; RETSKP ;ON SUCCESS
;
; Uses: T1-T4
SCSCBL: SAVEAC <M,W,P1,P2> ;GET A COPY OF M AND SAVE SOME PEAS
MOVE P2,T2 ;SAVE POINTER TO USER'S CONNECT BLK
SKIPN M,T2 ;GET THE POINTER TO CONNECT BLOCK
SCERR %NEABE,RTN,<Argument Block Format Error>
CALL SCGWRD ;GET ARG BLOCK LENGTH WORD
SCERR %NEADE,RTN,<Address Error>
HRRZ W,T1 ;SAVE FOR SCPWR1
LOAD P1,SACBP,(SA) ;MAKE P1 POINT TO THE CONNECT BLOCK
LOAD T1,CBNUM,(P1) ;GET THE NODE NUMBER
CALL SCTA2N## ;GET THAT NODE'S NAME
SETZ T1, ;DON'T HAVE A NAME, LEAVE IT ZERO LENGTH
CALL PUTSX1 ; AND PLACE IT AFTER LENGTH WORD
RET ;ERROR, CODE IN T1
XMOVEI T2,CB.SRC(P1) ;POINT TO THE SOURCE PROCESS DESCRIPTOR
CALL PUTPR1 ;PLACE IT IN THE USER'S AREA
RET ;ERROR, CODE IN T1
XMOVEI T2,CB.DST(P1) ;THE DESTINATION PROCESS DESCRIPTOR
CALL PUTPR1 ;PLACE IT IN THE USER'S AREA
RET ;ERROR, CODE IN T1
LOAD T1,CBUCT,(P1) ;GET THE USER ID BYTE COUNT
XMOVEI T2,CB.UID(P1) ;POINT TO THE STRING
CALL PUTST1 ;PLACE THE STRING
RET ;ERROR, CODE IN T1
LOAD T1,CBPCT,(P1) ;GET THE PASSWORD'S BYTE COUNT
XMOVEI T2,CB.PSW(P1) ;POINT TO THE STRING
CALL PUTST1 ;PLACE IN USER SPACE
RET ;ERROR, CODE IN T1
LOAD T1,CBACT,(P1) ;GET THE ACCOUNT NAME BYTE COUNT
XMOVEI T2,CB.ACC(P1) ;POINT TO THE STRING
CALL PUTST1 ; AND PUT IT IN THE USER'S AREA
RET ;ERROR, CODE IN T1
LOAD T1,CBCCT,(P1) ;GET THE COUNT OF CONNECT DATA
XMOVEI T2,CB.UDA(P1) ;POINT TO THE CONNECT DATA
CALL PUTST1 ; PLACE IT IN THE USER'S AREA
RET ;ERROR, CODE IN T1
MOVE T1,P2 ;RESTORE CONNECT BLOCK POINTER
RETSKP ; AND RETURN
SUBTTL Argument Writers -- SCSSBL - Store String Block into User Space
;SCSSBL - Give user a string block back
;
; Call:
; T1/ Contents of SAAAx after SCLINK (ignored here)
; T2/ User pointer to string block
; P1/ Pointer to flag word in SCUTAB for function
; SJ/ Pointer to Session Control Job Block
; M/ Pointer to pointer to string block in user's address space
;
; Return:
; RET ;ON ADDRESS FAILURE
; RETSKP ;ON SUCCESS
;
; Uses: T1-T4
;
;In this routine, we ignore the contents of SAAAx, since we have a
;pointer to the string block in SASBP.
SCSSBL: SAVEAC P1 ;SAVE PTR TO USER STRING BLK HERE
MOVE P1,T2 ;WE'LL NEED THIS LATER
LOAD T2,SASBP,(SA) ;POINTER TO STRING BLOCK
LOAD T1,SBCNT,(T2) ;GET COUNT OF BYTES WE GOT FROM MESSAGE
ADDI T2,SB.DAT ;POINT TO START OF STRING'S DATA
CALL PUTSTR ;PUT STRING IN USER'S STRING BLOCK
RET ;ADDRESS ERROR, CODE IN T1
MOVE T1,P1 ;RESTORE UVA OF STRING BLK FOR SCUWAAx
RETSKP ;SUCCESS RETURN
SUBTTL Argument Writers -- SCSARG, SCSBCT, SCSBPT
;SCSARG - Store some random argument
;
; Call:
; T1/ Contents of argument word
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;COULDN'T DO IT
; RETSKP ;WITH T1 CONTAINING WHAT TO STORE IN THE
; ; USER'S ARG BLOCK
;
; Uses: T1
SCSBCT: ;NO NEED TO CHECK THIS ON WRITE-BACK
SCSBPT: ;DITTO
SCSARG: RETSKP ;JUST GIVE HIM WHAT HE GAVE US
SUBTTL Argument Discarders -- SCDARG, SCDCBL, SCDSBL
;SCDARG - Discard a block we just built to check for user page faults
;
; Call:
; SA/ Pointer to SA block
; SJ/ Pointer to Session Control Job Block
;
; Return:
; RET ;ONLY RETURN
;
; Uses: T1
SCDBCT: ;NOTHING TO DO FOR BYTE COUNT
SCDBPT: ;NOTHING TO DO FOR BYTE POINTER
SCDARG: RET ;NOTHING TO DO FOR SINGLE ARG
SCDCBL: OPSTR <SKIPE T1,>,SACBP,(SA) ;IS THERE A CONNECT BLK?
CALL DNFWDS ;YES, FREE THE CONNECT BLOCK
SETZRO SACBP,(SA) ;NO MORE CONNECT BLOCK
RET
SCDSBL: OPSTR <SKIPE T1,>,SASBP,(SA) ;IS THERE A STRING BLK?
CALL DNFWDS ;YES, FREE THE CONNECT BLOCK
SETZRO SASBP,(SA) ;NO MORE STRING BLOCK
RET
SUBTTL Subroutines -- SCUHBR - Subroutine to do the HIBERs.
;SCUHBR - Called by SCLINK to hibernate
;
; Call:
; T1/ Pointer to SJB
;
; Return:
; RET ;ONLY RETURN
;
; Uses: T1
SCUHBR: SAVEAC <FREE1,FREE2,MB,MS,F,J,SJ> ;SAVE A FEW ACS
MOVE SJ,T1 ;POINTER TO SJB
SETZM F ;F DOES NOT HOLD PTR TO A DDB!
LOAD J,SJJOB,(SJ) ;MONITOR WANTS TO KNOW WHAT JOB THIS IS
MOVX T1,EV.DCN ;DECNET EVENT WAIT
MCALL (RG,MCSEC0,ESLEEP##) ;SCUWAK GETS US OUT OF THIS.
RET ;AND RETURN
SUBTTL Subroutines -- SCUWAK - Subroutine to do the WAKEs.
;SCUWAK - Called when SCLINK thinks we might want to wake the user
;
; Call: T1/ Old Status,,PSI Mask
; T2/ New Status,,Channel Number
; T3/ Pointer to Session Control Job Block
; T4/ Link identifier to pass to SCTWKQ
; T5/ ???,,Status Changes
;
; Return:
; RET ;Tells SCLINK not to queue SLB
; RETSKP ;Tells SCLINK to queue SLB for SCTPSQ
;
; Uses: T1,T2,T3,T4
;
;SCLINK calls this routine (via SAWKA,(SA)) when either the link
;state has changed or one of the status bits has changed from a
;zero to a one.
SCUWAK: ;INISAB PASSES ADDR TO SCLINK
SAVEAC <FREE1,FREE2,MB,MS,J,P1> ;SAVE A FEW ACS FROM TOPS-10
MOVE P1,T3 ;POINTER TO SJB
;Note that T4 contains the link identifier we pass to SCTWKQ
T5==T4+1 ;DEFINE T5 FOR INTERFACE WITH DECNET
AND T5,T1 ;AND CHANGES WITH THE PSI MASK
TRNN T5,-1 ;ANY INTERESTING CHANGES?
JRST SCUWK1 ;NO, SKIP PSI
;Here to signal a PSI interrupt. PSISER will call SCTPSI later
;to discover the reason, so we offer none here.
;If the PSI is accepted, we don't have to do a WAKE as well, because
;PSISER does that for us.
MOVE T1,T4 ;PASS LINK IDENTIFIER TO SCTWKQ
CALL SCTWKQ ;ASK SCLINK TO QUEUE THIS LINK FOR SCTPSQ
JUMPE T1,SCUWK1 ;ALREADY QUEUED; DON'T DO IT AGAIN
LOAD J,SJJOB,(P1) ;GET JOB NUMBER WE'RE TO INTERRUPT
; SIGNAL C$NSP ;SIGNAL A PSI INTERRUPT
HRROI T1,C$NSP ;THIS HAS TO BE DONE BY HAND SINCE XCALL MUST BE EXECUTED
XCT NOPISK## ;PSI ENABLED?
MCALL (RG,MSEC1,PSICND##) ;SIGNAL
JRST SCUWK1 ;HIBER WAKE ALSO IF PSI DIDN'T WAKE
JRST SCUWK2 ;SKIP ASYNCH I/O WAKE IF PSI DID WAKE
;We have to wake the job anyway, for users with asynchronous I/O
SCUWK1: LOAD J,SJJOB,(P1) ;GET JOB NUMBER
MOVSI T1,IOACE## ;ASYNC IO WAKE BIT (USER CALLS IT HB.RIO)
TDNE T1,JBTRTD##(J) ;IS THIS JOB INTERESTED IN SUCH WAKEUPS?
MCALL (RG,MCSEC0,WAKEJB##);HIBERING ON ASYNC I/O, WAKE IT UP.
SCUWK2: LOAD T1,SJJOB,(P1) ;GET JOB NUMBER FOR EWAKE
MCALL (RG,MCSEC0,EWAKE##);(T1)GET JOB OUT OF EW OR MARK FOR WAKE
RET ;AND RETURN
PURGE T5 ;AND FORGET ABOUT THIS DEFINITION
SUBTTL Subroutines -- SCTPSI - Get PSI associated variable
;SCTPSI - Called from PSISER to get associated variable for interrupt
;
; Call: J/ Job Number
;
; Return:
; T2/ Link Status,,Link Number (Channel Number)
; ;T2 is zero if error found
; RET ;Always
;
; Uses: T1,T2,T3,T4
;
;Since there is no state zero, if we return a zero in T2 (the
;value that will be given to the user as PSI's associated variable)
;we are telling the user that this is a null interrupt. We should
;not give null interrupts, of course, but we need some way of passing
;on errors here...
SCTPSI::
SEC1 ;DO OUR STUFF IN EXTENDED SECTIONS
SAVEAC <T1,T3,T4,W,M,CX>;PSISER IS PICKY. DECNET TRASHES THESE ACS.
IFN <<T4-W+1>!<T4-M+2>>,<PRINTX ?W OR M HAS MOVED. FIX THIS CODE>
;Load up SJ with the SJB pointer to SCLINK
SKIPN T1,JBTPDB##(J) ;GET POINTER TO JOB'S PDB
BUG. CHK,SCMNP2,SCMUUO,SOFT,<No SJB for SCTPSI>,,<
Cause: This BUG is not documented yet.
>,SCTPSE
HRRZS T1 ;MAKE IT A SECTION ZERO POINTER (NFYPGS)
SKIPN T1,.PDSJB##(T1) ;GET POINTER TO JOB'S SJB FOR SCTPSQ
JRST SCTPSE ;NO SJB, SHOULD NOT HAPPEN
CALL SCTPSQ ;ASK SCLINK TO DEQUEUE NEXT SLB
JRST SCTPSE ;NONE THERE, RETURN T2/ ZERO
TXNN T1,PSMOR ;ANY MORE SLBs NEED INTERRUPTS?
RET ;NO, RETURN T2/ STATUS,,CHN NUMBER
PUSH P,T2 ;YES, SAVE T2 FROM PSISER
;J IS ALREADY LOADED BY PSISER
; SIGNAL C$NSP ;SIGNAL ANOTHER INT AFTER THIS ONE
HRROI T1,C$NSP ;DO THIS BY HAND
XCT NOPISK## ;PSI ENABLED?
MCALL (RG,MSEC1,PSICND##) ;SIGNAL THE INTERRUPT
JFCL ;IGNORE FAIL RETURN (UNLIKELY)
POP P,T2 ;RESTORE ASSOCIATED VARIABLE FOR PSISER
RET ;RETURN T2/ STATUS,,CHN NUMBER
;Here on error
SCTPSE: MOVEI T2,0 ;ERROR RETURN, GIVE USER NULL INTERRUPT
RET
SUBTTL Subroutines -- SCGWRD & SCPWRD
; Calls:
; T1/ Word to write for SCPWRD & SCPWR1
; M/ User Address to GET/PUT
; W/ Remaining length of user arg block
; SJ/ Pointer to Session Control Job Block
; SA/ Pointer to Message Block used for SA args
;
; Return:
; RET ;ADDRESS ERROR, CALLER MUST HANDLE IT
; ; SA BLOCK HAS BEEN DEALLOCATED
; RETSKP ;WITH T1 HOLDING SCGWRD/SCGWR1 WORD
;
; Uses: T1
;
;When the caller reads the length (first) word of a user arg block,
;s/he is expected to HRRZ W,T1 afterwards for these routines.
;
;Calls to SCGWRD and SCPWRD are assumed to know whether or not there
;is room, eg, they are used to get/put the length word.
;Calls to SC?WR1 are checked for room before they are executed.
IFN R-CX,<PRINTX ?SCGWRD needs CX and R to be the same AC>
;These routines do not save R, assuming that it is CX, the super-temp.
SCGWR1: ADDI M,1 ;GET THE NEXT WORD
SOJLE W,SCGW.1 ;LEAVE IF NO MORE TO READ
SCGWRD:
LOAD J,SJJOB,(SJ) ;SET UP J IN CASE OF PAGE FAULT
MOVE R,.CPADR## ;GETWRD NEEDS R SET UP
MCALL (RG,MSEC1,GETWRD##) ;YES, CALL STANDARD TOPS10 GET WORD
RET ;BAD RETURN
RETSKP ;SKIP RETURN
SCGW.1: SETZ T1, ;NO, RETURN ZERO
RETSKP ;SUCCESS RETURN
SCPWR1: ADDI M,1 ;PUT IN THE NEXT WORD
SOJLE W,SCGW.1 ;LEAVE IF NO MORE ROOM TO WRITE
SCPWRD: LOAD J,SJJOB,(SJ) ;SET UP J IN CASE OF PAGE FAULT
MOVE R,.CPADR## ;PUTWRD NEEDS R SET UP
MCALL (RG,MSEC1,PUTWRD##) ;CALL STANDARD TOPS10 PUT WORD
RET ;NON-SKIP RETURN
RETSKP ;SKIP RETURN
SUBTTL Subroutines -- GETPRO - Get process block
;GETPRO - Transfer user's process block to a portion of internal connect block
;
; Call:
; T1/ Pointer to user's process block (destination or source)
; T2/ Pointer to some portion of the internal connect block
;
; Return:
; RET ;ON ERROR WITH T1 CONTAINING ERROR CODE
; RETSKP ;ON SUCCESS
;
; Uses: T1-T4
GETPRO: SAVEAC <M,W,P1,P2> ;GET OUR OWN M AND SAVE A P
MOVE P2,T2 ;SAVE THE POINTER TO INTERNAL CBLOCK
SKIPN M,T1 ;SET UP TO GET WORDS FROM USER'S BLOCK
RETSKP ;LEAVE EMPTY BLOCK IF NO USER POINTER
;LENGTH
CALL SCGWRD ;GET THE LENGTH WORD
SCERR %NEADE,RTN,<Address Error>
HRRZ W,T1 ;TELL SC?WR1 LENGTH OF ARG BLOCK
JUMPE W,RSKP ;LEAVE EMPTY BLK IF USER'S IS ZERO LONG
CAIL W,PBL.MN ;RANGE CHECK THE LENGTH
CAILE W,PBL.MX
SCERR %NEPBL,RTN,<Process block length error>
STOR W,PBSIZ,(P2) ;STORE THE LENGTH
;FORMAT TYPE
CALL SCGWR1 ;GET THE FORMAT TYPE
SCERR %NEADE,RTN,<Address Error>
STOR T1,PBFOR,(P2) ;STORE IT IN THE INTERNAL CONNECT BLOCK
CAIL T1,FRM.0 ;RANGE CHECK THE
CAILE T1,FRM.MX ; FORMAT TYPE
SCERR %NEBFT,RTN,<Bad format type in process block>
;OBJECT TYPE
CALL SCGWR1 ;GET THE OBJECT TYPE
SCERR %NEADE,RTN,<Address Error>
TMNN PBFOR,(P2) ;IS THIS A ZERO FORMAT TYPE?
STOR T1,PBOBJ,(P2) ;YES, STORE THE OBJECT TYPE
;Fall through to next page
;From previous page
IFN <PB.USR-PB.GRP>,<IF2,<PRINTX ?PB.USR and PB.GRP must be the same>>
;PPN
CALL SCGWR1 ;GET THE PPN (GRPCODE AND USRCOD)
SCERR %NEADE,RTN,<Address Error>
AND T1,[177777,,177777] ;LIMIT TO 16 BITS IN EITHER HALF
LOAD T2,PBFOR,(P2) ;GET THE FORMAT TYPE AGAIN
CAIN T2,FRM.2 ;IS IT A FORMAT TWO?
MOVEM T1,PB.USR(P2) ;YES, PRINTX ABOVE CHECKS THIS MOVEM
;TASK NAME
CALL SCGWR1 ;GET THE POINTER TO THE STRING BLOCK
SCERR %NEADE,RTN,<Address Error>
XMOVEI T2,PB.NAM(P2) ;SETUP TO STORE STRING IN INT. CBLOCK
CALL GETSTR ;STORE IT
SCERR %NEADE,RTN,<Address Error>
STOR T1,PBNCT,(P2) ;STORE STRING LENGTH TOO
RETSKP ;SUCCESS RETURN
SUBTTL Subroutines -- GETSTR - Get a string block
;GETSTR - Transfer user's string block to internal string block
;
; Call:
; T1/ Pointer to the user's string block
; T2/ Pointer to internal block to store string in (not a byte pointer)
;
; Return:
; RET ;ADDRESS FAILURE
; RETSKP ;SUCCESS, T1/ BYTE COUNT
;
; Uses: T1-T4
GETSTR: MOVEI T3,SB.MAX ;DEFAULT MAXIMUM LENGTH OF STRING
GETST1: SAVEAC <M,W,P1,P2> ;GET A COPY OF M AND SAVE TWO PS
SKIPN M,T1 ;SET UP TO SCGWRD FROM HERE
RETSKP ;DON'T DO ANYTHING IF NO POINTER GIVEN
MOVE P2,T2 ;SAVE THE INTERNAL SBLOCK POINTER
CALL SCGWRD ;GET THE COUNT
RET ;ADDRESS ERROR, CALLER WILL DEAL W/ IT
HRRE W,T1 ;TELL SCGWR1 LENGTH OF ARG BLOCK
HLRZS T1 ;ISOLATE BYTE COUNT IN RIGHT HALF
JUMPE T1,RSKP ;LEAVE NOW IF NOTHING TO DO
CAMLE T1,T3 ;WILL THIS FIT IN A STRING BLOCK?
RET ;NO, ADDRESS ERROR
SAVEAC T1 ;RETURN BYTE COUNT ON EXIT
MOVEI P1,3(T1) ;SET TO ROUND UP ON DIVIDE
ASH P1,-2 ;CHANGE BYTE COUNT TO WORD COUNT
GETS.1: CALL SCGWR1 ;GET NEXT WORD FROM USER'S STR BLK
RET ;CALLER WILL HANDLE ADDRESS CHECK
MOVEM T1,(P2) ;STORE IN MONITOR BUFFER
AOJ P2, ;WALK UP THE MONITOR BUFFER
SOJG P1,GETS.1 ;LOOP OVER ALL WORDS SPECIFIED
RETSKP ;SUCCESS RETURN, SEE SAVEAC T1 ABOVE
SUBTTL Subroutines -- GETSXR - Get string block to sixbit word
;GETSXR - Transfer user's string block to internal sixbit word
;
; Call:
; T1/ Pointer to the user's string block
;
; Return:
; T1/ SIXBIT word (usually node name)
;
; Uses:
; T1-T4
GETSXR: SAVEAC <M,W,P1,P2,F> ;WE USE A BUNCH OF ACS
SKIPN M,T1 ;PUT POINTER WHERE SCGWRD CAN FIND IT
RETSKP ;IF NO POINTER, SIMPLY RETURN.
CALL SCGWRD ;GET STRING BLOCK HEADER
RET ;FAIL
HRRE W,T1 ;LENGTH OF STRING BLOCK IN WORDS.
HLRZ P1,T1 ;NUMBER OF BYTES TO FETCH
CAILE P1,6 ;WILL NAME FIT IN A SIXBIT WORD
RET ;NO.
SETZ P2, ;CLEAR DESTINATION WORD
MOVE F,[POINT 6,P2] ;BYTE POINTER TO SAVE SIXBIT BYTES
GETSX1: JUMPLE P1,GETSX9 ;IF NO MORE BYTES TO DO, EXIT
CALL SCGWR1 ;MORE BYTES TO DO, GET A WORD TO PROCESS
RET ;FAIL
MOVE T4,[POINT 8,T1] ;BYTE POINTER INTO SOURCE STRING
MOVEI T3,4 ;MAX NUMBER OF BYTES IN A WORD
CAMLE T3,P1 ;ARE THAT MANY BYTES LEFT?
MOVE T3,P1 ;NO, TAKE THE NUMBER THAT ARE LEFT
SUB P1,T3 ;DECREMENT NUMBER OF BYTES LEFT
GETSX2: ILDB T2,T4 ;GET A BYTE
CAILE T2,^O140 ;IS IT LOWER CASE?
SUBI T2,^O40 ;YES, MAKE IT UPPER CASE
SUBI T2,^O40 ;MAKE IT SIXBIT
IDPB T2,F ;SAVE IN DESTINATION WORD
SOJG T3,GETSX2 ;AND LOOP FOR ANOTHER BYTE
JRST GETSX1 ;AND LOOP FOR ANOTHER WORD
GETSX9: MOVE T1,P2 ;SIXBIT WORD.
RETSKP ;RETURN SUCCESS
SUBTTL Subroutines -- PUTPRO - Write Process Block to User's Space
;PUTPRO - Write Process Block to User's Space
;
; Call:
; T2/ Pointer to the Process Block portion of the CBLOCK
; M/ Pointer to the next argument in the CBLOCK
; W/ Remaining Length of block M points at
;
; Return:
; RET ;ON ERROR, CODE IN T1
; RETSKP ;ALL IS OK
;
; Uses: T1-T4
PUTPR1: ADDI M,1 ;INCR FIRST, LIKE SCGWR1,SCPWR1, ETC
SOJLE W,RSKP ;LEAVE IF NO ADDRESS SUPPLIED
PUTPRO: SAVEAC <M,W,P1,P2>
MOVE P2,T2 ;SAVE THE POINTER TO PROCESS BLOCK
CALL SCGWRD ;GET THE NEXT ARG POINTER FROM CBLOCK
SCERR %NEADE,RTN,<Address Error>
MOVE M,T1 ;SET UP THE POINTER TO PBLOCK
CALL SCGWRD ;GET THE USER'S LENGTH WORD
SCERR %NEADE,RTN,<Address Error>
HRRZ W,T1 ;SAVE LENGTH IN WORDS
;FORMAT TYPE
LOAD T1,PBFOR,(P2) ;GET THE FORMAT TYPE
CALL SCPWR1 ;PLACE THIS WORD AFTER COUNT WORD
SCERR %NEADE,RTN,<Address Error>
LOAD T1,PBOBJ,(P2) ;GET THE OBJECT TYPE
;OBJECT TYPE
CALL SCPWR1 ;PLACE THE OBJECT TYPE IN USER SPACE
SCERR %NEADE,RTN,<Address Error>
;TASK NAME
IFN <PB.USR-PB.GRP>,<IF2,<PRINTX ?PB.USR and PB.GRP must be the same>>
MOVE T1,PB.USR(P2) ;PBUSR AND PBGRP ARE CHECK TO BE THE SAME
CALL SCPWR1 ;STORE PPN (USER AND GROUP)
SCERR %NEADE,RTN,<Address Error>
LOAD T1,PBNCT,(P2) ;GET THE BYTE COUNT
XMOVEI T2,PB.NAM(P2) ;POINT TO THE STRING
CALL PUTST1 ;PLACE IT BACK IN USER'S SPACE
RET ;BUG. ALREADY GIVEN FOR ADDRESS ERROR
RETSKP ;ALL IS OK
SUBTTL Subroutines -- PUTSTR - Write String Block to User's Space
;PUTSTR - Write String Block to User's Space
;
; Call:
; T1/ Byte Count of String
; T2/ Pointer (not a byte pointer) to String
; M/ Pointer to Pointer to User's String Block
; W/ Remaining Length of block M points at
;
; Return:
; RET ;ON ADDRESS ERROR, CALLER TO HANDLE IT
; RETSKP ;ON SUCCESS
;
; Uses: T1-T4
PUTST1: ADDI M,1 ;STR BLK POINTER IS IN NEXT USER WORD
SOJLE W,RSKP ;LEAVE IF NO ADDRESS SUPPLIED
PUTSTR: SAVEAC <M,W,P1,P2>
DMOVE P1,T1 ;SAVE BYTE COUNT,BYTE POINTER
CALL SCGWRD ;GET PTR TO STRING BLOCK
SCERR %NEADE,RTN,<Address Error>
SKIPN M,T1 ;GET OUR M SET UP
RETSKP ;OOPS, COPIED NOTHING
;There should be a count in the first word of the string block
;indicating the maximum count of bytes to place in the string.
CALL SCGWRD ;GET THE COUNT WORD
SCERR %NEADE,RTN,<Address Error>
HRRZ W,T1 ;TELL SCPWR1 ABOUT THE LENGTH
HRRZ T3,T1 ;GET WORD COUNT AGAIN
SOJLE T3,RSKP ;SUBTRACT ONE DUE TO LENGTH WORD
ASH T3,2 ;MULT BY FOUR TO GET BYTE COUNT
CAMLE P1,T3 ;THERE ENOUGH ROOM IN THE USER'S BLOCK?
MOVE P1,T3 ;NO, USE HIS MAX
HRL T1,P1 ;GET THE BYTE COUNT IN LEFT HALF
;WORD LENGTH STILL IN THE RIGHT HALF
CALL SCPWRD ;PLACE IT IN THE COUNT WORD
SCERR %NEADE,RTN,<Address Error>
ADDI P1,3 ;MAKE FOLLOWING DIVIDE ROUND UP
ASH P1,-2 ;CONVERT BYTE COUNT TO WORD COUNT
;Note that we come all the way to here even if the byte count is zero
;because we have to put the count in the user's string block.
PUTS.1: SOJL P1,RSKP ;SUCCESS WHEN WE'VE COPIED ALL THERE IS
MOVE T1,(P2) ;GET NEXT WORD FROM MONITOR BUFFER
CALL SCPWR1 ;PUT IT IN NEXT WORD OF USER'S STR BLK
SCERR %NEADE,RTN,<Address Error>
AOJA P2,PUTS.1 ;POINT TO NEXT SOURCE WORD AND TRY IT
SUBTTL Subroutines -- PUTSTR - Write SIXBIT word to user's String Block
;PUTSXR - Write SIXBIT word into String block in user space
;
; Call:
; T1/ SIXBIT word (usually node name)
; M/ Pointer to Pointer to User's Arg Block
; W/ Remaining Length of block M points at
;
; Return:
; RET ;ON ADDRESS ERROR, CALLER TO HANDLE IT
;
; Uses T1-T4
;
PUTSX1: ADDI M,1 ;POINT TO NEXT LOCATION IN ARG BLOCK
SOJLE W,RSKP ;IF NOT IN BLOCK, JUST RETURN
PUTSXR: SAVEAC <M,W,P1,P2,F> ;SOME ACS WE USE
MOVE P1,T1 ;SAVE SIXBIT WORD
CALL SCGWRD ;GET THE ENTRY FOR THIS STRING BLOCK
SCERR %NEADE,RTN,<Address error>
SKIPN M,T1 ;MAKE SURE WE GOT SOMETHING
RETSKP ;USER DOESN'T WANT THE NODE NAME
CALL SCGWRD ;GET THE STRING BLOCK HEADER WORD
SCERR %NEADE,RTN,<Address error>
HRRZ W,T1 ;NUMBER OF WORDS IN STRING BLOCK
;COUNT THE CHARACTERS IN SIXBIT WORD
MOVSI T2,770000 ;MASK FOR SIXBIT CHARACTER
TDZA P2,P2 ;START OFF COUNT AT ZERO BYTES
PUTSX2: LSH T2,-6 ;SHIFT MASK BY ONE CHARACTER
TDNE T2,P1 ;DO WE HAVE A CHARACTER IN THIS POSITION?
AOJA P2,PUTSX2 ;YES, COUNT IT AND TRY FOR NEXT CHARACTER
HRL T1,P2 ;RETURN THE NUMBER OF BYTES WE ARE GIVING
CALL SCPWRD ; IN THE HEADER WORD OF THE STRING BLOCK
SCERR %NEADE,RTN,<Address error>
MOVE F,[POINT 6,P1] ;BYTE POINTER TO SIXBIT WORD
PUTSX3: JUMPE P2,RSKP ;RETURN
MOVE T4,[POINT 8,T1] ;BYTE POINTER TO EIGHTBIT DESTINATION WORD
SETZ T1, ;CLEAR DESTINATION WORD
MOVEI T3,4 ;NUMBER OF BYTES WHICH WILL FIT IN FIRST WORD
CAMLE T3,P2 ;GREATER THAN AVAILABLE BYTES?
MOVE T3,P2 ;YES, SET TO LOWER LIMIT
SUB P2,T3 ;DECRMENT NUMBER OF BYTES USED
PUTSX4: ILDB T2,F ;GET A BYTE FROM SIXBIT WORD
ADDI T2,^O40 ;MAKE IT ASCII
IDPB T2,T4 ;STORE IT IN DESTINATION WORD
SOJG T3,PUTSX4 ;LOOP FOR MORE CHARACTERS
CALL SCPWR1 ;COPY THE WORD TO USER'S BLOCK
SCERR %NEADE,RTN,<Address error>
JRST PUTSX3 ;AND LOOP ON ANOTHER WORD
U=:SJ ;WE USE U AS AN AC BELOW
PURGE SJ ;WE DON'T USE SJ ANY MORE
SUBTTL DNET. UUO -- Argument block
;FLAGS WORD AT BEGINNING OF EACH ARGUMENT BLOCK
BEGSTR FL
FIELD FLA,6 ;FLAGS FIELD - 6 BITS
BIT FLS ; STEP
BIT FLK ; KNOWN
BIT FLR ; ACTIVE (REACHABLE)
BIT FLE ; EXECUTOR
FILLER 6 ;RESERVED
FIELD FNC,6 ;FUNCTION CODE
XP .DNLNN,1 ;LIST NODE NAMES
XP .DNNDI,2 ;RETURN NODE INFO
XP .DNSLS,3 ;SHOW LINKS STATUS
HWORD ARG ;LENGTH OF ARGUMENT BLOCK
ENDSTR
;WORDS IN FUNCTION .DNNDI -
BEGSTR D1 ;ROUTER INFO, WORD .DNRTR
FIELD RCH,1 ;REACHABILITY
FILLER 9 ;RESERVED
FIELD HOP,8 ;HOPS TO NODE
FILLER 2 ;RESERVED
FIELD CST,16 ;COST TO NODE
ENDSTR
BEGSTR D2 ;LLINKS INFO, WORD .DNLLI
FIELD VLD,1 ;VALIDITY BIT
FILLER 8 ;RESERVED
FIELD LNK,9 ;ACTIVE LINKS
HWORD DLY ;MILLISECONDS DELAY
ENDSTR
BEGSTR DS ;.DNSLS ARGUMENT BLOCK
; WORD FLA ;FLAGS, DESCRIBED ABOVE
;
; HWORD JOB ;JOB WHICH CHANNEL BELONGS TO
; HWORD CHN ;CHANNEL
WORD NOD ;NODE NAME FOR CONNECT.
HWORD DOB ;DESTINATION OBJECT TYPE
HWORD SOB ;SOURCE OBJECT TYPE
HWORD LSW ;LINK STATUS WORD
HWORD STA ;SIXBIT STATE
HWORD IQT ;INPUT QUOTA
HWORD OQT ;OUTPUT QUOTA
WORD SEG ;SEGMENT SIZE
HWORD XMF ;XMIT FLOW CONTROL
HWORD RCF ;RECV FLOW CONTROL
HWORD MRC ;MESSAGES RECEIVED
HWORD MXM ;MESSAGES TRANSMITTED
WORD MPR ;MONITOR PROCESS WORD
ENDSTR
SUBTTL DNET. UUO -- Errors
DEFINE DNERR(TXT,LONG),<
JRST [ MOVX T1,DN'TXT'%
RET]
>
;Error codes.
XP DNADE%,1 ;Address error
XP DNWNA%,2 ;Wrong number of arguments
XP DNIJN%,3 ;Illegal job number
XP DNFNE%,4 ;Illegal function number
XP DNILF%,5 ;Illegal flag set
XP DNNSN%,6 ;No such node name
XP DNNSC%,7 ;No such channel
XP DNNDA%,10 ;Node is in different area
SUBTTL DNET. UUO -- Processor
;DNET - Main entry from UUOCON
;Call
; From UUOCON,
; T1/ Contents of AC
; M/ MUUO as executed
;Return
; RET ;On failure, error code stored in user's AC
; RETSKP ;on success
;
;Note that this code runs in section one, since most of DECnet-36's
;data base is in extended sections. There are a number of places we
;call routines which must run in section zero; Be careful when modifying
;code here.
INTERNAL DNET
XRENT DNET
IFE FTXMON,<CALL SVDCN##> ;SWITCH TO DECNET CONTEXT
CALL DNETCM ;CALL PROCESSOR (KLUDGE FOR SAVEAC)
JRST [MCALL (RG,MCSEC0,STOTAC##) ;STORE ERROR CODE IN USER'S AC
RET]
RETSKP ;SUCCESS
DNETCM: SAVEAC <M,W,P1> ;PRESERVE ALL ACS
HRR M,T1 ;SET UP POINTER TO UUO ARGUMENT BLOCK
MCALL (RG,MSEC1,GETWRD##) ;GET FIRST WORD OF ARGUMENT BLOCK
DNERR ADE,<Address check>
MOVE P1,T1 ;SAVE THIS WORD FOR POSTERITY
LOAD T1,FLARG,+P1 ;GET THE LENGTH OF THE ARGUMENT BLOCK
SOSG W,T1 ;SET UP W WITH NUMBER OF WORDS LEFT IN BLOCK
DNERR WNA,<Wrong number of arguments> ;WE'VE USED UP ONE ALREADY.
LOAD T1,FLFNC,+P1 ;GET THE FUNCTION CODE
CAXL T1,.DNLNN ;RANGE
CAXLE T1,.DNSLS ; CHECK
DNERR FNE,<Illegal function>
JRST @.+1-.DNLNN(T1) ;DISPATCH ON FUNCTION
IFIW DNULNN ;.DNLNN
IFIW DNUNDI ;.DNNDI
IFIW DNUSLS ;.DNSLS
SUBTTL DNET. uuo -- .DNLNN - List node names
;DNULNN - Return list of node names
;Call
; M/ Pointer to uuo argument block
; W/ Count of words left in block
; P1/Flags word of argument block
;Return
; RET ;On failure, T1 contains error code
; RETSKP ;On success
;
DNULNN: SAVEAC <P2,P3,P4> ;SAVE ACS
LOAD T1,FLFLA,+P1 ;GET FLAGS FOR FUNCTION
TXNE T1, <FL%FLK!FL%FLR!FL%FLE> ;MAKE SURE ONE OF THESE IS LIT
TXNE T1,^-<FL%FLK!FL%FLR!FL%FLE> ;AND MAKE SURE NOTHING ELSE IS
DNERR ILF,<Illegal flag set>
TXNE T1,FL%FLE ;LIMITED TO EXECUTOR?
MOVX P2,<1B1> ;YES, SET FLAG FOR LOCAL [RNLCL]
TXNE T1,FL%FLR ;LIMITED TO ACTIVE (REACHABLE)?
MOVX P2,<1B0> ;YES, SET FLAG FOR REACHABLE [RNRCH]
TXNE T1,FL%FLK ;LIMITED TO KNOWN?
MOVX P2,-1 ;YES, MAKE SURE NON-ZERO WORD.
SETZ T1, ;CLEAN
CALL DNPNWR ;STORE A ZERO IN .DNCNT TEMPORARILY
DNERR WNA,<Wrong number of arguments>
MOVE P4,M ;SAVE POINTER TO .DNCNT WORD
SETZ P3, ;START AT NODE 0. (HOME AREA)
DNULN3: AOS T2,P3 ;BUMP NODE NUMBER
ADD T2,RTRNRV## ;POINT TO WORD IN ROUTER VECTOR
TDNN P2,(T2) ;TEST ROUTER FLAGS FOR APPLICABILITY
JRST DNULN9 ;NOT APPLICABLE TO US, STEP TO NEXT
MOVE T1,P3 ;GET NODE NUMBER
CALL SCTA2N ;CONVERT NODE NUMBER INTO NODE NAME
SKIPA ;NO NAME, TEST IF REACHABLE
JRST DNULN8 ;HAVE NAME, GO STORE IN ARG BLOCK
MOVE T2,P3 ;GET NODE NUMBER AGAIN
ADD T2,RTRNRV## ;POINT TO WORD IN ROUTER VECTOR
SKIPL (T2) ;IF [RNRCH] IS SET, NODE IS "ACTIVE"
JRST DNULN9 ;NO - IGNORE THIS NODE
MOVE T1,P3 ;COPY NODE NUMBER IN PLACE OF NAME
MOVE T2,RTRHOM ;INCLUDE HOME AREA
DPB T2,[POINTR (T1,RN%ARE)] ;...
DNULN8: CALL DNPNWR ;PUT THIS NAME ON LIST RETURNED
TRN ;IGNORE FAILURE - WE STILL WANT TO COUNT
DNULN9: CAMG P3,RTRMXN## ;WILL WE REACH MAXIMUM NODE NUMBER?
JRST DNULN3 ;NO, LOOP AND GET NEXT
SUB M,P4 ;NUMBER OF NODE NAMES WE PUT AWAY.
UMOVEM M,0(P4) ;STORE NUMBER OF NODES IN ARG BLOCK.
RETSKP ;AND RETURN HAPPILY.
SUBTTL DNET. uuo -- .DNNDI - Return node info
;DNUNDI - Return detailed info about a node
;Call
; M/ Pointer to uuo argument block
; W/ Count of words left in block
; P1/Flags word of argument block
;Return
; RET ;On failure, T1 contains error code
; RETSKP ;On success
;
DNUNDI: SAVEAC <F,U,P2,P3> ;SAVE ACS
LOAD T1,FLFLA,+P1 ;GET FLAGS
TXNE T1,FL%FLS ;IS STEP SET?
TXNE T1,<FL%FLK!FL%FLR!FL%FLE> ;YES, MAKE SURE AT LEAST ONE QUALIFIER
TXNE T1,^-<FL%FLS!FL%FLK!FL%FLR!FL%FLE> ;MAKE SURE NO EXTRANEOUS BITS
DNERR ILF,<Illegal flag set>
CALL DNGNWR ;GET THE NODE NAME
DNERR WNA,<Wrong number of arguments>
TXNE P1,FLFLS ;STEP SET?
JUMPE T1,DNUND2 ;IF SO AND NODE NAME 0, SKIP CONVERSION
TLNN T1,-1 ;ANYTHING IN LEFT HALF?
JRST DNUND1 ;IF NOT, MUST BE AN ADDRESS
CALL SCTN2A## ;CONVERT NAME TO ADDRESS
DNERR NSN,<No such node name>
DNUND1: LDB T2,[POINTR(T1,RN%ARE)] ;GET AREA NUMBER
SKIPE T2 ;DEFAULT TO OUR AREA?
CAMN T2,RTRHOM## ;OR SPECIFYING OUR HOME AREA?
SKIPA ;YES, ALL OK
DNERR NDA,<Node is in different area>
ANDX T1,RN%NOD ;MASK TO JUST NODE WITHIN AREA
CAMLE T1,RTRMXN ;CHECK FOR OUT OF RANGE
DNERR NSN,<No such node name>
DNUND2: MOVE P2,T1 ;SAVE NODE NUMBER SOMEWHERE SAFE
TXNN P1,FLFLS ;STEP SET?
JRST DNUND4 ;NO, SKIP STEP CODE
TXNE P1,FLFLE ;LIMITED TO EXECUTOR?
MOVX T3,<1B1> ;YES, SET FLAG FOR LOCAL [RNLCL]
TXNE P1,FLFLR ;LIMITED TO ACTIVE (REACHABLE)?
MOVX T3,<1B0> ;YES, SET FLAG FOR REACHABLE [RNRCH]
TXNE P1,FLFLK ;LIMITED TO KNOWN?
MOVX T3,-1 ;YES, MAKE SURE NON-ZERO WORD.
DNUND3: AOS T2,P2 ;BUMP NODE NUMBER
CAMLE T2,RTRMXN## ;BEYOND MAXIMUM NODE NUMBER?
JRST [ SETZ T1, ;NODE NAME OF ZERO
MCALL (RG,MSEC1,PUTWRD##) ;STORE WORD
DNERR ADE,<Address error>
RETSKP] ;AND RETURN
ADD T2,RTRNRV## ;POINT TO ENTRY IN ROUTER VECTOR
TDNN T3,(T2) ;TEST FOR OUT CONDITION
JRST DNUND3 ;NOT GOOD, TRY FOR ANOTHER
DNUND4: MOVE T1,RTRHOM ;SET UP CORRECT AREA NUMBER
DPB T1,[POINTR (P2,RN%ARE)] ;...
MOVE T1,P2 ;GET NODE NUMBER
CALL SCTA2N ;CONVERT NODE NUMBER INTO NODE NAME
MOVE T1,P2 ;USE NODE NUMBER IF NO NODE NAME
MCALL (RG,MSEC1,PUTWRD##) ;STORE NODE NAME BACK IN ARG BLOCK
DNERR ADE,<Address error>
MOVE T2,P2 ;COPY NODE ADDRESS
ANDX T2,RN%NOD ;MASK TO JUST NODE NUMBER WITHIN AREA
;.DNRTR
SETZ T1, ;CLEAR DESTINATION WORD
ADD T2,RTRNRV## ;POINT TO ROUTER WORD
LDB T3,RTNRCH## ;GET REACHABILITY OF THIS NODE
STOR T3,D1RCH,+T1 ;SET THE REACHABILITY BIT
LDB T3,RTNHOP## ;GET NUMBER OF HOPS
STOR T3,D1HOP,+T1 ;STORE HOPS
LDB T3,RTNCST## ;GET COST TO NODE
STOR T3,D1CST,+T1 ;STORE COST
CALL DNPNWR ;STORE THIS IN USER'S ARGUMENT BLOCK
RETSKP ;MUST BE DONE, EXIT SUCCESSFULLY
;.DNLLI
SETZ U, ;CLEAR DESTINATION WORD
MOVE T1,P2 ;SET UP NODE NUMBER FOR SRHNOD
CALL SRHNOD## ;SEARCH FOR THE LLINKS NODE DATABASE
JRST DNUND5 ;NO LLINKS DATABASE FOR NODE, SKIP THIS
LOAD T3,NNDLY,(T1) ;GET THE DELAY
STOR T3,D2DLY,+U ;SAVE IN DESTINATION WORD
LOAD T3,NNLKC,(T1) ;GET THE NUMBER OF LINKS TO NODE
STOR T3,D2LNK,+U ;SAVE...
TQO D2VLD,+U ;INDICATE VALID INFORMATION
DNUND5: MOVE T1,U ;GET WORD TO STORE
CALL DNPNWR ;PUT THIS WORD IN USERS ARG BLOCK
RETSKP ;END OF ARG BLOCK, RETURN
;.DNADR
MOVE T1,P2 ;COPY NODE ADDRESS
CALL DNPNWR ;STORE ADDRESS
RETSKP ;IF WON'T FIT, FINISHED.
;.DNCKT
MOVE T2,P2 ;GET NODE NUMBER
ANDX T2,RN%NOD ;MASK TO JUST NODE NUMBER WITHIN AREA
ADD T2,RTRNRV## ;POINT TO WORD IN NORMAL ROUTING VECTOR
LDB T3,RTNRCH## ;GET THE REACHABILITY BIT
LDB T1,RTNLCL## ;GET THE LOCAL BIT
ANDCM T3,T1 ;TRUTH TABLE
JUMPE T3,[
SKIPE T1 ;WAS IT LOCAL?
MOVE T1,[ASCII \local\] ;YES
CALL DNPNWR ;STORE INFO IN ARG BLOCK
RETSKP ;END OF ARG BLOCK, FINIT.
JRST DNUND8] ;AND CLEAN UP.
MOVE T1,P2 ;GET NODE NUMBER
CALL RTNLID## ;GET LINE ID OF ROUTE TO NODE
JRST DNUND8 ;NO LINE ID? OH WELL
STKVAR <<TXTBUF,5>> ;TEMPORARY AREA FOR CIRCUIT NAME
MOVEI T2,TXTBUF ;MAKE A LOCAL POINTER TO TXTBUF
HRLI T2,(POINT 8,) ;BYTE POINTER TO BUFFER
IFN <<T4-W+1>!<T4-M+2>>,<PRINTX ?W OR M HAS MOVED. FIX THIS CODE>
CALL [SAVEAC <M,W> ;TRASHED BY NTMAN
CALLRET NMXC2N##] ;CONVERT LINE ID TO NAME
RET ;SOMETHING WRONG. NMXC2N BUGCHKED
MOVE P1,[POINT 8,TXTBUF];(OK TO TRASH P1 NOW - DON'T NEED FLAGS)
ILDB F,P1 ;GET NUMBER OF BYTES
SETZ U, ;CLEAR TEMPORARY FOR DNPNAB
DNUND7: ILDB T1,P1 ;GET A BYTE OF TEXT
CALL DNPNAB ;PUT IT INTO USER STREAM
RETSKP ;END OF ARG BLOCK, EXIT
SOJG F,DNUND7 ;AND LOOP
CALL DNPNAC ;TERMINATE STRING
RETSKP ;END OF ARG BLOCK, RETURN
ENDSV. ;END STKVAR
DNUND8: SETZ T1, ;ZERO
CALL DNPNWR ;STORE IN USER AREA
RETSKP ;RETURN
RETSKP ;ALSO RETURN
SUBTTL DNET. uuo -- .DNSLS - Show link status
;DNUSLS - Show status about a link
;Call
; M/ Pointer to uuo argument block
; W/ Count of words left in block
; P1/Flags word of argument block
;Return
; RET ;On failure, T1 contains error code
; RETSKP ;On success
;
DNUSLS: SAVEAC <U,F,P2> ;STORAGE
LOAD T1,FLFLA,+P1 ;GET FLAGS FIELD
TXNE T1,^-FL%FLS ;MAKE SURE NO EXTRANEOUS BITS SET
DNERR ILF,<Illegal flag set>
CALL DNGNWR ;GET THE JOB/CHANNEL WORD
DNERR WNA,<Wrong number of arguments>
MOVE P2,T1 ;SAVE WORD IN SAFE PLACE
STKVAR <<DSARG,DS.LEN>> ;GET US SOME STORAGE
CALL GETCHN ;GET THE CHANNEL NUMBER
DNERR NSC,<No such channel> ;Give error return
JUMPE P2,DNUSL7 ;IF CHANNEL&JOB 0, WE HAVE FINISHED
LOAD T1,SLPKS,(T2) ;#GET NUMBER OF MESSAGES SENT
LOAD T3,SLPKR,(T2) ;#NUMBER OF MESSAGES RECEIVED
HRL T3,T1 ;#MAKE AN XWD OF TWO FIELDS
DNUSL4: MOVEM T3,DS.MRC+DSARG ;#SAVE IN ARG BLOCK
D36ON ;#ALLOW INTERUPTS AGAIN.
;NOTE - The SLB is now unsafe. It can be trashed while we are looking at it.
; This is unimportant in the normal case, but if there are any pointers
; to be traced, they MUST be traced under D36OFF, above.
LOAD T1,SLDNA,(T2) ;GET THE NODE NUMBER
STOR T1,DSNOD,+DSARG ;STORE FOR LATER USE
IFN <SLDOB+SLSOB+1>!<SL.DOB-SL.SOB>,<XWD 0,,0 ;SLDOB AND SLSOB MOVED>
MOVE T1,SL.SOB(T2) ;GET OBJECT TYPES
MOVEM T1,DS.SOB+DSARG ;STORE IN OUR ARG BLOCK
LOAD T1,SLINQ,(T2) ;GET INPUT QUOTA
STOR T1,DSIQT,+DSARG ;STORE IN ARG BLOCK
LOAD T1,SLOTQ,(T2) ;GET OUTPUT QUOTA
STOR T1,DSOQT,+DSARG ;STORE
LOAD T1,SLSIZ,(T2) ;GET SEGMENT SIZE
STOR T1,DSSEG,+DSARG ;STORE IN ARGUMENT BLOCK
LOAD T1,SLSST,(T2) ;GET SLB FLAGS (BINARY STATE)
LOAD T3,SLSTA,(T2) ;GET STATE ORDINAL
HLL T1,STASIX-1(T3) ;GET SIXBIT STATE INTO LEFT HALF
MOVSM T1,DS.STA+DSARG ;STORE IN OUR ARG BLOCK
CAXN T2,.NSSCW ;CONNECT WAIT?
JRST [ SETZM DS.XMF+DSARG ;YES, DON'T RETURN FLOW CONTROL
JRST DNUSL3] ;AND CONTINUE AFTER
LOAD T1,SLXFL,(T2) ;GET TRANSMIT FLOW CONTROL
ADDI T1,1 ;OFFSET
STOR T1,DSXMF,+DSARG ;STORE
LOAD T1,SLRFL,(T2) ;GET RECEIVE FLOW CONTROL
ADDI T1,1 ;OFFSET
STOR T1,DSRCF,+DSARG ;
DNUSL3: SETZ U, ;DON'T NEED THIS ANY MORE.
SKIPL P2 ;IS THIS A MONITOR JOB (I.E., NRTSER)
JRST DNUSL5 ;
HRRZ U,P2 ;COPY CHANNEL NUMBER
XCALL (MSEC1,NRTLFC##) ;ASK NRTSER FOR THE TTY NUMBER
DNUSL5: STOR U,DSMPR,+DSARG ;NRTLFC RETURNS WORD IN U
SKIPE T1,DS.NOD+DSARG ;GET NODE NUMBER
CALL SCTA2N## ;CONVERT TO NODE NAME
TRNA ;IF THIS HAPPENS, LEAVE NODE NUMBER THERE
MOVEM T1,DS.NOD+DSARG ;STORE NODE NAME BACK IN ARG BLOCK
MOVE T1,P2 ;GET CURRENT JOB/CHANNEL
MCALL (RG,MSEC1,PUTWRD##) ;STORE IT IN USER SPACE
DNERR ADE,<Address error>
MOVE T1,DS.NOD+DSARG ;GET NODE NAME
CALL DNPNWR ;STORE IT IN USER BLOCK
RETSKP
MOVE T1,DS.SOB+DSARG ;GET OBJECT TYPES
CALL DNPNWR ;STORE IN USER BLOCK
RETSKP
MOVE T1,DS.LSW+DSARG ;GET STATUS
CALL DNPNWR ;STORE IN USER BLOCK
RETSKP
MOVE T1,DS.IQT+DSARG ;QUOTAS
CALL DNPNWR ;STORE
RETSKP
MOVE T1,DS.SEG+DSARG ;SEGMENT SIZE
CALL DNPNWR ;STORE
RETSKP
MOVE T1,DS.XMF+DSARG ;FLOW CONTROLS
CALL DNPNWR ;STORE
RETSKP
MOVE T1,DS.MRC+DSARG ;MESSAGES
CALL DNPNWR ;STORE
RETSKP
MOVE T1,DS.MPR+DSARG ;MONITOR PROCESS WORD
CALL DNPNWR ;STORE
RETSKP
RETSKP
DNUSL7: SETZ T1, ;CLEAR
MCALL (RG,MSEC1,PUTWRD##) ;INDICATE END OF LIST
DNERR ADE,<Address error>
RETSKP ;AND SAY WE DIDN'T FAIL
;GETCHN - Get channel number to talk about.
;
;Call
; P1/ Flags word
; P2/ Job,,channel
;Return
; Ret, no can do.
; RETSKP, success,
; if wrapped, P2/ 0
; else, D36OFF and
; P2/ Job,,channel as determined
; U/ SJB
; T2/ SLB
GETCHN:
SAVEAC <J,W> ;WE USE THESE
TXNE P1,FLFLS ;DO WE STEP?
ADDI P2,1 ;YES, SKIP PAST CURRENT SLB
HLRZ J,P2 ;EXTRACT JOB NUMBER
;GET SJB POINTER
GETCH1: CAIN J,-1 ;WAS THIS NRTSER?
JRST [ SKIPE U,NRTSJP## ;YES, GET POINTER TO NRT'S SJB
JRST GETCH5 ;AND JOIN COMMON CODE LATER
JRST GETCH2] ;NO SJB, INCREMENT JOB
SKIPE J ;ZERO JOB?
CAILE J,JOBMAX## ;WITHIN LIMITS?
JRST GETCH2 ;NO, GO TO INCREMENT LOGIC DIRECTLY
MCALL (RG,MSEC1,FNDPDB##) ;GET POINTER TO THE PDB
JRST GETCH2 ;NO PDB, INCREMENT JOB
SKIPE U,.PDSJB(W) ;GET POINTER TO SJB
JRST GETCH5 ;HAVE POINTER TO SJB, JOIN COMMON CODE
GETCH2: TXNN P1,FLFLS ;DO WE HAVE STEP SET?
RET ;NO, WE FAIL
SETZ P2, ;CLEAR CHANNEL NUMBER
MOVEI J,1(J) ;BUMP THE JOB NUMBER (18 BIT INCREMENT)
CAILE J,JOBMAX## ;JOB NUMBER IN RANGE
JRST [ MOVEI J,-1 ;NO, SET UP FOR NRTSER
JRST GETCH1] ;AND GO THROUGH THE LOOP AGAIN
JUMPN J,GETCH1 ;IF JOB NUMBER POSITIVE, LOOP
RETSKP ;WRAPPED ALL THE WAY AROUND, SUCCESS WITH 0
;GET SLB POINTER
GETCH5:
HRL P2,J ;COPY JOB BACK INTO LOOP POINTER
D36OFF ;#TO TOUCH SLB'S, MUST HAVE INTERLOCK
LOAD T3,SJCHC,(U) ;#GET NUMBER OF CHANNEL SLOTS IN SJB
LOAD T4,SJCHT,(U) ;#GET POINTER TO CHANNEL T4
TRNN P2,-1 ;#DO WE HAVE A CHANNEL NUMBER YET?
JRST GETCH7 ;#NO, INCREMENT NOW
GETCH6: CAIGE T3,(P2) ;#IS CHANNEL OUT OF RANGE?
JRST [ D36ON ;#YES, INCREMENT JOB
JRST GETCH2] ;AND TRY NEXT JOB
MOVE T1,T4 ;#COPY POINTER TO TABLE
ADDI T1,-1(P2) ;#ADD OFFSET TO CHANNEL POINTER
SKIPE T2,(T1) ;#GET POINTER TO SLB
JRST GETCH8 ;#GOT IT, EXIT GRACEFULLY
GETCH7: TXNN P1,FLFLS ;#NO POINTER
JRST GETCH9 ;#CAN'T STEP, SO RETURN ERROR
HRRI P2,1(P2) ;#18 BIT INCREMENT
JRST GETCH6 ;#AND TRY AGAIN
GETCH8: LOAD T3,SLCHN,(T2) ;#GET CHANNEL NUMBER FROM SLB
CAIE T3,(P2) ;#COMPARE TO CHANNEL WE THINK WE ARE USING
BUG.(CHK,SCMBCN,SCMUUO,SOFT,<Bad channel number>,,<
Cause: The channel number obtained from the SLB field SLCHN doesn't
match the channel number we thought we were getting. This probably
means that the interlocks aren't correctly arranged, and the SLB
has changed out from under us.
>,GETCH9)
RETSKP ;#HAVE POINTERS, RETURN D36OFF
GETCH9: D36ON ;#RELEASE INTERLOCK
RET ;AND RETURN
SUBTTL DNET. uuo -- Conversion from binary to sixbit state
STASIX: SIXBIT |CW| ;CONNECT WAIT
SIXBIT |CR| ;CONNECT RECEIVED
SIXBIT |CS| ;CONNECT SENT
SIXBIT |RJ| ;REMOTE REJECTED CONNECT INIT
SIXBIT |RN| ;LINK IS UP AND RUNNING
SIXBIT |DR| ;DISCONNECT RECEIVED
SIXBIT |DS| ;DISCONNECT SENT
SIXBIT |DC| ;DISCONNECT CONFIRMED
SIXBIT |CF| ;NO CONFIDENCE
SIXBIT |LK| ;NO LINK
SIXBIT |CM| ;NO COMMUNICATION
SIXBIT |NR| ;NO RESOURCES
SUBTTL DNET. uuo -- Utility routines
;DNPNAB - Put next ascii byte
;Call
; W/ Number of words left in arg block
; M/ Pointer to word before word to deposit
; U/ Cummulative word
;Return
; RET on end of arg block
; RETSKP succes
; DNERR from calling routine on address error
DNPNAB: ROT U,7 ;MAKE ROOM FOR ANOTHER BYTE
IOR U,T1 ;OR IT IN
TLNN U,(377B7) ;HAVE WE FILLED WORD?
RETSKP ;NO, RETURN SUCCESS
ROT U,1 ;YES, LEFT JUSTIFY
MOVE T1,U ;PUT WORD INTO USEFULL PLACE
SETZ U, ;AND CLEAR FOR NEXT SET OF WORDS
CALLRET DNPNWR ;AND PUT THE WORD IN USER'S BUFFER.
;Terminate string (finish putting it into user space)
DNPNAC:
SKIPN T1,U ;PUT WORD WHERE WE CAN PLAY WITH IT
CALLRET DNPNWR ;NOTHING THERE, JUST DEPOSIT A ZERO WORD
LSH T1,1 ;LEFT JUSTIFY
DNPNAD: LSH T1,7 ;MOVE NEXT BYTE INTO TOP
TLNN T1,(377B6) ;ANYTHING THERE?
JRST DNPNAD ;NOPE, KEEP TRYING
; ... ;FALL THROUGH.
;DNPNWR - Put next word
;Call
; W/ Number of words left in arg block
; M/ Pointer to word before word to store in
; T1/Word to store
;Return
; M incremented always (DNULNN depends on this)
; RET ;On end of arg block
; RETSKP ;success
; DNERR from calling routine on address error
DNPNWR: HRRI M,1(M) ;18 BIT INCREMENT
SOJL W,RTN ;RETURN IF RAN OUT OF ARG BLOCK
MCALL (RG,MSEC1,PUTWRD##) ;STORE THE WORD
TRNA ;ARGH. ERROR CONDITION, HANDLE IT.
RETSKP ;SUCCESS
ADJSP P,-1 ;BLOW AWAY CALL TO THIS ROUTINE.
DNERR ADE,<Address error>;GIVE ADDRESS CHECK FROM CALLING ROUTINE
;DNGNWR - Get next word
;Call
; W/ Number of words left in arg block
; M/ Pointer to word before word to fetch
;Return
; RET ;on end of arg block
; RETSKP ;success
; DNERR from calling routine on address error
DNGNWR: HRRI M,1(M) ;18 BIT INCREMENT
SOJL W,RTN ;RETURN IF RAN OUT OF ARG BLOCK
MCALL (RG,MSEC1,GETWRD##) ;GET THE WORD
TRNA ;ERROR CONDITION, HANDLE IT.
RETSKP ;SUCCESS
ADJSP P,-1 ;BLOW AWAY CALL TO THIS ROUTINE
DNERR ADE,<Address error>
SUBTTL Impure Storage
RESCD ;IMPURE STUFF
SCUDFT::
REPEAT 0,<EXP <FLD(%NSGOL,PDGOL) ! FLD(%NSDQT,PDDQT) ! FLD(%NSIPR,PDIPR)>>
REPEAT 1,<EXP <FLD(^D9,PDGOL) ! FLD(^D16,PDDQT) ! FLD(^D50,PDIPR)>>
XRESCD ;SO LITERALS ARE PURE
SUBTTL End of SCMUUO
.XCMSY
RESDT
SCULOW::!
XRESCD
END