Google
 

Trailing-Edge - PDP-10 Archives - BB-4172H-BM - language-sources/mountr.mac
There are 35 other files named mountr.mac in the archive. Click here to see a list.
TITLE	MOUNTR
SUBTTL	1-Jan-82

;
;
;
;              COPYRIGHT (c) 1979,1980,1981,1982 BY
;           DIGITAL EQUIPMENT CORPORATION, MAYNARD, MA.
;
;     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.



; Version Information

	VMAJOR==4		;MAJOR VERSION #
	VMINOR==2		;MINOR VERSION #
	VEDIT==153		;EDIT #
	VWHO==0			;GROUP WHO LAST EDITED (0=DEC DEVELOPMENT)

	VERS==<VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT


	SEARCH MONSYM,MACSYM,ACTSYM,SERCOD,GLXMAC,QSRMAC,ORNMAC
	.REQUIRE SYS:MACREL

	EXTERN .JBOPS		;JOBDAT CELL COMMANDEERED FOR TEST FLAG
	EXTERN .JBSA		;LH/ ADDR OF 1ST LOCATION AFTER PROGRAM
	EXTERN .JBSYM		;POINTER TO SYMBOL TABLE FOR DDT
	EXTERN .RLEND		;LAST LOCATION IN MACREL

	SALL
	.DIRECTIVE FLBLST	;SUPPRESS ASCIZ MACHINE CODE EXPANSION
SUBTTL	Edit history

;153 - Make Data Error a non-fatal interrupt and simply report it to the
;      operator
;
;152 - Report unload error to operator.
;
;151 - ALLOW LONGER I/O JSYS TIMEOUT PERIOD.
;
;137	Increase MAXDSK to 100 to allow 64 mountable disks so that 
;	the 16 structures promised in documentation are available.
;
;136	Add disposition field to the magtape and structure account
;	status blocks.  Output disposition with rest of usage record.
;
;135	Change .OT??? symbols to be .OD??? symbols (operator commands).
;
;134	Update copyrights. Add Edit history. Make it rememble GALAXY progs.
;
;EDIT 133 - MAKE MOUNTR IGNORE NULL ACKS FROM QUASAR.
;
;EDIT 132 - ALLOW RECOVERY FROM MONX06.
;
;EDIT 131 - REMOVE EDIT 130 FOR POST 4.1 AND MAKE THIS VERSION 4.2.
;
;EDIT - 130 Add local symbols which are usually found in other files.
; This edit is for this release only.
;
;EDIT - 127 Remove edit 105. Edit 124 will report USAGE failure and edit
; 120 should prevent all occurances of bad numbers in the usage block.
;
;EDIT - 126 Remove edit 116. CHKPNT does this.
;
;EDIT - 125 Clean up account blocks if non-regulated structure is physically
; mounted. Correctly check for domestic structure.
;
;EDIT - 124 Don't crash if DIRST or USAGE fails.
;
;EDIT - 123 Make magtape account block code be pre-association.
;
;EDIT - 122 Set flag R%DSM for OPR originated dismount request.
;
;EDIT - 121 Ring bell for a mount request.
;
;EDIT - 120 Reorganize accounting to make times more meaningful.
; Rework edit 117 to insure that no account blocks are lost if a request is
; cancelled during a volume switch.
;
;EDIT - 117 Insure preservation of accounting blocks on volume switch.
;
;EDIT - 116 Have elapsed time of use be in seconds not difference of GTADs.
;
;EDIT - 115 Do not allow a user to get an unlabelled tape twice without
; operator intervention.
;
;EDIT - 114 Change SHOW STATUS DISK-DRIVE display to be readable with no
; abbreviations. Use TMCTN and TMCTO macros to set up args for TMCT0 and
; call TMCT0.
;
;EDIT - 113 Add program name and version to USAGE records.
;
;EDIT - 112 Change .OTxxx symbols back.
;
;EDIT - 111 Remove edit 71.
;
;EDIT - 110 Display users remark during tape set request.
;
;EDIT - 107 Correctly clear account blocks during their allocation.
;
;EDIT - 106 Improve processing of MOUNTR.CMD to make DEFAULT function
; correctly.
;
;EDIT - 105 Insure that usage records do not contain bad numbers.
;
;EDIT - 104 Improve structure dismount logic in regard to MS%DIS.
;
;EDIT - 103 Shorten structure options to make OPR display more readable.
;
;EDIT - 102 Delete invalid structure definitions left over from pre-edit 101
;
;EDIT 101 - Make major changes to magtape accounting. Also fix mispelling
; from edit 77.
;
;EDIT 100 - Fix a bug in new RP20 code. In DDSLOP use ac T2, not T1.
;	    Also, change the .OTxxx operator symbols to .ODxxx
;
;EDIT 77 - Do not give an unlabelled tape to any user after it has
; been DISMOUNTED unless the operator IDENTIFYs it.
;
;EDIT 76 - Report offline status of disk drive to OPR.
;
;EDIT 75 - Prevent problem of MOUNTR crashing with invalid
; simultaneous access if LPTSPL has a tape drive.
;
;EDIT 74 - Give more complete structure status.
;
;EDIT 73 - Don't set OF%OFL when opening tspe or offline check will
; be ignored.
;
;EDIT 72 - Load STR correctly in KSST. Fixes memory trashing problem.
;
;EDIT 71 - Make serviced date/time of structure mount accurate.
;
;EDIT 70 - Store device designator in account block.
;
;EDIT 67 - Do not ask operator for next volid when initializing unlabelled
; tapes.
;
;spr 20-14504 Change .SICNT to .SICTR. Also change the MOVE to a HLRZ at
;	location NOS2 and TABDUP.
;
;
;TCO 5.1047 - ADD RP20 SUPPORT
;
;TCO 5.1023 -- Get more unique PID name and enhance messages when deubgging
;
;TCO 4.2605 - Get disk characteristics after mounting structure
;Correct structure mount count in accounting record
;
;REMOVE STRUCTURE STATUS CODE FROM DISK STATUS CODE IN DDSCIH
;
;ADD ERCAL FOR MSTR IN STRDM3:
;
;UPDATE COPYRIGHT DATE
;
;TCO 4.2587 - CLASSIFY TAPES WITHOUT HDR1'S AS UNLABELED
;
;Return to user immediately if structure not found for dismount
;
;MAKE MOVES IMMEDIATE IN REARNG
;
;MOVE TEST FLAG TO WRITE-PROTECTED AREA
;CHANGES TO STOP ROUTINE:  REMOVE CHECKS FOR RUNNING DETACHED,
;IF CRASH FILE WASN'T CREATED, MAKE SURE MOUNTR SAYS WHY
;TCO 4.2560 - DEFEND AGAINST HUNG TAPE DRIVES CAUSING MOUNTR TO HANG
;
;PUT STRUCTURE ACCOUNTING BACK IN
;
;CHECK IF STRUCTURE JUST MADE AVAILABLE IN DDSCIH
;
;TCO 4.2539 - GIVEN A TOPS-20 TAPE OWNED BY USER X, PERMIT OPERATOR TO
;SCRATCH IT WITH IDENTIFY COMMAND ONLY FOR A SCRATCH REQUEST FROM USER X
;ALSO... CHANGE TEXT IN ACKNOWLEDGMENT TO OPR DELETE COMMAND
;FROM "DELETED" TO "CANCELED"
;
;TCO 4.2526 - CHANGE MONX01 TO MREQ31
;
;TCO 4.2508 - WRITE-PROTECT PURE PROCEDURE
;REPLACE LOST INSTRUCTIONS IN SYTSET ROUTINE
;
;TCO 4.2505 - USE GJ%OLD IN GTJFN IN GTINAM ROUTINE
;
;TCO 4.2501 - GIVE SPECIFIC-VOLID REQUESTS PRIORITY OVER SCRATCH
;
;CORRECT IGNORED STRUCTURE CODE
;
;Implement SET DISK-DRIVE command for OPR
;
;CHECK FOR DRIVE NOT BEING WRITE-LOCKED IN DDSCIH
;ALLOW FOR NEW DRIVES COMING ON-LINE TO BE INSERTED BETWEEN OLD DRIVES
;
;FIX DIAGNOSTIC WHEN IDENTIFYING REQUEST THAT IS WAITING FOR WTOR
;
;TCO 4.2432 - CLEAR SJ%REW IF SJ%OFS IS SET
;
;FIXUPS FOR EXTENDED ADDRESSING
;
;TCO 4.2353 - CHANGE PS:<SYSTEM>DEVICE-STATUS.BIN TO SYSTEM:...
;
;TCO 4.2346 - FIX VOLUME-PROTECTION BUGS FOR TOPS-20 TAPES
;
;TCO 4.2343 - CHANGE "UNLOAD" TO "DISMOUNT TAPE" IN WARNING MESSAGE
;
;PRINT PHYSICAL NAME OF STRUCTURE IF NOT SAME AS ALIAS
;
;MOUNT ALL POSSIBLE STRUCTURES AT MOUNTR STARTUP
;TCO 4.2324 - ALLOW MAX TOPS-20 RECORD SIZE WHEN READING FOR VOL1
;
;MORE OF SAME
;
;
;CORRECT CODE FOR MULTI-PACK STRUCTURES COMING ON-LINE
;
;CHANGE "LINE" TO "TERMINAL" IN OPR MESSAGES (%U)
;
;CORRECT LOSING ALIAS FOR DISMOUNT IF ASKING OPR IF OK TO PROCEED
;
;COSMETIC FIXUPS, REMOVE ";" FROM TITLE COMMAND FOR JUDY
;TELL OPR IF WRONG VOLID KEYED IN FOR AVR-OFF DRIVE
;
;
;CHANGE OPR MESSAGE TITLE FOR SHOW DISK STATUS
;
;ALWAYS REWRITE LABELS OF SCRATCH TAPE WHEN GIVING IT TO USER
;
;MAKE CLRTAP RETURN +1 IF GDSTS TIMES OUT, +2 OTHERWISE
;
;MORE WORK ON MATCHING STRUCTURE REQUESTS TO PACK ON-LINE
;
;FIX BUGS IN PREVIOUS EDIT:
;1 - CHANGE MOVE ac,RSBLT TO LOAD ac,RSBLT
;2 - ADD INDEX REGISTER (RSB) TO MOVE ac,RSBUNO
;
;REMOVE VOLUME-INITIALIZATION FEATURES THAT WERE USED BY CHECKD
;ADD DECTAPE SUPPORT UNDER NOSHIP
;
;FIX REQRSB - PRESERVE T1 ON +1 RETURN, SCAN ABORTED RSB'S TOO
;
;MAKE STACK LARGER
;
;SET UP RSBASN BEFORE CALLING MOLOC
;
;OPR DISMOUNT COMMAND, CHANGE OPR DISPLAY FOR DISMOUNT REQUESTS
;
;FIX BUGS IN OPR SWITCH COMMAND
;
;ADD JOB MESSAGES
;ADD SUPPORT FOR SWITCH COMMAND IN OPR
;IMPLEMENT NEW SHOW STATUS COMMANDS, REMOVE SHOW PARAMETERS
;DON'T WTO FOR MOUNT IF REQUESTED VOLUME IS BEING AVR'ED
;REWORK TMC TO USE %-SEQUENCES INSTEAD OF SUBROUTINES
;PERMIT UNNAMED UNLABELED SCRATCH TAPES
;REJECT "SET TAPE INIT" IF A USER HAS THE DRIVE
;ADD GJ%ACC TO GTJFN CALLS TO PREVENT TAMPERING BY OTHER FORKS
;INHIBIT ERROR LOGGING FOR REWIND OPERATIONS
;REMOVE WTOR FOR MOUNTING TAPES
;ADD SUPPORT FOR OPR COMMANDS: IDENTIFY, DELETE
;
;MAKE MOUNTR SAVE CRASH FILES IN SPOOL DIRECTORY
;
;IN EIHR, CLEAR IRETF BEFORE DEBRKING TO SCHEDULER
;SPECIAL-CASE UNLABELED VOLUME-SWITCH TO THE SAME VOLUME
;ADD SPECIAL CODE FOR CALLING STOP WHEN P IS KNOWN TO BE BAD
;
;DON'T SEND IPCF REPLIES (TELUSR) FOR OPR-GENERATED REQUESTS
;
;CHANGE MULTIPLE-MOUNTR PROTECTION TO WORK FROM MDA SYSTEM PID
;MISCELLANEOUS DISPLAY CLEANUP
;
;ADD MULTIPLE-MOUNTR PROTECTION
;REMOVE REQUIREMENT FOR VOLID WHEN INITIALIZING UNLABELED TAPES
;SET R%PRIV IN GORSB
;ADD SUPPORT FOR TAPE-RECOGNITION-ERRORS COMMAND IN CONFIG FILE
;REMOVE TAPE-MOUNT DEFAULTS
;MAKE ACCOUNTING CHANGES
;ACCEPT OPNX8 IN MTAOPx, FIX BUSY-WTB CRASHES AGAIN
;
;ADD CODE TO PARSE "SET TAPE INIT" MESSAGE FROM OPR/ORION/QUASAR
;
;STOP COMND JSYS CRASHES WHEN PARSING NULL RESPONSE FROM WTOR
;
;FIX BUGS IN KVI
;
;ADD MISSING CALL TO MTARJF IN AVR
;FIX LOGIC IN DDSADD/DDSMCH THAT CAUSED AREQ TO BE CALLED WITH RSB/ 0
;
;FIX MISCELLANEOUS BUGS, LAY GROUNDWORK FOR SET TAPE INITIALIZE,
;LET OPERATOR RESPOND TO TAPE MOUNT WITH DRIVE NAME
SUBTTL PREFACE
COMMENT ^

MOUNTR - THIS PROGRAM CONTOLS MAGNETIC TAPE AND  STRUCTURE  MOUNT
REQUEST QUEUEING AND PROCESSING UNDER TOPS-20. IT INTERFACES WITH
QUASAR, ORION, NON-PRIVILEGED USER-MODE PROGRAMS  (TOPS-20  EXEC,
ET AL), AND THE SYSTEM OPERATOR.

ACCUMULATOR CONVENTIONS:

F, Q1-Q3, AND SPECIAL-PURPOSE AC'S (E.G. MTA)  ARE  PRESERVED  BY
SUBROUTINES, WHILE T1-T4 AND CX MAY BE CLOBBERED. SOME MACROS USE
CX TO LINK TO DRIVERS, SO BE  CAREFUL.  F  CONTAINS  PROGRAM-WIDE
FLAGS THAT MAY BE MODIFIED AND TESTED BY ANY ROUTINE  THAT  NEEDS
THEM. MACRO DRIVERS GENERALLY PRESERVE T1-T4.

INTERRUPT-LEVEL OPERATION:

TO  MINIMIZE  THE  POSSIBILITY  OF  TIMING  BUGS,  PROCESSING  AT
INTERRUPT LEVEL WILL BE KEPT TO AN ABSOLUTE  MINIMUM.  INTERRUPTS
FROM SOURCES EXTERNAL TO THE PROGRAM ARE  PROCESSED  AT  PRIORITY
LEVEL 3 (DEFINED BY "PRIEXT" EQUATE). TYPICALLY, THE ONLY  ACTION
TAKEN IS TO REQUEST  THAT  THE  SCHEDULER  PASS  CONTROL  TO  THE
APPROPRIATE EVENT PROCESSOR AT  NON-INTERRUPT  LEVEL  (ALL  EVENT
PROCESSOR TAGS  END  IN  "IH").  DEBRK  IS  DONE  EITHER  TO  THE
INTERRUPTED PC OR TO THE BEGINNING OF  THE  SCHEDULER,  DEPENDING
UPON THE SETTING OF THE FLAG, IRETF. ALL  PANIC-CHANNEL  ACTIVITY
OCCURS AT LEVEL 1 (DEFINED BY "PRIPAN" EQUATE).

ASSOCIATED PROCESSES:

THIS PROGRAM RELIES UPON SEVERAL OTHER SYSTEM  TASKS  TO  PERFORM
ITS FUNCTIONS. THESE ARE REFERRED TO AS  "ASSOCIATED  PROCESSES",
ABBREVIATED A/P. PARALLEL A/P  TABLES  ARE  MAINTAINED  IN  CORE,
INDEXED BY THE A/P INDEX  (A SMALL INTEGER  ASSOCIATED  WITH  THE
PROCESS).

RESTARTABILITY:

IT IS INTENDED THAT MOUNTR BE RESTARTABLE  WITH  A  MINOR  IMPACT
UPON  SYSTEM  PERFORMANCE.  SOME  OF  THE  PROBLEMS  CREATED   BY
RESTARTING THE PROGRAM ARE:

     1.	ALL STRUCTURE-MOUNT AND ACCOUNTING INFORMATION IS LOST.
     2.	ALL ACCOUNTING INFORMATION FOR CURRENTLY-MOUNTED TAPES IS
	LOST.
     3.	ALL TAPE-MOUNT REQUESTS THAT HAVE NOT BEEN ASSIGNED AN MT
	DEVICE ARE LOST.
     4. USERS WITH MT DEVICES MAY CONTINUE USING  THEM,  BUT  ANY
	ATTEMPT AT A VOLUME SWITCH WILL RECEIVE AN ERROR.

WRITE-PROTECTION:

AS A SECURITY MEASURE,  THE WRTP ROUTINE WRITE-PROTECTS  AS  MUCH
OF MOUNTR AS POSSIBLE TO GUARD AGAINST STRAY STORES.

EXTENDED ADDRESSING:

THOUGH MOUNTR WILL NOT NORMALLY RUN IN A  NON-ZERO  SECTION,  ITS
CODE SHOULD NOT PRECLUDE THAT POSSIBILITY. BECAUSE OF THE VARIETY
OF JSYS'S IT EXECUTES, MOUNTR  CAN  BE  OF  GREAT  ASSISTANCE  IN
TESTING THE USER-MODE EXTENDED ADDRESSING FEATURES OF THE MONITOR.

TEST MODE:

PLACING A NON-ZERO VALUE IN LOCATION 137 (.JBOPS) BEFORE STARTING
MOUNTR  WILL  CAUSE  MOUNTR  TO  RUN  IN  A  TESTING  MODE  (THIS
CONVENTION IS ADOPTED  FROM  THE  GALAXY  WORLD).  THE  ESSENTIAL
DIFFERENCES FROM LIVE MODE ARE THAT MOUNTR WILL TALK  TO  PRIVATE
GALAXY COMPONENTS, AND IT WILL REFRAIN FROM DOING  THINGS  (E.G.,
ASSIGNING MTA DEVICES) THAT WOULD INTERFERE WITH THE OPERATION OF
THE REAL MOUNTR.
^
SUBTTL PROGRAM-WIDE MACROS

; MACRO TO PROVIDE A VALUE 1 GREATER THAT IT DID THE LAST TIME

DEFINE NEXT <NEXT$		;;GIVE CURRENT VALUE
	NEXT$==NEXT$+1		;;INCREMENT IT
>

; MACRO TO DEFINE OFFSETS TO FIELDS WITHIN A MEMORY BLOCK

DEFINE FLDDEF (FLDSYM,FLDLEN) <
	FLDSYM==FLDPTR		;;DEFINE FIELD-OFFSET SYMBOL
	FLDPTR==FLDPTR+FLDLEN	;;RESERVE ROOM FOR FIELD
>

; SAVEQ MACRO - WORKS LIKE SAVEAC <Q1,Q2,Q3>
; SAVET MACRO - WORKS LIKE SAVEAC <T1,T2,T3,T4>
; STAKT MACRO - WORKS LIKE ASUBR WITH NO ARGUMENTS, DOESN'T USE AC15
;   Tn ON STACK MAY BE REFERENCED AS CTn

DEFINE SAVEQ <JSP CX,SAVEQR>
DEFINE SAVET <JSP CX,SAVETR>
DEFINE STAKT <JSP CX,STAKTR>
DEFINE CT1<-4(P)>		;CALLER'S T1
DEFINE CT2<-3(P)>		;CALLER'S T2
DEFINE CT3<-2(P)>		;CALLER'S T3
DEFINE CT4<-1(P)>		;CALLER'S T4

; ASSEMBLY-CONTROL

DEFINE PRINT1(PR1) <IF1 <PRINTX PR1>> ;PRINTX FOR PASS1 ONLY

; MACRO TO DEFINE ASSOCIATED-PROCESS TABLES

DEFINE APTABL <
	APENT QSR		;;QUASAR
	APENT ORN		;;ORION
>

; MACROS TO GENERATE BYTE POINTERS TO FIELDS IN LBUF2
;  LPTR(ARG)  - BYTE POINTER TO FIELD FOR LDB/DPB
;  ILPTR(ARG) - BYTE POINTER TO FIELD FOR ILDB/IDPB
; ARGUMENT IS BYTE POSITION OF FIELD (VALUE BETWEEN 1 AND 80)

DEFINE LPTR (LCP1)
 <POINT 7,LBUF2+<LCP1+4>/5-1,<LCP1-<<LCP1-1>/5*5>>*7-1>
DEFINE ILPTR (LCP1)
 <POINT 7,LBUF2+<LCP1+3>/5-1,<LCP1-<<LCP1+3>/5-1>*5>*7-8>

; CONDITIONAL ASSEMBLY MACROS FOR "NOSHIP" CODE

IFNDEF SHIPSW,<SHIPSW==-1>
DEFINE NOSHIP<IFE SHIPSW>
; MACROS TO GENERATE CALLS TO ASCIZ TEXT MESSAGE COMPOSER

DEFINE TMCT (TMCTA) <
	MOVEI CX,[ASCIZ\TMCTA\]	;;GET ADDRESS OF FORMATTING STRING
	CALL TMCT0		;;CALL FORMATTING ROUTINE
>

DEFINE TMCTO (TMCTA) <
	CALL TMCT0		;;CALL FORMATTING ROUTINE ONLY
>

DEFINE TMCTN (TMCTA) <
	MOVEI CX,[ASCIZ\TMCTA\]	;;GET ADDRESS OF FORMATTING STRING ONLY
>

DEFINE TMCTR (TMCTA) <
	JSP CX,TMCT0		;;POINT CX AT STRING AND CALLRET TMCT0
	ASCIZ\TMCTA\
>

; MACROS TO ABORT USER MOUNT REQUEST - RSB ADDRESS MUST BE IN RSB AC

DEFINE ABTREQ (ABTCOD,ABTFLG<0>) <
	CALL AREQ		;;CALL ABORT ROUTINE
	EXP ABTCOD+ABTFLG
>

DEFINE ABTRET (ABTCOD,ABTFLG<0>) <
	CALL ARET		;;CALL ABORT-AND-RET ROUTINE
	EXP ABTCOD+ABTFLG
>

ABT%OP==1B0			;OPERATOR RESPONSE IS PRESENT
ABT%IN==1B1			;ABTCOD IS ADDRESS OF LOC CONTAINING CODE

; MACRO TO EXECUTE AND TIME OUT I/O JSYS

DEFINE IOXCT (IOJSYS,IOERR,IOTIMO) <
	CALL IOXCTR		;;CALL DRIVER ROUTINE
	 IOJSYS			;;JSYS TO BE EXECUTED
	 XWD IOERR,IOTIMO	;;ERROR ADDRESS, TIMEOUT ADDRESS
>

; MACRO TO CREATE AND INIT STACK AREA AND QSB AC FOR QUEUE SCAN
; ARGUMENT IS ADDRESS OF QUEUE DESCRIPTOR BLOCK (QDB)

DEFINE QSCANI (QDBADR) <
	JSP CX,QSCNIR		;;CALL DRIVER
	SETZ QDBADR		;;QDB ADDRESS IN IFIW FORMAT
>

; MACRO TO MARK PLACES THAT HAVE TO CHANGE IF MORE LABEL TYPES ARE ADDED

DEFINE MAXLT <IFN .LTMAX-4,<IF2 <PRINTX LABEL TYPE ADDED>>>
SUBTTL EQUATES

; IT IS EXPECTED THAT THE EQUATES ON THIS PAGE MAY CHANGE TO
; REFLECT CHANGES IN TOPS-20 OR IN THE REQUIREMENTS OF THIS PROGRAM

; TABLE OF VALID TOPS-20 DENSITIES INDEXED BY MONSYM DENSITY CODE

DEFINE DENLST <
	0		;;ZEROTH ENTRY UNUSED
	^D200		;;.SJDN2
	^D556		;;.SJDN5
	^D800		;;.SJDN8
	^D1600		;;.SJD16
	^D6250		;;.SJD62
>
; MISCELLANEOUS

POLINT==^D120		;NUMBER OF SECONDS BETWEEN MAGTAPE POLLS
MAXACC==400		;NUMBER OF ACCOUNTING-BLOCKS
MAXDSK==100		;MAXIMUM # OF DISK DRIVES SUPPORTED
MAXMRQ==200		;MAXIMUM # OF MOUNT REQUESTS
MAXMT==100		;MAXIMUM # OF MT DEVICES
MAXMTA==100		;MAXIMUM # OF MTA DEVICES
ANSV=="3"		;ANSI LABELING STANDARD VERSION NUMBER
DECV=="1"		;DEC LABELING STANDARD VERSION NUMBER
PDLEN==140		;LENGTH OF PUSH-DOWN LIST (WORDS)
RMKLEN==30		;MAXIMUM SIZE (WORDS) OF ASCIZ MOUNT REMARK
DSFPGS==1		;# OF PAGES IN DEVICE-STATUS FILE
SYRMSZ==40		;MAX WORDS IN SYSERR MSG EXCLUDING HEADER
IFNDEF TST,<TST==0>	;1=TEST VERSION, 0=REAL VERSION
SYRHSZ==4		;# OF WORDS IN SYSERR ENTRY HEADER
MOSTAL==.MODVT+1	;LENGTH OF .MOSTA MTOPR ARGUMENT BLOCK
; ACCUMULATOR DEFINITIONS

	F=0		;FLAGS
	T1=1		;TEMPORARY
	T2=2		;TEMPORARY
	T3=3		;TEMPORARY
	T4=4		;TEMPORARY
	Q1=5		;PRESERVED
	Q2=6		;PRESERVED
	Q3=7		;PRESERVED
	MTA=10		;ADDRESS OF MTA STATUS BLOCK
	DSK=10		;ADDRESS OF DISK STATUS BLOCK
	RSB=11		;ADDRESS OF USER REQUEST STATUS BLOCK
	MT=12		;ADDRESS OF MT STATUS BLOCK
	STR=12		;ADDRESS OF STRUCTURE STATUS BLOCK
	QSB=13		;ADDRESS OF QUEUE-SCAN BLOCK
	ACC=14		;ADDRESS OF ACCOUNT BLOCK
	CX=16		;USED BY SUPPORT CODE
	P=17		;PUSH-DOWN POINTER

; DEFINITIONS OF BITS IN FLAG REGISTER (F)

IRETF==1B35		;1 = EXTERNAL INTERRUPTS DEBRK TO SCHEDULER
MRMSF==1B34		;1 = DO MRECV
MRPGF==1B33		;1 = DO MRECV IN PAGE MODE
ABORTF==1B32		;1 = ABORTED REQUEST(S) EXIST IN RSB QUEUE
NOMTF==1B31		;1 = MT SHORTAGE EXISTS
JTOAF==1B30		;1 = JSYS TIMER ARMED
TALCF==1B29		;1 = TAPE-DRIVE ALLOCATION BY SETSPD
POLLF==1B28		;1 = MAGTAPE POLLING IN PROGRESS
INITF==1B27		;1 = IN INITIALIZATION SEQUENCE
CDENF==1B26		;1 = ^D INTERRUPT ENABLED (^D SCHEDULES DDT)
ARGF==1B25		;1 = ARGUMENT PRESENT (TMCT0 ROUTINE)

; PSI PRIORITY EQUATES (IN ORDER OF DESCENDING PRIORITY)

PRIPAN==1		;PANIC (CRASH) HANDLERS
PRIEXT==3		;EXTERNAL INTERRUPTS

; DEFINITION OF ASSOCIATED PROCESS INDICES

DEFINE APENT (X) <.AP'X==NEXT>
NEXT$==0		;INITIALIZE VARIABLE
	APTABL		;DEFINE SYMBOLS OF FORM .APxxx AS A/P INDICES
APNUM==NEXT$		;# OF ASSOCIATED PROCESSES

;DEFINITIONS FOR COMND JSYS

CMKEY==<.CMKEY>B8	;PARSE A KEYWORD
CMNOI==<.CMNOI>B8	;PARSE A GUIDE WORD
CMCFM==<.CMCFM>B8	;CONFIRM
CMFLD==<.CMFLD>B8	;PARSE AN ARBITRARY FIELD

; OTHER EQUATES

DAYSEC==^D60*^D60*^D24	;# OF SECONDS IN A DAY (NEVER CHANGES)
DSFSZ==DSFPGS*1000	;# OF WORDS IN DEVICE-STATUS FILE
LBLSIZ==^D80		;SIZE OF TAPE LABELS IN FRAMES
LB7WDS==<LBLSIZ+4>/5	;LENGTH IN WORDS OF 7-BIT-BYTE LABEL
LB8WDS==<LBLSIZ+3>/4	;LENGTH IN WORDS OF 8-BIT-BYTE LABEL
MTNAV==1		;MTRSB VALUE THAT INDICATES MT NOT AVAILABLE
USRLH==500000		;LEFT HALF OF USER NUMBER WORD
.MNTDT==77		;REQUEST TYPE FOR DECTAPE-MOUNT
; OFFSETS OF LABEL FIELDS (VALUES IN THE RANGE 1-80)

V1VID==^D5		;VOL1 - VOLUME IDENTIFIER
V1ACS==^D11		;VOL1 - ACCESSIBILITY
V1SCD==^D25		;VOL1 - SYSTEM CODE
V1OWN==^D38		;VOL1 - OWNER IDENTIFIER
V1INAM==^D41		;VOL1 - INSTALLATION NAME (ANSI, TOPS-20)
V1INME==^D42		;VOL1 - INSTALLATION NAME (EBCDIC)
TPNMSZ==^D10		;VOL1 - LENGTH OF V1INAM AND V1INME FIELDS
V1DECV==^D51		;VOL1 - DEC STANDARD VERSION #
V1ANSV==^D80		;VOL1 - ANSI STANDARD VERSION #

V2PRO==^D5		;VOL2 - PROTECTION CODE
V2PPN==^D11		;VOL2 - PROJECT-PROGRAMMER NUMBER
V2OWN==^D23		;VOL2 - OWNER'S NAME
V2OWNL==^D39		;VOL2 - LENGTH OF OWNER'S NAME

H1SET==^D22		;HDR1 - FILE SET IDENTIFIER (SETNAME)
H1CRE==^D42		;HDR1 - CREATION DATE
H1EXP==^D48		;HDR1 - FILE EXPIRATION DATE
H1ACS==^D54		;HDR1 - ACCESSIBILITY

H2PRO==^D38		;HDR2 - PROTECTION CODE (TOPS-20 ONLY)
SUBTTL DATA STRUCTURES

;	DEVICE STATUS FILE
;	==================

; TOPS-20 DEVICE STATUS IS KEPT IN SYSTEM:DEVICE-STATUS.BIN. IT
; IS MAINTAINED AND EXAMINED SOLELY BY THIS PROGRAM. ITS PURPOSE IS
; TO PRESERVE SYSTEM PERIPHERAL DEVICE STATUS ACROSS  RELOADS.  THE
; FILE IS TREATED AS A MONOLITHIC SET OF PAGES THAT  IS  MAPPED  IN
; ITS ENTIRETY INTO THE AREA DSBUF, WHICH HAS THIS FORMAT:

;		!=====================================!
;	DSB.CK	!          CHECKSUM OF FILE           !
;		!-------------------------------------!
;	DSB.PS	!          APR SERIAL NUMBER          !
;		!-------------------------------------!
;	DSB.NE	!      # OF ENTRIES IN FILE (n)       !
;		!-------------------------------------!
;	DSB.EO	!                                     !
;		\               ENTRY 1               \
;		!                                     !
;		!-------------------------------------!
;		!                  .                  !
;		\                  .                  \
;		!                  .                  !
;		!-------------------------------------!
;		!                                     !
;		\               ENTRY n               \
;		!                                     !
;		!=====================================!


; ENTRY SIZE IS FIXED, SET BY THE EQUATE FOR DSFESZ
; ALL ENTRIES BEGIN AS FOLLOWS:
;
;	WORD 0 - DEVICE TYPE CODE
;	WORD 1 - DEVICE IDENTIFIER (UNIQUE WITHIN DEVICE TYPE)

;MAGNETIC TAPE ENTRIES:
;  WORD 0 = DEVICE TYPE (.DVMTA)
;  WORD 1 = TOPS-20 DEVICE DESIGNATOR

;DISK DRIVE ENTRIES:
;  WORD 0 - DEVICE TYPE (.DVDSK)
;  WORD 1 - CKU NUMBER (CHANNEL, CONTROLLER, AND UNIT NUMBERS)

MTS.SF==2		;STATUS FLAGS
  MTS%AV==1B0		;1 = AVAILABLE FOR SYSTEM USE

DSFESZ==3		;SIZE OF DEVICE-STATUS FILE ENTRIES (WORDS)
;	WTB - WRITE-TO-OPERATOR-WITH-REPLY BLOCK
;	========================================

; WHEN A ROUTINE MUST ISSUE A MESSAGE TO THE OPERATOR AND RECEIVE A
; RESPONSE, IT CALLS  THE  BTWTOR  ROUTINE.  BTWTOR  SENDS  A  WTOR
; REQUEST TO ORION, BUILDS A WTB, AND PLACES THE WTB ON A QUEUE  OF
; OUTSTANDING  WTOR  REQUESTS.  WHEN  THE  OPERATOR'S  RESPONSE  IS
; RECEIVED FROM ORION,  INWTOR  DEQUEUES  THE  WTB  AND  CALLS  THE
; ROUTINE SPECIFIED IN T1 OF THE BTWTOR CALL WITH:
;  T1/ BYTE POINTER TO ASCIZ REPLY FROM OPERATOR
;  T2/ ADDRESS OF WTB

;	!=======================================================!
;WTBLNK	!                WTB QUEUE LINKAGE WORD                 !
;	!-------------------------------------------------------!
;WTBCOD	!         ACKNOWLEDGMENT CODE FOR THIS MESSAGE          !
;	!-------------------------------------------------------!
;WTBENT	!       ORIGINATOR'S ROUTINE ADDRESS (BTWTOR T1)        !
;	!=======================================================!

FLDPTR==0
FLDDEF WTBLNK,1		;QUEUE LINKAGE WORD
FLDDEF WTBCOD,1		;ORION ACKNOWLEDGMENT CODE
FLDDEF WTBENT,1		;ORIGINATOR'S ROUTINE ADDRESS
WTBSIZ==FLDPTR		;SIZE OF WTB
;		TAPE MOUNT REQUEST STATUS BLOCK
;		===============================

;	!=======================================================!
;RSBLNK	!                  QUEUE LINKAGE WORD                   !
;	!-------------------------------------------------------!
;RSBIFL	!                    INTERNAL FLAGS                     !
;	!-------------------------------------------------------!
;RSBUFL	!                  USER-SUPPLIED FLAGS                  !
;	!-------------------------------------------------------!
;RSBMC1	!     USER'S JOB NUMBER     !       REQUEST TYPE        !
;	!-------------------------------------------------------!
;RSBMC2	!CURRENT STATE OR ERROR CODE!   ADDR OF ACCOUNT BLOCK   !
;	!-------------------------------------------------------!
;RSBITN	!           INTERNAL TASK NUMBER FROM QUASAR            !
;	!-------------------------------------------------------!
;RSBUNO	!                  USER'S USER NUMBER                   !
;	!-------------------------------------------------------!
;RSBPID	!                      USER'S PID                       !
;	!-------------------------------------------------------!
;RSBCOD	!              USER'S ACKNOWLEDGEMENT CODE              !
;	!-------------------------------------------------------!
;RSBRNM	!               SIXBIT MOUNT REQUEST NAME               !
;	!-------------------------------------------------------!
;RSBWTB	!                                                       !
;	\       WRITE-TO-OPERATOR-WITH-REPLY BLOCK (WTB)        \
;	!                                                       !
;	!-------------------------------------------------------!
;RSBACT	!                                                       !
;	\                 USER'S ACCOUNT STRING                 \
;	!                                                       !
;	!-------------------------------------------------------!
;RSBRMK	!                                                       !
;	\                     USER'S REMARK                     \
;	!                                                       !
;	!=======================================================!
;RSBSSN	!         USER-SUPPLIED VOLUME SET NAME (SIXBIT)        !
;	!-------------------------------------------------------!
;RSBASN	!             ACTUAL VOLUME SET NAME (SIXBIT)           !
;	!-------------------------------------------------------!
;RSBVLS	!          QUEUE DESCRIPTOR BLOCK FOR VOLID LIST        !
;	!-------------------------------------------------------!
;RSBMT1	!   DENSITY   ! DRIVE TYPE  ! LABEL TYPE  !      0      !
;	!-------------------------------------------------------!
;RSBMT2	!  ADDR OF MT STATUS BLOCK  !  VOLUME PROTECTION CODE   !
;	!-------------------------------------------------------!
;RSBMT3	!    CURRENT VOLID INDEX    !             0             !
;	!=======================================================!
; USER TAPE MOUNT  REQUESTS  THAT  ARE  RECEIVED  FROM  QUASAR  ARE
; TRANSFORMED UPON  ARRIVAL  INTO  A  FIXED-FORMAT  REQUEST  BLOCK,
; DESCRIBED BELOW. WHEN A GIVEN MOUNT REQUEST IS BEING  REFERENCED,
; RSB POINTS TO THE FIRST WORD OF THE BLOCK.

FLDPTR==0
FLDDEF RSBLNK,1		;LINKAGE TO NEXT ENTRY IN QUEUE
FLDDEF RSBIFL,1		;INTERNAL FLAGS
  R%PRIV==1B0		;USER IS PRIVILEGED
  R%ORES==1B1		;OPERATOR RESPONSE PRESENT
  R%WVL==1B2		;VOLUME LABELS SHOULD BE WRITTEN
  R%ONV==1B3		;OPERATOR WAS NOTIFIED OF VOLID LIST
  R%OPR==1B4		;REQUEST FROM OPR
  R%DSM==1B5		;DISMOUNT REQUEST
  R%ONR==1B6		;MOUNT-REQUEST MESSAGE SENT TO OPERATOR
FLDDEF RSBUFL,1		;USER-DEFINED FLAGS
FLDDEF RSBMC1,1		;MISCELLANEOUS DATA
FLDDEF RSBMC2,1		;MISCELLANEOUS DATA
FLDDEF RSBITN,1		;QUASAR INTERNAL TASK NUMBER
FLDDEF RSBUNO,1		;USER'S USER NUMBER
FLDDEF RSBPID,1		;USER'S PID
FLDDEF RSBCOD,1		;USER'S ACKNOWLEDGMENT CODE
FLDDEF RSBRNM,1		;MOUNT REQUEST NAME (SIXBIT)
FLDDEF RSBWTB,WTBSIZ	;WTOR BLOCK
FLDDEF RSBACT,10	;USER'S ACCOUNT STRING (ASCIZ)
FLDDEF RSBRMK,RMKLEN	;USER'S REMARK (ASCIZ)
RSBCSZ==FLDPTR		;SIZE OF AREA COMMON TO ALL RSB'S
FLDDEF RSBSSN,1		;USER-SUPPLIED VOLUME SET NAME (SIXBIT)
FLDDEF RSBASN,1		;ACTUAL VOLUME SET NAME (SIXBIT)
FLDDEF RSBVLS,1		;QUEUE DESCR BLOCK FOR VOLID LIST
FLDDEF RSBMT1,1		;MISCELLANEOUS DATA
FLDDEF RSBMT2,1		;MISCELLANEOUS DATA
FLDDEF RSBMT3,1		;MISCELLANEOUS DATA
MTRSBS==FLDPTR	;SIZE OF TAPE MOUNT RSB

DEFSTR (RSBJNO,RSBMC1(RSB),17,18)	;USER'S JOB NUMBER
DEFSTR (RSBTYP,RSBMC1(RSB),35,18)	;REQUEST TYPE CODE
DEFSTR (RSBSTE,RSBMC2(RSB),17,18)	;CURRENT STATE OF REQUEST
DEFSTR (RSBACC,RSBMC2(RSB),35,18)	;ADDRESS OF ACCOUNT BLOCK

DEFSTR (RSBDEN,RSBMT1(RSB),8,9)		;DENSITY
DEFSTR (RSBDRV,RSBMT1(RSB),17,9)	;DRIVE TYPE
DEFSTR (RSBLT,RSBMT1(RSB),26,9)		;LABEL TYPE
DEFSTR (RSBMT,RSBMT2(RSB),17,18)	;MT STATUS BLOCK ADDRESS
DEFSTR (RSBVPR,RSBMT2(RSB),35,18)	;VOLUME PROTECTION CODE
DEFSTR (RSBCV,RSBMT3(RSB),17,18)	;INDEX TO CURRENT VOLID

  NEXT$==0				;DEFINE MAGTAPE REQUEST STATES
  RST.IN==NEXT				  ;RSB BEING INITIALIZED
  RST.WV==NEXT				  ;WAITING FOR VOLID KEYIN
  RST.WM==NEXT				  ;WAITING FOR TAPE MOUNT
  RST.AC==NEXT				  ;ACTIVE (USING VOLUME)
;STATE CODES .GE. .ERBAS IMPLY THAT THE REQUEST IS ABORTED
  ABRTNR==.ERBAS			  ;ABORTED, NO RESPONSE TO USER

;DECTAPE RSB DEF'S

RSBDTA==RSBASN		;DECTAPE DEVICE DESIGNATOR
; WHEN THE "SET TAPE-DRIVE INITIALIZE" OPR COMMAND IS USED TO
; INITIALIZE TAPES, A SPECIAL RSB WITH R%OPR SET IS ALLOCATED
; AND ATTACHED TO THE MTA VIA A FAKE MT STATUS BLOCK WITHIN
; THE RSB. SPECIAL RSB FIELDS REQUIRED FOR THIS FUNCTION WILL
; OVERLAY THE RSBACT FIELD WHICH IS IGNORED HERE.

; SPECIAL RSB FIELDS FOR OPR-REQUESTED VOLUME INITIALIZATION:

RSBICT==RSBACT+0		;# OF VOLUMES TO INITIALIZE
RSBIVI==RSBACT+1		;NUMERIC VOLID INCREMENT
RSBIVL==RSBACT+2		;CURRENT VOLID BEING INITIALIZED
RSBIVN==RSBACT+3		;INTEGER VOLID
RSBIMT==RSBACT+4		;FAKE MT STATUS BLOCK
;		STRUCTURE MOUNT REQUEST STATUS BLOCK
;		====================================

;	!=======================================================!
;RSBLNK	!                  QUEUE LINKAGE WORD                   !
;	!-------------------------------------------------------!
;RSBIFL	!                    INTERNAL FLAGS                     !
;	!-------------------------------------------------------!
;RSBUFL	!                  USER-SUPPLIED FLAGS                  !
;	!-------------------------------------------------------!
;RSBMC1	!     USER'S JOB NUMBER     !       REQUEST TYPE        !
;	!-------------------------------------------------------!
;RSBMC2	!CURRENT STATE OR ERROR CODE!   ADDR OF ACCOUNT BLOCK   !
;	!-------------------------------------------------------!
;RSBITN	!           INTERNAL TASK NUMBER FROM QUASAR            !
;	!-------------------------------------------------------!
;RSBUNO	!                  USER'S USER NUMBER                   !
;	!-------------------------------------------------------!
;RSBPID	!                      USER'S PID                       !
;	!-------------------------------------------------------!
;RSBCOD	!              USER'S ACKNOWLEDGEMENT CODE              !
;	!-------------------------------------------------------!
;RSBRNM	!               SIXBIT MOUNT REQUEST NAME               !
;	!-------------------------------------------------------!
;RSBWTB	!                                                       !
;	\       WRITE-TO-OPERATOR-WITH-REPLY BLOCK (WTB)        \
;	!                                                       !
;	!-------------------------------------------------------!
;RSBACT	!                                                       !
;	\                 USER'S ACCOUNT STRING                 \
;	!                                                       !
;	!-------------------------------------------------------!
;RSBRMK	!                                                       !
;	\                     USER'S REMARK                     \
;	!                                                       !
;	!=======================================================!
;RSBSTN	!                STRUCTURE NAME (SIXBIT)                !
;	!-------------------------------------------------------!
;RSBSTA	!               STRUCTURE ALIAS (SIXBIT)                !
;	!-------------------------------------------------------!
;RSBMS1	! ADDR OF STR STATUS BLOCK  !             0             !
;	!=======================================================!
FLDPTR==RSBCSZ			;SET POINTER TO END OF COMMON SECTION

FLDDEF RSBSTN,1			;STRUCTURE NAME (SIXBIT)
FLDDEF RSBSTA,1			;STRUCTURE ALIAS (SIXBIT)
FLDDEF RSBMS1,1			;MISCELLANEOUS DATA

STRSBS==FLDPTR			;SIZE OF STRUCTURE-MOUNT RSB

DEFSTR (RSBSS,RSBMS1(RSB),17,18) ;STR STATUS BLOCK ADDR

; SET RSBSIZ = MAX(MTRSBS,STRSBS)

RSBSIZ==MTRSBS
IFG STRSBS-MTRSBS,<RSBSIZ==STRSBS>
;	MTA STATUS BLOCK
;	================

; EACH MTA DEVICE SUPPORTED BY THE SYSTEM HAS A STATUS  BLOCK  THAT
; CONTAINS VARIOUS PIECES OF DEVICE-DEPENDENT INFORMATION. THE  MTA
; AC CONTAINS A POINTER TO THE FIRST WORD OF THE BLOCK THAT BELONGS
; TO THE MTA DEVICE CURRENTLY BEING SERVICED.

;	!=======================================================!
;MTAVOL	!           VOLID OF CURRENTLY-MOUNTED VOLUME           !
;	!-------------------------------------------------------!
;MTASET	!          SETNAME OF CURRENTLY-MOUNTED VOLUME          !
;	!-------------------------------------------------------!
;MTAIDV	!              VOLID FROM IDENTIFY COMMAND              !
;	!-------------------------------------------------------!
;MTAFLG	!                   SINGLE-BIT FLAGS                    !
;	!-------------------------------------------------------!
;MTAFIL	!            JFN            !        GTJFN COUNT        !
;	!-------------------------------------------------------!
;MTAP1	!             !    STATE    ! LABEL TYPE  !   DENSITY   !
;	!-------------------------------------------------------!
;MTAP2	!  MT STATUS BLOCK ADDRESS  ! REWIND END-ACTION ADDRESS !
;	!-------------------------------------------------------!
;MTASDN	!    SUPPORTED DENSITIES    !      DRIVE TYPE CODE      !
;	!-------------------------------------------------------!
;MTAV1	!                                                       !
;	\              IMAGE OF VOL1 LABEL ON TAPE              \
;	!            (ASCII OR EBCDIC, 8-BIT BYTES)             !
;	!-------------------------------------------------------!
;MTAV2	!                                                       !
;	\              IMAGE OF VOL2 LABEL ON TAPE              \
;	!            (ASCII OR EBCDIC, 8-BIT BYTES)             !
;	!=======================================================!

; DEFINITIONS OF FIELDS WITHIN MTA STATUS BLOCK

FLDPTR==0

FLDDEF MTAVOL,1		;CURRENT MTA VOLID (SIXBIT), 0 IF NONE
FLDDEF MTASET,1		;CURRENT MTA SETNAME (SIXBIT), 0 IF NONE
FLDDEF MTAIDV,1		;QUEUE LINKAGE WORD
FLDDEF MTAFLG,1		;SINGLE-BIT FLAGS
  MA%LOD==1B0		;DRIVE IS LOADED
  MA%OPN==1B1		;JFN IS OPEN
  MA%AVE==1B2		;AVR ENABLED
  MA%AVS==1B3		;AVR SUPPORTED FOR THIS DRIVE
  MA%WEN==1B4		;WRITE PERMITTED
  MA%SCR==1B5		;VOLUME IS SCRATCH
  MA%UXV==1B6		;UNEXPIRED LABELED VOLUME
  MA%VMG==1B7		;VOLUME-MOUNTED MESSAGE GIVEN TO OPERATOR
  MA%ULP==1B8		;UNLOAD DRIVE WHEN REWIND COMPLETES
  MA%OPF==1B9		;OVERWRITE-PROTECTION FLAG, IF SET:
			; ANSI - VOLUME MAY NOT BE OVERWRITTEN
			; TOPS-20 - NON-OWNER MAY NOT OVERWRITE
FLDDEF MTAFIL,1		;FILE STATUS
FLDDEF MTAP1,1		;DEFSTR-DEFINED DATA
FLDDEF MTAP2,1		;DEFSTR-DEFINED DATA
FLDDEF MTASDN,1		;DEFSTR-DEFINED DATA
FLDDEF MTAV1,LB8WDS	;IMAGE OF VOL1 LABEL ON TAPE
FLDDEF MTAV2,LB8WDS	;IMAGE OF VOL2 LABEL ON TAPE
MTASZ==FLDPTR	;SIZE OF MTA STATUS BLOCK IN WORDS

DEFSTR (MTAJFN,MTAFIL(MTA),17,18)	;JFN
DEFSTR (MTAJCT,MTAFIL(MTA),35,18)	;JFN-IN-USE COUNT
DEFSTR (MTASTE,MTAP1(MTA),17,9)	;CURRENT STATE OF DRIVE
  ; MTASTE/ 0 IF AND ONLY IF MTA NOT ASSIGNED TO MY JOB (VIA ASND)
  S.UNAV==0				;UNAVAILABLE TO MOUNTR
  S.AV==1				;AVAILABLE FOR USE BY USERS
  S.INIT==2				;INITIALIZING TAPE VOLUMES
DEFSTR (MTALT,MTAP1(MTA),26,9)		;LABEL TYPE
DEFSTR (MTADEN,MTAP1(MTA),35,9)		;DENSITY
DEFSTR (MTAMT,MTAP2(MTA),17,18)		;MT STAT BLK ADDR OR 0 IF NONE
DEFSTR (MTAREA,MTAP2(MTA),35,18)	;REWIND END-ACTION SCHEDULE ADDR
DEFSTR (MTADRV,MTASDN(MTA),35,18)	;DRIVE TYPE
;	MT STATUS BLOCK
;	===============

; EACH MT DEVICE SUPPORTED BY THE SYSTEM HAS A  STATUS  BLOCK  THAT
; CONTAINS DEVICE-RELATED INFORMATION. THE  MT  AC  POINTS  TO  THE
; FIRST WORD OF THE STATUS BLOCK OF THE MT CURRENTLY BEING SERVICED.

;	!=======================================================!
;MTP1	! ADDR OF MTA STATUS BLOCK  !ADDR OF REQUEST STATUS BLK !
;	!=======================================================!

; DEFINITIONS OF FIELDS WITHIN MT STATUS BLOCK

FLDPTR==0

FLDDEF MTP1,1		;DEFSTR-DEFINED DATA
MTSZ==FLDPTR	;SIZE OF MT STATUS BLOCK

DEFSTR (MTMTA,MTP1(MT),17,18)		;MTA STATUS BLOCK ADDRESS
DEFSTR (MTRSB,MTP1(MT),35,18)		;REQUEST STATUS BLK ADDRESS
;	DISK STATUS BLOCK
;	=================

;EACH DISK ON THE SYSTEM HAS A STATUS BLOCK THAT CONTAINS INFORMATION
;ABOUT THAT DRIVE.  THE DSK AC CONTAINS A POINTER TO THE FIRST WORD
;OF THE BLOCK THAT BELONGS TO THE DISK CURRENTLY BEING SERVICED.

;	!=======================================================!
;DSKSTN !                 SIXBIT STRUCTURE NAME                 !
;	!-------------------------------------------------------!
;DSKSTA !                 SIXBIT STRUCTURE ALIAS                !
;	!-------------------------------------------------------!
;DSKLNK !                     QUEUE LINKAGE                     !
;	!-------------------------------------------------------!
;DSKFLG !                    STATUS OF UNIT                     !
;	!-------------------------------------------------------!
;DSKNS  !    LOGICAL UNIT NUMBER    !      NUMBER OF UNITS      !
;	!-------------------------------------------------------!
;DSKP1  !                           0                           !
;	!-------------------------------------------------------!
;DSKP2  !  STR STATUS BLOCK ADDRESS !             0             !
;	!-------------------------------------------------------!
;DSKCKU !  CKU NUMBERS (CHANNEL, CONTROLLER, AND UNIT NUMBERS)  !
;	!=======================================================!

; DEFINITIONS OF FIELDS WITHIN DISK STATUS BLOCK

FLDPTR==0

FLDDEF DSKSTN,1		;CURRENT FILE STRUCTURE NAME(SIXBIT) - 0 IF NONE
FLDDEF DSKSTA,1		;CURRENT FILE STRUCTURE ALIAS(SIXBIT)-0 IF NONE
FLDDEF DSKLNK,1		;QUEUE LINKAGE WORD
FLDDEF DSKFLG,1		;STATUS OF UNIT
;ITEMS BELOW DEFINED IN MONSYM
;  MS%MNT=1B0		;UNIT IS PART OF A MOUNTED STRUCTURE
;  MS%DIA==1B2		;UNIT IS BEING USED BY ON-LINE DIAGNOTIC PROGRAM
;  MS%OFL==1B3		;UNIT IS OFF LINE
;  MS%ERR==1B4		;UNIT HAS ERROR THAT WAS DETECTED DURING READING
;  MS%BBB==1B5		;UNIT HAS A BAD BAT BLOCK
;  MS%WLK==1B6		;UNIT IS WRITE-LOCKED
;  MS%TYP==777B17	;TYPE OF DISK UNIT
;    .MSRP4==1		;RP04
;    .MSRP5==5		;RP05
;    .MSRP6==6		;RP06
;    .MSRP7==7		;RP07
FLDDEF DSKNS,1		;LOGICAL UNIT # WITHIN STR,,# OF UNITS IN STR
FLDDEF DSKP1,1		;UNUSED
FLDDEF DSKP2,1		;STR STATUS BLOCK ADDR
FLDDEF DSKCKU,1		;CHANNEL, CONTROLLER, AND UNIT NUMBERS
DSKSZ==FLDPTR		;SIZE OF DSK STATUS BLOCK

DEFSTR (DSKTYP,DSKFLG,17,11)	;TYPE OF DISK UNIT
DEFSTR (DSKLUN,DSKNS,17,18)	;LOGICAL UNIT NUMBER OF DISK WITHIN STR
DEFSTR (DSKNOU,DSKNS,35,18)	;NUMBER OF DISK UNITS IN STRUCTURE
DEFSTR (DSKSSA,DSKP2,17,18)	;STRUCTURE STATUS BLOCK ADDRESS
MSKSTR (DSKCHN,DSKCKU,DOP%C2)	;CHANNEL NUMBER
MSKSTR (DSKCTR,DSKCKU,DOP%K2)	;CONTROLLER NUMBER
MSKSTR (DSKDRV,DSKCKU,DOP%U2)	;DRIVE NUMBER
;	STR STATUS BLOCK
;	================

;EACH STRUCTURE HAS A STATUS BLOCK THAT CONTAINS INFORMATION.  THE STR
;AC POINTS TO THE FIRST WORD OF THE STATUS BLOCK OF THE STRUCTURE
;CURRENTLY BEING SERVICED.

;	!=======================================================!
;STRALI !                SIXBIT STRUCTURE ALIAS                 !
;	!-------------------------------------------------------!
;STRNAM !                SIXBIT STRUCTURE NAME                  !
;	!-------------------------------------------------------!
;STRFLG !                   STRUCTURE FLAGS                     !
;	!-------------------------------------------------------!
;STRCNT ! # OF UNITS ! MOUNT COUNT  ! ADDR OF REQUEST STATUS BLK!
;	!-------------------------------------------------------!
;STRADD !                                                       !
;       \           ADDRESS(ES) OF DISK STATUS BLOCK(S)         \
;	!                                                       !
;	!=======================================================!

FLDPTR==0
FLDDEF STRALI,1			;STRUCTURE ALIAS IN SIXBIT
FLDDEF STRNAM,1			;STRUCTURE NAME IN SIXBIT
FLDDEF STRFLG,1			;STRUCTURE STATUS AS DEFINED IN MONSYM
  MS%PS==1B0			;THIS STRUCTURE IS PUBLIC
  MS%DIS==1B1			;STRUCTURE IS BEING DISMOUNTED
  MS%DOM==1B2			;STRUCTURE IS DOMESTIC
  MS%PPS==1B3			;STRUCTURE IS PRIMARY PUBLIC STRUCTURE
  MS%INI==1B4			;STRUCTURE IS BEING INITIALIZED
  MS%LIM==1B5			;STRUCTURE LIMITED TO 2050 SIZES
  MS%NRS==1B6			;STRUCTURE IS NOT REGULATED
  MS%MT==1B35			;STRUCTURE IS MOUNTED
FLDDEF STRCNT,1			;# OF UNITS IN STR,,RSB ADDR
FLDDEF STRADD,10		;ADDRESSES OF DISK STRUCTURE BLOCKS
STRSZ==FLDPTR			;SIZE OF STR STATUS BLOCK

DEFSTR (STRUNI,STRCNT,8,9)	;NUMBER OF UNITS IN STRUCTURE
DEFSTR (STRMCT,STRCNT,17,9)	;COUNT OF UNITS MOUNTED IN STRUCTURE
DEFSTR (STRRSB,STRCNT,35,18)	;ADDRESS OF REQUEST STATUS BLOCK
;	MAGTAPE ACCOUNT STATUS BLOCK
;	======= ======= ====== =====

;EACH TAPE DISMOUNT CAUSES AN ACCOUNT RECORD TO BE PUT INTO THE SYSTEM
;USAGE FILE.  THE ACCOUNT STATUS BLOCK IS MADE WHEN A TAPE IS MOUNTED.

;	!=======================================================!
;ACCLNK	!                     QUEUE LINKAGE                     !
;	!-------------------------------------------------------!
;ACCDD	!                   DEVICE DESIGNATOR                   !
;	!-------------------------------------------------------!
;ACCNO	!             JOB NUMBER    !        LINE NUMBER        !
;	!-------------------------------------------------------!
;ACCUSR	!                                                       !
;	\                       USER NAME                       \
;	!                                                       !
;	!-------------------------------------------------------!
;ACCSTG	!                                                       !
;	\                 USER'S ACCOUNT STRING                 \
;	!                                                       !
;	!-------------------------------------------------------!
;ACCCRT	!             DATE/TIME OF REQUEST CREATION             !
;	!-------------------------------------------------------!
;ACCSCD	!               DATE/TIME WHEN SCHEDULED                !
;	!-------------------------------------------------------!
;ACCSVT	!                DATE/TIME WHEN SERVICED                !
;	!-------------------------------------------------------!
;ACCEUT !                  ELAPSED TIME OF USE                  !
;	!-------------------------------------------------------!
;ACCDSP	!		       DISPOSITION			!
;	!-------------------------------------------------------![TEST]
;ACCVID	!                   VOLUME IDENTIFIER                   !
;	!                                                       !
;	!-------------------------------------------------------!
;ACCMC1	!CONTROLLER! LABEL!  LABEL  !            0              !
;	!-------------------------------------------------------!
;ACCPR	!                    RECORDS READ			!
;	!-------------------------------------------------------!
;ACCPW	!                   RECORDS WRITTEN			!
;	!-------------------------------------------------------!
;ACCFR	!                FRAMES READ / 1000.			!
;	!-------------------------------------------------------!
;ACCFW	!              FRAMES WRITTEN / 1000.			!
;	!-------------------------------------------------------!
;ACCSR	!            NUMBER OF SOFT READ ERRORS			!
;	!-------------------------------------------------------!
;ACCSW	!            NUMBER OF SOFT WRITE ERRORS		!
;	!-------------------------------------------------------!
;ACCHR	!            NUMBER OF HARD READ ERRORS			!
;	!-------------------------------------------------------!
;ACCHW	!            NUMBER OF HARD WRITE ERRORS		!
;	!-------------------------------------------------------!
;ACCFSI	!                  FILE SET IDENTIFIER                  !
;	!=======================================================!
FLDPTR==0
FLDDEF ACCLNK,1			;LINKAGE TO NEXT ENTRY IN QUEUE
FLDDEF ACCDD,1			;DEVICE DESIGNATOR AS DEFINED BY SYSTEM
FLDDEF ACCNO,1			;USER JOB NUMBER,,USER LINE NUMBER
FLDDEF ACCUSR,10		;ASCIZ USER NAME
FLDDEF ACCSTG,10		;USER ACCOUNT STRING
FLDDEF ACCCRT,1			;DATE AND TIME OF REQUEST CREATION
FLDDEF ACCSCD,1			;DATE AND TIME REQUEST SERVICED
FLDDEF ACCSVT,1			;DATE AND TIME WHEN REQUEST SERVICED
FLDDEF ACCEUT,1			;ELAPSED TIME OF USE
FLDDEF ACCDSP,1			; DISPOSITION OF REQUEST
ACCCSZ=FLDPTR			;SIZE OF AREA COMMON TO ALL ACC BLOCKS
FLDDEF ACCVID,2			;VOLUME IDENTIFIER
FLDDEF ACCMC1,1			;CONTROLLER TYPE,LABEL TYPE,LABEL STATE
FLDDEF ACCPR,1			;NUMBER OF PHYSICAL RECORDS READ
FLDDEF ACCPW,1			;NUMBER OF PHYSICAL RECORDS WRITTEN
FLDDEF ACCFR,1			;NUMBER OF FRAMES READ/1000.
FLDDEF ACCFW,1			;NUMBER OF FRAMES WRITTEN/1000.
FLDDEF ACCSR,1			;NUMBER OF SOFT READ ERRORS
FLDDEF ACCSW,1			;NUMBER OF SOFT WRITE ERRORS
FLDDEF ACCHR,1			;NUMBER OF HARD READ ERRORS
FLDDEF ACCHW,1			;NUMBER OF HARD WRITE ERRORS
FLDDEF ACCFSI,1			;FILE SET IDENTIFIER (ASCIZ)
ACCSIZ==FLDPTR			;SIZE OF MAGTAPE ACCOUNT BLOCK

DEFSTR (ACCJN,ACCNO(ACC),17,18)	;USER'S JOB NUMBER
DEFSTR (ACCLN,ACCNO(ACC),35,18)	;USER'S LINE NUMBER
DEFSTR (ACCKT,ACCMC1(ACC),5,6)	;CONTROLLER TYPE
DEFSTR (ACCLT,ACCMC1(ACC),11,6)	;LABEL TYPE
DEFSTR (ACCLS,ACCMC1(ACC),17,6)	;VOLUME LABEL STATE
;	STRUCTURE ACCOUNT STATUS BLOCK
;	========= ======= ====== =====

;EACH STRUCTURE DECREMENT CAUSES AN ACCOUNT RECORD TO BE PUT INTO THE
;SYSTEM USAGE FILE.  THE ACCOUNT STATUS BLOCK IS MADE WHEN A STRUCURE
;IS INCREMENTED.

;	!=======================================================!
;ACCLNK	!                     QUEUE LINKAGE                     !
;	!-------------------------------------------------------!
;ACCDD	!                   DEVICE DESIGNATOR                   !
;	!-------------------------------------------------------!
;ACCNO	!             JOB NUMBER    !        LINE NUMBER        !
;	!-------------------------------------------------------!
;ACCUSR	!                                                       !
;	\                       USER NAME                       \
;	!                                                       !
;	!-------------------------------------------------------!
;ACCSTG	!                                                       !
;	\                 USER'S ACCOUNT STRING                 \
;	!                                                       !
;	!-------------------------------------------------------!
;ACCCRT	!             DATE/TIME OF REQUEST CREATION             !
;	!-------------------------------------------------------!
;ACCSCD	!               DATE/TIME WHEN SCHEDULED                !
;	!-------------------------------------------------------!
;ACCSVT	!                DATE/TIME WHEN SERVICED                !
;	!-------------------------------------------------------!
;ACCEUT !                  ELAPSED TIME OF USE                  !
;	!-------------------------------------------------------!
;ACCDSP	!		       DISPOSITION			!
;	!-------------------------------------------------------!
;ACCSTN	!                    STRUCTURE NAME                     !
;	!-------------------------------------------------------!
;ACCMCT	!    MOUNT COUNT BEFORE     !     MOUNT COUNT AFTER     !
;	!-------------------------------------------------------!
;ACCMC2	!CONTROLLER! DEVICE!   STR  !      NUMBER OF UNITS      !
;	!-------------------------------------------------------!
;ACCFRK	!     NUMBER OF JOB FORKS INCREMENTING MOUNT COUNT      !
;	!=======================================================!


FLDPTR==ACCCSZ			;SET POINTER TO END OF COMMON SECTION

FLDDEF ACCSTN,1			;ASCIZ STRUCTURE PHYSICAL ID
FLDDEF ACCMCT,1			;MOUNT COUNT BEFORE,,MOUNT COUNT AFTER
FLDDEF ACCMC2,1			;CONTROLLER,DEVICE,STR TYPE,# OF UNITS
FLDDEF ACCFRK,1			;NUMBER OF JOB FORKS INCREMENTING COUNT

DEFSTR (ACCDT,ACCMC2(ACC),11,6)	;DEVICE TYPE
DEFSTR (ACCST,ACCMC2(ACC),17,6)	;STRUCTURE TYPE
DEFSTR (ACCNU,ACCMC2(ACC),35,18) ;NUMBER OF UNITS IN STRUCTURE
DEFSTR (ACCMB,ACCMCT(ACC),17,18) ;MOUNT COUNT BEFORE MOUNTING STR
DEFSTR (ACCMA,ACCMCT(ACC),35,18) ;MOUNT COUNT AFTER DISMOUNTING STR
SUBTTL ADDRESS SPACE ALLOCATION

; MACRO TO ASSIGN LARGE REGIONS OF ADDRESS SPACE

DEFINE ADASN (ADSYM,ADSIZ,ADPAG) <
	IFNB <ADPAG>,<ADPTR==<<ADPTR+777>&777000>> ;;PAGE BOUNDARY
	ADSYM=ADPTR		;;DEFINE START OF REGION
	ADPTR==ADPTR+ADSIZ	;;INCREMENT ALLOCATION POINTER
>
ADLOW==34000			;START ASSIGNING SPACE AT THIS ADDRESS
ADPTR==ADLOW			;INITIALIZE CURRENT ASSIGNMENT LOCATION

; ASSIGNMENT OF ADDRESS SPACE

ADASN RBUF,1000,PAGE		;BUFFER FOR RECEIVING IPCF MESSAGES
ADASN TBUF,1000,PAGE		;MSEND MESSAGES BUILT HERE
ADASN BADMSG,1000,PAGE		;BAD GALAXY IPCF MESSAGES SAVED HERE
ADASN DSBUF,DSFSZ,PAGE		;DEVICE-STATUS FILE BUFFER PAGE
;NOTE - LBUF1W MUST BE .GE. MAXPPB*1000 (MAXPPB IS DEFINED IN STG)
LBUF1W==30000
ADASN LBUF1,LBUF1W,PAGE		;DUMPI/DUMPO LABEL BUFFER
ADASN SRQ,^D100*3		;SCHEDULER REQUEST QUEUE
ADASN TMCMSG,1000		;TEXT MESSAGE COMPOSITION AREA
ATMSIZ==100
ADASN ATMBFR,ATMSIZ		;ATOM BUFFER FOR COMND JSYS
ADASN MTA0,MTASZ*MAXMTA		;MTA STATUS BLOCKS
ADASN MT0,MTSZ*MAXMT		;MT STATUS BLOCKS
ADASN RSB0,<<MAXMRQ+1>*RSBSIZ>	;RSB POOL
ADASN DSKSTB,DSKSZ*MAXDSK	;DSK STATUS BLOCKS
ADASN STRSTB,STRSZ*MAXDSK	;STR STATUS BLOCKS
VOLPN==<MAXMRQ+1>*5		;AVERAGE 5 VOLIDS PER TAPE REQUEST
ADASN VOLP0,VOLPN*2		;VOLID STORAGE POOL
STSIZ==100
ADASN STRTBL,STSIZ		;STRUCTURE COMMANDS FOR MOUNTS
ADASN SSCNAM,STSIZ		;STRUCTURE NAMES FOR STATUS CHANGES
IGNLEN==20
ADASN IGNTBL,IGNLEN		;STRUCTURE NAMES TO BE IGNORED
ADASN ACC0,<<MAXACC+1>*ACCSIZ>	;ACCOUNT BLOCK POOL

IFG ADPTR-700000,<PRINT1 <ADDRESS SPACE OVERFLOW>>


; DEVICE STATUS BUFFER EQUATES

DSB.CK==DSBUF			;CHECKSUM WORD
DSB.PS==DSBUF+1			;APR SERIAL NUMBER
DSB.NE==DSBUF+2			;# OF ENTRIES IN DEVICE-STATUS FILE
DSB.EO==DSBUF+3			;ORIGIN OF ENTRY LIST IN BUFFER
SUBTTL MODIFYABLE DATA AREA

; ALL DATA FROM ZROBGN TO ZROEND WILL BE SET TO ZEROS AT STARTUP

ZROBGN:			;BEGINNING OF AUTOMATIC ZERO AREA
NSR:	BLOCK 1			;# OF REQUESTS IN SCHEDULER QUEUE
TDSCF:	BLOCK 1			;.GE. 0 SCHED REQUEST EXISTS FOR TDSCIR
DSFJFN:	BLOCK 1			;DISK-STATUS FILE JFN
MYPID:	BLOCK 1			;SYSTEM MDA PID
MSGSIN:	BLOCK 1			;# OF IPCF MESSAGES RECEIVED
SHORT:	BLOCK 1			;MAXIMUM LENGTH OF NON-PAGE IPCF MESSAGE
MTAN:	BLOCK 1			;NUMBER OF MTA DEVICES ON SYSTEM
MTN:	BLOCK 1			;NUMBER OF MT DEVICES ON SYSTEM
PBACW:	BLOCK 1			;GLOBAL ADDR OF ARGUMENT COUNT WORD
PBBPT:	BLOCK 1			;ADDR OF NEXT BUILDING BLOCK TO BE BUILT
TMCPTR:	BLOCK 1			;BYTE POINTER INTO TMCMSG
TMCTSP:	BLOCK 1			;TMCT0 ROUTINE SOURCE STRING POINTER
TMCWDS:	BLOCK 1			;CURRENT LENGTH OF TMCMSG IN WORDS
WTRQDB:	BLOCK 1			;QDB FOR OUTSTANDING WTOR REQUESTS
ARBQDB:	BLOCK 1			;QDB FOR ACTIVE REQUEST STATUS BLOCKS
IRBQDB:	BLOCK 1			;QDB FOR INACTIVE REQUEST STATUS BLOCKS
FVSQDB:	BLOCK 1			;QDB FOR FREE VOLID SLOTS IN VOLP0
UNIQUE:	BLOCK 1			;UNIQUE VALUE WORD (ACCESSED WITH AOS)
BTFLGS:	BLOCK 1			;.OFLAG WORD FOR WTO'S AND ACK'S
TAPNAM:	BLOCK TPNMSZ/5+1	;INSTALLATION-SUPPLIED NAME FOR VOL1
CRSHAC:	BLOCK 20		;AC'S AT TIME OF CRASH
SSSDAT:	BLOCK 2			;DATA AND ROUTINE ADDRESS FOR DEBUG
LSTERR:	BLOCK 1			;LAST ERROR AT TIME OF CRASH
CSB:	BLOCK 12		;STATE BLOCK FOR COMND JSYS
FDB:	BLOCK 4			;FUNCTION DESCRIPTOR BLOCK FOR COMND
APPID:	BLOCK APNUM		;A/P PID TABLE
MRPDB:	BLOCK 10		;PDB FOR MRECV OPERATIONS
TRPDB:	BLOCK 4			;MSEND PDB
PDL:	BLOCK PDLEN+1		;PUSH-DOWN STACK
PDL1:	BLOCK 4			;ALTERNATE PDL - USED BY STOPP ROUTINE
BADP:	BLOCK 1			;CONTENTS OF P WHEN STACK PROBLEM FOUND
SYRHDR:	BLOCK SYRHSZ+SYRMSZ	;SYSERR HEADER AND MESSAGE
SYRMSG==SYRHDR+SYRHSZ		;ADDRESS OF SYSERR MESSAGE
COMJFN:	BLOCK 1			;HOLDS HANDLE (JFN) OF COMMANDS FILE
STAMP:	BLOCK 1			;LAST KNOWN WRITE TIME OF COMMANDS FILE
SAVEDP:	BLOCK 1			;USED TO SAVE STACK POINTER FOR REPARSES
SSCDEF:	BLOCK 1			;DEFAULT STR STATUS SETTING
IABQDB:	BLOCK 1			;QDB FOR INACTIVE ACCOUNT BLOCKS
AABQDB:	BLOCK 1			;QDB FOR ACTIVE ACCOUNT BLOCKS
READCL:	BLOCK 2			;DUMPI IOWD LIST FOR READING LABELS
LPC1:	BLOCK 2			;PSI LEVEL 1 FLAGS & PC
LPC2:	BLOCK 2			;PSI LEVEL 2 FLAGS & PC
LPC3:	BLOCK 2			;PSI LEVEL 3 FLAGS & PC
DAEPC:	BLOCK 1			;PC OF LAST DATA ERROR
ZROEND==.-1		;END OF AUTOMATIC ZERO AREA

; CDFLG - DEPOSIT 0 TO DISABLE ^D, DEPOSIT 1 TO ENABLE ^D
CDFLG:	EXP -1			;CONTROL-D ENABLE/DISABLE SWITCH
CFSPEC:	ASCIZ/PS:<SPOOL>MOUNTR-CRASH.EXE/ ;CRASH FILESPEC
LBUF2:	BLOCK LB7WDS		;7-BIT ASCII REPRESENTATION OF LBUF1
OPRHSZ==12
OPRHDR:	BLOCK OPRHSZ		;TEMPORARY TEXT STORAGE
MSTRBK:	BLOCK 20		;PLACE FOR MSTR DSK STATUS ARG BLOCK
MSTNM:	BLOCK 2			;STRUCTURE NAME FOR MSTR IN 7-BIT ASCII
MSTAL:	BLOCK 2			;STRUCTURE ALIAS FOR MSTR IN 7-BIT ASCII
DSFE:	BLOCK DSFESZ		;CURRENT DEVICE-STATUS FILE ENTRY
; STORAGE AREA FOR USAGE DATA
; ===========================

JOBNO:	BLOCK 1			;JOB NUMBER
LINO:	BLOCK 1			;LINE NUMBER
USRNAM:	BLOCK 10		;ASCIZ USER NAME
ACOUNT:	BLOCK 10		;ASCIZ ACCOUNT USTING

USTCRT:				;DATE/TIME OF REQUEST CREATION
UMTCRT:	BLOCK 1			;CREATION DATE/TIME OF REQUEST

USTSCD:				;SCHEDULED TIME
UMTSCD:	BLOCK 1

USTSRV: 			;DATE/TIME WHEN SERVICED
UMTSRV: BLOCK 1			;SERVICED DATE/TIME

USTEUT:				;ELAPSED USAGE TIME
UMTEUT:	BLOCK 1

USTDSP:				;DISPOSITION OF REQUEST
UMTDSP:	BLOCK 1

USTTXT:				;OPERATOR/SYSTEM TEXT
UMTTXT:	BLOCK 10

USGCSZ==.-JOBNO+1

USTNM:				;STRUCTURE NAME
UMTVID: BLOCK 1			;MAGTAPE VOLUME IDENTIFIER

USTKTP: 			;CONTROLLER TYPE
UMTKTP:	BLOCK 1			;CONTROLLER TYPE

USTDTP: 			;DEVICE TYPE
UMTLT:	BLOCK 1			;LABEL TYPE
				; 1 = UNLABELED, 2 = ANSI
				; 3 = EBCDIC, 4 = DEC

USTSTP:				;STRUCTURE TYPE (3=DOMESTIC,4=FOREIGN)
UMTLS:	BLOCK 1			;LABEL STATUS
				; 0 = UNLABLED VOLUME
				; 1 = PRIVATE VOLUME
				; 2 = SCRATCH VOLUME
				; 3 = SCRATCH VOLUME ASSIGNED TO USER
				;     DURING THIS MOUNT

USTTNP: 			;NUMBER OF PACKS IN STRUCTURE
UMTMRD: BLOCK 1			;MAGTAPE READS

USTMC:				;MOUNT COUNT BEFORE MOUNT
UMTMWR:	BLOCK 1			;MAGTAPE WRITES

USTDC:				;MOUNT COUNT AFTER MOUNT
UMTMRF:	BLOCK 1			;THOUSANDS OF FRAMES READ OF MTA

USTATP:				;ACCESS TYPE
UMTMWF:	BLOCK 1			;THOUSANDS OF FRAMES WRITTEN

UMTFSI:	BLOCK 1			;FILE SET IDENTIFIER
UMTSRE:	BLOCK 1			;NUMBER OF SOFT READ ERRORS
UMTSWE:	BLOCK 1			;NUMBER OF SOFT WRITE ERRORS
UMTHRE:	BLOCK 1			;NUMBER OF HARD READ ERRORS
UMTHWE:	BLOCK 1			;NUMBER OF HARD WRITE ERRORS
UMTVSN:	BLOCK 1			;VISUAL SERIAL NUMBER

USGSIZ==.-JOBNO+1
SUBTTL STATIC DATA AREA

	BLOCK 1000		;GET INTO A NEW PAGE
PURE:				;LOWEST LOCATION IN STATIC DATA AREA

; EVERYTHING BEYOND THIS POINT WILL BE WRITE-PROTECTED BY THE
; ROUTINE WRTP, WHICH IS CALLED IN THE INITIALIZATION PHASE

TSTF:	BLOCK 1			;MODE FLAG: 0=LIVE, 1=TEST MODE

; SOFTWARE INTERRUPT SYSTEM DATA AREAS
; ------------------------------------

LEVTAB:	LPC1
	LPC2
	LPC3

; MACRO TO DEFINE PANIC-CHANNEL INTERRUPT CHNTAB ENTRIES

DEFINE PANIC (PANHDL) <
	INTMSK==INTMSK+1B<.-CHNTAB> ;;SET BIT IN CHANNEL MASK
	XWD PRIPAN,PANHDL	;;GENERATE CHNTAB ENTRY
>

; MACRO TO DEFINE EXTERNAL INTERRUPT CHNTAB ENTRIES

DEFINE EXTPSI (ENAM,EADR) <
	INTMSK==INTMSK+1B<.-CHNTAB> ;;SET BIT IN CHANNEL MASK
	ENAM'CN==.-CHNTAB	;;DEFINE CHANNEL# SYMBOL
  IFB <EADR>,<
	XWD PRIEXT,[CALL EIHR	;;GENERATE CHNTAB ENTRY
		    EXP ENAM'IH] ;;ENTRY POINT FOR SCHEDULER
  > ;;END IFB EADR
  IFNB <EADR>,<
	XWD PRIEXT,EADR		;;GENERATE CHNTAB ENTRY
  > ;;END IFNB EADR
>

INTMSK==0			;INITIAL VALUE OF INTRPT CHANNEL MASK
CHNTAB:
	EXTPSI DDT		;0 - LOAD AND SCHEDULE DDT
	0,,0			;1 - ASSIGNABLE CHANNEL 1
	0,,0			;2 - ASSIGNABLE CHANNEL 2
	0,,0			;3 - ASSIGNABLE CHANNEL 3
	0,,0			;4 - ASSIGNABLE CHANNEL 4
	0,,0			;5 - ASSIGNABLE CHANNEL 5
	0,,0			;6 - ARITHMETIC OVERFLOW
	0,,0			;7 - FLOATING OVERFLOW
	0,,0			;8 - RESERVED
	PANIC PANPOV		;9 - PDL OVERFLOW
	0,,0			;10 - END OF FILE
	PANIC PANDAE		;11 - DATA ERROR
	PANIC PANQTA		;12 - QUOTA EXCEEDED
	0,,0			;13 - RESERVED
	0,,0			;14 - TIME OF DAY (RESERVED)
	PANIC PANILI		;15 - ILLEG INSTRUCTION
	PANIC PANIRD		;16 - ILLEGAL READ
	PANIC PANIWR		;17 - ILLEGAL WRITE
	0,,0			;18 - ILLEGAL EXECUTE (RESERVED)
	0,,0			;19 - INFERIOR FORK TERMINATION
	PANIC PANMSE		;20 - MACHINE SIZE EXCEEDED
	0,,0			;21 - TRAP TO USER (RESERVED)
	0,,0			;22 - NONEXISTENT PAGE REFERENCED
	0,,0			;23 - ASSIGNABLE CHANNEL 23
	EXTPSI MRCV		;24 - IPCF MESSAGE WAITING
	EXTPSI TDSC,TDSCIH	;25 - MTA DEVICE STATUS CHANGE
	EXTPSI JTO,JTOIH	;26 - JSYS TIMER EXPIRED
	EXTPSI DDSC		;27 - DISK DEVICE STATUS CHANGE
	0,,0			;28 - ASSIGNABLE CHANNEL 28
	0,,0			;29 - ASSIGNABLE CHANNEL 29
	0,,0			;30 - ASSIGNABLE CHANNEL 30
	0,,0			;31 - ASSIGNABLE CHANNEL 31
	0,,0			;32 - ASSIGNABLE CHANNEL 32
	0,,0			;33 - ASSIGNABLE CHANNEL 33
	0,,0			;34 - ASSIGNABLE CHANNEL 34
	0,,0			;35 - ASSIGNABLE CHANNEL 35
; ENTRY VECTOR

ENTVEC:	JRST START		;STARTING ADDRESS
	JRST DEBUG		;REENTER ADDRESS
LVERS:	EXP VERS		;PROGRAM VERSION
ENTVSZ==.-ENTVEC

; TABLE OF SUPPORTED DENSITIES

DENTAB:	DENLST			;GENERATE LIST OF DENSITIES
DENMAX==.-DENTAB-1		;MAXIMUM DENSITY INDEX

; POINTERS TO TEXT STRINGS INDEXED BY LABEL TYPE

LTTXT:	0
	[ASCIZ/Unlabeled/]
	[ASCIZ/ANSI/]
	[ASCIZ/EBCDIC/]
	[ASCIZ/TOPS-20/]
MAXLT			;CODE NEEDED HERE IF NEW LABEL TYPE ADDED

; POINTERS TO TEXT STRINGS INDEXED BY DRIVE TYPE

DRVTXT:	0
	[ASCIZ/9-TRACK/]
	[ASCIZ/7-TRACK/]
; TABLE OF INITIALIZATION ROUTINE ADDRESSES FOR ASSOCIATED PROCESSES;
; ROUTINE IS CALLED DURING PROGRAM INITIALIZATION, AND POSSIBLY
; BY THE RECOVERY ROUTINE IF THE PROCESS CRASHES.

DEFINE APENT (X) <IFIW!X'INI>
APINI:	APTABL			;GENERATE LIST OF INIT ROUTINE ADDRS

; TABLE OF IPCF INPUT-MESSAGE PROCESSING ROUTINE ADDRESSES FOR A/P'S;
; ROUTINE IS CALLED WHEN AN IPCF MESSAGE IS RECEIVED FROM A PID THAT
; IS LISTED IN THE APPID TABLE

DEFINE APENT (X) <IFIW!X'MRC>
APMRC:	APTABL			;GEN LIST OF IPCF-RECEIVE HANDLER ADDRS
;	TEMPLATES FOR USAGE JSYS
;	========================

;STRUCTURE USE RECORD

USGSTR:	USENT. (.UTMNT,1,1)	;STRUCTURE USAGE RECORD TYPE
	USPNM. (<SIXBIT/MOUNTR/>,US%IMM) ;PROGRAM NAME
	USPVR. (VERS,US%IMM)	;VERSION NUMBER
	USJNO. (JOBNO)		;JOB NUMBER
	USLNO. (LINO)		;LINE NUMBER
	USACT. (<-1,,ACOUNT>)	;ACCOUNT
	USNM2. (<-1,,USRNAM>)	;USER NAME
	USSSI. (USTNM)		;STRUCTURE NAME
	USSTP. (USTSTP)		;STRUCTURE TYPE
	USTNP. (USTTNP)		;TOTAL NUMBER OF PACKS IN FILE STRUCTURE
	USKTP. (USTKTP)		;CONTROLLER TYPE (RH20)
	USDTP. (USTDTP)		;DEVICE TYPE (RP04,ETC.)
	USDSP. (USTDSP)		;DISPOSITION
	USTXT. (<-1,,USTTXT>)	;SYSTEM/OPERATOR TEXT
	USCRT. (USTCRT)		;CREATION DATE/TIME OF REQUEST
	USSCD. (USTSCD)		;SCHEDULED TIME
	USSRV. (USTSRV)		;SERVICED DATE/TIME
	USMCT. (USTMC)		;MOUNT COUNT BEFORE MOUNT
	USDCT. (USTDC)		;MOUNT COUNT AFTER DISMOUNT
	USATP. (USTATP)		;ACCESS TYPE
	USEUT. (USTEUT)		;ELAPSED TIME OF USAGE
	0			;END OF RECORD

;TAPE MOUNT RECORD

USGMTA:	USENT. (.UTMMT,2,1)	;MAGTAPE USAGE RECORD TYPE
	USPNM. (<SIXBIT/MOUNTR/>,US%IMM) ;PROGRAM NAME
	USPVR. (VERS,US%IMM)	;VERSION NUMBER
	USJNO. (JOBNO)		;JOB NUMBER
	USLNO. (LINO)		;LINE NUMBER
	USACT. (<-1,,ACOUNT>)	;ACCOUNT
	USNM2. (<-1,,USRNAM>)	;USER NAME
	USVID. (UMTVID)		;VOLUME IDENTIFIER IN VOL1 LABEL
	USMRF. (UMTMRF)		;THOUSANDS OF FRAMES READ
	USMWF. (UMTMWF)		;THOUSANDS OF FRAMES WRITTEN
	USDSP. (UMTDSP)		;DISPOSITION
	USTXT. (<-1,,UMTTXT>)	;SYSTEM/OPERATOR TEXT
	USCRT. (UMTCRT)		;CREATION DATE/TIME
	USSCD. (UMTSCD)		;SCHEDULED TIME
	USSRV. (UMTSRV)		;SERVICED DATE/TIME
	USKTP. (UMTKTP)		;CONTROLLER TYPE
	USMLT. (UMTLT)		;LABEL TYPE
	USMLS. (UMTLS)		;LABEL STATE
	USMRD. (UMTMRD)		;NUMBER OF TAPE READS
	USMWR. (UMTMWR)		;NUMBER OF TAPE WRITES
	USFSI. (UMTFSI)		;FILE SET IDENTIFIER
	USSRE. (UMTSRE)		;NUMBER OF SOFT READ ERRORS
	USSWE. (UMTSWE)		;NUMBER OF SOFT WRITE ERRORS
	USHRE. (UMTHRE)		;NUMBER OF HARD READ ERRORS
	USHWE. (UMTHWE)		;NUMBER OF HARD WRITE ERRORS
	USVSN. (UMTVSN)		;VISUAL SERIAL NUMBER
	USEUT. (UMTEUT)		;ELAPSED TIME OF USAGE
	0			;END OF RECORD
; ASCII-TO-EBCDIC TRANSLATION TABLE

; TABLE IS COMPOSED OF 128 8-BIT BYTES, INDEXED BY THE
; ASCII CHARACTER VALUE

AETT:
BYTE (8)000,001,002,003,067,055,056,057,026,005,045,013,014,015,016,017
BYTE (8)020,021,022,023,074,075,062,046,030,031,077,047,034,035,036,037
BYTE (8)100,117,177,173,133,154,120,175,115,135,134,116,153,140,113,141
BYTE (8)360,361,362,363,364,365,366,367,370,371,172,136,114,176,156,157
BYTE (8)174,301,302,303,304,305,306,307,310,311,321,322,323,324,325,326
BYTE (8)327,330,331,342,343,344,345,346,347,350,351,112,340,132,137,155
BYTE (8)171,201,202,203,204,205,206,207,210,211,221,222,223,224,225,226
BYTE (8)227,230,231,242,243,244,245,246,247,250,251,300,152,320,241,007



; EBCDIC-TO-ASCII TRANSLATION TABLE

; TABLE IS COMPOSED OF 256 7-BIT ASCII BYTES, INDEXED BY THE
; EBCDIC CHARACTER VALUE

XXX==.CHCNZ		;VALUE OF EBCDIC CHARS WITHOUT IMAGES (^Z=SUB)

EATT:
BYTE (7)000,001,002,003,XXX,011,XXX,177,XXX,XXX,XXX,013,014,015,016
BYTE (7)017,020,021,022,023,XXX,XXX,010,XXX,030,031,XXX,XXX,034,035
BYTE (7)036,037,XXX,XXX,XXX,XXX,XXX,012,027,033,XXX,XXX,XXX,XXX,XXX
BYTE (7)005,006,007,XXX,XXX,026,XXX,XXX,XXX,XXX,004,XXX,XXX,XXX,XXX
BYTE (7)024,025,XXX,032,040,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,133
BYTE (7)056,074,050,053,041,046,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX
BYTE (7)135,044,052,051,073,136,055,057,XXX,XXX,XXX,XXX,XXX,XXX,XXX
BYTE (7)XXX,174,054,045,137,076,077,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX
BYTE (7)XXX,140,072,043,100,047,075,042,XXX,141,142,143,144,145,146
BYTE (7)147,150,151,XXX,XXX,XXX,XXX,XXX,XXX,XXX,152,153,154,155,156
BYTE (7)157,160,161,162,XXX,XXX,XXX,XXX,XXX,XXX,XXX,176,163,164,165
BYTE (7)166,167,170,171,172,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX
BYTE (7)XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,173,101,102
BYTE (7)103,104,105,106,107,110,111,XXX,XXX,XXX,XXX,XXX,XXX,175,112
BYTE (7)113,114,115,116,117,120,121,122,XXX,XXX,XXX,XXX,XXX,XXX,134
BYTE (7)XXX,123,124,125,126,127,130,131,132,XXX,XXX,XXX,XXX,XXX,XXX
BYTE (7)060,061,062,063,064,065,066,067,070,071,XXX,XXX,XXX,XXX,XXX
BYTE (7)XXX,0,0,0,0
;COMMANDS FROM THE COMMAND FILE FOR STRUCTURE MOUNTS FOR COMND JSYS

COMTBL:	COMLEN,,COMLEN		;LIST OF LEGAL COMMANDS
	[ASCIZ /DOMESTIC/],,[TXO T4,MS%DOM] ;SET UP STR TO BE DOMESTIC
	[ASCIZ /FOREIGN/],,[TXZ T4,MS%DOM] ;SET STR TO BE FOREIGN
	[ASCIZ /NONREGULATED/],,[TXO T4,MS%NRS] ;SET STR TO BE NONREGULATED
	[ASCIZ /REGULATED/],,[TXZ T4,MS%NRS] ;SET STR TO BE REGULATED
COMLEN==.-COMTBL-1		;NUMBER OF COMMANDS IN TABLE

COMDEF:	1,,1			;ONLY 1 COMMAND
	[ASCIZ /DEFAULT/],,0	;SET UP DEFAULTS FOR MOUNTING STRS

;NAME OF COMMANDS FILE

COMNAM:	ASCIZ /SYSTEM:MOUNTR.CMD/

STRINI:	STSIZ			;LENGTH,,MAX (INITIAL SETTING) FOR TBLUK
SSCINI:	SSCNAM			;POSITION - 1 OF NEXT ENTRY IN TABLE



;DISPLAY MESSAGES FOR DISK STATUS


SFHDR:	ASCIZ "
FREE DRIVES:

Type  Chan Ctrl Drive     Structure
----  ---------------     ---------
"

SMHDR:	ASCIZ "
MOUNTED DRIVES:

Structure     Type Chan Ctrl Drive Count Options
------------- ---- --------------- ----- -----------------
"


;DISK UNIT TYPE TABLE

UNTYTB:	XWD .MSRP4,[ASCIZ/RP04/]	;1 - RP04
	XWD .MSRP5,[ASCIZ/RP05/]	;5 - RP05
	XWD .MSRP6,[ASCIZ/RP06/]	;6 - RP06
	XWD .MSRP7,[ASCIZ/RP07/]	;7 - RP07
	XWD .MSRM3,[ASCIZ/RM03/]	;11 - RM03
	XWD .MSR20,[ASCIZ/RP20/]	;24 - RP20
	XWD -1,[ASCIZ/Unk /]		;ENTRY IN CASE NONE OF ABOVE

	MXUTYP==.-UNTYTB-1		;NUMBER OF KNOWN ENTRIES
SUBTTL INITIALIZATION

; PROGRAM EXECUTION BEGINS HERE

START:	HLRZ T1,.JBSA		;GET UPPER BOUND OF PROGRAM
	CAIL T1,ADLOW		;PROGRAM TOO BIG?
	JRST [	TMSG <MOUNTR program overlaps ADLOW> ;YES, ERROR
		HALTF]		;MAKE ADLOW HIGHER TO CORRECT PROBLEM
	RESET			;CLOSE JFNS, CLEAR PSI, DUMP PIDS, ETC.
	MOVE P,[IOWD PDLEN,PDL]	;SET UP STACK POINTER
	MOVX F,INITF		;INITIALIZE FLAGS AC
	MOVE T1,.JBOPS		;GET GALAXY STANDARD TEST FLAG
	MOVEM T1,TSTF		;COPY TO WRITE-PROTECTED LOCATION

; ZERO OUT MODIFYABLE DATA AREA

	SETZM ZROBGN		;CLEAR FIRST WORD OF ZERO AREA
	MOVE T1,[ZROBGN,,ZROBGN+1] ;GET BLT POINTER
	BLT T1,ZROEND		;CLEAR THE REST OF THE ZERO AREA
	SETOM TDSCF		;SET NO SCHED REQUEST PRESENT FOR TDSCIR

; TURN ON INTERRUPT SYSTEM

	MOVEI T1,.FHSLF		;THIS FORK
	MOVE T2,[LEVTAB,,CHNTAB] ;TABLE ADDRESSES
	SIR			;COMMUNICATE TABLE ADDR'S TO MNTR
	EIR			;TURN ON INTERRUPT SYSTEM
	MOVX T2,INTMSK
	AIC			;ENABLE INTERRUPT CHANNELS
	SETO T3,
	EPCAP			;ENABLE ALL CAPABILITIES

; PERFORM VARIOUS INITIALIZATION OPERATIONS

	CALL WRTP		;WRITE-PROTECT MY CODE
	MOVEI T1,.SFMTA
	TMON			;TAPE-DRIVE ALLOCATION ENABLED?
	JUMPN T2,[TXO F,TALCF	;YES, SET FLAG
		MOVEI T1,POLINT	;GET POLLING INTERVAL
		MOVEI T2,POLLR	;GET ADDRESS OF POLLING ROUTINE
		CALL SRAI	;SCHEDULE MAGTAPE POLLING TASK
		JRST .+1]
	CALL PIDINI		;CREATE SYSTEM MDA PID
	CALL GTINAM		;GET INSTALLATION NAME
	CALL INAP		;MAKE FRIENDS WITH ASSOCIATED PROCESSES
	SKIPN TSTF		;RUNNING LIVE?
	JRST [	CALL DSFINI	;YES, MAP DEVICE-STATUS FILE
		TXNE F,TALCF	;SKIP MTA ASSIGN IF ALLOCATION DISABLED
		CALL ASMTA	;ASSIGN PHYSICAL MAGTAPES TO MYSELF
		CALL ASMT	;PUT LOGICAL MAGTAPES IN ALLOC POOL
		JRST .+1]
	CALL GETRSI		;INITIALIZE FREE RSB POOL
	CALL DSKINI		;SET UP DSK AND STR STATUS BLOCKS
	CALL MNTALL		;MOUNT ALL STRUCTURES POSSIBLE
	CALL VQSPIN		;INITIALIZE VOLID-SLOT POOL
	CALL GETABI		;INITIALIZE FREE ACCOUNT BLOCK POOL
	CALL TDSCIR		;REWIND TAPES, DO AVR, ETC.
	TXZ F,INITF		;NOT INITIALIZING ANY MORE
	JRST SSS		;ENTER SCHEDULER
SUBTTL SERVICE SCHEDULER (SS)

; SCHEDULER REQUEST QUEUE ENTRY EQUATES

FLDPTR==0
  FLDDEF(RE.TIM,1)		;OFFSET TO ACTIVATION TIME
  FLDDEF(RE.ENT,1)		;OFFSET TO GLOBAL ENTRY ADDRESS
  FLDDEF(RE.ARG,1)		;OFFSET TO ARGUMENT
RE.LEN==FLDPTR			;LENGTH OF SCHEDULER ENTRY

; ONCE AGAIN INTO THE FRAY, DEAR FRIENDS

SSS:	TXZ F,IRETF		;SET NOT INTERRUPTIBLE
	CAME P,[IOWD PDLEN,PDL]	;STACK POINTER OK?
	JSP CX,STOPP		;NO, CRASH
	CALL DDCTLD		;CHECK FOR ENABLE/DISABLE ^D
	TXO F,IRETF		;SET INTERRUPTIBLE
	SKIPN NSR		;QUEUES EMPTY?
	WAIT			;YES, REG TO SLEEP
	GTAD			;GET CURRENT TIME & DATE IN T1
	MOVE T2,SRQ+RE.TIM	;GET TIME/DATE OF EARLIEST REQUEST
	SUB T2,T1		;IS IT IN THE FUTURE?
	JUMPLE T2,SSER		;NO, GET ON IT RIGHT AWAY

; SLEEP UNTIL WAKE-UP TIME OF EARLIEST REQUEST

	MOVE T1,T2		;COPY INTERNAL FORMAT SLEEP INTERVAL
	MUL T1,[DAYSEC*^D1000]	;COMPUTE # OF MILLISECONDS
	ASHC T1,^D17		; TO SLEEP IN T1
	DISMS			;SLEEP UNTIL NEEDED
	JRST SSS		;ATTEMPT SCHEDULE AGAIN

; SCHEDULE THE FIRST REQUEST IN THE QUEUE

SSER:	TXZ F,IRETF		;AIN'T IDLE NO MORE
	MOVEI T1,.FHSLF
	DIR			;INHIBIT INTERFERENCE
	MOVE T4,SRQ+RE.ENT	;GET ROUTINE ENTRY ADDRESS
	MOVE T3,SRQ+RE.ARG	;GET ARG FOR HANDLER ROUTINE
	SOS T1,NSR		;GET # OF REQUESTS REMAINING
	JUMPE T1,SSS1		;IF NONE LEFT, DON'T BLT
	IMULI T1,RE.LEN		;COMPUTE # OF WORDS TO BLT
	MOVE T2,[SRQ+RE.LEN,,SRQ] ;GET BLT SOURCE,,DESTINATION
	BLT T2,SRQ+RE.LEN-1(T1)	;DELETE HEAD OF QUEUE
SSS1:	MOVEI T1,.FHSLF
	EIR			;PERMIT INTERRUPTS
	DMOVEM T3,SSSDAT	;STORE CALLED-ROUTINE INFO FOR DEBUG
	CALL (T4)		;CALL USER ROUTINE WITH ARG IN T3
	TXZE F,ABORTF		;WERE ANY REQUESTS ABORTED?
	CALL PRQABT		;YES, PURGE THEM FROM REQUEST QUEUE
	JRST SSS		;GO SEE IF MORE WORK TO DO
; SRA - ADD SCHEDULER REQUEST TO QUEUE (2 ENTRY POINTS)
; SRAA - ABSOLUTE INTERNAL-FORMAT TIME & DATE IN T1
; SRAI - INCREMENTAL FORM: # OF SECONDS FROM NOW IN T1
; SRAN - REQUEST IS TO BE SCHEDULED AS SOON AS POSSIBLE (T1 MEANINGLESS)
;  T2/ ROUTINE ADDRESS IN RIGHT HALF
;  T3/ ARGUMENT TO BE SUPPLIED TO ROUTINE IN T3 AT TIME OF CALL
; RETURNS +1: ALWAYS

SRAI:	STAKT			;STACK T1-T4
	MUL T1,[1,,0]		;CONVERT # OF SECONDS
	DIVI T1,DAYSEC		; TO INCREMENTAL INTERNAL FORMAT
	MOVE T2,T1		;CLEAR OUT OF T1 FOR GTAD
	GTAD			;GET CURRENT INTERNAL T/D
	ADD T1,T2		;ADD INCREMENT
	JRST SRA1		;SKIP OTHER ENTRY

SRAN:	SETZ T1,		;IMMEDIATE FLAVOR - STUFF T1
SRAA:	STAKT			;STACK T1-T4

; COMMON CODE FOR SRAx

SRA1:	MOVE T4,T1		;MOVE ACTIVATION TIME TO T4
	MOVEI T1,.FHSLF
	DIR			;INHIBIT INTERFERENCE
	SETZ T2,		;INIT SCAN INDEX
	MOVNI T3,RE.LEN		;INIT QUEUE POINTER
SRA2:	ADDI T3,RE.LEN		;BUMP QUEUE POINTER
	CAMGE T2,NSR		;ANY ENTRIES LEFT TO CHECK AGAINST?
	JRST [	CAML T4,SRQ+RE.TIM(T3) ;YES, EARLIER THAN THIS ENTRY?
		AOJA T2,SRA2	;NO, CONTINUE SEARCH
		JRST .+1]	;YES, GO INSERT IT HERE
	SUB T2,NSR		;COMPUTE # OF
	MOVNS T2		; ENTRIES TO BE SHIFTED DOWN
	IMULI T2,RE.LEN		;COMPUTE # OF WORDS TO SHIFT
	MOVE T3,NSR
	IMULI T3,RE.LEN		;SET UP LOAD/STORE INDEX AT TAIL
	JUMPE T2,SRA3		;IF NONE, SKIP SHIFTING STUFF
SRA4:	MOVE T1,SRQ-1(T3)	;GET A WORD
	MOVEM T1,SRQ+RE.LEN-1(T3) ;SHIFT IT DOWN
	SOS T3			;INDEX NEXT WORD
	SOJG T2,SRA4		;LOOP TILL ALL SHIFTING DONE

; INSTALL ENTRY IN NEWLY-CREATED SLOT

SRA3:	MOVEM T4,SRQ+RE.TIM(T3)	;STUFF TIME/DATE
	XMOVEI T1,20
	HRR T1,CT2
	MOVEM T1,SRQ+RE.ENT(T3)	;STUFF GLOBAL ENTRY ADDRESS
	MOVE T1,CT3
	MOVEM T1,SRQ+RE.ARG(T3)	;STUFF ARGUMENT
	AOS NSR			;BUMP # OF ENTRIES IN QUEUE
	MOVEI T1,.FHSLF
	EIR			;PERMIT INTERRUPTS
	RET
; EIHR - SUPPORT ROUTINE FOR EXTERNAL INTERRUPTS

EIHR:	ADJSP P,5		;CREATE ROOM ON STACK FOR T1-T4, CX
	MOVEM CX,-4(P)		;SAVE CX
	DMOVEM T1,-3(P)		;SAVE T1 & T2
	DMOVEM T3,-1(P)		;SAVE T3 & T4

; REQUEST SCHEDULING AT INTERRUPT HANDLER ENTRY POINT

	MOVE T2,@-5(P)		;GET ADDRESS OF ROUTINE
	CALL SRAN		;SCHEDULE AT THIS ADDRESS IMMEDIATELY

; RESTORE AC'S AND EXIT TO INTERRUPTED PROGRAM OR SCHEDULER

	MOVE CX,-4(P)		;RESTORE CX
	DMOVE T1,-3(P)		;RESTORE T1 & T2
	DMOVE T3,-1(P)		;RESTORE T3 & T4
	ADJSP P,-6		;DELETE TEMP SPACE FROM STACK
	TXZN F,IRETF		;SCHED GOOFING OFF?
	DEBRK			;NO, GO BACK TO INTERRUPTED CODE
	MOVE CX,[PC%USR+SSS]	;YES, GET NEW PC
	MOVEM CX,@LEVTAB+PRIEXT-1 ;STUFF IT
	DEBRK			;EXIT TO SCHEDULER
SUBTTL ACCOUNTING ROUTINES

;ACCSTI - STRUCTURE COUNT BEING INCREMENTED. BUILD ACCOUNTING BLOCK FOR
;	  USER

ACCSTI:	HRRZ T1,RBUF+4		;GET STRUCTURE STATUS
	TRNE T1,(MS%NRS)	;IS IT NON-REGULATED?
	JRST ACCS3		;YES, FORGET ENTRY AND DELETE OLD BLOCK
	HLRZ T1,RBUF+2		;GET JOB NUMBER
	HRRZ T2,RBUF+3		;GET DEVICE DESIGNATOR
	HRLI T2,.DVDES+.DVDSK	;ADD DISK DESIGNATION
	CALL FNDACC		;SEE IF THERE IS A BLOCK ALREADY
	JRST ACCS1		;NO
        SKIPN ACCSVT(ACC)	;IS THERE A SERVICED TIME
	JRST ACCS2		;NO. SO STORE INFORMATION.
	AOS ACCFRK(ACC)		;YES, INCREMENT FORK COUNT
	RET			;FINISHED
ACCS1:	CALL GETACC		;GET AN ACCOUNT BLOCK
	 CALLRET DELACC		;ABORT SINCE ACC BLOCKS IN SHORT SUPPLY
ACCS2:	AOS ACCFRK(ACC)		;SET NUMBER OF FORKS USING STR TO 1

;STORE ACCOUNTING INFORMATION

	HRRZ T1,RBUF+3		;GET STRUCTURE UNIQUE CODE
	HRLI T1,.DVDES+.DVDSK	;ADD DISK DESIGNATOR
	MOVEM T1,ACCDD(ACC)	;STORE IN ACCOUNTING BLOCK
	MOVE T1,RBUF+2		;GET JOB #,,LINE #
	MOVEM T1,ACCNO(ACC)
	MOVE T2,RBUF+10		;GET USER #
	HRROI T1,ACCUSR(ACC)
	DIRST			;TRANSLATE TO NAME
	 JFCL
	MOVEI T1,ACCSTG(ACC)	;SET UP BLT POINTER
	HRLI T1,RBUF+11
	BLT T1,ACCSTG+7(ACC)	;STORE ACCOUNT STRING
	MOVE T1,RBUF+7
	SKIPN ACCSCD(ACC)	;IF NO TIME SCHEDULED
	MOVEM T1,ACCSCD(ACC)	;TIME SCHEDULED
	MOVEM T1,ACCSVT(ACC)	;AND SERVICED ARE THE SAME
	MOVE T1,RBUF+6
	MOVEM T1,ACCSTN(ACC)	;STORE STRUCTURE NAME
	HLRZ T1,RBUF+4
	STOR T1,ACCMB		;STORE MOUNT COUNT
	HLRZ T1,RBUF+5
	STOR T1,ACCNU		;STORE NUMBER OF UNITS
	HRRZ T1,RBUF+5
	STOR T1,ACCDT		;STORE DISK TYPE
	HRRZ T1,RBUF+4		;GET STRUCTURE STATUS
	MOVEI T2,4		;ASSUME STRUCTURE IS FOREIGN
	TRNE T1,(MS%DOM)	;IS IT DOMESTIC?
	MOVEI T2,3		;YES, GET DOMESTIC CODE
	STOR T2,ACCST		;STORE STRUCTURE TYPE
	SETONE ACCKT		;SET CONTROLLER TO ALL ONES
	MOVE T1,[SIXBIT/NORMAL/] ;PRESET TO NORMAL DISPOSITION
	MOVEM T1,ACCDSP(ACC)	; SAVE IT
	RET
ACCS3:	HLRZ T1,RBUF+2		;GET JOB NUMBER
	HRRZ T2,RBUF+3		;GET DEVICE DESIGNATOR
	HRLI T2,.DVDES+.DVDSK	;ADD DISK DESIGNATION
	CALL FNDACC		;SEE IF THERE IS A BLOCK ALREADY
	RET			;NO, JUST RETURN
	SKIPE ACCSVT(ACC)	;IS IT LEFT OVER FROM A PHYSICAL MOUNT REQ?
	RET			;NO, LEAVE IT ALONE
	CALLRET DELACC		;YES, DELETE IT
;ACCSTD - STRUCTURE COUNT BEING DECREMENTED. MAKE USAGE ENTRY.

ACCSTD:	HLRZ T1,RBUF+2		;GET JOB NUMBER
	MOVE T2,RBUF+3		;GET DEVICE DESIGNATOR
	HRLI T2,.DVDES+.DVDSK	;ADD DISK DESIGNATION
	CALL FNDACC		;FIND ACCOUNT BLOCK
	 RET			;THERE WAS NONE
	SOSE ACCFRK(ACC)	;ANY OTHER FORKS HAVE IT INCREMENTED?
	RET			;YES, DON'T SEND ANY INFO, YET
	CALL STOSTR		;STORE STR INFO FROM ACCOUNT BLOCK
	HRRZ T1,RBUF+2		;GET MOUNT COUNT
	MOVEM T1,USTDC
	MOVEI T1,.UTMNT		;THIS IS STRUCTURE MOUNT INFO
	CALL SNDACC		;SEND USAGE INFO TO MONITOR
	CALLRET DELACC		;DELETE ACCOUNT BLOCK

;ACCSTR - STRUCTURE BEING REMOVED.  SEND ACCOUNT BLOCKS TO USAGE

ACCSTR:	QSCANI AABQDB		;SET UP TO SCAN ACTIVE ACCOUNT BLOCKS
	MOVE Q1,RBUF+3		;GET DEVICE DESIGNATOR
	HRLI Q1,.DVDES+.DVDSK	;ADD DISK DESIGNATION
ACCSR1:	CALL QMSCAN		;GET ADDRESS OF NEXT ACC IN T2
	 RET			;NONE LEFT
	MOVEI ACC,-ACCLNK(T2)	;LOAD ACC ADDRESS
	CAME Q1,ACCDD(ACC)	;IS THIS THE STR BEING REMOVED
	JRST ACCSR1		;NO, GET NEXT ACCOUNT BLOCK
	CALL STOSTR		;STORE STR INFO INTO USAGE BLOCK
	MOVEI T1,.UTMNT		;THIS IS STRUCTURE MOUNT INFO
	CALL SNDACC		;SEND USAGE INFO TO MONITOR
	CALL DELACC		;DELETE ACCOUNT BLOCK
	JRST ACCSR1		;GET NEXT BLOCK
;ACCMTR - TAPE BEING REQUESTED.  BUILD ACCOUNTING BLOCK FOR USER

ACCMTR:	CALL GETACC		;GET ACCOUNT BLOCK
	 JRST DELACC		;ABORT SINCE ACC BLOCKS IN SHORT SUPPLY
	MOVSI T1,RSBACT(RSB)	;BLT SOURCE
	HRRI T1,ACCSTG(ACC)	;BLT DESTINATION
	BLT T1,ACCSTG+7(ACC)	;MOVE USER'S ACCOUNT STRING TO ACC
	GTAD			;STORE TIME SCHEDULED
	MOVEM T1,ACCSCD(ACC)	;IN ACCOUNT BLOCK
	LOAD T1,RSBJNO		;GET USER'S JOB NUMBER
	STOR T1,ACCJN
	CALL STONAM		;STORE USER'S NAME
	 JRST DELACC		;USER NOT AROUND, DELETE ACC BLOCK
	MOVSI T1,.DVDES+.DVMTA	;GET DEVICE DESIGNATOR
	MOVEM T1,ACCDD(ACC)	;STORE IN ACCOUNT BLOCK
	MOVE T1,[SIXBIT/NORMAL/] ;PRESET TO NORMAL DISPOSITION
	MOVEM T1,ACCDSP(ACC)	; SAVE IT
	STOR ACC,RSBACC		;STORE ACCOUNT BLOCK ADDRESS INTO RSB
	RETSKP

;ACCMTD - TAPE BEING DISMOUNTED. MAKE USAGE ENTRY FOR USER

;ACCEPTS: MT/	ADDRESS OF MT STATUS BLOCK
;	  MTA/	ADDRESS OF MTA STATUS BLOCK
;	  RSB/  ADDRESS OF REQUEST STATUS BLOCK

ACCMTD:	SAVEAC <ACC>
	LOAD ACC,RSBACC		;RETRIEVE ACCOUNT BLOCK ADDRESS
	MOVE T1,MTAVOL(MTA)	;GET VOLID
	MOVEM T1,UMTVID
	LOAD T1,MTALT		;GET LABEL TYPE
	MOVEM T1,UMTLT		; INTO USAGE BLOCK
	MOVEI T2,.LSUNL		;LABEL STATE, ASSUME UNLABELLED.
	CAIE T1,.LTUNL		;IS IT REALLY UNLABELLED?
	MOVEI T2,.LSPRI		;NO, MUST BE PRIVATE.
	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	TXNE T1,MA%SCR		;IS IT SCRATCH?
	MOVEI T2,.LSSCR		;YES, SAY SO
	MOVEM T2,UMTLS		;LABEL STATE INTO USAGE BLOCK
	CALL MTAGJF		;GET MAGTAPE JFN
	MOVEI T2,.MOINF		;GET TAPE INFORMATION
	MOVEI T3,.MOIWF		;GET LENGTH OF INFO BLOCK
	MOVEM T3,MSTRBK
	MOVEI T3,MSTRBK		;PUT ALL INFO INTO MSTRBK
	MTOPR
	CALL MTARJF		;RELEASE JFN
	MOVE T1,MSTRBK+.MOIRD	;GET NUMBER OF PHYSICAL RECS READ
	SUB T1,ACCPR(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTMRD
	MOVE T1,MSTRBK+.MOIWT	;GET NUMBER OF PHYSICAL RECS WRITTEN
	SUB T1,ACCPW(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTMWR
	MOVE T1,MSTRBK+.MOIRF	;GET NUMBER OF FRAMES READ
	IDIVI T1,^D1000		;IN THOUSANDS
	SUB T1,ACCFR(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTMRF
	MOVE T1,MSTRBK+.MOIWF	;GET NUMBER OF FRAMES WRITTEN
	IDIVI T1,^D1000		;IN THOUDANDS
	SUB T1,ACCFW(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTMWF
	MOVE T1,MSTRBK+.MOISR	;GET NUMBER OF SOFT READ ERRORS
	SUB T1,ACCSR(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTSRE
	MOVE T1,MSTRBK+.MOISW	;GET NUMER OF SOFT WRITE ERRORS
	SUB T1,ACCSW(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTSWE
	MOVE T1,MSTRBK+.MOIHR	;GET NUMBER OF HARD READ ERRORS
	SUB T1,ACCHR(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTHRE
	MOVE T1,MSTRBK+.MOIHW	;GET NUMBER OF HARD WRITE ERRORS
	SUB T1,ACCHW(ACC)	;SUBTRACT STARTING VALUE
	MOVEM T1,UMTHWE
	MOVE T1,RSBASN(RSB)	;GET VOLUME SET NAME
	MOVEM T1,UMTFSI
	MOVE T1,ACCDSP(ACC)	; GET DISPOSITION OF REQUEST
	MOVEM T1,UMTDSP		; SAVE IT
	MOVEI T1,.UTMMT		;THIS IS TAPE MOUNT INFO
	CALLRET SNDACC		;SEND ACCOUNTING INFO TO MONITOR
;DELACC - DELETE ACCOUNT BLOCK FROM QUEUE
;ACCEPTS: ACC/	ADDRESS OF ACCOUNT BLOCK
;RETURNS: +1, NOTHING

DELACC:	SETZM ACCDD(ACC)	;SET ACC INACTIVE
	QSCANI AABQDB		;SET UP TO SCAN ACTIVE ACC QUEUE
	SAVEAC <ACC>

; SEARCH ACCOUNT BLOCK QUEUE AND EXTRACT ABORTED REQUESTS

DELAC1:	CALL QMSCAN		;GET ADDRESS OF NEXT ACC ON QUEUE
	 RET			;NONE LEFT, EXIT
	MOVEI ACC,-ACCLNK(T2)	;LOAD ACC WITH ACC BLOCK ADDRESS
	SKIPE ACCDD(ACC)	;IS REQUEST ABORTED?
	JRST DELAC1		;NO, SKIP IT
	CALL QMDQS		;DEQUEUE ACC, GET LINKAGE ADDR IN T2
	MOVEI T1,IABQDB		;GET QDB ADDRESS
	CALL QMQH		;QUEUE ACC TO HEAD OF INACTIVE QUEUE
	JRST DELAC1		;CONTINUE SCAN

;FNDACC - FIND AN EXISTING ACCOUNT BLOCK

;ACCEPTS: T1/	JOB NUMBER
;	  T2/	DEVICE DESIGNATOR

;RETURNS: +1,	FAILURE, COULD NOT FIND BLOCK
;	  +2,	SUCCESS, ACC/ ADDRESS OF ACCOUNT BLOCK

FNDACC:	SAVEQ
	DMOVE Q1,T1
	QSCANI AABQDB		;SET UP TO SCAN ACTIVE ACC QUEUE
FNDAC1:	CALL QMSCAN		;GET ADDRESS OF NEXT ACC IN T2
	 RET			;NONE LEFT
	MOVEI ACC,-ACCLNK(T2)	;LOAD ACC ADDRESS
	CAME Q2,ACCDD(ACC)	;IS THIS THE RIGHT DEVICE DESIGNATOR?
	JRST FNDAC1		;NO, GET ANOTHER ACC
	LOAD T1,ACCJN
	CAME Q1,T1		;IS THIS THE RIGHT JOB?
	JRST FNDAC1		;NO, TRY ANOTHER ACC
	RETSKP			;SUCCESS

; GETABI - INITIALIZE FREE ACC POOL FOR GETACC
; RETURNS +1: ALWAYS

GETABI:	SAVEQ
	MOVEI Q1,ACC0		;GET ADDRESS OF ACC POOL
	MOVEI Q2,MAXACC+1	;# OF ACCS IN POOL
GTABI1:	MOVEI T1,IABQDB		;GET QDB ADDRESS
	MOVEI T2,ACCLNK(Q1)	;GET ADDRESS OF ACC LINKAGE
	CALL QMQT		;QUEUE ACC TO TAIL OF FREE QUEUE
	ADDI Q1,ACCSIZ		;POINT Q1 AT NEXT ACC
	SOJG Q2,GTABI1		;LOOP THRU ALL ACCOUNT BLOCKS
	RET
; GETACC - ALLOCATE AN ACCOUNT BLOCK
; RETURNS +1: ACCOUNT BLOCK ALLOCATED, BUT IT'S THE LAST ONE
;	  +2: ACCOUNT BLOCK ALLOCATED, MORE FREE ACC BLOCK'S LEFT
;  ACC/ ADDR OF ACCOUNTING BLOCK

GETACC:	MOVEI T1,IABQDB		;POINT TO INACTIVE ACC QUEUE
	CALL QMDQH		;DEQUEUE HEAD OF QUEUE
	 CALL STOP		;QUEUE EMPTY, PROGRAM LOGIC ERROR
	MOVEI ACC,-ACCLNK(T2)	;LOAD UP ACC AC
	MOVSI T1,1(ACC)		;BLT SOURCE
	HRRI T1,2(ACC)		;BLT DESTINATION
	SETZM 1(ACC)		;CLEAR 2ND WORD OF ACC
	BLT T1,ACCSIZ-1(ACC)	;CLEAR THE REST OF THE ACC
	GTAD
	MOVEM T1,ACCCRT(ACC)	;STORE TIME WHEN REQUEST WAS RECEIVED
	MOVEI T2,ACCLNK(ACC)	;GET ADDRESS OF ACC LINKAGE WORD
	SKIPN IABQDB		;WAS THIS THE LAST FREE ACC?
	JRST [	MOVEI T1,IABQDB	;YES, CAN'T GIVE IT AWAY
		CALLRET QMQH]	;PUT ON INACTIVE QUEUE AND TAKE +1
	MOVEI T1,AABQDB		;NOT THE LAST FREE ONE
	CALL QMQT		;QUEUE TO TAIL OF ACTIVE QUEUE
	RETSKP

;SNDACC - SEND ACCOUNTING INFORMATION TO MONITOR

;ACCEPTS: T1/	TYPE OF ENTRY
;	  ACC/	ADDRESS OF ACCOUNT BLOCK

;RETURNS: +1,	ALWAYS

SNDACC:	MOVE T4,T1		;SAVE TYPE OF ENTRY
	GTAD			;GET CURRENT DATE AND TIME
	SUB T1,ACCSVT(ACC)	;SUBTRACT SERVICED TIME GIVING DAYS,,FRACTION
	MOVEM T1,ACCEUT(ACC)	; AND STORE. CHKPNT WILL CONVERT TO SECONDS.
	MOVE T1,T4		;RESTORE TYPE OF ENTRY
	MOVEI T2,USRNAM		;MOVE COMMON INFO FROM ACCOUNT BLOCK
	HRLI T2,ACCUSR(ACC)	; TO USAGE AREA
	BLT T2,USRNAM+ACCCSZ-4
	LOAD T2,ACCJN		;GET JOB NUMBER
	MOVEM T2,JOBNO
	LOAD T2,ACCLN		;GET LINE NUMBER
	MOVEM T2,LINO
	MOVEI T2,USGSTR		;ASSUME STRUCTURE RECORD
	CAIE T1,.UTMNT		;IS IT A STRUCTURE?
	MOVEI T2,USGMTA		;NO, IT'S A MAGTAPE ENTRY
	MOVEI T1,.USENT		;WRITE AN ENTRY INTO SYSTEM DATA FILE
	SKIPN TSTF		;DON'T MAKE USAGE ENTRY IF TESTING
	USAGE
	 ERCAL WOUSGF		;REPORT ERROR
	SETZM JOBNO		;ZERO USAGE AREA
	MOVE T1,[JOBNO,,JOBNO+1]
	BLT T1,JOBNO+USGSIZ-2
	RET
;STONAM - STORE USER'S NAME INTO ACCOUNT BLOCK

;ACCEPTS: T1/	USER NUMBER
;RETURNS: +1,	FAILURE, COULD NOT FIND USER
;	  +2,	SUCCESS

STONAM:	MOVE T2,[-2,,Q1]
	MOVEI T3,.JITNO		;GET TERMINAL AND USER NUMBERS
	GETJI
	 RET			;USER NOT AROUND
	SKIPN Q2		;IS USER REALLY THERE?
	RET			;NO
	STOR Q1,ACCLN		;STORE LINE NUMBER
	HRROI T1,ACCUSR(ACC)	;GET USER NAME
	MOVE T2,Q2
	DIRST
	 JFCL			;CAN'T GET NAME
	RETSKP

;STOSTR - STORE STRUCTURE INFO INTO USAGE BLOCK

;ACCEPTS: ACC/	ADDRESS OF ACCOUNT BLOCK
;RETURNS: +1,	ALWAYS

STOSTR:	MOVE T1,ACCSTN(ACC)	;GET STRUCTURE NAME
	MOVEM T1,USTNM
	LOAD T1,ACCKT		;GET CONTROLLER TYPE
	MOVEM T1,USTKTP
	LOAD T1,ACCDT		;GET DEVICE TYPE
	MOVEM T1,USTDTP
	LOAD T1,ACCST		;GET STRUCTURE TYPE
	MOVEM T1,USTSTP
	LOAD T1,ACCNU		;GET NUMBER OF PACKS
	MOVEM T1,USTTNP
	LOAD T1,ACCMB		;GET MOUNT COUNT BEFORE MOUNTING
	MOVEM T1,USTMC
	MOVE T1,ACCDSP(ACC)	; GET DISPOSITION OF REQUEST
	MOVEM T1,USTDSP		; SAVE IT
	RET
SUBTTL AVR - AUTOMATIC VOLUME RECOGNITION

; AVR - INITIATE AVR SEQUENCE FOR A TAPE DRIVE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

AVR:	JN MTAJCT,,R		;EXIT IF I'M ALREADY PROCESSING
	JN MTALT,,R		;EXIT IF VOLUME ALREADY RECOGNIZED
	JN MTAMT,,[LOAD T1,MTASTE ;GET STATE
		CAIE T1,S.INIT	;IN INIT MODE?
		RET		;NO, EXIT
		JRST .+1]	;YES, PROCEED
	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	MOVEI T2,.LTUNL
	TXNN T1,MA%AVS		;IS AVR SUPPORTED FOR THIS DRIVE?
	STOR T2,MTALT		;NO, MUST CLASSIFY AS UNLABELED
	TXNN T1,MA%AVE		;IS AVR ENABLED FOR THIS DRIVE?
	JRST [	CALL REW	;NO, IS DRIVE LOADED?
		 RET		;NO
		CALLRET WOTMD]	;YES, TELL OPERATOR ABOUT IT
	MOVX T1,MA%UXV+MA%OPF
	ANDCAM T1,MTAFLG(MTA)	;CLEAR LABEL-RELATED FLAGS
	CALL MTAGJF		;GET JFN ON MTA DEVICE
	MOVEI T1,DENMAX
	STOR T1,MTADEN		;START AT HIGHEST DENSITY

; LOOP TO CHECK FOR LABEL AT ALL AVAILABLE DENSITIES

AVR2:	LOAD T1,MTADEN		;GET DENSITY
	CALL DRVDEN		;CAN THE DRIVE OPERATE AT THIS DENSITY?
	 JRST AVR2B		;NO, SKIP TO THE NEXT DENSITY
	MOVEI T1,AVR2A		;ENTER AT AVR2A AFTER REWIND
	CALL REWEA		;TRY TO REWIND
	 JRST AVR3		;CAN'T REWIND, WRAP UP AVR
	RET			;EXIT UNTIL REWIND COMPLETES

; END-ACTION FOR REWIND

AVR2A:	CALL CHKLT		;CHECK LABEL TYPE OF THE TAPE
	 SKIPA			;CAN'T READ TAPE AT THIS DENSITY
	JRST AVR3		;TAPE WAS IDENTIFIFED AT THIS DENSITY
AVR2B:	DECR MTADEN		;NEXT DENSITY
	JN MTADEN,,AVR2		;GO AROUND FOR ANOTHER TRY

; NOTHING CAN BE READ FROM THIS TAPE

	MOVEI T1,.SFTDF
	TMON			;GET TAPE-MOUNT CONTROLS SET BY SETSPD
	JXN T2,MT%UUT,[CALL UNLOAD ;IF UNLOAD SET BY INSTALLATION, DO IT
		CALL MTARJF	;DUMP JFN
		CALL WOLRDX	;TELL OPERATOR
		JRST AVR4]	;GO CHECK WAITING RSB'S

; MTA STATUS BLOCK NOW REFLECTS THE ATTRIBUTES OF THE AVR'ED VOLUME

AVR3:	CALL MTARJF		;DUMP JFN
	LOAD T1,MTASTE
	CAIN T1,S.INIT		;DRIVE IN INITIALIZE MODE?
	JRST [	CALLRET KVITAV]	;YES, SPECIAL EXIT
	CALL CKMPAV		;DRIVE STILL AVAILABLE?
	 CALL DACMTA		;NO, HERE IS A GOOD PLACE TO DEACTIVATE
	MOVE T1,MTAFLG(MTA)
	JXE T1,MA%LOD,AVR4	;WRAP UP IF DRIVE NOT LOADED
	CALL WOTMD		;TELL OPERATOR TAPE IS MOUNTED
	CALL WOCKSW		;IS THIS A WRITE-PROTECTED SCRATCH TAPE?
	 JRST AVR4		;YES, DRIVE UNLOADED AND MESSAGE TYPED
	SKIPN MTAVOL(MTA)	;HAS THE VOLUME BEEN IDENTIFIFED?
	RET			;NO, MUST WAIT FOR KEYIN
	CALL MATCHV		;YES, TRY FOR A MATCH

; CHECK IF NECESSARY TO TELL THE OPERATOR OF PENDING TAPE MOUNT REQUESTS

AVR4:	QSCANI ARBQDB		;SET UP TO SCAN REQUEST QUEUE
AVR41:	CALL NMTRSB		;GET NEXT TAPE REQUEST IN RSB AC
	 RET			;NONE LEFT
	CALL WOVMT		;TELL OPERATOR IF NECESSARY
	JRST AVR41		;LOOP THRU ALL REQUESTS
; CHKLT - IDENTIFY LABEL TYPE OF A TAPE AND UPDATE MTA STATUS BLOCK
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: COULD NOT READ ANY INFORMATION FROM THE TAPE
;	  +2: TAPE WAS IDENTIFIED AT DENSITY IN MTADEN

CHKLT:	SAVEQ

; Q1/	BIT 01 SET - VOL1 ACCESSIBILITY IS NOT BLANK
;	BIT 02 SET - HDR1 ACCESSIBILITY IS NOT BLANK
;	BIT 04 SET - OVERWRITE ACCESS DENIED - WORLD DP%CN IS RESET
;	BIT 10 SET - OVERWRITE ACCESS DENIED - WORLD FP%WR IS RESET
; Q2/	1 = READING CORE-DUMP MODE, 0 = READING INDUSTRY-COMPATIBLE MODE
; Q3/	CONTENTS OF MTAVOL AT TIME CHKLT WAS CALLED (USED TO RESTORE
;	MTAVOL IF TAPE HAS A VOL1 BUT NO HDR1)

	MOVE Q3,MTAVOL(MTA)	;REMEMBER CURRENT VOLID
	SETZ Q1,
	MOVEI T1,.LTUNL
	STOR T1,MTALT		;SET UNLABELED INITIALLY FOR LBLICV
	CALL MTAOPI		;OPEN MTA JFN
	 RETSKP			;OFFLINE

; CHECK FOR AND PROCESS VOL1 LABEL
; THE FIRST READ IS DONE IN CORE-DUMP MODE TO ALLOW FOR READING THE
; LARGEST POSSIBLE RECORD THAT TOPS-20 CAN WRITE (MOST LIKELY CASE
; SEEMS TO BE AN UNLABELED DUMPER TAPE WITH A LARGE BLOCKING FACTOR).
; BITS 0-31 OF THE FIRST WORD LOOK THE SAME IN CORE-DUMP AND I/C MODES,
; AND THAT'S THE FIRST 4 FRAMES OF THE RECORD (ALL I CARE ABOUT HERE).
; IF IT'S A VOL1, THEN REWIND AND READ IT AND ALL OTHER LABELS IN I/C
; MODE.  IF IT'S NOT A VOL1, THEN JUST CLASSIFY THE TAPE AS UNLABELED.

	MOVEI Q2,1		;SETUP Q2 FOR LOOPING
CHKL1:	CALL REW		;REWIND TO TEST IF DRIVE IS ONLINE
	 JRST [	CALL MTACLS	;OFFLINE, CLOSE JFN
		RETSKP]		;PREVENT CHECKING OTHER DENSITIES
	LOAD T1,MTAJFN		;GET JFN
	MOVEI T2,.MOSDM		;MTOPR FUNCTION CODE
	MOVE T3,[EXP .SJDM8,.SJDMC](Q2) ;GET DESIRED DATA MODE
	MTOPR			;SET DATA MODE
	CALL RDLBL		;TRY TO READ 1ST RECORD FROM TAPE
	 JRST [	JUMPLE T1,CHKLR1 ;TIMEOUT OR DATA ERROR
		SKIPG Q2	;SKIP IF CORE-DUMP READ
		SETZM LBUF1	;NON-LABEL READ SUCCESSFULLY
		JRST .+1]	; SO FORCE CHKV1 TO SAY IT'S UNLABELED
	SOJE Q2,[LOAD T1,MTAJFN	;FIRST READ ATTEMPT, GET JFN
		MOVEI T2,.MORDN	;FUNCTION = READ DENSITY
		MTOPR		;GET DENSITY THE TAPE WAS READ AT IN T3
		STOR T3,MTADEN	;REMEMBER IT
		CALL CHKV1A	;IS IT A VOL1?
		 JRST CHKLP	;NO, CLASSIFY AS UNLABELED
		JRST CHKL1]	;YES, REWIND AND READ IN I/C MODE
	CALL CHKV1		;CHECK FOR VOL1, FILL IN STATUS BLOCK
	 JRST CHKLP		;NOT LABELED (SHOULD NEVER GET HERE)
	CAIE T1," "		;VOL1 ACCESSIBILITY BLANK?
	TRO Q1,1		;NO, SET FLAG
	SETZM MTASET(MTA)	;LABELED TAPE - CLEAR SETNAME
	JUMPE T2,CHKL2		;JUMP IF IT CAN'T BE A TOPS-20 TAPE

; CHECK FOR AND PROCESS VOL2 LABEL

	CALL RDLBL		;YES, GET LABEL AFTER VOL1
	 JRST CHKLUN		;NO LABEL AFTER VOL1, IT'S UNLABELED
	CALL CHKV2		;IS IT A VOL2?
	 JRST CHKL3		;NO
	STOR T1,MA%SCR,MTAFLG(MTA) ;YES, STORE SCRATCH FLAG
	TRNN T2,DP%CN		;WORLD DP%CN RESET?
	TRO Q1,4		;YES, SET DP%CN ACCESS-DENIED FLAG
	MOVEI T1,.LTT20
	STOR T1,MTALT		;SET LABEL-TYPE TO TOPS-20

; CHECK FOR AND PROCESS HDR1 LABEL

CHKL2:	CALL RDLBL		;GET NEXT LABEL
	 JRST CHKLUN		;NO LABEL HERE, TAPE IS UNLABELED
CHKL3:	MOVE T1,LBUF2		;GET FIRST 5 CHARACTERS FROM RECORD
	TRZ T1,77777		;KEEP THE FIRST 3 CHARACTERS
	CAME T1,[ASCIZ/VOL/]	;IS IT A VOL
	CAMN T1,[ASCIZ/UVL/]	; OR A UVL?
	JRST CHKL2		;YES, CONTINUE SEARCH
	CALL CKHDR1		;IF HDR1, UPDATE STATUS BLOCK
	 JRST CHKLUN		;NOT HDR1, TAPE IS UNLABELED
	CAIE T1," "		;HDR1 ACCESSIBILITY BLANK?
	TRO Q1,2		;NO, SET FLAG

; CHECK FOR AND PROCESS HDR2 LABEL

	CALL RDLBL		;GET NEXT LABEL
	 JRST CHKLP		;NO LABEL
	CALL CKHDR2		;CHECK IF HDR2
	 JRST CHKLP		;NOT HDR2
	TRNN T1,FP%WR		;WORLD WRITE-ACCESS ALLOWED TO FILE?
	TRO Q1,10		;NO, SET WRITE-ACCESS DENIED
CHKLP:	CALL CHKLR1		;REWIND AND CLOSE JFN
	LOAD T1,MTALT		;GET LABEL TYPE
	CAIN T1,.LTANS		;ANSI?
	JRST [	TRNE Q1,1+2	;YES, ANY NON-BLANK ACCESSIBILITIES?
		JRST CHKLPS	;YES, SET PROTECTED
		JRST CHKLPR]	;NO, RESET PROTECTED
	CAIN T1,.LTT20		;TOPS-20?
	JRST [	TRNE Q1,4	;YES, WORLD WRITE ACCESS DENIED TO VOL?
		JRST CHKLPS	;YES, SET PROTECTED
		TRNE Q1,2	;RESET PROT IF FILE ACCESSIBILITY BLANK
		TRNN Q1,10	; OR IF WORLD WRITE ACCESS IS ALLOWED
		JRST CHKLPR
		JRST CHKLPS]	;NEITHER, SET PROTECTED
	RETSKP

CHKLPS:	SETONE MA%OPF,MTAFLG(MTA) ;SET OVERWRITE-PROTECTED FLAG
CHKLPR:	JE MA%SCR,MTAFLG(MTA),RSKP ;RETURN IF NOT SCRATCH
	MOVX T1,MA%OPF+MA%UXV	;IT'S A SCRATCH TAPE
	ANDCAM T1,MTAFLG(MTA)	;TURN OFF OVERWRITE INHIBITORS
	RETSKP

CHKLR1:	CALL REW		;GET BACK TO BOT
	 JFCL			;OFFLINE, WILL BE CAUGHT BY AVR
CHKLID:	CALL MTACLS		;CLOSE MTA
	RET

; TAPE HAS A VOL1 BUT NO HDR1 - CLASSIFY IT AS UNLABELED

CHKLUN:	MOVEI T1,.LTUNL
	STOR T1,MTALT		;SET LABEL TYPE TO UNLABELED
	MOVEM Q3,MTAVOL(MTA)	;REPLACE OLD VOLID
	JRST CHKLP		;WRAP UP AND EXIT
; CHKV1 - IDENTIFY A VOLUME WHOSE FIRST RECORD IS IN LBUF1
;  MTA/ ADDR OF MTA STATUS BLOCK
;  LBUF1/ UNMODIFIED RECORD READ FROM TAPE
; RETURNS +1: VOLUME IS UNLABELED, MTALT UPDATED
;	  +2: VOLUME IS LABELED, MTALT AND MTAVOL UPDATED
;		T1/ VOL1 ACCESSIBILITY CHARACTER
;		T2/ 1 MEANS VOL1 MEETS NECESSARY CONDITIONS FOR
;		    CLASSIFICATION AS TOPS-20 LABEL TYPE, ELSE 0

; CHKV1A - DETERMINE IF RECORD IN LBUF1 (IN CORE-DUMP FORMAT) IS A VOL1
;  LBUF1/ UNMODIFIED RECORD READ FROM TAPE IN CORE-DUMP MODE
; RETURNS +1: NOT A VOL1
;	  +2: IS A VOL1

CHKV1:	TDZA T1,T1		;REMEMBER CHKV1 ENTRY
CHKV1A:	MOVEI T1,1		;REMEMBER CHKV1A ENTRY
	SAVET			;SET UP TO RETURN VALUES TO CALLER
	SETZM CT2		;SET NOT TOPS-20
	MOVE T2,LBUF1		;GET 1ST 4 FRAMES FROM TAPE
	TRZ T2,17		;B32-B35 MEANINGLESS, SO SET TO ZERO
	CAMN T2,[713533,,237420] ;EBCDIC VOL1?
	JRST [	MOVEI T1,.LTEBC	;YES, SET LABEL TYPE TO EBCDIC
		JRST CHKV11]	;SKIP OTHER TESTS
	TDZ T2,[1B0+1B8+1B16+1B24] ;CLEAR 8TH BITS FOR ASCII CHECK
	CAMN T2,[BYTE(8) "V","O","L","1"] ;ASCII VOL1?
	JRST [	MOVEI T1,.LTANS	;YES, IS EITHER ANSI OR TOPS-20
		JRST CHKV11]	; BUT ASSUME ANSI FOR NOW...
CHKV12:	MOVEI T1,.LTUNL
	SKIPN CT1		;DON'T STORE LABEL TYPE IF CHKV1A
	STOR T1,MTALT		;SET LABEL TYPE = UNLABELED
	RET			;+1 RETURN FOR UNLABELED

; VOL1 LABEL WAS FOUND

CHKV11:	SKIPE CT1		;CHKV1A ENTRY?
	RETSKP			;YES, INDICATE RECORD WAS A VOL1
	STOR T1,MTALT		;STORE LABEL TYPE IN MTA TABLE
	CALL LBLICV		;CONVERT LABEL TO 7-BIT ASCII
	MOVE T1,[ILPTR(V1VID)]	;ADDRESS VOLID FIELD IN VOL1
	MOVEI T2,6		;6-CHARACTER FIELD
	CALL CVTA6		;CONVERT VOLID TO SIXBIT
	 JRST CHKV12		;BAD VOLID, SO ASSUME UNLABELED

; GIVE ERROR IF VOLID FROM "IDENTIFY" COMMAND DOESN'T MATCH THE
; ACTUAL VOLID THAT IS RECORDED ON THE TAPE

	MOVEM T1,MTAVOL(MTA)	;STORE ACTUAL VOLID IN MTA STATUS BLOCK
	SKIPE MTAIDV(MTA)	;DOES ALLEGED VOLID EXIST?
	CAMN T1,MTAIDV(MTA)	;YES, ALLEGED VOLID MATCH ACTUAL VOLID?
	SKIPA			;NO ALLEGED VOLID, OR IT MATCHES ACTUAL
	CALL [	TMCT <%I%M Cannot Change Volid Of Labeled Tape>
		MOVEI T3,TMCMSG	;POINT TO MESSAGE
		CALLRET BTWTON]	;TELL OPERATOR HE BLEW IT
	SETZM MTAIDV(MTA)	;CLEAR ALLEGED VOLID

; COPY VOL1 TO MTA STATUS BLOCK AND CHECK FOR TOPS-20 LABEL TYPE

	MOVSI T1,LBUF1		;BLT SOURCE
	HRRI T1,MTAV1(MTA)	;BLT DESTINATION
	BLT T1,MTAV1+LB8WDS-1(MTA) ;TRANSFER VOL1 LABEL TO STATUS BLOCK
	LDB T1,[LPTR(V1ACS)]	;GET ACCESSIBILITY CHARACTER
	MOVEM T1,CT1		;RETURN ACCESSIBILTY TO CALLER
	CAIE T1,"1"		;TOPS-20 PROTECTION?
	RETSKP			;NO, WILL CLASSIFY AS ANSI TAPE
	MOVE T1,[ILPTR(V1SCD)]	;GET POINTER TO SYS CODE IN VOL1
	MOVE T2,[POINT 7,T20SCD] ;GET POINTER TO TOPS-20 SYS CODE
CHK201:	ILDB T3,T1		;GET CHAR FROM VOL1
	ILDB T4,T2		;GET CHAR FROM TOPS-20 SYS CODE
	JUMPE T4,[AOS CT2	;MATCH SUCCESSFUL, SET TOPS-20 VOL1
		RETSKP]
	CAMN T3,T4		;MATCH SO FAR?
	JRST CHK201		;YES, CONTINUE SCAN
	RETSKP			;RETURN, NON-TOPS-20 VOL1

; TOPS-20 SYSTEM CODE

T20SCD:	ASCIZ /DECSYS20**   /
; CHKV2 - EXAMINE LABEL BUFFER FOR VOL2 RECORD
;  LBUF2/ RECORD TO BE EXAMINED
; RETURNS +1: RECORD IS NOT A VOL2
;	  +2: RECORD IS A VOL2
;		T1/ 0=NON-SCRATCH  1=SCRATCH
;		T2/ TOPS-20 VOLUME PROTECTION CODE

CHKV2:	SAVET			;SET UP TO RETURN VALUES TO CALLER
	SETZM CT1
	MOVE T1,LBUF2		;GET FIRST 5 CHARS OF LABEL
	TRZ T1,377		;MASK DOWN TO 4 CHARACTERS
	CAME T1,[ASCII/VOL2/]	;IS IT A VOL2?
	RET			;NO, RETURN +1
	MOVSI T1,LBUF1		;BLT SOURCE
	HRRI T1,MTAV2(MTA)	;BLT DESTINATION
	BLT T1,MTAV2+LB8WDS-1(MTA) ;TRANSFER VOL2 LABEL TO STATUS BLOCK

	MOVE T1,[ILPTR(V2PRO)]	;GET POINTER TO PROTECTION FIELD
	CALL PROTIN		;GET PROTECTION IN T1
	 MOVEI T1,777777	;BAD PROTECTION, ASSUME ACCESSIBLE
	MOVEM T1,CT2		;RETURN PROTECTION CODE TO CALLER

	MOVE T2,[ILPTR(V2OWN)]	;GET POINTER TO VOL2 OWNER-NAME FIELD
	MOVEI T3,V2OWNL		;GET # OF CHARACTERS TO SCAN
CHKV21:	ILDB T4,T2		;GET A CHAR FROM OWNER'S NAME
	CAIE T4," "		;SPACE?
	RETSKP			;NO, NOT SCRATCH SO RETURN
	SOJG T3,CHKV21		;CONTINUE SCAN
	AOS CT1			;SCAN COMPLETE, IT'S A SCRATCH
	RETSKP
; CKHDR1 - CHECK LBUF2 FOR HDR1 AND PROCESS HDR1 FIELDS
;  LBUF2/ LABEL TO BE EXAMINED
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: NOT HDR1 LABEL
;	  +2: WAS HDR1 LABEL, INFORMATION STORED IN MTA STATUS BLOCK
;		T1/ HDR1 ACCESSIBILITY CODE

CKHDR1:	MOVE T1,LBUF2		;GET FIRST 5 CHARS OF LABEL
	TRZ T1,377		;MASK DOWN TO 4 CHARACTERS
	CAME T1,[ASCII/HDR1/]	;IS THIS A HDR1?
	RET			;NO
	MOVE T1,[ILPTR(H1SET)]	;YES, POINT TO SETNAME FIELD
	MOVEI T2,6		;6-CHARACTER FIELD
	CALL CVTA6		;CONVERT SETNAME TO SIXBIT
	 SETZ T1,		;BAD SETNAME, ASSUME NONE
	MOVEM T1,MTASET(MTA)	;STORE SET NAME IN STATUS BLOCK
	MOVE T1,[ILPTR(H1EXP)]	;POINT AT EXPIRATION-DATE FIELD
	CALL LDATIN		;CONVERT THE DATE FROM THE LABEL
	 SETZ T1,		;BAD DATE, ASSUME EXPIRED
	SETO T2,		;SPECIFY CURRENT DATE/TIME
	MOVX T4,IC%JUD		;WANT JULIAN FORM
	ODCNV			;GET T2/ YEAR,,JULIANDAY
	MOVX T3,MA%UXV
	CAMLE T1,T2		;IS THE TAPE EXPIRED?
	IORM T3,MTAFLG(MTA)	;NO, SET NOT-EXPIRED FLAG
	LDB T1,[LPTR(H1ACS)]	;GET ACCESSIBILITY CODE FOR CALLER
	RETSKP


; CKHDR2 - CHECK LBUF2 FOR HDR2 LABEL
;  LBUF2/ LABEL TO BE EXAMINED
; RETURNS +1: NOT HDR2
;	  +2: HDR2, T1/ TOPS-20 FILE PROTECTION CODE

CKHDR2:	MOVE T1,LBUF2		;GET 5 CHARS
	TRZ T1,377		;MASK DOWN TO 4 CHARACTERS
	CAME T1,[ASCII/HDR2/]	;HDR2?
	RET			;NO
	MOVE T1,[ILPTR(H2PRO)]	;GET POINTER TO PROTECTION CODE FIELD
	CALL PROTIN		;GET PROTECTION
	 MOVEI T1,777777	;ERROR, ASSUME UNPROTECTED
	RETSKP
; LBLICV - CONVERT INDUSTRY-COMPATIBLE LABEL IN LBUF1 TO 7-BIT ASCII
;	   LABEL IN LBUF2, USING THE FOLLOWING RULES:
;		NO CONVERSION PERFORMED FOR UNLABELED TAPES
;		ANSI AND TOPS-20 LABEL TYPES ASSUMED TO BE 8-BIT ASCII
;		EBCDIC LABEL TYPE ASSUMED TO BE 8-BIT EBCDIC
;  LBUF1/ LABEL TO BE CONVERTED, 80 8-BIT BYTES
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS, LBUF2/ 7-BIT ASCII EQUIVALENT OF LABEL IN LBUF1

LBLICV:	SAVEQ
	LOAD T1,MTALT		;GET LABEL TYPE IN T1
	CAIN T1,.LTUNL		;UNLABELED?
	RET			;YES, RETURN TAKING NO ACTION
	DMOVE Q1,[POINT 8,LBUF1	;GET LOAD POINTER IN Q1
		POINT 7,LBUF2]	;GET GET STORE POINTER IN Q2
	MOVEI T2,LBLSIZ		;GET # OF FRAMES TO PROCESS
LBLCV1:	ILDB T3,Q1		;GET A BYTE FROM LBUF1
	CAIN T1,.LTEBC		;EBCDIC LABEL?
	JRST [	ADJBP T3,[POINT 7,EATT,6] ;YES, POINT AT ASCII EQUIV.
		LDB T3,T3	;GET ASCII EQUIVALENT IN T3
		JRST .+1]
	IDPB T3,Q2		;STORE CHARACTER IN LBUF2
	SOJG T2,LBLCV1		;LOOP THRU ENTIRE BUFFER
	RET
; RDLBL - READ A LABEL FROM A TAPE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: T1/ -1 = READ I/O OPERATION TIMED OUT
;	      T1/  0 = DEVICE OR DATA ERROR ON READ
;	      T1/  1 = TAPE MARK OR RECORD .LT. 80 FRAMES READ
;	  +2: RECORD OF 80 BYTES OR LONGER READ SUCCESSFULLY INTO
;	      LBUF1 IN INDUSTRY-COMPATIBLE FORMAT; ASCII EQUIVALENT
;	      LABEL IN LBUF2

RDLBL:	MOVE T1,[IOWD LBUF1W,LBUF1] ;GET IOWD FOR ENTIRE BUFFER
	SKIPN READCL		;FIRST READ SINCE I STARTED?
	MOVEM T1,READCL		;YES, SET UP TRIAL IOWD, EXPECT DUMPX3
RDLBL0:	LOAD T1,MTAJFN
	MOVEI T2,READCL		;GET ADDRESS OF COMMAND LIST
	IOXCT DUMPI,RDLBL1,RDLBL2 ;EXECUTE AND TIME OUT DUMPI JSYS
	JRST RDLBL3		;SUCCESSFUL (PROBABLY VERY RARE)

; ERROR RETURN FROM DUMPI

RDLBL1:	CALL CLRTAP		;CLEAR ERRORS AND GET ERROR INFO
	 JRST RDLBL2		;TIMED OUT
	CAIN T1,DUMPX3		;RECORD SIZE TOO LARGE?
	JRST [	MOVSI T1,1000	;YES
		ADDM T1,READCL	;REDUCE IT BY A PAGE
		JRST RDLBL0]	;TRY IT AGAIN WITH SMALLER RECORD SIZE
	CAIN T1,IOX4
	JRST [	MOVEI T1,1	;TAPE MARK, SET NON-LABEL
		RET]
	CAIE T1,IOX5		;DEVICE OR DATA ERROR?
	CALL STOP		;NO, I CAN'T HANDLE THIS ONE
	TXNE T2,MT%DVE+MT%DAE	;DEVICE ERROR OR DATA ERROR?
	JRST [	SETZ T1,	;YES
		RET]
	CAIGE T3,LBLSIZ		;IS THE RECORD LONG ENOUGH?
	JRST [	MOVEI T1,1	;NO
		RET]
RDLBL3:	CALL LBLICV		;GOOD LABEL, CONVERT IT
	RETSKP			;SUCCESSFUL RETURN

; DUMPI DID NOT COMPLETE IN TIME

RDLBL2:	CALL WOTIMO		;REPORT TIMEOUT TO OPERATOR
	SETO T1,		;RETURN -1
	RET
; POLLR - SELF-PERPETUATING PERIODIC MAGTAPE POLLING ROUTINE
;	  CHECKS FOR ONLINE-TO-OFFLINE AND OFFLINE-TO-ONLINE TRANSITIONS
; RETURNS +1: ALWAYS

POLLR:	TXO F,POLLF		;CAUSE CHECKS FOR ONLINE-TO-OFFLINE
	CALL TDSCIR		;PERFORM DRIVE SCAN
	TXZ F,POLLF
	MOVEI T1,POLINT		;GET INTERVAL BETWEEN POLLS
	MOVEI T2,POLLR		;ROUTINE ADDRESS
	CALLRET SRAI		;SCHEDULE NEXT POLL AND EXIT

; TDSCIH - CALLED AS A RESULT OF MTA STATUS CHANGE INTERRUPTS

TDSCIH:	AOSE TDSCF		;SCHEDULING REQUEST PRESENT ALREADY?
	DEBRK			;YES, EXIT
	CALL EIHR		;NO, REQUEST SCHEDULING AT TDSCIR
	EXP TDSCIR

; TDSCIR - CALLED BY SCHEDULER, REQUESTED BY TDSCIH
; RETURNS +1: ALWAYS

TDSCIR:	SAVEQ
	SAVEAC <MTA>
	SETOM TDSCF		;SET NO SCHEDULER REQUESTS FOR TDSCIR
	MOVE Q1,MTAN		;GET # OF MTA DEVICES ON SYSTEM
	MOVEI MTA,MTA0-MTASZ	;INIT MTA STATUS BLOCK POINTER

; I DON'T KNOW WHICH DRIVE DID IT, SO I HAVE TO CHECK EVERY ONE

TDSCI1:	SOJL Q1,R		;EXIT IF NO MTA DEVICES LEFT TO CHECK
	ADDI MTA,MTASZ		;GET STATUS BLOCK ADDRESS
	CALL TDSC1		;CHECK IT FOR A STATUS CHANGE
	JRST TDSCI1		;LOOP THRU ALL DRIVES
; TDSC1 - CHECK TAPE DRIVE FOR ONLINE/OFFLINE/REWIND-COMPLETE TRANSITION
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

TDSC1:	SAVEQ
	LOAD T1,MTASTE		;GET STATE
	JUMPE T1,R		;IGNORE IF NOT AVAILABLE
	CAIE T1,S.INIT		;IN INIT MODE?
	JRST [	JN MTAMT,,R	;NO, EXIT IF USER HAS THE DRIVE
		JRST .+1]
	CALL MTAGJF		;GET JFN NOW TO REDUCE GTJFN OVERHEAD
	MOVE Q1,MTAFLG(MTA)	;Q1/ MTA FLAGS
	CALL GMTADS
	MOVE Q2,T1		;Q2/ MTA STATUS BITS FROM MONITOR
	JXN Q2,SJ%OFS,[TXZE Q1,MA%LOD ;IF OFFLINE, DID I THINK SO TOO?
		CALL WOUNLW	;NO, ADMONISH OPERATOR
		MOVEM Q1,MTAFLG(MTA) ;UPDATE FLAGS
		JRST .+1]
	LOAD Q3,MTAREA		;END-ACTION ADDRESS PRESENT?
	JUMPN Q3,TDSC11		;YES
	TXNE Q1,MA%LOD		;PROCEED IF I THINK DRIVE IS UNLOADED
	TXNE Q1,MA%ULP		;PROCEED IF UNLOAD PENDING
	JRST TDSC11		;ONE OF THE ABOVE WAS TRUE
	TXNN F,POLLF		;POLLING?
	JRST [	CALLRET MTARJF]	;NO, NO NEED FOR FURTHER ANALYSIS
TDSC11:	LOAD T1,SJ%WLK,Q2	;GET WRITE-LOCKED BIT
	TRC T1,1		;COMPLEMENT TO GET WRITE-ENABLED
	STOR T1,MA%WEN,MTAFLG(MTA) ;STORE HERE FOR EASY REFERENCE

; CHECK FOR PENDING UNLOAD-REQUEST OR REWIND-ENDACTION

	TXZE Q1,MA%ULP		;WAS AN UNLOAD-REQUEST PENDING?
	JRST [	JXN Q2,SJ%REW,[CALLRET MTARJF] ;YES
		MOVEM Q1,MTAFLG(MTA) ;RESET MA%ULP IN STATUS BLOCK
		CALL UNLOAD	;UNLOAD THE DRIVE
		JRST .+1]
	JUMPN Q3,[JXN Q2,SJ%REW,[CALLRET MTARJF] ;EXIT IF REWINDING
		SETZRO MTAREA	;CLEAR END-ACTION ADDRESS
		CALL MTARJF	;DUMP JFN
		CALLRET (Q3)]	;CALL END-ACTION ROUTINE AND RETURN

; DRIVE NOT UNDER USER CONTROL AND AVR SEQUENCE NOT IN PROGRESS

	TXNN F,POLLF		;CHECK FOR ANY TRANSITION IF POLLING
	TXNN Q1,MA%LOD		;EXIT IF I THINK THE DRIVE IS LOADED
	CAIA			;POLLING OR DRIVE UNLOADED
	JRST [	CALLRET MTARJF]	;NOT POLLING AND DRIVE LOADED
	CALL REW		;IS IT LOADED NOW?
	 JRST [	TXNE Q1,MA%LOD	;NO, DID I THINK IT WAS LOADED?
		CALL WOUNLW	;YES, ADMONISH OPERATOR
		CALLRET MTARJF]	;DUMP JFN AND RETURN
	CALL MTARJF		;YES, DUMP JFN SO AVR CAN OCCUR
	TXNE Q1,MA%LOD		;HAS IT BEEN ONLINE ALL ALONG?
	RET			;YES, TAKE NO ACTION

; DRIVE IS COMING ON-LINE

	SETONE MA%LOD,MTAFLG(MTA) ;SET DRIVE-LOADED
	MOVX T1,MA%SCR+MA%UXV+MA%OPF+MA%ULP+MA%VMG
	ANDCAM T1,MTAFLG(MTA)	;CLEAR VARIOUS FLAGS
	SETZB T1,MTAVOL(MTA)	;SET VOLUME NOT IDENTIFIED (YET)
	SETZM MTAIDV(MTA)	;CLEAR OPERATOR-SUPPLIED VOLID
	STOR T1,MTALT		;SET RECOGNITION NOT ATTEMPTED (YET)
	LOAD T1,MTASTE
	CAIN T1,S.INIT		;DRIVE IN INITIALIZE MODE?
	JRST [	CALLRET KVITAV]	;YES, SPECIAL EXIT
	CALLRET AVR		;PERFORM IDENTIFICATION SEQUENCE
NOSHIP,<
SUBTTL DECTAPE SUPPORT

; RLSDTA - PROCESS RELEASE OF ALLOC'ED DECTAPE DEVICE
;  T1/ DEVICE DESIGNATOR
; RETURNS +1: ALWAYS

RLSDTA:	SAVEQ
	MOVE Q1,T1		;SAVE DESIGNATOR
	MOVE T2,T1		;COPY DESIGNATOR TO T2 FOR ALLOC
	MOVEI T1,.ALCAL		;ALLOC FUNCTION CODE
	MOVNI T3,1		;MAKE DTA AVAILABLE TO ALL USERS
	ALLOC
	 JFCL			;IGNORE FAILURE

; FIND REQUEST THAT WAS USING THIS DECTAPE AND DELETE IT

	TMCT <%I%5V Released>
	QSCANI ARBQDB		;SET UP TO SCAN REQUEST QUEUE
RDTA1:	CALL NXXRSB		;GET ADDRESS OF NEXT ACTIVE RSB
	 JRST RDTA2		;NONE LEFT
	LOAD T1,RSBTYP		;GET REQUEST TYPE
	CAIE T1,.MNTDT		;IS IT A DECTAPE-MOUNT REQUEST?
	JRST RDTA1		;NO, SKIP IT
	CAME Q1,RSBDTA(RSB)	;DOES THIS REQUEST OWN THE DECTAPE?
	JRST RDTA1		;NO
	LOAD T1,RSBJNO		;GET OWNER'S JOB #
	TMCT < by job %1D>
	ABTREQ (ABRTNR)		;FOUND THE OWNER, DELETE REQUEST
RDTA2:	MOVEI T3,TMCMSG		;GET ADDRESS OF MESSAGE
	CALLRET BTWTON		;TELL OPR'S THAT DECTAPE WAS RELEASED
; TLUDT - BUILD BLOCKS FOR SUCCESSFUL DECTAPE-MOUNT RESPONSE
;	  (CALLED BY TELUSR)
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS, T1/ FLAGS FOR GALAXY MSG HEADER

TLUDT:	STKVAR <<DVBLK,3>>
	CALL VQGCV		;GET VOLID IN T1
	TMCT <%I[DECtape volume %1S mounted]%_>
	MOVEI T1,TMCMSG		;GET ADDRESS OF TEXT
	MOVEI T2,.MNRTX		;GET ARGUMENT TYPE
	CALL PBTXT		;CREATE BUILDING BLOCK CONTAINING TEXT
	MOVE T1,[FLD(3,AR.LEN)+FLD(.MNRDV,AR.TYP)] ;GET HEADER
	MOVE T2,RSBSSN(RSB)	;GET SETNAME
	DMOVEM T1,DVBLK		;STORE HEADER AND SETNAME
	MOVE T1,RSBDTA(RSB)	;GET DECTAPE DEVICE DESIGNATOR
	MOVEM T1,2+DVBLK	;STORE DESIGNATOR IN .MNRDV BLOCK
	MOVEI T1,DVBLK		;GET ADDRESS OF BLOCK
	CALL PBBLK		;INSTALL BLOCK IN MESSAGE
	SETZ T1,		;NO FLAGS
	RET
; UDTM - PROCESS USER DECTAPE-MOUNT REQUEST RECEIVED FROM QUASAR
;  T1/ ADDRESS OF DECTAPE-MOUNT ENTRY IN IPCF MESSAGE FROM QUASAR
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

UDTM:	MOVEI T2,[[	MOVX T1,TM%WEN ;ROUTINE TO PROCESS FLAGS
			AND T1,.MEFLG(Q1)
			MOVEM T1,RSBUFL(RSB)
			RETSKP]
		BTRSET		;SETNAME
		BTRVLS		;VOLID LIST
		BTRRMK		;REMARK
		0]
	CALL BTMRSB		;BUILD RSB
	 RET			;ABORTED, EXIT
	MOVEI T1,1
	STOR T1,RSBCV		;CURRENT VOLUME = 1
	CALL PWATCH		;ABORT REQUEST IF USER DELETES PID
	MOVEI T1,RST.WM
	STOR T1,RSBSTE		;SET STATE = WAITING FOR MOUNT

; BUILD HEADER LINE

UDTM1:	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%IDECtape Mount Request # %1D>
	CALL CPYHDR		;COPY HEADER TO OPRHDR

; BUILD BODY OF MESSAGE

	CALL VQGCV		;GET CURRENT VOLID IN T1
	TMCT <%IMount volume %1S%_%U>
	SKIPE RSBRMK(RSB)	;DID THE USER SUPPLY A REMARK?
	JRST [	MOVEI T1,RSBRMK(RSB) ;YES, GET ADDR OF REMARK
		TMCT <%_User's remark: %1A>
		JRST .+1]
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <
  RESPOND msg# DTAn:
   or
  DELETE MOUNT-REQUEST %1D /REASON:reason>

; SEND MESSAGE AND GET RESPONSE

	MOVEI T2,RSBWTB(RSB)	;GET WTB ADDRESS
	MOVEI T3,OPRHDR		;GET ADDRESS OF HEADER
	JSP T1,BTWTOR		;SEND WTOR AND RECEIVE REPLY

; PROCESS RESPONSE

	MOVEI RSB,-RSBWTB(T2)	;LOAD RSB AC
	CALL COMNDI		;INIT FOR COMND PARSING
	MOVEI T2,[FLDDB. .CMDEV]
	CALL COMNDX		;PARSE DEVICE NAME
UDTM2:	 JRST [	MOVEI T3,[ASCIZ/Response Does Not Specify DECtape/]
		CALL BTACK	;REJECT IT
		JRST UDTM1]	;RE-ISSUE WTOR
	LOAD T1,DV%TYP,T2	;GET DEVICE TYPE
	CAIE T1,.DVDTA		;DECTAPE?
	JRST UDTM2		;NO, REJECT
	MOVEI T1,.ALCAL		;GET ALLOC FUNCTION CODE
	LOAD T3,RSBJNO		;GET USER'S JOB #
	ALLOC			;TRY TO ALLOC DTA TO USER
	 JRST UDTM3		;FAILED

; ALLOCATION SUCCESSFUL

	MOVEM T2,RSBDTA(RSB)	;STORE DEVICE DESIGNATOR
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%I%2V Allocated To Request # %1D>
	MOVEI T3,TMCMSG
	CALL BTACK		;ACKNOWLEDGE SUCCESSFUL ALLOCATION
	MOVEI T1,RST.AC
	STOR T1,RSBSTE		;SET STATE TO ACTIVE
	CALL TELUSR		;TELL THE USER HE GOT IT
	CALLRET TCKP		;TELL QUASAR

; ALLOCATION FAILED

UDTM3:	CALL [	SAVET		;PRESERVE T1-T4
		TMCT <%ICannot Allocate %2V> ;BUILD HEADER
		CALLRET CPYHDR]	;SAVE HEADER IN OPRHDR
	CAIE T1,ALCX5		;SOMEONE ELSE HAS IT?
	JRST [	TMCT <%IError from ALLOC JSYS: %1J>
		JRST UDTM4]
	MOVE T1,T2		;ANOTHER JOB HAS IT
	DVCHR			;GET OWNER'S JOB # IN LH(T3)
	HLRZS T3		;MOVE TO RIGHT HALF
	TMCT <%IAlready in use by job %3D>
UDTM4:	MOVEI T3,OPRHDR
	CALL BTACKT		;TELL OPERATOR ABOUT ALLOC FAILURE
	JRST UDTM1		;SEND WTOR AGAIN
>;NOSHIP
SUBTTL IPCF SEND AND RECEIVE

; GSYSPD - DOES MUTIL TO GET PID FROM SYSTEM PID TABLE
;  T1/ INDEX INTO SYSTEM PID TABLE
; RETURNS +1: PID COULD NOT BE OBTAINED
;	  +2: SUCCESS, PID IN T1

GSYSPD:	SKIPE TSTF		;TESTING?
	JRST GSYSPT		;YES, SPECIAL CODE
	MOVE T2,T1		;COPY INDEX TO T2 FOR XMUTIL
	MOVEI T1,.MURSP		;FUNCTION = RETURN SYSTEM PID
	CALL XMUTIL		;GET IT
	 JRST [	CAIN T1,IPCF27	;SYSTEM PID TABLE SLOT EMPTY?
		RET		;YES, TAKE ERROR RETURN
		CALL STOP]	;UNEXPECTED ERROR
	MOVE T1,T3		;COPY TO T1 FOR RETURN
	RETSKP			;SUCCESSFUL RETURN

GSYSPT:	STAKT
	MOVE T2,[[EXP IP%CPD,0,0,<20,,TBUF+4>,.IPCIW,0],,TBUF]
	BLT T2,TBUF+5		;MOVE PDB AND PART OF MESSAGE TO BUF
	SKIPL SYPIDS(T1)	;WANT USERNAME PREFIX?
	JRST [	HRROI T1,TBUF+6	;NO, SET UP DESTINATION POINTER
		JRST GSYSP1]	;COPY PID NAME SANS PREFIX INTO TMSG
	GJINF			;GET USER# IN T1
	MOVE T2,T1		;COPY INTO T2
	MOVE T1,[POINT 7,TBUF+6] ;GET POINTER
	MOVEI T3,"["
	IDPB T3,T1
	DIRST			;ADD USER NAME
	 JSHLT
	MOVEI T2,"]"
	IDPB T2,T1
GSYSP1:	MOVE T2,CT1		;GET SYSTEM PID TABLE INDEX
	HRRO T2,SYPIDS(T2)	;GET POINTER TO STRING
	SETZ T3,		;STOP ON NULL
	SOUT			;ADD PID NAME
	MOVEI T1,4
	MOVEI T2,TBUF
	MSEND			;SHIP OFF QUESTION TO INFO
	 JSHLT
	SETZM TBUF		;CLEAR FLAGS WORD FOR RECEIVE
	MOVE T3,TBUF+1		;GET MY PID SO I CAN RECEIVE
	MOVE T4,[20,,TBUF+4]	;SIZE,,MSGADDR
	DMOVEM T3,TBUF+2	;SET WORDS 2 & 3 OF PDB
	MRECV			;RECEIVE INFO'S REPLY
	 JSHLT
	LOAD T4,IP%CFE,TBUF+.IPCFL ;ERROR FROM INFO?
	JUMPN T4,[MOVEI T1,.MUDES ;YES, NO SUCH PID
		MOVE T2,TBUF+2	;GET THE PID WE PICKED UP
		CALL XMUTIL	;LIQUIDATE IT
		 JSHLT		;COULDN'T
		HRROI T1,TBUF+6	;RETURN POINTER TO PID NAME
		RET]
	TMSG <% MOUNTR Found PID for >
	HRROI T1,TBUF+6
	PSOUT
	 TMSG <
>
	MOVEI T1,.MUDES
	MOVE T2,TBUF+2		;GET THE PID I USED FOR THIS CRAP
	CALL XMUTIL		;LIQUIDATE IT
	 JSHLT
	MOVE T1,TBUF+5		;GET PID FOR CALLER
	RETSKP			;GIVE IT TO HIM
SYPIDS:	0
	0
	-1,,[ASCIZ/QUASAR/]
	-1,,[ASCIZ/MOUNTR/]
	-1,,[ASCIZ/ORION/]
; MRCVIH - ENTERED BY SCHEDULER WHEN INTERRUPT RECEIVED FROM PID
; RETURNS +1: ALWAYS

MRCVIH:	TXO F,MRMSF+MRPGF	;EXPECTING PAGE-MODE MESSAGE

; RECEIVE THE HEAD MESSAGE FROM THE QUEUE

MRCVI1:	TXZN F,MRMSF		;RECEIVE QUEUE EMPTY?
	RET			;YES, EXIT TO SCHEDULER
	TXCN F,MRPGF		;NON-PAGE-MODE MESSAGE COMING?
	JRST [	MOVX T1,IP%CFB+IP%TTL ;YES, GET FLAGS
		MOVE T2,[1000,,RBUF] ;SIZE,,ADDRESS
		JRST MRCVI3]	;REJOIN
	MOVX T1,IP%CFB+IP%TTL+IP%CFV ;DON'T BLOCK, TRUNCATE, PAGE MODE
	MOVE T2,[1000,,RBUF_-9]	;SIZE,,PAGE#
MRCVI3:	MOVEM T1,.IPCFL+MRPDB	;SET FLAGS
	MOVEM T2,.IPCFP+MRPDB	;SET RECEIVER BUFFER LENGTH,,ADDRESS
	MOVE T3,MYPID
	MOVEM T3,.IPCFR+MRPDB	;SET RECEIVER'S PID
	MOVEI T1,4		;LENGTH OF PDB
	MOVEI T2,MRPDB		;ADDRESS OF PDB
	MRECV			;RECEIVE THE MESSAGE
	 JRST [	CAIN T1,IPCFX2	;QUEUE EMPTY?
		RET		;YES, EXIT TO SCHEDULER
		TXO F,MRMSF	;SET DO-MRECV FLAG
		CAIN T1,IPCF16	;WRONG MODE?
		JRST MRCVI1	;YES, TRY OTHER MODE
		CALL STOP]	;CAN'T HANDLE THIS ERROR
	AOS MSGSIN		;COUNT # OF MESSAGES IN
	JUMPN T1,[TXNE T1,IP%CFV ;THERE IS ANOTHER MSG, WHAT MODE?
		TXO F,MRPGF	;PAGE-MODE
		TXO F,MRMSF	;FORCE ANOTHER MRECV
		JRST .+1]
	TXNN F,INITF		;DISCARD MESSAGE IF INITIALIZING
	CALL MRCVPM		;PROCESS MESSAGE
	JRST MRCVI1		;GO CHECK FOR MORE MESSAGES

; REFER THE MESSAGE TO THE APPROPRIATE PROCESSING ROUTINE

MRCVPM:	JN IP%CFM,MRPDB+.IPCFL,R ;DISCARD UNDELIVERED MAIL
	LOAD T1,IP%CFC,MRPDB+.IPCFL ;SENT BY <SYSTEM> ?
	JUMPN T1,[CALLRET MRSYS] ;YES, PROCESS IT
	MOVE T1,MRPDB+.IPCFS	;GET SENDER'S PID
	MOVEI T2,APNUM-1	;# OF ASSOCIATED PROCESSES - 1
MRCVAP:	CAMN T1,APPID(T2)	;FROM THIS A/P?
	JRST [	CALLRET @APMRC(T2)] ;YES, GIVE IT TO HIS HANDLER
	SOJGE T2,MRCVAP		;NO, CHECK THE OTHERS
	RET			;I DON'T KNOW THE SENDER, SO PITCH IT
; MRSYS - PROCESS IPCF MESSAGE FROM SYSTEM TASK
;  T1/ SYSTEM SENDER CODE FROM IP%CFC FIELD OF PDB
;  MRPDB, RBUF/ PDB AND MESSAGE
; RETURNS +1: ALWAYS

MRSYS:	CAIN T1,.IPCCF		;SENT BY INFO?
	JRST [	LOAD T1,IP%CFE,MRPDB+.IPCFL ;YES, GET CODE
		CAIN T1,.IPCKM	;WATCHED PID DELETED?
		JRST [	CALLRET INFOK] ;YES, GO PROCESS IT
		CAIE T1,.IPCBP	;BAD PID (RESPONSE TO .IPCIK) ?
		RET		;I DON'T RECOGNIZE IT, SO PITCH IT
		CALLRET PRQPID]	;BAD PID, CHECK REQUEST QUEUE
	CAIE T1,.IPCCC		;SENT BY SYSTEM IPCF?
	RET			;NO, PITCH IT
	HLRZ T1,MRPDB+.IPCFP	;GET SIZE OF MESSAGE
	JUMPE T1,R		;NO MESSAGE, NO WORK
	MOVE T2,RBUF		;GET SYSTEM MESSAGE CODE
	CAIN T2,.IPCSA
	JRST [	CALLRET SALMSG]	;ALLOCATED DEVICE BEING RETURNED
	CAIN T2,.IPCTR
	JRST [	CALLRET SMTMSG]	;MESSAGE ABOUT MAGTAPES
	CAIN T2,.IPCMS
	JRST [	CALLRET ACCSTI]	;STRUCTURE COUNT BEING INCREMENTED
	CAIN T2,.IPCDS
	JRST [	CALLRET ACCSTD]	;STRUCTURE COUNT BEING DECREMENTED
	CAIN T2,.IPCRS
	JRST [	CALLRET ACCSTR]	;STRUCTURE BEING REMOVED
	RET
; INFOK - PROCESS PID-KILLED MESSAGE FROM INFO
;  RBUF/ PID THAT WAS KILLED
; RETURNS +1: ALWAYS

INFOK:	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB>
INFOK1:	CALL QMSCAN		;GET NEXT ENTRY FROM RSB QUEUE
	 RET			;NONE LEFT, SPLIT
	MOVEI RSB,-RSBLNK(T2)	;GET RSB ADDRESS
	MOVE T1,RSBPID(RSB)	;GET PID FROM RSB
	CAMN T1,RBUF		;WAS IT KILLED?
	CALL VALPID		;YES, ABORT REQUEST IF NECESSARY
	 JFCL
	JRST INFOK1


; SALMSG - PROCESS ALLOCATED-DEVICES-RELEASED MESSAGE
; RETURNS +1: ALWAYS

SALMSG:	SAVEQ
	HLRZ Q1,MRPDB+.IPCFP	;GET # OF DEVICES PLUS 1
SALMS1:	SOJLE Q1,[CALLRET MCHWMT] ;EXIT WHEN DEVICE LIST EXHAUSTED
	MOVE T1,RBUF(Q1)	;GET DEVICE DESIGNATOR
NOSHIP,<
	LOAD T2,DV%TYP,T1	;GET DEVICE TYPE
	CAIN T2,.DVDTA		;DECTAPE?
	JRST [	CALL RLSDTA	;YES, CALL PROCESSOR
		JRST SALMS1]	;GET NEXT DEVICE
>;NOSHIP
	CALL DDMT		;CONVERT IT TO MT STATUS BLK ADDR IN MT
	 JRST SALMS1		;NOT MT DEVICE, IGNORE IT
	CALL MTRLS		;PROCESS RELEASE OF MT DEVICE
	JRST SALMS1		;ON TO NEXT DEVICE IN IPCF MESSAGE
; SMTMSG - PROCESS IPCF MESSAGES FROM MONITOR TAPE SERVICE
; RETURNS +1: ALWAYS

SMTMSG:	SAVEQ
	MOVEI Q1,RBUF+1		;GET ADDRESS OF .VMCOD WORD
	SKIPL T1,.VSMTN(Q1)	;GET MT# AND CHECK IF LESS THAN 0
	CAML T1,MTN		; OR TOO BIG
	CALL STOP		;ILLEGAL MT# FROM MONITOR
	IMULI T1,MTSZ		;EXPAND TO OFFSET
	MOVEI MT,MT0(T1)	;LOAD MT WITH ADDR OF MT STATUS BLOCK
	MOVE T1,.VMCOD(Q1)	;DISPATCH BY MESSAGE SUBCODE
	CAIN T1,.VMVSM
	JRST SMTVS		;VOLUME-SWITCH
	CALL STOP		;CODE NOT RECOGNIZED

; PROCESS VOLUME-SWITCH

SMTVS:	LOAD RSB,MTRSB		;GET REQUEST STATUS BUFFER ADDRESS
	CAIN RSB,MTNAV		;DOES USER OWN MT AND NO RSB?
	JRST [	MOVEI T1,.MTNVV	;YES
		MOVE T2,MT	;COMPUTE MT #
		SUBI T2,MT0
		IDIVI T2,MTSZ
		MOVEI T3,[EXP 3,MREQX8,0] ;GET ARGUMENT BLOCK
		MTU%		;MOUNTR CRASHED, SO YOU CAN'T VOLSWITCH
		RET]
	SKIPN RSB		;DO I OWN THE MT?
	CALL STOP		;YES, WHAT'S GOING ON HERE?
	LOAD T2,VS%COD,.VSFLG(Q1) ;TYPE OF SWITCH
	SKIPLE T2		;VALIDATE TYPE
	CAILE T2,4
	CALL STOP		;UNKNOWN TYPE
	LOAD T1,RSBCV		;GET CURRENT VOLID INDEX
	XCT [	MOVE T1,.VSCNT(Q1)	;1 - MOUNT ABSOLUTE VOLUME #
		MOVEI T1,1		;2 - MOUNT FIRST VOLUME
		CALL VQCNT		;3 - MOUNT LAST VOLUME
		ADD T1,.VSCNT(Q1)]-1(T2) ;4- MOUNT RELATIVE VOLUME
	LOAD T2,VS%WRT,.VSFLG(Q1) ;GET READ/WRITE FLAG
	LOAD T3,RSBLT		;GET LABEL TYPE
	CAIN T3,.LTUNL		;UNLABELED?
	SETZ T2,		;YES, DON'T REWRITE VOLUME LABELS
	STOR T2,R%WVL,RSBIFL(RSB) ;SET OR RESET FLAG IN RSB
	CALLRET VOLSW		;PERFORM VOLUME-SWITCH
; PIDINI - GET AND INITIALIZE PID FOR COMMUNICATION WITH THE WORLD
; RETURNS +1: ALWAYS

PIDINI:	SAVEQ

; SET JOB PID QUOTA TO A LARGE VALUE

	MOVEI T1,.MUSPQ		;FUNCTION = SET JOB PID QUOTA
	SETO T2,		;THIS JOB
	MOVEI T3,777		;NEW QUOTA
	CALL XMUTIL
	 JFCL

; TRY TO USE THE PID IN THE SYSTEM PID TABLE (IF IT EXISTS)
; IF THIS IS NOT POSSIBLE, CREATE A NEW PID AND USE IT
; Q1/ 0 IF I CREATED THE PID, 1 IF THE PID IS RECYCLED

	SETZ Q1,		;Q1/0 MEANS I CREATED THE PID
	MOVEI T1,.SPMDA		;OFFSET INTO TABLE FOR MDA PID
	CALL GSYSPD		;DOES MDA PID EXIST?
	 JRST PIN1		;NO
	MOVEM T1,MYPID		;YES, SAVE IT
	AOJA Q1,PIN2		;TRY TO RECYCLE IT

PIN1:	MOVEI T1,.MUCRE		;FUNCTION = CREATE PID
	MOVE T2,[IP%JWP+.FHSLF]	;JOB-WIDE
	CALL XMUTIL		;CREATE PID
	 CALL STOP		;CAN'T WORK WITHOUT A PID
	MOVEM T3,MYPID		;STORE MY PID
PIN2:	MOVEI T1,.MUPIC		;FUNCTION = PUT PID ON INTERRUPT CHANNEL
	MOVE T2,MYPID		;PID
	MOVEI T3,MRCVCN		;CHANNEL #
	CALL XMUTIL		;CAN PID BE PUT ON INT CHANNEL?
	 JRST [	SOJE Q1,PIN3	;NO, REPORT ERROR IF NOT MY PID
		CALL STOP]	;CAN'T PUT MY OWN PID ON INT CHANNEL

	MOVEI T1,.MUSSQ		;FUNCTION = SET SEND AND RECEIVE QUOTAS
	MOVE T2,MYPID		;PID
	MOVEI T3,777100		;SEND = 777, RECEIVE = 100
	CALL XMUTIL		;SET SEND/RECEIVE QUOTAS
	 JFCL
	SKIPE Q1		;RECYCLING OLD MDA PID?
	CALL MRCVIH		;YES, DISCARD ANY CURRENT MESSAGES

; IDENTIFY MYSELF TO THE WORLD

	SKIPE TSTF		;TESTING?
	JRST [	MOVE T2,[[EXP 0,0,0,<20,,TBUF+4>,.IPCII,0],,TBUF]
		BLT T2,TBUF+5		;MOVE PDB AND PART OF MESSAGE TO BUF
		MOVE T1,MYPID
		MOVEM T1,TBUF+.IPCFS	;SET SENDER'S PID
		GJINF			;GET USER# IN T1
		MOVE T2,T1		;COPY INTO T2
		MOVE T1,[POINT 7,TBUF+6] ;GET POINTER
		MOVEI T3,"["
		IDPB T3,T1
		DIRST			;ADD USER NAME
		 JSHLT
		MOVEI T2,"]"
		IDPB T2,T1
		HRROI T2,[ASCIZ/MOUNTR/] ;GET POINTER TO STRING
		SETZ T3,		;STOP ON NULL
		SOUT			;ADD PID NAME
		MOVEI T1,4
		MOVEI T2,TBUF
		MSEND
		 CALL STOP
		TMSG <% MOUNTR Becoming >
		HRROI T1,TBUF+6		;INFORM USER WE HAVE GOT PID
		PSOUT
		TMSG <
>
		JRST PIN4]
	MOVEI T1,.MUSSP		;FUNCTION = SET VALUE IN SYS PID TABLE
	MOVEI T2,.SPMDA		;OFFSET INTO TABLE
	MOVE T3,MYPID		;PID
	CALL XMUTIL		;SET MY PID AS SYSTEM MDA PID
	 CALL STOP
PIN4:

; OBTAIN AND REMEMBER MAXIMUM LENGTH OF NON-PAGE-MODE IPCF PACKETS

	MOVEI T1,.MUMPS		;FUNCTION = RETURN MAX NON-PAGE PACKET
	CALL XMUTIL
	 CALL STOP
	MOVEM T2,SHORT		;SAVE IT
	RET

; ERROR ENCOUNTERED WHILE ASSIGNING EXISTING MDA PID TO PSI CHANNEL
; THIS IMPLIES THAT ANOTHER MOUNTR IS RUNNING, SO DON'T INTERFERE

PIN3:	TMSG <?MDA PID is already defined>
	MOVEI T1,.MUFOJ
	MOVE T2,MYPID		;GET THE PID
	CALL XMUTIL		;GET JOB# OF PID'S OWNER
	 HALTF
	TMSG < by job >
	MOVEI T1,.PRIOU
	MOVE T2,T3		;COPY JOB#
	MOVEI T3,12		;BASE 10
	NOUT			;DISPLAY JOB#
	 JFCL
	HALTF
; PWATCH - TELL INFO TO WATCH THE PID IN RSBPID
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

PWATCH:	MOVEI T1,.IPCIK
	MOVEM T1,TBUF+.IPCI0	;STORE INFO FUNCTION CODE
	MOVE T1,RSBPID(RSB)
	MOVEM T1,TBUF+.IPCI2	;STORE PID TO BE WATCHED
	SETZ T1,		;SENDING TO INFO
	MOVEI T2,3		;3 WORDS
	CALLRET TRANM
; TRANG - TRANSMIT GALAXY IPCF MESSAGE TO ASSOCIATED PROCESS
; TRANU - TRANSMIT GALAXY IPCF MESSAGE TO USER PROCESS
; TRANM - TRANSMIT IPCF MESSAGE TO SPECIFIED PID
;  T1/ ASSOCIATED-PROCESS INDEX (TRANG) OR PID (TRANM, TRANU)
;  T2/ MESSAGE LENGTH IN WORDS (TRANM ONLY)
;  TBUF/ MESSAGE TO BE TRANSMITTED
; RETURNS +1: ALWAYS

TRANG:	MOVE T1,APPID(T1)	;GET PID OF ASSOCIATED PROCESS
TRANU:	LOAD T2,MS.CNT,TBUF+.MSTYP ;GET SIZE FROM GALAXY HEADER
	JUMPE T1,TRAN1		;IF RECEIVER PID IS 0, DON'T BOTHER
TRANM:	SAVEQ
	MOVEI Q1,1		;SET UP RETRY COUNTER

; BUILD PDB AND ATTEMPT TO TRANSMIT THE MESSAGE

	SETZM TRPDB+.IPCFL	;CLEAR PDB FLAGS WORD
	MOVE T4,MYPID
	MOVEM T4,TRPDB+.IPCFS	;STORE SENDER'S PID IN PDB
	MOVEM T1,TRPDB+.IPCFR	;STORE RECEIVER'S PID IN PDB
	CAMG T2,SHORT		;CAN I SEND A SHORT MESSAGE?
	JRST [	MOVSM T2,TRPDB+.IPCFP ;YES, SET SIZE IN PDB
		MOVEI T2,TBUF
		HRRM T2,TRPDB+.IPCFP ;INSTALL MSG ADDRESS IN PDB
		JRST TRAN2]	;SKIP PAGE-MODE STUFF
	MOVX T2,IP%CFV
	IORM T2,TRPDB+.IPCFL	;SET PAGE-MODE IN PDB
	MOVE T2,[1000,,TBUF_-9]
	MOVEM T2,TRPDB+.IPCFP	;SET SIZE,,PAGE#

TRAN2:	MOVEI T1,4		;PDB LENGTH
	MOVEI T2,TRPDB		;PDB ADDRESS
	MSEND			;SEND THE MESSAGE
	 JRST TRAN3		;FAILED
TRAN1:	SETZM TBUF		;CLEAR 1ST WORD OF TBUF
	MOVE T1,[TBUF,,TBUF+1]	;BLT SOURCE AND DESTINATION
	BLT T1,TBUF+777		;CLEAR TBUF FOR NEXT CALLER
	RET

; IPCF TRANSMIT FAILED, FIND OUT WHY

TRAN3:	CAIN T1,IPCFX4
	JRST TRAN1		;RECEIVER'S PID IS INVALID
	CAIN T1,IPCFX5
	JRST TRAN1		;THE JERK DISABLED HIS PID
	CAIN T1,IPCFX6
	JRST TRAN4		;SEND QUOTA EXCEEDED
	CAIN T1,IPCFX7
	JRST TRAN5		;RECEIVE QUOTA EXCEEDED
	CAIN T1,IPCFX8
	JRST TRAN4		;IPCF FREE SPACE EXHAUSTED
	CAIN T1,MONX06
	JRST TRAN4		;NO SWAPPABLE FREE SPACE
	CALL STOP		;I CAN'T HANDLE THIS ERROR

TRAN5:	SOJL Q1,TRAN1		;GIVE UP IF RETRY COUNT EXHAUSTED
TRAN4:	MOVEI T1,^D1000		;RETRYABLE FAILURE
	DISMS			;DELAY
	JRST TRAN2		;TRY IT AGAIN
SUBTTL LABELED TAPE INITIALIZATION

; LTINIT - CHECK IF LABELED TAPE MUST BE INITIALIZED, AND IF SO,
;	   WRITE VOLUME LABELS AND A DUMMY FILE ON THE TAPE
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ERROR, TAPE DISMOUNTED OR REQUEST ABORTED
;	  +2: SUCCESS, TAPE IS PROPERLY PREPARED

LTINIT:	MOVX T1,R%WVL
	TDNN T1,RSBIFL(RSB)	;SKIP IF LABELS MUST BE WRITTEN
	RETSKP			;YES, SHOULDN'T WRITE LABELS!
	CALL OWCHK		;OVERWRITE PERMITTED?
	 RET			;NO, REQUEST ABORTED
	LOAD T1,RSBDEN		;GET DESIRED DENSITY
	STOR T1,MTADEN		;OPEN MTA AT THAT DENSITY
	LOAD T1,RSBLT		;GET LABEL TYPE
	STOR T1,MTALT		;SET NEW LABEL TYPE OF TAPE
	CALL MTAOPO		;OPEN MTA FOR OUTPUT
	 JRST [	CALLRET UNLOAD]	;WRITE PROTECTED OR OFFLINE ???
	MOVEI T1,.MOREW
	MOVEI T2,1
	CALL XMTOPR		;REWIND TAPE (SHOULDN'T TAKE LONG)
	 JRST LTINI1
	LOAD T1,RSBLT
	CAIN T1,.LTUNL		;UNLABELED TAPE?
	JRST [	SETZM LBUF1	;YES
		MOVE T1,[LBUF1,,LBUF1+1]
		BLT T1,LBUF1+^D19 ;ZERO THE BUFFER
		MOVEI T1,LBUF1	;GET BUFFER ADDRESS
		CALL WRTLBL	;WRITE A RECORD OF ZEROS
		 JRST LTINI2	;ERROR
		JRST LTINI0]	;SUCCESSFUL, GO WRAP UP
	CALL BLDV1		;BUILD VOL1 LABEL
	MOVEI T1,MTAV1(MTA)	;GET ADDRESS OF VOL1
	CALL WRTLBL		;WRITE VOL1
	 JRST LTINI2		;ERROR
	SETZM MTAV2(MTA)	;ZAP VOL2 BUFFER
	LOAD T1,RSBLT		;GET LABEL TYPE
	CAIN T1,.LTT20		;IS THIS A TOPS-20 VOLUME?
	JRST [	CALL BLDV2	;YES, BUILD VOL2 LABEL
		MOVEI T1,MTAV2(MTA) ;GET ADDRESS OF VOL2
		CALL WRTLBL	;WRITE VOL2
		 JRST LTINI2	;ERROR
		JRST .+1]

; --- USER VOLUME LABELS WOULD BE WRITTEN HERE ---

	CALL BLDH1		;BUILD HDR1 FOR DUMMY FILE
	MOVEI T1,LBUF1		;GET ADDRESS OF HDR1
	CALL WRTLBL		;WRITE HDR1
	 JRST LTINI2		;ERROR
	MOVEI T1,.MOEOF
	MOVEI T2,2		;REPEAT COUNT
	CALL XMTOPR		;DOUBLE TAPE MARK FRAMING EMPTY FILE
	 JRST LTINI1
	CALL BLDEF1		;BUILD EOF1
	MOVEI T1,LBUF1		;GET ADDRESS OF EOF1
	CALL WRTLBL		;WRITE EOF1
	 JRST LTINI2
LTINI0:	MOVEI T1,.MOEOF
	MOVEI T2,2		;REPEAT COUNT
	CALL XMTOPR		;WRITE DOUBLE TAPE MARK
	 JRST LTINI1
	CALL REW		;REWIND TAPE
	 JRST LTINI2		;OFFLINE ERROR
	CALL MTACLS		;CLOSE TAPE
	RETSKP			;I DID IT!!

; DEVICE ERROR OR TIMEOUT OCCURRED

LTINI1:	CALL XMTREP		;TELL OPERATOR ABOUT ERROR OR TIMEOUT
LTINI2:	CALL UNLOAD		;UNLOAD THE TAPE FROM THE DRIVE
	CALL MTACLS		;CLOSE THE JFN
	CALLRET WOLINF		;TELL OPERATOR LABEL INIT FAILED


; WRTLBL - WRITE A LABEL TO TAPE
;  T1/ ADDRESS OF INDUSTRY-COMPATIBLE FORMAT LABEL
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: I/O ERROR OR DRIVE TIMED OUT
;	  +2: LABEL WRITTEN SUCCESSFULLY

WRTLBL:	STKVAR <<WCLIST,2>>
	SUBI T1,1		;GET BUFFER ADDRESS MINUS 1
	HRLI T1,-LBLSIZ/4	;GET MINUS # OF WORDS TO WRITE
	MOVEM T1,WCLIST		;STORE IOWD
	SETZM 1+WCLIST		;FOLLOW IOWD WITH ZERO WORD
	LOAD T1,MTAJFN		;GET JFN
	MOVEI T2,WCLIST		;GET COMMAND LIST ADDRESS
	IOXCT DUMPO,WRTLB1,WRTLB2 ;DO THE I/O
	RETSKP			;SUCCESS

WRTLB1:	CALL CLRTAP		;CLEAR ERRORS, GET ERROR CODE IN T1
	 JRST WRTLB2		;TIMED OUT
	CAIN T1,IOX5		;DEVICE OR DATA ERROR?
	RET			;YES, TELL CALLER
	CALL STOP		;I CAN'T HANDLE THIS

WRTLB2:	CALLRET WOTIMO		;TELL OPERATOR ABOUT TIMEOUT AND TAKE +1
; BLDV1 - BUILD VOL1 LABEL
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS, VOL1 LABEL IN MTAV1 IN MTA STATUS BLOCK

BLDV1:	DMOVE T1,[ASCII/VOL1      /]
	DMOVEM T1,LBUF2		;SET FIRST 2 WORDS OF VOL1
	MOVE T1,[LBUF2+1,,LBUF2+2]
	BLT T1,LBUF2+LB7WDS-1	;SET THE REST TO BLANKS
	MOVE T1,MTAVOL(MTA)	;GET VOLID
	MOVE T2,[ILPTR(V1VID)]	;GET DESTINATION POINTER
	CALL SIXASC		;PUT VOLID IN LABEL
	LOAD T1,RSBLT		;GET LABEL TYPE
	CAIN T1,.LTEBC		;EBCDIC?
	JRST BLDV11		;YES, SKIP ANSI/TOPS20 STUFF
	CAIN T1,.LTT20		;IS THIS A TOPS-20 VOLUME?
	JRST [	MOVEI T1,"1"	;YES
		DPB T1,[LPTR(V1ACS)] ;SET ACCESSIBILITY FIELD
		HRROI T1,T20SCD
		MOVE T2,[ILPTR(V1SCD)]
		CALL MOVSTR	;PUT TOPS-20 SYSTEM CODE IN VOL1
		JRST .+1]
	HRROI T1,[ASCIZ/D%K/]
	MOVE T2,[ILPTR(V1OWN)]
	CALL MOVSTR		;PUT MACHINE CODE IN OWNER-ID FIELD
	MOVEI T1,DECV
	DPB T1,[LPTR(V1DECV)]	;STORE DEC STANDARD VERSION
	MOVEI T1,ANSV
	DPB T1,[LPTR(V1ANSV)]	;STORE ANSI STANDARD VERSION
	SKIPA T2,[ILPTR(V1INAM)] ;GET POINTER TO ANSI/TOPS20 OWNER NAME
BLDV11:	MOVE T2,[ILPTR(V1INME)]	;GET POINTER TO EBCDIC OWNER NAME
	HRROI T1,TAPNAM		;POINT TO INSTALLATION NAME
	CALL MOVSTR		;COPY INSTALLATION NAME INTO LABEL
	MOVEI T1,MTAV1(MTA)	;GET DESTINATION ADDRESS
	CALLRET LBLOCV		;CONVERT TO OUTPUT FORMAT AND RETURN
; BLDV2 - BUILD VOL2 LABEL
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS, VOL2 LABEL IN MTAV2 IN MTA STATUS BLOCK

BLDV2:	DMOVE T1,[ASCII/VOL2      /]
	DMOVEM T1,LBUF2		;SET FIRST 2 WORDS OF VOL2
	MOVE T1,[LBUF2+1,,LBUF2+2]
	BLT T1,LBUF2+LB7WDS-1	;SET THE REST TO BLANKS
	MOVE T1,[ILPTR(V2PRO)]	;GET POINTER TO ACCESS CODE FIELD
	LOAD T2,RSBVPR		;GET PROTECTION CODE
	TRO T2,770000		;FORCE COMPLETE OWNER ACCESS
	TRZ T2,007700		;CLEAR WORLD ACCESS (NOT DEFINED YET)
	MOVE T3,[6,,10]		;FIELD WIDTH,,RADIX
	CALL FNOUT		;PUT NUMERIC FIELD IN LABEL
	HRROI T1,[ASCIZ/000000000000/] ;DUMMY PPN
	MOVE T2,[ILPTR(V2PPN)]
	CALL MOVSTR		;INSTALL PPN
	HRROI T1,MTAV2(MTA)	;USE MTAV2 TEMPORARILY
	MOVE T2,RSBUNO(RSB)	;USER'S USER #
	DIRST			;TRANSLATE USER # TO STRING
	 SETZM MTAV2(MTA)
	HRROI T1,MTAV2(MTA)	;(ALL THIS FUDGING IS BECAUSE DIRST
	MOVE T2,[ILPTR(V2OWN)]	; PUTS AN UNWANTED NULL AT THE END)
	CALL MOVSTR		;TRANSFER OWNER'S NAME TO LABEL
	MOVEI T1,MTAV2(MTA)	;GET DESTINATION ADDRESS
	CALLRET LBLOCV		;CONVERT TO OUTPUT FORMAT AND RETURN
; BLDH1 - BUILD DUMMY HDR1 LABEL
; BLDEF1 - BUILD DUMMY EOF1 LABEL
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS, LABEL IN LBUF1

BLDH1:	SKIPA T1,[ASCII/HDR1D/]
BLDEF1:	MOVE T1,[ASCII/EOF1D/]
	MOVEM T1,LBUF2		;SET FIRST WORD OF LABEL
	MOVE T1,[SKEL1,,LBUF2+1]
	BLT T1,LBUF2+LB7WDS-1	;SUPPLY REMAINDER OF SKELETON
	MOVE T1,MTAVOL(MTA)	;GET VOLID
	MOVE T2,[ILPTR(H1SET)]	;GET DESTINATION POINTER
	CALL SIXASC		;PUT VOLID IN FILE SET NAME FIELD
	SETO T2,		;SPECIFY CURRENT DATE/TIME
	MOVX T4,IC%JUD		;WANT JULIAN FORM
	ODCNV			;GET T2/ YEAR,,JULIANDAY
	HLRZ T1,T2		;GET YEAR
	SUBI T1,^D1900		;DROP CENTURY PART
	IMULI T1,^D1000		;DECIMAL SHIFT
	HRRZS T2		;ISOLATE DAY IN T2
	ADD T2,T1		;GET T2/ YYDDD (DECIMAL)
	MOVE T1,[ILPTR(H1CRE+1)] ;GET POINTER TO LABEL FIELD
	MOVE T3,[5,,12]		;5 CHARS WIDE, BASE 10
	CALL FNOUT		;EDIT CREATION DATE INTO LABEL
	MOVEI T1,LBUF1		;GET DESTINATION ADDRESS
	CALLRET LBLOCV		;CONVERT TO OUTPUT FORMAT AND RETURN

SKEL1:	ASCII     /UMMY-FILE-0000        0001000100010/ ;CP  6-40
	ASCII/0       00000 000000DECSYSTEM20         / ;CP 41-80


; LBLOCV - CONVERT 7-BIT ASCII LABEL IN LBUF2 TO 8-BIT ASCII OR EBCDIC
;  T1/ ADDRESS OF DESTINATION LABEL
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

LBLOCV:	SAVEQ
	HRLI T1,(POINT 8,0)	;MAKE POINTER TO DESTINATION
	MOVE T2,[POINT 7,LBUF2]	;GET POINTER TO SOURCE
	MOVEI T3,LBLSIZ		;GET # OF BYTES IN LABEL
	LOAD T4,RSBLT		;GET LABEL TYPE
LBLOC1:	ILDB Q1,T2		;GET SOURCE BYTE
	CAIN T4,.LTEBC		;EBCDIC LABEL?
	JRST [	ADJBP Q1,[POINT 8,AETT,7] ;YES, GET POINTER TO TABLE
		LDB Q1,Q1	;TRANSLATE ASCII TO EBCDIC
		JRST .+1]
	IDPB Q1,T1		;STORE BYTE IN DESTINATION
	SOJG T3,LBLOC1
	RET
; OWCHK - CHECK IF USER MAY OVERWRITE TAPE VOLUME
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: OVERWRITE NOT PERMITTED, REQUEST ABORTED
;	  +2: OVERWRITE PERMITTED

OWCHK:	JN R%PRIV,RSBIFL(RSB),RSKP ;PRIVILEGED USERS CAN DO ANYTHING
	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	JXN T1,MA%UXV,[ABTRET (MREQ28)] ;ERROR IF FIRST FILE NOT EXPIRED
	JXN T1,MA%SCR,RSKP	;OK IF IT'S A SCRATCH TAPE
	LOAD T1,MTALT		;GET LABEL TYPE
	LOAD T2,MA%OPF,MTAFLG(MTA) ;GET OVERWRITE-PROTECT FLAG
	JRST @OWCDV(T1)		;DISPATCH ACCORDING TO LABEL TYPE

OWCDV:	IFIW!RSKP		;LABEL TYPE NOT KNOWN YET
	IFIW!RSKP		;UNLABELED
	IFIW!OWCANS		;ANSI
	IFIW!OWCPV		;EBCDIC (WRITE ACCESS NOT SUPPORTED)
	IFIW!OWCT20		;TOPS-20
MAXLT

OWCANS:	JUMPE T2,RSKP		;OK IF FLAG IS RESET
OWCPV:	ABTRET (MREQ29)		;OVERWRITE ACCESS VIOLATION, ABORT REQ

OWCT20:	JUMPE T2,RSKP		;OK IF FLAG RESET
	STKVAR <<OWNER,10>>
	MOVEI T1,OWNER		;PROVIDE WORK AREA FOR GETVU
	CALL GETVU		;GET TAPE-OWNER'S USER # IN T2
	CAME T2,RSBUNO(RSB)	;TAPE USER # MATCH REQUESTOR USER # ?
	JRST OWCPV		;NO, PROTECTION VIOLATION
	RETSKP			;YES, YOU OWN IT, SO YOU CAN OVERWRITE
SUBTTL OPERATOR INTERFACE

; BADOM, BADQM - TYPE A MESSAGE ON CTY INDICATING THAT I RECEIVED A
;		 BAD IPCF MESSAGE FROM ORION OR QUASAR
; RETURNS +1: ALWAYS

BADOM:	SKIPA T1,[[ASCIZ/ORION/]]
BADQM:	MOVEI T1,[ASCIZ/QUASAR/]
	MOVE T2,[RBUF,,BADMSG]
	BLT T2,BADMSG+777	;MAKE A COPY JUST FOR THE RECORD
	TMCT <%IBad IPCF message received from %1A>
	LOAD T1,MS.TYP,RBUF+.MSTYP ;GET MESSAGE TYPE
	CAIN T1,MT.TXT		;IS THIS
	SKIPE RBUF+.OARGC	;A NULL TEXT MESSAGE?
	SKIPA			;NO
	RET			;YES, RETURN
	CAIN T1,MT.TXT		;TEXT MESSAGE?
	CALL [	MOVEI T1,RBUF+.OHDRS+ARG.DA ;YES, POINT TO TEXT
		TMCTR <%_TEXT MESSAGE: %1A>] ;DISPLAY IT
	MOVEI T3,[ASCIZ/MOUNTR System Task Error/]
	CALLRET BTWTO		;OUT TO CTY AND RETURN
; TO CLEAR SOME OF THE CONFUSION HERE, AN "ACK" IS USED WHEN SENDING
; TEXT TO A PARTICULAR OPR (E.G. WHEN TELLING THE OPERATOR THAT
; HE MADE A BAD KEYIN), WHEREAS "WTO" AND "WTOR" MESSAGES ARE SEEN
; BY ALL USERS RUNNING OPR THE TIME THE MESSAGE IS RECEIVED BY ORION.
; ALL OF THE BTxxx ROUTINES RETURN +1 ALWAYS

; BTACK - BUILD AND TRANSMIT ACK MESSAGE WITHOUT TEXT
;  RBUF+.MSCOD/ ID OF OPR WHO WILL RECEIVE ACK
;  T3/ ADDRESS OF ASCIZ MESSAGE TYPE

; BTACKT - BUILD AND TRANSMIT ACK MESSAGE WITH TEXT
;  TMCMSG/ ASCIZ MESSAGE TO BE TRANSMITTED
;  T3/ ADDRESS OF ASCIZ MESSAGE TYPE

; BTWTO - BUILD AND TRANSMIT WTO MESSAGE
;  TMCMSG/ ASCIZ MESSAGE TO BE TRANSMITTED
;  T3/ ADDRESS OF ASCIZ MESSAGE TYPE

; BTWTOR - BUILD AND TRANSMIT WTOR MESSAGE
;  TMCMSG/ ASCIZ MESSAGE TO BE TRANSMITTED
;  T1/ 0 ,, ADDR OF ROUTINE TO BE SCHEDULED WHEN RESPONSE IS RECEIVED
;  T2/ ADDRESS OF WTB
;  T3/ ADDRESS OF ASCIZ MESSAGE TYPE

BTACK:	SKIPA T4,[1B0+.OMACK]	;ACK MESSAGE, NO TEXT BLOCK
BTACKT:	MOVEI T4,.OMACK		;ACK MESSAGE WITH TEXT BLOCK
	JRST BT1		;ENTER COMMON CODE
BTWTON:	MOVE T4,[1B0+.OMWTO]	;WTO MESSAGE WITHOUT TEXT BLOCK
	JRST BT1
BTWTOR:	SKIPA T4,[.OMWTR]	;WTOR MESSAGE
BTWTO:	MOVEI T4,.OMWTO		;WTO MESSAGE
BT1:	STAKT			;STACK T1-T4
	SETZ T1,
	EXCH T1,BTFLGS		;GET CURRENT FLAGS AND CLEAR WORD
	TXO T1,WT.SJI		;ALWAYS SUPPRESS JOB INFORMATION
	MOVEM T1,TBUF+.OFLAG	;SET FLAGS WORD OF MESSAGE TO ORION

; CONSTRUCT BUILDING BLOCKS IN IPCF MESSAGE TO ORION

	CALL PBINIT		;SET UP TO CREATE BUILDING BLOCKS
	MOVEI T1,[2,,.WTOCD
		  .OTMNT]
	CALL PBBLK		;INSERT MESSAGE CLASSIFICATION BLOCK
	MOVEI T1,TMCMSG		;ADDR OF FORMATTED TEXT
	MOVEI T2,.WTTXT		;TYPE CODE
	SKIPL CT4		;TEXT PRESENT?
	CALL PBTXT		;YES, INSTALL IT
	HRRZ T1,CT3		;ADDR OF ASCIZ MESSAGE TYPE
	MOVEI T2,.WTTYP		;TYPE CODE
	CALL PBTXT		;INSTALL MESSAGE TYPE TEXT

; BUILD GALAXY HEADER AND SHIP THE MESSAGE OFF TO ORION

	HRRZ T1,CT4		;GET MESSAGE TYPE
	CAIE T1,.OMACK		;ACK MESSAGE?
	AOSA T3,UNIQUE		;NO, GET A UNIQUE NUMBER
	MOVE T3,RBUF+.MSCOD	;YES, GET OPR ID
	MOVE T2,PBBPT
	SUBI T2,TBUF		;COMPUTE SIZE OF IPCF MESSAGE
	HRL T1,T2		;GET LENGTH,,MSGTYPE
	SETZ T2,		;NO FLAGS
	CALL GALHDR		;BUILD GALAXY MESSAGE HEADER IN TBUF
	MOVEI T1,.APORN		;GOING TO ORION
	CALL TRANG		;QUEUE IT UP FOR TRANSMISSION
	HRRZ T1,CT4		;GET FUNCTION CODE
	CAIE T1,.OMWTR		;WHAT FUNCTION?
	RET			;NOT WTOR - ALL DONE

; WTOR - MAKE ENTRY IN RESPONSE-EXPECTED QUEUE

	MOVE T1,CT2		;GET WTB ADDRESS
	SKIPE WTBCOD(T1)	;MESSAGE OUTSTANDING?
	CALL STOP		;YES, PROGRAM LOGIC ERROR
	MOVE T2,UNIQUE
	MOVEM T2,WTBCOD(T1)	;SAVE ACK CODE
	XMOVEI T2,20
	HRR T2,CT1
	MOVEM T2,WTBENT(T1)	;SAVE CALLER'S GLOBAL ENTRY ADDRESS
	MOVEI T2,WTBLNK(T1)	;GET ADDRESS OF PACKET LINKAGE WORD
	MOVEI T1,WTRQDB		;GET QUEUE DESCRIPTOR BLOCK ADDRESS
	CALLRET QMQT		;PUT PACKET ON EXPECTED-RESPONSE QUEUE

; BTJOB - REQUEST WT.JOB BE SET IN NEXT MESSAGE TO ORION
; BTNFO - REQUEST WT.NFO BE SET IN NEXT MESSAGE TO ORION
; RETURNS +1: ALWAYS

BTJOB:	SKIPA T1,[WT.JOB]
BTNFO:	MOVX T1,WT.NFO
	IORM T1,BTFLGS		;SET APPROPRIATE FLAG
	RET
; CANWTR - CANCEL AN OUTSTANDING WTOR MESSAGE
;  T1/ ACK CODE FROM WTB
; RETURNS +1: ALWAYS

CANWTR:	QSCANI WTRQDB		;SET UP TO SCAN OUTSTANDING WTOR QUEUE
	STKVAR <CANCOD>
	MOVEM T1,CANCOD		;SAVE ACK CODE

; SEARCH WTB QUEUE FOR THE WTB WITH THE SPECIFIED ACK CODE

CANWT1:	CALL QMSCAN		;GET ADDRESS OF NEXT WTB ON CHAIN
	 CALL STOP		;END OF LIST, EXPECTED WTB MISSING
	MOVE T3,WTBCOD(T2)	;GET ACK CODE FROM WTB
	CAME T3,CANCOD		;IS THIS THE ONE THE CALLER WANTS?
	JRST CANWT1		;NO, CONTINUE SEARCH

; FOUND THE WTB FOR THE WTOR REQUEST THAT'S GOING TO BE CANCELED
; BUILD AND TRANSMIT CANCEL-WTOR MESSAGE TO ORION

	CALL QMDQS		;DEQUEUE WTB
	SUBI T2,WTBLNK		;GET WTB ADDRESS IN T2
	SETZM WTBCOD(T2)	;MARK WTB AS INACTIVE
	MOVE T1,[.OARGC+1,,.OMWTR] ;BUILD GALAXY HEADER
	SETZ T2,		; FLAGS
	MOVE T3,CANCOD		; ACK CODE
	CALL GALHDR
	MOVX T1,WT.KIL+WT.SJI	;GET FLAG FOR KILL-WTOR
	MOVEM T1,TBUF+.OFLAG
	SETZM TBUF+.OARGC	;NO ARGUMENTS
	MOVEI T1,.APORN		;MESSAGE GOING TO ORION
	CALLRET TRANG		;SEND CANCEL REQUEST TO ORION


; CMDCFM - PARSE END-OF-LINE
;  CSB/ COMND STATE BLOCK
; RETURNS +1: ERROR, MESSAGE SENT TO OPERATOR
;	  +2: SUCCESS

CMDCFM:	MOVEI T2,[FLDDB. .CMCFM]
	CALL COMNDX		;PARSE IT
	 SKIPA			;ERROR
	RETSKP			;SUCCESS
	JSP T1,RSPERR
	ASCIZ/Superfluous information at end of response/
; COMNDI - SET UP COMND STATE BLOCK FOR PARSING OPERATOR RESPONSE
;  T1/ ADDRESS OF ASCIZ OPERATOR RESPONSE TEXT
; RETURNS +1: ALWAYS, CSB SET UP FOR PARSING

COMNDI:	STAKT			;STACK T1-T4
	TMCT <%I>		;INIT MESSAGE COMPOSER
	MOVE T1,CT1		;GET ADDRESS OF RESPONSE TEXT
	CALL TMCRSP		;COPY TEXT TO THE WIDE OPEN SPACES
	MOVX T3,CM%RAI+CM%XIF	;RAISE INPUT, NO INDIRECT FILE
	MOVEM T3,CSB+.CMFLG
	SETZM CSB+.CMIOJ	;SET BAD JFNS TO PREVENT TTY I/O
	HRROI T3,[0]
	MOVEM T3,CSB+.CMRTY	;CTRL/R BUFFER BYTE POINTER
	HRROI T1,TMCMSG
	MOVEM T1,CSB+.CMBFP	;BEGINNING OF INPUT
	MOVEM T1,CSB+.CMPTR	;POINTER TO NEXT FIELD TO BE PARSED
	MOVEI T2,5000
	MOVEM T2,CSB+.CMCNT	;SIZE OF AREA AFTER .CMPTR
	MOVEM T2,CSB+.CMINC	;# OF UNPARSED CHARS AFTER .CMPTR
	HRROI T3,ATMBFR
	MOVEM T3,CSB+.CMABP	;POINTER TO ATOM BUFFER
	MOVEI T3,ATMSIZ*5
	MOVEM T3,CSB+.CMABC	;SIZE OF ATOM BUFFER (CHARACTERS)
	SETZM CSB+.CMGJB	;GTJFN BUFFER ADDRESS
	RET


; COMNDX - EXECUTE COMND JSYS TO PARSE OPERATOR RESPONSE IN CORE
;  T2/ ADDRESS OF FUNCTION DESCRIPTOR BLOCK CHAIN
;  CSB/ COMND JSYS STATE BLOCK SET UP BY COMNDI SUBROUTINE
; RETURNS +1: PARSE FAILED
;	  +2: PARSE SUCCEEDED, T2/ T2 RETURNED BY COMND JSYS
;			       T3/ ADDRESS OF FDB ACTUALLY USED

COMNDX:	SAVEQ
	MOVE T1,CSB+.CMINC	;GET # OF UNPARSED CHARACTERS
	CAIN T1,5000		;FIRST PARSE FOR THIS COMMAND LINE?
	JRST [	MOVX Q1,FLD(.CMCFM,CM%FNC) ;YES
		HRR Q1,T2	;PREFIX CALLER'S FDB WITH CONFIRM FDB
		MOVEI T2,Q1	;SUBSTITUTE THE ADDRESS OF MY FDB
		JRST .+1]
	MOVEI T1,CSB		;GET ADDRESS OF COMND STATE BLOCK
	COMND			;CALL MONITOR
	 ERJMP R		;JSYS FAILED, MAKE LIKE PARSE ERROR
	HRRZS T3		;GET ACTUAL FDB ADDRESS IN T3
	TXNN T1,CM%NOP		;PARSE ERROR?
	CAIN T3,Q1		; OR NULL COMMAND LINE?
	RET			;YES, RETURN +1, ERROR CODE IN T2
	RETSKP
; COMNDV - PARSE A VOLID WITHIN OPERATOR RESPONSE
;  CSB/ COMND JSYS STATE BLOCK
; RETURNS +1: BAD VOLID, ERROR MESSAGE SENT TO OPERATOR
;	  +2: SUCCESS, T1/ SIXBIT VOLID

COMNDV:	MOVEI T2,[FLDDB.(.CMQST,,,,,[FLDDB.(.CMFLD)])]
	CALL COMNDX		;PARSE QUOTED STRING OR FIELD
	 SETZM ATMBFR		;SYNTACTICAL ERROR
	MOVEI T1,ATMBFR		;GET STRING ADDRESS
	CALL ASCIZL		;GET LENGTH OF VOLID IN T2
	JUMPE T2,[JSP T1,RSPERR	;ERROR IF NULL VOLID
		ASCIZ/Syntactical error in volume-id/]
	CAILE T2,6		;TOO LONG?
	JRST [	JSP T1,RSPERR	;YES
		ASCIZ/Volume identifier longer than 6 characters/]
	MOVE T1,[POINT 7,ATMBFR] ;GET POINTER TO ASCII VOLID
	CALL CVTA6R		;CONVERT VOLID TO SIXBIT
	 JRST [	JSP T1,RSPERR	;ERROR
		ASCIZ/Illegal volume identifier/]
	RETSKP			;LOOKS GOOD, RETURN IT TO CALLER
; INWTOR - PROCESS INCOMING RESPONSE TO OUTSTANDING WTOR MESSAGE
;  RBUF/ IPCF MESSAGE FROM ORION, MESSAGE TYPE = .OMRSP
; RETURNS +1: ALWAYS

INWTOR:	QSCANI WTRQDB		;SET UP TO SCAN OUTSTANDING WTOR QUEUE
	STKVAR <WTBAD>

; SCAN OUTSTANDING WTOR MESSAGE QUEUE FOR THE MESSAGE THAT
; MATCHES UP WITH THE RESPONSE I JUST GOT

INWTO1:	CALL QMSCAN		;GET ADDR OF NEXT PACKET IN QUEUE
	 RET			;RACE - OPERATOR RESPONDED TO MESSAGE
				;JUST BEFORE ORION GOT MY KILL ORDER
	MOVE T3,WTBCOD-WTBLNK(T2) ;GET ACK CODE FROM ENTRY
	CAME T3,RBUF+.MSCOD	;DOES IT MATCH CODE IN IPCF MESSAGE?
	JRST INWTO1		;NO, CONTINUE SCAN

; THE RESPONSE HAS BEEN IDENTIFIED - DEQUEUE THE WTB,
; LOAD AC'S FOR HANDLER, AND SCHEDULE IT

	CALL QMDQS		;DEQUEUE THIS ENTRY, GET ADDR IN T2
	SUBI T2,WTBLNK		;SUBTRACT LINKAGE WORD OFFSET
	MOVEM T2,WTBAD		;SAVE ADDRESS OF WTB
	SETZM WTBCOD(T2)	;MARK WTB AS INACTIVE
	MOVEI T1,.ACKID
	CALL ORNBLF		;LOOK UP OPR-IDENTIFIER BLOCK
	 SETZ T2,		;NOT THERE
	JUMPE T2,[CALLRET BADOM] ;BLOCK NOT THERE OR TOO SHORT
	MOVE T1,(T1)		;GET ID OF RESPONDING OPR
	MOVEM T1,RBUF+.MSCOD	;SET IN CASE I WANT TO CALL BTACK
	MOVEI T1,.CMTXT		;SPECIFY ARG TYPE I WANT
	CALL ORNBLF		;SCAN ARG LIST FOR RESPONSE
	 JRST [	CALLRET BADOM]	;NO RESPONSE BLOCK, BAD MSG FROM ORION
	HRLI T1,(POINT 7)	;CONSTRUCT POINTER TO RESPONSE TEXT
	MOVE T2,WTBAD		;GET WTB ADDRESS IN T2

; ENTER RESPONSE PROCESSOR WITH THE FOLLOWING AC SETUP:
;   T1/ BYTE POINTER TO ASCIZ RESPONSE FROM OPERATOR
;   T2/ ADDRESS OF WTB

	CALLRET @WTBENT(T2)	;CALL BTWTOR CLEANUP CODE
; KC ROUTINES - CHECK FOR VARIOUS TAPE DRIVE CONDITIONS
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: CONDITION NOT SATISFIED, ERROR MESSAGE SENT TO OPERATOR
;	  +2: CONDITION SATISFIED

; CHECK FOR DRIVE AVAILABLE TO USERS

KCAVL:	LOAD T2,MTASTE		;GET STATE
	CAIN T2,S.AV		;AVAILABLE?
	RETSKP			;YES
	MOVEI T1,[ASCIZ/Not Under Operator Control/]
	JUMPE T2,KC1		;JUMP IF DRIVE NOT ASSIGNED
	JSP T1,KC1		;ONLY OTHER CASE IS INITIALIZING
	ASCIZ/In INITIALIZE Mode/

; CHECK IF DRIVE IS LOADED

KCLOAD:	JN MA%LOD,MTAFLG(MTA),RSKP
	JSP T1,KC1
	ASCIZ/Not Loaded/

; CHECK IF DRIVE IS IN USE BY ME OR USER

KCUSE:	SAVEAC <MT,RSB>
	JN MTAJCT,,[TMCT <%I%M Is In Use By MOUNTR, Try Later>
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;SEND REPLY AND RETURN +1
	LOAD MT,MTAMT		;MT ASSOCIATED?
	JUMPE MT,RSKP		;RETURN GOOD IF DRIVE NOT IN USE
	LOAD RSB,MTRSB		;GET RSB ADDRESS
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%I%M Is In Use By Request # %1D> ;A USER HAS IT
	MOVEI T3,TMCMSG
	CALLRET BTACK		;TELL OPERATOR

; KC1 - T1/ ADDRESS OF ASCIZ ERROR MESSAGE

KC1:	TMCT <%ITape Drive %M is %1A>
	MOVEI T3,TMCMSG
	CALLRET BTACK		;SEND ACK BACK TO OPR AND TAKE +1 RET
; KDMT - PROCESS DELETE MOUNT-REQUEST COMMAND FROM OPR
; RETURNS +1: ALWAYS

KDMT:	SAVEQ
	MOVEI T1,.ORREA
	CALL ORNBLF		;LOOKUP REASON BLOCK
	 SETZ T2,		;NOT FOUND
	SKIPE Q1,T2		;REASON GIVEN?
	JRST [	MOVSS T1	;YES, GET BLT SOURCE
		HRRI T1,ATMBFR	;BLT DESTINATION
		BLT T1,ATMBFR-1(T2) ;COPY REASON TO ATMBFR FOR TELUSR
		SETZM ATMBFR(T2) ;TIE IT OFF
		JRST .+1]
	MOVEI T1,.ORREQ
	CALL ORNBLF		;LOOKUP REQUEST # BLOCK
	 JRST KDMT1		;NOT THERE, TRY STRUCTURE FORM

; DELETING SPECIFIC MOUNT REQUEST

	JUMPE T2,KBADM		;REJECT HEADER-ONLY ENTRY
	MOVE T1,(T1)		;GET REQUEST #
	CALL REQRSB		;TRANSLATE REQ# TO RSB ADDR
	 JRST KNXREQ		;REQUEST DOES NOT EXIST
	LOAD T2,RSBSTE		;GET STATE OF REQUEST
	CAIE T2,RST.WM		;WAITING FOR MOUNT?
	CAIN T2,RST.WV		; OR WAITING FOR VOLID LIST KEYIN?
	SKIPA			;IF EITHER, OK TO DELETE
	JRST [	JSP T2,KACKRQ	;CAN'T DELETE THIS REQUEST
		ASCIZ/Is Not Waiting/]
	MOVEI T2,[ASCIZ/Canceled/]
	CALL KACKRQ		;TELL OPERATOR I DELETED IT
	JUMPN Q1,[ABTRET (MREQ15,ABT%OP)] ;ABORT WITH REASON
	ABTRET (MREQ15)		;ABORT WITHOUT REASON

; DELETING ALL MOUNT REQUESTS FOR SPECIFIED STRUCTURE

KDMT1:	MOVEI T1,.STRDV		;SPECIFY BLOCK TYPE
	CALL KGTSTR		;GET STRUCTURE NAME
	 JRST KBADM		;NOT THERE, ERROR
	MOVE Q2,T1		;SAVE SIXBIT STRUCTURE NAME
	QSCANI ARBQDB		;SET UP TO SCAN REQUEST QUEUE
	SETZ Q3,		;SET ABORTED REQUEST COUNT TO ZERO

; SCAN REQUEST QUEUE ABORTING REQUESTS FOR THIS STRUCTURE

KDMT2:	CALL NSTRSB		;GET NEXT RSB
	 JRST KDMT3		;NONE LEFT
	LOAD T1,RSBTYP		;GET TYPE
	CAIE T1,.MNTST		;STRUCTURE MOUNT?
	JRST KDMT2		;NO, SKIP IT
	SKIPN T1,RSBSTN(RSB)	;STRUCTURE NAME SPECIFIED?
	MOVE T1,RSBSTA(RSB)	;NO, USE ALIAS
	CAME Q2,T1		;WANT TO CANCEL THIS REQUEST?
	JRST KDMT2		;NO, SKIP IT
	JUMPN Q1,[ABTREQ (MREQ15,ABT%OP) ;ABORT WITH REASON
		AOJA Q3,KDMT2]	;COUNT IT AND CONTINUE SCAN
	ABTREQ (MREQ15)		;ABORT WITHOUT REASON
	AOJA Q3,KDMT2		;COUNT IT AND CONTINUE SCAN

; TELL THE OPERATOR HOW MANY REQUESTS WERE DELETED

KDMT3:	JUMPE Q3,[TMCT <%INo>
		JRST KDMT3A]
	TMCT <%I%7D>		;DISPLAY # OF REQUESTS
KDMT3A:	TMCT < Mount Request>
	SOJN Q3,[TMCT <s>	;TACK ON S IF NOT 1 REQUEST
		JRST .+1]
	TMCT < Canceled>
	MOVEI T3,TMCMSG		;GET ADDRESS OF MESSAGE
	CALLRET BTACK		;RESPOND TO DELETE COMMAND
; KDIS/KENA - PROCESS ENABLE AND DISABLE COMMANDS FROM OPR
; RETURNS +1: ALWAYS

KDIS:	SKIPA T1,[[LOAD T1,MTASTE
		CAIE T1,S.AV
		RET
		MOVX T1,MA%AVE
		ANDCAM T1,MTAFLG(MTA)
		RET]]		;COROUTINE FOR DISABLE
KENA:	MOVEI T1,[LOAD T1,MTASTE
		CAIE T1,S.AV
		RET
		CALL AVRENA
		CALLRET AVR]	;COROUTINE FOR ENABLE
	JXE F,TALCF,KNALC	;REJECT IF ALLOCATION NOT ENABLED
	STAKT
	MOVEI T1,.AVREC		;CHECK FOR AVR KEYWORD
	CALL ORNBLF		;IS IT THERE?
	 JRST KBADM		;NO
	MOVE T1,CT1		;GET ADDRESS OF COROUTINE
	CALL KTXCT		;DO IT FOR SPECIFIED TAPE DRIVES
	 JRST KBADM		;BAD MESSAGE FROM QUASAR
	RET
; KGBLK - LOOK UP SPECIFIED BLOCK TYPE IN MESSAGE
;  T1/ BLOCK TYPE
;  T2/ UPPER LIMIT OF ARGUMENT (LOWER LIMIT = 0)
;      IF T2/ 0, NO LIMIT CHECKING IS DONE
;  T3/ DEFAULT, APPLIED IF (T2).NE.0 AND VALUE=0
;		OR IF ENTRY NOT PRESENT
; RETURNS +1: HEADER-ONLY ENTRY OR VALUE BEYOND LIMITS
;	  +2: T1/ VALUE (OR DEFAULT IF APPLICABLE)

KGBLK:	STAKT			;SAVE ARGS
	CALL ORNBLF		;LOOKUP ARGUMENT
	 JRST KGBLK1		;NOT THERE, TAKE THE DEFAULT
	JUMPE T2,R		;ERROR IF HEADER-ONLY
	MOVE T1,(T1)		;GET ARGUMENT
	SKIPN CT2		;LIMIT CHECK REQUESTED?
	RETSKP			;NO, JUST PASS IT BACK
	CAMG T1,CT2		;GREATER THAN UPPER LIMIT?
	SKIPGE T1		; OR BELOW 0 ?
	RET			;YES, ERROR
	SKIPN T1		;IS IT 0 ?
KGBLK1:	MOVE T1,CT3		;YES, SUBSTITUTE THE DEFAULT
	RETSKP


; KGTSTR - LOCATE AND EXTRACT STRUCTURE OR ALIAS NAME
;  T1/ ENTRY TYPE CODE (.STRDV OR .STALS)
; RETURNS +1: ENTRY NOT FOUND
;	  +2: SUCCESS, T1/ SIXBIT STRUCTURE NAME  T2,T3/ ASCIZ NAME

KGTSTR:	CALL ORNBLF		;LOOKUP SPECIFIED BLOCK TYPE
	 RET			;NOT FOUND
	SAVET			;SET UP TO RETURN VALUES TO CALLER
	DMOVE T3,(T1)		;GET ASCIZ NAME FROM ENTRY
	CAIG T2,1		;ENTRY 1 WORD LONG?
	SETZ T4,		;YES, ZAP SECOND WORD
	DMOVEM T3,CT2		;RETURN ASCIZ NAME IN T2,T3
	MOVSI T1,(POINT 7)
	HRRI T1,CT2		;CONSTRUCT POINTER TO ASCIZ NAME
	MOVEI T2,CT1		;RETURN SIXBIT EQUIVALENT HERE
	CALL SEVSIX		;CONVERT NAME TO SIXBIT
	RETSKP


; KGTVOL - EXTRACT SIXBIT VOLID FROM .VOLID ENTRY
; RETURNS +1: ERROR, MESSAGE SENT TO OPR
;	  +2: T1/ 0 IF .VOLID ENTRY ABSENT, ELSE SIXBIT VOLID

KGTVOL:	SAVEQ
	MOVEI T1,.VOLID
	CALL ORNBLF		;VOLID SPECIFIED?
	 JRST [	SETZ T1,	;NO, RETURN ZERO
		RETSKP]
	JUMPE T2,KBADV		;MUST HAVE SOMETHING AFTER HEADER
	MOVE Q1,T1		;SAVE ADDRESS OF ASCIZ VOLID
	CALL ASCIZL		;GET # OF CHARACTERS IN VOLID
	SKIPE T2		;NULL VOLID IS AN ERROR
	CAILE T2,6		;LONGER THAN 6 CHARACTERS?
	JRST KBADV		;YES, ERROR
	MOVE T1,Q1		;FETCH ADDRESS OF VOLID
	HRLI T1,(POINT 7)	;MAKE BYTE POINTER
	CALL CVTA6R		;CONVERT TO SIXBIT
	 JRST KBADV		;NOT A LEGAL VOLID
	RETSKP
; KIDN - PROCESS IDENTIFY COMMAND FROM OPR
; RETURNS +1: ALWAYS

KIDN:	SAVEQ
	SAVEAC <MT,MTA,RSB>
	STKVAR <<OWNER,10>>	;LOCAL WORK AREA FOR GETVU ROUTINE
; VALIDATE TAPE DRIVE

	MOVEI T1,.TAPDV
	CALL ORNBLF		;TAPE DRIVE SPECIFIED?
	 JRST KBADM		;NO, BAD MESSAGE FROM QUASAR
	JXE F,TALCF,KNALC	;REJECT IF ALLOCATION IS NOT ENABLED
	CALL STMTA		;CONVERT STRING TO MTA STATUS BLOCK ADDR
	 JRST KBADM		;NOT MTA DEVICE STRING

	MOVEI T1,.ORREQ
	CALL ORNBLF		;LOOKUP REQUEST # BLOCK
	 JRST KIDV		;NOT THERE, MAYBE ANOTHER FORM OF CMD
	JUMPE T2,KBADM		;REJECT HEADER-ONLY ENTRY
	MOVE Q3,(T1)		;GET REQUEST #

; PROCESS COMMAND:  IDENTIFY drive REQUEST-ID n

	MOVE T1,Q3		;GET REQUEST #
	CALL REQRSB		;GET RSB ADDRESS FOR THIS REQUEST
	 JRST KNXREQ		;REQUEST DOES NOT EXIST
	HRROI T2,[ASCIZ/Not Waiting For Tape Mount/]
	LOAD T3,RSBTYP
	CAIE T3,.MNTTP		;TAPE REQUEST?
	JRST KACKRQ		;NO, REJECT IT
	LOAD T3,RSBSTE		;GET STATE
	CAIN T3,RST.WV		;WAITING FOR KEYIN?
	JRST [	JSP T2,KACKRQ	;YES, REJECT WITH APPROPRIATE MESSAGE
		ASCIZ/Waiting For RESPOND Keyin/]
	CAIE T3,RST.WM		;WAITING FOR TAPE MOUNT?
	JRST KACKRQ		;NO
	CALL VQGCV		;DOES USER WANT A SCRATCH TAPE?
	JUMPE T1,KIDR1		;YES, TAKE ALTERNATE PATH
	MOVE Q1,T1		;SPECIFIC VOLID, SAVE IT
	MOVX T2,TM%BYP
	TDNE T2,RSBUFL(RSB)	;BYPASS MODE?
	SETZ T1,		;YES, KEEP KVAC FROM BARFING
	SETZ T2,		;NOT SCRATCH
	CALL KVAC		;OK TO SET NEW VOLID?
	 RET			;NO, ERROR MESSAGE SENT
	MOVEM Q1,MTAIDV(MTA)	;SET ALLEGED VOLID
	EXCH Q1,MTAVOL(MTA)	;SET NEW VOLID, SAVE OLD
	CALL VRA		;TRY TO MATCH REQUEST TO VOLUME NOW
	 SKIPA			;DIDN'T MATCH
	RET			;DID MATCH, ALL DONE
	MOVEM Q1,MTAVOL(MTA)	;RESTORE OLD VOLID
	CALL CHKAB		;REQUEST ABORTED?
	 JRST KIDR0		;YES, CLEAN UP AND LEAVE
	CALL VOLMNT		;STILL THERE, TRY TO MOUNT AGAIN
	JN MTAJCT,,R		;RETURN IF AVR IN PROGRESS
KIDR0:	SETZM MTAIDV(MTA)	;REQ ABORTED OR NOT DOING AVR
	RET

; SAME AS ABOVE, BUT USER IS REQUESTING SCRATCH VOLUME

KIDR1:	SETZ T1,		;NOT SETTING VOLID
	MOVEI T2,1		;SCRATCH
	CALL KVAC		;OK TO SCRATCH THIS VOLUME?
	 RET			;NO, ERROR MESSAGE SENT
	LOAD T1,MTALT
	CAIN T1,.LTT20		;TOPS-20 LABELED TAPE?
	JRST [	JN MA%SCR,MTAFLG(MTA),.+1 ;YES, OK IF ALREADY SCRATCH
		MOVEI T1,OWNER	;SUPPLY WORK AREA ADDRESS TO GETVU
		CALL GETVU	;GET TAPE OWNER'S USER # IN T2
		CAME T2,RSBUNO(RSB) ;OWNER AND REQUESTOR THE SAME?
		JRST KNOSCR	;NO, REJECT KEYIN
		JRST .+1]	;YES, PERMIT IT
	MOVE Q1,MTAFLG(MTA)	;SAVE FLAGS
	SETONE MA%SCR,MTAFLG(MTA) ;SET SCRATCH
	SETZRO MA%OPF,MTAFLG(MTA) ;CLEAR OVERWRITE-PROTECTED
	CALL VRA		;TRY TO MATCH REQUEST TO VOLUME
	 SKIPA			;DIDN'T MATCH
	RET			;DID MATCH, ALL DONE
	MOVX Q2,MA%SCR+MA%OPF	;RESTORE MA%SCR AND MA%OPF IN MTAFLG
	AND Q1,Q2
	ANDCAM Q2,MTAFLG(MTA)
	IORM Q1,MTAFLG(MTA)
	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%I%M Tape Not Compatible With Request %1D>
	MOVEI T3,TMCMSG
	CALLRET BTACK		;SEND IT OFF

; PROCESS FOLLOWING FORMS OF IDENTIFY COMMAND:
;    IDENTIFY drive VOLUME-ID volid
;    IDENTIFY drive SCRATCH-TAPE

KIDV:	CALL KGTVOL		;LOOKUP .VOLID ENTRY
	 RET			;SOME ERROR, OPERATOR NOTIFIED
	MOVE Q1,T1		;SAVE VOLID IN Q1

	MOVEI T1,.SCRTP
	MOVEI Q2,1		;ASSUME SCRATCH SPECIFIED
	CALL ORNBLF		;SCRATCH SPECIFIED?
	 JRST [	SETZ Q2,	;NO, SET NO SCRATCH
		JUMPN Q1,.+1	;ARE .SCRTP AND .VOLID BOTH ABSENT?
		JRST KBADM]	;YES, BAD MESSAGE
	JUMPN Q2,[MOVE T1,MTAFLG(MTA) ;IF SCRATCHING, GET FLAGS
		LOAD T2,MTALT	;AND LABEL TYPE
		TXNN T1,MA%SCR	;ALREADY SCRATCH?
		CAIE T2,.LTT20	;OR NOT TOPS-20 LABEL?
		JRST .+1	;YES TO EITHER, OK TO SCRATCH
		JRST KNOSCR]	;CAN'T SCRATCH TOPS-20 TAPE WITH THE
				;IDENTIFY COMMAND - MUST SET TAPE INIT
	DMOVE T1,Q1		;GET VOLID AND SCRATCH FLAG
	CALL KVAC		;OK TO DO THIS TO THIS DRIVE?
	 RET			;NO, ERROR MESSAGE SENT

; EVERYTHING LOOKS LEGAL, NOW DO WHAT THE OPERATOR WANTS

	SKIPE Q1		;SETTING VOLID?
	MOVEM Q1,MTAVOL(MTA)	;YES, DO IT
	JUMPN Q2,[SETONE MA%SCR,MTAFLG(MTA) ;SETTING SCRATCH FLAG
		SETZRO MA%OPF,MTAFLG(MTA) ;CLEAR OVERWRITE PROTECTION
		JRST .+1]
	CALLRET MATCHV		;TRY TO MATCH VOLUME WITH A REQUEST
; KSHT - PROCESS SHOW STATUS TAPE-DRIVE COMMAND FROM OPR
; ACCEPTS IPCF MESSAGE IN RBUF
; RETURNS +1: ALWAYS

KSHT:	SAVEQ
	JXE F,TALCF,KNALC	;REJECT IF ALLOCATION IS NOT ENABLED
	TMCTN <%IDRIVE  STATE     VOLID   REQ#  JOB#  USER
-----  -----     ------  ----  ----  ---->
	MOVE T1,RBUF+.OFLAG	;GET FLAGS
	TXNE T1,ST.AVA		;/FREE
	TMCTN <%IDRIVE  STATE    AVR  WRITE  VOLID   SCR  LBL TYPE  DENSITY
-----  -----    ---  -----  ------  ---  --------  ------->
	TXNE T1,ST.CHR		;CHARACTERISTICS
	TMCTN <%IDRIVE  TYPE     SUPPORTED DENSITIES
-----  ----     ------------------->
	TMCTO			;INSERT HEADING
	MOVE Q1,TMCPTR		;GET CURRENT TEXT POINTER
	MOVEI T1,KSHSCR		;GET COROUTINE ADDRESS
	CALL KTXCT		;BUILD THE BODY OF THE DISPLAY
	 JRST KBADM		;BAD IPCF MESSAGE
	CAMN Q1,TMCPTR		;ANYTHING DISPLAYED?
	JRST [	JE ST.AVA,RBUF+.OFLAG,.+1 ;NO, FREE-DRIVE DISPLAY?
		MOVEI T3,[ASCIZ/There Are No Free Tape Drives/] ;YES
		CALLRET BTACK]
	MOVEI T3,[ASCIZ/Tape Drive Status/]
	CALL BTNFO		;REQUEST NO FORMATTING
	CALLRET BTACKT		;SEND DISPLAY TO OPERATOR AND SPLIT

; COROUTINE FOR SHOW STATUS

KSHSCR:	SAVEQ
	SAVEAC <MT,RSB>
	MOVE Q3,RBUF+.OFLAG	;GET MESSAGE FLAGS
	JXN Q3,ST.AVA,KSHF	;/FREE
	JXN Q3,ST.CHR,KSHC	;/CHARACTERISTICS
; SHOW STATUS TAPE-DRIVE [/ALL]

	LOAD MT,MTAMT		;GET ADDRESS OF MT STATUS BLOCK
	JE MTASTE,,[CALL GMTADD	;DRIVE UNAVAILABLE, GET DESIGNATOR
		DVCHR		;GET LH(T3)/ OWNER'S JOB#
		TLNN T3,-1	;SHOW IF PHYSICAL DEVICE EXISTS
		CALL CKMPAV	;SHOW IF SET UNAVAILABLE
		 JRST .+1
		RET]		;DON'T SHOW
	TMCT <%_%M%8C>		;DISPLAY DRIVE NAME
	LOAD Q1,MTASTE
	CAIE Q1,S.AV		;AVAILABLE TO USERS?
	JRST [	JUMPE Q1,[TMCTR <Unavailable>] ;NO
		TMCT <Initialize>
		LOAD RSB,MTRSB	;GET RSB ADDRESS
		SKIPN RSBWTB+WTBCOD(RSB) ;WAITING FOR OPER RESPONSE?
		RET		;NO
		TMCTR <, operator response wait>]
	MOVE Q1,MTAFLG(MTA)	;GET MTA FLAGS
	JXE Q1,MA%LOD,[TMCT <Unloaded>
		JRST KSHN1]
	MOVEI T1,[ASCIZ/Loaded/] ;ASSUME JUST LOADED
	SKIPE MT		;RIGHT?
	MOVEI T1,[ASCIZ/In Use/] ;NO, CHANGE TO IN USE
	TMCT <%1A%18C>		;DISPLAY STATE
	SKIPE T1,MTAVOL(MTA)	;DO I KNOW VOLID?
	CALL [	TMCTR <%1S>]	;YES, DISPLAY IT
	JUMPE MT,KSHN1		;THAT'S ALL IF NO USER
	LOAD RSB,MTRSB		;GET REQUEST STATUS BLOCK ADDRESS
	CAIN RSB,MTNAV		;MT OWNED BY PHANTOM USER?
	JRST KSHN1		;YES, THAT'S ALL
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	LOAD T2,RSBJNO		;GET JOB #
	MOVE T3,RSBUNO(RSB)	;GET USER #
	TMCT <%26C%1D%32C%2D%38C%3U> ;SHOW USER INFO
KSHN1:	JXE Q3,ST.ALL,R		;/ALL REQUESTED?
	LOAD T1,MA%AVE,Q1	;YES, GET AVR STATUS
	TMCT <%_%8CAVR: %1Y>	;DISPLAY AVR STATE
	JXE Q1,MA%LOD,R		;EXIT IF NOT LOADED
	LOAD T1,MA%WEN,Q1	;GET WRITE-ENABLED FLAG
	TMCT <, Write: %1Y>	;DISPLAY IT
	LOAD T1,MTALT		;GET LABEL TYPE
	JUMPE T1,R		;NOT IDENTIFIED YET
	MOVE T2,LTTXT(T1)	;GET LABEL-TYPE TEXT
	MOVEI T3,[0]		;ASSUME UNLABELED
	CAIE T1,.LTUNL
	MOVEI T3,[ASCIZ/ labels/]
	TXNE Q1,MA%SCR		;SCRATCH?
	MOVEI T3,[ASCIZ/ scratch tape/]
	TMCT <, %2A%3A>		;SHOW LABEL TYPE, SCRATCH
	CAIN T1,.LTUNL		;UNLABELED?
	RET			;YES
	LOAD T2,MTADEN		;LABELED, SHOW DENSITY
	MOVE T2,DENTAB(T2)
	TMCTR <, %2D BPI>

; SHOW STATUS TAPE-DRIVE /FREE

KSHF:	LOAD T1,MTASTE		;GET STATE
	CAIE T1,S.AV		;AVAILABLE TO USERS?
	RET			;NO, SKIP IT
	JN MTAMT,,R		;DON'T SHOW IF A USER HAS IT
	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	MOVEI T2,[ASCIZ/Unloaded/] ;ASSUME UNLOADED
	TXNE T1,MA%LOD		;LOADED?
	MOVEI T2,[ASCIZ/Loaded/] ;YES
	LOAD T3,MA%AVE,T1	;GET AVR FLAG
	TMCT <%_%M%8C%2A%17C%3Y> ;DISPLAY DRIVE, STATE, AVR
	JXE T1,MA%LOD,R		;END OF LINE IF DRIVE NOT LOADED
	LOAD T2,MA%WEN,T1	;GET WRITE-ENABLED FLAG
	MOVE T3,MTAVOL(MTA)	;GET VOLID
	LOAD T4,MA%SCR,T1	;GET SCRATCH FLAG
	TMCT <%23C%2Y%29C%3S%37C%4Y> ;DISPLAY WRITE, VOLID, SCRATCH
	LOAD T1,MTALT		;GET LABEL TYPE
	JUMPE T1,R		;UNKNOWN
	MOVE T2,LTTXT(T1)	;GET POINTER TO TEXT
	TMCT <%42C%2A>		;DISPLAY LABEL TYPE
	CAIN T1,.LTUNL		;LABELED?
	RET			;NO, DONE
	LOAD T2,MTADEN		;YES, GET DENSITY CODE
	MOVE T2,DENTAB(T2)	;GET DENSITY
	TMCTR <%52C%2D>		;DISPLAY AND RETURN

; SHOW STATUS TAPE-DRIVE /CHARACTERISTICS

KSHC:	JE MTASTE,,R		;DON'T SHOW DRIVE IF I DON'T CONTROL IT
	LOAD T1,MTADRV		;GET DRIVE TYPE CODE
	MOVE T1,DRVTXT(T1)	;GET ADDRESS OF TEXT
	TMCT <%_%M%8C%1A%17C>	;DISPLAY DRIVE, TYPE
	MOVSI T1,-DENMAX-1	;GET AOBJP POINTER
	MOVSI T2,(1B0)		;SET UP INTERROGATION BIT
	MOVEI T3,[0]		;NO ", " BEFORE FIRST DENSITY
KSHC1:	AOBJP T1,R		;GET OUT OF LOOP IF DONE
	LSH T2,-1		;SHIFT BIT TO NEXT POSITION
	TDNN T2,MTASDN(MTA)	;IS THIS DENSITY SUPPORTED?
	JRST KSHC1		;NO, TEST NEXT DENSITY
	MOVE T4,DENTAB(T1)	;GET DENSITY
	TMCT <%3A%4D>		;DISPLAY DENSITY
	MOVEI T3,[ASCIZ/, /]	;SEPARATE SUBSEQUENT DENS WITH A COMMA
	JRST KSHC1
; KSTP - PROCESS SET TAPE-DRIVE COMMAND FROM OPR
; RETURNS +1: ALWAYS

KSTP:	SAVEQ
	SAVEAC <MTA>
	JXE F,TALCF,KNALC	;REJECT IF ALLOCATION IS NOT ENABLED
	MOVEI T1,.TAPDV
	CALL ORNBLF		;TAPE DRIVE SPECIFIED?
	 JRST KBADM		;NO
	CALL STMTA		;CONVERT STRING TO MTA STATUS BLOCK ADDR
	 JRST KBADM		;BAD MTA STRING
	SETZ Q1,		;ASSUME SETTING UNAVAILABLE
	MOVEI T1,.DVUAV
	CALL ORNBLF		;CHECK IF SETTING UNAVAILABLE
	 JRST [	MOVEI T1,.DVAVL	;NO
		CALL ORNBLF	;SETTING AVAILABLE?
		 SKIPA		;NO
		AOJA Q1,KSTPA	;SETTING AVAILABLE
		MOVEI T1,.DVINI
		CALL ORNBLF	;SETTING INITIALIZE MODE?
		 JRST KBADM	;NO, BAD MESSAGE
		CALLRET KVI]	;YES, GO DO IT

; SETTING DRIVE UNAVAILABLE

	MOVEI T1,.ORREA
	CALL ORNBLF		;REASON BLOCK PRESENT?
	 JRST KBADM		;NO
	MOVE Q2,T1		;COPY ADDRESS OF REASON TEXT
	CALL CKMPAV		;IS DRIVE ALREADY SET UNAVAILABLE?
KSTP1:	 JRST [	MOVE T1,[[ASCIZ/Unavailable/]
			 [ASCIZ/Available/]](Q1) ;GET TEXT POINTER
		TMCT <%ITape Drive %M Is Already Set %1A>
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;TELL OPRTR HIS COMMAND HAS NO EFFECT
	LOAD T1,MTASTE
	CAIN T1,S.INIT		;IN INITIALIZE MODE?
	JRST [	CALL KVICU	;YES, CAN I GET OUT OF IT NOW?
		 RET		;NO
		JRST .+1]	;YES, CONTINUE
	MOVEI T1,CS%DDV		;GET CODE FOR DETACH-DEVICE
	MOVE T2,Q2		;GET ADDRESS OF ASCIZ REASON
	CALL SYTSET		;LOG SYSERR ENTRY FOR DRIVE SET UNAVAIL
	CALL DACMTA		;DEACTIVATE THE DRIVE IF POSSIBLE
	SETZ T1,		;GET 0 TO SET UNAVAILABLE
	CALL SMPAV		;UPDATE DEVICE STATUS FILE
	CALL WOTDAV		;TELL ALL OPERATORS WHAT HAPPENED
	RET

; SETTING DRIVE AVAILABLE

KSTPA:	LOAD T1,MTASTE		;GET CURRENT STATE
	CAIN T1,S.INIT		;INITIALIZING VOLUMES?
	JRST [	CALL KVICU	;YES, CLEAR INITIALIZE STUFF
		 RET		;CAN'T DO IT NOW
		CALLRET KVIDAV]	;GET BACK TO AVAILABLE STATE
	MOVEI Q2,1		;REMEMBER INITIAL SMPAV STATE IN Q2
	SKIPE T1		;OK IF DRIVE NOT BEING SCHEDULED
	CALL CKMPAV		;OK IF DRIVE SET UNAVAILABLE
	 TDZA Q2,Q2		;ONE OF THE ABOVE CONDITIONS WAS TRUE
	JRST KSTP1		;NEITHER TRUE, THAT'S AN ERROR
	MOVEI T1,1
	CALL SMPAV		;SET AVAILABLE IN STATUS FILE
	MOVEI T1,S.AV		;GET DESIRED STATE
	CALL ACTMTA		;TRY TO ACTIVATE THE MTA
	 JRST KSTP3		;CAN'T, SO SEND DIAGNOSTIC TO OPR
	CALL TDSC1		;CHECK IF LOADED, DO AVR, ETC.
	JUMPE Q2,[MOVEI T1,CS%ADV ;GET CODE FOR ATTACH-DEVICE
		SETZ T2,	;NO REASON
		CALL SYTSET	;LOG SYSERR ENTRY FOR DRIVE SET AVAIL
		JRST .+1]
	CALLRET WOTDAV		;TELL OPERATORS IT'S BACK

; TAPE DRIVE WAS ASSIGNED TO ANOTHER JOB   T1/ JOB#

KSTP3:	MOVE Q2,T1		;SAVE JOB #
	TMCT <%I%M is >
	SKIPLE Q2		;ASSIGNED TO JOB 0
	CAIL Q2,4000		;OR SOME FUNNY JOB?
	JRST [	TMCT <not accessible by MOUNTR>
		JRST KSTP2]	;YES, SPECIAL MESSAGE
	MOVE T1,Q2		;GET JOB#
	TMCT <assigned to Job %1D>
KSTP2:	MOVEI T3,[ASCIZ/Cannot Set Tape Drive Available/]
	CALLRET BTACKT		;TELL OPERATOR WHY I CAN'T SET AVAIL
; KSWI - PROCESS SWITCH COMMAND FROM OPR
; RETURNS +1: ALWAYS

; VALIDATE REQUEST NUMBER AND STATE

KSWI:	SAVEQ
	SAVEAC <MT,MTA,RSB>
	MOVEI T1,.ORREQ
	CALL ORNBLF		;LOOKUP REQUEST #
	 JRST KBADM		;NOT THERE
	MOVE T1,(T1)		;GET REQ#
	CALL REQRSB		;FIND RSB
	 JRST KNXREQ		;UNKNOWN REQUEST #
	MOVEI T2,[ASCIZ/Not Using An Unlabeled Tape/]
	LOAD T3,RSBTYP		;GET REQ TYPE
	CAIE T3,.MNTTP		;TAPE-MOUNT REQUEST?
	JRST KACKRQ		;NO, REJECT IT
	LOAD T3,RSBSTE		;GET STATE
	LOAD T4,RSBLT		;GET LABEL-TYPE
	CAIN T3,RST.AC		;MUST BE ACTIVE
	CAIE T4,.LTUNL		;MUST HAVE UNLABELED TAPE
	JRST KACKRQ		;DOESN'T QUALIFY, REJECT IT
	LOAD MT,RSBMT		;GET MT STATUS BLOCK ADDRESS

; VALIDATE VOLID

	CALL KGTVOL		;LOOKUP VOLID
	 RET			;SCREWED-UP VOLID
	SKIPN Q1,T1		;WAS THERE A .VOLID ENTRY?
	JRST KBADM		;NO, BAD NEWS

; CHECK IF TAPE DRIVE SPECIFIED

	SETZ MTA,		;ASSUME NO DRIVE SPECIFIED
	MOVEI T1,.TAPDV
	CALL ORNBLF		;TAPE DRIVE SPECIFIED?
	 JRST KSWI1		;NO
	CALL STMTA		;YES, LOAD MTA AC FOR THIS DRIVE
	 JRST KBADM		;BAD DRIVE NAME FROM QUASAR
	LOAD T1,MTMTA		;GET CURRENT DRIVE
	CAMN T1,MTA		;SWITCHING TO SAME DRIVE?
	JRST [	MOVEI T3,[ASCIZ/Cannot SWITCH To Same Drive/] ;YES
		CALLRET BTACK]
	MOVE T1,Q1		;GET VOLID
	SETZ T2,		;NOT SETTING SCRATCH
	CALL KVAC		;CHECK IF I CAN USE THIS MTA
	 RET			;NO, ERROR MSG SENT
	LOAD T1,MTALT
	CAIE T1,.LTUNL		;UNLABELED TAPE?
	JRST [	TMCT <%I%M Does Not Contain An Unlabeled Tape>
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;TELL OPERATOR
KSWI1:

; COMMAND HAS BEEN VALIDATED, NOW PERFORM SPECIFIED TASKS

	CALL GMTDD		;GET MT DEVICE DESIGNATOR IN T1
	LDB T2,[POINT 9,T1,35]	;GET MT UNIT# IN T2
	MOVEI T1,.MTCVV		;FUNCTION CODE = CLEAR VOLUME-VALID
	MTU%			;YANK MT AND MTA APART IN MONITOR
	 ERJMP [MOVE T1,RSBITN(RSB) ;CAN'T DO IT, GET REQUEST #
		TMCT <%ICannot SWITCH - Request %1D Has Tape Drive Open>
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;TELL OPR THE BAD NEWS
	MOVX T1,TM%NUL
	MOVE Q2,RSBUFL(RSB)	;GET CURRENT SETTING OF UNLOAD FLAG
	AND Q2,T1		;EXTRACT TM%NUL FLAG
	ANDCAM T1,RSBUFL(RSB)	;MAKE SURE TAPE GETS UNLOADED
	CALL PLDISA		;DISASSOCIATE MT&MTA IN MY TABLES
	IORM Q2,RSBUFL(RSB)	;RESTORE USER SETTING OF TM%NUL
	LOAD T1,RSBCV		;GET CURRENT VOLUME #
	MOVE T2,Q1		;GET VOLID
	CALL VQSET		;SET NEW VOLID IN USER REQUEST
	 CALL STOP		;VOLID LIST SCREWED UP
	JUMPE MTA,[CALLRET VOLMNT] ;NO MTA SPECIFIED, REQUEST TAPE MOUNT

; TRY TO ASSOCIATE SPECIFIED DRIVE WITH USER REQUEST

	MOVEI T1,RST.WM
	STOR T1,RSBSTE		;SET REQUEST WAITING FOR MOUNT
	EXCH Q1,MTAVOL(MTA)	;SET NEW VOLID
	CALL VRA		;TRY TO ASSOCIATE REQUEST WITH DRIVE
	 SKIPA			;NO GO
	RET			;ASSOCIATION DONE, EXIT
	MOVEM Q1,MTAVOL(MTA)	;RESTORE OLD VOLID
	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES
	CALLRET VOLMNT		;NO, ASK FOR VOLUME
; KTXCT - IMPLEMENTS EXECUTION OF MTA FUNCTION FOR ONE OR ALL TAPE
;	  DRIVES, ACCORDING TO PRESENCE OF .TAPDV AND .ALTAP BLOCKS
;  T1/ ADDRESS OF COROUTINE TO BE CALLED; COROUTINE RECEIVES MTA
;      STATUS BLOCK ADDRESS IN MTA AC, AND RETURNS +1 ALWAYS
; RETURNS +1: ERROR IN COMMAND MESSAGE
;	  +2: SUCCESS

KTXCT:	SAVEAC <MTA>
	SAVEQ
	MOVE Q2,T1		;SAVE COROUTINE ADDRESS
	MOVEI T1,.ALTAP
	CALL ORNBLF		;LOOKUP ALL-TAPES BLOCK
	 TDZA MTA,MTA		;NOT THERE, CLEAR MTA
	MOVEI MTA,MTA0		;ALL TAPES, POINT AT MTA0 STATUS BLOCK
	MOVEI T1,.TAPDV
	CALL ORNBLF		;LOOKUP SPECIFIC-TAPE-DRIVE BLOCK
	 JRST [	JUMPE MTA,R	;NO TAPE INFO SPECIFIED, BAD MESSAGE
		MOVE Q1,MTAN	;ALL DRIVES, GET # OF DRIVES
		JRST KTXCT1]	;GO DO THEM
	JUMPN MTA,R		;CAN'T HAVE BOTH!
	CALL STMTA		;GET MTA STATUS BLK ADDR FROM STRING
	 RET			;STRING DOESN'T SPECIFY MTA DEVICE
	MOVEI Q1,1		;DOING 1 DRIVE
KTXCT1:	CALL (Q2)		;CALL COROUTINE
	ADDI MTA,MTASZ		;POINT AT NEXT MTA STATUS BLOCK
	SOJG Q1,KTXCT1		;LOOP THRU SPECIFIED # OF DRIVES
	RETSKP
; KUNL - PROCESS UNLOAD COMMAND FROM OPR
; RETURNS +1: ALWAYS

KUNL:	SAVEQ
	SAVEAC <MTA>
	MOVEI T1,.TAPDV
	CALL ORNBLF		;TAPE DRIVE SPECIFIED?
	 JRST KBADM		;NO, REJECT MESSAGE
	JXE F,TALCF,KNALC	;REJECT IF ALLOCATION IS NOT ENABLED
	CALL STMTA		;CONVERT STRING TO MTA STATUS BLK ADDR
	 JRST KBADM		;ERROR, BAD MESSAGE
	MOVE Q1,MTAFLG(MTA)	;GET FLAGS
	CALL KCAVL		;DRIVE AVAILABLE TO USERS?
	 RET			;NO
	JN MTAMT,,[CALL KCUSE	;GIVE ERROR IF A USER HAS THE DRIVE
		 JFCL		;SHOULD ALWAYS RETURN +1
		RET]
	JN MTAJCT,,[SETONE MA%ULP,MTAFLG(MTA) ;IN USE BY ME, SET UNLOAD
		JRST KUNL1]	; PENDING
	CALL UNLOAD		;NOT IN USE BY ME, UNLOAD IT
KUNL1:	TXNN Q1,MA%LOD		;DID I THINK IT WAS LOADED?
	SETZM MTAVOL(MTA)	;NO, SUPPRESS VOLID IN UNLOAD MESSAGE
	CALLRET WOUNL		;TELL OPERATORS IT'S UNLOADED
; KVAC - CHECK IF LEGAL FOR OPERATOR TO CHANGE VOLUME ATTRIBUTES
;  T1/ 0 IF NOT CHANGING VOLID, NON-ZERO IF CHANGING VOLID
;  T2/ 0 IF NOT SETTING SCRATCH, NON-ZERO IF SETTING SCRATCH
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: FUNCTION ILLEGAL, ERRROR MESSAGE SENT TO OPERATOR
;	  +2: FUNCTION IS LEGAL

KVAC:	SAVEQ
	DMOVE Q1,T1		;COPY ARGS TO A SAFE PLACE
	CALL KCAVL		;DRIVE MUST BE AVAILABLE TO USERS
	 RET
	CALL KCLOAD		;DRIVE MUST BE LOADED
	 RET
	CALL KCUSE		;DRIVE MUST NOT BE IN USE
	 RET
	LOAD Q3,MTALT		;GET LABEL TYPE
	JUMPN Q1,[JUMPE Q3,.+1	;VOLID OK IF AVR NOT PERFORMED YET
		CAIN Q3,.LTUNL	;WHAT KIND OF TAPE?
		JRST .+1	;UNLABELED, VOLID OK HERE
		JSP T1,KVAX	;CAN'T SPECIFY VOLID FOR LABELED TAPE
		ASCIZ/Cannot Change Volid Of Labeled Tape/]
	JUMPE Q2,RSKP		;OK IF NOT SETTING SCRATCH
	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	JXN T1,MA%UXV,[JSP T1,KVAX ;CAN'T SCRATCH AN UNEXPIRED VOLUME
		ASCIZ/Cannot Scratch - Volume Is Not Expired/]
	JXE T1,MA%WEN,[JSP T1,KVAX ;CAN'T SCRATCH A WRITE-PROTECTED VOL
		ASCIZ/Cannot Scratch - Drive Is Write-Protected/]
	JUMPE Q3,[JSP T1,KVAX	;CAN'T SCRATCH UNTIL I'VE DONE AVR
		ASCIZ/Cannot Scratch - AVR Not Enabled/]
	RETSKP

; ERROR DETECTED, T1/ ADDR OF ERROR TEXT

KVAX:	TMCT <%I%M %1A>
	MOVEI T3,TMCMSG		;GET ADDRESS OF MESSAGE
	CALLRET BTACK		;SEND ERROR MESSAGE AND RETURN +1
; KVI - SUPPORT VOLUME INITIALIZATION UNDER OPR CONTROL
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RBUF/ "SET TAPE-DRIVE INIT" MESSAGE FROM OPR
; RETURNS +1: ALWAYS

KVI:	JE MA%AVS,MTAFLG(MTA),[LOAD T1,MTADRV
		MOVE T1,DRVTXT(T1)
		TMCT <%ICommand Illegal For %1A Drives>
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;BLAST THE OPERATOR
	CALL KCAVL		;DRIVE IN S.AV STATE?
	 RET			;NO, CAN'T DO THIS
	CALL KCUSE		;DRIVE IN USE?
	 RET			;YES, ERROR
	CALL GORSB		;GET RSB FOR INITIALIZATION
	 RET			;RSB POOL EXHAUSTED, MESSAGE TYPED
	MOVEI T1,.MNTTP
	STOR T1,RSBTYP		;SET RSB TYPE = TAPE-MOUNT
	MOVEI T1,RST.AC
	STOR T1,RSBSTE		;SET RSB ACTIVE
	CALL KVIRSB		;BUILD RSB FROM USER PARAMETERS
	 RET			;ERROR, RSB ABORTED, MESSAGE SENT TO OPR
	MOVEI T1,S.INIT
	STOR T1,MTASTE		;PUT TAPE DRIVE IN PROPER STATE
	MOVEI MT,RSBIMT(RSB)	;GET PSEUDO-MT STATUS BLOCK ADDRESS
	STOR RSB,MTRSB		;LINK MT TO RSB
	STOR MT,RSBMT		;LINK RSB TO MT
	STOR MTA,MTMTA		;LINK MT TO MTA
	STOR MT,MTAMT		;LINK MTA TO MT

; GET VOLID OF VOLUME TO BE INITIALIZED

KVI0:	LOAD T1,RSBLT
	CAIE T1,.LTUNL		;UNLABELED?
	SKIPE RSBIVL(RSB)	;OR DO I KNOW THE VOLID?
	JRST KVI2A		;YES TO EITHER, PROCEED
KVI1:	JSP T1,KVIMR1		;NO, HAVE TO ASK OPERATOR
	MOVEI RSB,-RSBWTB(T2)	;GET RSB ADDRESS
	LOAD MT,RSBMT
	LOAD MTA,MTMTA		;GET MTA STATUS BLOCK ADDR
	CALL PINI		;PARSE RESPONSE
	 JRST KVI1		;ERROR, TRY IT AGAIN JACK
KVI2:	MOVEM T1,RSBIVL(RSB)	;REMEMBER VOLID

; MAKE SURE DRIVE IS READY, DO AVR IF NEEDED

KVI2A:	JN MTAJCT,,R		;WAIT IF AVR OR REWIND IN PROGRESS
	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	JXE T1,MA%LOD,KVIM1	;IF TAPE NOT UP, SAY SO
	TXNE T1,MA%AVE		;WANT TO CHECK IF EXPIRED?
	JRST [	JE MTALT,,[CALLRET AVR] ;YES, DO AVR IF NOT DONE YET
		JXE T1,MA%UXV,.+1 ;AVR DONE, OK IF EXPIRED
		CALL KVIM4	;TELL OPERATOR IT'S NOT EXPIRED
		CALL UNLOAD	;UNLOAD IT
		JRST KVIM1]	;ASK HIM TO DO IT AGAIN
	CALL MTAGJF		;LOCK UP THE DRIVE
	MOVEI T1,KVI2B		;GET REWIND END-ACTION ADDRESS
	CALL REWEA		;REWIND
	 JRST KVI2B		;FAILED, MA%LOD CLEARED
	RET			;EXIT UNTIL REWIND COMPLETES

; REWIND END-ACTION

KVI2B:	CALL MTARJF		;RELEASE LOCK
	LOAD MT,MTAMT
	LOAD RSB,MTRSB		;RESTORE RSB ADDRESS
	JE MA%LOD,MTAFLG(MTA),KVIM1 ;ASK FOR TAPE IF NOT LOADED
; WRITE LABELS TO TAPE

	MOVE T1,RSBIVL(RSB)	;GET VOLID
	MOVEM T1,MTAVOL(MTA)	;STUFF IT FOR LTINIT
	SETONE R%WVL,RSBIFL(RSB) ;REQUEST LTINIT TO WRITE LABELS
	CALL LTINIT		;WRITE LABELS TO TAPE
	 JRST KVIM1		;ERROR, TELL OPERATOR TO MOUNT AGAIN
	CALL KVIM2		;TELL OPERATOR WHAT HAPPENED
	MOVX T1,TM%NUL
	TDNN T1,RSBUFL(RSB)	;UNLOAD REQUESTED?
	CALL UNLOAD		;YES, DO IT

; CHECK IF MORE INITIALIZATIONS LEFT TO DO

	SOSG RSBICT(RSB)	;ANY TAPES LEFT TO DO?
	JRST [	CALL KVICU	;NO, CLEAR INITIALIZE STUFF
		 CALL STOP
		CALLRET KVIDAV]	;GET BACK TO AVAILABLE STATE
	SETZM RSBIVL(RSB)	;YES, CLEAR VOLID
	SKIPN T1,RSBIVI(RSB)	;DOING NUMERIC VOLIDS?
	JRST KVI0		;NO, MUST ASK FOR NEXT VOLID
	ADD T1,RSBIVN(RSB)	;YES, STEP TO NEXT VOLID
	MOVEM T1,RSBIVN(RSB)	;RESTORE NUMERIC VOLID
	CALL INT26		;CONVERT TO SIXBIT
	JRST KVI2		;GO GET IT MOUNTED

; KVICU - PROCESS REQUEST TO CANCEL INITIALIZATION SERIES
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: DRIVE BUSY, OPERATOR TOLD ABOUT FAILURE
;	  +2: SUCCESS, TAPE DRIVE INITIALIZE STATE IS CLEARED

KVICU:	SAVEAC <MT,RSB>
	LOAD MT,MTAMT
	LOAD RSB,MTRSB		;GET RSB ADDRESS
	JN MTAJCT,,[JSP T1,KC1	;ERROR IF DRIVE BUSY
		ASCIZ/Busy/]
	SETZRO MTAMT		;CLEAR MTA LINK TO MT
	SETZRO RSBMT		;CLEAR RSB LINK TO MT
	SETZRO MA%LOD,MTAFLG(MTA) ;CLEAR DRIVE-LOADED
	ABTREQ (ABRTNR)		;DUMP THE RSB
	RETSKP

; KVIDAV - EXIT FROM INITIALIZE MODE TO AVAILABLE MODE

KVIDAV:	MOVEI T1,S.AV
	STOR T1,MTASTE		;SET STATE BACK TO AVAILABLE
	CALL AVRENA		;ENABLE AVR IF POSSIBLE
	CALL KVIM3		;TELL OPERATOR THE DRIVE IS AVAIL
	CALLRET TDSC1		;GO CHECK IF DRIVE OCCUPIEDPIPER

; KVITAV - REPORT TAPE DRIVE COMING ONLINE OR AVR COMPLETED
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

KVITAV:	SAVEAC <MT,RSB>
	LOAD MT,MTAMT
	LOAD RSB,MTRSB		;GET RSB ADDRESS
	JE MA%WEN,MTAFLG(MTA),[CALL UNLOAD ;WRITE-PROTECTED
		TMCT <%I%M Write Protected, Unloading Volume>
		MOVEI T3,TMCMSG	;GET ADDRESS OF TEXT
		CALLRET BTWTON]	;TELL OPERATOR THE BAD NEWS
	SKIPE RSBWTB+WTBCOD(RSB) ;WTOR OUTSTANDING?
	RET			;YES, WAIT TILL IT COMES BACK
	JN MA%LOD,MTAFLG(MTA),KVI0 ;IF TAPE IS READY, GET THINGS MOVING
	RET			;OTHERWISE, STILL HAVE TO WAIT

; KVIM1 - TELL OPERATOR TO MOUNT TAPE TO BE INITIALIZED

KVIM1:	TMCT <%IMount tape>
	SKIPE T1,RSBIVL(RSB)	;KNOW VOLID?
	JRST [	TMCT < volume %1S> ;YES
		JRST .+1]
	TMCT < for initialization on %M>
	MOVEI T3,[ASCIZ/Mount Tape To Be Initialized/]
	CALLRET BTWTO		;SEND MESSAGE TO OPERATOR

; KVIM2 - TELL OPERATOR TAPE WAS INITIALIZED SUCCESSFULLY

KVIM2:	TMCT <%I%M>		;DISPLAY DRIVE NAME
	LOAD T1,RSBLT
	CAIN T1,.LTUNL		;UNLABELED TAPE?
	JRST [	TMCT < Unlabeled Tape> ;YES, SAY SO
		JRST .+2]	;DON'T TYPE VOLID
	CALL TMCVOL		;DISPLAY VOLID
	TMCT < Initialized>
	CALL CPYHDR		;COPY HEADER TO A SAFE PLACE
	LOAD T1,RSBLT		;GET LABEL TYPE
	MOVE T1,LTTXT(T1)	;GET POINTER TO TEXT
	LOAD T2,RSBDEN
	MOVE T2,DENTAB(T2)	;GET DENSITY
	TMCT <%ILabel type: %1A%25CDensity: %2D>
	LOAD T1,RSBLT
	CAIE T1,.LTT20		;TOPS-20 TAPE?
	JRST KVIM21		;NO
	TMCT <
Owner: >			;YES, MORE INFO
	SKIPN T2,RSBUNO(RSB)	;GET OWNER USER #
	JRST [	TMCT <Scratch>	;IF ZERO, IT'S A SCRATCH TAPE
		JRST KVIM21]
	TMCT <%2U%23C  Protection: >
	MOVE T1,TMCPTR
	LOAD T2,RSBVPR		;GET PROTECTION CODE
	MOVE T3,[NO%LFL+NO%ZRO+FLD(6,NO%COL)+10]
	NOUT			;INSTALL IT
	 SKIPA
	MOVEM T1,TMCPTR		;RESTORE UPDATED POINTER
	CALL TMC1		;STANDARD TMC CLEANUP
KVIM21:	MOVEI T3,OPRHDR		;GET ADDRESS OF MESSAGE TYPE TEXT
	CALLRET BTWTO		;TELL OPERATORS WHAT HAPPENED

; KVIM3 - TELL OPERATOR DRIVE IS NO LONGER INITIALIZING

KVIM3:	TMCT <%I%M available for user tape requests>
	MOVEI T3,[ASCIZ/INITIALIZE Completed/]
	CALLRET BTWTO

; KVIM4 - TELL OPERATOR TAPE I CAN'T INITIALIZE - TAPE IS NOT EXPIRED

KVIM4:	TMCT <%I>
	CALL TMCVOL		;DISPLAY VOLID
	TMCT < on drive %M is not expired, unloading>
	MOVEI T3,[ASCIZ/Tape Volume Not Expired/]
	CALLRET BTWTO

; KVIMR1 - ISSUE WTOR TO ASK OPERATOR FOR VOLID TO BE INITIALIZED

KVIMR1:	STAKT
	TMCT <%IWhat is the volume-id of the next tape to be
initialized on drive %M ?
Respond with:
  RESPOND n volid>
	MOVE T1,CT1		;GET END-ACTION ADDRESS
	MOVEI T2,RSBWTB(RSB)	;GET WTB ADDRESS
	MOVEI T3,[ASCIZ/Key In Volume Identifier/]
	CALLRET BTWTOR
; KVIRSB - SCAN "SET TAPE INITIALIZE" IPCF MESSAGE FROM OPR AND
;	   BUILD REQUEST STATUS BLOCK
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ERROR DETECTED, OPERATOR NOTIFIED, RSB ABORTED
;	  +2: SUCCESS, INFORMATION STORED IN RSB

KVIRSB:	CALL KGTVOL		;GET VOLID
	 JRST KVIABT		;ERROR, MESSAGE SENT
	MOVEM T1,RSBIVL(RSB)	;STORE VOLID OR 0 IF NONE

	MOVEI T1,.SILBT		;CODE FOR LABEL TYPE
	MOVEI T2,.LTMAX		;LIMIT
	MOVEI T3,.LTT20		;DEFAULT
	CALL KGBLK		;LOOKUP LABEL TYPE
	 JRST KVIBM		;ERROR
	STOR T1,RSBLT		;STORE LABEL TYPE

	MOVEI T1,.SIDEN		;CODE FOR DENSITY
	MOVEI T2,DENMAX		;LIMIT
	MOVEI T3,.SJD16		;DEFAULT
	CALL KGBLK		;LOOKUP DENSITY
	 JRST KVIBM		;ERROR
	STOR T1,RSBDEN		;STORE DENSITY
	CALL DRVDEN		;CAN THE DRIVE OPERATE AT THIS DENSITY?
	 JRST [	LOAD T1,RSBDEN	;NO
		MOVE T1,DENTAB(T1) ;GET NUMERIC DENSITY
		TMCT <%I%1D BPI Is Not Supported On %M>
		MOVEI T3,TMCMSG	;GET MESSAGE ADDRESS
		CALL BTACK	;SEND ERROR MESSAGE
		JRST KVIABT]	;ABORT REQUEST

	MOVEI T1,.SICTR		;CODE FOR COUNT BLOCK
	HRLOI T2,377777		;LIMIT
	MOVEI T3,1		;DEFAULT
	CALL KGBLK		;LOOKUP COUNT
	 JRST KVIBM		;ERROR
	MOVEM T1,RSBICT(RSB)	;STORE COUNT

	MOVEI T1,.SISVI		;CODE FOR STARTING NUMERIC VOLID
	CALL ORNBLF		;LOOKUP VOLID
	 SETZ T2,		;NOT THERE
	JUMPE T2,KVIR2		;STARTING VOLID SPECIFIED?
	MOVE T1,(T1)		;YES, GET IT
	MOVEM T1,RSBIVN(RSB)	;STORE IT
	CALL INT26		;CONVERT TO SIXBIT
	MOVEM T1,RSBIVL(RSB)	;SET SIXBIT VOLID TOO

	MOVEI T1,.SIINC		;CODE FOR NUMERIC VOLID INCREMENT
	SETZ T2,		;NO LIMIT
	MOVEI T3,1		;DEFAULT = 1
	CALL KGBLK		;LOOKUP INCREMENT
	 JRST KVIBM		;ERROR
	MOVEM T1,RSBIVI(RSB)	;STORE INCREMENT
KVIR2:
	MOVEI T1,.SIHLD		;REQUESTED TO KEEP TAPE ON DRIVE?
	CALL ORNBLF
	 SKIPA			;NO
	JRST [	MOVE T1,RSBICT(RSB) ;YES, GET COUNT
		MOVX T2,TM%NUL
		CAIN T1,1	;INITIALIZING 1 TAPE?
		IORM T2,RSBUFL(RSB) ;YES, OK TO KEEP ON DRIVE
		JRST .+1]

	MOVEI T1,.SIOWN		;CODE FOR OWNER-ID
	SETZB T2,T3		;NO LIMIT, DEFAULT = 0 (SCRATCH)
	CALL KGBLK		;LOOK OWNER-ID
	 JRST KVIBM		;ERROR
	MOVEM T1,RSBUNO(RSB)	;STORE OWNER-ID

	MOVEI T1,.SIPRO		;CODE FOR PROTECTION
	SETZ T2,		;NO LIMIT
	MOVEI T3,777777		;DEFAULT = 777777
	CALL KGBLK		;LOOKUP PROTECTION
	 JRST KVIBM		;ERROR
	STOR T1,RSBVPR		;STORE PROTECTION

	MOVEI T1,.SIOVR		;OVERRIDE EXPIRATION-DATE CHECK?
	CALL ORNBLF
	 SKIPA T1,[1]		;NO
	SETZ T1,		;YES
	STOR T1,MA%AVE,MTAFLG(MTA) ;STORE OVERRIDE FLAG

	RETSKP

; ERROR CONDITIONS

KVIBM:	CALL BADQM		;ERROR IN IPCF MESSAGE FROM QUASAR
KVIABT:	ABTRET (ABRTNR)		;ABORT RSB AND RETURN +1
; ERROR HANDLERS FOR UNSOLICITED OPERATOR KEYINS ("K" ROUTINES)
; RET IS DONE THROUGH BTACK, GIVING ERROR MESSAGE TO OFFENDING OPR

KBADM:	CALLRET BADQM		;ERROR IN MESSAGE RECEIVED FROM QUASAR

KNXREQ:	MOVEI T2,[ASCIZ/Does Not Exist/]
KACKRQ:	TMCT <%IMount Request %1D %2A> ;T1/ REQ#, T2/ ADDRESS OF TEXT
	MOVEI T3,TMCMSG
	CALLRET BTACK		;SEND IT OFF TO OPERATOR

KBADV:	MOVEI T3,[ASCIZ/Illegal Volume Identifier/]
	CALLRET BTACK

KNALC:	MOVEI T3,[ASCIZ/Tape drive allocation is not enabled/]
	CALLRET BTACK

;REJECT IDENTIFY KEYIN TO SCRATCH A TAPE

KNOSCR:	STKVAR <<OWNER,10>>
	TMCT <%ICannot Scratch %M> ;BUILD HEADING WITH DRIVE NAME
	CALL CPYHDR		;SAVE MESSAGE HEADING
	MOVEI T1,OWNER		;OWNER'S NAME GOES HERE
	CALL GETVU		;GET POINTER TO OWNER'S NAME IN T1
	MOVE T2,MTAVOL(MTA)	;GET VOLID
	TMCT <%IVolume %2S owned by user %1A>
	MOVEI T3,OPRHDR		;POINT TO HEADING
	CALLRET BTACKT		;TELL OPERATOR I REJECTED IT
; ORNBCK - CHECK BUILDING BLOCK STRUCTURE OF ORION-STYLE IPCF MESSAGE
;	   IN RBUF (ASSUMES CKGHDR HAS BEEN CALLED)
; RETURNS +1: ERROR IN BLOCK STRUCTURE
;	  +2: BLOCK STRUCTURE OK

ORNBCK:	MOVE T1,RBUF+.OARGC	;GET # OF ARGS
	MOVEI T2,RBUF+.OHDRS	;GET ADDRESS OF 1ST ARG
	LOAD T3,MS.CNT,RBUF+.MSTYP ;GET SIZE OF IPCF MESSAGE FROM HEADER
	SUBI T3,.OHDRS		;COMPUTE SIZE OF BUILDING BLOCK AREA
	CALLRET CKBSTR		;CHECK BLOCK STRUCTURE


; ORNBLF - FIND ARGUMENT BLOCK IN ORION-STYLE IPCF MESSAGE
;  T1/ TYPE CODE OF DESIRED ARGUMENT
; RETURNS +1: NO ARGUMENTS OF REQUESTED TYPE FOUND
;	  +2: SUCCESS, T1/ ADDRESS OF FIRST WORD OF ARGUMENT
;		       T2/ LENGTH OF ARGUMENT (NOT COUNTING HEADER)

ORNBLF:	MOVE T3,T1		;COPY ARG TYPE TO T3 FOR BLKFND
	MOVEI T1,RBUF+.OARGC	;GET ADDRESS OF ARG COUNT WORD
	MOVEI T2,RBUF+.OHDRS	;GET ADDRESS OF 1ST BLOCK
	CALLRET BLKFND		;CALL BLKFND TO DO LOOKUP


; ORNINI - ESTABLISH IPCF RAPPORT WITH ORION
; RETURNS +1: ALWAYS

ORNINI:	STKVAR <TSTFLG>		;FLAG USED ONLY FOR DEBUGGING
	SETOM TSTFLG		;INITIALIZE FLAG
ORNIN1:	MOVEI T1,.SPOPR
	CALL GSYSPD		;GET ORION'S PID FROM SYSTEM PID TABLE
	 JRST [	AOSN TSTFLG	;HAVE WE BEEN HERE BEFORE?
		CALL TSTWAT	;NO, INFORM USER WE ARE WAITING
		MOVEI T1,^D5000	;NOT THERE YET
		DISMS		;WAIT 5 SECONDS
		JRST ORNIN1]	; AND TRY AGAIN
	MOVEM T1,APPID+.APORN	;STUFF PID IN A/P TABLE
	GTAD			;GET FAIRLY UNIQUE VALUE IN RH(T1)
	HRLM T1,UNIQUE		;INSURE CODES UNIQUE TO SYSTEM STARTUP
	RET


; TSTWAT - INFORMS USER WHO WE ARE WAITING FOR IF DEBUGGING
; REQUIRES PONTER TO ASCII PID NAME IN T1
; RETURNS +1: ALWAYS

TSTWAT:	SKIPN TSTF		;ARE WE DEBUGGING
	 RET			;NO
	PUSH P,T1		;SAVE POINTER
	TMSG <% MOUNTR Waiting for >
	POP P,T1		;POINTER TO PID NAME STRING
	PSOUT			;TYPE IT TO TERMINAL
	TMSG <
>
	RET			;RETURN
; ORNMRC - PROCESS INCOMING IPCF MESSAGE FROM ORION
;  RBUF/ INCOMING IPCF MESSAGE
;  MRPDB/ PDB THAT WAS USED TO RECEIVE THE MESSAGE
; RETURNS +1: ALWAYS

ORNMRC:	CALL CKGHDR		;GALAXY HEADER OK?
	 JRST [	CALLRET BADOM]	;NO
	CALL ORNBCK		;BLOCK STRUCTURE OK?
	 JRST [	CALLRET BADOM]	;NO
	LOAD T1,MS.TYP,RBUF+.MSTYP ;GET MESSAGE TYPE
	CAIN T1,.OMRSP		;WHAT TYPE?
	JRST [	CALLRET INWTOR]	;RESPONSE TO WTOR
	LOAD T2,MF.SUF,RBUF+.MSFLG ;GET SIXBIT SUFFIX
	CAIN T1,MT.TXT		;TEXT MESSAGE?
	JRST [	CAIE T2,'NMC'	;CHECK FOR - NO MESSAGE WITH THIS CODE
		CAIN T2,'ODE'	;CHECK FOR - OPR DOESN'T EXIST
		RET		;IGNORE THIS ERROR
		JRST .+1]	;CAN'T HANDLE THIS TEXT MESSAGE
	CALLRET BADOM		;BAD TEXT MESSAGE, REPORT IT
; PINI - PARSE OPERATOR RESPONSE TO REQUEST FOR VOLID TO BE INIT'ED
;  T1/ ADDRESS OF ASCIZ OPERATOR RESPONSE TEXT
; RETURNS +1: ERROR, MESSAGE SENT TO OPERATOR
;	  +2: SUCCESS, T1/ SIXBIT VOLID

PINI:	SAVET			;SETUP TO RETURN VALUE IN T1
	CALL COMNDI
	CALL COMNDV		;PARSE VOLID
	 RET			;FAILED
	MOVEM T1,CT1		;RETURN VOLID TO CALLER
	CALLRET CMDCFM		;GET CONFIRMATION AND RETURN

; PMR - PARSE OPERATOR RESPONSE TO WTOR ASKING FOR VOLID LIST
;  T1/ ADDRESS OF ASCIZ OPERATOR RESPONSE TEXT
;  RSB/ ADDRESS OF REQUEST STATUS BLOCK
; RETURNS +1: ERROR DETECTED WHILE PARSING RESPONSE, OPERATOR NOTIFIED
;	  +2: SUCCESSFUL PARSE
;	      T1/ 0 - RSB AND VOLID LIST SET UP
;	      T1/ 1 - REQUEST ABORTED

PMR:	CALL COMNDI		;INITIALIZE FOR COMND JSYS
	MOVEI T2,[FLDDB.(.CMKEY,,PMRT1)] ;SET UP FOR KEYWORD PARSE
	CALL COMNDX		;ISSUE COMND JSYS TO DO PARSE
	 JRST [	MOVEI T3,[ASCIZ/Syntactical Error In Response/]
		CALLRET BTACK]	;HE BLEW THE KEYWORD
	HRRZ T2,(T2)		;GET ADDRESS OF KEYWORD PROCESSOR
	CALLRET (T2)		;DISPATCH TO KEYWORD PROCESSOR

PMRT1:	PMRT1L,,PMRT1L		;KEYWORD TABLE
	[ASCIZ/REFUSE/],,PMRREF	;REFUSE reason
	[ASCIZ/VOLUMES/],,PMRVOL ;VOLUMES volid,...,volid
PMRT1L==.-PMRT1-1

PMRREF:	CALL PREFUS		;PARSE REFUSAL
	 RET			;OPERATOR ERROR
	ABTREQ (MREQ16,ABT%OP)	;ABORT REQUEST
	MOVEI T1,1		;SET T1 TO INDICATE ABORTION
	RETSKP


; PREFUS - COMPLETE PARSING OF REFUSAL BY OPERATOR
; RETURNS +1: ERROR, OPERATOR NOTIFIED
;	  +2: SUCCESSFUL PARSE, ATMBFR/ ASCIZ REASON GIVEN BY OPERATOR

PREFUS:	MOVEI T2,[FLDDB. .CMTXT] ;PARSE TEXT OUT TO CARRIAGE RETURN
	CALL COMNDX
	 JRST PREFU1		;ERROR
	LDB T1,[POINT 7,ATMBFR,6] ;WAS THERE A REASON GIVEN?
	JUMPN T1,RSKP		;YES, TAKE GOOD RETURN
PREFU1:	JSP T1,RSPERR		;ERROR, TELL OPERATOR
	ASCIZ/No reason given/
; PMRVOL - PARSE VOLID LIST FROM OPERATOR
;  RSB/ ADDRESS OF REQUEST STATUS BLOCK
; RETURNS +1: ERROR, T1/ ADDRESS OF ASCIZ ERROR MESSAGE FOR OPERATOR
;	  +2: T1/ 0 - RSB AND VOLID LIST SET UP
;	      T1/ 1 - REQUEST ABORTED

PMRVOL:	CALL VQDEL		;DELETE VOLID LIST (IF ANY)
	MOVEI T1,1
	STOR T1,RSBCV		;SET CURRENT VOLUME # TO 1
PMRV1:	CALL COMNDV		;PARSE VOLID
	 RET			;FAILED
	CALL VQADD		;ADD VOLUME TO LIST
	 JRST [	MOVEI T1,1	;OUT OF TABLE SPACE
		RETSKP]
	MOVEI T2,[FLDDB.(.CMCMA,,,,,[FLDDB.(.CMCFM)])]
	CALL COMNDX		;PARSE COMMA OR CARRIAGE RETURN
	 JRST [	JSP T1,RSPERR	;PARSE FAILED
		ASCIZ/Syntactical error in volume-id list/]
	HRRZS T3		;GET ADDRESS OF ACTUAL FDB
	LOAD T3,CM%FNC,(T3)	;GET FUNCTION CODE FROM FDB
	CAIN T3,.CMCMA		;WHAT DID I JUST PARSE?
	JRST PMRV1		;COMMA, GO GET ANOTHER VOLID
	SETZ T1,		;CARRIAGE RETURN, CLEAR T1
	RETSKP
; PNVR - PARSE OPERATOR RESPONSE TO "KEYIN NEXT VOLID" WTOR
;  T1/ ADDR OF ASCIZ RESPONSE TEXT
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ERROR, T1/ ADDRESS OF ASCIZ ERROR MESSAGE FOR OPERATOR
;	  +2: T1/ 0 - VOLID ADDED TO RSB VOLID LIST
;	      T1/ 1 - REQUEST ABORTED

PNVR:	CALL COMNDI		;SET UP FOR PARSING WITH COMND
	MOVEI T2,[FLDDB. .CMKEY,,PNVKT] ;GET FDB ADDRESS
	CALL COMNDX		;PARSE KEYWORD
	 JRST [	JSP T1,RSPERR	;ERROR
		ASCIZ/REFUSE or VOLUME keyword missing/]
	HRRZ T2,(T2)		;GET HANDLER ADDRESS
	CALLRET (T2)		;DISPATCH TO HANDLER

PNVKT:	PNVKTL,,PNVKTL		;KEYWORD TABLE
	[ASCIZ/REFUSE/],,PMRREF
	[ASCIZ/VOLUME/],,PNVVOL
PNVKTL==.-PNVKT-1

PNVVOL:	SAVEQ			;OPERATOR RESPONDED WITH A VOLID
	CALL COMNDV		;PARSE VOLID
	 RET			;FAILED
	MOVE Q1,T1		;SAVE VOLID
	CALL CMDCFM		;CHECK FOR EOL
	 RET			;NOT THERE
	MOVE T1,Q1		;GET VOLID
	CALL VQADD		;TACK IT ON TO THE END OF THE LIST
	 JRST [	MOVEI T1,1	;OUT OF TABLE SPACE
		RETSKP]
	SETZ T1,		;SET SUCCESSFUL COMPLETION
	RETSKP
; PSMR - PARSE OPERATOR RESPONSE TO STRUCTURE MOUNT WTOR MESSAGE
;  T1/ ADDRESS OF ASCIZ RESPONSE TEXT
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ERROR DETECTED WHILE PARSING RESPONSE, OPERATOR NOTIFIED
;	  +2: SUCCESSFUL PARSE, REQUEST ABORTED
;	      ATMBFR/ ASCIZ REASON GIVEN BY OPERATOR

PSMR:	CALL COMNDI		;INIIALIZE FOR COMND JSYS
	MOVEI T2,[FLDDB.(.CMKEY,,PSMKT)] ;SET UP FOR KEYWORD PARSE
	CALL COMNDX		;PARSE KEYWORD
	 JRST [	JSP T1,RSPERR	;BAD KEYWORD, GIVE ERROR
		ASCIZ/Response must be of the form:
REFUSE reason/]
	MOVX T2,R%OPR
	TDNE T2,RSBIFL(RSB)	;IS THIS AN OPR REQUEST?
	RETSKP			;YES, FORGET REASON
	CALL PREFUS		;PARSE REMAINDER OF REFUSAL
	 RET			;OPERATOR ERROR
	ABTREQ (MREQ15,ABT%OP)	;OPERATOR REFUSED TO MOUNT VOLUME
	RETSKP

PSMKT:	PSMKTL,,PSMKTL
	[ASCIZ/REFUSE/],,0
PSMKTL==.-PSMKT-1
; RSPERR - TELL OPERATOR THAT THERE WAS AN ERROR IN HIS RESPONSE
;  T1/ ADDRESS OF ASCIZ ERROR MESSAGE
; RETURNS +1: ALWAYS

RSPERR:	TMCT <%I%1A>
	MOVEI T3,[ASCIZ/Response Error/] ;GET MESSAGE TYPE
	CALLRET BTACKT		;SEND IT OFF TO THE OPERATOR


; WOASO - TELL OPERATOR A TAPE HAS BEEN GIVEN TO A USER
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

WOASO:	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%I%M Given To Request %1D>
	CALL CPYHDR		;COPY HEADER TO OPRHDR
	TMCT <%I>
	CALL TMCVOL		;DISPLAY VOLID
	TMCT < now in use by%_ %U>
	MOVE T1,RSBIFL(RSB)
	TXNN T1,R%ONR		;WAS OPERATOR TOLD TO MOUNT TAPE?
	CALL BTJOB		;NO, MAKE THIS A JOB MESSAGE
	MOVEI T3,OPRHDR		;POINT TO HEADING
	CALLRET BTWTO		;SHIP IT OFF TO THE OPERATOR


; WOCKSW - IF A SCRATCH VOLUME IS WRITE-PROTECTED, DISMOUNT IT AND
;	   GIVE AN ERROR MESSAGE TO THE OPERATOR
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: WRITE-PROTECTED SCRATCH VOLUME UNLOADED
;	  +2: TAPE WAS NOT A WRITE-PROTECTED SCRATCH

WOCKSW:	MOVE T1,MTAFLG(MTA)	;GET FLAGS
	TXNE T1,MA%SCR		;TAKE +2 IF NOT SCRATCH
	TXNE T1,MA%WEN		;TAKE +2 IF WRITE-ENABLED
	RETSKP
	TMCT <%IUnloading drive %M>
	SKIPE MTAVOL(MTA)	;DO I KNOW ITS VOLID?
	CALL TMCVOL		;YES, THROW IT IN THERE TOO
	TMCT <
Remount scratch tape with write ring>
	MOVEI T3,[ASCIZ/No Ring In Scratch Tape/]
	CALL BTWTO		;TELL OPERATOR
	CALLRET UNLOAD		;UNLOAD THE TAPE


; WODISA - TELL OPERATOR A USER HAS RELEASED A TAPE DRIVE
;  T1/ ADDR OF ASCIZ DISPOSITION TEXT
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WODISA:	STAKT
	TMCT <%I%M>
	SKIPN MTAVOL(MTA)	;TAPE HAVE A VOLID?
	JRST [	TMCT < Tape>	;NO
		JRST .+2]
	CALL TMCVOL		;DISPLAY VOLID
	MOVE T1,CT1		;GET ADDRESS OF CALLER'S TEXT
	TMCT < %1A>
	CALL BTJOB		;THIS IS A JOB MESSAGE
	MOVEI T3,[ASCIZ/Tape Drive Released By User/]
	CALLRET BTWTO		;SEND IT OFF

; WOUSGF - TELL OPERATOR THAT USAGE JSYS FAILED.
;
; RETURNS +1: ALWAYS

WOUSGF:	TMCT <%IAccount record not written. %U. Reason: %J>
	MOVEI T3,[ASCIZ/MOUNTR System Task Error/]
	CALLRET BTWTO		;OUT TO OPERATOR

; WOLINF - TELL OPERATOR THAT I FAILED TO WRITE LABELS ON A TAPE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOLINF:	TMCT <%IError writing labels on %M>
	CALL TMCVOL		;DISPLAY VOLID
	MOVEI T3,[ASCIZ/Tape Error Writing Labels/]
	CALLRET BTWTO		;OUT TO OPERATOR


; WOLOCF - TELL OPERATOR THAT .MOLOC MTOPR FAILED
;  MTA/ ADDR OF MTA STATUS BLOCK
;  MT/ ADDR OF MT STATUS BLOCK
; RETURNS +1: ALWAYS

WOLOCF:	TMCT <%IFailed to associate %M with %N%_Reason: %J>
	MOVEI T3,[ASCIZ/MOUNTR System Task Error/]
	CALLRET BTWTO		;OUT TO OPERATOR


; WOLRDX - TELL OPERATOR I COULDN'T READ ANYTHING FROM THE TAPE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOLRDX:	TMCT <%ITape on %M may be labeled at a density that
is not supported by this drive.
Tape has been unloaded.>
	MOVEI T3,[ASCIZ/Cannot Read Tape/]
	CALLRET BTWTO


; WORCAN - TELL OPERATOR A MOUNT REQUEST WAS CANCELED
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

WORCAN:	MOVE T1,RSBIFL(RSB)	;GET FLAGS
	TXNN T1,R%ONR		;DID THE OPERATOR SEE THE MESSAGE?
	RET			;NO, DON'T SAY ANYTHING WAS CANCELED
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%IMount Request # %1D Canceled>
	MOVEI T3,TMCMSG		;GET ADDRESS OF TEXT
	CALLRET BTWTON		;TELL ALL OPERATORS


; WOTDAV - TELL OPERATOR OF AVAILABILITY OF TAPE DRIVE FOR SYSTEM USE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOTDAV:	SAVEQ
	SAVEAC <MT,RSB>
	MOVEI Q1,1		;ASSUME AVAILABLE
	CALL CKMPAV		;IS IT AVAILABLE?
	 SETZ Q1,		;NO, SET NOT AVAILABLE
	TMCT <%I%M set >
	JUMPE Q1,[TMCT <un>
		JRST .+1]
	TMCT <available for assignment by MOUNTR>
	LOAD MT,MTAMT		;MT ASSOCIATED?
	JUMPN MT,[LOAD RSB,MTRSB ;YES, GET RSB ADDRESS
		TMCT <%_%%Drive is currently in use by %U>
		JRST .+1]
	MOVE T3,[[ASCIZ/Tape Drive Set Unavailable/]
		 [ASCIZ/Tape Drive Set Available/]](Q1) ;GET HEADER
	CALLRET BTWTO		;GET MESSAGE OUT TO OPERATOR


; WOTIMO - REPORT MTA DEVICE TIMEOUT TO THE OPERATOR
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOTIMO:	TMCT <%I%M operation timed out>
	MOVEI T3,[ASCIZ/Tape Drive Timed Out/]
	CALLRET BTWTO		;TELL THE OPERATOR


; WOTMD - TELL OPERATOR A TAPE HAS BEEN MOUNTED ON A DRIVE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOTMD:	MOVX T1,MA%VMG
	TDNE T1,MTAFLG(MTA)	;HAS THE OPERATOR BEEN TOLD ALREADY?
	RET			;YES, NO ACTION THEN
	IORM T1,MTAFLG(MTA)	;NO, SET MESSAGE-GIVEN
	TMCT <%I%M>
	SKIPE MTAVOL(MTA)	;DOES IT HAVE A VOLID?
	JRST [	CALL TMCVOL	;YES, DISPLAY IT
		TMCT <,>
		JRST .+1]
	LOAD T1,MTALT		;GET LABEL TYPE
	JUMPE T1,WOTMD1		;JUMP IF LT NOT KNOWN (AVR DISABLED)
	MOVE T2,LTTXT(T1)	;GET ADDRESS OF TEXT
	TMCT < %2A>		;SPEW OUT LABEL TYPE
	CAIE T1,.LTUNL		;IS IT LABELED?
	CALL [	TMCTR < labeled>] ;YES
WOTMD1:	TMCT < tape mounted>
	MOVEI T3,TMCMSG		;GET ADDRESS OF TEXT
	CALLRET BTWTON		;BUILD AND TRANSMIT WTO MESSAGE


; WOUNL  - TELL OPERATOR THAT A TAPE HAS BEEN UNLOADED
; WOUNLW - SAME AS WOUNL, EXCEPT WARNING MESSAGE IS GIVEN TOO
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOUNLW:	SKIPA T1,[BTWTO]	;DISPLAY WARNING
WOUNL:	MOVEI T1,BTWTON		;SUPPRESS WARNING
	STAKT
	TMCT <%I%M>		;DISPLAY DRIVE NAME
	SKIPE MTAVOL(MTA)	;DO I KNOW THE VOLID?
	CALL TMCVOL		;YES, DISPLAY IT
	TMCT < unloaded>
	CALL CPYHDR		;COPY HEADER TO OPRHDR
	TMCT <%I%%Use the DISMOUNT TAPE command to unload tape drives>
	MOVEI T3,OPRHDR		;GET ADDRESS OF HEADER
	MOVE T1,CT1		;GET ADDRESS OF ROUTINE TO CALL
	CALLRET (T1)		;OUT TO OPERATOR AND RETURN
; WOVMT - TELL OPERATOR A TAPE VOLUME MUST BE MOUNTED
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

WOVMT:	SAVEQ
	SAVEAC <MTA>
; IN THE EVENT THAT A USER IS REQUESTING A SPECIFIC VOLUME AND
; THAT VOLUME IS UNDERGOING AVR ON A TAPE DRIVE, WE WANT TO
; INHIBIT SENDING THE WTO TO REQUEST THE TAPE UNTIL THE AVR
; SEQUENCE COMPLETES.  THIS CODE CHECKS FOR THIS CONDITION.

	LOAD T1,RSBSTE		;GET REQUEST STATE
	MOVE T2,RSBIFL(RSB)	;GET FLAGS
	CAIN T1,RST.WM		;WAITING FOR MOUNT
	TXNE T2,R%ONR		; AND OPERATOR NOT TOLD YET?
	RET			;NOT BOTH, DON'T DO ANYTHING
	CALL VQGCV		;GET CURRENT VOLID
	JUMPE T1,WOV2		;SCRATCH
	MOVE T2,MTAN		;GET # OF MTA'S TO SCAN
	MOVEI MTA,MTA0-MTASZ	;START HERE
WOV1:	ADDI MTA,MTASZ		;POINT AT NEXT MTA
	SOJL T2,WOV2		;NONE LEFT, SEND MESSAGE
	LOAD T3,MTASTE		;GET DRIVE STATE
	CAIE T3,S.AV		;AVAILABLE TO USERS?
	JRST WOV1		;NO, SKIP IT
	JE MTAJCT,,WOV1		;SKIP IF AVR NOT IN PROGRESS
	CAMN T1,MTAVOL(MTA)	;DRIVE & REQUEST VOLIDS MATCH?
	RET			;YES, MESSAGE SUPPRESSED
	JRST WOV1		;NO, CONTINUE DRIVE SCAN

; MUST TELL THE OPERATOR TO MOUNT THE TAPE, START BUILDING MESSAGE

WOV2:	SETONE R%ONR,RSBIFL(RSB) ;SET OPERATOR-NOTIFIED
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%ITape Mount Request # %1D>
	CALL CPYHDR		;COPY HEADER TO OPRHDR

; BUILD THE BODY OF THE MESSAGE

	TMCT <%IMount >
	CALL VQGCV		;GET VOLID IN T1
	MOVE Q1,T1		;COPY VOLID TO SAFE PLACE
	LOAD T2,RSBLT		;LABEL TYPE KNOWN?
	JUMPN T2,[MOVEI T1,[ASCIZ/Labeled/] ;YES
		CAIE T2,.LTUNL
		SKIPE Q1
		MOVE T1,LTTXT(T2) ;UNLABELED OR NOT SCRATCH
		MOVX T2,TM%BYP
		TDNE T2,RSBUFL(RSB) ;BYPASS?
		MOVEI T1,[ASCIZ/BYPASS/] ;YES, SAY SO
		TMCT <%1A >	;DISPLAY LABEL TYPE
		JRST .+1]
	JUMPE Q1,[TMCT <scratch tape> ;SCRATCH TAPE, SAY SO
		JRST .+1]
	JUMPN Q1,[TMCT <volume %5S> ;DISPLAY SPECIFIC VOLUME
		JRST .+1]
	LOAD Q1,RSBDRV		;DRIVE TYPE KNOWN?
	JUMPN Q1,[MOVE T1,DRVTXT(Q1) ;GET POINTER TO DRIVE TEXT
		TMCT <, %1A>	;DISPLAY DRIVE TYPE
		JRST .+1]
	LOAD Q1,RSBDEN		;DENSITY KNOWN?
	JUMPN Q1,[MOVE T1,DENTAB(Q1) ;YES, GET DENSITY
		TMCT <, %1D BPI>
		JRST .+1]
	MOVEI T1,[ASCIZ/, READ-ONLY/] ;ASSUME READ-ONLY
	MOVX T2,TM%WEN
	TDNE T2,RSBUFL(RSB)
	MOVEI T1,[ASCIZ/, WRITE-ENABLED/]
	TMCT <%1A%_%U>
	JE R%ONV,RSBIFL(RSB),[SETONE R%ONV,RSBIFL(RSB)
		CALL VQCNT	;MORE THAN 1 VOLID IN SET?
		SOJLE T1,.+1	;NO
		MOVE T1,RSBSSN(RSB) ;GET SETNAME
		TMCT <
Volumes in set %1S: >
		CALL TMCVLS	;DISPLAY VOLID LIST
		JRST .+1]
	SKIPE RSBRMK(RSB)	;DID THE USER SUPPLY A REMARK?
	JRST [	MOVEI T1,RSBRMK(RSB) ;YES, GET ADDR OF REMARK
		TMCT <%_User's remark: %1A>
		JRST .+1]
	MOVEI T3,OPRHDR		;GET ADDRESS OF HEADING
	CALLRET BTWTO		;SEND WTO OFF TO THE OPERATOR


; WOWDDR - REQUEST REMOUNT OF TAPE - DRIVE COULDN'T HANDLE DENSITY
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

WOWDDR:	TMCT <%I%M>
	CALL TMCVOL		;DISPLAY VOLID
	MOVE T1,MTAVOL(MTA)	;GET VOLID
	LOAD T2,RSBDEN
	MOVE T2,DENTAB(T2)	;GET NUMERIC DENSITY
	TMCT < being unloaded
Remount volume %1S on %2D BPI drive>
	MOVEI T3,[ASCIZ/Remount Tape Volume/]
	CALLRET BTWTO


; WOWPE - TELL OPERATOR THAT WRITE RING SHOULD BE INSERTED OR REMOVED
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

WOWPE:	TMCT <%I%M>
	CALL TMCVOL		;DISPLAY VOLID
	LOAD T1,MA%WEN,MTAFLG(MTA) ;GET CURRENT WRITE STATUS
	MOVE T1,[[ASCIZ/Insert/]
		 [ASCIZ/Remove/]](T1) ;GET WHAT TO DO
	TMCT <%_%1A write ring and remount tape>
	MOVEI T3,[ASCIZ/Tape Write Protect Error/]
	CALLRET BTWTO		;OUT TO OPERATOR


; WRNXTV - ASK OPERATOR FOR NEXT VOLUME OF VOLUME SET
;  T1/ ADDR OF RESPONSE HANDLER THAT WILL BE CALLED BY INWTOR
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

WRNXTV:	MOVE T2,RSBSSN(RSB)
	TMCT <%ISupply next volume-id for tape set %2S%_%U
Respond with either of:
  VOLUME volid
  REFUSE reason>
	SKIPE RSBRMK(RSB)	;DID THE USER SUPPLY A REMARK?
	JRST [	MOVEI T2,RSBRMK(RSB) ;YES, GET ADDR OF REMARK
		TMCT <%_User's remark: %2A>
		JRST .+1]
	MOVEI T2,RSBWTB(RSB)	;GET WTB ADDRESS
	MOVEI T3,[ASCIZ/Key In Next Volume Identifier/]
	CALLRET BTWTOR		;SEND IT OFF


; WRUTR - TELL OPERATOR THAT A USER TAPE MOUNT REQUEST HAS BEEN
;	   RECEIVED AND ASK HIM TO KEY IN VOLID LIST
;  T1/ ADDRESS OF RESPONSE HANDLER THAT WILL BE CALLED BY INWTOR
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

WRUTR:	MOVE T2,RSBSSN(RSB)
	TMCT <%IVolume set %2S, %U
Respond with either of:
  RESPOND n VOLUMES volid,volid,...
  RESPOND n REFUSE reason>
	SKIPE RSBRMK(RSB)	;DID THE USER SUPPLY A REMARK?
	JRST [	MOVEI T2,RSBRMK(RSB) ;YES, GET ADDR OF REMARK
		TMCT <%_User's remark: %2A>
		JRST .+1]
	MOVEI T2,RSBWTB(RSB)	;WTB ADDRESS
	MOVEI T3,[ASCIZ/Tape Set Request/] ;MESSAGE TYPE
	CALLRET BTWTOR		;SEND OFF WTOR
; TEXT MESSAGE COMPOSITION (TMC) SUBROUTINES
; ALL TMC SUBROUTINES RETURN +1 ALWAYS

TMC1:	MOVE T1,TMCPTR		;GET BUFFER POINTER
	SETZ T2,
	IDPB T2,T1		;PUT A NULL AT THE END OF THE BUFFER
	SUBI T1,TMCMSG-1	;COMPUTE BUFFER SIZE IN WORDS
	HRRZM T1,TMCWDS		;STORE IT FOR CALLING ROUTINES
	RET


; TMCRSP - SPECIAL VERSION OF TMCASZ FOR INCOMING WTOR RESPONSES
;  T1/ 0 ,, ADDRESS OF ASCIZ WTOR RESPONSE

TMCRSP:	HRLI T1,(POINT 7)	;CONSTRUCT BYTE POINTER
TMCRS1:	ILDB T2,T1		;GET A BYTE FROM RESPONSE TEXT
	JUMPE T2,[TMCTR <%_>]	;END, APPEND CRLF AND RETURN
	CAIN T2,"F"-100
	JRST TMCRS1		;DON'T COPY CTRL/F
	CAIN T2,.CHESC
	JRST TMCRS1		;DON'T COPY ESCAPE
	CAIN T2,"?"
	JRST TMCRS1		;DON'T COPY QUESTION MARK
	CAIN T2,.CHCRT
	JRST TMCRS1		;DON'T COPY CARRIAGE RETURN
	CAIN T2,.CHLFD
	MOVEI T2," "		;CHANGE LINE FEED TO BLANK
	IDPB T2,TMCPTR		;PUT CHARACTER IN TMCMSG
	JRST TMCRS1		;LOOP UNTIL NULL

; CPYHDR - COPY CONTENTS OF TMCMSG TO OPRHDR

CPYHDR:	MOVE T1,[TMCMSG,,OPRHDR] ;BLT SOURCE,,DESTINATION
	BLT T1,OPRHDR+OPRHSZ-1
	RET


; TMCVOL - DISPLAY THE TEXT " Volume " FOLLOWED BY THE MTA VOLID
;  MTA/ ADDR OF MTA STATUS BLOCK

TMCVOL:	SKIPN T1,MTAVOL(MTA)	;GET VOLID
	JRST [	TMCTR < scratch tape>] ;ZERO, THEREFORE SCRATCH
	TMCTR < Volume %1S>	;DISPLAY AND RETURN


; TMCVLS - DISPLAY THE VOLUME-ID LIST FOR A GIVEN USER REQUEST
;  RSB/ ADDR OF REQUEST STATUS BLOCK

TMCVLS:	SAVEQ
	QSCANI <RSBVLS(RSB)>	;SET UP TO SCAN VOLID LIST
	SETO Q1,		;INIT COUNTER
TMCVL1:	CALL QMSCAN		;GET ADDRESS OF NEXT VOLID ENTRY IN T2
	 RET			;NONE LEFT, SPLIT
	AOJG Q1,[TMCT <, >	;SEPARATE VOLIDS WITH COMMAS
		JRST .+1]
	SKIPN T1,1(T2)		;GET SIXBIT VOLID
	JRST [	TMCT <scratch>	;HE'S DEAD, JIM
		JRST TMCVL1]
	TMCT <%1S>		;VOLID IS KNOWN
	JRST TMCVL1		;LOOP UNTIL ALL VOLIDS ARE DISPLAYED
; DRIVER FOR TMCT AND TMCTR MACROS
;  CX/ ADDRESS OF FORMATTING STRING

TMCT0:	HRLI CX,(POINT 7)	;MAKE BYTE POINTER TO SOURCE STRING
	MOVEM CX,TMCTSP		;SAVE POINTER
	SAVET			;ALL AC'S PRESERVED (EXCEPT 15,16)
	TRVAR <TMCTAR,<TMCTAC,4>>
	DMOVEM T1,TMCTAC	;SAVE T1-T4
	DMOVEM T3,2+TMCTAC
TMCT1:	ILDB T1,TMCTSP		;GET NEXT CHARACTER FROM STRING
	JUMPE T1,TMC1		;END OF STRING
	CAIE T1,"%"		;TRIGGER CHARACTER?
	JRST [	IDPB T1,TMCPTR	;NO, JUST COPY IT
		JRST TMCT1]	;LOOP THRU STRING
	TXZ F,ARGF		;SAY NO ARGUMENT (YET)
	SETZM TMCTAR		;ZERO ARGUMENT ACCUMULATOR
TMCT2:	ILDB T1,TMCTSP		;GET NEXT CHARACTER
	CAIG T1,"9"		;NUMERIC?
	CAIGE T1,"0"
	JRST TMCT3		;NO
	SUBI T1,"0"		;YES, CONVERT ASCII TO INTEGER
	MOVE T2,TMCTAR		;GET CURRENT ACCUMULATOR
	IMULI T2,12		;DECIMAL SHIFT
	ADD T2,T1		;ADD IN NEXT DIGIT
	MOVEM T2,TMCTAR		;STORE UPDATED ACCUMULATOR
	TXO F,ARGF		;SET ARG-SEEN
	JRST TMCT2		;CONTINUE ARGUMENT SCAN

TMCT3:	MOVSI T2,-TMCDTL	;GET AOBJN POINTER TO DISPATCH TABLE
TMCT4:	HLRZ T3,TMCDT(T2)	;GET CHARACTER FROM DISPATCH TABLE
	CAME T1,T3		;MATCH FUNCTION CHARACTER?
	JRST [	AOBJN T2,TMCT4	;NO, CONTINUE SCAN
		JRST TMC1]	;NO MATCH??? ERROR IN FORMAT STRING
	HRRZ T1,TMCDT(T2)	;FOUND IT, GET ROUTINE ADDRESS
	CALL (T1)		;CALL HANDLER
	MOVE T1,TMCPTR		;GET BUFFER POINTER
	SETZ T2,
	IDPB T2,T1		;PUT A NULL AT THE END OF TEXT
	SUBI T1,TMCMSG-1	;COMPUTE TEXT SIZE IN WORDS
	HRRZM T1,TMCWDS		;STORE IT FOR CALLERS
	JRST TMCT1		;FUNCTION DONE, CONTINUE STRING SCAN

; TMCT DISPATCH TABLE

TMCDT:	"A",,%A		;ASCIZ STRING, ARG = AC CONTAINING ADDRESS
	"C",,%C		;ADVANCE TO COLUMN, ARG = COLUMN#
	"D",,%D		;DECIMAL #, ARG = AC CONTAINING #
	"I",,%I		;INITIALIZE TMC FORMATTED STRING
	"J",,%J		;JSYS ERROR MESSAGE, ARG = AC CONT. ERROR CODE
			;NO ARG MEANS USE MOST RECENT MOUNTR ERROR
	"K",,%K		;TYPE DRIVE NUMBERS, ARG = CKU NUMBER
	"M",,%M		;DISPLAY "MTAn:" (NEEDS MTA AC)
	"N",,%N		;DISPLAY "MTn:" (NEEDS MT AC)
	"O",,%O		;OCTAL NUMBER, ARG = AC CONTAINING #
	"S",,%S		;SIXBIT, ARG = AC CONTAINING SIXBIT VALUE
	"U",,%U		;USER NAME, ARG = AC CONTAINING USER#
			;NO ARG MEANS DO NAME/JOB/LINE FOR CURRENT RSB
	"V",,%V		;DEVICE NAME, ARG = AC CONTAINING DESIGNATOR
	"Y",,%Y		;ARG = AC CONTAINING NON-0 FOR Yes OR 0 FOR No
	"%",,%%		;PERCENT SIGN
	"_",,%CRLF	;CRLF
TMCDTL==.-TMCDT		;NUMBER OF ENTRIES IN TABLE

GETREG:	JXE F,ARGF,[ADJSP P,-1	;IF NO ARG PRESENT
		RET]		;RETURN TO CALLER'S CALLER
	MOVE T1,TMCTAR		;GET ARGUMENT
	CAIG T1,T4		;IN T1-T4?
	ADDI T1,-1+TMCTAC	;YES, ADD OFFSET TO STORED AC'S
	MOVE T1,(T1)		;GET CONTENTS OF REGISTER
	RET

%CRLF:	SKIPA T1,[[ASCIZ/
/]]
%A:	CALL GETREG		;GET ADDRESS OF TEXT
%A0:	HRLI T1,(POINT 7)	;MAKE STRING POINTER
%A1:	ILDB T2,T1		;GET NEXT CHARACTER FROM STRING
	JUMPE T2,R		;EXIT IF END OF STRING
	IDPB T2,TMCPTR		;COPY CHARACTER TO OUTPUT STRING
	JRST %A1		;LOOP THRU INPUT

%C:	MOVE T3,[POINT 7,TMCMSG] ;GET POINTER TO EXISTING MESSAGE
TMCC2:	SETZ T2,		;# OF CHARACTERS SINCE LAST LINEFEED
TMCC1:	ILDB T4,T3		;GET NEXT CHARACTER FROM MESSAGE
	CAIN T4,.CHLFD		;IS IT A LINEFEED?
	JRST TMCC2		;YES, RESET COUNTER AND CONTINUE SCAN
	SKIPE T4		;END OF STRING?
	AOJA T2,TMCC1		;NO, COUNT CHARACTER AND LOOP
	MOVE T1,TMCTAR		;GET DESIRED COLUMN POSITION
	SUB T1,T2		;GET # OF SPACES PLUS 1
	MOVEI T2," "		;GET SPACE
TMCC3:	SOJLE T1,TMC1		;EXIT IF NO MORE SPACES NEEDED
	IDPB T2,TMCPTR		;INSERT A SPACE
	JRST TMCC3		;LOOP UNTIL POSITION IS REACHED

%D:	CALL GETREG		;GET NUMBER
	MOVEI T3,12		;BASE 10
	JRST %DO		;MERGE
%O:	CALL GETREG		;GET NUMBER
	MOVEI T3,10		;BASE 8
%DO:	MOVE T2,T1		;# TO T2 FOR NOUT
	MOVE T1,TMCPTR		;GET DESTINATION STRING POINTER
	NOUT			;OUTPUT NUMBER
	 SKIPA
	MOVEM T1,TMCPTR		;STORE UPDATED POINTER
	RET

%I:	MOVE T1,[POINT 7,TMCMSG] ;GET PTR TO TEXT STRING
	MOVEM T1,TMCPTR		;INITIALIZE IT
	RET

%J:	MOVEI T1,-1		;ASSUME NO ARGUMENT
	TXNE F,ARGF		;ARG PRESENT?
	CALL GETREG		;YES, GET ERROR CODE FROM AC
	MOVE T2,T1		;CODE TO T2 FOR ERSTR
	HRLI T2,.FHSLF		;FORK HANDLE ,, ERROR CODE
	MOVE T1,TMCPTR		;DESTINATION STRING POINTER
	SETZ T3,		;NO LIMIT ON LENGTH
	ERSTR			;GET ERROR STRING
	 JFCL
	 JFCL
	MOVEM T1,TMCPTR		;STORE UPDATED POINTER
	RET

%K:	CALL GETREG		;READ ARGUMENT
	MOVE T4,T1		;REMEMBER IT
	MOVE T1,TMCPTR		;GET BYTE POINTER
	HRROI T2,[ASCIZ/Channel /]	;TEXT
	SETZ T3,		;ALL OF IT
	SOUT			;TYPE IT
	LOAD T2,DOP%C2,T4	;GET CHANNEL
	MOVEI T3,^D8		;OCTAL
	NOUT			;TYPE IT
	 JFCL
	TXC T4,DOP%K2		;GET READY
	TXCN T4,DOP%K2		;ANY CONTROLLER TO TYPE?
	JRST %K2		;NO, SKIP ON
	HRROI T2,[ASCIZ/ Controller /]	;YES
	SETZ T3,		;ASCIZ
	SOUT			;TYPE THIS
	LOAD T2,DOP%K2,T4	;GET CONTROLLER NUMBER
	MOVEI T3,^D8		;OCTAL
	NOUT			;TYPE IT
	 JFCL
%K2:	HRROI T2,[ASCIZ/ Drive /]	;MORE TEXT
	SETZ T3,		;ASCIZ
	SOUT			;TYPE IT
	LOAD T2,DOP%U2,T4	;GET DRIVE NUMBER
	MOVEI T3,^D8		;OCTAL AGAIN
	NOUT			;TYPE IT
	 JFCL
	MOVEM T1,TMCPTR		;REMEMBER NEW POINTER
	RET			;DONE


%M:	CALL GMTADD		;GET MTA DEVICE DESIGNATOR
	SKIPA
%N:	CALL GMTDD		;GET MT DEVICE DESIGNATOR
%V1:	MOVE T2,T1		;DESIGNATOR TO T2 FOR DEVST
	MOVE T1,TMCPTR		;GET DEST STRG PTR
	DEVST			;GET DEVICE NAME
	 CALL STOP
	MOVEM T1,TMCPTR		;STORE UPDATED POINTER
	MOVEI T1,":"
	IDPB T1,TMCPTR		;PUT A COLON AT THE END
	RET

%S:	CALL GETREG		;GET SIXBIT QUANTITY
%S1:	SETZ T2,		;CLEAR T2 FOR SHIFT
	ROTC T1,6		;GET NEXT CHARACTER IN T2
	ADDI T2,40		;CONVERT TO ASCII
	IDPB T2,TMCPTR		;STORE IT
	JUMPN T1,%S1		;LOOP IF MORE NON-BLANKS REMAINING
	RET

%U:	JXE F,ARGF,%UNA		;JUMP IF NO ARGUMENT
	CALL GETREG		;GET USER#
	MOVE T2,T1		;USER# TO T2 FOR DIRST
	MOVE T1,TMCPTR		;GET DEST POINTER
	DIRST			;GET USER NAME
	 SKIPA
	MOVEM T1,TMCPTR		;STORE UPDATED POINTER
	RET

%UNA:	PUSH P,TMCTSP		;SAVE CURRENT INPUT POINTER
	TMCT <User>
	CAIN RSB,MTNAV		;RSB AVAILABLE?
	JRST %U1		;NO, THAT'S ALL
	LOAD T1,RSBJNO		;GET JOB #
	MOVE T2,RSBUNO(RSB)	;GET USER #
	TMCT < %2U, Job %1D>
	MOVSS T1		;MOVE JOB # TO LEFT HALF
	HRRI T1,.JOBTT		;GET TABLE # IN RIGHT HALF
	GETAB			;GET LINE # FROM JOBTTY TABLE
	 CALL STOP
	HLRES T1		;DETACHED?
	JUMPE T1,%U1		;IF ZERO, USER PROBABLY LOGGED OUT
	JUMPL T1,[TMCT <, DETACHED> ;IF DETACHED, SAY SO
		JRST %U1]
	TMCT <, Terminal %1O>	;SHOW LINE # AND RETURN
%U1:	POP P,TMCTSP		;RESTORE PREVIOUS STRING POINTER
	RET

%V:	CALL GETREG		;GET DESIGNATOR IN T1
	JRST %V1		;GO DISPLAY IT

%Y:	CALL GETREG		;GET ARG IN T1
	JUMPN T1,[JSP T1,%A0	;NON-ZERO, SAY YES
		ASCIZ/Yes/]
	JSP T1,%A0		;ZERO, SAY NO
	ASCIZ/No/

%%:	MOVEI T1,"%"
	IDPB T1,TMCPTR		;STORE PERCENT CHARACTER
	RET
SUBTTL QUASAR INTERFACE

; GETRSB - ALLOCATE A REQUEST STATUS BLOCK
; RETURNS +1: RSB ALLOCATED, BUT IT'S THE LAST ONE
;	  +2: RSB ALLOCATED, MORE FREE RSB'S LEFT
;  RSB/ ADDR OF REQUEST STATUS BLOCK

GETRSB:	MOVEI T1,IRBQDB		;POINT TO INACTIVE RSB QUEUE
	CALL QMDQH		;DEQUEUE HEAD OF QUEUE
	 CALL STOP		;QUEUE EMPTY, PROGRAM LOGIC ERROR
	MOVEI RSB,-RSBLNK(T2)	;LOAD UP RSB AC
	MOVS T1,RSB		;BLT SOURCE
	HRRI T1,1(RSB)		;BLT DESTINATION
	SETZM (RSB)		;CLEAR 1ST WORD OF RSB
	BLT T1,RSBSIZ-1(RSB)	;CLEAR THE REST OF THE RSB
	MOVEI T2,RSBLNK(RSB)	;GET ADDRESS OF RSB LINKAGE WORD
	MOVEI T1,ARBQDB
	CALL QMQT		;QUEUE TO TAIL OF ACTIVE QUEUE
	SKIPN IRBQDB		;WAS THIS THE LAST FREE RSB?
	RET			;YES, RETURN +1
	RETSKP


; GETRSI - INITIALIZE FREE RSB POOL FOR GETRSB
; RETURNS +1: ALWAYS

GETRSI:	SAVEQ
	MOVEI Q1,RSB0		;GET ADDRESS OF RSB POOL
	MOVEI Q2,MAXMRQ+1	;# OF RSBS IN POOL
GTRSI1:	MOVEI T1,IRBQDB		;GET QDB ADDRESS
	MOVEI T2,RSBLNK(Q1)	;GET ADDRESS OF RSB LINKAGE
	CALL QMQT		;QUEUE RSB TO TAIL OF FREE QUEUE
	ADDI Q1,RSBSIZ		;POINT Q1 AT NEXT RSB
	SOJG Q2,GTRSI1		;LOOP THRU ALL RSBS
	RET

; GORSB - GET RSB FOR FUNCTION REQUESTED VIA OPR COMMAND
;  T1/ REQUEST TYPE CODE
; RETURNS +1: RSB POOL EMPTY, ACK MESSAGE SENT TO OPERATOR
;	  +2: SUCCESS, RSB/ ADDR OF REQUEST STATUS BLOCK

GORSB:	STAKT
	CALL GETRSB		;TRY TO ASSIGN RSB
	 TDZA T4,T4		;SET SHORTAGE FLAG
	MOVEI T4,1		;SET NO SHORTAGE
	MOVE T1,CT1
	STOR T1,RSBTYP		;SET TYPE IN RSB
	MOVX T1,R%OPR+R%PRIV	;SET FROM-OPERATOR AND PRIVILEGED
	IORM T1,RSBIFL(RSB)
	JUMPN T4,RSKP		;TAKE +2 IF NO FREESPACE SHORTAGE
	ABTREQ (ABRTNR)		;SHORTAGE, ABORT REQUEST
	CALL PRQABT		;PUT RSB BACK ON INACTIVE QUEUE
	MOVEI T3,[ASCIZ/Space exhausted, try later/]
	CALLRET BTACK		;TELL OPERATOR ABOUT BUMMER
; MATR - PROCESS USER REQUEST FOR ATTRIBUTES OF MOUNTED DEVICE
;	 (CURRENTLY VALID ONLY FOR TAPES)
;  RBUF/ ATTRIBUTE-REQUEST MESSAGE
;  T1/ SIZE OF MESSAGE (WORDS)
; RETURNS +1: ALWAYS

MATR:	SAVEQ
	SAVEAC <MT,RSB>
	CAIE T1,.MATQS		;CHECK SIZE
	JRST [	CALLRET BADQM]	;NOT WHAT IT SHOULD BE
	MOVE T1,RBUF+.MATDV	;GET DEVICE DESIGNATOR
	CALL DDMT		;GET MT STATUS BLOCK ADDRESS
	 TDZA RSB,RSB		;BAD MT DEVICE, FORCE ERROR RETURN
	LOAD RSB,MTRSB		;GET RSB ADDRESS
	SKIPE RSB
	CAIN RSB,MTNAV
	JRST [	TMCT <%IInvalid device> ;BAD MT OR NO REQ ASSOCIATED
		MOVE T1,RBUF+.MATPD ;GET USER'S PID
		MOVX T2,MF.FAT	;GET FATAL-ERROR FLAG
		MOVE T3,RBUF+.MSCOD ;GET USER'S ACK CODE
		CALLRET TXTMSG]	;RESPOND TO USER WITH GLX TEXT MESSAGE

; CONSTRUCT RESPONSE, BUILDING-BLOCK STYLE

	CALL PBINIT		;INITIALIZE BUILDING-BLOCK STRUCTURE
	MOVE Q1,[2,,.MATDD]	;CONSTRUCT DEVICE-DESIGNATOR BLOCK
	MOVE Q2,RBUF+.MATDV
	MOVEI T1,Q1		;GET ADDR OF SOURCE BLOCK
	CALL PBBLK		;INSTALL IT
	HRRI Q1,.TMSET		;GET SIZE AND TYPE FOR SETNAME
	MOVE Q2,RSBSSN(RSB)	;GET SETNAME
	MOVEI T1,Q1		;GET ADDR OF SOURCE BLOCK
	CALL PBBLK		;INSTALL IT
	CALL VQCNT		;GET # OF VOLIDS
	MOVSI Q1,1(T1)		;BLOCK LENGTH = # OF VOLIDS + 1
	HRRI Q1,.TMVOL		;GET BLOCK TYPE
	MOVEI T1,Q1		;GET ADDR OF SOURCE BLOCK
	HRRZ Q2,PBBPT		;GET ADDRESS OF DESTINATION BLK HEADER
	CALL PBBLK		;INSTALL IT
	HLRZS Q1		;GET # OF VOLIDS + 1
MATR3:	SOJG Q1,[AOBJN Q2,	;BUMP INDICES (NEVER JUMPS)
		HLRZ T1,Q2	;GET VOLID INDEX
		CALL VQGET	;GET VOLID
		 JFCL		;SHOULD NEVER FAIL
		MOVEM T1,(Q2)	;STORE VOLID INTO MESSAGE
		JRST MATR3]	;LOOP THRU ALL VOLIDS
	MOVE T1,PBBPT		;MESSAGE IS COMPLETE, GET HIGH ADDRESS
	SUBI T1,TBUF		;COMPUTE LENGTH OF MESSAGE
	MOVSS T1		;TO LEFT HALF
	HRRI T1,.QOMAR		;GET MESSAGE CODE
	SETZ T2,		;NO FLAGS
MATR2:	MOVE T3,RBUF+.MSCOD	;GET ACK CODE FOR USER
	CALL GALHDR		;BUILD GALAXY HEADER IN MESSAGE
	MOVE T1,RBUF+.MATPD	;GET USER'S PID
	CALLRET TRANU		;SEND MESSAGE TO USER
; QMNT - PROCESS USER MOUNT REQUEST MESSAGE FROM QUASAR
;  RBUF/ IPCF MOUNT MESSAGE
;  T1/ SIZE OF MESSAGE (WORDS)
; RETURNS +1: ALWAYS

QMNT:	SAVEQ
	CAIE T1,1000		;DID I GET A PAGE OF DATA?
	JRST [	CALLRET BADQM]	;NO, QUASAR BLEW IT

; GET RSB AND COPY USER-DESCRIPTOR INFORMATION INTO IT

	SETZ Q2,		;ASSUME NO PROBLEMS WITH RSB POOL
	CALL GETRSB		;ALLOCATE STATUS BLOCK FOR THIS REQUEST
	 SETO Q2,		;FREE RSB POOL IS NOW EMPTY
	MOVE T1,RBUF+.MMNAM
	MOVEM T1,RSBRNM(RSB)	;MOVE REQUEST NAME TO RSB
	MOVE T1,RBUF+.MMITN
	MOVEM T1,RSBITN(RSB)	;MOVE QUASAR INTERNAL TASK # TO RSB
	MOVE T1,RBUF+.MMUCD
	MOVEM T1,RSBCOD(RSB)	;MOVE USER'S ACK CODE TO RSB
	MOVE T1,RBUF+.MMPID
	MOVEM T1,RSBPID(RSB)	;MOVE USER'S PID TO RSB
	LOAD T1,MD.PJB,RBUF+.MMCAP
	STOR T1,RSBJNO		;MOVE USER'S JOB # TO RSB
	MOVE T1,RBUF+.MMUNO
	MOVEM T1,RSBUNO(RSB)	;MOVE USER'S USER # TO RSB
	MOVX T1,MD.PWH+MD.POP
	MOVX T2,R%PRIV
	TDNE T1,RBUF+.MMCAP	;DOES USER HAVE WHEEL OR OPERATOR?
	IORM T2,RSBIFL(RSB)	;YES, MARK HIM AS PRIVILEGED
	MOVSI T1,RBUF+.MMACT	;BLT SOURCE
	HRRI T1,RSBACT(RSB)	;BLT DESTINATION
	BLT T1,RSBACT+7(RSB)	;MOVE USER'S ACCOUNT STRING TO RSB

; IDENTIFY REQUEST TYPE AND DISPATCH TO THE APPROPRIATE PROCESSOR

	JUMPN Q2,[ABTREQ (MREQ31) ;ABORT IF RSB'S IN SHORT SUPPLY
		TXZ F,ABORTF	;CLEAR ABORTED-REQUESTS-PRESENT
		CALLRET PRQABT]	;MAKE SURE AT LEAST 1 FREE RSB IS LEFT
	MOVE T1,RBUF+.MMARC	;GET ENTRY COUNT
	CAIE T1,1		;IS IT 1?
	JRST MSERR		;NO, FORMAT ERROR
	MOVEI T2,RBUF+.MMHSZ	;GET ADDRESS OF FIRST ENTRY
	MOVE T3,RBUF+.MMUMS	;GET SIZE OF USER IPCF MESSAGE
	SUBI T3,.MMHSZ		;COMPUTE SIZE OF MOUNT-ENTRY REGION
	CALL CKBSTR		;CHECK BUILDING-BLOCK STRUCTURE
MSERR:	 JRST [	ABTRET (MREQ13)] ;STRUCTURAL ERROR IN MOUNT MESSAGE
	MOVEI T1,RBUF+.MMHSZ	;GET ADDRESS OF FIRST ENTRY
	LOAD T2,AR.TYP,(T1)	;GET TYPE OF ENTRY
	STOR T2,RSBTYP		;STORE REQUEST TYPE IN RSB
	CAIN T2,.MNTTP		;IS IT A USER TAPE MOUNT?
	JRST [	CALLRET UTM]	;YES, GO PROCESS IT
	CAIN T2,.MNTST		;USER STRUCTURE MOUNT?
	JRST [	CALLRET USM]	;YES, GO PROCESS IT
	CAIN T2,.DSMST		;DISMOUNT STRUCTURE?
	JRST [	CALLRET USD]	;YES
NOSHIP,<
	CAIN T2,.MNTDT		;DECTAPE MOUNT?
	JRST [	CALLRET UDTM]	;YES
>;NOSHIP
	ABTRET (MREQ21)		;I CAN'T HANDLE ANYTHING ELSE
; QSRINI - ESTABLISH IPCF RAPPORT WITH QUASAR
; RETURNS +1: ALWAYS

QSRINI:	STKVAR <TSTFLG>		;FLAG USED ONLY FOR DEBUGGING
	SETOM TSTFLG		;INITIALIZE FLAG
QSRIN1:	MOVEI T1,.SPQSR
	CALL GSYSPD		;GET QUASAR'S PID FROM SYSTEM PID TABLE
	 JRST [	AOSN TSTFLG	;HAVE WE BEEN HERE BEFORE?
		CALL TSTWAT	;NO, INFORM USER WE ARE WAITING
		MOVEI T1,^D5000	;NOT THERE YET
		DISMS		;WAIT 5 SECONDS
		JRST QSRIN1]	; AND TRY AGAIN
	MOVEM T1,APPID+.APQSR	;STUFF PID IN A/P TABLE

; BUILD AND TRANSMIT HELLO MESSAGE TO QUASAR

	MOVE T1,[HEL.SZ,,.QOHEL] ;MESSAGE LENGTH ,, MESSAGE TYPE
	SETZB T2,T3		;NO FLAGS, NO ACK CODE
	CALL GALHDR		;CONSTRUCT GALAXY HEADER IN TBUF
	MOVE T1,[SIXBIT/MOUNTR/]
	MOVEM T1,TBUF+HEL.NM	;MY NAME
	MOVX T1,FLD(%%.QSR,HEFVER)
	MOVEM T1,TBUF+HEL.FL	;QSRMAC VERSION #
	MOVX T1,FLD(1,HENNOT)+FLD(HENMAX,HENMAX)
	MOVEM T1,TBUF+HEL.NO	;# OF OBJ TYPES, MAX # OF JOBS
	MOVX T1,.OTMNT
	MOVEM T1,TBUF+HEL.OB	;I HANDLE MAGTAPE MOUNT REQUESTS

	MOVEI T1,.APQSR		;GOING TO QUASAR
	CALL TRANG		;TRANSMIT MESSAGE
	RET
; QSRMRC - DISPATCH IPCF MESSAGES FROM QUASAR TO APPROPRIATE ROUTINES
;  MRPDB, RBUF/ PDB AND MESSAGE
; RETURNS +1: ALWAYS

QSRMRC:	SAVEQ
	CALL CKGHDR		;CHECK OUT GALAXY HEADER
	 JRST [	CALLRET BADQM]	;BAD HEADER

; T1/ MESSAGE LENGTH (WORDS)   T2/ MESSAGE TYPE

	MOVSI T4,-QDTABL	;GET AOBJN POINTER
QSRMR1:	HLRZ T3,QDTAB(T4)	;GET MESSAGE TYPE FROM TABLE
	CAME T2,T3		;DOES IT MATCH THE MESSAGE I JUST GOT?
	JRST [	AOBJN T4,QSRMR1	;NO, LOOP
		CALLRET BADQM]	;DOESN'T MATCH ANYTHING IN THE TABLE
	HRRZ T2,QDTAB(T4)	;GET ADDRESS OF DISPATCH WORD
	MOVE T2,(T2)		;GET DISPATCH WORD
	TLZE T2,1		;HAVE TO CALL ORNBCK?
	JRST [	DMOVE Q1,T1	;YES, SAVE T1 & T2
		CALL ORNBCK
		 JRST [	CALLRET BADQM] ;ERROR, REPORT IT AND RETURN
		DMOVE T1,Q1	;COPY 'EM BACK
		JRST .+1]
	CALLRET (T2)		;DISPATCH TO HANDLER, T1/ MSG LENGTH

; DISPATCH TABLE FOR MESSAGE TYPES RECEIVED FROM QUASAR

; 1 IN LEFT HALF OF LITERAL MEANS ORNBCK MUST BE CALLED BEFORE DISPATCH

QDTAB:	.QOMNT,,[0,,QMNT]	;MOUNT REQUEST FROM USER
	.QOMTA,,[0,,TCAN]	;TAPE MOUNT CANCEL
	.QOMAT,,[0,,MATR]	;ATTRIBUTE REQUEST FROM USER
	.ODDMT,,[1,,KDMT]	;OPR COMMAND - DELETE MOUNT-REQUEST
	.ODENA,,[1,,KENA]	;OPR COMMAND - ENABLE
	.ODDIS,,[1,,KDIS]	;OPR COMMAND - DISABLE
	.ODDSM,,[1,,KDSM]	;OPR COMMAND - DISMOUNT
	.ODSDK,,[1,,KSDK]	;OPR COMMAND - SET DISK-DRIVE
	.ODIDN,,[1,,KIDN]	;OPR COMMAND - IDENTIFY
	.ODMTS,,[1,,KMSS]	;OPR COMMAND - MOUNT
	.ODSTP,,[1,,KSTP]	;OPR COMMAND - SET TAPE-DRIVE
	.ODSHD,,[1,,KSHD]	;OPR COMMAND - SHOW STATUS DISK
	.ODSHT,,[1,,KSHT]	;OPR COMMAND - SHOW STATUS TAPE
	.ODSST,,[1,,KSST]	;OPR COMMAND - SET STRUCTURE
	.ODSWI,,[1,,KSWI]	;OPR COMMAND - SWITCH
	.ODUNL,,[1,,KUNL]	;OPR COMMAND - UNLOAD
QDTABL==.-QDTAB
; REQRSB - TRANSLATE REQUEST NUMBER INTO RSB ADDRESS
;  T1/ REQUEST NUMBER
; RETURNS +1: UNKNOWN REQUEST #, T1/ REQUEST #
;	  +2: SUCCESS, RSB/ RSB ADDR,  T1/ REQUEST #

REQRSB:	QSCANI ARBQDB		;SET UP TO SCAN RSB QUEUE
	SAVET			;PRESERVE T1 AS ADVERTISED
REQR1:	CALL QMSCAN		;GET NEXT RSB
	 RET			;NONE LEFT, REQUEST # UNKNOWN
	MOVEI RSB,-RSBLNK(T2)	;LOAD RSB AC WITH ADDRESS OF RSB
	MOVE T1,CT1		;GET REQ# FROM RSB
	CAME T1,RSBITN(RSB)	;DOES IT MATCH WHAT THE CALLER GAVE?
	JRST REQR1		;NO, CONTINUE SCAN
	RETSKP			;YES, SUCCESS


; RLSMSG - SEND RELEASE MESSAGE TO QUASAR
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

RLSMSG:	MOVE T1,RSBITN(RSB)	;GET ITN
	MOVEM T1,TBUF+REL.IT	;STORE IN MESSAGE
	MOVE T1,[REL.SZ,,.QOMTR] ;GET GALAXY HEADER
	SETZB T2,T3
	CALL GALHDR		;BUILD HEADER
	MOVEI T1,.APQSR
	CALLRET TRANG		;SEND RELEASE MESSAGE TO QUASAR
; TCAN - PROCESS USER TAPE REQUEST CANCEL MESSAGE FROM QUASAR
;  RBUF/ IPCF TAPE MOUNT CANCEL MESSAGE
;  T1/ SIZE OF MESSAGE (WORDS)
; RETURNS +1: ALWAYS

TCAN:	SAVEQ
	MOVE T3,T1		;COPY SIZE OF MESSAGE
	SUBI T3,.OHDRS		;GET SIZE OF BLOCK REGION OF MESSAGE
	JUMPLE T3,TCANQE	;NO BLOCK REGION, ERROR BY QUASAR
	MOVE T1,RBUF+.OARGC	;GET # OF BLOCKS
	MOVEI T2,RBUF+.OHDRS	;GET ADDRESS OF 1ST BLOCK
	CALL CKBSTR		;CHECK BLOCK STRUCTURE
TCANQE:	 JRST [	CALLRET BADQM]	;BAD STRUCTURE, QUASAR GOOFED
	DMOVE T1,[EXP RBUF+.OARGC,RBUF+.OHDRS]
	MOVEI T3,.MTPID		;GET TYPE OF BLOCK BEING SOUGHT
	CALL BLKFND		;LOOK UP USER'S PID
	 JRST TCANQE		;PID BLOCK NOT THERE
	JUMPE T2,TCANQE		;MAKE SURE THERE'S ROOM FOR A PID
	MOVE Q2,(T1)		;GET PID SO I CAN REPLY TO THE USER
	DMOVE T1,[EXP RBUF+.OARGC,RBUF+.OHDRS]
	MOVEI T3,.MTITN		;GET BLOCK TYPE
	CALL BLKFND		;LOOK UP ITN LIST
	 JRST TCANQE		;NOT THERE
	SETZ Q1,		;CLEAR COUNTER OF CANCELED REQUESTS
	JUMPE T2,TCAN2		;NO SCAN IF NOTHING TO CANCEL
	MOVN Q3,T2		;GET NEGATIVE NUMBER OF ITN'S
	MOVSS Q3		;OVER TO LEFT HALF FOR AOBJN
	HRR Q3,T1		;MAKE AOBJN POINTER TO ITN LIST

; LOOP THROUGH ITN LIST, TRYING TO CANCEL EACH ONE

TCAN1:	MOVE T1,(Q3)		;GET AN ITN
	CALL TCITN		;TRY TO CANCEL IT
	 SKIPA			;CAN'T CANCEL
	AOS Q1			;COUNT CANCELED REQUEST
	AOBJN Q3,TCAN1		;LOOP
	; ..
	; ..

; BUILD TEXT REPLY TO CANCEL MESSAGE IN TMCMSG

TCAN2:	JUMPG Q1,[TMCT <%I%5D>	;AT LEAST 1 REQUEST CANCELED
		JRST TCAN3]
	TMCT <%INo>		;NO REQUESTS CANCELED
TCAN3:	TMCT < mount request>
	SOJN Q1,[TMCT <s>	;IF NOT 1 REQUEST, TACK ON AN "S"
		JRST .+1]
	TMCT < canceled>

; BUILD IPCF MESSAGE AND SEND IT TO THE CANCELER

	MOVE T1,Q2		;GET USER'S PID
	SETZ T2,		;NO FLAGS
	MOVE T3,RBUF+.MSCOD	;GET CANCELER'S ACK CODE
	CALLRET TXTMSG		;RESPOND TO CANCEL WITH GLX TEXT MESSAGE
; TCKP - SEND A STATUS UPDATE FOR A MOUNT REQUEST TO QUASAR
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

TCKP:	SAVEQ
	SAVEAC <MT,MTA>
	MOVE T1,RSBITN(RSB)
	MOVEM T1,TBUF+CHE.IT	;STORE ITN IN MESSAGE
	SETZM TBUF+CHE.FL	;SET NO SPECIAL FLAGS
	MOVEI Q1,TBUF+CHE.IN	;GET ADDR OF START OF CKPT INFO AREA

	LOAD Q2,RSBTYP		;GET REQUEST TYPE
	MOVEM Q2,.MTTYP(Q1)	;STORE IT
	CAIE Q2,.MNTTP		;TAPE REQUEST?
	CAIN Q2,.MNTDT		; OR DECTAPE REQUEST?
	SKIPA			;YES
	JRST TCKP0		;NO, SKIP VOLID STUFF

	CALL VQGCV		;GET VOLID OF CURRENT VOLUME IN T1
	SKIPN T1		;SCRATCH?
	MOVEI T1,%VOLSC		;YES, GET 1 TO DISPLAY "Scratch"
	LOAD T2,RSBSTE		;GET CURRENT STATE OF REQUEST
	CAIGE T2,.ERBAS		;ABORTED OR
	CAIN T2,RST.WV		; WAITING FOR VOLID LIST?
	MOVEI T1,%VOLBL		;YES, DON'T DISPLAY ANYTHING
	MOVEM T1,.MTVOL(Q1)	;STORE VOLID
TCKP0:

	CAIN T2,RST.AC		;REQUEST HAVE MTA OR DTA?
	JRST [	MOVE T1,RSBDTA(RSB) ;YES, ASSUME DECTAPE
		CAIN Q2,.MNTDT	;DECTAPE?
		JRST TCKP1	;YES, T1/ DECTAPE DEVICE DESIGNATOR
		LOAD MT,RSBMT	;MAGTAPE REQUEST
		LOAD MTA,MTMTA	;LOAD MTA AC
		CALL GMTADD	;GET MTA DESIGNATOR IN T1
		JRST TCKP1]	;GO STORE IT
	MOVEI T1,%STAWT		;ASSUME WAITING FOR SOMETHING
	CAIL T2,.ERBAS		;ABORTED?
	MOVEI T1,%STAAB		;YES, SAY SO THEN
TCKP1:	MOVEM T1,.MTSTA(Q1)	;STORE STATE FIELD OF MESSAGE

	MOVE T1,[CHE.IN+EQCKSZ,,.QOMTC] ;GET SIZE AND MESSAGE TYPE
	SETZB T2,T3		;NO FLAGS OR ACK CODE
	CALL GALHDR		;BUILD GALAXY HEADER
	MOVEI 1,.APQSR
	CALLRET TRANG		;SEND CHECKPOINT MESSAGE TO QUASAR
; TXTMSG - SEND GALAXY IPCF TEXT-MESSAGE
;  T1/ RECEIVER'S PID
;  T2/ FLAGS FOR GALAXY MESSAGE HEADER
;  T3/ ACK CODE FOR MESSAGE HEADER
;  TMCMSG/ ASCIZ MESSAGE TO BE SENT
; RETURNS +1: ALWAYS

TXTMSG:	STAKT
	AOS TBUF+.OARGC		;SET ARGUMENT COUNT TO 1
	MOVE T1,TMCWDS		;GET LENGTH OF MESSAGE (WORDS)
	MOVSI T2,1(T1)		;CONSTRUCT
	HRRI T2,.CMTXT		; ARGUMENT HEADER WORD
	MOVEM T2,TBUF+.OHDRS	;STORE ARG HEADER
	MOVE T2,[TMCMSG,,TBUF+.OHDRS+1] ;GET BLT SOURCE,,DESTINATION
	BLT T2,TBUF+.OHDRS(T1)	;COPY TEXT INTO IPCF MESSAGE
	MOVSI T1,.OHDRS+1(T1)	;GET SIZE OF ENTIRE MESSAGE
	HRRI T1,MT.TXT		;BUILD SIZE,,TYPE
	MOVE T2,CT2		;GET FLAGS
	MOVE T3,CT3		;GET ACK CODE
	CALL GALHDR		;BUILD GALAXY HEADER FOR MESSAGE
	MOVE T1,CT1		;GET RECEIVER'S PID
	CALLRET TRANU		;TRANSMIT MESSAGE AND RETURN
SUBTTL STRUCTURE ROUTINES

;BSRALI - GET STRUCTURE ALIAS FROM QUASAR MSSG INTO RSB

;ACCEPTS: T1/ ADDRESS OF SUBENTRY COUNT WORD
;	  T2/ ADDRESS OF FIRST SUBENTRY
;	  RSB/ ADDR OF REQUEST STATUS BLOCK

;RETURNS: +1,	FAILURE
;	  +2,	SUCCESS

BSRALI: MOVEI T3,.SMALI		;GET STRUCTURE ALIAS CODE
	CALL BLKFND		;LOOKUP ALIAS
	 JRST [	ABTRET(MREQ22)]	;ERROR, CAN'T MOUNT STR IF NO ALIAS
	JUMPE T2,[ABTRET(MREQ22)] ;TREAT ZERO-LENGTH NAME LIKE NO NAME
	MOVE T1,(T1)		;GET ALIAS IN T1
	MOVEM T1,RSBSTA(RSB)	;STORE ALIAS IN RSB
	RETSKP


;BSRNAM - GET STRUCTURE NAME FROM QUASAR MSSG INTO RSB

;ACCEPTS: T1/ ADDRESS OF SUBENTRY COUNT WORD
;	  T2/ ADDRESS OF FIRST SUBENTRY
;	  RSB/ ADDR OF REQUEST STATUS BLOCK

;RETURNS: +1,	FAILURE
;	  +2,	SUCCESS

BSRNAM:	MOVEI T3,.SMNAM		;GET STRUCTURE NAME CODE
	CALL BLKFND		;LOOKUP NAME
	 JRST BSRNA1		;NAME NOT GIVEN
	JUMPE T2,BSRNA1		;TREAT ZERO-LENGTH NAME AS NO NAME
	MOVE T1,(T1)		;GET NAME IN T1
	CAME T1,RSBSTA(RSB)	;IS NAME SAME AS ALIAS
	JRST [	MOVX T2,R%PRIV	;NO, IS USER PRIVILEGED?
		TDNE T2,RSBIFL(RSB)
		JRST .+1	;YES, LET IT GO
		ABTRET (CAPX1)]	;NOT PRIVLEGED, ABORT REQUEST
	SKIPA
BSRNA1:	SETZ T1,		;STORE ZERO IF NO NAME MENTIONED
	MOVEM T1,RSBSTN(RSB)	;STORE NAME IN REQUEST BLOCK
	RETSKP
;THIS SECTION HANDLES COMMANDS, WHICH ARE READ FROM A SPECIAL FILE

;HERE'S THE "COMNDS" ROUTINE.  ANY PLACE THAT A DECISION MUST BE MADE
;WHICH DEPENDS ON COMMANDS THAT MIGHT BE IN THE COMMAND FILE, MUST CALL
;THIS ROUTINE BEFORE MAKING THE DECISION.
;(REMEMBER, SOMEONE MIGHT UPDATE THE COMMANDS FILE WHILE IS RUNNING)

COMNDS:	SAVEQ
	MOVX T1,GJ%OLD+GJ%SHT+GJ%ACC
	HRROI T2,COMNAM		;GET POINTER TO COMMANDS FILE NAME
	GTJFN			;GET HANDLE ON COMMANDS FILE
	 RET			;COULD NOT GET FILE
	MOVE T2,[70000,,OF%RD]	;BITS FOR OPENING FILE FOR READ
	MOVE T4,T1		;COPY JFN IN CASE OF FAILURE
	OPENF			;OPEN COMMANDS FILE FOR READING
	 JRST [	MOVE T1,T4	;GET JFN BACK
		RLJFN		;DUMP IT
		 JFCL
		JRST COMEO2]	;TYPE REASON AND GIVE UP
	MOVEM T1,COMJFN		;REMEMBER NEW HANDLE ON COMMANDS FILE
	GTAD			;GET CURRENT TIME AND DATE
	MOVE T4,T1		;T4 CONTAINS A NUMBER GUARANTEED DIFFERENT FROM FILE WRITE DATE
	MOVE T1,COMJFN		;GET HANDLE ON COMMANDS FILE
	MOVEI T2,T4		;WE'LL READ TIME INTO T4
	MOVEI T3,1		;ONLY ONE DATUM REQUESTED
	RFTAD			;GET LAST WRITE-TIME FOR COMMANDS FILE
	CAMN T4,STAMP		;DIFFERENT THAN LAST TIME WE CHECKED?
	JRST COMEO1		;NO, SO COMMANDS ARE UP TO DATE
	;...
;THERE'S A NEW COMMANDS FILE, SO CLEAR OLD COMMANDS STATUS AND READ
;NEW COMMANDS IN.
	MOVEM T4,STAMP		;REMEMBER NEW UPDATE STAMP
	SETZM STRTBL+1		;ZERO FIRST ENTRY OF STRUCTURE TABLE
	MOVE T1,[STRTBL+1,,STRTBL+2] ;TO CLEAR STRUCTURE TABLE FOR NEW
	BLT T1,STRTBL+STSIZ-1	; COMMANDS FILE
	MOVE T1,STRINI		;INITIALIZE STRTBL
	MOVEM T1,STRTBL
	MOVE T1,SSCINI		;INITIALIZE SSCTBL FOR TBADD, ALSO
	MOVEM T1,SSCNAM
COMND1:	CALL CREADI		;INITIALIZE FOR COMND JSYS
	MOVEI T1,COMTBL		;GET POINTER TO COMMANDS
	MOVEM T1,FDB+.CMDAT
	MOVX T1,CMKEY		;SPECIFY "KEYWORD"
	HRRI T1,[FLDDB.(.CMKEY,,COMDEF)] ;CHECK IF SETTING UP DEFAULTS
	CALL CREAD		;DO COMND JSYS
	HRRZ T2,(T2)		;GET ADDRESS OF COMMAND'S SUPPORT ROUTINE
	SKIPE T2		;SETTING DEFAULTS?
	JRST SETSTR		;NO, SET UP STR CHARACTERISTICS
	JRST SETDEF		;YES
;ROUTINE TO DO COMND JSYS.  IT RETURNS IFF A SUCCESFUL PARSE HAPPENS.
;CALL IT WITH THE VALUE FOR THE FIRST WORD OF THE FUNCTION BLOCK IN A.

CREAD:	MOVEM T1,FDB
	MOVEI T1,CSB
	MOVEI T2,FDB		;COMMAND STATE BLOCK AND FUNCTION BLOCK
	COMND			;READ COMMAND NAME
	 ERJMP COMEOF		;ERROR, HOPEFULLY END OF FILE
	TXNE T1,CM%NOP		;DID IT PARSE CORRECTLY?
	 JRST COMBAD		;NO, GIVE WARNING AND CONTINUE
	RET			;SUCCESFUL COMND JSYS, RETURN

;ROUTINE TO INITIALIZE POINTERS ETC. FOR COMND JSYS

CREADI:	SETZM FDB+.CMFNP
	SETZM FDB+.CMDAT
	SETZM FDB+.CMHLP
	SETZM FDB+.CMDEF	;CLEAR FUNCTION DESCRIPTOR BLOCK
	MOVX T1,CM%RAI		;RAISE INPUT
	MOVEM T1,CSB+.CMFLG	;SET UP REPARSE ADDRESS
	HRL T1,COMJFN		;INPUT FROM COMMAND FILE JFN
	HRRI T1,377777		;NO EDITING OUTPUT
	MOVEM T1,CSB+.CMIOJ
	HRROI T1,TMCMSG		;POINTER TO USER'S (FILE'S) INPUT
	MOVEM T1,CSB+.CMRTY	;CONTROL-R BUFFER IS REGULAR INPUT BUFFER
	MOVEM T1,CSB+.CMBFP
	MOVEM T1,CSB+.CMPTR	;POINTER TO NEXT FIELD TO BE PARSED
	MOVEI T1,5000		;GET LENGTH OF INPUT BUFFER
	MOVEM T1,CSB+.CMCNT
	SETZM CSB+.CMINC	;NO UNPARSED CHARACTERS YET
	HRROI T1,ATMBFR		;POINTER TO ATOM BUFFER
	MOVEM T1,CSB+.CMABP
	MOVEI T1,ATMSIZ*5	;LENGTH OF ATOM BUFFER
	MOVEM T1,CSB+.CMABC
	SETZM CSB+.CMGJB	;NO GTJFN BLOCK
	RET
; DDSADD - ADD A DISK COMING ON-LINE

;ACCEPTS: DSK/	NUMBER OF DISK
;RETURNS: +1,	ALWAYS

DDSADD:	CALL STRINF		; YES, STORE STRUCTURE INFORMATION
	LOAD T1,STRUNI,(STR)	;GET NUMBER OF DISKS IN STR
	LOAD T2,STRMCT,(STR)	;GET NUMBER OF DISKS MOUNTED IN STR
	CAME T1,T2		;ARE ALL DISK PACKS MOUNTED?
	RET			;NO, RETURN

;TRY TO MATCH STRUCTURE COMING ON-LINE TO USER REQUEST

	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB,DSK>
	CALL PRQPID		;CLEAN UP REQUEST QUEUE FIRST
	MOVE Q2,DSKFLG(DSK)	;GET DISK STATUS
	TXNE Q2,MS%MNT		;IS IT MOUNTED ALREADY?
	JRST [	CALLRET DDSMC0]	;YES, CHECK MOUNT QUEUES
DDSAD1:	CALL NSTRSB		;GET ADDRESS OF NEXT RSB
	 RET			;NONE LEFT
	LOAD T1,RSBSTE		;GET STATE OF REQUEST
	CAIE T1,RST.WM		;IS USER WAITING FOR STRUCTURE
	JRST DDSAD1		;NO, TRY NEXT REQUEST
	SKIPN T1,RSBSTN(RSB)	;GET STRUCTURE NAME IN REQUEST
	MOVE T1,RSBSTA(RSB)	;THERE IS NONE, GET ALIAS FOR NAME
	CAME T1,STRNAM(STR)	;IS IT SAME AS STRUCTURE COMING ON-LINE
	JRST DDSAD1		;NO, TRY NEXT REQUEST
	CALL STRMNT		;MOUNT THE STRUCTURE
	 RET			;ERROR IN MOUNTING STRUCTURE
	SETZ T1,		;CHECK MOUNT REQUESTS
	CALLRET DDSMCH		;STRUCTURE IS NOW READY FOR USERS. TELL THEM
; DDSMCH - MATCH USER REQUEST TO MOUNTS AND DISMOUNTS

;ACCEPTS: T1/	0=LOOK AT MOUNT REQUESTS
;		R%DSM=LOOK AT DISMOUNT REQUESTS
;	  QSB/ ADDRESS OF QUEUE SCAN BLOCK
;	  STR/ ADDRESS OF STRUCTURE BLOCK
;RETURNS:  +1,	ALWAYS

DDSMC0:	SAVEQ			;ALTERNATE ENTRY FOR MOUNT REQUESTS
	SETZ Q1,
	JRST DDSMC1

DDSMCH:	SAVEQ
	MOVE Q1,T1
	JUMPE Q1,DDSMC2		;GO TO DDSMC2 FOR MOUNT REQUESTS
DDSMC1:	CALL NSTRSB		;GET NEXT USER REQUEST
	 RET			;NONE LEFT
	LOAD T1,RSBSTE		;GET STATE OF REQUEST
	CAIE T1,RST.WM		;IS USER WAITING FOR STRUCTURE
	JRST DDSMC1		;NO, TRY NEXT REQUEST
	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	CAME T1,STRALI(STR)	;IS IT SAME AS THIS ONE
	JRST DDSMC1		;NO, TRY NEXT REQUEST
	SKIPN T1,RSBSTN(RSB)	;GET STRUCTURE NAME
	JRST DDSMC2		;NONE SPECIFIED. ALLOW THIS MOUNT
	CAME T1,STRNAM(STR)	;IS THIS THE SAME AS CURRENT STR
	JRST DDSMC1		;NO, GET NEXT REQUEST
DDSMC2:	MOVE T1,RSBIFL(RSB)	;GET INTERNAL FLAGS
	XOR T1,Q1		;ARE WE LOOKING AT RIGHT REQUEST TYPE
	TXNE T1,R%DSM
	JRST DDSMC1		;NO
	LOAD ACC,RSBACC		;GET ACC IF ANY ASSOCIATED.
	JUMPE ACC,DDSMC3	;NO ASSOCIATED ACC
	SETZRO RSBACC		;DELINK ACC AND RSB
	MOVEI T1,RSBSTA(RSB)	;POINT TO SIXBIT ALIAS
	MOVE T2,[POINT 7,MSTAL]	;ASCII GOES HERE
	CALL SIXSEV		;CONVERT ALIAS TO ASCII
	HRROI T1,MSTAL		;POINT TO ASCII ALIAS
	STDEV			;GET DEVICE DESIGNATOR
	 CALL STOP		;ERROR NO SUCH DEVICE?
	JRST [	HLRZ T1,T2	;GET LEFT HALF OF DESIGNATOR
		CAIE T1,.DVDES+.DVDSK ;IS IT A DISK?
		 CALL STOP	;NOT A DISK?
		MOVEM T2,ACCDD(ACC) ;SAVE IT FOR FNDACC.
		JRST .+1 ]
DDSMC3:	MOVX T1,R%OPR
	TDNN T1,RSBIFL(RSB)	;DID OPERATOR REQUEST THIS?
	CALL TELUSR		;NO, LET USER KNOW HE HAS STRUCTURE
	ABTREQ (ABRTNR)		;ABORT RSB WITH NO REPLY TO USER
	JRST DDSMC1
;DDSCIH - ENTERED BY SCHEDULER WHEN PSI INTERRUPT RECEIVED
;	  INDICATING THAT A DISK STATUS CHANGE HAS OCCURRED

;ACCEPTS: NOTHING
;RETURNS: +1,	ALWAYS


DDSCIH:	SAVEQ			;SAVE ACS
	CALL DSTINI		;INITIALIZE TO LOOP OVER ALL DISKS

DDSLOP:	CALL DSTNXT		;GET STATUS OF NEXT DISK
	 RET			;NO MORE, ALL DONE
	CALL DSTSRC		;LOOK FOR UNIT IN TABLES
	 SKIPA T2,[EXP DDSNEW]	;NOT FOUND, USE THIS ROUTINE
	MOVEI T2,DDSCHK		;OR USE THIS ONE IF KNOWN DISK
	CALL (T2)		;EXAMINE THE DISK
	JRST DDSLOP		;THEN LOOK AT NEXT ONE



;HERE WHEN A NEW UNIT HAS TO BE ADDED TO THE DISK TABLES:
;  DSK/	ADDRESS OF FREE ENTRY, OR ZERO IF NO MORE ROOM
;  T1/	CKU NUMBERS FOR UNIT


DDSNEW:	JUMPE DSK,R		;IGNORE UNIT IF TABLES WERE FULL
	MOVSI T2,0(DSK)		;SETUP BLT POINTER
	IORI T2,1(DSK)		;TO CLEAR THE DISK STATUS BLOCK
	SETZM (DSK)		;CLEAR FIRST WORD
	BLT T2,DSKSZ-1(DSK)	;THEN THE REST
	MOVEM T1,DSKCKU(DSK)	;REMEMBER CKU NUMBERS
	MOVE Q2,MSTRBK+.MSRST	;GET STATUS OF DISK
	MOVEM Q2,DSKFLG(DSK)	;REMEMBER IN BLOCK
	TXNN Q2,MS%OFL		;IS PACK ON-LINE?
	CALL DDSADD		;YES, ADD STRUCTURE INFORMATION
	RET			;DONE WITH UNIT
;HERE TO CHECK ON A DISK WHICH WAS ALREADY IN OUR TABLES.  UPDATE
;THE DATA FOR IT.
;  DSK/	ADDRESS OF THIS DRIVE'S DATA



DDSCHK:	MOVE Q2,MSTRBK+.MSRST	;GET STATUS OF UNIT
	MOVE Q1,Q2
	MOVE Q3,DSKFLG(DSK)	;GET OLD STATUS
	XOR Q1,Q3		;GET CHANGED BITS
	MOVEM Q2,DSKFLG(DSK)	;STORE NEW STATUS
	TXNN Q1,MS%OFL!MS%MNT!MS%WLK ;CHANGE IN MOUNT, OFF-LINE, OR WRITE-LOCK?
	JRST [	TXNE Q2,MS%OFL	;NO, IS PACK ON-LINE?
		RET		;NOPE
		MOVE T1,[POINT 7,MSTNM] ;YES, CHECK IF SAME PACK
		MOVEI T2,Q3
		CALL SEVSIX	;CONVERT NAME TO SIXBIT
		CAMN Q3,DSKSTN(DSK) ;HAS PACK BEEN CHANGED?
		RET		;NOPE
		CALL DDSDEL	;YES, DELETE CURRENT STRUCTURE INFO
		JRST DDSADD]	;THEN ADD NEW INFORMATION
	TXNE Q2,MS%OFL		;IS DISK ON-LINE
	JRST DDSDEL		;NO, GO DELETE STRUCTURE INFORMATION
	TXNN Q1,MS%OFL		;DID STRUCTURE JUST COME ON-LINE
	TXNE Q2,MS%MNT		;NO, IS STRUCTURE NOW MOUNTED?
	JRST DDSADD		;YES, ADD STRUCTURE INFORMATION
	TXNE Q1,MS%WLK		;WAS DRIVE UNLOCKED
	JRST DDSADD		;YES, ADD STR
	SETZM DSKSTA(DSK)	;ZERO OUT DISK ALIAS
	LOAD STR,DSKSSA,(DSK)	;GET STRUCTURE BLOCK ADDRESS
	JUMPE STR,R		;RETURN IF NOT PART OF MOUNTED STR
	SETZM STRALI(STR)	;ZERO STRUCTURE ALIAS
	MOVX T1,MS%MT		;TURN OFF FLAG SAYING STR IS MOUNTED
	ANDCAM T1,STRFLG(STR)
	RET			;DONE
;DSTSRC - LOOK FOR THE DISK ENTRY MATCHING SPECIFIED CKU NUMBERS


;ACCEPTS: T1/	CKU NUMBER (CHANNEL, CONTROLLER, UNIT NUMBERS)
;RETURNS: +1,	UNIT WAS NOT IN TABLES
;		   DSK/	ADDRESS OF FIRST FREE SLOT OR ZERO IF NONE
;	  +2,	UNIT FOUND
;		  DSK/	ADDRESS OF DISK STATUS BLOCK FOR UNIT



DSTSRC:	MOVE DSK,[-MAXDSK,,DSKSTB]	;GET AOBJN POINTER READY
	SETZ T2,		;NO FREE ENTRY FOUND YET

DSTSRL:	SKIPN DSKFLG(DSK)	;THIS ENTRY IN USE?
	JRST DSTSRF		;NO, GO REMEMBER FREE ENTRY
	CAME T1,DSKCKU(DSK)	;IS THIS THE UNIT?
	JRST DSTSRN		;NO, TRY NEXT ONE
	ANDI DSK,-1		;FOUND THE UNIT, REMOVE JUNK
	RETSKP			;SUCCESSFUL RETURN

DSTSRF:	SKIPN T2		;HAVE FREE ENTRY REMEMBERED YET?
	MOVE T2,DSK		;NO, THEN REMEMBER THIS ONE
DSTSRN:	ADDI DSK,DSKSZ-1	;MOVE TO NEXT ENTRY
	AOBJN DSK,DSTSRL	;GO DO IT
	HRRZ DSK,T2		;UNIT NOT FOUND, GET FREE BLOCK IF ANY
	RET			;AND RETURN IT
;DDSDEL - DELETE STRUCTURE INFORMATION ABOUT A DISK

;ACCEPTS: DSK/	DISK NUMBER
;RETURNS: +1,	ALWAYS

DDSDEL:	LOAD STR,DSKSSA,(DSK)	;GET STRUCTURE BLOCK ADDRESS
	JUMPE STR,R		;RETURN IF NOT PART OF A STRUCTURE
	LOAD T1,STRMCT,(STR)	;GET NUMBER OF DISKS MOUNTED IN STR
	SOJN T1,DDSDE1		;JUMP IF THERE IS MORE THAN 1 DISK
	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB,DSK>
	CALL PRQPID		;CLEAN UP REQUEST QUEUE FIRST
	MOVX T1,R%DSM		;CHECK DISMOUNT QUEUES
	CALL DDSMCH		;MATCH AND FINISH ACTIVE RSB'S
	SETZM STRALI(STR)	;ZERO OUT THIS STR STATUS BLOCK
	MOVEI T1,STRNAM(STR)
	HRLI T1,STRALI(STR)
	BLT T1,STRALI+STRSZ-1(STR)
	JRST DDSDE2		;CONTINUE CLEARING STRUCTURE INFO
DDSDE1:	STOR T1,STRMCT,(STR)	;STORE NUMBER OF DISKS MOUNTED IN STR
	LOAD T1,DSKLUN,(DSK)	;GET DISK LOGICAL NUMBER
	ADD T1,STR		;GET DISK ADDRESS INDEX
	SETZM STRADD(T1)	; AND ZERO IT OUT
DDSDE2:	SETZM DSKSTN(DSK)	;ZERO STRUCTURE NAME
	SETZM DSKSTA(DSK)	;ZERO STRUCTURE ALIAS
	RET

;DDSERR - RECOVER FROM AN ERROR WHEN TRYING TO MOUNT A STRUCTURE

DDSERR:	MOVEI T1,MSTNM
	TMCT <%IProblem with structure %1A: %J%_%U>
	MOVEI T3,[ASCIZ/MOUNT PROBLEM/]
	CALLRET BTWTO		;SEND MESSAGE TO OPERATOR

;DSFMGT - GET DEVICE-STATUS FILE ENTRY FOR SPECIFIED DRIVE

;ACCEPTS Q2:	CKU NUMBER OF DRIVE
;RETURNS +1,	ALWAYS,  DSFE/ ENTRY FOR SPECIFIED DRIVE

DSFMGT:	SAVET
	MOVEI T1,.DVDSK		;GET DISK DESIGNATOR
	MOVEM T1,DSFE
	MOVEM Q2,DSFE+1		;STORE CKU NUMBER
	CALL DSFLOC		;LOOK UP THIS DRIVE
	 JRST [ MOVX T1,MTS%AV	;NOT ON FILE YET
		MOVEM T1,DSFE+MTS.SF ;SET UP DEFAULT ENTRY IN DSFE
		CALLRET DSFPUT]	;ADD DRIVE TO FILE AND RETURN
	MOVSS T1		;FOUND IT.  GET BLT SOURCE
	HRRI T1,DSFE		;BLT DESTINATION
	BLT T1,DSFE+DSFESZ-1	;TRANSFER ENTRY TO DSFE
	RET			;FOUND IT.  RETURN
;DSKINI - SET UP DISK DRIVE AND STRUCTURE STATUS TABLES

;ACCEPTS: NOTHING
;RETURNS: +1, ALWAYS


DSKINI:	MOVEI T1,1		;SET UP IGNORED STRUCTURES TABLE
	MOVEM T1,IGNTBL
	MOVEI T1,33		;GET INTERRUPT CHANNEL FOR DISK
	MOVEM T1,MSTRBK+.MSCHN	; STATUS CHANGE
	MOVE T1,[1,,.MSOFL]	;TELL MONITOR TO INTERRUPT US IF
	MOVEI T2,MSTRBK		; THERE IS DISK CHANGE
	SKIPN TSTF		;DON'T DO MSTR IF TESTING
	MSTR
	MOVE DSK,[-MAXDSK,,DSKSTB]	;GET READY FOR LOOP
	CALL DSTINI		;INITIALIZE FOR SCANNING OF UNITS

DSKLOP:	CALL DSTNXT		;GET STATUS OF NEXT DISK
	 RET			;END OF DISKS
	MOVEM T1,DSKCKU(DSK)	;REMEMBER CKU NUMBERS FOR UNIT
	MOVE Q2,MSTRBK+.MSRST	;GET STATUS OF UNIT
	MOVEM Q2,DSKFLG(DSK)	;SAVE IT
	TXNN Q2,MS%OFL		;IS DISK ON-LINE?
	CALL STRINF		;YES, ADD STRUCTURE INFORMATION

DSKNXT:	ADDI DSK,DSKSZ-1	;GET NEXT DISK STATUS BLOCK
	AOBJN DSK,DSKLOP	;IF STILL MORE DISKS, GO PROCESS
	RET			;FINISHED WITH DISKS

;DSTGIV - GET STATUS FOR GIVEN DISK UNIT

;ACCEPTS: DSK/	ADDRESS OF DISK STATUS BLOCK
;RETURNS: +1	ERROR, INVALID UNIT
;	  +2	SUCCESS, STATUS IN MSTRBK BLOCK

DSTGIV:	LOAD T1,DSKCTR,(DSK)	;GET CONTROLLER NUMBER
	LOAD T2,DSKCHN,(DSK)	;GET CHANNEL NUMBER
	LOAD T3,DSKDRV,(DSK)	;GET UNIT NUMBER
	CAIN T1,<.RTJST(-1,DOP%K2)>	;ALL ONES?
	SETO T1,		;YES, MAKE IT A FULL WORD
	MOVEM T1,MSTRBK+.MSRCT
	MOVEM T2,MSTRBK+.MSRCH
	MOVEM T3,MSTRBK+.MSRUN	;STORE VALUES FOR MSTR JSYS
	MOVE T1,[.MSRST+1,,.MSRUS] ;RETURN STATUS OF THE GIVEN UNIT
	MOVEI T2,MSTRBK		;GIVE ADDRESS OF ARGUMENT BLOCK
	MSTR
	 ERJMP R		;FAILURE RETURN
	RETSKP
;DSTINI - INITIALIZE MSTR BLOCK FOR SCANNING UNITS

;ACCEPTS: NOTHING
;RETURNS: +1,	ALWAYS


DSTINI:	SETOM MSTRBK		;SET UP MSTR TO LOOK AT FIRST CHANNEL
	SETOM MSTRBK+1		; FOR FIRST CONTROLLER
	SETOM MSTRBK+2		; FOR FIRST DISK
	RET			;DONE


;DSTNXT - GET STATUS OF THE NEXT DISK

;ACCEPTS: MSTRBK BLOCK FOR MSTR JSYS
;RETURNS: +1,	FAILURE
;	  +2,	SUCCESS, STATUS RETURNED IN MSTRBK BLOCK
;		  T1/	CKU NUMBERS FOR UNIT


DSTNXT:	MOVE T1,[POINT 7,MSTNM] ;GET POINTER TO STRUCTURE NAME
	MOVEM T1,MSTRBK+.MSRSN	; AND STORE IN MSTR ARGUMENT BLOCK
	MOVE T1,[POINT 7,MSTAL]	;DO SAME FOR STRUCTURE ALIAS
	MOVEM T1,MSTRBK+.MSRSA
	MOVE T1,[7,,.MSRNU]	;SET UP CALL TO MONITOR TO GET STATUS
	MOVEI T2,MSTRBK		;PUT STATUS IN MSTR BLOCK
	SETZM MSTNM		;CLEAR NAME IN CASE NOT PART OF STRUCTURE
	SETZM MSTAL		;CLEAR ALIAS ALSO
	MSTR			;GET STATUS
	 ERJMP R		;END OF DISKS
	SETZ T1,		;START WITH ZERO AC
	MOVE T2,MSTRBK+.MSRCH	;GET CHANNEL NUMBER
	STOR T2,DOP%C2,T1	;STORE INTO AC
	MOVE T2,MSTRBK+.MSRCT	;GET CONTROLLER NUMBER
	STOR T2,DOP%K2,T1	;STORE WITH CHANNEL
	MOVE T3,MSTRBK+.MSRUN	;FINALLY GET UNIT NUMBER
	STOR T3,DOP%U2,T1	;STORE WITH REST
	RETSKP			;DONE
;KSDK - PROCESS SET DISK-DRIVE COMMAND FROM OPR
;***  NOTICE:  THIS CANNOT HANDLE RP20'S UNTIL GALAXY REDEFINES
;***  THEIR ARGUMENT BLOCK TO INCLUDE CONTROLLER NUMBERS

;RETURNS +1,	ALWAYS

KSDK:	SAVEQ
	SAVEAC <DSK>
	MOVEI T1,.DSKDV
	CALL ORNBLF		;DISK DRIVE SPECIFIED?
	 JRST KBADM		;NO
	MOVX Q2,DOP%K2		;**** HAVE TO ASSUME NO CONTROLLER FOR NOW
	MOVE T2,0(T1)		;GET CHANNEL NUMBER
	DPB T2,[POINTR Q2,DOP%C2]	;PUT INTO AC
	MOVE T2,1(T1)		;GET DRIVE NUMBER
	DPB T2,[POINTR Q2,DOP%U2]	;STORE ALSO
	CALL DDSCIH		;MAKE SURE TABLES UP-TO-DATE
	MOVE T1,Q2		;COPY CKU NUMBER TO RIGHT AC
	CALL DSTSRC		;FIND THIS DISK DRIVE
	 JRST [	TMCT <%ICommand ignored.  Unknown %1K>	;NOT FOUND, COMPLAIN
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;TELL OPERATOR NO SUCH DRIVE
	SETZ Q1,		;ASSUME SETTING UNAVAILABLE
	MOVEI T1,.DVUAV
	CALL ORNBLF		;CHECK IF SETTING UNAVAILABLE
	 JRST [ MOVEI T1,.DVAVL	;NO
		CALL ORNBLF	;SETTING AVAILABLE?
		 JRST KBADM	;NO
		AOJA Q1,KSDKA]	;SETTING AVAILABLE

;SETTING DRIVE UNAVAILABLE

	MOVEI T1,.ORREA
	CALL ORNBLF		;REASON BLOCK PRESENT
	 JRST KBADM		;NO
	MOVE Q3,T1		;COPY ADDRESS OF REASON TEXT
	CALL DSFMGT		;GET DEVICE-STATUS FILE ENTRY
	MOVX T1,MTS%AV		;GET AVAILABLE-STATUS BIT
	TDNN T1,DSFE+MTS.SF	;DRIVE AVAILABLE?
KSDK3:	JRST [ MOVE T1,[[ASCIZ/Unavailable/]
			[ASCIZ/Available/]](Q1) ;GET TEXT POINTER
		MOVE T2,Q2			;GET UNIT ADDRESS
		TMCT <%I%2K Is Already Set %1A>
		MOVEI T3,TMCMSG
		CALLRET BTACK]	;TELL OPRTR COMMAND HAS NO EFFECT
	MOVEI T1,CS%DDV		;GET CODE FOR DETACH-DEVICE
	MOVE T2,Q3		;GET ADDRESS OF ASCIZ REASON
	CALL SYMSET		;LOG SYSERR ENTRY FOR DRIVE SET UNAVAIL
	SETZ T1,		;SET UNAVAILABLE
	STOR T1,MTS%AV,DSFE+MTS.SF ;STORE FLAG
	CALL DSFPUT		;PUT ENTRY BACK IN FILE
	CALLRET WOMDAV		;TELL ALL OPERATORS WHAT HAPPENED

;SETTING DRIVE AVAILABLE

KSDKA:	CALL DSFMGT		;GET DEVICE-STATUS FILE ENTRY
	MOVX T1,MTS%AV		;GET AVAILABLE-STATUS BIT
	TDNN T1,DSFE+MTS.SF	;DRIVE AVAILABLE?
	SKIPA			;NO,
	JRST KSDK3		;ALREADY SET AVAILABLE
	MOVEI T1,1		;SET AVAILABLE
	STOR T1,MTS%AV,DSFE+MTS.SF ;STORE FLAG
	CALL DSFPUT		;PUT ENTRY BACK IN FILE
	MOVEI T1,CS%ADV		;GET CODE FOR ATTACH-DEVICE
	SETZ T2,		;NO REASON
	CALL SYMSET		;LOG SYSERR ENTRY FOR DRIVE AVAILABLE
	CALLRET WOMDAV		;TELL OPERATORS IT'S BACK
;KDSM - PROCESS DISMOUNT STRUCTURE COMMAND FROM OPR

;RETURNS +1,	ALWAYS

KDSM:	SAVEAC <STR>
	CALL DDSCIH		;MAKE SURE TABLES UP-TO-DATE
	MOVEI T1,.DSMST		;GET RSB TYPE
	CALL OPRSB		;SET UP RSB FOR THIS OPR REQUEST
	 RET			;NO RSB AVAILABLE, MESSAGE SENT
	MOVX T1,R%DSM		;GET DISMOUNT FLAG
	IORM T1,RSBIFL(RSB)	;AND SET INTO RSB
	SETZM RSBSTN(RSB)	;ZERO STRUCTURE NAME FOR MATCHS
	MOVEI T1,RST.WM
	STOR T1,RSBSTE		;SET STATE TO WAITING FOR DISMOUNT
	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	MOVE T2,RSBSTN(RSB)	;GET STRUCTURE NAME
	CALL MATCHS		;MATCH REQUEST TO STRUCTURE
	 JRST [ABTRET (ABRTNR)]	;STRUCTURE NOT MOUNTED. NOTHING TO DO.
	STOR STR,RSBSS		;STORE THE STRUCTURE ADDR INTO RSB
	SKIPL STR		;IS STRUCTURE MOUNTED?
	JRST [ MOVEI T1,RSBSTA(RSB) ;YES, DISMOUNT IT
		MOVE T2,[POINT 7,MSTAL]
		CALL SIXSEV
		CALLRET STRDMT]
	CALLRET WOVDS		;ASK OPERATOR TO REMOVE
;KMSS - PROCESS MOUNT STRUCTURE COMMAND FROM OPR

;RETURNS: +1,	ALWAYS

KMSS:	CALL DDSCIH		;MAKE SURE TABLES UP-TO-DATE
	MOVEI T1,.MNTST		;GET REQUEST TYPE
	CALL OPRSB		;BUILD REQUEST BLOCK FOR OPERATOR
	 RET			;NO RSB AVAILABLE, MESSAGE SENT
	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	MOVE T2,RSBSTN(RSB)	;GET STRUCTURE NAME
	CALL MATCHS		;MATCH REQUEST TO STRUCTURE
	 JRST KMS2		;STRUCTURE NOT MOUNTED, YET
	JUMPLE STR,[LOAD T1,STRUNI,(STR) ;GET # OF DISKS IN STR
		    LOAD T2,STRMCT,(STR) ;GET # OF DISKS ON-LINE IN STR
		    CAME T1,T2	;ARE THEY ALL ON-LINE
		    JRST KMS2	;NO, ASK OPERATOR
		    CALL STRMNT	;SPINNING BUT NOT MOUNTED
		     JRST KMS2	;PROBLEMS IN MOUNTING. ASK OPERATOR
		    JRST .+1]
	ABTRET (ABRTNR)		;DISCARD REQUEST
KMS2:	MOVEI T1,RST.WM
	STOR T1,RSBSTE		;SET STATE TO WAITING FOR MOUNT
	CALLRET WOVMS		;TELL OPERATOR TO MOUNT STRUCTURE
;KSHD - SHOW DISK STATUS COMMAND FROM OPR

;RETURN: +1,	ALWAYS

KSHD:	SAVEQ
	TMCT <%I>
	CALL DDSCIH		;MAKE SURE TABLES UP-TO-DATE
	MOVE Q1,RBUF+.OFLAG	;GET COMMAND TYPE
	CAMN Q1,[ST.MNT]	;IS IT ASKING FOR MOUNTED DISKS?
	JRST KSHD2		;YES, SHOW THEM
	MOVEI T1,SFHDR		;GET HEADER FOR FREE DRIVES
	TMCT <%1A>
	MOVE DSK,[-MAXDSK,,DSKSTB]	;SET UP FOR LOOP
KSHD1:	SKIPE T1,DSKFLG(DSK)	;THIS ENTRY EXIST?
	TXNE T1,MS%MNT		;AND STATUS SAYS STRUCTURE ISN'T MOUNTED?
	SKIPA			;NO, SKIP OUTPUT
	CALL WOFRE		;YES, DISPLAY THE UNIT'S STATUS
	ADDI DSK,DSKSZ-1	;GET NEXT DISK STATUS BLOCK
	AOBJN DSK,KSHD1		;IF STILL MORE DISKS, GO PROCESS
	CAMN Q1,[ST.AVA]	;WERE WE ASKED ONLY FOR FREE DRIVES?
	JRST KSHD4		;YES, FINISH DISPLAY
KSHD2:	MOVEI T1,SMHDR		;GET HEADER FOR MOUNTED DRIVES
	TMCT <%1A>
	MOVE DSK,[-MAXDSK,,DSKSTB]	;SET UP FOR LOOP
KSHD3:	MOVE T1,DSKFLG(DSK)	;GET DISK STATUS
	TXNE T1,MS%MNT		;IS IT MOUNTED?
	CALL WOMNT		;YES, DISPLAY THIS UNIT'S STATUS
	ADDI DSK,DSKSZ-1	;GET NEXT DISK STATUS BLOCK
	AOBJN DSK,KSHD3		;IF STILL MORE DISKS, GO PROCESS
KSHD4:	MOVEI T3,[ASCIZ/Disk Drive Status/]
	CALL BTNFO		;ASK FOR NO FORMATTING
	CALLRET BTACKT		;END OF DISKS, SEND STATUS TO OPR
;KSST - PROCESS SET STRUCTURE COMMAND FROM OPR

;ACCEPTS: MRPDB, RBUF/ PDB AND MESSAGE FROM OPR
;	  +1,	ALWAYS

KSST:	CALL DDSCIH		;MAKE SURE TABLES UP TO DATE
	MOVEI T1,.STRDV		;GET BLOCK TYPE CODE
	CALL KGTSTR		;GET STRUCTURE NAME
	 JRST KBADM		;NOT THERE, REJECT MESSAGE
	DMOVEM T2,MSTAL		;STORE ASCII STRUCTURE NAME
	SETZ T2,		;LEAVE ONLY ALIAS FOR MATCHS
	CALL MATCHS		;SET UP STR
	 JFCL			;NO SUCH STR
	MOVEI T1,.STCHR
	CALL ORNBLF		;WAS A CHARACTERISTIC SPECIFIED?
	 JRST KBADM		;NO, REJECT MESSAGE
	MOVE Q3,(T1)		;GET CHARACTERISTIC
	SKIPL Q3		;IS IT WITHIN RANGE?
	CAIL Q3,S.UREG+1
	JRST KBADM		;NO, REJECT MESSAGE
	CAIE Q3,S.ACKN		;WAS CHARACTERISTIC ACKNOWLEDGED?
	CAIN Q3,S.IGNO		; OR IGNORED?
	JRST KSS1		;YES
	HRLZI Q2,-CHRTL		;FORM INDEX INTO CHRTBL
	CAME Q3,CHRTBL(Q2)	;IS THIS THE CHARACTERISTIC
	AOBJN Q2,.-1		;NO, TRY AGAIN
	HRLZ T2,CHRACT(Q2)	;GET VALUE OF MASKED BIT
	MOVEM T2,MSTRBK+.MSSST
	HLLZ T2,CHRACT(Q2)	;GET BIT TO CHANGE
	MOVEM T2,MSTRBK+.MSSMW
	MOVE T1,[POINT 7,MSTAL]	;GET POINTER TO ALIAS
	MOVEM T1,MSTRBK+.MSSSN
	MOVE T1,[3,,.MSSSS]	;SET UP TO CHANGE STATUS
	MOVEI T2,MSTRBK
	MSTR
	 ERJMP KSSERR		;SOMETHING WENT WRONG
	HRRZ T1,CHRACT(Q2)	;GET STATUS SETTING
	SKIPE T1		;IS STATUS BEING SET TO ZERO?
	TLOA T1,STRFLG(STR)	;NO, SET IT TO ONE
	JRST [ HLRZ T1,CHRACT(Q2) ;YES, GET BIT BEING CHANGED
		TLZ T1,STRFLG(STR) ;SET IT
		JRST .+1]
	MOVEM T1,STRFLG(STR)
	MOVE T1,CHRSTG(Q2)	;SET STATUS CHANGED
	CALLRET WOSSC		;TELL OPERATOR

;UPDATE STRUCTURE IGNORED TABLE

KSS1:	MOVE T1,[POINT 7,MSTAL]
	MOVEI T2,Q1		;STORE SIXBIT ALIAS IN Q1
	CALL SEVSIX		;CONVERT ALIAS
	MOVE T1,IGNTBL		;GET INDEX AND # OF ENTRIES
	JUMPG T1,KSS2		;JUMP IF NO NAMES STORED YET
	CAME Q1,IGNTBL(T1)	;IS THIS THE STRUCTURE
	AOBJN T1,.-1		;CHECK NEXT ENTRY
	SKIPL T1		;WAS STRUCTURE FOUND?
	JRST KSS2		;NO
	CAIE Q3,S.ACKN		;IS STR BEING SET ACKNOWLEDGED?
	JRST [	MOVE T1,CHRSTG+4 ;NO, TELL OPERATOR STRUCTURE IS
		CALLRET WOSSC]	; SET IGNORED
	MOVEI T2,IGNTBL(T1)	;SET UP TO MOVE IGNORED ENTRIES UP
	MOVE T3,T2
	HRLI T2,1(T2)
	HLRO T4,T1		;GET # OF ENTRIES TO MOVE
	MOVNS T4		;MAKE POSITIVE
	BLT T2,IGNTBL(T4)	;MOVE ENTRIES
	HLRO T1,IGNTBL		;GET # OF ENTRIES
	AOS T1			;DECREMENT IT
	HRLM T1,IGNTBL
	MOVE T1,CHRSTG		;TELL OPERATOR STRUCTURE IS
	CALLRET WOSSC		; ACKNOWLEDGED

KSS2:	CAIE Q3,S.IGNO		;IS IT BEING SET IGNORED?
	JRST [	MOVE T1,CHRSTG	;NO, TELL OPERATOR STRUCTURE IS
		CALLRET WOSSC]	; SET ACKNOWLEDGED
	MOVEM Q1,IGNTBL(T1) 	;STORE NEW NAME
	HLRZ T1,IGNTBL		;GET # OF ENTRIES IN TABLE
	SOS T1
	CAILE T1,-IGNLEN	;IS THERE ROOM FOR ANOTHER?
	JRST KSS3		;NO, ISSUE ERROR
	HRLM T1,IGNTBL
	MOVE T1,CHRSTG+4	;TELL OPERATOR STRUCTURE IS SET
	CALLRET WOSSC		; IGNORED

KSS3:	RET

;POSSIBLE CHARACTERISTICS TO BE CHANGED

CHRTBL:	S.ACKN
	S.AVAL
	S.DOMS
	S.FORN
	S.IGNO
	S.REGU
	S.UAVL
	S.UREG
CHRTL==.-CHRTBL

;BIT SETTINGS FOR STRUCTURE CHARACTERISTICS

CHRACT:	MS%DIS			;ACKNOWLEDGED
	MS%DIS			;AVAILABLE
	MS%DOM+100000		;DOMESTIC
	MS%DOM			;FOREIGN
	MS%DIS+200000		;IGNORED
	MS%NRS			;REGULATED
	MS%DIS+200000		;UNAVAILABLE
	MS%NRS+004000		;UNREGULATED

;ASCIZ STRINGS FOR STATUS

CHRSTG:	-1,,[ASCIZ/ACKNOWLEDGED/]
	-1,,[ASCIZ/AVAILABLE/]
	-1,,[ASCIZ/DOMESTIC/]
	-1,,[ASCIZ/FOREIGN/]
	-1,,[ASCIZ/IGNORED/]
	-1,,[ASCIZ/REGULATED/]
	-1,,[ASCIZ/UNAVAILABLE/]
	-1,,[ASCIZ/UNREGULATED/]
KSSERR:	MOVEI T1,MSTAL
	TMCT <%IProblem with structure %1A: %J>
	MOVEI T3,[ASCIZ/STRUCTURE STATUS NOT SET/]
	CALLRET BTACKT		;SEND MSSG TO OPERATOR
;MATCHS - MATCH REQUEST TO STRUCTURE


;ACCEPTS: T1	SIXBIT STRUCTURE ALIAS
;	  T2	SIXBIT STRUCTURE NAME

;RETURNS: +1, STRUCTURE NOT FOUND
;		STR/ FIRST FREE STRUCTURE BLOCK
;	  +2, STRUCTURE SPINNING, BUT NOT MOUNTED
;		STR/ -1,,CURRENT STRUCTURE BLOCK ADDRESS
;	  +2, STRUCTURE MOUNTED
;		STR/ 0,,CURRENT STRUCTURE BLOCK ADDRESS

MATCHS:	SAVEQ
	MOVE STR,[-MAXDSK,,STRSTB]	;GET SET FOR LOOPING
	SETZ T3,		;SET FLAG FOR NO FREE BLOCK FOUND YET

;FIND STRUCTURE BLOCK, OR IF NOT FOUND, FIRST FREE BLOCK

MAT1:	SKIPN STRNAM(STR)	;IS THIS BLOCK FREE?
	JRST [	JUMPN T3,MAT4	;YES, JUMP IF ALREADY HAVE BLOCK
		MOVEI T3,(STR)	;SAVE BLOCK ADDRESS
		JRST MAT4]
	MOVE T4,STRFLG(STR)	;IS THIS STRUCTURE MOUNTED?
	TXNN T4,MS%MT
	JRST MAT3		;NO
	MOVE T4,STRALI(STR)	;GET STRUCTURE ALIAS

;STRUCTURE BLOCK CONTAINS MOUNTED STRUCTURE

	CAME T1,T4		;IS THIS THE ONE WE'RE LOOKING FOR
	JRST MAT4		;NO, GET NEXT STRUCTURE
	JUMPE T2,MAT2		;WAS ONLY AN ALIAS SPECIFIED?
	CAME T2,STRNAM(STR)	;NO, IS THIS THE RIGHT STRUCTURE NAME
	JRST MAT4		;NO, CONTINUE LOOKING
MAT2:	HRRZS STR		;ZERO COUNT
	RETSKP

;STRUCTURE BLOCK CONTAINS SPINNING, BUT NOT MOUNTED STRUCTURE

MAT3:	JUMPL T3,MAT4		;JUMP IF STR NAME ALREADY FOUND
	SKIPN T4,T2		;SKIP IF STR NAME GIVEN
	MOVE T4,T1		;NOT GIVEN, USE ALIAS INSTEAD
	CAME T4,STRNAM(STR)	;IS THIS THE RIGHT STRUCTURE
	JRST MAT4		;NO, CONTINUE LOOKING
	SETO T3,		;YES, RECORD IT
	HRRI T3,(STR)
	; ...

	; ...

;INCREMENT STRUCTURE BLOCK INDEX FOR NEXT DISK UNIT

MAT4:	ADDI STR,STRSZ-1	;GET NEXT STRUCTURE STATUS BLOCK
	AOBJN STR,MAT1		;CHECK NEXT STRUCTURE
	MOVE STR,T3		;GET BLOCK ADDRESS
	SKIPL T3		;IS STRUCTURE SPINNING?
	RET			;NO, IT WASN'T FOUND
	RETSKP			;STR SPINNING, BUT NOT MOUNTED
;MESCHK - CHECK IF MESSAGE FOR STRUCTURE ALREADY SENT TO OPERATOR

;ACCEPTS:  RSB/	ADDRESS OF RSB
;RETURNS:  +1,	OPERATOR ALREADY NOTIFIED OF STRUCTURE
;	   +2,	OPERATOR NOT NOTIFIED

MESCHK:	SAVEQ
	MOVE Q1,RSBSTN(RSB)	;GET STRUCTURE NAME
	MOVE Q2,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	MOVE Q3,RSB		;SAVE ADDRESS OF RSB
	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB>
	CALL PRQPID		;CLEAN UP REQUEST QUEUE FIRST
MESCH1:	CALL NSTRSB		;GET ADDRESS OF NEXT RSB
	RETSKP			;NONE LEFT
	CAMN Q3,RSB		;IS THIS THE CURRENT RSB?
	JRST MESCH1		;YES, FORGET IT
	CAMN Q1,RSBSTN(RSB)	;SAME STRUCTURE NAME?
	CAME Q2,RSBSTA(RSB)	;YES, SAME ALIAS?
	JRST MESCH1		;NO, TRY NEXT RSB
	RET			;SAME NAME AND ALIAS
;MNTALL - MOUNT ALL STRUCTURES NOT ALREADY MOUNTED

;ACCEPTS:  NOTHING
;RETURNS:  +1,	ALWAYS

MNTALL:	CALL GORSB		;MUST GET RSB SINCE MOUNT CODE
				; WAS WRITTEN AROUND RSB LOGIC
	 JFCL			;RSB'S IN SHORT SUPPLY
	MOVE STR,[-MAXDSK,,STRSTB]	;GET READY FOR LOOPING
MNTAL1:	SKIPE T1,STRNAM(STR)	;IS A STRUCTURE IN THIS BLOCK?
	CAMN T1,[SIXBIT 'PS']	;YES, IS IT PS?
	JRST MNTNXT		;YES, DON'T TRY THIS ONE
	MOVE T1,STRFLG(STR)	;IS THIS STRUCTURE MOUNTED?
	TXNE T1,MS%MT
	JRST MNTNXT		;YES, GET NEXT ONE
	LOAD T1,STRUNI,(STR)	;GET NUMBER OF DISKS IN STRUCTURE
	LOAD T2,STRMCT,(STR)	;GET NUMBER OF DISKS ON-LINE
	CAME T1,T2		;ARE ALL DISKS ON-LINE?
	JRST MNTNXT		;NO, GET NEXT ONE
	MOVE T1,STRNAM(STR)	;GET STRUCTURE NAME
	MOVEM T1,RSBSTA(RSB)	;ALIAS OF STRUCTURE WILL BE PHYSICAL NAME
	CALL STRMNT		;MOUNT THE STRUCTURE
	JFCL			;LET OPERATOR HANDLE THIS
MNTNXT:	ADDI STR,STRSZ-1	;GET NEXT STRUCTURE STATUS BLOCK
	AOBJN STR,MNTAL1	;JUMP IF THERE ARE MORE
	ABTRET (ABRTNR)		;GET RID OF RSB AND RETURN
;OPRSB - SET UP REQUEST BLOCK FOR OPR MOUNT OR DISMOUNT COMMAND

;ACCEPTS: T1/	REQUEST TYPE (.MNTST OR .DSMST)
;	  MRPDB, RBUF/ PDB AND MESSAGE FROM OPR IPCF REQUEST

;RETURNS: +1,	FAILURE
;	  +2,	SUCCESS, RSB/ ADDR OF REQUEST STATUS BLOCK

OPRSB:	CALL GORSB		;GET A STATUS BLOCK FOR REQUEST
	 RET			;NO RSB'S AVAILABLE, TAKE ERROR RETURN
	MOVEI T1,.STRDV		;GET BLOCK TYPE
	CALL KGTSTR		;GET STRUCTURE NAME
	 JRST [	ABTREQ (ABRTNR)	;NOT THERE, RELEASE RSB
		JRST KBADM]	;REJECT MESSAGE
	MOVEM T1,RSBSTN(RSB)	;STORE SIXBIT STRUCTURE NAME IN RSB
	MOVEM T1,RSBSTA(RSB)	;DEFAULT ALIAS TO STRUCTURE NAME
	MOVEI T1,.STALS	
	CALL KGTSTR		;WAS AN ALIAS SPECIFIED?
	 SKIPA			;NO
	MOVEM T1,RSBSTA(RSB)	;YES, STORE IT IN RSB
	MOVE T1,MRPDB+.IPCFS	;GET PID OF SENDER
	MOVEM T1,RSBPID(RSB)	;STORE IN RSB
	MOVEM T1,MSTRBK+1
	MOVEI T1,.MUFOJ		;GET SENDER'S JOB NUMBER
	MOVEM T1,MSTRBK
	MOVEI T1,3		;3 WORDS IN ARGUMENT BLOCK
	MOVEI T2,MSTRBK		; WHICH IS MSTRBK
	MUTIL
	 JRST [	ABTRET (ABRTNR)] ;SOMETHING HAPPENED TO REQUESTER
	MOVE T1,MSTRBK+2	;GET JOB NUMBER
	STOR T1,RSBJNO
	MOVE T2,[-1,,T4]	;GET USER NUMBER
	MOVEI T3,.JIUNO
	GETJI
	 JRST [	ABTRET (ABRTNR)] ;SOMETHING HAPPENED TO REQUESTER
	MOVEM T4,RSBUNO(RSB)	;STORE USER NUMBER
	RETSKP
;PSDR - PARSE OPERATOR RESPONSE TO DISMOUNT MESSAGE WHEN OTHER JOBS
;	USING STRUCTURE

;ACCEPTS: T1/	ADDRESS OF ASCIZ RESPONSE TEXT
;	  RSB/	ADDRESS OF REQUEST STATUS BLOCK

;RETURNS: +1,	ERROR DETECTED WHILE PARSING RESPONSE, OPERATOR TOLD
;	  +2,	SUCCESSFUL PARSE
;		IF ANSWER IS YES, T1/	0
;		IF ANSWER IS NO,  T1/	-1

PSDR:	CALL COMNDI		;INITIALIZE FOR COMND JSYS
	MOVEI T2,[FLDDB.(.CMKEY,,PSDKT)] ;SETUP FOR KEYWORD PARSE
	CALL COMNDX		;PARSE KEYWORD
	 JRST [	MOVEI T1,[ASCIZ/Response must be YES or NO/]
		CALLRET RSPERR]	;DIDN'T SAY YES OR NO, GIVE ERROR
	HRRZ T1,(T2)		;GET 0 FOR NO, 1 FOR YES
	SOJA T1,RSKP		;RETURN -1 FOR NO, 0 FOR YES

PSDKT:	PSDKTL,,PSDKTL
	[ASCIZ/NO/],,0
	[ASCIZ/YES/],,1
PSDKTL==.-PSDKT-1
;SET UP DEFAULT STATUS FOR STRUCTURES TO MOUNT

SETDEF:	MOVE T4,SSCDEF		;INITIALIZE STATUS TO DEFAULT
SETDE1:	MOVX T1,CMKEY		;SPECIFY 'KEYWORD'
	HRRI T1,[FLDDB.(.CMCFM)] ;ALSO, LOOK FOR CONFIRMATION
	CALL CREAD		;READ NEXT FIELD
	MOVE T2,(T2)		;GET DATA FOR FUNCTION
	CAME T2,FDB		;IS IT END OF LINE?
	JRST [	HRRZS T2	;NO
		XCT (T2)	;SET STATUS
		JRST SETDE1]	;GET NEXT FIELD
	MOVEM T4,SSCDEF		;STORE DEFAULT STRUCTURE STATUS CHANGE
	JRST COMND1		;GET NEXT COMMAND

;SET UP STRUCTURE STATUS CHANGES FOR MOUNT REQUESTS

SETSTR:	MOVE T4,SSCDEF		;INITIALIZE STR STATUS TO DEFAULT
SETST1:	HRRZS T2		;CLEAR TRASH OUT OF LEFT HALF
	XCT (T2)		;SET BIT FOR STR STATUS
	HRROI T1,[ASCIZ /STRUCTURE/] ;GUIDE WORD STRING
	MOVEM T1,FDB+.CMDAT
	MOVX T1,CMNOI		;ALLOW 'NOISE' FUNCTION
	CALL CREAD
	MOVEI T1,COMTBL
	MOVEM T1,FDB+.CMDAT	;CHECK FOR KEYWORD AGAIN
	MOVX T1,CMKEY
	HRRI T1,[FLDBK.(.CMFLD,,,,,<[BRMSK.(KEYB0.,KEYB1.,KEYB2.,KEYB3.,<:>)]>)]
				;CHECK FOR STRUCTURE NAME & COLON, ALSO
	CALL CREAD
	MOVE T2,(T2)		;GET DATA PORTION OF FUNCTION
	CAME T2,FDB		;IS THIS THE STRUCTURE FIELD?
	JRST SETST1		;NO, ANOTHER STATUS CHANGE
	MOVE T2,SSCNAM		;GET ADDRESS TO STORE NAME
	AOS T2			;INCREMENT LOCATION TO USE
	CAIL T2,SSCNAM+STSIZ	;HAVE WE RUN OUT OF STRUCTURE NAME SPACE
	JRST NOSRUM		;YES, ERROR
	MOVSS T4		;SET STATUS CHANGES IN RIGHT HALF
	HRL T4,T2		;MOVE ADDRESS OF STRING FOR TBADD JSYS
	MOVEM T4,Q1		;SAVE ENTRY INFO FOR TBADD
	MOVE T1,[POINT 7,ATMBFR] ;GET POINTER TO STRUCTURE NAME
	MOVEI T4,6		;MAX OF 6 CHARACTERS IN A STRUCTURE
	HRLI T2,(POINT 7)	;MAKE BYTE POINTER TO STORE NAME
SETST2:	ILDB T3,T1		;GET CHARACTER
	JUMPE T3,SETST3		;FINISHED IF ZERO
	CAIN T3,":"		;WAS THERE A COLON ON STRUCTURE NAME
	JRST SETST3		;YES, FINISHED WITH NAME
	IDPB T3,T2		;STORE CHARACTER
	SOJG T4,SETST2		;JUMP IF MORE CHARACTERS
SETST3:	CAIN T4,1		;IS AN EXTRA WORD OF ZEROS NEEDED.
	AOS T2			;YES, FOR ASCIZ STRING
	HRRZM T2,SSCNAM		;STORE NEXT ADDRESS TO USE
	MOVX T1,CMCFM		;GET COMMAND CONFIRMATION
	CALL CREAD		;ASSURE GOOD CONFIRMATION
	MOVEI T1,STRTBL		;GET ADDRESS OF STR STATUS CHANGE TABLE
	MOVE T2,Q1		;GET ENTRY NAME
	TBADD			;ADD ENTRY
	 ERJMP TABFAL		;COULDN'T, GO SEE WHY
	JRST COMND1		;GO READ NEXT COMMAND
;SEVSIX - ROUTINE TO CONVERT 7-BIT ASCII TO 6-BIT

;ACCEPTS: T1	POINTER TO ASCIZ STRING
;	  T2	ADDRESS OF WORD IN WHICH TO STORE 6-BIT STRING

;RETURNS: +1, ALWAYS

SEVSIX:	HRLI T2,(POINT 6,0)	;SET UP SIXBIT POINTER
	SETZM (T2)		;CLEAR THE DESTINATION WORD
	MOVEI T4,6		;MAXIMUM OF 6 CHARACTERS

;LOOP OVER CHARACTERS

SEVLOP:	ILDB T3,T1		;GET 7-BIT CHARACTER
	JUMPE T3,R		;RETURN IF END OF STRING
	CAIL T3,"a"		;IS IT LOWER CASE?
	TRZ T3,40		;MAKE SURE IT IS UPPER CASE
	SUBI T3,40		;CONVERT TO 6-BIT
	IDPB T3,T2		;STORE CHARACTER
	SOJG T4,SEVLOP		;JUMP IF MORE CHARACTERS
	RET

;SIXSEV - ROUTINE TO CONVERT SIXBIT TO ASCIZ

;ACCEPTS: T1	ADDRESS OF WORD CONTAINING SIXBIT CHARACTERS
;	  T2	POINTER TO WORDS FOR STORING ASCIZ STRING (2 WORDS)

;RETURNS: +1, ALWAYS

SIXSEV:	HRLI T1,(POINT 6)	;SET UP BYTE POINTER FOR SIXBIT WORD
	MOVEI T4,6		;MAXIMUM OF 6 CHARACTERS

;LOOP OVER CHARACTERS

SIXLOP:	ILDB T3,T1		;GET CHARACTER
	JUMPE T3,SIXEND		;IF ZERO, THEN END OF STRING
	ADDI T3,40		;MAKE 7-BIT
	IDPB T3,T2		;STORE WORD
	SOJG T4,SIXLOP		;JUMP IF MORE CHARACTERS
SIXEND:	ADDI T4,4		;ZERO OUT REST OF WORD(S)
	SETZ T3,
	IDPB T3,T2		;DEPOSIT ZERO
	SOJG T4,.-1		;JUMP BACK IF MORE CHARACTERS
	RET
;STRDMT - DISMOUNT A STRUCTURE

;ACCEPTS: RSB/	ADDR OF REQUEST STATUS BLOCK
;	  MSTAL/ ASCIZ ALIAS OF STRUCTURE

;RETURNS: +1,	ALWAYS

STRDMT:	MOVE T1,[POINT 7,MSTAL]	;GET POINTER TO STRUCTURE ALIAS
	MOVEM T1,MSTRBK+.MSSSN
	MOVX T1,MS%DIS
	MOVEM T1,MSTRBK+.MSSST	;CHANGE ONLY THE BIT TO SAY THE STR
	MOVEM T1,MSTRBK+.MSSMW	; IS BEING DISMOUNTED
	MOVE T1,[3,,.MSSSS]	;CHANGING STRUCTURE STATUS
	MOVEI T2,MSTRBK
	MSTR
	 ERJMP [CALL GETERR	;ERROR, GET CODE
		MOVEM T1,LSTERR	;PUT IN A SAFE PLACE
		ABTRET (LSTERR,ABT%IN)] ;RETURN MSTR ERROR TO USER
	MOVE T1,[POINT 7,MSTAL]	;NOW SET UP TO SEE IF THERE IS ANY USER
	MOVEM T1,MSTRBK+.MSGSN
	MOVE T1,[5,,.MSGSS]
	MSTR
	MOVE T1,MSTRBK+.MSGST	;GET STRUCTURE STATUS
	TXNE T1,MS%PPS		;IS THIS THE PRIMARY PUBLIC STR?
	JRST [	ABTRET (MSTX24)] ;YES, CAN'T DO THIS
	SKIPN MSTRBK+.MSGMC	;IS ANYONE CONNECTED TO THIS STR
	SKIPE MSTRBK+.MSGFC	;NO, ARE ANY FILES OPEN?
	SKIPA			;YES
	JRST STRDM2		;NO ONE CONNECTED & NO FILES OPEN

; WHILE WE WAIT FOR OPERATOR RESPONSE ALLOW OTHERS TO USE STRUCTURE

	MOVE T1,[POINT 7,MSTAL] ;GET POINTER TO ALIAS
	MOVEM T1,MSTRBK+.MSSSN
	MOVX T1,MS%DIS		;RESET STATUS OF STRUCTURE TO SAY
	MOVEM T1,MSTRBK+.MSSMW	;IT IS NOT BEING DISMOUNTED
	SETZM MSTRBK+.MSSST
	MOVE T1,[3,,.MSSSS]
	MOVEI T2,MSTRBK
	MSTR			;CHANGE STATUS
	 ERCAL STDERR		;STRUCTURE DISAPPEARED.
STRDM5:	MOVEI T1,STRDM1		;GET END-ACTION ADDRESS
	CALLRET WRDSC		;ASK OPERATOR IF OK TO PROCESS REQUEST
STRDM1:	MOVEI RSB,-RSBWTB(T2)	;LOAD RSB AC
	LOAD STR,RSBSS		;GET STRUCTURE STATUS BLOCK AGAIN
	CALL PSDR		;PARSE OPERATOR RESPONSE
	 JRST STRDM5		;BAD RESPONSE, TRY IT AGAIN
	JUMPN T1,STRDM3		;OPERATOR REFUSED REQUEST
	MOVEI T1,RSBSTA(RSB)	;GET ALIAS AGAIN
	MOVE T2,[POINT 7,MSTAL]
	CALL SIXSEV		;CONVERT TO ASCIZ
	MOVE T1,[POINT 7,MSTAL]	;GET POINTER TO STRUCTURE ALIAS
	MOVEM T1,MSTRBK+.MSSSN
	MOVX T1,MS%DIS		;SAY STRUCTURE IS BEING DISMOUNTED
	MOVEM T1,MSTRBK+.MSSST
	MOVEM T1,MSTRBK+.MSSMW
	MOVE T1,[3,,.MSSSS]
	MOVEI T2,MSTRBK
	MSTR
	 ERCAL STDERR		;STRUCTURE IS GONE!!!!

;STRUCTURE HAS NO USERS OR OPERATOR HAS OK'ED DISMOUNT

STRDM2:	MOVE T1,[POINT 7,MSTAL]	;GET POINTER TO ALIAS OF STR
	MOVEM T1,MSTRBK+.MSDNM
	MOVE T1,[1,,.MSDIS]	;DISMOUNT STRUCTURE
	MOVEI T2,MSTRBK
	MSTR
	 ERJMP STDERR
	MOVEI T1,STRNAM(STR)	;GET SIXBIT STRUCTURE NAME AND
	MOVE T2,[POINT 7,MSTNM]	; AND CONVERT TO ASCIZ
	CALL SIXSEV
	CALL WOSDM		;TELL OPERATOR OF DISMOUNT
	MOVX T1,MS%MT		;GET MOUNTED FLAG
	ANDCAM T1,STRFLG(STR)	;SAY STRUCTURE NOT MOUNTED
	CALLRET WOVDS		;TELL OPERATOR TO REMOVE STRUCTURE
;OPERATOR HAS REFUSED TO DISMOUNT STRUCTURE

STRDM3:	ABTRET (MREQ23,ABT%OP)	;OPERATOR REFUSED TO DISMOUNT STRUCTURE

;STDERR - RECOVER FROM AN ERROR WHEN TRYING TO DISMOUNT A STRUCTURE

STDERR:	MOVEI T1,MSTNM
	TMCT <%IProblem with structure %1A: %J%_%U>
	MOVEI T3,[ASCIZ/DISMOUNT PROBLEM/]
	CALLRET BTWTO		;SEND MESSAGE TO OPERATOR
;STRGSB - GET STRUCTURE STATUS BLOCK (BUILD ONE IF NECESSARY)

;ACCEPTS: T1	LOGICAL UNIT # OF CURRENT DISK,,# OF UNITS IN STRUCTURE
;	  T2	SIXBIT STRUCTURE ALIAS
;	  T3	SIXBIT STRUCTURE NAME
;	  DSK	DISK STATUS BLOCK ADDRESS

;RETURNS: +1, ALWAYS
;		STR/ CURRENT STRUCTURE BLOCK ADDRESS

STRGSB:	STAKT
	DMOVE T1,T2
	CALL MATCHS		;DOES THIS STRUCTURE EXIST?
	SKIPA			;NO
	JRST STRFND		;YES, DON'T NEED TO BUILD NEW BLOCK

;DID NOT FIND STRUCTURE.  BUILD NEW BLOCK

STRGS1:	DMOVE T2,CT2		;RESTORE STR NAME AND ALIAS
	MOVEM T3,STRNAM(STR)	;SAVE STR NAME
	MOVEM T2,STRALI(STR)	;SAVE STR ALIAS
	HRRZ T3,CT1		;GET NUMBER OF UNITS
	STOR T3,STRUNI,(STR)	;AND STORE

;STORE DISK STATUS BLOCK ADDRESS

STRFND:	HLRZ T3,CT1		;GET UNIT NUMBER
	ADD T3,STR		;GET OFFSET TO
	HRRZM DSK,STRADD(T3)	; SAVE DISK STATUS BLOCK ADDRESS
	SETZ T4,		;LOOP THRU TO GET # OF PACKS
	MOVEI T3,STRADD(STR)	;GET START OF PACK LIST
	HRLI T3,-10		;WILL HAVE 8 AT MOST
	SKIPE (T3)		;IS THIS A PACK
	AOS T4			;YES, COUNT IT
	AOBJN T3,.-2		;LOOK FOR ALL OF THEM
	STOR T4,STRMCT,(STR)	; AND STORE
	RET
;STRINF - STORE STRUCTURE INFORMATION FOR A DISK

;ACCEPTS: Q2/	STATUS OF UNIT
;	  DSK/	DISK NUMBER
;	  MSTRBK/ BLOCK FROM MSTR CALL

;RETURNS: NOTHING

STRINF:	MOVE T1,[POINT 7,MSTNM]	;GET POINTER TO STRUCTURE NAME
	MOVEI T2,DSKSTN(DSK)	;GET WORD IN WHICH TO STORE NAME
	CALL SEVSIX		; CONVERT FROM 7-BIT TO 6-BIT
	TXNN Q2,MS%MNT		;DOES DRIVE HAVE MOUNTED STRUCTURE
	JRST STRIN1		;NO, STORE REST OF INFORMATION
	MOVE T1,[POINT 7,MSTAL]	;GET POINTER TO ALIAS NAME
	MOVEI T2,DSKSTA(DSK)	;GET WORD IN WHICH TO STORE ALIAS
	CALL SEVSIX		;CONVERT FROM 7-BIT TO 6-BIT
STRIN1:	MOVE T1,MSTRBK+.MSRNS	;GET LOGICAL UNIT,,NUMBER OF UNITS
	MOVEM T1,DSKNS(DSK)	; AND STORE
	MOVE T2,DSKSTA(DSK)	;GET STRUCTURE ALIAS IN SIXBIT
	MOVE T3,DSKSTN(DSK)	;GET STRUCTURE NAME
	CALL STRGSB		;BUILD STR STATUS TABLE & GET STR ADDR
	STOR STR,DSKSSA,(DSK)	;STORE STR STATUS BLOCK ADDRESS
	TXNN Q2,MS%MNT		;IS STR MOUNTED?
	RET			;NO
	MOVX T1,MS%MT		;SET STR MOUNTED
	IORM T1,STRFLG(STR)
	RET
;STRMNT - MOUNT A STRUCTURE

;ACCEPTS: RSB/	CURRENT REQUEST BLOCK
;	  STR/	STRUCTURE TO MOUNT

;RETURNS: +1/	FAILURE
;	  +2/	SUCCESS
STRMNT:	SAVEQ
	MOVE T2,[POINT 7,MSTNM]	;GET PTR TO CONVERT STR NAME TO ASCIZ
	MOVEM T2,MSTRBK+.MSTNM	;STORE POINTER FOR LATER MSTR CALL
	MOVEI T1,RSBSTN(RSB)
	SKIPN (T1)		;IF NO PHYSICAL NAME WAS SPECIFIED,
	MOVEI T1,RSBSTA(RSB)	; USE ALIAS
	CALL SIXSEV
	MOVE T2,[POINT 7,MSTAL]	;DO SAME FOR STRUCTURE ALIAS
	MOVEM T2,MSTRBK+.MSTAL
	MOVEI T1,RSBSTA(RSB)
	CALL SIXSEV
	LOAD T1,STRUNI,(STR)	;GET NUMBER OF UNITS IN STRUCTURE
	HRRZM T1,MSTRBK+.MSTFL	; AND DON'T SET ANY SPECIAL ACTION FLAGS
	MOVNS T1		;NEGATE NUMBER OF UNITS
	MOVSS T1		;SET UP INDEX FOR DISK ADDRESS
	HRR T1,STR		;GET START OF STR STATUS BLOCK
	MOVEI T2,MSTRBK+.MSTUI	;SET UP INDEX FOR STORING DISK INFO
STRMN1:	MOVE DSK,STRADD(T1)	;GET ADDRESS OF DISK STATUS BLOCK
	LOAD T3,DSKCHN,(DSK)	;GET DISK CHANNEL
	MOVEM T3,(T2)		;STORE FOR MSTR CALL
	LOAD T3,DSKCTR,(DSK)	;GET CONTROLLER
	CAIN T3,<.RTJST(-1,DOP%K2)>	;ALL ONES?
	SETO T3,		;YES, MAKE FULL-WORD
	MOVEM T3,1(T2)		;STORE IT
	LOAD T3,DSKDRV,(DSK)	;AND FOR DRIVE NUMBER
	MOVEM T3,2(T2)
	MOVE Q2,DSKCKU(DSK)	;GET CKU NUMBERS FOR CALL
	CALL DSFMGT		;GET DISK DRIVE ENTRY FROM DEVICE TABLE
	MOVX Q1,MTS%AV		;GET AVAILABLE-STATUS BIT
	TDNN Q1,DSFE+MTS.SF	;DRIVE AVAILABLE?
	JRST [	MOVE T1,RSBSTN(RSB) ;NO, GET STRUCTURE NAME
		MOVE T2,Q2	;GET CKU NUMBER
		TMCT <%I%2K Unavailable For Mounting %1S>
		MOVEI T3,TMCMSG
		CALLRET BTWTO]	;TELL OPERATOR
	ADDI T2,3
	AOBJN T1,STRMN1		;STORE UNIT INFO FOR NEXT DRIVE
	SUBI T2,MSTRBK		;GET LENGTH OF ARGUMENT BLOCK
	MOVEI T1,.MSMNT		;SET UP TO MOUNT A STRUCTURE
	HRL T1,T2
	MOVEI T2,MSTRBK		;GET ADDRESS OF ARGUMENT BLOCK
	MSTR			;FINALLY, MOUNT IT
	 ERJMP STMERR		; SOMETHING WENT WRONG
	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	MOVEM T1,STRALI(STR)	; AND STORE
	MOVX T1,MS%MT		;SET STRUCTURE MOUNTED
	IORM T1,STRFLG(STR)

;HAVE MOUNTED STRUCTURE.  MODIFY STRUCTURE STATUS IF NEEDED.

	CALL COMNDS		;CHECK IF STR STATUS TABLE UP-TO-DATE
	MOVEI T1,STRTBL		;CHECK IF STRUCTURE IS IN TABLE TO
	MOVE T2,[POINT 7,MSTAL]	; CHANGE STATUS
	TBLUK
	TXNE T2,TL%EXM		;WAS A MATCH FOUND
	JRST [HRLZ T1,(T1)	;YES, GET STATUS IN T1
		JRST STRMN2]
	SKIPN T1,SSCDEF		;IS THERE A NONSTANDARD DEFAULT FOR STRS
	JRST STRMN3		;NO, DON'T NEED TO CHANGE ANY STATUS
STRMN2:	MOVEM T1,MSTRBK+.MSSST	;STORE IN ARGUMENT BLOCK
	MOVE T1,[POINT 7,MSTAL]	;POINT TO ALIAS OF STR
	MOVEM T1,MSTRBK+.MSSSN
	MOVX T1,MS%DOM+MS%NRS	;GET BITS THAT ARE POSSIBLE TO CHANGE
	MOVEM T1,MSTRBK+.MSSMW
	MOVE T1,[3,,.MSSSS]	;NOW SET UP CHANGE STATUS FUNCTION
	MOVEI T2,MSTRBK		;POINT TO ARGUMENT BLOCK
	MSTR			;CHANGE STATUS
	 ERJMP DDSERR		;SOMETHING WENT WRONG
	MOVE T1,MSTRBK+.MSSST	;GET STRUCTURE STATUS
	IORM T1,STRFLG(STR)	; AND STORE
STRMN3:	LOAD T4,STRMCT,(STR)	;GET NUMBER OF DISKS IN STRUCTURE
	MOVNS T4
	HLRZS T4
	HRRI T4,STRADD(STR)
STRMN4:	MOVE DSK,(T4)
	CALL DSTGIV		;GET STATUS OF GIVEN UNIT
	 CALL STOP		;THERE IS AN INCONSISTENCY
	MOVE T1,MSTRBK+.MSRST	;GET STATUS OF UNIT
	MOVEM T1,DSKFLG(DSK)	;STORE IT
	MOVE T1,STRALI(STR)	;GET ALIAS
	MOVEM T1,DSKSTA(DSK)	; AND STORE
	AOBJN T4,STRMN4
	CALL WOSMT		;TELL OPERATOR OF SUCCESS
	RETSKP

;STMERR - ERROR IN MOUNTING A STRUCTURE

STMERR:	SAVEQ
	MOVEI T1,.FHSLF		;GET THE ERROR
	GETER
	HRRZS T2		;GET ERROR ONLY
	CAIL T2,MSTRX6		;CHECK TO SEE IF ERROR IS CORRECTABLE
	CAIL T2,MSTX14
	JRST [	CAIE T2,MSTX20
		CAIN T2,MSTX23
		JRST .+1
		CAIE T2,MSTX25
		CAIN T2,MSTX30
		JRST .+1
		JRST DDSERR]	;IT IS, TELL OPERATOR
	MOVE Q1,T2		;COPY ERROR CODE TO SAFE PLACE
	CALL DDSERR		;TELL OPERATOR OF PROBLEM
	ABTRET (Q1,ABT%IN)	;ABORT REQUEST AND RETURN TO CALLER
;SYMSET - BUILD AND LOG SYSERR ENTRY FOR DISK DRIVE STATUS CHANGE

;ACCEPTS: T1/ FUNCTION CODE (CS%ADV = SET AVAILABLE, CS%DDV = SET UNAVAILABLE)
;	  T2/ ADDRESS OF ASCIZ REASON, OR 0 IF NO REASON GIVEN
;	  Q2/ CHANNEL,,DRIVE
;	  DSK/ ADDR OF DISK STATUS BLOCK
;RETURNS: +1, ALWAYS

SYMSET:	SAVEQ
	SETZM SYRMSG		;ZERO OUT SYSERR MESSAGE AREA
	MOVE T4,[SYRMSG,,SYRMSG+1]
	BLT T4,SYRMSG+SYRMSZ-1

; TRANSFER OPERATION CODE AND REASON TO MESSAGE

	STOR T1,CS%OPR,SYRMSG+CS%OPW ;STORE OPERATION CODE INTO MESSAGE
	MOVEI Q1,SYRHSZ+CS%SIZ	;ASSUME NO REASON GIVEN
	SKIPN T1,T2		;REASON GIVEN?
	JRST SYMSE1		;NO
	MOVS Q3,T1		;YES, COPY ADDRESS OF STRING FOR BLT
	CALL ASCIZL		;GET # OF CHARACTERS
	IDIVI T2,5		;GET # OF WORDS MINUS 1
	CAIL T2,SYRMSZ		;TOO LONG?
	MOVEI T2,SYRMSZ-1	;YES, TRUNCATE
	MOVEI Q1,SYRHSZ+CS%SIZ+1(T2) ;SAVE SIZE OF ENTIRE MESSAGE
	HRRI Q3,SYRMSG+CS%SIZ	;GET BLT DESTINATION
	BLT Q3,SYRMSG+CS%SIZ(T2) ;TRANSFER STRING TO MESSAGE
	MOVEI T1,CS%SIZ
	STOR T1,CS%RSN,SYRMSG+CS%RSW ;STORE POINTER TO REASON
SYMSE1:	MOVEI T1,SEC%CS		;GET CONFIGURATION STATUS CHANGE CODE
	DPB T1,[POINT 9,SYRHDR,8] ;STORE INTO SYSERR ENTRY HEADER

;BUILD AND STORE SIXBIT DEVICE NAME

	MOVE T1,[SIXBIT/DP000 /]
	MOVE T2,[POINT 6,1,11]
	HLRZ T3,Q2		;GET CHANNEL
	ADDI T3,20		;MAKE IT A SIXBIT NUMBER
	IDPB T3,T2		;SET CHANNEL INTO NAME
	HRRZ T3,Q2		;GET DRIVE NUMBER
	ADDI T3,20
	IDPB T3,T2		;SET DRIVE INTO NAME
	MOVEM T1,SYRMSG+CS%DNM	;STORE SIXBIT DEVICE NAME
	SETZM SYRMSG+CS%ADS	;CAN'T GET THE SERIAL NUMBER
	LOAD T1,DSKTYP,(DSK)	;GET DISK TYPE
	STOR T1,CS%UTP,SYRMSG+CS%HTP

;LOG THE MESSAGE

	MOVEI T1,SYRHDR		;GET ADDRESS OF SYSERR MESSAGE
	MOVE T2,Q1		;GET # OF WORDS IN MESSAGE
	SKIPN TSTF		;DON'T LOG SYSERRS IF TESTING
	SYERR			;LOG IT
	 ERJMP R		;IGNORE ERRORS
	RET
;TLUSR - BUILD BLOCK FOR SUCCESSFUL STRUCTURE REMOVAL RESPONSE

;ACCEPTS: RSB/	ADDRESS OF REQUEST STATUS BLOCK

;RETURNS:  +1,	ALWAYS

TLUSR:	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE NAME
	TMCT <%IStructure %1S: removed
>
	MOVEI T1,TMCMSG		;GET ADDRESS OF ASCIZ TEXT
	MOVEI T2,.MNRTX		;GET ARGUMENT TYPE
	CALL PBTXT		;CREATE TEXT BUILDING BLOCK
	SETZ T1,		;SET NO FLAGS IN GALAXY HEADER
	RET
;TLUSS - BUILD BLOCKS FOR SUCCESSFUL STRUCTURE MOUNT RESPONSE

;ACCEPTS: RSB/	ADDRESS OF REQUEST STATUS BLOCK

;RETURNS: +1:	ALWAYS

TLUSS:	STKVAR <<DVBLK,2>>
	TMCT <%I>		;NEED THIS?
	MOVE T1,[FLD(2,AR.LEN)+FLD(.MNSDV,AR.TYP)] ;GET HEADER
	MOVE T2,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	DMOVEM T1,DVBLK		;STORE HEADER AND STRUNCTURE NAME
	MOVEI T1,DVBLK		;GET ADDRESS OF DEVICE BLOCK
	CALL PBBLK		;ADD IT TO BUILDING BLOCK LIST
	SETZ T1,		;SET NO FLAGS IN GALAXY HEADER
	RET
;USD - PROCESS USER STRUCTURE DISMOUNT REQUEST RECEIVED THRU QUASAR

;ACCEPTS: T1/	ADDR OF STRUCTURE MOUNT ENTRY IN IPCF MSSG FROM QUASAR
;	  RSB/	ADDR OF REQUEST STATUS BLOCK

;RETURNS: +1,	ALWAYS

USD:	SAVEQ
	MOVEI T2,BSRRTA		;SET UP ANALYSIS TABLE FOR BTMRSB
	CALL BTMRSB		;BUILD RSB FROM QUASAR MESSAGE
	 RET			;REQUEST ABORTED, EXIT
	MOVX T1,R%DSM		;GET DISMOUNT FLAG
	IORM T1,RSBIFL(RSB)	;AND SET INTO RSB
	CALL DDSCIH		;MAKE SURE TABLES UP-TO-DATE
	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES, MADE UNCORRECTABLE MOUNT ERROR
	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	MOVE T2,RSBSTN(RSB)	;GET STRUCTURE NAME
	CALL MATCHS		;MATCH REQUEST TO STRUCTURE
	 JRST [ABTRET(MREQ25)]	;STRUCTURE NOT FOUND
	STOR STR,RSBSS		;STORE STRUCTURE STATUS BLOCK ADDR

;MAKE SURE USER ISN'T CONNECTED TO STRUCTURE TO DISMOUNT

	LOAD T1,RSBJNO		;GET USER'S JOB NUMBER
	MOVE T2,[-1,,Q1]	;GET USER'S CONNECTED DIRECTORY
	MOVEI T3,.JIDNO		; INTO Q1
	GETJI
	 RET			;INVALID JOB, ABORT REQUEST
	HRROI T1,TMCMSG		;POINT TO PLACE TO PUT NAME OF CONN DIR
	MOVE T2,Q1		;GET CONNECTED DIRECTORY
	DIRST
	 JRST USD1		;FORGET CONNECTED STR
	HRROI T1,TMCMSG		;GET DESIGNATOR OF CONNECTED STR
	STDEV
USD1:	 SETZ T2,		;FORGET CONNECTED STR
	MOVE Q1,T2		;STORE DESIGNATOR IN T3
	MOVEI T1,RSBSTA(RSB)	;GET SIXBIT ALIAS
	MOVE T2,[POINT 7,MSTAL]	;THIS IS PLACE TO STORE 7-BIT
	CALL SIXSEV		;CONVERT IT
	HRROI T1,MSTAL		;POINT TO ALIAS
	STDEV			;GET ITS DESIGNATOR
	 JRST [	JUMPN STR,[MOVEI T1,RST.WM ;STR SPINNING,BUT NOT MOUNTED?
			   STOR T1,RSBSTE ;SET STATE TO WAITING
			   JRST WOVDS]
		ABTRET (MREQ25)] ;STR IS NOT TO BE FOUND
	CAMN Q1,T2		;IS USER CONNECTED TO STR BEING REMOVED?
	JRST [	ABTRET (MREQ24)] ;YES, ILLEGAL

;USER ISN'T CONNECTED TO STRUCTURE.  PREPARE TO DISMOUNT IT.

	MOVEI T1,RST.WM
	STOR T1,RSBSTE		;SET STATE TO WAITING FOR DISMOUNT
	MOVEI T1,RSBSTN(RSB)	;CONVERT SIXBIT NAME TO 7-BIT
	MOVE T2,[POINT 7,MSTNM]
	CALL SIXSEV
	CALL TCKP		;UPDATE QUASAR'S QUEUES FOR "INFO MOUNT"
	CALLRET STRDMT		;DISMOUNT STRUCTURE
;USM - PROCESS USER STRUCTURE MOUNT REQUEST RECEIVED THROUGH QUASAR

;ACCEPTS: T1/	ADDR OF STRUCTURE MOUNT ENTRY IN IPCF MSSG FROM QUASAR
;	  RSB/	ADDR OR REQUEST STATUS BLOCK

;RETURNS: +1,	ALWAYS

USM:	MOVEI T2,BSRRTA		;SET UP ANALYSIS TABLE FOR BTMRSB
	CALL BTMRSB		;BUILD RSB FROM QUASAR MESSAGE
	 RET			;REQUEST ABORTED, EXIT
	MOVEI T1,RSBSTA(RSB)	;POINT TO SIXBIT ALIAS
	MOVE T2,[POINT 7,MSTAL]	;ASCII GOES HERE
	CALL SIXSEV		;CONVERT ALIAS TO ASCII
	HRROI T1,MSTAL		;POINT TO ASCII ALIAS
	STDEV			;IS THIS A TTY: OR OTHER ILLEGAL DEVICE
	 SKIPA			;ERROR, MUST BE OKAY
	JRST [	HLRZS T2	;GET LEFT HALF OF DESIGNATOR
		CAIN T2,.DVDES+.DVDSK ;IS IT A DISK?
		JRST [	CALL TELUSR ;YES, AND ALREADY MOUNTED
			ABTRET (ABRTNR)]
		MOVEI Q1,MSTRX7 ;GET ERROR MESSAGE
		ABTRET (Q1,ABT%IN)] ;ILLEGAL DEVICE FOR MOUNT
	MOVEI T1,RST.WM
	STOR T1,RSBSTE		;SET STATE TO WAITING FOR MOUNT
	MOVN T1,IGNTBL		;CHECK IF STRUCTURE IS TO BE IGNORED
	HRL T1,T1		;SET UP COUNTER FOR AOBJN LOOP
	HRRI T1,1		;START AT SECOND WORD IN TABLE
	SKIPN T2,RSBSTN(RSB)	;GET STRUCTURE NAME
	MOVE T2,RSBSTA(RSB)
	CAME T2,IGNTBL(T1)	;IS THIS THE STRUCTURE
	AOBJN T1,.-1		;CHECK NEXT ENTRY
	SKIPG T1		;DID WE FIND A MATCH?
	JRST [	MOVEI T1,IGNTBL(T1) ;YES,CONVERT STRUCTURE NAME TO ASCIZ
		MOVE T2,[POINT 7,MSTNM]
		CALL SIXSEV
		MOVEI T1,.FHSLF
		MOVEI T2,MREQ27	; TELL OPERATOR A REQUEST HAS COME
		SETER		; FOR A STRUCTURE THAT HAS BEEN SET
		CALL DDSERR	; IGNORED
		JRST USM1]	;ALLOW OPERATOR TO CHANGE STR STATUS
	CALL DDSCIH		;MAKE SURE TABLES UP-TO-DATE
	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES, MADE UNCORRECTABLE MOUNT ERROR
	MOVE T1,RSBSTA(RSB)	;GET STRUCTURE ALIAS
	MOVE T2,RSBSTN(RSB)	;GET STRUCTURE NAME
	CALL MATCHS		;MATCH REQUEST TO STRUCTURE
	 JRST USM1		;STRUCTURE NOT MOUNTED YET
	SKIPG STR		;IS STRUCTURE MOUNTED?
	JRST [	LOAD T1,STRUNI,(STR) ;NO, GET # OF DISKS IN STR
		LOAD T2,STRMCT,(STR) ;GET # OF DISK ON-LINE IN STR
		CAME T1,T2	;ARE ALL DISKS ON-LINE?
		JRST USM1	;NO, ASK OPERATOR
		CALL STRMNT	;PACK IS SPINNING. MOUNT IT
		 JRST USM1	;PROBLEM IN MOUNTING,CHECK WITH OPERATOR
		JRST .+1]
	CALL TELUSR		;LET USER KNOW HE HAS STRUCTURE
	ABTRET (ABRTNR)		;DUMP THE RSB AND RETURN TO CALLER
USM1:	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES, DON'T TALK TO OPERATOR
	CALL TCKP		;UPDATE QUASAR'S QUEUES FOR "INFO MOUNT"
	CALL PWATCH		;WATCH FOR USER DELETING HIS PID
	CALL GETACC		;GET AN ACCOUNT BLOCK
	 JRST [	CALL DELACC	;ABORT SINCE ACC BLOCKS IN SHORT SUPPLY
		ABTRET (MREQ31)] ;AND KILL REQUEST.
	SETOM ACCDD(ACC)	;FLAG ACCOUNT BLOCK NOT DELETABLE
	GTAD			;GET NOW
	MOVEM T1,ACCSCD(ACC)	;AS SCHEDULED TIME
	LOAD T1,RSBJNO		;GET USER'S JOB NUMBER
	STOR T1,ACCJN		;SAVE IN RSB
	STOR ACC,RSBACC		;ASSOCIATE ACC WITH REQUEST
	CALLRET WOVMS		;TELL OPERATOR TO MOUNT STRUCTURE
;WOFRE - SET UP STRING CONTAINING INFORMATION ON FREE DRIVE

;ACCEPTS DSK/	CURRENT DISK STATUS BLOCK ADDRESS
;RETURNS +1,	ALWAYS

WOFRE:	SAVEQ
	MOVE Q1,DSKFLG(DSK)	;GET STATUS WORD
	LOAD T1,MS%TYP,Q1
	MOVSI T2,-MXUTYP	;GET READY FOR SEARCH
	HLRZ T3,UNTYTB(T2)	;GRAB NEXT TYPE FROM TABLE
	CAME T1,T3		;IS THIS IT?
	AOBJN T2,.-2		;NO, KEEP GOING
	HRRZ T1,UNTYTB(T2)	;GET POINTER TO DISK TYPE STRING
	TMCT <%1A%9C>		;TYPE IT
	LOAD T1,DSKCHN,(DSK)	;GET CHANNEL NUMBER
	TMCT <%1O>		;TYPE IT
	LOAD T1,DSKCTR,(DSK)	;GET CONTROLLER NUMBER
	CAIN T1,<.RTJST(-1,DOP%K2)>	;IS THERE ONE?
	JRST WOFRE3		;NO, SKIP ON
	TMCT <%13C%1O>		;YES, TYPE IT
WOFRE3:	LOAD T1,DSKDRV,(DSK)	;GET UNIT NUMBER
	TMCT <%17C%1O%27C>	;TYPE IT
	TXNE Q1,MS%HBB		;VALID HOME BLOCKS?
	HRROI T1,[ASCIZ /Bad home blocks/]
	TXNE Q1,MS%DIA		;MAINT MODE?
	HRROI T1,[ASCIZ /Maintenance mode/]
	TXNE Q1,MS%OFL		;OFF-LINE?
	HRROI T1,[ASCIZ /Offline /]
	TXNE Q1,MS%DIA!MS%OFL!MS%HBB
	JRST [	TMCT <%1A>	;OUTPUT ERROR MESSAGE
		JRST WOFRE2]	;NO MORE INFORMATION TO OUTPUT
	MOVE T1,DSKSTN(DSK)	;GET STRUCTURE NAME
	TMCT <%1S: (>
	LOAD T1,DSKLUN,(DSK)
	AOS T1			;CHANGE UNIT NUMBER TO ORDINAL
	TMCT <%1D OF >
	LOAD T1,DSKNOU,(DSK)	;GET # OF UNITS IN STRUCTURE
	TMCT <%1D)>
WOFRE2:	TMCTR <%_>		;CRLF
;WOMDAV - TELL OPERATOR OF AVAILABILITY OF DISK DRIVE FOR SYSTEM USE

;ACCEPTS: Q1/  0 IF UNAVAILABLE, 1 IF AVAILABLE
;	  Q2/  CKU NUMBER
;RETURNS: +1,  ALWAYS

WOMDAV:	MOVE T1,Q2		;COPY FOR CALL
	TMCT <%I%1K set >	;TYPE UNIT ADDRESS
	JUMPE Q1,[TMCT <un>
		  JRST .+1]
	TMCT <available for mounting by MOUNTR>
	MOVE T3,[[ASCIZ/Disk Drive Set Unavailable/]
		 [ASCIZ/Disk Drive Set Available/]](Q1) ;GET HEADER
	CALLRET BTWTO		;GET MESSAGE OUT TO OPERATOR
;WOMNT - SET UP STRING CONTAINING INFORMATION ON MOUNTED DRIVE

;ACCEPTS DSK/	CURRENT DISK STATUS BLOCK ADDRESS
;RETURNS +1,	ALWAYS

WOMNT:	SAVEQ
	MOVE Q1,DSKFLG(DSK)	;GET STATUS WORD
	MOVE T1,DSKSTA(DSK)	;GET STRUCTURE ALIAS
	TMCT <%1S:>
	LOAD Q2,DSKNOU,(DSK)	;GET NUMBER OF UNITS IN STR
	CAIN Q2,1		;ONLY ONE UNIT?
	JRST WOMNT1		;YES, FORGET TELLING NUMBER OF UNITS
	TMCT < (>
	LOAD T1,DSKLUN,(DSK)
	MOVE Q3,T1		;SAVE UNIT NUMBER
	AOS T1			;CHANGE UNIT NUMBER TO ORDINAL
	TMCT <%1D/%6D)>		;UNIT# / # OF UNITS
WOMNT1:	LOAD T1,MS%TYP,Q1
	MOVSI T2,-MXUTYP	;GET READY FOR SEARCH
	HLRZ T3,UNTYTB(T2)	;GRAB NEXT TYPE FROM TABLE
	CAME T1,T3		;IS THIS IT?
	AOBJN T2,.-2		;NO, KEEP GOING
	HRRZ T1,UNTYTB(T2)	;GET POINTER TO DISK TYPE STRING
	LOAD T2,DSKCHN,(DSK)	;GET CHANNEL NUMBER
	TMCT <%15C%1A%22C%2O>	;GIVE UNIT TYPE AND CHANNEL NUMBER
	LOAD T1,DSKCTR,(DSK)	;GET CONTROLLER NUMBER
	CAIN T1,<.RTJST(-1,DOP%K2)>	;IS THERE ONE?
	JRST WOMNT4		;NO, SKIP ON
	TMCT <%26C%1O>		;YES, TYPE IT
WOMNT4:	LOAD T1,DSKDRV,(DSK)	;GET UNIT NUMBER
	TMCT <%32C%1O>		;TYPE IT
	SOJE Q2,WOMNT2		;JUMP IF ONLY ONE UNIT
	SKIPE Q3		;IS THIS FIRST UNIT OF STRUCTURE?
	JRST WOMNT3		;NO, HAVE ALREADY OUTPUT INFORMATION
WOMNT2:	MOVE T2,[POINT 7,MSTAL];SET UP POINTER FOR ALIAS
	MOVEM T2,MSTRBK+.MSGSN
	MOVEI T1,DSKSTA(DSK)
	CALL SIXSEV		;CONVERT SIXBIT ALIAS TO NEEDED 7-BIT
	MOVE T1,[4,,.MSGSS]	;GET 4 WORDS OF STRUCTURE STATUS
	MOVEI T2,MSTRBK
	MSTR
	 ERJMP WOMNT3		;NO STRUCTURE?
	MOVE T1,MSTRBK+.MSGMC	;GET MOUNT COUNT
	TMCT <%36C%1D%42C>
	SETZ Q2,		;THIS IS FLAG TO SEE IF STATUS PRINTED
	MOVE Q1,MSTRBK+.MSGST	;GET STRUCTURE STATUS
	TMCTN <Domestic >	;ASSUME DOMESTIC
	TXNN Q1,MS%DOM		;IS IT?
	TMCTN <Foreign >	;NO, FOREIGN
	TMCTO			:PRINT IT
	TMCTN <Regulated >	;ASSUME REGULATED
	TXNE Q1,MS%NRS		;IS IT?
	TMCTN <Unregulated >	;NO, UNREGULATED
	TMCTO			;PRINT IT
	TMCTN <Available >	;ASSUME AVAILABLE
	TXNE Q1,MS%DIS		;IS IT
	TMCTN <Unavailable >	;NO, UNAVALABLE
	TMCTO			;PRINT IT
	MOVE T1,IGNTBL		;CHECK TO SEE IF STRUCTURE IS IGNORED
	MOVE T2,DSKSTN(DSK)
	CAME T2,IGNTBL(T1)	;IS THIS THE STRUCTURE?
	AOBJN T1,.-1		;CHECK NEXT ENTRY
	TMCTN <%_%42CAcknowledged >	;ASSUME ACKNOWLEDGED
	SKIPG T1		;DID WE FIND A MATCH?
	TMCTN <%_%42CIgnored >	;YES, IT IS IGNORED.
	TMCTO			;PRINT IT
	MOVE T1,DSKSTA(DSK)	;GET ALIAS
	CAMN T1,T2		;ARE NAME AND ALIAS THE SAME?
	JRST WOMNT3		;YES
	TMCT <Name: %2S>	;OUTPUT NAME
WOMNT3:	TMCTR <%_>		;NEW LINE AND RETURN
;WOSM - TELL OPERATOR OF A STRUCTURE

WOSM:	MOVEI T1,MSTNM		;GET STRUCTURE NAME
	TMCT <%IStructure %1A>
	MOVE T1,MSTNM		;ARE ALIAS AND NAME THE SAME
	CAME T1,MSTAL
	JRST WOS1		;NO, PRINT THE ALIAS
	MOVE T1,MSTNM+1
	CAMN T1,MSTAL+1
	RET			;YES, FORGET THE ALIAS
WOS1:	MOVEI T1,MSTAL		;POINT TO ALIAS
	TMCTR <: (Alias: %1A)>

;WOSDM - TELL OPERATOR OF A STRUCTURE DISMOUNT

WOSDM:	CALL WOSM		;SET UP STRUCTURE NAMES
	TMCT < dismounted>
	MOVEI T3,[ASCIZ/STRUCTURE DISMOUNTED/]
	CALLRET BTWTO		;TELL OPERATOR

;WOSMT - TELL OPERATOR OF A STRUCTURE MOUNT

WOSMT:	CALL WOSM		;SET UP STRUCTURE NAMES
	TMCT < mounted>
	MOVEI T3,[ASCIZ/STRUCTURE MOUNTED/]
	CALLRET BTWTO		;TELL OPERATOR

;WOSSC - TELL OPERATOR STATUS OF STRUCTURE AFTER STATUS CHANGE

WOSSC:	STAKT
	MOVEI T2,MSTAL		;GET STRUCTURE NAME
	TMCT <%I%2A: set %1A for use by system>
	MOVEI T3,[ASCIZ/STRUCTURE STATUS SET/]
	CALLRET BTWTO		;GET MESSAGE TO OPERATOR
;WRDSC - ASK OPERATOR IF STRUCTURE SHOULD BE REMOVED, EVEN THOUGH THERE
;	 ARE USERS ON IT

;ACCEPTS: T1/	ADDRESS OF RESPONSE HANDLER CALLED BY INWTOR
;	  STR/	ADDRESS OF STRUCTURE STATUS BLOCK
;	  RSB/	ADDRESS OF REQUEST STATUS BLOCK

;RETURNS: +1,	ALWAYS

WRDSC:	MOVE T3,STRNAM(STR)	;GET STRUCTURE NAME
	MOVE T2,STRALI(STR)	;GET ALIAS
	TMCT <%IRemoval of structure %3S: (Alias %2S:) requested.
Other jobs are currently using it.  Should
removal request be processed (YES or NO)?
%U>
	MOVEI T2,RSBWTB(RSB)	;GET WTB ADDRESS
	MOVEI T3,[ASCIZ/DISMOUNT QUERY/]
	CALLRET BTWTOR		;SEND WTOR OFF TO THE OPERATOR
;WOVDS - TELL OPERATOR A STRUCTURE MUST BE DISMOUNTED AND ACCEPT A
;	 POSSIBLE REFUSAL

;ACCEPTS: T1/	ADDRESS OF RESPONSE HANDLER CALLED BY INWTOR
;	  STR/	ADDRESS OF STRUCTURE STATUS BLOCK
;	  RSB/	ADDRESS OF REQUEST STATUS BLOCK

;RETURNS: +1,	ALWAYS

WOVDS:	STAKT
	MOVE T1,STRNAM(STR)	;GET SIXBIT STRUCTURE NAME
	MOVE T2,RSBSTA(RSB)	;GET SIXBIT STRUCTURE ALIAS
	TMCT <%IRemove %1S: (alias %2S:)%_%U%_>
	SKIPE RSBRMK(RSB)	;DID THE USER SUPPLY A REMARK?
	JRST [	MOVEI T1,RSBRMK(RSB) ;YES, GET ADDRESS OF ASCIZ REMARK
		TMCT <User's remark: %1A%_>
		JRST .+1]
	MOVEI T1,SMHDR		;GET STATUS HEADER TEXT
	TMCT <%1A>
	LOAD Q1,STRUNI,(STR)	;GET NUMBER OF UNITS IN STRUCTURE
	MOVNS Q1		;SET UP INDEX
	HRLZ Q1,Q1
	MOVE T1,STR
	ADDI T1,STRADD		;GET INDEX TO START OF DISK ADDRESSES
	HRR Q1,T1		;GET ADDRESS FOR DISK
WOVD1:	MOVE DSK,(Q1)		;GET DISK BLOCK ADDRESS
	JUMPE DSK,WOVD2		;JUMP IF PACK GONE
	MOVX T1,MS%MNT		;MAKE SURE DISK IS NOT MOUNTED
	ANDCAM T1,DSKFLG(DSK)
	CALL WOMNT		;DISPLAY UNIT
WOVD2:	AOBJN Q1,WOVD1		;IF MORE PACKS, DISPLAY THEM
	MOVE T1,CT1		;GET RESPONSE HANDLER'S ADDRESS
	MOVEI T2,RSBWTB(RSB)	;GET WTB ADDRESS
	MOVEI T3,[ASCIZ/DISMOUNT STRUCTURE/]
	CALLRET BTWTO		;SEND WTO OFF TO THE OPERATOR
;WOVMS - TELL OPERATOR A STRUCTURE MUST BE MOUNTED

;ACCEPTS: RSB/ ADDRESS OF REQUEST STATUS BLOCK

;RETURNS: +1,	ALWAYS

WOVMS:	CALL MESCHK		;HAVE WE ALREADY NOTIFIED OPR OF STR?
	RET			;YES, FORGET THIS
	SETONE R%ONR,RSBIFL(RSB) ;SET OPERATOR-NOTIFIED
	MOVE T1,RSBITN(RSB)	;GET REQUEST #
	TMCT <%IStructure Mount Request # %1D>
	CALL CPYHDR		;COPY HEADER TO OPRHDR
	SKIPN T1,RSBSTN(RSB)	;GET SIXBIT STRUCTURE NAME
	MOVE T1,RSBSTA(RSB)	;NONE SPECIFIED, GET ALIAS AS NAME
	MOVE T2,RSBSTA(RSB)	;GET SIXBIT STRUCTURE ALIAS
	TMCT <%IMount %1S: (alias %2S:)%_%U%_>
	SKIPE RSBRMK(RSB)	;DID THE USER SUPPLY A REMARK?
	JRST [	MOVEI T1,RSBRMK(RSB) ;YES, GET ADDRESS OF REMARK
		TMCT <User's remark: %1A%_>
		JRST .+1]
	MOVEI T1,SFHDR		;GET STATUS HEADER TEXT
	TMCT <%1A>
	MOVE DSK,[-MAXDSK,,DSKSTB]	;GET READY FOR LOOP
	SETZ Q1,		;SET FLAG TO SAY NO AVAILABLE DRIVES
WOVM1:	SKIPN T1,DSKFLG(DSK)	;IF STATUS ZERO, MUST NOT BE A DISK
	JRST WOVM2		;NO DISK
	TXNN T1,MS%MNT		;IS THIS DISK MOUNTED?
	TXNE T1,MS%DIA		;NO, IS IT IN MAINT MODE?
	JRST WOVM2		;YES, SKIP THIS DISK
	CALL WOFRE		;DISPLAY STATUS OF THIS DRIVE
	SETO Q1,		;SET FLAG TO SAY WE HAVE A DRIVE
WOVM2:	ADDI DSK,DSKSZ-1	;GET NEXT STATUS BLOCK
	AOBJN DSK,WOVM1		;IF STILL MORE DISKS, GO PROCESS
	JUMPE Q1,[TMCT <No drives available> 
		JRST .+1]
	MOVEI T3,OPRHDR		;GET ADDRESS OF HEADER TEXT
	CALLRET BTWTO		;SEND WTO OFF TO THE OPERATOR
;NO ROOM FOR ANOTHER STRING...

NOSRUM:	MOVEI T1,ATMBFR		;POINT TO STRUCTURE NAME
	TMCT <No more room, structure %1A: not put on structures list
>
	JRST NOS1		;SEND MESSAGE TO OPERATOR

;TBADD FAILED WHEN TRYING TO ADD STRUCTURE TO LIST

TABFAL:	TMCT <%I>
	CALL GETERR		;GET ERROR CODE
	CAIN T1,TADDX1		;TABLE FULL?
	JRST TABFUL		;YES
	CAIN T1,TADDX2		;ENTRY ALREADY THERE?
	JRST TABDUP		;YES
NOS2:	HLRZ T1,Q1		;POINT TO STR NAME
	TMCT <Structure %1A: not put on structures list>
NOS1:	MOVEI T3,[ASCIZ/ERROR IN MOUNTR COMMAND FILE/]
	CALL BTWTO		;WRITE MESSAGE TO OPERATOR
	JRST COMND1		;GO GET NEXT COMMAND

TABFUL:	TMCT <Structures table full, >
	JRST NOS2		;GO SAY WHICH STR DIDN'T GET PUT ON LIST

TABDUP:	HLRZ T1,Q1		;GET STRUCTURE NAME
	TMCT <Duplicate structure name %1A:%_>
	JRST NOS1		;GO GET NEXT COMMAND
;GET TO HERE ON BAD COMMAND

COMBAD:	POP P,T1		;GET RID OF RETURN ADDRESS
	MOVEI T1,ATMBFR		;GET BAD COMMAND
	TMCT <%ICommand line containing "%1A" being ignored
>
	JRST NOS1		;SEND MESSAGE TO OPERATOR

;GET TO HERE ON COMND JSYS ERROR, HOPEFULLY END OF FILE CONDITION

COMEOF:	POP P,T1		;GET RID OF RETURN ADDRESS
	CALL GETERR		;GET ERROR CODE
	CAIN T1,IOX4		;END OF FILE?
	JRST COMEO1		;YES
COMEO2:	TMCT <%ICommand file execution failed, reason: %J>
	MOVEI T3,[ASCIZ/ERROR IN MOUNTR COMMAND FILE/]
	CALL BTWTO		;TELL OPERATOR

;HERE ON END OF COMMAND FILE...

COMEO1:	MOVE T1,COMJFN		;GET JFN ON COMMANDS FILE
	CLOSF			;CLOSE IT
	 JFCL			;IGNORE FAILURE
	RET			;RETURN TO CALLER
SUBTTL USER TAPE MOUNT REQUEST

; BTMRSB - EXTRACT INFORMATION FROM USER MOUNT REQUEST AND
;	   TRANSFER IT TO THE REQUEST STATUS BUFFER
;  T1/ ADDRESS OF MOUNT ENTRY IN IPCF MESSAGE FROM QUASAR
;  T2/ ADDRESS OF TABLE MOUNT REQUEST ANALYSIS ROUTINE ADRESSES
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: FAILURE, MOUNT REQUEST ABORTED
;	  +2: SUCCESS, INFORMATION TRANSFERRED TO RSB

BTMRSB:	SAVEQ
	DMOVE Q1,T1		;COPY ADDRESSES TO A SAFE PLACE

; PERFORM STRUCTURAL VALIDATION OF MOUNT ENTRY

	MOVE T1,.MECNT(Q1)	;GET SUBENTRY COUNT
	MOVEI T2,.MEHSZ(Q1)	;GET ADDRESS OF FIRST SUBENTRY
	LOAD T3,AR.LEN,.MEHDR(Q1) ;GET LENGTH OF SUBENTRY
	SUBI T3,.MEHSZ		;COMPUTE SIZE OF SUBENTRY AREA
	SKIPL T3		;ERROR IF HEADER IS INCOMPLETE
	CALL CKBSTR		;CHECK STRUCTURE OF MOUNT REQUEST
	 JRST [	ABTRET (MREQ20)] ;STRUCTURE ERROR IN MOUNT ENTRY

; PERFORM SEMANTIC ANALYSIS OF MOUNT ENTRY

BTMR1:	MOVEI T1,.MECNT(Q1)	;ADDRESS OF SUBENTRY COUNT WORD
	MOVEI T2,.MEHSZ(Q1)	;ADDRESS OF FIRST SUBENTRY
	SKIPN (Q2)		;FINISHED WITH ANALYSIS ROUTINES?
	RETSKP			;YES, GO HOME
	CALL @(Q2)		;CALL ANALYSIS ROUTINE
	 RET			;ERROR DETECTED, PASS IT TO CALLER
	AOJA Q2,BTMR1		;LOOP THRU ALL ANALYSIS ROUTINES

; TABLE OF TAPE MOUNT REQUEST ANALYSIS ROUTINE ADDRESSES
;   WARNING:
;   DO NOT CHANGE THE ORDER OF THE ROUTINES IN THIS TABLE - SOME
;   DEPEND UPON RSB FIELDS SET UP BY THEIR PREDECESSORS

BTRRTA:	IFIW!BTRFLG		;BIT FLAGS
	IFIW!BTRDEN		;DENSITY
	IFIW!BTRDRV		;DRIVE-TYPE
	IFIW!BTRLT		;LABEL TYPE
	IFIW!BTRSET		;SET NAME
	IFIW!BTRRMK		;REMARK
	IFIW!BTRVLS		;VOLID LIST
	IFIW!BTRSTV		;STARTING VOLID NUMBER
	IFIW!BTRVPR		;VOLUME PROTECTION
	0			;END OF ROUTINES

;TABLE OF STRUCTURE MOUNT REQUEST ANALYSIS ROUTINE ADDRESSES
;    WARNING:
;    BSRALI MUST BE AFTER BSRNAM IN THE TABLE

BSRRTA:	IFIW!BSRALI		;ALIAS OF STRUCTURE
	IFIW!BSRNAM		;NAME OF STRUCTURE
	IFIW!BTRRMK		;REMARK
	0			;END OF ROUTINES
; ROUTINES FOR PROCESSING SUBENTRIES OF TAPE MOUNT REQUEST
;  T1/ ADDRESS OF SUBENTRY COUNT WORD
;  T2/ ADDRESS OF FIRST SUBENTRY
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: REQUEST ABORTED
;	  +2: SUBENTRY PROCESSED SUCCESSFULLY

; DENSITY

BTRDEN:	MOVEI T3,.TMDEN
	MOVEI T4,DENMAX		;GET MAXIMUM
	CALL BTRG1		;LOOKUP DENSITY PARAMETER
	 JRST [	ABTRET (MREQX3)] ;DENSITY ILLEGAL
	STOR T1,RSBDEN		;STORE DENSITY IN RSB
	RETSKP

; DRIVE TYPE

BTRDRV:	MOVEI T3,.TMDRV
	MOVEI T4,.TMDMX		;GET MAXIMUM
	CALL BTRG1		;LOOKUP DRIVE PARAMETER
	 JRST [	ABTRET (MREQX4)] ;DRIVE TYPE ILLEGAL
	STOR T1,RSBDRV		;STORE DRIVE TYPE IN RSB
	RETSKP

; BIT FLAGS

BTRFLG:	MOVE T1,.MEFLG(Q1)	;GET USER-SUPPLIED FLAGS
	TXNE T1,TM%BYP		;DOES HE WANT BYPASS?
	JRST [	MOVX T2,R%PRIV	;YES
		TDNE T2,RSBIFL(RSB) ;IS HE PRIVILEGED?
		JRST .+1	;YES, LET HIM DO IT
		ABTRET (CAPX1)]	;NOT PRIVILEGED, ABORT REQUEST
	TXNE T1,TM%SCR
	JRST [	TXO T1,TM%NEW+TM%WEN ;FLAGS IMPLIED BY TM%SCR
		TXZ T1,TM%OSV+TM%VFY
		JRST .+1]
	TXNE T1,TM%NEW
	JRST [	TXO T1,TM%WEN	;FLAGS IMPLIED BY TM%NEW
		TXZ T1,TM%VFY
		MOVX T2,R%WVL
		IORM T2,RSBIFL(RSB)
		JRST .+1]
	MOVEM T1,RSBUFL(RSB)	;MOVE USER REQUEST FLAGS TO RSB
	RETSKP
; LABEL TYPE (MUST BE CALLED AFTER BTRDRV)

BTRLT:	MOVEI T3,.TMLT
	MOVEI T4,.LTMAX		;GET MAXIMUM
	CALL BTRG1		;LOOKUP DRIVE-TYPE PARAMETER
	 JRST [	ABTRET (MREQX5)] ;LABEL TYPE ILLEGAL
	MOVX T2,TM%BYP
	TDNE T2,RSBUFL(RSB)	;BYPASS?
	MOVEI T1,.LTUNL		;YES, FORCE LABEL TYPE = UNLABELED
	CAIE T1,.LTUNL		;LABELED TAPE?
	JUMPN T1,[LOAD T2,RSBDRV ;YES, GET DRIVE TYPE
		CAIE T2,.TMDR7	;7-TRACK?
		JRST .+1	;NO
		ABTRET (MREQX2)] ;YES, 7-TRACK LABELS NOT SUPPORTED
	STOR T1,RSBLT		;STORE LABEL TYPE IN RSB
	RETSKP

; REMARK

BTRRMK:	MOVEI T3,.TMRMK
	CALL BLKFND		;LOOKUP REMARK
	 RETSKP			;NO REMARK
	JUMPE T2,RSKP		;TREAT ZERO-LENGTH REMARK LIKE NO REMARK
	CAILE T2,RMKLEN		;IS REMARK TOO LONG?
	MOVEI T2,RMKLEN		;YES, TRUNCATE
	MOVSS T1		;BLT SOURCE
	HRRI T1,RSBRMK(RSB)	;BLT DESTINATION
	ADDI T2,RSBRMK-1(RSB)	;LAST WORD OF DESTINATION
	BLT T1,(T2)		;BLT REMARK INTO RSB
	MOVEI T1,377
	ANDCAM T1,(T2)		;MAKE SURE REMARK ENDS WITH A NULL
	RETSKP

; SETNAME

BTRSET:	MOVEI T3,.TMSET
	CALL BLKFND		;LOOKUP SETNAME
	 JRST BTRSE1		;SETNAME MISSING
	JUMPE T2,BTRSE1		;ERROR IF HEADER-ONLY SUBENTRY
	MOVE T1,(T1)		;GET SETNAME IN T1 FOR CHKID
	CALL CHKID		;IS IT A LEGAL SETNAME?
BTRSE1:	 JRST [	ABTRET (MREQX6)] ;SETNAME ILLEGAL OR MISSING
	MOVEM T1,RSBSSN(RSB)	;STORE USER-SUPPLIED SETNAME IN RSB
	MOVX T2,TM%NEW
	TDNE T2,RSBUFL(RSB)	;USER CREATING NEW VOLUME SET?
	MOVEM T1,RSBASN(RSB)	;YES, HIS SETNAME GOES IN THE LABELS
	RETSKP
; STARTING VOLID NUMBER (MUST BE CALLED AFTER BTRVLS)

BTRSTV:	SAVEQ
	MOVEI T3,1
	STOR T3,RSBCV		;DEFAULT CURRENT VOLID # IS 1
	MOVEI T3,.TMSTV
	CALL BLKFND		;STARTING VOLID ENTRY PRESENT?
	 RETSKP			;NO, DEFAULT WILL BE USED
	JUMPE T2,BTRSTI		;ERROR IF HEADER-ONLY SUBENTRY
	MOVX T3,TM%OSV+TM%NEW
	TDNE T3,RSBUFL(RSB)	;ANY BITS SET?
	JRST BTRSTI		;YES, USER CAN'T SPECIFY THIS PARAMETER
	SKIPE Q1,(T1)		;SPECIFYING NUMBER OR VOLID?
	JRST [	CALL VQCNT	;NUMBER, GET # OF VOLIDS IN REQUEST
		CAMG Q1,T1	;ERROR IF SPECIFIED VALUE .GT. MAX
		SKIPG Q1	;ERROR IF STARTING VOLID NOT POSITIVE
		JRST BTRSTI
		STOR Q1,RSBCV	;OFFSET IS LEGAL, STORE IT
		RETSKP]
	CAIGE T2,2		;SPECIFYING VOLID, IS ENTRY LONG ENOUGH?
	JRST BTRSTI		;NO
	MOVE Q1,1(T1)		;GET VOLID
	MOVEI Q2,1		;GET COUNTER
	QSCANI <RSBVLS(RSB)>	;SET UP TO SCAN VOLID LIST
BTRST1:	CALL QMSCAN		;LOOK AT NEXT VOLID FOR THIS REQUEST
BTRSTI:	 JRST [	ABTRET (MREQX7)] ;ABORT REQUEST - ILLEGAL STARTING VOLID
	CAME Q1,1(T2)		;IS THIS THE ONE?
	AOJA Q2,BTRST1		;NO, BUMP COUNTER & CONTINUE SEARCH
	STOR Q2,RSBCV		;FOUND IT, STORE ORDINAL VOLID #
	RETSKP
; VOLID LIST

BTRVLS:	SAVEQ
	MOVX T3,TM%OSV+TM%SCR
	TDNE T3,RSBUFL(RSB)	;IS USER PERMITTED TO SPECIFY VOLIDS?
	RETSKP			;NO, IGNORE VOLID LIST IF PRESENT
	MOVEI T3,.TMVOL
	CALL BLKFND		;LOOKUP VOLID LIST
	 SETZ T2,		;NO VOLID LIST
	JUMPE T2,[MOVX T2,TM%OSV+TM%NEW ;ZERO-LENGTH IS LIKE NO LIST
		TDNE T2,RSBUFL(RSB) ;IS VOLID LIST REQUIRED?
		RETSKP		;NO, LET HIM BY
		ABTRET (MREQ17)] ;YOU FORGOT TO LIST YOUR VOLIDS FELLA
	MOVN Q1,T2		;GET -#VOLIDS IN Q1
	MOVSS Q1		;CONSTRUCT LEFT HALF OF AOBJN POINTER
	HRR Q1,T1		;VOLID SOURCE ADDRESS IN RIGHT HALF
BTRVL1:	MOVE T1,(Q1)		;GET A VOLID FROM SUBENTRY
	CALL CHKID		;IS IT A LEGAL VOLID?
	 JRST [	ABTRET (MREQX9)] ;NO, ABORT REQUEST
	CALL VQADD		;ADD VOLID TO END OF LIST
	 RET			;POOL EXHAUSTED, REQUEST ABORTED
	AOBJN Q1,BTRVL1		;LOOP TO TRANSFER ALL VOLIDS
	RETSKP

; VOLUME PROTECTION

BTRVPR:	MOVEI T3,.TMVPR
	CALL BLKFND		;SEARCH FOR VOLUME-PROTECTION ENTRY
	 SETZ T2,		;NONE FOUND
	MOVE T1,(T1)		;GET ARG IF THERE
	SKIPN T2		;SKIP IF ARGUMENT PRESENT
	MOVEI T1,777777		;USE DEFAULT
	STOR T1,RSBVPR		;STORE VOLUME-PROTECTION CODE
	RETSKP
; BTRG1 - GET A NUMERIC ARGUMENT FROM A BUILDING-BLOCK LIST
;	  IF NO VALUE SPECIFIED, RETURN 0
;	  IF VALUE SUPPLIED, VERIFY THAT 0 .LE. VALUE .LE. MAXIMUM
; T1-T3/ ARGUMENTS FOR BLKFND
; T4/ MAXIMUM VALUE
; RETURNS +1: ENTRY CONTAINS HEADER ONLY OR ARG LIES OUTSIDE LIMITS
;	  +2: ARGUMENT VALID, T1/ VALUE

BTRG1:	STAKT
	CALL BLKFND		;SEARCH FOR ENTRY
	 JRST [	SETZ T1,	;ENTRY NOT THERE, RETURN ZERO
		RETSKP]
	JUMPE T2,R		;ERROR IF HEADER-ONLY
	SKIPGE T1,(T1)		;GET ARGUMENT
	RET			;CAN'T BE LESS THAN ZERO
	CAMLE T1,CT4
	RET			;.GT. UPPER LIMIT
	RETSKP


; TCITN - CANCEL A TAPE MOUNT REQUEST WITH A SPECIFIED ITN
;  T1/ INTERNAL TASK NAME (ITN) OF REQUEST TO BE CANCELED
; RETURNS +1: ITN NOT FOUND OR REQUEST COULD NOT BE CANCELED
;	  +2: REQUEST CANCELED

TCITN:	QSCANI ARBQDB		;SET UP TO SCAN TAPE REQUEST QUEUE
	SAVEAC <RSB>
	SAVEQ
	MOVE Q1,T1		;SAVE ITN
TCITN1:	CALL QMSCAN		;GET ADDR OF NEXT RSB IN T2
	 RET			;NONE LEFT, EXIT
	MOVEI RSB,-RSBLNK(T2)	;GET ADDRESS OF RSB INTO RSB AC
	CAME Q1,RSBITN(RSB)	;IS THIS THE RIGHT REQUEST?
	JRST TCITN1		;NO, CONTINUE SEARCH
	LOAD T1,RSBTYP
	CAIN T1,.MNTTP		;TAPE REQUEST?
	JRST [	JE RSBMT,,.+1	;YES, CANCEL ONLY IF MT NOT ASSIGNED YET
		RET]		;MT ASSIGNED, CAN'T CANCEL IT
	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES, CAN'T CANCEL
	ABTREQ (MREQX1)		;OK, KILL IT
	CALL WORCAN		;TELL OPERATOR REQUEST WAS CANCELED
	RETSKP
; TELMON - TELL THE MONITOR A TAPE VOLUME SWITCH WAS NOT PERFORMED
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

MTUABS==3			;SIZE OF ARGUMENT BLOCK
TELMON:	STKVAR <<MTUAB,MTUABS>>
	MOVEI T1,MTUABS
	MOVEM T1,.MTCNT+MTUAB	;SET COUNT IN ARGUMENT BLOCK
	LOAD T1,RSBSTE		;GET ERROR CODE
	MOVEM T1,.MTCOD+MTUAB	;SET ERROR CODE IN ARG BLOCK
	SETZ T1,		;ASSUME NO ERROR MESSAGE
	MOVX T2,R%ORES
	TDNE T2,RSBIFL(RSB)	;IS THERE AN OPERATOR RESPONSE?
	HRROI T1,ATMBFR		;YES, GET POINTER TO RESPONSE STRING
	MOVEM T1,.MTPTR+MTUAB	;SET STRING POINTER OR 0 IN ARG BLOCK

; ARGUMENT BLOCK IS SET UP, NOW LOAD THE AC'S AND ISSUE THE CALL

	MOVEI T1,.MTNVV		;GET MTU FUNCTION CODE
	LOAD T2,RSBMT		;GET MT STATUS BLOCK ADDRESS
	SUBI T2,MT0		;COMPUTE DISPLACEMENT FROM 0TH BLOCK
	IDIVI T2,MTSZ		;COMPUTE MT#
	MOVEI T3,MTUAB		;GET ARGUMENT BLOCK ADDRESS
	MTU%			;TELL MONITOR
	RET
; TELUSR - BUILD AND SEND IPCF MESSAGE TO USER TO NOTIFY HIM OF THE
;	   DISPOSITION OF A MOUNT REQUEST
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

TELUSR:	SAVEQ
	SETZM TBUF+.OFLAG	;CLEAR FLAGS WORD
	CALL PBINIT		;SET UP FOR CREATING BUILDING BLOCKS
	MOVE Q1,[2,,.MNRNM]	;BUILD BLOCK CONTAINING REQUEST NAME
	MOVE Q2,RSBRNM(RSB)
	MOVEI T1,Q1
	CALL PBBLK
	LOAD T1,RSBSTE		;GET REQUEST STATE
	CAIN T1,ABRTNR		;SHOULD USER GET A RESPONSE?
	RET			;NO, EXIT
	CAIL T1,.ERBAS		;IS THE REQUEST ABORTED?
	JRST [	CALL TLUAB	;YES, BUILD MESSAGE FOR ABORT
		JRST TELUS1]
	LOAD T1,RSBTYP		;GET REQUEST TYPE
	MOVEI T2,STOP		;IN CASE NO MATCH IS FOUND
	CAIN T1,.MNTTP		;TAPE-MOUNT?
	MOVEI T2,TLUTS		;YES
	CAIN T1,.MNTST		;STRUCTURE MOUNT?
	MOVEI T2,TLUSS		;YES
	CAIN T1,.DSMST		;DISMOUNT STRUCTURE?
	MOVEI T2,TLUSR		;YES
NOSHIP,<
	CAIN T1,.MNTDT		;DECTAPE-MOUNT?
	MOVEI T2,TLUDT		;YES
>;NOSHIP
	CALL (T2)		;CALL APPROPRIATE TELL-ROUTINE

; TELUS1 - T1/ GALAXY HEADER FLAGS

TELUS1:	MOVE T2,T1		;COPY FLAGS TO T2 FOR GALHDR
	MOVE T1,PBBPT		;GET POINTER AFTER LAST BLOCK
	SUBI T1,TBUF		;COMPUTE LENGTH OF MESSAGE
	MOVSS T1		;MOVE TO LH OF T1
	HRRI T1,.QOMNA		;PUT MESSAGE TYPE IN RIGHT HALF
	MOVE T3,RSBCOD(RSB)	;GET USER'S ACK CODE
	CALL GALHDR		;BUILD GALAXY HEADER FOR USER
	MOVE T1,RSBPID(RSB)	;GET USER'S PID
	CALLRET TRANU		;SEND THE MESSAGE AND RETURN TO CALLER
; TLUTS - BUILD BLOCKS FOR SUCCESSFUL TAPE MOUNT RESPONSE

TLUTS:	STKVAR <<DVBLK,3>,SAVMT>
	CALL VQGCV		;GET CURRENT VOLID IN T1
	MOVE T2,RSBSSN(RSB)	;GET SETNAME
	JUMPE T1,[TMCT <%I[Tape set %2S, scratch tape mounted]%_>
		JRST TLUTS1]
	TMCT <%I[Tape set %2S, volume %1S mounted]%_>
TLUTS1:	JN TM%OSV,RSBUFL(RSB),[TMCT <[Volume identifiers: >
		CALL TMCVLS	;DISPLAY VOLID LIST
		TMCT <]
>
		JRST .+1]
	MOVEI T1,TMCMSG		;GET ADDR OF ASCIZ TEXT
	MOVEI T2,.MNRTX		;GET ARGUMENT TYPE
	CALL PBTXT		;CREATE TEXT BUILDING BLOCK
	MOVE T1,[FLD(3,AR.LEN)+FLD(.MNRDV,AR.TYP)] ;GET HEADER
	MOVE T2,RSBSSN(RSB)	;GET SETNAME
	DMOVEM T1,DVBLK		;STORE HEADER AND SETNAME
	MOVEM MT,SAVMT		;PRESERVE MT AC
	LOAD MT,RSBMT		;GET ADDR OF MT STATUS BLOCK
	CALL GMTDD		;GET MT DEVICE DESIGNATOR IN T1
	MOVE MT,SAVMT		;RESTORE MT AC
	MOVEM T1,2+DVBLK	;STORE MT DESIGNATOR IN .MNRDV BLOCK
	MOVEI T1,DVBLK		;GET ADDRESS OF .MNRDV BLOCK
	CALL PBBLK		;ADD IT TO BUILDING BLOCK LIST
	SETZ T1,		;SET NO FLAGS IN GALAXY HEADER
	RET
; TLUAB - BUILD BLOCKS FOR UNSUCCESSFUL MOUNT-REQUEST RESPONSE

TLUAB:	SAVEQ
	MOVE Q1,[FLD(2,AR.LEN)+FLD(.MNREC,AR.TYP)] ;GET HEADER
	LOAD Q2,RSBSTE		;GET ERROR CODE
	MOVEI T1,Q1		;POINT AT ERROR CODE BLOCK
	CALL PBBLK		;PUT BLOCK IN MESSAGE
	JN R%ORES,RSBIFL(RSB),[MOVEI T1,ATMBFR ;POINT TO REASON
		TMCT <%IReason given by operator: %1A>
		MOVEI T1,TMCMSG	;GET ADDRESS OF ASCIZ TEXT
		MOVEI T2,.MNRTX	;GET ENTRY TYPE
		CALL PBTXT	;INSTALL TEXT BUILDING BLOCK
		JRST .+1]
	MOVX T1,MF.FAT		;GET FATAL-ERROR FLAG
	RET
; TRESCK - CHECK IF THE SYSTEM HAS AT LEAST ONE OF THE TYPE OF
;	   TAPE DRIVE REQUESTED BY THE USER JOB
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: REQUEST CANNOT BE HANDLED BY THE SYSTEM
;	  +2: REQUEST CAN BE HANDLED BY THE SYSTEM

TRESCK:	SAVEAC <MTA>
	SAVEQ
	SKIPE TSTF		;TEST MODE?
	RETSKP			;YES, ALWAYS SUCCEED
	MOVE Q1,MTAN		;GET # OF MTA DEVICES ON SYSTEM
	MOVEI MTA,MTA0-MTASZ	;INIT MTA AC FOR STATUS BLOCK SCAN
	LOAD Q2,RSBDRV		;GET REQUESTED DRIVE TYPE

; SCAN AVAILABLE TAPE DRIVES FOR ONE THAT CAN POTENTIALLY
; SATISFY THE USER TAPE MOUNT REQUEST

TRES1:	SOJL Q1,R		;TAKE +1 RETURN IF NONE LEFT TO CHECK
	ADDI MTA,MTASZ		;POINT AT NEXT MTA STATUS BLOCK
	JE MTASTE,,TRES1	;SKIP DRIVE IF NOT ASSIGNED TO ME
	JUMPN Q2,[LOAD T1,MTADRV ;GET TYPE OF DRIVE
		CAME T1,Q2	;DOES IT MATCH WHAT THE USER WANTS?
		JRST TRES1	;NO, SKIP IT
		JRST .+1]
	LOAD T1,RSBDEN		;GET REQUESTED DENSITY
	JUMPE T1,RSKP		;OK IF NOT PARTICULAR ABOUT DENSITY
	CALL DRVDEN		;CAN THE DRIVE OPERATE AT THIS DENSITY?
	 JRST TRES1		;NO, SKIP IT
	RETSKP			;OK, AT LEAST 1 DRIVE CAN DO IT
; UTM - PROCESS USER TAPE MOUNT REQUEST RECEIVED THROUGH QUASAR
;	1 - ANALYZE BUILDING-BLOCK REQUEST AND BUILD RSB
;	2 - GET VOLID LIST FROM OPERATOR (IF TM%OSV SET)
;	3 - GET THE FIRST REQUESTED VOLUME MOUNTED
;  T1/ ADDRESS OF TAPE MOUNT ENTRY IN IPCF MESSAGE FROM QUASAR
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

UTM:	MOVEI T2,BTRRTA		;TABLE OF TAPE MOUNT SUBENTRY PROCESSORS
	CALL BTMRSB		;BUILD RSB FROM QUASAR MESSAGE
	 RET			;REQUEST ABORTED, EXIT
	JXE F,TALCF,[ABTRET (MREQ26)] ;MUST HAVE ALLOCATION ENABLED
	CALL TRESCK		;ARE REQUESTED TAPE RESOURCES AVAILABLE?
	 JRST [	ABTRET (MREQ19)] ;NO, ABORT REQUEST
	CALL ACCMTR		;CREATE ACCOUNT BLOCK
	 JRST [	ABTRET (MREQ31)] ;ABORT REQUEST, NO BLOCKS AVAILABLE
	CALL PWATCH		;TELL INFO TO WATCH USER'S PID
	MOVX T1,TM%OSV
	TDNN T1,RSBUFL(RSB)	;WHO IS SUPPLYING THE VOLIDS?
	JRST [	CALLRET VOLMNT]	;USER, GO GET THE FIRST VOLUME MOUNTED

; GET THE VOLID LIST FROM THE OPERATOR

	MOVEI T1,RST.WV		;OPERATOR IS SUPPLYING VOLIDS
	STOR T1,RSBSTE		;SET STATE TO WAITING FOR VOLID KEYIN
	CALL TCKP		;SEND STATUS UPDATE TO QUASAR
UTM1:	JSP T1,WRUTR		;ASK OPERATOR TO KEY IN VOLID LIST
	MOVEI RSB,-RSBWTB(T2)	;LOAD UP ADDR OF REQUEST STATUS BLOCK
	CALL PMR		;PARSE RESPONSE TO VOLID REQUEST
	 JRST UTM1		;BAD RESPONSE, TRY IT AGAIN
	JUMPN T1,R		;RETURN IF REQUEST ABORTED
	CALLRET VOLMNT		;GET 1ST VOLUME MOUNTED AND RETURN
SUBTTL VOLUME/REQUEST ASSOCIATION LOGIC

; MATCHR - TRY TO MATCH USER REQUEST TO TAPE VOLUME
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

MATCHR:	SAVEAC <MTA,Q1>
	MOVE Q1,MTAN		;GET # OF MTA DEVICES ON SYSTEM
	MOVEI MTA,MTA0-MTASZ	;INIT MTA AC FOR SCAN

; SCAN MTA STATUS BLOCKS FOR VOLUMES THAT CAN SATISFY THE REQUEST

MCHR1:	ADDI MTA,MTASZ		;POINT AT NEXT MTA STATUS BLOCK
	SOJL Q1,R		;NONE LEFT, SO SPLIT
	CALL VRA		;TRY TO MATCH REQUEST TO VOLUME
	 JRST MCHR1		;CAN'T, SO CONTINUE SEARCH
	RET


; MATCHV - TRY TO MATCH TAPE VOLUME TO USER REQUEST
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

MATCHV:	SAVEQ
	SAVEAC <RSB>
; PROBLEM: IF THE VOLUME IS A SCRATCH TAPE WITH A VOLID, I WANT TO
; ENSURE THAT ANY USER REQUESTING THE TAPE BY ITS VOLID GETS PRIORITY
; OVER ANY USER REQUESTING A RANDOM SCRATCH TAPE.

; SOLUTION: IMPLEMENT THE HAIRY CODE BELOW THAT PERFORMS A 2-PASS
; SEARCH OF THE RSB QUEUE WHEN THE VOLUME IS A SCRATCH TAPE. THE FIRST
; PASS (Q1/1) CHECKS ONLY RSB'S THAT ARE REQUESTING SPECIFIC (I.E.,
; NON-SCRATCH) VOLUMES. THE SECOND PASS (Q1/0) WILL CHECK ALL RSB'S. IF
; THE TAPE IS NOT A SCRATCH TAPE, ONLY THE SECOND PASS IS EXECUTED.

	LOAD Q1,MA%SCR,MTAFLG(MTA) ;GET 1 IFF VOLUME IS A SCRATCH
MATV1:	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
MATV2:	CALL NMTRSB		;GET NEXT RSB
	 JRST [	SOJGE Q1,MATV1	;MAKE 2ND PASS IF NEEDED
		RET]		;ELSE RETURN
	CALL VQGCV		;THIS USER WANT A SCRATCH TAPE?
	SKIPN T1		;NO
	JUMPG Q1,MATV2		;YES, BYPASS IF IN NON-SCRATCH PASS
	CALL VRA		;TRY TO MATCH REQUEST TO VOLUME
	 JRST MATV2		;CAN'T DO IT, CONTINUE SEARCH
	RET			;REQUEST MATCHED TO VOLUME, EXIT
; MCHWMT - THIS ROUTINE IS CALLED WHEN MT DEVICES ARE FREED BY USER
;	   JOBS. ITS PURPOSE IS TO SCAN THE REQUEST QUEUE FOR REQUESTS
;	   THAT COULD NOT BE SATISFIED BECAUSE NO MT'S WERE AVAILABLE.
; RETURNS +1: ALWAYS

MCHWMT:	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB>
	TXZN F,NOMTF		;DOES AN MT SHORTAGE EXIST?
	RET			;NO, NOTHING TO DO

; SCAN REQUEST QUEUE FOR REQUESTS THAT NEED MT DEVICES

MCHWM1:	TXNN F,NOMTF		;EXIT IF MT SHORTAGE EXISTS
	CALL NMTRSB		;GET NEXT RSB
	 RET			;NOTHING MORE TO DO
	JN RSBMT,,MCHWM1	;BYPASS IF HE'S GOT AN MT ALREADY
	LOAD T1,RSBSTE		;GET STATE OF REQUEST
	CAIE T1,RST.WM		;WAITING FOR TAPE MOUNT?
	JRST MCHWM1		;NO, DOESN'T NEED MT
	CALL MATCHR		;TRY TO FIND A MATE FOR THIS REQUEST
	JRST MCHWM1		;GO ON TO NEXT REQUEST
; MOLOC - PERFORM .MOLOC MTOPR FUNCTION
;  MT/ ADDR OF MT STATUS BLOCK
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

MOLASZ==10			;SIZE OF .MOLOC ARG BLOCK
MOLOC:	STKVAR <<MOLARG,MOLASZ>>
; SET UP ARGUMENT BLOCK FOR MTOPR

	MOVEI T1,MOLASZ		;SET SIZE OF ARG BLOCK
	MOVEM T1,.MOCNT+MOLARG
	MOVE T1,MT		;GET MT STATUS BLOCK ADDR
	SUBI T1,MT0		;SUBTRACT BASE ADDRESS
	IDIVI T1,MTSZ		;COMPUTE MT UNIT#
	MOVEM T1,.MOMTN+MOLARG	;SET MT UNIT #
	LOAD T1,RSBDEN
	MOVEM T1,.MODNS+MOLARG	;SET DENSITY
	MOVEI T1,MTAV1(MTA)
	MOVEM T1,.MOAVL+MOLARG	;SET LABEL ADDRESS
	LOAD T1,RSBCV
	MOVEM T1,.MOCVN+MOLARG	;SET CURRENT VOLUME #
	MOVE T1,RSBASN(RSB)
	MOVEM T1,.MOVSN+MOLARG	;SET SIXBIT FILE SET IDENTIFIER
	LOAD T1,RSBLT
	MOVEM T1,.MOLBT+MOLARG	;SET LABEL TYPE
	MOVEI T2,1		;ASSUME EBCDIC OR ANSI
	CAIN T1,.LTUNL
	MOVEI T2,0		;UNLABELED
	CAIN T1,.LTT20
	MOVEI T2,2		;TOPS-20
	MOVEM T2,.MONVL+MOLARG	;SET LABEL COUNT

; NOW PASS ALL THIS STUFF ON DOWN TO THE MONITOR

	CALL MTAGJF		;GET JFN FOR MTOPR
	MOVEI T2,.MOLOC		;GET MTOPR FUNCTION CODE
	MOVEI T3,MOLARG		;ADDRESS OF ARGUMENT BLOCK
	MTOPR			;PERFORM REQUESTED FUNCTION
	 ERCAL WOLOCF		;ERROR, DISPLAY TO OPERATOR
	LOAD T1,MTAJFN		;GET JFN
	MOVEI T2,.MOSID		;FUNCTION = SET VOLUME-ID
	MOVE T3,MTAVOL(MTA)	;GET VOLID
	MTOPR			;MAKE VOLID AVAILABLE TO USER VIA .MOINF
	CALLRET MTARJF		;RELEASE JFN AND RETURN
; MTALC - ALLOC MT DEVICE TO A USER JOB
;  MT/ ADDR OF MT STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: FAILED, USER JOB DISAPPEARED
;	  +2: SUCCESS, MT AND RSB LINKED TO EACH OTHER

MTALC:	CALL GMTDD		;GET MT DEVICE DESIGNATOR IN T1
	MOVE T2,T1		;MOVE IT TO T2 FOR ALLOC JSYS
	MOVEI T1,.ALCAL		;ALLOC FUNCTION CODE
	LOAD T3,RSBJNO		;GET USER'S JOB #
	ALLOC			;ALLOCATE MT DEVICE TO USER JOB
	 JRST [	CAIE T1,ALCX4	;INVALID JOB #?
		CALL STOP	;NO, I CAN'T HANDLE THIS ERROR
		ABTRET (ABRTNR)] ;ABORT - USER WENT AWAY
	STOR MT,RSBMT		;STORE MT STATUS BLOCK ADDR IN RSB
	STOR RSB,MTRSB		;STORE RSB ADDR IN MT STATUS BLOCK
	RETSKP			;SUCCESSFUL COMPLETION


; MTGET - LOCATE A FREE MT DEVICE
; RETURNS +1: NO FREE MT'S AVAILABLE
;	  +2: FREE MT FOUND, MT/ ADDR OF MT STATUS BLOCK

MTGET:	MOVEI MT,MT0-MTSZ	;INIT MT AC FOR STATUS BLOCK SEARCH
	MOVE T1,MTN		;GET # OF MT DEVICES ON SYSTEM
MTGET1:	ADDI MT,MTSZ		;POINT AT NEXT MT STATUS BLOCK
	SOJL T1,[TXO F,NOMTF	;NONE LEFT, SET NONE-LEFT FLAG
		RET]		;ERROR RETURN
	JN MTRSB,,MTGET1	;SKIP THIS ONE IF IT'S IN USE
	RETSKP			;FREE MT FOUND


; MTRLS - PROCESS RELEASE OF MT DEVICE BY USER
;  MT/ ADDR OF MT STATUS BLOCK
; RETURNS +1: ALWAYS

MTRLS:	SAVEAC <RSB>
	LOAD RSB,MTRSB		;GET RSB ADDRESS
	JUMPE RSB,R		;EXIT IF NO RSB ASSOCIATED
	CALL PLDISA		;DISASSOCIATE MT FROM MTA
	SETZRO MTRSB		;CLEAR OWNER-OF-MT FIELD
	CAIN RSB,MTNAV		;WAS THERE AN RSB?
	RET			;NO, BYPASS RSB PROCESSING
	SETZRO RSBMT		;CLEAR POINTER TO MT IN RSB
	SKIPE T1,RSBWTB+WTBCOD(RSB) ;WTOR OUTSTANDING?
	CALL CANWTR		;YES, CANCEL IT
	TXO F,ABORTF		;FORCE A SCAN TO DUMP THE RSB
	ABTRET (ABRTNR)		;GET THE REQUEST OUT OF MY QUEUES
; PLDISA - DISASSOCIATE PHYSICAL AND LOGICAL TAPE DEVICES
;  MT/ ADDR OF MT STATUS BLOCK
; RETURNS +1: ALWAYS

; NOTE - IF MOUNTR CRASHES AND GETS RESTARTED, THE CURRENT MT-MTA
;	 ASSOCIATIONS ARE RESTORED FROM MONITOR TABLES (ASMT ROUTINE)
;	 BUT MTRSB WILL CONTAIN MTNAV (HENCE PLDISA CHECKS FOR THIS)

PLDISA:	SAVEAC <MTA,RSB>
	LOAD MTA,MTMTA		;GET MTA STATUS BLOCK ADDRESS
	JUMPE MTA,R		;EXIT IF NO MTA ASSOCIATED WITH MT
	LOAD RSB,MTRSB		;GET REQUEST STATUS BLOCK ADDRESS
	SETZRO MTAMT		;CLEAR MTA-TO-MT LINK
	SETZRO MTMTA		;CLEAR MT-TO-MTA LINK
	CALL SCIENA		;GET STATUS INTERRUPTS FOR THIS DRIVE

	CAIN RSB,MTNAV		;RSB ASSOCIATED?
	JRST PLDISU		;NO, UNLOAD DRIVE TO PLAY IT SAFE
	CALL ACCMTD		;SEND ACCOUNT INFO TO MONITOR
	CALL CKMPAV		;DID OPERATOR SET MTA UNAVAILABLE?
	 JRST PLDISU		;YES, UNLOAD IT
	JE TM%NUL,RSBUFL(RSB),PLDISU ;JUMP IF USER WANTS VOLUME UNLOADED
	CALL REW		;IS MTA OFFLINE?
	 JRST PLDISU		;YES, NO HOPE FOR RE-USE
	MOVEI T1,[ASCIZ/Remaining mounted on drive/]
	CALL WODISA		;TELL OPERATOR THAT USER RELEASED TAPE
	LOAD T1,MTALT		;GET LABEL TYPE
	CAIE T1,.LTUNL		;UNLABELLED?
	JRST PLDSA1		;NO, DON'T TOUCH VOLID
	SETZM MTAVOL(MTA)	;CLEAR VOLID
	SETZM MTAIDV(MTA)	;AND OPERATOR KEYIN
PLDSA1:	JE MA%AVS,MTAFLG(MTA),[CALLRET MATCHV] ;TRY MATCHUP IF NON-AVR
	MOVX T1,MA%UXV+MA%OPF+MA%SCR
	ANDCAM T1,MTAFLG(MTA)	;CLEAR SOME FLAGS
	SETZRO MTALT		;CLEAR MTALT SO AVR WILL WORK
	CALLRET AVR		;INITIATE AVR SEQUENCE FOR DRIVE

; AVR SEQUENCE MAY NOT BE PERFORMED UPON TAPE

PLDISU:	LOAD T1,MTALT		;GET LABEL TYPE
	CAIN T1,.LTUNL		;UNLABELLED?
	JRST [SETZM MTAVOL(MTA)	;YES, CLEAR VOLID
	      SETZM MTAIDV(MTA)	;AND OPERATOR KEYIN
	      JRST .+1]		;CONTINUE
	CALL UNLOAD		;UNLOAD THE DRIVE
	MOVEI T1,[ASCIZ/Being unloaded/]
	CAIE RSB,MTNAV		;IF NO RSB, DON'T GIVE MESSAGE
	CALL WODISA		;TELL OPERATOR THAT USER RELEASED TAPE
	CALL CKMPAV		;DID OPERATOR SET MTA NOT-AVAILABLE?
	 CALL DACMTA		;YES, DEACTIVATE MTA
	RET			;NO
; PRQABT - PURGE ABORTED REQUESTS FROM MOUNT REQUEST QUEUE
; RETURNS +1: ALWAYS

PRQABT:	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB>

; SEARCH MOUNT REQUEST QUEUE AND EXTRACT ABORTED REQUESTS

PRQAB1:	CALL QMSCAN		;GET ADDRESS OF NEXT RSB ON QUEUE
	 RET			;NONE LEFT, EXIT
	MOVEI RSB,-RSBLNK(T2)	;LOAD RSB AC WITH RSB ADDRESS
	CALL CHKAB		;REQUEST ABORTED?
	 SKIPA			;YES
	JRST PRQAB1		;NO, SKIP IT
	LOAD T1,RSBTYP		;GET TYPE OF REQUEST
	CAIN T1,.MNTTP		;TAPE MOUNT?
	JRST [	JN RSBMT,,PRQAB1 ;YES, SKIP IF USER STILL HAS MT DEVICE
		CALL VQDEL	;RELEASE VOLID LIST
		JRST .+1]	;CONTINUE DELETION LOGIC

; DEQUEUE AND DISCARD ABORTED RSB

	SKIPE RSBWTB+WTBCOD(RSB) ;IS WTB ACTIVE?
	CALL STOP		;YES, CRASH!!!
	MOVX T1,R%OPR
	TDNN T1,RSBIFL(RSB)	;WAS THIS REQUEST FROM OPR?
	CALL RLSMSG		;NO, TELL QUASAR TO RELEASE THIS ITN
	CALL QMDQS		;DEQUEUE RSB, GET LINKAGE ADDR IN T2
	MOVEI T1,IRBQDB		;GET QDB ADDRESS
	CALL QMQH		;QUEUE RSB TO HEAD OF INACTIVE QUEUE
	JRST PRQAB1		;CONTINUE SCAN OF RSB QUEUE
; PRQPID - PURGE REQUESTS FROM MOUNT REQUEST QUEUE WHOSE OWNERS
;	   HAVE DELETED THEIR PIDS BEFORE THE FIRST VOLUME WAS MOUNTED
; RETURNS +1: ALWAYS

PRQPID:	QSCANI ARBQDB		;SET UP TO SCAN ACTIVE RSB QUEUE
	SAVEAC <RSB>
PURGR1:	CALL QMSCAN		;GET ADDR OF NEXT RSB IN T2
	 RET			;END OF RSB QUEUE, EXIT
	MOVEI RSB,-RSBLNK(T2)	;COPY RSB ADDRESS TO RSB AC
	CALL CHKAB		;REQUEST ABORTED?
	 JRST PURGR1		;YES, SKIP IT
	CALL VALPID		;CHECK PID
	 JFCL			;REQUEST ABORTED
	JRST PURGR1		;CONTINUE SEARCH


; VALPID - ABORT REQUEST IF PID IS DELETED
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: REQUEST ABORTED BECAUSE USER PID WAS DELETED
;	  +2: REQUEST NOT ABORTED

VALPID:	LOAD T1,RSBTYP
	CAIN T1,.MNTTP		;TAPE REQUEST?
	JRST [	JE RSBMT,,.+1	;YES, DOES THE USER HAVE AN MT?
		RETSKP]		;YES, DON'T DO PID CHECK
	CAIN T1,.MNTDT		;DECTAPE-MOUNT REQUEST?
	SKIPN RSBDTA(RSB)	;DOES USER HAVE THE DTA?
	SKIPA			;NO TO EITHER
	RETSKP			;USER HAS DECTAPE, PRESERVE REQUEST
	MOVEI T1,.MUFOJ
	MOVE T2,RSBPID(RSB)	;GET USER'S PID
	CALL XMUTIL		;IS IT STILL VALID?
	 JRST [	CALL WORCAN	;NO, TELL OPERATOR REQ WAS CANCELED
		ABTRET (ABRTNR)] ;ABORT REQUEST
	RETSKP			;PID STILL GOOD
; VOLMNT - ATTEMPT TO MATCH REQUEST WITH MOUNTED VOLUME; IF THIS IS
;	   NOT POSSIBLE, THE OPERATOR IS TOLD TO MOUNT THE VOLUME
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

VOLMNT:	CALL VQCNT		;GET # OF VOLUMES IN SET IN T1
	LOAD T2,RSBCV		;GET CURRENT VOLUME #
	MOVX T3,R%WVL
	TDNN T3,RSBIFL(RSB)	;NEED TO ASK OPERATOR FOR NEXT VOLID?
	CAMG T2,T1
	SKIPA T1,[RST.WM]	;NO
	JRST [	MOVEI T1,RST.WV	;YES
		STOR T1,RSBSTE	;SET STATE TO WAITING FOR VOLID KEYIN
		CALL TCKP	;TELL QUASAR
		MOVEI T1,VOLMT2	;GET END-ACTION ADDRESS
		CALLRET WRNXTV]	;GO ASK FOR NEXT VOLID
	STOR T1,RSBSTE		;SET STATE TO WAITING FOR TAPE MOUNT
	SETZRO R%ONR,RSBIFL(RSB) ;CLEAR OPERATOR-NOTIFIED FLAG
	CALL TCKP		;SEND CHECKPOINT MESSAGE TO QUASAR
	CALL MATCHR		;MATCH REQUEST TO VOLUME
	CALL CHKAB		;REQUEST ABORTED?
	 RET			;YES, BACK TO CALLER
	LOAD T1,RSBSTE		;GET STATE TO SEE WHAT MATCHR DID
	CAIE T1,RST.WM		;STILL WAITING FOR A MOUNT?
	RET			;NO, EXIT
	CALLRET WOVMT		;TELL OPERATOR TO MOUNT VOLUME

; PROCESS RESPONSE TO WTOR ASKING OPERATOR TO SUPPLY NEXT VOLID

VOLMT2:	MOVEI RSB,-RSBWTB(T2)	;LOAD RSB AC
	CALL PNVR		;PARSE RESPONSE
	 JRST [	MOVEI T1,VOLMT2	;BAD RESPONSE, GET END-ACTION ADDRESS
		CALLRET WRNXTV]	;LET HIM TRY IT AGAIN
	JUMPN T1,R		;RETURN NOW IF REQUEST ABORTED
	JRST VOLMNT		;GOT THE VOLID, NOW GO GET IT MOUNTED
; VOLSW - PERFORM TAPE VOLUME-SWITCH
;  T1/ ABSOLUTE VOLUME NUMBER TO SWITCH TO
;  MT/ ADDR OF MT STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

VOLSW:	SAVEAC <MTA,ACC>
	STAKT
	LOAD T2,RSBCV		;GET CURRENT VOLUME #
	CAMN T1,T2		;SWITCHING TO SAME VOLUME?
	JRST [	LOAD MTA,MTMTA	;YES, GET MTA STATUS BLK ADDR
		CALLRET MOLOC]	;HOOK UP MT&MTA AGAIN
	CALL PLDISA		;DISASSOCIATE MTA FROM MT
	LOAD ACC,RSBACC		;GET ACC
	GTAD			;GET TIME
	MOVEM T1,ACCSCD(ACC)	;SAVE IN ACCOUNT BLOCK AS SCHEDULED TIME
	CALL VQCNT		;GET # OF VOLUMES IN SET
	ADDI T1,1		;ADD 1 IN CASE EXPANDING VOLUME SET
	SKIPLE T2,CT1		;ERROR IF GOING TO VOLUME BEFORE FIRST
	CAMLE T2,T1		;ERROR IF GOING BEYOND END OF SET
	JRST [	ABTRET (MREQX8)] ;ATTEMPT TO SWITCH TO VOL OUTSIDE SET
	STOR T2,RSBCV		;SET CURRENT VOLUME # IN RSB
	CALLRET VOLMNT		;GET THE REQUESTED VOLUME MOUNTED
; VRA - ASSOCIATE USER REQUEST AND TAPE VOLUME (IF POSSIBLE)
;  MTA/ ADDR OF MTA STATUS BLOCK OF DRIVE TO BE CHECKED
;  RSB/ ADDR OF USER REQUEST STATUS BLOCK
; RETURNS +1: FAILED, REQUEST MAY BE ABORTED
;	  +2: SUCCESS, MT/ ADDR OF MT STATUS BLOCK

VRA:	SAVEQ
	MOVE T1,MTAFLG(MTA)
	LOAD T2,MTASTE
	CAIN T2,S.AV		;INELIGIBLE IF DRIVE NOT AVAIL TO USERS
	TXNN T1,MA%LOD		;INELIGIBLE IF DRIVE NOT LOADED
	RET
	SKIPN MTAVOL(MTA)	;IS VOLUME IDENTIFIED?
	TXNE T1,MA%SCR		; OR SCRATCH?
	SKIPA			;YES TO EITHER, PROCEED
	RET			;BOTH NO
	JN MTAJCT,,R		;INELIGIBLE IF AVR IN PROGRESS
	JN MTAMT,,R		;INELIGIBLE IF DRIVE IN USE
	LOAD T1,RSBSTE		;GET STATE OF REQUEST
	CAIE T1,RST.WM		;WAITING FOR VOLUME TO BE MOUNTED?
	RET			;NO

; REQUEST AND DRIVE ARE IN THE PROPER STATES... A GOOD SIGN

	MOVEI Q1,VRACCN		;ASSUME NOT REQUESTING SCRATCH
	CALL VQGCV		;GET CURRENT VOLID IN T1
	SKIPN T1		;WANT SCRATCH VOLUME?
	MOVEI Q1,VRACCS		;YES, CALL SCRATCH ROUTINE
	CALL (Q1)		;CALL APPROPRIATE ROUTINE
	 RET			;WRONG VOLUME OR REQUEST ABORTED

; MISCELLANEOUS CHECKS BEFORE I ASSIGN AN MT TO THE USER

	CALL VALPID		;CHECK FOR DELETED PID
	 RET			;REQUEST ABORTED
	CALL REW		;CHECK IF DRIVE IS REALLY LOADED
	 RET			;NO, DON'T ASSIGN
	LOAD T1,MA%WEN,MTAFLG(MTA) ;GET DRIVE WRITE STATUS
	LOAD T2,TM%WEN,RSBUFL(RSB) ;GET REQUESTED WRITE STATUS
	CAME T1,T2		;DO DRIVE AND USER AGREE?
	JRST [	CALL UNLOAD	;NO, UNLOAD THE DRIVE
		CALLRET WOWPE]	;TELL THE OPERATOR TO FIX IT

; GET MT DEVICE FOR THIS REQUEST IF IT DOESN'T ALREADY HAVE ONE

	LOAD MT,RSBMT		;GET MT STATUS BLOCK ADDRESS
	JUMPE MT,[CALL MTGET	;NO MT YET, ANY MT'S AVAILABLE?
		 RET		;NO, FAILED
		JRST .+1]	;MT AC LOADED (NOT ALLOC'ED YET)
	CALL VQCNT		;GET # OF VOLIDS IN REQUEST
	LOAD T2,RSBCV		;GET CURRENT VOLUME #
	CAMGE T1,T2		;ASSIGNING SCRATCH TAPE TO USER?
	JRST [	MOVE T1,MTAVOL(MTA) ;YES, GET VOLID OF TAPE
		CALL VQADD	;TACK VOLID ON THE END OF LIST
		 RET		;REQUEST ABORTED (RESOURCES EXHAUSTED)
		JRST .+1]

; PUT VALUES IN DEFAULTED RSB FIELDS (DENSITY, DRIVE-TYPE, LABEL-TYPE)

	LOAD T1,MTADRV		;DRIVE-TYPE
	LOAD T2,RSBDRV
	SKIPN T2
	STOR T1,RSBDRV
	LOAD T1,MTALT		;LABEL-TYPE
	LOAD T2,RSBLT
	SKIPN T2
	STOR T1,RSBLT
	LOAD T1,RSBLT		;DENSITY
	CAIE T1,.LTUNL		;LABELED?
	JRST [	LOAD T1,MTADEN	;YES
		LOAD T2,RSBDEN
		SKIPN T2
		STOR T1,RSBDEN
		MOVX T1,MA%SCR
		MOVX T2,R%WVL
		TDNE T1,MTAFLG(MTA) ;SCRATCH TAPE?
		IORM T2,RSBIFL(RSB) ;YES, INSURE LABELS GET REWRITTEN
		CALL LTINIT	;WRITE LABELS IF NECESSARY
		 RET		;ERROR
		JRST .+1]

; ALLOC THE MT TO THE USER (HAPPENS WHEN MOUNTING THE FIRST TAPE OF SET)

	LOAD Q1,RSBMT		;HAVE I ALLOC'ED THE MT TO THE USER YET?
	JUMPE Q1,[CALL MTALC	;NO, ALLOC MT TO USER
		 RET		;ALLOC FAILED (USER DISAPPEARED)
		JRST .+1]	;MT DEVICE ALLOC'ED TO USER JOB

; MT DEVICE ASSIGNED TO USER JOB - ASSOCIATE MTA WITH MT

	MOVE T1,MTASET(MTA)	;GET SETNAME FROM TAPE
	SKIPN RSBASN(RSB)	;DOES THIS REQUEST HAVE A SETNAME YET?
	MOVEM T1,RSBASN(RSB)	;NO, USE SETNAME FROM HDR1 ON TAPE
	CALL MTAGJF		;GET MAGTAPE JFN
	MOVEI T2,.MOINF		;GET TAPE INFO
	MOVEI T3,.MOIWF		;LENGTH OF INFO BLOCK
	MOVEM T3,MSTRBK
	MOVEI T3,MSTRBK		;INFO INTO MSTRBK
	MTOPR			;GET IT
	CALL MTARJF		;RELEASE JFN
	MOVE T1,MSTRBK+.MOIRD	;NUMBER OF PHISACAL RECORDS READ
	MOVEM T1,ACCPR(ACC)
	MOVE T1,MSTRBK+.MOIWT	;NUMBER OF PHISICAL RECORDS WRITTEN
	MOVEM T1,ACCPW(ACC)
	MOVE T1,MSTRBK+.MOIRF	;GET FRAMES READ
	IDIVI T1,^D1000		;IN THOUDANDS
	MOVEM T1,ACCFR(ACC)
	MOVE T1,MSTRBK+.MOIWF	;GET FRAMES WRITTEN
	IDIVI T1,^D1000		;IN THOUSANDS
	MOVEM T1,ACCFW(ACC)
	MOVE T1,MSTRBK+.MOISR	;GET NUMBER OF SOFT READ ERRORS
	MOVEM T1,ACCSR(ACC)
	MOVE T1,MSTRBK+.MOISW	;GET NUMBER OF SOFT WRITE ERRORS
	MOVEM T1,ACCSW(ACC)
	MOVE T1,MSTRBK+.MOIHR	;GET NUMBER OF HARD READ ERRORS
	MOVEM T1,ACCHR(ACC)
	MOVE T1,MSTRBK+.MOIHW	;GET NUMBER OF HARD WRITE ERRORS
	MOVEM T1,ACCHW(ACC)
	CALL MOLOC		;ISSUE JSYS TO ASSOCIATE MT WITH MTA
	CALL SCIDIS		;DON'T TAKE INTERRUPTS FROM THIS MTA
	SKIPN Q1		;WAS MT DEVICE JUST GIVEN TO USER?
	CALL TELUSR		;YES, SEND IPCF CONFIRMATION MSG TO USER

; PERFORM MISCELLANEOUS POST-ASSOCIATION TASKS

	GTAD
	LOAD ACC,RSBACC		;GET ADDRESS OF ACCOUNT BLOCK
	MOVEM T1,ACCSVT(ACC)	;STORE SERVICED-TIME
	SKIPE T1,RSBWTB+WTBCOD(RSB) ;WTOR MESSAGE OUTSTANDING?
	CALL CANWTR		;YES, CANCEL IT
	MOVEI T1,RST.AC
	STOR T1,RSBSTE		;SET STATE TO ACTIVE
	STOR MT,MTAMT		;PUT MT STATUS BLK ADDR IN MTA STAT BLK
	STOR MTA,MTMTA		;PUT MTA STATUS BLK ADDR IN MT STAT BLK
	CALL TCKP		;TELL QUASAR ABOUT STATE CHANGE
	MOVX T1,MA%SCR
	ANDCAM T1,MTAFLG(MTA)	;NOT SCRATCH AFTER I GIVE IT TO USER
	CALL WOASO		;TELL OPERATOR ABOUT ASSOCIATION
	RETSKP
; VRACCN - CHECK COMPATIBILITY OF NON-SCRATCH REQUEST AND TAPE VOLUME
;  T1/ SIXBIT VOLID BEING REQUESTED
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: NOT COMPATIBLE OR REQUEST ABORTED
;	  +2: COMPATIBLE

VRACCN:	SAVEQ
	CAME T1,MTAVOL(MTA)	;DO I HAVE THE RIGHT VOLUME?
	RET			;NO
	LOAD T1,RSBDRV		;DID USER SPECIFY A DRIVE TYPE?
	JUMPN T1,[LOAD T2,MTADRV ;YES, GET ACTUAL DRIVE TYPE
		CAMN T1,T2	;DO THEY MATCH?
		JRST .+1	;YES
		ABTRET (MREQ11)] ;NO, ABORT REQUEST
	JN TM%BYP,RSBUFL(RSB),VRACN3 ;IF BYPASS, JUST CHECK DENSITY
	JE MTALT,,[LOAD Q1,MA%AVE,MTAFLG(MTA) ;TAPE NOT AVR'ED YET
		SETONE MA%AVE,MTAFLG(MTA) ;FORCE AVR
		CALL AVR	;INITIATE AVR SEQUENCE
		STOR Q1,MA%AVE,MTAFLG(MTA) ;RESTORE AVR-ENABLED FLAG
		RET]		;YOU HAVE TO WAIT UNTIL AVR IS DONE
	JN R%WVL,RSBIFL(RSB),VRACN2 ;SPECIAL CASE IF WRITING VOL LABELS
	LOAD T1,RSBLT		;CHECK LABEL TYPES
	LOAD T2,MTALT
	JUMPN T1,[CAMN T1,T2	;USER SPECIFIED LT, DOES IT MATCH TAPE?
		JRST .+1	;YES, PROCEED
		ABTRET (MREQ12)] ;NO, LABEL TYPE MISMATCH
	CAIN T2,.LTUNL		;WHAT KIND OF REQUEST?
	JRST VRACN3		;UNLABELED, CHECK DRIVE CAPABILITIES
	LOAD T1,RSBDEN		;DID USER SPECIFY DENSITY?
	JUMPN T1,[LOAD T2,MTADEN ;YES, GET DENSITY OF TAPE
		CAMN T1,T2	;DO REQUEST AND TAPE DENSITIES MATCH?
		JRST .+1	;YES, PROCEED
		ABTRET (MREQ10)] ;MISMATCHED DENSITY
	MOVX T1,TM%VFY
	TDNE T1,RSBUFL(RSB)	;CHECKING SETNAME OF LABELED TAPE?
	JRST [	MOVE T1,RSBSSN(RSB) ;YES, GET SETNAME FROM RSB
		CAMN T1,MTASET(MTA) ;DOES IT MATCH SETNAME OF VOLUME?
		JRST .+1	;YES
		ABTRET (MREQ14)] ;MISMATCHED SET NAME
	RETSKP

; REWRITING VOLUME LABELS

VRACN2:	CALL VRWLT		;LABEL TYPES COMPATIBLE?
	 JRST [	ABTRET (MREQ12)] ;NO, LABEL TYPE MISMATCH

; MAKE SURE THE DRIVE WILL HANDLE THE REQUESTED DENSITY

VRACN3:	LOAD T1,RSBDEN		;ANY DENSITY SPECIFIED?
	JUMPE T1,RSKP		;NO, IT'S OK
	CALL DRVDEN		;WILL THE DRIVE HANDLE IT?
	 JRST [	CALL UNLOAD	;NO, UNLOAD IT
		CALLRET WOWDDR]	;TELL OPERATOR AND POSTPONE REQUEST
	RETSKP			;DRIVE CAN HANDLE THE DENSITY, OK


; VRACCS - CHECK COMPATIBILITY OF SCRATCH REQUEST AND TAPE VOLUME
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: NOT COMPATIBLE
;	  +2: COMPATIBLE

VRACCS:	JE MA%SCR,MTAFLG(MTA),R	;REJECT VOLUME IF NOT A SCRATCH
	LOAD T1,RSBDRV		;GET REQUESTED DRIVE TYPE
	JUMPN T1,[LOAD T2,MTADRV ;GET DRIVE-TYPE OF DRIVE
		CAME T1,T2	;SAME DRIVE TYPE?
		RET		;NO
		JRST .+1]
	LOAD T1,RSBDEN		;GET REQUESTED DENSITY
	JUMPN T1,[CALL DRVDEN	;CAN THE DRIVE OPERATE AT THIS DENSITY?
		 RET		;NO, THIS SCRATCH WON'T WORK
		JRST .+1]
	CALLRET VRWLT		;CHECK IF LABEL TYPES ARE COMPATIBLE


; VRWLT - TAPE VOLUME LABELS WILL BE REWRITTEN - CHECK IF LABEL TYPES
;	  OF REQUEST AND VOLUME ARE COMPATIBLE
;  MTA/ ADDR OF MTA STATUS BLOCK
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: LABELED-UNLABELED OR UNLABELED-LABELED
;	  +2: UNLABELED-UNLABELED OR LABELED-LABELED

VRWLT:	LOAD T1,RSBLT		;GET REQUESTED LABEL TYPE
	JUMPE T1,RSKP		;NOT PARTICULAR, THIS ONE WILL DO
	LOAD T2,MTALT		;GET LABEL TYPE OF TAPE
	MOVE T3,[CAIE T2,.LTUNL] ;ASSUME HE WANTS UNLABELED SCRATCH
	CAIE T1,.LTUNL		;RIGHT?
	HRLI T3,(CAIN T2,)	;NO, WANTS LABELED
	XCT T3			;COMPARE REQUEST AND VOLUME
	 RET			;UNLABELED-LABELED OR LABELED-UNLABELED
	RETSKP			;LABELED-LABELED OR UNLABELED-UNLABELED
SUBTTL SUBROUTINES

; ACTMTA - ACTIVATE AN MTA DEVICE (INITIALIZE STATUS BLOCK, ETC.)
;  MTA/ ADDR OF MTA STATUS BLOCK
;  T1/ MTA STATE CODE
; RETURNS +1: MTA ASSIGNED TO ANOTHER JOB  T1/ OWNING JOB #
;	  +2: SUCCESS, MTA ACTIVATED

ACTMTA:	STKVAR <ACTCOD,<MTOBLK,MOSTAL>>
	MOVEM T1,ACTCOD		;SAVE STATE CODE
	JN MTASTE,,RSKP		;RETURN GOOD IF ALREADY ACTIVATED
; ASSIGN MTA TO MY JOB

	CALL GMTADD		;GET DEVICE DESIGNATOR
	ASND			;TRY TO ASSIGN DEVICE TO MY JOB
	 JRST [	CALL GMTADD	;GET DESIGNATOR
		DVCHR
		HLRZ T1,T3	;GET T1/ OWNER'S JOB#
		RET]

; TRY TO OPEN DRIVE. IF THIS FAILS ANOTHER PROCESS IN THIS JOB IS USING
; THE DRIVE.

	CALL MTAGJF		;GET JFN ON MTA
	MOVX T2,FLD(17,OF%MOD)+FLD(10,OF%BSZ)+OF%OFL+OF%RD
	OPENF			;TRY TO OPEN
	 JRST [	CAIE T1,OPNX9	;SOMEONE ELSE HAS THE DRIVE?
		JRST .+1	;NO IT IS OK
		CALL MTARJF	;YES, DUMP JFN
		SETZM T1	;SET SPECIAL JOB FLAG
		RET ]		;EXIT SADLY
	SETONE MA%OPN,MTAFLG(MTA)	;SET OPEN JFN FLAG
	CALL MTACLS		;CLOSE MTA

; INITIALIZE MTA STATUS BLOCK AND ENABLE FOR STATUS-CHANGE INTERRUPT

	SETZM (MTA)		;ZERO 1ST WORD OF STATUS BLOCK
	MOVS T1,MTA		;BLT SOURCE
	HRRI T1,1(MTA)		;BLT DESTINATION
	BLT T1,MTASZ-1(MTA)	;CLEAR ENTIRE STATUS BLOCK
	MOVE T1,ACTCOD
	STOR T1,MTASTE		;SET STATE
	CALL SCIENA		;RECEIVE STATUS CHANGE INTERRUPTS
	MOVEI T1,MTOBLK		;GET MOSTA ARG BLOCK ADDRESS
	CALL MOSTA		;GET MTA STATUS & CHARACTERISTICS
	MOVE T1,.MODDN+MTOBLK	;GET SUPPORTED DENSITIES
	HLLM T1,MTASDN(MTA)	;STORE SUPPORTED DENSITIES
	LOAD T1,SJ%7TR,.MOTRK+MTOBLK ;GET 7-TRACK FLAG
	MOVE T2,[EXP .TMDR9,.TMDR7](T1) ;GET DRIVE TYPE CODE
	STOR T2,MTADRV		;STORE DRIVE TYPE IN STATUS BLOCK
	TRC T1,1		;GET 0 FOR 7-TRACK, 1 FOR 9-TRACK
	STOR T1,MA%AVS,MTAFLG(MTA) ;STORE AVR-SUPPORTED FLAG
	CALL AVRENA		;ENABLE AVR (IF LEGAL)
	RETSKP
; AREQ - DRIVER FOR ABTREQ MACRO, ABORTS USER REQUEST
; ARET - DRIVER FOR ABTRET MACRO, ABORTS REQUEST AND DOES RET
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; CALL:	ABTREQ (abortcode,flags)
;	 OR
;	ABTRET (abortcode,flags)

AREQ:	SKIPA T2,[AOS (P)]	;GET AREQ INSTRUCTION
ARET:	MOVE T2,[ADJSP P,-1]	;GET ARET INSTRUCTION
	MOVE T1,@(P)		;GET FLAGS AND CODE
	XCT T2			;EXECUTE INSTRUCTION BASED ON ENTRY
	SAVEAC <MT,ACC>
	HRRZ T2,T1		;GET CODE
	TXNE T1,ABT%IN		;INDIRECT?
	MOVE T2,(T2)		;YES, GET CODE FROM LOCATION
	LOAD T3,RSBSTE		;GET CURRENT STATE OF REQUEST
	CAIE T2,ABRTNR		;FORCE STORE IF NO-REPLY ABORT
	CAIGE T3,.ERBAS		;STORE IF REQUEST NOT ABORTED YET
	JRST [	STOR T2,RSBSTE	;STORE CODE INTO RSB STATE FIELD
		LOAD T2,ABT%OP,T1 ;GET OPERATOR-RESPONSE-PRESENT FLAG
		STOR T2,R%ORES,RSBIFL(RSB) ;COPY FLAG TO RSB
		LOAD T1,RSBTYP	;GET REQUEST TYPE
		CAIE T1,.MNTTP	;TAPE-MOUNT?
		JRST .+1	;NO
		JE RSBMT,,.+1	;DON'T UPDATE STATUS IF RSB GOING AWAY
		CALL TCKP	;UPDATE QUASAR QUEUE DISPLAY
		JRST .+1]
	SKIPE T1,RSBWTB+WTBCOD(RSB) ;WTOR MESSAGE OUTSTANDING?
	CALL CANWTR		;YES, CANCEL IT
	LOAD ACC,RSBACC		;CHECK FOR ACCOUNT BLOCK PRESENT.
	SKIPE ACC		;IS THERE AN ACCOUNT BLOCK?
	CALL DELACC		;YES, DELETE IT.
	TXO F,ABORTF		;FORCE PURGE UPON RETURN TO SCHEDULER
	LOAD T1,RSBSTE		;GET REQUEST STATE
	MOVE T2,RSBIFL(RSB)	;GET INTERNAL REQUEST FLAGS
	TXNN T2,R%OPR		;DON'T REPLY TO OPR-ORIGINATED REQUEST
	CAIN T1,ABRTNR		;DON'T REPLY IF NO-REPLY REQUESTED
	RET
	LOAD T1,RSBTYP
	CAIE T1,.MNTTP		;TAPE RSB?
	JRST [	CALLRET TELUSR]	;NO, TELL USER VIA IPCF
	JE RSBMT,,[CALLRET TELUSR] ;TELL USER ON 1ST VOLUME
	CALLRET TELMON		;OTHERWISE TELL MONITOR TO TELL USER
; ASMT - PLACE MT DEVICES IN THE DEVICE ALLOCATOR'S POOL
;	 CALLED DURING INITIALIZATION
; RETURNS +1: ALWAYS

ASMT:	SAVEQ
	SAVEAC <MT,MTA>
	MOVSI Q1,-MAXMT		;RH(Q1)/ MT UNIT NUMBER
	MOVEI MT,MT0		;ADDRESS OF FIRST MT STATUS BLOCK

; LOOP TO PLACE ALL MT DEVICES IN THE DEVICE ALLOCATOR'S POOL

ASMT1:	SETZM (MT)		;CLEAR FIRST WORD OF MT STATUS BLOCK
IFG MTSZ-1,<
	MOVS T1,MT		;BLT SOURCE
	HRRI T1,1(MT)		;BLT DESTINATION
	BLT T1,MTSZ-1(MT)	;CLEAR REMAINDER OF MT STATUS BLOCK
>
	CALL GMTDD		;GET MT DEVICE DESIGNATOR IN T1
	DVCHR			;IS THIS A VALID DESIGNATOR?
	 ERJMP ASMT2		;NO, SKIP NON-DEVICE
	HRRZM Q1,MTN		;SET HIGHEST MT UNIT NUMBER
	MOVE T2,T1		;MOVE DESIGNATOR TO T2 FOR ALLOC
	MOVEI T1,.ALCAL		;GET ALLOC FUNCTION CODE
	MOVNI T3,1		;RELEASE DEVICE TO FREE POOL
	ALLOC			;TRY TO FREE UP THE DEVICE
	 MOVEI T1,.ALCAL	;IGNORE ERROR, RESTORE T1
	MOVNI T3,2		;ASSIGN MT TO ALLOCATOR'S POOL
	ALLOC			;TRY TO ASSIGN TO ALLOCATOR
	 SKIPA			;FAILED
	JRST ASMT2		;ASSIGNED TO ALLOCATOR, GO DO NEXT MT

; CANNOT PUT MT IN ALLOCATOR'S POOL, SO THIS IS PROBABLY A RESTART
; AND THE MT IS STILL IN A USER'S POSSESSION.  THE LOGIC HERE FINDS
; OUT WHAT MTA DEVICE IS ASSOCIATED WITH THE MT, LINKS THEM UP, AND
; BUSYS THEM OUT UNTIL THE USER RELEASES THE MT.

 	MOVEI T1,MTNAV		;CAN'T GET CONTROL OF MT
	STOR T1,MTRSB		;RSB ADDR NON-0 TO PREVENT ALLOCATION
	MOVEI T1,.MTASI		;GET MTU FUNCTION CODE
	HRRZ T2,Q1		;GET MT UNIT #
	MOVEI T3,Q2		;GET ARGUMENT BLOCK ADDRESS (Q2,Q3)
	MOVEI Q2,2		;SET LENGTH IN ARG BLOCK
	MTU%			;ASK MONITOR FOR ASSIGNMENT INFO
	CAIN Q3,.MTNUL		;ANY MTA ASSIGNED TO THIS MT?
	JRST ASMT2		;NO
	MOVE T1,Q3		;GET MTA UNIT #
	HRLI T1,.DVDES+.DVMTA	;MAKE DESIGNATOR
	CALL DDMTA		;GET MTA STATUS BLOCK ADDRESS IN MTA
	 CALL STOP		;BAD MTA UNIT # FROM MONITOR
	MOVEI T1,S.AV		;GET AVAILABLE-TO-USER STATE
	CALL ACTMTA		;ACTIVATE MTA IF POSSIBLE
	 JRST ASMT2		;CAN'T, SO DON'T CROSS-LINK
	STOR MT,MTAMT		;ASSOCIATE MT WITH MTA
	STOR MTA,MTMTA		;...
	SETONE MA%LOD,MTAFLG(MTA) ;SET DRIVE-LOADED FOR KSHS
ASMT2:	ADDI MT,MTSZ		;POINT AT NEXT MT STATUS BLOCK
	AOBJN Q1,ASMT1		;LOOP THRU ALL POSSIBLE MT'S
	AOS MTN			;CONVERT HIGHEST UNIT# TO # OF DEVICES
	RET
; ASMTA - ASSIGN MTA DEVICES TO THIS JOB
;	  CALLED DURING INITIALIZATION
; RETURNS +1: ALWAYS

ASMTA:	SAVEAC <MTA,Q1>
	MOVSI Q1,-MAXMTA	;# OF MTA DEVICES I CAN HANDLE
	MOVEI MTA,MTA0		;ADDRESS OF MTA0: STATUS BLOCK

; LOOP TO CHECK AND POSSIBLY ACTIVATE EVERY MTA DEVICE ON THE SYSTEM

ASMTA1:	SETZRO MTASTE		;SET DRIVE NOT ASSIGNED
	CALL GMTADD		;GET MTA DEVICE DESIGNATOR IN T1
	DVCHR			;IS THIS A VALID DESIGNATOR?
	 ERJMP ASMTA2		;NO, SKIP NON-DEVICE
	HRRZM Q1,MTAN		;STORE HIGHEST MTA UNIT #
	CALL CKMPAV		;IS THIS DRIVE SET AVAILABLE?
	 JRST ASMTA2		;NO, DON'T ASSIGN IT
	MOVEI T1,S.AV		;GET AVAILABLE-TO-USER STATE
	CALL ACTMTA		;ACTIVATE THE MTA
	 JFCL			;DON'T CARE IF I CAN'T ASND
ASMTA2:	ADDI MTA,MTASZ		;POINT AT NEXT MTA STATUS BLOCK
	AOBJN Q1,ASMTA1		;LOOP THROUGH ENTIRE DEVICE TABLE
	AOS MTAN		;CONVERT HIGHEST UNIT# TO # OF DEVICES
	RET
; ASCIZL - COMPUTE THE LENGTH OF AN ASCIZ STRING (NOT COUNTING NULL)
;  T1/ ADDRESS OF STRING
; RETURNS +1: ALWAYS, WITH LENGTH IN BYTES IN T2

ASCIZL:	HRLI T1,(POINT 7)	;CONSTRUCT BYTE POINTER
	SETZ T2,		;CLEAR COUNTER
ASCIL1:	ILDB T3,T1		;LOAD A BYTE
	JUMPE T3,R		;EXIT IF END OF STRING
	AOJA T2,ASCIL1		;OTHERWISE, COUNT IT AND LOOP


; AVRENA - ENABLE AVR FOR DRIVE (IF AVR SUPPORTED FOR THIS DRIVE TYPE)
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

AVRENA:	MOVX T1,MA%AVS
	TDNN T1,MTAFLG(MTA)	;AVR SUPPORTED FOR THIS DRIVE?
	RET			;NO
	MOVX T1,MA%AVE
	IORM T1,MTAFLG(MTA)	;SET AVR-ENABLED
	RET


; BLKFND - SEARCH A GALAXY-STYLE BUILDING BLOCK ARGUMENT LIST FOR
;	   THE LAST OCCURRENCE OF A SPECIFIED ARGUMENT TYPE
;  T1/ ADDRESS OF ARGUMENT COUNT WORD
;  T2/ ADDRESS OF FIRST ARGUMENT BLOCK
;  T3/ TYPE CODE OF DESIRED ARGUMENT
; RETURNS +1: NO ARGUMENTS OF REQUESTED TYPE FOUND
;	  +2: SUCCESS, T1/ ADDRESS OF FIRST WORD OF ARGUMENT
;		       T2/ LENGTH OF ARGUMENT (NOT COUNTING HEADER)

BLKFND:	STKVAR <GETLA>
	SETZM GETLA		;CLEAR ADDRESS OF LAST MATCHING HDR
	SKIPG T1,(T1)		;GET # OF ARGUMENTS
	RET			;NONE ???
BLKFN1:	LOAD T4,AR.TYP,(T2)	;GET ARGUMENT TYPE CODE
	CAMN T3,T4		;DOES IT MATCH THE ONE I WANT?
	MOVEM T2,GETLA		;YES, SAVE ITS ADDRESS
	LOAD T4,AR.LEN,(T2)	;GET LENGTH OF THIS ENTRY
	ADD T2,T4		;COMPUTE ADDRESS OF NEXT ENTRY
	SOJG T1,BLKFN1		;LOOP UNTIL ARG COUNT EXHAUSTED
	SKIPN T1,GETLA		;SCAN COMPLETE, ANY MATCHES?
	RET			;NO
	LOAD T2,AR.LEN,(T1)	;YES, GET SIZE OF ENTRY & HDR
	SOS T2			;SUBTRACT SIZE OF HEADER
	AOJA T1,RSKP		;POINT T1 AT 1ST DATA WORD & RETURN
; CHKAB - CHECK IF MOUNT REQUEST IS ABORTED
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: REQUEST IS ABORTED
;	  +2: REQUEST IS NOT ABORTED

CHKAB:	LOAD T1,RSBSTE		;GET STATE
	CAIL T1,.ERBAS		;ABORTED?
	RET			;YES
	RETSKP			;NO


; CHKID - DETERMINE IF A WORD QUALIFIES AS A LEGAL SIXBIT VOLID/SETNAME
;  T1/ WORD TO BE TESTED
; RETURNS +1: NOT A LEGAL VOLID/SETNAME
;	  +2: LEGAL VOLID SETNAME  T1/ PRESERVED

CHKID:	SKIPN T2,T1		;COPY WORD TO PRESERVE T1
	RET			;ALL BLANKS - ILLEGAL
CHKID1:	SETZ T3,		;CLEAR T3 FOR ROTATING
	ROTC T2,6		;MOVE A CHARACTER FROM T2 INTO T3
	ADJBP T3,[POINT 1,CHKCHR,0] ;GET BYTE POINTER TO BIT
	LDB T3,T3		;IS THIS A LEGAL CHARACTER?
	JUMPE T3,R		;NO, ERROR RETURN
	JUMPN T2,CHKID1		;LOOP IF MORE CHARACTERS LEFT IN T2
	RETSKP			;LOOKS OK TO ME

; TABLE OF LEGAL CHARACTERS FOR VOLIDS AND SETNAMES

CHKCHR:	^B111001111111111111111111111111110111 ;40-103
	^B111111111111111111111110000000000000 ;104-147
; CKBSTR - CHECK GALAXY BUILDING BLOCK STRUCTURE TO VERIFY THAT ALL
;	   BUILDING BLOCKS LIE WITHIN THE STRUCTURE
;  T1/ ENTRY COUNT
;  T2/ ADDRESS OF FIRST ENTRY
;  T3/ SIZE OF STRUCTURE
; RETURNS +1: ERROR WAS DETECTED
;	  +2: NO ERROR DETECTED

CKBSTR:	JUMPL T1,R		;NEGATIVE ENTRY COUNT IS AN ERROR
	JUMPL T3,R		;NEGATIVE STRUCTURE SIZE ALSO AN ERROR
	JUMPE T1,RSKP		;ZERO ENTRY COUNT IS OK
CKBST1:	LOAD T4,AR.LEN,(T2)	;GET SIZE OF THIS ENTRY
	JUMPE T4,R		;ENTRY MUST HAVE A NON-ZERO SIZE
	SUB T3,T4		;SUBTRACT FROM REMAINING STRUCTURE SIZE
	JUMPL T3,R		;ERROR IF BLOCK EXTENDS BEYOND END
	ADD T2,T4		;POINT T2 AT NEXT BLOCK
	SOJG T1,CKBST1		;LOOP THROUGH ALL BLOCKS
	RETSKP			;LOOKS OK TO ME


; CKGHDR - PERFORM BASIC CONSISTENCY CHECK ON INCOMING GALAXY MESSAGE
;  RBUF, MRPDB/ MESSAGE AND PDB
; RETURNS +1: ERROR IN HEADER
;	  +2: HEADER OK,  T1/ SIZE OF MESSAGE IN WORDS
;			  T2/ MESSAGE TYPE

CKGHDR:	HLRZ T2,MRPDB+.IPCFP	;GET ACTUAL SIZE OF MESSAGE FROM PDB
	LOAD T1,MS.CNT,RBUF+.MSTYP ;GET SIZE OF MESSAGE FROM GLX HEADER
	CAIL T1,MSHSIZ		;CRASH IF MSG DOESN'T CONTAIN FULL HDR
	CAMGE T2,T1		;IS MSG AS BIG AS ITS HEADER CLAIMS?
	RET			;NO, ERROR IN HEADER
	LOAD T2,MS.TYP,RBUF+.MSTYP ;GET MESSAGE TYPE FOR CALLER
	RETSKP
; CKMPAV - TEST IF TAPE DRIVE IS AVAILABLE FOR USE BY SYSTEM
;	   BY CHECKING STATUS BIT IN DEVICE-STATUS FILE ENTRY
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: DRIVE NOT AVAILABLE
;	  +2: DRIVE AVAILABLE

CKMPAV:	CALL GMTADD		;GET T1/ MTA DEVICE DESIGNATOR
	CALL DSFTGT		;GET DEVICE STATUS FILE ENTRY FOR DRIVE
	MOVX T1,MTS%AV		;GET AVAILABLE-STATUS BIT
	TDNN T1,DSFE+MTS.SF	;DRIVE AVAILABLE?
	RET			;NO
	RETSKP			;YES


; CLRTAP - ISSUE MTOPR TO CLEAR ERRORS IN MTA DEVICE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: GDSTS TIMED OUT
;	  +2: SUCCESS, AC'S SET UP:
;		T1/ LAST ERROR CODE ENCOUNTERED BY PROCESS
;		T2/ GDSTS T2
;		T3/ # OF BYTES TRANSFERRED (LH OF GDSTS T3)

CLRTAP:	SAVET			;SET UP RETURN VALUES IN STACK
	CALL GETERR		;GET LAST ERROR CODE
	MOVEM T1,CT1		;GIVE TO CALLER
	LOAD T1,MTAJFN		;GET JFN
	IOXCT GDSTS,R,R		;GET STATUS IN T2,T3
	MOVEM T2,CT2		;GIVE T2 TO CALLER VERBATIM
	HLRZM T3,CT3		;PUT # OF BYTES XFERRED IN CALLER'S T3
	MOVEI T2,.MOCLE		;GET CLEAR-ERRORS FUNCTION
	MTOPR			;CLEAR ANY ERROR FLAGS
	 ERCAL STOP
	RETSKP			;RETURN PULLING T1-T4 FROM STACK


; CTIMER - CANCEL ALL TIMER JSYS REQUESTS FOR THIS FORK
; RETURNS +1: ALWAYS

CTIMER:	MOVE T1,[.FHSLF,,.TIMAL] ;FORK,,FUNCTION
	SETZB T2,T3		;PROPITIATE TIMER JSYS
	TIMER			;CANCEL ALL REQUESTS FOR THIS FORK
	 CALL STOP
	RET
; CVTA6 - CONVERT CONTIGUOUS ASCII CHARACTERS TO SIXBIT
; CVTA6R - SAME AS CVTA6, BUT INTERPRET LOWER CASE LETTERS AS UPPER CASE
;  T1/ BYTE POINTER TO FIRST ASCII CHARACTER
;  T2/ NUMBER OF CHARACTERS TO PROCESS
; RETURNS +1: FIELD WAS NOT A LEGAL VOLID OR SETNAME
;	  +2: FIELD WAS A LEGAL VOLID OR SETNAME,  T1/ SIXBIT RESULT

CVTA6:	TDZA T3,T3		;REMEMBER NO-RAISE ENTRY
CVTA6R:	MOVEI T3,1		;REMEMBER RAISE ENTRY
	STAKT
	SETZ T1,		;CLEAR RESULT REGISTER
	MOVE T4,[POINT 6,T1]	;GET BYTE POINTER FOR BUILDING RESULT
CVTA61:	ILDB T3,CT1		;GET NEXT CHARACTER FROM FIELD
	CAIL T3,"a"
	CAILE T3,"z"		;LOWER CASE?
	JRST CVTA62		;NO
	SKIPE CT3		;RAISING LOWER CASE?
	SUBI T3,40		;YES, DO IT
CVTA62:	SUBI T3,40		;CONVERT TO SIXBIT REPRESENTATION
	TRNE T3,777700		;OUT OF RANGE?
	RET			;YES, RETURN ERROR
	IDPB T3,T4		;PACK IT INTO T1
	SOJG T2,CVTA61		;LOOP THRU ALL CHARS IN FIELD
	CALLRET CHKID		;PASS JUDGMENT UPON CONVERTED VALUE


; DACMTA - UNDO THE EFFECTS OF ACTMTA (I.E. DEACTIVATE MTA DEVICE)
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

DACMTA:	JE MTASTE,,R		;RETURN IF ALREADY DONE
	JN MTAJCT,,R		;CAN'T DO IT IF I'M USING THE DRIVE
	JN MTAMT,,R		;CAN'T DO IT IF A USER HAS THE DRIVE
	CALL SCIDIS		;DON'T TAKE INTERRUPTS FROM THIS MTA
	CALL GMTADD		;GET DEVICE DESIGNATOR
	RELD			;RELEASE CONTROL OF DEVICE
	 CALL STOP
	SETZRO MTASTE		;SET MTA NOT ASSIGNED
	RET
; DDMT - CONVERT MT DEVICE DESIGNATOR TO STATUS BLOCK ADDRESS
;  T1/ DEVICE DESIGNATOR
; RETURNS +1: FAILED, NOT A VALID MT DEVICE DESIGNATOR
;	  +2: SUCCESS, MT/ ADDRESS OF MT STATUS BLOCK

DDMT:	HLRZ T2,T1		;GET LEFT HALF OF DESIGNATOR
	CAIN T2,.DVDES+.DVMTA	;CHECK LEFT HALF
	TRZN T1,400000		;CHECK RIGHT HALF
	RET			;SOMETHING'S ROTTEN
	HRRZ MT,T1		;GET UNIT# PART OF DESIGNATOR
	CAML MT,MTN		;DO I KNOW ABOUT IT?
	RET			;NO, ERROR
	IMULI MT,MTSZ		;COMPUTE ADDRESS
	ADDI MT,MT0		; OF STATUS BLOCK
	RETSKP			;SUCCESS


; DDMTA - CONVERT MTA DEVICE DESIGNATOR TO STATUS BLOCK ADDRESS
;  T1/ DEVICE DESIGNATOR
; RETURNS +1: FAILED, NOT A VALID MTA DEVICE DESIGNATOR
;	  +2: SUCCESS, MTA/ ADDRESS OF MTA STATUS BLOCK

DDMTA:	HLRZ T2,T1		;GET LEFT HALF OF DESIGNATOR
	CAIE T2,.DVDES+.DVMTA	;IS IT AN MTA DEVICE?
	RET			;NO, ERROR
	HRRZ MTA,T1		;GET RIGHT HALF OF DESIGNATOR
	CAML MTA,MTAN		;DO I KNOW ABOUT IT?
	RET			;NO, ERROR
	IMULI MTA,MTASZ		;COMPUTE ADDRESS
	ADDI MTA,MTA0		; OF STATUS BLOCK
	RETSKP			;SUCCESS


; DRVDEN - DETERMINE IF DRIVE CAN OPERATE AT A GIVEN DENSITY
;  T1/ DENSITY CODE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: DRIVE CANNOT OPERATE AT THIS DENSITY
;	  +2: DRIVE CAN OPERATE AT THIS DENSITY

DRVDEN:	MOVNS T1		;NEGATE FOR RIGHT SHIFT
	MOVSI T2,(1B0)
	LSH T2,(T1)		;POSITION BIT FOR INTERROGATION
	TDNN T2,MTASDN(MTA)	;CAN THE DRIVE WORK AT THIS DENSITY?
	RET			;NO
	RETSKP			;YES
; DDCTLD - CHECK FOR REQUEST TO ENABLE OR DISABLE ^D INTERCEPT
; RETURNS +1: ALWAYS

DDCTLD:	SKIPGE T1,CDFLG		;HAS A REQUEST BEEN MADE?
	RET			;NO
	SETOM CDFLG		;YES, CLEAR IT
	JUMPE T1,[MOVEI T1,.TICCD ;REQUEST TO DISABLE ^D
		DTI
		TXZ F,CDENF	;RESET ^D-ENABLED
		RET]
	MOVX T1,<.TICCD,,DDTCN>	;REQUEST TO ENABLE ^D
	ATI
	TXO F,CDENF		;SET ^D-ENABLED
	RET

; DDT INTERRUPT PROCESSOR

DDTIH:	CALL DDTLOD		;TRY TO LOAD DDT
	 SKIPA			;NO CAN DO
	CALL 770000		;CALL DDT - RETURN IS R$G
	MOVEI T1,.FHSUP
	MOVX T2,1B0
	TXNN F,CDENF		;DON'T INTERRUPT IF CALLED BY ^D
	IIC			;TRIGGER CHANNEL-0 INTERRUPT UPSTAIRS
	RET			;EXIT TO SCHED

; DDTLOD - LOADS DDT INTO MY ADDRESS SPACE IF NOT ALREADY THERE
; RETURNS +1: ERROR LOADING DDT
;	  +2: DDT LOADED SUCCESSFULLY

DDTLOD:	MOVE T1,[.FHSLF,,770]
	RPACS			;IS DDT LOADED ALREADY?
	JXN T2,PA%PEX,RSKP	;YES, RETURN +2
	MOVX T1,GJ%OLD+GJ%SHT
	HRROI T2,[ASCIZ/SYS:UDDT.EXE/]
	GTJFN
DDTLDX:	 JRST [	TMSG <% MOUNTR Can't find or get DDT>
		JRST JSERR0]	;TYPE MESSAGE AND RETURN +1
	HRLI T1,.FHSLF
	GET
	 ERJMP DDTLDX
	MOVE T1,.JBSYM		;GET ADDRESS OF SYMBOL TABLE
	HRRZ T2,770001		;GET ADDRESS OF WHERE TO STUFF IT
	MOVEM T1,(T2)		;POINT DDT AT MY SYMBOL TABLE
	RETSKP

; REENTER ADDRESS

DEBUG:	MOVE P,[IOWD PDLEN,PDL]	;NEED STACK POINTER FOR CALL
	CALL DDTLOD		;LOAD DDT
	 HALTF			;CAN'T
	JRST 770000		;GO RIGHT TO DDT
; DSFCKS - COMPUTE CHECKSUM OF DEVICE-STATUS FILE BUFFER
; RETURNS +1: ALWAYS, WITH CHECKSUM IN T1

DSFCKS:	MOVE T1,LVERS		;START WITH CURRENT VERSION
	MOVEI T3,DSFSZ-1	;INIT SCANNING POINTER
DSFCK1:	TLZ T1,400000		;POSITIVE
	TRO T1,1		; AND ODD
	MULI T1,400003		;RANDOMIZE
	MOVE T1,T2		;COPY BACK TO T1
	XOR T1,DSBUF(T3)	;MERGE NEXT WORD
	SOJG T3,DSFCK1		;LOOP THRU BUFFER
	RET			;RETURN TO CALLER


; DSFINI - MAPS DEVICE-STATUS FILE INTO DSBUF
; RETURNS +1: ALWAYS

DSFINI:	MOVX T1,GJ%SHT+GJ%ACC	;FLAGS
	HRROI T2,[ASCIZ/SYSTEM:DEVICE-STATUS.BIN/] ;FILESPEC
	GTJFN			;GET JFN ON DEVICE-STATUS FILE
	 RET			;ERROR, GIVE UP
	MOVEM T1,DSFJFN		;SAVE JFN
	MOVX T2,OF%RD+OF%WR	;FLAGS FOR OPENF
	CALL DSFMAP		;TRY OPENING FILE FOR UPDATE
	 TRNA			;CAN'T DO IT
	RET			;OPEN, RETURN
	MOVX T2,OF%WR		;GET FLAGS FOR OPENF
	CALL DSFMAP		;TRY RECREATING THE FILE
	 RET			;NO LUCK...
	RET			;IT WORKED!


; DSFLOC - LOCATE ENTRY FOR SPECIFIED DEVICE IN DEVICE-STATUS FILE
;  DSFE/ DEVICE TYPE
;  DSFE+1/ DEVICE IDENTIFIER
; RETURNS +1: DEVICE NOT REPRESENTED IN FILE
;	  +2: DEVICE ENTRY FOUND, T1/ ADDRESS OF ENTRY

DSFLOC:	SKIPN T4,DSB.NE		;GET # OF ENTRIES TO CHECK
	RET			;NONE, IT AIN'T HERE!
	MOVEI T1,DSB.EO		;START SCAN HERE
	DMOVE T2,DSFE		;GET REQUESTED TYPE AND IDENTIFIER
DSFLC1:	CAME T2,(T1)		;DO DEVICE TYPES MATCH?
	JRST DSFLC2		;NO, SKIP IT
	CAMN T3,1(T1)		;DO IDENTIFIERS MATCH?
	RETSKP			;YES, I FOUND IT
DSFLC2:	ADDI T1,DSFESZ		;POINT AT NEXT ENTRY
	SOJG T4,DSFLC1		;GO CHECK NEXT ENTRY IF THERE IS ONE
	RET			;NOT FOUND, ERROR RETURN
; DSFMAP - MAPS DEVICE-STATUS.BIN INTO DSBUF
;	   INTERNAL SUBROUTINE FOR DSFINI
;  T2/ AC2 FOR OPENF
; RETURNS +1: FAILURE IN I/O JSYS
;	  +2: SUCCESS

DSFMAP:	MOVE T1,DSFJFN		;GET JFN
	TXO T2,OF%DUD		;NO AUTOMATIC UPDATING OF FILE PAGES
	OPENF			;OPEN DEVICE-STATUS FILE
	 RET			;ERROR
	HRLZ T1,DSFJFN		;GET JFN ,, FILE PAGE #
	MOVE T2,[.FHSLF,,DSBUF_-9] ;FORK HANDLE ,, FORK PAGE #
	MOVE T3,[PM%CNT+PM%RWX+PM%PLD+DSFPGS] ;FLAGS,,#PAGES
	PMAP			;MAP THE FILE IN
	 ERJMP [MOVE T1,DSFJFN	;ERROR, GET JFN
		TXO T1,CO%NRJ	;KEEP JFN
		CLOSF		;CLOSE THE FILE
		 JFCL
		RET]		;TAKE ERROR RETURN
	CALL DSFCKS		;COMPUTE CHECKSUM
	CAME T1,DSB.CK		;IS IT RIGHT?
	JRST DSFMA1		;NO
	MOVEI T1,.APRID
	GETAB			;GET APR SERIAL #
	 JFCL			;SHOULD NEVER FAIL
	CAMN T1,DSB.PS		;SAME CPU?
	RETSKP			;OK, THE FILE LOOKS GOOD

; RESET CONTENTS OF DEVICE-STATUS FILE  (T1/ APR SERIAL #)

DSFMA1:	SETZM DSBUF
	MOVE T2,[DSBUF,,DSBUF+1] ;GET BLT POINTER
	BLT T2,DSBUF+DSFSZ-1	;CLEAR REMAINDER OF BUFFER
	MOVEM T1,DSB.PS		;STORE APR SERIAL #
	CALL DSFUPD		;UPDATE PAGES IN FILE
	RETSKP			;ALL DONE, TAKE GOOD RETURN


; DSFPUT - ADD/REPLACE ENTRY IN DEVICE STATUS FILE
;  DSFE/ ENTRY THAT IS TO BE ADDED OR REPLACED
; RETURNS +1: ALWAYS

DSFPUT:	CALL DSFLOC		;DO I KNOW ABOUT IT ALREADY?
	 JRST [	MOVE T1,DSB.NE	;NO, APPEND TO END OF BUFFER
		IMULI T1,DSFESZ	;COMPUTE DISPLACEMENT TO END
		ADDI T1,DSB.EO	;ADD OFFSET TO START OF ENTRY AREA
		AOS DSB.NE	;ADD THIS ENTRY TO THE TOTAL COUNT
		JRST .+1]	;GO INSTALL IT
	MOVEI T2,DSFESZ-1(T1)	;COMPUTE ADDR OF LAST WORD IN DEST
	HRLI T1,DSFE		;BLT SOURCE
	BLT T1,(T2)		;INSTALL ENTRY IN DSBUF
	CALL DSFUPD		;UPDATE COPY OF FILE ON DISK
	RET
; DSFTGT - GET DEVICE-STATUS FILE ENTRY FOR SPECIFIED TAPE DRIVE
;  T1/ DEVICE DESIGNATOR OF TAPE DRIVE
; RETURNS +1: ALWAYS, DSFE/ ENTRY FOR SPECIFIED DRIVE

DSFTGT:	MOVEM T1,DSFE+1		;STORE DESIGNATOR
	MOVEI T1,.DVMTA
	MOVEM T1,DSFE		;STORE DEVICE TYPE
	CALL DSFLOC		;LOOK UP THIS DRIVE
	 JRST [	MOVX T1,MTS%AV	;NOT ON FILE YET
		MOVEM T1,DSFE+MTS.SF ;SET UP DEFAULT ENTRY IN DSFE
		CALLRET DSFPUT]	;ADD DRIVE TO FILE AND RETURN
	MOVSS T1		;FOUND IT, GET BLT SOURCE
	HRRI T1,DSFE		;BLT DESTINATION
	BLT T1,DSFE+DSFESZ-1	;TRANSFER ENTRY TO DSFE
	RET			;FOUND IT, RETURN


; DSFUPD - COMPUTES AND INSTALLS CHECKSUM IN DEVICE-STATUS FILE
;	   BUFFER, THEN WRITES BUFFER OUT TO DISK
; RETURNS +1: ALWAYS

DSFUPD:	CALL DSFCKS		;COMPUTE CHECKSUM OF BUFFER
	MOVEM T1,DSB.CK		;STORE IT
	HRLZ T1,DSFJFN		;GET JFN ,, FIRST PAGE #
	JUMPE T1,R		;OOPS, NO JFN... HEH HEH HEH... BYE!
	MOVEI T2,DSFPGS		;# OF PAGES TO UPDATE
	UFPGS			;WRITE 'EM OUT
	 JFCL			;IGNORE ERRORS
	RET


; ELOGOF - INHIBIT ERROR LOGGING FOR MAGTAPE
; ELOGON - RESTORE ERROR LOGGING FOR MAGTAPE
;  MTA/ ADDR OF MTA STATUS BLOCK (MTA MUST BE OPEN)
; RETURNS +1: ALWAYS, REQUESTED FUNCTION PERFORMED

ELOGON:	TDZA T3,T3		;ENABLE ERROR LOGGING
ELOGOF:	MOVEI T3,1		;INHIBIT ERROR LOGGING
	LOAD T1,MTAJFN		;GET JFN
	MOVEI T2,.MOIEL		;FUNCTION = CONTROL ERROR LOGGING
	IOXCT MTOPR,R,R		;SET DESIRED STATE
	RET
; FNOUT - TRANSLATE A NUMBER INTO RIGHT-JUSTIFIED, ZERO-FILLED ASCII
;  T1/ BYTE POINTER TO FIELD
;  T2/ NUMBER
;  T3/ FIELD SIZE ,, RADIX
; RETURNS +1: ALWAYS

FNOUT:	HLRZ T4,T3		;GET FIELD SIZE
	ADJBP T4,T1		;GET POINTER TO BYTE AFTER FIELD
	ILDB T4,T4		;GET BYTE FOLLOWING FIELD
	TXO T3,NO%LFL+NO%ZRO	;TURN ON FLAGS
	NOUT			;OUTPUT NUMBER
	 JFCL
	IDPB T4,T1		;FIX UP STUPID NULL LEFT BY NOUT
	RET


; GALHDR - CONSTRUCT STANDARD GALAXY HEADER IN TBUF
;  T1/ LENGTH OF MESSAGE (WORDS) ,, MESSAGE TYPE CODE
;  T2/ MESSAGE FLAGS ,, SIXBIT SUFFIX
;  T3/ ACKNOWLEDGMENT CODE
; RETURNS +1: ALWAYS, WITH GALAXY HEADER BUILT IN BEGINNING OF TBUF
; NOTE: THIS IS THE ONLY PLACE WHERE THE GALAXY HEADER IS BUILT
;	IN THE ENTIRE MODULE

GALHDR:	MOVEM T1,TBUF+.MSTYP
	MOVEM T2,TBUF+.MSFLG
	MOVEM T3,TBUF+.MSCOD
	RET


; GETERR - RETURN THE MOST RECENT ERROR CODE FOR THIS FORK
; RETURNS +1: ALWAYS, WITH ERROR CODE IN T1

GETERR:	MOVEI T1,.FHSLF
	GETER			;GET MOST RECENT ERROR IN RH OF T2
	 ERJMP .+1
	HRRZ T1,T2		;MOVE TO T1 STRIPPING LEFT HALF
	RET
; GETVU - TRANSFER USER NAME FROM VOL2 LABEL TO CALLER'S STRING AND
;	  RETURN USER NUMBER CORRESPONDING TO THE USER NAME
;  T1/ ADDRESS OF 8-WORD AREA TO RECEIVE ASCIZ USER NAME
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: T1/ BYTE POINTER TO CALLER'S ASCIZ USER NAME STRING
;	      T2/ USER # CORRESPONDING TO NAME OR 0 IF THE USER DOESN'T
;		  EXIST ON THE SYSTEM

GETVU:	HRLI T1,(POINT 7)	;CREATE BYTE POINTER TO CALLER'S AREA
	SAVET			;RETURN IT TO CALLER IN T1
	MOVEI T2,V2OWN-1
	ADJBP T2,[POINT 8,MTAV2(MTA)] ;GET BYTE PTR TO VOL2 USER NAME
	MOVEI T3,V2OWNL		;GET MAX LENGTH OF USER NAME
GETVU1:	ILDB T4,T2		;GET CHARACTER FROM VOL2
	TRZ T4,200		;MASK OFF TRASH
	CAIN T4," "		;END OF NAME?
GETVU2:	SETZ T4,		;YES, TIE IT OFF WITH A NULL
	IDPB T4,T1		;COPY CHARACTER TO CALLER'S AREA
	JUMPN T4,[SOJG T3,GETVU1 ;LOOP IF MORE LEFT IN VOL2 LABEL
		JRST GETVU2]	;OTHERWISE WRAP UP

; NOW TRY TO IDENTIFY THE USER WITH RCUSR

	SETZM CT2		;RETURN 0 IN T2 IF RCUSR FAILS
	MOVX T1,RC%EMO		;REQUEST EXACT MATCH
	MOVE T2,CT1		;GET POINTER TO CALLER'S STRING
	RCUSR			;TRY TO RECOGNIZE USER NAME
	 ERJMP R		;FAILED
	TXNN T1,RC%NOM		;GOT A MATCH?
	MOVEM T3,CT2		;YES, RETURN USER # IN T2
	RET
; GMTADD - GET MTA DEVICE DESIGNATOR
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS, WITH DEVICE DESIGNATOR IN T1

GMTADD:	MOVE T1,MTA		;COPY STATUS BLK ADDR
	SUBI T1,MTA0		;COMPUTE OFFSET FROM START OF BLOCKS
	IDIVI T1,MTASZ		;COMPUTE MTA UNIT #
	HRLI T1,.DVDES+.DVMTA	;ADD LEFT HALF OF DEVICE DESIGNATOR
	RET


; GMTADS - ISSUE MTOPR AND RETURN MTA DEVICE STATUS
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS, T1/ .MOSTA STATUS WORD .MOCST

GMTADS:	STKVAR <<MTOBLK,MOSTAL>>
	MOVEI T1,MTOBLK		;GET ARG BLOCK ADDRESS
	CALL MOSTA		;GET STATUS & CHARACTERISTICS
	MOVE T1,.MOCST+MTOBLK	;GET STATUS INFO FOR CALLER
	TXNE T1,SJ%OFS		;OFFLINE?
	TXZ T1,SJ%REW		;YES, CAN'T BE REWINDING THEN
	RET


; GMTDD - GET MT DEVICE DESIGNATOR
;  MT/ ADDR OF MT STATUS BLOCK
; RETURNS +1: ALWAYS, WITH DEVICE DESIGNATOR IN T1

GMTDD:	MOVE T1,MT		;COPY STATUS BLK ADDR
	SUBI T1,MT0		;COMPUTE OFFSET FROM START OF BLOCKS
	IDIVI T1,MTSZ		;COMPUTE MT UNIT #
	TDO T1,[.DVDES+.DVMTA,,400000] ;ADD THE FRILLS
	RET
; GTINAM - GET INSTALLATION NAME FROM FILE
; RETURNS +1: ALWAYS, ASCIZ INSTALLATION NAME IN TAPNAM

GTINAM:	MOVX T1,GJ%SHT+GJ%ACC+GJ%OLD
	HRROI T2,[ASCIZ/SYSTEM:TAPNAM.TXT/]
	GTJFN			;GET JFN ON FILE
	 RET			;NO JFN, NO ARBEIT
	MOVE T4,T1		;SAVE JFN
	MOVX T2,FLD(7,OF%BSZ)+OF%RD
	OPENF			;OPEN FILE FOR READ ACCESS
	 JRST [	MOVE T1,T4	;OPEN FAILED, GET JFN
		RLJFN		;DUMP IT
		 JFCL
		RET]
	HRROI T2,TAPNAM		;GET ADDRESS OF TEXT IN CORE
	MOVNI T3,TPNMSZ		;GET MAX # OF BYTES TO READ
	SIN			;READ 'EM IN
	 ERJMP .+1		;IGNORE ERRORS
	CLOSF			;CLOSE FILE, DUMP JFN
	 JFCL
	MOVE T1,[POINT 7,TAPNAM] ;GET POINTER TO TEXT
GTINM1:	ILDB T2,T1		;GET A BYTE
	JUMPE T2,R		;EXIT IF END OF STRING
	CAIE T2,.CHCRT		;CARRIAGE-RETURN?
	JRST GTINM1		;NO, CONTINUE SCAN
	SETZ T2,		;YES
	DPB T2,T1		;DELETE C/R AND EVERYTHING AFTER IT
	RET


; INAP - PERFORM INITIALIZATION RELATED TO ASSOCIATED PROCESSES
; RETURNS +1: ALWAYS

INAP:	SAVEQ
	MOVEI Q1,APNUM		;GET # OF A/P'S
INAP1:	SOJL Q1,R		;EXIT IF NONE LEFT
	CALL @APINI(Q1)		;CALL A/P INIT ROUTINE
	JRST INAP1		;LOOP THRU ALL A/P TABLE ENTRIES

; INT26 - CONVERT INTEGER TO SIXBIT, RIGHT-JUSTIFIED ZERO-FILLED
;  T1/ INTEGER
; RETURNS +1: ALWAYS, T1/ SIXBIT RESULT

INT26:	MOVM T2,T1		;GET ABSOLUTE VALUE
	IDIV T2,[^D1000000]	;GET NUMBER MOD 1000000 IN T3
	MOVE T1,[SIXBIT/000000/] ;INIT RESULT
	MOVE T2,[POINT 6,T1,35]	;GET POINTER TO RESULT
INT261:	IDIVI T3,12		;PEEL OFF A DIGIT
	ADDI T4,20		;CONVERT INTEGER TO SIXBIT
	DPB T4,T2		;STORE INTO T1
	ADD T2,[6B5]		;BACK UP BYTE POINTER
	JUMPN T3,INT261		;LOOP IF MORE TO DO
	RET
; IOXCTR - DRIVER FOR IOXCT MACRO; EXECUTES AND TIMES OUT A JSYS
;  T1-T4/ ARGUMENTS FOR JSYS
; CALL:	IOXCT <JSYS,ERJMP ADDRESS,TIMEOUT ADDRESS>
; RETURNS TO ERJMP ADDRESS IF JSYS ERJMP'ED
;	  TO TIMEOUT ADDRESS IF JSYS TIMED OUT
;	  TO INSTRUCTION AFTER IOXCT MACRO IF JSYS SUCCEEDED
;	ALL RETURNS: T1-T4 CONTAINING VALUES RETURNED BY JSYS

; CAUTION - IN ORDER TO PICK UP THE ARGUMENTS THAT FOLLOW THE CALL,
;	    THIS ROUTINE DOES SOME SHADY THINGS WITH THE STACK

IOXCTR:	CALL [	SAVET		;PRESERVE AC'S FOR JSYS
		MOVE T1,[14,,.SYSTA]
		GETAB		;GET CURRENT LOAD AVERAGE
		 CALL STOP	;SHOULD NEVER FAIL
		FIXR T2,T1	;CONVERT TO AN INTEGER
		IMULI T2,3	;TIMES 3
		CAIGE T2,^D60	;WAIT AT LEAST 60 SECONDS
		MOVEI T2,^D60
		MOVE T1,[.FHSLF,,.TIMEL] ;FORK,,FUNCTION
		IMULI T2,^D1000	;CONVERT SECONDS TO MILLISECONDS
		MOVEI T3,JTOCN	;GET INTERRUPT CHANNEL #
		TIMER		;SET UP FOR INTERRUPT
		 JFCL
		RET]
	TXO F,JTOAF		;SET JSYS-TIMEOUT-ARMED
	XCT @(P)		;EXECUTE JSYS
	 ERJMP [TXZ F,JTOAF	;DISARM TIMER
		CALL [	SAVET
			CALLRET CTIMER] ;CANCEL TIMER
		POP P,CX	;GET ADDRESS OF CALL+1
		HLRZ CX,1(CX)	;GET ERJMP ADDRESS
		JRST (CX)]	;RETURN TO ERJMP ADDRESS
	TXZ F,JTOAF		;DISARM TIMER
	CALL [	SAVET
		CALLRET CTIMER]	;CANCEL TIMER
	AOS (P)			;RETURN TO
	RETSKP			; CALL+3

; INTERRUPT HANDLER FOR TIMER JSYS INTERRUPT

JTOIH:	TXZN F,JTOAF		;TIMER STILL ARMED?
	DEBRK			;NO, DON'T DO ANYTHING
	MOVEM T1,@LEVTAB+PRIEXT-1 ;SAVE T1
	MOVE T1,[PC%USR+IOXCT1]	;GET NEW PC
	EXCH T1,@LEVTAB+PRIEXT-1 ;RESTORE T1, SET NEW PC
	DEBRK			;DEBREAK TO IOXCT1

IOXCT1:	POP P,CX		;TIMEOUT OCCURRED, GET ADDR OF CALL+1
	HRRZ CX,1(CX)		;GET TIMEOUT-HANDLER ADDRESS
	JRST (CX)		;EXIT TO CALLER'S TIMEOUT HANDLER
; LDATIN - PARSE AND RETURN DATE FROM TAPE LABEL (IN FORM " YYDDD")
;  T1/ ILDB POINTER TO FIRST CHARACTER OF DATE FIELD
; RETURNS +1: DATE CONTAINED NON-NUMERIC CHARACTERS OR WAS ILLEGAL
;	  +2: DATE PARSED SUCCESSFULLY,
;		T1/ YEAR,,JULIANDAY   OR   0 (IF DATE WAS " 00000")

LDATIN:	SAVEQ
	IBP T1			;SKIP OVER THE SPACE
	MOVE Q1,T1		;MOVE POINTER TO ANOTHER PLACE
	SETO Q2,		;SET FOR 1ST PASS
LDAT1:	MOVEI T4,3(Q2)		;COMPUTE # OF DIGITS TO SCAN
	SETZ T2,		;CLEAR ACCUMULATOR
LDAT2:	ILDB T3,Q1		;GET NEXT CHARACTER
	CAIL T3,"0"		;ERROR IF .LT. 0
	CAILE T3,"9"		; OR .GT. 9
	RET
	IMULI T2,^D10		;SHIFT CONTENTS OF ACCUMULATOR
	ADDI T2,-"0"(T3)	;ADD IN NEW DIGIT
	SOJG T4,LDAT2		;LOOP
	AOJE Q2,[MOVS T1,T2	;DOING YEAR, GET T1/ YEAR-1900,,0
		JRST LDAT1]	;NOW GO BACK AND DO THE DAY
	JUMPE T2,[JUMPE T1,RSKP	;IF YEAR=DAY=0, RETURN GOOD WITH T1/ 0
		RET]		;IF DAY=0 BUT YEAR.NE.0, ERROR
	CAILE T2,^D366		;IS DAY TOO LARGE?
	RET			;YES, ERROR
	HRR T1,T2		;GET YEAR-1900,,JULIANDAY
	ADD T1,[^D1900,,0]	;ADD IN THE 1900
	RETSKP
; MOSTA - ISSUE .MOSTA MTOPR TO GET TAPE DRIVE CHARACTERISTICS AND STATUS
;	  NOTE - THIS MTOPR FUNCTION MUST BE GUARANTEED NOT TO BLOCK
;  T1/ ADDRESS OF BLOCK TO RECEIVE INFORMATION (MOSTAL WORDS LONG)
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS, WITH INFORMATION IN ARGUMENT BLOCK

MOSTA:	STAKT
	CALL MTAGJF		;GET JFN FOR MTOPR IN T1
	MOVEI T2,.MOSTA		;MTOPR FUNCTION CODE
	MOVE T3,CT1		;GET ADDR OF ARGUMENT BLOCK
	MOVEI T4,MOSTAL
	MOVEM T4,(T3)		;PUT LENGTH IN FIRST WORD OF BLOCK
	MTOPR			;GET STATUS INFO INTO ARG BLOCK
	CALLRET MTARJF		;RELEASE JFN AND RETURN


; MOVSTR - MOVE ASCIZ STRING (TRAILING NULL IS NOT MOVED)
;  T1/ SOURCE STRING POINTER
;  T2/ DESTINATION STRING POINTER
;  STRING POINTERS MAY BE OF THE FORM:  -1,,ADDRESS
; RETURNS +1: ALWAYS

MOVSTR:	TLC T1,-1
	TLCN T1,-1
	HRLI T1,(POINT 7)
	TLC T2,-1
	TLCN T2,-1
	HRLI T2,(POINT 7)
MOVST1:	ILDB T3,T1
	JUMPE T3,R
	IDPB T3,T2
	JRST MOVST1
; MTAGJF - GET A JFN ON MTA DEVICE
;  MTA/ MTA STATUS BLOCK
; RETURNS +1: ALWAYS, WITH JFN IN MTAJFN AND T1

MTAGJF:	JN MTAJCT,,MTAGJ1	;JFN EXISTS ALREADY, USE IT
	STKVAR <<GJFTXT,2>>
	CALL GMTADD		;GET DEVICE DESIGNATOR IN T1
	MOVE T2,T1		;MOVE TO T2 FOR DEVST
	HRROI T1,GJFTXT		;GET ADDRESS OF TEXT BUFFER
	DEVST			;BEGIN JFN STRING WITH "MTAn"
	 CALL STOP
	MOVEI T2,":"
	IDPB T2,T1		;TACK ON A COLON
	SETZ T2,
	IDPB T2,T1		;TERMINATE WITH A NULL
	MOVX T1,GJ%SHT+GJ%ACC	;GTJFN FLAGS
	HRROI T2,GJFTXT		;POINTER TO STRING
	GTJFN			;GET JFN ON MTA DEVICE
	 CALL STOP
	STOR T1,MTAJFN		;STORE JFN IN TABLE
MTAGJ1:	INCR MTAJCT		;INCREMENT JFN-IN-USE COUNT
	LOAD T1,MTAJFN		;GET JFN FOR CALLER
	RET


; MTARJF - RELEASE MTA JFN OBTAINED WITH MTAGJF
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

MTARJF:	LOAD T1,MTAJCT		;GET JFN-IN-USE COUNT
	SOSGE T1		;GOING NEGATIVE?
	CALL STOP		;YES, PROGRAM LOGIC ERROR
	STOR T1,MTAJCT		;STORE NEW COUNT
	JUMPG T1,R		;EXIT IF JFN STILL IN USE
	LOAD T1,MTAJFN		;GET JFN
	RLJFN			;DISCARD IT
	 CALL STOP
	SETZRO MTAJFN		;CLEAR JFN JUST TO PLAY IT SAFE
	RET
; MTAOPI - GET A JFN OPEN FOR READ ON AN MTA DEVICE
; MTAOPO - GET A JFN OPEN FOR WRITE ON AN MTA DEVICE
;  MTA/ ADDR OF MTA STATUS BLOCK (DENSITY SET FROM MTADEN)
; RETURNS +1: FAILED, DRIVE OFFLINE OR WRITE-LOCKED
;	  +2: SUCCESS, JFN IN MTAJFN AND T1

MTAOPI:	SKIPA T1,[OF%RD]	;OPEN FOR READ ACCESS
MTAOPO:	MOVX T1,OF%WR		;OPEN FOR WRITE ACCESS
	SAVEQ
	MOVE Q1,T1		;SAVE MODE
	MOVE T1,MTAFLG(MTA)	;GET MTA FLAGS
	TXNE T1,MA%OPN		;JFN OPEN ALREADY?
	CALL STOP		;YES, PROGRAM FAILURE
	CALL MTAGJF		;GET JFN ON MTA
	MOVX T2,FLD(17,OF%MOD)+FLD(10,OF%BSZ)
	TDO T2,Q1		;SET MODE BIT
	OPENF			;OPEN THE JFN
	 JRST [	CAIN T1,OPNX8	;DEVICE OFFLINE?
		JRST [	SETZRO MA%LOD,MTAFLG(MTA) ;YES, UPDATE STATUS
			CALLRET MTARJF] ;DUMP JFN AND TAKE +1
		CAIE T1,OPNX25	;DEVICE WRITE PROTECTED?
		CALL STOP	;NO, CAN'T HACK THIS ONE
		CALLRET MTARJF]	;YES, DUMP JFN AND TAKE +1
	SETONE MA%OPN,MTAFLG(MTA) ;SET JFN-OPEN FLAG
	MOVEI T2,.MOSDM
	MOVEI T3,.SJDM8		;SPECIFY INDUSTRY-COMPATIBLE MODE
	MTOPR			;SET DATA MODE OF DRIVE
	MOVEI T2,.MOSDN
	LOAD T3,MTADEN		;GET DESIRED DENSITY CODE
	MTOPR			;SET DENSITY
	RETSKP			;RETURN +2, T1/ JFN


; MTACLS - CLOSE MTA JFN
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

MTACLS:	MOVX T1,MA%OPN
	TDNN T1,MTAFLG(MTA)	;IS THE JFN OPEN?
	CALL STOP		;NO, PROGRAM FAILURE
	ANDCAM T1,MTAFLG(MTA)	;IT'LL BE CLOSED WHEN I GET DONE
	LOAD T1,MTAJFN		;GET MTA JFN
	LOAD T2,MTAJCT		;GET JFN-IN-USE COUNT
	SOSGE T2		;GOING NEGATIVE?
	CALL STOP		;YES, PROGRAM LOGIC ERROR
	STOR T2,MTAJCT		;STORE NEW COUNT
	SKIPE T2		;DOES SOMEONE ELSE NEED THE JFN?
	TXO T1,CO%NRJ		;YES, DON'T DUMP JFN, JUST CLOSE IT
	TXO T1,CZ%ABT		;CLOSE WITHOUT BLOCKING
	CLOSF			;CLOSE (AND POSSIBLY DISCARD) JFN
	 CALL STOP
	JUMPN T2,R		;EXIT IF JFN STILL IN USE
	SETZRO MTAJFN		;CLEAR JFN JUST TO PLAY IT SAFE
	RET
; NMTRSB - GET ADDRESS OF NEXT MAGTAPE MOUNT RSB
; NSTRSB - GET ADDRESS OF NEXT STRUCTURE MOUNT OR DISMOUNT RSB
; NXXRSB - GET ADDRESS OF NEXT ACTIVE RSB
;  QSB/ ADDR OF QUEUE SCAN BLOCK FOR ARBQDB
; RETURNS +1: NO RSB'S LEFT
;	  +2: SUCCESS, RSB/ ADDR OF REQUEST STATUS BLOCK

NMTRSB:	SAVEQ
	JSP Q1,NRSB1		;SETUP COROUTINE ADDRESS IN Q1
	CAIE T1,.MNTTP		;COROUTINE FOR TAPE MOUNT
	JRST NRSB1
	RETSKP

NSTRSB:	SAVEQ
	JSP Q1,NRSB1		;SETUP COROUTINE ADDRESS IN Q1
	CAIE T1,.MNTST		;COROUTINE FOR STRUCTURE MNT/DSMNT
	CAIN T1,.DSMST
	RETSKP
	JRST NRSB1

NXXRSB:	SAVEQ
	JSP Q1,NRSB1		;SETUP COROUTINE ADDRESS IN Q1
	RETSKP			;COROUTINE TO SUCCEED FOR ANY RSB

; CHECK NEXT RSB TO SEE IF IT QUALIFIES

NRSB1:	CALL QMSCAN		;GET ADDRESS OF RSB LINKAGE IN T2
	 RET			;END OF RSB LIST
	MOVEI RSB,-RSBLNK(T2)	;LOAD RSB AC
	CALL CHKAB		;REQUEST ABORTED?
	 JRST NRSB1		;YES, SKIP IT
	LOAD T1,RSBTYP		;LIVE RSB, GET TYPE FOR COROUTINE
	JRST (Q1)		;DISPATCH TO COROUTINE
; PB ROUTINES - CONSTRUCT GALAXY-STYLE BUILDING-BLOCK LIST IN TBUF

; PBINIT - SET UP DATABASE FOR CALLS TO OTHER PB ROUTINES
; RETURNS +1: ALWAYS

PBINIT:	XMOVEI T1,TBUF+.OARGC	;GET ADDRESS OF ARGUMENT COUNT WORD
	MOVEI T2,TBUF+.OHDRS	;GET ADDRESS OF FIRST BUILDING BLOCK
	MOVEM T1,PBACW		;SAVE ADDR OF ARGUMENT COUNT WORD
	SETZM (T1)		;ZERO THE ARGUMENT COUNT
	MOVEM T2,PBBPT		;SAVE ADDR OF 1ST BUILDING BLOCK
	RET


; PBBLK - ADD PREFORMATTED BUILDING BLOCK TO LIST
;  T1/ ADDRESS OF BUILDING BLOCK WITH HEADER
; RETURNS +1: ALWAYS

PBBLK:	LOAD T2,AR.LEN,(T1)	;GET LENGTH OF BLOCK
	MOVSS T1		;BLT SOURCE
	HRR T1,PBBPT		;BLT DESTINATION
	ADDB T2,PBBPT		;COMPUTE ADDR OF NEXT BLOCK
	BLT T1,-1(T2)		;MOVE BLOCK INTO LIST
	AOS @PBACW		;BUMP ARG COUNT
	RET


; PBTXT - CONSTRUCT ASCIZ TEXT BUILDING BLOCK
;  T1/ ADDRESS OF ASCIZ TEXT
;  T2/ ARGUMENT TYPE CODE
; RETURNS +1: ALWAYS

PBTXT:	MOVE T4,PBBPT		;GET ADDR OF BLOCK HEADER
	STOR T2,AR.TYP,(T4)	;STORE TYPE CODE IN HEADER
	HRLI T1,(POINT 7)	;GET BYTE POINTER TO SOURCE
	MOVEI T2,1(T4)		;COMPUTE ADDRESS OF TEXT IN BLOCK
	HRLI T2,(POINT 7)	;GET BYTE POINTER TO DESTINATION
PBTXT1:	ILDB T3,T1		;GET BYTE
	IDPB T3,T2		;TRANSFER IT
	JUMPN T3,PBTXT1		;CONTINUE UNTIL I HIT A NULL
	MOVEI T2,1(T2)		;GET ADDR OF WORD AFTER LAST TEXT WORD
	MOVEM T2,PBBPT		;UPDATE BLOCK POINTER
	SUB T2,T4		;COMPUTE LENGTH OF BLOCK
	STOR T2,AR.LEN,(T4)	;PUT LENGTH IN HEADER
	AOS @PBACW		;BUMP ARG COUNT
	RET
; PROTIN - CONVERT 6-DIGIT ASCII PROTECTION CODE TO FIXED-POINT INTEGER
;  T1/ BYTE POINTER TO PROTECTION CODE
; RETURNS +1: CODE CONTAINED AT LEAST 1 NON-OCTAL DIGIT
;	  +2: SUCCESS, T1/ CODE

PROTIN:	MOVE T4,T1		;COPY POINTER TO T4
	SETZ T1,		;INIT VALUE AC
	MOVEI T2,6
PROT1:	ILDB T3,T4		;GET ASCII CHAR
	SUBI T3,"0"
	TRNE T3,777770		;LEGAL OCTAL DIGIT?
	RET			;NO
	LSH T1,3		;YES, SHIFT TO MAKE ROOM
	ADD T1,T3		;ADD IN THIS DIGIT
	SOJG T2,PROT1		;LOOP
	RETSKP
; QUEUE-MANAGING ROUTINES
;	ADD AND REMOVE PACKETS FROM QUEUES; QUEUES ARE DEFINED BY A
;	1-WORD QUEUE DESCRIPTOR WITH ADDRESS OF HEAD PACKET IN LEFT
;	HALF AND ADDRESS OF TAIL IN RIGHT. IF ZERO, QUEUE IS EMPTY.


; QMDQH - DEQUEUE THE HEAD PACKET OF A QUEUE
;  T1/ ADDRESS OF QUEUE DESCRIPTOR BLOCK
; RETURNS +1: QUEUE WAS EMPTY
;	  +2: SUCCESS, T2/ ADDRESS OF DEQUEUED HEAD PACKET

QMDQH:	HLRZ T2,(T1)		;GET ADDRESS OF HEAD PACKET
	JUMPE T2,R		;IF EMPTY, QUIT NOW
	SKIPN T3,(T2)		;QUEUE GOING TO BE EMPTY?
	SETZM (T1)		;YES, CLEAR DESCRIPTOR BLOCK
	HRLM T3,(T1)		;SET NEW HEAD POINTER IN QDB
	RETSKP


; QMQH - ADD A PACKET TO THE HEAD OF A QUEUE
;  T1/ ADDRESS OF QUEUE DESCRIPTOR BLOCK
;  T2/ ADDRESS OF PACKET TO BE ADDED TO HEAD OF QUEUE
; RETURNS +1: ALWAYS

QMQH:	HLRZ T3,(T1)		;GET ADDRESS OF CURRENT HEAD
	HRLM T2,(T1)		;SET ADDRESS OF NEW HEAD IN QDB
	JUMPE T3,[HRRM T2,(T1)	;QUEUE WAS EMPTY, SET NEW TAIL
		SETZM (T2)	;CLEAR LINKAGE IN ONLY ENTRY
		RET]
	MOVEM T3,(T2)		;POINT NEW HEAD AT OLD HEAD
	RET


; QMQT - ADD A PACKET TO THE TAIL OF A QUEUE
;  T1/ ADDRESS OF QUEUE DESCRIPTOR BLOCK
;  T2/ ADDRESS OF PACKET TO BE ADDED TO TAIL OF QUEUE
; RETURNS +1: ALWAYS

QMQT:	SETZM (T2)		;CLEAR LINKAGE IN NEW TAIL
	HRRZ T3,(T1)		;GET CURRENT TAIL ADDRESS
	HRRM T2,(T1)		;SET NEW TAIL
	JUMPE T3,[HRLM T2,(T1)	;QUEUE WAS EMPTY, SET NEW HEAD
		RET]
	MOVEM T2,(T3)		;POINT OLD TAIL AT NEW TAIL
	RET
; ROUTINES ON THIS PAGE ARE USED FOR SCANNING A QUEUE, POSSIBLY
; WITH THE INTENT OF DEQUEUEING ONE OF ITS ENTRIES.

; QUEUE-SCAN-BLOCK (QSB) OFFSETS:

QSB.QB==0		;OFFSET TO QUEUE DESCRIPTOR BLOCK
QSB.LE==1		;OFFSET TO LAST ENTRY SCANNED
QSB.LP==2		;OFFSET TO ENTRY BEFORE LAST ENTRY


; QSCNIR - DRIVER FOR QSCANI MACRO
; CALL:	QSCANI qdb-address

QSCNIR:	PUSH P,QSB		;SAVE QSB AC
	MOVEI QSB,1(P)		;GET ADDRESS OF QSB IN STACK
	PUSH P,(CX)		;QSB.QB - QDB ADDRESS
	PUSH P,[0]		;QSB.LE - ADDRESS OF LAST ENTRY SCANNED
	PUSH P,[0]		;QSB.LP - ADDRESS OF ENTRY BEFORE THAT
	CALL 1(CX)		;BACK TO CALLER FOR A WHILE
	 TRNA			;NON-SKIP RETURN
	AOS -4(P)		;SKIP RETURN
	ADJSP P,-3		;DELETE QSB FROM STACK
	POP P,QSB		;RESTORE QSB AC
	RET			;TAKE +1 OR +2


; QMSCAN - RETURN ADDRESS OF NEXT ENTRY IN QUEUE
;  QSB/ ADDRESS OF QUEUE SCAN BLOCK
; RETURNS +1: NO ENTRIES REMAINING IN QUEUE
;	  +2: SUCCESS, T2/ ADDRESS OF NEXT ENTRY IN QUEUE

QMSCAN:	SKIPN T2,QSB.LE(QSB)	;FIRST CALL FOR THIS QUEUE SCAN?
	JRST [	SETZM QSB.LP(QSB) ;YES, CLEAR OLD-LAST ADDRESS
		HLRZ T2,@QSB.QB(QSB) ;GET ADDRESS OF HEAD PACKET
		JRST QMS1]
	MOVEM T2,QSB.LP(QSB)	;NOT FIRST TIME, SET OLD-LAST
	MOVE T2,(T2)		;GET ADDRESS OF NEXT PACKET
QMS1:	MOVEM T2,QSB.LE(QSB)	;SET NEW-LAST
	JUMPN T2,RSKP		;TAKE +2 IF I FOUND SOMETHING
	RET			;OTHERWISE +1

; QMDQS - DEQUEUE LAST PACKET RETURNED BY QMSCAN
;  QSB/ ADDRESS OF QUEUE SCAN BLOCK
; RETURNS +1: ALWAYS, T2/ ADDRESS OF DEQUEUED PACKET

QMDQS:	MOVE T2,QSB.LE(QSB)	;GET ADDRESS OF ENTRY TO BE DEQUEUED
	MOVE T3,QSB.LP(QSB)	;GET ADDRESS OF PREVIOUS ENTRY
	MOVEM T3,QSB.LE(QSB)	;FIX LE IN CASE QMSCAN IS CALLED AGAIN
	SKIPN T4,(T2)		;GET ADDR OF FOLLOWING ENTRY
	HRRM T3,@QSB.QB(QSB)	;IF DEQING TAIL, SET NEW TAIL IN QDB
	JUMPE T3,[HRLM T4,@QSB.QB(QSB) ;DEQING HEAD, SET NEW HEAD IN QDB
		RET]
	MOVEM T4,(T3)		;NOT HEAD, FIX LINKAGE IN PREDECESSOR
	RET
; REW - INITIATES A REWIND OPERATION ON AN MTA
; REWEA - LIKE REW, BUT ALSO SCHEDULES A CALLER-SPECIFIED ROUTINE
;	  WHEN THE REWIND IS COMPLETE
;  T1/ ADDRESS OF END-ACTION ROUTINE THAT WILL BE ENTERED WHEN
;      REWIND OPERATION IS COMPLETE (REWEA ONLY)
;  MTA/ ADDR OF STATUS BLOCK
; RETURNS +1: DEVICE OFFLINE OR TIMED OUT
;	  +2: REWIND OPERATION INITIATED
;		CONTROL IS GIVEN TO END-ACTION ROUTINE WHEN REWIND
;		COMPLETES. MTA AC WILL HAVE ADDR OF MTA STATUS BLK.
; NOTE: SINCE NOT ALL THE MAGTAPE HARDWARE IS CONSCIENTIOUS ABOUT
;	REPORTING STATUS CHANGES, THIS PROGRAM RELIES HEAVILY UPON
;	DEVICE OPERATIONS (IN PARTICULAR, REWIND) TO DETERMINE THE
;	LOADED/UNLOADED STATUS OF A TAPE DRIVE. THE BASIC LINE OF
;	REASONING IS: IF SJ%OFS IS SET THEN BELIEVE IT; IF IT IS
;	RESET, CHECK FOR ONLINE/OFFLINE BY ISSUING A REWIND MTOPR.

REW:	SETZ T1,
REWEA:	SAVEQ
	MOVEI Q3,1		;SET UP FOR SUCCESSFUL RETURN
	MOVE Q2,T1		;SAVE END-ACTION ADDRESS
	LOAD T1,MTAREA
	SKIPE T1		;END-ACTION ALREADY REQUESTED?
	CALL STOP		;YES, PROGRAM LOGIC FAILURE
	CALL MTAGJF		;GET JFN NOW TO LIMIT GTJFN CALLS
	CALL GMTADS		;GET MTA DEVICE STATUS
	JXN T1,SJ%OFS,[SETZRO MA%LOD,MTAFLG(MTA) ;OFFLINE, SAY SO
		CALLRET MTARJF] ;DUMP JFN AND GIVE ERROR RETURN
	JXN T1,SJ%REW,[CALL MTARJF ;REWINDING ALREADY, DUMP JFN
		STOR Q2,MTAREA	;SET END-ACTION ADDRESS
		RETSKP]		;TAKE SUCCESSFUL RETURN
	LOAD Q1,MA%OPN,MTAFLG(MTA) ;IS MTA JFN OPEN ALREADY?
	JUMPE Q1,[CALL MTAOPI	;NO, OPEN IT
		 SKIPA		;OFFLINE
		JRST .+1	;OPENED
		CALLRET MTARJF] ;DUMP JFN AND GIVE ERROR RETURN
	CALL MTARJF		;UN-NEST PRIOR MTAGJF
	CALL ELOGOF		;DON'T LOG ERRORS
	MOVEI T1,.MOREW
	MOVEI T2,1		;REPEAT COUNT
	CALL XMTOPR		;INITIATE REWIND
	 SETZ Q3,		;OFFLINE OR TIMED OUT, SET +1 RETURN
	CALL ELOGON		;RESTORE ERROR LOGGING
	STOR Q3,MA%LOD,MTAFLG(MTA) ;SET STATE (LOADED/UNLOADED)
	SKIPN Q1		;SKIP IF I DIDN'T OPEN MTA
	CALL MTACLS		;I OPENED IT, SO I'LL CLOSE IT
	JUMPE Q3,R		;TAKE ERROR RETURN IF INDICATED
	STOR Q2,MTAREA		;GOOD RETURN, SET END-ACTION ADDR
	RETSKP
; SCIDIS - DISABLE STATUS-CHANGE INTERRUPTS FROM MTA DEVICE
; SCIENA - ENABLE STATUS-CHANGE INTERRUPTS FROM MTA DEVICE
;	WHEN A TAPE DRIVE IS ENABLED FOR STATUS-CHANGE INTERRUPTS, THE
;	FOLLOWING EVENTS CAUSE A PSI INTERRUPT ON CHANNEL "TDSCCN":
;	TRANSITION TO ONLINE, TRANSITION TO OFFLINE, REWIND COMPLETE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

SCIDIS:	SKIPA T2,[0,,-1]
SCIENA:	MOVEI T2,TDSCCN
	MOVEI T1,2		;BUILD ARG BLOCK IN CT1 AND CT2
	STAKT
	CALL MTAGJF		;GET JFN ON MTA
	MOVEI T2,.MOOFL		;MTOPR FUNCTION CODE
	MOVEI T3,CT1		;GET ADDRESS OF ARG BLOCK
	MTOPR			;ENABLE OR DISABLE
	CALLRET MTARJF		;DUMP JFN AND EXIT


; SIXASC - CONVERT SIXBIT WORD TO ASCII STRING
;  T1/ SIXBIT WORD
;  T2/ BYTE POINTER TO ASCII DESTINATION STRING
; RETURNS +1: ALWAYS, 6 CHARACTERS PLACED IN DESTINATION STRING

SIXASC:	MOVE T4,T2		;MOVE POINTER OUT OF T2
	MOVEI T3,6
SIXAS1:	SETZ T2,		;CLEAR FOR SHIFT
	ROTC T1,6		;GET A SIXBIT CHARACTER
	ADDI T2,40		;CONVERT TO ASCII
	IDPB T2,T4		;STORE CHARACTER
	SOJG T3,SIXAS1
	RET
; SAVEQR - DRIVER FOR SAVEQ MACRO

SAVEQR:	ADJSP P,3		;CREATE ROOM ON STACK FOR Q1-Q3
	DMOVEM Q1,-2(P)		;STACK Q1 & Q2
	MOVEM Q3,0(P)		;STACK Q3
	CALL (CX)		;BACK TO CALLER
	 TRNA			;NON-SKIP RETURN
	AOS -3(P)		;SKIP RETURN
	DMOVE Q1,-2(P)		;RESTORE Q1 & Q2
	MOVE Q3,0(P)		;RESTORE Q3
	ADJSP P,-3		;DELETE TEMP SPACE FROM STACK
	RET			;BACK TO CALLER'S CALLER +1 OR +2

; SAVETR - DRIVER FOR SAVET MACRO

SAVETR:	ADJSP P,4		;CREATE ROOM ON STACK FOR T1-T4
	DMOVEM T1,-3(P)		;STACK T1 & T2
	DMOVEM T3,-1(P)		;STACK T3 & T4
	CALL (CX)		;BACK TO CALLER
	 TRNA			;NON-SKIP RETURN
	AOS -4(P)		;SKIP RETURN
	DMOVE T1,-3(P)		;RESTORE T1 & T2
	DMOVE T3,-1(P)		;	 T3 & T4
	ADJSP P,-4		;DELETE TEMP SPACE FROM STACK
	RET			;BACK TO CALLER'S CALLER +1 OR +2

; STAKTR - DRIVER FOR STAKT MACRO

STAKTR:	ADJSP P,4		;CREATE ROOM ON STACK FOR T1-T4
	DMOVEM T1,-3(P)		;STACK T1 & T2
	DMOVEM T3,-1(P)		;STACK T3 & T4
	CALL (CX)		;BACK TO CALLER
	 TRNA			;NON-SKIP RETURN
	AOS -4(P)		;SKIP RETURN
	ADJSP P,-4		;DELETE TEMP SPACE FROM STACK
	RET			;BACK TO CALLER'S CALLER +1 OR +2
; SMPAV - SET AVAILABLE STATUS OF TAPE DRIVE
;  T1/ 0 TO SET DRIVE UNAVAILABLE, 1 TO SET DRIVE AVAILABLE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

SMPAV:	STAKT
	CALL GMTADD		;GET DESIGNATOR
	CALL DSFTGT		;GET DEVICE STATUS FILE ENTRY FOR DRIVE
	MOVE T1,CT1		;GET AVAILABLE OR UNAVAILABLE FLAG
	STOR T1,MTS%AV,DSFE+MTS.SF ;STORE FLAG
	CALLRET DSFPUT		;PUT ENTRY BACK IN FILE AND RETURN


; STMTA - CONVERT AN ASCIZ STRING TO AN MTA STATUS BLOCK ADDRESS
;  T1/ ADDRESS OF ASCIZ STRING FOR MTA (IN FORM SUITABLE FOR STDEV JSYS)
; RETURNS +1: STRING DOES NOT SPECIFY MTA DEVICE
;	  +2: MTA/ ADDR OF MTA STATUS BLOCK

STMTA:	HRLI T1,-1		;GET STRING POINTER TO ASCIZ DEVNAME
	STDEV			;TRANSLATE STRING TO DEV DESIGNATOR
	 RET			;NOT A DEVICE
	MOVE T1,T2		;GET DESIGNATOR
	CALLRET DDMTA		;CONVERT TO MTA STATUS BLOCK ADDR IN MTA


; STOP - A FATAL ERROR WAS DETECTED; PROGRAM MUST HALT
; INVOKED BY:
;	CALL STOP

STOP:	MOVEM 17,CRSHAC+17	;SAVE AC'S FROM CRASH
	MOVEI 17,CRSHAC
	BLT 17,CRSHAC+16
	MOVEI T1,.FHSLF
	SETZ T2,
	GETER			;GET MOST RECENT ERROR
	 ERJMP .+1
	HRRZM T2,LSTERR		;STORE IT FOR ANALYSIS
	DIR			;DISABLE ALL INTERRUPTS
	TMSG <

?MOUNTR crashing, PC = >
	MOVEI T1,.PRIOU
	HRRZ T2,CRSHAC+P	;GET TOP-OF-STACK ADDRESS
	HRRZ T2,(T2)		;GET ADDRESS OF CALL + 1
	SOS T2			;GET ADDRESS OF CALL
	MOVE T3,[NO%ZRO+NO%LFL+FLD(6,NO%COL)+10]
	NOUT			;TYPE PC
	 JFCL
	SKIPE TSTF		;TESTING?
	JRST [	TMSG <
Test flag set, not saving MOUNTR core image> ;YES, DON'T SAVE CORE IMAGE
		JRST STOP1]

; SAVE CORE IMAGE IN CRASH FILE

	MOVX T1,GJ%SHT+GJ%FOU+GJ%ACC
	HRROI T2,CFSPEC		;GET POINTER TO FILESPEC
	GTJFN			;GET JFN ON CRASH FILE
	 JRST STOP2
	MOVE Q2,T1		;COPY JFN TO A SAFE PLACE
	TMSG <
Saving MOUNTR core image on file >
	MOVEI T1,.PRIOU
	MOVE T2,Q2		;JFN
	SETZ T3,
	JFNS			;DISPLAY FILESPEC
	 ERJMP STOP2
	MOVSI T1,.FHSLF
	HRR T1,Q2		;FORK HANDLE,,JFN
	MOVE T2,[-1000,,SS%CPY]	;ALL PAGES OF PROCESS, COPY-ON-WRITE
	SETZ T3,
	SSAVE			;SAVE CORE IMAGE
	 ERJMP STOP2
	JRST STOP1		;SKIP AROUND FAILURE-PROCESSOR

; ERROR SAVING CORE IMAGE, REPORT IT

STOP2:	TMSG <
?Cannot save MOUNTR core image: >
	MOVEI T1,.PRIOU
	HRLOI T2,.FHSLF		;FORK HANDLE ,, -1 (MOST RECENT ERROR)
	SETZ T3,		;NO LIMIT
	ERSTR			;SHOW WHY SAVE FAILED
	 JFCL
	 JFCL
STOP1:	MOVSI 17,CRSHAC		;GET BLT SOURCE,,DESTINATION
	BLT 17,17		;RESTORE AC'S TO CRASH STATE
	HALTF

; STOPP - STOP BECAUSE OF SOME KIND OF STACK PROBLEM
; INVOKED BY:
;	JSP CX,STOPP

STOPP:	MOVEM P,BADP		;SAVE BAD P
	MOVE P,[IOWD 4,PDL1]	;GET NEW P SO PDL IS PRESERVED
	CALL STOP		;NOW CRASH

; PANIC INTERRUPT HANDLERS - PROGRAM IS CRASHING
; DATA ERROR IS NON FATAL AND IS REPORTED

PANPOV:	JSP CX,STOPP		;PDL OVERFLOW
PANDAE:	EXCH T1,@LEVTAB+PRIPAN-1 ;GET RETURN PC
	MOVEM T1,DAEPC		;SAVE IT
	EXCH T1,@LEVTAB+PRIPAN-1 ;RESTORE T1 AND PC
	SOS DAEPC		;PC OF INTERRUPT
	CALL EIHR		;SCHEDULE
	EXP DAEIH		;ROUTINE TO SCHEDULE	
PANQTA:	CALL STOP		;QUOTA EXCEEDED
PANILI:	CALL STOP		;ILLEGAL INSTRUCTION
PANIRD:	CALL STOP		;ILLEGAL READ
PANIWR:	CALL STOP		;ILLEGAL WRITE
PANMSE:	CALL STOP		;MACHINE SIZE EXCEEDED

; DAEIH - INFORM OPERATOR OF A DATA ERROR.
; RETURNS +1 ALWAYS

DAEIH:	MOVE T1,DAEPC		;GET PC OF ERROR
	TMCT <%IData Error encountered. PC= %1O Last Error: %J>
	MOVEI T3,[ASCIZ/MOUNTR System Task Error/]
	CALLRET BTWTO		;TELL OPERATOR
; SYTSET - BUILD AND LOG SYSERR ENTRY FOR TAPE DRIVE STATUS CHANGE
;  T1/ FUNCTION CODE (CS%ADV = SET AVAILABLE, CS%DDV = SET UNAVAILABLE)
;  T2/ ADDRESS OF ASCIZ REASON, OR 0 IF NO REASON GIVEN
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

SYTSET:	SAVEQ
	STKVAR <<SYTA,.MOISN+1>>
	SETZM SYRMSG		;ZERO OUT SYSERR MESSAGE AREA
	MOVE T4,[SYRMSG,,SYRMSG+1]
	BLT T4,SYRMSG+SYRMSZ-1

; TRANSFER OPERATION CODE AND REASON TO MESSAGE

	STOR T1,CS%OPR,SYRMSG+CS%OPW ;STORE OPERATION CODE INTO MESSAGE
	MOVEI Q1,SYRHSZ+CS%SIZ	;ASSUME NO REASON GIVEN
	SKIPN T1,T2		;REASON GIVEN?
	JRST SYTSE1		;NO
	MOVS Q2,T1		;YES, COPY ADDRESS OF STRING FOR BLT
	CALL ASCIZL		;GET # OF CHARACTERS
	IDIVI T2,5		;GET # OF WORDS MINUS 1
	CAIL T2,SYRMSZ		;TOO LONG?
	MOVEI T2,SYRMSZ-1	;YES, TRUNCATE
	MOVEI Q1,SYRHSZ+CS%SIZ+1(T2) ;SAVE SIZE OF ENTIRE MESSAGE
	HRRI Q2,SYRMSG+CS%SIZ	;GET BLT DESTINATION
	BLT Q2,SYRMSG+CS%SIZ(T2) ;TRANSFER STRING TO MESSAGE
	MOVEI T1,CS%SIZ
	STOR T1,CS%RSN,SYRMSG+CS%RSW ;STORE POINTER TO REASON
SYTSE1:	MOVEI T1,SEC%CS		;GET CONFIGURATION STATUS CHANGE CODE
	DPB T1,[POINT 9,SYRHDR,8] ;STORE INTO SYSERR ENTRY HEADER

; BUILD AND STORE SIXBIT DEVICE NAME (E.G. MTA0)
; (CAN'T STORE CHANNEL TYPE BECAUSE I DON'T KNOW IT)

	CALL GMTADD		;GET MTA DEVICE DESIGNATOR
	MOVE T2,T1		;TO T2 FOR DEVST
	HRROI T1,SYTA		;GET ADDR OF STRING AREA
	DEVST			;GET ASCIZ DEVICE NAME (E.G. MTA0)
	 SETZM SYTA		;SHOULD NEVER FAIL
	MOVEI T1,SYTA		;GET ADDR OF STRING
	CALL ASCIZL		;GET LENGTH OF STRING FOR CVTA6
	MOVSI T1,(POINT 7)
	HRRI T1,SYTA		;GET POINTER TO STRING
	CALL CVTA6		;GET SIXBIT DEVICE NAME IN T1
	 SETZ T1,		;SHOULDN'T FAIL
	MOVEM T1,SYRMSG+CS%DNM	;STORE SIXBIT DEVICE NAME

; GET DEVICE ADDRESS AND SERIAL#

	JE MTASTE,,R		;DON'T BOTHER IF DEVICE NOT ASSIGNED
	MOVEI T1,.MOISN
	MOVEM T1,.MOICT+SYTA	;SET ARG BLOCK LENGTH IN ARG BLOCK
	CALL MTAGJF		;GET MTA JFN IN T1
	MOVEI T2,.MOINF		;GET MTOPR FUNCTION CODE
	MOVEI T3,SYTA		;GET ADDRESS OF ARG BLOCK
	MTOPR			;GET MTA INFO FROM MONITOR
	CALL MTARJF		;DUMP JFN
	MOVE T1,.MOISN+SYTA	;GET UNIT ADDRESS AND SERIAL#
	MOVEM T1,SYRMSG+CS%ADS	;STORE IN SYSERR MESSAGE
	MOVE T1,.MOITP+SYTA	;GET DRIVE TYPE CODE
	STOR T1,CS%UTP,SYRMSG+CS%HTP ;STUFF IT

; LOG THE MESSAGE

	MOVEI T1,SYRHDR		;GET ADDRESS OF SYSERR MESSAGE
	MOVE T2,Q1		;GET # OF WORDS IN MESSAGE
	SKIPN TSTF		;DON'T LOG SYSERRS IF TESTING
	SYERR			;LOG IT
	 ERJMP R		;IGNORE ERRORS
	RET
; UNLOAD - UNLOAD A VOLUME FROM AN MTA DEVICE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

UNLOAD:	SAVEQ
	CALL MTAGJF		;GET JFN NOW TO LIMIT GTJFN CALLS
	CALL GMTADS		;GET DEVICE STATUS IN T1
	JXN T1,SJ%OFS,[SETZRO MA%LOD,MTAFLG(MTA) ;OFFLINE, SAY SO
		CALLRET MTARJF] ;DUMP JFN AND RETURN
	JXN T1,SJ%REW,[SETONE MA%ULP,MTAFLG(MTA) ;SET UNLOAD-PENDING
		CALLRET MTARJF]	;DUMP JFN AND RETURN
	SETZRO MA%LOD,MTAFLG(MTA) ;SET STATUS TO UNLOADED
	LOAD Q1,MA%OPN,MTAFLG(MTA) ;IS MTA JFN OPEN ALREADY?
	JUMPE Q1,[CALL MTAOPI	;NO, OPEN IT
		 SKIPA		;OFFLINE
		JRST .+1	;OPENED
		CALLRET MTARJF] ;DUMP JFN AND GIVE ERROR RETURN
	CALL MTARJF		;UN-NEST PRIOR MTAGJF
	CALL ELOGOF		;DON'T LOG ERRORS
	MOVEI T1,.MORUL
	MOVEI T2,1		;REPEAT COUNT
	CALL XMTOPR		;INITIATE REWIND-AND-UNLOAD
	 CALL XMTREP		;REPORT UNLOAD ERROR
	CALL ELOGON		;RESUME LOGGING ERRORS
	JUMPN Q1,R		;EXIT IF I DIDN'T OPEN MTA
	CALLRET MTACLS		;I OPENED IT, SO I'LL CLOSE IT
; VQADD - APPEND A NEW VOLID TO THE END OF THE RSB VOLID LIST
;  T1/ SIXBIT VOLID
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: NO SLOTS LEFT IN VOLID POOL, REQUEST ABORTED
;	  +2: SUCCESS

VQADD:	STAKT
	MOVEI T1,FVSQDB		;POINT TO FREE POOL QDB
	CALL QMDQH		;DEQUEUE HEAD OF FREE CHAIN
	 JRST [	ABTRET (MREQ31)] ;NO FREE SLOTS, ABORT REQUEST
	MOVE T1,CT1		;T2/ SLOT ADDR, GET VOLID
	MOVEM T1,1(T2)		;STORE VOLID IN SLOT
	MOVEI T1,RSBVLS(RSB)	;GET ADDR OF RSB VOLID LIST QDB
	CALL QMQT		;ADD NEW VOLID TO END OF RSB VOLID QUEUE
	RETSKP


; VQCNT - RETURN THE LENGTH OF THE RSB VOLID LIST
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS, T1/ LENGTH OF VOLID LIST

VQCNT:	SETZ T1,		;CLEAR COUNTER
	HLRZ T2,RSBVLS(RSB)	;GET HEAD OF QUEUE
VQCNT1:	JUMPE T2,R		;END OF QUEUE, RETURN
	MOVE T2,(T2)		;NOT THE END, GET ADDR OF NEXT ENTRY
	AOJA T1,VQCNT1		;COUNT THIS ENTRY AND LOOP


; VQDEL - RETURN RSB VOLID QUEUE TO FREE VOLID SLOT POOL
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS

VQDEL:	SKIPN T1,RSBVLS(RSB)	;IS QUEUE EMPTY?
	RET			;YES, NOTHING TO DO
	SETZM RSBVLS(RSB)	;CLEAR QDB IN RSB
	HRRZ T2,FVSQDB		;GET CURRENT FREE POOL TAIL
	JUMPE T2,[MOVEM T1,FVSQDB ;NO FREE POOL, SO CREATE IT
		RET]
	HLRZM T1,(T2)		;POINT CURRENT TAIL AT RSB LIST HEAD
	HRRM T1,FVSQDB		;SET TAIL OF FREE POOL TO RSB TAIL
	RET
; VQGCV - GET CURRENT VOLID FOR TAPE MOUNT REQUEST
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: ALWAYS, T1/ 0 IF SCRATCH TAPE, ELSE SIXBIT VOLID

VQGCV:	LOAD T1,RSBCV		;GET CURRENT VOLUME #
	CALL VQGET		;GET VOLID IN T1
	 SETZ T1,		;BAD INDEX, MUST BE A SCRATCH
	RET


; VQGET - RETURN A VOLID FROM RSB VOLID LIST
; VQSET - STORE A VOLID INTO RSB VOLID LIST
;  T1/ ORDINAL NUMBER OF VOLID TO BE RETURNED
;  T2/ SIXBIT VOLID TO BE STORED (VQSET ONLY)
;  RSB/ ADDR OF REQUEST STATUS BLOCK
; RETURNS +1: VOLID NUMBER OUT OF RANGE
;	  +2: SUCCESS, T1/ SIXBIT VOLID

VQGET:	SKIPA T3,[MOVE T1,1(T2)]
VQSET:	MOVE T3,[MOVEM T1,1(T2)]
	JUMPLE T1,R		;CHECK FOR FUNNY INPUT
	QSCANI <RSBVLS(RSB)>	;SET UP TO SCAN RSB VOLID LIST
	STAKT
VQGET1:	CALL QMSCAN		;GET NEXT VOLID IN LIST
	 RET			;NONE LEFT, FAILED
	SOSLE CT1		;IS THIS THE ONE THE CALLER WANTED?
	JRST VQGET1		;NO, CONTINUE SCAN
	MOVE T1,CT2		;GET VOLID IN CASE OF VQSET
	XCT CT3			;LOAD OR STORE VOLID AS REQUESTED
	RETSKP


; VQSPIN - INITIALIZE FREE POOL OF VOLID SLOTS
; RETURNS +1: ALWAYS

VQSPIN:	SAVEQ
	SETZM FVSQDB		;SET QUEUE EMPTY INITIALLY
	MOVEI Q1,VOLP0		;GET ADDRESS OF 1ST SLOT IN POOL
	MOVEI Q2,VOLPN		;GET # OF SLOTS IN POOL
VQSPI1:	MOVEI T1,FVSQDB		;GET QDB ADDRESS
	MOVE T2,Q1		;GET ADDRESS OF NEXT SLOT
	CALL QMQT		;ADD SLOT TO TAIL OF FREE LIST
	ADDI Q1,2		;POINT TO NEXT SLOT
	SOJG Q2,VQSPI1		;LOOP
	RET
; WRTP - WRITE-PROTECT MOUNTR'S CODE TO CATCH STRAY STORES
; RETURNS +1: ALWAYS

WRTP:	MOVEI T1,PURE		;COMPUTE PAGE # OF FIRST
	LSH T1,-11		; PAGE OF NON-MODIFYABLE MEMORY
	HRLI T1,.FHSLF		;GET FORK HANDLE ,, PAGE#
	MOVX T2,PA%RD+PA%EX	;REQUEST READ AND EXECUTE ACCESS
	MOVEI T3,.RLEND		;COMPUTE PAGE # OF LAST READ-ONLY
	LSH T3,-11		; PAGE PLUS 1
WRTP1:	CAIG T3,(T1)		;ALL DONE?
	RET			;YES
	SPACS			;SET PAGE TO READ & EXECUTE
	AOJA T1,WRTP1		;INCREMENT PAGE # AND LOOP


; XMTOPR - EXECUTE MAGTAPE MTOPR FUNCTION A GIVEN NUMBER OF TIMES
;  T1/ MTOPR FUNCTION CODE
;  T2/ NUMBER OF TIMES TO EXECUTE
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: DEVICE FAILURE, T1/ 0=ERROR 1=TIMEOUT
;	  +2: SUCCESS

XMTOPR:	SAVEQ
	DMOVE Q1,T1		;SAVE FUNCTION CODE AND REPEAT COUNT
XMTOP1:	LOAD T1,MTAJFN		;GET JFN
	MOVE T2,Q1		;GET MTOPR FUNCTION CODE
	IOXCT MTOPR,XMTOP2,XMTOP3 ;START POSITIONING OPERATION
	MOVEI T2,.MONOP
	IOXCT MTOPR,XMTOP2,XMTOP3 ;WAIT TILL OPERATION COMPLETES
	CALL CLRTAP		;CLEAR ERRORS
	 JRST XMTOP3		;TIMED OUT
	TXNE T2,MT%DVE+MT%DAE	;ANY SERIOUS PROBLEMS?
	JRST XMTOP2		;YES
	SOJG Q2,XMTOP1		;LOOP TILL DONE
	RETSKP			;SUCCESS

XMTOP2:	TDZA T1,T1		;ERROR, PUT 0 IN T1
XMTOP3:	MOVEI T1,1		;TIMEOUT, PUT 1 IN T1
	RET			;TAKE ERROR RETURN
; XMTREP - REPORT MTA DEVICE FAILURE TO OPERATOR
;  T1/ 0 TO REPORT DEVICE ERROR, 1 TO REPORT DEVICE TIMEOUT
;  MTA/ ADDR OF MTA STATUS BLOCK
; RETURNS +1: ALWAYS

XMTREP:	JUMPN T1,[CALLRET WOTIMO] ;TIMEOUT, RETURN THROUGH TIMEOUT CODE
	TMCT <%I%M positioning operation failed. Last Error: %J>
	MOVEI T3,[ASCIZ/Tape Positioning Error/]
	CALLRET BTWTO		;TELL OPERATOR AND RETURN


; XMUTIL - EXECUTE MUTIL FOR CALLER
;  T1-T4/ ARGUMENT BLOCK WORDS 0-3
; RETURNS +1: ERROR ON MUTIL CALL, CODE IN T1
;	  +2: SUCCESS, WITH COPY OF ARG BLOCK IN T1-T4

XMUTIL:	SAVET			;SAVE CALLER'S AC'S ON STACK
	MOVEI T1,4		;ARGUMENT BLOCK LENGTH
	MOVEI T2,CT1		;ADDRESS OF ARGUMENT BLOCK
	MUTIL			;DO MUTIL (ARG BLOCK IS IN STACK)
	 JRST [	MOVEM T1,CT1	;ERROR, SUPPLY ERROR TO CALLER
		RET]		;TAKE ERROR RETURN
	RETSKP			;GOOD RETURN, T1-T4 COME OFF STACK


LIT:				;ADDRESS OF START OF LITERAL POOL
	END <ENTVSZ,,ENTVEC>