Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93L-BB_1990 - 10,7/galaxy/lptspl/lptmta.mac
There are 10 other files named lptmta.mac in the archive. Click here to see a list.
TITLE	LPTMTA - Magtape printer driver for LPTSPL-10
SUBTTL	D. Mastrovito/DPM	16-OCT-89

;
;
;		COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
;		     1984,1985,1986,1987,1990.
;			ALL RIGHTS RESERVED.
;
;     THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;     AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
;     AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.   THIS
;     SOFTWARE  OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
;     OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON.  NO  TITLE  TO
;     AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
;     THE INFORMATION  IN  THIS  SOFTWARE  IS  SUBJECT  TO  CHANGE
;     WITHOUT  NOTICE  AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
;     BY DIGITAL EQUIPMENT CORPORATION.
;
;     DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
;     OF  ITS  SOFTWARE  ON  EQUIPMENT  WHICH  IS  NOT SUPPLIED BY
;     DIGITAL.
;

	SEARCH	GLXMAC			;SEARCH GALAXY PARAMETERS
	SEARCH	QSRMAC			;SEARCH QUASAR PARAMETERS
	SEARCH	ORNMAC			;SEARCH ORION/OPR PARAMETERS
	SEARCH	LPTMAC			;SEARCH LPTSPL PARAMETERS
	PROLOG	(LPTMTA)

IF2,<PRINTX Assembling GALAXY-10 LPTMTA>

	%%.LPT==:%%.LPT			;VERSION

	SALL				;FOR CLEAN LISTINGS
	.DIRECT	FLBLST			;FOR CLEANER LISTINGS

	ENTRY	LPTMTA			;LOAD IF LIBRARY SEARCH

COMMENT	\



LPTMTA will drive any magtape.  It will spool any request queued to  the
appropriate unit number or one destined for unit class "MAGTAP".  LPTMTA
is a functional replacement for all previous versions  of  LPTSPL  which
would  spool to magtape.  It does, however, have some features that have
not previously existed.

Normally, when the operator wants to spool to a  magtape,  the  standard
OPR  command  "START PRINTER n/DEVICE:name"  command  is issued.  In the
past, the operator had to set a tape UNAVAILABLE to allow for LPTSPL  to
write  the  tape.   This  proceedure still works.  If, however, you want
LPTMTA to generate a mount request for a scratch tape, then you have two
options.

You   may   set   the   various    magtape    parameters    using    the
"SET PRINTER n MAGTAPE"  command  and  include the appropriate switches.
If you elect to specify a volume-set name, then it must be  a  cataloged
volume-set.   This  restriction  is necessary because LPTSPL has no idea
what reelids constitute the volume-set.

The other option is to specify a generic magtape device to  the  /DEVICE
switch.   A generic device may be of the form MTA, MTB, MT, M7, M9, etc.
When  a  generic  device  is  used,  LPTMTA  will  make  the   following
assumptions:

      1.  A device name is M7 or M9 will force a request  for  the
          appropriate  track  type.  Otherwise, the system default
          track type  will  be  used.   This  may  be  changed  by
          redefining the value of MTAMTK.

      2.  The system default density for the given track type will
          be used.  This may be changed by redefining the value of
          MTAMDN.

      3.  The system default label type will be used.  This may be
          changed by redefining MTAMTL.

      4.  A     scratch      volume-set      with      a      name
          yyymmdd-hhmmss-LPT-MAGTAP will be requested.  "yyyymmdd"
          represents the current date  and  "hhmmss"  the  current
          time.

      5.  The tape will be written at the default parity  for  the
          drive  assigned.   This  may  be  changed  by redefining
          MTAMPR.


LPTMTA has one other new feature.  It will  write  a  magtape  directory
file containing all the reelids, requests, and specific files written to
tape.  This feature may be enabled by redefining the value of MTAMDI  or
using  the  /DIRECTORY-FILE  switch  on  the SET command to vary magtape
parameters.

\
SUBTTL	LPTMTA - Dispatch table


; This module will drive any magtape tape.

LPTMTA::DEVDSP	(MTA,<Magtape>)


LPDAT:	ITEXT(<^C/[-1]/ LPDAT	>)
LPDIR:	ITEXT(<^C/[-1]/ LPDIR	>)
LPMTA:	ITEXT(<^C/[-1]/ LPMTA	>)

; Assembly parameters
	ND	MTAMRL,.OBMRY		;DEFAULT MULTI-REEL TAPES ON
	ND	MTAMDI,.OBMDN		;DEFAULT DIRECTORY FILE OFF
	ND	MTAMTK,DEFTRK		;DEFAULT NUMBER OF TRACKS
IFN <MTAMTK-%TRK7>,<ND MTAMDN,DEF7TK>	;DEFAULT 7-TRACK DENSITY
IFN <MTAMTK-%TRK9>,<ND MTAMDN,DEF9TK>	;DEFAULT 9-TRACK DENSITY
	ND	MTAMPR,.OBMPO		;DEFAULT TAPE PARITY ODD
	ND	MTAMLT,DEFLBT		;DEFAULT LABEL TYPE

; Driver specific per-job data
	 .ORG	J$DWDS			;DEFINE WORDS STARTING AT J$DWDS
MTADEV:! BLOCK	1			;REQUESTED DEVICE NAME (FROM SETUP)
MTACND:! BLOCK	1			;DEVICE CONDITIONING WORD
MTAACK:! BLOCK	1			;ACK CODE FOR TAPE MOUNTS
MTAAFL:! BLOCK	1			;ACK FLAG
MTASCR:! BLOCK	1			;NON-ZERO IF A SCRATCH VOLUME-SET
MTAVSN:! BLOCK	VSNLEN			;VOLUME-SET NAME
MTARMK:! BLOCK	RMKLEN			;REMARK STRING
MTARID:! BLOCK	1			;REELID
MTATMP:! BLOCK	1			;TEMP STORAGE FOR WTOR
MTAFOB:! BLOCK	FOB.SZ			;DIRECTORY FILE FOB
MTAFIL:! BLOCK	FDXSIZ			;DIRECTORY FILE FD
MTAIFN:! BLOCK	1			;DIRECTORY FILE IFN
MTAPRT:! BLOCK	1			;DIRECTORY FILE PROTECTION
MTADLN:! BLOCK	1			;DIRECTORY FILE LINE NUMBER
MTADPG:! BLOCK	1			;DIRECTORY FILE PAGE NUMBER
MTARLC:! BLOCK	1			;DIRECTORY FILE REEL COUNT
MTARQC:! BLOCK	1			;DIRECTORY FILE REQUEST COUNT
MTASPC:! BLOCK	1			;DIRECTORY FILE SPOOLED PAGE COUNT
MTASFC:! BLOCK	1			;DIRECTORY FILE SPOOLED FILE COUNT
MTALP2:! BLOCK	1			;LP20 SIMULATION FLAG
MTASIZ:!				;END OF DRIVER SPECIFIC DATA
	 .ORG

IF2,<
	IFL <DRVWDS-<MTASIZ-J$DWDS>>,<
	PRINTX ? Magtape driver definitions overflow storage
	>
> ;END IF2
SUBTTL	MTAINX - Initialization


MTAINX:	JUMPE	M,.RETT			;RETURN IF LPTSPL INITIALIZATION
	MOVSI	S1,J$DWDS(J)		;START OF DRIVER DEPENDENT DATA
	HRRI	S1,J$DWDS+1(J)		;MAKE A BLT POINTER
	SETZM	J$DWDS(J)		;CLEAR FIRST WORD
	BLT	S1,J$DWDS+DRVWDS-1(J)	;CLEAR ENTIRE BLOCK
	MOVE	S1,STREAM##		;GET STREAM NUMBER
	MOVE	S1,JOBOBA##(S1)		;AND THE OBJECT BLOCK
	MOVE	S1,OBJ.ND(S1)		;GET STATION NUMBER
	PUSHJ	P,LPTANF##		;MUST BE ANF-10
	JUMPF	INIT.2			;ELSE RETURN
	SKIPN	S1,SUP.UT(M)		;GET UNIT TYPE CODE
	JRST	INIT.1			;NOT THERE, MUST CHECK FOR DEVICE
	CAME	S1,['MAGTAP']		;MAGTGAPE?
	JRST	INIT.2			;NO
	MOVEM	S1,J$LTYP(J)		;SAVE UNIT TYPE
	SKIPN	S1,SUP.ST(M)		;IS THERE A DEVICE?
	MOVSI	S1,'MTA'		;NO--DEFAULT
	MOVEM	S1,SUP.ST(M)		;UPDATE

INIT.1:	SKIPN	S1,SUP.ST(M)		;IS THERE A DEVICE?
	JRST	INIT.2			;DEVICE NOT FOR US
	MOVEM	S1,MTADEV(J)		;SAVE HERE
	MOVEM	S1,J$LDEV(J)		;AND HERE TOO
	MOVE	T1,S1			;COPY
	DEVCHR	T1,UU.PHY		;GET DEVICE CHARACTERISTICS
	TXNN	T1,DV.MTA		;PROPER DEVICE TYPE?
	JRST	INIT.2			;NOT FOR US
	MOVE	T1,['MAGTAP']		;NORMAL UNIT TYPE IDENTIFIER
	SKIPN	J$LTYP(J)		;ALREADY SET (FROM SETUP MSG)?
	MOVEM	T1,J$LTYP(J)		;NO--SAVE FOR QUASAR
	HRLZI	T1,LPTMTA		;POINT TO DISPATCH TABLE
	HRRI	T1,J$$DEV(J)		;MAKE A BLT POINTER
	BLT	T1,J$$DND(J)		;COPY INTO JOB STORAGE AREA
	SETZM	J$POSF(J)		;MTA DOESN'T POSITION
	SETZM	J$FFDF(J)		;MTA DOESN'T DO FORM FEEDS
	SETOM	J$DC3F(J)		;MTA HANDLES DC3S
	SETZM	J$MNTF(J)		;MTA DOESN'T SUPPORT MOUNTABLE FORMS
	SETOM	J$LLCL(J)		;MTA HANDLES LOWER CASE
	LOAD	S1,SUP.FL(M),SUFLP2	;GET LP20 SIMULATION FLAG (DEFAULT NO)
	PUSH	P,S1			;SAVE IT
	CAIN	S1,.OFLYE		;IF YES
	SETOM	MTALP2(J)		;REMEMBER THAT FACT
	CAIN	S1,.OFLYE		;IF YES
	PUSHJ	P,VFUINX##		;INITIALIZE SIMULATOR (CHANGES FLAGS)
	PUSHJ	P,DEFPRM		;DEFAULT MAGTAPE PARAMETERS
	MOVE	T1,SUP.MT(M)		;GET MAGTAPE CHARACTERISTICS WORD
	MOVEM	T1,MTACND(J)		;SAVE
	MOVSI	T1,SUP.VS(M)		;POINT TO POSSIBLE VOLUME-SET NAME
	HRRI	T1,MTAVSN(J)		;AND TO OUR STORAGE
	BLT	T1,MTAVSN+VSNLEN-1(J)	;COPY
	MOVEI	S1,%RSUOK		;LOAD THE CODE
	SETZ	S2,			;SET LP20 SIMULATION FLAG IN S2
	POP	P,T1
	STORE	T1,S2,OF.LP2
	$RETT				;RETURN

INIT.2:	MOVNI	S1,1			;-1 MEANS DEVICE NOT FOR US
	$RETF				;RETURN

INIT.3:	SKIPA	S1,[%RSUNA]		;UNIT NOT AVAILABLE
INIT.4:	MOVEI	S1,%RSUDE		;UNIT WILL NEVER BE AVAILABLE
	$RETF				;RETURN
DEFPRM:	LOAD	T1,SUP.MT(M),OB.MRL	;MULTI-REEL VOLUME-SETS
	CAIN	T1,.OBMRD		;DEFAULT?
	MOVEI	T1,MTAMRL		;YES
	STORE	T1,SUP.MT(M),OB.MRL	;UPDATE

	LOAD	T1,SUP.MT(M),OB.MDI	;DIRECTORY FILE
	CAIN	T1,.OBMDD		;DEFAULT?
	MOVEI	T1,MTAMDI		;YES
	STORE	T1,SUP.MT(M),OB.MDI	;UPDATE

	SKIPN	SUP.VS(M)		;VOLUME-SET SPECIFIED?
	SETOM	MTASCR(J)		;FLAG A SCRATCH VOLUME-SET
	$RETT				;RETURN
SUBTTL	MTAIPC - Special IPCF message processing


MTAIPC:	CAIE	S2,MT.TXT		;TEXT MESSAGE (ACK)?
	JRST	IPCF.6			;NO
	PUSH	P,J			;SAVE J
	MOVSI	T1,-NPRINT		;AOBJN POINTER
	SKIPN	J,JOBPAG##(T1)		;STREAM IN USE?

IPCF.1:	AOBJN	T1,.-1			;CHECK ALL
	JUMPGE	T1,IPCF.5		;MESSAGE NOT FOR US
	MOVE	T2,J$LTYP(J)		;GET PRINTER CLASS
	CAME	T2,['MAGTAP']		;MAGTAPE?
	JRST	IPCF.1			;MESSAGE NOT FOR THIS STREAM
	MOVE	T2,.MSCOD(M)		;GET ACK CODE WE'RE LOOKING FOR
	CAME	T2,MTAACK(J)		;MATCH?
	JRST	IPCF.1			;MESSAGE NOT FOR THIS STREAM
	HRRZM	T1,STREAM##		;SET STREAM NUMBER
	AOSLE	T2,MTAAFL(J)		;GET ACK COUNT/FLAG
	CAIE	T2,1			;FINAL MOUNT ACK?
	JRST	IPCF.4			;NO--JUST IGNORE JUNK STUFF
	MOVX	T2,PSF%MW		;GET WAIT STATE
	ANDCAM	T2,JOBSTW##(T1)		;CLEAR MOUNT WAIT
	SETOM	JOBUPD##(T1)		;FORCE STATUS UPDATE
	MOVX	T2,MF.FAT		;GET DEADLY BIT
	TDNE	T2,.MSFLG(M)		;FATAL ACK?
	JRST	IPCF.2			;YES--MOUNT WAS CANCELED
	PUSH	P,S			;SAVE S
	MOVE	S,J$RACS+S(J)		;SET UP STREAM FLAGS
	PUSHJ	P,OPEN.1		;GO OPEN THE DEVICE
	MOVEM	S,J$RACS+S(J)		;UPDATE STREAM FLAGS
	POP	P,S			;RESTORE S
	JUMPT	IPCF.3			;LET JOBS START ON NEXT SCHEDULER PASS
	SKIPA	T2,[[ASCIZ /Cannot open device/]]

IPCF.2:	MOVEI	T2,[ASCIZ /Volume-set not available/]
	MOVEI	T3,.OHDRS+ARG.DA(M)	;POINT TO START OF ERROR ACK
	$WTO	(<^T/(T2)/>,<^T/(T3)/>,@JOBOBA##(T1))
	$WTO	(<Requeued>,<^R/.EQJBB(J)/>,@JOBOBA##(T1)) ;INDICATE REQUEUE
	MOVX	T2,GOODBY+ABORT+RQB	;MAGIC BITS
	IORM	T2,J$RACS+S(J)		;REQUEUE JOB, SHUTDOWN STREAM
	MOVEI	S1,%RSUDE		;DEVICE WILL NEVER BE AVAILABLE
	PUSHJ	P,RSETUP##		;TELL QUASAR
	JRST	IPCF.4			;FINISH UP

IPCF.3:	MOVEI	S1,.TFREW		;REWIND
	PUSHJ	P,TAPOP			;...
IPCF.4:	POP	P,J			;RESTORE J
	$RETT				;INDICATE MESSAGE PROCESSED

IPCF.5:	POP	P,J			;RESTORE J
IPCF.6:	MOVNI	S1,1			;SAY MESSAGE NOT FOR US
	$RETF				;RETURN
SUBTTL	MTASCD - Scheduler call


MTASCD:	$RETT				;RETURN
SUBTTL	MTAWAK - Wakeup time check


MTAWAK:	$RETT				;RETURN
SUBTTL	MTAOPX - OPEN device


MTAOPX:	SKIPLE	MTAAFL(J)		;ALREADY OWN A TAPE?
	JRST	OPEN.1			;YES--ALREADY DID MOUNT STUFF
	MOVE	T1,MTADEV(J)		;GET REQUESTED DEVICE
	DEVTYP	T1,UU.PHY		;MUST SEE IF A SPECIFIC UNIT
	  JRST	OPEN.3			;UNIT NOT AVAILABLE
	TXNN	T1,TY.GEN		;GENERIC DEVICE (MTA, M7, M9, ETC.)?
	JRST	OPEN.1			;NO--JUST GO OPEN WHAT WE HAVE
	PUSHJ	P,GENVSN		;GENERATE A UNIQUE VOLUME-SET NAME
	PUSHJ	P,GENRMK		;GENERATE REMARK TEXT
	MOVS	T1,MTADEV(J)		;GET DEVICE NAME AGAIN
	LOAD	T2,MTACND(J),OB.MTK	;GET SPECIFIED TRACK TYPE
	CAIN	T1,'M7 '		;7-TRACK?
	MOVEI	T2,.TMDR7		;YES
	CAIN	T1,'M9 '		;9-TRACK?
	MOVEI	T2,.TMDR9		;YES
	STORE	T2,MTACND(J),OB.MTK	;UPDATE
	PUSHJ	P,MOUNT			;MOUNT A TAPE
	MOVX	T1,PSF%MW		;GET WAIT STATE
	MOVE	T2,STREAM##		;AND STREAM NUMBER
	IORM	T1,JOBSTW##(T2)		;PUT STREAM IN MOUNT WAIT
	SETOM	JOBUPD##(T1)		;FORCE STATUS UPDATE
	SETOM	MTAAFL(J)		;INDICATE EXPECTING JUNK ACK
	JUMPF	OPEN.4			;CHECK FOR ERRORS
	JRST	OPEN.2			;LIE AND SAY WE'RE ALL SET

OPEN.1:	MOVEI	T1,1			;SET ACK FLAG POSITIVE
	MOVEM	T1,MTAAFL(J)		; SO THINGS PROCEED SMOOTHLY
	MOVX	T1,IO.SFF!.IOASC	;OPEN BITS + MODE
	PUSHJ	P,LPTOPN##		;SETUP I/O, OPEN CHANNEL, ETC.
	JUMPF	OPEN.3			;CAN'T HAVE IT RIGHT NOW
	PUSHJ	P,INTCNL##		;CONNECT TO INTERRUPT SYSTEM
	JUMPF	OPEN.4			;GIVE UP
	TXO	S,INTRPT		;INDICATE WE'RE CONNECTED
	MOVEI	S1,1			;FLAG
	PUSHJ	P,TAPDEN		;SET DENSITY
	JUMPF	OPEN.4			;DOESN'T WORK
	MOVEI	S1,1			;FLAG
	PUSHJ	P,TAPPAR		;SET TAPE PARITY
	JUMPF	OPEN.4			;FAILED
	PUSHJ	P,LPTTXT##		;FIX UP "OUTPUT TO ..." TEXT
	PUSHJ	P,DIROPN		;OPEN DIRECTORY FILE
	JUMPF	OPEN.4			;CAN'T
	AOS	MTARLC(J)		;AND COUNT IT TOO
	SKIPE	MTALP2(J)		;VFU SIMULATION ENABLED?
	PUSHJ	P,VFUOPX##		;YES, DO VFU OPEN PROCESSING

OPEN.2:	MOVEI	S1,%RSUOK		;LOAD THE CODE
	$RETT				;RETURN

OPEN.3:	SKIPA	S1,[%RSUNA]		;UNIT NOT AVAILABLE
OPEN.4:	MOVEI	S1,%RSUDE		;UNIT WILL NEVER BE AVAILABLE
	$RETF				;RETURN
; GENERATE A UNIQUE VOLUME-SET NAME
; CALL:	PUSHJ	P,GENVSN
;
; ON RETURN, MTAVSN(J) WILL CONTAIN AN ASCIZ VSN
;
; VSN WILL BE ASCIZ/YYYYMMDD-HHMMSS-LPT-FILES/

GENVSN:	PUSHJ	P,I%NOW			;GET CURRENT UDT
	MOVEM	S1,MTAACK(J)		;SAVE AS ACK CODE FOR TAPE MOUNTS
	PUSHJ	P,S%U2DT		;CONVERT TO DECSYSTEM-10 DATE/TIME
	MOVE	T1,S1			;GET TIME IN MILLISECONDS
	AND	T1,[000707,,070707]	;MAKE NUMERIC
	TDO	T1,[SIXBIT /L00000/]	;MAKE SIXBIT
	MOVEM	T1,J$LDEV(J)		;SAVE AS THE LOGICAL NAME FOR OPENS
	SKIPE	MTAVSN(J)		;ALREADY HAVE A VOLUME-SET NAME
	POPJ	P,			;YES--ALL DONE
	MOVE	T1,S2			;GET 15-BIT DATE
	IDIVI	T1,^D31			;GET DAYS AS 0-30
	MOVE	T3,T1			;SAVE REST
	MOVEI	T1,1(T2)		;NORMALIZE
	IDIVI	T3,^D12			;GET MONTHS AS 0-11
	MOVEI	T2,1(T4)		;NORMALIZE
	IMULI	T2,^D100		;POSITION
	ADD	T1,T2			;INCLUDE IN DATE WORD
	MOVEI	T2,^D1964(T3)		;GET YEAR
	IMULI	T2,^D10000		;POSITION
	ADD	T1,T2			;INCLUDE IN DATE WORD
	MOVE	S2,T1			;SAVE
	MOVE	T1,S1			;GET TIME IN MILLISECONDS
	IDIV	T1,[^D3600000]		;GET HOURS
	IMULI	T1,^D10000		;POSITION
	IDIVI	T2,^D60000		;GET MINUTES
	IMULI	T2,^D100		;POSITION
	ADD	T1,T2			;INCLUDE IN TIME WORD
	IDIVI	T3,^D1000		;GET SECONDS
	ADD	T1,T3			;INCLUDE IN TIME WORD
	MOVE	S1,T1			;SAVE
	$TEXT	(<-1,,MTAVSN(J)>,<^I/VSNTXT/^0>)
	POPJ	P,			;RETURN


VSNTXT:	ITEXT	(<^D/S2/-^D6R0/S1/-LPT-^W/J$LTYP(J)/>)
; GENERATE REMARK TEXT
; CALL:	PUSHJ	P,GENRMK
;
; ON RETURN, MTARMK(J) WILL CONTAIN AN ASCIZ REMARK
;
; REMARK WILL BE ASCIZ/PRINTER N [NODE] CLASS/

GENRMK:	MOVE	S1,STREAM##		;GET STREAM NUMBER
	MOVE	S1,JOBOBA##(S1)		;AND THE OBJECT BLOCK
	MOVE	T1,OBJ.UN(S1)		;UNIT NUMBER
	MOVE	T2,OBJ.ND(S1)		;STATION
	MOVE	T3,J$LTYP(J)		;CLASS
	$TEXT	(<-1,,MTARMK(J)>,<Printer ^D/T1/ [^N/T2/] ^W/T3/^0>)
	POPJ	P,			;RETURN
; MOUNT A VOLUME-SET
; CALL:	PUSHJ	P,MOUNT
;
; TRUE RETURN:	TAPE MOUNTED
; FALSE RETURN:	OPERATOR CANCELED MOUNT

MOUNT:	PUSHJ	P,.SAVE3		;SAVE SOME ACS
	PUSHJ	P,M%GPAG		;GET A PAGE
	MOVE	P1,S1			;COPY PAGE ADDRESS
	MOVE	T1,[.MMHSZ,,.QOMNT]	;INITIAL MSG LENGTH,,FUNCTION CODE
	MOVEM	T1,.MSTYP(P1)
	MOVX	T1,MF.ACK		;NEED AN ACK
	MOVEM	T1,.MSFLG(P1)		;SAVE FLAGS
	MOVE	T1,MTAACK(J)		;ACK CODE
	MOVEM	T1,.MSCOD(P1)

; MOUNT MESSAGE HEADER
MOUNT1:	MOVX	T1,MM.WAT		;WAIT FOR MOUNT (IMPLIES IPCF ACK)
	MOVEM	T1,.MMFLG(P1)		;SAVE MOUNT FLAGS
	HRROI	T1,.GTNM1		;GET OUR NAME (WORD 1)
	GETTAB	T1,
	  SETZ	T1,
	HRROI	T2,.GTNM2		;GET OUR NAME (WORD 2)
	GETTAB	T2,
	  SETZ	T2,
	DMOVEM	T1,.MMUSR(P1)		;SAVE NAME
	MOVE	T1,[.ACTRD,,T2]		;SET UP UUO AC
	MOVEI	T2,2			;TWO WORDS IN ARG BLOCK
	MOVNI	T3,1			;-1 FOR OUR JOB
	HRROI	T4,.MMUAS(P1)		;RESULTS GO HERE
	ACCT.	T1,			;READ ACCOUNT STRING
	  JFCL				;TOO BAD
	MOVEI	P2,.MMHSZ(P1)		;POINT TO START OF FIRST MOUNT BLOCK

; REQUEST HEADER
MOUNT2:	MOVE	T1,[.MEHSZ,,.MNTTP]	;LENGTH,,/TAPE
	MOVEM	T1,.MEHDR(P2)
	HLLZS	T1			;ISOLATE LENGTH
	ADDM	T1,.MSTYP(P1)		;ACCUMULATE
	MOVX	T1,TM%WEN		;/WE
	SKIPE	MTASCR(J)		;SCRATCH VOLUME-SET?
	TXO	T1,TM%SCR		;LITE /SCRATCH BIT
	MOVEM	T1,.MEFLG(P2)
	MOVEI	P3,.MEHSZ(P2)		;POINT TO FIRST DATA BLOCK STORAGE
	AOS	.MMARC(P1)		;ONLY ONE MOUNT BLOCK IN MESSAGE

; VOLUME-SET NAME BLOCK
MOUNT3:	MOVE	T1,[VSNLEN+ARG.DA,,.TMSET] ;LENGTH,,BLOCK TYPE
	MOVEM	T1,ARG.HD(P3)
	MOVSI	T1,MTAVSN(J)		;VSN ADDRESS
	HRRI	T1,ARG.DA(P3)		;MAKE A BLT POINTER
	BLT	T1,ARG.DA+VSNLEN-1(P3)	;COPY
	PUSHJ	P,MOUNTB		;COUNT THE BLOCK

; TRACK BLOCK
MOUNT4:	SKIPN	MTASCR(J)		;SCRATCH VOLUME-SET?
	JRST	MOUNT5			;NO--USE PARAMETERS FROM CATALOG
	MOVE	T1,[1+ARG.DA,,.TMDRV]	;LENGTH,,BLOCK TYPE
	LOAD	T2,MTACND(J),OB.MTK	;GET TRACK TYPE
	CAIE	T2,.TMDRD		;DEFAULT?
	PUSHJ	P,MOUNTD		;SAVE DATA, ADVANCE POINTERS

; DENSITY BLOCK
	MOVE	T1,[1+ARG.DA,,.TMDEN]	;LENGTH,,BLOCK TYPE
	LOAD	T2,MTACND(J),OB.MDN	;GET DENSITY
	SKIPE	T2			;DEFAULT?
	PUSHJ	P,MOUNTD		;SAVE DATA, ADVANCE POINTERS

; LABEL TYPE BLOCK
	MOVE	T1,[1+ARG.DA,,.TMLT]	;LENGTH,,BLOCK TYPE
	LOAD	T2,MTACND(J),OB.MLT	;GET LABEL TYPE
	MOVX	T3,OB.MLV		;BIT TO TEST
	TDNE	T3,MTACND(J)		;LABEL TYPE FIELD VALID?
	PUSHJ	P,MOUNTD		;SAVE DATA, ADVANCE POINTERS


; LOGICAL NAME BLOCK
MOUNT5:	MOVE	T1,[1+ARG.DA,,.TMLNM]	;LENGTH,,BLOCK TYPE
	MOVE	T2,J$LDEV(J)		;GET LOGICAL NAME
	PUSHJ	P,MOUNTD		;SAVE DATA, ADVANCE POINTERS

; REMARK STRING BLOCK
MOUNT6:	MOVE	T1,[RMKLEN+ARG.DA,,.TMRMK] ;LENGTH,,BLOCK TYPE
	MOVEM	T1,ARG.HD(P3)
	MOVSI	T1,MTARMK(J)		;VSN ADDRESS
	HRRI	T1,ARG.DA(P3)		;MAKE A BLT POINTER
	BLT	T1,ARG.DA+RMKLEN-1(P3)	;COPY
	PUSHJ	P,MOUNTB		;COUNT THE BLOCK

; QUEUE UP MOUNT
MOUNT7:	MOVEI	T1,(P1)			;POINT TO MESSAGE
	PUSHJ	P,SNDQSR##		;SEND IT OFF TO QUASAR
	$RETT				;RETURN

MOUNTD:	DMOVEM	T1,ARG.HD(P3)		;SAVE HEADER + ONE WORD OF DATA
MOUNTB:	AOS	.MECNT(P2)		;COUNT THE BLOCK
	LOAD	T1,ARG.HD(P3),AR.LEN	;GET BLOCK LENGTH
	ADDI	P3,(T1)			;ADVANCE POINTER
	HRLZS	T1			;PUT IN LH
	ADDM	T1,.MEHDR(P2)		;ADD TO MOUNT REQUEST HEADER
	ADDM	T1,.MSTYP(P1)		;ADD TO TOTAL LENGTH OF MESSAGE
	POPJ	P,			;RETURN
SUBTTL	MTACLS - CLOSE device


MTACLS:	SKIPG	MTAAFL(J)		;OWN DEVICE YET?
	$RETT				;NOTHING TO DO
	TXZE	S,INTRPT		;PSI INTERRUPTS ENABLED?
	PUSHJ	P,INTDCL##		;DISCONNECT PSI
	MOVE	S1,J$LCHN(J)		;GET THE CHANNEL
	LSH	S1,^D23			;POSITION THE CHANNEL NUMBER
	TLO	S1,(CLOSE 0,0)		;MAKE IT A CLOSE UUO
	XCT	S1			;CLOSE THE MAG TAPE
	MOVEI	S1,.TFUNL		;UNLOAD TAPE
	PUSHJ	P,TAPOP			; MAY NOT WORK IF MDA CONTROLLED
	MOVEI	S1,0			;JOB ZERO
	MOVE	S2,J$LDEV(J)		;DEVICE NAME
	REASSI	S1,			;DEASSIGN DRIVE (WHEN RELEASE IS DONE)
	  JFCL				;IGNORE ERRORS
	MOVE	S1,J$LCHN(J)		;GET THE CHANNEL NUMBER AGAIN
	LSH	S1,^D23			;POSITION IT
	TLO	S1,(RELEASE 0,0)	;MAKE IT A RELEASE UUO
	XCT	S1			;RELEASE THE DEVICE
	$RETT				;AND RETURN
SUBTTL	MTAFLS - Flush a job


MTAFLS:	PJRST	LPTFLS##		;CALL COMMON FLUSH ROUTINE
SUBTTL	MTAFVU - Load VFU


MTAVFU:	SKIPE	MTALP2(J)		;IF LP20 SIMULATION
	PJRST	VFUVFU##		;LET THE SIMULATOR DO PROCESSING
	$RETT				;OTHERWISE, NO VFU LOADING NECESSARY
SUBTTL	MTARAM - Load RAM


MTARAM:	SKIPE	MTALP2(J)		;IF LP20 SIMULATION
	PJRST	VFURAM##		;LET THE SIMULATOR DO PROCESSING
	$RETT				;OTHERWISE, NO RAM LOADING NECESSARY
SUBTTL	MTALER - File LOOKUP error processing


MTALER:	PJRST	LPTLER##		;CALL COMMON ERROR ROUTINE
SUBTTL	MTAIER - File input error processing


MTAIER:	PJRST	LPTIER##		;CALL COMMON ERROR ROUTINE
SUBTTL	MTACHO - Output a virtual character

MTACHO:	SKIPN	MTALP2(J)		;LP20 SIMULATION RUNNING?
	 $RETT				;NO, LPTSPL WILL OUTPUT CHARACTER
	PJRST	VFUCHO##		;YES, PASS THRU THE LP20
SUBTTL	MTAOUT - Output a buffer


MTAOUT:	PJRST	LPTOUT##		;CALL COMMON OUTPUT ROUTINE
SUBTTL	MTAOER - Output error processing


MTAOER:	PUSHJ	P,VFUOER##		;CHECK FOR LP20 ERRORS
	PUSHJ	P,TAPLBE		;CHECK FOR LABELING ERROR
	$RETIF				;RETURN IF ERROR ALREADY PROCESSED

OUTE.1:	TXNN	S1,IO.IMP		;WRITE LOCKED TAPE?
	JRST	OUTE.2			;NO
	PUSHJ	P,TAPDEV		;GET PHYSICAL DRIVE NAME IN MTATMP(J)
	MOVEI	T1,[ITEXT (<Device ^W/MTATMP(J)/ write locked>)]
	MOVEI	T2,[ITEXT (<Insert write ring and put drive online^M^J^T/ENDRSP/>)]
	MOVEI	T3,CONANS		;KEYWORD TABLE
	PUSHJ	P,LPTOPR##		;ASK FOR OPERATOR ACTION
	PJRST	@J$OUTP(J)		;RETRY THE OUTPUT

OUTE.2:	TXNN	S1,IO.EOT		;END OF TAPE?
	JRST	OUTE.3			;NO
	PUSHJ	P,TAPRSW		;DO A REEL SWITCH
	JUMPT	@J$OUTP(J)		;RETRY THE OUTPUT IF ON A NEW TAPE
	PUSHJ	P,TAPIOS		;UPDATE I/O STATUS
	PUSHJ	P,TAPLBE		;CHECK EXTENDED ERROR CODE
	$RETIF				;RETURN IF ERROR ALREADY PROCESSED
	PUSHJ	P,TAPDEV		;GET PHYSICAL DRIVE NAME IN MTATMP(J)
	MOVE	S1,STREAM##		;GET STREAM NUMBER
	$WTO	(<Operator canceled reel switch>,,@JOBOBA(S1))
	$RETF				;GIVE UP

OUTE.3:	TXNN	S1,IO.DER!IO.DTE!IO.BKT	;ANY FATAL ERRORS?
	$RETT				;NO
	PUSHJ	P,TAPDEV		;GET PHYSICAL DRIVE NAME IN MTATMP(J)
	MOVEI	S1,[ITEXT (<>)]		;ASSUME NO EXTENDED STATUS
	SKIPE	J$XIOS(J)		;IS THERE ONE?
	MOVEI	S1,[ITEXT (</^O/J$XIOS(J)/>)]
	MOVE	S2,STREAM##		;GET STREAM NUMBER
	$WTO	(<I/O error ^O6R0/J$LIOS(J),RHMASK/^I/(S1)/ on device ^W/MTATMP(J)/>,,@JOBOBA(S2))
	$RETF				;GIVE UP


CONANS:	$STAB
	 KEYTAB	(0,PROCEED)
	$ETAB

ENDRSP:	ASCIZ	/Type 'RESPOND <number> PROCEED' when ready/
SUBTTL	MTAEOX - Output EOF processing


MTAEOX:	MOVE	TF,[2,,S1]		;SET UP UUO AC
	MOVX	S1,.TFWTM		;GET WRITE TAPE MARK CODE
	MOVE	S2,J$LCHN(J)		;GET THE DEVICE CHANNEL #
	TAPOP.	TF,			;DO IT
	  JFCL				;IGNORE ANY ERRORS
	$RETT				;AND RETURN
SUBTTL	MTABJB - Begining of job


MTABJB:	$TEXT	(LOGCHR,<^I/LPDAT/^T/J$LOUT(J)/>) ;LOG DEVICE INFO
	MOVEI	S1,.TFRID		;FUNCTION CODE
	PUSHJ	P,TAPOP			;READ THE REELID
	MOVEM	S1,MTARID(J)		;SAVE
	MOVEI	S1,[ASCIZ /(none)/]	;ASSUME THE WORST
	SKIPE	MTAVSN(J)		;HAVE A VOLUME-SET?
	MOVEI	S1,MTAVSN(J)		;POINT TO IT
	$TEXT	(LOGCHR##,<^I/LPMTA/Magtape volume-set: ^T/(S1)/>)
	MOVEI	S1,MTAFIL(J)		;DIRECTORY FILESPEC
	SKIPLE	MTAIFN(J)		;HAVE ONE?
	$TEXT	(LOGCHR##,<^I/LPDIR/Directory file: ^T/(S1)/>)
	$RETT				;RETURN
SUBTTL	MTAEJB - End of job


MTAEJB:	AOS	MTARQC(J)		;COUNT THE REQUEST
	MOVE	S1,J$APRT(J)		;GET PAGE COUNT FOR JOB
	ADDM	S1,MTASPC(J)		;ACCUMULATE
	MOVE	S1,J$AFXC(J)		;GET FILE COUNT FOR JOB
	ADDM	S1,MTASFC(J)		;ACCUMULATE
	PUSHJ	P,DIRLOG		;MAKE A DIRECTORY FILE LOG ENTRY
	$RETT				;RETURN
SUBTTL	MTABFL - Begining of file


MTABFL:	SETZM	J$LERR(J)		;NO OUTPUT ERRORS ARE ALLOWED
	$RETT				;RETURN
SUBTTL	MTAEFL - End of file


MTAEFL:	$RETT				;RETURN
SUBTTL	MTABAN - Banner initialization


MTABAN:	$RETT				;RETURN
SUBTTL	MTAHDR - Header initialization


MTAHDR:	$RETT				;RETURN
SUBTTL	MTAWID - Header width initialization


MTAWID:	$RETT				;RETURN
SUBTTL	MTARUL - Ruler processing

MTARUL:	PJRST	LPTRUL##		;PRINT STANDARD RULER
SUBTTL	MTASHT - Stream shutdown


MTASHT:	PUSHJ	P,DIRCLS		;CLOSE DIRECTORY FILE
	SKIPE	MTALP2(J)		;IF SIMULATING
	PUSHJ	P,VFUSHT##		;HANDLE SHUTDOWN FOR VIRTUAL LP20
	$RETT				;RETURN
SUBTTL	MTASTS - Status message generation


MTASTS:	MOVE	S1,J$RFLN(J)		;GET RELATIVE FILE NUMBER
	LOAD	S2,.EQSPC(J),EQ.NUM	;GET TOTAL NUMBER OF FILES
	SUBM	S2,S1			;GET NUMBER PROCESSED
	ADDI	S1,1			;CORRECT IT
	$TEXT	(DEPBP##,<, spooling file ^D/S1/ of ^D/S2/^0>)
	$RETT				;RETURN
SUBTTL	MTACHR - Character translator


MTACHR:	$RETT				;RETURN
SUBTTL	Directory routines -- DIRCHR - Character output


DIRCHR:	MOVE	S2,S1			;COPY CHARACTER
	SKIPG	S1,MTAIFN(J)		;FILE OPENED?
	$RETT				;NO
	CAIN	S2,.CHLFD		;NEW LINE?
	SOSLE	MTADLN(J)		;AND TIME FOR A NEW PAGE?
	JRST	DIRCH1			;NO
	PUSHJ	P,DIRHDR		;PUT OUT A NEW HEADER
	$RETT				;AND RETURN

DIRCH1:	PUSHJ	P,F%OBYT		;WRITE CHARACTER TO DISK
	$RETIT				;RETURN IF NO ERRORS
	MOVEI	S1,[ITEXT (<^E/[-1]/ writing ^F/MTAFIL/>)]
	PJRST	DIRERR			;OUTPUT ERROR
SUBTTL	Directory routines -- DIRCLS - Close file


DIRCLS:	SKIPG	MTAIFN(J)		;FILE OPEN?
	$RETT				;NO
	MOVEI	T1,[ITEXT (<^D/MTARLC(J)/ reels>)]
	MOVE	S1,MTARLC(J)		;GET COUNT
	CAIN	S1,1			;ONLY ONE?
	MOVEI	T1,[ITEXT (<one reel>)]	;YES
	$TEXT	(DIRCHR,<^M^JA total of ^I/(T1)/ of tape containing ^A>)

	MOVEI	T1,[ITEXT (<^D/MTASPC(J)/ pages>)]
	MOVE	S1,MTASPC(J)		;GET COUNT
	CAIN	S1,1			;ONLY ONE?
	MOVEI	T1,[ITEXT (<one page>)]	;YES

	MOVEI	T2,[ITEXT (<(^D/MTASFC(J)/ files)>)]
	MOVE	S1,MTASFC(J)		;GET COUNT
	CAIN	S1,1			;ONLY ONE?
	MOVEI	T2,[ITEXT (<(one file)>)] ;YES

	MOVEI	T3,[ITEXT (<^D/MTARQC(J)/ requests>)]
	MOVE	S1,MTARQC(J)		;GET REQUEST COUNT
	CAIN	S1,1			;ONLY ONE
	MOVEI	T3,[ITEXT (<one request>)] ;YES
	$TEXT	(DIRCHR,<^I/(T1)/ ^I/(T2)/ in ^I/(T3)/>)

	MOVE	S1,MTAIFN(J)		;IFN
	PUSHJ	P,F%REL			;RELEASE IT
	SETZM	MTAIFN(J)		;INVALIDATE IFN
	$RETT				;RETURN
SUBTTL	Directory routines -- DIRERR - I/O error reporting


DIRERR:	MOVE	S2,STREAM##		;GET STREAM NUMBER
	$WTO	(<Magtape directory file I/O error>,<^I/(S1)/>,@JOBOBA(S1))
	MOVE	S1,MTAIFN(J)		;IFN
	PUSHJ	P,F%REL			;CLOSE THE FILE
	SETZM	MTAIFN(J)		;INVALIDATE IFN
	$RETF				;GIVE UP
SUBTTL	Directory routines -- DIRHDR - Generate header text


DIRHDR:	PUSHJ	P,.SAVET		;SAVE T1-T4
	PUSH	P,S1			;SAVE S1
	PUSH	P,S2			;SAVE S2
	PUSHJ	P,LPTTXT##		;GENERATE "OUTPUT TO ..." TEXT
	MOVEI	T1,^D55			;LINES PER PAGE
	MOVEM	T1,MTADLN(J)		;RESET COUNT
	MOVEI	T1,LPCNF##		;POINT TO MONITOR NAME
	AOS	T2,MTADPG(J)		;GET PAGE NUMBER
	MOVEI	T3,MTAVSN(J)		;POINT TO VOLUME-SET NAME
	SKIPN	(T3)			;HAVE ONE?
	MOVEI	T3,[ASCIZ /(none)/]	;NO
	$TEXT	(DIRCHR,<^I/HDRTXT/>)	;GENERATE HEADER
	POP	P,S2			;RESTORE S2
	POP	P,S1			;RESTORE S1
	POPJ	P,			;RETURN

HDRTXT:	ITEXT	(<^L
LPTSPL version ^V/[%%.LPT]/    ^T24L/(T1)/   ^H9L/[-1]/   Page ^D/T2/
^T/J$LOUT(J)/
Magtape volume-set ^T39L/(T3)/

 Reel    Form   Job name   Req#   Files   Pages             User          
------  ------  --------  ------  -----  -------  ------------------------>)


DENTAB:	SIXBIT	/???/
	SIXBIT	/200/
	SIXBIT	/556/
	SIXBIT	/800/
	SIXBIT	/1650/
	SIXBIT	/6250/

LBLTAB:	[ASCIZ	/Bypass/]
	[ASCIZ	/ANSI/]
	[ASCIZ	/ANSI/]
	[ASCIZ	/IBM/]
	[ASCIZ	/IBM/]
	[ASCIZ	/Leading tape mark/]
	[ASCIZ	/Non-standard/]
	[ASCIZ	/No labels/]
	[ASCIZ	/COBOL-ASCII/]
	[ASCIZ	/COBOL-SIXBIT/]
	[ASCIZ	/User-EOT/]

PARTAB:	[ASCIZ	/???/]
	[ASCIZ	/Odd/]
	[ASCIZ	/Even/]

TRKTAB:	SIXBIT	/???/
	SIXBIT	/7/
	SIXBIT	/9/
SUBTTL	Directory routines -- DIRLOG - Log a file printed


DIRLOG:	SKIPG	MTAIFN(J)		;FILE OPEN?
	$RETT				;NO
	PUSHJ	P,.SAVE2		;SAVE P1 AND P2
	MOVE	T1,MTADLN(J)		;GET PAGE LINE COUNT
	CAIGE	T1,2			;EACH REQUEST NEEDS AT LEAST TWO LINES
	PUSHJ	P,DIRHDR		;START A NEW PAGE
	PUSHJ	P,DIRREQ		;LOG REQUEST DATA
	LOAD	P1,.EQSPC(J),EQ.NUM	;NUMBER OF FILES IN THIS REQUEST
	MOVNS	P1			;PUT IN LH
	HRLZS	P1			;AOBJN POINTER
	HRRI	P1,1			;START WITH FILE NUMBER ONE
	LOAD	P2,.EQLEN(J),EQ.LOH	;LENGTH OF EQ HEADER
	ADDI	P2,(J)			;POINT TO FIRST FP/FD PAIR

DIRLO1:	SKIPG	MTADLN(J)		;TIME FOR A NEW PAGE?
	PUSHJ	P,DIRHDR		;YES
	HRRZ	T1,P1			;GET FILE NUMBER
	LOAD	T2,.FPLEN(P2),FP.LEN	;LENGTH OF FP
	ADDI	T2,(P2)			;OFFSET TO FD
	LOAD	T3,.FPINF(P2),FP.FCY	;GET NUMBER OF COPIES
	MOVEI	T4,[ITEXT (< (^D/T3/ copies)>)]
	CAIN	T3,1			;ONLY ONE?
	MOVEI	T4,[ITEXT (<>)]		;YES
	$TEXT	(DIRCHR,<        ^D2R /T1/. ^F/(T2)/^I/(T4)/>)
	LOAD	T3,.FDLEN(T2),FD.LEN	;LENGTH OF FD
	ADDI	T2,(T3)			;OFFSET TO NEXT FP
	MOVEI	P2,(T2)			;COPY ADDRESS
	AOBJN	P1,DIRLO1		;LOOP FOR ALL FILES IN REQUEST

DIRLO2:	MOVE	S1,MTAIFN(J)		;IFN
	PUSHJ	P,F%CHKP		;CHECKPOINT THE FILE
	$RETIT				;RETURN IF NO ERRORS
	MOVEI	S1,[ITEXT (<^E/[-1]/ checkpointing ^F/MTAFIL/>)]
	PJRST	DIRERR			;CHECKPOINT ERROR
DIRREQ:	MOVE	T1,MTARID(J)		;REELID
	MOVE	T2,J$FORM(J)		;FORMS TYPE
	MOVE	T3,.EQJOB(J)		;JOB NAME
	MOVE	T4,.EQRID(J)		;REQUEST-ID
	$TEXT	(DIRCHR,<^W6L /T1/  ^W6L /T2/   ^W6L /T3/   ^D6R /T4/  ^A>)
	MOVE	T1,J$AFXC(J)		;FILES SPOOLED
	MOVE	T2,J$APRT(J)		;PAGES SPOOLED
	DMOVE	T3,.EQJBB+JIB.NM(J)	;USER NAME
	MOVEI	S1,[ITEXT (<^W6L /T3/^W/T4/>)]
	SKIPN	T4			;SECOND WORD IN USE?
	MOVEI	S1,[ITEXT (<^W/T3/>)]	;NO
	MOVE	S2,.EQOID(J)		;GET PPN
	$TEXT	(DIRCHR,<^D5R /T1/  ^D7R /T2/  ^I/(S1)/ ^U/S2/>)
	$RETT				;RETURN
SUBTTL	Directory routines -- DIROPN - Open directory file


DIROPN:	SETOM	MTAIFN(J)		;MARK FILE AS NOT OPENED YET
	LOAD	S1,MTACND(J),OB.MDI	;GET DIRECTORY STUFF
	CAIN	S1,.OBMDN		;WANT IT?
	$RETT				;NO
	MOVSI	S1,DIRFOB		;POINT TO PROTOTYPE FOB
	HRRI	S1,MTAFOB(J)		;MAKE A BLT POINTER
	BLT	S1,MTAFOB+FOB.SZ-1(J)	;COPY
	MOVSI	S1,DIRFD		;POINT TO PROTOTYPE FD
	HRRI	S1,MTAFIL(J)		;MAKE A BLT POINTER
	BLT	S1,MTAFIL+FDXSIZ-1(J)	;COPY
	MOVEI	S1,MTAFIL(J)		;FD ADDRESS
	MOVEM	S1,MTAFOB+FOB.FD(J)	;SAVE

DIROP1:	MOVSI	S1,'DSK'		;INCASE DEBUGGING
	SKIPE	DEBUGW			;CHECK IT
	MOVEM	S1,MTAFIL+.FDSTR(J)	;CHANGE DEVICE NAME
	PUSHJ	P,I%NOW			;GET CURRENT UDT
	AND	S1,[000707,,070707]	;MAKE IT NUMERIC
	TDO	S1,[SIXBIT/L00000/]	;TURN ON SOME BITS
	MOVEM	S1,MTAFIL+.FDNAM(J)	;SAVE
	MOVEI	S1,FOB.SZ		;FOB SIZE
	MOVEI	S2,MTAFOB(J)		;FOB ADDRESS
	PUSHJ	P,F%OOPN		;OPEN FILE FOR OUTPUT
	JUMPT	DIROP2			;CHECK FOR ERRORS
	CAIN	S1,ERFAE$		;FILE ALREADY EXIST?
	JRST	DIROP1			;YES--TRY AGAIN
	MOVEI	T1,[ITEXT (<Cannot create magtape directory file>)]
	MOVEI	T2,[ITEXT (<^E/[-1]/ for ^F/MTAFIL(J)/^T/DIRRSP/>)]
	MOVEI	T3,DIRTAB		;KEYWORD TABLE
	PUSHJ	P,LPTOPR##		;ASK FOR OPERATOR ACTION
	CAIE	S1,1			;WAS ANSWER "PROCEED"
	$RETF				;GIVE UP
	JRST	DIROP1			;TRY AGAIN

DIROP2:	MOVEM	S1,MTAIFN(J)		;SAVE IFN
	MOVNI	S2,1			;-1 FOR ACTUAL FILESPEC
	PUSHJ	P,F%FD			;GET FILESPEC
	JUMPF	DIROP3			;CHECK FOR ERRORS
	LOAD	S2,.FDLEN(S1),FD.LEN	;GET RETURNED FD LENGTH
	HRLZS	S1			;POINT FD IN LH
	HRRI	S1,MTAFIL(J)		;AND TO OUR STORAGE
	ADDI	S2,MTAFIL(J)		;COMPUTE END OF BLT
	BLT	S1,-1(S2)		;COPY RETURNED FD

DIROP3:	PUSHJ	P,DIRHDR		;GENERATE HEADER
	MOVEI	S1,MTAFIL(J)		;ADDRESS OF FILESPEC
	MOVE	S2,STREAM##		;STREAM NUMBER
	$WTO	(<Magtape directory file: ^F/(S1)/>,,@JOBOBA##(S2))
	$RETT				;AND RETURN
DIRFOB:	$BUILD	(FOB.SZ)		;BLOCK LENGTH
	  $SET	(FOB.CW,FB.PHY,1)	  ;PHYSICAL I/O
	  $SET	(FOB.CW,FB.NFO,1)	  ;NEW FILE ONLY
	  $SET	(FOB.CW,FB.BSZ,7)	  ;7-BIT BYTES
	  $SET	(FOB.AB,FWMASK,DIRFAB)	  ;FILE ATTRIBUTES BLOCK ADDRESS
	$EOB				;END OF BLOCK

DIRFD:	$BUILD	(FDXSIZ)		;BLOCK LENGTH
	  $SET	(.FDLEN,FD.LEN,FDXSIZ)	  ;LENGTH OF FILESPEC
	  $SET	(.FDLEN,FD.TYP,.FDNAT)	  ;NATIVE MODE FILESPEC
	  $SET	(.FDSTR,FWMASK,'SPL   ')  ;DEVICE NAME
	  $SET	(.FDEXT,LHMASK,'DIR')	  ;EXTENSION
	$EOB				;END OF BLOCK

DIRFAB:	$BUILD	(7)			;BLOCK LENGTH
	  $SET	(0,,7)			  ;SIZE OF ENTIRE BLOCK
	  $SET	(1,FI.LEN,1)		  ;LENGTH OF ARGUMENT
	  $SET	(1,FI.ATR,.FIPRO)	  ;PROTECTION CODE
	  $SET	(2,FWMASK,<MTAPRT(J)>)	  ;PROTECTION CODE ADDRESS
	  $SET	(3,FI.LEN,1)		  ;LENGTH IS ONE WORD
	  $SET	(3,FI.ATR,.FIBSZ)	  ;THE LOGICAL DATA BYTE SIZE
	  $SET	(4,FWMASK,7)		  ;DEFINED VALUE
	  $SET	(5,FI.IMM,1)		  ;IMMEDIATE ARGUMENT
	  $SET	(5,FI.LEN,1)		  ;LENGTH IS ONE WORD
	  $SET	(5,FI.ATR,.FIDTY)	  ;THE DATA TYPE
	  $SET	(6,,.RBDAS)		  ;ASCII
	$EOB				;END OF BLOCK


DIRTAB:	$STAB
	KEYTAB	(0,<ABORT>)
	KEYTAB	(1,<PROCEED>)
	$ETAB

DIRRSP:	ASCIZ	/
Type 'RESPOND <number> ABORT' to requeue job and shutdown stream
Type 'RESPOND <number> PROCEED' when problem has been resolved
/
SUBTTL	Miscellaneous routines


; ROUTINE TO DO TAPE POSITIONING
; CALL:	MOVE	S1, TAPOP. UUO FUNCTION CODE
;	PUSHJ	P,TAPOP

TAPOP:	MOVE	TF,[2,,S1]		;SET UP UUO AC
	MOVE	S2,J$LCHN(J)		;GET CHANNEL NUMBER
	TAPOP.	TF,			;DO TAPE OPERATION
	  JFCL				;IGNORE ERRORS
	MOVE	S1,TF			;GET RESULT
	POPJ	P,			;RETURN


; ROUTINE TO REPORT AN UNEXPECTED TAPOP. UUO ERROR
; CALL:	MOVE	T1, ERROR CODE
;	MOVE	T2, WTO "TYPE" TEXT
;	PUSHJ	P,TAPERR

TAPERR:	MOVEI	T3,[ITEXT (<Unexpected TAPOP. UUO error ^O/T1/>)]
	MOVE	T4,STREAM##		;GET STREAM NUMBER
	$WTO	(<^T/(T2)/>,<^T/(T3)/>,@JOBOBA##(T4))
	POPJ	P,			;RETURN
; ROUTINE TO CHECK FOR AND REPORT LABELING ERRORS
; CALL:	PUSHJ	P,TAPLBE
;
; TRUE RETURN:	NO ERRORS EXIST, S1 CONTAINS I/O STATUS WORD
; FALSE RETURN:	LABELING ERROR CODE RETURNED IN S1

TAPLBE:	MOVE	S1,J$LIOS(J)		;GET I/O STATUS WORD
	TRC	S1,IO.ERR		;CHECK FOR TAPE
	TRCE	S1,IO.ERR		; LABELING ERROR
	$RETT				;NOT ONE OF THESE
	MOVE	S1,J$XIOS(J)		;GET EXTENDED STATUS
	JUMPE	S1,TAPLB1		;RETURN IF NOTHING
	CAIE	T1,IOVFE%		;IS THE ERROR BAD VFU ?
	CAIN	T1,IOPAR%		;RAM PARITY ERROR?
	JRST	LP2OER			;YES
	CAIN	T1,IOUNC%		;UNDEFINED CHARACTER INTERRUPT?
	JRST	LP2OER			;YES
	CAIE	S1,IONOP%		;NO-OP?
	CAIN	S1,IOEOF%		;EOF?
	JRST	TAPLB1			;NOT AN ERROR
	CAIN	S1,IOBOT%		;BOT?
	JRST	TAPLB1			;NOT AN ERROR
	PUSH	P,T1			;SAVE T1
	MOVE	T1,S1			;SAVE ERROR CODE
	PUSHJ	P,TAPCLR		;CLEAR LABELING ERRORS
	PUSHJ	P,TAPDEV		;GET PHYSICAL DRIVE NAME IN MTATMP(J)
	MOVE	S1,STREAM##		;GET STREAM NUMBER
	$WTO	(<Labeling error ^O/T1/ on device ^W/MTATMP(J)/>,,@JOBOBA(S1))
	MOVE	S1,T1			;GET ERROR CODE BACK IN S1
	POP	P,T1			;RESTORE T1
	$RETF				;RETURN

TAPLB1:	MOVE	S1,J$LIOS(J)		;GET I/O STATUS
	$RETT				;AND RETURN

LP2OER:	PUSHJ	P,LPTOER##		;REPORT "LP20" ERRORS
	$RETF				;RETURN "ERROR PROCESSED"
; ROUTINE TO CLEAR TAPE ERRORS
; CALL:	PUSHJ	P,TAPCLR

TAPCLR:	PUSH	P,S2+1			;SAVE AC
	MOVE	TF,[3,,S1]		;SET UP UUO AC
	MOVEI	S1,.TFURQ		;USER REQUEST
	MOVE	S2,J$LCHN(J)		;CHANNEL NUMBER
	MOVEI	S2+1,.TFCLE		;SUB-FUNCTION
	TAPOP.	TF,			;CLEAR LABELING ERRORS
	  JFCL				;IGNORE ERRORS
	POP	P,S2+1			;RESTORE AC
	POPJ	P,			;RETURN


; ROUTINE TO DETERMINE PHYSICAL TAPE DRIVE NAME AND STORE IT
; IN MTATMP(J) FOR WTO MESSAGES
; CALL:	PUSHJ	P,TAPDEV

TAPDEV:	PUSH	P,T1			;SAVE T1
	MOVE	T1,J$LCHN(J)		;GET CHANNEL NUMBER
	DEVNAM	T1,			;CONVERT TO NAME
	  MOVSI	T1,'MTA'		;???
	MOVEM	T1,MTATMP(J)		;SAVE
	POP	P,T1			;RESTORE T1
	POPJ	P,			;RETURN


; ROUTINE TO READ I/O STATUS
; CALL:	PUSHJ	P,TAPIOS

TAPIOS:	MOVE	S1,J$LCHN(J)		;GET CHANNEL NUMBER
	LSH	S1,^D23			;POSITION IT
	IOR	S1,[GETSTS J$LIOS(J)]	;MAKE IT AN INSTRUCTION
	XCT	S1			;AND EXECUTE IT
	MOVE	S1,J$LIOS(J)		;PUT IN S1 TOO
	TRC	S1,IO.ERR		;MUST SEE IF
	TRCN	S1,IO.ERR		; EXTENDED STATUS NEEDED TOO
	$RET				;NO, DONE
	MOVE	TF,[2,,S1]		;PREPARE FOR DEVOP. UUO
	MOVEI	S1,.DFRES		;READ EXTENDED ERROR STATUS
	MOVE	S2,J$LCHN(J)		;GET CHANNEL NUMBER
	DEVOP.	TF,
	  SETZ	TF,			;???
	MOVEM	TF,J$XIOS(J)		;SAVE FOR POSTERITY
	MOVE	S1,J$LIOS(J)		;RETURN STANDARD ERROR STATUS
	POPJ	P,			;RETURN
; ROUTINE TO SET AND/OR READ TAPE PARITY
TAPPAR:	JUMPE	S1,TAPPA1		;JUMP IF ONLY READING
	MOVE	T1,[3,,T2]		;SET UP UUO AC
	MOVEI	T2,.TFPAR+.TFSET	;FUNCTION CODE
	MOVE	T3,J$LCHN(J)		;CHANNEL
	LOAD	T4,MTACND(J),OB.MPR	;GET DESIRED PARITY
	SOJL	T4,TAPPA1		;DO NOTHING IF DEFAULTING
	TAPOP.	T1,			;SET DENSITY
	  SKIPA	T2,[[ITEXT (<Cannot set magtape parity on ^W/MTATMP(J)/>)]]
	JRST	TAPPA1			;GO READ IT BACK
	PUSHJ	P,TAPERR		;REPORT FAILURE
	$RETF				;RETURN

TAPPA1:	MOVEI	S1,.TFPAR		;FUNCTION CODE
	PUSHJ	P,TAPOP			;READ PARITY
	STORE	S1,MTACND(J),OB.MPR	;SAVE
	$RETT				;RETURN


; ROUTINE TO SET AND/OR READ TAPE DENSITY
TAPDEN:	JUMPE	S1,TAPDE1		;JUMP IF ONLY READING
	MOVE	T1,[3,,T2]		;SET UP UUO AC
	MOVEI	T2,.TFDEN+.TFSET	;FUNCTION CODE
	MOVE	T3,J$LCHN(J)		;CHANNEL
	LOAD	T4,MTACND(J),OB.MDN	;GET DESIRED DENSITY
	TAPOP.	T1,			;SET DENSITY
	  SKIPA	T2,[[ITEXT (<Cannot set magtape density on ^W/MTATMP(J)/>)]]
	JRST	TAPDE1			;GO READ IT BACK
	PUSHJ	P,TAPERR		;REPORT FAILURE
	$RETF				;RETURN

TAPDE1:	MOVEI	S1,.TFDEN		;FUNCTION CODE
	PUSHJ	P,TAPOP			;READ DENSITY
	STORE	S1,MTACND(J),OB.MDN	;SAVE
	$RETT				;RETURN
; ROUTINE TO REQUEST A REEL SWITCH
; CALL:	PUSHJ	P,TAPRSW
;
; TRUE RETURN:	SWITCHED TO A NEW REEL
; FALSE RETURN:	REEL SWITCH CANCELED BY OPERATOR

TAPRSW:	MOVEI	S1,.TFWTM		;FUNCTION CODE
	PUSHJ	P,TAPOP			;WRITE A TAPE MARK
	MOVE	S1,J$LCHN(J)		;GET THE CHANNEL
	LSH	S1,^D23			;POSITION THE CHANNEL NUMBER
	TLO	S1,(SETSTS 0,(S2))	;FORM INSTRUCTION
	MOVEI	S2,IO.ERR!IO.EOT	;ERROR + EOT BITS
	ANDCAB	S2,J$LIOS(J)		;CLEAR
	XCT	S1			;UPDATE I/O STATUS
	PUSHJ	P,TAPDEV		;GET PHYSICAL DRIVE NAME IN MTATMP(J)
	MOVEI	S1,.TFLBL		;FUNCTION CODE
	PUSHJ	P,TAPOP			;READ LABEL TYPE
	JUMPE	S1,TAPRS1		;DO SPECIAL STUFF FOR BYPASS
	MOVE	T1,[2,,T2]		;SET UP UUO AC
	MOVEI	T2,.TFFEV		;FUNCTION CODE
	MOVE	T3,J$LCHN(J)		;CHANNEL NUMBER
	TAPOP.	T1,			;FORCE EOV (REQUEST REEL SWITCH)
	  SKIPA	T2,[[ITEXT (<Reel switch failed on device ^W/MTATMP(J)/>)]]
	$RETT				;RETURN GOODNESS
	PUSHJ	P,TAPERR		;REPORT UNEXPECTED TAPOP. UUO ERROR
	$RETF				;GIVE UP

TAPRS1:	MOVEI	S1,.TFUNL		;FUNCTION CODE
	PUSHJ	P,TAPOP			;UNLOAD THE TAPE
	MOVEI	T1,[ITEXT (<End of tape on device ^W/MTATMP(J)/>)]
	MOVEI	T2,[ITEXT (<Please mount next volume^T/RSWRSP/>)]
	MOVEI	T3,RSWTAB		;KEYWORD TABLE
	PUSHJ	P,LPTOPR##		;ASK FOR OPERATOR ACTION
	CAIE	S1,1			;WAS ANSWER "PROCEED"
	$RETF				;GIVE UP
	$RETT				;RETURN


RSWTAB:	$STAB
	KEYTAB	(0,<ABORT>)
	KEYTAB	(1,<PROCEED>)
	$ETAB


RSWRSP:	ASCIZ	/
Type 'RESPOND <number> ABORT' to terminate job
Type 'RESPOND <number> PROCEED' when new tape mounted
/
SUBTTL	Literal pool


MTALIT:	LIT

MTAEND::!END