Trailing-Edge
-
PDP-10 Archives
-
BB-JR93L-BB_1990
-
10,7/galaxy/quasar/qsradm.mac
There are 45 other files named qsradm.mac in the archive. Click here to see a list.
TITLE QSRADM -- System Administrative and Operator Functions
;
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1975,1976,1977,1978,
;1979,1980,1981,1982,1983,1984,1985,1986,1987. ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH QSRMAC,GLXMAC ;PARAMETER FILE
PROLOGUE(QSRADM) ;GENERATE NECESSARY SYMBOLS
SEARCH ORNMAC ;NEED ORION INTERFACE
QSRVRS==:QSRVRS ;REFERENCE QUASAR'S VERSION
%%.QSR==:%%.QSR ;AND QSRMAC'S
SUBTTL Module Storage and Constants
;Dummy STARTUP message for VARIOUS PROCESSORS
COMSTA:: $BUILD .ARGLN+OBJ.SZ
$SET(.MSTYP,MS.CNT,.ARGLN+OBJ.SZ)
$SET(.MSTYP,MS.TYP,.OMSTA)
$SET(.MSCOD,,-1)
$SET(.OARGC,,1)
$SET(.OHDRS+ARG.HD,AR.LEN,OBJ.SZ+1)
$SET(.OHDRS+ARG.HD,AR.TYP,.OROBJ)
$SET(.OHDRS+ARG.DA+OBJ.TY,,0)
$SET(.OHDRS+ARG.DA+OBJ.ND,,0)
$EOB
SUBTTL OBJECT TABLE AND MISC STORAGE
;Table of OBJECT types
DEFINE X(OBJ,QUE,PARM),<
EXP .OT'OBJ
> ;END DEFINE X
OBJTAB: MAPOBJ ;GENERATE THE TABLE
NOBJS==.-OBJTAB ;NUMBER OF OBJECTS
BLKADR: BLOCK 1 ;IPCF MSG BLOCK ADDRESS.
ILLMSG: $ACK (<ORION error>,<Illegally formatted message>,,.MSCOD(M))
$RETF
BADMSG: $ACK (Orion Message Error,Invalid Object Block Specified,,.MSCOD(M))
$RETF
DEVUNK: $ACK (Device Unknown,,0(P1),.MSCOD(M))
$RETT
DASMSG: $ACK (<Cannot set unit type>,<Device started>,OBJTYP(P1),.MSCOD(M))
$RETF
NOOMSG: $ACK (<Not an output object>,,OBJTYP(P1),,.MSCOD(M))
$RETF
TMPMSG: BLOCK MOD.SZ+3 ;SPACE FOR TEMP OPR MSG
DEFINE X(A,B,C),<
XXXX==0
IRP C,<
IFE <C>,<STOPI>
IFN <C>,<XXXX==XXXX+1>
>
IFE <XXXX>,<EXP 0>
IFG <XXXX>,<XWD XXXX,[EXP C]>
>
;DEFINE THE OBJECT STATUS CODE LIMITS AND DEVICE TYPES
; 0 = DEVICE STATUS GOOD FOR ALL DEVICES
; COUNT,,ADDRESS = # OF DEVICE TYPES LOCATED AT ADDRESS
; THESE ARE THE ONLY DEVICES FOR WHICH THE STATUS CODE IS VALID
OBJCDS: STATUS ;LETERRIP
; Display table to give meaningful node definition messages
DEFTAB: ASCIZ/Red/
ASCIZ/D/
SUBTTL Initialization Entry
;CALLED DURING QUASAR INITIALIZATION TO INITIALIZE THE ADMINISTRATIVE
; DATABASE.
A$INIT::PUSHJ P,I%NOW ;GET NOW!!
MOVEM S1,G$ITEM+$$STAR ;SAVE IT
MOVE S1,G$LNAM## ;GET THE HOST NODE ID.
MOVEM S1,COMSTA+.OHDRS+ARG.DA+OBJ.ND ;SAVE IT IN THE MESSAGE
MOVX S1,.OTEVT ;GET THE EVENT OBJECT TYPE
STORE S1,COMSTA+.OHDRS+ARG.DA+OBJ.TY ;SAVE IT
MOVEI M,COMSTA ;GET START MESSAGE ADDRESS
PUSHJ P,A$OSTA ;STARTUP THE EVENT PROCESSOR
MOVEI S1,.OTBIN ;GET THE CORRECT OBJECT TYPE
STORE S1,COMSTA+.OHDRS+ARG.DA+OBJ.TY ;SAVE IT IN THE MESSAGE
MOVEI M,COMSTA ;STARTUP MESSAGE FOR BIN QUEUE
PUSHJ P,A$OSTA ;SETUP THE OBJECT BLOCK
MOVX S1,.OTDBM ;GET THE DBMS OBJECT TYPE
STORE S1,COMSTA+.OHDRS+ARG.DA+OBJ.TY ;SAVE FOR DBMS STARTUP
MOVEI M,COMSTA ;GET START MESSAGE ADDRESS
PUSHJ P,A$OSTA ;STARTUP THE DBMS PROCESSOR
$RETT ;AND RETURN
SUBTTL Administrative Message Handlers
;THE MESSAGE HANDLERS ARE TOP LEVEL ROUTINES WHICH PROCESS THE
; VARIOUS MESSAGES THAT ARE SENT TO QUASAR. THEY ARE
; CALLED DIRECTLY OUT OF THE MAIN PROCESSING LOOP WITH
; ACCUMULATOR "M" POINTING TO THE FIRST WORD OF THE MESSAGE.
; THE MESSAGE HANDLERS HAVE FULL USE OF ALL ACCUMULATORS
; EXCEPTING "M" AND THE "P" REGS.
INTERN A$HELLO ;FUNCTION 1 -- HELLO
INTERN A$COUNT ;FUNCTION 20 -- COUNT
SUBTTL HELLO -- Function 1
;THE HELLO MESSAGE IS SENT TO QUASAR BY ONE OF THE KNOWN SYSTEM
; COMPONENTS UNDER TWO CIRCUMSTANCES, THE FIRST BEING PROGRAM
; STARTUP, THE SECOND, PROGRAM SHUTDOWN.
A$HELL::DOSCHD ;FORCE A SCHEDULING PASS
PUSHJ P,.SAVE1 ;SAVE P1
LOAD S1,.MSTYP(M),MS.CNT ;GET THE MESSAGE SIZE
CAIGE S1,HEL.OB ;AT LEAST BIG ENOUGH?
PJRST E$MTS## ;NO, INDICATE MESSAGE TOO SHORT
PUSHJ P,A$WHEEL ;SEE IF CALLER IS AN OPERATOR
JUMPF E$IPE## ;ISN'T, CANNOT BECOME A KNOWN COMPONENT
LOAD S1,HEL.FL(M),HEFVER ;GET PROGRAMS VERSION OF QSRMAC
CAXE S1,%%.QSR ;BETTER BE THE SAME AS MINE
PJRST E$WVN## ;ISN'T, GIVE WRONG VERSION ERROR
LOAD S1,HEL.FL(M),HEFBYE ;SAYING GOODBYE?
JUMPN S1,HELL.1 ;YUP, BYE!!
LOAD S1,HEL.NO(M),HENNOT ;GET THE NUMBER OF OBJECT TYPES
JUMPE S1,E$MTS## ;AND GIVE AN ERROR IF ZERO
TOPS20< MOVE S2,HEL.OB(M) ;GET THE FIRST OBJECT TYPE
CAIN S2,.OTMNT ;IS IT FOR TAPE/DISK MOUNTS ???
PUSHJ P,I$MINI## > ;YES,,GO CLEAN UP THE MOUNT QUEUE
MOVE S1,G$SND## ;GET PID OF CURRENT SENDER
LOAD S2,HEL.NM(M) ;GET PROGRAM NAME OF SENDER
PUSHJ P,GETPSB ;FIND HIS PSB
MOVE P1,S1 ;STORE ADDRESS OF PSB IN P1
SKIPE PSBPID(P1) ;IS IT A NEW ONE?
JRST HELL.2 ;NO, MUST BE RESTARTING
SKIPE PSBNAM(P1) ;MAYBE, NAME THERE?
JRST HELL.C ;YES, WE WERE PROBABLY WAITING
LOAD S1,HEL.NM(M) ;GET PROGRAM NAME
STORE S1,PSBNAM(P1) ;STORE IN THE PSB
HELL.C: MOVE S1,G$SND## ;GET SENDER'S PID
MOVEM S1,PSBPID(P1) ;AND STORE IT IN THE PSB
LOAD S1,HEL.NO(M),HENMAX ;GET MAXIMUM NUMBER OF JOBS
STORE S1,PSBLIM(P1),PSLMAX ;AND STORE IT
LOAD S1,HEL.NO(M),HENNOT ;LOAD NUMBER OF OBJECT TYPES
STORE S1,PSBFLG(P1),PSFNOT ;AND STORE IT
MOVE S2,M ;GET THE MSG ADDRESS IN S2
HELL.0: LOAD TF,HEL.OB(S2),HELATR ;GET THE OBJECT ATTRIBUTES
JUMPN TF,.+3 ;IF SET,,SKIP THIS
MOVX TF,%GENRC ;NO,,GET 'GENERIC' ATTRIBUTES
STORE TF,HEL.OB(S2),HELATR ;AND SET THEM FOR THIS OBJECT
AOS S2 ;BUMP TO NEXT OBJECT
SOJG S1,HELL.0 ;CONTINUE FOR ALL OBJECTS
LOAD S1,HEL.NO(M),HENNOT ;LOAD NUMBER OF OBJECT TYPES
MOVSI S2,HEL.OB(M) ;GET SOURCE FOR A BLT
HRRI S2,PSBOBJ(P1) ;AND THE DESTINATION
ADDI S1,PSBOBJ-1(P1) ;GET THE END ADDRESS
BLT S2,0(S1) ;AND BLT THE OBJECT TYPES
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
$LOG(<Process ^W/PSBNAM(P1)/ signon to QUASAR>,<Process PID is ^O/PSBPID(P1)/, Process Object Type is ^O/PSBOBJ(P1),HELOBJ/(^1/PSBOBJ(P1),HELOBJ/)>,,<$WTFLG(WT.SJI)>)
MOVX S1,PS.RUN ;GET RUNNING STATUS
LOAD S2,PSBFLG(P1),PSFSTS ;GET STATUS
STORE S1,PSBFLG(P1),PSFSTS ;SET RUNNING STATUS IN PSB
MOVE S1,P1 ;GET PSB ADDRESS IN S1
CAXN S2,PS.KSY ;BATCON KSYS MSG NEEDED?
PUSHJ P,I$SKSM## ;YES, GO SEND IT
MOVE S1,PSBOBJ(P1) ;GET THE OBJECT TYPE
CAMN S1,[%GENRC,,.OTBAT] ;IS THIS THE BATCH PROCESSOR??
PUSHJ P,D$PMDR## ;GO PROCESS ALLOCATIONS
MOVE S1,P1 ;GET PSB ADDRESS
PUSHJ P,HELL.3 ;SEND ODB MESSAGE IF NEEDED
;Each time we get a HELLO message, poll the processors and see
; if any have died
$SAVE <G$ACK##,G$MCOD##,G$ERR##,G$SND##> ;SAVE LOTS OF VARIABLES
SETZM G$ACK## ;ZAP THE ACK FLAG
SETZM G$ERR## ;ZAP THE ERROR CODE
SETZM G$MCOD## ;ZAP THE ACK CODE
PUSH P,P1 ;SAVE PSB
LOAD P1,HDRPSB##+.QHLNK,QH.PTF ;GET THE FIRST PROCESSOR BLOCK
HELL.A: JUMPE P1,HELL.B ;NONE,,THATS WIERD !!!
MOVE S1,PSBPID(P1) ;GET ITS PID
MOVEM S1,G$SND## ;MAKE BELIEVE HE SENT US A MSG
LOAD P1,.QELNK(P1),QE.PTN ;GET NEXT PSB,,THIS ONE MAY GO AWAY
PUSHJ P,G$MSND## ;SEND A NULL ACK
JRST HELL.A ;AND GO SEND ANOTHER
HELL.B: POP P,P1 ;GET PSB BACK
MOVE S1,P1 ;COPY
PUSHJ P,HELSTA ;START OBJECTS IF NECESSARY
$RETT ;AND RETURN
;HERE WHEN WE RECEIVE A GOOD-BYE MESSAGE
HELL.1: MOVE S1,G$SND## ;GET SENDERS PID
SETZM S2 ;DON'T USE PROCESSOR NAME
PUSHJ P,A$FPSB ;FIND THE PSB
JUMPE S1,E$NKC## ;LOSE
PJRST KILPSB ;ELSE, KILL THE PSB
;HERE WHEN WE RECEIVE A HELLO FROM A KNOWN PROGRAM. WE ASSUME THE
; PROGRAM ABENDED AND HAS BEEN RESTARTED, SO WE FORCE A
; GOODBYE FOLLOWED BY A NEW HELLO.
HELL.2: PUSHJ P,KILPSB ;BYE....
JRST A$HELLO ;HI.....
;HERE TO SEND AN ODB MESSAGE(S) TO PROCESSOR IF NEEDED.
;S1/PSB ADDRESS
HELL.3: PUSHJ P,.SAVET ;SAVE T1 - T4
MOVE T1,S1 ;SAVE PSB ADDRESS
LOAD T2,PSBFLG(T1),PSFNOT ;GET NUMBER OF OBJECTS SUPPORTED
JUMPE T2,.RETF ;IF NONE, RETURN FALSE
MOVNS T2 ;MAKE AOBJN POINTER
HRLZS T2
HRRI T2,PSBOBJ(T1)
HELL.4: LOAD S1,(T2),HELOBJ ;GET OBJECT TYPE
LOAD T4,HDRODB##+.QHLNK,QH.PTF ;GET THE FIRST ODB BLOCK
HELL.5: JUMPE T4,HELL.8 ;IF NONE, LOOP
CAMN S1,ODB.OT(T4) ;OBJECT TYPES MATCH?
JRST HELL.7 ;YES, GO SEND ODB MESSAGE
HELL.6: LOAD T4,.QELNK(T4),QE.PTN ;NO, GET POINTER TO NEXT ODB
JRST HELL.5 ;LOOP
HELL.7: MOVE S2,PSBPID(T1) ;GET PROCESSOR PID FROM PSB
PUSH P,S1 ;SAVE OBJECT TYPE
MOVE S1,T4 ;GET ODB ADDRESS
PUSHJ P,SNDODB ;GET SEND ODB MESSAGE
POP P,S1 ;GET OBJECT TYPE BACK
JRST HELL.6 ;LOOP FOR NEXT ODB
HELL.8: AOBJN T2,HELL.4 ;LOOP FOR ALL OBJECTS SUPPORTED
POPJ P,
; Here to restart any objects not owned by a spooler
; Call: MOVE S1, PSB address
; PUSHJ P,HELSTA
HELSTA: $SAVE <M> ;SAVE M
PUSHJ P,.SAVE3 ;SAVE SOME ACS
MOVE P1,S1 ;COPY PSB ADDRESS
LOAD P2,PSBFLG(P1),PSFNOT ;GET THE OBJECT COUNT
MOVNS P2 ;NEGATE
MOVSS P2 ;PUT IN LH
HRRI P2,PSBOBJ(P1) ;MAKE AN AOBJN POINTER
LOAD P3,HDROBJ##+.QHLNK,QH.PTF ;POINT TO THE FIRST OBJ
HELS.1: JUMPE P3,.RETT ;RETURN IF NO MORE OBJECTS
SKIPE OBJPID(P3) ;OBJECT OWNED?
JRST HELS.2 ;YES--TRY ANOTHER
MOVE S1,P2 ;GET POINTER TO OBJECTS
HRRZ S2,(S1) ;GET AN OBJECT TYPE
CAME S2,OBJTYP(P3) ;SAME?
AOBJN S1,.-1 ;CHECK MORE
JUMPGE S1,HELS.2 ;JUMP IF NO MORE OBJECTS
MOVX S1,OBSSTA!OBSSUP!OBSDAA ;STARTED+SETUP+DEVICE ATTRIBUTES
TDNN S1,OBJSCH(P3) ;ANY OF THESE BITS SET?
JRST HELS.2 ;NO, WELL IT NEVER WAS STARTED.
ANDCAM S1,OBJSCH(P3) ;CLEAR FOR RESTART
MOVEI M,COMSTA ;POINT TO INTERNAL START MESSAGE
SETOM .MSCOD(M) ;ACK ALL OPERATORS
MOVE S1,OBJTYP(P3) ;OBJECT TYPE
MOVEM S1,.OHDRS+ARG.DA+OBJ.TY(M)
MOVE S1,OBJNOD(P3) ;NODE NAME/NUMBER
MOVEM S1,.OHDRS+ARG.DA+OBJ.ND(M)
MOVE S1,OBJUNI(P3) ;UNIT NUMBER
MOVEM S1,.OHDRS+ARG.DA+OBJ.UN(M)
LOAD S1,OBJDAT(P3),RO.ATR ;GET ATTRIBUTES
PUSH P,S1 ;SAVE
MOVEI S1,%GENRC ;TO ALLOW STARTUP
CAIE S2,.OTNQC ;DON'T SCREW UP NQC
CAIN S2,.OTBAT ;[1466] OR GIVE BATCON A BUM MSG
TRNA ;[1466]
STORE S1,OBJDAT(P3),RO.ATR ;SO THAT WE MAY DETERMINE ATTRIBUTES
MOVEI S1,.OHDRS+ARG.DA(M) ;PONT TO THE OBJECT BLOCK
PUSHJ P,A$ISTA ;START THE OBJECT
POP P,S1 ;GET ORIGINAL ATTRIBUTES BACK
STORE S1,OBJDAT(P3),RO.ATR ;RESTORE
HELS.2: LOAD P3,.QELNK(P3),QE.PTN ;POINT TO NEXT OBJECT
JRST HELS.1 ;AND LOOP
SUBTTL COUNT -- Function 20
;COUNT MESSAGE IS SENT TO QUASAR BY A USER TO REQUEST A COUNT-ANSWER
; CONTAINING ALL OF QUASAR'S INTERESTING COUNTERS.
A$COUNT:
MOVE S1,G$NOW## ;GET NOW
$SITEM S1,NOW ;SAVE IT
$COUNT (MCAN) ;NUMBER OF COUNTANSWER MESSAGES
$CALL M%GPAG ;GET A PAGE
MOVEM S1,G$SAB##+SAB.MS ;SAVE IT IN THE SAB
MOVE S2,[CAN.SZ,,.QOCAN] ;GET LEN,,FUNCTION
MOVEM S2,.MSTYP(S1) ;STORE IT IN THE MESSAGE
MOVSI S2,G$ITEM## ;GET START ADDRESS
HRRI S2,CAN.BL(S1) ;GET DEST ADDRESS
BLT S2,CAN.SZ-1(S1) ;BLT THE MESSAGE
MOVEI S1,PAGSIZ ;PUT IN PAGE LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
MOVE S1,G$SND## ;GET PID OF SENDER
MOVEM S1,G$SAB##+SAB.PD ;SAVE IT IN THE SAB
PJRST C$SEND## ;SEND IT
SUBTTL Auto-file request -- Function 67
; Here to request auto-file processing from ORION.
; Call: MOVE S1, FD address
; PUSHJ P,A$AUTO
A$AUTO::$SAVE <M> ;SAVE M
PUSH P,S1 ;SAVE FD ADDRESS
$CALL M%GPAG ;GET A PAGE
MOVE M,S1 ;COPY ADDRESS
MOVEI S1,.QOATO ;FUNCTION CODE
STORE S1,.MSTYP(M),MS.TYP ;SAVE
MOVEI S1,.OHDRS+FDXSIZ ;LENGTH
STORE S1,.MSTYP(M),MS.CNT ;SAVE
MOVEI S1,1 ;ARGUMENT COUNT
MOVEM S1,.OARGC(M) ;SAVE
GETLIM S1,.QELIM(AP),SWIT ;GET THE ACK CODE
MOVEM S1,.OFLAGS(M) ;AND STORE IT
POP P,S1 ;GET FD ADDRESS BACK
HRLZS S1 ;PUT IN LH
HRRI S1,.OHDRS(M) ;WHERE TO PUT FD
MOVEI S2,.OHDRS+FDXSIZ(M) ;COMPUTE END OF BLT
BLT S1,-1(S2) ;COPY FD
MOVEM M,G$SAB##+SAB.MS ;SAVE MESSAGE ADDRESS IN THE SAB
LOAD S1,.MSTYP(M),MS.CNT ;GET LENGTH OF MESSAGE
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
MOVE S1,G$OPR## ;GET ORION'S PID
MOVEM S1,G$SAB##+SAB.PD ;SAVE IT IN THE SAB
PJRST C$SEND## ;SEND THE MESSAGE
SUBTTL Operator Messages
;The following messages are received from ORION:
INTERN A$OSTA ;STARTUP AN OBJECT
INTERN A$OSHT ;SHUTDOWN AN OBJECT
INTERN A$OSET ;SET PARAMETERS FOR AN OBJECT
INTERN A$OPAU ;PAUSE AN OBJECT
INTERN A$OCON ;CONTINUE AN OBJECT
INTERN A$OSHC ;SHOW CONTROL FILE (EXAMINE)
INTERN A$OREQ ;REQUEUE A JOB
INTERN A$OCAN ;CANCEL A JOB
INTERN A$OFWS ;FORWARD SPACE
INTERN A$OBKS ;BACK SPACE
INTERN A$OALI ;ALIGN FORMS ON PRINTER
INTERN A$OSUP ;SUPPRESS CARRIAGE CONTROL
INTERN A$OSND ;SEND MESSAGE TO LOG FILE
INTERN A$OREL ;RELEASE MESSAGE.
INTERN A$OHLD ;HOLD MESSAGE
INTERN A$ORTE ;ROUTE MESSAGE.
INTERN A$ODEL ;DELETE QUEUES MSG
INTERN A$MODIFY ;MODIFY QUEUE ENTRY MESSAGE
INTERN A$DEFINE ;DEFINE NODE COMMAND PROCESSOR
INTERN A$DN60 ;DN60 OPERATOR MSG PROCESSOR
INTERN A$STND ;START NODE PROCESSOR
INTERN A$ISTA ;INTERNAL STARTUP OF AN OBJECT
SUBTTL A$AGE -- Routine to compare two times in internal format
; Compute age in seconds based on the universal date/time format
; Call: S1 and S2 contain the UDTs to compare
; PUSHJ P,A$AGE
;
; On return S1:= age in seconds. AC usage: S1 and S2
;
A$AGE:: PUSH P,T1 ;SAVE T1
CAMGE S1,S2 ;ORDERING CHECK
EXCH S1,S2 ;WANT THE LARGEST IN S1
ADDI S1,1 ;ROUND UP
SUB S1,S2 ;SUBTRACT THEM
HLRZ T1,S1 ;GET DIFFERENCE IN DAYS
IMULI T1,^D24*^D60*^D60 ;CONVERT TO SECONDS
HRRZS S1 ;ISOLATE FRACTIONAL PORTION OF DAY
MULI S1,^D24*^D60*^D60 ;CONVERT TO SECONDS
ASHC S1,21 ;POSITION RESULT
ADD S1,T1 ;ADD IN DIFFERENCE IN DAYS
POP P,T1 ;RESTORE T1
POPJ P, ;RETURN
SUBTTL A$AFT -- Routine to modify an internal time
; Compute C(G$NOW) + a specified interval
; Call: S1/ interval in minutes
; PUSHJ P,A$AFT
;
; On return, S1:= new time. AC usage: S1 and S2.
;
A$AFT:: ZERO S2 ;ZERO FOR A SHIFT
ASHC S1,-^D17 ;GENERATE DOUBLE CONSTANT
; = ARG*2^18
DIVI S1,^D1440 ;DIVIDE BY MIN/DAY
ADD S1,G$NOW## ;ADD IN NOWTIM
$RETT ;AND RETURN
SUBTTL I$WHEEL -- Determine whether sender of current message is privileged
; Determine whether the send of the current IPCF message has lots of privs
; Call: No arguments
; PUSHJ P,A$WHEEL
; TRUE return: caller is a wheel (or operator)
; FALSE return: caller has no special privs
;
A$WHEEL::
MOVE S1,G$PRVS## ;GET PRIVS WORD
SKIPN DEBUGW ;IF DEBUGGING, ALWAYS SUCCEED
TXNE S1,MD.PWH!MD.POP ;WHEEL OR OPERATOR?
$RETT ;YES, RETURN TRUE
$RETF ;NOW RETURN FALSE
SUBTTL A$OSTA / A$ISTA -- Startup an object
; The A$OSTA entry to this routine is the normal entry for a normal startup
; command. It can include a range for the object.
; The A$ISTA entry to this routine is to startup an object as part of
; start node processing. S1 must contain a pointer to an object block.
; A range is not allowed. In addition, use of this entry point causes
; the check for starting individual objects on an IBM node to be skipped.
A$OSTA: $SAVE P1
MOVEI S1,.OROBJ ;GET THE OBJECT BLOCK TYPE
PUSHJ P,A$FNDB ;FIND THE OBJECT BLOCK IN THE MESSAGE
JUMPF A$STND ;NO,,MIGHT BE START NODE SO CHECK IT OUT
PUSHJ P,ORANGE ;CHECK FOR A RANGE
MOVE P1,S1 ;Save S1 for a min.
MOVE S1,OBJ.ND(S1) ;Get the node name
PUSHJ P,N$NODE## ;Get the node entry
; Since we are not part of a start node, want to check if this is the
; start of an IBM object, since that is illegal in this case.
LOAD S1,NETSTS(S2),NETIBM ;Get IBM status
SKIPE S1 ;Is it IBM object?
JRST OSTA.5 ;Yes, error, go tell the operator
SKIPA S1,P1 ;Get object block back
A$ISTA: $SAVE P1
PUSHJ P,GETOBJ ;GET THE OBJECT
JUMPF .RETT ;NO GOOD,,RETURN.
MOVE P1,S1 ;SAVE THE OBJECT ADDRESS
MOVX S1,OBSSTA ;GET STARTED BIT...
TDNE S1,OBJSCH(P1) ;ARE WE ALREADY STARTED ?
JRST OSTA.3 ;YES,,LET'EM KNOW ...
IORM S1,OBJSCH(P1) ;NO,,SET IT
$ACK (Startup Scheduled,,OBJTYP(P1),.MSCOD(M))
MOVE S1,P1 ;GET THE OBJECT ADDRESS BACK
PUSHJ P,A$OBST ;SETUP THE OBJECT STATUS.
DOSCHD ;FORCE A SCHEDULING PASS
MOVE S1,OBJTYP(P1) ;GET THE OBJECT TYPE
MOVX S2,OBSSUP!OBSFRR!OBSINV ;SETUP + FREE RUNNING + INVISIVBLE
CAIN S1,.OTEVT ;EVENT OBJECT?
IORM S2,OBJSCH(P1) ;YES--LITE LOTS OF BITS
;Check to see if object has a Physical Device Name
OSTA.1: MOVX S1,.CMDEV ;WANT A DEVICE BLOCK
PUSHJ P,A$FNDB ;SEE IF THERE IS ONE
JUMPF OSTA.2 ;NO
HRLI S1,(POINT 7,0) ;BYTE POINTER TO THE ASCIZ STRING
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVEM S2,OBJPRM+.OOTAP(P1) ;SAVE THE DEVICE NAME FOR LATER
MOVX S1,OBSSPL ;GET SPOOL TO TAPE FUNCTION
IORM S1,OBJSCH(P1) ;LITE IT IN THE SCHEDULING VECTOR
OSTA.2: MOVE S1,OBJTYP(P1) ;GET OBJECT TYPE
LOAD S2,OBJDAT(P1),RO.ATR ;GET ATTRIBUTES
PUSHJ P,I$GOPD## ;GET OBJECT PROCESSOR TYPE
JUMPF .RETT ;SOMEBODY IS CONFUSED IF NOT THERE
SKIPN DEBUGW ;DEBUGGING?
CAXN S2,%STCMD ;FIRE UP ON START COMMAND?
TRNA ;YES TO EITHER
$RETT ;NO, WAIT FOR A JOB
MOVE S1,P1 ;COPY OBJECT BLOCK
PUSHJ P,S$FPSB## ;FIND THE PROCESSOR STATUS BLOCK
JUMPF .RETT ;DONE IF NO PROCESSOR
PUSHJ P,S$SETU## ;SEND SETUP MESSAGE TO PROCESSOR
$RETT ;AND RETURN
OSTA.3: MOVX S1,OBSSEJ ;GET 'SHUTDOWN AT EOJ'
TDNN S1,OBJSCH(P1) ;WAS SHUTDOWN PENDING ???
JRST OSTA.4 ;NO,,SAY ALREADY STARTED
ANDCAM S1,OBJSCH(P1) ;CLEAR PENDING SHUTDOWN
$ACK (Pending shutdown cancelled,,OBJTYP(P1),.MSCOD(M))
$RETT ;RETURN
OSTA.4: $ACK (Already Started,,OBJTYP(P1),.MSCOD(M))
$RETT
OSTA.5: $ACK (<Illegal to start a specific object for IBM node ^N/OBJ.ND(P1)/>,<Use START NODE command>,,.MSCOD(M))
$RETT
SUBTTL A$STND - START NODE MESSAGE PROCESSOR
A$STND: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
$SAVE <M> ;SAVE THE ORIGIONAL MESSAGE ADDRESS
MOVX S1,.ORNOD ;GET NODE BLOCK TYPE
PUSHJ P,A$FNDB ;FIND IT IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,THATS AN ERROR
MOVE S1,0(S1) ;GET THE NODE NAME
MOVE S2,.MSCOD(M) ;GET THE ACK CODE
MOVEI M,COMSTA ;POINT TO THE COMMON START MESSAGE
MOVEM S1,.OHDRS+ARG.DA+OBJ.ND(M) ;SAVE IN OUR OBJECT BLOCK
MOVEM S2,.MSCOD(M) ;SAVE THE ACK CODE IN THE MESSAGE
SETZM .OHDRS+ARG.DA+OBJ.UN(M) ;WANT UNIT 0
PUSHJ P,N$PORT## ;LOOK FOR OTHER DEVICES STARTED ON
JUMPT STAERR ; THE SAME PORT/LINE (IBM ONLY)
; S2 now contains the pointer to the node entry, check out the IBM status.
MOVE P1,S2 ;SAVE NET QUEUE ADDRESS
LOAD S1,NETSTS(P1),NETIBM ;GET IBM STATUS
LOAD S2,NETSTS(P1),NT.MOD ;GET THE MODE
JUMPE S1,STND.2 ;JUMP IF NOT IBM
CAXN S2,DF.EMU ;IN EMULATION MODE ???
JRST STND.1 ;YES,,START A BATCH STREAM
CAXE S2,DF.PRO ;Is it prototype mode?
JRST STAE.2 ;No, can't start an actual termination
PUSH P,S1 ;Save S1 for a min.
MOVX S1,.OTRDR ;GET CARD READER OBJECT TYPE
PUSHJ P,STND.X ;START A CDR
POP P,S1 ;GET BACK IBMNESS
JUMPN S1,.RETT ;DONE IF IBM
MOVX S1,.OTLPT ;GET LINE PRINTER OBJECT TYPE
PUSHJ P,STND.X ;START A LPT
SETOM .MSCOD(M) ;CLEAR COMMON ACK CODE
$RETT ;AND RETURN
STND.1: MOVX S1,.OTBAT ;GET BATCH STREAM OBJECT TYPE
PUSHJ P,STND.X ;START A BATCH STREAM
SETOM .MSCOD(M) ;CLEAR COMMON ACK CODE
$RETT ;AND RETURN
; HERE TO START ALL DEVICES ON A REMOTE STATION
STND.2: SKIPE S1,NETCOL(P1) ;GET SYSTEM DEPENDANT IDENTIFIER
MOVEM S1,.OHDRS+ARG.DA+OBJ.ND(M) ;UPDATE INCASE OTHER NOTATION USED
PUSH P,[EXP 0] ;INIT COUNTER
MOVEI P2,NETOBJ(P1) ;POINT TO DEVICE WORDS
HRLI P2,-NETOBL ;MAKE AN AOBJN POINTER
STND.3: HLRZ S1,(P2) ;GET A DEVICE COUNT
JUMPE S1,STND.5 ;CONTINUE IF NONE
PUSH P,S1 ;SAVE COUNT
SETOM .OHDRS+ARG.DA+OBJ.UN(M) ;INIT UNIT NUMBER
STND.4: AOS .OHDRS+ARG.DA+OBJ.UN(M) ;ADVANCE UNIT NUMBER
HRRZ S1,(P2) ;GET AN OBJECT TYPE
PUSHJ P,STND.X ;START DEVIVE
AOS -1(P) ;COUNT THE DEVICE STARTED
SOSLE (P) ;COUNT DOWN
JRST STND.4 ;LOOP
POP P,(P) ;TRIM STACK
STND.5: AOBJN P2,STND.3 ;LOOP FOR ALL DEVICES
POP P,S1 ;GET DEVICE STARTED COUNTER BACK
JUMPN S1,STND.6 ;CONTINUE IF DEVICES STARTED
MOVE S1,NETCOL(P1) ;GET NODE NAME/NUMBER
PUSHJ P,N$NODE## ;SEE IF ONLINE
SKIPN S1,NETCOL(P1) ;GET NODE NAME/NUMBER BACK
MOVE S1,NETLOC(P1) ;MUST BE NON-ZERO
MOVEI S2,[ASCIZ /has no devices/]
SKIPT ;SKIP IF ONLINE
MOVEI S2,[ASCIZ /is offline/]
$ACK (<No devices started>,<Node ^N/S1/ ^T/(S2)/>,,.MSCOD(M))
STND.6: SETZM .OHDRS+ARG.DA+OBJ.UN(M) ;RESET UNIT NUMBER FOR NEXT CALLER
SETOM .MSCOD(M) ;CLEAR COMMON ACK CODE
$RETT ;AND RETURN
; START A DEVICE
; CALL: MOVE S1, OBJECT TYPE
; PUSHJ P,STND.X
STND.X: MOVEM S1,.OHDRS+ARG.DA+OBJ.TY(M) ;SAVE AS THE OBJECT TYPE
MOVEI S1,.OHDRS+ARG.DA(M) ;Get the start of the object block
PUSHJ P,A$ISTA ;START A BATCH STREAM FOR THE NODE
$RETT ;AND RETURN
STAERR: PUSHJ P,DN60ID ;GENERATE DN60 IDENTIFIER
$ACK (<Illegal start command>,<^T/(S2)/ already started>,,.MSCOD(M))
$RETT ;RETURN
STAE.2: MOVE S1,.OHDRS+ARG.DA+OBJ.ND(M) ;Get the node name back
$ACK (<Illegal to start termination node ^N/S1/>,<Only defined prototype nodes may be started>,,.MSCOD(M))
$RETT
DN60ID: PUSHJ P,.SAVET ;SAVE SOME ACS
LOAD T4,NETPTL(S1),NT.PRT ;GET THE PORT DATA
HRLZS T4 ;CAL11. STYLE
LOAD T1,T4,C1.1CN ;CPU NUMBER
LOAD T2,T4,C1.1TY ;PORT TYPE
MOVE T2,PORTAB(T2) ;CONVERT TO TEXT
LOAD T3,T4,C1.1PN ;PORT NUMBER
LOAD T4,NETPTL(S1),NT.LIN ;LINE NUMBER
MOVE S2,NETCOL(S1) ;GET NODE NUMBER
$TEXT (<-1,,DN60TX>,<^I/DN60IT/^0>)
MOVEI S2,DN60TX ;POINT TO TEXT
POPJ P, ;RETURN
DN60IT: ITEXT (<Station ^N/S2/ CPU^D/T1/ ^T/(T2)/ port ^O/T3/ line ^O/T4/>)
DN60TX: BLOCK 25
PORTAB: [ASCIZ /DL10/]
[ASCIZ /DTE/]
[ASCIZ /KMC/]
[ASCIZ /DMR/]
SUBTTL A$OSHT -- Shutdown an object
A$OSHT: PUSHJ P,.SAVE2 ;SAVE P1 AND P2 FOR A MINUTE
MOVX S1,.OROBJ ;GET THE OBJECT BLOCK TYPE
PUSHJ P,A$FNDB ;FIND THE OBJECT BLOCK IN THE MESSAGE
JUMPF SHUTNODE ;NO OBJECT BLK,,TRY SHUTDOWN NODE
PUSHJ P,ORANGE ;BREAK UP A RANGE
MOVE P1,S1 ;SAVE THE OBJECT BLOCK ADDRESS
; Need to make certain it is not a shutdown for an IBM node device
MOVE S1,OBJ.ND(S1) ;Get the node name
PUSHJ P,N$GNOD## ;Get the node entry
JUMPF BADMSG ;It must be there!
LOAD S1,NETSTS(S2),NETIBM ;Get the IBM status
SKIPE S1 ;Is it IBM object?
JRST A$SH.3 ;Yes, not allowed
MOVE S1,P1 ;Get back the object block address
PUSHJ P,A$FOBJ ;FIND IT IN OUR DATA BASE
JUMPF DEVUNK ;NOT THERE,,ACK THE OPR AND RETURN
MOVE P1,S1 ;SAVE THE OBJECT QUEUE ENTRY ADDRESS
LOAD S1,OBJSCH(P1) ;GET OBJ SCHEDULING BITS
TXNN S1,OBSSUP ;IS IT SETUP ???
JRST A$SH.0 ;NO,,JUST SHUT IT DOWN.
TXO S1,OBSSEJ ;LITE SHUTDOWN AT END OF JOB BIT
TXNE S1,OBSBUS ;IS IT BUSY ??? IF SO,SEND THE ACK.
$ACK (Shutdown at EOJ Scheduled,,OBJTYP(P1),.MSCOD(M))
MOVE S2,OBJTYP(P1) ;GET OBJECT TYPE
TXNE S1,OBSFRR ;IS THIS A FREE RUNNING DEVICE ??
CAIN S2,.OTFAL ;YES, BUT IS IT FAL?
TRNA ;NOT FREE RUNNING OR FREE RUNNING AND FAL
TXZ S1,OBSBUS ;YES,,CLEAR THE BUSY BIT
MOVEM S1,OBJSCH(P1) ;SAVE THE SCHEDULING BITS
DOSCHD ;FORCE A SCHEDULING PASS
$RETT ;AND RETURN
A$SH.0: MOVE S1,P1 ;GET THE OBJECT ADDRESS
PUSHJ P,S$SHUT## ;SHUT IT DOWN
$RETT ;AND RETURN
A$SH.3: $ACK (<Illegal to shutdown a specific object for IBM node ^N/OBJ.ND(P1)/>,<Use SHUTDOWN NODE command>,,.MSCOD(M))
$RETT ;Tell the operator and quit
SUBTTL SHUTNODE - ROUTINE TO SHUTDOWN AN ENTIRE NODE
SHUTNO: MOVX S1,.ORNOD ;GET THE NODE BLOCK TYPE
PUSHJ P,A$FNDB ;GO FIND IT IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,THATS ALL SHE WROTE !!
MOVE S1,0(S1) ;GET THE NODE NAME/NUMBER
SHUT.1: PUSHJ P,N$GNOD## ;FIND IT IN OUR DATA BASE
DMOVE P1,S1 ;COPY NODE NAME & ADDRESS
JUMPF SHUT.8 ;If not found, just return an error
; Check to see if we are shutting down an online proto. If so, mark the
; proto node and then go for the devices on the actual node
LOAD S1,NETSTS(P2),NT.MOD ;Get the mode
JUMPE S1,SHUT.2 ;CONTINUE IF NON-DN60 NODE
CAME P1,NETLOC(P2) ;Skip this if proto is same as actual
CAIE S1,DF.PRO ;Is it proto mode?
JRST SHUT.3 ;No, continue on
LOAD S1,NETSTS(P2),NETPRO ;Get proto online flag
SKIPN S1 ;Is it online prototype?
JRST SHUT.3 ;No, just shutdown the proto
MOVX S1,NETSHT ;Get the network shutdown bit
IORM S1,NETSTS(P2) ;Set it in the proto node
MOVE S1,NETLOC(P2) ;Get the actual node name
JRST SHUT.1 ;Go shut the actual node
SHUT.2: SKIPN P1,NETCOL(P2) ;GET SYSTEM DEPENDENT IDENTIFIER
MOVE P1,NETLOC(P2) ;ELSE USE ALTERNATE
SHUT.3: SETZM .OARGC(M) ;INDICATE NO OBJECT SHUTDOWN YET !!!
MOVX S1,NETSHT ;GET THE NETWORK SHUTDOWN BIT
IORM S1,NETSTS(P2) ;LITE IT FOR THIS NODE
MOVEI H,HDROBJ## ;GET THE OBJECT HEADER ADDRESS
LOAD P2,.QHLNK(H),QH.PTF ;GET THE FIRST OBJECT
SHUT.4: JUMPE P2,SHUT.7 ;NO MORE,,WE ARE DONE
MOVE S1,OBJSCH(P2) ;GET THE SCHEDULING BITS
TXNN S1,OBSINV ;IS IT INVISIBLE ???
CAME P1,OBJNOD(P2) ;ARE WE SHUTING DOWN THIS OBJECT ???
JRST SHUT.5 ;INVISIBLE OR WRONG NODE,,TRY NEXT
TXNN S1,OBSSUP ;IS THE OBJECT SETUP ???
JRST SHUT.6 ;NO,,JUST SHUT IT DOWN
TXO S1,OBSSEJ ;LITE SHUT DOWN AT EOJ BIT
TXNE S1,OBSBUS ;IS THE OBJECT BUSY ???
$ACK (<Shutdown at EOJ Scheduled>,,OBJTYP(P2),.MSCOD(M));YES !!
MOVE S2,OBJTYP(P2) ;GET OBJECT TYPE
TXNE S1,OBSFRR ;IS THIS A FREE RUNNING DEVICE ??
CAIN S2,.OTFAL ;YES, BUT IS IT FAL?
TRNA ;NOT FREE RUNNING OR FREE RUNNING AND FAL
TXZ S1,OBSBUS ;YES,,CLEAR THE BUSY BIT
STORE S1,OBJSCH(P2) ;RESTORE THE SCHEDULING BITS
DOSCHD ;FORCE A SCHEDULING PASS
AOS .OARGC(M) ;BUMP SHUTDOWN COUNT BY 1
SHUT.5: LOAD P2,.QELNK(P2),QE.PTN ;GET THE NEXT OBJECT ADDRESS
JRST SHUT.4 ;AND CONTINUE
SHUT.6: MOVE S1,P2 ;GET THE OBJECT ADDRESS
LOAD P2,.QELNK(P2),QE.PTN ;GET NEXT OBJ ADDR,,THIS ONE IS LEAVING
PUSHJ P,S$SHUT## ;SHUT THE OBJECT DOWN
AOS .OARGC(M) ;BUMP SHUTDOWN COUNT BY 1
JRST SHUT.4 ;AND CONTINUE
SHUT.7: SKIPN .OARGC(M) ;DID WE SHUTDOWN ANY OBJECTS ???
SHUT.8: $ACK (<No devices started on node ^N/P1/>,,,.MSCOD(M)) ;NO !!
$RETT ;RETURN
SUBTTL A$OSET -- Set parameters for an object
A$OSET: PUSHJ P,.SAVE3 ;SAVE P1 & P2 FOR A MINUTE
MOVEI S1,.OROBJ ;GET THE OBJECT BLOCK TYPE
PUSHJ P,A$FNDB ;FIND THE OBJECT BLOCK IN THE MESSAGE
JUMPF NETSET ;NOT THERE,,TRY NETWORK SET
MOVE P1,S1 ;SAVE THE OBJ BLK ADDRESS FOR A MINUTE
OSET.0: PUSHJ P,A$GBLK ;GET FIRST/NEXT MESSAGE BLOCK
JUMPF BADMSG ;NO MORE,,RETURN THROUGH 'BADMSG'
MOVSI S1,-NSETS ;GET NEGATIVE # OS SET COMMANDS.
OSET.1: HLRZ S2,SETTBL(S1) ;PICK UP A SET COMMAND TYPE.
CAMN S2,T1 ;DO WE MATCH ???
JRST OSET.2 ;YES,,GO PROCESS IT
AOBJN S1,OSET.1 ;BUMP TO NEXT TBL ENTRY AND CONTINUE.
JRST OSET.0 ;NO MATCH,,TRY NEXT
OSET.2: HRRZ P2,SETTBL(S1) ;GET THE PROCESSING ROUTINE ADDRESS
MOVE P3,T3 ;SAVE THE 'SET' DATA ADDRESS
MOVE S1,P1 ;GET THE OBJ BLK ADDRESS
PUSHJ P,ORANGE ;BREAK UP THE RANGE
MOVE P1,S1 ;SAVE THE OBJ BLK ADDRESS
PUSHJ P,GETOBJ ;FIND/CREATE THE OBJ BLK.
JUMPF .RETT ;NO GOOD,,RETURN
MOVE P1,S1 ;SAVE THE OBJECT QUEUE ADDRESS
PJRST 0(P2) ;GO PROCESS IT (ADDRESS FROM OSET.2)
SETPGL: MOVEI S1,.OOLIM ;GET PAGE LIMIT OFFSET.
PJRST SETMMX ;GO SET MIN/MAX.
SETFRM: LOAD S1,0(P3) ;GET FORMS TYPE.
STORE S1,OBJPRM+.OOFRM(P1) ;AND SAVE IT IN QUEUE.
MOVX S1,OBSFRM ;GET 'SET FORMS TYPE' STATUS
MOVE S2,OBJTYP(P1) ;GET THE OBJECT TYPE
CAXN S2,.OTLPT ;PRINTER 'SET' ???
IORM S1,OBJSCH(P1) ;YES,,SET FORMS CHANGE STATUS
JRST SETMSG ;GO SAY ITS OK...
SETMEM: MOVEI S1,.OBCOR ;GET CORE LIMIT OFFSET.
PJRST SETMMX ;GO SET MIN/MAX.
SETTIM: MOVEI S1,.OBTIM ;GET TIME LIMIT OFFSET.
PJRST SETMMX ;GO SET MIN/MAX.
SETPRI: MOVEI S1,.OOPRI ;GET PRIORTY LIMIT OFFSET.
PJRST SETMMX ;GO SET MIN/MAX.
SETSOI: MOVEI S1,.OPINS ;GET SYSTEM INTERVENTION CODE
JRST SETOIX ;CONTINUE
SETOIA: SKIPA S1,[.OPINY] ;GET OPR INTERVN ALLOWED CODE
SETNOI: MOVE S1,[.OPINN] ;GET NO OPR INTERVN ALLOWED CODE
SETOIX: STORE S1,OBJPRM+.OBFLG(P1),.OPRIN ;SAVE IT
JRST SETMSG ;SEND AN ACK AND RETURN
SETLEA: LOAD S1,0(P3) ;GET THE ACTION CODE
STORE S1,OBJPRM+.OOFLG(P1),.OFLEA ;SAVE IT IN THE OBJECT BLOCK
JRST SETMSG ;SEND THE ACK
SETLP2: MOVE S1,(P3) ;GET THE ACTION CODE
STORE S1,OBJPRM+.OOFLG(P1),OF.LP2 ;SAVE IN THE OBJECT BLOCK
JRST SETMSG ;SEND THE ACK
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
SETMMX: ADDI S1,OBJPRM(P1) ;CALC QUEUE PARAMETER ADDRESS.
LOAD S2,0(P3) ;PICK UP MIN VALUE.
STORE S2,0(S1),OBPMIN ;SAVE THE MIN VALUE.
LOAD S2,1(P3) ;PICK UP MAX VALUE.
STORE S2,0(S1),OBPMAX ;SAVE THE MAX VALUE.
SETMSG: $ACK (Set Accepted,,OBJTYP(P1),.MSCOD(M))
MOVE S1,P1 ;GET OBJECT ADDRESS IN S1
PUSHJ P,A$OBST ;UPDATE THE OBJECT STATUS
DOSCHD ;FORCE A SCHEDULING PASS
$RETT ;RETURN.
SETUTY: PUSHJ P,UTYCHK ;CHECK FOR ALREADY SETUP, OUTPUT
$RETIF ;GIVE UP IF ERROR ALREADY ACKED
MOVE S1,(P3) ;GET UNIT TYPE
MOVEM S1,OBJPRM+.OOUNT(P1) ;SAVE SIXBIT QUANTITY
PJRST SETMSG ;GO ACK
SETNTY: MOVE S1,(P3) ;GET NETWORK-TYPE
CAIE S1,ST.ANF ;ANF-10?
CAIN S1,ST.DCN ;DECNET?
TRNA ;YES, TO ONE OF THEM
JRST SETA.2 ;NO, TO BOTH
MOVEM S1,OBJPRM+.OBNTY(P1) ;NO, STORE IN OBJECT BLOCK
PJRST SETMSG ;ACK OPR AND RETURN
SETATR: LOAD S1,OBJDAT(P1),RO.ATR ;GET ATTRIBUTES
CAMN S1,0(P3) ;NEED TO BE CHANGED?
PJRST SETMSG ;NO,,JUST RETURN
LOAD S1,OBJSCH(P1) ;GET SCHEDULER FLAGS
TXNE S1,OBSSUP!OBSSIP ;ERROR IF SETUP STARTED
JRST SETA.1
MOVE S1,0(P3) ;GET THE NEW ATTRIBUTES
STORE S1,OBJDAT(P1),RO.ATR ;STORE THEM
PJRST SETMSG ;RETURN
SETA.1: $ACK (Attribute may not be changed,,OBJTYP(P1),.MSCOD(M))
$RETF
SETA.2: $ACK (Invalid attribute specified,,OBJTYP(P1),.MSCOD(M))
$RETF
SETTBL: .STPGL,,SETPGL ;PAGE LIMIT
.STFRM,,SETFRM ;FORMS TYPE
.STMEM,,SETMEM ;CORE LIMIT
.STTIM,,SETTIM ;TIME LIMIT
.STPRI,,SETPRI ;PRIORTY LIMIT
.STOIA,,SETOIA ;OPR INTERVENTION ACTION
.STNOI,,SETNOI ;NO OPR INTERVENTION ACTION.
.STLEA,,SETLEA ;LIMIT EXCEEDED ACTION
.STATR,,SETATR ;SET ATTIBUTES
.STNTY,,SETNTY ;FAL-STREAM NETWORK-TYPE (ATTRIBUTE)
.STMTA,,SETMTA ;SET MAGTAPE SPOOLING PARAMETERS
.STUTY,,SETUTY ;SET PRINTER UNIT-TYPE
.STLP2,,SETLP2 ;SET LP20 SIMULATION
.STSOI,,SETSOI ;SET SYSTEM-OPR-INTERVENTION
NSETS==.-SETTBL
;CHECK FOR ALREADY SETUP AND OUTPUT OBJECT
UTYCHK: MOVX S1,OBSSTA!OBSSUP!OBSSIP ;VARIOUS SETUP BITS
TDNE S1,OBJSCH(P1) ;ALREADY SETUP?
PJRST DASMSG ;DEVICE ALREADY STARTED
MOVE S1,OBJTYP(P1) ;GET THE OBJECT TYPE
PUSHJ P,A$OB2Q ;CONVERT TO QUEUE HEADER
JUMPF BADMSG ;BAD ORION MESSAGE
LOAD S1,.QHTYP(S1),QH.TYP ;GET QUEUE TYPE
CAIE S1,.QHTOU ;OUTPUT?
JRST BADMSG ;ORION BUILT A BAD MESSAGE
$RETT ;RETURN GOODNESS
;SET MAGTAPE SPOOLING PARAMETERS
SETMTA: PUSHJ P,UTYCHK ;ALREADY SETUP, OUTPUT?
$RETIF ;ERROR ACK SENT
MOVE S1,OBJPRM+.OOUNT(P1) ;GET CURRENT (MAYBE ZERO) UNIT TYPE
MOVEM S1,OLDUTY ;SAVE INCASE OF ERROR
MOVE S1,OBJPRM+.OOMTA(P1) ;GET CURRENT MTA PARAMETERS
MOVEM S1,OLDMTA ;SAVE INCASE OF ERROR
MOVSI S1,OBJPRM+.OOVSN(P1) ;POINT TO CURRENT VSN
HRRI S1,OLDVSN ;MAKE A BLT POINTER
BLT S1,OLDVSN+VSNLEN-1 ;COPY AWAY INCASE OF ERROR
SKIPN S1,OBJPRM+.OOUNT(P1) ;GET UNIT TYPE
MOVE S1,MTAUTT ;DEFAULT
MOVSI S2,-MTAUTL ;AOBJN POINTER
CAME S1,MTAUTT(S2) ;VALID UNIT TYPE?
AOBJN S2,.-1 ;LOOP THROUGH TABLE
JUMPGE S2,SETMT5 ;NO
MOVEM S1,OBJPRM+.OOUNT(P1) ;POSSIBLY UPDATE IT
SETMT1: PUSHJ P,A$GBLK ;GET FIRST/NEXT BLOCK
JUMPF SETMT4 ;BAD MESSAGE
MOVSI S1,-MTALEN ;AOBJN POINTER
SETMT2: HLRZ S2,MTATAB(S1) ;GET SWITCH BLOCK TYPE
CAIN T1,(S2) ;MATCH?
JRST SETMT3 ;YES
AOBJN S1,SETMT2 ;LOOP THROUGH TABLE
JRST SETMT4 ;BAD MESSAGE
SETMT3: HRRZ S2,MTATAB(S1) ;GET DISPATCH ADDRESS
PUSHJ P,(S2) ;PROCESS SWITCH
JUMPF SETMT6 ;CHECK FOR ERROR
ADDI T3,-ARG.DA(T2) ;OFFSET TO NEXT POSSIBLE BLOCK
SKIPE (T3) ;END?
JRST SETMT1 ;LOOP BACK FOR ANOTHER
PUSHJ P,MDACHK ;DO MDA RESOURCE CHECKING
JUMPT SETMSG ;GO ACK IF OK
JRST SETMT6 ;ELSE RESET THINGS
SETMT4: SKIPA S1,[[ITEXT (<Unknown magtape parameter ^O/T1/>)]]
SETMT5: MOVEI S1,[ITEXT (<Unit type is not MAGTAP>)]
$ACK (<ORION message error>,<^I/(S1)/>,OBJTYP(P1),.MSCOD(M))
SETMT6: MOVE S1,OLDUTY ;GET PREVIOUS UNIT TYPE
MOVEM S1,OBJPRM+.OOUNT(P1) ;REPLACE
MOVE S1,OLDMTA ;GET PREVIOUS PARAMETERS
MOVEM S1,OBJPRM+.OOMTA(P1) ;REPLACE
MOVSI S1,OLDVSN ;POINT TO PREVIOUS VSN
HRRI S1,OBJPRM+.OOVSN(P1) ;AND TO STORAGE
BLT S1,OBJPRM+.OOVSN+VSNLEN-1(P1) ;REPLACE
$RETF
MTATAB: .SWMDN,,MTAMDN ;/DENSITY
.SWMDI,,MTAMDI ;/DIRECTORY-FILE
.SWMLT,,MTAMLT ;/LABEL-TYPE
.SWMRL,,MTAMRL ;/MULTI-REEL
.SWMPR,,MTAMPR ;/PARITY
.SWMTK,,MTAMTK ;/TRACKS
.SWMVS,,MTAMVS ;/VOLUME-SET
MTALEN==.-MTATAB ;LENGTH OF TABLE
MTAUTT: SIXBIT /MAGTAP/ ;DEFAULT UNIT TYPE (MUST BE FIRST)
MTAUTL==.-MTAUTT ;LENGTH OF TABLE
OLDUTY: BLOCK 1 ;OLD UNIT TYPE
OLDMTA: BLOCK 1 ;OLD MAGTAPE PARAMETERS
OLDVSN: BLOCK VSNLEN ;OLD VOLUME-SET NAME
;DENSITY
MTAMDN: MOVE S1,(T3) ;GET DENSITY ACTION
STORE S1,OBJPRM+.OOMTA(P1),OB.MDN ;SET DENSITY
$RETT ;RETURN
;DIRECTORY-FILE
MTAMDI: MOVE S1,(T3) ;GET YES/NO ACTION
STORE S1,OBJPRM+.OOMTA(P1),OB.MDI ;SET MAGTAPE DIRECTORY
$RETT ;RETURN
;LABEL TYPE
MTAMLT: MOVX S1,OB.MLV!OB.MLT ;AND LABEL TYPE AND VALID BITS
ANDCAM S1,OBJPRM+.OOMTA(P1) ;INITIALLY CLEAR THEM
MOVE S1,(T3) ;GET LABEL TYPE ACTION
CAIN S1,-1 ;DEFAULT?
$RETT ;YES--USE SPOOLER DEFAULT
STORE S1,OBJPRM+.OOMTA(P1),OB.MLT ;SET LABEL TYPE
MOVX S1,OB.MLV ;ONE MORE BIT
IORM S1,OBJPRM+.OOMTA(P1) ;INDICATE LABEL TYPE IS VALID
$RETT ;RETURN
;MULTI-REEL
MTAMRL: MOVE S1,(T3) ;GET YES/NO ACTION
STORE S1,OBJPRM+.OOMTA(P1),OB.MRL ;SET MULTI-REEL VOLUME-SET
$RETT ;RETURN
;PARITY
MTAMPR: MOVE S1,(T3) ;GET ODD/EVEN/DEFAULT ACTION
STORE S1,OBJPRM+.OOMTA(P1),OB.MPR ;SET PARITY
$RETT ;RETURN
;TRACKS
MTAMTK: MOVE S1,(T3) ;GET 7/9/DEFAULT ACTION
STORE S1,OBJPRM+.OOMTA(P1),OB.MTK ;SET TRACK TYPE
$RETT ;RETURN
;VOLUME-SET NAME
MTAMVS: MOVSI S1,OBJPRM+.OOVSN(P1) ;VOLUME-SET DESTINATION
HRRI S1,OBJPRM+.OOVSN+1(P1) ;MAKE A BLT POINTER
SETZM OBJPRM+.OOVSN(P1) ;CLEAR FIRST WORD
BLT S1,OBJPRM+.OOVSN+VSNLEN-1(P1); CLEAR STORAGE
MOVSI S1,(T3) ;POINT TO VOLUME-SET NAME
HRRI S1,OBJPRM+.OOVSN(P1) ;MAKE A BLT POINTER
LOAD S2,-ARG.DA(T3),AR.LEN ;GET LENGTH OF VSN STRING
CAILE S2,VSNLEN ;REASONABLE?
MOVEI S2,VSNLEN ;TRUNCATE
ADDI S2,OBJPRM+.OOVSN(P1) ;COMPUTE END OF BLT
BLT S1,-1(S2) ;COPY VSN
$RETT ;RETURN
;HERE FOR MDA RESOURCE CHECK WITH DENSITY IN S1 AND TRACKS IN S2
MDACHK: SKIPN G$MDA## ;MDA SUPPORT?
$RETT ;NO
LOAD S1,OBJPRM+.OOMTA(P1),OB.MDN ;GET DENSITY
CAIN S1,.TFD00 ;DEFAULT DENSITY?
JRST MDACH1 ;YES
MOVNI S2,-1(S1) ;NEGATE DENSITY INDEX FOR LSH
MOVX S1,UC.200 ;STARTING DENSITY BIT
LSH S1,(S2) ;SELECT PROPER BIT
JRST MDACH2 ;ONWARD
MDACH1: MOVE S1,[UC.200+UC.556+UC.800+UC.1600+UC.6250]
MDACH2: LOAD S2,OBJPRM+.OOMTA(P1),OB.MTK ;GET TRACKS
JUMPN S2,MDACH3 ;PROCEED IF TRACK TYPE KNOWN
PUSH P,S1 ;SAVE DENSITY BIT(S)
MOVEI S2,%TRK9 ;FIRST TRY 9-TRACK
PUSHJ P,D$TRSN## ;...
POP P,S1 ;GET DENSITY BIT(S) BACK
JUMPT .RETT ;RETURN IF RESOURCE FOUND
MOVEI S2,%TRK7 ;NOW TRY 7-TRACK
MDACH3: PUSHJ P,D$TRSN## ;FIND A MATCHING RESOURCE
JUMPT .RETT ;RETURN IF A RESOURCE EXISTS
$ACK (<No units with desired density and tracks>,,OBJTYP(P1),.MSCOD(M))
$RETF ;RETURN
SUBTTL A$ETSR - ENABLE TIMESHARING
TOPS10 <
A$ETSR::PUSHJ P,A$WHEEL ;MAKE SURE SENDER IS PRIV'ED
JUMPF E$IPE## ;NO PRIVS
PUSHJ P,.SAVE2 ;SAVE P1 AND P2
SETZB P1,P2 ;CLEAR JOB AND REQUEST-ID
SKIPGE S1,G$KSYS## ;KSYS TIMED OUT?
JRST ETSR.3 ;YES
JUMPE S1,ETSR.4 ;ERROR IF NOT PENDING
MOVEI H,HDREVT## ;POINT TO EVENT QUEUE HEADER
LOAD AP,.QHLNK(H),QH.PTF ;POINT TO THE FIRST ENTRY
ETSR.1: JUMPE AP,ETSR.3 ;RETURN IF NO MORE ENTRIES
GETLIM S1,.QELIM(AP),TYPE ;GET EVENT CODE
CAIE S1,.EVKSY ;KSYS?
TDZA S1,S1 ;NO
GETLIM S1,.QELIM(AP),ACTV ;GET ACTIVE BIT
JUMPN S1,ETSR.2 ;ONLY VALID IF ACTIVE
LOAD AP,.QELNK(AP),QE.PTN ;GET POINTER TO NEXT ENTRY
JRST ETSR.1 ;AND LOOP
ETSR.2: MOVE P1,.QEJOB(AP) ;SAVE JOB NAME
MOVE P2,.QERID(AP) ;AND REQUEST-ID
PUSHJ P,Q$KPRO## ;KILL OFF THIS REQUEST
ETSR.3: MOVE S1,[.STKSY,,0] ;FUNCTION,,CLEAR TIMER
SKIPN DEBUGW ;DEBUGGING?
SETUUO S1, ;SET KSYS
JFCL ;SHOULDN'T FAIL
MOVEI S2,ETSR.K ;POINT TO KILL TEXT
SKIPN P2 ;HAVE A REQUEST-ID?
MOVEI S2,ETSR.N ;NO--POINT TO NULL TEXT
MOVEI S1,ETSR.A ;POINT TO NORMAL ACK TEXT
JRST ETSR.5 ;FINISH UP
ETSR.4: MOVEI S1,ETSR.E ;POINT TO ERROR ACK TEXT
MOVEI S2,ETSR.N ;POINT TO NULL TEXT
ETSR.5: $ACK (<^T/(S1)/>,<^I/(S2)/>,,.MSCOD(M))
POPJ P, ;RETURN
ETSR.A: ASCIZ /Timesharing enabled/
ETSR.E: ASCIZ /No KSYS pending/
ETSR.N: ITEXT (<>)
ETSR.K: ITEXT (<Event ^W/P1/ request #^D/P2/ cancelled>)
> ;END TOPS-10 CONDITIONAL
SUBTTL NETSET - 'SET NODE' PROCESSING ROUTINE
NETSET:
IFN FTDN60,<
MOVX S1,.ORNOD ;GET THE NODE BLOCK TYPE
PUSHJ P,A$FNDB ;SEE IF ITS THERE
JUMPF BADMSG ;THAT WAS HIS LAST CHANCE
MOVE S1,0(S1) ;GET THE NODE NAME/NUMBER
SETO S2, ;Say we want online check
$CALL N$CKND## ;Check out the node
JUMPF NETS.3 ;Failed, either online or
; objects started
JUMPE S2,NETS.2 ;Not found, not defined
MOVE P1,S2 ;SAVE THE DATA BASE ENTRY ADDRESS
LOAD S2,NETSTS(P1),NT.MOD ;GET THE IBM REMOTE STATUS BITS
JUMPE S2,NETS.2 ;NOT IBM,,CAN'T DO THIS !!!
CAIN S2,DF.TRM ;Is it an actual termination node?
JRST NETS.4 ;Yes, can't do set
NETS.1: PUSHJ P,A$GBLK ;GO GET A BLOCK
CAIN T1,.ORNOD ;IS THIS THE NODE BLOCK (ALREADY DONE) ?
JRST NETS.1 ;YES,,TRY THE NEXT ONE
MOVE T3,0(T3) ;GET THE ARGUMENT DATA
CAIN T1,.STCSD ;IS IT THE CLEAR TO SEND DELAY VALUE
STORE T3,NETCSD(P1) ;YES,,SAVE IT
CAIN T1,.STDTR ;IS IT THE DATA TERMINAL READY VALUE ???
STORE T3,NETSTS(P1),NT.DTR ;YES,,SAVE IT
CAIN T1,.STRPM ;IS IT THE RECORDS PER MESSAGE VALUE ???
STORE T3,NETRPM(P1) ;YES,,SAVE IT
CAIN T1,.STSWL ;IS IT THE SILO WARNING LEVEL VALUE ???
STORE T3,NETSWL(P1) ;YES,,SAVE IT
CAIN T1,.STTOU ;IS IT THE TIMEOUT CATAGORY ???
STORE T3,NETSTS(P1),NT.TOU ;YES,,SAVE IT
CAIN T1,.STTRA ;IS IT THE TRANSPARENCY VALUE ???
STORE T3,NETSTS(P1),NT.TRA ;YES,,SAVE IT
CAIN T1,.STBPM ;IS IT BYTES PER MESSAGE ???
STORE T3,NETBPM(P1) ;YES,,SAVE IT
MOVX S1,NETSGN ;GET NODE SIGNON REQUIRED BIT
CAIN T1,.STSON ;IS SIGNON REQUIRED ???
IORM S1,NETSTS(P1) ;YES,,LIGHT THE BIT
CAIN T1,.STNSN ;IS SIGNON OPTIONAL ???
ANDCAM S1,NETSTS(P1) ;YES,,CLEAR THE BIT
$ACK (<Set for Node ^T/NETASC(P1)/ Accepted>,,,.MSCOD(M))
$RETT ;RETURN
NETS.2: $ACK(<Set for Node ^N/S1/ Ignored>,<It is Not Defined as an IBM Remote>,,.MSCOD(M))
$RETT
NETS.3: $ACK (<Set for Node ^T/NETASC(S2)/ Ignored>,<^I/0(S1)/>,,.MSCOD(M))
$RETT
NETS.4: $ACK (<Set for Node ^T/NETASC(P1)/ Ignored>,<It is a termination but not a prototype node>,,.MSCOD(M))
$RETT
>
IFE FTDN60,<JRST NODN60 > ;JUST ACK AND RETURN
SUBTTL A$MODIFY - ROUTINE TO SET THE JOBS PRIORTY
A$MODIFY: $SAVE <M,P1> ;SAVE 'M' & P1 FOR A SECOND
MOVEI S1,TMPMSG+MOD.RQ ;GET THE RDB BLOCK ADDRESS
PUSHJ P,GENRDB ;GO GENERATE THE RDB
MOVX S1,.MOPRI ;GET THE PRIORITY BLOCK TYPE
PUSHJ P,A$FNDB ;GO FIND THE PRIORITY BLOCK
JUMPF BADMSG ;IF NOT FOUND,,THATS AN ERROR
MOVE S1,0(S1) ;GET THE NEW PRIORITY
MOVEI M,TMPMSG ;POINT 'M' AT THE NEW MSG
MOVEM S1,MOD.SZ+2(M) ;SAVE THE NEW PRIORITY
MOVE S1,[MOD.SZ+3,,.QOMOD] ;GET THE MSG LENGTH AND TYPE
MOVEM S1,.MSTYP(M) ;SAVE IT
SETOM MOD.SZ+1(M) ;NO/AFTER PARAMETER
MOVEI S1,3 ;GET THE MAJOR BLOCK LENGTH
MOVEM S1,MOD.SZ(M) ;AND SAVE IT
SETZM G$ACK## ;WE DONT WANT AN ACK.
SETOM G$QOPR## ;THIS IS AN OPERATOR REQUEST
PUSHJ P,Q$MODIFY## ;GO MODIFY THE JOB PRIORTY
SETZM G$QOPR## ;RESET THE OPERATOR INDICATOR
SETZM G$RMTE## ;ZERO THE NODE WE USED (SET BY GENRDB)
SKIPG S1 ;MORE THEN 0 JOBS ???
$ACK (<No ^T/(S2)/s modified>,,,.MSCOD(M))
CAIN S1,1 ;JUST 1 JOB ???
$ACK (<1 ^T/(S2)/ modified>,,,.MSCOD(M))
CAILE S1,1 ;MORE THEN 1 JOB ???
$ACK (<^D/S1/ ^T/(S2)/s modified>,,,.MSCOD(M))
$RETT ;AND RETURN
SUBTTL A$QUEU - ENABLE/DISABLE SPECIFIC QUEUES
A$QUEU::PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVE P1,S2 ;GET THE CODE (.OMDIS/.OMENA)
MOVEI S1,.EDQUE ;GET THE MESSAGE TYPE
PUSHJ P,A$FNDB ;FIND THE BLOCK
JUMPF ILLMSG ;CAN'T FIND IT
MOVE S1,(S1) ;GET THE OBJECT TYPE
CAMN S1,[EXP -1] ;ALL QUEUES?
SKIPA S1,[-NQUEUE##,,TBLHDR##];AOBJN POINTER TO QUEUE HEADERS
PUSHJ P,A$OB2Q ;CONVERT TO QUEUE HEADER
JUMPF ILLMSG ;UNKNOWN QUEUE
PUSH P,H ;SAVE H
MOVE H,S1 ;COPY QUEUE HEADER ADDRESS
MOVX S1,QH.DIS ;GET DISABLED BIT
CAIE P1,.OMENA ;WHICH ONE?
SKIPA P2,[IORM S1,.QHTYP(H)] ;DISABLE
SKIPA P2,[ANDCAM S1,.QHTYP(H)] ;ENABLE
SKIPA P1,[[ASCIZ /disabled/]] ;DISABLE
MOVEI P1,[ASCIZ /enabled/] ;ENABLE
QUEU.1: LOAD S2,.QHTYP(H),QH.TYP ;GET QUEUE TYPE
CAIE S2,.QHTOU ;OUTPUT?
CAIN S2,.QHTIP ;INPUT?
XCT P2 ;TOGGLE BIT
JUMPG H,QUEU.2 ;DONE IF ONLY A SINGLE QUEUE
ADDI H,QHSIZE-1 ;ACCOUNT FOR MULTI-WORD ENTRIES
AOBJN H,QUEU.1 ;LOOP THROUGH ALL THE HEADERS
MOVEI S1,[ASCIZ .All input/output.]
MOVEI S2,[ASCIZ /queues are/]
JRST QUEU.3 ;GO ACK
QUEU.2: MOVE S1,.QHLQN(H) ;GET QUEUE LISTING NAME
MOVEI S2,[ASCIZ /queue is/] ;ASSUME A SINGLE QUEUE
QUEU.3: POP P,H ;RESTORE H
$ACK (<^T/(S1)/ ^T/(S2)/ ^T/(P1)/>,,,.MSCOD(M))
$RETT ;RETURN
SUBTTL A$OREQ - Operator REQUEUE Request
A$OREQ: PUSHJ P,.SAVE1 ;SAVE P1
MOVX S1,.OROBJ ;GET OBJECT BLOCK TYPE CODE
PUSHJ P,A$FNDB ;GO FIND IT IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,RETURN WITH AN ERROR
PUSHJ P,ORANGE ;CHECK FOR A RANGE
MOVE P1,S1 ;SAVE THE OBJECT BLOCK ADDRESS
MOVE S2,OBJ.UN(P1) ;GET THE UNIT NUMBER
MOVEM S2,.OHDRS+ARG.DA+OBJ.UN(M) ;SAVE IT IN THE MESSAGE
PUSHJ P,A$FOBJ ;FIND THE OBJ ENTRY
JUMPF DEVUNK ;NOT THERE,,ACK THE OPR AND RETURN
MOVE P1,S1 ;SAVE THE OBJECT QUEUE ENTRY ADDRESS
MOVE S1,OBJSCH(P1) ;GET THE SCHEDULING BITS
TXNN S1,OBSBUS ;IS THE OBJECT BUSY ???
JRST A$RQ.2 ;NO,,LET'EM KNOW AND RETURN.
SETZM OBJRID(P1) ;Prevent further NEXT processing
TXNE S1,OBSFRR ;IS THIS A FREE RUNNING DEVICE ???
JRST OREQ.3 ;YES,,JUST SEND THE MESSAGE
LOAD S1,OBJITN(P1) ;GET THE ITN
PUSHJ P,Q$SUSE## ;FIND IT IN THE USE QUEUE
SKIPT ;SKIP IF WE WON
STOPCD (RJM,HALT,,<Requeue job missing>)
MOVE AP,S1 ;SAVE THE QE ADDRESS
OREQ.1: PUSHJ P,A$GBLK ;GET FIRST/NEXT MESSAGE BLOCK
JUMPF OREQ.3 ;NO MORE,,SEND THE MSG.
CAIE T1,.ORREQ ;IS THIS THE REQUEST ID BLOCK
JRST OREQ.1 ;NO,,TRY THE NEXT ONE
LOAD S1,.QERID(AP) ;GET THE REQUEST ID
CAME S1,0(T3) ;DO WE MATCH ???
JRST A$RQ.3 ;NO,,TOUGH BREAKEEEE
JRST OREQ.1 ;YES,,CONTINUE
OREQ.3: MOVE S1,P1 ;LOAD S1 WITH OBJECT BLOCK ADDR.
PJRST SNDOAC ;GO SEND THE MSG.
A$RQ.2: $ACK (Not Active,,OBJTYP(P1),.MSCOD(M))
$RETT
A$RQ.3: $ACK (Request Id Invalid,,OBJTYP(P1),.MSCOD(M))
$RETT
SUBTTL COMMMM - OPERATOR REQUEST COMMON PROCESSING ROUTINE.
A$COMM: PUSHJ P,.SAVE1 ;SAVE P1 AND P2 FOR A MINUTE
MOVX S1,.OROBJ ;GET THE OBJECT BLOCK TYPE CODE
PUSHJ P,A$FNDB ;FIND THE OBJECT BLOCK IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,TOO BAD !!!
PUSHJ P,ORANGE ;DETERMINE OBJECT RANGE.
MOVE P1,S1 ;SAVE THE OBJECT BLOCK ADDRESS
MOVE S2,OBJ.UN(P1) ;GET THE UNIT NUMBER
MOVEM S2,.OHDRS+ARG.DA+OBJ.UN(M) ;SAVE IT IN THE MESSAGE
PUSHJ P,A$FOBJ ;FIND THE OBJECT BLOCK.
JUMPF DEVUNK ;NOT THERE,,ACK THE OPR AND RETURN
MOVE P1,S1 ;SAVE THE OBJECT QUEUE ENTRY ADDRESS
MOVX S1,OBSSTP ;GET THE 'STOPPED' STATUS BIT
LOAD S2,.MSTYP(M),MS.TYP ;GET THE MESSAGE TYPE
CAXN S2,.OMCON ;IS THE MESSAGE 'CONTINUE' ???
ANDCAM S1,OBJSCH(P1) ;YES,,TURN OFF THE 'STOP' BIT
MOVX S1,OBSBUS!OBSFCH ;[1163] PICK UP BUSY BIT AND FORMS CHANGE BIT
TDNN S1,OBJSCH(P1) ;IS THE DEVICE BUSY ???.
JRST COMM.2 ;IF NOT,, RETURN.
MOVE S1,P1 ;GET THE OBJECT ADDRESS
PUSHJ P,SNDOAC ;GO SEND THE MSG.
MOVE S1,P1 ;GET THE OBJECT ADDRESS
PUSHJ P,A$OBST ;UPDATE THE OBJECT STATUS
$RETT ;RETURN...
COMM.2: LOAD S2,.MSTYP(M),MS.TYP ;GET THE MESSAGE TYPE
CAXE S2,.OMCON ;IS THE MESSAGE 'CONTINUE' ???
JRST COMM.4 ;NO,,JUST ACK AND LEAVE
$ACK (Continued,,OBJTYP(P1),.MSCOD(M)) ;TELL THE OPERATOR
MOVE S1,P1 ;GET THE OBJECT ADDRESS
PUSHJ P,A$OBST ;UPDATE THE OBJECT STATUS
DOSCHD ;FORCE A SCHEDULING PASS
$RETT ;AND RETURN
COMM.4: $ACK (Not Active,,OBJTYP(P1),.MSCOD(M))
$RETT
SUBTTL OPERATOR COMMAND PROCESSING ROUTINES.
A$OCON: PJRST A$COMM ;PROCESS THE CONTINUE COMMAND.
A$OALI: PJRST A$COMM ;PROCESS THE ALIGN COMMAND.
A$OCAN: PJRST A$OREQ ;PROCESS THE CANCEL COMMAND.
A$OFWS: PJRST A$COMM ;PROCESS THE FORWARD SPACE COMMAND.
A$OBKS: PJRST A$COMM ;PROCESS THE BACK SPACE COMMAND.
A$OSUP: PJRST A$COMM ;PROCESS THE SUPPRESS COMMAND.
A$OSND: PUSHJ P,.SAVE1 ;SAVE P1
MOVX S1,.OROBJ ;GET THE OBJECT BLOCK TYPE
PUSHJ P,A$FNDB ;FIND THE OBJECT BLOCK IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,THATS AN ERROR
MOVE P1,S1 ;SAVE THE ADDRESS FOR A MINUTE
PUSHJ P,A$FOBJ ;FIND THE OBJECT IN OUR OBJECT QUEUE
JUMPF DEVUNK ;NOT THERE,,ACK THE OPR AND RETURN
MOVE P1,S1 ;SAVE THE OBJECT ADDRESS
MOVE S1,OBJNOD(P1) ;GET THE NODE FOR THIS OBJECT
PUSHJ P,N$NODE## ;FIND IT IN OUT DATA BASE
MOVE S1,P1 ;RESTORE THE OBJECT ADDRESS TO S1
LOAD S2,NETSTS(S2) ;GET THE NODE STATUS BITS IN S2
TXNN S2,NETIBM ;IS THIS NODE SOME FLAVOR OF DN60 ???
JRST A$COMM ;NO,,ALL THIS FOR NOTHING !!!
LOAD S2,S2,NT.MOD ;GET THIS NODES MODE OF OPERATION
CAXE S2,DF.EMU ;IS IT EMULATION ???
JRST A$COMM ;NO,,WELL WE STILL LOSE !!!
LOAD S2,OBJSCH(S1) ;SO FAR, SO GOOD - GET SCHEDULING BITS
TXNE S2,OBSSUP ;OBJECT MUST BE SETUP.IF SO HE WINS
JRST SNDOAC ;ALL THIS FOR DN60! ITS NOT WORTH IT !!
$ACK (<Not Active>,,OBJTYP(S1),.MSCOD(M))
$RETT ;JUST RETURN
A$OSHC: PJRST A$COMM ;PROCESS THE SHOW CONTROL FILE COMMAND.
SUBTTL A$OPAU - STOP OPERATOR MESSAGE PROCESSOR
A$OPAU: PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
MOVX S1,.OROBJ ;GET THE OBJECT BLOCK TYPE CODE
PUSHJ P,A$FNDB ;FIND THE OBJECT BLOCK IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,TOO BAD !!!
PUSHJ P,ORANGE ;DETERMINE OBJECT RANGE.
MOVE P1,S1 ;SAVE THE OBJECT BLOCK ADDRESS
MOVE S2,OBJ.UN(P1) ;GET THE UNIT NUMBER
MOVEM S2,.OHDRS+ARG.DA+OBJ.UN(M) ;SAVE IT IN THE MESSAGE
PUSHJ P,A$FOBJ ;FIND THE OBJECT BLOCK.
JUMPF DEVUNK ;NOT THERE,,ACK THE OPR AND RETURN
MOVE P1,S1 ;SAVE THE OBJECT QUEUE ENTRY ADDRESS
MOVE S1,.OFLAGS(M) ;GET THE MESSAGE FLAG BITS
TXNE S1,ST.ACR+ST.AER ;IS THIS AN 'IMMEDIATE' STOP ???
JRST OPAU.1 ;NO,,SKIP THIS
LOAD S1,OBJSCH(P1),OBSBUS ;IS THE DEVICE ACTIVE ???
JUMPE S1,OPAU.2 ;NO,,JUST ACK AND RETURN
MOVE S1,P1 ;GET THE OBJECT ADDRESS IN S1
PUSHJ P,SNDOAC ;SEND THE REQUEST OFF
JRST OPAU.3 ;[1202] GO SET 'STOPPED' AND UPDATE
OPAU.1: MOVX S2,OBSSER ;GET THE 'STOP AFTER EVERY REQUEST' BIT
TXNE S1,ST.AER ;DOES HE WANT EACH REQUEST STOPPED ???
IORM S2,OBJSCH(P1) ;YES,,SET THE STATUS BIT
MOVEI S2,[ASCIZ/Stop is Pending/] ;GET THE ACK TEXT
MOVX S1,OBSBUS ;GET THE ACTIVE STATUS
TDNN S1,OBJSCH(P1) ;ARE WE ACTIVE NOW ???
OPAU.2: MOVEI S2,[ASCIZ/Stopped/] ;NO,,JUST SAY STOPPED
$ACK (^T/0(S2)/,,OBJTYP(P1),.MSCOD(M)) ;ACK THE OPR
OPAU.3: MOVX S1,OBSSTP ;GET THE 'STOPPED' STATUS BIT
IORM S1,OBJSCH(P1) ;AND SET IT
MOVE S1,P1 ;GET THE OBJECT ADDRESS IN S1
PUSHJ P,A$OBST ;UPDATE THE STATUS
$RETT ;RETURN
SUBTTL A$OREL, A$OHLD - RELEASE/HOLD OPERATOR MESSAGES.
A$OREL: TXOA S1,HB.FRL ;INDICATE RELEASE ENTRY POINT.
A$OHLD: SETZ S1, ;INDICATE HOLD ENTRY POINT.
$SAVE <M,P1> ;SAVE 'M' AND P1 FOR A SECOND
MOVE P1,S1 ;SAVE THE ENTRY TYPE
MOVEI S1,TMPMSG+HBO.RQ ;GET THE RDB BLOCK ADDRESS
PUSHJ P,GENRDB ;GO CREATE THE MESSAGE RDB
MOVEI M,TMPMSG ;GET THE MSG ADDRESS IN 'M'
MOVEM P1,HBO.FL(M) ;SAVE THE TYPE FLAGS
MOVE S1,[HBO.SZ,,.QOHBO] ;GET THE MSG LENGTH,,TYPE
MOVEM S1,.MSTYP(M) ;SAVE IT
SETZM G$ACK## ;INDICATE NO ACK.
SETOM G$QOPR## ;SHOW THAT MSG IS FROM THE OPERATOR.
PUSHJ P,Q$HOLD## ;PERFORM HOLD/RELEASE
SETZM G$QOPR## ;TURN OFF THE QUEUE SEARCH FLAG.
SETZM G$RMTE## ;ZERO THE NODE WE USED (SET BY GENRDB)
MOVEI TF,[ASCIZ/held/] ;ASSUME HOLD MESSAGE.
SKIPE P1 ;CHECK FLAGS,,IF 0 WE WERE RIGHT
MOVEI TF,[ASCIZ/released/] ;ELSE MAKE IT RELEASE.
SKIPG S1 ;MORE THEN 0 JOBS ???
$ACK (<No ^T/(S2)/s ^T/@TF/>,,,.MSCOD(M))
CAIN S1,1 ;IS THERE ONLY 1 JOB ???
$ACK (<1 ^T/(S2)/ ^T/@TF/>,,,.MSCOD(M))
CAILE S1,1 ;MORE THEN 1 JOB ???
$ACK (<^D/S1/ ^T/(S2)/s ^T/@TF/>,,,.MSCOD(M))
SKIPE P1 ;IS THIS A RELEASE MSG ???
DOSCHD ;YES,,FORCE A SCHEDULING PASS
$RETT ;AND RETURN.
SUBTTL A$ODEL - ROUTINE TO REMOVE JOBS FROM THE SYSTEM QUEUES
;CALL: M/ The Operator CANCEL msg address
;
;RET: True Always
A$ODEL: $SAVE <M> ;SAVE THE INCOMMING MSG ADDRESS
MOVEI S1,TMPMSG+KIL.RQ ;GET THE RDB BLOCK ADDRESS
PUSHJ P,GENRDB ;GO CREATE THE RDB FOR THE MSG
MOVEI M,TMPMSG ;GET THE MSG ADDRESS IN 'M'
MOVE S1,[KIL.SZ,,.QOKIL] ;GET THE MSG LENGTH,,TYPE
MOVEM S1,.MSTYP(M) ;SAVE IT
SETZM G$ACK## ;NO ACK (PERIOD)
SETOM G$QOPR## ;THIS IS AN OPERATOR REQUEST
PUSHJ P,Q$KILL## ;GO DO IT !!!
SETZM G$QOPR## ;CLEAR OPR FLAG
SETZM G$RMTE## ;ZERO THE NODE WE USED (SET BY GENRDB)
SKIPG S1 ;NO JOBS KILLED !!!
$ACK (<No ^T/(S2)/s canceled>,,,.MSCOD(M))
CAIN S1,1 ;1 JOB KILLED !!!
$ACK (<1 ^T/(S2)/ canceled>,,,.MSCOD(M))
CAILE S1,1 ;MORE THE 1 JOB !!!
$ACK (<^D/S1/ ^T/(S2)/s canceled>,,,.MSCOD(M))
$RETT ;RETURN,,WE'RE DONE
SUBTTL A$ORTE - ROUTINE TO PROCESS OPERATOR ROUTE COMMAND.
A$ORTE: PUSHJ P,A$WHEEL ;IS THIS GUY A WHEEL ???
JUMPF E$IPE## ;NO,,A FRAUD !!
MOVX S1,.ORRTN ;GET THE ROUTE BLOCK TYPE
PUSHJ P,A$FNDB ;FIND THE BLOCK IN THE MESSAGE
JUMPF BADMSG ;NOT THERE,,RETURN AN ERROR
PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
MOVE P1,S1 ;SAVE THE DATA ADDRESS
MOVSI S1,RTELEN+.OHDRS ;GET THE MSG LENGTH
MOVEM S1,.MSTYP(M) ;SAVE IT IN THE MESSAGE
MOVEI S1,2 ;GET 2 BLOCKS
MOVEM S1,.OARGC(M) ;SAVE IT IN THE MESSAGE
MOVEI S2,.OHDRS(M) ;POINT TO THE FIRST BLOCK
MOVE S1,[4,,.RTEFM] ;GET THE FIRST BLOCK HEADER
MOVEM S1,ARG.HD(S2) ;SAVE IT
SETOM ARG.DA+OBJ.TY(S2) ;ALL DEVICES
SETOM ARG.DA+OBJ.UN(S2) ;ALL UNITS
LOAD S1,.SNODE-1(P1) ;GET THE SOURCE NODE NAME/NUMBER
MOVEM S1,ARG.DA+OBJ.ND(S2) ;SAVE IT
MOVEI S2,OBJ.SZ+1(S2) ;POINT TO THE NEXT BLOCK
MOVE S1,[4,,.RTETO] ;GET THE SECOND BLOCK HEADER
MOVEM S1,ARG.HD(S2) ;SAVE IT
SETOM ARG.DA+OBJ.TY(S2) ;ALL DEVICES
SETOM ARG.DA+OBJ.UN(S2) ;ALL UNITS
LOAD S1,.DNODE-1(P1) ;GET THE DESTINATION NODE NBR.
MOVEM S1,ARG.DA+OBJ.ND(S2) ;SAVE IT
PJRST N$NRTE## ;GO PERFORM THE ROUTING & RETURN
SUBTTL A$DEFINE - Routine to process the 'DEFINE' network command
;Call: M/ The message address
;Ret: TRUE always
; The purpose of this routine is to add a prototype node to the node data base.
; The current characteristics are:
; 1. If the node already exists, verify its current state. If it already
; has objects started, is online, or has devices started on the
; same port/line, thats an error.
; 2. If 1 passed, add the node to the node database.
; 3. If the node is termination, and signon is required, find the signon
; file and validate all of the actual nodes as specified in
; step 1. Also add the node to the data base as an IBM term.
; node (unless it has objects started on it, in which case
; the operator is notified of the error.)
; 4. Notify the operator of the completion of the definition.
A$DEFINE:
$SAVE <P1,P2,P3,P4> ;Save P1,P2,P3,P4 for a minute
;P1 is used for node name
;P2 is used for node entry address
;P3 is used for block header
;P4 is used for display
MOVX S1,.ORNOD ;GET THE NODE NAME BLOCK TYPE
PUSHJ P,A$FNDB ;GO FIND IT
JUMPF BADMSG ;NOT THERE,,ORION BUG !!!
MOVE S1,0(S1) ;GET THE NODE NAME
SETO S2, ;Say we want online check
MOVE P1,S1 ;Save the node name
$CALL N$CKND## ;Check out the node
JUMPF DEFBD1 ;Failed, either online or
; objects started
MOVE P2,S2 ;Remember the results of N$CKND
SETZ P4, ;Say this is a definition
SKIPN P2 ;Is it?
AOJ P4, ;No, say redefinition
; Find the DEFINE Msg Block
MOVX S1,.DFBLK ;GET THE DEFINE BLOCK TYPE
PUSHJ P,A$FNDB ;GO FIND IT
JUMPF BADMSG ;NOT THERE,,ORION ERROR
MOVEI P3,-1(S1) ;MAKE SURE WE ARE POINTING AT BLK HEADER
LOAD S1,DEF.TY(P3),DF.TPP ;Get the type
CAXN S1,DF.LAT ;Is it a LAT server?
JRST DEFLAT ;Yes, special handling
CAXN S1,DF.SRV ;SERVER?
JRST DEFSRV ;YES
IFE FTDN60,<
NODN60: $ACK (< DN60 remotes are not supported >,,,.MSCOD(M))
$RETT
>
IFN FTDN60,<
MOVE S1,P1 ;Get back the node name
MOVE S2,DEF.MD(P3) ;GET THE NODE MODE
CAXE S2,DF.TRM ;Is it termination?
JRST DEFI.1 ;No, skip this
LOAD S2,DEF.TY(P3),DF.FLG ;Get the signon flag
CAIN S2,DF.NSN ;Is no signon required?
JRST DEFI.1 ;No signon required, skip this
; Check out the prototype termination signon file
MOVE S2,P2 ;Give what we know of node address
PUSHJ P,N$SACT## ;Go check out signon file and nodes
JUMPF DEFBD1 ;Failed, tell the operator about it
MOVE P2,S2 ;Remember the entry
; Add the node to the data base if needed
DEFI.1: JUMPN P2,DEFI.2 ;Skip this if node already defined
PUSHJ P,N$NNET## ;Add the node
MOVE P2,S2 ;Remember the entry
DEFI.2: MOVE S2,DEF.MD(P3) ;Get the node mode
CAXN S2,DF.TRM ;Is it termination
MOVX S2,DF.PRO ;Yes, make it a prototype
STORE S2,NETSTS(P2),NT.MOD ;SAVE IT IN OUR DATA BASE
LOAD S2,DEF.TY(P3),DF.TPP ;Get the type of node
STORE S2,NETSTS(P2),NT.TYP ;SAVE IT IN OUR DATA BASE
MOVE S2,DEF.PT(P3) ;GET THE PORT NUMBER
STORE S2,NETPTL(P2),NT.PRT ;SAVE THE PORT NUMBER
MOVE S2,DEF.LN(P3) ;GET THE LINE NUMBER
STORE S2,NETPTL(P2),NT.LIN ;SAVE THE LINE NUMBER
; Setting defaults
; BPM--If 3780 then 512 else 400
MOVEI S1,^D400 ;Get most likely
LOAD S2,NETSTS(P2),NT.TYP ;GET THE REMOTE TYPE
CAXN S2,DF.378 ;IS IT 3780 ???
MOVEI S1,^D512 ;Yes, set it different
STORE S1,NETBPM(P2),FWMASK ;And set it
; CSD--Is always set to 3
MOVEI S1,3 ;Get the normal value
STORE S1,NETCSD(P2),FWMASK ;And set it
; RPM--If 2780 then 7 else 0
SETZ S1, ;Get most likely
CAXN S2,DF.278 ;Is it 2780 ???
MOVEI S1,7 ;Yes, set it different
STORE S1,NETRPM(P2),FWMASK ;And set it
; Timeout cat.--If proto termination, then primary else secondary
MOVEI S1,ST.SEC ;Must start somewhere
LOAD S2,NETSTS(P2),NT.MOD ;GET THE REMOTE MODE
CAXN S2,DF.PRO ;IS IT PROTO TERMINATION MODE ???
MOVEI S1,ST.PRI ;Yes, say primary
STORE S1,NETSTS(P2),NT.TOU ;And set it
; Transparancy--Always off
MOVEI S1,ST.OFF ;Set it off
STORE S1,NETSTS(P2),NT.TRA ;And set it
; Set port/line handle
MOVE S1,G$NOW## ;GET THE UDT FOR PORT/LINE HANDLE
MOVEM S1,NETIDN(P2) ;SAVE IT IN THE DATA BASE
; Say we are IBM node
MOVEI S1,1 ;GET A 1
STORE S1,NETSTS(P2),NETIBM ;LITE THE IBM NODE BIT
; Set the signon according to the define
LOAD S2,DEF.TY(P3),DF.FLG ;Get the signon flag
CAIN S2,DF.NSN ;Is signon required?
SETZ S1, ;Want to clear the bit
STORE S1,NETSTS(P2),NETSGN ;SET 'SIGNON REQUIRED' BIT
>; END IFN FTDN60
DEFGOD: $ACK (< ^T/DEFTAB(P4)/efine for node ^T/NETASC(P2)/ accepted >,,,.MSCOD(M))
$RETT ;AND RETURN
DEFLAT: JUMPN P2,DEFL.1 ;Already defined: not again
MOVE S1,P1 ;Restore the node name
PUSHJ P,N$NNET## ;Add this node
MOVE P2,S2 ;Remember the entry
DEFL.1: LOAD S2,DEF.TY(P3),DF.TPP ;Save the type of node
STORE S2,NETSTS(P2),NT.TYP ;
MOVEI S1,1 ;
STORE S1,NETSTS(P2),NETLAT ;Set the LAT server bit
HRLI S1,DEF.LA(P3) ;Source,,0
HRRI S1,NETLNM(P2) ;Source,,destination
BLT S1,NETLNM+LPTNLN-1(P2) ;Copy LAT server/service/port
JRST DEFGOD ;Send the ACK
DEFSRV: MOVE S1,P1 ;GET BACK THE NODE NAME
PUSHJ P,N$NNET## ;ADD THE NODE
MOVE P2,S2 ;REMEMBER THE ENTRY
MOVEI S1,1 ;GET A 1
STORE S1,NETSTS(P2),NETSRV ;LITE THE SERVER NODE BIT
MOVE S1,[1,,.OTLPT] ;ONE LPT
MOVEM S1,NETLPT(S2) ;SAVE
JRST DEFGOD ;GO ACK THEM
DEFBD1: $ACK(< Define for node ^N/P1/ ignored >,<^I/0(S1)/>,,.MSCOD(M))
$RETT
SUBTTL A$DN60 - ROUTINE TO SEND A OPERATOR RESPONSE TO LPTSPL
;CALL: M/ The Operator response message address
;
;RET: True Always
A$DN60:
IFN FTDN60,<
PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVX S1,.OTLPT ;GET PRINTER OBJECT TYPE
MOVEM S1,G$MSG##+OBJ.TY ;SAVE IT IN OBJECT BLOCK
SETZM G$MSG##+OBJ.UN ;WANT UNIT 0
MOVE S1,.MSCOD(M) ;GET THE NODE NAME
MOVEM S1,G$MSG##+OBJ.ND ;SAVE IT IN OBJECT BLOCK
MOVEI S1,G$MSG## ;POINT TO OUR OBJECT BLOCK
PUSHJ P,A$FOBJ ;FIND IT IN THE OBJECT QUEUE
JUMPF DN60.1 ;NOT THERE,,TELL OPERATOR AND RETURN
MOVE P1,S1 ;SAVE THE OBJECT ADDRESS
LOAD S1,OBJSCH(P1) ;GET THE OBJECT SCHEDULING BITS
TXNN S1,OBSSUP+OBSSIP ;OBJ MUST BE SETUP OR SETUP-IN-PROGRESS
JRST DN60.1 ;NO,,TELL OPERATOR AND RETURN
LOAD S1,OBJNOD(P1) ;GET THIS OBJECTS NODE NAME
PUSHJ P,N$NODE## ;FIND IT IN OUR DATA BASE
LOAD S1,NETSTS(S2),NETIBM ;GET THE DN60 FLAG BIT
JUMPE S1,DN60.1 ;NOT DN60,,TELL OPR AND RETURN
MOVE S1,P1 ;GET THE OBJECT ADDRESS
PJRST SNDOAC ;AND SEND THE MESSAGE OFF TO LPTSPL
DN60.1: $WTO(<No Operator Console for IBM Remote ^N/.MSCOD(M)/>,,,<$WTFLG(WT.SJI)>)
MOVEI S1,G$MSG## ;[1206] GET MESSAGE BUFFER ADDR
PJRST SNDOPR ;RETURN THE MSG TO ORION AND RETURN
>
IFE FTDN60,<JRST NODN60 > ;SHOULD NOT HAPPEN
SUBTTL A$DQNM - Define a Queue Name
A$DQNM::$SAVE <AP,H,E,P1,P2> ;SAVE THE AC'S
MOVX S1,.DFQNM ;GET THE BLOCK TYPE
PUSHJ P,A$FNDB ;FIND IT IN THE MESSAGE
JUMPF BADMSG ;SHOULD BE THERE
MOVEI P1,-1(S1) ;POINT AT THE BLOCK HEADER
MOVEI S1,DFQ.QN(P1) ;POINT AT THE QUEUE NAME
HRLI S1,(POINT 8) ;WE STORE THE NAME IN 8-BIT ASCII
PUSHJ P,ASCUPR ;MAKE SURE IT'S UPPER CASE
MOVEI H,HDRQNM## ;POINT AT THE QUEUE HEADER
SETZB P2,E ;ASSUME A REDEFINITION
LOAD AP,.QHLNK(H),QH.PTF ;GET POINTER TO FIRST ENTRY IN QUEUE
DQNM.1: JUMPE AP,DQNM.3 ;IF NOTHING THERE, GO CREATE AN ENTRY
MOVEI S1,DFQ.QN(P1) ;TEST STRING
MOVEI S2,QNM.QN(AP) ;BASE STRING
HRLI S1,(POINT 8) ;BOTH 8-BIT ASCII STRINGS
HRLI S2,(POINT 8)
PUSHJ P,S%SCMP ;COMPARE THE STRINGS
SKIPF ;DID IT MATCH?
JUMPE S1,DQNM.4 ;YES, IF EXACT MATCH, TAKE IT
JUMPG E,DQNM.2 ;CONTINUE IF POSITION FOUND
TXNN S1,SC%GTR ;NEW NAME GREATER THAN OLD?
MOVE E,AP ;REMEMBER POSITION IN QUEUE
DQNM.2: LOAD AP,.QELNK(AP),QE.PTN ;GET POINTER TO NEXT ENTRY
JRST DQNM.1 ;CHECK FOR THAT
DQNM.3: SKIPN DFQ.OT(P1) ;CREATING AND DELETING?
JRST DQNM.6 ;TELL FOOL TO GET STUFFED
PUSHJ P,M$GFRE## ;GET A FREE CELL
SKIPGE E ;KNOW WHERE TO PUT NEW ENTRY?
LOAD E,.QHLNK(H),QH.PTF ;STICK AT FRONT OF QUEUE
PUSHJ P,M$LINK## ;LINK IT IN
MOVEI P2,1 ;THIS IS A DEFINITION
DQNM.4: MOVSI S1,DFQ.QN(P1) ;SOURCE
HRRI S1,QNM.QN(AP) ;DESTINATION
BLT S1,QNM.QN+QNMLEN-1(AP) ;GET IT ALL
MOVE S1,DFQ.TY(P1) ;GET THE QUEUE TYPE
CAXE S1,.KYLCL ;LOCAL QUEUE?
TDZA S1,S1 ;NO, GET A ZERO
MOVX S1,QN.LCL ;YES, GET THE FLAG
MOVEM S1,QNM.FL(AP) ;STUFF FLAGS
MOVE S1,DFQ.ND(P1) ;GET THE NODE NAME
MOVEM S1,QNM.RO+.ROBND(AP) ;STUFF IT
MOVE S1,DFQ.OT(P1) ;GET THE OBJECT TYPE
MOVEM S1,QNM.RO+.ROBTY(AP) ;STUFF IT
MOVE S1,DFQ.UN(P1) ;GET THE UNIT NUMBER
MOVEI S2,%PHYCL ;ASSUME PHYSICAL
CAME S1,[EXP -1] ;ANY UNIT?
SKIPE DFQ.UT(P1) ;OR A UNIT TYPE?
MOVEI S2,%GENRC ;CALL IT GENERIC
STORE S1,QNM.RO+.ROBAT(AP),RO.UNI ;STUFF IT
STORE S2,QNM.RO+.ROBAT(AP),RO.ATR ;STUFF IT
MOVE S1,DFQ.UT(P1) ;GET THE UNIT TYPE
MOVEM S1,QNM.RO+.ROBUT(AP) ;STUFF IT
MOVE S1,QNM.RO+.ROBND(AP) ;NODE
SETZ S2, ;NO NUMBER
PUSHJ P,N$NNET## ;ADD REMOTE NODE
MOVX S1,NETNQC ;MAGICAL BIT
IORM S1,NETSTS(S2) ;MAKE UNREAL NODE
SKIPN QNM.RO+.ROBTY(AP) ;OBJECT TYPE?
JRST DQNM.5 ;DELETING QUEUE NAME
$ACK (<^T/DEFTAB(P2)/efine for network queue ^Q/QUEQUE/ accepted>,,,.MSCOD(M))
$RETT ;ALL SET
DQNM.5: $ACK (<Network queue ^Q/QUEQUE/ deleted>,,,.MSCOD(M))
PUSHJ P,M$RFRE## ;DEALLOCATE, RETURN CORE
$RETT ;RETURN
DQNM.6: $ACK (<Network queue ^Q/QUEMSG/ does not exist>,,,.MSCOD(M))
$RETT ;RETURN
QUEQUE: POINT 8,QNM.QN(AP) ;POINTER TO NAME IN QUEUE
QUEMSG: POINT 8,DFQ.QN(P1) ;POINTER TO NAME IN MSG
;ROUTINE TO CONVERT A STRING TO UPPER-CASE ASCII. CALL WITH THE
;BYTE POINTER TO THE STRING IN S1.
ASCUPR::ILDB S2,S1 ;GET A BYTE
JUMPE S2,.RETT ;DONE WHEN A NULL IS ENCOUNTERED
CAIL S2,"a" ;LOWER CASE ASCII?
CAILE S2,"z" ;...
JRST ASCUPR ;NOPE, NO SWEAT
SUBI S2,"a"-"A" ;CONVERT TO UPPER CASE
DPB S2,S1 ;STORE IT BACK
JRST ASCUPR ;LOOP
SUBTTL A$NEXT - NEXT COMMAND PROCESSOR
A$NEXT:: MOVX S1,.OROBJ ;[NXT] GET THE OBJECT BLOCK TYPE
PUSHJ P,A$FNDB ;[NXT] FIND THE OBJECT BLOCK IN THE MSG
JUMPF BADMSG ;[NXT] NOT THERE,,TOO BAD !!!
$SAVE <P1,AP> ;[NXT] SAVE P1 AND AP
MOVE P1,S1 ;[NXT] SAVE THE OBJECT BLOCK ADDRESS
PUSHJ P,GETOBJ ;[1167] [NXT] FIND OR CREATE OBJ ENTRY
JUMPF DEVUNK ;[NXT] NOT THERE,,ACK THE OPR AND RETURN
MOVE P1,S1 ;[NXT] SAVE THE OBJECT ADDRESS
MOVX S1,.ORREQ ;[NXT] GET THE REQUEST ID BLOCK
PUSHJ P,A$FNDB ;[NXT] LOCATE IT IN THE MESSAGE
JUMPF BADMSG ;[NXT] NOT THERE,,THAS AN ERROR
MOVE S1,0(S1) ;[NXT] GET THE REQUEST ID
MOVE AP,S1 ;[NXT] SAVE IT HERE FOR A SECOND
PUSHJ P,A$FREQ ;[NXT] LOCATE THE REQUEST
JUMPF NEXT.2 ;[NXT] NOT THERE,,OH WELL...
MOVE AP,S1 ;[NXT] SAVE THE QE ADDRESS
MOVE S1,OBJTYP(P1) ;GET OBJECT TYPE
CAIE S1,.OTNQC ;NETWORK QUEUE CONTROLLER?
MOVE S1,.QEROB+.ROBTY(AP) ;[NXT] GET THE REQUEST DEVICE TYPE
CAME S1,OBJTYP(P1) ;[NXT] THESE MUST MATCH !!!
JRST NEXT.3 ;[NXT] NO,,THATS AN ERROR
PUSHJ P,Q$CDEP## ;[NXT] MAKE SURE NO DEPENDIENCIES
JUMPF NEXT.4 ;[NXT] OH WELL,,WE TRIED !!!
MOVE S1,.QERID(AP) ;[NXT] GET THE REQUEST ID BACK
MOVEM S1,OBJRID(P1) ;[NXT] SAVE IT FOR THE SCHEDULER
DOSCHD ;[NXT] FORCE A SCHEDULING PASS
$ACK (<NEXT request #^D/S1/ scheduled>,,OBJTYP(P1),.MSCOD(M))
$RETT ;[NXT] RETURN
NEXT.2: $ACK (<NEXT request #^D/AP/ does not exist>,,,.MSCOD(M))
$RETT ;[NXT] RETURN
NEXT.3: $ACK (<Illegal device specified for NEXT request #^D/.QERID(AP)/>,,,.MSCOD(M))
$RETT ;[NXT] RETURN
NEXT.4: $ACK (<NEXT request #^D/.QERID(AP)/ is not schedulable>,,,.MSCOD(M))
$RETT ;[NXT] RETURN
SUBTTL A$OODB - Process a Object Type Data Message
;Call: M/Addr of message from ORION
A$OODB::LOAD S1,.MSTYP(M),MS.CNT ;GET MESSAGE SIZE
CAILE S1,.OHDRS ;IF TOO SMALL
CAILE S1,PAGSIZ ;OR TOO BIG
JRST BADMSG ;FORGET IT
ADD S1,M ;POINT TO END OF MESSAGE
PUSHJ P,.SAVE4 ;SAVE PRESERVED ACS
SETZB P3,AP ;P3 WILL GET OBJECT TYPE
;AP WILL GET SIZE OF DATA FOR ODB
MOVE P2,S1 ;SAVE END OF MESSAGE ADDR
MOVE P1,.OARGC(M) ;GET NUMBER OF ARG BLOCKS
CAIE P1,2 ;NEED 2, 1 FOR OBJ TYP, 1 FOR DATA
JRST BADMSG ;NOT ENOUGH
$CALL M%GPAG ;GET A SCRATCH PAGE
JUMPF BADMSG ;IF NO MEMORY, FORGET IT
MOVEI S2,.OHDRS(M) ;POINT TO FIRST BLOCK
$SAVE <H,AP> ;SAVE THESE TOO
SETZ H, ;ODB ARG COUNTER
;Loop thru message copying arg blocks to go into variable length ODB.
;S1 = address where to put data in scratch page, S2 = pointer into message
OODB.1: LOAD TF,ARG.HD(S2),AR.TYP ;GET ARG BLOCK TYPE
CAIE TF,.ORTYP ;OBJECT BLOCK TYPE?
JRST OODB.2 ;NO, GO COPY ARG BLOCK
;Process Object type arg block - save object type in P3
JUMPN P3,ODBERR ;ERROR IF OBJECT TYPE ALREADY FOUND
MOVE TF,ARG.DA(S2) ;GET OBJECT TYPE
CAILE TF,0 ;WITHIN RANGE?
CAILE TF,.OTMAX
JRST ODBERR ;NO, GO FREE MEMORY AND RETURN
MOVE P3,TF ;SAVE OBJECT TYPE
LOAD P4,ARG.HD(S2),AR.LEN ;GET LENGTH OF .ORTYP BLOCK
JRST OODB.3 ;GO LOOK FOR NEXT ARG BLOCK
;Process any other arg block - copy to scratch page
OODB.2: LOAD TF,ARG.HD(S2),AR.LEN ;GET ARGUMENT LENGTH
MOVE P4,TF ;SAVE IT
ADD TF,S2 ;COMPUTE END OF BLOCK
CAILE TF,(P2) ;WITHIN MESSAGE STILL?
JRST ODBERR ;NO, QUIT NOW
HRL TF,S2 ;GET SOURCE ADDRESS FOR BLT
HRR TF,S1 ;GET DESTINATION ADDRESS FOR BLT
ADD S1,P4 ;GET ENDING ADDRESS + 1 (NEXT FREE)
BLT TF,-1(S1) ;COPY ARG BLOCK
ADD AP,P4 ;COUNT UP WORDS NEEDED IN ODB
AOS H ;COUNT NUMBER OF ARGS COPIED
OODB.3: ADD S2,P4 ;POINT TO NEXT ARG BLOCK
SOJG P1,OODB.1 ;LOOP FOR ALL ARG BLOCKS
;Here when ready to copy scratch page data and object type into ODB.
JUMPE P3,ODBERR ;CAN'T DO ANYTHING WITHOUT OBJ TYPE
MOVE P1,S1 ;GET SCRATCH PAGE ADDR IN P1
TRZ P1,777 ;POINT TO START OF PAGE
MOVE P2,AP ;SAVE DATA SIZE
MOVE P4,H ;SAVE COUNT OF ARGS COPIED
MOVEI H,HDRODB## ;GET QUEUE HEADER ADDR, AP IS ALL SET
PUSHJ P,M$GFRE## ;GET ENTRY, SIZE IS ODBSIZ + (AP)
MOVEM P3,ODB.OT(AP) ;STORE OBJECT TYPE IN ODB
MOVEM P4,ODB.AC(AP) ;STORE ARG COUNT
HRL S1,P1 ;GET SOURCE ADDRESS FOR BLT
HRRI S1,ODB.DA(AP) ;GET DESTINATION ADDRESS FOR BLT
ADDI P2,ODB.DA-1(AP) ;COMPUTE ENDING ADDRESS FOR BLT
BLT S1,(P2) ;COPY DATA FROM SCRATCH PAGE TO ODB
MOVE S1,P3 ;GET OBJECT TYPE IN S1
LOAD S2,ODB.DA+ARG.HD(AP),AR.TYP ;GET ARG TYPE
PUSHJ P,FNDOAR ;SEE IF ODB EXISTS WITH SAME ARG TYPE
JUMPF OODB.4 ;IF ODB DOESN'T EXIST, SKIP OVER
PUSH P,AP ;SAVE AP
MOVE AP,S1 ;GET ODB ADDRESS
PUSHJ P,M$RFRE## ;DELINK AND RETURN MEMORY
POP P,AP ;GET POINTER TO NEW ODB BACK
OODB.4: PUSHJ P,M$ELNK## ;LINK ODB INTO QUEUE
MOVE S1,P1 ;GET SCRATCH PAGE ADDRESS
$CALL M%RPAG ;GIVE IT BACK TO GLXMEM
MOVE S1,P3 ;GET THE OBJECT TYPE
PUSHJ P,OBJNAM ;GET THE NAME STRING ASSOCIATED
PUSH P,S1 ;SAVE STRING ADDRESS
LOAD S1,ODB.DA+ARG.HD(AP),AR.TYP ;GET ARG TYPE
PUSHJ P,ARGNAM ;GET ARG NAME STRING ADDRESS
POP P,S2 ;GET OBJECT NAME STRING ADDR BACK
$ACK (<^T/(S1)/ defined for all ^T/(S2)/s>,,,.MSCOD(M))
;Look in PSB queue for processors that handle object type in P3.
$CALL M%GPAG ;GET A PAGE FOR PID STACK
PUSH P,S1 ;SAVE PAGE ADDRESS
ADD S1,[-100,,-1] ;SHOULD BE BIG ENOUGH STACK
PUSH S1,[-1] ;END OF STACK MARKER
MOVE S2,P3 ;GET OBJECT TYPE
PUSHJ P,STKPSB ;GET PIDS ON STACK FROM PSB QUEUE
;Send ODB messages to processors whose PIDs are on stack pointed to by S1.
MOVE P1,S1 ;GET STACK POINTER IN SAFE AC
OODB.5: POP P1,S2 ;GET POTENTIAL PID
CAMN S2,[-1] ;END OF STACK MARKER?
JRST OODB.6 ;YES, GO CLEAN UP
MOVE S1,AP ;GET ODB POINTER
PUSHJ P,SNDODB ;GO SEND MESSAGE TO PROCESSOR
JRST OODB.5 ;LOOP FOR NEXT PSB
OODB.6: POP P,S1 ;GET STACK PAGE ADDRESS BACK
$CALL M%RPAG ;LET IT GO
$RETT ;RETURN
ODBERR: TRZ S1,777 ;GET PAGE ADDRESS AGAIN
$CALL M%RPAG ;RETURN IT
JRST BADMSG ;COMPLAIN
SUBTTL OBJNAM - Find Object Name
;Call: S1/ object type (.OTxxx)
;
;Ret: S1/ address of ASCIZ object name
OBJNAM::CAILE S1,0 ;IN RANGE?
CAILE S1,.OTMAX
$RETF ;NO
PUSHJ P,.SAVE1 ;SAVE P1
MOVSI P1,-.OTMAX ;MAKE AOBJN POINTER
HRRI P1,ONMTAB ;GET OBJECT NAME TABLE
OBJN.1: MOVE S2,(P1) ;GET TABLE ENTRY
CAIE S1,(S2) ;OBJECT TYPES MATCH?
AOBJN P1,OBJN.1 ;NO, GOT TO BE THERE
HLRZ S1,S2 ;YES, GET ADDRESS OF ASCIZ STRING
$RETT ;RETURN
DEFINE X (TYP,TXT) <
XWD [ASCIZ\'TXT\],TYP
>
ONMTAB:: OBJCTS ;GENERATE TABLE (OBJCTS IN GLXMAC)
;ARGNAM - Find argument name string for ODB message ACKs.
;
;Call: S1/ arg type (.ORxxx) (must be in ARGTAB below.)
;Ret: TRUE S1/ string address or address of "Unknown"
ARGNAM: PUSHJ P,.SAVE1 ;SAVE P1
MOVEI P1,ARGTAB ;GET TABLE ADDRESS
ARGN.1: SKIPN S2,(P1) ;ANYTHING THERE
JRST ARGN.2 ;NO, NO MATCH FOUND
CAIE S1,(S2) ;ARG TYPES MATCH?
AOJA P1,ARGN.1 ;NO, LOOP
HLRZ S1,S2 ;YES, GET ARG NAME STRING ADDRESS
$RETT
ARGN.2: MOVEI S1,[ASCIZ\Unknown argument\] ;GET 'DUNNO' STRING
$RETT
ARGTAB: [ASCIZ\Default network PPN\],,.ORDPP
[ASCIZ\Rejection list\],,.ORREJ
0
SUBTTL FNDODB & FNDOAR & SNDODB
;FNDODB - Look for ODB for a specified object type
;
;Call: S1/ object type
;Ret: TRUE S1/ entry addr
; FALSE means none found
;
;NXTODB - Get next ODB in queue for a specified object type
;
;Call: S1/Address of current ODB
; S2/Object type
;Ret: TRUE S1/Address of next ODB with specified object type
; FALSE no more
FNDODB: $SAVE <H> ;SAVE H
MOVEI H,HDRODB## ;GET QUEUE HEADER FOR ODB
MOVE S2,S1 ;GET OBJECT TYPE IN S2
LOAD S1,.QHLNK(H),QH.PTF ;GET 1ST ENTRY ADDRESS
FNDO.1: JUMPE S1,.RETF ;IF EMPTY, NOT THERE
CAMN S2,ODB.OT(S1) ;OBJECT TYPES MATCH?
$RETT ;YES, RETURN TRUE
NXTODB: LOAD S1,.QELNK(S1),QE.PTN ;GET POINTER TO NEXT ODB
JRST FNDO.1 ;LOOP
;FNDOAR - Find ODB for a specified object type and arg type
;
;Call: S1/ abject type
; S2/ arg type
;Ret: TRUE S1/ODB address
; FALSE None found
FNDOAR: $SAVE <T1,T2> ;SAVE T1 & T2
DMOVE T1,S1 ;SAVE OBJECT AND ARG TYPES
PUSHJ P,FNDODB ;GET 1ST ODB FOR OBJECT TYPE
$RETIF ;RETURN IF NONE FOUND
FNDA.1: LOAD TF,ODB.DA+ARG.HD(S1),AR.TYP ;FOUND ODB, GET ARG TYPE
CAIN TF,(T2) ;ONE WE WANT?
$RETT ;RETURN WITH S1 POINTING TO ODB
MOVE S2,T1 ;GET OBJECT TYPE IN S2, S1 IS SETUP
PUSHJ P,NXTODB ;LOOK FOR NEXT ODB FOR OBJECT TYPE
JUMPT FNDA.1 ;CHECK ARG TYPES IF ODB FOUND
$RETF ;RETURN FALSE IF NONE FOUND
;SNDODB - Send ODB message to processor
;
;Call: S1/ ODB address
; S2/ processor PID
;Ret: TRUE always
SNDODB: $SAVE <P1> ;SAVE P1
MOVE P1,S1 ;COPY ODB ADDRESS
MOVEM S2,G$SAB##+SAB.PD ;PUT PID IN SAB
$CALL M%GPAG ;GET A PAGE OF FOR MESSAGE
MOVEM S1,G$SAB##+SAB.MS ;SAVE ADDRESS ON SAB
LOAD S2,.QEVSZ(P1),QE.VSZ ;GET SIZE OF DATA BLOCK IN ODB
ADDI S2,.OHDRS+ARG.SZ ;ADD IN HEADER PLUS 1 ARG BLOCK
STORE S2,.MSTYP(S1),MS.CNT ;SAVE IN MESSAGE
MOVEM S2,G$SAB##+SAB.LN ;IN SAB TOO
MOVX S2,.QOODB ;GET MESSAGE TYPE
STORE S2,.MSTYP(S1),MS.TYP ;SAVE IN MESSAGE
MOVE S2,ODB.AC(P1) ;GET ARG COUNT IN DATA
MOVEI S2,1(S2) ;ADD ONE FOR ARG BLOCK TO BUILD
MOVEM S2,.OARGC(S1) ;PUT IN MESSAGE HEADER
SETZM .MSFLG(S1) ;NO FLAGS
SETZM .OFLAG(S1)
MOVE S2,.MSCOD(M) ;GET AN OPR'S ACK CODE
MOVEM S2,.MSCOD(S1) ;LET SPOOLER TALK TO SOMEONE
MOVE S2,[2,,.ORTYP] ;OBJECT TYPE ARG BLOCK HEADER WORD
MOVEM S2,.OHDRS+ARG.HD(S1) ;STORE ARE 1ST ARG BLOCK HEADER
MOVE S2,ODB.OT(P1) ;GET OBJECT TYPE
MOVEM S2,.OHDRS+ARG.DA(S1) ;PUT OBJECT TYPE IN ARG BLOCK
HRLI TF,ODB.DA(P1) ;GET START OF DATA TO COPY
HRRI TF,.OHDRS+ARG.SZ(S1) ;GET WHERE TO COPY IT
LOAD S2,.MSTYP(S1),MS.CNT ;GET MESSAGE LENGTH
ADD S2,S1 ;POINT TO END+1
BLT TF,-1(S2) ;COPY TO END OF MESSAGE
SETZM G$SAB##+SAB.SI ;NO SPECIAL PID INDEX
MOVE P1,S1 ;SAVE PAGE ADDRESS
PUSHJ P,C$SEND## ;SEND IT OFF
MOVE S1,P1 ;GET IT BACK
$CALL M%RPAG ;GIVE PAGE BACK
$RETT
SUBTTL STKPSB - Stack PIDs of Processors for an Object
;STKPSB - Routine to stack the PIDs of processors that can handle
; a specfied object type.
;
;Call: S1/ stack pointer to PID stack
; S2/ object type
;
;Ret: TRUE always
STKPSB: $SAVE <P1,P2,P3> ;SAVE SOME ACS
LOAD P1,HDRPSB##+.QHLNK,QH.PTF ;GET 1ST PSB ADDRESS
STKP.1: JUMPE P1,.RETT ;RETURN WHEN NO MORE
LOAD P2,PSBFLG(P1),PSFNOT ;GET NUMBER OF OBJECTS PROCESSOR HANDLES
JUMPE P2,STKP.3 ;PARANOIA CHECK
MOVNS P2
HRLZS P2
HRRI P2,PSBOBJ(P1) ;BUILD AOBJN POINTER
STKP.2: LOAD P3,(P2),HELOBJ ;GET OBJECT TYPE
CAIN S2,(P3) ;OBJECT TYPES MATCH?
PUSH S1,PSBPID(P1) ;YES, PUT PID ON STACK
AOBJN P2,STKP.2 ;LOOP FOR ALL OBJECTS SUPPORTED
STKP.3: LOAD P1,.QELNK(P1),QE.PTN ;GET POINTER TO NEXT PSB
JRST STKP.1 ;CONTINUE
SUBTTL SNDOAC -- Send an Operator Action Message
;CALL: S1/ADDR OF OBJECT BLOCK
; M/ADDR OF MSG TO BE SENT
SNDOPR: TDZA S2,S2 ;INDICATE SEND ORION ENTRY POINT
SNDOAC: SETOM S2 ;INDICATE SEND PROCESSOR ENTRY POINT
$SAVE <AP,T2,T3> ;SAVE AP, T2 AND T3
DMOVE T2,S1 ;SAVE OBJ BLK ADDR AND ENTRY POINT FLAG
PUSHJ P,M%ACQP ;GET A PAGE.
PG2ADR S1 ;CONVERT TO AN ADDRESS.
MOVEM S1,G$SAB##+SAB.MS ;SAVE IT IN THE SAB
LOAD T1,.MSTYP(M),MS.CNT ;GET THE MSG LENGTH.
ADD T1,S1 ;CALC BLT END ADDRESS.
HRL S1,M ;GEN BLT AC.
BLT S1,-1(T1) ;COPY MSG OVER.
MOVX S1,PAGSIZ ;GET THE PAGE LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
MOVE S1,OBJPID(T2) ;GET THE PID
SKIPN T3 ;IS THIS A SEND TO OPR
MOVE S1,G$OPR## ;YES,,GET ORIONS PID
MOVEM S1,G$SAB##+SAB.PD ;SAVE IT IN THE SAB
PJRST C$SEND## ;SEND THE MESSAGE
SUBTTL Global Routines
;THE FOLLOW ARE ADDITIONAL GLOBAL ROUTINES FOUND IN THIS MODULE
; OTHER THAN THE TOP-LEVEL MESSAGE HANDLERS.
INTERN A$KLPD ;KILL OFF A PSB GIVEN ITS PID
INTERN A$FPSB ;FIND A PSB GIVEN A PID
INTERN A$GPSB ;FIND A GENERIC PSB IN THE PSB CHAIN
INTERN A$LPSB ; " " " " " " " " "
INTERN A$FQNM ;FIND A QUEUE NAME ENTRY
INTERN A$FOBJ ;FIND AN OBJECT
INTERN A$CPOB ;COPY OVER AN OBJECT BLOCK
INTERN A$FREQ ;FIND A REQUEST VIA REQUEST ID
INTERN A$OB2Q ;CONVERT OBJECT TYPE TO QUE HEADER
INTERN A$OBST ;UPDATE OBJECT STATUS
INTERN A$GBLK ;BREAK DOWN BLOCK TYPE IPCF MESSAGES
SUBTTL A$KLPD -- Routine to kill a PSB given its PID
;A$KLPD IS CALLED TO "KILL" A PSB ENTRY. A$KLPD IS CALLED
; WITH THE PID OF THE PSB TO BE KILLED (E.G. WHEN A SEND TO
; A KNOWN COMPONENT FAILS WITH "UNKNOWN PID").
;
;CALL WITH ARGUMENT IN S1
A$KLPD: $SAVE AP ;SAVE CALLERS REGISTERS
$SAVE H ; ""
SETZM S2 ;DON'T USE NAME
PUSHJ P,A$FPSB ;FIND THE PSB GIVEN THE PID
JUMPE S1,.RETT ;RETURN IF NOT THERE
PJRST KILPSB ;KILL THE PSB ENTRY AND RETURN
SUBTTL A$FPSB -- Subroutine to find a PSB
;A$FPSB - Find a PSB given a PID or a processor name
;
; Call: S1/ PID or 0 or -1
; S2/ processor name or 0
; S1 can't be 0 or -1 when S2 is 0
;
; When S2 contains a name, S1 = 0 means find PSB that matches
; name and when S1 = -1, find PSB that matches name regardless
; of PID.
;
; Return TRUE S1/ PSB address
; FALSE S1/ 0
A$FPSB: $SAVE <T1> ;NEED AN AC
CAME S1,[EXP -1] ;CHECK ARGS
SKIPN S1
JUMPE S2,.RETF ;BAD ARGS, A LOSER
MOVE T1,S1 ;COPY PID ARG
MOVEI H,HDRPSB## ;ADDRESS OF PSB QUEUE HEADER
LOAD S1,.QHLNK(H),QH.PTF ;GET ADDRESS OF FIRST
FPSB.1: JUMPE S1,.RETF ;RETURN IF LAST ONE (OR NONE)
CAME T1,[EXP -1]
SKIPN T1
JRST FPSB.2 ;IF NO PID, CHECK NAME
CAMN T1,PSBPID(S1) ;PID MATCH?
$RETT ;YES, RETURN PSB ADDRESS IN S1
JRST FPSB.3 ;NO, GO TRY NEXT PSB
FPSB.2: CAME S2,PSBNAM(S1) ;NAME MATCH?
JRST FPSB.3 ;NO, GET NEXT PSB
JUMPL T1,.RETT ;YES, RETURN IF DON'T CARE ABOUT PID
SKIPN PSBPID(S1) ;WE DO CARE. PID THERE?
$RETT ;NO, RETURN WITH ADDRESS IN S1
FPSB.3: LOAD S1,.QELNK(S1),QE.PTN ;GET POINTER TO NEXT
JRST FPSB.1 ;AND LOOP
SUBTTL A$GPSB - ROUTINE TO FIND A PSB IN THE PSB CHAIN
; A$LPSB - " " " " " " " " " "
;CALL: S1/ The Object Type
; S2/ The Attributes
;
;RET: S1/ The PSB Address
A$LPSB: TDZA TF,TF ;FLAG 'LPSB' ENTRY POINT
A$GPSB: SETOM TF ;FLAG 'GPSB' ENTRY POINT
PUSHJ P,.SAVE3 ;SAVE P1 - P3
DMOVE P1,S1 ;SAVE THE OBJECT TYPE AND ATTRIBUTES
MOVE P3,TF ;SAVE THE ENTRY POINT INDICATOR
LOAD S1,HDRPSB##+.QHLNK,QH.PTF ;GET THE FIRST ENTRY
SKIPA ;SKIP OVER THE LOAD NEXT PSB
GPSB.1: LOAD S1,.QELNK(S1),QE.PTN ;GET THE NEXT PSB IN THE CHAIN
JUMPE S1,.RETF ;NOT FOUND,,RETURN
LOAD S2,PSBFLG(S1),PSFSTS ;GET PSB STATUS
CAXE S2,PS.RUN ;PROCESSOR "RUNNING"?
JRST GPSB.1 ;NO, TRY NEXT
LOAD S2,PSBFLG(S1),PSFNOT ;GET THE OBJECT COUNT
MOVNS S2 ;NEGATE IT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,PSBOBJ(S1) ;CREATE OBJECT SEARCH AC
LOAD TF,0(S2),HELOBJ ;GET THE OBJECT TYPE
CAME TF,P1 ;DO WE MATCH ???
GPSB.2: AOBJN S2,.-2 ;NO,,TRY NEXT
JUMPGE S2,GPSB.1 ;NO MATCH,,TRY NEXT PSB
LOAD TF,0(S2),HELATR ;GET THE OBJECT ATTRIBUTES
CAME TF,P2 ;DO THEY MATCH ???
JRST GPSB.2 ;NO,,TRY NEXT OBJECT
JUMPE P3,.RETT ;NO SETUP CHECK,,RETURN
LOAD TF,PSBLIM(S1),PSLCUR ;GET THE CURRENT SETUP COUNT
LOAD S2,PSBLIM(S1),PSLMAX ;GET THE MAX SETUP COUNT
CAML TF,S2 ;ALL USED UP ???
JRST GPSB.1 ;YES,,TRY NEXT PSB
$RETT ;NO,,RETURN THIS PSB
SUBTTL A$WPSB - Find/Create a "waiting" PSB for an object
;A$WPSB - This routine will find a PSB in the PSB queue that is already
; "waiting" for the object processor to be "fired up" or say "hello".
; If a PSB is not found, one is created with a PS.FIR (to be
; "fired up") status.
;
; Call: S1/ address of object's CJB
;
; Return: TRUE "waiting" PSB was found
; FALSE to be "fired up" PSB was created
;
; Either return:
; S1/ address of CJB passed in call
; S2/ address of PSB
A$WPSB::LOAD S2,HDRPSB##+.QHLNK,QH.PTF ;GET ADDRESS OF FIRST PSB
WPSB.1: JUMPE S2,WPSB.3 ;IF NONE, GO START ONE
MOVE TF,CJB.NM(S1) ;GET PROCESSOR NAME
CAME TF,PSBNAM(S2) ;NAMES MATCH?
JRST WPSB.2 ;NO, GO LOOK AT NEXT PSB
LOAD TF,PSBFLG(S2),PSFSTS ;YES, GET PROCESSOR'S STATUS
CAXE TF,PS.WAT ;FIRE UP IN PROGRESS?
CAXN TF,PS.KSY ;OR WAITING FOR BATCON AT KSYS?
$RETT ;YES, GOT WHAT WE WANT
CAXN TF,PS.FIR ;NEEDS TO BE "FIRED UP"?
$RETT ;YES, ANOTHER WINNER
WPSB.2: LOAD S2,.QELNK(S2),QE.PTN ;MUST BE RUNNING
JRST WPSB.1 ;LOOP
;Here to create a PSB and set it up so processor is fired up
WPSB.3: PUSH P,S1 ;SAVE CJB ADDRESS
SETZB S1,S2 ;CLEAR S1 AND S2
PUSHJ P,GETPSB ;GET A NEW PSB FOR US
MOVE S2,S1 ;GET PSB ADDRESS IN S2
POP P,S1 ;GET CJB ADDRESS BACK IN S1
MOVE TF,CJB.NM(S1) ;GET PROCESSOR NAME
MOVEM TF,PSBNAM(S2) ;PUT PROCESSOR NAME IN PSB
MOVX TF,PS.FIR ;SET NEEDS TO BE FIRED UP STATUS
STORE TF,PSBFLG(S2),PSFSTS
$RETF ;DONE
SUBTTL A$APSB - Adjust PSB Object/Attribute parameters
; Call: MOVE S1, [attrributes,,object-type]
; MOVE S2, PSB address
; PUSHJ P,A$APSB
A$APSB::PUSHJ P,.SAVE2 ;SAVE P1 AND P2
DMOVE P1,S1 ;COPY ARGUMENTS
LOAD S1,PSBFLG(P2),PSFNOT ;GET THE OBJECT COUNT
MOVNS S1 ;NEGATE
MOVSS S1 ;PUT IN LH
HRRI S1,PSBOBJ(P3) ;MAKE AN AOBJN POINTER
CAME P1,(S1) ;MATCH?
AOBJN S1,.-1 ;NO--TRY THE NEXT
JUMPL S1,.RETT ;RETURN IF FOUND
LOAD S2,PSBFLG(P2),PSFNOT ;GET OBJECT COUNT AGAIN
ADDI S2,1 ;GOING TO ADD ANOTHER OBJECT/ATTRIB
CAIL S2,OBPRSZ ;TOO MANY?
JRST APSB.1 ;YES
STORE S2,PSBFLG(P2),PSFNOT ;UPDATE COUNT
MOVEM P1,(S1) ;SAVE NEW OBJECT/ATTRIBUTE COMBINATION
$RETT ;AND RETURN
APSB.1: $WTO (<Object/Attribute count exceeded>,<^I/APSB.2/>,OBJTYP(P1))
$RETF ;RETURN
APSB.2: ITEXT (<Program: ^W6L /PSBNAM(P1)/ PID: ^12R0/PSBPID(P1)/>)
SUBTTL A$FRMC - Send a forms change request
;CALL: S1/ The object block address
A$FRMC:: PUSHJ P,.SAVE1 ;Save p1
MOVE P1,S1 ;Save the object address
SKIPN S1,OBJPID(P1) ;Get the processors pid
$RETT ;None,,return
MOVEM S1,G$SAB##+SAB.PD ;Save it
MOVX S1,.OHDRS+OBJ.SZ+1 ;Get the message length
MOVEM S1,G$SAB##+SAB.LN ;Save it
STORE S1,G$MSG##+.MSTYP,MS.CNT ;Here also
MOVX S1,.QOFCH ;Get the message type
STORE S1,G$MSG##+.MSTYP,MS.TYP ;Save it
SETZM G$MSG##+.MSCOD ;No ack code
SETZM G$MSG##+.MSFLG ;No flags yet
MOVEI S1,1 ;Get 1 block count
MOVEM S1,G$MSG##+.OARGC ;Save it
MOVE S1,OBJPRM+.OOFRM(P1) ;Get the forms type
MOVEM S1,G$MSG##+.OFLAG ;Save it
MOVE S1,[OBJ.SZ,,.OROBJ] ;Get the object block header
MOVEM S1,G$MSG##+.OHDRS+ARG.HD ;Save it
MOVEI S1,G$MSG##+.OHDRS+ARG.DA ;Get object block data address
HRLI S1,OBJTYP(P1) ;Get source obj blk address
BLT S1,G$MSG##+.OHDRS+ARG.DA+OBJ.SZ-1 ;Copy the obj blk over
MOVEI S1,G$MSG## ;Get the message address
MOVEM S1,G$SAB##+SAB.MS ;Save it
SETZM G$SAB##+SAB.SI ;No special pid index
PUSHJ P,C$SEND## ;Send the message off
JUMPF .RETT ;Failed,,return
MOVX S1,OBSFCH ;[1163] Get the 'forms change' bit
IORM S1,OBJSCH(P1) ;lite it
MOVX S1,OBSFRM ;Get forms change flag
ANDCAM S1,OBJSCH(P1) ;Clear them
MOVE S1,P1 ;Get the object address
PUSHJ P,A$OBST ;Update the status
$RETT ;Return
SUBTTL A$FOBJ -- Find an entry in the object queue
;CALL: S1/ An Object Block Address
;
;RET: S1/ The address that object queue entry or false
A$FOBJ: PUSHJ P,.SAVET ;SAVE THE 'T' ACS
MOVE T1,OBJ.TY(S1) ;GET THE MODEL OBJECT TYPE
MOVE T2,OBJ.UN(S1) ;GET THE MODEL OBJECT UNIT
MOVE T3,OBJ.ND(S1) ;GET THE MODEL OBJECT NODE
LOAD T4,HDROBJ##+.QHLNK,QH.PTF ;GET THE FIRST OBJECT ENTRY
SKIPA ;SKIP THE FIRST TIME THROUGH
FOBJ.1: LOAD T4,.QELNK(T4),QE.PTN ;GET THE NEXT OBJECT ENTRY ADDRESS
JUMPE T4,.RETF ;IF NO ENTRIES OR END, RETURN
CAMN T1,OBJTYP(T4) ;DO OBJECT TYPES MATCH ???
CAME T2,OBJUNI(T4) ;DO OBJECT UNITS MATCH ???
JRST FOBJ.1 ;NO TO EITHER,,TRY NEXT OBJECT
MOVE S1,T3 ;GET THE MODEL OBJECT NODE NAME/NUMBER
MOVE S2,OBJNOD(T4) ;GET THE SOURCE OBJECT NODE NAME/NUMBER
PUSHJ P,N$MTCH## ;DO THEY MATCH ???
JUMPF FOBJ.1 ;NO,,TRY NEXT OBJECT IN THE QUEUE
MOVE S1,T4 ;GET THE OBJECT QUEUE ENTRY ADDRESS
$RETT ;AND RETURN
SUBTTL A$FQNM -- Find a queue name entry
;CALL: S1/ Pointer to a queue name
;
;RET: S1/ The entry address if found, false otherwise
A$FQNM: $SAVE <AP,P1> ;GRAB A FEW FREE AC'S
HRLI S1,(POINT 8) ;SET BYTE POINTER FOR 8-BIT ASCII
MOVE P1,S1 ;COPY THE NAME POINTER
LOAD AP,HDRQNM##+.QHLNK,QH.PTF ;GET POINTER TO FIRST QUE NAME ENTRY
FQNM.1: JUMPE AP,.RETF ;RETURN FALSE IF END OF NAMES
MOVE S1,P1 ;GET POINTER TO BASE STRING
MOVEI S2,QNM.QN(AP) ;GET ADDRESS OF TEST STRING
HRLI S2,(POINT 8) ;IT'S 8-BIT ASCII
PUSHJ P,S%SCMP ;COMPARE THE STRINGS
JUMPN S1,FQNM.2 ;ONLY ACCEPT EXACT MATCH
MOVE S1,AP ;COPY THE ENTRY ADDRESS
$RETT ;TRUE RETURN
FQNM.2: LOAD AP,.QELNK(AP),QE.PTN ;GET POINTER TO NEXT ENTRY
JRST FQNM.1 ;LOOP
SUBTTL A$CPOB -- Copy an object block
;A$CPOB IS CALLED TO COPY AN OBJECT BLOCK OVER TO A NEW BLOCK
;
;CALL: S1/ ADDRESS OF SOURCE OBJECT BLOCK
; S2/ ADDRESS OF DESTINATION OBJECT BLOCK
A$CPOB: PUSHJ P,.SAVE1 ;SAVE P1
HRLZ P1,S1 ;GET THE SOURCE OBJECT BLOCK ADDRESS
HRR P1,S2 ;GET THE DESTINATION OBJECT BLOCK ADD.
BLT P1,OBJ.SZ-1(S2) ;MOVE THE OBJECT BLOCK
$RETT ;AND RETURN
SUBTTL A$FREQ - ROUTINE TO FIND A REQUEST IN ANY QUEUE VIA REQUEST ID
;CALL: S1/ The Request ID
;
;RET: S1/ The .QE Address if Found, False Otherwise
A$FREQ: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVE P1,S1 ;SAVE THE REQUEST ID
HRLZI P2,-NOBJS ;CREATE AOBJN SEARCH AC
FREQ.1: MOVE S1,PROQUE(P2) ;GET A PROCESSING QUEUE HDR ADDRESS
LOAD S1,.QHLNK(S1),QH.PTF ;GET THE FIRST QUEUE ENTRY
FREQ.2: JUMPE S1,FREQ.3 ;NO MORE,,TRY NEXT QUEUE
CAMN P1,.QERID(S1) ;IS THIS THE REQUEST WE WANT ???
$RETT ;YES,,RETURN
LOAD S1,.QELNK(S1),QE.PTN ;GET THE NEXT QUEUE ENTRY
JUMPN S1,FREQ.2 ;AND GO CHECK IT OUT
FREQ.3: AOBJN P2,FREQ.1 ;NOT IN THIS QUEUE,,TRY NEXT
$RETF ;REQUEST IS NOT IN THE SYSTEM !!!
SUBTTL A$OB2Q -- Convert object type to queue header
;A$OB2Q IS CALLED TO CONVERT AN OBJECT TYPE INTO THE ADDRESS OF THE
; QUEUE HEADER FOR THAT OBJECT.
;
;CALL: S1/ OBJECT TYPE
;
;T RET: S1/ ADDRESS OF QUEUE HEADER (HDRXXX)
;
;F RET: NO SUCH OBJECT
A$OB2Q: PUSHJ P,.SAVE1 ;SAVE P1
HRLZI P1,-NOBJS ;MAKE AOBJN POINTER TO TABLE
MOVE S2,S1 ;PUT OBJECT TYPE INTO S2
OB2Q.1: CAMN S2,OBJTAB(P1) ;IS THIS OBJECT A MATCH?
JRST OB2Q.2 ;WIN!!!!
AOBJN P1,OB2Q.1 ;LOOP
$RETF ;NOT FOUND, RETURN FAILURE
OB2Q.2: LOAD S1,PROQUE(P1) ;GET THE QUEUE HEADER ADDRESS
$RETT ;AND RETURN
;NOW GENERATE THE TABLE OF QUEUE HEADER ADDRESSES PARALLEL TO OBJTAB
DEFINE X(OBJ,QUE,PARM),<
EXP HDR'QUE'##
> ;END DEFINE X
PROQUE: MAPOBJ
SUBTTL A$OBST -- Update Object Status
;A$OBST should be called whenever the status of an object changes so that
; the operator status changes.
;
;Call: S1/ address of OBJ entry
;
;T Ret: always
A$OBST: PUSHJ P,.SAVE1 ;SAVE P1
MOVE P1,S1 ;GET THE OBJECT ADDRESS
MOVX S1,%IDLE ;DEFAULT TO 'IDLE'
MOVE S2,OBJSCH(P1) ;GET THE SCHEDULING BITS
TXNE S2,OBSIGN ;ARE WE IGNORING THE OBJECT ???
MOVX S1,%NAVAL ;YES,,GET 'NOT AVAILABLE' CODE
TXNN S2,OBSHUT ;IS IT IN 'INTERNAL SHUTDOWN' STATE ???
TXNE S2,OBSFRR ;OR IS IT A FREE RUNNING DEVICE ???
MOVX S1,%IDLE ;YES,,ITS IDLE !!!!
TXNN S2,OBSSTA ;IS THE OBJECT STARTED ???
MOVX S1,%NSTRT ;NO,,GET THE 'NOT STARTED' CODE
TXNE S2,OBSBUS ;IS THE OBJECT BUSY ???
MOVX S1,%ACTIV ;YES,,GET THE 'ACTIVE' CODE
TXNE S2,OBSSTP ;IS THE DEVICE STOPPED ???
MOVX S1,%STOPD ;YES,,GET THE 'STOPPED' CODE
TXC S2,OBSBUS+OBSSTP ;ARE WE ACTIVE & STOPPED ???
TXNN S2,OBSBUS+OBSSTP ;LETS CHECK !!!
MOVX S1,%STPPN ;YES,,THEN STOPPED PENDING
TXNE S2,OBSSEJ ;IS IT SHUT DOWN AT END OF JOB ???
MOVX S1,%SHUTD ;YES,,GET 'SHUTTING DOWN' CODE
TXNE S2,OBSFCH ;[1166] CHANGING FORMS?
MOVX S1,%FRMCH ;[1163] YES,,GET 'CHANGING FORMS' STATUS
MOVEM S1,OBJSTS(P1) ;SAVE THE DEVICE STATUS
$RETT ;AND RETURN
SUBTTL A$STATUS - UPDATE THE DEVICE STATUS
;CALL: M/STATUS UPDATE MESSAGE ADDRESS
;
;RET: TRUE ALWAYS
;
;ERRORS: E$SNY FOR ANY VALIDATION ERRORS
A$STATUS::
PUSHJ P,.SAVE2 ;SAVE P1 & P2
LOAD P2,.MSTYP(M),MS.CNT ;GET MESSAGE SIZE
CAIGE P2,STU.SZ ;AT LEAST MINIMUM LENGTH?
PJRST E$MTS## ;NO
PUSHJ P,A$WHEEL ;MAKE SURE MSG HAS PRIVS
JUMPF E$SNY## ;NO,,TOUGH BREAKEEE
MOVEI S1,STU.RB(M) ;GET THE OBJECT BLOCK ADDRESS
PUSHJ P,A$FOBJ ;GO FIND THE OBJECT
JUMPF E$SNY## ;NOT THERE,,THATS NO GOOD !!
MOVE P1,S1 ;PUT THE OBJ ADDRESS INTO P1
MOVE S1,OBJPID(P1) ;GET THE CONTROLLING PID
CAME S1,G$SND## ;IS IT THE SAME GUY ???
JRST E$SNY## ;NO,,BETTER LUCK NEXT TIME !!
MOVE S1,STU.CD(M) ;GET THE DEVICE STATUS CODE
JUMPLE S1,E$SNY## ;MUST BE GREATER THEN 0
CAILE S1,%STMAX ;MUST ALSO BE LESS THEN MAX STATUS CODE
JRST E$SNY## ;ELSE HE LOSES !!
HRRZ S2,OBJCDS(S1) ;PICK UP THE OBJ TYPE LIST ADDRESS
JUMPE S2,STAT.2 ;IF 0,,THEN THIS CODE IS GOOD FOR ALL
HLRZ T1,OBJCDS(S1) ;GET THE # OF DEVICES SPECIFIED
MOVE T2,STU.RB+OBJ.TY(M) ;GET THE MESSAGE OBJECT TYPE
STAT.1: CAMN T2,0(S2) ;DOES MSG DEVICE MATCH DEVICE LIST ??
JRST STAT.2 ;YES,,THEN HE WINS AT LAST !!
AOS S2 ;BUMP TO NEXT ENTRY IN DEVICE LIST
SOJG T1,STAT.1 ;KEEP TRYING WHILE WE CAN
JRST E$SNY## ;NOT A VALID DEVICE,,BUMP HIM !!
STAT.2: EXCH P1,S1 ;SWAP OBJ ADDRESS AND OBJ STATUS CODE
CAIN P1,%RESET ;IS IT 'RESET' ???
PJRST [DOSCHD ;FORCE A SCHEDULING PASS
MOVX S2,OBSSTP!OBSFCH;[1163] YES,,GET 'STOPPED' AND 'CHANGING FORMS' STATUS
ANDCAM S2,OBJSCH(S1) ;CLEAR THEM
PJRST A$OBST ] ;GO UPDATE THE STATUS
STORE P1,OBJSTS(S1) ;NO,,SAVE THE NEW DEVICE STATUS
CAIG P2,STU.SZ ;DOES MESSAGE INCLUDE OPTIONAL DATA?
$RETT ;NO, ALL DONE
MOVE S2,OBJSCH(S1) ;GET SCHEDULING BITS
CAIN P1,%IDLE ;IDLE?
TXZA S2,OBSBUS ;YES, CLEAR BUSY
TXO S2,OBSBUS ;NO, SET BUSY
MOVEM S2,OBJSCH(S1) ;PUT BITS BACK
HRLI S2,STU.PR(M) ;COPY PARM WORDS
HRRI S2,OBJPRM(S1) ;FROM MESSAGE TO OBJ BLOCK
BLT S2,OBJPRM+OBPRSZ-1(S1)
HRLI S2,STU.ST(M) ;COPY STATUS STRING FROM MESSAGE
HRRI S2,OBJST1(S1) ;TO OBJ BLOCK
BLT S2,OBJST1+STSSIZ-1(S1)
$RETT ;RETURN
SUBTTL A$GBLK - ROUTINE TO BREAK DOWN IPCF MESSAGES
;CALL: M/ THE MESSAGE ADDRESS
;
;RET: T1/ THE BLOCK TYPE
; T2/ THE BLOCK LENGTH
; T3/ THE BLOCK DATA ADDRESS
; FALSE IF NO MORE BLOCKS
A$GBLK: SKIPE S1,G$BLKA## ;GET THE BLOCK ADDRESS IF THERE IS ONE
JRST .+4 ;NOT FIRST TIME THROUGH,,SO SKIP INITLZN
MOVE S1,.OARGC(M) ;GET THE MESSAGE BLOCK COUNT
MOVEM S1,BLKCNT ;AND SAVE IT
MOVEI S1,.OHDRS+ARG.HD(M) ;IF NOT,,GET THE FIRST ONE
SOSGE BLKCNT ;CHECK THE BLOCK COUNT
$RETF ;NO MORE,,JUST RETURN
LOAD TF,.MSTYP(M),MS.CNT ;GET THE MSG LENGTH
ADD TF,M ;GET END ADDRESS
CAMLE S1,TF ;VALIDATE THE ENTRY ADDRESS
$RETF ;NO GOOD...
LOAD T1,ARG.HD(S1),AR.TYP ;GET THE BLOCK TYPE
LOAD T2,ARG.HD(S1),AR.LEN ;GET THE BLOCK LENGTH
JUMPE T2,.RETF ;VALIDATE THE ENTRY LENGTH
MOVEI T3,ARG.DA(S1) ;POINT TO THE ACTUAL DATA
ADD S1,T2 ;POINT TO THE NEXT BLOCK
MOVEM S1,G$BLKA## ;SAVE IT FOR THE NEXT TIME AROUND
$RETT ;AND RETURN
BLKCNT: BLOCK 1 ;MESSAGE BLOCK COUNT
SUBTTL Utility Routines
; GETPSB -- FIND OR CREATE A PSB GIVEN A PID
; KILPSB -- KILL A SPECIFIED PSB
; GETOBJ -- FIND OR CREATE AN OBJ ENTRY
; ORANGE -- HANDLE A RANGE OF OBJECTS
SUBTTL GETPSB -- Routine to get a PSB
;GETPSB - Find a PSB using PID or processor name
;
;This routine will first search by PID. If PSB found, its address
;is returned. If S1 zero or PID not found, a search is done using name
;in S2 if nonzero. If still not found or both S1 and S2 are zero,
;a PSB is created and address is returned in S1. A PSB address is
;always returned. A$FPSB does the searching.
;
; Call: S1/ PID or zero
; S2/ Processor name or zero
; Return: TRUE S1/ PSB address
; FALSE never
GETPSB::JUMPE S1,GETP.0 ;JUMP IF NO PID
PUSH P,S2 ;SAVE POSSIBLE NAME
SETZM S2 ;USE PID
PUSHJ P,A$FPSB ;FIND KNOWN PID
POP P,S2 ;GET POSSIBLE NAME BACK
JUMPN S1,.RETT ;FOUND IT
GETP.0: JUMPE S2,GETP.1 ;JUMP IF NOT FOUND AND NO NAME
;OR JUST WANT A PSB
PUSHJ P,A$FPSB ;FIND PSB USING NAME
JUMPN S1,.RETT ;JUMP IF FOUND, ELSE...
GETP.1: MOVEI H,HDRPSB ;LOAD ADR OF PSB HEADER
PUSHJ P,M$GFRE## ;GET A FREE CELL
PUSHJ P,M$ELNK## ;LINK IN THE PSB
MOVE S1,AP ;RETURN ANSWER IN S1
$RETT ;AND RETURN
SUBTTL KILPSB -- Routine to kill a PSB given its address
;KILPSB is called to clean-up after known components which seem to have
; disappeared behind QUASAR's back. It releases any job interlocks
; held by that program and deletes the PSB entry.
;
;Call: S1/ address of PSB
KILPSB: $SAVE H ;SAVE H
$SAVE AP ;AND AP
PUSHJ P,.SAVE3 ;SAVE P1 AND P2 AND P3
DOSCHD ;FORCE ANOTHER SCHEDULING PASS
MOVE P2,S1 ;COPY THE ARG OVER TO P2
LOAD P1,HDROBJ##+.QHLNK,QH.PTF ;POINT TO THE FIRST OBJ
KILP.1: JUMPE P1,KILP.6 ;NO MORE OBJECTS, WE ARE DONE
MOVE S1,PSBPID(P2) ;GET THE PID
CAME S1,OBJPID(P1) ;OBJECT HELD BY PSB IN QUESTION?
JRST KILP.5 ;NO, LOOP FOR NEXT OBJECT
ZERO OBJPID(P1) ;YES, CLEAR THE INTERLOCK WORD
MOVE S2,OBJSCH(P1) ;GET THE SCHEDULER FLAG BITS
TXZ S2,OBSDAA ;FOGET WE KNOW ATTRIBUTES
MOVE TF,OBJTYP(P1) ;GET OBJECT TYPE
CAXN TF,.OTNQC ;DON'T FOOL WITH NEBULA'S OBJ ATTRIBS
JRST KILP1A
LOAD S1,OBJDAT(P1),RO.ATR ;GET ATTRIBUTES
HRL S1,TF ;GET OBJECT TYPE
CAMN S1,[.OTBAT,,%IBMBT] ;IBMSPL STREAM OBJECT BLOCK?
JRST KILP1A ;YES, DO NOT RESET THE ATTRIBUTE
MOVX S1,%GENRC ;GET GENERIC ATTRIBUTES
STORE S1,OBJDAT(P1),RO.ATR ;YES,,RESET THEM
TXZ S2,OBSATR ;REMEMBER THE FACT
KILP1A: MOVEM S2,OBJSCH(P1) ; AND SAVE THE FLAG BITS
TXZN S2,OBSSIP ;SETUP-IN-PROGRESS?
JRST KILP.2 ;NO,,TRY SOMETHING ELSE
MOVEM S2,OBJSCH(P1) ;SAVE THE FLAG BITS
JRST KILP.5 ;AND LOOP FOR NEXT OBJECT
KILP.2: TXZN S2,OBSSUP ;WAS OBJECT SETUP ???
JRST KILP.5 ;NO,,GET NEXT OBJECT
MOVEM S2,OBJSCH(P1) ;SAVE THE NEW FLAG BITS
;Here check to see if it was an IBM remote
MOVE S1,OBJNOD(P1) ;GET THIS OBJECTS NODE
PUSHJ P,N$NODE## ;GET ITS DATA BASE ENTRY
LOAD TF,NETSTS(S2),NETIBM ;IS THIS AN IBM REMOTE STATION ???
JUMPE TF,KIL.2A ;NO,,SKIP THIS
MOVE S1,S2 ;PASS THE NODE DB ADDRESS IN S1
MOVE S2,P1 ;PASS THE OBJECT ADDRESS IN S2
PUSHJ P,N$NOFF## ;PERFORM NODE OFFLINE PROCESSING
KIL.2A: LOAD S1,OBJSCH(P1),OBSFRR ;GET THE FREE RUNNING BIT.
JUMPN S1,KILP.7 ;IF OBJ IS FREE RUNNING,,RLSE INT-LCKS
LOAD S1,OBJSCH(P1),OBSBUS ;IS IT BUSY?
JUMPE S1,KILP.5 ;NO, ON TO THE NEXT OBJECT
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVEI H,HDRUSE## ;LOAD USE QUEUE HEADER
LOAD AP,.QHLNK(H),QH.PTF ;POINT TO FIRST ENTRY
KILP.3: SKIPN AP ;ANY LEFT?
STOPCD (IJM,HALT,,<Interlocked Job Missing>)
CAMN P1,.QEOBJ(AP) ;IS THIS THE JOB?
JRST KILP.4 ;YES, GO FREE IT UP
LOAD AP,.QELNK(AP),QE.PTN ;NO, GET POINTER TO NEXT
JRST KILP.3 ;AND LOOP
KILP.4: MOVE S1,OBJITN(P1) ;GET OBJECT ITN
CAME S1,.QEITN(AP) ;CONSISTENCY CHECK
STOPCD (IJW,HALT,,<Interlocked Job Wrong>)
LOAD S1,.QEROB+.ROBTY(AP) ;GET REQUESTED OBJECT TYPE
PUSHJ P,A$OB2Q ;GET THE QUEUE HEADER ADDRES
PUSH P,S1 ;SAVE QUEUE HEADER ADDRESS
LOAD S1,.QHPAG(S1),QH.SCH ;GET ADR OF SCHED VECTOR
PUSHJ P,SCHRJI(S1) ;RELEASE THE INTERLOCK
POP P,S1 ;GET QUEUE HEADER ADR BACK
PUSHJ P,M$MOVE## ;MOVE IT
KILP.5: LOAD P1,.QELNK(P1),QE.PTN ;POINT TO NEXT OBJECT
JRST KILP.1 ;AND LOOP
KILP.6: $LOG(<Process ^W/PSBNAM(P2)/ Deleted From QUASAR>,<Process PID is ^O/PSBPID(P2)/, Process Object Type is ^O/PSBOBJ(P2),HELOBJ/(^1/PSBOBJ(P2),HELOBJ/)>,,<$WTFLG(WT.SJI)>)
MOVEI H,HDRPSB## ;POINT TO PSB QUEUE HEADER
MOVE AP,P2 ;GET ADDRESS OF PSB
PJRST M$RFRE## ;AND RETURN TO FREE SPACE
;Here for 'Free Running' Processors
KILP.7: LOAD S2,OBJSCH(P1),OBSQUH ;GET THE QUEUE HEADER ADDRESS
LOAD S2,.QHPAG(S2),QH.SCH ;GET THE ADDR OF SCHED VECTOR
MOVE S1,P1 ;PUT THE OBJ ADDRESS INTO S1.
PUSHJ P,SCHRJI(S2) ;RELEASE DEVICE INTERLOCKS
JRST KILP.5 ;GO GET THE NEXT OBJ.
SUBTTL A$PSBC - Check on "waiting" PSBs
;A$PSBC - Look in PSB queue and check on "waiting" PSBs. If PS.FIR
; set, try to "fire it up". Check PSBUDT if PS.WAT set. Issue
; WTO if we're finally giving up on an object processor.
;
; Call: No args.
; Return: True always
A$PSBC::SKIPE DEBUGW ;DEBUGGING?
$RETT ;YES, SAVE SOME TIME
$SAVE <H,AP,P1> ;USE THESE IN CASE M$RFRE CALLED
MOVE P1,[EXP 377777777777] ;GET BIG UDT
LOAD AP,HDRPSB##+.QHLNK,QH.PTF ;GET THE FIRST ENTRY
TRNA
PSBC.1: LOAD AP,.QELNK(AP),QE.PTN ;GET THE NEXT PSB IN THE CHAIN
JUMPE AP,PSBC.6 ;NOT FOUND, GO CHECK UDT
LOAD S1,PSBFLG(AP),PSFSTS ;GET PSB STATUS
CAXN S1,PS.RUN ;"RUNNING"?
JRST PSBC.1 ;YES, LOOP FOR MORE
CAXN S1,PS.FIR ;NO, NEED TO BE "FIRED"?
JRST PSBC.3 ;YES, GO DO IT
CAXE S1,PS.WAT ;"WAITING"
CAXN S1,PS.KSY ;OR SPECIAL BATCON "WAITING"
TRNA ;"WAITING" EITHER WAY
JRST PSBC.1 ;NO, LOOK AT NEXT PSB
;Here when PSB is "waiting" check UDT and see if we need to try and
;"fire" it again.
MOVE S1,PSBUDT(AP) ;GET UDT WE WAIT UNTIL
CAMGE S1,G$NOW## ;EXPIRED?
JRST PSBC.2 ;YES, GO COMPLAIN
CAMGE S1,P1 ;NO, NEXT IN LINE TO EXPIRE?
MOVE P1,S1 ;YES, SAVE THE UDT
JRST PSBC.1 ;LOOK AT NEXT PSB
PSBC.2: $WTO (<^W/PSBNAM(AP)/ failed to startup>,,,$WTFLG(WT.SJI))
LOAD S1,PSBFLG(AP),PSFSTS ;GET STATUS AGAIN
CAXN S1,PS.KSY ;WAITING FOR A KSYS BATCON?
$WTO (<Use OPSER for KSYS logouts since BATCON didn't start>,,,$WTFLG(WT.SJI))
JRST PSBC.5 ;GO GET RID OF THE PSB
;Here to "fire up" an object processor
PSBC.3: MOVE S1,PSBNAM(AP) ;GET PROCESSOR NAME
PUSHJ P,I$FCJB## ;GO FIND CJB FOR PROCESSOR
JUMPF PSBC.5 ;IF NOT THERE, RELEASE PSB ????
HRLS S1 ;COPY PROCESSOR'S CJB TO OURS
HRRI S1,QSRCJB##
BLT S1,QSRCJB##+CJB.SZ-1
MOVEI S1,QSRCJB## ;GET CJB ADDRESS IN S1 FOR I%CJOB CALL
MOVEI S2,^D60 ;WAIT 1 MINUTE FOR FRCLIN IF NEEDED
STORE S2,CJB.TP(S1),CJ.TIM ;STORE IN CJB
$CALL I%CJOB ;"FIRE" AWAY
JUMPF PSBC.4 ;JUMP IF MISFIRE
MOVX S1,PS.WAT ;GET "WAITING" STATUS
STORE S1,PSBFLG(AP),PSFSTS ;SET IN PSB
$CALL I%NOW ;GET UDT
ADD S1,[EXP ^D60*^D3] ;MAKE ONE MINUTE FROM NOW
MOVEM S1,PSBUDT(AP) ;STORE IN PSB
CAMGE S1,P1 ;NEXT IN LINE TO EXPIRE?
MOVE P1,S1 ;YES, SAVE THE UDT
JRST PSBC.1 ;GET NEXT PSB
;Here to check retry count on "misfire". S1 = error from I%CJOB
PSBC.4: LOAD S2,PSBFLG(AP),PSFCNT ;GET "FILE UP" TRY MAXIMUM
SOJG S2,[STORE S2,PSBFLG(AP),PSFCNT ;SAVE NEW COUNT
JRST PSBC.1] ;LOOP FOR MORE PSB'S
$WTO (<Retry count exhausted trying to start ^W/PSBNAM(AP)/>,<Last error: ^E/S1/>,,$WTFLG(WT.SJI))
;Here to release the PSB from PSB queue
PSBC.5: MOVEI H,HDRPSB## ;GET QUEUE HEADER ADDRESS
PUSHJ P,M$RFRE## ;AND RETURN PSB TO FREE SPACE
JRST PSBC.1 ;LOOK AT NEXT PSB
;Here to set next wake up time
PSBC.6: AOJL P1,.RETT ;IF NO UDT FROM HERE, RETURN
SKIPN S1,G$WTIM## ;GET NEXT WAKEUP TIME
JRST [MOVEM P1,G$WTIM## ;NONE, SET IT
$RETT] ;RETURN
CAMGE P1,S1 ;OUR TIME EARLIER?
MOVEM P1,G$WTIM## ;YES, OVERRIDE PREVIOUS TIME
$RETT ;ALL DONE
SUBTTL GETOBJ -- Find or create an OBJ queue entry
;GETOBJ WILL LOOK FOR THE SPECIFIED OBJECT AND IF NOT FOUND, IT
; WILL CREATE THE OBJ ENTRY AND FILL IN THE OBJECT BLOCK IN
; IT
;
;CALL: S1/ POINTER TO AN OBJECT BLOCK
;
;T RET: S1/ POINTER TO AN OBJ QUEUE ENTRY
GETOBJ: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVE P1,S1 ;SAVE THE ARGUMENT
MOVE S1,OBJ.ND(P1) ;GET THE NODE NAME/NUMBER
PUSHJ P,N$NODE## ;PUT IT INTO OUR DATA BASE
SKIPE S1 ;DON'T STORE A ZERO
MOVEM S1,OBJ.ND(P1) ;STORE NODE NUMBER
MOVE P2,S2 ;SAVE THE NODE DATA BASE ENTRY ADDRESS
MOVE S1,P1 ;GET THE OBJECT ADDRESS IN S1
PUSHJ P,A$FOBJ ;FIND THE OBJECT
JUMPT .RETT ;RETURN IF YOU DID
PUSHJ P,CHKOBJ ;GO VALIDATE THE OBJ BLK.
JUMPF .RETF ;NO GOOD,,JUST RETURN
;HERE IF WE HAVE TO CREATE AN OBJECT QUEUE ENTRY
GETO.0: $SAVE H ;SAVE AC H
$SAVE AP ;AND AP
MOVX S1,NETSHT ;GET THE NETWORK SHUTDOWN BIT
ANDCAM S1,NETSTS(P2) ;AND CLEAR IT (JUST IN CASE IT WAS ON)
MOVEI H,HDROBJ## ;LOAD ADR OF OBJ HEADER
PUSHJ P,M$GFRE## ;GET A FREE CELL
MOVE S1,P1 ;POINT TO SOURCE OBJECT
MOVEI S2,OBJTYP(AP) ;POINT TO DESTINATION OBJECT
PUSHJ P,A$CPOB ;COPY THE OBJECT BLOCK
MOVE S1,OBJTYP(AP) ;GET THE OBJECT TYPE
PUSHJ P,A$OB2Q ;CONVERT IT TO A QUEUE HEADER
JUMPF BADMSG ;NOT THERE,,ORION ERROR !!!
STORE S1,OBJSCH(AP),OBSQUH ;STORE QUEUE HEADER ADDRESS
LOAD S1,.QHTYP(S1) ;GET THE QUEUE TYPE.
TXC S1,.QHFRR ;COMPILMENT FREE RUNNING BITS
MOVX S2,OBSFRR ;GET SCHEDULING FREE RUNNING BITS
TXNN S1,QH.TYP ;IS THIS A FREE RUNNING OBJECT ???
IORM S2,OBJSCH(AP) ;YES,,LITE FREE RUNNING BIT
MOVX S2,OBSINV ;GET INVISIBLE BIT
TXNE S1,QH.INV ;IS THIS OBJECT INVISIBLE ???
IORM S2,OBJSCH(AP) ;YES,,LITE THE INVISIBLE BIT
TXNE S1,QH.OAV ;OBJECT ALWAYS VISIBLE?
ANDCAM S2,OBJSCH(AP) ;THEN IGNORE QH.INV SETTING
MOVSI S1,-NOBJS ;AOBJN PTR TO OBJTAB
MOVE S2,OBJTYP(AP) ;AND THE OBJECT TYPE
CAME S2,OBJTAB(S1) ;FIND THE OBJECT
AOBJN S1,.-1 ;THIS MUST WORK SINCE A$OB2Q DID
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
HRRZS S1 ;GET OBJECT NUMBER
IMULI S1,OBPRSZ ;MULTIPLY BY PARAMS/OBJ
ADDI S1,PRMTAB ;POINT TO INITIAL PARAMETERS
MOVSS S1 ;PUT SOURCE IN LEFT HALF
HRRI S1,OBJPRM(AP) ;PLACE TO BLT THEM
BLT S1,OBJPRM+OBPRSZ-1(AP) ;AND MOVE THEM
MOVX S1,%GENRC ;GET 'GENRIC' ATTRIBUTES
MOVE TF,OBJTYP(AP) ;[1466] GET OBJECT TYPE
LOAD S2,NETSTS(P2),NT.MOD ;[1466] GET THE MODE OF THE NODE
CAXN S2,DF.EMU ;[1466] IS IT EMULATION ???
CAXE TF,.OTBAT ;[1466] AND IS THE OBJECT TYPE BATCH ???
TRNA ;[1466] NOT EMULATION or NOT EMULATION+BATCH !!!
MOVX S1,%IBMBT ;[1466] GET IBM BATCH ATTRIBUTE
STORE S1,OBJDAT(AP),RO.ATR ;AND STORE THEM
MOVX S1,%NSTRT ;GET 'NOT STARTED'
MOVEM S1,OBJSTS(AP) ;SET IT
LOAD E,.QHLNK(H),QH.PTF ;GET POINTER TO FIRST OBJECT
GETO.1: JUMPE E,GETO.4 ;LINK AT END IF NONE LEFT
MOVE S1,OBJTYP(AP) ;GET OBJECT TYPE OF NEW ONE?
CAMN S1,OBJTYP(E) ;SAME?
JRST GETO.2 ;YUP, CONTINUE ON
LOAD E,.QELNK(E),QE.PTN ;GET NEXT
JRST GETO.1 ;AND LOOP
GETO.2: MOVE S1,OBJNOD(AP) ;GET THE NODE
CAMG S1,OBJNOD(E) ;SEARCH FOR FIRST ONE BIGGER
JRST GETO.3 ;GOT IT
LOAD E,.QELNK(E),QE.PTN ;GET POINTER TO NEXT
JUMPE E,GETO.4 ;END, JUST LINK IT IN
MOVE S1,OBJTYP(AP) ;GET THE OBJECT TYPE
CAME S1,OBJTYP(E) ;STILL IN THE SAME TYPE?
JRST GETO.4 ;NO, JUST LINK IT
JRST GETO.2 ;YES, KEEP LOOKING
GETO.3: MOVE S1,OBJNOD(AP) ;GET NODE OF NEW ONE
CAME S1,OBJNOD(E) ;SAME AS ENTRY IN LIST?
JRST GETO.4 ;NO, JUST LINK IT IN
MOVE S1,OBJUNI(AP) ;GET THE UNIT NUMBER
CAMG S1,OBJUNI(E) ;SEARCH FOR A BIGGER ONE
JRST GETO.4 ;GOT IT, LINK IT
LOAD E,.QELNK(E),QE.PTN ;GET NEXT
JUMPE E,GETO.4 ;END, LINK IT IN
MOVE S1,OBJTYP(AP) ;GET THE OBJECT TYPE
CAMN S1,OBJTYP(E) ;STILL THE SAME?
JRST GETO.3 ;NO, LOOP
GETO.4: PUSHJ P,M$LINK## ;LINK IN THE ENTRY
MOVE S1,AP ;POINT THE ANSWER TO IT
$RETT ;AND RETURN
SUBTTL CHKOBJ - ROUTINE TO VALIDATE OBJECT BLOCK REQUESTS.
CHKOBJ: LOAD S1,OBJ.TY(P1) ;GET THE OBJECT TYPE.
LOAD S2,NETSTS(P2),NT.MOD ;GET THE MODE OF THE NODE
CAXN S2,DF.EMU ;IS IT EMULATION ???
CAXN S1,.OTBAT ;AND IS THE OBJECT TYPE BATCH ???
SKIPA ;NOT EMULATION or EMULATION+BATCH !!!
JRST CHKO.3 ;EMULATION BUT NOT BATCH,,ERROR
JUMPLE S1,.RETT ;FUNNY OBJ,, RETURN OK.
CAIN S1,.OTBAT ;IS IT A BATCH OBJECT BLOCK ???
JRST CHKO.1 ;YES,,GO PROCESS IT.
MOVEI S2,10 ;ASSUME NORMAL DEVICE LIMITATIONS
CAIN S1,.OTNQC ;NET QUE CTL?
MOVEI S2,1000 ;DIFFERENT LIMIT
LOAD S1,OBJ.UN(P1) ;GET THE UNIT NUMBER
CAIGE S1,(S2) ;MORE THAN MAX?
$RETT ;NO,,THEN RETURN TRUE.
$ACK (<Invalid unit number specified>,,0(P1),.MSCOD(M)) ;TELL OPR
$RETF ;RETURN FALSE.
CHKO.1: LOAD S1,OBJ.UN(P1) ;GET THE UNIT NUMBER.
CAIGE S1,INPMAX ;MORE THAN INPMAX STREAMS?
JRST CHKO.2 ;NO
$ACK (<Invalid stream number specified>,,0(P1),.MSCOD(M)) ;TELL OPR
$RETF ;AND RETURN
CHKO.2: SOSL G$NBAT## ;SUBTRACT 1 FROM MAX BATCH COUNT.
$RETT ;OK,,RETURN.
$ACK (<Batch stream maximum exceeded>,,0(P1),.MSCOD(M)) ;TELL OPR
SETZM G$NBAT## ;RESET THE COUNT TO 0.
$RETF ;RETURN.
CHKO.3: $ACK (<Device invalid for Emulation>,,0(P1),.MSCOD(M)) ;TELL OPR
$RETF
SUBTTL FNDDEV - CHECK FOR ANY DEVICE STARTED FOR THE SPECIFIED NODE
;CALL: S1/ The Node DB Entry Address for the Node we are looking for
;
;RET: True - If we find a device started for the specified node
; False - If there are no devices started for the node
FNDDEV: PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVE P1,S1 ;SAVE THE NETWORK NODE DB ADDRESS IN P1
LOAD S2,HDROBJ+.QHLNK,QH.PTF ;GET PTR TO FIRST OBJ QUEUE ENTRY
SKIPA ;SKIP FIRST TIME THROUGH
FNDD.0: LOAD S2,.QELNK(S2),QE.PTN ;GET THE NEXT OBJ ENTRY ADDRESS
JUMPE S2,.RETF ;NO MORE,,RETURN FALSE
MOVE S1,OBJNOD(S2) ;GET THE OBJECTS NODE NAME
CAME S1,NETNAM(P1) ;DO
CAMN S1,NETNBR(P1) ; WE
$RETT ; MATCH ??? YES - RETURN TRUE
JRST FNDD.0 ;NO,,CHECK NEXT OBJECT
SUBTTL A$FNDB - ROUTINE TO FIND ANY BLOCK IN AN IPCF MESSAGE
;CALL: M/ THE MESSAGE ADDRESS
; S1/ THE TYPE OF BLOCK WE WANT
;
;RET: S1/ THE BLOCK ADDRESS (OR FALSE IF NOT FOUND)
INTERN A$FNDB ;MAKE IT GLOBAL
A$FNDB: PUSHJ P,.SAVE2 ;SAVE P1
LOAD P1,.OARGC(M) ;GET THE MESSAGE ARGUMENT COUNT
MOVE P2,S1 ;SAVE THE BLOCK TYPE
MOVEI S1,.OHDRS(M) ;POINT TO THE FIRST BLOCK
LOAD TF,.MSTYP(M),MS.CNT ;GET THE MESSAGE LENGTH
CAXLE TF,PAGSIZ ;CAN'T BE GREATER THEN A PAGE
$RETF ;ELSE THATS AN ERROR
ADD TF,M ;POINT TO THE END OF THE MESSAGE
FNDB.1: LOAD S2,ARG.HD(S1),AR.TYP ;GET THIS BLOCK TYPE
CAMN S2,P2 ;IS IT THE BLOCK HE WANTS ???
JRST FNDB.2 ;YES,,HE WINS BIG !!!
LOAD S2,ARG.HD(S1),AR.LEN ;NO,,GET THIS BLOCKS LENGTH
ADD S1,S2 ;POINT TO THE NEXT BLOCK
CAMLE TF,S1 ;ARE WE STILL IN THE MESSAGE ???
SOJG P1,FNDB.1 ;CONTINUE TILL DONE
$RETF ;BLOCK NOT FOUND
FNDB.2: MOVEI S1,ARG.DA(S1) ;POINT TO THE OBJECT BLOCK
$RETT ;AND RETURN
SUBTTL GENRDB - ROUTINE TO CREATE AN RDB FOR HOLD/RELEASE/SET JOB PRIO
;CALL: M/ HOLD/RELEASE/SET JOB PRIO MESSAGE ADDRESS
; S1/ OUTPUT RDB ADDRESS
;
;RET: ALWAYS TRUE
GENRDB: PUSHJ P,.SAVE1 ;SAVE P1
MOVE P1,S1 ;SAVE THE RDB ADDRESS
SETZM TMPMSG ;ZAP THE FIRST WORD
MOVE S1,[TMPMSG,,TMPMSG+1] ;GET SOURCE,,DESTINATION
BLT S1,TMPMSG+MOD.SZ+3-1 ;ZERO THE TEMP OPR MSG
MOVE S1,.MSCOD(M) ;GET THE OPR ACK CODE
MOVEM S1,TMPMSG+.MSCOD ;SAVE IT IN THE TEMP MSG
MOVEI S1,NBLKS-1 ;GET THE BLOCK COUNT
SETZM RDBPRM(S1) ;ZERO THE RDB PARM BLOCK
SOJGE S1,.-1 ;CONTINUE TILL DONE
GENR.1: PUSHJ P,A$GBLK ;GET THE FIRST/NEXT MESSAGE BLOCK
JUMPF GENR.3 ;NO MORE,,BUILD THE RDB
MOVSI S1,-NBLKS ;CREATE AOBJN AC
LOAD S2,0(T3) ;GET THE MESSAGE ARGUMENT
CAIN T1,.CMUSR ;IS THIS THE USER ENTRY ???
MOVE S2,T3 ;YES,,GET ITS ADDRESS
GENR.2: CAME T1,DSPRDB(S1) ;DO BLOCK TYPES MATCH ???
AOBJN S1,GENR.2 ;NO,,IGNORE IT AND LOOP BACK
STORE S2,RDBPRM(S1) ;YES,,SAVE THE ARGUMENT
JRST GENR.1 ;AND GO PROCESS ANOTHER BLOCK
GENR.3: LOAD S1,RDBPRM ;GET THE QUEUE TYPE
MOVEM S1,TMPMSG+MSHSIZ ;SAVE IT IN THE MSG
MOVE S1,RDBPRM+2 ;GET THE USERS ENTRY ADDRESS
MOVE S2,P1 ;GET THE OUTPUT ADDRESS
PUSHJ P,I$MUSR## ;MOVE THE USER INFO
MOVE S1,RDBPRM+1 ;GET THE REQUEST ID NUMBER
MOVEM S1,.RDBRQ(P1) ;SAVE IT
MOVE S1,RDBPRM+3 ;GET THE .ORNOD BLOCK NODE SPECIFICATION
MOVEM S1,G$RMTE## ;SAVE IT FOR THE QUEUE SEARCH
$RETT ;RETURN
DSPRDB: 0,,.ORTYP
0,,.ORREQ
0,,.CMUSR
0,,.ORNOD
NBLKS==.-DSPRDB
RDBPRM: BLOCK NBLKS+1 ;SAVE AREA FOR MSG RDB PARAMETERS
SUBTTL PRMTAB - OBJECT INITIAL PARAMETERS TABLE.
DEFINE X(OBJ,QUE,PARM),<
ZZZ==0 ;;INITIAL PARAMETER COUNTER
IRP PARM,<
EXP PARM ;;GENERATE A WORD
ZZZ==ZZZ+1 ;;COUNT ANOTHER WORD
IFE ZZZ-OBPRSZ,<STOPI> ;;STOP IF WE'VE GOT ENOUGH
> ;;END IRP PARM
BLOCK OBPRSZ-ZZZ ;;EXTEND BLOCK TO FULL SIZE
> ;END DEFINE X
PRMTAB: MAPOBJ ;GENERATE THE TABLE
SUBTTL ORANGE -- Handle a range of objects
;ORANGE IS CALLED AT THE START OF PROCESSING A COMMAND FROM ORION
; WHICH MIGHT CONTAIN A RANGE OF OBJECTS. ORANGE ACTS AS A
; CO-ROUTINE SO THAT EACH OBJECT IN THE RANGE WILL CAUSE
; CONTROL TO BE TRANSFERED TO THE LOCATION AFTER THE CALL
; TO ORANGE. THE FLOW OF THE CALLING ROUTINE IS AS FOLLOWS:
;MESSAGE-FROM-ORION:
; LOAD S1 WITH ADR OF OBJECT BLOCK IN MESSAGE
; CALL ORANGE
;
; ALL CODE FROM HERE TO THE RETURN IS EXECUTED ONCE FOR EACH
; OBJECT SPECIFIED IN THE RANGE.
;END-OF-ROUTINE
;CALL: S1/ ADDRESS OF OBJECT BLOCK (MAY OR MAY NOT CONTAIN RANGE)
;
;T RET: S1/ ADDRESS OF OBJECT BLOCK FOR A SINGLE OBJECT
ORANGE: HLRZ S2,OBJ.UN(S1) ;GET THE UPPER LIMIT
JUMPE S2,.RETT ;NO RANGE, JUST RETURN
MOVEM S2,ORAN.B ;STORE UPPER LIMIT
HRRZ S2,OBJ.UN(S1) ;GET LOWER LIMIT
MOVEM S2,ORAN.A ;STORE IT AWAY
MOVE S2,OBJ.TY(S1) ;GET OBJECT TYPE
MOVEM S2,ORAN.C ;STORE IT
MOVE S2,OBJ.ND(S1) ;GET NODE
MOVEM S2,ORAN.D ;STORE IT
POP P,ORAN.E ;GET CALLING ADDRESS
ORAN.1: MOVEI S1,ORAN.F ;GET ADDRESS OF RETURN BLOCK
MOVE S2,ORAN.C ;GET OBJECT TYPE
MOVEM S2,OBJ.TY(S1) ;STORE IT
MOVE S2,ORAN.D ;GET NODE
MOVEM S2,OBJ.ND(S1) ;STORE IT
MOVE S2,ORAN.A ;GET NEXT UNIT NUMBER
MOVEM S2,OBJ.UN(S1) ;STORE IT
PUSHJ P,@ORAN.E ;CALL THE CALLER
AOS S1,ORAN.A ;INCREMENT FOR NEXT ONE
CAMG S1,ORAN.B ;ALL DONE?
JRST ORAN.1 ;NO, LOOP
$RETT ;YES, RETURN
ORAN.A: BLOCK 1 ;LOWER LIMIT (INCREMENTED)
ORAN.B: BLOCK 1 ;UPPER LIMIT
ORAN.C: BLOCK 1 ;OBJECT TYPE
ORAN.D: BLOCK 1 ;NODE NAME
ORAN.E: BLOCK 1 ;CALLERS LOCATION
ORAN.F: BLOCK 3 ;OBJECT BLOCK TO RETURN TO USER
END