TITLE SETSPD - Execute x-CONFIG.CMD and Copy System Dumps
SEARCH MONSYM,MACSYM,SERCOD,CMD
.CPYRT <<1976, 1988>>
.REQUIRE SYS:MACREL ;Use MACREL routines
.REQUIRE SYS:CMD ;Use CMD package
SALL ;Suppress ugly MACRO expansions
.DIRECTIVE FLBLST ;Only first line binary in the listing
; This program is run by job 0 to perform various user-mode functions
; that affect the operation of the system. Depending upon the desired
; action, the program is started at one of several positions in its
; entry vector. SETSPD.EXE should be copied to BS:<SYSTEM>x-y-SETSPD.EXE,
; where "x" is the major version number and "y" is the minor version number
; of the monitor (if any).

SUBTTL Version Number
;[7.1081] Clean up general comments
; VERSION NUMBER DEFINITIONS
VMAJOR==7 ;Major version of SETSPD
VMINOR==0 ;Minor version number
VEDIT==^D253 ;Edit number
VWHO==0 ;Group who last edited (0=DEC development)
VSTSPD==VI%DEC+<VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT
;Define registers used
A==1 ;[7.1081] Old code used A/B/C/D
B==2 ;[7.1081]
C==3 ;[7.1081]
D==4 ;[7.1081]
STDAC. ;[7.1081] New code uses standard ACs

SUBTTL Entry Vector
;[7.1235][7.1081] Update comments about entry vector
;
; Pos Description
; --- --------
;
; 0 This is the normal starting entry for programs. If SETSPD is started
; here then it will read from the terminal instead of n-CONFIG.CMD.
; Running SETSPD this way is reccomended for debugging new n-CONFIG
; commands or for an occasional interactive command using SETSPD. This
; entry point is not used by the monitor.
;
; 1 Called once during system startup by RUNDD routine in MEXEC.
; Reads file "SYSTEM:x-CONFIG.CMD" for commands such as ENABLE,
; DISABLE, CHANGE, DEFINE, HOST, NODE, MAGTAPE, PRINTER, TERMINAL,
; and so on.
;
; 2 Contains TOPS-20 standard program version number.
;
; 3 Called by RUNDD routine in MEXEC during system
; initialization after a crash to:
; 1. Copy PS:<SYSTEM>DUMP.EXE to DMP:DUMP-nnn-xxx.CPY
; where "nnn" is the monitor's edit number and "xxx"
; is the BUG name that caused the dump.
; 2. Extract unrecorded SPEAR entries from DUMP.EXE and
; log them using the SYERR JSYS.
;
; 4 Called by CHKR routine in MEXEC while system is running
; whenever PHYSIO detects that a tape drive has come online
; and PHYSIO didn't know about the drive at system startup.
; The x-CONFIG file is read as if entered at entry vector
; position 1, except only the "MAGTAPE" commands in the
; file are processed; all other commands are ignored.
;
; 5 Called by the CHKR routine in MEXEC when a Dump On BUGCHK
; dump has been created, looks on all dumpable structures for
; a dump to copy from str:<SYSTEM>DUMP.EXE to DMP:DUMP-nnn-xxx.CPY.
;[7.1081] Program entry vector
ENTVEC: JRST START0 ;[7.1235][7.1081] Starting location
MONVEC: JRST START1 ;[7.1081][63] The monitor starts SETSPD here
VSTSPD ;[7.1081] Version number
JRST START3 ;[7.1081][63] Entry point for making DUMP.CPY
JRST START4 ;[7.1081][63] MTA/DISK online entry vector
JRST START5 ;[7.1081] Copy continuable dump
ENVLEN==.-ENTVEC ;[7.1081] Entry vector length

; HERE TO SET THE "IGNORE INPUT" (NO BELLS) BIT
NOBELL: HRRZ D,LINES ;GET LAST LINE NUMBER
HLRZ B,LINES ;GET FIRST LINE NUMBER
SUBI B,1(D) ;FORM - NUMBER IN RANGE
HRLI D,(B) ;FORM AN AOBJN POINTER TO LOOP
HLR D,LINES ; OVER ALL THE LINES IN THE RANGE
NOBEL1: MOVEI A,.TTDES(D) ;[63] Get line designator
MOVX B,.MOSIG ;SET "IGNORE INPUT" BIT
MOVX C,1 ;TURN THE BIT ON
MTOPR ;SET THE LINE TO IGNORE CHARACTERS UNTIL OPENED
ERJMP .+1 ;IGNORE FAILURE HERE
AOBJN D,NOBEL1 ;LOOP OVER ALL THE LINES IN THE INDICATED RANGE
JRST LINKEY ;GO GET THE NEXT KEYWORD IN THE COMMAND

;Ignore system messages for terminal lines
IGNORE: HRRZ D,LINES ;[64] Get last line number
HLRZ B,LINES ;[64] Get first line number
SUBI B,1(D) ;[64] Form - number in range
HRLI D,(B) ;[64] Make AOBJN pointer for loop
HLR D,LINES ;[64] Do all lines in range
IGNOR1: MOVEI A,.TTDES(D) ;[64] Get line designator
MOVX B,.MOSNT ;[64] Ignore system messages function
MOVX C,.MOSMN ;[64] Tell line to refuse system messages
MTOPR% ;[64] Do it
ERJMP .+1 ;[64] Don't care about failure
AOBJN D,IGNOR1 ;[64] Do all lines when there is a range
JRST LINKEY ;[64] Go get next keyword in command

;Ignore user messages for terminal lines
IGUMSG: HRRZ D,LINES ;[64] Get last line number
HLRZ B,LINES ;[64] Get first line number
SUBI B,1(D) ;[64] Form - number in range
HRLI D,(B) ;[64] Make AOBJN pointer for loop
HLR D,LINES ;[64] Do all lines in range
IGUMS1: MOVEI A,.TTDES(D) ;[64] Get line designator
MOVX B,.MOSTF ;[64] Ignore user messages function
MOVX C,<MO%NUM!MO%NTM> ;[64] Make line ignore all SENDs
MTOPR% ;[64] Do it
ERJMP .+1 ;[64] Don't care about failure
AOBJN D,IGUMS1 ;[64] Do all lines when there is a range
JRST LINKEY ;[64] Go get next keyword in command

SUBTTL Commands -- TIMEZONE
;SET LOCAL TIME ZONE; IT MUST BE A NUMBER FROM -12 TO 12
TIMZON: MOVEI A,[FLDDB. .CMNUM,CM%SDH,5+5,<timezone number>]
CALL CFIELD ;GET NUMBER AND CONFIRMATION
MOVM D,B ;CHECK IT FOR RANGE
CAILE D,^D12 ;MUST BE FROM -12 TO 12 DECIMAL
ERROR (<Timezone must be -12 to 12 inclusive>,<JRST CMDER1>)
MOVEI A,.SFTMZ ;SET TIME ZONE
SMON ;ARGUMENT IN B
JSYERR (<Unable to set TIMEZONE>)
RET ;DONE

;[7.1081] Get bugname and monitor edit information from the dump
HRRZ T1,PG0ADR+2 ;[7.1081] Look for process page 0
SKIPE T1 ;[7.1081] Is this the entry for page 0?
IFSKP. ;[7.1081] Yes, map it to get vers and name
HRLZ T1,QUEJFN ;[7.1081] Get the file JFN
HRR T1,PG0ADR+1 ;[7.1081] Get the page number in the file
MOVX T2,<.FHSLF,,PG1PG> ;[7.1081] Map it to this page
PMAP ;[7.1081] so we can look at it
ERJMP .+1 ;[7.1081] If error we'll probably get zeroes
MOVE T1,PG1ADR+.JBVER ;[7.1081] Get edit info of monitor from dump
MOVEM T1,BUGVER ;[7.1081] Save it for filename
MOVE T1,PG1ADR+.JBBNM ;[7.1081] Get the bug name (SIXBIT)
MOVEM T1,BUGNAM ;[7.1081] Store that too
ELSE. ;[7.1081]
SETZM BUGVER ;[7.1081] No version found
SETZM BUGNAM ;[7.1081] No bug name found
ENDIF. ;[7.1081]
;[7.1081] Finally, copy the dump
HRRZ T1,QUEJFN ;[7.1081] Get JFN of original dump file
MOVE T2,QUEPGS ;[7.1081] Get highest page number to copy
CALL CPYDMP ;[7.1081] (T1,T2/) Copy the dump file
SKIPE @QUEFAD ;[7.1081] Dump written by BOOTS?
JRST QUEDON ;[7.1081] No - skip SYSERR stuff
;[7.1081] Yes, fall through

SUBTTL System Dumps -- Process a Dump -- Finish Up
;[7.1081] Here to unmap pages, kill fork, close JFNs, and return
;Sets the DUMP.EXE file as "copied"
QUEDON: ;[7.1081] Start of cleanup/exit code
IFN FTSC,< ;[7.1081]
CALL SETCNT ;[7.1081] Set SPEAR count if needed
> ;[7.1081]
SKIPN QUEJFN ;[7.1081] Did we get a open JFN on DUMP.EXE?
RET ;[7.1081] No, return now
SKIPE QUEFAD ;[7.1081] If a flag address is used
SETOM @QUEFAD ;[7.1081] Now mark that we have copied it
SETO T1, ;[7.1081] Unmap that page
MOVE T2,[.FHSLF,,PG0PG] ;[7.1081] Do all of the pages we need
MOVX T3,PM%CNT!<ENDPG-PG0PG> ;[7.1081] Unmap all of these pages
PMAP ;[7.1081] Zap
ERJMP .+1 ;[7.1081] We certainly don't care now
CALL FLUSH ;[7.1081] () Flush incore copy to disk
SKIPE T1,QUEJFN ;[7.1081] Skip if no JFN to close
CLOSF% ;[7.1081] Yes, close it
JSYERR (<Can't close JFN for DUMP.EXE>) ;[7.1081] Entered garkland
RET ;ALL DONE

SUBTTL System Dumps -- Process a Dump -- Flush Incore Pages
;[7.1081] Small routine to flush incore pages to disk. This is needed since
;[7.1081] DOB code writes directly to disk. We have to make sure that we get a
;[7.1081] copy from disk and not from any copy that is still in memory.
FLUSH: MOVE T1,QUEJFN ;[7.1081] Load the JFN of DUMP.EXE
SIZEF% ;[7.1081] Get the size of that file
JSYERR (<Can't get size of DUMP.EXE file>)
MOVEM T3,QUESIZ ;[7.1081] Save size of the DUMP.EXE file
HRLZ T1,QUEJFN ;[7.1081] Load JFN of DUMP.EXE,,page 0
MOVE T2,T3 ;[7.1081] Get count of pages to update
TXO T2,UF%FSH ;[7.1081] Don't keep incore copy
UFPGS% ;[7.1081] Flush incore copy of these pages
JSYERR (<Can't flush pages of DUMP.EXE before mapping>) ;[7.1081] Owie
RET ;[7.1081] Always return

SUBTTL System Dumps -- Process a Dump -- Mount Dump Structures
;Routine to mount the structure (all of it) that is implied by the expansion
;of DMP:.
STRMOU: MOVEI T1,RTYTIM ;[7.1081] Get number of retry times
MOVEM T1,TIMVAL ;this is for CI disks
STRRTY: ;here is our retry entry point
MOVX T1,.LNSSY ;Lookup a system-wide logical name
HRROI T2,[ASCIZ |DMP|] ;Logical name without colon
SETZ T3, ;We don't want the translation
LNMST ;See if a logical name DMP:
RET ;Return now if no DMP:
MOVX T1,<GJ%SHT!GJ%OFG> ;This is the short form and parse only
HRROI T2,[ASCIZ |DMP:|] ;Logical name for dump structure
GTJFN ;Get a parse only JFN on DMP:
RET ;If it fails, leave now
HRRZM T1,T2 ;Set up the JDN in the right place
HRROI T1,DMPSTR ;Loc for the name of the structure
MOVX T3,FLD(.JSAOF,JS%DEV) ;Only output device field
SETZ T4, ;No file attribute
JFNS% ;Get the device implied by DMP:
ERJMP R ;[7.1081] Fail and try default
HRROI T1,DMPDIR ;[7.1081] Get the directory implied by DMP:
MOVX T3,FLD(.JSAOF,JS%DIR) ;[7.1081] Do directory field
JFNS% ;[7.1081] Get the directory name
ERJMP R ;[7.1081] Forget it
HRROI T1,DMPSTR ;Point to that structure name
STDEV ;String to device designator
IFSKP. ;[7.1081] If it worked
HRROI T1,DMPSTR ;[7.1081] Point to structure name
MOVEM T1,MSTRAD+.MSDEV ;[7.1081] Store it in MSTR block
MOVE T1,[XWD .MSJOB,.MSIMC] ;[7.1081] Length,,Function
MOVEI T2,MSTRAD ;[7.1081] Point to MSTR block
MSTR% ;[7.1081] Increment the mount count
ERJMP .+2 ;[7.1081] Not necessary, don't set flag
SETOM CPYINC ;[7.1081] Say we incremented the mount count
RET ;[7.1081] and return
ENDIF.

;Here when we have real work to do. Loop over all disks looking for all units
;in the dump structure.
SETOM MSTRAD+.MSRCH ;Start with the first unit
SETOM MSTRAD+.MSRCT ; and the first controller
SETOM MSTRAD+.MSRUN ; and the first unit
DSKLOP: MOVE T1,[XWD .MSRLN,.MSRNU] ;Length of args,,function code
MOVEI T2,MSTRAD ;Address of the MSTR block
HRROI T3,CURSTR ;Byte pointer to the name of current structure
MOVEM T3,MSTRAD+.MSRSN ;Store in the arg block
HRROI T3,ALISTR ;Byte pointer to current structure alias
MOVEM T3,MSTRAD+.MSRSA ;Store it in the arg block
MSTR ;Get disk info
ERJMP MSTRER ;Handle an MSTR failure
HRROI T1,CURSTR ;Get the name of the current structure
HRROI T2,DMPSTR ;Is this the one we seek (Sorry)
STCMP ;Compare the strings
SKIPN T1 ;Are the strings the same???
JRST FNDSTR ;We have found the structure, go mount it
JRST DSKLOP ;Loop for more disks

; Here when we have found the disk name we are looking for and are ready to
;mount the critter. But first we must loop to find the other units and build
;the mount block.
FNDSTR: HRRZ T1,MSTRAD+.MSRNS ;Get the number of units in this structure
MOVEM T1,NUMUNT ;Store
MOVEM T1,UNTLFT ;Also store as the number of units left to find
UNTLOP: SOS UNTLFT ;Show that we have touched this unit
HLRZ T1,MSTRAD+.MSRNS ;Get the unit number within the structure
IMULI T1,.MSTNO ;Multiply by the block size to get the offset
ADDI T1,<MNTBLK+.MSTUI> ;Now make it the base addr of the unit block
MOVE T2,MSTRAD+.MSRCH ;Get the channel number
MOVEM T2,.MSTCH(T1) ;Store the channel number in the unit block
MOVE T2,MSTRAD+.MSRCT ;Get the controller number
MOVEM T2,.MSTCT(T1) ;Store in unit block
MOVE T2,MSTRAD+.MSRUN ;Get the unit number
MOVEM T2,.MSTUN(T1) ;Store in the unit block
SKIPG UNTLFT ;Are there any more units left to be done???
JRST MNTDSK ;No, mount the disk
NXTUNT: MOVE T1,[XWD .MSRLN,.MSRNU] ;Arg block len,,function code
MOVEI T2,MSTRAD ;Point to the arg block
HRROI T3,CURSTR ; Re-initialize the string
MOVEM T3,MSTRAD+.MSRSN ; pointers for the structure name
HRROI T3,ALISTR ; and alias
MOVEM T3,MSTRAD+.MSRSA ; before comparing each unit
MSTR ;Get the status of the next unit
ERJMP MSTRER ;handle an MSTR failure
HRROI T1,DMPSTR ;Get the name of the dump structure
HRROI T2,CURSTR ;Do they match???
STCMP ;Compare the strings
SKIPE T1 ;Do they match???
JRST NXTUNT ;No, dont count this one in unit list
JRST UNTLOP ;Loop to get all the units