Google
 

Trailing-Edge - PDP-10 Archives - tops10_704_monitoranf_bb-x140c-sb - 10,7/mon/usronc.mac
There are no other files named usronc.mac in the archive.
TITLE	USRONC - USER MODE INTERFACE FOR ONCE-ONLY DIALOGUE
SUBTTL	NED SANTEE			13-SEP-88

	SEARCH	F,S,DEVPRM,UUOSYM
	$RELOC
	$TWICE

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1987,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1987,1988>

XP	VUSRONC,20

;THIS MUST BE THE *LAST* MONITOR MODULE LOADED AS THE MONEND DEFINITIONS
;ARE DEFINED HERE.

	ENTRY	USRONC

	BLKPUN==^D50		;NUMBER OF BLOCKS/SCRATCH UNIT
	SUBTTL	TWICE ROUTINES

;IF THE MONITOR IS STARTED IN USER MODE THE FOLLOWING CODE WILL BE CALLED TO
;RUN THROUGH THE ONCE (TWICE) DIALOGUE.

USRONC::RESET			;FORGIVE THE WORLD, FOR IT HAS SINNED
	SETOM	.UONCE##	;FLAG THAT WE ARE IN TWICE
	SETOM	DINITF##	;WE ARE SORT OF LIKE SYSINI
	SETZM	FILFLG		;NO SCRATCH FILE SPECIFIED INITIALLY
	MOVEI	T1,ONCTYO##	;ROUTINE TO HANDLE TTY OUTPUT
	MOVEM	T1,.C0TOA##	;PLACE IT IN THE CDB
	MOVE 	P,.C0NPD##	;USE THE NULL JOBS STACK
	PUSHJ	P,PAGINI	;INIT PAGING AND SECTION MAGIC
	MOVE	T1,[%CNTIC]	;TICSEC
	GETTAB	T1,		;READ IT
	  MOVEI	T1,^D60		;ASSUME IT
	MOVEM	T1,TICSEC##	;SET IT FOR SYSINI
	IMULI	T1,^D60		;MAKE TICS PER MINUTE
	MOVEM	T1,TICMIN##	;SYSINI WANTS THIS AS WELL
	PUSHJ	P,FIXLOK	;NEUTER INTERLOCKS
	MOVEI	T1,DOLBLK	;SETUP .JBINT TO INTERCEPT DISK OFF LINE
	MOVEM	T1,.JBINT##	;ALSO INTERCEPT XJRSTs ON THE KS
	PUSHJ	P,BLDDAT	;SET UP DISK DATABASE
	  HALT	.		;NO CORE OR KDB TABLE FULL, LIFE IS GRIM
	SETZM	NOTPRV		;ASSUME A PRIVILEGED USER
	MOVE	T1,[%LDFFA]	;SET UP FOR GETTAB OF FFA PPN
	GETTAB	T1,		;WHAT IS THE FFA PPN
	  MOVE	T1,FFAPPN##	;HMMMM, JUST TAKE A GUESS
	GETPPN	T2,		;GET OUR PPN
	  JFCL			;WE REALLY DON'T CARE
	CAME	T1,T2		;ARE WE FFA?
	SETOM	NOTPRV		;NOT PRIVILEGED
	MOVEI	T1,[ASCIZ /Use scratch file/]
	MOVSI	T2,'NO '	;DEFAULT RESPONSE
	SKIPE	NOTPRV		;NOT PRIVILEGED?
	MOVSI	T2,'YES'	;DIFFERENT DEFAULT
	PUSHJ	P,PRSYNQ##	;ASK YES/NO
	SKIPE	T1		;WANT SCRATCH FILE?
	SETOM	FILFLG		;YES
	JUMPN	T1,USRON1	;NO PRIVS NEEDED IF I/O TO SCRATCH FILE
	SKIPE	NOTPRV		;NON-PRIVILEGED USER?
	JRST	USRXIT		;NOPE SCREAM AND DIE
USRON1:	PUSHJ	P,GETRWT	;ALLOCATE TABLES FOR READ/WRITE UNITS
	MOVEI	T1,[ASCIZ /Read units:/]
	MOVE	T3,REDTAB	;ADDRESS OF TABLE TO FILL
	SETZ	S,		;READING UNITS
	PUSHJ	P,ASKRWT	;PROMPT FOR UNITS
	MOVEI	T1,[ASCIZ /Write units:/]
	MOVE	T3,WRTTAB	;ADDRESS OF TABLE TO FILL
	MOVSI	S,IO		;WRITING UNITS
	PUSHJ	P,ASKRWT	;PROMPT FOR UNITS
	SETZM	CURUNI		;FORCE DSKCHR TO BE DONE AGAIN LATER
	MOVE	T1,[-USRLEN,,USRCMD] ;AOBJN POINTER TO COMMANDS
	MOVEM	T1,OPTPTR##	;SAVE FOR SYSINI
	MOVEI	T1,USRDSP	;DISPATCH TABLE
	MOVEM	T1,OPTDSP##	;SAVE FOR SYSINI
	MOVEI	T1,USRHLP	;HELP TEXT
	MOVEM	T1,OPTHLP##	;SAVE FOR SYSINI
	MOVE	T1,[-USRSWL,,USRSWN] ;AOBJN POINTER TO SWITCHES
	MOVEM	T1,SWTPTR##	;SAVE FOR SYSINI
	MOVEI	T1,USRSWD	;DISPATCH TABLE
	MOVEM	T1,SWTDSP##	;SAVE FOR SYSINI
	MOVEI	T1,USRSWH	;HELP TEXT TABLE
	MOVEM	T1,SWTHLP##	;SAVE FOR SYSINI
	MOVE	T1,[-SHWLEN,,SHWTAB] ;AOBJN POINTER TO SHOW COMMANDS
	MOVEM	T1,SHWPTR##	;SAVE FOR SYSINI
	MOVEI	T1,SHWADR	;DISPATCH TABLE
	MOVEM	T1,SHWDSP##	;SAVE FOR SYSINI
	MOVE	T1,[-CHGLEN,,CHGTAB] ;AOBJN POINTER TO CHANGE COMMANDS
	MOVEM	T1,CHGPTR##	;SAVE FOR SYSINI
	MOVEI	T1,CHGADR	;DISPATCH TABLE
	MOVEM	T1,CHGDSP##	;SAVE FOR SYSINI
	PJRST	STRTUP##	;START THE MONITOR

USRXIT:	MOVEI	T1,[ASCIZ .? Must be [1,2].]  ;MESSAGE TO PUT OUT
	PUSHJ	P,CONOUT##	;PRINT ERROR MESSAGE
.EXIT:	EXIT	1,		;LEAVE HERE
	JRST	.-1		;DON'T CONTINUE
DEFINE	OPTINS,<

X (CHANGE,.CHANG##,<Change system parameters>)
X (DEFINE,.DEFIN##,<Define structures and system lists>)
X (DISSOLVE,.DISSO##,<Dissolve a single structure>)
X (EXIT,.GO##,<Return to monitor level>)
X (REFRESH,.REFRE##,<Refresh selected structures>)
X (SHOW,.SHOW##,<Display system parameters>)

>; END DEFINE OPTINS


DEFINE SWTCHS,<
X (NOERROR,.IGNOR,<Re-write HOM blocks despite errors>)
> ;END DEFINE SWTCHS

DEFINE	X	(NAME,ADDR,HELP),<EXP	<SIXBIT/'NAME/>>
USRCMD:	OPTINS
USRLEN==.-USRCMD

USRSWN:	SWTCHS
USRSWL==.-USRSWN

DEFINE	X	(NAME,ADDR,HELP),<IFIW	ADDR>
USRDSP:	OPTINS

USRSWD:	SWTCHS

DEFINE	X	(NAME,ADDR,HELP),<IFIW	[ASCIZ \'HELP\]>
USRHLP:	OPTINS

USRSWH:	SWTCHS



DEFINE	CHGOPT,<

X	(ASL,CHGASL##)
X	(SDL,CHGSDL##)
X	(SETS,CHGSET##)
X	(SSL,CHGSSL##)
X	(STRUCT,CHGSTR##)
X	(UNIT,CHGUNI##)

> ;END DEFINE CHGOPT

DEFINE	X	(NAME,ADDR),<EXP <SIXBIT/NAME/>>
CHGTAB:	CHGOPT
CHGLEN==.-CHGTAB

DEFINE	X	(NAME,ADDR),<IFIW ADDR>
CHGADR:	CHGOPT


DEFINE	SHWOPT,<

X	(ASL,SHWASL##)
X	(NETWOR,SHWNET##)
X	(SDL,SHWSDL##)
X	(SETS,SHWSET##)
X	(SSL,SHWSSL##)
X	(STRUCT,SHWSTR##)
X	(UNIT,SHWUNI##)

> ;END DEFINE SHWOPT

DEFINE	X	(NAME,ADDR),<EXP <SIXBIT/NAME/>>
SHWTAB:	SHWOPT
SHWLEN==.-SHWTAB

DEFINE	X	(NAME,ADDR),<IFIW ADDR>
SHWADR:	SHWOPT


.IGNOR:	SETOM	IGNORE##	;LIGHT FLAG FOR SYSINI
	JRST	CPOPJ1##	;SUCCESSFUL SWITCH
;INITIALIZE USER MODE PAGING

PAGINI:	SETZ	T1,		;MAKE THE HIGH-SEG WRITEABLE
	SETUWP	T1,		;SO WE CAN TOUCH THE WORLD!
	  HALT	.		;DOESN'T LOOK GOOD
	MOVE	T1,.JBREL##	;CURRENT END OF LOWSEG
	AOS	T1		;POINT TO START OF FREE SPACE
	MOVEM	T1,.JBFF##	;FOR CORE ALLOCATION
	MOVEI	T1,CSBORG##-1	;HIGHEST AMOUNT TO GROW TO
	MOVEM	T1,LOWLIM##	;AND REMEMBER THAT
	MOVE	T1,.JBFF##	;WHERE WE CAN ALLOCATE MEMORY
	MOVEM	T1,SYSSIZ##	;REMEBER THAT FOR GETWDS
	MOVNI	T2,<.CPLEN##+PG.BDY>/PAGSIZ ;-VE NUMBER OF PAGES IN CDB
	MOVE	T1,[XWD .PAGCD,T2] ;CREATE PAGES, BLOCK STARTING AT T2
	MOVE	T3,[PA.GDC!<.CPCDB##/PAGSIZ>] ;START HERE EVEN IF ALREADY EXIST
	PAGE.	T1,		;CREATE THEM
	  HALT	.		;OOPS, HOW DID THIS HAPPEN?
IFN FTXMON,<
	MOVE	T1,[.PAGSC,,T2]	;UUO AC
	MOVEI	T2,1
	MOVE	T3,[PA.GMS!PA.GDC!<0,,1>]
	PAGE.	T1,		;MAP SECTIONS 0 AND 1 TOGETHER
	  HALT	.
	MOVE	T3,[PA.GAF!PA.GDC!<(MS.SAT)>] ;DELETE SECTION WITH SATS
	PAGE.	T1,		;RESET CORE USAGE
	  MOVE	T1,[.PAGSC,,T2]	;RESET UUO AC & IGNORE ERROR
	MOVE	T3,[PA.GAF!PA.GDC!2] ;DELETE WHOLE SECTION
	SKIPN	.JBDDT##	;PATCH TO JFCL IF YOU DON'T LIKE/WANT SYMBOLS
	PAGE.	T1,		;THROW AWAY SECTION 2
	  JFCL			;DON'T CARE
	MOVE	T1,NZSFCH##+<(MS.SAT)> ;HEADER FOR SAT CORE
	MOVEM	T1,NZSFCE##+<(MS.SAT)> ;INITIALIZE TAIL POINTER
> ;END IFN FTXMON
	MOVE	T1,[.C0CDB##,,.CPCDB##] ;MOVE .C0 INTO .CP SPACE
	BLT	T1,.CPCDB##+.CPLEN##-1 ;SPLAT
	POPJ	P,		;RETURN


;NEUTER INTERLOCKS
FIXLOK:	MOVSI	T1,-LOKLEN	;AOBJN POINTER
	MOVSI	T2,(POPJ P,)	;TURN INTO NOOP
	MOVEM	T2,@LOKTAB(T1)	;TURN OFF LOCK OR UNLOCK
	AOBJN	T1,.-1		;LOOP FOR ALL INTERLOCKS
	POPJ	P,		;RETURN

LOKTAB:	EXP	LOKSPI##,ONPOPJ## ;SYSTEM
	EXP	LOKBTI##,ONPOPB## ;BIT DIDDLER
	EXP	LOKDPI##,ONPOPD## ;DISK
IFN FTMP,<
	EXP	DDBLOK##,DDBULK## ;DDB SCANNING
>; END IFN FTMP
LOKLEN==.-LOKTAB		;LENGTH OF TABLE
SUBTTL	SET UP TWICE DATA BASE

;THIS ROUTINE BUILDS THE DATA STRUCTURES NEEDED BY THE ONCE CODE BASED
;ON THE CONFIGURATION OF THE RUNNING MONITOR.  THIS CODE DEPENDS ON
;TWICE BEING ASSEMBLED WITH THE SUPPLIED CONFIGURATION FILE.

BLDDAT:	SE1ENT			;JUMP TO SECTION 1
	PUSHJ	P,AUTINI##	;INITIALIZE AUTCON'S DATABASE
	SETZM	KDBTAB##+.TYDSK	;ZERO LINK TO FIRST KONTROLLER IN SYSTEM
	HRRZS	SYSUNI##	;ZERO LINK TO FIRST UNIT IN SYSTEM
	SETZ	P2,		;START WITH FIRST UNIT
BLDDT1:	SYSPHY	P2,		;GET THE NEXT UNIT
	  JRST	CPOPJ1##	;ASSUME NO MORE UNTIS
	SKIPN	T1,P2		;GET UNIT NAME
	JRST	CPOPJ1##	;DONE, GO ASK FOR READ, WRITE UNITS
	PUSHJ	P,GETDSK	;READ DISK CHARACTERISTICS
	  JRST	BLDDT1		;DUH?
	PUSHJ	P,FNDDSP	;FIND THE DRIVER DISPATCH FOR UNIT
	  JRST	BLDDT1		;NOT LOADED IN THIS MONITOR
	MOVE	T2,T1		;PUT IN PROPER PLACE
	HLRZ	T1,P2		;FAKE UP A UNIT PER-KONTROLLER DEVICE CODE
	SETZ	T3,		;NO CHANNEL DATA BLOCK YET
	PUSHJ	P,AUTSET##	;SET UP FOR AUTOCONFIGURE
	MOVSI	T1,0		;CHANNEL BITS
	PUSHJ	P,AUTCHN##	;BUILD A CHANNEL DATA BLOCK
	  POPJ	P,		;NO CORE
	MOVE	T1,P2		;GET UNIT NAME
	PUSHJ	P,SETCTR	;FAKE UP AUTCON'S COUNTERS TO MAGIC HAPPENS
	MOVNI	T1,1		;WE DON'T HAVE REAL MASSBUS UNITS EITHER
	PUSHJ	P,AUTKDB##	;BUILD A KDB (COMES BACK IN W)
	  POPJ	P,		;NO CORE
	MOVE	J,W		;PUT KDB IN J FOR DSKDRV
	PUSHJ	P,PHYUNI	;RETURN PHYSICAL UNIT,,TABLE OFFSET
	  JRST	BLDDT1		;KDB TABLE FULL
	MOVE	T2,CHRUTY	;GET UNIT TYPE
	PUSHJ	P,DSKDRV##	;BUILD A UDB
	  POPJ	P,		;NO CORE SO STOP NOW
	MOVE	T1,CHRBTS	;GET THE UNIT FLAGS
	MOVEM	T1,UNIDES(U)	;NOW THAT WE HAVE U, SAVE THEM AWAY
	MOVE	T1,CHRBUF+.DCPAS ;GET POSITION IN ASL
	MOVEM	T1,UNISUN(U)	;SAVE POSITION IN THE ACTIVE SWAPPING LIST
	MOVE	T1,CHRBUF+.DCUID ;GET UNIT'S PACK NAME
	MOVEM	T1,UNIHID(U)	;SAVE AWAY
	MOVSI	T1,UNPNNA	;USER-MODE TIMESHARED BIT
	SKIPE	CHRBUF+.DCSNM	;IF THIS UNIT IS IN A MOUNTED STRUCTURE,
	IORM	T1,UNIDES(U)	;FLAG FOR THOSE COMMANDS THAT CARE
	JRST	BLDDT1		;LOOP FOR OTHER UNITS


;FIND A DRIVER DISPATCH
FNDDSP:	MOVEI	T1,DRVLST##-DRVLNK ;SET PREDECESSOR
FNDDS1:	SKIPN	T1,DRVLNK(T1)	;LINK TO NEXT DISPATCH
	POPJ	P,		;NO MORE
	LDB	T2,[POINTR (DRVCNF(T1),DR.DVT)] ;GET DEVICE TYPE
	CAIE	T2,.TYDSK	;A DISK?
	JRST	FNDDS1		;NOPE
	LDB	T2,[POINTR (DRVCF2(T1),DR.KTY)] ;GET KONT TYPE FROM DRIVER
	MOVE	T3,CHRKTY	;GET KONTROLLER TYPE
	CAIE	T2,(T3)		;MATCH?
	JRST	FNDDS1		;TRY ANOTHER
	JRST	CPOPJ1##	;RETURN GOODNESS


;SETUP AUTCON COUNTERS
SETCTR:	PUSH	P,T1		;SAVE UNIT NAME FROM MONITOR
	MOVE	T1,.CPCPN##	;GET OUR CPU NUMBER
	PUSHJ	P,AUTADP##	;GENERATE A BYTE POINTER
	POP	P,T3		;GET UNIT NAME BACK
	HLRZS	T3		;KEEP ONLY KONT NAME
	ANDI	T3,77		;STRIP DOWN TO SPECIFIC KONTROLLER
	SUBI	T3,'A'		;REDUCE TO KONTROLLER NUMBER
	MOVEI	T4,1(T3)	;PLUS ONE TO AVOID OVERFLOW
	DPB	T4,T1		;STORE AS LIMIT FOR THIS CPU
IFE FTXMON,<AOS	T1>		;ADVANCE TO ALLOCATED WORD
IFN FTXMON,<AOS	T2>		;ADVANCE TO ALLOCATED WORD
	DPB	T3,T1		;SET ALLOCATED COUNT SO FAR
	POPJ	P,		;RETURN

;OBTAIN PHYSICAL UNIT NUMBER AND KONTROLLER TABLE OFFSET
PHYUNI:	MOVE	T1,CHRPUN	;GET PHYSICAL UNIT NUMBER
	HRLS	T1		;MAKE IT PHYSICAL,,OFFSET
	MOVE	T2,CHRKTY	;GET KONTROLLER TYPE
	CAIE	T2,TYPRA	;CI DISK?
	JRST	CPOPJ1##	;NO--DONE
	MOVE	T2,KDBIUN(J)	;AOBJN POINTER TO UNITS
	SKIPE	(T2)		;FREE SLOT?
	AOBJN	T2,.-1		;KEEP LOOKING
	JUMPGE	T2,CPOPJ##	;NO MORE ROOM
	SUB	T2,KDBIUN(J)	;REDUCE TO OFFSET
	HRL	T2,T1		;GET PHYSICAL UNIT,,OFFSET
	MOVE	T1,T2		;PUT IN PROPER AC
	JRST	CPOPJ1##	;RETURN
SUBTTL	DATE/TIME SUPPORT

USRDTM::TIMER	T1,		;GET TIME OF DAY IN JIFFIES
	MOVE	T2,[%CNDAY]	;LOCDAY GETTAB
	MOVE	T3,[%CNMON]	;LOCMON GETTAB
	MOVE	T4,[%CNYER]	;LOCYER GETTAB
	GETTAB	T2,		;GRAB IT
	  HALT			;SICK MONITOR?
	GETTAB	T3,		;THEN MONTH
	  HALT
	GETTAB	T4,		;AND THE YEAR
	  HALT
	MOVEM	T2,LOCDAY##	;SAVE IT AWAY
	MOVEM	T3,LOCMON##	;FOR DATIME
	MOVEM	T4,LOCYER##
	TIMER	T2,		;GET SOME JIFFIES AGAIN
	CAMGE	T2,T1		;DID WE CROSS MIDNIGHT OR SOMETHING?
	JRST	USRDTM		;YES--TRY IT AGAIN
	MOVEM	T2,TIME##	;NO--STORE THE CURRENT JIFFIES AWAY
	DATE	T2,		;GET 15-BIT DATE
	MOVEM	T2,THSDAT##	;SAVE FOR REFSTR
	PJRST	SUDATE##	;RECOMPUTE UNIVERSAL DATE/TIME AND RETURN
SUBTTL	CORE ALLOCATION

IFN FTXMON,<
USRNZN::CAIE	T2,1		;BETTER ONLY WANT ONE PAGE
	POPJ	P,		;FAIL OTHERWISE
	MOVSI	P1,-<HLGPNO+1>/8 ;HOW MANY ITERATIONS
	MOVEI	T1,<(MS.SAT)>_S2PLSH ;STARTING PAGE NUMBER
	MOVE	P2,[.PAGAL,,PALBUF] ;SETUP UUO AC

USRNZ1:	MOVEM	T1,PALBUF+1	;SETUP STARTING PAGE FOR THIS PASS
	PAGE.	P2,		;GET A LIST OF PAGES
	  POPJ	P,		;PROPAGATE FAILURE
	MOVSI	T2,-8		;HOW MANY PAGES TO CHECK
	SKIPL	PALBUF+2(T2)	;IF THIS ONE EXISTS,
	AOBJN	T2,.-1		;CHECK THE NEXT
	ADDI	T1,(T2)		;UPDATE PAGE NUMBER
	JUMPL	T2,USRNZ2	;SUCCEED IF FOUND A NON-EX PAGE IN MS.SAT
	AOBJN	P1,USRNZ1	;KEEP TRYING IF NOT
	POPJ	P,		;ENTIRE SECTION SEEMS TO BE FULL

USRNZ2:	MOVE	P1,[.PAGCD,,P2]	;UUO ARGUMENT
	MOVEI	P2,1		;ONE PAGE TO BE CREATED
	MOVEI	P3,(T1)		;COPY IT
	LSH	T1,P2WLSH	;OUR RETURN VALUE IS AN ADDRESS
	PAGE.	P1,		;CREATE THE PAGE
	  TRNA			;MAYBE NO ROOM--TRY VIRTUAL PAGE
	JRST	CPOPJ1##	;PROPAGATE SUCCESS
	MOVE	P1,[.PAGCD,,P2]	;RESET UUO AC
	TLO	P3,(PA.GCD)	;ON-DISK FLAG
	PAGE.	P1,		;TRY AGAIN
	  POPJ	P,		;PROPAGATE FAILURE IF CAN'T CREATE IT ABZ
	JRST	CPOPJ1##	;WE WIN

PALBUF:	EXP	8+2+1		;BUFFER SIZE + OVERHEAD + OFF-BY-ONE BUG
	BLOCK	8+1+1		;STARTING PAGE + BUFFER + SLOP
> ;END IFN FTXMON
SUBTTL	TWICE DISK I/O

;THE FOLLOWING ROUTINE DOES THE USER MODE DISK I/O FOR TWICE.  THIS
;ROUTINE USES SUSET. TO POSITION FOR THE READ/WRITE OF THE DISK

	DSK==1			;I/O CHANNEL

USRDIO::SKIPN	FILFLG		;SKIP IF USING SCRATCH FILE
	JRST	USRDI1		;NO, REGULAR WAY
	SKIPG	FILFLG		;SKIP IF FILE OPEN
	PUSHJ	P,OPNFIL	;NO, OPEN IT
	PUSHJ	P,FNDUNI	;FIND 1ST BLOCK FOR THIS UNIT
	 STOPCD	.,STOP,UIONSU,	;++NO SUCH UNIT
	IMULI	T1,BLKPUN	;TIMES BLOCKS=BEGINNING OF THIS UNIT
	MOVE	T2,DEVBLK##(F)	;BLOCK ON UNIT
	CAILE	T2,BLKPUN-1	;SKIP IF IN RANGE
	MOVEI	T2,BLKPUN-1	;DONT OVERFLOW TO FOLLOWING UNITS
	ADD	T1,T2		;ADD IN BLOCK ON UNIT, = BLOCK FOR IO
	ADDI	T1,1		;FIRST BLOCK OF FILE = 1, NOT ZERO
	MOVEM	T1,FOPBLK	;SAVE BLOCK FOR I/O IN MEMORY
	JRST	USRDIX		;CONTINUE

USRDI1:	CAME	U,CURUNI	;SKIP IF UNIT OPEN
	PUSHJ	P,OPNUNI	;NO, OPEN UNIT
	 PUSHJ	P,CHKIO		;UNIT OPEN--SEE IF READ OR WRITE IS LEGAL
	   JRST	[MOVSI	T1,UNPOFL ;BIT FOR OFFLINE
		 IORM	T1,UNIDES(U) ;SET IT
		 HRRI	S,IO.ERR ;LIGHT ALL ERROR BITS
		 JRST	USRDOE]	;AND RETURN BADNESS
USRDIX:	MOVEI	T1,.FOFXI	;SET FOR IN
	TLNE	S,IO		;OR WAS THIS FOR OUTPUT?
	MOVEI	T1,.FOFXO	;YES--DO AN OUT
	HRRM	T1,FOPIOB	;SET IN FILOP. BLOCK
	HLRE	T2,DEVDMP##(F)	;GET -VE SIZE OF TRANSFER
	MOVM	T2,T2		;MAKE POSITIVE
IFN FTXMON,<
	CAILE	T2,200		;WILL IT FIT?
	STOPCD	.,STOP,UIO2BB,DIEUNI## ;++USER I/O TOO BIG FOR BUFFER
>
	MOVEM	T2,FOPLST	;SAVE SIZE OF TRANSFER
	HRRZ	T3,DEVDMP##(F)	;GET ADDRESS-1 OF I/O BUFFER
	AOJ	T3,		;ADJUST TO START OF BUFFER
IFN FTXMON,<
	HRL	T3,DEVISN##(F)	;GET THE SECTION NUMBER AS WELL
	XMOVEI	T4,FOPBUF	;AND OUR BUFFER
	TLNE	S,IO		;IF THIS IS FOR OUTPUT,
	EXTEND	T2,[XBLT]	;MOVE THE DATA NOW
>
IFE FTXMON,<MOVEM T3,FOPLST+1>	;JUST USE THE ADDRESS IF S0
	MOVEI	T1,DEVBLK##(F)	;ADDRESS OF BLOCK FOR I/O
	SKIPE	FILFLG		;USING SCRATCH FILE?
	MOVEI	T1,FOPBLK	;YES, BLOCK TO WRITE IS HERE
	MOVEM	T1,FOPIOB+2	;STUFF IN USETI/O WORD
	MOVE	T1,[3,,FOPIOB]	;UUO ARG BLOCK
	FILOP.	T1,		;DO THE I/O
	  JRST	USRDO1		;GO DEAL WITH ERROR (BITS IN T1)
IFN FTXMON,<
	TLNE	S,IO		;IF THIS WAS FOR OUTPUT,
	JRST	USRDO1		;WE ALREADY MOVED THE DATA
	EXCH	T3,T4		;MOVE IT THE OTHER WAY
	EXTEND	T2,[XBLT]	;FROM OUR BUFFER TO ONCMOD'S
> ;END IFN FTXMON
USRDO1:	HRR	S,T1		;SAVE BITS IN S
	TRZE	T1,IO.ERR	;CLEAR ERROR BITS AND SKIP IF NO ERRORS
	SETSTS	DSK,(T1)	;CLEAR ERRORS IN STATUS FOR FUTURE I/O
USRDOE:	MOVEM	S,DEVIOS(F)	;SAVE STATUS BITS
	POPJ	P,		;RETURN
OPNUNI:	PUSH	P,T1		;SAVE AN AC TO USE
	MOVE	T1,UDBNAM(U)	;UNIT NAME
	MOVEM	T1,FOPSIO+.FODEV ;SAVE FOR I/O
	MOVE	T1,[.FONBF+1,,FOPSIO] ;POINT TO ARG BLOCK
	FILOP.	T1,		;INIT FOR SUPER I/O
	  JRST	OPNUNN		;CAN'T DO I/O IF CAN'T OPEN
	MOVEM	U,CURUNI	;REMEMBER OPEN UNIT
	JRST	TPOPJ##		;RESTORE AC AND RETURN

OPNUNN:	SETZM	CURUNI		;DON'T REMEMBER UNIT NAME
	JRST	TPOPJ1##	;AND NOTE CAN'T WRITE

;SUBROUTINE TO OPEN SCRATCH FILE

OPNFIL:	HLLZS	FOPLEB+1	;CLEAR DATE/TIME
	SETZM	FOPLEB+2	;...
	SETZM	FOPLEB+3	;CLEAR DIRECTORY
	MOVE	T1,[.FOLEB+1,,FOPOPN] ;POINT TO ARG BLOCK
	FILOP.	T1,		;OPEN FOR I/O
	  JRST	OPNFLE		;CAN'T UPDATE?
	PUSH	P,U		;SAVE U
	SETZ	U,		;LOOK FOR END OF LIST
	PUSHJ	P,FNDUNI	;TO GET NUMBER OF UNITS IN OUR "SYS"
;*** NORMALLY WOULD BE A SKIP RETURN POSSIBLE, BUT CAN NEVER FIND UNIT 
;*** 0 BECAUSE 0 IS END OF LIST
	IMULI	T1,BLKPUN	;TIMES BLOCKS FOR EACH UNIT
	PUSH	P,T1		;SAVE NUMBER OF UNITS
	PUSHJ	P,OTSET##	;INITIALIZE OUTPUT BUFFER
	PUSHJ	P,INLMES##	;PRINT SOME IN-LINE TEXT
	ASCIZ	/[Creating scratch file TWICE.BIN]
/
	PUSHJ	P,OPOUT##	;LET THEM SEE THE MESSAGE
	POP	P,T1		;RESTORE NUMBER OF UNITS
	USETO	DSK,1(T1)	;ALLOCATE THAT MANY BLOCKS AND CLEAR
	HRRZS	FILFLG		;NOTE FILE READY TO WRITE
	JRST	UPOPJ##		;RESTORE U AND RETURN

OPNFLE:	HRRZ	T1,FOPLEB+1	;GET ERROR CODE
OPNFL4:	STOPCD	.,STOP,UIOCCS,DIECCS ;++CAN'T CREATE SCRATCH FILE
DIECCS:	PUSH	P,T1		;SAVE ERROR CODE
	PUSHJ	P,INLMES##	;PRINT SOME TEXT
	ASCIZ	/FILOP. error /
	POP	P,T1		;RESTORE ERROR
	PJRST	PRTDI8##	;PRINT IN OCTAL AND RETURN

;SUBROUTINE TO FIND POSITION OF UNIT IN LIST OF UNITS
;ARGS	U=ADDR OF UNIT DATA BLOCK
;VALUES	T1=POSITION OF UNIT IN LIST OF UNITS (0=1ST, ETC)
;NONSKIP IF UNIT NOT FOUND, T1=NUMBER OF UNITS
;SKIP	IF UNIT FOUND, T1 SET UP

FNDUNI:	SETZ	T1,		;CLEAR T1 IN CASE NO UNITS
	HLRZ	T2,SYSUNI##	;ADDR OF 1ST UNIT IN SYS
FNDUN1:	JUMPE	T2,CPOPJ##	;JUMP IF THAT WAS LAST UNIT
	CAMN	T2,U		;SKIP IF NOT DESIRED UNIT
	JRST	CPOPJ1##	;FOUND UNIT, GOOD RETURN
	HLRZ	T2,UNISYS(T2)	;MOVE TO NEXT UNIT IN SYS
	AOJA	T1,FNDUN1	;COUNT UNITS
CHKIO:	HLLZ	T2,RWTPTR	;-LENGTH OF TABLES
	HRR	T2,REDTAB	;ASSUME READING
	TLNE	S,IO		;OUTPUT?
	HRR	T2,WRTTAB	;YES
CHKIO1:	MOVE	T1,(T2)		;GET OUR NAME FOR THIS UNIT
	CAME	T1,UDBNAM(U)	;IS IT THE DRIVE'S NAME?
	CAMN	T1,UNIHID(U)	;OR THIS PACK'S NAME?
	TRNA			;YES--USE IT
	AOBJN	T2,CHKIO1	;NO--SEARCH THE TABLE
	JUMPL	T2,CPOPJ1##	;RETURN IF FOUND A MATCH
	MOVEI	T1,[ASCIZ /% /]
	PUSHJ	P,ICONM##	;START THE MESSAGE
	MOVE	T2,UDBNAM(U)	;GET DRIVE NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	MOVEI	T1,[ASCIZ / (/]
	PUSHJ	P,CONMES##	;PRINT SEPARATOR
	MOVE	T2,UNIHID(U)	;GET LOGICAL UNIT ID
	PUSHJ	P,PRNAME##	;PRINT IT
	MOVEI	T1,[ASCIZ /) is not a valid unit for /]
	PUSHJ	P,CONMES##	;PRINT TEXT
	MOVEI	T1,[ASCIZ /reading/]
	TLNE	S,IO		;OUTPUT?
	MOVEI	T1,[ASCIZ /writing/]
	PUSHJ	P,CONMES##	;APPEND OPERATION
	PJRST	CRLFOP##	;END LINE
SUBTTL	TWICE CHECK WRITE LOCK ROUTINE

UCKWLK::MOVE	T1,UDBNAM(U)	;NAME OF UNIT
	PUSHJ	P,GETDSK	;READ DISK CHARACTERISTICS
	  JRST	CHKCP2		;NO SUCH UNIT
	MOVE	T1,CHRBTS	;GET RETURNED BITS
	TLNE	T1,(DC.HWP)	;HARDWARE WRITE PROTECT?
	AOS	(P)		;YES
	POPJ	P,		;RETURN
SUBTTL	TWICE CHECK UNIT CAPACITY ROUTINE

UCKCPY::MOVE	T1,UDBNAM(U)	;NAME OF UNIT
	PUSHJ	P,GETDSK	;READ DISK CHARACTERISTICS
	  JRST	CHKCP2		;NO SUCH UNIT
	MOVE	T2,CHRBUF+.DCBUM ;BLOCKS/UNIT PLUS MAINTENANCE BLOCKS
	MOVE	T3,CHRBUF+.DCBUC ;BLOCKS/UNIT IN COMPATIBILITY MODE
	MOVE	T4,CHRUTY	;GET UNIT TYPE
	LDB	W,[POINTR (CHRBUF+.DCUCH,DC.UCT)] ;BLOCKS/TRACK
	HRLZS	W		;IN LEFT HALF
	HRR	W,CHRBUF+.DCUCH	;BLOCKS/CYLINDER
	MOVE	T1,CHRBTS	;GET RETURNED BITS
	TLNE	T1,(DC.OFL)	;SKIP UNLESS UNIT OFF LINE
	TLOA	T4,KOPUHE	;FLAG THAT ONCMOD EXPECTS
	AOS	(P)		;ON LINE, SKIP RETURN
	MOVE	T1,CHRBUF+.DCUSZ ;CAPACITY OF UNIT
	POPJ	P,		;RETURN
CHKCP2:	MOVSI	T4,KOPUHE	;SET FLAG FOR ONCMOD
	TLO	T4,KOPNSU	;NOTE ALSO NO SUCH UNIT
	POPJ	P,		;RETURN
SUBTTL	READ DISK CHARACTERISTICS


;READ DISK CHARACTERISTICS
;CALL:	MOVE	T1, UNIT NAME
;	PUSHJ	P,GETDSK
;	  <NON-SKIP>		;NO SUCH UNIT
;	<SKIP>			;DATA FETCHED, CHR??? UPDATED

GETDSK:	PUSH	P,T1		;SAVE ARGUMENT
	MOVE	T1,[CHRBUF,,CHRBUF+1] ;SET UP BLT
	SETZM	CHRBUF		;CLEAR FIRST WORD
	BLT	T1,CHRBUF+CHRLEN-1
	POP	P,CHRBUF	;STORE UNIT NAME
	MOVE	T1,[CHRLEN,,CHRBUF] ;SET UP UUO AC
	DSKCHR	T1,UU.PHY	;GET UNIT CHARACTERISTICS
	  POPJ	P,		;NO SUCH DEVICE
	MOVEM	T1,CHRBTS	;SAVE AC WORD
	PUSH	P,T2		;SAVE AN AC
	MOVE	T2,REDTAB	;UNITS TO READ
	JUMPE	T2,GETDS6	;SKIP IF NOT YET SETUP
	HLL	T2,RWTPTR	;AOBJN POINTER

GETDS1:	MOVE	T1,(T2)		;GET NEXT UNIT
	JUMPE	T1,GETDS2	;NOT THERE--MARK IT OFFLINE
	CAME	T1,CHRBUF+.DCUPN ;MATCH ITS PHYSICAL NAME?
	CAMN	T1,CHRBUF+.DCUID ;OR ITS REAL NAME?
	JRST	GETDS3		;YES--LEAVE IT ALONE FOR NOW
	AOBJN	T2,GETDS1	;LOOP OVER ALL OF REDTAB

GETDS2:	MOVSI	T1,(DC.OFL!DC.HWP!DC.AWL) ;OFFLINE AND WRITE-PROTECTED
	IORM	T1,CHRBTS	;FLAG UNAVAILABLE

GETDS3:	MOVE	T2,WRTTAB	;UNITS FOR OUTPUT
	HLL	T2,RWTPTR	;AOBJN POINTER

GETDS4:	MOVE	T1,(T2)		;GET NEXT UNIT
	JUMPE	T1,GETDS5	;NOT THERE--MARK IT WRITE-PROTECTED
	CAME	T1,CHRBUF+.DCUPN ;MATCH ITS PHYSICAL NAME?
	CAMN	T1,CHRBUF+.DCUID ;OR ITS REAL NAME?
	JRST	GETDS6		;YES--LEAVE IT ALONE FOR NOW
	AOBJN	T2,GETDS4	;LOOP OVER ALL OF WRTTAB

GETDS5:	MOVSI	T1,(DC.HWP!DC.AWL) ;WRITE-PROTECTED
	IORM	T1,CHRBTS	;FLAG NOT TO WRITE ON IT
	IORM	T1,UNIDES(U)	;I MEAN IT

GETDS6:	POP	P,T2		;RESTORE AC USED
	LDB	T1,[POINTR (CHRBTS,DC.CNT)] ;GET KONTROLLER TYPE
	MOVEM	T1,CHRKTY	;SAVE
	LDB	T1,[POINTR (CHRBTS,DC.UNT)] ;GET UNIT TYPE
	MOVEM	T1,CHRUTY	;SAVE UNIT TYPE
	LDB	T1,[POINTR (CHRBUF+.DCXCH,DC.XCU)] ;GET PHYSICAL UNIT NUMBER
	MOVEM	T1,CHRPUN	;SAVE
	JRST	CPOPJ1##	;RETURN
;CHECK TO SEE IF THE STRUCTURE ABOUT OT BE REFRESHED IS MOUNTED
;UNDER TIMESHARING
;CALL:	MOVE	T1, STRUCTURE NAME
;	PUSHJ	P,UCKREF
;	  <NON-SKIP>		;STR MOUNTED (DO NOT REFRESH)
;	<SKIP>			;OK TO REFRESH

UCKREF::PUSH	P,T2		;SAVE T2
	MOVE	T2,[1,,T1]	;SET UP UUO AC
	DSKCHR	T2,UU.PHY	;ASK MONITOR
	  JRST	UCKRF1		;NOT A DISK--OK
	LDB	T2,[POINTR (T2,DC.TYP)] ;GET ARGUMENT TYPE FIELD
	CAIE	T2,.DCTFS	;A FILE STRUCTURE?
UCKRF1:	AOS	-1(P)		;NO--OK TO REFRESH
	POP	P,T2		;RESTORE T2
	POPJ	P,		;RETURN
;HERE TO CHECK A DISK TO SEE IF WE CARE THAT IT'S MOUNTED

UCKSTR::PUSHJ	P,SAVT##	;PRESERVE ALL REGISTERS
	MOVSI	T1,UNPNNA	;OUR TIMESHARED BIT
	SKIPN	FILFLG		;DON'T WORRY IF SCRATCH FILE
	TDNN	T1,UNIDES(U)	;IS THIS UNIT IN A MOUNTED STRUCTURE?
	JRST	CPOPJ1##	;NO--GIVE GOODNESS RETURN
	MOVE	T1,UDBNAM(U)	;YES--GET ITS NAME
	PUSHJ	P,GETDSK	;DO A DSKCHR AGAIN
	  JRST	CPOPJ1##	;SHOULD NEVER HAPPEN
	SKIPN	T1,CHRBUF+.DCSNM ;GET STRUCTURE NAME
	JRST	UCKST1		;IT GOT DISMOUNTED SINCE WE LAST LOOKED
	MOVEI	T2,[ASCIZ /is mounted to this system./]
	PUSHJ	P,SWARN##	;GIVE A WARNING
	MOVEI	T1,[ASCIZ /Proceed anyway/]
	MOVSI	T2,'NO '	;DEFAULT IS TO ABORT
	PUSHJ	P,PRSYNQ##	;GET A YES/NO ANSWER
	JUMPN	T1,CPOPJ1##	;THE FOOL IS BRAVE
	POPJ	P,		;GIVE THE ABORT RETURN

UCKST1:	MOVSI	T1,UNPNNA	;GET OUR TIMESHARED BIT AGAIN
	ANDCAM	T1,UNIDES(U)	;IT'S CLEAN NOW
	JRST	CPOPJ1##	;GIVE THE PROCEED RETURN
SUBTTL	ASK FOR READ AND WRITE UNITS


ASKRWT:	SETZM	RWTALL		;CLEAR "ALL" FLAG
	MOVEI	T2,CHKRWT	;ROUTINE TO VALIDATE RESPONSE
	HLL	T3,RWTPTR	;MAKE IT AN AOBJN POINTER
	PUSHJ	P,PRSLST##	;GET LIST OF WRITE UNITS
	SKIPN	RWTALL		;WAS "ALL" TYPED?
	POPJ	P,		;NO--DONE
	HLL	T3,RWTPTR	;RESET AOBJN POINTER
	HLRZ	U,SYSUNI##	;GET FIRST UNIT DATA BLOCK IN SYSTEM

ASKRW1:	MOVE	T1,UDBNAM(U)	;GET A DRIVE NAME
	MOVEM	T1,(T3)		;STORE RESULTS
	PUSHJ	P,CHKRW3	;FIX THE BITS
	  JFCL			;IGNORE ERRORS
	AOBJP	T3,CPOPJ##	;END OF TABLE?
	HLRZ	U,UNISYS(U)	;LINK TO NEXT UNIT
	JUMPN	U,ASKRW1	;LOOP BACK FOR MORE
	SETZM	(T3)		;CLEAR TABLE ENTRY
	AOBJN	T3,.-1		;DO REMAINDER OF TABLE
	POPJ	P,		;RETURN


;CHECK A SPECIFIED UNIT FOR VALIDITY
CHKRWT:	CAMN	T1,['ALL   ']	;WAS ALL SPECIFIED?
	JRST	CHKRW2		;YES--SPECIAL CASE
	HLRZ	U,SYSUNI##	;GET FIRST UNIT DATA BLOCK IN SYSTEM

CHKRW1:	CAME	T1,UNIHID(U)	;MATCH ON UNIT ID
	CAMN	T1,UDBNAM(U)	;OR DRIVE NAME
	JRST	CHKRW3		;SPECIFIED UNIT IS VALID
	HLRZ	U,UNISYS(U)	;LINK TO NEXT UNIT
	JUMPN	U,CHKRW1	;LOOP BACK AND TRY AGAIN
	PUSH	P,T1		;SAVE UNIT NAME
	MOVEI	T1,[ASCIZ /% Can't find unit /]
	PUSHJ	P,ICONM##	;START THE MESSAGE
	POP	P,T2		;RESTORE NAME
	PUSHJ	P,PRNAME##	;TYPE IT
	PJRST	CRLFOP##	;END LINE AND RETURN FAILURE

CHKRW2:	SETOM	RWTALL		;FLAG "ALL" SPECIFIED
	MOVEI	T1,[ASCIZ //]	;NULL TEXT
	PUSHJ	P,CONOUT##	;GIVE THE USER HIS SEPARATION
	JRST	CPOPJ2##	;AND GIVE 'DONE' RETURN

CHKRW3:	MOVSI	T2,UNPOFL	;ASSUME THIS IS FOR INPUT
	TLNN	S,IO		;GOOD ASSUMPTION?
	ANDCAM	T2,UNIDES(U)	;YES--FIX THE UNIT
	TDNE	T2,UNIDES(U)	;CHECK AGAIN FOR OUTPUT
	JRST	CHKRW4		;NO--SAY WHAT'S WRONG
	MOVSI	T2,UNPHWP!UNPAWL ;OUTPUT BITS
	TLNE	S,IO		;DO WE CARE YET?
	ANDCAM	T2,UNIDES(U)	;YES--FIX THE UNIT
	JRST	CPOPJ1##	;RETURN VALIDITY

CHKRW4:	PUSH	P,T1		;SAVE THE NAME
	MOVEI	T1,[ASCIZ /% Can't access unit /]
	PUSHJ	P,ICONM##	;START THE MESSAGE
	POP	P,T2		;RESTORE NAME
	PUSHJ	P,PRNAME##	;TYPE IT
	PJRST	CRLFOP##	;END LINE & RETURN FAILURE


;ALLOCATE READ/WRITE TABLES
GETRWT:	SKIPE	T1,RWTLEN	;ALREADY HAVE TABLES?
	POPJ	P,		;YES
	MOVEI	U,SYSUNI##-UNISYS ;SET PREDESSOR
	MOVSI	T2,UNPOFL!UNPHWP!UNPAWL ;OFFLINE + WRITE-PROTECTED (TWICE)

GETRW1:	HLRZ	U,UNISYS(U)	;GET A UNIT
	JUMPE	U,GETRW2	;END OF CHAIN
	IORM	T2,UNIDES(U)	;MARK THE UNIT
	AOJA	T1,GETRW1	;COUNT THEM UP

GETRW2:	MOVEM	T1,RWTLEN	;SAVE AS READ/WRITE TABLE LENGTH
	MOVN	T2,T1		;NEGATE
	HRLZM	T2,RWTPTR	;SAVE AS AOBJN POINTER
	PUSHJ	P,INICOR##	;ALLOCATE CORE
	MOVEM	T2,REDTAB	;SAVE READ TABLE ADDRESS
	PUSHJ	P,INICOR##	;ALLOCATE CORE
	MOVEM	T2,WRTTAB	;SAVE WRITE TABLE ADDRESS
	POPJ	P,		;RETURN
SUBTTL DEVICE SEARCHING

;WHEN WISHING TO CHECK FOR CONFLICT WITH A PHYSICAL DEVICE WHILE DEFINING
; A STRUCTURE, WE COME HERE TO SEE HOW TO HANDLE IT IN USER MODE
;CALL:	SKIPE	.UONCE		;IF USER MODE,
;	PUSHJ	P,DEVPHU	;ASK USRONC
;	 PUSHJ	P,DEVPHY	;ELSE SEARCH THE DEVICE CHAIN
;	  JRST FOO		;NOT FOUND
;	JRST	BAR		;FOUND A MATCH

DEVPHU::MOVE	T2,T1		;COPY THE NAME IN QUESTION
	SETZ	F,		;NO DDB YET
	GETCHR	T2,UU.PHY	;(DEVCHR THAT DOESN'T CONFLICT WITH DDB WORDS)
	JUMPE	T2,CPOPJ1##	;GIVE NON-SKIP FROM DEVPHY
	TLNN	T2,(DV.TTY)	;IF A TTY,
	TLNN	T2,(DV.DSK)	;IT ISN'T REALLY A DISK
	JRST	CPOPJ2##	;RETURN 'FOUND'
	MOVE	T2,[1,,T1]	;IT'S A DISK, SET TO SEE WHAT KIND
	DSKCHR	T2,UU.PHY	;ASK THE MONITOR
	  JRST	CPOPJ1##	;NOT A REAL ONE
	LDB	T2,[POINTR (T2,DC.TYP)] ;GET ARGUMENT TYPE FIELD
	CAIN	T2,.DCTAB	;IF STRUCTURE ABBREVIATION,
	JRST	CPOPJ1##	;THEN LET IT PASS
	CAIE	T2,.DCTDS	;IF GENERIC DSK,
	CAIN	T2,.DCTFS	;OR AN EXISTING STRUCTURE,
	MOVEI	F,DSKDDB##	;FAKE IT UP FOR ONCMOD TO KNOW
	JRST	CPOPJ2##	;GIVE 'FOUND' RETURN
SUBTTL DISK OFF LINE INTERCEPTION

;WHEN A FILE STRUCTURE IS REMOVED VIA STRUUO, AND THE OPERATOR
; REMOVES THE PACK(S), THE RP10 HARDWARE DOES NOT INTERRUPT
; AS THE UNIT GOES OFF LINE, NOR IS THERE ANY WAY TO PASSIVELY CHECK
; TO SEE IF THE UNIT IS OFF LINE.  THEREFORE, TWICE MUST INTERCEPT
; THE DISK OFF LINE MESSAGE.
;

DOLBLK:	4,,DOLINT		;INTERRUPT TO DOLINT
DOLCLS:	.ERMSG,,ER.EIJ!ER.OFL!ER.IDV ;INHIBIT MESSAGE, TRAP ON DISK OFF LINE
DOLPC:	0			;STARTS OUT ZERO
DOLCL:	0			;EXTRA STUFF
DOLSAV:	BLOCK	1

DOLINT:	MOVEM	T1,DOLSAV	;SAVE T1
	HLRZ	T1,DOLCL	;GET THE CLASS FLAGS IN T2
	CAIN	T1,ER.EIJ	;FATAL ERROR IN JOB (PROBABLY HALT INSTR)?
	JRST	DOLINJ		;YEP
	CAIE	T1,ER.IDV	;IS THERE A PROBLEM ON DEVICE?
	JRST	DOLIN1		;NOPE MUST BE AN UNEXPECTED DISK OFF-LINE
	MOVSI	T1,UNPOFL	;THIS UNIT MUST BE DOWN, GET BIT
	IORM	T1,UNIDES(U)	;MARK IT IN UNIDES
	PUSH	P,DOLPC		;SAVE THE RETURN PC
	SETZM	DOLPC		;CLEAR SO WE CAN INTERRUPT AGAIN
	GETSTS	DSK,T1		;GET CURRENT I/O STATUS
	TRO	T1,IO.IMP	;GIVE AN ERROR TO THE FILOP.
	JRST	CPOPJ1##	;AT ITS ERROR RETURN
DOLIN1:	SETZ	T1,		;CLEAR DOLPC SO WE CAN INTERRUPT AGAIN
	EXCH	T1,DOLPC	;
	EXCH	T1,DOLSAV	;GET PC INTO DOLSAV, RESTORE T1
	OUTSTR	[ASCIZ/% Unexpected disk off line condition
/]
	AOS	DOLSAV		;SKIP OFFENDING UUO
	JRST	@DOLSAV		;RETURN

DOLINJ:	OUTSTR	[ASCIZ /% Fatal error in job at PC /]
	HRRZ	T1,DOLPC	;GET PC
	PUSHJ	P,PRTDI8##	;PRINT IT
	PUSHJ	P,CRLFOP##	;OUTPUT CRLF
	JRST	.EXIT		;QUIT
	SUBTTL	DATA STORAGE

NOTPRV:	BLOCK	1		;NON-ZERO IF NON-PRIVILEGED USER
FILFLG:	BLOCK	1		;NON-ZERO IF USING SCRATCH FILE
FOPOPN:	DSK,,.FOSAU		;SINGLE ACCESS UPDATE
	.IODMP			;IN DUMP MODE
	SIXBIT	/DSK/		;DEVICE NAME
	EXP	0,0		;NO BUFFERS
	EXP	.+1		;ADDRESS OF LOOKUP/ENTER BLOCK
FOPLEB:	SIXBIT	/TWICE/		;FILE NAME
	SIXBIT	/BIN/		;EXTENSION
	EXP	0,0		;PRIVS/DATE/ETC. DEFAULTED
FOPSIO:	DSK,,.FOSIO		;BLOCK TO OPEN CHANNEL FOR SUPER-I/O
	.IODMP			;IN DUMP MODE
	BLOCK	1		;DEVICE NAME GOES HERE
	EXP	0,0		;NO BUFFERS
FOPIOB:	DSK,,.FOFXI		;BLOCK FOR DOING I/O
	FOPLST			;POINTER TO CHANNEL COMMAND LIST
	BLOCK	1		;RESERVED FOR ADDRESS OF BLOCK NUMBER FOR I/O
FOPLST:	BLOCK	1		;SIZE OF TRANSFER
IFE FTXMON,<BLOCK 1>		;ADDRESS OF BUFFER
IFN FTXMON,<FOPBUF>		;LOCAL BUFFER TO BYPASS A BUG
	EXP	0,0		;TERMINATOR
IFN FTXMON,<
FOPBUF:	BLOCK	200		;A LOCAL BUFFER FOR I/O
>
FOPBLK:	BLOCK	1		;BLOCK NUMBER FOR I/O IF SCRATCH FILE IN USE

CURUNI:	BLOCK	1		;CURRENT UNIT OPENED FOR TWICE
CHRKTY:	BLOCK	1		;KONTROLLER TYPE
CHRUTY:	BLOCK	1		;UNIT TYPE
CHRPUN:	BLOCK	1		;PHYSICAL UNIT NUMBER
RWTPTR:	BLOCK	1		;AOBJN POINTER
RWTLEN:	BLOCK	1		;READ/WRITE TABLE LENGTH
RWTALL:	BLOCK	1		;NON-ZERO IF "ALL" SPECIFIED
REDTAB:	BLOCK	1		;READ TABLE ADDRESS
WRTTAB:	BLOCK	1		;WRITE TABLE ADDRESS
CHRBTS:	BLOCK	1		;DSKCHR UUO BITS
CHRLEN==.DCXCH+1		;DSKCHR OFFSETS TO EXTENDED UNIT CHARACTERISTICS
CHRBUF:	BLOCK	CHRLEN		;DSKCHR UUO BLOCK

	PRGEND
TITLE	MONEND - PSECT END LOCATIONS
SUBTTL	PSECT END LOCATIONS

	SEARCH	F,S
	$RELOC
	$HIGH			;INTO HIGH SEGMENT
	ENTRY	MONEND		;FORCE LOAD IF LIBRARY SEARCH
	ZZ==.-1			;LAST ADDRESS USED IN HIGH SEGMENT
	$INIT			;INTO INIT CODE PSECT
MONEND::EXP	ZZ		;STORE FOR SYSINI

	$CSUB			;INTO COMMON SUBROUTINES PSECT
	ZZ==.-1			;LAST ADDRESS USED IN GLOBAL SUBROUTINES PSECT
	$INIT			;INTO INIT CODE PSECT
CSBEND::EXP	ZZ		;STORE FOR SYSINI
IFN FTXMON,<
	$XHIGH			;INTO EXTENDED HIGH SEGMENT
	ZZ==.-1			;LAST ADDRESS USED IN EXTENDED HIGH SEGMENT
	$INIT			;INTO INIT CODE PSECT
XHIEND::EXP	ZZ		;STORE FOR SYSINI
>; END IFN FTXMON

	$LOW			;INTO LOW SEGMENT
	END