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

1027 lines
36 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE PLROPR - Operator Interface Module
SUBTTL Author: Dave Cornelius 3-Aug-83
;
;
;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 GLXMAC ;Get GALAXY library conventions
SEARCH ORNMAC ;For keyword descriptions
SEARCH PLRMAC
SEARCH QSRMAC
PROLOG (PLROPR)
GLOB NUMBER
NUMBER: ITEXT (<^7/[.CHLAB]/number^7/[.CHRAB]/>)
SUBTTL COMERR - Error handler for messages
;This routine will complain to the operator if anything in the
; dialogs between PULSAR and any other component is screwed up.
; In all probablity, something is going to be messed up
; and perhaps beyond repair, but we should try to keep going.
; Call -
; JSP S1,COMERR
;Returns -
; $RETT, always
O$CERR::
COMERR::
MOVEM S1,G$COMR## ;Save the PC of the last mistake
LOAD S1,.MSTYP(M),MS.TYP ;Get the type of message code
LOAD S2,.MSFLG(M),MF.SUF ;And SIXBIT suffix
CAIN S1,.OMTXT ;Is it just text?
CAIE S2,'ODE' ;And sent to gone operator
$WTO (PULSAR Internal Error,<Message type ^O/.MSTYP(M),MS.TYP/ is unknown or unrecognizable>,,$WTFLG(WT.SJI))
$RETT ;Try to continue
SUBTTL UNLOAD command processing
O$CUNL::
$SAVE <P1> ;Save a reg
MOVX S1,.RECDV ;Look for a tape recognize block
PUSHJ P,FNDBLK ;Find that in the message
SKIPT ;Got it?
JSP S1,COMERR ;Noper, complain
MOVE S1,.RECDN(S1) ;Get the device name
MOVE P1,S1 ;Save the real dev name
PUSHJ P,G$FTCB## ;Find the TCB for that drive
JUMPF [MOVE T1,P1 ;Get device name
SETZB T2,T3 ;Clear job number and owner
PUSHJ P,G$MTCB## ;Make up a new TCB
JUMPT OACU.0 ;Get one?, start the recognizer
STOPCD (CMV,HALT,,<Can't make TCB>)]
OACU.0: LOAD S1,TCB.WS(B) ;Get the wait state
CAXN S1,TW.MNT ;Waiting for mount?
JRST OACU.M ;Yes, do a special unload
CAXN S1,TW.LBL ;No, Waiting for RESPONSE?
JRST OACM.R ;Yes, indicate that to OPR
JUMPN S1,[MOVX S2,TS.KIL ;Get the rundown in progress bit
TDNN S2,TCB.ST(B) ;Are we killing this TCB
JRST OACM.U ;Anything but idle, don't touch
$RETF ] ;Killing TCB, let it die down
MOVEI S1,1 ;Wait for the Monitor to catch up
SLEEP S1, ;ZZZZ
LOAD S1,TCB.DV(B) ;Get dev name requested
PUSHJ P,T$CKAV## ;Can we use it?
JUMPF OACM.U ;No, complain to OPR again
MOVX S1,TI.OAV ;Get open for AVR only bit
IORM S1,TCB.IO(B) ;Set so we clean up later
SETZM TCB.LT(B) ;Clear the label type
SETZM TCB.OW(B) ;Clear the owner ppn
SETZM TCB.JB(B) ;And the owner's job number
SETZM TCB.ST(B) ;Clear all status bits
MOVEI S1,D$UNLC## ;Assume a disk
LOAD S2,TCB.CH(B),TC.TYP ;Get the device type
CAIN S2,%TAPE ;Magtape?
MOVEI S1,O$UNLC ;Yes
CAIN S2,%DTAP ;DECtape?
MOVEI S1,D$UDTA## ;Yes
PJRST G$NPRC## ;Go to it!
OACU.M: MOVEI S1,O$UNLC ;Get addr of routine to do on-the-side
PJRST CALSUB ;And do that on the side
;HERE FOR PART TWO OF THE COMMAND ON A SCHEDULE CYCLE
O$UNLC: $TRACE (O$UNLC,6) ;TRACE IT
PUSHJ P,L$CLEF## ;Clear out any errors
PUSHJ P,T$OPEN## ;OPEN THE TAPE
JUMPF .RETT ;ERROR, Oh well
MOVEI S1,'UNL' ;GET THE UNLOAD COMMAND
PUSHJ P,T$POS## ;DO IT
JUMPF .RETT ;ERROR, Oh well
ZERO TCB.VL(B) ;And first part of volid
ZERO TCB.VL+1(B) ;And second part, too
MOVEI S1,BNKWD## ;Aim at 8 blanks
PJRST I$RLID## ;SET THE REELID AND RRETURN
SUBTTL OACREW - Rewind a volume
;This directive is given by MDA when a volume
; switch request can't be satisfied on this volume.
; The idea is to overlap the rewinding with the operator's
; searching for the next tape.
O$CREW::
$SAVE <P1> ;Save a reg
MOVX S1,.RECDV ;Look for a tape recognize block
PUSHJ P,FNDBLK ;Find that in the message
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
MOVE S1,.RECDN(S1) ;Get the device name
MOVE P1,S1 ;Save the real dev name
PUSHJ P,G$FTCB## ;Find the TCB for that drive
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
LOAD S1,TCB.WS(B) ;Get this guy's wait state
CAIE S1,TW.MNT ;Waiting for a volume switch?
$RETT ;Nope, race conditions with abort stuff
MOVEI S1,O$REWC ;Addr of routine to run
PJRST CALSUB ;Run the TCB, and come back
;Here in the TCB's context (In case we fall into offline device trap!)
O$REWC:
$TRACE (O$REWC,6)
MOVEI S1,'REW' ;Get the command
PUSHJ P,T$POS## ;Do it
$RETT ;Ignore the error
SUBTTL MOUNT tape recognize command
O$CREC::
$SAVE <P1> ;Save a reg
MOVX S1,.RECDV ;Look for a tape recognize block
PUSHJ P,FNDBLK ;Go find it...
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
MOVE S1,.RECDN(S1) ;Get the device name
MOVE P1,S1 ;Save the real dev name
PUSHJ P,G$FTCB## ;Find the TCB for that drive
JUMPF OACM.2 ;No TCB, go make one
ZERO TCB.ST(B),TS.NTP ;Clear the 'no-tape' bit
LOAD S1,TCB.WS(B) ;Get wait state for the TCB
CAIN S1,TW.MNT ;Is the TCB waiting for this?
JRST OACM.4 ;Yes, get the recognizer running
CAIN S1,TW.OFL ;Or is it offline?
PJRST G$STRN## ;Off line, pick up where we left off
CAIN S1,TW.LBL ;Is it waiting for RESPONSE?
JRST OACM.R ;Yes, say that
CAIN S1,TW.INM ;Waiting for initialization mount?
JRST OACM.5 ;Yes, go can the ack, and use the tape
CAIE S1,TW.IGN ;Is it idle
JRST OACM.U ;No, don't touch the tape
LOAD S1,TCB.DV(B) ;Get dev name requested
PUSHJ P,T$CKAV## ;Can we use it?
JUMPF OACM.U ;No, tell OPR someone has it
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to fire up a volume recognition for the drive
OACM.1: SETZM TCB.ST(B) ;Clear all status bits
PUSHJ P,L$CLEF## ;Clear out the error status
MOVEI S1,L$MDC## ;Assume a magtape
LOAD S2,TCB.CH(B),TC.TYP ;Get device type code
CAIN S2,%DISK ;A disk?
MOVEI S1,D$HOM## ;Yes
CAIN S2,%DTAP ;DECtape?
MOVEI S1,D$RDTA## ;Yes
PJRST G$NPRC## ;Create a new context in TCB (B)
OACM.2: MOVE S1,P1 ;Get device name
PUSHJ P,T$CKAV## ;Make sure we don't
;rewind some user's tape!
JUMPF OACM.Z ;In use, tell OPR
MOVE T1,P1 ;Get device name
SETZB T2,T3 ;Clear job number and owner
PUSHJ P,G$MTCB## ;Make up a new TCB
SKIPT ;Get one?, start the recognizer
STOPCD (CMU,HALT,,<Can't make TCB>)
MOVX S1,TI.OAV ;Get 'Open for VR' bit
IORM S1,TCB.IO(B) ;Lite that so we'll delete label DDB
JRST OACM.1 ;And start the recognizer
OACM.4: MOVEI S1,L$MDC## ;Addr of routine to run on-the-side
PJRST CALSUB ;Do it, and get out
;Here if the drive is intializing, and was waiting for a new tape
OACM.5: PUSHJ P,CANWTO ;Cancel outstanding WTOR's
PJRST G$STRN## ;Return true to process
OACM.Z: STKVAR <<OBJ,OBJ.SZ>> ;It sure is hard being pretty
MOVEI S2,OBJ ;Get the object block address
MOVX S1,.OTMNT ;Get the tape object type
MOVEM S1,OBJ.TY(S2) ;Save it
MOVEM P1,OBJ.UN(S2) ;Save the device name
SETZM OBJ.ND(S2) ;There is no node name
SKIPA ;Skip over general entry point
OACM.U: MOVEI S2,TCB.OB(B) ;Get the object block address
MOVE S1,OBJ.UN(S2) ;Get the device name
DEVTYP S1, ;Get the owners job number
SETZM S1 ;Failed,,zero
LOAD S1,S1,TY.JOB ;Get the job number in S1
$WTO (<Invalid request - drive is assigned by job ^D/S1/>,,0(S2),$WTFLG(WT.SJI))
$RETT
;Here if there is a message outstanding
OACM.R: $WTO (<Please RESPOND to outstanding MESSAGE>,,TCB.OB(B),$WTFLG(WT.SJI))
$RETT
SUBTTL CALSUB - Call a subroutine for a TCB
;This routine will take an existing TCB and call an other
; routine in that TCB's context
;Call -
; S1/ Addr of the routine to be called
; B/ TCB to be run
CALSUB: EXCH P,TCB.AC+P(B) ;Get Process PDL
LOAD S2,TCB.WS(B) ;Save the wait state
PUSH P,S2 ;Save the current wait state
PUSH P,[EXP CALDON] ;Where to go when done
PUSH P,S1 ;Routine to call
EXCH P,TCB.AC+P(B) ;Restore both stacks
PJRST G$STTR## ;Start the TCB
CALDON: POP P,S1 ;Get back the wait state
STORE S1,TCB.WS(B) ;Put the TCB in that state
PJRST G$NJOB## ;And continue scheduling
SUBTTL Mount message from MDA
;Enter with M pointing to the message.
;This routine will build the required data base to
; service this user's labelled tape processing
O$CVMN::
$SAVE <P1>
MOVX S1,.RECDV ;Block type for device name block
PUSHJ P,FNDBLK ;Get that block from the message
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
MOVE S1,.RECDN(S1) ;Get the drive name
MOVE P1,S1 ;Save across FTCB call
PUSHJ P,G$FTCB## ;Find that guy's data block
JUMPF MOUN.1 ;Not found, go make a block
;Here if a TCB already exists
PUSHJ P,CANWTO ;Cancel outstanding WTOR's
MOVX S1,TI.OPN ;Get the open bit
TDNN S1,TCB.IO(B) ;Channel opened?
JRST MOUN.2 ;No
MOVX S1,TS.SLR ;Get skip label release bit
IORM S1,TCB.ST(B) ;Memorize it
PUSHJ P,T$RELE## ;Zap open channel and clean up
JRST MOUN.2 ;Keep going
;Here to make up a new TCB
MOUN.1: MOVE T1,P1 ;Get device name
SETZ T2, ;No known job number
SETZ T3, ;Don't know ppn of owner yet
PUSHJ P,G$MTCB## ;Get the block made up
MOUN.2: PUSHJ P,MVOLIN ;PROCESS THE VOLUME INFO
MOVEI S1,L$MOUN## ;ASSUME MAGTAPE
LOAD S2,TCB.CH(B),TC.TYP ;GET THE DEVICE TYPE
CAIN S2,%DTAP ;DECTAPE?
MOVEI S1,D$MDTA## ;YES
PUSHJ P,G$NPRC## ;CREATE CONTEXT, SET PARAMETERS
$RETT
SUBTTL O$CVDM - Volume Dismount message from MDA
;This routine handles the volume dismounted message from the allocator.
; It is responsible for cleaning up and perhaps deleting the TCB
O$CVDM::
MOVX S1,.RECDV ;Argument block type
PUSHJ P,FNDBLK ;Find drive spec block in message
SKIPT ;Got it?
JSP S1,COMERR ;No, that's a problem
MOVE S1,.RECDN(S1) ;Get the sixbit drive name
PUSHJ P,G$FTCB## ;Go find this guy's database
JUMPF .RETT ;Not there??? We must have restarted
PUSHJ P,CANWTO ;Cancel outstanding WTOR's
MOVX S1,TI.OAV ;Get open for AVR bit
IORM S1,TCB.IO(B) ;Lite so release will throw out lbl DDB
MOVX S1,TS.KIL ;Get the rundown bit
IORM S1,TCB.ST(B) ;Lite so we throw out the TCB
MOVEI S1,O$UNW ;Get TCB level code to unwind
PJRST G$NPRC## ;Come back at TCB level
;Here when the TCB has been scheduled
O$UNW:
PUSHJ P,T$OPEN## ;Get the label DDB set up
$RETT ;Return, and flush the TCB, and Lbl DDB
SUBTTL MVOLIN - Process volume info for newly mounted volume
;This routine takes whatever MDA tells us about a volume and
; stores that info in our TCB
;Call -
; M /Message addrs
; B /TCB adrs
MVOLIN: $SAVE <P1,P2>
MOVX S1,.VOLMN ;Block type for the volume info block
PUSHJ P,FNDBLK ;Find that one
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
MOVE P1,S1 ;Save addr of block
LOAD LT,.VMNIN(P1),VI.LTY ;Get the label type
STORE LT,TCB.LT(B) ;Save in TCB for future reference
MOVE S1,.VMNIV(P1) ;Get the initial volume name
MOVEI S2,TCB.VL(B) ;Offset of where to store volid
PUSHJ P,CN6VL8 ;Convert SIXBIT volid to 8-bit
MOVE S1,.VMNFV(P1) ;Get first volume in set
MOVEI S2,TCB.FV(B) ;Offset of where to store it
PUSHJ P,CN6VL8 ;Convert that one, too
LOAD S1,.VMNIN(P1),VI.WLK ;Get the write-locked bit
STORE S1,TCB.PT(B),TP.RWL ;Save in TCB for software write-lock
LOAD P2,.VMNIN(P1),VI.JOB ;Get this guy's job number
STORE P2,TCB.JB(B) ;Save in TCB for future
MOVE S1,P2 ;Move job # into place
MOVX S2,JI.USR ;Code to get user id
$CALL I%JINF ;Get this guy's [p,pn]
STORE S2,TCB.OW(B) ;Save in TCB
PUSHJ P,I$USRN## ;Get the user's name (job # in S1)
$RETT
SUBTTL OACVSD - Action routine for volume switch directives
;This routine fields directions from MDA for TCBs which are
; waiting for volume switch requests
; It will swap the units, and get the unit scheduled again
;Returns TRUE if the message could be processed now,
; FALSE if the message should be queued up and run later
O$CVSD::
$SAVE <P1,P2,P3> ;Save some space
MOVX S1,.VSDBL ;Look for this type of block
PUSHJ P,FNDBLK ;Find a Volume switch directive block
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
MOVE P1,S1 ;Save the addrs of the VSD block
LOAD S1,.VSDID(P1) ;Get the old drive name
PUSHJ P,G$FTCB## ;Find that one
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
LOAD S1,TCB.WS(B) ;Get the wait state
CAIE S1,TW.MNT ;Is it expecting this?
$RETF ;TCB busy, try again later
PUSHJ P,CANWTO ;Cancel outstanding WTOR's
SETZM S1 ;Default to no errors
MOVE S2,.MSFLG(M) ;Get the flags
TXNE S2,%VABT ;Have we been gonged?
MOVX S1,PLR%CN ;Yes,,get 'cancelled' status
TXNE S2,%VEOF ;No, how about EOF?
MOVX S1,PLR%ES ;Yes,,get 'EOF' status
TXNE S2,%VTMV ;How about volume limit exceeded ?
MOVX S1,PLR%TM ;Yes,,get 'Too Many Volumes' status
JUMPN S1,[STORE S1,TCB.AC+S1(B) ;Error,,save status in TCB
PJRST G$STFL## ] ;And return false
PUSHJ P,MVOLIN ;Move the volume info
LOAD S1,.VSDCD(P1) ;Get the new device
CAMN S1,TCB.DV(B) ;Same drive as before?
JRST VDIR.2 ;Yup, charge on!
MOVE P2,S1 ;Save the new drive name
MOVE P3,B ;Save the old drive TCB
PUSHJ P,G$FTCB## ;Find the new one's data base
JUMPT VDIR.1 ;Got it
MOVE T1,P2 ;Get the drive name back
SETZB T2,T3 ;No job, no PPN
PUSHJ P,G$MTCB## ;Make some space
VDIR.1: LOAD S1,TCB.WS(B) ;Get the prospecitve new TCB wait state
CAIE S1,TW.IGN ;Idle?
JSP S1,COMERR ;No!, error
PUSHJ P,CANWTO ;Cancel outstanding WTOR's
EXCH B,P3 ;Get to the old TCB
MOVE S1,P2 ;Get the new drive name
PUSHJ P,T$NUNI## ;Swap the guy over to this unit
JRST VDIR.3 ;ONWARD
VDIR.2: PUSHJ P,T$SUNI## ;SWAP SAME UNIT
VDIR.3: PJRST G$STTR## ;just return true to process
SUBTTL CN6VL8 - Convert SIXBIT volume id to 8-bit
;Call -
; S1/ SIXBIT volume id
; S2/ Addr where string whould be stored
;Return
; TRUE (always)
O$CN68::
CN6VL8: $SAVE <P1>
MOVE P1,S1 ;Save the volume id
HRLI S2,(POINT 8,) ;Make an 8-bit pointer
MOVE S1,[POINT 6,P1] ;Aim at the volid
CN6V.1: ILDB TF,S1 ;Get a byte
ADDI TF,40 ;Convert to ASCII
IDPB TF,S2 ;Store it
TLNE S1,770000 ;Done six yet?
JRST CN6V.1 ;No, keep moving
$RETT
; Convert 8-bit reelid to something useful in S2
O$CN86::$SAVE <P1,P2> ;SAVE P1 AND P2
HRLI S1,(POINT 8,) ;MAKE A BYTE POINTER
MOVE P1,[POINT 6,S2] ;BYTE POINTER TO STORAGE
MOVEI P2,6 ;BYTE COUNT
CN86.1: ILDB TF,S1 ;GET A BYTE
SUBI TF,40 ;CONVERT TO SIXBIT
IDPB TF,P1 ;PUT A BYTE
SOJG P2,CN86.1 ;LOOP FOR ALL CHARACTERS
POPJ P, ;RETURN
SUBTTL FNDBLK - Find a given block in the incoming message
;Call with S1/ desired block type
; M/Message addrs
;Returns: Addrs of data in block if found (TRUE return)
; or false, block not found in message
O$FNDBLK::
FNDBLK:
$SAVE <P1>
LOAD P1,.OARGC(M) ;Get the number of blocks in the message
MOVEI S2,.OHDRS(M) ;Aim at the first block
FNDB.1: SOJL P1,.RETF ;Return if none found
LOAD TF,ARG.HD(S2),AR.TYP ;Get the type of this block
CAMN TF,S1 ;Match what we're looking for?
JRST [MOVEI S1,ARG.DA(S2) ;Yes, aim at its data
$RETT] ;And return true
LOAD TF,ARG.HD(S2),AR.LEN ;Get length of this block
ADD S2,TF ;And step over it
JRST FNDB.1 ;And try next
SUBTTL Error Typeout Utility Routines
;ROUTINE TO TYPE DRIVE NAME FOLLOWED BY A MESSAGE
;CALLED WITH S1 POINTING TO AN $ITEXT MESSAGE TO BE TYPED AFTER THE DEVICE NAME
;On call, B must point to the TCB in question.
;The ITEXT passed must not use the S regs, or the T regs.
;This routine will send a WTOR and wait for
;an OPR response. If the response is NOT PROCEED or ABORT,
;the operator will be asked again, until the answer is right.
;Call -
; S1/ Addr of 'text' line ITEXT (can't reference S1-T4)
;For O$LERT and O$SERT only
; S2/ Addr of 'Type RESPOND <number> ABORT' to xxx ITEXT
;Returns -
; TRUE or FALSE, depending on OPRs answer
O$LERR::MOVEI S2,0 ;Clear RESPOND text
O$LERT::MOVE T4,S2 ;Save RESPOND text (if any)
MOVEI S2,[ITEXT(<Label error>)]
PJRST OPRWAT ;Type the messages, wait for ack
;Here on a structure error. Str TCB addr in B, ITEXT in S1
O$SERR::MOVEI S2,0 ;Clear RESPOND text
O$SERT::MOVE T4,S2 ;Save RESPOND text (if any)
MOVEI S2,[ITEXT(<Problem removing structure>)]
; PJRST OPRWAT ;Type the mesages, wait for ack
;Enter here to type the error and wait for OPR
; to get it right.
; S1/ Addr of 'text' field ITEXT
; S2/ Addr of 'type' field ITEXT
; T4/ Addr of RESPOND ITEXT block (0=standard ABORT, PROCEED)
OPRWAT: DMOVE T1,S1 ;Copy the two fields
JUMPN T4,OPRW.1 ;Got something good?
MOVEI T4,[ITEXT(<Type 'RESPOND ^I/number/ ABORT' to terminate this operation
Type 'RESPOND ^I/number/ PROCEED' to continue processing>)]
OPRW.1: AOS T3,G$ACK## ;Get next ack code
STORE T3,TCB.AK(B) ;Save so we can recognize RESPOND
$WTOR (<^I/(T2)/>,<^I/(T1)/^M^J^I/(T4)/>,TCB.OB(B),T3,$WTFLG(WT.SJI))
MOVX S1,TW.LBL ;Get Label wait code
STORE S1,TCB.WS(B) ;Mark in the TCB
PUSHJ P,G$NJOB## ;Set the code, and wait
ZERO TCB.AK(B) ;Clear the ack code
PUSH P,S1 ;SAVE OPR RESPONSE CODE
LOAD S1,TCB.CH(B),TC.TYP ;Get the device type
CAIN S1,%DISK ;Is it a disk?
JRST OPRW.2 ;YES
MOVEI S1,TCB.OB(B) ;Get the object block address
MOVE S1,OBJ.UN(S1) ;Get the device name
DEVTYP S1, ;Get the owners job number
SETZ S1, ;Can't
TXNE S1,TY.MDA ;DEVICE OWNED BY MDA?
SKIPA TF,[TRUE] ;YES--SET TRUE
MOVX TF,FALSE ;ELSE SET FALSE
OPRW.2: POP P,S1 ;RESTORE OPR RESPONSE CODE
POPJ P, ;RETURN EITHER TRUE OR FALSE
SUBTTL O$NTAP - Get a new tape mounted for initialization
;This routine will arrange with the operator to get a new tape mounted
; during intialization. The operator has a number of choices.
; S/he can simply mount the next tape on the initializing
; drive and continue either via AVR or Manual Volume Recognition.
; Or, S/he can RESPOND to the WTOR with ABORT or CANCEL
; to get out of the initialization state.
;Call -
; S1/ Adrs of ASCIZ type field for WTOR
; S2/ Adrs of ITEXT for text field for WTOR
; This ITEXT must not use the T's for pointers/data
; B/ TCB adrs
O$NTAP::
$CALL .SAVET ;Save the Ts
DMOVE T1,S1 ;Save the type, text pointers
NTAP.1: MOVX S1,TW.INM ;Get Initialization Mount wait state
STORE S1,TCB.WS(B) ;Let the world know
AOS T3,G$ACK## ;Get a new ack ID
STORE T3,TCB.AK(B) ;Save so we can find it later
$WTOR (<^T/0(T1)/>,<^I/0(T2)/
Type 'RESPOND ^I/number/ ABORT' to terminate this operation
Type 'RESPOND ^I/number/ PROCEED' after completing requested operation>,TCB.OB(B),T3,$WTFLG(WT.SJI))
PUSHJ P,G$NJOB## ;Run someone else
JUMPT .POPJ ;Wins, try this tape
CAXN S1,PLR%TY ;Want to retype?
JRST NTAP.1 ;Yes, do it
$RETF ;Otherwise, give the gong
SUBTTL RESPONSE command for label errors
;Enter with M pointing to incoming message
;Returns true always, but may start up a waiting process
O$CRSP::
PUSHJ P,.SAVE1 ;Save a reg
LOAD S1,.MSCOD(M) ;Get the ack number
PUSHJ P,G$FACK## ;Find TCB with that ack number
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
ZERO TCB.AK(B) ;Clear out this ack code, it's been answered
MOVEI P1,.OHDRS(M) ;Get pointer to data area
LOAD S2,ARG.HD(P1),AR.TYP ;Find out the type of argument
LOAD S1,.OARGC(M) ;Get number of arguments on the message
CAIN S1,2 ;We demand exactly two args
CAIE S2,.CMTXT ;And it must be a text arg
JSP S1,COMERR ;Not the case, OPR is out of sync
MOVEI S1,RSPTAB ;Aim at legal OPR responses
HRROI S2,ARG.DA(P1) ;Get a pointer to the OPR text
$CALL S%TBLK ;Find a match
TXNN S2,TL%EXM!TL%ABR ;A match??
SKIPA S1,[EXP OACR.R] ;Set dispatch routine for retyping
HRRZ S1,(S1) ;Get particular service routine
PUSHJ P,(S1) ;Call the service routine
PJRST G$STTF## ;Save the TF indicator for the process,
;And continue the process
;These routines set the TCB to retype or just ABORT on OPR errors
;Handle the PROCEED response
OACR.P: PUSHJ P,CHKMNT ;Waiting for MOUNT?
JUMPT OACR.R ;PROCEED IS ILLEGAL IF MOUNT WAIT
MOVEI S1,PLR%PR ;GET PROCEED CODE
MOVEM S1,TCB.AC+S1(B) ;SET IT
$RETT ;AND RETURN
;Here if we want to retype the request
OACR.R: LOAD S1,ARG.HD(P1),AR.LEN ;Get length of text
ADDI P1,(S1) ;Advance ptr to next block
LOAD S1,ARG.HD(P1),AR.TYP ;Get type of block
CAIE S1,.ACKID ;Is this block a ACK code?
JSP S1,COMERR ;No, die, we're out of sync w ORION
$ACK (<Invalid Response>,,,ARG.DA(P1))
MOVX S1,PLR%TY ;Set code to retype error
JRST OACR.S ;Go store, and retype
; Handle the RETRY response
OACR.T: MOVX S1,TS.FSE ;GET A BIT
TDNN S1,TCB.S2(B) ;FILE SEQUENCE ERROR PROCESSING?
JRST OACR.R ;NO--BAD RESPONSE
MOVEI S1,PLR%RT ;OPR SAID RETRY
MOVEM S1,TCB.AC+S1(B) ;SET IN TCB
$RETT ;RETURN
;Handle the ABORT response
OACR.A: MOVX S1,PLR%AB ;Don't retype, OPR ABORTed
OACR.S: STORE S1,TCB.AC+S1(B) ;Set retype code in TCB
$RETF ;Return false (to set in TCB)
;Little routine to return true if TCB is waiting for MOUNT
CHKMNT: LOAD S1,TCB.WS(B) ;Get wait state code
CAIE S1,TW.MNT ;MOUNT wait?
$RETF ;No, return false
$RETT ;Yes, return true
;Some storage for the RESPONSE command
RSPTAB: $STAB
KEYTAB (OACR.A,ABORT) ;ABORT ,, set bad
KEYTAB (OACR.P,PROCEED) ;PROCEED ,, return true
KEYTAB (OACR.T,RETRY) ;RETRY ,, return true
$ETAB
;Routine to cancel a WTOR. This happens if the OPR hangs a tape (AVR)
; for which PULSAR has sent a WTOR
;
;Call: B/ TCB address
;
;Ret: +1 always
CANWTO::
SKIPE TCB.AK(B) ;Waiting for OPR response ???
$KWTOR (TCB.AK(B)) ;Yes,,kill the WTOR
SETZM TCB.AK(B) ;Zap the ACK code
$RET ;Return
; Special routine to cancel a WTOR when labeler abort is processed.
; Call: MOVEI S1, text address
; PUSHJ P,O$KWTO
O$KWTO::SKIPE TCB.AK(B) ;PENDING WTOR?
$WTOR (<>,<^T/(S1)/>,TCB.OB(B),TCB.AK(B),<$WTFLG(WT.KIL!WT.SJI)>)
SETZM TCB.AK(B) ;CLEAR ACK CODE
$RETT ;RETURN
SUBTTL Debugging type-out routine
IFN FTTRACE,<
STSD.L::
$SAVE <P1,P2,P3>
$TEXT (,<Label Status:^A>)
MOVSI P2,-NUMBTS ;Get number of bits to check
MOVE P1,TCB.ST(B) ;GET THE STATUS BITS
STSD.1: HRRZ P3,BITTAB(P2) ;Get addr of word with bit to check
TDNE P1,(P3) ;Is the bit on?
$TEXT (,<^W3/BITTAB(P2)/!^A>) ;Yes, note it
AOBJN P2,STSD.1 ;Check all of them
LOAD P1,TCB.EC(B),TE.TRM ;GET THE ERROR CODE
SKIPE P1 ;
$TEXT (,<Err=^O/P1/^A>)
POPJ P, ;Return as if nothing happened
DEFINE BITS(X),<IRP X,<
XWD ''X'',[EXP TS.'X']
>
>;END DEFINE BITS
BITTAB: BITS(<VLV,PSN,INP,OUT,NTP,NOW,WLK,EXP,D1A,FFF,ERR,NFI,NFO,PSF,IHL,ATM,IUD>)
NUMBTS==.-BITTAB
>;END IFN FTTRACE
SUBTTL O$STAT Send updated status message to MDA
;This routine takes a TCB addr in B and sends a status message to
; MDA. This message is sent in response to a request
; from MDA to recognize the labels on a tape
; If the TCB is for a disk, and the caller is trying to send updated
; status to MDA because HOM blocks were just read, then:
; T1/ HOMe block id (volume id)
; T2/ Volid of next volume in structure
; T3/ Logical unit number in structure
; T4/ Structure name in SIXBIT
O$STAT::MOVE S1,TCB.DV(B) ;Get MTxnnn device name
MOVEM S1,UNIBLK+.STUNT ;Save as drive name in status block
SETZM UNIBLK+.STFLG ;Clear status word
LOAD S1,TCB.ST(B),TS.NTP ;Get offline bit from status word
STORE S1,UNIBLK+.STFLG,ST.OFL ;Save in message to MDA
JUMPN S1,STAT.1 ;Offline, don't send volume id
LOAD S1,TCB.PT(B),TP.RWL ;Get write lock bit as read from drive
STORE S1,UNIBLK+.STFLG,ST.LOK ;Set in message to MDA
LOAD S1,TCB.CH(B),TC.TYP ;Get the device type
CAIN S1,%TAPE ;Magtape?
JRST MTASTS ;Yes
CAIN S1,%DISK ;Structure?
JRST DSKSTS ;Yes
CAIN S1,%DTAP ;DECtape?
JRST DTASTS ;Yes
$RETF ;Else just give up
MTASTS: MOVX S1,.TLSTA ;Get block type - tape status
STORE S1,STSVOL+ARG.HD,AR.TYP ;Set this block for us
SETZM VOLBLK+.TLVOL ;Clear volume id
MOVE S1,TCB.LT(B) ;Get label type code
STORE S1,UNIBLK+.STFLG,TS.LAB ;Save label type code
LOAD S1,TCB.PS(B),TP.DEN ;Get density code as read from drive
STORE S1,UNIBLK+.STFLG,TS.DEN ;And put in message
MOVE S1,[POINT 6,VOLBLK+.TLVOL] ;SIXBIT ptr to volume id in message
MOVEM S1,STSPTR ;Save in ptr for $TEXT coroutine
HRRI S1,TCB.VL(B) ;Addr of volume id
HRLI S1,(POINT 8,) ;8-bit bytes
$TEXT (STSDBP,<^Q6/S1/^A>) ;Convert the VOLID to SIXBIT
STAT.1: DMOVE S1,[EXP SSBLEN,STSSAB] ;Len, adr of send arg block
$CALL C%SEND ;Off to MDA
$RETT
;A little routine to convert 8-bit ASCII to SIXBIT as $TEXT output
STSDBP: SKIPE S1 ;Null byte?
SUBI S1,40 ;No, convert ASCII to SIXBIT
IDPB S1,STSPTR ;And dump in volume block
$RETT ;And back to $TEXT
;Here to return the DECtape reelid contained in T1
DTASTS: MOVEI S1,.DLSTA ;GET BLOCK TYPE
STORE S1,STSVOL+ARG.HD,AR.TYP ;SET IN MESSAGE
MOVEM T1,VOLBLK+.DLRID ;SAVE REELID
PJRST STAT.1 ;GO SEND MESSAGE
;Here if sending valid volume status for a disk unit
;The T ACs contain valuable info!
DSKSTS: MOVEI S1,.DSSTA ;Get block type - disk status
STORE S1,STSVOL+ARG.HD,AR.TYP ;Set this block for us
MOVEM T1,VOLBLK+.DSHID ;Put in volume ID
MOVEM T2,VOLBLK+.DSNXV ;Next volume in str
MOVEM T3,VOLBLK+.DSLUN ;Logical volume (unit) in str
MOVEM T4,VOLBLK+.DSSNM ;And structure name
MOVE S1,TCB.OW(B) ;Get owner PPN
MOVEM S1,VOLBLK+.DSPPN ;Save it
JRST STAT.1 ;Go send the message
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
STSPTR: BLOCK 1 ;Space for the pointer
;Data space for the update status message to MDA
STSSAB: $BUILD SAB.SZ
$SET (SAB.LN,,STSSIZ) ;Size of the message
$SET (SAB.MS,,STSMSG) ;Addr of the message
$SET (SAB.SI,SI.FLG,1) ;Send by system PID
$SET (SAB.SI,SI.IDX,SP.MDA) ;Send to MDA
$EOB
SSBLEN==.-STSSAB ;Length of the SAB
;The message is a header, and one block
STSMSG: $BUILD .OHDRS
$SET (.MSTYP,MS.CNT,STSSIZ) ;Size of the message
$SET (.MSTYP,MS.TYP,.QOTST) ;Message type - tape status
$SET (.OARGC,,2) ;Two argument blocks
$EOB
$BUILD ARG.DA ;Device descriptor block
$SET (ARG.HD,AR.LEN,ARG.DA+.STLEN) ;Length of block
$SET (ARG.HD,AR.TYP,.STSTS) ;Device status block type
$EOB
UNIBLK: $BUILD .STLEN ;Status for device
;Contents filled in @ runtime
$EOB
STSVOL: $BUILD ARG.DA
$SET (ARG.HD,AR.LEN,VOLSIZ) ;Length of the arg block
; $SET (ARG.HD,AR.TYP,.TLVOL) ;Volume type - set at runtime (disk or tape)
$EOB
;Note - We always send the same size blocks, regardless of
; whether it is a disk or a tape.
; Hopefully, MDA will ignore the discrepancy
VOLBLK: $BUILD .DSSIZ
;Contents of this block filled in
; on a call to O$STAT
$EOB
VOLSIZ==.-STSVOL ;Length of the volume block
STSSIZ==.-STSMSG ;Length of the message
SUBTTL O$CASL - Add or remove str to user's search list
;This is the action routine for the .QOASL message from MDA
;Call -
; M/ .QOASL message addrs
O$CASL::PUSHJ P,D$SLCH## ;PROCESS SEARCH LIST CHANGE MESSAGE
$RETT ;RETURN
SUBTTL OACBLD - Build a structure
;This is the action routine for the .QOBLD message from MDA
; This routine will build at TCB for the strucutre, fill
; in the neccessary items, and set the TCB runnable.
; The structure TCB will run, requesting HOM block reading and
; all the other good stuff, and eventually, the strucutre will
; be built.
;Call -
; M/ .QOBLD message adrs
;Returns -
; Marks structure TCB as runnable to build structure
O$CBLD::
PUSHJ P,ESTRBL ;Extract the block info, setup TCB
JUMPF .POPJ ;Can't, so quit
MOVEI S1,D$SDEF## ;Where to start - Str definer
PUSHJ P,G$NPRC## ;Fire it up!
$RETT
SUBTTL OACDSM - Dismount a structure
;This is the action routine for a .QODSM directive from MDA.
;This routine will setup a process which will run the structure
; dismount code.
;Call -
; M/ .QODSM message adrs
;Returns -
; Structure TCB runnable at the structure dismounter
O$CDSM::
PUSHJ P,ESTRBL ;Get the structure info into a TCB
JUMPF .POPJ ;Can't, so quit
MOVEI S1,D$SREM## ;Routine to run - structure remover
PUSHJ P,G$NPRC## ;Start the TCB there
$RETT
SUBTTL ESTRBL - Extract structure info from a MDA message
;This routine breaks down a message from MDA and moves pertinent info into
; the TCB. The message is either a .QOBLD (Define a structure)
; or .QODSM (Dismount str). This is a common preprocessor routine since
; those messages are similar in format.
;Call -
; M/ .QOBLD or .QODSM message adrs
;Returns - TRUE:
; (FALSE if the message looks bad!)
; B/ Structure TCB adrs
ESTRBL: $SAVE <P1>
MOVX S1,.BLDSN ;Block type - structure name
PUSHJ P,FNDBLK ;Get there
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
MOVE P1,S1 ;Preserve that guy for a minute
LOAD S1,0(P1) ;Get the structure name to be built
PUSHJ P,G$FTCB## ;Get that TCB
JUMPT BLD.1 ;Got it, so run it
LOAD T1,0(P1) ;Get the str name again
SETZB T2,T3 ;Clear the extraneous stuff
PUSHJ P,G$MTCB## ;Make up some space
BLD.1: LOAD S1,1(P1) ;Get the owner's ppn
STORE S1,TCB.OW(B) ;And stuff that in the TCB
SETZM TCB.SF(B) ;Init structure flag word
LOAD S1,.OFLAG(M),.DMNCK ;Get /NOCHECK bit
STORE S1,TCB.SF(B),TS.NCK ;Set/clear it
LOAD S1,.OFLAG(M),.MTWLK ;Get /WRITE-LOCKED bit
STORE S1,TCB.SF(B),TS.HWP ;Set/clear it
LOAD S1,.OFLAG(M),.DMNRQ ;Get number of requests that need str
STORE S1,TCB.SF(B),TS.NRQ ;Save for REMCHK
LOAD S1,.OFLAG(M),.DMOSN ;Get /OVERRIDE-SET-NUMBER bit
STORE S1,TCB.SF(B),TS.OSN ;Set/clear it
MOVX S1,.BLDUN ;Block type - units
PUSHJ P,FNDBLK ;Get that block
SKIPT ;Got it?
JSP S1,COMERR ;No, complain
LOAD S2,-ARG.DA(S1),AR.LEN ;Get the length of the block
SUBI S2,ARG.DA ;Discount the block header length
LSH S2,-1 ;Get real number of units
SKIPLE S2 ;Reasonable number?
CAILE S2,MAXVOL ;Do we have space for this structure?
JRST [$WTO (<PULSAR Internal error>,<Volume list for ^W/0(P1)/: Length of ^D/S2/ is wrong>,,$WTFLG(WT.SJI))
$RETF] ;Lose
STORE S2,TCB.NV(B) ;Save the # of volids
HRRI P1,TCB.DU(B) ;Point at the Disk Unit name area
BLD.2: MOVE TF,0(S1) ;Get the next unit name
MOVEM TF,0(P1) ;Save in unit list
MOVE TF,1(S1) ;Get the next volume name (pack id)
MOVEM TF,TCB.VL-TCB.DU(P1) ;Save in volume name list
ADDI S1,2 ;Account for the words just moved
AOS P1 ;And step to next Vol/Unit entry
SOJG S2,BLD.2 ;Do each of the Vol/Unit pairs
$RETT ;Return with TCB in B
SUBTTL - Ack/Nak senders
;These routines will send positive and negative acknowledgments to
; MDA after various flavors of requests.
; Typically, these routines are called after some function has been
; completed, and the function must tell MDA success or failure.
;Call -
; S1/ Flags,,Ack code type (%CAT, %MOUNT,%DSMNT)
; S2/ SIXBIT volume set name (structure name)
; Someday, we should take a pointer to a long VSN....
; G$COD/ Ack code to identify this request from others in QUASAR
O$ACK:: TDZA TF,TF ;Get winning indicator
O$NAK:: SETOM TF ;Get losing indicator
PUSHJ P,BLDACK ;Build the ack,
ACK.1: DMOVE S1,[EXP SAB.SZ,G$MSAB##] ;Aim at the arg block
$CALL C%SEND ;Fire it off
$RETT
;Here to just build the ack
;
; TF/ 1 for NAK, 0 for ACK
; S1/ Flags,,ack type
; S2/ SIXBIT volid
BLDACK: $SAVE <P1,P2,P3> ;Preserve some regs
DMOVE P1,S1 ;Save the input args
MOVE P3,TF ;Save good/bad indicator
$CALL M%GPAG ;Get a message page
MOVEM S1,G$MSAB##+SAB.MS ;Save in send block
MOVX S2,PAGSIZ ;Size of message
MOVEM S2,G$MSAB##+SAB.LN ;Save in arg block
MOVX S2,.QOACK ;Message type - ACK
STORE S2,.MSTYP(S1),MS.TYP ;Save in message
LOAD S2,P1,.MTWLK ;Get write-locked bit
STORE S2,.OFLAG(S1),.MTWLK ;Tell QUASAR
MOVX S2,.OHDRS+ARG.DA ;Initial size of message
STORE S2,.MSTYP(S1),MS.CNT ;Count the message
HRRZS P1 ;Strip off flags
STORE P1,.MSFLG(S1),AK.TYP ;Save ack type
STORE P3,.MSFLG(S1),AK.NAK ;Set ack/nak indicator
MOVE S2,G$COD## ;Get old ack code
MOVEM S2,.MSCOD(S1) ;Identify this ack from the rest
MOVEI S2,1 ;Only one..
MOVEM S2,.OARGC(S1) ; ...argument block
MOVX S2,<ARG.DA,,.RCTVS> ;Block type - volume set name
MOVEM S2,.OHDRS+ARG.HD(S1) ;Label the block
HRRI P1,.OHDRS+ARG.DA(S1) ;Place to put volume set name
HRLI P1,(POINT 7,) ;Make a pointer to it
MOVEM P1,ACKPTR ;Save that one
$TEXT (ACKDPB,<^W/P2/^0>) ;Move in the volume set name
HRRZ S1,ACKPTR ;Get terminating word
SUBI S1,-1(P1) ;Figure # words used
HRLZS S1 ;To LH (count field)
MOVE S2,G$MSAB##+SAB.MS ;Get message adrs again
ADDM S1,.MSTYP(S2) ;Update total message length
ADDM S1,.OHDRS+ARG.HD(S2) ;And update block length
$RETT
ACKDPB: IDPB S1,ACKPTR ;Stuff the next byte
$RETT ;And get out
ACKPTR: BLOCK 1 ;Space for the byTE pointer
SUBTTL O$ACKU - User Mount/Dismount ACK processor
; O$NCKU - User Mount/Dismount NAK processor
;These routines build the ACK/NAK back to MDA when a user does a
; structure Mount/Dismount.
;
;
; CALL: S1/ Type code (%ADSTR or %DMSTR)
; S2/ Sixbit structure name
; G$COD/ Ack code to identify this request from others in QUASAR
;
; RET: True Always
O$ACKU::TDZA TF,TF ;This is an ACK !!!
O$NCKU::SETOM TF ;This is a NAK !!!
PUSHJ P,BLDACK ;Build the message
SKIPN G$TXTB## ;Any additional info ???
JRST NCKU.1 ;No,,send the ACK/NAK off
$SAVE <P1,P2> ;Save some work ACs
MOVE P1,G$MSAB##+SAB.MS ;Get the message adrs
LOAD P2,.MSTYP(P1),MS.CNT ;Get length
AOS .OARGC(P1) ;One more arg block
ADDI P2,0(P1) ;Aim at first free
MOVE S1,[TXTSIZ,,.OMTXT] ;Get the text block length,,type
MOVEM S1,ARG.HD(P2) ;Store block header
HLLZS S1 ;Get just additional length
ADDM S1,.MSTYP(P1) ;Update total message length
MOVEI S1,ARG.DA(P2) ;Get destination address
HRLI S1,G$TXTB## ;Get source,,destination address
BLT S1,ARG.DA+TXTSIZ-1(P2) ;Copy the text to the ACK/NAK message
NCKU.1: DMOVE S1,[EXP SAB.SZ,G$MSAB##] ;Aim at the arg block
$CALL C%SEND ;Fire it off
$RETT ;Return
SUBTTL O$CLST - MANIPULATE SYSTEM LISTS
;This routine is the one that finally handles the
; operators request to add or remove and file structure or
; disk unit from the system-search-list or
; the crash-dump-list, or the active-swap-list
O$CLST::
$SAVE <P1,P2>
MOVEI S1,.STRDV ;Block type
PUSHJ P,FNDBLK ;Go get it
SKIPT ;Got it?
JSP S1,COMERR ;Nope, give up
HRROI S1,0(S1) ;Aim at the block
$CALL S%SIXB ;Convert to SIXBIT
MOVE P2,S2 ;Protect the device name
MOVEI S1,.SLSTY ;Block type -List descriptor
PUSHJ P,FNDBLK ;Find it
SKIPT ;Got it?
JSP S1,COMERR ;No, Oh well
LOAD P1,0(S1),SL.TCD ;Get the list ID
HRRZ S2,ADDTAB-SL.TMN(P1) ;Assume we want to add
MOVE S1,P2 ;Put back the device name
LOAD TF,.OFLAG(M),AD.REM ;Get the removal bit
SKIPE TF ;Is it really remove?
HLRZ S2,ADDTAB-SL.TMN(P1) ;Yes, get the removal adrs
PUSHJ P,0(S2) ;Add it, or remove it
PUSHJ P,@POSTAB(P1) ;Do whatever is customary at completion
$RETT
;Table of removal routines,,add routines
ADDTAB: XWD D$RSSL##,D$ASSL## ;System Search List
XWD D$RCDL##,D$ACDL## ;Crash Dump List
XWD D$RSUN##,D$ASUN## ;Active swap list
;Table of post-removal/addition routines
POSTAB: EXP CPOPJ
EXP CPOPJ
EXP CPOPJ
CPOPJ: $RETT
SUBTTL O$SLST - SHOW SYSTEM LISTS
;This routine pre-processes the message from OPR
; requesting information about various system lists
; Then it calls P$SLST to do the display
O$SLST::
MOVEI S1,.SLSTY ;Block type - list descriptor
PUSHJ P,FNDBLK ;See if there is one
JUMPF SLST.1 ;Is there a list block?
MOVE S1,0(S1) ;Yes, get the list type
SKIPA S1,LSTBLK-SL.TMN(S1) ;Load the right bit
SLST.1: MOVE S1,[EXP DS.ALL] ;No list block, show all lists
PJRST P$SLST## ;Go do the work
LSTBLK: EXP DS.SSL ;Display the system search list
EXP DS.CDL ;Display the crash dump list
EXP DS.ASL ;Display the active swapping list
END