   $€ðskQ	› c,        	.TITLE	TTDRV
	.IDENT	/32.00/
	
;
;
;		COPYRIGHT (c) 1981 BY
;	DIGITAL EQUIPMENT CORPORATION, MAYNARD
;	 MASSACHUSETTS.  ALL RIGHTS RESERVED.
;
; COPYRIGHT (c) 1973
;
; 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 TRANSFERED.
;
; THE INFORMATION  IN THIS DOCUMENT 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 THAT IS NOT SUPPLIED BY DIGITAL.
;
;
; VERSION 32.00
;
; D. N. CUTLER 24-OCT-73
;
; PRE-VERSION 18 MODIFICATIONS BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	R. LARY
;	E. L. BAATZ
;	C. SPITZ
;      
; MODIFIED BY:
;
;	M. S. HARVEY	12-JUL-79
;	MSH041 -- CHANGE TS.CKR REFERENCE TO T.CKR
;		** RETRACTED - 4/6/81 **
;
;	ERIC BAATZ 21-JUL-79
;	EB228 -- REDISPATCH CPU AFTER SINGLE-USER MCR OPEN
;
;	ERIC BAATZ 10-NOV-79
;	EB251 -- CLEAR U.ATT IF BAD IO.ATA
;
;	ERIC BAATZ 6-JAN-80
;	EB252 -- DO NOT USE CURBF FOR DZTIM
;
;	ERIC BAATZ 26-MAY-80
;	EB266 -- HIGHLIGHT HOW TO CONTROL THE LENGTH OF THE
;		 INTERVAL DURING WHICH LOSS OF CARRIER ON
;		 REMOTE DH11 LINES IS NOT CONSIDERED A REASON
;      		 TO HANG UP
;
;	ERIC BAATZ 26-MAY-80
;	EB267 -- OPTIONALLY DO NOT SET TERMINAL CHARACTERISTICS
;		 TO A KNOWN STATE WHEN ANSWERING A REMOTE LINE
;
;	ERIC BAATZ 26-MAY-80
;	EB268 -- OPTIONALLY ALLOW LINE FEEDS TO BE TREATED "LIKE FORM
;		 FEEDS"
;
;	ERIC BAATZ 26-MAY-80
;	EB269 -- OPTIONALLY ALLOW A HARDWARE IMPLEMENTATION OF
;		 XON/XOFF
;
;	T. M. MARTIN 9-SEP-80
;	TMM008 -- PREVENT DOUBLE LOCK ON US.ECH IN ACCEPTANCE ROUTINE
;		  OF IO.WBT, WHICH CAN RESULT IN DOUBLE FORKS AFTER
;		  US.      ECH IS CLEARED
;
;	T.M. MARTIN 9-SEP-80
;	TMM009 -- DO NOT CHECK US.OUT WHEN BREAKING-THRU A BUSY UNIT
;
;	T. M. MARTIN 
;	TMM010 -- CLEAR I.PRM+16 ( RMS LOCKING WORD ) BEFORE CALLING $IODON
;
;	T. M. MARTIN 31-OCT-80
;	TMM011 -- IMPLEMENT MULTIPLE BUFFERED I/O SUPPORT
;
;	T. M. MARTIN 15-NOV-80
;	TMM012 -- ALLOW VT100 ANSI ESCAPE SEQUENCES TO BE RECOGNIZED
;
;	T. M. MARTIN 20-DEC-80
;	TMM013 -- DZ MODEM SUPPORT, DO NOT CHECK FOR CARRIER IMMEDIATELY
;		  AFTER SETTING DTR
;
;	T. M. MARTIN       7-MAR-81
;	TMM032 -- ADD ALTERNATE CLI SUPPORT
;
;	T. M. MARTIN 20-APR-81
;	TMM035 -- RESTRUCTURE U.CW3 FOR SETTABLE REMOTE BAUD RATE
;		  AND FREE UP A FEW BITS IN THE HDX-TTDRV UCB
;
;	T. M. MARTIN 27-APR-81
;	TMM036 -- ADD ASR33 TERMINAL TYPE (UPCASE OUTPUT)
;
;
; TERMINAL DRIVER FOR DL11-A LINE INTERFACE AND DH11/DJ11/DZ11
;	LINE MULTIPLEXERS
;
;-
; MACROS TO CONSOLIDATE LOADABLE DRIVER CONDITIONAL ASSEMBLY
;
; IF NECESSARY, SAVE THE PS WORD FROM THE INTERRUPT (IT
; CONTAINS THE UNIT N      UMBER OF THE INTERRUPTER), SAVE R4 AND R5,
; AND LOWER OUR PRIORITY.  IF THE DRIVER IS LOADABLE AND MAPPED, ALL
; OF THAT IS DONE BY ANOTHER PART OF THE EXEC (THE INTERRUPT CONTROL
; BLOCK) SO IT DOES NOT HAVE TO BE DONE HERE
;	TYPE = DL, DH, DJ, OR DZ
;	PRI = PRIORITY TO CALL $INTSV WITH
;	NCTRLR = NUMBER OF CONTROLLERS
;
	.MACRO	TTSAV$	TYPE,PRI,NCTRLR

	.IF NDF	L$$DRV!M$$MGE!LD$TT

	.IF GT	NCTRLR-1

	MFPS	TYPE'TMP

	.ENDC

	CALL	$INTSV,PRI

	.ENDC

	JSR	R3,TYPE'SAV

	.ENDM
;
; GE      NERATE COMMON CODE FOR THE SAVE ROUTINES OF THE VARIOUS
; DEVICES THIS DRIVER SUPPORTS.  IF THIS DRIVER IS LOADABLE,
; SOME OF THE CODE IS DONE BY ANOTHER PART OF THE EXEC (THE
; INTERRUPT CONTROL BLOCK) SO IT DOES NOT HAVE TO BE DONE HERE.
;	TYPE = DL, DH, DJ, DZ
;	NCTRLR = NUMBER OF CONTROLLERS
;	MUX = NONNULL IF TO GENERATE FOR A MULTIPLEXER
;
	.MACRO	TTSET$	TYPE,NCTRLR,MUX
	MOV	R3,-(SP)

	.IF GT	NCTRLR-1

	.IF NDF	L$$DRV!M$$MGE!LD$TT

	MOV	TYPE'TMP,R4
	BIC	#177760,R4
	ASL	R4

	.ENDC
      
	.IF NB	MUX

	MOV	TYPE'TBL(R4),R3
	MOV	TYPE'CSR(R4),R4

	.IFF

	MOV	CNTBL(R4),R5

	.ENDC

	.IFF

	.IF NB	MUX

	MOV	TYPE'TBL,R3
	MOV	TYPE'CSR,R4

	.IFF

	MOV	CNTBL,R5

	.ENDC

	.ENDC

	.ENDM

;
; DEFINE THE MACRO USED TO GENERATE THE SET SPEED TABLE FOR SF.SMC
;
;	SYMBOL = A BAUD RATE SYMBOL FROM TTSYM$ (OF THE FORM S.X)
;	DH = THE FOUR BIT PATTERN THAT MUST BE ASSERTED IN THE
;	     DH11 LINE PARAMETER CSR TO GET THE BAUD RATE REPRESENTED
;	     BY SYMBOL.  A VALUE OF ZER      O INDICATES THAT A SPEED IS
;	     NOT SUPPORTED BY THE DH11.
;	DZ = THE FOUR BIT PATTERN THAT MUST BE ASSERTED IN THE
;	     DZ11 LINE PARAMETER CSR TO GET THE BAUD RATE REPRESENTED
;	     BY SYMBOL.  A VALUE OF ZERO INDICATES THAT A SPEED IS
;	     NOT SUPPORTED BY THE DZ11.
;

	.MACRO	SPDTAB	SYMBOL,DH,DZ
	.BYTE	DH*20+DZ
	.BYTE	SYMBOL
	.ENDM

;
; MACRO LIBRARY CALLS
;

	.MCALL	PCBDF$,TTSYM$,UCBDF$						;TMM008
	UCBDF$	,,TTDEF								;TMM008
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFS      ETS		;**-1
	TTSYM$			;DEFINE "TF.", "F1.", "F2.", "T.",
				; AND "TC." SYMBOLS

	.IF DF	D$$M11

	.GLOBL	U.DMCS		;REFERENCE SO SYMBOL WILL BE IN
				; TTDRV.STB FOR LOA.TSK

	.ENDC

;
; THE SUBFUNCTION BIT IO.UMD (VALUE OF 4) SHOULD NEVER BE USED
; TO INDICATE A TERMINAL SUBFUNCTION, BECAUSE IT FLAGS THE FUNCTION
; AS A USER MODE DIAGNOSTIC.  FUNCTION CODE 10 (10*400 IF YOU PREFER)
; IS RESERVED FOR DIAGNOSTICS.
;

M$$CRI=80.		;NUMBER OF BYTES OF INFORMATION IN A MCR BUFFER

;
; EQUATED       SYMBOLS
;
; FOR CONVENIENCE DEFINE AN INTERNAL CONDITIONAL ASSEMBLY SYMBOL
;

	.IF DF	T$$UTB
	.IF NDF	C$$CKP!T$$BUF
NOEXBF=0		;DEFINED IF TASK'S BUFFER TO BE USED FOR
			; CHARACTER BUFFERING AND SYSTEM CANNOT
			; CHECKPOINT
	.ENDC
	.ENDC
										;TMM011
	.IF DF	C$$CKP&T$$BUF							;TMM011
										;TMM011
DFCKP=0				;DEFINED  FOR BUFFERED INPUT			;TMM011
										;TMM011
	.ENDC									;TMM011
										;TMM011

	.IF DF	T$$RNE!T$$RPR!T$$RST!T$$TRW

SS.RAL=200		;SET IN S.STS IF R      EAD ALL MODE
SS.WAL=100		;SET IN S.STS IF WRITE ALL MODE
SS.RNE=40		;SET IN S.STS IF READ WITH NO ECHO
SS.RST=20		;SET IN S.STS IF READ WITH SPECIAL TERMINATORS

	.ENDC

;
; IN PRE-V3.2 VERSIONS OF THIS TERMINAL DRIVER, "ESC P IC FC"
; WAS AN ESCAPE SEQUENCE (SEE COMMENTS IN FRONT OF THE LABEL
; 200$ THAT PRECEDES THE LABEL TTCAN), BECAUSE THE VT61 COULD
; EMIT A SUBSTANTIAL NUMBER OF SUCH ESCAPE SEQUENCES.  BECAUSE
; OF THE INCREASING NUMBER OF TERMINALS THAT THINK "ESC P" IS
; A COMPLETE ESCA      PE SEQUENCE (VT52, VT100 (THE PF1 KEY), ETC.),
; THE TERMINAL DRIVER HAS BEEN MODIFIED TO RECOGNIZE "ESC P"
; AS AN ESCAPE SEQUENCE.  THE DRIVER CAN BE MODIFIED TO
; RECOGNIZE "ESC P IC FC" RATHER THAN "ESC P" AS AN ESCAPE
; SEQUENCE BY REMOVING THE SEMICOLON THAT PRECEDES THE
; FOLLOWING DEFINITION.
;

;ESCPIC=0
										; EB266
;										; EB266
; THE LENGTH OF THE INTERVAL DURING WHICH LOSS OF CARRIER ON			; EB266
; A REMOTE DH11 LINE DOES NOT CAUSE A HANG UP IS FROM A				; EB266
; MINIMUM       OF (N-1)*4 SECONDS TO N*4 SECONDS, WHERE N IS				; EB266
; DEFINED BY THE VALUE OF DMGLTC, WHICH STANDS FOR "DM11			; EB266
; GLITCH VALUE".								; EB266
;										; EB266
										; EB266
DMGLTC=2									; EB266
										; EB268
;										; EB268
; SOME FILE FORMATS AND APPLICATION SYSTEMS USE LINE FEEDS			; EB268
; RATHER THAN LINE FEEDS/CARRIAGE RETURN PAIRS AS RECORD			; EB268
; TERMINATORS.  UNDER THOSE CIRCUMSTANCES, THE TERMINAL				; EB268
; DRIVER WILL DO AUTOMATIC LINE WRAPAROUND      , BECAUSE IT DOES			; EB268
; NOT SEE A CARRIAGE RETURN FOR LONG STRETCHES OF TIME.				; EB268
;										; EB268
; REMOVING THE SEMICOLON IN FRONT OF THE NEXT SYMBOL DEFINITION			; EB268
; CAUSES LINE FEEDS TO BE TREATED LIKE FORM FEEDS (THEY ARE			; EB268
; PASSED TO THE TERMINAL AND RESET THE CURRENT HORIZONTAL			; EB268
; POSITION TO THE LEFT MARGIN) FOR DEVICES THAT CAN HANDLE			; EB268
; HARDWARE FORM FEEDS.								; EB268
;										; EB268
										; EB268
;.IIF DF T$$HFF,	PASSLF=0						;       EB268
										; EB269
;										; EB269
; REMOVING THE SEMICOLON IN FRONT OF THE NEXT SYMBOL DEFINITION			; EB269
; CAUSES THE TERMINAL DRIVER TO HANDLE THE LOSS OF A MODEM			; EB269
; SIGNAL FOR A TERMINAL THAT KNOWS HOW TO HANDLE HARDWARE			; EB269
; FORM FEEDS AND IS CONNECTED BY A REMOTE DH11 LINE (A				; EB269
; DM11-BB) AS IF AN XOFF HAD BEEN RECEIVED.  THE ASSERTION			; EB269
; OF THE SIGNAL IS HANDLED AS IF AN XON HAD BEEN RECEIVED.			; EB269
;										; EB269
; THE SECONDARY RECEIVE       SIGNAL IS USED AS AN EXAMPLE				; EB269
;										; EB269
										; EB269
;.IIF DF T$$HLD!T$$SYN,	XONSIG=0						; EB269
.IIF DF XONSIG, XONBIT=10000	;SECONDARY RECEIVE IN 1ST CSR			; EB269
.IIF DF XONSIG, XONBI2=20	;SECONDARY RECEIVE IN 2ND CSR			; EB269
										; EB267
;										; EB267
; THE NORMAL BEHAVIOR OF THE TERMINAL DRIVER IS TO SET A REMOTE			; EB267
; LINE TO A KNOWN SET OF TERMINAL CHARACTERISTICS BEFORE			; EB267
; ANSWERING THE LINE.  THIS IS TO AVOID CONFUSION (FOR EXAMPLE,			      ; EB267
; HAVING THE LINE SET TO HOLD SCREEN MODE) AND MISCHIEF (A			; EB267
; TERMINAL CAN BE DISABLED BY SETTING ITS BUFFER SIZE TO TWO			; EB267
; AND THEN HANGING UP).								; EB267
;										; EB267
; REMOVING THE SEMICOLON IN FRONT OF THE NEXT SYMBOL DEFINITION			; EB267
; CAUSES THE TERMINAL DRIVER NOT TO CHANGE THE CHARACTERISTICS			; EB267
; OF A TERMINAL (TO USE THOSE FROM THE LAST MCR SET COMMANDS)			; EB267
; BEFORE ANSWERING A REMOTE DH11 LINE.						; EB267
;										; EB267
						      				; EB267
;USECDH=0									; EB267
										; EB267
;										; EB267
; REMOVING THE SEMICOLON IN FRONT OF THE NEXT SYMBOL DEFINITION			; EB267
; CAUSES THE TERMINAL DRIVER NOT TO CHANGE THE CHARACTERISTICS			; EB267
; OF A TERMINAL (TO USE THOSE FROM THE LAST MCR SET COMMANDS)			; EB267
; BEFORE ANSWERING A REMOTE DZ11 LINE.						; EB267
;										; EB267
										; EB267
;USECDZ=0									; EB267
;										;TMM035
;										;TMM035
; HALF DUPLEX TERMINAL DRIVER SPECIFIC U.CW3 DEFINIT      IONS			;TMM035
;										;TMM035
;	   +-------------------------------------+				;TMM035
;U.CW3	   |15|14|13|12|11 10 9 8|7 6 5 4|3 2 1 0|				;TMM035
;	   +-------------------------------------+				;TMM035
;            | 	|  |  |     |        |       |					;TMM035
;	  odd   |  |  |     |        |       |					;TMM035
;       parity  |  |  |     |        |       |					;TMM035
;(DH's & DZ's)  |  |  |     |        |       |					;TMM035
;		|  |  |     |        |       |					;TMM035
;	   enable  |  |           |        |       |					;TMM035
;	   parity  |  |     |        |       |					;TMM035
;    (DH's & DZ's) |  |     |        |       |					;TMM035
;		   |  |     |        |       |					;TMM035
;	       U3.UPC |     |        |       |					;TMM035
;	Upcase Output |     |        |       |					;TMM035
;	              |     |        |       |					;TMM035
;		undefined   |        |       |					;TMM035
;			    |        |       |					;TMM035
;			  Remote     |       |					;TMM035
;			  Answer     |       |	      				;TMM035
;			  Speed      |       |					;TMM035
;				     |       |					;TMM035
;				  Transmit   |					;TMM035
;				   Speed     |					;TMM035
;					     |					;TMM035
;					  Receive				;TMM035
;					   Speed				;TMM035
;										;TMM035
;										;TMM035
										;**-28
;
; TERMINAL CONTROL BLOCK OFFSET DEFINITIONS
;

STATS=0				;TERMINAL STATUS WORD
STRBF=2				;CURRENT BUFFER ADDRESS (INPUT)
RMBYT=4				;REMAINING BYTES IN BUFFER (INPUT)
FNBYT=5				;FINAL (TERMINATING) BYTE OF A R      EAD
CURBF=6				;STARTING BUFFER ADDRESS (INPUT)
HORPS=10			;HORIZONTAL POSITION OF CARRIAGE		;**-1
FLBYT=11			;FILL BYTE
DFUIC=12			;DEFAULT UIC OF TERMINAL
MEBUF=14			;MULTI-ECHO BUFFER ADDRESS
MBUFR=16			;DYNAMIC MULTI-ECHO BUFFER
INPRQ=20			;IF NONZERO, UNSOLICITED INPUT REQUEST
MBUF0=21			;ZERO BYTE TERMINATING M-E BUFFER
DHBUF=22			;DH11 OUTPUT BUFFER
IHORP=23			;INITIAL HORIZONTAL POSITION (T$$RUB)
DZTIM=IHORP			;TIME OUT COUNT FOR DZ11 REMOTE LINES		; EB252
NEXTB=IHORP+1

	.IIF DF	T$$AC      R!T$$BTW!T$$CCA!T$$CCO!T$$ESC!T$$HLD,	T1=0
	.IF DF	T1!T$$RPR!T$$SYN!T$$TRW!T$$UTB!T$$30P!DFCKP			;TMM011
ATERS=NEXTB			;ADDITIONAL TERMINAL STATUS			;**-1
NEXTB=NEXTB+2
	.ENDC
	.IF DF	T$$CCA&A$$TRP
CCAST=NEXTB			;STARTING ADDRESS OF CONTROL C AST
NEXTB=NEXTB+2
	.ENDC
	.IF DF	T$$ESC
SYNTX=NEXTB			;ADDRESS OF CURRENT SYNTAX RULE FOR
NEXTB=NEXTB+2			; ESCAPE SEQUENCES
	.ENDC
	.IF DF	D$$M11
DMTIM=NEXTB			;TIME OUT COUNT ON REMOTE LINES
NEXTB=NEXTB+1
UDMVC=NEXTB			;VECTOR ADDR OF DM11 (USED BY LO      A.TSK)
NEXTB=NEXTB+1
DMCSR=NEXTB			;CSR OF DM11 FOR THIS UNIT
; U.DMCS=DMCSR			;DEFINED BY SGN.  USED BY LOA.TSK
NEXTB=NEXTB+2
	.ENDC

;
; TERMINAL STATUS WORD BIT DEFINITIONS
;

MODE=100000			;MODE OF BUSY TERMINAL (0=INPUT 1=OUTPUT)
LFCT=74000			;UNPROCESSED LINE FEED COUNT FIELD
LFBT=4000			;UNPROCESSED LINE FEED ADD/SUB BIT
CRTY=2000			;CARRIAGE CONTROL AT END OF LINE (1=YES)
CRJT=1000			;CARRIAGE RETURN JUST TYPED (1=YES)
EOLS=400			;END OF LINE SEEN (1=YES)
UIFP=200			;UNSOLICITED INP      UT FORK PENDING (1=YES)
SOLI=100			;SOLICITED INPUT (1=YES)
CTLO=40				;OUTPUT DISABLED (1=YES)
RUBP=20				;RUBOUT SEQUENCE IN PROGRESS (1=YES)
FLCT=17				;UNPROCESSED FILL COUNT FIELD
FLBT=1				;UNPROCESSED FILL COUNT BIT

;
; ADDITIONAL TERMINAL STATUS WORD BIT DEFINITIONS
;

RPRM=100000		;SET IF CURRENT WRITE IS THE PROMPT FROM IO.RPR
BTWP=20000		;SET IF A WRITE IS BREAKING THROUGH A READ
CCPN=10000		;SET IF A CONTROL C IS PENDING UNDER SPECIAL
			; CIRCUMSTANCES (T$$SYN, T$$HLD)
BAKS=4000      		;SET IF SENDING EXIT HOLD-SCREEN MODE ESCAPE
			; SEQUENCE (T$$HLD)
FKCR=2000		;SET IF LAST CR WAS JUST TO DISPLAY A LONG
			; LINE ON MULTIPLE CRT LINES (T$$ACR)
ECHO=1000		;SET IF ECHOING IN PROGRESS (T$$30P)
XOFF=400		;SET IF XOFF TO BE SENT AT END OF PRESENT READ
			; (T$$RPR)
UPND=200		;SET IF DHBUF HOLDS BYTE SUPPRESSED BY XOFF
			; (T$$HLD, T$$SYN)
CHAR=100		;SET IF MBUFR HOLDS AN INPUT CHARACTER THAT
			; HAS BEEN RECEIVED BUT NOT ECHOED (T$$30P)
WESC=40			;SET IF ATTACHED TASK WANTS ES      CAPE SEQUENCES
			; (T$$ESC)
ESCS=20			;SET IF IN MIDDLE OF AN ESCAPE SEQUENCE (T$$ESC)
CCON=10			;SET IF CONTROL C AST CODE IS ACTIVE (T$$CCA)
MCTR=4			;SET IF DOING CONTROL R FROM TASK'S BUFFER
			; (T$$CTR, T$$UTB)
NCKP=2			;SET IF SOLICITED INPUT REQUEST IS FROM
			; A NONCHECKPOINTABLE TASK (T$$UTB)
UOFF=1			;SET IF OUTPUT TURNED OFF BY AN XOFF
			; (T$$HLD, T$$SYN)

;
; MOST LOCAL DATA (SEE ALSO CNTBL)
;
; ESCAPE SEQUENCE SYNTAX TABLE
;

	.IF DF	T$$ESC

SYNTAB:	.BYTE	73,73		;;;A ;
      	.WORD	265$		;;;
	.BYTE	77,77		;;;A ?
	.WORD	265$		;;;
	.BYTE	117,117		;;;AN O
	.WORD	270$		;;;

	.IF DF	ESCPIC

	.BYTE	120,120		;;;A P
	.WORD	265$		;;;

	.ENDC

	.BYTE	131,131		;;;A Y
	.WORD	280$		;;;
	.BYTE	133,133		;;;CONTROL SEQUENCE INTRODUCER			;TMM012
	.WORD	300$		;;;						;TMM012
265$:	.BYTE	40,57		;;;AN INTERMEDIATE CHARACTER
	.WORD	265$		;;;
	.BYTE	60,176		;;;ANYTHING ELSE
	.WORD	0		;;;
270$:	.BYTE	40,57		;;;AN INTERMEDIATE CHARACTER
	.WORD	270$		;;;
	.BYTE	100,176		;;;SPECI      AL O RANGE TERMINATOR
	.WORD	0		;;;
280$:	.BYTE	40,176		;;;FIRST COORDINATE (BIAS 40)
	.WORD	290$		;;;
290$:	.BYTE	40,176		;;;SECOND COORDINATE (BIAS 40)
	.WORD	0		;;;
300$:	.BYTE	40,77		;;;PARAMETER OR INTERMEDIATE CHARACTER		;TMM012
	.WORD	300$		;;;						;TMM012
	.BYTE	100,176		;;;SPECIAL FINAL CHARACTER			;TMM012
	.WORD	0		;;;						;TMM012

	.ENDC

	.IF DF	T$$GTS

;
; FORM THE WORDS RETURNED BY IO.GTS THAT INDICATE WHICH SYSGEN
; OPTIONS ARE IN THIS DRIVER
;

T2=0

	.IF DF	T$$ACR
T      2=T2!F1.ACR
	.ENDC
	.IF DF	T$$BTW
T2=T2!F1.BTW
	.ENDC
	.IF DF	T$$BUF&C$$CKP
T2=T2!F1.BUF
	.ENDC
	.IF DF	T$$CCA&A$$TRP
T2=T2!F1.UIA
	.ENDC
	.IF DF	T$$CCO
T2=T2!F1.CCO
	.ENDC
	.IF DF	T$$ESC
T2=T2!F1.ESQ
	.ENDC
	.IF DF	T$$HLD
T2=T2!F1.HLD
	.ENDC
	.IF DF	T$$LWC
T2=T2!F1.LWC
	.ENDC
	.IF DF	T$$RNE
T2=T2!F1.RNE
	.ENDC
	.IF DF	T$$RPR
T2=T2!F1.RPR
	.ENDC
	.IF DF	T$$RST
T2=T2!F1.RST
	.ENDC
	.IF DF	T$$RUB
T2=T2!F1.RUB
	.ENDC
	.IF DF	T$$SYN
T2=T2!F1.SYN
	.ENDC
	.IF DF	T$$TRW
T2=T2      !F1.TRW
	.ENDC
	.IF DF	T$$UTB
T2=T2!F1.UTB
	.ENDC
	.IF DF	T$$VBF
T2=T2!F1.VBF
	.ENDC

;
; ALL WORDS OF "T2" MUST BE CONTIGUOUS
;

TCHR1:	.WORD	T2

T2=0			;RSX-11M DOES NOT SUPPORT F2.DCH (DUMP/RESTORE
			; CHARACTERISTICS), RSX-11D STYLE IO.KIL
			; (F2.DKL), ALTS ECHOING AS "$" (F2.ALT),
			; OR SIMULATED FORM FEEDS (F2.SFF)

	.IF DF	T$$SMC
T2=T2!F2.SCH
	.ENDC
	.IF DF	T$$GMC
T2=T2!F2.GCH
	.ENDC

	.WORD	T2

TCHR1E=.

	.ENDC		; DF T$$GTS

	.IF DF	T$$GMC!T$$SMC

;
; DATA ST      RUCTURES FOR GET AND SET MULTIPLE CHARACTERISTICS
;
; FROM U2.VT5 TO U2.L3S CONTAINS MASKS FOR U.CW2 TO TEST FOR TERMINAL
;	TYPE.  THIS INFORMATION MUST PRECEDE ANY INFORMATION
;	ASSOCIATED WITH THE MATERIAL FROM TC.SCP TO TC.XSP.
; FROM 0*400+360 TO 1*400+360 CONTAINS CONSTANTS USED FOR SETTING
;	RECEIVER AND TRANSMITTER BAUD RATES (SPEEDS)
; FROM U2.CRT TO U2.PRV CONTAINS MASKS FOR U.CW2 TO TEST FOR TERMINAL
;	CHARACTERISTICS
; FROM TC.SCP TO TC.XSP CONTAINS WHAT CHARACTERISTICS ARE RECOGNIZED
;      	BY SF.SMC AND SF.GMC (NOTE THAT TC.RSP AND TC.XSP ARE NOT
;	RECOGNIZED BY SF.GMC)
; FROM T.VT05 TO T.L30S CONTAINS WHAT TERMINAL TYPES ARE RECOGNIZED
;	BY SF.SMC AND SF.GMC
;

	.WORD	0		;

	.WORD	U2.L3S		;LA30
	.WORD	U2.VT5		;VT05
	.WORD	0		;

	.IF DF	T$$SMC
	.WORD	200*400+360	;REMOTE ANSWER SPEED				;TMM035
	.WORD	1*400+360	;TRANSMITTER SPEED
	.WORD	0*400+360	;RECEIVER SPEED
	.ENDC

	.WORD	U2.PRV		;PRIVILEGED

	.IF DF	T$$HFF
	.WORD	U2.HFF		;HANDLES HARDWARE FORM FEED
	.ENDC

	.WORD      	U2.SLV		;SLAVE
	.WORD	U2.HLD		;HOLD-SCREEN MODE

	.IF DF	T$$RNE
	.WORD	U2.NEC		;NO ECHO MODE
	.ENDC

	.WORD	U2.LWC		;LOWER TO UPPER CASE CONVERSION
	.WORD	U2.ESC		;CAN GENERATE ESCAPE SEQUENCES
	.WORD	U2.CRT		;CRT (SCOPE)
GMCTAB:				;
	.BYTE	TC.SCP		;SCOPE (CRT)
	.BYTE	TC.ESQ		;ESCAPE SEQUENCES
	.BYTE	TC.SMR		;LOWER TO UPPER CASE CONVERSION

	.IF DF	T$$RNE
	.BYTE	TC.NEC		;NO ECHO MODE
	.ENDC

	.BYTE	TC.HLD		;HOLD-SCREEN MODE
	.BYTE	TC.SLV		;SLAVED

	.IF DF	T$$HFF
	.BYTE	TC.HFF
	.END      C

	.BYTE	TC.PRI		;PRIVILEGED

	.IF DF	T$$SMC
ENDCW2:	.BYTE	TC.RSP		;RECEIVER SPEED (END OF U.CW2
				; CHARACTERISTICS)
	.BYTE	TC.XSP		;TRANSMITTER SPEED
	.BYTE	TC.ASP		;REMOTE ANSWER SPEED				;TMM035
	.ENDC

	.BYTE	T.VT05		;VT05
	.BYTE	T.L30S		;LA30

	.BYTE	0		;

	.ENDC			; DF T$$GMC!T$$SMC

;
; LEGAL MULTIPLEXER SPEEDS TABLE FOR SF.SMC
;
; EACH ENTRY IS TWO CONSECUTIVE BYTES CONSISTING OF:
;
;		HIGH BYTE		LOW BYTE
;
;	------------------------------------------------
;	!       BA      UD RATE      ! DH11 BITS ! DZ11 BITS !
;	------------------------------------------------
;
; WHERE BAUD RATE = A TTSYM$ SYMBOL INDICATING WHICH BAUD RATE THIS
;	(8 BITS)    ENTRY IS FOR
;
;	DH11 BITS = IF ZERO, THE BAUD RATE IS NOT SUPPORTED FOR THE DH11
;	(4 BITS)    IF NONZERO, THE BIT PATTERN THAT MUST BE ASSERTED
;			IN THE DH11 LINE PARAMETER REGISTER TO GET THE
;			BAUD RATE FOR RECEPTION OR TRANSMISSION
;
;	DZ11 BITS = IF ZERO, THE BAUD RATE IS NOT SUPPORTED FOR THE DZ11
;	(4 BITS)    IF       NONZERO, THE BIT PATTERN THAT MUST BE ASSERTED
;			IN THE DZ11 LINE PARAMETER REGISTER TO GET THE
;			BAUD RATE FOR RECEPTION AND TRANSMISSION
;
; A BYTE OF ZEROS (DZ11 AND DH11 BITS ARE ZERO) TERMINATES THE TABLE.
; DH11 BITS = 1 IS A SPECIAL CASE.
;
; THE SUPPORTED SPEEDS ARE THOSE SUPPORTED BY THE MCR COMMAND SET /SPEED.
;

	.IF DF	T$$SMC

SPDTB:	SPDTAB	S.0,1,0		;SPECIAL CASE FOR DH11
	SPDTAB	S.110,3,2
S150:	SPDTAB	S.150,5,4
	SPDTAB	S.200,6,0
	SPDTAB	S.300,7,5
	SPDTAB	S.600,10,6
	SPDTA      B	S.1200,11,7
	SPDTAB	S.1800,12,10
	SPDTAB	S.2000,0,11
	SPDTAB	S.2400,13,12
	SPDTAB	S.3600,0,13
	SPDTAB	S.4800,14,14
	SPDTAB	S.7200,0,15
	SPDTAB	S.9600,15,16
	SPDTAB	S.EXTA,16,0
	SPDTAB	S.EXTB,17,0
	.BYTE	0

	.ENDC

;
; CONTROL OUTPUT MESSAGES
;


	.IF NDF	M$$CLI!A$$CLI							;TMM032
										;TMM032
										;**-1
CTRLC:	.ASCIZ	<15><12>/MCR>/ 	;

	.ENDC	;M$$CLI

CTRLZ:	.ASCIZ	/^Z/<15><12>
CTRLU:	.ASCIZ	/^U/<15><12>	;MUST BE AFTER A ZERO BYTE

	.IF DF	T$$HLD

LEVHSM:	.ASCIZ	      <33>/\/		;LEAVE HOLD-SCREEN MODE

	.ENDC

	.IF DF	T$$RUB

	.ASCIZ	<10><10><10><10><10><10><10><10> ;BACKSPACES
CRTBS=.-1			;MUST BE AT END OF BACKSPACES
CRTRUB:	.ASCIZ	<10>/ /<10>	;BACKSPACE, SPACE, BACKSPACE

	.ENDC

;
; LA30S CARRIAGE RETURN FILL TABLE
;

FILTB:	.BYTE	4.		;0-8.
	.BYTE	8.		;9.-16.
	.BYTE	6.		;17.-24.
	.BYTE	3.		;25.-32.
	.BYTE	0.		;33.-40.
	.BYTE	2.		;41.-48.
	.BYTE	4.		;49.-56.
	.BYTE	6.		;57.-64.
	.BYTE	8.		;65.-72.
	.BYTE	10.		;73.-80.

	.EVEN
	.SBTTL	TERMIN      AL INITIATOR

	.IF DF	T$$RPR!T$$BTW

TTCHK:	MOV	R1,R3		;SAVE START OF PACKET FOR $IOFIN

	.IF NDF	T$$RPR

	BR	30$		;SKIP AROUND CODE

	.ENDC

	.ENDC			; DF T$$RPR!T$$BTW

	.IF DF	T$$RPR

;+
; **-TTCHK-TERMINAL DRIVER SPECIAL PARAMETER CHECKING
;
; ENTRY HERE FROM DRQIO WHEN A QIO FOR THE TERMINAL DRIVER HAS BEEN
; CHECKED.  A READ-WITH-PROMPT QIO HAS A SECOND BUFFER
; SPECIFICATION THAT NEEDS TO BE CHECKED IN THE CONTEXT OF THE
; ISSUING TASK.  IF NECESSARY, DO THE CHECKS.  ALWAYS QUEU      E THE REQUEST.
;
; INPUTS:
;
;	R1 -> I/O REQUEST PACKET
;	R4 -> SCB
;	R5 -> UCB
;
; OUTPUTS:
;
;	THE PROMPT (WRITE) BUFFER IS ADDRESS CHECKED TO MAKE SURE IT
;	LIES WITHIN THE ISSUING TASK.  IF IT DOES, THE BUFFER ADDRESS
;	IS RELOCATED AND STORED IN THE I/O PACKET, THE PACKET IS
;	INSERTED IN THE CONTROLLER QUEUE, AND THE DEVICE INITIATOR
;	IS ENTERED TO START THE CONTROLLER.
;-

	CMPB	#IO.RPR/400,I.FCN+1(R1) ;QIO NEED SPECIAL CHECKING?

	.IF DF	T$$BTW

	BNE	30$		;IF NE NO

	.IFF

      	BNE	20$		;IF NE NO -- JUST QUEUE IT

	.ENDC

	MOV	I.PRM+10(R3),R0	;GET VIRTUAL ADDRESS OF BUFFER

	.IF DF	A$$CHK!M$$MGE

	MOV	I.PRM+12(R3),R1	;GET LENGTH OF BUFFER
	BEQ	8$		;MUST PROMPT WITH AT LEAST 1 CHAR

	.IF DF	T$$VBF

	CMP	#255.,R1	;PROMPT BIGGER THAN LARGEST BUFFER?

	.IFF

	CMP	#80.,R1		;PROMPT BIGGER THAN LARGEST BUFFER?

	.IFTF

	BHIS	7$		;IF HIS NO
	MOV	#IE.BAD&377,R0	;RETURN BAD PARAMETER STATUS
	BR	9$		;

	.ENDC

7$:	CALL	$ACHKB		;ADDRESS CHECK BUFFER
	BCC	10$		;IF       CC OKAY
8$:	MOV	#IE.SPC&377,R0	;RETURN ILLEGAL BUFFER STATUS
9$:	CLR	R1		;SET IOSB+2 TO ZERO
	CALLR	$IOFIN		;FINISH I/O OPERATION
10$:				;REF LABEL

	.ENDC

	CALL	$RELOC		;RELOCATE BUFFER ADDRESS
	MOV	R1,I.PRM+10(R3)	;SET RELOCATION BIAS OF BUFFER
	MOV	R3,R1		;COPY I/O PACKET ADDRESS
	ADD	#I.PRM+14,R3	;POINT INTO I/O PACKET
	MOV	(R3)+,(R3)	;SAVE VERTICAL FORMAT CONTROL
	CMP	-(R3),-(R3)	;POINT AT PROMPT BUFFER SIZE
	MOV	(R3)+,(R3)	;MOVE BUFFER SIZE TO SAFETY
	MOV	R2,-(R3)	;SET ADDRESS OF BUFF      ER

	.ENDC			; DF T$$RPR

	.IF DF	T$$RPR!T$$BTW

20$:	MOV	R4,R0		;SET ADDRESS OF I/O QUEUE LISTHEAD
	CALL	$QINSP		;INSERT I/O PACKET IN REQUEST QUEUE
23$:	JMP	TTINI		;GO TO WORK

	.ENDC

	.IF DF	T$$BTW

30$:	CMPB	#IO.WLB/400,I.FCN+1(R1) ;A WRITE?
	BNE	20$		;IF NE NO -- JUST QUEUE IT
	BITB	#TF.WBT,I.FCN(R1) ;A BREAKTHROUGH WRITE?
	BEQ	20$		;IF EQ NO -- JUST QUEUE IT

	.IF DF	M$$MUP

	MOV	I.TCB(R1),R2	;GET TCB OF REQUESTING TASK
	BIT	#T3.PRV!T3.CLI,T.ST3(R2) ;IS TASK PRIV. OR A CLI?		;TM      M011
	BEQ	35$		;IF EQ NO					;**-1

	.ENDC

	.IF DF	D$$M11&D$$H11!D$$ZMD

	MOV	#IE.DNR&377,R0	;ASSUME WRITING TO DISABLED LINE
	BITB	#US.DSB,U.STS(R5) ;IS LINE DISABLED?
	BNE	9$		;IF NE YES -- REJECT PACKET

	.ENDC

	BISB	#TF.CCO,I.FCN(R1) ;IO.WBT IMPLIES CANCEL CONTROL O

	.IF DF	T$$HLD!T$$SYN

	BIC	#UOFF,U.CNT+2+ATERS(R5) ;IGNORE ANY XOFF'S

	.ENDC

	MTPS	S.PRI(R4)	;DISALLOW INTERRUPTS
	MOVB	U.STS(R5),R2	;;;SAVE STATUS OF US.ECH			;TMM008
	BISB	#US.ECH,U.STS(R5) ;;;DISALLOW INPUT (B      USYING OF UNIT)
										;TMM008
	.IIF NE US.BSY-200,	.ERROR US.BSY					;TMM008
										;TMM008
				;;; UNIT BUSY?					;TMM008
	BMI	40$		;IF MI YES (RATS!)				;**-1
32$:				;REF LABEL
	MOV	(R4),(R1)	;QUEUE THIS AS FIRST IN QUEUE
	BNE	3400$		;IF NE ANOTHER PACKET IN QUEUE
	MOV	R1,2(R4)	;MAKE "LAST" POINT AT THIS PACKET
3400$:	MOV	R1,(R4)		;
	MTPS	#0		;;;REDUCE PRIORITY
	BR	23$		;HANDLE IT NORMALLY

	.IF DF	M$$MUP

35$:	MOV	#IE.PRI&377,R0	;IO.WBT ILLEGAL FROM UNPRIVILEGED TASK
	BR	9$		; IN       A MULTIUSER PROTECTION SYSTEM

	.ENDC

40$:	TSTB	@U.CNT+2+MEBUF(R5) ;;;DOING A MULTIECHO (GENERALLY
				   ;;; A CONTROL/R)?
	BNE	42$		   ;;;IF NE YES
				  ;;; CHARACTER IN TRANSMITTER BUFFER		;**-2
	BIT	#SOLI!MODE,U.CNT+2+STATS(R5) ;;;SOLICITED INPUT OR
					     ;;; OUTPUT IN PROGRESS?
	BNE	41$		;IF NE YES
	MOV	U.CNT+2+STRBF(R5),R0 ;POINT AT UNSOLICITED INPUT BUFFER
	BR	46$		;PRESS ON
41$:	MOV	S.PKT(R4),R0	;GET START OF PACKET THAT IS BEING
				; PROCESSED
	BIT	#RPRM!BTWP,U.CNT+2+ATERS(R5      ) ;;;BREAKING THROUGH OR
				;;; PROMPTING?
	BEQ	43$		;;;IF EQ NO
42$:	MOV	#IE.RSU&377,R0	;;;UNSHARABLE RESOURCE IN USE (CANNOT
				;;; IO.WBT WHILE DOING AN IO.WBT,
				;;; PROMPT, OR MULTIECHO)
	BITB	#US.ECH,R2	;;; WAS US.ECH ALREADY SET ?			;TMM008
	BNE	44$		;;; IF NE YES, DO NOT CLEAR IT.			;TMM008
	CALL	INPT0		;;;CLEAR US.ECH
44$:				;;; REF LABEL					;TMM008
	MTPS	#0		;;;REDUCE PRIORITY

	.IF DF	A$$CHK!M$$MGE&T$$RPR

	BR	9$		;

	.IFF

9$:	CLR	R1		;WANT IOSB+2 TO BE ZERO
	CALLR	$IOFI      N		;FINISH OFF I/O PACKET

	.ENDC

43$:	CMPB	#IO.RLB/400,I.FCN+1(R0) ;;;DOING A READ?
	BEQ	46$		;;;IF EQ YES -- BREAKTHROUGH

	.IIF NE	UPND-200,	.ERROR	UPND

	TSTB	U.CNT+2+ATERS(R5) ;;;HAVE A HELD UP CHARACTER?
	BPL	32$		;;;IF PL NO
	BIC	#UPND,U.CNT+2+ATERS(R5) ;;;CLEAR PENDING FLAG
	MOV	#45$,-(SP)	;;;WANT TO RETURN TO 45$
	MOVB	U.CNT+2+DHBUF(R5),-(SP) ;;;RETRIEVE HELD UP CHARACTER
	CALLR	FCHAR		;;;FORCE IT OUT
45$:	MOV	U.SCB(R5),R4	;;;RESTORE THE MESSED UP REGISTER
	BR	32$		;;;DO THIS IO.WB      T AS NEXT FUNCTION
46$:	MOV	R5,R3		;POINT AT TERMINAL STATUS
	ADD	#U.CNT+2+STATS,R3 ;
	BIT	#EOLS,(R3)	;;;HAS THE READ "FINISHED"?
	BNE	32$		;;;IF NE YES -- JUST QUEUE BREAKTHROUGH
	BIT	#SOLI,(R3)	;SOLICITED INPUT GOING ON?
	BNE	48$		;IF NE YES
	MOV	(R3),-(R0)	;SAVE TERMINAL STATUS FOR UNSOL READ
	BIC	#LFCT!CRTY!CRJT!CTLO!FLCT,(R0) ;;;MAKE SAVED STATUS
				;;; SHOW INACTIVE ON OUTPUT
	CLR	I.PRM+16(R1)	;SIGNAL UNSOLICITED READ BREAKTHROUGH
	SUB	#U.CNT+2+STATS-U.BUF,R3 ;POINT AT U.BUF
	BR	50$		;
4      8$:	MOVB	S.STS(R4),(R0)	;SAVE STATUS OF DISPLACED READ
	MOV	R0,I.PRM+16(R1)	;SAVE POINTER TO DISPLACED PACKET
	ADD	#I.PRM+14,R0	;POINT NEAR END OF DISPLACED PACKET
	MOV	(R3),(R0)	;SAVE STATS
	BIC	#LFCT!CRTY!CRJT!CTLO!FLCT,(R0) ;;;MAKE SAVED STATS
				;;; SHOW INACTIVE ON OUTPUT

; NEXT INSTUCTION DEPENDS ON STATS=U.CNT+2

	MOV	-(R3),-(R0)	;SAVE U.CNT
	MOV	-(R3),-(R0)	;SAVE U.BUF+2
	MOV	-(R3),-(R0)	;SAVE U.BUF
50$:	MOV	I.PRM(R1),(R3)+	;RESET U.BUF FOR IO.WBT
	MOV	I.PRM+2(R1),(R3)+ ;RESET U.BUF+2      
	MOV	I.PRM+4(R1),(R3)+ ;RESET U.CNT
	MOV	R1,S.PKT(R4)	;MAKE IO.WBT THE CURRENT I/O PACKET
	BIC	#CTLO!LFCT!CRTY!EOLS!RUBP!SOLI,(R3) ;;;RESET
	BIS	#MODE,(R3)	;;; STATUS WORD FOR IO.WBT
	BIS	#BTWP,ATERS(R3)	;FLAG IO.WBT ACTION
	JMP	FWRITE		;DO THE WRITE

	.ENDC

	.ENABL	LSB

	.IF DF	T$$SMC

;
; R0 = IS.SUC&377 (PRESERVE IF AN ERROR IS NOT DETECTED)
; R1 = POINTER TO WORD PRECEDING GMCTAB THAT CORRESPONDS TO BUFFER'S
;      CHARACTERISTIC SYMBOL (SCRATCH)
; -(R2) = BUFFER'S CHARACTERISTIC SYM      BOL (SCRATCH)
; R3 = (SCRATCH)
; R4 = ADDRESS OF I/O PACKET (PRESERVE)
; R5 = UCB ADDRESS (PRESERVE)
; NOTHING ON THE STACK
;

1820$:	MOV	U.CW2(R5),-(SP)	;GET CHARACTERISTICS WORD

; NEXT INSTRUCTION DEPENDS ON U2.DH1=100000

	.IF DF	D$$H11!D$$Z11							;TMM035
										;TMM035
	BPL	1852$		;IF PL TERMINAL IS NOT ON A MULTIPLEXER
	ASL	(SP)		;IS MULTIPLEXER A DJ11?

; NEXT INSTRUCTION DEPENDS ON U2.DJ1=U2.DH1/2

	BMI	1852$		;IF MI YES -- BAUD RATE NOT PROGRAMMABLE
	MOVB	(R1)+,R3	;GET DZ11       BAUD RATE MASK			;TMM035
										;TMM035
	.IF DF	D$$H11								;TMM035
										;TMM035
	TSTB	(SP)		;IS MULTIPLEXER A DH11?				;TMM035
										;TMM035
	.IF DF	D$$Z11								;TMM035
										;TMM035
	BMI	1822$		;IF MI NO					;TMM035
										;TMM035
	.IFF									;TMM035
										;TMM035
	BMI	1852$		;IF MI NO NAD THERE'S NO DZ11 SUPPORT		;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	COMB	R3		;CONVERT TO DH11 MASK				;TMM035
										;TMM035
	.IFF									;TMM0      35
										;TMM035
	.IF DF	D$$Z11								;TMM035
										;TMM035
	TSTB	(SP)		;IS MULTIPLEXER A DH11?				;TMM035
	BPL	1852$		;IF PL YES AND THERE'S NO DH11 SUPPORT		;TMM035
	TSTB	(SP)+		;CLEANUP STCAK					;TMM035
										;TMM035
	.ENDC			;D$$Z11						;TMM035
										;TMM035
	.ENDC			;D$$H11						;TMM035
										;TMM035
1822$:	CALL	$GTBYT		;GET BUFFER'S BAUD RATE SYMBOL			;**-7
	MOV	#SPDTB,R0	;POINT AT LEGAL SPEED TABLE
1824$:	MOVB	(R0)+,R2	;GET BAUD RATE BITS				;TMM035
	BNE	1826$		;      IF NE HAVE NOT FOUND END OF TABLE		;**-1
1825$:	JMP	18772$		;
1826$:	CMPB	(R0)+,(SP)	;ARE THE BAUD RATE BITS FOR THE
				; BUFFER'S BAUD RATE SYMBOL?
	BNE	1824$		;IF NE NO
	BIC	R3,R2		;THROW AWAY BITS FOR OTHER MULTIPLEXER		;TMM035
	BEQ	1825$		;IF EQ THIS MULTIPLEXER DOES NOT		;**-1
				; SUPPORT THIS BAUD RATE
	TST	(SP)+		;POP STACK					;TMM035
	TSTB	(R1)		;WORKING ON TC.RSP OR TC.RSP?			;TMM035
	BGT	1829$		;IF GT TC.TSP					;TMM035
										;TMM035
	.IF DF	D$$M11!D$$ZMD							;TMM035
							      			;TMM035
	BEQ	1828$		;IF EQ TC.RSP					;TMM035
	INC	R5		;TC.ASP AFFECTS U.CW3+1				;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
1828$:	BICB	#<17>,U.CW3(R5)	;CLEAR A SPOT FOR ASP OR RSP			;TMM035
1829$:										;TMM035
										;TMM035
	.IF DF	D$$H11								;TMM035
										;TMM035
	TSTB	(SP)+		;IS MULTIPLEXER A DZ11?				;TMM035
	BPL	1830$		;IF PL IT'S A DH11				;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.IF DF	D$$Z11								;TMM035
							      			;TMM035
	SWAB	R2		;POSITION BAUD RATE BITS FOR DZ11		;TMM035
										;TMM035
	.IF DF D$$ZMD								;TMM035
										;TMM035
	TSTB	(R1)		;TC.ASP?					;TMM035
	BMI	1832$		;IF MI YES					;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	CLRB	U.CW3(R5)	;CLEAR OUT BOTH TSP AND RSP FIELDS FOR DZ11	;TMM035
	CALL	SSSZSP		;SET BAUD RATE BITS INTO U.CW3			;TMM035
										;TMM035
	.IF DF	D$$H11!D$$ZMD							;TMM035
										;TMM035
	BR	1838$		;GO TELL DZ11 ABOUT CHANGE			;TMM0      35
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.IF DF	D$$H11								;TMM035
										;TMM035
1830$:	CMP	#<1*20>,R2	;IS THIS THE DH11 SPECIAL CASE?			;TMM035
	BNE	1831$		;IF NE NO					;TMM035
	CLR	R2		;CLEAR OUT BAUD RATE BITS FOR A "ZERO" BAUDRATE	;TMM035
1831$:	TSTB	(R1)		;IS THIS TC.RSP OR TC.ASP?			;TMM035
	BLE	1833$		;IF LE YES					;TMM035
	BIC	#<360>,U.CW3(R5);CLEAR OUT SPOT FOR TSP				;TMM035
										;TMM035
	.ENDC									;TMM      035
										;TMM035
	.IF DF	D$$H11!D$$ZMD							;TMM035
										;TMM035
1832$:	BISB	R2,U.CW3(R5)	;SET UP NEW ASP OR RSP				;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.IF DF	D$$H11								;TMM035
										;TMM035
	BR	1834$		;GO SET UP LPR IN DH				;TMM035
1833$:	CALL	SSSCW3		;SHIFT,SWAB AND SET BAUDRATE IN R2 INTO U.CW3	;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.IF DF	D$$ZMD!D$$M11							;TMM035
										;TMM035
1834$:	BIC	#1,R5		;ADJU      ST R5 TO POINT TO UCB			;TMM035
										;TMM035
	.IFF									;TMM035
										;TMM035
1834$:				;REF LABEL					;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
1838$:	MOV	U.SCB(R5),R2	;GET SCB ADDRESS				;TMM035
	MOV	S.CSR(R2),R2	;GET CSR ADDRESS				;TMM035
	MTPS	#7		;LOCK OUT INTERRUPTS				;TMM035
	CALL	SETLIN		;;;SET THE NEW BAUD RATE INTO THE CONTROLLER	;TMM035
	MTPS	#0		;RETURN TO NORMAL PRIORITY			;TMM035
	MOV	#IS.SUC&377,R0	;RESTORE SUCCESS STATUS				;TMM035
	BR	187      2$		;DECODE NEXT BUFFER BYTE			;TMM035
										;TMM035
	.IFF			;D$$H11!D$$Z11					;TMM035
										;TMM035
	BR	1852$		;RETURN ERROR IF NO DZ OR DH SUPPORT		;TMM035
										;TMM035
	.ENDC			;D$$H11!D$$Z11					;TMM035
										;TMM035
	.ENDC			;T$$SMC						;TMM035
										;TMM035
										;**-58
	.IF DF	T$$GMC!T$$SMC

1840$:	TST	(SP)+		;DESTROY SAVED R3
	SUB	#2,U.CNT(R5)	;FINISHED DECIPHERING BUFFER?
	BLT	1846$		;IF LT YES
	MOV	#GMCTAB,R2	;POINT AT RECOGNITION TABLE
	MOV	R2,R1		;COPY       THE POINTER
	CALL	$GTBYT		;GET BYTE TO DECIPHER
1842$:	TST	-(R1)		;TABLE OF CHARACTERISTICS EXHAUSTED?
	BEQ	1850$		;IF EQ YES
	CMPB	(R2)+,(SP)	;RECOGNIZE CHARACTERISTIC?
	BNE	1842$		;IF NE NO
	SEC			;SET C-BIT TO SHOW TC. MATCH
1844$:	RTS	R3		;RETURN AND CLEAR STACK
1846$:	JMP	5$		;RETURN WITH IOSB+2 = 0
1850$:	CMPB	#TC.TTP,(SP)	;WORRYING ABOUT TERMINAL TYPE?
	BEQ	1844$		;IF EQ YES (C-BIT IS CLEAR)
1852$:	MOV	#SE.NIH*400!<IE.ABO&377>,R0 ;DID NOT RECOGNIZE BYTE
1854$:	MOV	S.PKT(R4),R3	;POINT AT       I/O PACKET
	MOV	U.BUF+2(R5),R1	;PICK UP WHERE WE STOPPED IN BUFFER
				; (ASSUME BUFFER < 4096.-32. BYTES)
	SUB	I.PRM+2(R3),R1	;STOPPING POINT - START OF BUFFER
	DEC	R1		;ADJUST
	TST	(SP)+		;CLEAN UP STACK

	.IF DF	T$$GTS

	BR	1868$		;RETURN AN ERROR TO THE TASK

	.IFF

	JMP	IODON		;RETURN AN ERROR TO THE TASK

	.ENDC

	.ENDC			; DF T$$GMC!T$$SMC

1860$:				;REF LABEL

	.IF DF	T$$GMC!T$$SMC&A$$CHK!T$$GTS

	MOV	U.CNT(R5),R3	;COPY LENGTH OF BUFFER

	.ENDC

	.IF DF	T$$GMC!T$$GTS!T$$S      MC&A$$CHK

	BIT	#1,U.BUF+2(R5)	;BUFFER ON A BYTE BOUNDARY?
	BEQ	1861$		;IF EQ NO					; EB251
19088$:	MOV	#IE.SPC&377,R0	;ILLEGAL BUFFER					;TMM036
										;**-9
	.IF DF	T$$GMC!T$$SMC

	BR	1846$		;

	.IFF

	JMP	5$		;

	.ENDC

1861$:				;REF LABEL					; EB251
	BIT	#1,R3		;BUFFER CONTAINS WORDS?				;**-4
1862$:	BNE	19088$		;IF NE NO					; EB251
	CMP	#4096.-32.,R3	;BUFFER TOO LARGE				;**-1
	BLT	19088$		;IF LT YES -- MIGHT BLOW ERROR OFFSET		;TMM036
				; ON A MAPPED SYSTEM				;**-1

	      .ENDC			; DF T$$GMC!T$$GTS!T$$SMC&A$$CHK

	.IF DF	T$$GTS

	CMPB	#IO.GTS,I.FCN(R1) ;GET TERMINAL SUPPORT QIO?
	BNE	1870$		;IF NE NO
	CMP	#TCHR1E-TCHR1,R3 ;WANTS MORE THAN WE DELIVER?
	BGE	1863$		;IF GE NO
	MOV	#TCHR1E-TCHR1,R3 ;CHANGE TO OUR MAXIMUM
1863$:	MOV	#TCHR1,R2	;POINT AT SUPPORT INFO WORDS
	CLR	R1		;CLEAR COUNTER OF MOVED BYTES
1864$:	MOVB	(R2)+,-(SP)	;PUT THE 1ST BYTE OF THE 1ST
	CALL	$PTBYT		; SUPPORT WORD INTO THE TASK'S BUFFER
	INC	R1		;COUNT A BYTE MOVED
	CMP	R1,R3		;TASK WANTS MO      RE?
	BLT	1864$		;IF LT YES
1868$:	JMP	IODON		;RETURN STATUS
1870$:				;REF LABEL

	.ENDC

	.IF DF	T$$SMC

	CMPB	#SF.SMC,I.FCN(R1) ;SET MULTIPLE CHARACTERISTICS?
	BNE	1880$		;IF NE NO

	.IF DF	M$$MUP

	MOV	I.TCB(R1),R3	;POINT AT TCB OF REQUESTING TASK
	CMP	T.UCB(R3),R5	;IS TASK'S TI: THIS TERMINAL?
	BEQ	1872$		;IF EQ YES -- ALMOST ANYTHING IS LEGAL
	BIT	#T3.PRV,T.ST3(R3) ;IS THE TASK PRIVILEGED
	BNE	1872$		;IF NE YES -- ALMOST ANYTHING IS LEGAL
	MOV	#IE.PRI&377,R0	;PRIVILEGE VIOLATION
	BR      	1846$		;

	.ENDC

1872$:	JSR	R3,1840$	;DECIPHER MEANING OF THEIR
				; CHARACTERISTICS BYTE
	BCC	1876$		;IF CC WORRY ABOUT TERMINAL TYPE
	CMP	#ENDCW2,R2	;U.CW2 CHARACTERISTIC OR SPEED?
	BHIS	18722$		;IF HIS U.CW2 CHARACTERISTIC
	JMP	1820$		;
18722$:	CALL	$GTBYT		;GET DESIRED VALUE FOR CHARACTERISTIC
	CMP	#U2.PRV,(R1)	;TASK TRYING TO CHANGE PRIVILEGE STATUS?
	BEQ	1852$		;IF EQ YES -- DO NOT ALLOW THAT
	BITB	#376,(SP)	;VALUE IS 1 OR 0?
	BEQ	1873$		;IF EQ YES
	MOV	#SE.BIN*400!<IE.ABO&377>,R0 ;I      T SHOULD HAVE BEEN
	BR	1854$		;
1873$:	BIC	(R1),U.CW2(R5)	;ASSUME THE VALUE IS ZERO
1874$:	TSTB	(SP)+		;IS THE VALUE ZERO?
	BEQ	1872$		;IF EQ YES
1875$:	BIS	(R1),U.CW2(R5)	;SET THE APPROPRIATE BIT
	BR	1872$		;TRY TO DECIPHER THEIR NEXT BYTE
1876$:	CALL	$GTBYT		;GET DESIRED TERMINAL TYPE VALUE
1877$:	TST	-(R1)		;EXHAUSTED LIST OF RECOGNIZIBLE VALUES?
	BNE	1878$		;IF NE NO
	CMPB	#T.UNK0,(SP)	;SET TERMINAL TO UNKNOWN TYPE?
	BEQ	1879$		;IF EQ YES
	CMP	#T.AS33,(SP)	;SET TERMINAL TO ASR33 (UPCASE OUTP      UT?)		;TMM036
	BNE	18772$		;IF NE NO					;TMM036
	BIS	#U3.UPC,U.CW3(R5) ;SET CHARACTERISTIC				;TMM036
	BIC	#U2.VT5!U2.L3S,U.CW2(R5) ;IGNORE OLD TERMINAL TYPE		;TMM036
	TST	(SP)+		;CLEAN STACK					;TMM036
	BR	1872$		;TRY TO DECIPHER NEXT BYTE			;TMM036
18772$:	MOV	#SE.VAL*400!<IE.ABO&377>,R0 ;SHOW INAPPROPRIATE VALUE
	BR	1854$		;
1878$:	CMPB	(R2)+,(SP)	;RECOGNIZE THE TERMINAL TYPE VALUE?
	BNE	1877$		;IF NE NO
1879$:	BIC	#U2.VT5!U2.L3S,U.CW2(R5) ;IGNORE OLD TERMINAL TYPE
	BIC	#U3.UPC,U.CW3(R5) ;RE      SET ASR33 TERMINAL TYPE			;TMM036
	BR	1874$		;SET THEIR TYPE [(SP) IS GENERALLY NONZERO]
1880$:				;REF LABEL

	.ENDC

	.IF DF	T$$GMC

	CMPB	#SF.GMC,I.FCN(R1) ;GET MULTIPLE CHARACTERISTICS?
	BNE	1888$		;IF NE NO
1882$:	JSR	R3,1840$	;FIND OUT WHAT CHARACTERISTIC THEY
				; ARE INQUIRING ABOUT
	BCC	1884$		;IF CC WANT TO KNOW THE TERMINAL TYPE
	CLR	-(SP)		;ASSUME CHARACTERISTIC NOT ASSERTED

	.IF DF	T$$SMC

	CMP	#ENDCW2,R2	;GETTING U.CW2 CHARACTERISTIC?
	BHIS	18822$		;IF HIS YES					;TMM036
      	JMP	1852$		;IF LO -- CANNOT GET SPEEDS			;TMM036
18822$:										;TMM036
										;**-1
	.ENDC

	BIT	(R1),U.CW2(R5)	;CHARACTERISTIC ASSERTED?
	BEQ	1883$		;IF EQ NO
	INC	(SP)		;REMEMBER ITS BEING ASSERTED
1883$:	CALL	$PTBYT		;PUT VALUE INTO TASK'S BUFFER
	BR	1882$		;TRY AGAIN
1884$:	MOVB	#T.UNK0,-(SP)	;ASSUME UNKNOWN TERMINAL TYPE
1885$:	TSTB	(R2)+		;TERMINAL TYPE TABLE EXHAUSTED?
	BEQ	1886$		;IF EQ YES					;TMM036
	BIT	-(R1),U.CW2(R5)	;IS THIS TERMINAL THIS TYPE?			;**-1
	BEQ	1885$		;IF EQ       NO
	MOVB	-(R2),(SP)	;PICK UP THE TERMINAL TYPE
	BR	1883$		;RETURN IT TO THE TASK
1886$:	BIT	#U3.UPC,U.CW3(R5) ;COULD THIS TERMINAL BE AN ASR33?		;TMM036
	BEQ	1883$		;IF EQ NO					;TMM036
	MOVB	#T.AS33,(SP)	;GET ASR33 TERMINAL TYPE			;TMM036
	BR	1883$		;RETURN TYPE TO TASK				;TMM036
1888$:				;REF LABEL

	.ENDC

	.IF DF	T$$GMC!T$$GTS!T$$SMC

	MOV	#IE.IFC&377,R0	;NO OTHER SUBFUNCTIONS ARE SUPPORTED
	BR	304$		;
1889$:	JMP	1860$		;						;TMM036
										;**-1
	.ENDC

	.IF DF	T$$CCA&A$$TRP
      
;
; SET UP FOR UNSOLICITED CHARACTER AST
;

1900$:	MOV	I.PRM(R1),CCAST(R3) ;SAVE AST ENTRY POINT ADDRESS
	BEQ	1907$		;IF EQ BAD ADDRESS				; EB251
	BIT	#1,CCAST(R3)	;IS ADDRESS ODD?				;**-1
	BNE	1907$		;IF NE YES					; EB251
	BIS	#CCON,ATERS(R3)	;ARM UNSOLICITED CHAR AST CODE			;**-1
	BR	1910$		;
1907$:	CLR	U.ATT(R5)	;SHOW NOT ATTACHED				; EB251
1908$:	MOV	#IE.SPC&377,R0	;THERE'S NO POINT IF NO
1910$:	BR	304$		; AST ADDRESS

	.ENDC

	.IF DF	T$$RPR

;
; START ANALYSIS OF READ AFTER PRO      MPT QIO FOR SUBFUNCTIONS
;

1920$:	MOV	#RPRM,-(SP)	;COPY BIT PATTERN FOR ATERS
	BITB	#TF.XOF,I.FCN(R1) ;XOFF TERMINATION SUBFUNCTION?
	BEQ	1922$		;IF EQ NO
	BIS	#XOFF,(SP)	;REMEMBER NEED FOR XOFF
1922$:	BIS	(SP)+,ATERS(R3)	;SET STATUS FOR LATER REFERENCE
	CMP	I.PRM+14(R1),U.CNT(R5) ;PROMPT BUFFER LONGER THAN READ?
	BLE	1924$		;IF LE NO
	MOV	I.PRM+14(R1),U.CNT(R5) ;WANT TO ALLOCATE EXECUTIVE
1924$:	BR	305$		; BUFFER THAT IS BIG ENOUGH FOR EITHER

	.ENDC

;+
; **-TTINI-TERMINAL INTITIATOR
;
      ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER (UN      IT) TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;
; SEE THE I/O DRIVERS REFERENCE MANUAL FOR A DETAILED DESCRIPTION
; OF WHAT THIS DRIVER SUPPORTS.  IN BRIEF:
;
; A$$CHK = ADDRESS CHECKING (GOES WITH T$$RPR, T$$GMC, T$$SMC, T$$GTS)
; A$$TRP = AST SUPPORT IN SYSTEM (GOES WITH T$$CCA)
; C$$CKP = CHECKPOINT SUPPORT IN SYSTEM (GOES WITH T$$BUF)
; D$$      H11 = DH11 MULTIPLEXERS
; D$$J11 = DJ11 MULTIPLEXERS
; D$$L11 = DL11/A/B/C/D
; D$$M11 = DM11-BB MODEM CONTROLLER FOR DH11
; D$$YNC = DYNAMIC CHECKPOINTING (GOES WITH C$$CKP AND T$$BUF)
; D$$YNM = DYNAMIC MEMORY MANAGEMENT IN SYSTEM (GOES WITH M$$MGE,
;	   C$$CKP, AND T$$BUF)
; D$$ZMD = BELL 103A MODEM CONTROL FOR DZ11 LINES
; D$$Z11 = DZ11 MULTIPLEXER
; I$$RAR = REMOVE AFTER RUNNING (GOES WITH I$$RDN AND M$$MGE)
; I$$RDN = I/O RUNDOWN (GOES WITH I$$RAR AND M$$MGE)
; LD$$H, LD$$J, LD$$L, LD$$Z = V      ARIOUS FLAVORS OF LOADABLE USER DRIVERS
;	   (NOT SUPPORTED)
; LD$TT	= DEFINED IF TERMINAL DRIVER IS LOADABLE
; L$$DRV = DEFINED IF LOADABLE TERMINAL DRIVER SUPPORT IN SYSTEM
; L$$SI1 = LSI-11 SUPPORT.  EFFECTS MTPS MACRO.
;	   (DH11, DJ11, DM11, AND DZ11 ARE NOT COMPATIBLE WITH Q-BUS)
; L$$50H = FIFTY HERTZ VT05 SUPPORT
; M$$MGE = MEMORY MANAGEMENT SUPPORT
; M$$MUP = AUTOMATIC "BYE" ON DM11 AND DZ11 HANGUPS AND PRIVILEGE CHECKS
; P$$LAS = MEMORY MANAGEMENT DIRECTIVES
; R$$LKL = RMS-11 LOCKING
;       R$$11S = IGNORE UNSOLICITED INPUT ON RSX-11S SYSTEMS THAT HAVE
;	   NO BASIC MCR
; T$$ACR = AUTOMATIC CR/LF FOR LINES THAT ARE BIGGER THAN TERMINAL
;	   BUFFER SIZE (U.CW4)
; T$$BTW = BREAKTHROUGH WRITE
; T$$BUF = CHECKPOINTING DURING TERMINAL INPUT (GOES WITH C$$CKP)
; T$$CCA = UNSOLICITED CHARACTER AST'S (GOES WITH A$$TRP)
; T$$CCO = CLEAR CONTROL O INHIBIT BEFORE DOING WRITE
; T$$CTR = CONTROL R DISPLAYS THE INTERPRETED INCOMPLETE INPUT BUFFER
; T$$ESC = RECOGNITION OF ESCAPE SEQUENCES FOR SOLIC      ITED READS
; T$$GMC = GET MULTIPLE TERMINAL CHARACTERISTICS
; T$$GTS = GET TERMINAL DRIVER SUPPORT MASKS
; T$$HFF = FORM FEEDS ARE PASSED THROUGH ON OUTPUT
; T$$HLD = HOLD-SCREEN MODE SUPPORT (ALMOST T$$SYN SUPPORT) AND
;	   CONTROL C KNOCKS TERMINAL OUT OF IT.  INTERACTS WITH MCR.
; T$$LWC = LOWER CASE TO UPPER CASE MAPPING ON INPUT AND RECOGNITION
;	   OF 175 AND 176 AS ASCII CHARACTERS
; T$$MIN = DEFINED IN THE MINIMUM TERMINAL DRIVER AND THE MINIMUM
;	   MULTIUSER DRIVER (ALONG WITH T$$BTW, T$$      RNE, T$$RST)
; T$$RNE = READ WITH NO ECHO
; T$$RPR = READ AFTER PROMPT
; T$$RST = READ WITH SPECIAL TERMINATORS
; T$$RUB = RUBOUTS ERASE PRINTING CHARACTERS AND TABS ON CRT'S
; T$$SMC = SET MULTIPLE TERMINAL CHARACTERISTICS
; T$$SYN = CTRL S AND Q SUPPORT.  CTRL C CLEARS EFFECT OF CTRL S.
; T$$TRW = TRANSPARENT READS AND WRITES
; T$$UTB = WHEN POSSIBLE, RECEIVED CHARACTERS ARE PUT DIRECTLY INTO THE
;	   TASK'S BUFFER
; T$$VBF = VARIABLE LENGTH BUFFERS (FROM 1 BYTE TO 255.) ARE USED BY THE
;	   DR      IVER
; T$$30P = ONE CHARACTER SOFTWARE BUFFERING OF RECEIVED CHARACTERS
;	   (NEEDED ONLY BY LA30P'S BECAUSE THEIR INTERFACES ARE NOT
;	   HARDWARE DOUBLE BUFFERED).
;-

	.IIF NE	UIFP-200,	.ERROR	UIFP

1$:	TSTB	U.CNT+2+STATS(R5) ;UNSOLICITED INPUT FORK PENDING?
	BMI	2$		;IF MI YES -- WAIT FOR FORK
	MOV	U.SCB(R5),R4	;POINT TO SCB
	CALLR	TINP1		;START UNSOLICITED READ

; NEXT INSTRUCTION DEPENDS ON US.BSY=200

TTINI:	TSTB	U.STS(R5)	;UNIT BUSY?
2$:	BMI	900$		;IF MI YES
	BISB	#US.ECH,U.STS(R5)       ;IGNORE INPUT CHARACTERS
	TSTB	U.CNT+2+INPRQ(R5) ;UNSOLICITED INPUT REQUEST?
	BNE	1$		;IF NE YES
	CALL	$GTPKT		;GET AN I/O PACKET

	.IF DF	T$$MIN

	BCS	28$		;IF CS CONTROLLER BUSY OR NO REQUEST
				;SO CLEAR ECHO-IN-PROGRESS AND EXIT

	.IFF

	BCS	9$		;IF CS CONTROLLER BUSY OR NO REQUEST
				; SO CLEAR ECHO-IN-PROGRESS AND EXIT

	.ENDC

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROL      LER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER (UNIT) TO BE INITIATED.
;
; TERMINAL I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
;	WD. 06 --       VIRUTAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCATION BIAS OF I/O BUFFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- CARRIAGE CONTROL BYTE.
;	WD. 16 -- RELOCATION BIAS OF PROMPT.
;	WD. 17 -- BUFFER ADDRESS OF PROMPT.
;	WD. 20 -- NUMBER OF BYTES IN PROMPT.
;	WD. 21       -- CARRIAGE CONTROL BYTE FOR PROMPT.
;


	MOV	R5,R3		  ;CALCULATE ADDRESS OF
	ADD	#U.CNT+2+STATS,R3 ;STATUS WORD

	.IF DF	D$$M11&D$$H11!D$$ZMD

	MOV	#IE.DNR&377,R0	;ASSUME TERMINAL DISABLED
	BITB	#US.DSB,U.STS(R5) ;UNIT DISABLED?

	.IF DF	T$$CCA&A$$TRP!T$$ESC

	BEQ	3$		;IF EQ NO
	CMPB	#IO.DET/400,I.FCN+1(R1) ;DETACH FUNCTION?
	BNE	5$		        ;IF NE NO
	MOV	#IS.SUC&377,R0	;THE DETACH WILL SUCCEED
	BR	301$		;

	.IFF

	BNE	5$		;IF NE YES

	.ENDC

	.ENDC

3$:	CMPB	#IO.WLB/400,I.FCN      +1(R1) ;WRITE LOGICAL BLOCK FUNCTION?

	.IF DF	T$$MIN

	BEQ	30$		;IF EQ YES

	.IFF

	BEQ	8$		;IF EQ YES

	.ENDC

	BIC	#CTLO,(R3)	;ENABLE OUTPUT
	MOV	#IS.SUC&377,R0	;ASSUME A HAPPY ENDING

	.IF DF	T$$CCA&A$$TRP&T$$ESC

	CMPB	#IO.ATT/400,I.FCN+1(R1) ;ATTACH FUNCTION?
	BNE	300$		;IF NE NO
	BITB	#TF.ESQ,I.FCN(R1) ;WANT ESCAPE SEQUENCE SUBFUNCTION?
	BEQ	3000$		;IF EQ NO
	BIS	#WESC,ATERS(R3)	;SHOW WANT ESCAPE SEQUENCES
3000$:	BITB	#TF.AST,I.FCN(R1) ;WANT UNSOLICITED CHAR AST'S?
	BNE	1900$		      ;IF NE YES

	.IFF

	.IF DF	T$$CCA&A$$TRP

	CMP	#IO.ATT!TF.AST,I.FCN(R1) ;UNSOLICITED INPUT AST ATTACH?
	BEQ	1900$		;IF EQ YES

	.ENDC

	.IF DF	T$$ESC

	CMP	#IO.ATT!TF.ESQ,I.FCN(R1) ;ATTACH WITH ESCAPE SEQUENCES?
	BNE	300$		;IF NE NO
	BIS	#WESC,ATERS(R3)	;REMEMBER THAT THEY ARE WANTED

	.ENDC

	.ENDC			; DF T$$CCA&A$$TRP&T$$ESC

300$:				;REF LABEL

	.IF DF	T$$RPR

	CMPB	#IO.RPR/400,I.FCN+1(R1) ;READ AFTER PROMPT?
	BEQ	1920$		;IF EQ YES

	.ENDC

	.IF DF	T$$GMC!T$$GTS!T$$SMC

	      CMPB	#IO.GTS/400,I.FCN+1(R1) ;SET/GET CHARACTERISTICS?
	BEQ	1889$		;IF EQ YES

	.ENDC

	.IF DF	T$$CCA&A$$TRP!T$$ESC

	CMPB	#IO.DET/400,I.FCN+1(R1) ;DETACH?
	BNE	302$		;IF NE NO
301$:	BIC	#CCON!WESC,ATERS(R3) ;SHOW NO CONTROL C AST ACTION
				; AND NO DESIRE FOR ESCAPE SEQUENCES
	BR	5$		;LEAVE SUCCESSFUL
302$:				;REF LABEL

	.ENDC

	CMPB	#IO.RLB/400,I.FCN+1(R1) ;READ LOGICAL BLOCK FUNCTION?
304$:	BNE	5$		;IF NE NO
305$:				;REF LABEL

	.IF DF	T$$TRW

	BITB	#TF.RAL,I.FCN(R1) ;READ ALL?      
	BEQ	306$		;IF EQ NO
	BISB	#SS.RAL,S.STS(R4) ;REMEMBER READING ALL
306$:				;REF LABEL

	.ENDC

	.IF DF	T$$RST

	BITB	#TF.RST,I.FCN(R1) ;READ WITH SPECIAL TERMINATORS?
	BEQ	4$		;IF EQ NO
	BISB	#SS.RST,S.STS(R4) ;SET SPECIAL TERMINATOR FLAG
4$:				;REF LABEL

	.ENDC

	.IF DF	T$$RNE

	BIT	#U2.NEC,U.CW2(R5) ;TERMINAL IN NO ECHO MODE?
	BNE	400$		;IF NE YES
	BITB	#TF.RNE,I.FCN(R1) ;THIS READ WITH NO ECHO?
	BEQ	401$		;IF EQ NO
400$:	BISB	#SS.RNE,S.STS(R4) ;REMEMBER READING WITH NO ECHO
401$      :				;REF LABEL

	.ENDC

										;**-1
	.IF DF	DFCKP								;TMM011
										;**-1
										;TMM011
	.IF DF	T$$RPR								;TMM011
										;TMM011
	TST	ATERS(R3)	;READ AFTER PROMPT				;TMM011
	BPL	402$		;IF PL NO					;TMM011
	MOV	I.PRM+16(R1),-(SP) ;SAVE PROMPT VFC				;TMM011
402$:										;TMM011
	.ENDC	;T$$RPR								;TMM011
										;TMM011
	MOV	R1,R3		;COPY ADDRESS OF START OF I/O PACKET		;TMM011
	CALL	$TSTBF		;CAN I/O BUFFERING BE INITIATED?		;TMM011
	BCC	403$		;IF CC YES					;      TMM011
	BIS	#NCKP,ATERS+U.CNT+2(R5) ;REMEMBER AS NONCHECKPOINTABLE		;TMM011
										;**-5
	.ENDC		;DF DFCKP						;TMM011
										;TMM011
	.IF DF	T$$UTB								;TMM011
										;TMM011
	MOV	U.BUF+2(R5),R0	;MAKE INPINI SET UCB TO POINT			;**-2
	CALL	INPINI		; AT TASK'S BUFFER
	BR	10$		;

	.ENDC			; DF T$$UTB

;
; REQUEST IS A SOLICITED INPUT REQUEST-GET A BUFFER FOR INPUT
;

403$:				;REF LABEL

	.IF NDF	T$$UTB!NOEXBF

	.IF DF	T$$VBF

	MOV	U.CNT(R5),R1	;GET HOW MUCH HE WANTS ALLOCA      TED
	ADD	#M$$CRB-M$$CRI,R1 ;EXEC BUFFER IS A BIT LONGER
	CALL	GETBF2		;ALLOCATE EXEC BUFFER

	.IFF

	CALL	GETBF		;GET BUFFER FOR INPUT

	.ENDC

	BCC	10$		;IF CC BUFFER ALLOCATED
	MOV	#IE.NOD&377,R0	;SET NO BUFFER AVAILABLE STATUS

	.IF DF	T$$UTB!T$$RPR

	BIC	#NCKP!RPRM!XOFF,ATERS(R3) ;CLEAR POSSIBLY SET BITS

	.ENDC

	.ENDC			; NDF T$$UTB!NOEXBF

5$:	CALL	$IOALT		;FINISH I/O OPERATION
BTTINI:	BR	TTINI		;TRY AGAIN

	.IF NDF	T$$MIN

8$:	BR	30$		;STRETCH THE BRANCH A BIT
9$:	BR	28$		      ; AND SAVE A WORD

	.ENDC

900$:	RETURN			;

10$:	BIS	#SOLI,(R3)	;SET SOLICITED INPUT FLAG

	.IF DF	T$$RPR

	.IIF NE	RPRM-100000,	.ERROR	RPRM

	TST	ATERS(R3)	;READ AFTER PROMPT?

	.IF DF	D$$YNM&M$$MGE

	BMI	29$		;IF MI YES

	.IFF

	BMI	70$		;IF MI YES

	.ENDC

	.ENDC

	BIT	#CRJT,(R3)	;CARRIAGE RETURN JUST TYPED?


	.IF DF	C$$CKP&T$$BUF

;
; TRY TO CHECKPOINT THE TASK WHILE IT IS WAITING FOR INPUT
;

	CALL	27$		;OUTPUT LF OR CLEAR ECHO-IN-PROGRESS
	MOV	U.SCB(R5),R4	;RETRIE      VE ADDRESS OF SCB
	BIT	#NCKP,ATERS+U.CNT+2(R5)	;BUFFERABLE?				;TMM011
	BNE	900$		;IF NE NO					;TMM011
	MOV	S.PKT(R4),R3	;GET ADDRESS OF I/O PACKET			;TMM011
	CALLR	$INIBF		;INITIATE I/O BUFFERING				;TMM011
				; AND $NXTSK					;**-55

	.ENDC			; DF C$$CKP&T$$BUF

27$:	BNE	55$		;IF NE OUTPUT LINE FEED AND RETURN
28$:				;REF LABEL

	.IF DF	T$$MIN

	.IF DF	T$$BTW

	CALLR	INPT0		;CLEAR ECHO IN PROGRESS AND RETURN

	.IFF

	BR	INPT0		;CLEAR ECHO IN PROGRESS AND RETURN

	.ENDC

	.IFF
      
	CALLR	INPT0		;CLEAR ECHO IN PROGRESS AND RETURN

	.ENDC			; DF T$$MIN

	.IF DF	D$$YNM&M$$MGE&T$$RPR

29$:	BR	70$		;

	.ENDC

;
; REQUEST IS AN OUTPUT REQUEST-SET UP CARRIAGE CONTROL FLAGS
;

30$:	BIC	#LFCT!CRTY!EOLS!RUBP!SOLI!FLCT,(R3) ;CLEAR STATUS WORD
	BIS	#MODE,(R3)	;SET OUTPUT MODE

	.IF DF	T$$BTW

	BITB	#TF.WBT,I.FCN(R1) ;IS THIS A BREAKTHROUGH WRITE?
	BNE	FWRITE		;IF NE YES (LEAVE US.ECH SET TO
				; DISALLOW CONTROL O DURING THE WRITE)

	.ENDC

	CALL	INPT0		;ALLOW INPUT IN      TERRUPTS
FWRITE:				;REF LABEL

	.IF DF	T$$CCO!T$$BTW

	BITB	#TF.CCO,I.FCN(R1) ;TASK WANTS TO CLEAR CONTROL O FLAG?
	BNE	33$		;IF NE YES

	.ENDC

	TST	U.ATT(R5)	;TERMINAL ATTACHED?
	BNE	34$		;IF NE YES
33$:	BIC	#CTLO,(R3)	;STOP SUPPRESSING OUTPUT
34$:				;REF LABEL

	.IF DF	T$$TRW

	BITB	#TF.WAL,I.FCN(R1) ;WRITE ALL?
	BEQ	36$		;IF EQ NO

	.IFF

	BR	36$		;PROCESS CARRIAGE CONTROL

	.ENDC

	.IF DF	T$$RPR!T$$TRW

35$:	BISB	#SS.WAL,S.STS(R4) ;REMEMBER WRITING ALL
	BIC	#CRJT,(R3)	;CL      EAR CR JUST TYPED INDICATOR
	CLRB	HORPS(R3)	;CLEAR HORIZANTAL POSITION INDICATOR
	BR	60$		;SKIP CARRIAGE CONTROL BYTE PROCESSING

	.ENDC

36$:	MOVB	I.PRM+6(R1),R0	;GET CARRIAGE CONTROL BYTE
37$:	BEQ	60$		;IF EQ NO CARRIAGE CONTROL
	CMPB	#'$,R0		;CARRIAGE RETURN AT END OF LINE?
	BEQ	40$		;IF EQ NO
	BIS	#CRTY,(R3)	;SET FOR CARRIAGE RETURN AT END
40$:	CMPB	#'+,R0		;LINE FEED AT START OF LINE?
	BEQ	60$		;IF EQ NO
	CMPB	#'1,R0		;FORM FEED AT BEGINNING OF LINE?
	BNE	50$		;IF NE NO

	.IF DF	T$$HFF      

	BIT	#U2.HFF,U.CW2(R5) ;TERMINAL CAN HANDLE FORM FEED?
	BEQ	48$		;IF EQ NO

	.IIF NE	FLBT-1,		.ERROR	FLBT

	INC	(R3)		;WANT ONE FILL CHARACTER
	MOVB	#14,FLBYT(R3)	;IT IS TO BE A FORM FEED
	BR	60$		;

	.ENDC

48$:	ADD	#LFBT*7,(R3)	;ADD IN SEVEN LINE FEEDS
50$:	ADD	#LFBT,(R3)	;ADD IN ONE LINE FEED
	CMPB	#'0,R0		;DOUBLE SPACE?
	BNE	60$		;IF NE NO
55$:	ADD	#LFBT,(R3)	;ADD IN ONE LINE FEED
60$:	MTPS	S.PRI(R4)	;;;LOCK OUT DEVICE INTERRUPTS
	CALLR	OUTPT1		;;;START OUTPUT

	.IF DF	T$$RPR

;      
; IF NECESSARY, COPY THE PROMPT TO AN EXECUTIVE BUFFER SO THE
; TASK CAN BE CHECKPOINTED FOR BOTH THE PROMPT WRITE AND THE
; FOLLOWING READ.
;

70$:	BIC	#CTLO,(R3)	;CLEAR CONTROL O FLAG
	MOV	S.PKT(R4),R1	;FIND START OF I/O PACKET
	ADD	#I.PRM+4,R1	;POINT AT READ BUFFER LENGTH
	CMP	(R1),U.CNT(R5)	;READ LARGER THAN OUR BUFFER?
	BHIS	72$		;IS HIS UCB PROPERLY SETUP FOR READ
	MOV	(R1),U.CNT(R5)	;RESTORE COUNT OF CHARS TO BE READ
	MOVB	(R1),RMBYT(R3)	;CORRECT COUNT OF BYTES LEFT IN READ BUF
72$:	CMP	      (R1)+,(R1)+	;POINT AT 1ST WORD OF ADDR DOUBLE WORD

	.IF DF	C$$CKP&T$$BUF

										;**-1
	.IFF

	MOV	I.PRM+16-I.PRM-10(R1),R0 ;PUT PROMPT WHERE IT'S EXPECTED

										;**-7
	.IFT

	BIT	#NCKP,ATERS(R3)	;CHECKPOINTABLE?				;TMM011
	BNE	78$		;IF NE NO					;**-3

	.IF DF	M$$MGE

	MOV	(R1)+,@#KISAR6	;MAP TO PROMPT (WRITE) BUFFER

	.IFF

	TST	(R1)+		;POINT AT PROMPT BUFFER ADDRESS

	.ENDC

	MOV	STRBF(R3),R2	;POINT AT EXEC READ BUFFER
	MOV	(R1),R0		;POINT AT PROMPT BUFFER
	MOV	R2,(R1      )+	;PUT EXEC BUFFER ADDRESS IN I/O PACKET
	MOV	(R1),-(SP)	;SAVE LENGTH OF PROMPT
75$:	MOVB	(R0)+,(R2)+	;COPY PROMPT TO EXEC BUFFER
	DEC	(SP)		;DONE?
	BGT	75$		;IF GT NO
	MOV	R3,(SP)		;SAVE R3
	MOV	S.PKT(R4),R3	;GET I/O PACKET ADDRESS				;TMM011
	CALL	$INIBF		;INITIATE BUFFERING				;TMM011
	MOV	(SP)+,R3	;RESTORE R3					;**-4
78$:	MOV	(SP)+,R0	;RETRIEVE PROMPT VFC

	.ENDC			; DF C$$CKP&T$$BUF

	MOV	S.PKT(R4),R1	;POINT AT I/O PACKET
	BITB	#TF.BIN,I.FCN(R1) ;WRITE ALL PROMPT?
	BNE	35$		;IF NE YES      
	MOV	R0,R0		;SET CONDITION BITS
	BR	37$		;INTERPRET PROMPT VFC

	.ENDC			; DF T$$RPR

	.DSABL	LSB
	.SBTTL	OUTPUT-NEXT-BYTE ROUTINE

	.ENABL	LSB

	.IF DF	T$$RPR

;
; WRITE OUT THE PROMPT OF AN IO.RPR
;

57$:	MOV	S.PKT(R4),R4	;;;FIND START OF I/O PACKET
	BIT	#CTLO,(R3)	;;;CONTROL/O IN MIDDLE OF PROMPT?
	BNE	5704$		;;;IF NE YES
	DEC	I.PRM+14(R4)	;;;DONE PROMPTING?
	BMI	5702$		;;;IF MI YES

	.IF DF	M$$MGE

	MOV	@#KISAR6,-(SP)	;;;SAVE EXECUTIVE MAPPING
	MOV	I.PRM+10(R4),@#KISAR6 ;;;MA      P TO PROMPT BUFFER
	MOVB	@I.PRM+12(R4),-(SP) ;;;GET NEXT BYTE OF PROMPT

	.IFF

	MOVB	@I.PRM+12(R4),-(SP) ;;;GET NEXT BYTE OF PROMPT

	.IFTF

	INC	I.PRM+12(R4)	;;;POINT AT ITS SUCCESSOR

	.IFT

	MOV	2(SP),@#KISAR6	;;;RESTORE EXECUTIVE MAPPING
	MOV	(SP)+,(SP)	;;;LEAVE PROMPT BYTE ON STACK

	.ENDC			;;; DF M$$MGE

	MOV	U.SCB(R5),R4	;;;RESTORE R4
	CALL	INPT0		;;;ALLOW CONTROL Q, S, AND O INPUT
				;;; (REDUNDANT AFTER FIRST CLEARING)
	BR	5703$		;;;TRANSMIT THE PROMPT CHARACTER
5702$:	BIT	      #CRTY,(R3)	;;;CARRIAGE RETURN AFTER PROMPT?
	BEQ	5704$		;;;IF EQ NO
	MOV	U.SCB(R5),R4	;;;RESTORE POINTER TO SCB
	MOV	#15,-(SP)	;;;TRANSMIT A CARRIAGE RETURN
	BIC	#CRTY,(R3)	;;;CLEAR WANT CARRIAGE RETURN FLAG

	.IF DF	T$$BTW&T$$30P

5703$:	JMP	ECHOB		;;;

	.IFF

5703$:	BR	BECHOB		;;;

	.ENDC

5704$:	BIC	#RPRM,ATERS(R3)	;;;CLEAR PROMPTING FLAG
	MOVB	#IO.RLB/400,I.FCN+1(R4) ;;;CONVERT IO.RPR TO IO.RLB
	MOV	U.SCB(R5),R4	;;;RESTORE POINTER TO SCB
	RETURN			;;;

	.IF DF	T$$BTW

5705$:	BR	57      $		;;;

	.ENDC

	.ENDC			;;; DF T$$RPR

	.IF DF	T$$30P

;
; TRANSMITTER NOT BUSY ECHOING, SO PROCESS CHARACTER THAT WAS
; RECEIVED (AND BUFFERED IN SOFTWARE), BUT NOT ECHOED.
;

5708$:	BIC	#CHAR,ATERS(R3)	;;;CLEAR FLAG
	CLR	-(SP)		;;;CLEAR UPPER BYTE OF STACK
	MOVB	MBUFR(R3),(SP)	;;;RETRIEVE INPUT CHARACTER
	JMP	RESUME		;;;PROCESS THE CHARACTER

	.ENDC

	.IF DF	T$$BTW

;
; RESTORE THE SCB AND UCB ENVIRONMENT FOR AN UNSOLICITED READ
; DISPLACED BY AN IO.WBT
;

5710$:	MOVB	#1,S.STS(      R4)	;LINE WAS ONLY BUSY
	CLR	(R3)+		;CLEAR U.BUF (BUFFER IS IN EXEC SPACE)
	MOV	U.CNT+2+CURBF(R5),(R3)+ ;RESTORE U.BUF+2

; NEXT INSTRUCTION DEPENDS ON STRBF=U.CNT+4

	CMP	(R3)+,(R3)+	;POINT AT STRBF
	MOV	(R3),-(SP)	;FORM POINTER TO SAVED STATS
	SUB	#1*2,(SP)	;
	MOV	@(SP)+,-(R3)	;RESTORE STATS
	BR	5800$		;FINISH WITH A FLOURISH

;
; RESTORE THE SCB AND UCB ENVIRONMENT OF THE READ DISPLACED
; BY AN IO.WBT
;

58$:	MOV	U.SCB(R5),R4	;RESTORE R4
	BISB	#US.BSY,U.STS(R5) ;REBUSY LINE
	BIC	#BTWP,      U.CNT+2+ATERS(R5) ;CLEAR BREAKTHROUGH FLAG
	MOV	R5,R3		;POINT AT U.BUF
	ADD	#U.BUF,R3	;
	MOV	U.CNT+2+STATS(R5),R1 ;RETRIEVE READ'S I/O PACKET POINTER
	BEQ	5710$		;IF EQ BROKE THROUGH UNSOLICITED READ
	MOVB	(R1),S.STS(R4)	;RESTORE SCB STATUS
	MOV	R1,S.PKT(R4)	;MAKE THE READ THE CURRENT OPERATION
	ADD	#I.PRM+6,R1	;POINT AT THE READ'S SAVED UCB INFO
	MOV	(R1)+,(R3)+	;RESTORE U.BUF
	MOV	(R1)+,(R3)+	;RESTORE U.BUF+2
	MOV	(R1)+,(R3)+	;RESTORE U.CNT

; NEXT INSTRUCTION DEPENDS ON STATS=U.CNT+2

	MOV	      (R1)+,(R3)	;RETRIEVE TERMINAL STATUS
	CMPB	#IE.ABO,FNBYT(R3) ;CANCEL THE DISPLACED READ?
	BNE	5800$		;IF NE NO
	JMP	INPT2		;TERMINATE READ
5800$:	MTPS	S.PRI(R4)	;RAISE PRIORITY FOR FAKE CONTROL R
	CLR	-(SP)		;;;FAKE A CONTROL R
	JMP	CTRLR		;;;

	.ENDC

;
; OUTPT - START OR CONTINUE AN OUTPUT STREAM
;
; AT ENTRY:
;	R5 -> UCB
;	R4 -> SCB
;	R3 -> TCB (UCB + #U.CNT+2)
;	INTERRUPT PRIORITY = THAT OF OUTPUT DEVICE
;
; EXITS VIA RETURN AFTER OUTPUTTING ANOTHER CHARACTER OR THROUGH
; $FORK AT 20      $ IF THERE ARE NO MORE CHARACTERS TO OUTPUT OR THROUGH
; $FORK AT INPT1 IF THE INPUT LINE IS COMPLETE (THE OUTPUT
; INTERRUPT IS FROM A CHARACTER ECHO).
;

OUTPT:				;;;REF LABEL

	.IF DF	T$$30P

	BIC	#ECHO,ATERS(R3)	;;;CLEAR ECHOING BIT

	.ENDC

	.IF DF	T$$HLD

	BIT	#BAKS,ATERS(R3)	;;;CLEARING HOLD-SCREEN MODE?
	BEQ	2$		;;;IF EQ NO
XITHSM:	MOVB	@MEBUF(R3),-(SP) ;;;GET NEXT BYTE OF "ESC \"
	BNE	5300$		;;;IF NE HAVE ANOTHER BYTE TO SEND
	BIC	#BAKS,ATERS(R3)	;;;CLEAR FLAG
	TST	(SP)+		;;;TH      ROW AWAY TERMINATING BYTE
2$:				;;;REF LABEL

	.ENDC

	.IF DF	T$$SYN!T$$HLD

	BIT	#CCPN,ATERS(R3)	;;;CONTROL C PENDING?
	BEQ	2002$		;;;IF EQ NO
	BIC	#CCPN,ATERS(R3)	;;;CLEAR FLAG
	TSTB	S.STS(R4)	;;;IS CONTROL C GOING TO BE PROCESSED
				;;; IMMEDIATELY?
	BEQ	2000$		;;;IF EQ YES

	.IIF NE	MODE-100000,	.ERROR	MODE

	TST	(R3)		;;;BUSY ON INPUT?
	BPL	2000$		;;;IF PL YES
	MOV	#2002$,-(SP)	;;;SETUP SO NEXT RETURN IS TO 2002$,
				;;; WHICH PROPAGATES THE RENEWED OUTPUT
2000$:	MOV	#3,-(SP)	;;;      FAKE A RECEIVED CONTROL C
	JMP	DOCTLC		;;;EVALUATE IT
2002$:				;;;REF LABEL

	.ENDC

	.IF DF	T$$30P

	BIT	#CHAR,ATERS(R3)	;;;HAVE AN INPUT CHAR TO PROCESS?
	BNE	5708$		;;;IF NE YES

	.ENDC

OUTPT1:	BIT	#FLCT,(R3)	;;;SHOULD A FILL BE ECHOED?
	BNE	60$		;;;IF NE YES
	BIT	#LFCT,(R3)	;;;ANY UNPROCESSED LINE FEEDS?
	BNE	40$		;;;IF NE YES
	MOVB	@MEBUF(R3),-(SP);;;MULTI-ECHO SEQUENCE IN PROGRESS?
	BNE	50$		;;;IF NE YES
3$:	TST	(SP)+		;;;NO - REMOVE ZERO CHAR FROM STACK

	.IF DF	T$$BTW!T$$CTR
      
	MOV	#CTRLU-1,MEBUF(R3) ;;;POINT AT ZERO THAT WON'T DISAPPEAR

	.ENDC

	.IF DF	T$$RPR

	.IIF NE	RPRM-100000,	.ERROR	RPRM

	TST	ATERS(R3)	;;;WRITING A PROMPT?

	.IF DF	T$$BTW

	BMI	5705$		;;;IF MI YES

	.IFF

	BMI	57$		;;;IF MI YES

	.ENDC

	.ENDC			;;; DF T$$RPR

	.IIF NE	MODE-100000,	.ERROR	MODE

	TST	(R3)		;;;INPUT OR OUTPUT IN PROGRESS?
	BPL	INPPT		;;;IF PL INPUT

;
; OUTPUT REQUEST IN PROGRESS
;

	BIT	#EOLS!CTLO,(R3)	;;;END OF LINE SEEN OR OUTPUT DISABLED?
	BNE	20$		;;;      IF NE YES
	DEC	U.CNT(R5)	;;;DECREMENT BYTE COUNT
	BMI	10$		;;;IF MI CHECK CARRIAGE CONTROL
	CALL	$GTBYT		;;;GET NEXT BYTE FROM USER BUFFER
BECHOB:	BR	ECHOB		;;;ECHO NEXT BYTE

	.IF DF	T$$BTW

9$:	BR	58$		;

	.ENDC

10$:	MOVB	#15,-(SP)	;;;ASSUME TRAILING CARRIAGE RETURN REQUIRED
	BIS	#EOLS,(R3)	;;;SET END OF LINE SEEN
	BIT	#CRTY,(R3)	;;;OUTPUT TRAILING CARRIAGE RETURN?
	BNE	ECHOB		;;;IF NE YES
	TST	(SP)+		;;;CLEAN STACK

;
; FINISHED AN OUTPUT REQUEST.  WANT TO RETURN STATUS.
;

20$:	CA      LL	$FORK		;;;CREATE A SYSTEM PROCESS AND RETURN
	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS
	BR	55$		;SEE IF ERROR OR SUCCESS

;
; ECHO LINE FEED
;

40$:	SUB	#LFBT,(R3)	;;;REDUCE LINE FEED COUNT
	MOVB	#12,-(SP)	;;;SET TO ECHO LINE FEED
	BR	ECHOB		;;;ECHO BYTE

;
; MULTI-ECHO SEQUENCE
;

50$:				;;;REF LABEL

	.IF DF	T$$BTW!T$$CTR&T$$UTB&M$$MGE

	BIT	#MCTR,ATERS(R3)	;;;CONTROL/R INPUT IN TASK'S BUFFER?
	BEQ	53$		;;;IF EQ NO

;
; DOING CONTROL R FOR A TASK THAT HAS THE INPUT       STRING IN ITS
; ADDRESS SPACE.  TRY HARDER.
;

	CALL	$GTBYT		;;;PUT NEXT BYTE ON STACK
	MOVB	(SP)+,(SP)	;;;COLLAPSE STACK
	BNE	ECHOB		;;;IF NE SOMETHING TO TRANSMIT
	DEC	U.BUF+2(R5)	;;;POINT AT POSITION TO STORE NEXT
				;;; INPUT CHARACTER
	BIC	#MCTR,ATERS(R3)	;;;CLEAR FLAG
	BR	3$		;;;DO NORMAL COMPLETION
53$:				;;;REF LABEL

	.ENDC

5300$:	INC	MEBUF(R3)	;;;INCREMENT BUFFER ADDRESS
	BR	ECHOB		;;;ECHO BYTE ON STACK

;
; TERMINAL TIMEOUT-FINISH I/O OPERATION
; ENTERED ON FORK LEVEL WITH       TERMINAL CONTROLLER ALREADY RESET
;

TTOUT1:	CMPB	#IE.ABO,U.CNT+2+FNBYT(R5) ;TIMEOUT OR CANCEL?
	BEQ	54$		;IF EQ CANCEL
	MOVB	R0,U.CNT+2+FNBYT(R5) ;REMEMBER TIMEOUT STATUS
54$:				;REF LABEL

	.IF DF	T$$BTW!T$$CTR

	MOV	#CTRLU-1,U.CNT+2+MEBUF(R5) ;POINT AT A ZERO BYTE

	.IF DF	T$$UTB&M$$MGE

	BIC	#MCTR,U.CNT+2+ATERS(R5) ;CLEAR SPECIAL CONTROL R FLAG

	.ENDC

	.ENDC

	.IIF NE	MODE-100000,	.ERROR	MODE

	TST	U.CNT+2+STATS(R5) ;INPUT OR OUTPUT IN PROGRESS?

	.IF DF	T$$MIN

	.IF DF	T$$B      TW

	BPL	INPT22		;IF PL INPUT

	.IFF

	BPL	INPT2		;IF PL INPUT

	.ENDC

	.IFF

	BPL	INPT22		;IF PL INPUT

	.ENDC

55$:	MOV	S.PKT(R4),R1	;POINT AT COMPLETED OUTPUT I/O PACKET
	MOV	I.PRM+4(R1),R1	;GET BYTES IT WANTED TRANSFERED
	BIT	#CTLO,U.CNT+2+STATS(R5) ;TERMINATION BY CONTROL O
				; OR EOLS?
	BNE	56$		;IF NE CONTROL O
	MOV	U.CNT(R5),R2	;SAVE BYTES LEFT TO TRANSFER
	BMI	56$		;IF MI DID THE ENTIRE WRITE
	SUB	R2,R1		;CALCULATE BYTES NOT TRANSFERED
	MOV	U.CNT+2+FNBYT-1(R5),R0 ;GET REA      SON FOR PARTIAL TRANSFER
	CLRB	R0		;CHANGE INTO IOSB
	SWAB	R0		;
56$:				;REF LABEL

	.IF DF	T$$BTW

	BIT	#BTWP,U.CNT+2+ATERS(R5) ;DID A BREAKTHROUGH WRITE?
	BEQ	IODON		;IF EQ NO
	MOV	S.PKT(R4),R2	;POINT AT I/O PACKET FOR WRITE
	MOV	I.PRM+16(R2),U.CNT+2+STATS(R5) ;SAVE DISPLACED READ'S
				; I/O PACKET ADDRESS IN THE UCB

	.IF DF	R$$LKL

	CLR	I.PRM+16(R2)	;MAKE LOCKING WORD ZERO AGAIN

	.ENDC

	.IFTF

IODON:	CALL	$IODON		;FINISH I/O OPERATION

	.IFT

	BIT	#BTWP,U.CNT+2+ATERS(R5) ;DI      D A BREAKTHROUGH WRITE?
	BNE	9$		;IF NE YES

	.ENDC

	.IF DF	T$$MIN

	.IF DF	T$$BTW

	JMP	TTINI		;GO AGAIN

	.IFF

	BR	BTTINI		;GO AGAIN

	.ENDC

	.IFF

	JMP	TTINI		;GO AGAIN

	.ENDC

;
; INPUT REQUEST IN PROGRESS
;

INPPT:	BIT	#EOLS,(R3)	;;;END OF LINE SEEN?

	.IF NDF	T$$MIN

	BNE	INPT11		;;;IF NE YES

	.IFF

	BNE	INPT1		;;;IF NE YES

	.ENDC

INPT0:	BICB	#US.ECH,U.STS(R5) ;;;ENABLE INPUT CHARACTER HANDLING
	RETURN			;;;

;
; ECHO FILL BYTE
;

	.IIF NE	FLBT-1,		      .ERROR	FLBT

60$:	DEC	(R3)		;;;DECREMENT FILL COUNT
	MOVB	FLBYT(R3),-(SP)	;;;SET TO ECHO FILL BYTE
				;;;FALL INTO CODE TO ECHO BYTE

	.DSABL	LSB

;
; ECHO NEXT BYTE
;

	.ENABL	LSB

ECHOB:				;;;REF LABEL

	.IF DF	T$$TRW

	BITB	#SS.WAL,S.STS(R4) ;;;WRITE PASS ALL?
	BNE	ECHB11		;;; IF NE YES					;TMM036
										;**-1
	.ENDC

;
; CHECK IF OUTPUT CHARACTER HAS SPECIAL SIGNIFICANCE
;

	CMPB	(SP),#37	;;;IS THIS A CONTROL CHARACTER?
	BHI	70$		;;;IF HI NO
	CMPB	#15,(SP)	;;;CARRIAGE       RETURN?
	BEQ	10$		;;;IF EQ YES
	CMPB	#14,(SP)	;;;FORM FEED?
	BEQ	30$		;;;IF EQ YES
	CMPB	#13,(SP)	;;;VERTICAL TAB?
	BEQ	40$		;;;IF EQ YES
	CMPB	#12,(SP)	;;;LINE FEED?
	BEQ	50$		;;;IF EQ YES
	CMPB	#11,(SP)	;;;HORIZONTAL TAB?
	BNE	79$		;;;IF NE NO

;
; HORIZONTAL TAB
;

	MOVB	HORPS(R3),(SP)	;;;GET CURRENT HORIZONTAL POSITION
	BIS	#177770,(SP)	;;;CALCULATE BLANK COUNT TO NEXT TAB STOP
	SUB	(SP),(R3)	;;;MERGE BLANK COUNT
	MOVB	#' ,FLBYT(R3)	;;;SET FILL TO A BLANK
5$:	TST	(SP)+		;;;REMOVE BYTE       FROM STACK

	.IF DF	T$$MIN

	.IF DF	T$$BTW

	JMP	OUTPT1		;;;START OUTPUT

	.IFF

	BR	OUTPT1		;;;START OUTPUT

	.ENDC

	.IFF

	JMP	OUTPT1		;;;START OUTPUT

	.ENDC

;
; CARRIAGE RETURN
;

10$:	BIS	#CRJT+FLBT,(R3)	;;;SET CR JUST TYPED AND FORCE 1 FILL
	BIT	#U2.L3S,U.CW2(R5) ;;;LA30S?
	BEQ	20$		;;;IF EQ NO
	CLR	-(SP)		;;;PICKUP CURRENT HORIZONAL POSITION
	BISB	HORPS(R3),(SP)	;;;

	.IF DF	T$$ACR

14$:	SUB	U.CW4(R5),(SP)	;;;REDUCE THE LOGICAL HORIZONTAL
	BGT	14$		;;; POSITION TO       THE PHYSICAL POSITION
	ADD	U.CW4(R5),(SP)	;;; (BETWEEN 0 AND 80).

	.IFTF

	ASR	(SP)		;;;DIVIDE POSITION BY 8.
	ASR	(SP)		;;;
	ASR	(SP)		;;;
	ADD	#FILTB,(SP)	;;;CALCULATE ADDRESS OF FILL TABLE ENTRY
	MOVB	@(SP)+,-(SP)	;;;GET CORRECT FILL COUNT
	BIC	#^C<17>,(SP)	;;;CLEAR EXTRANEOUS BITS ON WIDE CARRIAGE
	ADD	(SP)+,(R3)	;;;SET PROPER FILL COUNT
20$:				;;;REF LABEL

	.IFT

	BIT	#FKCR,ATERS(R3)	;;;FAKE CARRIAGE RETURN?
	BNE	60$		;;;IF NE YES -- NOT A NEW LINE

	.ENDC

27$:	CLRB	HORPS(R3)	;      ;;CLEAR HORIZONTAL POSITION
	BR	60$		;;;OUTPUT CARRIAGE RETURN

;
; FORM FEED
;

30$:				;;;REF LABEL

	.IF DF	T$$HFF

	BIT	#U2.HFF,U.CW2(R5) ;;;TERMINAL CAN HANDLE FORM FEED?
	BNE	27$		  ;;;IF NE YES

	.ENDC

	ADD	#LFBT*4,(R3)	;;;ADD IN FOUR LINE FEEDS

;
; VERTICAL TAB
;

40$:	ADD	#LFBT*4,(R3)	;;;ADD IN FOUR LINE FEEDS
	BR	5$		;;;GO BACK TO THE TOP TO PRINT THEM

	.IF NDF	T$$MIN

INPT22:	BR	INPT2		;;;
INPT11:	BR	INPT1		;;;

	.ENDC

										;TMM036
	.IF DF	T$$TRW								;      TMM036
										;TMM036
ECHB11:	BR	ECHOB1		;;;						;TMM036
										;TMM036
	.ENDC									;TMM036
										;TMM036
;
; LINE FEED
;

50$:	BIC	#CRJT,(R3)	;;;CLEAR CARRIAGE RETURN JUST TYPED
										; EB268
	.IF DF	PASSLF								; EB268
										; EB268
	BIT	#U2.HFF,U.CW2(R5) ;;;TREAT LF LIKE FF?				; EB268
	BNE	27$		  ;;;IF NE YES					; EB268
										; EB268
	.ENDC									; EB268
	BIT	#U2.VT5,U.CW2(R5) ;;;VT05B?
	BEQ	80$		;;;IF EQ NO

	.IF DF	L$$50H

	ADD	#FLBT*4,(R3)	;;;SET       FILL COUNT TO 4

	.IFF

	ADD	#FLBT*3,(R3)	;;;SET FILL COUNT TO 3

	.ENDC

60$:	CLRB	FLBYT(R3)	;;;SET NULL FILL BYTE
	BR	80$		;;;

	.IF DF	T$$MIN&T$$BTW

INPT22:	BR	INPT2		;;;

	.ENDC

;
; BYTE REQUIRES HORIZONTAL POSITION
;

70$:	BIC	#CRJT,(R3)	;;;CLEAR CARRIAGE RETURN JUST TYPED		;TMM036
	CMPB	(SP),#172	;;;IS THIS A LOWER CASE ALPHABETIC?		;TMM036
	BHI	71$		;;;IF HI NO ALSO NOT A SPECIAL CHAR		;TMM036
	CMPB	(SP),#141	;;;UPPER CASE OR CONTROL CHARACTER?		;TMM036
	BLO	71$		;;;IF LO Y      ES					;TMM036
	BIT	#U3.UPC,U.CW3(R5) ;;; IS THIS AN ASR33?				;TMM036
	BEQ	71$		;;; IF EQ NO, ALLOW LOWERCASE OUTPUT		;TMM036
	BIC	#40,(SP)	;;;CONVERT LOWERCASE TO UPPER CASE		;TMM036
71$:				;;;REF LABEL					;TMM036
	TSTB	(SP)		;;;BYPASS HORIZONAL POSITION CHECK?		;**-1
	BMI	80$		;;;IF MI YES

	.IF NDF	T$$ACR

;
; SEE IF OUTPUT (OR ECHO) IS OFF SCREEN.  THIS IMPLIES THAT NO MORE
; THAN 255. CHARACTERS CAN BE OUTPUT (TABS ARE EXPANDED INTO BLANKS
; SO THEY COUNT AS MORE THAN ONE CHARACTER) WIT      H ONE NORMAL WRITE.
;

	CMPB	HORPS(R3),U.CW4(R5) ;;;ANY ROOM LEFT?
	BHIS	5$		;;;IF HIS NO

	.IFF

;
; SEE IF LINE MUST BE WRAPPED AROUND SCREEN
;

	BIT	#FKCR,ATERS(R3)	;;;LAST PRINTING CHAR WRAPPED AROUND?
	BNE	75$		;;;IF NE YES -- DON'T TEST FOR WRAP
	CLR	-(SP)		;;;MAKE THE PRESENT HORIZONTAL
	MOVB	HORPS(R3),(SP)	;;; POSITION A WORD
73$:	SUB	U.CW4(R5),(SP)	;;;HORIZONTAL POSITION - BUFFER SIZE
	BGT	73$		;;;IF GT NOT LOGICALLY ON SAME LINE
	TST	(SP)+		;;;ADJUST STACK
	BEQ	90$		;;;IF EQ AT       RIGHT EDGE OF SCREEN
75$:	BIC	#FKCR,ATERS(R3)	;;;CLEAR DISPLAY TRANSITION FLAG

	.ENDC

	INCB	HORPS(R3)	;;;INCREMENT HORIZONTAL POSITION
79$:				;;;REF LABEL

	.IF DF	T$$RUB

	CMPB	#10,(SP)	;;;TRYING TO OUTPUT A BACKSPACE?
	BNE	80$		;;;IF NE NO
	TSTB	HORPS(R3)	;;;SAFE TO BACKUP ON LINE?
	BLE	80$		;;;IF LE NO
	DECB	HORPS(R3)	;;;BACKUP HORIZONTAL POSITION

	.ENDC

	.IIF NE	MODE-100000,	.ERROR	MODE

80$:	TST	(R3)		;;;INPUT MODE?
	BPL	ECHOB1		;;;IF PL YES
	BIT	#CTLO,(R3)	;;;OUTPUT DISABLED      ?
	BNE	5$		;;;IF NE YES
ECHOB1:	CALLR	OCHAR		;;;GO AND OUTPUT THE CHARACTER

	.IF DF	T$$ACR

;
; WRAP LINE AROUND SCREEN (BLOWS TABS EXPANDING AT RIGHT EDGE)
;

90$:	BIS	#FKCR,ATERS(R3)	;;;SIGNAL LINE WRAPPING AROUND SCREEN
	BIT	#FLCT,(R3)	;;;FILLING (DOING A TAB)?
	BEQ	93$		;;;IF EQ NO
	MOV	(R3),-(SP)	;;;CHANGE REMAINING FILL COUNT TO
	BIC	#^C<FLCT>,(SP)	;;; A WORD
	CLR	-(SP)		;;;DO THE SAME FOR HORIZONTAL
	MOVB	HORPS(R3),(SP)	;;; POSITION
	ADD	(SP)+,(SP)	;;;FORM LOGICAL SCREEN POSITION AF      TER
				;;; WRAPAROUND (DISPLAY WILL BE OFF)
	MOVB	(SP)+,HORPS(R3)	;;;SAVE IT.  IF THIS TRUNCATES,
				;;; CONSIDER IT A HINT TO THE USER.
93$:	TSTB	@MEBUF(R3)	;;;DOING MULTI-ECHO?
	BEQ	100$		;;;IF EQ NO

	.IF DF	T$$UTB&M$$MGE

	BIT	#MCTR,ATERS(R3)	;;;DOING CONTROL/R?
	BEQ	95$		;;;IF EQ NO
	INC	U.BUF+2(R5)	;;;SHOW LAST CHAR NOT REMOVED
	BR	96$		;;;
95$:				;;;REF LABEL

	.ENDC

	DEC	MEBUF(R3)	;;;SHOW LAST CHAR NOT REMOVED
96$:	BIS	#LFBT,(R3)	;;;WANT A LINE FEED EVENTUALLY
	MOV	#15,(SP)	;;      ;WANT A CARRIAGE RETURN NEXT
	JMP	10$		;;;						;TMM036
100$:	BIS	#LFBT+FLBT,(R3)	;;;SET UP ONE FILL CHAR AND 1 LF		;**-1
	MOVB	#15,FLBYT(R3)	;;;THE FILL CHAR IS A CR
	CLRB	1(SP)		;;;MAKE SURE BYTE ON STACK IS ASCIZ
	JMP	MECHO1		;;;DEFER OVFLO CHAR TO MULTI-ECHO BUFFER

	.ENDC

	.DSABL	LSB
	.SBTTL	END-OF-INPUT-LINE PROCESSOR

;
; INPT1 - FORK IN ORDER TO FINISH AN INPUT REQUEST
;
; ON ENTRY:
;	R5 -> UCB
;	R4 -> SCB
;	INTERRUPT PRIORITY = THAT OF DEVICE INPUT CAME FROM
;

INPT1:				;;;R      EF LABEL

	.IF DF	T$$RPR

	BIT	#XOFF,ATERS(R3)	;;;SEND XOFF AT READ COMPLETE?
	BEQ	10$		;;;IF EQ NO
	BIC	#XOFF,ATERS(R3)	;;;CLEAR FLAG
	MOV	#23,-(SP)	;;;PUT XOFF ON STACK
	BR	ECHOB1		;;;TRANSMIT IT
10$:				;;;REF LABEL

	.ENDC

	CALL	$FORK		;;;CREATE A SYSTEM PROCESS AND RETURN

	.ENABL	LSB

;
;	END-OF-LINE FORK PROCESS
;

INPT2:	MOV	R5,R3		;CALCULATE ADDRESS OF TERMINAL STATUS WORD
	ADD	#U.CNT+2+STATS,R3 ;
	BIT	#SOLI,(R3)+	;SOLICITED INPUT?
	BNE	20$		;IF NE YES

;
; UNSOLICITED I      NPUT FINISHED
;

	MOVB	FNBYT-2(R3),@CURBF-2(R3) ;SET FINAL BYTE FOR MCR
	MOV	(R3),R1		;GET STARTING ADDRESS OF BUFFER
	MOV	R5,-(R1)	;INSERT ADDRESS OF UCB IN BUFFER
	TST	-(R1)		;POINT TO BEGINNING OF BUFFER
	CALL	$QMCRL		;INSERT BUFFER IN MCR QUEUE
10$:	BICB	#US.BSY,U.STS(R5) ;CLEAR UNIT BUSY
	CLRB	S.STS(R4)	;CLEAR CONTROLLER (UNIT) BUSY
JTTINI:	JMP	TTINI		;GO AGAIN

;
; SOLICITED INPUT FINISHED
;

20$:	MOV	(R3)+,R1	;GET STARTING ADDRESS OF BUFFER
	MOV	U.CNT(R5),-(SP)	;CALCULATE NUMBER OF B      YTES IN INPUT
	SUB	(R3),(SP)	; BUFFER
	MOVB	#IS.SUC&377,(R3) ;ASSUME NORMAL COMPLETION
	CLRB	1(SP)		;MAKE SURE COUNT IS POSITIVE
	MOV	(R3)+,R0	;GET FINAL BYTE (STATUS INDICATION)
	BPL	30$		;IF PL NORMAL TERMINATION
	CLRB	R0		;PUT ERROR STATUS IN LOW BYTE OF
	SWAB	R0		; IOSB AND CLEAR UPPER BYTE

	.IF DF	T$$ESC

	INCB	-(R3)		;FOUND ESCAPE SEQUENCE?
	BNE	30$		;IF NE NO
	MOV	#IS.ESQ,R0	;SHOW AN ESCAPE SEQUENCE IN BUFFER

	.ENDC

30$:				;REF LABEL

;
; SEE IF NECESSARY TO MOVE THE RECEIVED       CHARACTERS FROM THE
; EXECUTIVE BUFFER TO THE TASK BUFFER
;

	MOV	S.PKT(R4),R3	;GET I/O PACKET ADDRESS				;TMM010
	.IF DF	T$$UTB

	.IF DF	C$$CKP&T$$BUF

	BIT	#NCKP,U.CNT+2+ATERS(R5)	;CHARS ALREADY IN TASK BUFFER?
	BEQ	35$		;IF EQ NO
	BIC	#NCKP,U.CNT+2+ATERS(R5)	;CLEAR NOT CHECKPOINTABLE FLAG

	.ENDC

	MOV	(SP)+,R1	;SET NUMBER OF BYTES PROCESSED
										;TMM010
	.IF DF	T$$RPR&R$$LKL							;TMM010
										;TMM010
	CLR	I.PRM+16(R3)	;CLEAR LOCKING WORD				;TMM010
										;TMM010
	.END      C									;TMM010
	CALL	$IODON		;FINISH I/O OPERATION
	BR	JTTINI		;ANYTHING ELSE TO DO?
35$:				;REF LABEL

	.IF DF	M$$MGE

	MOV	R1,U.BUF+2(R5)	;POINT AGAIN AT TASK'S BUFFER

	.ENDC

	.ENDC			; DF T$$UTB

	.IF NDF	T$$UTB!NOEXBF

	.IF DF	C$$CKP&T$$BUF

	MOV	I.TCB(R3),R2	;GET ADDRESS OF REQUESTER TCB			;**-1
	BIT	#NCKP,U.CNT+2+ATERS(R5) ;BUFFERED ?				;TMMO11
	BEQ	80$		;IF EQ YES					;TMMO11
										;**-2
	.IFTF

;
; MOVE CHARACTERS TO TASK'S BUFFER FROM AN EXECUTIVE BUFFER
;

	MO      V	(SP),R3		;SET LOOP COUNT

	.IF DF	M$$MGE

	MOV	U.BUF(R5),@#KISAR6 ;MAP INTO TASK'S SPACE

	.ENDC

	MOV	U.BUF+2(R5),R2	;POINT AT TASK'S BUFFER
50$:	DEC	R3		;ANY MORE BYTES TO MOVE?
	BLT	60$		;IF LT NO
	MOVB	(R1)+,(R2)+	;PUT BYTE IN TASK'S BUFFER
	BR	50$		;

;
; RETURN STATUS TO TASK AND RESOURCES TO EXEC FROM SOLICITED READ
;

60$:										;TMM010
	.IF DF	R$$LKL								;TMM010
										;TMM010
	MOV	S.PKT(R4),R3	;GET I/O PACKET ADDRESS				;TMM010
	CLR	I.PRM+16(R3)	;MAKE LOCKING WORD       ZERO AGAIN			;TMM010
				;POSSIBLY AN RPR PROMPT				;TMM010
	.ENDC	;R$$LKL								;TMM010
										;TMM010
	MOV	(SP)+,R1	;SET NUMBER OF BYTES PROCESSED			;TMM010
	CALL	$IODON		;FINISH I/O OPERATION				;**-1
	MOV	U.CNT+2+STRBF(R5),R0 ;RETRIEVE BUFFER ADDRESS

	.IF DF	T$$VBF

	MOV	-(R0),R1	;GET LENGTH OF BUFFER
	TST	-(R0)		;POINT TO BEGINNING OF BUFFER

	.IFF

	CMP	-(R0),-(R0)	;POINT TO BEGINNING OF BUFFER
	MOV	#M$$CRB,R1	;SET LENGTH OF BUFFER

	.ENDC

	CALL	$DEACB		;DEALLOCATE CORE BLOCK      
	BR	JTTINI		;

	.IFT			; DF C$$CKP&T$$BUF

;
; HAUL THE TASK INTO MEMORY SO THE RECEIVED CHARACTERS CAN BE COPIED
; INTO THE TASK'S BUFFER.  COPYING AND PACKET TERMINATION IS DONE BY
; $FINBF IN SYSXT.
;

80$:	CMP	-(R1),-(R1)	;POINT TO BEGINNING OF BUFFER			;TMM011
	MOV	R1,I.PRM+12(R3)	;SAVE BUFFER ADDRESS				;TMM011
	MOV	(SP)+,R1	;GET SECOND WORD OF STATUS			;TMM011
	CALL	$QUEBF		;KICK OFF KERNAL AST TO COPY BUFFER		;TMM011
				;INTO THE TASK AFTER THE TASK'S CONTEXT		;TMM011
				;HAS BEEN       LOADED.				;TMM011
	BR	10$		;CALL	$NXTSK					;TMM011
	.ENDC			; DF C$$CKP&T$$BUF				;**-24

	.ENDC			; NDF T$$UTB!NOEXBT

	.DSABL	LSB
	.SBTTL	CHARACTER INPUT INTERRUPT PROCESSOR

	.ENABL	LSB

	.IF DF	T$$CCA&A$$TRP

;
; QUEUE AN AST BLOCK FOR AN UNSOLICITED CHARACTER
;

1$:	CALL	INPT0		;CLEAR ECHO IN PROGRESS FLAG
	MOV	#6*2,R1		;LENGTH OF AST BLOCK
	CALL	$ALOCB		;ALLOCATE AN AST BLOCK
	BCS	20$		;IF CS DIDN'T GET ONE
	TST	(R0)+		;SKIP OVER LINK WORD
	MOV	R1,(R0)+	;SAVE SIZE OF AST BLOC      K
	MOV	R0,R1		;SAVE BEGINNING ADDRESS OF
	CMP	-(R1),-(R1)	; AST BLOCK
	MOV	#10*2,(R0)+	;SAVE BYTES TO ALLOCATE ON STACK
	MOV	U.CNT+2+CCAST(R5),(R0)+ ;SAVE AST TRAP ADDRESS
	MOV	#1,(R0)+	;SAVE NUMBER OF AST PARAMETERS
	MOV	(SP)+,(R0)	;UNSOLICITED CHAR IS AST PARAMETER
	MOV	U.ATT(R5),R0	;GET ADDRESS OF TASK'S TCB
	CALL	$QASTT		;INSERT AST BLOCK IN AST QUEUE
	BR	JTTINI		; AND CALL $SETCR

	.ENDC

;
; ICHAR - PROCESS AN INPUT CHARACTER
;
; AT ENTRY:
;	R5 -> UCB
;	R4 -> SCB
;	R3 -> TCB  (UCB +       #U.CNT+2)
;	INTERRUPT PRIORITY = THAT OF INTERRUPTING DEVICE
;
; INPUT CHAR IS ON TOP OF STACK AND PARITY BIT IS CLEARED (UNLESS
; INPUTTING IN READ-PASS-ALL MODE).
; EXIT VIA POPPING CHAR FROM STACK AND RETURNING OR BY
; QUEUING A FORK PROCESS AT INPT1 IF THE INPUT REQUEST IS
; SATISFIED OR BY QUEUING A FORK PROCESS AT TINP1 IF THE INPUT
; IS UNSOLICITED.
;

ICHAR:				;;;REF LABEL

	.IF DF	T$$30P

	BIT	#ECHO,ATERS(R3)	;;;ECHOING A CHARACTER?
	BEQ	3$		;;;IF EQ NO

;
; THE TRANSMITTER IS       BEING USED
; (WHICH IS TO SAY THE TERMINAL IS A LA30P CONNECTED BY A LC11) TO
; ECHO THE LAST CHARACTER.  BUFFER THIS CHAR IN THE SOFTWARE.
;

	MOVB	(SP),MBUFR(R3)	;;;SAVE CHAR IN MULTIECHO BUFFER
	BIS	#CHAR,ATERS(R3)	;;;FLAG INPUT CHAR IN BUFFER
	BR	20$		;;;WORRY ABOUT CHAR WHEN TRANSMITTER
3$:				;;; BECOMES FREE

	.ENDC

	BITB	#US.ECH,U.STS(R5) ;;;INPUT CHARACTERS LOCKED OUT?
	BNE	20$		;;;IF NE YES
DOCTLC:	BISB	#US.ECH,U.STS(R5) ;;;LOCK OUT INPUT CHARACTERS
RESUME:				;;;REF LABEL

	.IF       DF	T$$RPR

	.IIF NE RPRM-100000,	.ERROR	RPRM

	TST	ATERS(R3)	;;;DOING A PROMPT FOR AN IO.RPR?
	BMI	8$		;;;IF MI YES

	.ENDC

	.IF DF	T$$TRW!T$$RST

	.IIF NE	SS.RAL-200,	.ERROR	SS.RAL

	BITB	#SS.RAL!SS.RST,S.STS(R4) ;;;READ PASS ALL OR READ WITH
				;;; SPECIAL TERMINATORS?

	.IF DF	T$$TRW&T$$LWC

	BMI	156$		;;;IF MI READ PASS ALL

	.IF DF	T$$RST

	BNE	155$		;;;IF NE YES

	.ENDC

	.IFF			;;; DF T$$TRW&T$$LWC

	BNE	155$		;;;IF NE YES

	.ENDC			;;; DF T$$TRW&T$$LWC

	.ENDC			;;;       DF T$$TRW!T$$RST

8$:	CMPB	#17,(SP)	;;;CONTROL/O?
	BNE	26$		;;;IF NE NO
	MOV	#CTLO,-(SP)	;;;GET OUTPUT DISABLE BIT
	BIC	(R3),(SP)	;;;.NOT.TERMINAL STATUS.AND.DISABLE BIT
	BIC	#CTLO,(R3)	;;;.NOT.DISABLE BIT.AND.TERMINAL STATUS
	BIS	(SP)+,(R3)	;;;DISABLE BIT.OR.TERMINAL STATUS
10$:	CALL	INPT0		;;;CLEAR ECHO IN PROGRESS

;
; CONTROLLER IS BUSY ON OUTPUT.  IGNORE INPUT REQUEST
;

20$:	TST	(SP)+		;;;REMOVE BYTE FROM STACK
	RETURN			;;;EXIT INTERRUPT
26$:				;;;REF LABEL

	.IF DF	T$$RPR

	.II      F NE	RPRM-100000,	.ERROR	RPRM

	TST	ATERS(R3)	;;;DOING A PROMPT FOR AN IO.RPR?
	BMI	10$		;;;IF MI YES -- IGNORE CHAR IF NOT
				;;; A CONTROL Q, S, OR O

	.ENDC

	TSTB	S.STS(R4)	;;;CONTROLLER (UNIT) BUSY?
	BNE	30$		;;;IF NE YES
27$:				;;;REF LABEL

	.IF DF	T$$CCA&A$$TRP

	BIT	#CCON,ATERS(R3)	;;;CONTROL C AST CODE ACTIVE?
	BNE	140$		;;;IF NE YES -- CHAR CAUSES AST

	.ENDC

; NEXT INSTRUCTION DEPENDS ON U2.SLV=200

	TSTB	U.CW2(R5)	;;;SLAVE TERMINAL?
	BMI	10$		;;;IF MI YES
	CMPB	#3,(SP)      		;;;CONTROL C?
	BEQ	140$		;;;IF EQ YES
	TST	U.ATT(R5)	;;;UNIT ATTACHED?
	BNE	10$		;;;IF NE YES

;
; UNSOLICITED INPUT REQUEST
;

140$:				;;;REF LABEL

	.IF DF	T$$CCA&A$$TRP

	TSTB	INPRQ(R3)	;;;ALREADY WAITING TO FORK?
	BNE	10$		;;;IF NE YES -- IGNORE THIS CHAR
				;;; RATHER THAN THE PRECEDING ONE

	.ENDC

	TSTB	(SP)		;;;IS THE CHARACTER A NULL?
	BEQ	10$		;;;IF EQ YES -- IGNORE IT
	MOVB	(SP),INPRQ(R3)	;;;SAVE BYTE (ALSO UNSOL INP PNDG FLG)
	TSTB	S.STS(R4)	;;;UNIT BUSY ON INPUT OR OUT      PUT
	BNE	10$		;;;IF NE YES -- FORK LATER (TTINI)
	BIS	#UIFP,(R3)	;;;SET UNSOLICITED INPUT FORK PENDING
	TST	(SP)+		;;;REMOVE BYTE FROM STACK
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS AND RETURN

;
; UNSOLICITED INPUT FORK PROCESS
;

TINP1:	MOV	U.CNT+2+INPRQ(R5),-(SP) ;GET INPUT BYTE AND ZERO BYTE
	CLRB	U.CNT+2+INPRQ(R5) ;CLEAR UNSOL INPUT PENDING FLAG
	BIC	#UIFP,U.CNT+2+STATS(R5) ;CLEAR UNSOL INP FORK PEND FLG

	.IF DF	T$$CCA&A$$TRP

	BIT	#CCON,U.CNT+2+ATERS(R5) ;WORRY ABOUT CONTROL C AST'S?
      	BNE	1$		;IF NE YES

	.ENDC

	.IF DF	R$$11S

	TST	$MCRPT		;BASIC MCR AROUND?
	BEQ	10$		;IF EQ NO -- IGNORE CHAR

	.ENDC

	MOV	U.CW4(R5),U.CNT(R5) ;SET NUMBER OF BYTES REQUESTED
	CALL	GETBF		;GET BUFFER FOR INPUT AND SET R3
	BCS	10$		;IF CS DID NOT GET ONE

;
; BUFFER ALLOCATED.  SET CONTROLLER AND UNIT BUSY.
;

	BISB	#US.BSY,U.STS(R5) ;SET UNIT BUSY
	INCB	S.STS(R4)	;SET CONTROLLER BUSY
	BIT	#CRJT,(R3)	;CARRIAGE RETURN JUST TYPED?
	BEQ	150$		;IF EQ NO
	ADD	#LFBT,(R3)	;ADD IN ONE LINE F      EED
150$:	MTPS	S.PRI(R4)	;RAISE PRIO TO ENTER OUTPUT ROUTINES
	CMPB	#3,(SP)		;;;CONTROL C?
	BNE	35$		;;;IF NE NO

	.IF DF M$$CLI

	MOV	U.CLI(R5),(SP)	;;;GET TERMINAL'S CLI POINTER
	ADD	#2,(SP)		;;;POINT TO CLI'S PROMPT STRING

	.IFF	;M$$CLI
										;TMM032
	.IF NDF	A$$CLI								;TMM032

	MOV	#CTRLC,(SP)	;;;SET ADDRESS OF MULTI-ECHO BUFFER
										;TMM032
	.IFF									;TMM032
	MOV	U.MUP(R5),R1	;PICK UP CLI INDEX				;TMM032
	BIC	#^C<UM.CLI>,R1	;AND ONLY THE INDEX				;TMM032
	MOV	$CPTB      L(R1),R1	;GET ADDRESS OF CPB				;TMM032
	ADD	#C.PDPL,R1	;POINT TO DEFAULT PROMPT STRING LENGTH		;TMM032
	CLR	(SP)		;MAKE SURE HIGH BYTE IS ZERO			;TMM032
	MOVB	(R1)+,(SP)	;GET LENGTH OF DEFAULT PROMPT			;TMM032
	TSTB	(R1)+		;ANY CONTROL-C PROMPT?				;TMM032
	BEQ	158$		;IF EQ,NO					;TMM032
	ADD	R1,@SP		;FORM POINTER TO CONTROL-C PROMPT		;TMM032
	BR	180$								;TMM032
158$:	MOV	#CTRLU-1,@SP	;POINT TO A ZERO WHICH WILL NOT DISAPPEAR	;TMM032
	BR	180$								;TMM032
										;TMM032
	.ENDC			;A$$CL      I						;TMM032
										;TMM032

	.ENDC	;M$$CLI

152$:	BR	180$		;;;

	.IF DF	T$$TRW!T$$RST

155$:	JMP	36$		;;;

	.ENDC

	.IF DF	T$$TRW&T$$LWC!T$$ESC

156$:	JMP	37$		;;;

	.ENDC

	.IF NDF	T$$MIN

157$:	BR	10$		;;;

	.ENDC			;;; NDF T$$MIN

;
; CONTROLLER IS BUSY ON INPUT OR OUTPUT
;

	.IIF NE	MODE-100000,	.ERROR	MODE

30$:	TST	(R3)		;;;BUSY ON INPUT?
	BMI	27$		;;;IF MI NO
	CMPB	#3,(SP)		;;;CONTROL C?
	BEQ	27$		;;;IF EQ YES

;
; PROCESS NEXT INPUT BYTE
;

	.IF DF	T$$ES      C

	BIT	#ESCS,ATERS(R3)	;;;IN MIDDLE OF AN ESCAPE SEQUENCE?
	BNE	156$		;;;IF NE YES

	.ENDC

35$:				;;;REF LABEL

	.IF DF	T$$RUB

	CMP	STRBF(R3),CURBF(R3) ;;;THIS IS FIRST CHAR FOR BUFFER?
	BNE	350$		;;;IF NE NO
	MOVB	HORPS(R3),IHORP(R3) ;;;SAVE CURRENT HORIZONTAL POSITION
350$:				;;;REF LABEL

	.ENDC

	.IF DF	T$$CTR

	CMPB	#22,(SP)	;;;CONTROL R?
	BNE	352$		;;;IF NE NO

	.IFF

	.IF DF	T$$BTW

	BR	352$		;;;DO NOT TREAT CHAR AS CONTROL/R

	.ENDC

;
; CONTROL R
;

	.IFTF
      
	.IF DF	T$$BTW

CTRLR:				;;;REF LABEL

	.ENDC

	.IFT

	.IF DF	T$$RNE

	BITB	#SS.RNE,S.STS(R4) ;;;IGNORE CONTROL R IF NO ECHO
	BNE	10$		;;;

	.ENDC

	.ENDC			;;; DF T$$CTR

	.IF DF	T$$BTW!T$$CTR

	BIC	#RUBP,(R3)	;;;NEW LINE=NEW RUBOUT SEQUENCE
	BIS	#LFBT+FLBT,(R3)	;;;WANT 1 FILL CHAR AND 1 LF
	MOVB	#15,FLBYT(R3)	;;;FILL CHAR IS A CR

	.IF DF	T$$UTB&M$$MGE

	CLR	-(SP)		;;;ZERO TO SHOW END OF MULTIECHO
	CALL	$PTBYT		;;;SHOVE AT END OF TASK'S INPUT
	MOV	STRBF(R3),U.BUF+2(R5) ;;;POIN      T AT START OF INPUT
	BIS	#MCTR,ATERS(R3)  ;;;FLAG THE NEED TO MAP MULTIECHO
	MOV	#CTRLU,(SP)	;;;POINT AT A NONZERO BYTE

	.IFF

	CLRB	@CURBF(R3)	;;;SHOW END OF CHARS
	MOV	STRBF(R3),(SP)	;;;START FROM BEGINNING OF INPUT BUFFER

	.ENDC

	.IF DF	T$$RUB

	CLRB	IHORP(R3)	;;;OUTPUT STARTS AT LEFT MARGIN

	.ENDC

	BR	180$		;;;DO MULTI-ECHO BUFFER
352$:				;;;REF LABEL

	.ENDC			;;; DF T$$BTW!T$$CTR

	CMPB	#177,(SP)	;;;RUBOUT?
	BNE	185$		;;;IF NE NO

;
; RUBOUT
;

	CMP	CURBF(R3),STRBF(R      3) ;;;ANY BYTES TO RUBOUT?

	.IF DF	T$$MIN

	BEQ	10$		;;;IF EQ NO

	.IFF

	BEQ	157$		;;;IF EQ NO

	.ENDC

	DEC	CURBF(R3)	;;;BACK UP ONE BYTE

	.IF DF	T$$UTB&M$$MGE

	DEC	U.BUF+2(R5)	;;;POINT AT LAST CHARCTER
	CALL	$GTBYT		;;;PUT IT ON STACK
	DEC	U.BUF+2(R5)	;;;POINT AT PLACE FOR NEXT INPUT CHAR
	MOV	(SP)+,(SP)	;;;ADJUST STACK

	.IFF

	MOVB	@CURBF(R3),(SP)	;;;GET BYTE TO BE RUBBED OUT

	.ENDC

	INCB	RMBYT(R3)	;;;INCREMENT REMAINING SPACE IN BUFFER

	.IF DF	T$$RNE

	BITB	#SS.RNE      ,S.STS(R4) ;;;ECHOING CHARACTERS?

	.IF DF	T$$MIN

355$:	BNE	10$		;;;IF NE NO

	.IFF

355$:	BNE	157$		;;;IF NE NO

	.ENDC

	.ENDC			;;; DF T$$RNE

	.IF DF	T$$RUB

	BIT	#U2.CRT,U.CW2(R5) ;;;TERMINAL A CRT?
	BEQ	58$		;;;IF EQ NO

;
; CRT RUBOUT
;
; CHECK TO SEE IF TRYING TO RUB OUT A TAB.  IT IS THE ONLY
; CASE OF A SPECIAL CURSOR POSITIONING CHAR WE WORRY ABOUT.
; TOO BAD ABOUT THINGS LIKE BACKSPACE.
;

	CMPB	#11,(SP)	;;;LAST CHAR A TAB?
	BEQ	50$		;;;IF EQ YES

	.IF DF	T$$ACR
      
	BIS	#FKCR,ATERS(R3)	;;;FLAG DO NOT WORRY ABOUT WRAPAROUND

	.ENDC

	MOV	#CRTRUB,(SP)	;;;OVERPRINT CHAR WITH A
	BR	180$		;;; BACKSPACE, SPACE, BACKSPACE
50$:				;;;REF LABEL

	.IF DF	T$$UTB&M$$MGE

	MOV	STRBF(R3),U.BUF+2(R5) ;;;POINT AT START OF BUFFER

	.IFF

	MOV	STRBF(R3),R4	;;;POINT AT START OF INPUT LINE

	.IFTF

	MOVB	IHORP(R3),(SP)	;;;INITIALIZE LINE POSITION
	BR	56$		;;;1ST CHARACTER IS A TAB?
53$:				;;;REF LABEL

	.IFT

	CALL	$GTBYT		;;;PUT NEXT BYTE ON STACK
	CMPB	#11,(S      P)+	;;;IS OLD CHARACTER A TAB?

	.IFF

	CMPB	#11,(R4)+	;;;IS OLD CHARACTER A TAB?

	.IFTF

	BNE	55$		;;;IF NE NO
	BISB	#7,(SP)		;;;BUMP COUNT TO NEXT TAB STOP
55$:	INCB	(SP)		;;;COUNT THE CHARACTER
56$:				;;;REF LABEL

	.IFT

	CMP	U.BUF+2(R5),CURBF(R3) ;;;FOUND LAST TAB?

	.IFF

	CMP	R4,CURBF(R3)	;;;FOUND LAST TAB?

	.IFTF

	BLT	53$		;;;IF LT NO
	BIS	#177770,(SP)	;;;-SPACES LAST TAB PUT OUT
	ADD	#CRTBS,(SP)	;;;POINT AT SAME NUMBER OF BACKSPACES

	.IFF

	MOV	U.SCB(R5),R4	;;;REST      ORE R4

	.IFTF

	BR	180$		;;;BACKUP ON LINE

	.ENDC			;;; DF T$$UTB&M$$MGE

58$:				;;;REF LABEL

	.ENDC			;;; DF T$$RUB

	BIT	#RUBP,(R3)	;;;RUBOUT ALREADY IN PROGRESS?
	BNE	120$		;;;IF NE YES
	BIS	#RUBP,(R3)	;;;SET RUBOUT IN PROGRESS
60$:	SWAB	(SP)		;;;SWAP BYTE TO HIGH BYTE
	MOVB	#'\,(SP)	;;;INSERT BACKSLASH

;
; SET UP FOR MULTI-ECHO
;

MECHO1:	MOV	(SP),MBUFR(R3)	;;;SET FOR MULTI-ECHO OF 1-2 BYTES
	MOV	R3,(SP)		;;;CALCULATE ADDR OF MULTI-ECHO BUFFER
	ADD	#MBUFR,(SP)	;;;
180$:	MOV      	(SP)+,MEBUF(R3)	;;;INSERT ADDRESS OF MULTI-ECHO BUFFER
	JMP	OUTPT1		;;;START OUTPUT
185$:	CMPB	#25,(SP)	;;;LINE DELETE?
	BNE	75$		;;;IF NE NO

;
; LINE DELETE (CONTROL U)
;

	MOV	#CTRLU,(SP)	;;;SET ADDRESS OF MULTI-ECHO BUFFER
	BIC	#RUBP,(R3)	;;;CLEAR RUBOUT IN PROGRESS FLAG
	MOV	U.CNT(R5),RMBYT(R3) ;;;RESET REMAINING BYTES IN BUFFER
				;;; ALSO CLEARS FINAL BYTE INDICATOR
	MOV	STRBF(R3),CURBF(R3) ;;;RESET ADDRESS IN BUFFER

	.IF DF	T$$UTB&M$$MGE

	MOV	STRBF(R3),U.BUF+2(R5) ;;;POINT AT ST      ART OF BUFFER

	.ENDC

	.IF DF	T$$RNE

	BITB	#SS.RNE,S.STS(R4) ;;;IN NO ECHO MODE?
	BNE	355$		;;;IF NE YES -- DON'T TYPE ^U

	.ENDC

	BR	180$		;;;GO SET MULTI-ECHO BUFFER
75$:	CMPB	#33,(SP)	;;;ESCAPE OR ALTMODE
	BNE	85$		;;;IF NE NO

;
; ALTMODE CODE 33 (ESCAPE) AND POSSIBLY 37, 175, AND 176
;

	.IF DF	T$$ESC

	BIT	#WESC,ATERS(R3)	;;;TASK WANTS ESCAPE SEQUENCES?
	BEQ	81$		;;;IF EQ NO
	BIT	#U2.ESC,U.CW2(R5) ;;;TERMINAL OUTPUTS ESCAPE SEQUENCES?
	BEQ	81$		;;;IF EQ NO
	BIS	#ESCS,ATERS(      R3)	;;;SHOW IN AN ESCAPE SEQUENCE
	CLR	SYNTX(R3)	;;;SHOW HAVE ONLY THE ESC
	BR	37$		;;;SAVE ESC IN BUFFER

	.ENDC

81$:	CLRB	(SP)		;;;SET TO ECHO ZERO BYTE
	MOVB	#33,FNBYT(R3)	;;;SET FINAL BYTE
	BR	115$		;;;SET END OF LINE SEEN
85$:				;;;REF LABEL

	.IF DF	T$$ESC

	BIT	#U2.ESC,U.CW2(R5) ;;;TERMINAL OUTPUTS ESCAPE SEQUENCES?
	BEQ	87$		;;;IF EQ NO
	CMPB	#37,(SP)	;;;NEW "ESCAPE"?
	BEQ	81$		;;;IF EQ YES
87$:				;;;REF LABEL

	.ENDC

	.IF DF	T$$LWC

	BIT	#U2.LWC,U.CW2(R5) ;;;TERMINAL IN L      OWER CASE?
	BNE	88$		;;;IF NE YES -- 175&176 ARE CHARS

	.ENDC

	CMPB	#175,(SP)	;;;ALTMODE?
	BLOS	81$		;;;IF LOS YES
88$:	CMPB	#32,(SP)	;;;CONTROL Z?
	BNE	89$		;;;IF NE NO

;
; CONTROL Z (END OF FILE)
;

	MOVB	#IE.EOF&377,FNBYT(R3) ;;;SET CONTROL Z FLAG
	BIS	#EOLS,(R3)	;;;SET END OF LINE SEEN

	.IF DF	T$$RNE

	BITB	#SS.RNE,S.STS(R4) ;;;IN NO ECHO MODE?
	BNE	48$		;;;IF NE  YES -- DON'T TYPE ^Z

	.ENDC

	MOV	#CTRLZ,(SP)	;;;SET ADDRESS OF MULTI-ECHO BUFFER
	BR	180$		;;;
89$:	CMPB	#15,      (SP)	;;;CARRIAGE RETURN?
	BNE	36$		;;;IF NE NO

;
; CARRIAGE RETURN
;

	MOVB	(SP),FNBYT(R3)	;;;SET FINAL BYTE
115$:	BIS	#EOLS,(R3)	;;;SET END OF LINE SEEN

	.IF DF	T$$RNE

	BITB	#SS.RNE,S.STS(R4) ;;;SHOULD ECHO CR OR ESC?
	BNE	48$		;;;IF NE NO

	.ENDC

120$:	BIT	#LFCT,(R3)	;;;ANY LINE FEEDS WAITING?
	BNE	MECHO1		;;;IF NE YES
	JMP	ECHOB		;;;ECHO BYTE ON STACK

;
; STORE BYTE IN INPUT BUFFER
;

36$:				;;;REFERENCE BYTE

	.IF DF	T$$LWC

	BIT	#U2.LWC,U.CW2(R5) ;;;CASE CONVERSION EN      ABLED?
	BNE	37$		;;;IF NE NO
	CMPB	#173,(SP)	;;;UPPER END GRAPHICS?
	BLOS	37$		;;;IF LOS YES
	CMPB	#141,(SP)	;;;LOWER CASE LETTER?
	BHI	37$		;;;IF HI NO
	BICB	#40,(SP)	;;;CONVERT TO UPPER CASE

	.ENDC

37$:				;;;REF LABEL

	.IF DF	T$$UTB&M$$MGE

	MOV	(SP),-(SP)	;;;COPY UNKNOWN CHARCTER
	CALL	$PTBYT		;;;PUT IT INTO TASK'S BUFFER

	.IFF

	MOVB	(SP),@CURBF(R3)	;;;STORE BYTE IN BUFFER

	.ENDC

	DECB	RMBYT(R3)	;;;ANY REMAINING SPACE IN BUFFER
	BNE	39$		;;;IF NE YES
	BIS	#EOLS,(R3)	;;;TE      RMINATE ON BYTE COUNT
	BR	40$		;;;
39$:	INC	CURBF(R3)	;;;INCREMENT BUFFER ADDRESS
40$:				;;;REF LABEL

	.IF DF	T$$RST

	BITB	#SS.RST,S.STS(R4) ;;;READ WITH SPECIAL TERMINATORS?
	BNE	46$		;;;IF NE YES

	.ENDC

45$:				;;;REF LABEL

	.IF DF	T$$ESC

	BIT	#ESCS,ATERS(R3)	;;;DOING AN ESCAPE SEQUENCE?
	BNE	200$		;;;IF NE YES

	.ENDC

450$:				;;;REF LABEL

	.IF DF	T$$RNE

	BITB	#SS.RNE,S.STS(R4) ;;;SUPPOSED TO ECHO CHARACTER?
	BNE	48$		;;;IF NE NO

	.ENDC

	.IF DF	T$$30P

	BIS	#EC      HO,ATERS(R3)	;;;SHOW ECHOING CHAR

	.ENDC

	.IF DF	T$$SYN

	BIC	#UOFF!UPND,ATERS(R3) ;;;IGNORE PREVIOUS CONTROL/S

	.ENDC

	BIT	#RUBP,(R3)	;;;RUBOUT IN PROGRESS?
	BEQ	120$		;;;IF EQ NO
451$:	BIC	#RUBP,(R3)	;;;CLEAR RUBOUT IN PROGRESS

	.IF DF	T$$ESC

	JMP	60$		;;;

	.IFF

	BR	60$		;;;

	.ENDC

	.IF DF	T$$RST

;
; TERMINATE READ ON A SPECIAL TERMINATOR.  A SPECIAL TERMINATOR IS
;	FROM A LOWERCASE TERMINAL - ANY CHAR OUTSIDE OF [40,176]
;	FROM OTHER TERMINALS - ANY CHARACTER OUTSI      DE OF [40,174]
;

46$:	CMPB	(SP),#40	;;;CHARACTER LOWER THAN RANGE?
	BLO	47$		;;;IF LO YES -- IT IS A TERMINATOR
	CMPB	(SP),#174	;;;CHARACTER WITHIN RANGE?
	BLOS	450$		;;;IF LOS YES -- TREAT IT NORMALLY

	.IF DF	T$$LWC

	BIT	#U2.LWC,U.CW2(R5) ;;;TERMINAL SET TO LOWER CASE?
	BEQ	47$		;;;IF EQ NO -- ALT DECISION IS OKAY
	CMPB	(SP),#177	;;;CHAR IN EXPANDED ASCII RANGE?
	BLO	450$		;;;IF LO YES

	.ENDC

47$:	BIS	#EOLS,(R3)	;;;SHOW TERMINATOR FOUND

; NEXT INSTRUCTION IMPLIES 7-BIT CHARACTERS (      SEE AFTER INPT2)

	MOVB	(SP),FNBYT(R3)	;;;STORE FINAL BYTE FOR I/O STATUS
	INCB	RMBYT(R3)	;;;READJUST BYTE COUNT

	.ENDC			;;; DF T$$RST

	.IF DF	T$$ESC!T$$RNE!T$$RST!T$$TRW

48$:	TST	(SP)+		;;;REMOVE CHARACTER FROM STACK
	JMP	INPPT		;;;DO NOT ECHO CHARACTER

	.ENDC

	.IF DF	T$$ESC

;+
; GATHER AN ESCAPE SEQUENCE
;
; IN GENERAL, AN ESCAPE SEQUENCE IS
;	ESC IC FC
; WHERE ESC = 33
;	IC  = ZERO OR MORE INTERMEDIATE CHARACTERS (40-57)
;	FC  = FINAL CHARACTER (60-176)
; THE FOLLOWING VIOL      ATIONS OF THAT RULE ARE ALSO ESCAPE SEQUENCES:
;	ESC ; IC FC
;	ESC ? IC FC
;	ESC O IC SFC
;	ESC [ PC!IC SFC								;TMM012

	.IF DF	ESCPIC

;	ESC P IC FC

	.ENDC

;	ESC Y CO CO
; WHERE ;   = 73
;	?   = 77
;	O   = 117
;	P   = 120
;	Y   = 131
;	SFC = SPECIAL FINAL CHARACTER (100-176)
;	CO  = BIASED 40 COORDINATE (40-176)
;	PC = PARAMETER CHARACTER (60-77)					;TMM012
; AN ESCAPE SEQUENCE TERMINATES A SOLICITED READ.  A SYNTACTICALLY
; CORRECT ESCAPE SEQUENCE RETURNS A STATUS OF IS.ESQ IN       THE IOSB
; AND THE ESCAPE SEQUENCE IN THE INPUT BUFFER.  A SYNTACTICALLY
; INCORRECT ESCAPE SEQUENCE (RECEPTION OF A CHARACTER NOT IN THE
; LEGAL RANGE OF THE NEXT EXPECTED CHARACTER) RETURNS IE.IES
; (ILLEGAL ESCAPE SEQUENCE) IN THE IOSB AND THE INCORRECT ESCAPE
; SEQUENCE IN THE INPUT BUFFER.  IF THE INPUT BUFFER IS FILLED BEFORE
; A FINAL CHARACTER IS RECEIVED, IE.PES (PARTIAL ESCAPE SEQUENCE)
; IS RETURNED.  IF A RUBOUT (177) IS RECEIVED, THE PARTIAL ESCAPE
; SEQUENCE IS ERASED FROM THE INPUT B      UFFER AND ESCAPE SEQUENCE
; RECOGNITION MODE IS EXITED.
;-

200$:	MOV	SYNTX(R3),R4	;;;GET RULE TO HANDLE CHARACTER
	BNE	210$		;;;IF NE HAVE A RULE
	MOV	#SYNTAB,SYNTX(R3) ;;;GET RULE FOR 2ND CHARACTER
204$:	BIT	#EOLS,(R3)	;;;PARTIAL SEQUENCE FILLS BUFFER?
	BNE	245$		;;;IF NE YES
	BIT	#RUBP,(R3)	;;;RUBOUT IN PROGRESS?
	BEQ	225$		;;;IF EQ NO
	MOV	U.SCB(R5),R4	;;;RESTORE R4
	CLR	(SP)		;;;FAKE OUT RUBOUT PROCESSING
	BR	451$		;;;
210$:	CMPB	#37,(SP)	;;;CHAR IN RANGE 0 -> 37?
	BGE	240$		;;;IF GE YES       -- SYNTAX VIOLATION
	CMPB	#177,(SP)	;;;CHAR A DEL?
	BEQ	250$		;;;IF EQ YES -- FORGET ESCAPE SEQUENCE
215$:	CMPB	(SP),(R4)+	;;;CHAR LESS THAN LOW VALUE OF RANGE?
	BLO	230$		;;;IF LO YES -- TRY NEXT RANGE
	CMPB	(SP),(R4)+	;;;CHAR GREATER THAN RANGE'S HIGH VALUE?
	BHI	232$		;;;IF HI YES -- NO MATCH
	MOV	(R4),SYNTX(R3)	;;;SAVE NEXT SYNTAX RULE
	BNE	204$		;;;IF NE SEQUENCE NOT COMPLETED
	COMB	FNBYT(R3)	;;;SET A -1 TO GET IS.ESQ
220$:	BIS	#EOLS,(R3)	;;;SHOW BUFFER COMPLETE
222$:	BIC	#ESCS,ATERS(R3)	;;      ;SHOW OUT OF ESCAPE SEQUENCE
225$:	MOV	U.SCB(R5),R4	;;;RESTORE R4
	BR	48$		;;;CLEAN UP STACK AND LEAVE WITHOUT
				;;; ECHOING
230$:	INC	R4		;;;BUMP PAST TOP OF RANGE
232$:	TST	(R4)+		;;;TESTED ALL RANGES OF RULE?
	BNE	215$		;;;IF NE NO -- CHECK THE NEXT
240$:	MOVB	#IE.IES&377,FNBYT(R3) ;;;SAVE ESCAPE ERROR STATUS
	BR	220$		;;;GET OUT
245$:	MOVB	#IE.PES&377,FNBYT(R3) ;;;PARTIAL ESCAPE SEQUENCE STATUS
	BR	220$		;;;

;
; IGNORE THE PARTIAL ESCAPE SEQUENCE AND GET OUT OF ESCAPE SEQUENCE
; MODE
;      

250$:	TSTB	RMBYT(R3)	;;;DEL FILLED BUFFER?
	BNE	252$		;;;IF NE NO
	INC	CURBF(R3)	;;;MAKE UP FOR NOT BUMPING CURBF AT 39$
252$:				;;;REF LABEL

	.IF DF	T$$UTB&M$$MGE

	DEC	U.BUF+2(R5)	;;;POINT AT LAST CHAR IN BUFFER
	CALL	$GTBYT		;;;PUT IT ONTO STACK
	DEC	U.BUF+2(R5)	;;;POINT WHERE LAST CHAR CAME FROM
	DEC	CURBF(R3)	;;;MAKE BOTH POINTERS AGREE

	.IFF

	DEC	CURBF(R3)	;;;POINT AT LAST CHAR IN BUFFER
	MOVB	@CURBF(R3),-(SP) ;;;PUT IT ONTO STACK

	.ENDC

	INCB	RMBYT(R3)	;;;SHOW INCREASED R      OOM IN BUFFER
	CMPB	#33,(SP)+	;;;FOUND FIRST CHAR OF ESCAPE SEQUENCE?
	BNE	252$		;;;IF NE NO
	BIC	#EOLS,(R3)	;;;SHOW ARE NOT AT END OF LINE
	BR	222$		;;;LEAVE

	.ENDC			;;; DF T$$ESC

	.DSABL	LSB
	.SBTTL	MISCELLANY
;+
; TTCAN - CANCEL I/O OPERATION ENTRY POINT (FORCE I/O COMPLETE)
;
; AT ENTRY:
;	R0 -> ADDR OF ACTIVE I/O PACKET
;	R1 -> ADDR OF TCB OF CURRENT TASK
;	R3 -> CONTROLLER INDEX
;	R4 -> ADDR OF SCB
;	R5 -> ADDR OF UCB
;	INTERRUPT PRIORITY=THAT OF DEVICE
;-

	.ENABL	LSB

	.I      IF NE	MODE-100000,	.ERROR	MODE

TTCAN:	MOV	U.CNT+2+STATS(R5),R2 ;;;UNIT BUSY ON INPUT?
	BMI	10$		;;;IF MI NO
	BIT	#SOLI,R2	;;;SOLICITED INPUT?
	BEQ	40$		;;;IF EQ NO
10$:	CMP	R1,I.TCB(R0)	;;;REQUEST FOR CURRENT TASK?
	BNE	40$		;;;IF NE NO
15$:	BIT	#EOLS,R2	;;;END OF LINE SEEN?

	.IF DF	T$$SYN

	BEQ	18$		;;;IF EQ NO

	.IIF NE	UPND-200,	.ERROR	UPND

	TSTB	U.CNT+2+ATERS(R5) ;;;IS CHARACTER THAT SET EOLS
				  ;;;BEING HELD UP?
	BPL	40$		  ;;;IF PL NO

	.IFF

	BNE	40$		;;;IF NE END OF LINE       SEEN

	.ENDC

	.IIF NE	MODE-100000,	.ERROR	MODE

18$:	TST	R2		;;;INPUT OR OUTPUT?
	BMI	20$		;;;IF MI OUTPUT
	BISB	#US.ECH,U.STS(R5) ;;;DISABLE INPUT CHARACTER HANDLING
20$:	MOVB	#IE.ABO&377,U.CNT+2+FNBYT(R5) ;;;SETUP FOR ABORT STATUS
	BIS	#EOLS,U.CNT+2+STATS(R5) ;;;SET END OF LINE SEEN
	MOVB	#1,S.CTM(R4)	;;;SET TIMEOUT COUNT TO 1

	.IF DF	T$$BTW!T$$ESC!T$$RPR!T$$SYN

	BIC	#ESCS!RPRM!XOFF!UPND,U.CNT+2+ATERS(R5) ;;;
				;;; CLEAR STATUS BITS THAT MAY BE SET

	.ENDC

40$:	RETURN			;;;

;      
; ROUTINE EXECUTED WHENEVER A DM11 OR DZ11 LINE HANGS UP.
; CANCEL I/O AND SAY "BYE" IF NECESSARY ON A MULTIUSER SYSTEM.
;

	.IF DF	D$$M11!D$$ZMD

TTHUP:	MOV	R2,-(SP)	;;;SAVE R2
	CALL	80$		;;;CANCEL I/O IF UNIT IS BUSY
	MOV	#CTRLU-1,U.CNT+2+MEBUF(R5) ;;;SUPPRESS MULTIECHO

	.IF DF	T$$ACR!T$$BTW!T$$CCA!T$$ESC!T$$HLD!T$$SYN!T$$30P

T3=CCPN!BAKS!FKCR!ECHO!UPND!CHAR!WESC!CCON!MCTR!UOFF
	BIC	#T3,U.CNT+2+ATERS(R5) ;CLEAR ADDITIONAL TERMINAL STATUS

	.ENDC

	.IF DF	M$$MUP

	.IF DF	D$$M11

	MT      PS	#0		;;;DROP PRIORITY

	.ENDC

	BIT	#U2.LOG,U.CW2(R5) ;TERMINAL LOGGED ON?
	BNE	70$		;IF NE NO
	MOV	R3,-(SP)	;SAVE REGISTERS NEEDED
	MOV	R1,-(SP)	;
	MOV	R0,-(SP)	;
	MOV	#M$$CRB,R1	;SET SIZE OF MCR COMMAND LINE
	CALL	$ALOCB		;ALLOCATE MCR COMMAND LINE
	BCS	50$		;IF CS ALLOCATION FAILURE
	MOV	R0,R1		;COPY POINTER TO BUFFER
	TST	(R0)+		;POINT TO UCB WORD
	MOV	R5,(R0)+	;PASS UCB POINTER
	MOV	#"BY,(R0)+	;STICK IN BYE COMMAND
	MOV	(PC)+,(R0)+	;
	.ASCII	/E/<15>		;

	.IF DF M$$CLI

	MOV	$MCRP      T,R0	;POINT TO MCR'S TCB
	CALL	$QCLIL		;AND QUEUE "BYE" COMMAND

	.IFF	;M$$CLI

	CALL	$QMCRL		;QUEUE THE COMMAND

	.ENDC	;M$$CLI


	.IF DF	D$$ZMD

	CLC			;SHOW A SUCCESSFUL FORAY

	.ENDC

	.IF DF	D$$M11

	BR	60$		;

	.ENDC

50$:				;REF LABEL

	.IF DF	D$$M11&D$$ZMD

	BIT	#U2.DZ1,U.CW2(R5) ;THIS LINE ON A DZ11?
	BNE	60$		;IF NE YES

	.ENDC

	.IF DF	D$$M11

	BISB	#US.CRW,U.STS(R5) ;TRY AGAIN IN 4 SECONDS
	MOVB	#1,U.CNT+2+DMTIM(R5) ;SET TIMEOUT VALUE TO 4

	.ENDC

60$:	MOV      	(SP)+,R0	;RESTORE REGISTERS
	MOV	(SP)+,R1	;
	MOV	(SP)+,R3	;

	.ENDC			; DF M$$MUP

70$:	MOV	(SP)+,R2	;;;RESTORE R2
	RETURN			;;;

; NEXT INSTRUCTION DEPENDS ON US.BSY=200

80$:	TSTB	U.STS(R5)	;;;UNIT BUSY?
	BPL	40$		;;;IF PL NO - RETURN
	CLRB	U.CNT+2+INPRQ(R5) ;;;CLEAR UNSOLICITED INPUT PENDING FLG
	MOV	U.CNT+2+STATS(R5),R2 ;;;TERMINAL STATUS WORD INTO R2
	BR	15$		;;;BRANCH INTO CANCEL ROUTINE

	.ENDC

	.DSABL	LSB

;
; GETBF - GET AN INPUT BUFFER AND SETUP TERMINAL CONTROL BLOCK
;
;       WHEN ENTERED AT GETBF
;
;	R5 -> UCB
;
; DESTROYS R0, R1, R2
; SETS R3 = UCB+U.CNT+2
; PRESERVES R4, R5, SP
;
; WHEN ENTERED AT GETBF2
;
;	R1 =  NUMBER OF BYTES TO ALLOCATE
;	R5 -> UCB
;
; DESTROYS R0, R2
; SETS R3 = UCB+U.CNT+2
; PRESERVES R4, R5, SP
;
; EITHER ENTRY POINT GETS A BUFFER FROM THE EXEC CORE POOL AND
; MAKES THE UCB POINT TO IT
;

	.ENABL	LSB

GETBF:	MOV	#M$$CRB,R1	;SET LENGTH OF BUFFER REQUIRED

	.IF DF	T$$VBF

	CMP	#M$$CRI,U.CNT(R5) ;BUF=SCREEN SIZE TOO MUCH FOR M      CR?
	BGE	GETBF2		;IF GE NO
	MOV	#M$$CRI,U.CNT(R5) ;GIVE MCR ONLY WHAT IT CAN HANDLE

	.IFTF

GETBF2:	CALL	$ALOCB		;ALLOCATE A CORE BLOCK
	BCS	20$		;IF CS NO BLOCK AVAILABLE

	.IFTF									;TMM011
	CLR	(R0)+		;CLEAR FIRST WORD OF BUFFER			;TMM011
	MOV	R1,(R0)+	;SAVE LENGTH OF BUFFER				;**-3
										;**-6
	.IF DF	T$$UTB&M$$MGE

	CLR	U.BUF(R5)	;MAKE "TASK BUFFER POINTERS" POINT AT
	MOV	R0,U.BUF+2(R5)	; THE NEW EXECUTIVE BUFFER.  BUFFER TO
				; TASK TRANSFER DONE BY $FINBF WHICH
				; GET      S MAPPING FROM I/O PACKET.

	.ENDC

INPINI:	MOV	R5,R3		;COPY UCB ADDRESS
	ADD	#U.CNT,R3	;POINT TO NUMBER OF BYTES REQUESTED

	.IFT			; DF T$$VBF

	CMP	#255.,(R3)	;BUFFER TOO BIG FOR RMBYT?
	BHIS	10$		;IF HIS NO
	MOV	#255.,(R3)	;CUT IT DOWN TO SIZE

	.IFF			; DF T$$VBF

	CMP	#M$$CRI,(R3)	;MORE THAN ONE BUFFER?
	BHIS	10$		;IF HIS NO
	MOV	#M$$CRI,(R3)	;ALLOW ONLY ONE BUFFER'S WORTH

	.ENDC			; DF T$$VBF

10$:	MOV	(R3)+,-(SP)	;SET LENGTH OF INPUT REQUEST
	BIC	#MODE!LFCT!CRTY!EOLS!RUBP!SOLI      !CTLO!FLCT,(R3)+ ;CLEAR STATUS
	MOV	R0,(R3)+	;SET STARTING BUFFER ADDRESS
	MOV	(SP)+,(R3)+	;SET SPACE REMAINING IN BUFFER
	MOV	R0,(R3)		;SET CURRENT BUFFER ADDRESS
	SUB	#CURBF,R3	;POINT TO START OF CONTROL BLOCK

	.IF DF	T$$ESC

	BIC	#ESCS,ATERS(R3)	;CLEAR STATUS

	.ENDC

20$:	RETURN			;

	.DSABL	LSB
										;TMM011
	.IF DF	C$$CKP&T$$BUF							;TMM011
										;TMM011
;										;TMM011
; BUFFER DEALLOCATION ROUTINE CALLED FROM $FINBF WITH				;TMM011
;										;TMM011
;	R0 -> BUFFER       TO BE DEALLOCATED						;TMM011
;										;TMM011
TTDEA:										;TMM011
	MOV	2(R0),R1	;GET SIZE OF BUFFER ALLOCATED			;TMM011
	CALL	$DEACB		;DEALLOCATE CORE BLOCK				;TMM011
	RETURN									;TMM011
	.IF NDF	A$$BIO								;TMM011
									;**-1	;TMM011
;+										;TMM011
; **-$TSTBF-TEST IF I/O BUFFERING CAN BE INITIATED				;TMM011
;										;TMM011
; THIS ROUTINE DETERMINES IF A GIVEN I/O REQUEST IS ELIGIBLE FOR I/O		;TMM011
; BUFFERING, AND IF SO (FOR SYSTEMS THAT SUPPORT SYSTEM-CONTROLLED      	;MSH046	;TMM011
; PARTITIONS) IT STORES THE PCB ADDRESS OF THE REGION INTO WHICH	;MSH046	;TMM011
; THE TRANSFER IS TO OCCUR IN I.PRM+16 OF THE I/O PACKET.		;MSH046	;TMM011
;									;**-2	;TMM011
; INPUTS:									;TMM011
;										;TMM011
;	R3=ADDRESS OF I/O PACKET FOR I/O REQUEST				;TMM011
;										;TMM011
; OUTPUTS:									;TMM011
;										;TMM011
;	R3 IS PRESERVED.							;TMM011
;										;TMM011
;	C=0 IF I/O BUFFERING CAN BE INITIATED.					;TMM011
;										;TMM011
;	C=1 IF I/O       BUFFERING CAN NOT BE INITIATED.				;TMM011
;-										;TMM011
										;TMM011
$TSTBF::MOV	I.TCB(R3),R0	;GET ADDRESS OF REQUESTOR TCB			;TMM011
	SEC			;ASSUME TASK CANNOT BE STOPPED?			;TMM011
	BIT	#T2.CHK!T2.CKD,T.ST2(R0) ;STOP IT?			;MSH090	;TMM011
	BNE	20$		;IF NE NO				;**-1	;TMM011
									;MSH046	;TMM011
	.IF DF	M$$MGE&D$$YNM						;MSH046	;TMM011
									;MSH046	;TMM011
	SAVNR			;SAVE R4 AND R5					;TMM011
	MOV	T.PCB(R0),R1	;GET ADDRESS OF REQUESTER HEADER		;TMM011
	MOV	P.HDR(R1),R1	;	      					;TMM011
	MOV	H.WND(R1),R1	;POINT TO NUMBER OF WINDOW BLOCKS		;TMM011
	MOV	(R1)+,R2	;GET COUNT OF WINDOWS				;TMM011
10$:	SEC			;ASSUME NO MORE WINDOWS				;TMM011
	DEC	R2		;ANY MORE WINDOWS TO EXAMINE?			;TMM011
	BLT	20$		;IF LT NO, DON'T CHECKPOINT			;TMM011
	MOV	(R1)+,R4	;GET ADDRESS OF DESCRIPTOR PCB			;TMM011
	BEQ	30$		;IF EQ WINDOW NOT MAPPED			;TMM011
	MOV	(R1)+,-(SP)	;GET LOW VIRTUAL ADDRESS			;TMM011
	MOV	(R1)+,R5	;GET HIGH VIRTUAL ADDRESS			;TMM011
	SUB	(SP),R5		;CALCULATE NUMBER OF B      YTES MINUS 1		;TMM011
	SUB	#77,R5		;REDUCE TO ACTUAL NUMBER OF BYTES - 64B		;TMM011
	ASL	R5		;CONVERT TO 32W BLOCKS				;TMM011
	ROL	R5		;						;TMM011
	ROLB	R5		;						;TMM011
	SWAB	R5		;						;TMM011
	MOV	P.REL(R4),(SP)	;GET RELOCATION BIAS OF PCB			;TMM011
										;TMM011
										;TMM011
	.IF DF	P$$LAS!A$$HDR						;MSH096	;TMM011
									;**-1	;TMM011
	ADD	W.BOFF-W.BATT(R1),(SP) ;ADD IN OFFSET IN PARTITION		;TMM011
										;TMM011
	.ENDC									;TMM011
										;TMM011
										;T      MM011
	ADD	(SP),R5		;CALCULATE HIGHEST 32W BLOCK			;TMM011
	ADD	#W.BLGH-W.BATT,R1 ;POINT TO NEXT DESCRIPTOR			;TMM011
	CMP	I.PRM(R3),(SP)+ ;TRANSFER IN THIS PARTITION?			;TMM011
	BLO	10$		;IF LO NO					;TMM011
	CMP	R5,I.PRM(R3)	;TRANSFER IN THIS PARTITION?			;TMM011
	BLO	10$		;IF LO NO					;TMM011
	MOV	R4,I.PRM+16(R3)	;STORE PCB ADDRESS IN I/O PACKET		;TMM011
									;MSH046	;TMM011
	.IFF	;M$$MGE&D$$YNM						;MSH046	;TMM011
									;MSH046	;TMM011
	CLC			;I/O BUFFERING CAN BE INITIATED		;MSH046      	;TMM011
									;MSH046	;TMM011
	.IFTF								;MSH046	;TMM011
									;MSH046	;TMM011
20$:	RETURN			;						;TMM011
									;MSH046	;TMM011
	.IFT								;MSH046	;TMM011
									;MSH046	;TMM011
30$:	ADD	#W.BLGH-W.BLVR,R1 ;POINT TO NEXT WINDOW BLOCK			;TMM011
	BR	10$		;					;MSH046	;TMM011
									;MSH046	;TMM011
	.IFTF								;MSH046	;TMM011
									;**-1	;TMM011
										;TMM011
;+										;TMM011
; **-$INIBF-INITIATE I/O BUFFERING						;TMM011
;										;TMM011
; THIS ROUTINE INIT      IATES I/O BUFFERING BY DOING THE FOLLOWING:			;TMM011
;										;TMM011
;	    1.	DECREMENT THE TASK'S I/O COUNT.					;TMM011
;	    2.	INCREMENT THE TASK'S BUFFERED I/O COUNT.		;MSH046	;TMM011
;	    3.	INITIATE CHECKPOINTING IF A REQUEST IS PENDING.		;MSH046	;TMM011
;									;**-6	;TMM011
; INPUTS:									;TMM011
;										;TMM011
;	R3=ADDRESS OF I/O PACKET FOR I/O REQUEST.				;TMM011
;										;TMM011
; OUTPUTS:									;TMM011
;										;TMM011
;	R3 IS PRESERVED.							;TMM011
;-								      		;TMM011
										;TMM011
$INIBF::MOV	R5,-(SP)	;SAVE R5				;MSH046	;TMM011
	MOV	I.TCB(R3),R5	;POINT TO ISSUING TASK'S TCB		;MSH046	;TMM011
	INCB	T.TIO(R5)	;TALLY THE BUFFERED I/O			;MSH046	;TMM011
	DECB	T.IOC(R5)	;ADJUST OUTSTANDING I/O REQUEST COUNT	;MSH046	;TMM011
									;MSH046	;TMM011
	.IFT								;MSH046	;TMM011
									;MSH046	;TMM011
	MOV	I.PRM+16(R3),R1	;GET PCB				;**-4	;TMM011
	SUB	P.REL(R1),I.PRM(R3) ;CONVERT TO RELATIVE RELOCATION BIAS	;TMM011
									;MSH046	;TMM011
	.ENDC	;M$      $MGE&D$$YNM						;MSH046	;TMM011
									;**-1	;TMM011
	.IF DF	D$$ISK&C$$CKP							;TMM011
										;TMM011
	BIT	#TS.CKR,T.STAT(R5) ;CHECKPOINT REQUEST PENDING? ;MSH041		;TMM011
	BEQ	20$		;IF EQ NO				;**-1	;TMM011
	BIC	#TS.CKR,T.STAT(R5) ;CLEAR CHECKPOINT REQUEST ;MSH041		;TMM011
	MOV	R5,R1		;COPY TCB ADDRESS			;MSH041	;TMM011
	MOV	R3,-(SP)	;SAVE PACKET ADDRESS			;MSH041	;TMM011
										;TMM011
	.IF DF	D$$YNM&D$$SHF							;TMM011
										;TMM011
	MOV	R5,-(SP)	;SAVE TCB ADDRESS				;TMM011      
										;TMM011
	.IFTF									;TMM011
										;TMM011
	CALL	$ICHKP		;INITIATE CHECKPOINT OF PCB		;**-3	;TMM011
										;TMM011
	.IFT									;TMM011
										;TMM011
	MOV	(SP)+,R5	;RESTORE TCB ADDRESS				;TMM011
	TSTB	T.IOC(R5)	;I/O COUNT NOW ZERO?				;TMM011
	BNE	15$		;IF NE NO					;TMM011
	MOV	T.PCB(R5),R0	;GET TASK'S PCB ADDRESS				;TMM011
	BIT	#PS.LIO,P.STAT(R0) ;CLEAR LONG I/O BIT				;TMM011
	CALL	$NXTSK		;REALLOCATE PARTITION				;TMM011
										;TMM011
	.ENDC									;TMM011
      										;TMM011
15$:	MOV	(SP)+,R3	;RESTORE PACKET ADDRESS IN R3		;MSH046	;TMM011
									;**-1	;TMM011
	.ENDC									;TMM011
										;TMM011
20$:	MOV	(SP)+,R5	;RESTORE R5				;MSH046	;TMM011
	RETURN			;					;**-2	;TMM011
										;TMM011
;+										;TMM011
; **-$QUEBF-QUEUE BUFFERED I/O FOR COMPLETION					;TMM011
;										;TMM011
; THIS ROUTINE QUEUES A SPECIAL ENTRY TO A TASK'S AST QUEUE TO COMPLETE		;TMM011
; A BUFFERED I/O REQUEST THE NEXT TIME THE TASK IS SCHEDULED.  IT ALSO		;TMM01      1
; DECREMENTS THE TASK'S BUFFERED I/O COUNT.				;MSH046	;TMM011
;									;**-1	;TMM011
; NOTE: THIS ROUTINE IS EQUIVALENT TO CALLING $IOFIN AND IT DOES NOT		;TMM011
;	UNBUSY THE DEVICE.							;TMM011
;										;TMM011
; INPUTS:									;TMM011
;										;TMM011
;	R0=FIRST WORD OF I/O STATUS						;TMM011
;	R1=SECOND WORD OF I/O STATUS						;TMM011
;	R3=ADDRESS OF I/O PACKET						;TMM011
;										;TMM011
; OUTPUTS:									;TMM011
;										;TMM011
;	NONE									;TMM011
;-										;TMM      011
										;TMM011
$QUEBF::MOV	R0,I.PRM+6(R3)	;STORE OFFSPRING I/O RETURN STATUS		;TMM011
	MOV	R1,I.PRM+10(R3)	;						;TMM011
	MOV	I.TCB(R3),R0	;PICK UP OFFSPRING TCB ADDRESS			;TMM011
	BIC	#TS.RDN,T.STAT(R0) ;CLEAR RUNDOWN IN PROG			;TMM011
	MOV	R0,R2		;COPY TCB ADDRESS				;TMM011
	ADD	#T.ASTL,R2	;POINT TO AST LISTHEAD				;TMM011
	MOV	(R2),(R3)	;LINK PACKET TO FRONT OF LIST			;TMM011
	BNE	10$		;						;TMM011
	MOV	R3,2(R2)	;						;TMM011
10$:	MOV	R3,(R2)		;						;TMM011
	MOVB	#AK.BUF,A.CBL(R3      ) ;SET BUFFERED I/O KERNEL AST TYPE	;MSH091	;TMM011
	DECB	T.TIO(R0)	;DECREMENT BUFFERED I/O COUNT		;MSH046	;TMM011
	BIT	#T2.WFR,T.ST2(R0) ;TASK STOPPED FOR BUFFERED I/O?	;MSH046	;TMM011
	BNE	12$		;IF NE YES				;MSH046	;TMM011
	CALLR	$SETCR		;SET CONDITIONAL SCHEDULE REQUEST	;MSH046	;TMM011
									;MSH046	;TMM011
12$:	CALLR	$EXRQU		;UNSTOP TASK AND RETURN			;MSH046	;TMM011
									;**-3	;TMM011
									;**-1	;TMM011
										;TMM011
	.ENDC	;A$$BIO								;TMM011
	.ENDC	;C$$CKP&T$$BUF							;T      MM011
	.SBTTL	CONTROLLER-DEPENDENT DATA BASE

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER (UNIT) NUMBER)
;

	.IF DF	D$$L11

CNTBL:	.BLKW	D$$L11		;ADDRESS OF UNIT CONTROL BLOCK

	.IF NDF	L$$DRV!M$$MGE!LD$TT

	.IF GT	D$$L11-1

DLTMP:	.BLKW	1		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC

	.ENDC			; NDF L$$DRV!M$$MGE!LD$TT

	.ENDC			; DF D$$L11

	.IF DF	D$$H11

DHTBL:				;REF LABEL
N=0
	.REPT	D$$H11
	.WORD	UCBTB+N		;POINTER TO DH11 UCB TABLE
N=N+34.
	      .ENDR

UCBTB:				;REF LABEL
	.REPT	D$$H11
	.REPT	16.
	.WORD	0		;ADDR OF UCB FOR LINE (PLUGGED AT TTPWF)
	.ENDR
	.WORD	0		;ZERO SENTINEL WORD
	.ENDR

DHCSR:	.BLKW	D$$H11		;DH11 CSR ADDRESS

	.IF NDF	L$$DRV!M$$MGE!LD$TT

	.IF GT	D$$H11-1

DHTMP:	.BLKW	1		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC

	.ENDC			; NDF L$$DRV!M$$MGE!LD$TT

	.IF DF	D$$M11

DMTBL:				;DM11-BB CSR ADDRESSES
	.REPT	D$$M11
	.WORD	0
	.ENDR
CLKSW:	.WORD	0		;DM11-BB CLOCK SWITCH WORD

	.IF NDF	L$$DRV!LD$TT

      	.WORD	0,0,0,0,0	;DM11-BB CLOCK QUEUE CONTROL BLOCK
	.WORD	DMTMO		;DM11-BB TIMER SUBROUTINE ADDRESS

	.IF DF	L$$DRV&M$$MGE
	.WORD	0		;WORD FOR APR5 BIAS
	.ENDC

	.ENDC			; NDF L$$DRV!LD$TT

	.ENDC			; DF D$$M11

	.ENDC			; DF D$$H11

	.IF DF	D$$Z11

DZTBL:				;REF LABEL
N=0
	.REPT	D$$Z11

	.WORD	UCZTB+N		;POINTER TO DZ11 UCB TABLE (INDEXED BY
				; CONTROLLER NUMBER)
	.IF DF	L$$SI1
	.IF DF	D$$ZMD
N=N+10.
	.IFF
N=N+8.
	.ENDC
	.IFF
	.IF DF	D$$ZMD
N=N+18.
	.IFF
N=N+16.
	.ENDC
	      .ENDC

	.ENDR

UCZTB:				;REF LABEL

	.REPT	D$$Z11

	.IF NDF	L$$SI1
	.WORD	0,0,0,0		;UCB ADDRESS FOR EACH LINE (INDEXED BY
	.ENDC
	.WORD	0,0,0,0		; LINE (UNIT) NUMBER)
	.IF DF	D$$ZMD
	.WORD	0
	.ENDC

	.ENDR

DZCSR:	.BLKW	D$$Z11		;DZ11 CSR ADDRESS

	.IF NDF	L$$DRV!M$$MGE!LD$TT

	.IF GT	D$$Z11-1

DZTMP:	.WORD	0		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC

	.ENDC			; NDF L$$DRV!M$$MGE!LD$TT

	.IF DF	D$$ZMD

DZCLKS:	.WORD	0		;DZ11 CLOCK SWITCH WORD

	.IF NDF	L$$DRV!LD$TT

	.      WORD	0,0,0,0,0	;DZ11 CLOCK QUEUE ENTRY
	.WORD	DZTMO		;DZ11 TIMEOUT ENTRY POINT

	.IF DF	L$$DRV&M$$MGE
	.WORD	0		;WORD FOR APR5 BIAS
	.ENDC

	.ENDC			; NDF L$$DRV!LD$TT

	.ENDC			; DF D$$ZMD

	.ENDC			; DF D$$Z11

	.IF DF	D$$J11

DJTBL:				;REF LABEL
N=0

	.REPT	D$$J11
	.WORD	UCJTB+N		;POINTER TO DJ11 UCB TABLE
N=N+32.
	.ENDR

UCJTB:				;REF LABEL

	.REPT	D$$J11
	.REPT	16.
	.WORD	0		;ADDRESS OF LINE'S UCB
	.ENDR
	.ENDR

DJCSR:	.BLKW	D$$J11		;DJ11 CSR ADDRESS

	.IF NDF	L$$DRV!      M$$MGE!LD$TT

	.IF GT	D$$J11-1

DJTMP:	.BLKW	1		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC

	.ENDC			; NDF L$$DRV!M$$MGE!LD$TT

	.ENDC			; DF D$$J11

;+
; DRIVER DISPATCH TABLE
;
; THE $XYTBL GLOBAL SYMBOLS ARE FOR EASING THE MENTAL BURDEN WHEN
; CREATING LOADABLE USER TERMINAL DRIVERS FOR TEST PURPOSES
;-

	.IF DF	LD$$L
$DLTBL::
	.ENDC

	.IF DF	LD$$H
$DHTBL::
	.ENDC

	.IF DF	LD$$J
$DJTBL::
	.ENDC

	.IF DF	LD$$Z
$DZTBL::
	.ENDC

										;TMM011
	.IF DF	C$$CKP&T$$BUF			      				;TMM011
										;TMM011
	.WORD	TTDEA								;TMM011
										;TMM011
	.ENDC									;TMM011
										;TMM011
	.IF NDF	LD$$L & LD$$H & LD$$J & LD$$Z
$TTTBL::
	.ENDC

	.IF DF	T$$BTW!T$$RPR

	.WORD	TTCHK		;DEVICE INITIATOR ENTRY POINT

	.IFF

	.WORD	TTINI		;DEVICE INITIATOR ENTRY POINT

	.ENDC

	.WORD	TTCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	TTOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	TTPWF		;POWERFAIL ENTRY POINT
	.SBTTL	CONTROLLER-DEPENDENT OUTPUT INTERRUPT CODE

	.ENAB      L	LSB

;+
; **-$DZOUT-DZ11 TERMINAL MULTIPLEXER OUTPUT INTERRUPTS
;-

	.IF DF	D$$Z11

$DZOUT::			;REF LABEL
	TTSAV$	DZ,PR5,D$$Z11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER
	MOVB	1(R4),R5	;;;GET BYTE CONTAINING LINE NUMBER
	BIC	#177770,R5	;;;ISOLATE LINE NUMBER
	ASL	R5		;;;MAKE IT INTO A WORD INDEX
	MOV	R5,-(SP)	;;;SAVE IT
	ADD	R3,R5		;;;ADDR OF ADDR OF UCB FOR LINE
	MOV	(R5),R5		;;;ADDR OF UCB FOR LINE
	MOV	(      SP)+,R3	;;;SET R3 TO LINE NUMBER
	BITB	#US.OUT,U.STS(R5) ;;;EXPECT INTERRUPT?
	BNE	3$		;;;IF NE YES
	BICB	$BTMSK(R3),4(R4) ;;;SHOW NO DESIRE TO TRANSMIT
	MOV	U.SCB(R5),R4	;;;SET R4 TO START OF SCB
	BR	40$		;;;DONE
3$:	MOVB	U.CNT+2+DHBUF(R5),6(R4) ;;;TRANSMIT BYTE

	.IF DF	D$$J11

	BR	5$

	.ENDC

	.ENDC			;;; DF D$$Z11

;+
; **-$DJOUT-DJ11 TERMINAL MULTIPLEXER OUTPUT INTERRUPTS
;-


	.IF DF	D$$J11

$DJOUT::			;;;REF LABEL
	TTSAV$	DJ,PR5,D$$J11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INT      ERRRUPT PRIORITY
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER
	MOV	R3,R5		;;;COPY ADDRESS OF UCB TABLE
	ADD	#7,R4		;;;POINT TO UNIT NUMBER
	MOVB	(R4),R3		;;;GET INTERRUPTING UNIT
	BIC	#177760,R3	;;;CLEAR EXCESS BITS
	ASL	R3		;;;CONVERT UNIT NUMBER TO WORD INDEX
	ADD	R3,R5		;;;CALCULATE ADDRESS OF UCB ADDRESS
	MOV	(R5),R5		;;;GET ADDRESS OF UCB
	BEQ	40$		;;;IF EQ NO UCB -- IGNORE INTERRUPT
	MOVB	U.CNT+2+DHBUF(R5),-(R4) ;;;OUTPUT NEXT BYTE
	BIC	$BTMSK(R3),-(R4) ;;;CLEAR BUFFE      R ACTIVE

	.ENDC			;;; DF D$$J11

	.IF DF	D$$J11!D$$Z11

5$:	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOV	R5,R3		;;;CALCULATE ADDRESS OF TERMINAL STATUS
	ADD	#U.CNT+2+STATS,R3 ;;;

	.IF DF	D$$H11!D$$L11

	BR	35$		;;;

	.ENDC

	.ENDC			;;; DF D$$J11!D$$Z11

;+
; **-$DHOUT-DH11 TERMINAL MULTIPLEXER OUTPUT INTERRUPTS
;-


	.IF DF	D$$H11

$DHOUT::			;;;REF LABEL
	TTSAV$	DH,PR5,D$$H11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET       R4=CSR OF INTERRUPTER
	BIC	#101077,(R4)	;;;CLEAR CURRENT UNIT AND TRANSMIT INT
10$:	MOV	(R3)+,R5	;;;UNIT EXIST?
	BEQ	40$		;;;IF EQ NO -- DONE
	BITB	#US.OUT,U.STS(R5) ;;;OUTPUT INTERRUPT EXPECTED?
	BEQ	20$		;;;IF EQ NO
	TST	10(R4)		;;;ZERO BYTE COUNT?
	BEQ	30$		;;;IF EQ YES
20$:	INC	(R4)		;;;INCREMENT UNIT NUMBER
	BR	10$		;;;TRY AGAIN
30$:	MOV	R4,-(SP)	;;;SAVE R4 AND R3
	MOV	R3,-(SP)	;;;
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOV	R5,R3		;;;CALCULATE ADDRESS OF TERMINAL STATUS WORD
	ADD	#U.CNT      +2+STATS,R3 ;;;
	CALL	50$		;;;FINISH OUTPUT PROCESSING
	MTPS	#PR5		;;;OUTPT MAY RETURN THRU $FORK
	MOV	(SP)+,R3	;;;RESTORE R3 AND R4
	MOV	(SP)+,R4	;;;
	BR	20$		;;;GO AGAIN

	.ENDC

;+
; **-$DLOUT-DL11 TERMINAL OUTPUT INTERRUPTS
;-

	.IF DF	D$$L11
$DLOUT::			;;;REF LABEL
	TTSAV$	DL,PR4,D$$L11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3= R5+U.CNT+2
				;;; SET R4=ADDRESS OF SCB
				;;; SET R5=ADDRESS OF UCB

	.ENDC

	.IF DF	D$$J11!D$$L11!D$$Z11

35$:	BITB	#U      S.OUT,U.STS(R5) ;;;OUTPUT INTERRUPT EXPECTED?
	BNE	50$		;;;IF NE YES

	.ENDC

40$:	RETURN			;;;IGNORE SPURIOUS INTERRUPTS
50$:	BICB	#US.OUT,U.STS(R5) ;;;CLEAR OUTPUT INTERRUPT EXPECTED
	CLRB	S.CTM(R4)	;;;DISABLE UNIT TIMEOUT
	CALLR	OUTPT		;;;OUTPUT NEXT BYTE, IF THERE IS ONE

	.DSABL	LSB
	.SBTTL	TERMINAL TIMEOUT ROUTINE

;+
; TTOUT - TERMINAL DRIVER TIMEOUT ENTRY POINT
;
; ENTERED AT FORK LEVEL WITH
;	R5 -> UCB
;	R4 -> SCB
;	R3 -> CONTROLLER NUMBER
;	R2 -> CSR
;	R0 -> IE.DNR
;	INTERRU      PT PRIORITY = THAT OF DEVICE
;
; EXITS BY GOING TO COMMON CODE AFTER REENABLING INTERRUPTS ON
; DEVICE
;-

TTOUT:				;;;REF LABEL

	.IF DF	D$$H11!D$$J11!D$$Z11

	MOV	U.CW2(R5),R1	;;;MULTIPLEXED TERMINAL?

	.IF DF	D$$L11

; NEXT INSTRUCTION DEPENDS ON U2.DH1=100000

	BPL	25$		;;;IF PL NO

	.ENDC

	.IF DF	D$$H11

	.IF DF	D$$J11!D$$Z11

	ASL	R1		;;;DJ11 TERMINAL?

	.IF DF	D$$J11

; NEXT INSTRUCTION DEPENDS ON U2.DJ1=U2.DH1/2

	BMI	23$		;;;IF MI YES

	.ENDC

	.IF DF	D$$Z11

	      TSTB	R1		;;;DZ11 TERMINAL?

; NEXT INSTRUCTION DEPENDS ON U2.DZ1=100

	BMI	22$		;;;IF MI YES

	.ENDC

	.ENDC			;;; DF D$$J11!D$$Z11

	BIC	#1077,(R2)	;;;CLEAR CURRENT UNIT
	BIS	#20100,(R2)	;;;MAKE SURE INTERRUPTS ARE ENABLED
	BISB	U.UNIT(R5),(R2) ;;;SELECT DESIRED UNIT
	CLR	10(R2)		;;;ZERO BYTE COUNT

	.IF DF	D$$J11!D$$Z11

	BR	25$		;;;

	.ENDC

	.IFF			;;; DF D$$H11

	.IF DF	D$$J11&D$$Z11

	ASL	R1		;;;DJ11 TERMINAL?

; NEXT INSTRUCTION DEPENDS ON U2.DJ1=U2.DH1/2

	BMI	23$		;;;IF       NE YES

	.ENDC

	.ENDC			;;; DF D$$H11

	.IF DF	D$$Z11

22$:	BIS	#40140,(R2)	;;;MAKE SURE INTERRUPTS ENABLED

	.IF DF	D$$J11

	BR	25$		;;;

	.ENDC

	.ENDC			;;; DF D$$Z11

	.IF DF	D$$J11

23$:	BIS	#40501,(R2)	;;;MAKE SURE INTERRUPTS ARE ENABLED

	.ENDC

	.ENDC			;;; DF D$$H11!D$$J11!D$$Z11

25$:	BICB	#US.OUT,U.STS(R5) ;;;CLEAR OUTPUT INTERRUPT EXPECTED
	MTPS	#0		;;;ALLOW DEVICE INTERRUPTS
	CALLR	TTOUT1		;
	.SBTTL	CONTROLLER-DEPENDENT OUTPUT CHAR ROUTINE

;
; OCHAR - OUTPUT       A CHARACTER TO A TERMINAL
;
; AT ENTRY:
;	R5 -> UCB
;	R4 -> SCB
;	(SP) = CHAR TO OUTPUT
;	INTERRUPT PRIORITY = THAT OF OUTPUT DEVICE
;
; EXITS VIA RETURN
;

	.ENABL	LSB

OCHAR:				;;;REF LABEL

	.IF DF	T$$SYN

	BIT	#UOFF,U.CNT+2+ATERS(R5) ;;;OUTPUT TURNED OFF?
	BNE	100$		;;;IF NE YES

	.IFTF

FCHAR:	MOV	S.CSR(R4),R3	;;;GET ADDRESS OF CSR
	MOVB	S.ITM(R4),S.CTM(R4) ;;;ENABLE TIMEOUT

	.IF DF	D$$H11!D$$J11!D$$Z11

	.IF DF	D$$L11

	TST	U.CW2(R5)	;;;MULTIPLEXED TERMINAL?

; NEXT IN      STRUCTION DEPENDS ON U2.DH1=100000

	BPL	90$		;;;IF PL NO

	.ENDC

	MOVB	(SP)+,U.CNT+2+DHBUF(R5) ;;;PUT BYTE IN OUTPUT BUFFER
	MOVB	U.UNIT(R5),R4	;;;GET PHYSICAL UNIT NUMBER

	.IF DF	D$$H11

	.IF DF	D$$J11!D$$Z11

	BIT	#U2.DJ1!U2.DZ1,U.CW2(R5) ;;;DJ11 OR DZ11?
	BNE	83$		;;;IF NE YES

	.IFTF

	BIC	#1077,(R3)	;;;CLEAR CURRENT UNIT
	BIS	R4,(R3)		;;;SELECT DESIRED UNIT
	BIC	#60,(R3)+	;;;
	ADD	#4,R3		;;;POINT TO CURRENT ADDRESS REGISTER
	MOV	R5,(R3)		;;;CALCULATE ADDRESS OF BYTE BUFFER
	AD      D	#U.CNT+2+DHBUF,(R3)+ ;;;
	MOV	#-1,(R3)+	;;;SET BYTE COUNT TO MINUS ONE

	.IFT

	BR	87$		;;;

	.ENDC

	.IFTF			;;; DF D$$H11

	.IF DF	D$$J11!D$$Z11

83$:	ADD	#4,R3		;;;POINT TO BUFFER ACTIVE REGISTER

	.ENDC

87$:	ASL	R4		;;;CONVERT UNIT NUMBER TO WORD INDEX
	BIS	$BTMSK(R4),(R3) ;;;START OUTPUT

	.IF DF	D$$L11

	BR	95$		;;;SET OUTPUT INT EXPECTED AND EXIT

	.ENDC

	.ENDC			;;; DF D$$H11

	.ENDC			;;; DF D$$H11!D$$J11!D$$Z11

	.IF DF	D$$L11

90$:	MOVB	(SP)+,6(R3)	;;;OUTPUT BY      TE
	BIS	#100,4(R3)	;;;ENABLE OUTPUT INTERRUPT

	.ENDC

95$:	BISB	#US.OUT,U.STS(R5) ;;;SET OUTPUT INTERRUPT EXPECTED
	RETURN			;;;

	.IFT			;;; DF T$$SYN

100$:	MOVB	(SP)+,U.CNT+2+DHBUF(R5) ;;;SAVE BYTE TO OUTPUT
	BIS	#UPND,U.CNT+2+ATERS(R5) ;;;SET OUTPUT BYTE PENDING
	RETURN			;;;

	.ENDC			;;; DF T$$SYN


	.DSABL	LSB
	.SBTTL	CONTROLLER-DEPENDENT INPUT INTERRUPT CODE

	.ENABL	LSB

;+
; **-$DZINP-DZ11 TERMINAL MULTIPLEXER INPUT INTERRUPTS
;-

	.IF DF	D$$Z11

$DZINP::			;;;REF LAB      EL
	TTSAV$	DZ,PR5,D$$Z11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER

	.IF DF	D$$H11!D$$J11

	BR	1$		;;;

	.ENDC

	.ENDC			;;; DF D$$Z11

;+
; **-$DJINP-DJ11 TERMINAL MULTIPLEXER INPUT INTERRUPTS
;-

	.IF DF	D$$J11

$DJINP::			;;;REF LABEL
	TTSAV$	DJ,PR5,D$$J11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER

	.IF DF	D$$H11

	BR      	1$		;;;

	.ENDC

	.ENDC			;;; DF	D$$J11

	.IF DF	D$$H11

;+
; **-$DHINP-DH11 TERMINAL MULTIPLEXER INPUT INTERRUPTS
;-

$DHINP::			;;;REF LABEL
	TTSAV$	DH,PR5,D$$H11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER

	.ENDC

	.IF DF	D$$H11!D$$J11!D$$Z11

1$:	MOV	2(R4),-(SP)	;;;GET NEXT BYTE FROM SILO
	BPL	5$		;;;IF PL SILO IS EMPTY
	MOVB	1(SP),R5	;;;GET PHYSICAL UNIT NUMBER
	BIC	#177760,R5	;;;CLEAR EXCESS BITS      
	ASL	R5		;;;CONVERT UNIT NUMBER TO WORD INDEX
	ADD	R3,R5		;;;ADD BASE ADDRESS OF UCB TABLE
	MOV	(R5),R5		;;;GET ADDRESS OF UCB
	BEQ	5$		;;;IF EQ SPURIOUS INTERRUPT

	.IF DF	D$$M11&D$$H11!D$$ZMD

	BITB	#US.DSB,U.STS(R5) ;;;UNIT DISABLED?
	BNE	5$		;;;IF NE YES

	.ENDC

	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOV	R5,R3		;;;CALCULATE ADDRESS OF TERMINAL STATUS WORD
	ADD	#U.CNT+2+STATS,R3 ;;;

	.IF DF	D$$L11

	BR	2$		;;;FINISH IN COMMON CODE

	.ENDC

	.ENDC			;;; DF D$$H11!D$$J11!D$$Z11
      
;+
; **-$DLINP-DL11 TERMINAL INPUT INTERRUPT
;-

	.IF DF	D$$L11

$DLINP::			;;;REF LABEL
	TTSAV$	DL,PR4,D$$L11	;;;SAVE R3, R4, R5 AND LOWER
				;;; INTERRUPT PRIORITY
				;;; SET R3=R5+U.CNT+2
				;;; SET R4=ADDRESS OF SCB
				;;; SET R5=ADDRESS OF UCB
	MOV	S.CSR(R4),-(SP)	;;;GET ADDRESS OF CSR
	ADD	#2,(SP)		;;;POINT TO DATA BUFFER REGISTER
	MOV	@(SP)+,-(SP)	;;;GET INPUT BYTE AND ERROR BITS

	.ENDC

2$:				;;;REF LABEL

	.IF NDF	T$$MIN

	BIT	#60000,(SP)	;;;HAD A HARD ERROR?
	BNE	5$	      	;;;IF NE YES

	.ENDC

	.IF DF	T$$TRW

	.IIF NE	SS.RAL-200,	.ERROR	SS.RAL

	TSTB	S.STS(R4)	;;;READ PASS ALL?
	BMI	3$		;;;IF MI YES

	.ENDC

	BIC	#177600,(SP)	;;;CLEAR PARITY BIT AND HIGH BYTE

	.IF DF	T$$HLD!T$$SYN

	CMPB	#23,(SP)	;;;TURN OUTPUT OFF?
	BEQ	4$		;;;IF EQ YES
	CMPB	#21,(SP)	;;;TURN OUTPUT ON?
	BEQ	6$		;;;IF EQ YES

	.ENDC

	.IF DF	T$$HLD!T$$SYN

	CMPB	#3,(SP)		;;;CHARACTER A CONTROL C?
	BEQ	8$		;;;IF EQ YES

	.ENDC

3$:	CALLR	ICHAR

	.IF DF	T$$HLD!T$$SYN

;
;       TURN OUTPUT OFF (RECEIVED A XOFF)
;

4$:	BIS	#UOFF,ATERS(R3)	;;;TURN OUTPUT OFF

	.IFTF

	.IF DF	T$$MIN

	.IF DF	D$$H11!D$$J11!D$$Z11

5$:	TST	(SP)+		;;;NOW IGNORE CHARACTER
	RETURN			;;;RETURN FROM INTERRUPT

	.ENDC

	.IFF			;;; DF T$$MIN

5$:	TST	(SP)+		;;;NOW IGNORE CHARACTER
	RETURN			;;;RETURN FROM INTERRUPT

	.ENDC

	.IFT			;;; DF T$$HLD!T$$SYN

;
; TURN OUTPUT ON (RECEIVED A XON)
;

6$:	BIC	#UOFF,ATERS(R3) ;;;CLEAR HOLD OUTPUT FLAG

	.IIF NE	UPND-200,	.ERROR	UPND

	T      STB	ATERS(R3)	;;;OUTPUT BYTE PENDING?
	BPL	5$		;;;IF PL NO
7$:	MOVB	DHBUF(R3),(SP)	;;;GET HELD UP BYTE
7000$:	BIC	#UPND,ATERS(R3)	;;;CLEAR OUTPUT BYTE PENDING FLAG
	CALLR	OCHAR		;;;OUTPUT BYTE

	.ENDC			;;; DF T$$HLD!T$$SYN

	.IF DF	T$$HLD!T$$SYN

;
; RECEIVED A CONTROL C.  IF IN HOLD-SCREEN MODE, GET OUT OF IT.
; IF OUTPUT TURNED OFF, TURN IT ON.  IN ANY CASE, GET TO MCR.
;

8$:	BIC	#UOFF,ATERS(R3)	;;;TURN OUTPUT ON

	.ENDC

	.IF DF	T$$HLD

	BIT	#U2.HLD,U.CW2(R5) ;;;IN HOLD-SCREEN MODE      ?

	.IF DF	T$$SYN

	BEQ	9$		;;;IF EQ NO

	.IFF

	BEQ	3$		;;;IF EQ NO

	.ENDC

	BIS	#BAKS!CCPN,ATERS(R3) ;;;FLAG SPECIAL MULTI-ECHO AND
				;;; HAVE CONTROL/C
	BIC	#U2.HLD,U.CW2(R5) ;;;SHOW NOT IN HOLD-SCREEN MODE

;
; WANT TO GET OUT OF HOLD-SCREEN MODE (SEND "ESC \" TO TERMINAL AND
; HOPE IT EVENTUALLY PAYS ATTENTION), SEND CHAR HELD UP BY CONTROL/S,
; AND PROMPT WITH "MCR>."  ASSUME WE CANNOT IMMEDIATELY KICK TERMINAL
; OUT OF HOLD-SCREEN MODE (THE TERMINAL'S SILO AND THE INTERFACE'S
      ; DOUBLE BUFFERING PROBABLY HAVE STACKED UP CHARACTERS).  SO SEND HELD
; UP CHAR FIRST, BECAUSE IT IS CONVENIENT.  BECAUSE CONTROL/C IS
; CONSIDERED BY THE USER TO BE DESTRUCTIVE,  HE OR SHE SHOULD NOT BE
; CONCERNED WITH OUR ABUSE OF THE OUTPUT STREAM FLAGS.
;

	MOV	#LEVHSM,MEBUF(R3) ;;;MULTI-ECHO ESCAPE SEQUENCE
	BIC	#LFCT!FLCT,(R3)	;;;CLEAN UP FIELD FOR "MCR>"

	.IIF NE	UPND-200,	.ERROR	UPND

	TSTB	ATERS(R3)	;;;SOMETHING IN DHBUF?
	BMI	7$		;;;IF MI YES
	TST	(SP)+		;;;CLEAN UP STACK
	CALLR	X      ITHSM		;;;START SENDING ESCAPE SEQUENCE

	.ENDC			;;; DF T$$HLD

	.IF DF	T$$SYN

	.IIF NE	UPND-200,	.ERROR	UPND

9$:	TSTB	ATERS(R3)	;;;OUTPUT PENDING?
	BPL	3$		;;;IF PL NO
	BIS	#CCPN,ATERS(R3)	;;;TRY FOR AN MCR PROMPT
	BR	7$		;;;

	.ENDC

	.DSABL	LSB
	.SBTTL	CONTROLLER-DEPENDENT POWERFAIL CODE

;+
; TTPWF - POWERFAIL AND LOADED AS LOADABLE DRIVER ENTRY POINT
;
; ENTERED AT FORK LEVEL WITH
;	R5 -> UCB
;	R4 -> SCB
;	R3 = CONTROLLER INDEX
;-

TTPWF:	MOV	S.CSR(R4),R2	;GET ADDRESS OF       CSR

	.IF DF	D$$H11!D$$J11!D$$Z11

	MOV	U.CW2(R5),R0	;MULTIPLEXED TERMINAL?

	.IF DF	D$$L11

; NEXT INSTRUCTION DEPENDS ON U2.DH1=100000

	BPL	20$		;IF PL NO

	.ENDC

	MOVB	U.UNIT(R5),R1	;GET PHYSICAL UNIT NUMBER

	.IF DF	D$$H11

	ASL	R0		;DJ11 TERMINAL?

	.IF DF	D$$J11

; NEXT INSTRUCTION DEPENDS ON U2.DJ1=U2.DH1/2

	BMI	15$		;IF MI YES

	.ENDC

	.IF DF	D$$Z11

; NEXT INSTRUCTION DEPENDS ON U2.DZ1=100

	TSTB	R0		;DZ11 TERMINAL?
	BMI	18$		;IF MI YES

	.ENDC

	TST	R1		;LI      NE ZERO?
	BNE	5$		;IF NE NO
	MOV	#4000,(R2)	;CLEAR SILO, UARTS, AND DH11 CONTROLLER
	MOV	#20100,(R2)	;ENABLE INTERRUPTS
5$:	MOV	R2,DHCSR(R3)	;SAVE ADDRESS OF DH11 CSR
	MTPS	S.PRI(R4)	;;;LOCK OUT DEVICE INTERRUPTS
	CALL	SETLIN		;;;SET LINE PARAMETERS				;TMM035
	ASL	R1		;;;CONVERT UNIT TO WORD INDEX			;**-3
	ADD	DHTBL(R3),R1	;;;CALCULATE ADDRESS TO STORE UCB ADDRESS
	MOV	R5,(R1)		;;;SAVE ADDRESS OF UCB
	BICB	#US.CRW!US.DSB,U.STS(R5) ;;;ASSUME LOCAL UNIT

	.IF DF	D$$M11

; NEXT INSTRUCTION DEPEN      DS ON U2.RMT=U2.DJ1/2

	ASL	R0		;;;LOCAL UNIT?
	BPL	14$		;;;IF PL YES
	MOV	U.CNT+2+DMCSR(R5),R1 ;;;GET ADDRESS OF DM11-BB CSR
	MOV	@#4,-(SP)	;;;SAVE ADDRESS OF TRAP PC
	MOV	#13$,@#4	;;;CHANGE SO TRAP WILL COME TO US
	TST	(R1)		;;;LIED ABOUT EXISTENCE OF DM11?
	MOV	(SP)+,@#4	;;;RESTORE SYSTEM TRAP 4 PC
	BCS	35$		;;;IF CS YES (13$ LOWERED
				;;; PRIORITY AND SET C)
	MOV	R1,DMTBL(R3)	;;;SAVE ADDRESS OF DM11-BB CSR
	CALL	DMHUP		;;;HANG UP UNIT IF NOT READY
	MTPS	#0		;;;ALLOW DEVICE INTERRUPTS

	      .IF DF	L$$DRV&LD$TT

	MOV	CLKSW,R0	;CLOCK QUEUE ENTRY ALREADY MADE?
	BNE	35$		;IF NE YES
	MOV	U.DCB(R5),R0	;POINT AT DCB
	MOV	D.UCB(R0),R0	;POINT AT FIRST UCB
	MOV	U.SCB(R0),R0	;POINT AT FIRST SCB
	ADD	#S.DHCK,R0	;POINT AT CLOCK QUEUE ENTRY
	MOV	#DMTMO,12(R0)	;INSERT SUBROUTINE ENTRY POINT
	MOV	R0,CLKSW	;SAVE POINTER TO CLOCK QUEUE ENTRY

	.IFF

	MOV	#CLKSW,R0	;POINT TO CLOCK SWITCH WORD
	TST	(R0)		;CLOCK QUEUE ENTRY ALREADY MADE?
	BNE	35$		;IF NE YES
	MOV	PC,(R0)+	;INDICATE CLOCK QUEUE ENTR      Y MADE

	.ENDC

	CALLR	DMCLK		;INSERT ENTRY IN CLOCK QUEUE

;
; CONTROL GOES TO 13$ IF CSR OF DM11 IS NOT IN PRESENT ADDRESS SPACE
;

13$:	MOVB	#1,2(SP)	;;;LOWER PRIORITY TO ZERO, SET C
				;;; AND DEVESTATE T BIT
	RTI			;;;BACK TO DH POWERFAIL

	.ENDC			;;; DF D$$M11

14$:	MTPS	#0		;;;ALLOW DEVICE INTERRUPTS

	.IF DF	D$$J11!D$$Z11!D$$L11

	BR	35$		;;;

	.ENDC

	.IFF			; DF D$$H11

	.IF DF	D$$J11&D$$Z11

	ASL	R0		;DZ11 TERMINAL?
	BPL	18$		;IF PL YES

	.ENDC

	.ENDC			; DF D$      $H11

	.IF DF	D$$J11

15$:	MOV	R2,DJCSR(R3)	;SAVE ADDRESS OF DJ11 CSR
	ASL	R1		;CONVERT UNIT TO WORD INDEX
	BNE	17$		;IF NE NOT LINE ZERO
	MOV	#10,(R2)	;CLEAR SILO, UARTS, AND DJ11 CONTROLLER
16$:	BIT	#20,(R2)	;CLR COMPLETED?
	BNE	16$		;IF NE NO
	BIS	#40501,(R2)	;ENABLE INTERRUPTS
17$:	ADD	DJTBL(R3),R1	;CALCULATE ADDRESS TO STORE UCB

	.IF DF	D$$Z11

	.IF NDF	D$$ZMD

	BR	192$		;EXIT COMMONLY

	.IFF

	MOV	R5,(R1)		;SAVE ADDRESS OF UCB
	BR	35$		;

	.ENDC

	.IFF			; DF D$$Z11

	MOV	      R5,(R1)		;SAVE ADDRESS OF UCB

	.IF DF	D$$H11!D$$L11

	BR	35$		;

	.ENDC

	.ENDC			; DF D$$Z11

	.ENDC			; DF D$$J11

	.IF DF	D$$Z11

18$:	MOV	R2,DZCSR(R3)	;SAVE ADDR OF DZ11 CSR
	ASL	R1		;CONVERT UNIT # TO WORD INDEX
	BNE	191$		;IF NE NOT FIRST UNIT
	MOV	#20,(R2)	;CLR SILO, UARTS, AND CONTROLLER
19$:	BIT	#20,(R2)	;CLR DONE YET?
	BNE	19$		;IF NE NO
	BIS	#40140,(R2)	;ENABLE INTERRUPTS
191$:	ADD	DZTBL(R3),R1	;FORM ADDR TO STORE UCB
	CALL	SETLIN		;SET INITIAL LINE CHARACTERISTICS		;TMM035      
192$:	MOV	R5,(R1)		;SAVE ADDRESS OF UCB				;**-1

	.IF DF	D$$ZMD

	.IF DF	L$$DRV&LD$TT

	MOV	DZCLKS,R0	;CLOCK QUEUE ENTRY ALREADY MADE?
	BNE	35$		;IF NE YES
	MOV	U.DCB(R5),R0	;POINT AT DCB
	MOV	D.UCB(R0),R0	;POINT AT FIRST UCB
	MOV	U.SCB(R0),R0	;POINT AT FIRST SCB
	ADD	#S.DZCK,R0	;POINT AT CLOCK QUEUE ENTRY
	MOV	#DZTMO,12(R0)	;INSERT SUBROUTINE ADDRESS
	MOV	R0,DZCLKS	;SAVE POINTER TO CLOCK QUEUE ENTRY

	.IFF

	MOV	#DZCLKS,R0	;POINT AT CLOCK SWITCH WORD
	TST	(R0)		;CLOCK ENTRY ALREADY QUE      UED?
	BNE	35$		;IF NE YES
	MOV	PC,(R0)+	;MARK ENTRY AS QUEUED

	.ENDC

	CALLR	DZCLK		;INSERT ENTRY IN CLOCK QUEUE

	.IFF

	.IF DF	D$$L11

	BR	35$		;

	.ENDC

	.ENDC			; DF D$$ZMD

	.ENDC			; DF D$$Z11

	.ENDC			; DF D$$H11!D$$J11!D$$Z11

	.IF DF	D$$L11

20$:	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF UCB
	MOVB	2(R2),R0	;CLEAR DL11 INPUT DATA BUFFER REGISTER
	BIS	#100,(R2)	;ENABLE RECEIVER INTERRUPTS

	.ENDC

35$:	RETURN
	.SBTTL	MISCELLANEOUS CONTROLLER-DEPENDENT SUBROUTINES

	.ENABL      	LSB

;
; DH11 TERMINAL MULTIPLEXER SAVE ROUTINE
;

	.IF DF	D$$H11

DHSAV:	TTSET$	DH,D$$H11,MUX	;;;SAVE R3
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER

	.IF DF	D$$Z11!D$$J11!D$$L11

	BR	20$		;;;FINISH IN COMMON CODE

	.ENDC

	.ENDC			;;; DF D$$H11

;
; DZ11 TERMINAL MULTIPLEXER SAVE ROUTINE
;

	.IF DF	D$$Z11

DZSAV:	TTSET$	DZ,D$$Z11,MUX	;;;SAVE R3
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER

	.IF DF	D$$J11!D$$L11

	BR	20$		;;;FINI      SH IN COMMON CODE

	.ENDC

	.ENDC			;;; DF D$$Z11

;
; DJ11 TERMINAL MULTIPLEXER SAVE ROUTINE
;

	.IF DF	D$$J11

DJSAV:	TTSET$	DJ,D$$J11,MUX	;;;SAVE R3
				;;; SET R3=ADDR OF UCB TABLE
				;;; SET R4=CSR OF INTERRUPTER

	.IF DF	D$$L11

	BR	20$		;;;FINISH IN COMMON CODE

	.ENDC

	.ENDC			;;; DF D$$J11

;
; DL11 TERMINAL SAVE ROUTINE
;

	.IF DF	D$$L11

DLSAV:	TTSET$	DL,D$$L11	;;;SAVE R3
				;;; SET R5=ADDR OF UCB
	MOV	U.SCB(R5),R4	;;;RETRIEVE ADDRESS OF SCB
	MOV	R5,R3		;;;CALC      ULATE ADDRESS OF TERMINAL
	ADD	#U.CNT+2+STATS,R3 ;;; CONTROL BLOCK

	.ENDC

20$:	CALL	@(SP)+		;;;CALL THE CALLER BACK
	MOV	(SP)+,R3	;;;RESTORE R3
	RETURN			;;;EXIT FROM INTERRUPT

	.DSABL	LSB

;+
; **-$DM11B-DM11-BB MODEM CONTROL MULTIPLEXER INTERRUPTS
;-

	.IF DF	D$$M11

$DM11B::			;;;REF LABEL

	.IF NDF	L$$DRV!M$$MGE!LD$TT

	.IF GT	D$$M11-1

	MFPS	DHTMP		;;;SAVE CONTROLLER NUMBER

	.IFTF

	CALL	$INTSV,PR5	;;;SAVE REGISTERS AND SET PRIORITY
	MOV	R3,-(SP)	;;;SAVE R3 AND R2
	MOV	      R2,-(SP)	;;;

	.IFT

	MOV	DHTMP,R3	;;;RETRIEVE SAVED PS WORD
	BIC	#177760,R3	;;;CLEAR ALL BUT CONTROLLER NUMBER
	ASL	R3		;;;CONVERT TO WORD INDEX

	.IFF

	CLR	R3		;;;SET CONTROLLER NUMBER TO ZERO

	.ENDC

	.IFF			;;; NDF L$$DRV!M$$MGE!LD$TT

	MOV	R3,-(SP)	;;;SAVE R3 AND R2
	MOV	R2,-(SP)	;;;

	.IF GT	D$$M11-1

	MOV	R4,R3		;;;EXEC INTERRUPT ROUTINES PUT
				;;; CONTROLLER NUMBER IN R4

	.IFF

	CLR	R3		;;;SET CONTROLLER NUMBER TO ZERO

	.ENDC

	.ENDC			;;; NDF L$$DRV!M$$MGE!LD$TT      

	MOV	DMTBL(R3),R4	;;;GET ADDRESS OF DM11-BB CSR
	BEQ	50$		;;;IF EQ SPURIOUS INTERRUPT
	MOV	(R4)+,R5	;;;GET INTERRUPT STATUS
	MOV	R5,-(SP)	;;;SAVE INTERRUPT STATUS
	BIC	#177760,R5	;;;CLEAR ALL BUT UNIT NUMBER
	ASL	R5		;;;CONVERT UNIT NUMBER TO WORD INDEX
	ADD	DHTBL(R3),R5	;;;CALCULATE ADDRESS OF UCB ADDRESS
	MOV	(R5),R5		;;;GET ADDRESS OF UCB
	BNE	4$		;;;IF NE CORRESPONDING DH11 UCB EXISTS
	TST	(SP)+		;;;REMOVE INTERRUPT STATUS FROM STACK
	BR	50$		;;;IGNORE INTERRUPT
4$:	BIS	#7,(R4)		;;;SET REQ      UEST SEND+DATA ENABLE+
				;;; RING ENABLE
	MOV	(R4),R2		;;;GET UNIT STATUS
	COM	R2		;;;COMPLEMENT UNIT STATUS
	BIC	#1200,-(R4)	;;;REENABLE SCANNING
	ASL	(SP)		;;;RING, CARRIER, CLEAR TO SEND			; EB269
										; EB269
	.IF DF	XONSIG								; EB269
										; EB269
	BIT	#<XONBIT*2>,(SP)+ ;;; OR XON SIGNAL?				; EB269
										; EB269
	.IFTF									; EB269
										; EB269
	BCS	10$		;;;IF CS RING					;**-1
										; EB269
	.IFT									; EB269
										; EB269
	BEQ	7$		;;;IF EQ NOT X      ON SIGNAL				; EB269
										; EB269
;										; EB269
; XON SIGNAL TRANSITION								; EB269
;										; EB269
										; EB269
	BIT	#U2.HFF,U.CW2(R5)	;;;IGNORE XON SIGNAL?			; EB269
	BEQ	7$		  	;;;IF EQ YES				; EB269
	BITB	#XONBI2,R2		;;;XON SIGNAL ASSERTED?			; EB269
	BEQ	6$			;;;IF EQ YES				; EB269
	BIS	#UOFF,U.CNT+2+ATERS(R5) ;;;ACT LIKE GOT AN XOFF			; EB269
	BR	7$			;;;					; EB269
6$:	BIC	#UOFF,U.CNT+2+ATERS(R5)	;;;ACT LIKE GOT AN XON			; EB269
										; EB269
	.IIF NE UPND-20      0,	.ERROR UPND					; EB269
										; EB269
	TSTB	U.CNT+2+ATERS(R5) ;;;OUTPUT BYTE PENDING?			; EB269
	BPL	7$		  ;;;IF PL NO					; EB269
	MOV	R3,-(SP)	;;;SAVE R3					; EB269
	MOVB	U.CNT+2+DHBUF(R5),-(SP)	;;;GET HELD UP BYTE			; EB269
	BIC	#UPND,U.CNT+2+ATERS(R5)	;;;CLEAR OUTPUT BYTE			; EB269
					;;;PENDING FLAG				; EB269
	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS				; EB269
	CALL	FCHAR		;;;OUTPUT BYTE (DESTROYS R3)			; EB269
	MOV	(SP)+,R3	;;;RESTORE R3					; EB269
										; EB269
	.ENDC									      ; EB269
										; EB269
7$:				;;;REFERENCE LABEL				; EB269

;
; CARRIER OR CLEAR TO SEND TRANSITION
;

	MOVB	#DMGLTC,U.CNT+2+DMTIM(R5) ;;;ASSUME CARRIER OR CLEAR		; EB266
					  ;;;TO SEND NOT SET			; EB266
	BIT	#140,R2		;;;CARRIER AND CLEAR TO SEND SET?		;**-1
	BNE	40$		;;;IF NE NO
	BITB	#US.DSB,U.STS(R5) ;;;UNIT DISABLED?
	BEQ	30$		;;;IF EQ NO
	BR	20$		;;;FINISH IN COMMON CODE

;
; RING TRANSITION
;

10$:	MOVB	#7,U.CNT+2+DMTIM(R5) ;;;ASSUME CARRIER OR CLR TO SEND NOT SET
	BIT	#140      ,R2		;;;CARRIER AND CLEAR TO SEND SET?
	BNE	40$		;;;IF NE NO
20$:	BICB	#US.DSB,U.STS(R5) ;;;ENABLE UNIT
	CALL	COPASP			;;;COPY ANSWER BAUD RATE TO CURRENT	;TMM035
					;;;TRANSMIT AND RECEIVE BAUD RATES	;TMM035
	MOV	DHCSR(R3),R2		;;;GET ADDRESS OF DH11 CSR		;TMM035
	CALL	SETLIN			;;;SET NEW LINE CHARACTERISTICS		;TMM035
										; EB267
	.IF DF USECDH								; EB267
	.IFF									; EB267
										; EB267
	BIC	#U2.CRT!U2.ESC!U2.HLD!U2.L3S!U2.VT5!U2.LWC,U.CW2(R5) ;;;	;**-12
	BIC	#U3.UPC,U.CW3(R5      )	;;;CLEAR OUT ASR33 TYPE ON ANSWER	;TMM036
	MOV	#72.,U.CW4(R5)	;;;SET INITIAL BUFFER SIZE
										; EB267
	.ENDC									; EB267
										; EB267
	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS
	TSTB	S.STS(R4)	;;;IS I/O IN PROGRESS?
	BNE	30$		;;;IF NE YES
	BICB	#US.BSY!US.ECH!US.OUT,U.STS(R5) ;;;CLEAR BITS THAT
						;;;SHOULD NEVER BE SET
30$:	BICB	#US.CRW,U.STS(R5) ;;;CLEAR CARRIER WAIT
	BR	50$		;;;
40$:	BISB	#US.CRW,U.STS(R5) ;;;SET CARRIER WAIT
50$:	MOV	(SP)+,R2	;;;RESTORE R2 AND R3
	MOV	(SP)+,R3      	;;;
	RETURN			;;;EXIT FROM INTERRUPT

;
; SUBROUTINE TO HANG UP A DM11-BB UNIT IF NOT READY
;
; INPUTS:
;
;	R1=CSR ADDR OF DM11-BB
;	R5=UCB ADDR
;
; OUTPUTS:
;
;	NO REGISTERS ARE DESTROYED
;	UCB AND DM11-BB STATUSES ARE MODIFIED
;

DMHUP:	BICB	#US.CRW!US.DSB,U.STS(R5) ;;;CLEAR CARRIER WAIT AND ENABLE UNIT
	BIC	#1040,(R1)	;;;DISABLE SCAN
10$:	BIT	#20,(R1)	;;;SCAN STOPPED?
	BNE	10$		;;;IF NE NO
	MOV	(R1),-(SP)	;;;CANNOT USE BYTE INSTRUCTIONS
				;;; ON DM11-BB (UNDOCUMENTED)
	BIC	#1017      ,(SP)	;;;CLEAR CURRENT UNIT
	BISB	U.UNIT(R5),(SP)	;;;SET DESIRED UNIT
	MOV	(SP)+,(R1)+	;;;TELL DM11-BB ABOUT IT
	BIS	#7,(R1)		;;;SET REQUEST SEND+DATA ENABLE+RING ENABLE
	MOV	(R1),-(SP)	;;;GET CURRENT UNIT STATUS
	COM	(SP)		;;;COMPLEMENT UNIT STATUS
	BIT	#140,(SP)+	;;;CARRIER AND CLEAR TO SEND SET?
	BEQ	20$		;;;IF EQ YES
	BISB	#US.DSB,U.STS(R5) ;;;DISABLE UNIT
	BIC	#17,(R1)	;;;CLEAR CURRENT UNIT STATUS
	INC	(R1)		;;;ENABLE RING INTERRUPT
	CLC			;;;INDICATE UNIT HUNG UP
20$:	BIS	#140,-(R1)	;;;RES      TART SCAN AND ENABLE INTERRUPT
	RETURN			;;;

;
; DMTMO - DM11-BB TIME OUT ROUTINE
;
; THIS ROUTINE IS ENTERED EVERY 4 SECONDS FROM THE TIME DEPENDENT SCHEDULER
; TO CHECK FOR DM11-BB TIMEOUTS.
;
; INPUTS:
;
;	NONE
;
; OUTPUTS:
;
;	ALL DM11-BB UNITS ARE EXAMINED FOR TIMEOUT. IF A TIMEOUT OCCURS,
;	THEN THE UNIT IS HUNG UP.
;

DMTMO:	MOV	#D$$M11,R0	;SET NUMBER OF DM11-BB'S
	CLR	R3		;CLEAR CONTROLLER INDEX
10$:	MOV	DHTBL(R3),R2	;GET ADDRESS OF UCB TABLE
20$:	MTPS	#0		;ALLOW DEVICE INTERR      UTPS
	MOV	(R2)+,R5	;GET ADDRESS OF NEXT UCB
	BEQ	30$		;IF EQ END OF LIST
	BITB	#US.OFL,U.ST2(R5) ;IS THE LINE OFFLINE?
	BNE	30$		;IF NE YES -- OTHERS ARE ALSO
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MTPS	S.PRI(R4)	;;;LOCK OUT DEVICE INTERRUPTS
	BITB	#US.CRW,U.STS(R5) ;;;WAITING FOR CARRIER?
	BEQ	20$		;;;IF EQ NO
	DECB	U.CNT+2+DMTIM(R5) ;;;ANY TIME REMAINING?
	BNE	20$		;;;IF NE YES
	MOV	DMTBL(R3),R1	;;;GET ADDRESS OF DM11-BB CSR
	CALL	DMHUP		;;;HANG UP UNIT
	BCS	20$		;;;IF CS UNIT NOT HUNG UP
	C      ALL	TTHUP		;;;DO SPECIAL I/O CANCEL FOR HANGUP
	BR	20$		;;;
30$:	TST	(R3)+		;ADVANCE CONTROLLER INDEX
	DEC	R0		;ANY MORE DM11-BB'S?
	BGT	10$		;IF GT YES

	.IF DF	L$$DRV&LD$TT

	MOV	CLKSW,R0	;POINT AT CLOCK QUEUE CONTROL BLOCK

	.IFF

	MOV	#CLKSW+2,R0	;GET ADDRESS OF CLOCK QUEUE CONTROL BLOCK

	.ENDC

DMCLK:	CLR	R1		;ZERO HIGH ORDER DELTA TIME
	MOV	$TKPS,R2	;GET CLOCK TICKS PER SECOND
	ASL	R2		;CONVERT TO 4 SECOND INTERVAL
	ASL	R2		;
INSCLK:	MOV	#C.SYST,R4	;SET TYPE TO SYSTEM SUBROUTINE
      	CALLR	$CLINS		;INSERT ENTRY IN CLOCK QUEUE

	.ENDC			; DF D$$M11

	.IF DF	D$$ZMD

;+
; DZTMO - DZ11 TIME OUT ROUTINE
;
; THIS ROUTINE IS ENTERED EVERY HALF SECOND TO CHECK FOR ANY
; CHANGE IN CARRIER STATUS ON ANY DZ11 REMOTE LINE.
;
; INPUTS:
;
;	NONE
;
; OUTPUTS:
;
;	DESTROYS R0, R1, R2, R3, R4, R5
;
;	IF A REMOTE ENABLED LINE LOSES CARRIER, IT IS HUNG UP.  IF
;	A REMOTE, DISABLED LINE ASSERTS CARRIER, IT IS ENABLED ON THE
;	ASSUMPTION THAT IT HAS RUNG AND HAS BEEN ANSWERED.  ANSWER      ING
;	IS AUTOMATIC FOR LINES THAT HAVE DATA TERMINAL READY ASSERTED,
;	AND LINE HANG UP IS AUTOMATIC WHEN DTR IS DEASSERTED.
;	DISABLED IS A LOGICAL STATUS WHERE TTDRV IGNORES ANY INPUT
;	FROM THE LINE AND REJECTS ANY OUTPUT TO IT.
;
; NOTE:	NOT ALL MODEMS CAN BE CORRECTLY HANDLED BY THIS CODE.
;	THIS IS A CONSEQUENCE OF SOME TELEPHONE EXCHANGES,
;	SOME MODEMS, AND THE DZ11.  THE PRIMARY CONSTRAINTS
;	ARE:
;
;   1)	THE DZ11 PROVIDES ONLY A FEW MODEM CONTROL SIGNALS.
;
;   2)	THE DZ11 DOES NOT I      NTERRUPT ON CHANGES IN STATE OF
;	MODEM CONTROL SIGNALS.  AS A CONSEQUENCE, THE
;	SIGNALS MUST BE POLLED.  ANY POLLING PUTS A LOAD ON
;	THE CPU.  POLLING FAST ENOUGH TO HAVE A SIGNIFICANT
;	CHANCE OF CATCHING TRANSIENT SIGNALS PLACES AN
;	UNACCEPTABLE, FOR MOST INSTALLATIONS, BURDEN ON
;	THE CPU.
;
;   3)	THE RING SIGNAL IS NOT CONDITIONED OR LATCHED.
;	ITS SMOOTHNESS, SPIKINESS, DURATION, INTERVALS,
;	ETC. ARE A DIRECT FUNCTION OF THE TELEPHONE
;	EXCHANGE.  COMBINED WITH NUMBER 2 ABOVE, THIS
;	      MEANS THAT, IN GENERAL, RING CANNOT BE USED.
;	THE LARGEST PART OF DEALING WITH THE TELEPHONE
;	SYSTEM IS PLACED ON THE MODEM.
;-

DZTMO:	MOV	#D$$Z11,R0	;SAVE NUMBER OF DZ11'S IN SYSTEM
	CLR	R3		;START AT MULTIPLEXER ZERO
10$:	MOV	DZTBL(R3),R1	;GET ADDRESS OF UCB'S FOR THIS MUX		;TMM035
	MOV	DZCSR(R3),R2	;GET CSR ADDRESS FOR THIS MUX			;TMM035
20$:	MOV	(R1)+,R5	;GET UCB ADDRESS FOR NEXT LINE ON MUX		;TMM035
	BEQ	30$		;IF EQ NO MORE LINES TO EXAMINE			;**-3
	BIT	#U2.RMT,U.CW2(R5) ;THIS A REMOTE LI      NE?
	BEQ	20$		  ;IF EQ NO
	BITB	#US.OFL,U.ST2(R5) ;IS THE LINE OFFLINE?
	BNE	30$		  ;IF NE YES -- OTHER UNITS ARE ALSO
	MOVB	U.UNIT(R5),R4	;GET LINE NUMBER
	ASL	R4		;CONVERT TO WORD INDEX
	MOV	$BTMSK(R4),R4	;IN R4, ASSERT BIT N FOR UNIT N
	BITB	R4,5(R2)	;DTR ENABLED?					;TMM013
	BNE	21$		;IF NE YES					;TMM013
	BISB	R4,5(R2)	;ENABLE DTR FOR THIS LINE			;TMM013
	BR	20$		;DON'T CHECK FOR CARRIER UNTIL AFTER		;TMM013
				;NOISE FROM PREVIOUSLY ENABLING DTR SETTLES	;TMM013
				;LINE WILL GET CHECKE      D IN ANOTHER HALF SECOND	;TMM013
21$:	BITB	R4,7(R2)	;CARRIER ASSERTED?				;TMM013
	BEQ	25$		;IF EQ NO					;**-2
	BITB	#US.DSB,U.STS(R5) ;UNIT HUNGUP?
	BEQ	20$		  ;IF EQ NO
	CALL	COPASP		;COPY DEFAULT ANSWER BAUD RATE INTO RSP AND TSP	;TMM035
	MOV	DZCSR(R3),R2	;RESTORE CSR ADDRESS				;TMM035
	CALL	SETLIN		;SET UP LINE PARAMETERS				;TMM035
										; EB267
	.IF DF USECDZ								; EB267
	.IFF									; EB267
										;**-14
	BIC	#U2.CRT!U2.ESC!U2.HLD!U2.L3S!U2.VT5!U2.LWC,U.CW2(R5) ;
	BIC	#U3.UP      C,U.CW3(R5)	;RESET ASR33 TERMINAL TYPE ON ANSWER	;TMM036
	MOV	#72.,U.CW4(R5)	;START LINE IN A KNOWN STATE
										; EB267
	.ENDC									; EB267
										; EB267
	MOV	U.SCB(R5),R4	;GET SCB ADDRESS
	TSTB	S.STS(R4)	;IS I/O IN PROGRESS?
	BNE	23$		;IF NE YES
	BICB	#US.BSY!US.ECH!US.OUT,U.STS(R5) ;CLEAR BITS THAT
						;SHOULD NEVER BE SET
23$:	BICB	#US.DSB!US.CRW,U.STS(R5) ;ENABLE LINE (LOGICALLY
	BR	20$			 ;ANSWER IT)
25$:	BITB	#US.CRW,U.STS(R5) ;WAITING FOR CARRIER?
	BEQ	27$		  ;IF EQ NO
	DEC      B	U.CNT+2+DZTIM(R5) ;WAITED TOO LONG?
	BNE	20$		  ;IF EQ NO
	BICB	#US.CRW,U.STS(R5) ;SHOW NOT WAITING FOR CARRIER
	BICB	R4,5(R2)	;CLEAR MODEM (TELL IT TO HANG UP)		;TMM035
	BR	20$		  ;						;**-1
27$:	BITB	#US.DSB,U.STS(R5) ;LINE ALREADY HUNG UP?
	BEQ	28$		  ;IF EQ NO
	BISB	#US.CRW,U.STS(R5)    ;SHOW WAITING FOR CARRIER
	MOVB	#50,U.CNT+2+DZTIM(R5) ;INITIALIZE COUNTER
	BR	20$		;
28$:	BICB	R4,5(R2)	;LOWER DTR TO HANG UP				;TMM035
	MOV	U.SCB(R5),R4	;TTHUP MAY NEED SCB ADDRESS			;**-1
	CALL	TTHUP		      ;LOG OUT USER IF NECESSARY
	BCS	20$		;IF CS TRY TO SAY BYE LATER
	BISB	#US.DSB,U.STS(R5) ;DISABLE LINE (LOGICALLY HANGUP)
	BR	20$		;
30$:	TST	(R3)+		;INDEX TO NEXT MULTIPLEXER
	DEC	R0		;LOOKED AT THEM ALL?
	BGT	10$		;IF GT NO

	.IF DF	L$$DRV&LD$TT

	MOV	DZCLKS,R0	;POINT AT CLOCK QUEUE ENTRY

	.IFF

	MOV	#DZCLKS+2,R0	;REINSERT CLOCK ENTRY

	.ENDC

DZCLK:	CLR	R1		;ZERO HIGH ORDER DELTA TIME
	MOV	$TKPS,R2	;GET CLOCK TICKS PER SECOND
	ASR	R2		;WANT A HALF SECOND INTERVAL

	.IF DF	D$$M11
      
	BR	INSCLK		;INSERT ENTRY INTO CLOCK QUEUE

	.IFF

	MOV	#C.SYST,R4	;SET TYPE TO SYSTEM SUBROUTINE
	CALLR	$CLINS		;INSERT ENTRY IN CLOCK QUEUE

	.ENDC

	.ENDC			; DF D$$ZMD

;+										;TMM035
;** SETLIN **									;TMM035
;										;TMM035
; THIS ROUTINE SETS UP A DZ OR DH LINE AS SPECIFIED BY THE			;TMM035
; LINE CHARACTERISTICS (RSP,TSP,PARITY) IN U.CW3.				;TMM035
;										;TMM035
; INPUTS:									;TMM035
;	R5 -> UCB								;TMM035
;	R2 -> CSR								;TMM035
;										;TMM035
      ;										;TMM035
; OUTPUT:									;TMM035
;	APPROPRIATE LPR VALUE CHANGED						;TMM035
;	NO REGISTERS MODIFIED							;TMM035
;										;TMM035
; RESTRICTIONS:									;TMM035
;	THIS ROUTINE MUST BE CALLED AT DEVICE PRIORITY				;TMM035
;	THIS ROUTINE MAY ONLY BE CALLED FOR DZ'S OR DH'S			;TMM035
;										;TMM035
;-										;TMM035
	.IF DF	D$$Z11!D$$H11							;TMM035
										;TMM035
SETLIN:	MOV	U.CW3(R5),-(SP)		;;; GET CURRENT VALUE OF U.CW3		;TMM035
	SWAB	(SP)			;;; REFORMAT U.CW3 FOR L      PR TRANSFORMATIO;TMM035
										;TMM035
	.IF DF	D$$Z11&D$$H11							;TMM035
										;TMM035
	BIT	#U2.DZ1,U.CW2(R5)	;;; IS THIS A DZ OR DZV ?		;TMM035
	BEQ	2$			;;; IF EQ NO, MUST BE A DH		;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.IF DF	D$$Z11								;TMM035
										;TMM035
	BIC	#^C<7720>,(SP)		;;; CLEAR ALL BUT SPEED AND PARITY BITS	;TMM035
					;;; AND "FORCE TWO STOPBITS" BIT	;TMM035
	BIT	#20,(SP)		;;; FORCE TWO STOPBITS?			;TMM035
	BNE	4$			;;; IF NE YES				      ;TMM035
	CMP	(SP),#2000		;;; IS BAUD RATE 110 OR LESS?		;TMM035
	BHIS	1$			;;; IF HIS NO				;TMM035
4$:	BIS	#40,(SP)		;;; SET TWO STOP BITS			;TMM035
1$:	BIS	#10030,(SP)		;;; SET FOR EIGHT BIT CHARACTERS	;TMM035
	BISB	U.UNIT(R5),(SP)		;;; SET UP UNIT NUM			;TMM035
	MOV	(SP)+,2(R2)		;;; FINALLY, SET UP LPR			;TMM035
	RETURN									;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.IF DF	D$$H11								;TMM035
										;TMM035
2$:	ASR	(SP)			;;; SHIFT SPEED AND PARITY BITS		;TM      M035
	ASR	(SP)			;;; INTO THEIR LPR PLACES		;TMM035
	BIC	#^C<37764>,(SP)		;;; CLEAR ALL BUT TSP,RSP, AND PARITY	;TMM035
					;;; AND "FORCE TWO STOP BITS" BIT	;TMM035
	BIT	#4,(SP)			;;; FORCE TWO STOP BITS?		;TMM035
	BNE	3$			;;; IF NE YES				;TMM035
	BIT	#1400,(SP)		;;; TRANSMIT SPEED <= 110 BAUD ?	;TMM035
	BNE	3$			;;; IF NE NO				;TMM035
	BIS	#4,(SP)			;;; SET TWO STOP BITS			;TMM035
3$:	BIS	#3,(SP)			;;; SET FOR EIGHT BIT CHARACTERS	;TMM035
	BIC	#1077,(R2)		;;; RESET MAIN,MEM EXT, AND LINE NUM       BIT;TMM035
	BISB	U.UNIT(R5),(R2)		;;; SET LINE NUMBER			;TMM035
	MOV	(SP)+,4(R2)		;;; FINALLY, SET UP LPR			;TMM035
	RETURN									;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
	.ENDC									;TMM035
										;TMM035
;+										;TMM035
; ** COPASP -- COPY ANSWER BAUD RATE TO RECEIVE AND TRANSMIT SPEEDS		;TMM035
;										;TMM035
; THIS ROUTINE COPIES THE ANSWER BAUD RATE IN U.CW3 BITS (8-11) INTO		;TMM035
; THE RECEIVE SPEED (BITS 0-3) AND THE TRANSMIT SPEED (BITS 4-7)      .		;TMM035
;										;TMM035
; INPUTS:									;TMM035
;	NONE									;TMM035
;										;TMM035
; OUTPUTS:									;TMM035
;	U.CW3 IS ALTERED AS DESCRIBED ABOVE					;TMM035
;										;TMM035
;	R2 IS DESTROYED								;TMM035
;-										;TMM035
										;TMM035
	.IF DF	D$$ZMD!D$$M11							;TMM035
										;TMM035
COPASP:	CLRB	U.CW3(R5)	;CLR LOW ORDER BYTE (TSP AND RSP)		;TMM035
	MOV	U.CW3(R5),R2	;PICK UP ANSWER SPEED (BITS 8-11)		;TMM035
										;TMM035
	.ENDC									;TMM035
								      		;TMM035
	.IF DF	T$$SMC!D$$ZMD!D$$M11						;TMM035
										;TMM035
	.IF DF	D$$H11!D$$Z11!D$$ZMD!D$$M11					;TMM035
										;TMM035
SSSZSP:	CALL	SSSCW3		;DO SOME MAGIC TWICE				;TMM035
SSSCW3:	ASL	R2		;SHIFT LEFT FOUR TIMES, A NIBBLE IF U WILL	;TMM035
	ASL	R2								;TMM035
	ASL	R2								;TMM035
	ASL	R2								;TMM035
	SWAB	R2		;ANSWER BAUD RATE IN BITS (0-3)FIRST PASS	;TMM035
	BISB	R2,U.CW3(R5)	;BITS (4-8) SECOND PASS				;TMM035
	RETURN									;TMM035
										;TMM035
	.ENDC									;T   :   MM035
										;TMM035
	.ENDC									;TMM035
	.END
 :          # kQ	› c,        	.TITLE	EXDBT
	.IDENT	/05.11/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 05.11
;
; D. N. CUTLER 7-DEC-74
;
; PREVIOUSLY MODIFIED BY:
;
;	E. L. BAATZ
;	T. J. MILLER
;	E. L. BAATZ
;	J. E. PROVINO
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	22-DEC-80
;		MSH045 -- DRQIO FAULTS CAN ONLY OCCUR IF EXECUTI      VE
;			  COMMON MAPPED
;
;	M. S. HARVEY	24-DEC-80
;		MSH136 -- HANDLE FLOATING POINT EXCEPTION TRAPS FOR
;			  PROCESSORS WITH FIS
;
;	M. S. HARVEY	29-DEC-80
;		MSH137 -- OUTPUT ENTIRE SYSTEM ID ON VIRGIN BOOT AND
;			  MAKE SURE ALL OUTPUT IS ECHOED BEFORE
;			  TRANSFERRING TO $INITL ON VIRGIN BOOT
;
;	M. S. HARVEY	3-MAR-81
;		MSH155 -- ADD XON/XOFF SUPPORT
;
;	M. S. HARVEY	5-MAY-81
;		MSH165 -- MODIFY COMMON SUPPORT TO REFLECT THE
;			  EXISTENCE OF BOTH COMMONS
;
;	M. S. HARVEY	17-SEP      -81
;		MSH125 -- SET FATAL CRASH INDICATOR FOR CRASH ANALYSIS
;
; EXECUTIVE ODT
;
; THIS IS A VERSION OF ODT THAT MAY BE USED TO DEBUG RSX-11M EXECUTIVE
; MODULES. IT IS AN OUTGROWTH OF THE STANDARD RSX-11 ODT WHICH WAS PRO-
; DUCED BY M. SMITH , H. LEV ET. AL.
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS

;
; EQUATED SYMBOLS
;

BPT=3				;BREAKPOINT INSTRUCTION CODE
BKP=16				;NUMBER OF BREAKPOINTS -1 X 2
LPB=177516			;LINE PRINTER BUFFER REGISTER
LPS=      177514			;LINE PRINTER STATUS REGISTER
RLR=16				;NUMBER OF RELOCATION REGISTERS -1 X 2
TBT=20				;T-BIT MASK FOR PROCESSOR STATUS WORD
TKB=177562			;CONSOLE TERMINAL INPUT BUFFER REGISTER
TKS=177560			;CONSOLE TERMINAL INPUT STATUS REGISTER
TPB=177566			;CONSOLE TERMINAL OUTPUT BUFFER REGISTER
TPS=177564			;CONSOLE TERMINAL OUTPUT STATUS REGISTER

;
; LOCAL MACROS
;
; DECODE NEXT COMMAND
;

	.MACRO	DECODE
	IOT
	.ENDM

;
; ERROR
;

	.MACRO	ERROR
	EMT	0
	.ENDM

;
; TEST MODE FOR EX      EC OR USER
;

	.MACRO	TESTM ADDR
	JSR	R5,TESTM
	.WORD	ADDR
	.ENDM

;
; TYPE OUT CHARACTER(S)
;
;	TYPE OUT IS EFFECTED WITH A TRAP INSTRUCTION WITH THE BOTTOM
;	BYTE ENCODED AS FOLLOWS:
;
;		300 = OUTPUT BOTH BYTES IN R0.
;		200 = OUTPUT LOW BYTE IN R0.
;		340 = OUTPUT A <CR><LF> SEQUENCE.
;		240 = OUTPUT A <CR> SEQUENCE.
;
;		ALL OTHER COMBINATIONS ARE TREATED AS THE ACTUAL BYTE
;		TO OUTPUT.

	.MACRO	TYPE ARG
	.IF IDN	<ARG>,<R0>
	TRAP	200
	.IFF
	.IF IDN	<ARG>,<R0+R0>
	TRAP	300
	      .IFF
	.IF IDN	<ARG>,<CRLF>
	TRAP	340
	.IFF
	.IF IDN	<ARG>,<CR>
	TRAP	240
	.IFF
	TRAP	ARG&177
	.ENDC
	.ENDC
	.ENDC
	.ENDC
	.ENDM

;
; LOCAL DATA
;
; CONTEXT VARIABLES
; THE ORDER OF THESE ITEMS IS INTENTIONAL, SEE REGISTER MAPPING SCHEME
;

INTBEG	=.	;STARTING ADDRESS OF INTERNAL REGISTERS

UR0:	0			;USER R0			$0
	0			;     R1			$1
	0			;     R2			$2
	0			;     R3			$3
	0			;     R4			$4
	0			;     R5			$5
USP:	0			;USER SP			$6
UPC:	$INITL			;USER PC			$7
UST:	PR7			;USER PS		      	$S
ARG:	0			;ARGUMENT REGISTER		$A
LOW:	0			;LOW LIMIT			$L
HI:	0			;HIGH LIMIT			$H
CNST:	$XDT			;CONSTANT REGISTER		$C
QUAN:	0			;QUANTITY REGISTER		$Q
FORM:	0			;FORMAT REGISTER		$F

;
; INTERNAL TABLES
;

INTINX	=.		;STARTING ADDRESS OF INTERNAL TABLES

;
; BREAKPOINT CONTROL LISTS, AND EXTRA SLOT FOR SINGLE STEP
;

ADR1:		;ADDRESS OF THE BREAKPOINT	($0B-$7B)
	.WORD	TRTC,TRTC,TRTC,TRTC,TRTC,TRTC,TRTC,TRTC,TRTC

CT:		;PROCEED COUNT	($0G-$7G)
	.WORD	1,1,1,1,1,1,1,1,1

UIN:		;USER       INSTRUCTION SAVE LOCATION	($0I-$7I)
	.WORD	BPT,BPT,BPT,BPT,BPT,BPT,BPT,BPT,BPT

;
; RELOCATION REGISTERS
;

RELT:		;RELOCATION TABLES	($0R-$7R)
	.WORD	-1,-1,-1,-1,-1,-1,-1,-1

INTEND=.-2			;END OF INTERNAL REGISTERS AND TABLES

;
; EXEC SST TRAP VECTOR ADDRESSES
;

SSTVEC:	 +	ODDA		;0-ODD ADDRESS, OR HALT, VECTOR @4


	.IF	DF M$$MGE

	 +	SGMT		;1-SEGMENT FAULT

	.IFF

	+	$NONSI		; NO SEGMENT FAULT POSSIBLE

	.ENDC


	 +	BPTI		;2-T-BIT OR BPT
	 +	IOTX		;3-IOT
	 +	ILLI		;4-RESE      RVED OR ILLEGAL INSTRUCTION
	 +	NEMT		;5-EMT
	 +	TRPI		;6-TRAP

	.IF DF	F$$LTP							;MSH136
									;MSH136
	+	FPPE		;7-FLOATING POINT TRAP			;MSH136
									;MSH136
	.ENDC								;MSH136

;
; WORDS AND ORDERED BYTES, ITEMS MUST BE KEPT FROM COMMAND TO COMMAND
;

CAD:	.WORD	0		;ADDRESS OF CURRENTLY OPEN REGISTER
DOT:	.WORD	0		;ADDRESS OF LAST EXPLICITLY OPENED CELL
BW:	.WORD	0		;LAST OPEN MODE 1=BYTE, 2=WORD
OPN:	.WORD	0		;LOCATION OPEN FLAG 0=NOT OPEN, NON-ZERO=OPEN
D.ARGS:	.WORD	0		;S      EMI COLON PUSH WORD

;
; THE FOLLOWING ITEMS NEED NOT BE KEPT FROM COMMAND TO COMMAND
; THEIR ORDER IS INTENTIONAL SO KNOW THY MAKER!
;

OP:	.BYTE	0		;CURRENT ARITHMETIC OPERATOR
SMFD:	.BYTE	0		;SEMI-COLON COUNTER
EXP:	.WORD	0		;EXPRESSION BUCKET
OUTB:	.WORD	TPB		;CONSOLE PRINTER BUFFER ADDRESS
OUTS:	.WORD	TPS		;CONSOLE PRINTER STATUS REGISTER
PPC:	.BLKW	1		;SAVED PC LAST BREAKPOINT

;
; THE FOLLOWING ITEMS MUST BE KEPT FROM COMMAND TO COMMAND.
;

T:	.BYTE	0		;T BIT IN USE FLAG
P:	.BYTE	-      1		;PROCEED ALLOW FLAG
S:	.BYTE	0		;SINGLE INSTRUCTION MODE, 0=NORMAL, >0=ENABLE
FM:	.BYTE	2		;OUTPUT FORMAT MODE, BYTE, WORD, ANSII, RAD50
OBW:	.BYTE	2		;OPEN CELL TYPE, 1=BYTE, 2=WORD
SEQ:	.BYTE	0		;CHANGE SEQUENCE INDICATIOR

;
; THE BELOW LOCATION IS USED IN BREAKPOINT PROCESSING
;

TRTC:	BPT		;TRACE TRAP PROTOTYPE

;
; ALL XDT TYPE ERRORS JUST GO TO "ERR" OR SOMEWHERE ELSE
;

SSTXDT:	 +	ERR		;0-ODD ADDRESS
	 +	ERR		;1-SEGMENT FAULT
	 +	ERR		;2-BPT OR T-BIT ("MCR" CALL)
	 +	DCD		;3-IO      T ("DECODE")
	 +	ERR		;4-RESERVED OR ILLEGAL INSTRUCTION
	 +	ERR		;5-EMT ("ERROR")
	 +	TYPE		;6-TRAP
									;MSH136
	.IF DF	F$$LTP							;MSH136
									;MSH136
	+	ERR		;7-FLOATING POINT EXCEPTION		;MSH136
									;MSH136
	.IFTF								;MSH136
									;MSH136

;
; SST VECTOR ADDRESS TABLE
;

SSTADR:	.WORD	4		;ODD ADDRESS
	.WORD	250		;SEGMENT FAULT
	.WORD	14		;BPT
	.WORD	20		;IOT
	.WORD	10		;ILLEGAL INSTRUCTION
	.WORD	30		;EMT
	.WORD	34		;TRAP
									;MSH136
	.IFT								;MSH13      6
									;MSH136
	.WORD	244		;FLOATING POINT				;MSH136
									;MSH136
	.ENDC	;F$$LTP							;MSH136
									;MSH136

;
; INTERNAL REGISTER NAME AND CONTROL TABLES
;
; NON-INDEXED REGISTER NAMES
;

NIXMAP:	.ASCII	/01234567/	;USER REGISTER NAMES FOR MAPPING

NIXREG:	.BYTE	'S		;UST	USER STATUS
	.BYTE	'A		;ARG	ARGUMENT
	.BYTE	'L		;LOW	LOW SCAN LIMIT
	.BYTE	'H		;HI	HIGH SCAN LIMIT
	.BYTE	'C		;CNST	CONSTANT
	.BYTE	'Q		;QUAN	QUANTITY
	.BYTE	'F		;FORM	FORMAT CONTROL
	.BYTE	0		;END OF THIS       LIST

;
; INDEXED REGISTER NAMES
;

INXREG:	.BYTE	'B		;ADR1	BKPT ADDRESSES
	.BYTE	'G		;CT	BKPT PROCEED COUNTS
	.BYTE	'I		;UIN	BKPT USER INSTRUCTIONS
	.BYTE	'R		;RELT	RELOCATION REGISTERS
	.BYTE	0		;END OF THIS LIST

;
; INDEXED REGISTER TABLE BASES
;

	.EVEN
INXTBL:	.WORD	ADR1		;BKPT ADDRESS TABLE
	.WORD	CT		;BKPT PROCEED COUNTS
	.WORD	UIN		;BKPT'D INSTRUCTION
	.WORD	RELT		;RELOCATION TABLES
	.WORD	INTEND+2	;END OF TABLE AREA FOR ADDRESS MAPPING

;
; CHARACTER CONVERSION LISTS.
;
      
ALTTAB:	.BYTE	033,175,176	;ALTERNATE ALT-MODE FORMS
	.BYTE	0		;END OF THIS LIST TOO

;
; COMMAND NAME AND DISPATCH TABLES
;

COMTAB:		;ADDRESS OF THE CHARACTER TABLE

;
; OPEN REGISTER COMMANDS (ORDER AND POSITION CRITICAL)
;

	.BYTE	'\,'/,'','",'%

;
; CLOSE REGISTER COMMANDS
;

	.BYTE	015,012,'^,'_,'@,'>,'<

;
; SPECIAL FORMS
;

	.BYTE	021,'$,'=,'C,'Q,'.					;MSH155
									;**-1
;
; OPERATORS (ORDER OF -+* IS CRITCAL)
;

	.BYTE	';,'-,'+,'*,',

;
; COMMANDS
;

	.ASC      II	/BGKLOPRSX/
	.BYTE	0		;******* END OF THE LIST *******
	.EVEN

;
; THE DISPATCH TABLE, ORDERED ON ABOVE TABLE
;
; OPEN REGISTER COMMANDS
;

COMDIS:	.WORD	OCBYTE		;\	OPEN OCTAL BYTE
	.WORD	OCWORD		;/	OPEN OCTAL WORD
	.WORD	ANBYTE		;'	OPEN ANSII BYTE
	.WORD	ANWORD		;"	OPEN ANSII WORD
	.WORD	MODULO		;%	OPEN RADIX 50 WORD

;
; CLOSE REGISTER COMMANDS
;

	.WORD	CLCRET		;<CR>	CLOSE, NO SUCESSIVE OPEN
	.WORD	CLLNFD		;<LF>	CLOSE, OPEN NEXT
	.WORD	CLUPAR		;^	CLOSE, OPEN PREVIOUS
	.WORD	CLBA      CK		;_	CLOSE, OPEN PC RELATIVE MODE
	.WORD	CLATSG		;@	CLOSE, OPEN INDIRECT
	.WORD	CLGRTH		;>	CLOSE, OPEN PC OFFSET AS BRANCH
	.WORD	CLLSTH		;<	CLOSE, OPEN OLD SEQUENCE

;
; SPECIAL FORMS
;

	.WORD	DCD		;^Q	NULL, TERMINATE INPUT STRING	;MSH155
	.WORD	REGT		;$	INTERNAL REGISTER REFERENCE
	.WORD	EQUALS		;=	PRINT LEFT SIDE IN OCTAL
	.WORD	CHRCEE		;C	CONSTANT REGISTER CONTENTS
	.WORD	CHRQUE		;Q	QUANTITY REGISTER CONTENTS
	.WORD	CHRDOT		;.	LAST OPENED LOCATION'S ADDRESS

;
; OPERATORS
;

	.WOR      D	SEMI		;;	MULTIPLE ARGUMENT DELIMITER
	.WORD	MINS		;-	SUBTRACTION
	.WORD	PLUS		;+	.WORD	ADDITION
	.WORD	STAR		;*	MULTIPLY BY 50
	.WORD	COMM		;,	RELOCATION COMPUTE

;
; COMMANDS
;

	.WORD	SEBK		;B	SET / CLEAR BREAKPOINTS
	.WORD	GOTO		;G	GO TO USER'S DATA
	.WORD	KILO		;K	KOMPUTE AND TYPE RELOCATION DATA
	.WORD	LIST		;L	LIST MEMORY ON SPECIFIED DEVICE
	.WORD	OFST		;O	TYPE PC RELATIVE OFFSETS
	.WORD	PROC		;P	PROCEED FROM BREAKPOINT
	.WORD	RELO		;R	SET / RESET RELOCATION REGISTERS
	.WORD	SNGL		      ;S	SET / RESET SINGLE STEP MODE
	.WORD	EXIT		;X	EXIT TO CRASH ROUTINE

;+
; **-$XDT-RSX-11M EXECUTIVE ODT
;-

	.ENABL	LSB
$XDT::	MTPS	#PR7		;LOCK OUT INTERRUPTS
	MOV	SP,USP		;SAVE ENTRY STACK POINTER
	MOV	#USP,SP		;SET NEW STACK POINTER ADDRESS
	MOV	R5,-(SP)	;SAVE REGISTERS R5 THRU R0
	MOV	R4,-(SP)	;
	MOV	R3,-(SP)	;
	MOV	R2,-(SP)	;
	MOV	R1,-(SP)	;
	MOV	R0,-(SP)	;
	MOV	PC,SP		;CHANGE STACK POINTER
	MOV	#SSTADR,R0	;POINT TO TRAP VECTOR ADDRESS TABLE
	MOV	#SSTXDT,R1	;POINT TO XDT TRAP VECTOR       TABLE
10$:	MOV	(R1)+,@(R0)+	;INSERT XDT TRAP VECTOR ADDRESSES
	CMP	R1,#SSTADR	;ANY MORE TO SET?
	BLO	10$		;IF LO YES
	MOV	PC,SP		;LENGTHEN STACK
	TYPE	CRLF		;PLACE TERMINAL CARRIAGE IN PROPER POSITION
	TYPE	'X		;OUTPUT XDT IDENTIFICATION
	TYPE	'D		;
	TYPE	'T		;
	TYPE	':		;
	TYPE	40		;
	MOV	$SYSID,R0	;GET SYSTEM IDENTIFICATION
	TYPE	R0+R0		;OUTPUT SYSTEM IDENTIFICATION
	MOV	$SYSID+2,R0	;GET SECOND HALF OF SYSTEM ID		;MSH137
	TYPE	R0+R0		;OUTPUT SECOND HALF			;MSH137
	TYPE	CRLF		;PLACE TERMINA      L CARRIAGE IN PROPER POSITION
	JSR	SP,DCD		;DECODE NEXT COMMAND
XDTSTK:				;REF LABEL - START OF XDT STACK
	.DSABL	LSB
	.SBTTL	COMMAND PROCESSORS, SECTION ONE ( $ B R K A Q . )

.SBTTL "$,<ALT-MODE>" PROCESSOR - INTERNAL REGISTER MAPPER

;SYNTAX--
;$L		DELIVER INTERNAL ADDRESS OF L
;$NL		DELIVER INTERNAL ADDRESS OF L+2N
;$N		DELIVER INTERNAL ADDRESS OF USER REGISTER N

;SEE MAPPING TABLES, RANGE OF N IS 0-7

REGT:	JSR	PC,GETNUM	;GET AN OCTAL NUMBER
	JSR	PC,RTST		;CHECK FOR ERROR
	BCS	ERR0	      	;MPY R4 X 2
	TST	R2		;SEE IF ANYTHING TYPED
	BNE	10$		;IF SO IS INDEXED OR USER REGISTER
	JSR	R5,LOOKUP	;SEE IF NON-INDEXED
	 +	NIXREG
	BCS	12$		;NON-INDEXED TURNS INTO A COMMAND
	MOV	R1,R4		;PLACE IN LIST IS INTERNAL ORDER
	ADD	#UST,R4		;GET ADDRESS IN R4, GOTTA READ CHAR
	BR	20$
10$:	JSR	R5,LOOKUP	;SEE IF INDEXED
	 +	INXREG
	BCC	15$		;WAS TRULY INDEXED
12$:	CMP	#7+7,R4		;INTERNAL USER REGISTER RANGE CHECK
	BLO	ERR0
	ADD	#UR0,R4		;SET ACCESS TO R0-R7 OF THE USER
	BR	25$		;AVOID READING OF C      OMMAND
15$:	ADD	INXTBL(R1),R4	;COMPUTE ADDRESS TO INDEXED TABLE
20$:	JSR	PC,GET		;GET THE ASSUMED TERMINATOR
25$:	INC	R2		;SHOW THEM THAT R4 GOT VALID DATA
	JMP	CLGL		;RE-USE CHARACTER, R2 IS NON-ZERO
.SBTTL "B" PROCESSOR - SET AND REMOVE BREAKPOINTS

;SYNTAX--
;B			CLEAR ALL BREAKPOINTS
;NB			CLEAR BKPT N
;A;B			SET BKPT AT A, USE FIRST FREE  BKPT
;A;NB			SET BKPT N AT A

;DEPENDS MIGHTILY UPON LOCATION "TRTC" CONTAINING A TRAP INST.
;AND THAT A FREE BKPT CONTAINS THE ADDRESS "TRTC".

SEBK      :	ASL	R4		;MPY R4 X2, JUST IN CASE ALL IS GO
	MOV	#TRTC,R0	;SET MAGIC VALUE IN R0, JUST IN CASE
	TST	R3		;CHECK FOR THE REAL CASE
	BEQ	REMB		;REMOVAL CASES, CLEAR THEM UP
	BIT	#1,R5		;LOOK AT ADDRESS
	BNE	ERR		;THAT'S ODD ?
	TST	R2		;SEE IF I GET TO PICK IT OR NOT
	BNE	15$		;OR NOT, DISAPPOINTMENT
10$:	CMP	R0,ADR1(R4)	;LOOK FOR LOCATION WITH FREE ADDRESS
	BEQ	15$		;A HIT
	TST	(R4)+		;KEEP AT FOR A LONG WHILE
	BR	10$		;LOOOOOOOOP
15$:	MOV	R5,R0		;R0 HAS ADDRESS OF BREAKPOINT
	BR	RE02		;GO TUCK I      T IN

;REMOVE SOME BREAKPOINTS

REMB:	TST	R2		;SEE IF ONE OR ALL
	BEQ	RALL		;ALL
RE02:	JSR	PC,SETBRK	;SET THE ONE SET UP TO SET
	BCC	DCD		;IT HAPPENED
ERR0:	ERROR			;SOME THING WENT WRONG

;
; REMOVE ALL BREAKPOINTS
;

RALL:	CLR	R4		;R4 IS ZERO
10$:	JSR	PC,SETBRK	;SET THEM TILL
	BCC	10$		;THEY GET OUTTA
	DECODE			;HAND!!!!

;
; SUBROUTINE TO SET/CLEAR BREAKPOINTS
;

SETBRK:	CMP	#BKP,R4		;LEGAL BREAKPOINT NUMBER?
	BLO	10$		;IF LO NO
	MOV	R0,ADR1(R4)	;SET BREAKPOINT ADDRESS
	MOV	(R0)      ,UIN(R4)	;SAVE CONTENTS OF BREAKPOINT LOCATION
	MOV	#1,CT(R4)	;SET INITIAL PROCEED COUNT
	TST	(R4)+		;ADVANCE BREAKPOINT NUMBER
10$:	RETURN			;
.SBTTL "R" PROCESSOR - RELOCATION REGISTER PROCESSING

;DETERMINE IF CLEAR OR SET

RELO:	TSTB	SMFD		;SEMI-COLON ABSENT MEANS CLEAR
	BEQ	10$		;CLEAR DISPATCH, OR FALL TO SETTING

;FORMS HERE--
; A;NR			SET RELOC(N) TO A
;ABSENT A OR N DEFAULTS TO 0

	JSR	PC,RTST		;PROTECTION EDITING
	BCS	ERR		;ILLEGAL REGISTER NUMBER ?
	MOV	R5,RELT(R4)	;SET THE APPR      OPRIATE REGISTER
	DECODE			;GO GET NEXT COMMAND

;FORMS HERE--
;R			RESET ALL TO -1 FOR RELOC(0-7)
;NR			RESET ONLY RELOC(N)

10$:	TST	R2		;SEE IF NR OR JUST R
	BEQ	15$		;CLEAR ALL
	JSR	PC,RUCL		;CLEAR THE ONE IN R4
	BCS	ERR		;ERROR, INVALID REGISTER ?
	DECODE			;NEXT COMMAND
15$:	JSR	PC,RUAL		;DO THEM ALL
	DECODE			;OFF AND ON

;
; SUBROUTINE TO RESET RELOCATION BASE REGISTER
;

	.ENABL	LSB
RUCL:	CALL	RTST		;TEST FOR LEGAL REGISTER
	BCS	10$		;IF CS ILLEGAL REGISTER
	MOV	#-1,RELT(R4)	;      RESET RELOCATION REGISTER
	ASR	R4		;CONVERT BACK TO REGISTER NUMBER
10$:	RETURN			;

;
; SUBROUTINE TO CLEAR ALL RELOCATION REGISTERS
;

RUAL:	CLR	R4		;START WITH REGISTER 0
20$:	CALL	RUCL		;CLEAR NEXT RELOCATION REGISTER
	BCS	10$		;IF CS ALL DONE
	INC	R4		;ADVANCE TO NEXT REGISTER
	BR	20$		;
	.DSABL	LSB
.SBTTL "K" PROCESSOR - COMPUTE AND PRINT RELOCATION

;SYNTAX--
;AK				TYPE RELOCATION DEAL FROM DOT TO A
;L;AK				TYPE RELOCATION DEAL FROM L TO A

;IF A IS NULL THE THE OLD BEST FIT RU      LE APPLIES
;TYPES	=N,DDDDDD	WHERE N IS THE RELOCATION REGISTER
;				AND D-D IS THE RELOCATION BIAS

KILO:	TST	R2		;SEE WHO PICKS THE REGISTER
	BNE	10$
	TST	R3		; ADDRESS SPECIFIED?
	BNE	5$		; YES
	MOV	CAD,R4		; NO, GET CURRENT ADDRESS
	BR	7$		;
5$:	MOV	R5,R4		; GET ADDRESS SPECIFIED ON COMMAND
7$:	JSR	PC,LOCA		; GET CLOSEST RELOCATION REGISTER
	MOV	R0,R4		;DID WE FIND A RELOCATION REGISTER?
	BMI	ERR		;CAN'T FIND ONE THATS GOOD
10$:	BIC	#177770,R4	;EDIT REGISTER
	TYPE	'=		;OUTPUT CUE
	TYPE	40      		;
	MOVB	R4,R0		;TYPE REGISTER & A ,
	ADD	#"0,,R0
	TYPE	R0+R0		;
	ASL	R4		;GO GET IT AS TABLE INDEX
	TST	R3		;SEE WHO TYPED THE ADDRESS
	BNE	15$
	MOV	CAD,R5		;THAT CAD!
15$:	SUB	RELT(R4),R5
	MOV	R5,R0		;BIAS COMPUTE
	JSR	PC,CADW		;PRINT AS WORD
	DECODE

.SBTTL "A-Q-." PROCESSORS - SPECIAL VALUES

;MERELY SUBSTITUTE THE VALUE IN R4 WITH THE CONTENTS OF THE SPECIFIED
;REGISTER.

CHRQUE:	MOV	QUAN,R4		;LAST QUANTITY PRINTED
	BR	CHR001
CHRCEE:	MOV	CNST,R4		;CONSTANT REGISTER
	BR	CHR001
CHR      DOT:	MOV	CAD,R4		;CURRENT LOCATION
CHR001:	INC	R2		;ALLOW AS R4 IS REAL
	JSR	PC,GET		;GET NEXT CHARACTER AND ASSUME
	BR	CLGL		;IT IS A TERMINATOR
	.SBTTL	COMMAND DE-CODER AND MAIN LOOP OF ODT

; COMMAND DECODER - ODT

;  ALL REGISTERS MAY BE USED (R0-R5),

;ERROR ENTRY, TYPE FLAG AND GO DO COMMAND

ERR:	CALL	SETCN		;SET OUTPUT FOR CONSOLE
	TYPE	'?		;OUTPUT ERROR INDICATION

;
; DECODE FROM THE TOP, CLOSE ALL AND DO CR/LF/_
;

DCD:	MOV	#XDTSTK,SP	;SET THE STACK FOR SANITY
	CALL	SETCN		;S      ET OUTPUT FOR CONSOLE
	TYPE	CRLF		;PLACE TERMINAL CARRIAGE IN PROPER POSITION
	CLR	OPN		;SET NO LOCATION OPEN
	TYPE	'X		;OUTPUT INPUT SOLICITATION
	TYPE	'D		;
	TYPE	'T		;
	TYPE	76		;'>'

;MAINTAIN OPENED LOCATION, RE-INIT INPUT

NEWC:	CLRB	SMFD		;CLEAR SEMI-COLON FLAG/COUNT
	CLR	R3		;ZERO SECONDARY ARGUMENT FLAG
	CLR	R5		;AND ARGUMENT

;NEW SUB-EXPRESSION ENTRY

NEWE:	CLRB	OP		;CLEAR OPERATOR FOUND
	CLR	EXP		;SET ZERO IN EXPRESSION SO FAR LOCATION

;GET NUMBER AND THEN SCAN FOR COMMAND
      
NEWN:	JSR	PC,GETNUM	;GET AN OCTAL NUMBER AND TERMINATOR

;NON-OCTAL CHAR TYPED WHAT ARE WE TO DO?

CLGL:	JSR	R5,LOOKUP	;GO SEE IF IT IS REAL
	 +	COMTAB		;THIS DEFINES REAL
	BCS	ERR		;EASY ENOUGH IF NOT REAL
	TST	R2		;IF NOTHING TYPE BOTHER NOT
	BEQ	CL01		;WITH THE EXPRESSION
	JSR	PC,EXPCOM	;COMPUTE EXPRESSION
CL01:	JMP	@COMDIS(R1)	;GO TO PROPER ROUTINE

;FOR THE BENEFIT ALL REGISTERS ARE AS FOLLOWS

;R0	LAST CHARACTER TYPED, THE COMMAND ITSELF!
;R1	TABLE INDEX TO COMMAND ADDRESSES, IT IS USE      D.
;R2,R4	FIRST ARGUMENT, IF R2<>0 THEN R4 IS DATA
;R3,R5	SECOND ARGUMENT, IF R3<>0 THEN R5 IS DATA

;
; SET OUTPUT DEVICE TO CONSOLE TERMINAL
;

SETCN:	MOV	#TPB,OUTB	;SET OUTPUT BUFFER ADDRESS
	MOV	#TPS,OUTS	;SET OUTPUT STATUS ADDRESS
	RETURN			;
	.SBTTL	EXPRESSION SETUP COMMANDS ( ; + - * , )

;SEMI-COLON PROCESSOR

SEMI:	INCB	SMFD		;COUNT SEMI-COLON
	CMPB	#2,SMFD		;PUSH CONTENTS INTO MULTI
	BNE	SEM1		;SEMI COLON ARG LIST
	MOV	R5,D.ARGS
SEM1:	MOV	R2,R3		;PUSH R2 AND R4 INTO
	MOV	R4,R5      		;R3 AND R5 (FLAG AND CONTENTS)
	BR	NEWE		;CONTINUE SCANNER

;ADDITION SETUP

PLUS:	CLRB	OP		;OP IS 0 FOR +
	BR	CO00

;SUBTRACT SET UP

MINS:	MOVB	#2,OP
	BR	CO00

;MULTIPLY BY 50 AND ADD

STAR:	MOVB	#-2,OP		;OP IS -2 FOR *
CO00:	CLR	R4		;R4 IS RESET
	BR	NEWN

;MEMORY RELOCATION CHECK

COMM:	ASL	R4		;ALL NEED IT X 2
	CMP	R4,#RLR		;SEE IF REGISTER IS OUT OF RANGE
	BGT	ERR
	MOV	RELT(R4),EXP	;COMPUTE REAL CORE ADDRESS
	BR	PLUS
	.SBTTL	OPEN AND CLOSE PROCESSORS

.SBTTL "\-/-'-"-%-:"       PROCESSOR - OPEN AND TYPE CONTENT COMMANDS

;SYNTAX--
;NC				OPEN LOC N IN MODE C, SET MODE FOR NEXT
;C				TYPE LAST OPENED LOC IN MODE C

OCWORD:		;OCTAL WORD -		R1=2
ANWORD:		;ANSII WORD -		R1=6
MODULO:		;RADIX 50 WORD -	R1=10

;OPEN WORD MODE ENTRY, R1 CONTAINS FORMAT INDEX

	MOV	#2,R0		;SET BYTE FLAG TO WORD FLAG
	BR	OPE004		;GO TO IT ACE HOLE

OCBYTE:		;OCTAL BYTE -		R1=0
ANBYTE:		;ANSII BYTE -		R1=4

OPE001:	MOV	#1,R0		;SET WORD FLAG TO BYTE FLAG

OPE004:	TST	R2		;IF NO VALUE TYPE      D NO MODE SET
	BEQ	10$
	MOV	R0,BW		;SET MODE AND FORMAT FLAGS
	MOVB	R0,OBW		;SET THE LATER USE MODE
	MOVB	R1,FM		;SET THE MODE FLAG FOR SOOTH
	MOV	R4,CAD		;SET ADDRESS FOR EXPLICIT OPEN
	MOV	R4,DOT		;RESET RETURN PTR.
10$:	CMP	#1,R0		;CHECK ON BYTE MODE
	BEQ	15$		;NOT BYTE MODE
	BIT	#1,CAD		;SEE IF ADDRESS IS ODD
	BEQ	15$		;ALL IS GOOD
	CLR	R1		;THEY GET BYTE MODE ONLY
	BR	OPE001
15$:	MOV	R1,-(SP)	;SAVE FORMAT MAINLY
	JSR	PC,GETCAD	;GET THE DATA
	MOV	(SP)+,R1	;GET FORMAT
	JSR	PC,@TYFORM(R1)	      ;PRINT DATA IN PROPER FORMAT
	BR	NEWC		;GO GETTA NEW COMMAND TO DO
.SBTTL "<CR>-<LF>->-<-^-_-@" PROCESSOR - CLOSE AND OPEN REGISTERS

;CARRIAGE RETURN

CLCRET:	JSR	PC,PUTCAD	;CLOSE LOCATION
	BR	DCD		;RETURN TO DECODER

;LESS THAN, BACK TO MAIN STREAM

CLLSTH:	INCB	SEQ		;SET FLAG TO LATER RESTORE CAD

;LINE FEED, NEXT ONE DOWN

CLLNFD:	JSR	PC,PUTCAD	;CLOSE PRESENT CELL
	TSTB	SEQ		;SHOULD CAD BE RESTORED?
	BEQ	OP5		;BRANCH IF NOT
	MOV	DOT,CAD		;RESTORE PREVIOUS SEQUENCE
	CLRB	SEQ		;RESET F      LAG; NO LONGER NEEDED
	BR	OP2A		;
OP5:	ADD	BW,CAD		;GENERATE NEW ADDRESS
OP2:	MOV	CAD,DOT		;INITIALIZE DOT
OP2A:	TYPE	CRLF		;PLACE CARRIAGE IN PROPER POSITION
	MOV	CAD,R0		;NUMBER TO TYPE
	JSR	PC,RORA		; CHECK FORMAT
	MOVB	FM,R0		;SET FORMAT
	ASR	R0		;SPLIT R0 IN HALF
	MOVB	COMTAB(R0),R0	;SET SUFFIX CHARACTER
	TYPE	R0		;PRINT CHARACTER
	MOV	CAD,R4		;SET UP THE DATA
	CLR	R2		; SET TO USE CAD ADDRESS
	CLRB	OP		;THIS IS BECUZE
	CLR	EXP
	JMP	CLGL		;R0 HAS TERMIN, R4- DATA, R2= FLAG

;UP ARROW,       NEXT ONE UP

CLUPAR:	JSR	PC,PUTCAD
	SUB	BW,CAD		;GENERATE NEW ADDRESS
	BR	OP2		;GO DO THE REST

;BACK ARROW, PC RELATIVE COMPUTE

CLBACK:	JSR	PC,TCLS		;TEST WORD MODE AND CLOSE
	ADD	@R2,R2		;COMPUTE
	CMPB	(R2)+,(R2)+	;NEW ADDRESS
PCS:	MOV	R2,CAD		;UPDATE CAD
	BR	OP2A		;GO FINISH UP

;AT SIGN, ABSOLUTE OR INDIRECT CHAIN

CLATSG:	JSR	PC,TCLS		;TEST WORD MODE AND CLOSE
	MOV	@R2,R2		;GET ABSOLUTE ADDRESS
	BR	PCS

;GREATER THAN, PC OFFSET BRANCH ADDRESS

CLGRTH:	JSR	PC,TCLS		;TEST AND CLOSE      
	MOVB	@R2,R1		;COMPUTE NEW ADDRESS, EXTEND SIGN
	ASL	R1		;R2=2@R2)
	ADD	#2,R1		;+2
	ADD	R1,R2		;   +PC
	BR	PCS

;HANDY DANDY TO DO SOME LEG WORK

TCLS:	JSR	PC,PUTCAD	;CLOSE CURRENT CELL
	CMP	#2,BW		;ONLY WORD MODE ALLOWED
	BNE	ERR1		;BRANCH IF ERROR
	MOV	CAD,R2		;CURRENT ADDRESS IN R2
	RTS	PC
	.SBTTL	COMMAND PROCESSORS, SECTION TWO ( O = G S P )

.SBTTL "O" PROCESSOR - COMPUTE AND PRINT OFFSETS

;SYNTAX--
;AO				TYPE OFFSETS FROM . TO A
;L;AO				TYPE OFFSETS FROM L TO A

;TYPES	_PPPP      PP >DDDDDD			WHERE P-P IS PC RELATIVE
;					AND D-D IS BRANCH OFFSET

OFST:	TST	R3		;HOW ABOUT A VALUE OTHER
	BNE	10$		;THAN CAD
	MOV	CAD,R5		;RELUCTANTLY
10$:	SUB	R5,R4
	SUB	#2,R4		;NO TRICKS, ODD AND NON-EXIST THINGS
	TYPE	'_		;TYPE PC RELATIVE CUE
	TYPE	40		;
	MOV	R4,R0
	MOV	R4,-(SP)	;GOOD IDEA TO SAVE THIS
	JSR	PC,CADW		;TYPE VALUE + BLANK
	TYPE	76		;TYPE OFFSET BRANCH CUE
	MOV	(SP)+,R0
	ASR	R0		;DIVIDE
OF09:	JSR	PC,CADW		;16 BITS SO YOU CAN SEE HOW FAR OFF
	JMP	DCD		; GET NEXT COMMAND      

.SBTTL "=" PROCESSOR - PRINT LEFT SIDE EXPRESSION ON RIGHT SIDE

EQUALS:	MOV	R4,R0		;PROPER PRIOR PLANNING PREVENTS
	BR	OF09		;POOR PERFORMANCE

;JUST ANOTHER ERROR CALL

ERR1:	ERROR
.SBTTL	SST INTERRUPT VECTOR ENTRY POINTS


	.IF DF 	M$$MGE

;
; SEGMENT FAULT			- V1 - "MP" - NO PROCEED
;

SGMT:	TESTM	$SGFLT		;TEST IF IN EXEC MODE
	BIC	#160000,SR0	;UNFREEZE SEGMENT UNIT
	MOV	#"MP,EXP	;ENTRY PREFIX
	BR	NIXP		;

	.ENDC


;
; STACK OVERFLOW		-    - "SO" - NO PROCEED
; ODD ADDRESS      			- V0 - "OD" - NO PROCEED
; BPT				- V2 - "BE" - SPECIAL CASES
; T-BIT				- V2 - "TE" - PROCEED
; IOT				- V3 - "IO" - PROCEED
; RESERVED OR ILLEGAL		- V4 - "IL" - NO PROCEED
;

ODDA:	MOV	#"SO,EXP	;ASSUME STACK OVERFLOW
	CMP	SP,#V$$CTR+4	;STACK OVERFLOW?
	BLO	NIXP		;IF LO YES
	TESTM	$TRP04		;TEST IF IN EXEC MODE
	MOV	#"OD,EXP	;"OD:" FOR ODD ONE
	BR	NIXP		;NIX ON PROCEED
BPTI:	TESTM	$TRACE		;TEST IF IN EXEC MODE
	MOV	#"BE,EXP	;"BE:" FOR MAYBE A BAD ENTRY
	CLRB	P		;ALLOW PROCEED DEAL
	BR	INT      R		;SPECIAL NUMBER FOR THIS ONE
IOTX:	TESTM	$IOTRP		;TEST IF IN EXEC MODE
	MOV	#"IO,EXP	;"IO:" FOR IOTEE
	BR	ALOP		;ALLOW PROCEED
ILLI:	TESTM	$ILINS		;TEST IF IN EXEC MODE
	MOV	#"IL,EXP	;"IL:" FOR ILL INSTRUCTION
NIXP:	MOVB	#-1,P		;NO PROCEED
									;MSH125
	.IF DF	C$$RSH							;MSH125
									;MSH125
	BIS	#F3.CRA,$FMASK+4 ;SET FATAL SYSTEM CRASH BIT		;MSH125
									;MSH125
	.ENDC								;MSH125
									;MSH125
	BR	INTR		;

	.IF DF	F$$LTP							;MSH136
									;MSH136
;									;MSH      136
; FLOATING POINT EXCEPTION	- V7 - "FP" - NO PROCEED		;MSH136
;									;MSH136
									;MSH136
FPPE:	TESTM	$FLTRP		;TEST IF IN EXEC MODE			;MSH136
	MOV	#"FP,EXP	;"FP:" FOR FLOATING POINT		;MSH136
	BR	NIXP		;NIX ON PROCEED				;MSH136
									;MSH136
	.ENDC								;MSH136
									;MSH136
;
; EMT				- V5 - "EM" - PROCEED
; TRAP				- V6 - "TR" - NO PROCEED
;

NEMT:	TESTM	$EMTRP		;TEST IF IN EXEC MODE
	MOV	#"EM,EXP	;"EM:" FOR EMTEE


ALOP:	MOVB	#BKP+2,P	;ALLOW PROCEED

;
; COMMON INT      ERRUPT SERVICE AND DISPATCHER
;

INTR:	BIT	#TBT,2(SP)	;T-BIT SET IN STACKED PS WORD?
	BEQ	1$		;IF EQ NO
	CMP	PPC,(SP)	;PC CHANGE FROM LAST TRAP?
	BNE	1$		;IF NE YES
	JMP	RTN		;RTT MUST HAVE BEEN CHANGED TO AN RTI
1$:	MOV	(SP)+,UPC	;SET THE USER PC VALUE
	MOV	(SP)+,UST	;AND HIS ENTRY STATUS
	MOV	R0,UR0		;SAVE EXEC REGISTERS
	MOV	#UR0+2,R0	;POINT TO REGISTER SAVE AREA
	MOV	R1,(R0)+	;SAVE REGISTERS R1 THRU SP
	MOV	R2,(R0)+	;
	MOV	R3,(R0)+	;
	MOV	R4,(R0)+	;
	MOV	R5,(R0)+	;
	MOV	SP,(R0)+	;
	MOV      	#XDTSTK,SP	;SET XDT STACK POINTER
	MOV	#SSTADR,R0	;POINT TO TRAP VECTOR ADDRESS TABLE
	MOV	#SSTXDT,R1	;POINT TO XDT TRAP VECTOR TABLE
5$:	MOV	(R1)+,@(R0)+	;SET XDT TRAP VECTOR ADDRESSES
	CMP	R1,#SSTADR	;ANY MORE TO SET?
	BLO	5$		;IF LO YES

;TRY AND FIND OUT WHAT TO DO

	TSTB	P		;SEE IF CONTROLLED BREAKPOINT
	BNE	10$		;NOT DUE TO A PLANNED INTERRUPT
	TSTB	T		;IS A BPT OR T-BIT, SEE IF A PROCEED
	BNE	TBIT		;COMMAND IS BEING DONE, GO FINISH IT
	TSTB	S		;NO REMOVAL OF BREAKS ON S.I. MODE
	BNE	12      $		;SKIP NEXT TWO WORDS

;
; REMOVE EXEC BREAKPOINTS
;

10$:	MOV	#ADR1,R4	;POINT TO BREAKPOINT VECTOR
11$:	MOV	UIN-ADR1(R4),@(R4)+ ;REINSERT CORRECT CONTENTS
	CMP	#ADR1+BKP,R4	;ANY LEFT TO RESTORE?
	BHIS	11$		;IF HIS YES
12$:	MOV	UPC,R5		;GET A COPY OF THE PC AT INTERRUPT
	TSTB	P		;BREAKPOINT OR T-BIT CHECK
	BNE	30$		;DEFINITELY NOT A BREAKPOINT
	MOVB	S,R4		;SEE IF SINGLE STEPPING
	BNE	22$		;AND PRETEND

;AT THIS POINT IT MAY BE DUE TO T-BIT OR A BPT

	MOVB	#BKP+2,P	;SET ALLOW TO THE 8'TH       ONE
	CMP	-(R5),TRTC	;BACK-UP R5 AND SEE WHAT'S UP
	BEQ	30$		;IT WAS A NON-BREAK BPT
	MOV	#BKP,R4		;SET ADDRESS OF LEGIT BREAKS
15$:	CMP	R5,ADR1(R4)	;LOOK IT UP IN THE TABLE
	BEQ	20$		;FOUND THE NASTY LITTLE BUGGER
	SUB	#2,R4		;KEEP AT IT
	BGE	15$		;UNLESS NO MORE
	MOV	#"TE,R4		;NOT THERE, MUST BE T-BIT ERROR
	TST	(R5)+		;RESET PC TO MAKE IT RIGHT
	BR	26$		;LABOR
20$:	MOV	R5,UPC		;BACK-UP PC FOR BREAKPOINT
22$:	MOVB	R4,P		;BREAKPOINT IS A REAL ONE
	DEC	CT(R4)		;CHECK OUT THE PROCEED COUNT
	BNE	      C990		;LABOR ON A MIS-CONCEPTION
	INC	CT(R4)		;RESET PROCEED COUNT
	ASR	R4		;OCTAL TO UN-BIASED ASCII
	ADD	#"0B,R4		;BIAS TO ASCII
26$:	MOV	R4,EXP		;SET THE PREFIX UP

;COMMON TYPE ROUTINE FOR SST VECTORS USED UP

30$:	TYPE	CRLF		;PLACE CARRIAGE IN PROPER POSITION
	MOV	EXP,R0		;THE PREFIX
	TYPE	R0+R0		;
	TYPE	':		;
	MOV	R5,R0		;TYPE ADDRESS OF INTERRUPT
	JSR	PC,RORA		;AND THE REST OF THE ENTRY
	DECODE

;
; TRAPS ARE ALWAYS HANDLED BY EXEC
;

TRPI:	JMP	$TRTRP		;

;
; "G" PROCESSOR - GO       TO PROGRAM
;SYNTAX--
;LG			START PROGRAM AT LOCATION L
;G			START PROGRAM AT CURRENT PC

GOTO:	CLR	R0		;MAKE SURE THAT LAST CHARACTER TYPED IS	;MSH137
5$:	INC	R0		;OUTPUT BEFORE EXECUTING RESET IN INITL	;MSH137
	BNE	5$		;					;MSH137
	TST	R2		;SEE IF SPECIFIC ADDRESS		;MSH137
	BEQ	10$		;NO					;**-1
	MOV	R4,UPC		;SET THE PC
10$:	CLRB	S		;NO SINGLE INSTRUCTIONS
TBIT:	CLRB	T		;CLEAR T-BIT FLAGS
	BIS	#TBT,UST	;BOTH
	TSTB	S		;SEE IF WE NEED A T-BIT BIT
	BNE	GRTT		;NO GO ON
	BIC	#TBT,UST	;SET TH      E TEE BIT

;
; SET EXEC BREAKPOINTS
;

10$:	MOV	#ADR1,R4	;POINT TO BREAKPOINT VECTOR
20$:	MOV	@(R4),UIN-ADR1(R4) ;SAVE CONTENTS OF LOCATION
	MOV	TRTC,@(R4)+	;SET BREAKPOINT
	CMP	#ADR1+BKP,R4	;ANY MORE TO INSERT?
	BHIS	20$		;IF HIS YES
GRTT:	MOV	#PR7,-(SP)	;SET RTT PS WORD
	MOV	#20$,-(SP)	;SET RTT PC WORD
	MOV	#10$,@#10	;PLUG ILLEGAL INSTRUCTION TRAP
	MOV	(PC),R0		;GET RTT INSTRUCTION CODE
	RTT			;EXECUTE RTT INSTRUCTION
10$:	ADD	#4,SP		;CLEAN STACK
	MOV	(PC)+,R0	;GET RTI INSTRUCTION CODE
	      RTI			;
20$:	MOV	R0,RTN		;SET PROPER RETURN INSTRUCTION
	MOV	#SSTADR,R0	;POINT TO TRAP VECTOR ADDRESS TABLE
	MOV	#SSTVEC,R1	;POINT TO EXEC TRAP VECTOR TABLE
30$:	MOV	(R1)+,@(R0)+	;SET EXEC TRAP VECTORS
	CMP	R0,#SSTADR+<SSTADR-SSTXDT> ;ANY MORE TO SET?
	BLO	30$		;IF LO YES
	MOV	#UR0+2,R0	;POINT TO SAVED R1
	MOV	(R0)+,R1	;RESTORE REGISTERS R1 THRU SP THEN R0
	MOV	(R0)+,R2	;
	MOV	(R0)+,R3	;
	MOV	(R0)+,R4	;
	MOV	(R0)+,R5	;
	MOV	(R0)+,SP	;
	MOV	UR0,R0		;
	MOV	UST,-(SP)	;SET EXEC PS WORD
	MOV	UPC,      -(SP)	;SET EXEC PC WORD
	MOV	(SP),PPC	;SET PREVIOUS PC WORD
RTN:	RTI			;RETURN TO EXEC (MAY BE CHANGED TO RTT)

;
; "S" PROCESSOR - SINGLE STEP PROCEED
;SYNTAX--
;NS				EXECUTE N INSTRUCTIONS AND THEN STOP
;S				EXECUTE ONE INSTRUCTION

SNGL:	MOVB	#BKP+2,R0	;FAKE THE BREAK
	MOVB	R0,S		;SET THE FLAG FOR S.I. MODE
	BR	PR01		;FAKE A PROCEED IN S.I. MOOD

;
; "P" PROCESSOR - PROCEED FROM BREAKPOINT
;SYNTAX--
;NP				PROCEED THRU THIS BREAKPOINT N TIMES
;P				ASSUME N=1

PROC:	CLRB	S		;SET FAS      T MODE
	MOVB	P,R0		;GET NUMBER OF BREAK
	BMI	PR02		;THERE WASN'T ONE SO FAR ?
PR01:	TST	R2		;SEE IF VALUE IN R4 VIA R2
	BNE	10$		;SEE IF AND WHAT SETTING FOR COUNT
	MOV	#1,R4		;INIT IT TO ONE FOR A START
10$:	MOV	R4,CT(R0)	;SET USER'S COUNT
C990:	CMPB	P,#BKP		;SEE IF A REAL ONE OR A FAKE
	BGT	TBIT		;BRANCH IF FAKE
	TSTB	S		;SEE IF SINGLE INSTRUCTION MODE
	BNE	TBIT		;IF SO EXIT NOW
	INCB	T		;SET T-BIT FLAG
	BIS	#TBT,UST	;SET T-BIT
	BR	GRTT
PR02:	ERROR			;ANNOUNCE ERROR


;
; TEST IF IN EXEC       MODE
;

TESTM:	MOV	(R5)+,-(SP)	;PICK UP EXEC TRAP ROUTINE ADDRESS


	.IF DF	M$$MGE

	TST	$STKDP		;ALLOW EXEC TO HANDLE TRAP?
	BGT	20$		;IF GT YES, TRAP WAS IN USER MODE
	BLT	10$		;IF LT NO, BAD STACK DEPTH
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
	CMP	KISAR5,$XCOM1	;FIRST EXEC COMMON MAPPED?		;MSH165
	BNE	10$		;IF NE NO, SKIP EXEC BOUNDS CHECKS	;MSH165
									;MSH045
	.ENDC	;D$$PAR							;MSH045
									;MSH045
	CMP	4(SP),#$DRLM1	;TRAP OCCUR IN DIRECTIVE DISPATCH      ER?
	BLO	5$		;IF LO NO
	CMP	4(SP),#$DRLM2	;TRAP OCCUR IN DIRECTIVE DISPATCHER?
	BLOS	20$		;IF LO YES, PASS TRAP TO EXEC
5$:	CMP	4(SP),#$DQLM1	;TRAP OCCUR IN QIO DIRECTIVE?
	BLO	6$		;IF LO NO
	CMP	4(SP),#$DQLM2	;TRAP OCCUR IN QIO DIRECTIVE?
	BLOS	20$		;IF LOS YES, ALLOW EXEC TO HANDLE TRAP
6$:				;REF LABEL


	.IF DF	P$$LAS

	CMP	4(SP),#$DPLM1	;FAULT OCCUR RETRIEVING DEF BLOCK ADDR?
	BLO	10$		;IF LO NO
	CMP	4(SP),#$DPLM2	;FAULT OCCUR RETRIEVING DEF BLOCK ADDR?
	BLOS	20$		;IF LOS YES, ALLOW EX      EC TO HANDLE TRAP

	.ENDC


	.IFF

	TST	$STKDP		;TRAP IN EXEC?
	BLE	10$		;IF LE YES
	CMP	4(SP),$EXSIZ	;TRAP OCCUR IN EXEC CODE?
	BHIS	20$		;IF HIS NO
	BIT	#PR7,6(SP)	;EXECUTING AT PRIORITY OTHER THAN ZERO?
	BEQ	20$		;IF EQ NO

	.ENDC


10$:	MOV	R5,(SP)		;SET TO XDT ADDRESS
20$:	MOV	(SP)+,R5	;SET RETURN ADDRESS
	RTS	R5		;PROCESS TRAP
	.SBTTL	COMMAND PROCESSORS, SECTION THREE ( L V X W N E F )

.SBTTL "L" PROCESSOR - LIST MEMORY ON THE SPECIFIED DEVICE

;SYNTAX--
; D;S;FL		WHERE	D IS       DEV, <> OR 0 = CONSOLE, 1 = LPT
;				S IS START ADDRESS, SETS $L IF THERE
;				F IS STOP ADDRESS, SETS $H IF THERE

LIST:	TST	R2		;SET UPPER AND LOWER LIMITS
	BEQ	10$		;IF SPECIFIED TO DO SO
	MOV	R4,HI
10$:	TST	R3		;DO THE LOW ONE
	BEQ	15$
	MOV	R5,LOW
15$:	CMPB	#2,SMFD		;SEE IF AN EXTRA ARGUMENT
	BNE	17$		;USE THE CONSOLE
	TST	D.ARGS		;LOOK AT THE ARGUMENT
	BEQ	17$		;DO NOT ARGUE
	MOV	#LPS,OUTS	;SET OUTPUT STATUS REGISTER TO LINE PRINTER
	MOV	#LPB,OUTB	;
	TYPE	14		;OUTPUT A FORM FEED
17$:	      MOV	LOW,R5		;GET STARTING DUMP ADDRESS
	MOVB	OBW,R0		;GET ADDRESS INCREMENT
	SUB	R0,R5		;BIAS ADDRESS BY ADDRESS INCREMENT
	MOV	R5,CAD		;SET CURRENT ADDRESS
	TST	-(SP)		;MAKE A HOLE IN THE STACK
20$:	CLR	(SP)		;NEW LINE UP
	JSR	PC,SNAGIT	;ACCESS DEVICE FOR DATA
	JSR	PC,SPRINT	;PRINT ADDRESS AND FIRST ITEM
25$:	JSR	PC,SNAGIT	;GET MORE DATA
	JSR	PC,DPRINT	;JUST PRINT THE DATA
	INC	(SP)		;COUNT THE DATA
	CMP	#7,(SP)		;CHECK THE COUNT
	BNE	25$		;JUST LIKE THEY TOLD YOU AT THE
	BR	20$		;FAMOUS PROGR      AMMERS SCHOOL
;
; EXIT COMMAND
;
; SYNTAX X
;
; THE EXIT COMMAND IN XDT EFFECTS A JUMP TO THE EXECUTIVE $CRASH ROUTINE.
;

EXIT:	MOV	#UR0+2,R0	;POINT TO SAVED R1
	MOV	(R0)+,R1	;RESTORE REGISTERS R1 THRU SP THEN R0
	MOV	(R0)+,R2	;
	MOV	(R0)+,R3	;
	MOV	(R0)+,R4	;
	MOV	(R0)+,R5	;
	MOV	(R0)+,SP	;
	MOV	UR0,R0		;


	.IF DF	C$$RSH
									;MSH137
; MOVING THE DATA DIRECTLY PREVENTS A POSSIBLE STACK OVERFLOW ERROR	;MSH137

	MOV	UST,$CRUST	; MOVE USER PS FOR THE CRASH MODULE
	MOV	UPC,$CRUPC      	; MOVE USER PC FOR THE CRASH MODULE
	JMP	$CRALT		; ALTERNATE ENTRY POINT TO THE CRASH MODULE

	.IFF

	JMP	$CRASH		;IF NO CRASH SUPPORT, JUST CRASH

	.ENDC


	.SBTTL	UTILITIES - COMMAND SUPPORT ROUTINES

;TEST FOR VALID RELOCATION REGISTER IN R4

RTST:	CMP	#RLR/2,R4	;GET A GOOD NUMBER FOR A REGISTER
	BLO	10$		;NOT TOO GOOD, QUESTION IT
	ASL	R4
10$:	RETURN			;

;SNAG MEMORY LOCATION 	JSR PC,SNAGIT

;NEEDS--
;CAD		POINTS TO MEMORY WORD (APPROXIMATELY THAT IS)
;R0,R5		CONTAINS REAL WORD       UPON EXIT TO "SRCHEK"

SNAGIT:	MOVB	OBW,R0		;SET THE INCREMENT
	ADD	R0,CAD		;INCREMENT AND NOW
	CMP	CAD,HI		;SEE IF MORE TO DO
	BLOS	10$		;IF NOT DO NOT
	DECODE			;GO RESET STACK AND NO NEXT COMMAND
10$:	JSR	PC,GETCAD	;ACCESS METHOD
	MOV	R0,R5		;MAKE A COPY FOR LATER
	RETURN			;

;SEARCH HIT PRINT			JSR PC,SPRINT

;CAD POINTS TO THE LOC TO BE PRINTED
;R5 CONTAINS THE CONTENTS OF THE LOCATION TO BE PRINTED

SPRINT:	TYPE	CRLF		;PLACE CARRIAGE IN PROPER POSITION
	MOV	CAD,R0		;THE LOCATION
	JS      R	PC,RORA		;THE MODE
	MOVB	FM,R0		;PICK UP OLD CURENT MODE
	ASR	R0		;HALVES
	MOVB	COMTAB(R0),R0	;AH HA
	TYPE	R0		;TYPE THE MODE REGISTER

;DATA PRINT ROUTINE			JSR PC,DPRINT

;PRINTS DATA IN R5 IN CURRENT MODE

DPRINT:	MOVB	FM,R1		;SET THE MODE
	MOV	R5,R0		;THIS IS THE POOR DATA
	MOV	R5,-(SP)	;SAVE THE DATA
	JSR	PC,@TYFORM(R1)	;DO THAT __ TO THE POOR DATA
	MOV	(SP)+,R5	;RESTORE THE DATA
	RTS	PC		;RESTORE THE PC
;EXPRESSION COMPUTATION ROUTINE		JSR PC,EXPCOM

;NEEDS--
;OP			THE OPERATION       (-2=*, 0=+, *=2)
;EXP			THE LEFT SIDE
;R4			THE RIGHT SIDE

;SETS UP--
;OP			BACK TO 0 FOR ADD
;EXP,R4		ALL SO FAR

EXPCOM:	TSTB	OP		;SEE WHAT'S UP CHUCK
	BMI	20$
	BEQ	10$
	NEG	R4		;MINUS, OP=2
10$:	ADD	EXP,R4		;PLUS, OP=0
15$:	MOV	R4,EXP		;COMMON OUT, SET EXP TO WHATEVER
	CLRB	OP		;IS IN R4 TOO
	INC	R2		;SET R2 SO THAT R4 IS, OP=0
	RTS	PC
20$:	MOV	EXP,-(SP)	;GET THE LEFT SIDE OF EXPRESSION
	ASL	(SP)		; MULTIPLY BY 10
	ASL	(SP)		;
	ASL	(SP)		;
	ADD	(SP),R4		; ADD IT
	ASL	(SP)		; MULTIP      LY BY 40
	ASL	(SP)		; WHICH IS LIKE MULTIPLYING BY 50
	ADD	(SP)+,R4	;AND ADD IT TO THE RIGHT
	BR	15$		;COMMON OUT
;BUILD AN OCTAL NUMBER		JSR PC,GETNUM

;NEEDS AND RETURNS--
;R0	NON-OCTAL TERMINATING CHARACTER
;R2	OCTAL CHARACTER COUNT
;R4	OCTAL NUMBER THAT I GOT, YOU GET

GETNUM:	CLR	R2		;NEW R2 AND R4
	CLR	R4
10$:	JSR	PC,GET		;GET 1 CHARACTER
	CMPB	#'0,R0		;NON-OCTAL, LESS THAN "0"
	BHI	GETC99
	CMPB	#'7,R0		;NON-OCTAL, LESS THAN "7"
	BLO	GETC99
	BIC	#177770,R0	;MAKE INTO ACCEPTABLE RANG      E
	ASL	R4		; SHIFT LEFT
	ASL	R4		; 3 BITS
	ASL	R4		;
	ADD	R0,R4		;PLANT LO PLACE
	INC	R2		;ACCOUNT FOR NEW ONE
	BR	10$		;NEXT ONE OR OTHER

;SCAN A LIST OF CHARACTERS	JSR R5,LOOKUP

;CALL--
;		R0	HAS THE CHARACTER
;	JSR	R5,LOOKUP	;THAT IS IT
;	 +	LIST TO USE, 00 BYTE IS END OF LIST

;RETURNS AT CALL + 2 WITH--
;R0	STILL HAS CHARACTER
;R1	HAS INDEX X2 OF FOUND CHARACTER IF C=0
;C=1	CHARACTER WAS NOT FOUND

LOOKUP:	MOV	(R5),R1		;GET LIST START
10$:	CMPB	R0,(R1)		;IS THIS THE ONE
	BNE	20$      		;RIGHT IT WASN'T
	SUB	(R5)+,R1	;COMPUTE INDEX AND RETURN
	ASL	R1		;DO THIS FOR EVERBODY, C=0
	BR	30$
20$:	TSTB	(R1)+		;CHECK FOR END OF LIST
	BNE	10$		;IF NOT LOOK AT NEXT ITEM
	TST	(R5)+		;END, AVOID ILLEGAL INSTRUCTION
	SEC			;SECURITY EXCHANGE COMMISION
30$:	RTS	R5		;SECURITY ELSEWHERE
;GET CONTENTS OF ADDRESS IN THE MODE		JSR PC,GETCAD

;NEEDS--
;R0		THE MODE 1=BYTE, 2=WORD
;CAD		THE ADDRESS
;DEVI		THE DEVICE CODE

;RETURNS--
;R0		HAS THE DATA YOU ASKED FOR

GETCAD:	MOV	CAD,R3		; G      ET CORE ADDRESS
	MOV	SP,OPN		; SET LOCATION OPEN
	ASR	R0		;PUSH BW FLAG INTO CARRY BIT
	BCC	10$		;2 WON'T FIT SO IS WORD
	MOVB	(R3),R0		;ACCESS BYTE
	BR	GETC99
10$:	MOV	(R3),R0		;ACCESS WORD
GETC99:	RTS	PC		;STACK ACCESS

;PUT R4 INTO ADDRESS IN THE MODE		JSR PC,PUTCAD

;NEEDS--
;R2		CONTENT FLAG, 0 FOR NONE, ELSE R4 IS GOLD
;R4		THE DATA
;BW		THE MODE FLAG, IF 0 THEN NO LOCATION OPEN

PUTCAD:	TST	R2		;CHECK FOR TYPED VALUE
	BEQ	12$		;NO DATA NO DODO
	MOV	BW,R0		;PICK UP MODE AN CC'S
	TST      	OPN		; IS A LOCATION OPEN AT PRESENT?
	BEQ	12$		;NOT OPEN NOT STORED
	MOV	CAD,R3		; GET CORE ADDRESS
	BIT	#177776,R0	;CHECK MODE
	BNE	10$		;WORD MODE
	MOVB	R4,(R3)		;BYTE MODE
	BR	12$		;BRANCH MODE
10$:	MOV	R4,(R3)		;WORD MODE
12$:	RTS	PC



;
; GET CHARACTER FROM CONSOLE TERMINAL
;

GET:	TSTB	TKS		;CHARACTER READY?
	BPL	GET		;IF PL NO
	MOVB	TKB,R0		;READ INPUT BYTE
	BIC	#177600,R0	;CLEAR EXCESS BITS
	CMPB	R0,#23		;CONTROL-S TYPED?			;MSH155
	BNE	10$		;IF NE NO				;MSH155
5$:	TSTB	@#      TKS		;HAS A CHARACTER BEEN TYPED?		;MSH155
	BPL	5$		;IF PL NO				;MSH155
	MOVB	@#TKB,R0	;READ INPUT BYTE			;MSH155
	BIC	#177600,R0	;CLEAR EXCESS BITS			;MSH155
	CMPB	R0,#21		;CONTROL-Q TYPED?			;MSH155
	BNE	5$		;IF NE NO, IGNORE THIS INPUT		;MSH155
	BR	40$		;DON'T ECHO CONTROL-Q			;MSH155
									;MSH155
10$:	CMPB	R0,#12		;BRANCH IF <LF>				;MSH155
	BEQ	40$		;NO ECHO <LF>'S				;**-1
	JSR	R5,LOOKUP	;CHECK IF ALTMODE
	+	ALTTAB
	BCS	20$		;
	MOVB	#'$,R0		;CHANGE TO $ IF SO
20$:	MOV	R0,-(SP)	;SAVE       INPUT CHARACTER
	TYPE	R0		;ECHO CHARACTER
	MOV	(SP)+,R0	;RESTORE INPUT CHARACTER
	CMP	#141,R0		;LOWER CASE CHARACTER?
	BHI	30$		;IF HI NO
	CMP	#172,R0		;LOWER CASE CHARACTER?
	BLO	30$		;IF LO NO
	SUB	#40,R0		;CONVERT TO UPPER CASE CHARACTER
30$:	CMPB	#' ,R0		;CVT BLANK
	BNE	40$
	MOVB	#'+,R0		;INTO +
40$:	RETURN			;

;
; TYPE CHARACTER ON OUTPUT DEVICE
;

TYPE:	MOV	(SP),-(SP)	;DUPLICATE RETURN ADDRESS
	SUB	#2,(SP)		;POINT TO TRAP INSTRUCTION
	MOVB	@(SP)+,-(SP)	;GET LOW BYTE OF INSTRUCTION      
	BMI	10$		;IF MI CONTROL BYTE
	MOV	(SP)+,R0	;SET BYTE TO OUTPUT
	BR	30$		;
10$:	BIT	#40,(SP)	;OUTPUT CONTENTS OF R0?
	BEQ	20$		;IF EQ YES
	MOV	(PC)+,R0	;SET TO OUTPUT <CR><LF>
	.BYTE	15,12		;
20$:	ASLB	(SP)+		;OUTPUT TWO BYTES?
	BPL	30$		;IF PL NO
	TYPE	R0		;TYPE OUT FIRST BYTE
	SWAB	R0		;SET UP HIGH BYTE
30$:	CMP	OUTS,#TPS	;IS OUTPUT DEVICE A TERMINAL?		;MSH155
	BNE	34$		;IF NE NO				;MSH155
	TSTB	@#TKS		;HAS A CHARACTER BEEN TYPED IN?		;MSH155
	BPL	34$		;IF PL NO				;MSH155
	MOVB	@#TKB,-(      SP)	;GET THE CHARACTER			;MSH155
	BICB	#200,(SP)	;REMOVE PARITY BIT			;MSH155
	CMPB	(SP)+,#23	;IS IT A CONTROL-S?			;MSH155
	BNE	34$		;IF NE NO, IGNORE IT			;MSH155
33$:	TSTB	@#TKS		;HAS A CHARACTER BEEN TYPED IN?		;MSH155
	BPL	33$		;IF PL NO				;MSH155
	MOVB	@#TKB,-(SP)	;GET THE CHARACTER			;MSH155
	BICB	#200,(SP)	;CLEAR PARITY BIT			;MSH155
	CMPB	(SP)+,#21	;IS IT A CONTROL-Q?			;MSH155
	BNE	33$		;IF NE NO, IGNORE IT			;MSH155
34$:	TSTB	@OUTS		;OUTPUT DEVICE READY?			;MSH155
	BPL	34$		;IF PL NO	      			;MSH155
	MOVB	R0,@OUTB	;OUTPUT BYTE				;**-2
35$:	TSTB	@OUTS		;OUTPUT DEVICE READY?
	BPL	35$		;IF PL YES
	CMPB	#15,R0		;WAS OUTPUT BYTE A CARRIAGE RETURN?
	BNE	50$		;IF NE NO
	CMP	#LPS,OUTS	;OUTPUT DEVICE LINE PRINTER?
	BEQ	50$		;IF EQ YES
	MOV	#5,-(SP)	;SET FILL COUNT TO 5
	CLRB	R0		;SET OUTPUT NULLS
40$:	TYPE	R0		;OUTPUT A NULL
	DEC	(SP)		;ANY MORE TO OUTPUT?
	BGT	40$		;IF GT YES
	TST	(SP)+		;CLEAN STACK
50$:	RTI			;
	.SBTTL	UTILITIES - PRETTY PRINTERS

;PRINT ADDRESS- RELOC, SYMBOLIC      , OR ABSL	JSR PC.RORA

;R0	ADDRESS TO BE PRINTED
;FORM	CORE ADDRESS FORMAT (0-RELOC  1-ABSOL)

;REGISTER	'$R ' OR '$DR '
;CORE		'D,XXXXXX ' OR 'XXXXXX '

RORA:	MOV	R0,-(SP)	;CALLING VALUE ONA TOPPA SATCK
	CMP	#INTBEG,(SP)
	BHI	50$		;BELOW FIRST NON-INDEXED
	CMP	#INTEND,(SP)
	BLO	50$		;ABOVE LAST NON-INDEXED
	TYPE	'$		;ANNOUNCE INTENSIONS
	CMP	#INTINX,(SP)
	BLOS	20$		;GO TO DO INDEXED
	MOV	(SP)+,R0	;NON-INDEXED REGISTER ----- "$R "
	SUB	#INTBEG,R0	;CLEANED UP STACK, GET OFFSET
	ASR	R0		;BYT      E THAT WORD, WORD THAT BYTE
	MOVB	NIXMAP(R0),R0	;MAGIC CHARACTER FROM TABLE
15$:	BIS	(PC)+,R0
	.BYTE	000,' 		;CHARACTER PLUSSA BLANK
	TYPE	R0+R0		;NAME PLUS BLANK AND SPLIT
	RETURN			;
20$:	CLR	R1		;SEE WHICH SET OF TABLES WE GOT
22$:	CMP	INXTBL+2(R1),(SP) ;LOOK ON AHEAD TO FIND BEHIND
	BHI	24$		;R1 POINTS TO BASE OF SET
	TST	(R1)+		;THINK ABOUT THOSE DUMMY ENTRIES DUMMY
	BR	22$
24$:	MOV	(SP)+,R0	;INDEXED REGISTER ---- "$DR "
	SUB	INXTBL(R1),R0	;GET ADDRESS AND COMPUTE OFFSET IN WORDS
	ASR	R0		      ;AND FINALLY IN PLAIN TALK
	ADD	#'0,R0		;CONVERT TO ASCII
	TYPE	R0		;TYPE OUT REGISTER NUMBER
	ASR	R1
	MOVB	INXREG(R1),R0	;PICK UP THE REAL CHARACTER
	BR	15$		;GO PRINT REST OF IT
50$:	TST	FORM		;CORE ADDRESS SEE WHAT USER WANTS
	BNE	80$		;TYPE AS ABSOLUTE.
	MOV	(SP),R4		;RELOCATE ---- "R,XXXXXX "
	JSR	PC,LOCA		;WE ALWAYS PICK, XDT KNOWS BEST
	BMI	80$		;BUT NOT ALL THE TIME
	MOV	R1,(SP)		;SET THE DISPLACEMENT
	ADD	#"0,,R0		;PRINT REGISTER AND COMMA
	TYPE	R0+R0		;DISK AND CORE
80$:	MOV	(SP)+,R0      	;PRINT R0 AS A WORD

;TYPE R0 AS BYTE OR WORD, TWO ENTRIES
;	FOR A WORD				JSR PC,CADW
;	FOR A BITE				JSR PC,CADB

CADW:	MOV	R0,QUAN		;SET THE FAMOUS QUANTITY VALUE
	MOV	#6,R3		;# OF DIGITS
	MOV	#-2,R4		;# OF BITS FIRST-3
	BR	CA01		;DO THE COMMON THING
CADB:	CLR	QUAN		;SET FOR ALL OF QUAN A BYTE
	MOVB	R0,QUAN		;SET THE QUANTITY THING AGAIN
	MOV	#3,R3		;THERE ARE THREE DIGITS
	MOV	#-1,R4		;AND ONLY TWO BITS
	SWAB	R0		;SWITCH ENDS
CA01:	MOV	R0,-(SP)	;SAVE R0
10$:	ADD	#3,R4		;COMPUTE THE NUMB      ER OF BITS TO DO
	CLR	R0
15$:	ROL	(SP)		;GET A BIT
	ROL	R0		;STORE IT AWAY
	DEC	R4		;DECREMENT COUNTER
	BGT	15$		;LOOP IF MORE BITS NEEDED
	ADD	#'0,R0		;CONVERT TO ASCII
	TYPE	R0		;TYPE IT
	DEC	R3		;SEE IF MORE DIGITS TO DO
	BGT	10$		;LOOP IF SO
	MOVB	#' ,R0		;SET UP FOR TRAILING SPACE
	TST	(SP)+		;GET RID OF JUNK
FT01:	TYPE	R0		;
	RETURN			;
;TYPE CONTENTS OF WORD IN FORMAT	JSR PC,@TYFORM(R1)

;R0		WORD OR BYTE TO BE TYPED, RHJ
;R1	CODE-	ENTRY PT,	FORMAT,	CODE

TYFORM:	+	CADB		;BYTE OCT      AL - 0
	+	CADW		;WORD OCTAL - 2
	+	30$		;BYTE ANSII - 4
	+	20$		;WORD ANSII - 6
	+	10$		;RADIX 50  - 10

10$:	JSR	PC,TYRADX	;R0 GETS THE RADIX 50 TREATMENT
	BR	35$		;APPEND A BLANK TO 3 CHAR'S

20$:	TYPE	R0		;TYPE BYTE IN R0
	SWAB	R0		;SWAP EM AND TYPE IT
30$:	TYPE	R0		;TYPE BYTE IN R0
35$:	TYPE	40		;TYPE A SPACE
	RETURN			;

;TYPE CONTENTS OF R0 IN RADIX 50		JSR PC,TYRADX

TYRADX:	MOV	#3,R5		;COUNT OF CHARACTERS
	MOV	#50$,R2		;POINTER TO COEFFICENT TABLE
	MOV	R0,R1		;COPY OF RADIX 50 WOR      D
10$:	MOV	R1,R0		; GET DIVIDEND
	MOV	(R2)+,R1	; GET DIVISOR
	JSR	PC,$DIV		; DIVIDE, R0=QUOTIENT, R1 =REMAINDER
	TST	R0		; IS QUOTIENT ZERO? (SP)?
	BEQ	12$		;"SP" = 040
	CMPB	R0,#33		;RAD50-$ =33
	BEQ	16$		;"$" = 044
	BGT	14$		;"." OR "0-9" = 056 OR 060-071
	ADD	#40,R0		;RAD50-A = 1, "A" = 101
12$:	ADD	#16,R0		;40+16+11+11 = 100 + (A-Z)
14$:	ADD	#11,R0		;16+11+11 = 40 + (SP)
16$:	ADD	#11,R0		;11+11 = 22 + (.,0-9)
	TYPE	R0		;TYPE CHARACTER IN R0
	DEC	R5		;COUNT THE CHARACTERS
	BNE	10$		; LOOP      
	RTS	PC

;COEFFICENT TABLE, RADIX 50 CONVERT

50$:	.WORD	+1600.,+40.,+1.	;40.^2, 40.^1, 40.^0
;SELECT RELOCATION REGISTER			JSR PC,LOC

;CAD		ADDRESS TO USE IN SELECTION

;RETURNS--
;R0				REGISTER NUMBER FOUND, -1 IF NONE FOUND
;R1				DISTANCE, RELOCATION FACTOR

;SUBROUTINE TO LOCATE RELOCATION REGISTER NEAREST BUT STILL
;BELOW THE ADDRESS IN CAD.  RETURNS WITH THE REGISTER
;NUMBER IN R0, AND WITH THE DISTANCE BETWEEN THE REGISTER
;AND (CAD) IN R1
;IF NO GOOD RELOC. REG. FOUND, R0 WILL       = -1

LOC:	MOV	CAD,R4	;SET UP CAD DATA
LOCA:	CLR	R0
	MOV	#-1,-(SP)	;INITIALIZE RELOC. REG. INDEX
	MOV	(SP),R1		;INITIALIZE DISTANCE TO A HIGH VALUE
10$:	CMP	R0,#RLR		;ARE WE DONE COMPARING?
	BHI	20$		;BRANCH IF DONE
	CMP	RELT(R0),R4	;IS CURR. RELOC. BIAS > (R4)?
	BHI	15$		;IF SO, BRANCH -- DON'T SUBTRACT, GET NEXT
	MOV	R4,R2		;OTHERWISE TAKE THE DIFFERENCE
	SUB	RELT(R0),R2	;OF CURR. RELOC. REG. AND CAD
	CMP	R1,R2		;IS THE RESULT THE SMALLEST SO FAR?
	BHI	25$		;BRANCH IF YES (UNSIGNED CONDITIONA   z  L)
15$:	TST	(R0)+		;OTHERWISE, BUMP R0 FOR NEXT RELOC. REG.
	BR	10$		;LOOP BACK FOR NEXT COMPARISON
20$:	MOV	(SP)+,R0	;PUT REG.# IN R0
	RTS	PC		;JOB OVER, RETURN
25$:	MOV	R2,R1		;REMEMBER SMALLEST DIFFERENCE IN XXY
	ASR	R0		;AND ASSOCIATED REGISTER NUMBER
	MOV	R0,(SP)		; IN (SP)
	ASL	R0		;RESTORE R0 TO ORIGINAL VALUE
	BR	15$		;GO FO NEXT COMPARISON.

	.END	$XDT
 z         äðskQ	› c,        	.TITLE	ADDRV
	.IDENT	/04/
 
;
; COPYRIGHT (C) 1974, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 04
;
; D. N. CUTLER 24-NOV-73
;
; AD01-D ANALOG TO DIGITAL CONVERTER CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	PKTDF$
	PKTDF$			;DEFINE I/O PACKET OFFSETS
 
;
; LOCAL DATA
;
; DRIVER DISPATCH TABLE
;
 
$ADTBL::.WORD	ADINI		;DEVI      CE INITIATOR ENTRY POINT
	.WORD	ADCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	ADCAN		;DEVICE TIMEOUT ENTRY POINT
	.WORD	ADCAN		;POWERFAIL ENTRY POINT
 
;+
; **-ADINI-AD01-D ANALOG TO DIGITAL CONVERTER CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS RECEIVED FOR THE AD01-D ANALOG TO DIGITAL CONVERTOR. THE AD01-D HAS SUCH A
; FAST CONVERSION RATE (APPROXIMATELY 30US) THAT CONVERSIONS ARE PROGRAM
; RATHER THAN INTERRUPT DRIVEN. THUS REQUESTS A      RE NOT QUEUED BY THE QUEUE I/O
; DIRECTIVE AND THE QUEUING/DEQUEUING OVERHEAD IS BYPASSED.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLER TO BE INITIATED.
;
; AD01-D I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04       -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RBC).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER.
;	WD. 15 -- VIRTUAL ADDRESS OF CONTROL BUFFER.
;	WD. 16       -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
; THE DATA BUFFER RECEIVES CONVERTED VALUES AND THE CONTROL BUFFER CONTAINS
; CONTROL WORDS THAT CONTROL THE CONVERSION PROCESS. EACH WORD IN THE CONTROL
; BUFFER HAS THE FORMAT:
;
;	BITS 15-12 -- GAIN CODE.
;
;		LEGAL GAIN CODES ARE:
;
;		0000=GAIN OF 1.
;		0001=GAIN OF 2.
;		0010=GAIN OF 4.
;		0011=GAIN OF 8.
;
;	BITS 11-0 -- CHANNEL NUMBER.
;
;		EACH AD01-D MAY HAVE 64. CHANNELS. THE LEGALITY OF
;		A PARTICULAR CHANNEL NUMBER       IS DETERMINED BY THE
;		SECOND DEVICE CHARACTERISTICS WORD.
;
; OUTPUTS:
;
;	EACH CHANNEL IS CONVERTED ACCORDING TO THE CORRESPONDING WORD IN
;	THE CONTROL BUFFER AND THE RESULTANT VALUE IS PLACED IN THE
;	DATA BUFFER. IF AN ILLEGAL CONTROL WORD OR AD01-D ERROR IS DE-
;	TECTED, THEN THE CONVERSION PROCESS IS TERMINATED. THE SECOND I/O
;	STATUS WORD SPECIFIES THE NUMBER OF CHANNELS THAT WERE CONVERTED.
;-
 
ADINI:	MOV	R1,R3		;COPY ADDRESS OF I/O PACKET
	MOV	I.PRM+6(R3),R0 	;GET VIRTUAL ADDRESS       OF CONTROL BUFFER
 
 
	.IF DF	A$$CHK!M$$MGE
 
	MOV	I.PRM+4(R3),R1 	;SET LENGTH OF BUFFER TO CHECK
	CALL	$ACHCK		;ADDRESS CHECK CONTROL BUFFER
	BCS	50$		;IF CS ADDRESS CHECK FAILURE
 
	.IFTF
 
	CALL	$RELOC		;RELOCATE CONTROL BUFFER ADDRESS
	MOV	R5,R0		;COPY ADDRESS OF UCB
	ADD	#U.BUF,R0	;POINT TO BUFFER RELOCATION BIAS
	MOV	I.PRM(R3),(R0)+ ;INSERT DATA BUFFER RELOCATION BIAS
	MOV	I.PRM+2(R3),(R0)+ ;INSERT DATA BUFFER ADDRESS
	CLR	(R0)+		;CLEAR NUMBER OF SAMPLES PERFORMED
	MOV	R1,(R0)+	;INSER      T CONTROL BUFFER RELOCATION BIAS
	MOV	R2,(R0)		;INSERT CONTROL BUFFER ADDRESS
	MOV	S.CSR(R4),R4	;GET ADDRESS OF CONTROL STATUS REGISTER
 
;
; INITIATE I/O OPERATION
;
 
10$:	CALL	$GTCWD		;GET NEXT WORD FROM CONTROL BUFFER
	MOV	(SP)+,R1	;RETRIEVE CONTROL WORD
	BIT	#147700,R1	;BAD GAIN OR CHANNEL?
	BNE	60$		;IF NE YES
	CMPB	R1,U.CW2(R5)	;LEGAL CHANNEL THIS CONTROLLER?
	BHIS	60$		;IF HIS NO
	SWAB	R1		;SWAP CHANNEL AND GAIN FIELDS
	RORB	R1		;ADJUST GAIN TO PROPER POSITION
	MOV	R1,(R4)		;START CO      NVERSION
	MOV	#6,R2		;SET REPEAT COUNT
20$:	BIT	#100200,(R4)	;ERROR OR READY?
	BMI	30$		;IF MI ERROR
	BNE	40$		;IF NE READY
	DEC	R2		;TIMEOUT?
	BGT	20$		;IF GT NO
30$:	MOV	#IE.DNR&377,R0	;SET DEVICE NOT READY STATUS
	BR	70$		;
40$:	INC	U.CNT(R5)	;INCREMENT NUMBER OF SAMPLES TAKEN
	MOV	2(R4),-(SP)	;GET CONVERTED VALUE
	CALL	$PTWRD		;PUT VALUE IN DATA BUFFER
	SUB	#2,I.PRM+4(R3)	;ANY MORE SAMPLES TO TAKE?
	BGT	10$		;IF GT YES
	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS
	BR	70$		;
 
	   V  .IFT
 
50$:	MOV	#IE.SPC&377,R0	;SET ILLEGAL BUFFER STATUS
	BR	70$		;
 
	.ENDC
 
 
60$:	MOV	#IE.BAD&377,R0	;SET BAD PARAMETER STATUS
70$:	MOV	U.CNT(R5),R1	;SET NUMBER OF CHANNELS SAMPLED
	CALL	$IOFIN		;FINISH I/O OPERATION
 
;
; CANCEL I/O OPERATION, DEVICE TIMEOUT, AND POWERFAIL ARE NOP'ED.
;
 
ADCAN:	RETURN			;
 
	.END
 V         4ðskQ	› c,        	.TITLE	AFDRV
	.IDENT	/06/
 
;
; COPYRIGHT (C) 1974, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 06
;
; D. N. CUTLER 30-NOV-73
;
; PREVIOUSLY MODIFIED BY:
;
;	C. A. D'ELIA
;	T. J. MILLER
;
; MODIFIED BY:
;
; AFC11 ANALOG TO DIGITAL CONVERTER CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE R      EGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE TABLES (INDEXED BY CONTROLLER NUMBER)
;
 
CNTBL:	.BLKW	A$$F11		;ADDRESS OF UNIT CONTROL BLOCK
 
 
	.IF GT	A$$F11-1
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER
 
	.ENDC
 
	
;
; HARDWARE GAIN CODE TABLE
;
 
GAINTB:	.BYTE	160		;GAIN OF 1
	.BYTE	140		;GAIN OF 2
	.BYTE	100		;GAIN OF 10
	.BYTE	120		;GAIN OF 20
	.BYTE	60		;GAIN OF 50
	.BYTE	40		;GAIN OF 100
	.BYTE	20		;GAIN OF 200
	.BYTE      	0		;GAIN OF 1000
 
;
; DRIVER DISPATCH TABLE
;
 
$AFTBL::.WORD	AFCHK		;DEVICE INITIATOR ENTRY POINT
	.WORD	AFCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	AFOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	AFPWF		;POWERFAIL ENTRY POINT
 
;+
; **-AFCHK-AFC11 ANALOG TO DIGITAL CONVERTER CONTROLLER PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS RECEIVED FOR THE AFC11 ANALOG TO DIGITAL CONVERTOR. AFC11 I/O REQUESTS
; CONTAIN DEVICE DEPENDENT INFORMAT      ION THAT MUST BE CHECKED IN THE CONTEXT
; OF THE ISSUING TASK. THEREFORE THE I/O REQUEST IS NOT QUEUED BEFORE CALLING
; THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLER TO BE INITIATED.
;
; OUTPUTS:
;
;	THE CONTROL BUFFER IS ADDRESS CHECKED TO DETERMINE WHETHER IT LIES
;	WITHIN THE ISSUING TASK'S ADDRESS SPACE. IF THE ADDRESS CHECK
;	SUCCEEDS, THEN THE CONTROL BUFFER ADDRESS IS RELOCATED AND STO      RED
;	IN THE I/O PACKET, THE I/O PACKET IS INSERTED IN THE CONTROLLER
;	QUEUE, AND THE DEVICE INITIATOR IS ENTERED TO START THE CONTROLLER.
;	ELSE AN ILLEGAL BUFFER STATUS IS RETURNED AS THE FINAL I/O STATUS
;	OF THE REQUEST.
;-
 
AFCHK:	MOV	R1,R3		;COPY ADDRESS OF I/O PACKET
	MOV	I.PRM+6(R3),R0	;GET VIRTUAL ADDRESS OF CONTROL BUFFER
 
 
	.IF DF	A$$CHK!M$$MGE
 
	MOV	I.PRM+4(R3),R1	;SET LENGTH OF BUFFER TO CHECK
	CALL	$ACHCK		;ADDRESS CHECK CONTROL BUFFER
	BCC	10$		;IF CC ADDRESS OKAY
	MOV	#I      E.SPC&377,R0	;SET ILLEGAL BUFFER STATUS
	CALLR	$IOFIN		;FINISH I/O OPERATION
 
	.ENDC
 
 
10$:	CALL	$RELOC		;RELOCATE CONTROL BUFFER ADDRESS
	MOV	R1,I.PRM+6(R3)	;SET RELOCATION BIAS OF CONTROL BUFFER
	MOV	R2,I.PRM+10(R3)	;SET ADDRESS OF CONTROL BUFFER
	MOV	R3,R1		;SET ADDRESS OF I/O PACKET
	MOV	R4,R0		;SET ADDRESS OF I/O QUEUE LISTHEAD
	CALL	$QINSP		;INSERT I/O PACKET IN REQUEST QUEUE
 
;+
; **-AFINI-AFC11 ANALOG TO DIGITAL CONVERTOR CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE       QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF       THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-
 
	.ENABL	LSB
AFINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	AFCAN		;IF CS CONTROLLER BUSY OR NO REQUEST
 
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF       THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; AFC11 I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RBC).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	      WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER.
;	WD. 15 -- RELOCATION BIAS OF CONTROL BUFFER.
;	WD. 16 -- CONTROL BUFFER ADDRESS.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
; THE DATA BUFFER RECEIVES CONVERTED VALUES AND THE CONTROL BUFFER CONTAINS
; CONTROL WORDS THAT CONTROL THE CONVERSION PROCESS. EA      CH WORD IN THE CONTROL
; BUFFER HAS THE FORMAT:
;
;	BITS 15-12 -- GAIN CODE.
;
;		LEGAL GAIN CODES ARE:
;
;		0000=GAIN OF 1.
;		0001=GAIN OF 2.
;		0100=GAIN OF 10.
;		0101=GAIN OF 20.
;		1000=GAIN OF 50.
;		1001=GAIN OF 100.
;		1100=GAIN OF 200.
;		1101=GAIN OF 1000.
;
;	BITS 11-0 -- CHANNEL NUMBER.
;
;		EACH AFC11 MAY HAVE 2048. CHANNELS. THE LEGALITY OF
;		A PARTICULAR CHANNEL NUMBER IS DETERMINED BY THE
;		SECOND DEVICE CHARACTERISTICS WORD.
;
; EACH CHANNEL IS CONVERTED ACCORDING T      O THE CORRESPONDING WORD IN THE CONTROL
; BUFFER AND THE RESULTANT VALUE IS PLACED IN THE DATA BUFFER. IF AN ILLEGAL
; CONTROL WORD IS DETECTED THEN THE CONVERSION PROCESS IS TERMINATED. THE SECOND
; I/O STATUS WORD SPECIFIES THE NUMBER OF CHANNELS THAT WERE CONVERTED.
;-
 
	MOV	R5,CNTBL(R3)	;SAVE UCB ADDRESS
	MOV	I.PRM+6(R1),U.CBF(R5) ;SET RELOCATION BIAS OF CONTROL BUFFER
	MOV	I.PRM+10(R1),U.CBF+2(R5) ;SET ADDRESS OF CONTROL BUFFER
 
;
; INITIATE I/O OPERATION
;
 
10$:	CALL	$GTCWD		;GET NEXT       WORD FROM CONTROL BUFFER
	MOV	#IE.BAD&377,R0	;ASSUME ILLEGAL GAIN OR CHANNEL
	MOV	(SP)+,R1	;RETRIEVE CONTROL WORD
	MOV	R1,R2		;COPY CONTROL WORD
	BIC	#170000,R1	;CLEAR GAIN CODE BITS
	CMP	R1,U.CW2(R5)	;LEGAL CHANNEL THIS CONTROLLER?
	BHIS	AFOUT		;IF HIS NO
	BIC	#7777,R2	;CLEAR CHANNEL NUMBER
	ASL	R2		;ISOLATE HARDWARE GAIN
	ROL	R2		;
	ROL	R2		;
	BCS	AFOUT		;IF CS ILLEGAL GAIN CODE
	ASRB	R2		;DROP BIT 13 OF SOFTWARE GAIN
	ROL	R2		;RETRIEVE REMAINING GAIN BITS
	ROL	R2		;   FOR GAIN TABLE OFFSET      
	SWAB	R1		;GET HIGH BYTE OF GAIN COMMAND
	BISB	GAINTB(R2),R1	;SET GAIN CODE
	SWAB	R1		;RESTORE COMMAND
	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	MOV	S.CSR(R4),R4	;GET ADDRESS OF CONTROL STATUS REGISTER
	MOV	R1,4(R4)	;LOAD CHANNEL AND GAIN REGISTER
	MOV	#100,(R4)	;ENABLE INTERRUPT
 
;
; CANCEL I/O OPERATION IS A NOP FOR THE AFC11.
;
 
AFCAN:				;REF LABEL
 
;
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE ACTION ON THE DEVICE.
      ;
 
AFPWF:	RETURN			;
 
;+
; **$AFINT-AFC11 ANALOG TO DIGITAL CONVERTOR CONTROLLER INTERRUPTS
;-
 
$AFINT::			;REF LABEL
	INTSV$	AF,PR5,A$$F11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOV	S.CSR(R4),R3	;GET ADDRESS OF CONTROL STATUS REGISTER
	MOV	2(R3),-(SP)	;GET CONVERTED DIGITAL VALUE
	CALL	$PTWRD		;PUT CONVERTED VALUE IN DATA BUFFER
	SUB	#2,U.CNT(R5)	;ANY MORE TO CONVERT?
	BGT	10$		;IF GT YES
	MOV	#IS.SUC&377,R0	;SET SU      CCESSFUL COMPLETION STATUS
 
;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED WITH A FINAL
; I/O STATUS OF DEVICE NOT READY. THE SECOND I/O STATUS WORD CONTAINS THE
; NUMBER OF CHANNELS THAT WERE SAMPLED BEFORE THE TIMEOUT OCCURRED. TIMEOUTS
; ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A
; HARDWARE FAILURE.
;
 
AFOUT:	CLR	@S.CSR(R4)	;;;CLEAR INTERRUPT ENABLE
	CLRB	PS		;;;ALLOW INTERRUPTS
	MOV	S.PKT(R4),R3	;GET ADDRESS OF I/O PACKET
	MOV	I.PRM+4(R3),R1	;   Ú   GET SIZE OF ORIGINAL BUFFER
	SUB	U.CNT(R5),R1	;CALCULATE NUMBER OF BYTES PROCESSED
	ROR	R1		;CONVERT TO NUMBER OF SAMPLES PROCESSED
	CALL	$IODON		;FINISH I/O OPERATION
	BR	AFINI		;GO AGAIN
	.DSABL	LSB
 
	.END
 Ú          	ðskQ	› c,        	.TITLE	ARDRV
	.IDENT	/04.1/
 
;
; COPYRIGHT (C) 1974, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 04
;
; D.N. CUTLER / C.A. D'ELIA  1-JAN-75
;
; PREVIOUSLY MODIFIED BY:
;
;	C. A. D'ELIA
;	T. J. MILLER
;
; MODIFIED BY:
;
;	C. A. D'ELIA 24-MAR-77
;
;		CD037 -- REPLACE MISTYPED CONDITIONAL THAT CAUSES CRASH.
;
;	B. SCHREIBER 2-NOV-77
;
;	      	BS033 -- CLEAR I.PRM+16 BEFORE CALLING $IOFIN
;
;	B. SCHREIBER	19-MAY-78
;
;		BS049 -- FIX HANDLING OF DIGITAL INPUT WD. AT INTERRUPT
;
; AR11 LABORATORY PERIPHERAL SYSTEM CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	HWDDF$,PKTDF$,TCBDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
 
;
; EQUATED SYMBOLS
;
; SAMPLE CONTROL BLOCK OFFSET DEFINITIONS
;
 
	.PSECT	ARCTLQ,D,ABS
 
SLINK:	.BLKW	1		;SAMPLE QUEU      E THREAD WORD
RQPKT:	.BLKW	1		;ADDRESS OF I/O REQUEST PACKET
STATE:	.BLKW	1		;CURRENT SAMPLE STATE
RSTAT:	.BLKB	1		;SAMPLE STATUS BYTE
FINST:	.BLKB	1		;FINAL I/O STATUS
IOSB2:	.BLKW	2		;SECOND I/O STATUS WORD ADDRESS AND REL BIAS
STRBF:	.BLKW	1		;STARTING BUFFER ADDRESS AND RELOCATION BIAS
CURBF:	.BLKW	3		;CURRENT BUFFER ADDRESS AND RELOCATION BIAS
FULBF:	.BLKW	1		;SIZE OF FULL BUFFER IN WORDS
SMCNT:	.BLKW	1		;SPACE REMAINING TO END OF BUFFER
HAFBF:	.BLKW	1		;SIZE OF HALF BUFFER IN WORDS
 
 
	.      IF DF	D$$R11
 
DBMSK:	.BLKW	1		;DIGITAL INPUT/OUTPUT START MASK
DSMSK:	.BLKW	1		;DIGITAL INPUT STOP MASK
 
	.ENDC
 
 
CYCNT:	.BLKW	1		;NUMBER OF CLOCK TICKS TO NEXT SAMPLE
CRSET:	.BLKW	1		;RESET VALUE FOR CLOCK TICKS TO NEXT SAMPLE
SAMCT:	.BLKW	1		;NUMBER OF SAMPLE BUFFERS BEFORE BUFFER RUNOUT
DATAW:	.BLKW	1		;FUNCTION DEPENDENT DATA WORD
STRST:	.BLKW	1		;STARTING SAMPLE STATE
SLGTH:				;LENGTH OF SAMPLE CONTROL BLOCK
 
 
	.PSECT
 
;
; SAMPLE CONTROL BLOCK STATUS BYTE BIT DEFINITIONS
;
       
SPARE=200			;SPARE BIT
STROT=100			;SET DIGITAL OUTPUT BIT AT START (1=YES)
STPIN=40			;STOP ON DIGITAL INPUT BIT CLEAR (1=YES)
STPBR=20			;STOP ON BUFFER RUNOUT (1=YES)
GAINR=10	;(LPS11 ONLY)	;AUTOGAIN RANGING REQUESTED (1=YES)
SPARE=4				;SPARE BIT
RQEFN=2				;REQUEST EFN SETTING (1=YES)
STPRQ=1				;STOP SAMPLE REQUEST (1=YES)
 
;
; A/D TIMEOUT LOOP COUNT
;
 
TMOCNT=20.
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
 
CNTBL:	.BLKW	A$$R11		;ADDRE      SS OF CURRENT UNIT CONTROL BLOCK
 
 
	.IF DF	D$$R11
 
DGIWD:	.BLKW	A$$R11		;DIGITAL INPUT WORD LAST SYNCHRONOUS SAMPLE
 
	.ENDC
 
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE
 
;
; FORK REQUEST FLAG
;
 
FKFLG:	.WORD	0
 
;
; LEGAL FUNCTION VECTOR
;
 
LGFCN:	.BYTE	IO.SDO/256.	;WRITE DIGITAL OUTPUT REGISTER
	.BYTE	IO.SDI/256.	;READ DIGITAL INPUT REGISTER
	.BYTE	IO.STP/256.	;STOP IN-PROGRESS REQUEST
	.BYTE	IO.ADS/256.	;SYNCHRONOUS A/D SAMPLING
	.BYTE	IO.MDA/256.	;SYNCHRONOUS D/A OUTPUT
	.BYTE	      IO.MDO/256.	;SYNCHRONOUS DIGITAL OUTPUT
	.EVEN
 
;
; DRIVER DISPATCH TABLE
;
 
$ARTBL::.WORD	ARINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	ARCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	AROUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	ARPWF		;POWERFAIL ENTRY POINT
 
;+
; **-ARINI-AR11 LABORATORY PERIPHERAL SYSTEM CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS RECEIVED FOR THE AR11 LABORATORY PERIPHERAL SYSTEM. SEVEN FUNCTIONS ARE
; RECOGNIZED       BY THE AR11 DRIVER. FUNCTIONS ARE EITHER EXECUTED IMMEDITATELY
; OR PLACED IN A SAMPLE REQUEST QUEUE THAT IS MAINTAINED BY THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POIN      TER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE.
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;
; OUTPUTS:
;
;	IF THE FUNCTION IS STOP IN-PROGRESS REQUEST, WRITE DIGITAL OUTPUT
;	REGISTER, OR READ DIGITAL INPUT REGISTER,       THEN THE FUNCTION IS
;	EXECUTED IMMEDIATELY. ELSE A SECONDARY CONTROL BLOCK IS
;	CONSTRUCTED AND LINKED INTO THE SAMPLE REQUEST QUEUE.
;-
 
ARINI:	MOV	R4,R2		;GET ADDRESS OF SCB
	MOV	R1,R3		;SAVE I/O PACKET ADDRESS
	ADD	#I.PRM,R1	;POINT TO FIRST PARAMETER
	MOV	S.CSR(R2),R4	;GET ADDRESS OF CONTROL STATUS REGISTER
	MOV	#LGFCN,R0	;POINT TO LEGAL FUNCTION VECTOR
	MOVB	I.FCN+1(R3),-(SP) ;GET I/O FUNCTION CODE
	CMPB	(SP),(R0)+	;WRITE DIGITAL OUTPUT REGISTER?
 
 
	.IF DF	D$$R11
 
	BEQ	DIGIO		;IF E      Q YES
	CMPB	(SP),(R0)+	;READ DIGITAL INPUT REGISTER?
	BEQ	RDDIN		;IF EQ YES
 
	.IFF
 
	BEQ	ARONP		;IF EQ YES
	CMPB	(SP),(R0)+	;READ DIGITAL INPUT REGISTER?
	BEQ	ARONP		;IF EQ YES
 
	.ENDC
 
 
	CMPB	(SP),(R0)+	;STOP IN-PROGRESS REQUEST?
	BNE	ARFCN		;IF NE NO
 
;
; **-STOPR-STOP IN-PROGRESS REQUEST
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- BUFFER ADDRESS OF PREVIOUS REQUEST.
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
      ;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;	WD. 21 -- NOT USED.
;
 
STOPR:	MOV	(R1),R0		;GET ADDRESS OF BUFFER
	MOV	R2,R4		;SAVE ADDRESS OF SCB
	CALL	$RELOC		;RELOCATE BUFFER ADDRESS
	MOV	R3,-(SP)	;SAVE I/O PACKET ADDRESS
	MOV	R5,R3		;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R3	;
	MOVB	S.PRI(R4),PS	;;;LOCK OUT DEVICE INTERRUPTS
10$:	MOV	(R3),R3		;;;GET ADDRESS OF NEXT ENTRY
	BEQ	20$		;;;IF EQ DONE
	MOV	RQPKT(R3),R0	;;;GET ADDRESS OF I/O PACKET
	CMP	$TKTCB,I.TCB(R0) ;;;REQUEST       FOR CURRENT TASK?
	BNE	10$		;;;IF NE NO
	CMP	R1,STRBF(R3)	;;;RELOCATION BIAS MATCH?
	BNE	10$		;;;IF NE NO
	CMP	R2,STRBF+4(R3)	;;;BUFFER ADDRESS MATCH?
	BNE	10$		;;;IF NE NO
	MOVB	#IE.ABO,FINST(R3) ;;;SET FINAL STATUS ABORT
	CALL	TERMS		;;;TERMINATE SAMPLE REQUEST
20$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	MOV	(SP)+,R3	;RESTORE I/O PACKET ADDRESS
	BR	ARSUC		;TAKE COMMON EXIT
 
 
	.IF DF	D$$R11
 
;
; **-RDDIN-READ DIGITAL INPUT REGISTER
;
; INPUTS:
;
;	R1=POINTS TO WD. 12 OF I/O PACKET
;
      ; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- DIGITAL INPUT MASK WORD.
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;	WD. 21 -- NOT USED.
;
 
RDDIN:	SEC			;INDICATE DIGITAL INPUT REQUEST
DIGIO:	BITB	#20,U.CW2+1(R5)	;DR11-K PRESENT?
	BEQ	ARONP		;IF EQ NO
	MOV	U.CNT+4(R5),R4	;GET ITS CSR ADDRESS
	BCC	WRDOT		;BRANCH IF DIGITAL OUTPUT REQUESTED
 
 
	.IF GT	A$$R11-1
 
	MOVB	S.CON(R2),R2	;GE      T CONTROLLER INDEX
	MOV	DGIWD(R2),R2	;GET DIGITAL INPUT WORD LAST SYNCHRONOUS SAMPLE
 
	.IFF
 
	MOV	DGIWD,R2	;GET DIGITAL INPUT WORD LAST SYNCHRONOUS SAMPLE
 
	.ENDC
 
 
	TSTB	U.STS(R5)	;UNIT BUSY?
	BMI	10$		;IF MI YES
	MOV	2(R4),R2	;READ DIGITAL INPUT REGISTER
	MOV	R2,2(R4)	;CLEAR BITS IN DIGITAL INPUT REGISTER
10$:	COM	(R1)		;COMPLEMENT MASK WORD
	BIC	(R1),R2		;CLEAR UNWANTED BITS IN DATA WORD
	MOV	R2,R1		;SET SECOND I/O STATUS WORD
	BR	ARSUC1		;TAKE COMMON EXIT
 
;
; **-WRDOT-WRITE DI      GITAL OUTPUT REGISTER
;
; INPUTS:
;
;	R1=POINTS TO WD. 12 OF I/O PACKET
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- DIGITAL OUTPUT MASK WORD.
;	WD. 13 -- DIGITAL OUTPUT VALUE.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;	WD. 21 -- NOT USED.
;
 
WRDOT:	BIT	(R1),U.CNT+2(R5) ;DIGITAL OUTPUT BITS IN USE?
	BNE	ARRSU		;IF NE YES
	ADD	#4,R4		;POINT TO DIGITAL OUTPUT REGISTER
	COM	(R1)		;COMPLEMENT MASK WORD      
	BIC	(R1)+,(R1)	;CLEAR EXCESS BITS IN DATA WORD
	BIS	(R1),(R4)	;SET BITS IN DIGITAL OUTPUT REGISTER
	COM	(R1)		;COMPLEMENT DATA WORD
	BIC	-2(R1),(R1)	;CLEAR EXCESS BITS IN DATA WORD
	BIC	(R1),(R4)	;CLEAR BITS IN DIGITAL OUTPUT REGISTER
	MOV	(R4),R1		;SET SECOND I/O STATUS WORD
	BR	ARSUC1		;TAKE COMMON EXIT
 
	.ENDC
 
 
 
;
; SUCCESS COMPLETION OF FUNCTION
;
 
ARSUC:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
ARSUC1:	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS CODE
	BR	ARCMN1		;
 
;      
; BAD PARAMETER
;
 
ARBAD:	MOV	#IE.BAD&377,R0	;SET BAD PARAMETER STATUS CODE
	BR	ARCMN		;
 
 
	.IF DF	D$$R11
 
;
; RESOURCE IN USE
;
 
ARRSU:	MOV	#IE.RSU&377,R0	;SET RESOURCE IN USE STATUS CODE
	BR	ARCMN		;
 
	.ENDC
 
 
;
; PRIVILEGE VIOLATION
;
 
ARPRI:	MOV	#IE.PRI&377,R0	;SET PRIVILEGE VIOLATION STATUS
	BR	ARCMN		;
 
;
; OPTION NOT PRESENT
;
 
ARONP:	MOV	#IE.ONP&377,R0	;SET OPTION NOT PRESENT STATUS
	BR	ARCMN		;
 
;
; DYNAMIC MEMORY NOT AVAILABLE
;
 
ARNOD:	MOV	#IE.NO      D&377,R0	;SET MEMORY NOT AVAILABLE STATUS
 
;
; COMMON STATUS EXIT
;
 
ARCMN:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
ARCMN1:	TST	(SP)+		;REMOVE FUNCTION CODE FROM STACK
	CLR	I.PRM+16(R3)	;CLEAR BLOCK LOCKING WORD FOR $IOFIN
	CALLR	$IOFIN		;FINISH I/O OPERATION
 
;
; ALL REMAINING FUNCTIONS REQUIRE THE REQUESTING TASK TO BE EITHER FIXED
; IN MEMORY OR NOT CHECKPOINTABLE AND AN I/O STATUS DOUBLEWORD TO BE
; SPECIFIED.
;
; INPUTS:
;
;	R1=POINTS TO WD. 12 OF I/O PACKET
;
; FUNCTION DEPENDENT       I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF BUFFER.
;	WD. 13 -- BUFFER ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 14 -- BUFFER SIZE IN BYTES.
;	WD. 15 -- DIGITAL INPUT/OUTPUT POINT NUMBERS.
;	WD. 16 -- AR11 CLOCK TICKS BETWEEN SAMPLES.
;	WD. 17 -- NUMBER OF BUFFERS.
;	WD. 20 -- FUNCTION DEPENDENT DATA WORD.
;	WD. 21 -- SCRATCH.
;
 
ARFCN:	MOV	I.TCB(R3),R2	;GET REQUESTING TASK TCB ADDRESS
	BIT	#T2.CHK!T2.FXD,T.ST2(R2) ;TASK FXED OR NOT CHKPOINTABLE?
	BEQ	ARPRI		;IF EQ NO
	T      ST	I.IOSB+4(R3)	;I/O STATUS DOUBLEWORD SPECIFIED?
	BEQ	ARBAD		;IF EQ NO
	ADD	#6,R1		;POINT TO DIGITAL I/O BIT NUMBERS
	BITB	#340,I.FCN(R3)	;DIGITAL I/O SUB-FUNCTION REQUESTED?
 
 
	.IF DF	D$$R11
 
	BEQ	35$		;IF EQ NO
	BITB	#20,U.CW2+1(R5)	;DR11-K PRESENT?
	BEQ	ARONP		;IF EQ NO
	MOVB	I.FCN(R3),R2	;GET SUBFUNCTION MODIFIER BITS
	BPL	10$		;IF PL START IMMEDIATELY
	CMPB	(R1),#16.	;LEGAL DIGITAL POINT NUMBER?
	BHIS	ARBAD		;IF HIS NO
10$:	ASLB	R2		;SET DIGITAL OUTPUT ON START?
	BPL	20$		;IF PL NO      
	CMPB	(R1),#16.	;LEGAL DIGITAL POINT NUMBER?
	BHIS	ARBAD		;IF HIS NO
	MOVB	(R1),R4		;GET DIGITAL OUTPUT POINT NUMBER
	ASL	R4		;CONVERT TO WORD INDEX
	BIT	$BTMSK(R4),U.CNT+2(R5) ;DIGITAL OUTPUT BIT IN USE?
	BNE	ARRSU		;IF NE YES
20$:	ASLB	R2		;STOP ON DIGITAL INPUT?
	BPL	30$		;IF PL NO
	CMPB	1(R1),#16.	;LEGAL DIGITAL POINT NUMBER?
	BHIS	ARBAD		;IF HIS NO
30$:	ASL	(R1)		;CONVERT BOTH POINT NUMBERS TO WORD INDICES
 
	.IFF
 
	BNE	ARONP		;IF NE YES
 
	.ENDC
 
 
35$:	ADD	#8.,R1		;POINT TO LAST       (SCRATCH) WORD IN I/O PACKET
	CMPB	(SP),(R0)+	;SYNCHRONOUS A/D SAMPLING?
	BEQ	60$		;IF EQ YES
	CMPB	(SP),(R0)+	;SYNCHRONOUS D/A OUTPUT?
 
 
	.IF DF	A$$RDA
 
	BEQ	50$		;IF EQ YES
 
	.IFF
 
	BEQ	ARONP		;D/A NOT PRESENT
 
	.ENDC
 
 
	.IF DF	D$$R11
 
	BITB	#20,U.CW2+1(R5)	;DR11-K SUPPORT?
	BEQ	ARONP		;IF EQ NO
	CMPB	(SP),(R0)+	;SYNCHRONOUS DIGITAL OUTPUT?
	BNE	40$		;IF NE NO (SYNCHRONOUS DIGITAL INPUT)
 
;
; SYNCHRONOUS DIGITAL OUTPUT
;
; CONTENTS OF FUNCTION DEPENDENT WORD IN I/O PA      CKET
;	WD. 20 -- DIGITAL OUTPUT BIT MASK.
;
 
	MOV	#SYNDO,(R1)	;SET SYNCHRONOUS DIGITAL OUTPUT STATE
	BIT	-(R1),U.CNT+2(R5) ;ANY DIGITAL OUTPUT BITS IN USE?
	BR	45$		;CONTINUE IN COMMON CODE
 
;
; SYNCHRONOUS DIGITAL INPUT
;
; CONTENTS OF FUNCTION DEPENDENT WORD IN I/O PACKET
;	WD. 20 -- DIGITAL INPUT BIT MASK.
;
 
40$:	MOV	#SYNDI,(R1)	;SET SYNCHRONOUS DIGITAL INPUT STATE
	BIT	-(R1),U.CNT(R5)	;ANY DIGITAL INPUT BITS IN USE?
45$:	BNE	ARRSU		;IF NE YES
	BR	120$		;CONTINUE IN COMMON CODE
 
      	.IFF
 
	BR	ARONP		;DIGITAL I/O NOT PRESENT
 
	.ENDC
 
 
 
;
; SYNCHRONOUS D/A OUTPUT
;
; CONTENTS OF FUNCTION DEPENDENT WORD IN I/O PACKET
;	WD. 20 -- D/A CHANNELS.
;
 
 
	.IF DF	A$$RDA
 
50$:	MOV	#SYNDA,(R1)	;SET SYNCHRONOUS D/A OUTPUT STATE
	MOVB	U.CW2+1(R5),R0	;GET OPTION FLAGS AND NUMBER OF D/A'S
	BIT	#100,R0		;D/A OPTION PRESENT?
	BEQ	ARONP		;IF EQ NO
	BIC	#^C<17>,R0	;CLEAR ALL BUT NUMBER OF D/A'S
	MOVB	-(R1),R2	;GET NUMBER OF OUTPUT D/A'S
	MOVB	-(R1),R4	;GET STARTING D/A NUMBE      R
	BR	90$		;FINISH IN COMMON CODE
 
	.ENDC
 
 
;
; SYNCHRONOUS A/D SAMPLING
;
; CONTENTS OF FUNCTION DEPENDENT WORD IN I/O PACKET
;	WD. 20 -- A/D CHANNELS.
;
 
60$:	MOV	#SYNAD,(R1)	;SET SYNCHRONOUS A/D SAMPLING STATE
	MOVB	-(R1),R2	;GET NUMBER OF CHANNELS
	MOVB	-(R1),R4	;GET STARTING CHANNEL
	MOVB	U.CW2(R5),R0	;GET NUMBER OF A/D CHANNELS
90$:	DEC	R2		;REDUCE NUMBER OF CHANNELS
	ADD	R2,R4		;CALCULATE HIGHEST CHANNEL
	BCS	ARBAD		;IF CS BAD RANGE
	CMP	R4,R0		;LEGAL CHANNEL?
	BHIS	ARBAD		;I      F HIS NO
 
120$:	MOV	R3,R4		;SAVE I/O PACKET ADDRESS
	MOV	#SLGTH,R1	;SET LENGTH OF SECONDARY CONTROL BLOCK
	CALL	$ALOCB		;ALLOCATE SECONDARY CONTROL BLOCK
	MOV	R4,R3		;RESTORE I/O PACKET ADDRESS
	BCS	ARNOD		;IF CS NO MEMORY AVAILABLE
	MOV	R0,R1		;COPY SECONDARY CONTROL BLOCK ADDRESS
	CLR	(R1)+		;CLEAR LINK WORD
	MOV	R3,(R1)+	;INSERT I/O PACKET ADDRESS
	ADD	#I.FCN,R3	;POINT TO SUBFUNCTION MODIFIER BITS
 
 
	.IF DF	D$$R11
 
	MOV	#SDOUT,(R1)+	;ASSUME INITIAL STATE IS DIGITAL OUTPUT
 
	.IFF
       
	MOV	I.PRM+14.(R4),(R1)+ ;SET INITIAL STATE TO CONVERT REQUEST
 
	.ENDC
 
 
	MOV	(R3),(R1)	;INSERT SUBFUNCTION MODIFIER BITS
	BIC	#^C<STROT!STPIN!STPBR!GAINR>,(R1)+ ;CLEAR EXTRANEOUS BITS
	ADD	#I.IOSB+2,R4	;POINT TO I/O STATUS DOUBLEWORD ADDRESS
	MOV	(R4)+,(R1)+	;INSERT RELOCATION BIAS
	MOV	(R4)+,(R1)	;INSERT DISPLACEMENT ADDRESS
	ADD	#2,(R1)+	;CALCULATE ADDRESS OF SECOND I/O STATUS
	TST	(R4)+		;BYPASS AST ADDRESS AND CLEAR CARRY
	MOV	(R4),(R1)+	;INSERT BUFFER RELOCATION BIAS
	MOV	(R4)+,(R1)+	      ;
	MOV	(R4),(R1)+	;INSERT BUFFER DISPLACEMENT ADDRESS
	MOV	(R4)+,(R1)+	;
	MOV	(R4)+,(R1)	;INSERT SIZE OF BUFFER IN BYTES
	ROR	(R1)		;CONVERT TO SIZE IN WORDS
	MOV	(R1)+,(R1)	;INSERT SIZE OF BUFFER IN WORDS
	MOV	(R1)+,(R1)	;INSERT SIZE OF BUFFER IN WORDS
	ASR	(R1)+		;CONVERT TO SIZE IN DOUBLEWORDS
 
 
	.IF DF	D$$R11
 
	MOVB	(R4)+,R2	;GET DIGITAL INPUT/OUTPUT POINT INDEX
	CLR	(R1)		;ASSUME NO DIGITAL INPUT/OUTPUT POINT
	ASLB	(R3)		;START ON DIGITAL INPUT POINT?
	BCC	130$		;IF CC NO
	MOV	#SWAIT      ,STATE(R0) ;ALTER STATE TO WAIT ON DIGITAL INPUT
	BR	140$		;
130$:	BPL	150$		;IF PL NO DIGITAL OUTPUT ON START
140$:	MOV	$BTMSK(R2),(R1)	;INSERT DIGITAL INPUT/OUTPUT POINT MASK
	TSTB	(R3)		;SET DIGITAL OUTPUT POINT AT START?
	BPL	150$		;IF PL NO
	BIS	(R1),U.CNT+2(R5) ;SET DIGITAL OUTPUT POINT IN USE
150$:	TST	(R1)+		;ADVANCE TO NEXT WORD
	CLR	(R1)		;ASSUME NO DIGITAL INPUT POINT
	MOVB	(R4)+,R2	;GET DIGITAL INPUT POINT INDEX
	ASLB	(R3)		;STOP ON DIGITAL INPUT POINT?
	BPL	160$		;IF PL NO
	MOV	$BTM      SK(R2),(R1)	;INSERT DIGITAL INPUT POINT MASK
160$:	CMP	(R1)+,(SP)+	;ADVANCE TO NEXT WORD AND CLEAN STACK
 
	.IFF
 
	CMP	(R4)+,(SP)+	;SKIP DIGITAL I/O WORD AND CLEAN STACK
 
	.IFTF
 
	MOV	#1,(R1)+	;INSERT INITIAL CLOCK TICKS TO NEXT SAMPLE
	MOV	(R4)+,(R1)+	;INSERT CLOCK TICKS RESET VALUE
	MOV	(R4)+,(R1)+	;INSERT NUMBER OF BUFFERS TO COLLECT
	MOV	(R4)+,(R1)+	;INSERT FUNCTION DEPENDENT (CHANNELS) DATA WORD
	MOV	(R4),(R1)	;INSERT STARTING SAMPLE STATE
 
	.IFT
 
	CMP	#SYNDO,(R1)	;SYNCHRONOUS DIG      ITAL OUTPUT?
	BEQ	170$		;IF EQ YES
	CMP	#SYNDI,(R1)	;SYNCHRONOUS DIGITAL INPUT?
	BNE	190$		;IF NE NO
	BIS	-(R1),U.CNT(R5)	;SET DIGITAL INPUT BITS IN USE
	BR	180$		;
170$:	BIS	-(R1),U.CNT+2(R5) ;SET DIGITAL OUTPUT BITS IN USE
180$:	COM	(R1)		;COMPLEMENT MASK WORD
 
	.ENDC
 
 
190$:	MOV	U.BUF(R5),(R0)	;INSERT REQUEST IN SAMPLE QUEUE
	MOV	R0,U.BUF(R5)	;
	MOVB	I.EFN-<I.PRM+16>(R4),R0 ;GET SPECIFIED EVENT FLAG NUMBER
	MOV	R5,-(SP)	;SAVE UCB ADDRESS
	MOV	I.TCB-<I.PRM+16>(R4),R5 ;GET TCB ADDRESS OF       REQUESTER TASK
	CALL	$CEFI		;CONVERT EFN TO MASK AND ADDRESS
	MOV	R1,(R4)		;INSERT EFN MASK ADDRESS
	MOV	R0,-(R4)	;INSERT EFN MASK WORD
	MOV	(SP)+,R5	;RETRIEVE UCB ADDRESS
	MOV	U.SCB(R5),R3	;GET ADDRESS OF SCB
	TSTB	U.STS(R5)	;UNIT BUSY?
	BMI	200$		;IF MI YES
	MOV	S.CSR(R3),R2	;GET ADDRESS OF CONTROL STATUS REGISTER
	CMP	(R2)+,(R2)+	;POINT TO CLOCK STATUS REGISTER
	MOV	#506,(R2)+	;SET REPEAT MODE, 10KHZ, AND ENABLE INT
	MOV	U.CW4(R5),(R2)	;LOAD COUNTER PRESET REGISTER
	NEG	(R2)		;NEGATE PRESET       VALUE
	INC	-(R2)		;START CLOCK RUNNING
200$:	BISB	#US.BSY,U.STS(R5) ;SET UNIT BUSY
	MOVB	#1,S.STS(R3)	;SET CONTROLLER BUSY
	MOVB	S.ITM(R3),S.CTM(R3) ;SET CURRENT TIMEOUT COUNT
	RETURN			;
 
;+
;
; **-$ARCLK-AR11 LABORATORY PERIPHERAL SYSTEM CLOCK INTERRUPT
;
;-
 
$ARCLK::			;;;REF LABEL
$ARINT::			;;;REF LABEL
	INTSV$	AR,PR6,A$$R11	;;;GENERATE INTERRUPT SAVE CODE
	MOV	R3,-(SP)	;;;SAVE R3 AND R2
	MOV	R2,-(SP)	;;;
 
 
	.IF GT	A$$R11-1
 
	MOV	R1,-(SP)	;;;SAVE R1
	MOV	R4,R1		;;;PUT CONTRO      LLER INDEX IN R1
	
	.ENDC
 
 
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
	MOV	S.CSR(R4),R4	;;;GET ADDRESS OF CONTROL STATUS REGISTER
 
 
	.IF DF	D$$R11
 
	MOV	R0,-(SP)	;;;SAVE R0
	MOV	U.CNT+4(R5),R0	;;;GET CSR ADDRESS OF DR11-K
 
	.IF GT	A$$R11-1
 
	BEQ	10$		;;;SKIP IF NO DR11-K FOR THIS CONTROLLER
 
	.IFTF
 
	MOV	2(R0),R3	;;;READ DIGITAL INPUT REGISTER
 
	.IFT
 
	MOV	R3,DGIWD(R1)	;;;SAVE DIGITAL INPUT WORD
 
	.IFF
 
	MOV	R3,DGIWD	;;      ;SAVE DIGITAL INPUT WORD
 
	.ENDC
 
 
	MOV	R3,TEMP		;;;SAVE COMPLEMENT OF DIGITAL INPUT WORD
	COM	TEMP		;;;
	MOV	R3,2(R0)	;;;CLEAR BITS IN DIGITAL INPUT REGISTER
10$:				;;;REF LABEL
 
	.ENDC
 
 
	MOV	R5,R3		;;;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R3	;;;
 
 
	.IF DF	M$$MGE
 
	MOV	KISAR6,-(SP)	;;;SAVE CURRENT APR6 MAPPING
	
	.ENDC
 
 
;
; GET NEXT REQUEST FROM SAMPLE QUEUE AND PROCESS
;
 
	.ENABL	LSB
NXTRQ:	MOV	(R3),R3		;;;GET ADDRESS OF NEXT SAMPLE REQUEST
	BE      Q	20$		;;;IF EQ END OF REQUEST QUEUE
	DEC	CYCNT(R3)	;;;TIME TO SAMPLE?
	BNE	NXTRQ		;;;IF NE NO
10$:	MOV	CRSET(R3),CYCNT(R3) ;;;RESET SAMPLE CYCLE COUNT
	JMP	@STATE(R3)	;;;PROCESS SAMPLE REQUEST
20$:	JMP	ENDRQ		;;;
 
 
	.IF DF	D$$R11
 
;
; START SAMPLING IF DIGITAL INPUT BIT SET
;
 
SWAIT:	MOV	#1,CYCNT(R3)	;;;SET TO REPEAT TEST AT NEXT INTERVAL
	BIT	DBMSK(R3),TEMP	;;;START SAMPLING?
	BNE	NXTRQ		;;;IF NE NO
	BITB	#STROT,RSTAT(R3) ;;;SET DIGITAL OUTPUT BIT AT START?
	BEQ	30$		;;;IF EQ NO
 
      ;
; SET DIGITAL OUTPUT BIT
;
 
SDOUT:	BIS	DBMSK(R3),4(R0) ;;;SET DIGITAL OUTPUT BIT
30$:	MOV	STRST(R3),STATE(R3) ;;;CHANGE STATE TO STARTING VALUE
	BR	10$		;;;DISPATCH ON NEW STATE
 
;
; SYNCHRONOUS DIGITAL OUTPUT
;
 
SYNDO:				;;;REF LABEL
	CALL	RDWRD		;;;READ WORD FROM USER BUFFER
	BCS	NXTRQ		;;;IF CS BUFFER OVERRUN
	MOV	4(R0),-(SP)	;;;READ DIGITAL OUTPUT REGISTER
	MOV	DATAW(R3),-(SP)	;;;GET OUTPUT MASK WORD
	BIC	(SP),R2		;;;CLEAR EXCESS BITS IN DATA WORD
	COM	(SP)		;;;COMPLEMENT MASK WO      RD
	BIC	(SP)+,(SP)	;;;CLEAR FIELD BITS IN OUTPUT WORD
	BIS	(SP)+,R2	;;;MERGE DATA AND OUTPUT WORD
	MOV	R2,4(R0)	;;;WRITE VALUE INTO DIGITAL OUTPUT REGISTER
	BR	NXTRQ		;;;CONTINUE SCAN
 
	.ENDC
 
 
	.DSABL	LSB
 
 
;
; SYNCHRONOUS A/D SAMPLING
;
 
SYNAD:	MOV	DATAW(R3),-(SP)	;;;SET COUNT AND STARTING CHANNEL
 
 
	.IF DF	U$$NIP
 
10$:	MOVB	(SP),R2		;;;GET CHANNEL NUMBER
	ASL	R2		;;;CONVERT NUMBER TO OFFSET
	BIT	$BTMSK(R2),U.CW3(R5) ;;;EXAMINE CHANNEL POLARITY
	BEQ	15$		;;;IF EQ BIPOLAR
      	BIS	#100,R2		;;;SET UNIPOLAR
15$:	ASR	R2		;;;CONVERT BACK TO CHANNEL NUMBER
	MOVB	R2,1(R4)	;;;SET CHANNEL NUMBER AND POLARITY
 
	.IFF
 
10$:	MOVB	(SP),1(R4)	;;;SET CHANNEL NUMBER (BIPOLAR SAMPLE)
 
	.ENDC
 
 
	MOVB	#1,(R4)		;;;START CONVERSION
	MOV	#TMOCNT,R2	;;;SET TIMEOUT LOOP COUNT
20$:	TSTB	(R4)		;;;DONE?
	BMI	90$		;;;IF MI DONE
	DEC	R2		;;;TIMEOUT?
	BGT	20$		;;;IF GT NO
70$:	MOV	#177777,R2	;;;SET TIMEOUT ERROR VALUE
	BR	100$		;;;
90$:	MOV	2(R4),R2	;;;READ CONVERTED VALUE
100$:	CALL      	WRWRD		;;;WRITE WORD INTO USER BUFFER
	BCS	110$		;;;IF CS BUFFER OVERRUN
	INCB	(SP)		;;;INCREMENT CHANNEL NUMBER
	DECB	1(SP)		;;;ANY MORE CHANNELS TO SAMPLE?
	BGT	10$		;;;IF GT YES
110$:	TST	(SP)+		;;;CLEAN STACK
	JMP	NXTRQ		;;;CONTINUE SCAN
 
 
	.IF DF	A$$RDA
 
;
; SYNCHRONOUS D/A OUTPUT
;
 
SYNDA:	MOV	DATAW(R3),-(SP)	;;;SET COUNT AND STARTING D/A NUMBER
10$:	CALL	RDWRD		;;;READ WORD FROM USER BUFFER
	BCS	60$		;;;IF CS BUFFER OVERRUN
	BIC	#176000,R2	;;;CLEAR D/A NUMBER FIELD
	MOVB	(SP),      -(SP)	;;;COPY D/A NUMBER
	DECB	(SP)		;;;D/A 0 OR 1 ONLY
	BEQ	30$		;;;IF EQ D/A 1 (Y-REG)
	MOV	R2,12(R4)	;;;OUTPUT TO X-REG D/A
	BR	40$		;;;
30$:	MOV	R2,14(R4)	;;;OUTPUT TO Y-REG D/A
40$:	TST	(SP)+		;;;CLEAN STACK
50$:	INC	(SP)		;;;INCREMENT D/A NUMBER
	DECB	1(SP)		;;;ANY MORE TO GO?
	BGT	10$		;;;IF GT YES
60$:	TST	(SP)+		;;;CLEAN STACK
	JMP	NXTRQ		;;;CONTINUE SCAN
 
	.ENDC
 
 
 
	.IF DF	D$$R11
 
;
; SYNCHRONOUS DIGITAL INPUT SAMPLING
;
 
SYNDI:				;;;REF LABEL
 
 
	.IF GT	A$$R11-1      
 
	MOV	DGIWD(R1),R2	;;;GET SAVED DIGITAL INPUT WORD
 
	.IFF
 
	MOV	DGIWD,R2	;;;GET SAVED DIGITAL INPUT WORD
 
	.ENDC
 
 
	MOV	DATAW(R3),-(SP) ;;;GET INPUT MASK WORD
	BIC	(SP)+,R2	;;;CLEAR EXCESS BITS IN DATA WORD
	CALL	WRWRD		;;;WRITE WORD INTO USER BUFFER
	JMP	NXTRQ		;;;CONTINUE SCAN
 
	.ENDC
 
 
;
; END OF REQUEST QUEUE--CHECK IF FORK REQUIRED
;
 
ENDRQ:				;;;REF LABEL
 
 
	.IF DF M$$MGE
 
	MOV	(SP)+,KISAR6	;;;RESTORE APR6 MAPPING
 
	.ENDC
 
 
	.IF DF	D$$R11
 
	MOV	(SP)      +,R0	;;;RESTORE R0
 
	.ENDC
 
 
	.IF GT	A$$R11-1
 
	MOV	(SP)+,R1	;;;RESTORE R1
 
	.ENDC
 
 
	MOV	(SP)+,R2	;;;RESTORE R2 AND R3
	MOV	(SP)+,R3	;;;
	TST	FKFLG		;;;FORK REQUESTED?
	BEQ	10$		;;;IF EQ NO
	CLR	FKFLG		;;;CLEAR FORK REQUESTED FLAG
	BITB	#US.FRK,U.STS(R5) ;;;FORK ALREADY IN PROGRESS?
	BEQ	ENDRQ1		;;;IF EQ NO
10$:	JMP	$INTXT		;;;EXIT INTERRUPT
 
;+
; **-ARCAN-CANCEL I/O REQUESTS
;
; THIS ROUTINE IS ENTERED TO CANCEL ALL I/O REQUESTS THAT ARE IN PROGRESS FOR
; THE CURRENT TASK.       THE SAMPLE QUEUE IS SCANNED AND ALL REQUESTS FOR THE CURRENT
; TASK ARE MARKED FOR TERMINATION WITH A FINAL REQUEST STATUS OF 'IE.ABO'.
;
; INPUTS:
;
;	R0=ADDRESS OF THE CURRENT I/O PACKET (MEANINGLESS).
;	R1=ADDRESS OF THE TCB OF THE CURRENT TASK.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	ALL REQUESTS FOR THE CURRENT TASK ARE MARKED FOR TERMINATION WITH
;	A FINAL STATUS OF 'IE.ABO'.
;-
 
	.ENABL	LSB
ARCAN:	MO      V	#IE.ABO&377,R0	;;;SET FINAL STATUS CODE TO ABORT
	BR	10$		;;;FINISH IN COMMON CODE
 
;+
; **-AROUT-DEVICE TIMEOUT
;
; THIS ROUTINE IS ENTERED WHEN AN AR11 OPERATION TIMES OUT. ALL REQUESTS IN THE
; SAMPLE QUEUE ARE MARKED FOR TERMINATION WITH A FINAL STATUS OF 'IE.DNR'.
; TIMEOUTS ARE USUALLY CAUSED BY A POWER FAILURE BUT MAY ALSO BE THE RESULT
; OF A HARDWARE FAILURE.
;
; INPUTS:
;
;	R0=DEVICE TIMEOUT STATUS 'IE.DNR'.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=A      DDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	ALL REQUESTS ARE MARKED FOR TERMINATION WITH A FINAL STATUS OF
;	'IE.DNR'.
;-
 
AROUT:	MOV	S.CSR(R4),R2	;;;GET ADDRESS OF CONTROL STATUS REGISTER
	CLR	(R2)		;;;CLEAR A/D INTERRUPTS
	CLR	4(R2)		;;;CLEAR CLOCK INTERRUPTS
10$:	MOV	R5,R2		;;;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R2	;;;
20$:	MOV	(R2),R2		;;;GET ADDRESS OF NEXT ENTRY
	BEQ	40$		;;;IF EQ NONE
	CMPB	#IE.ABO,R0	;;;CANCEL I/O?
	BNE	30$		;;;IF NE NO
	MOV	RQPKT(R2),R3	;      ;;GET ADDRESS OF I/O PACKET
	CMP	R1,I.TCB(R3)	;;;REQUEST FOR CURRENT TASK?
	BNE	20$		;;;IF NE NO
30$:	BISB	#STPRQ,RSTAT(R2) ;;;SET TO TERMINATE SAMPLE REQUEST
	MOVB	R0,FINST(R2)	;;;SET FINAL REQUEST STATUS
	MOV	#NXTRQ,STATE(R2) ;;;SET STATE TO TERMINATION IN PROGRESS
	BR	20$		;;;
40$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	BR	ENDRQ2		;FINISH IN COMMON CODE
	.DSABL	LSB
 
;+
; **-ARPWF-POWERFAIL
;
; THIS ROUTINE IS ENTERED AS THE RESULT OF A POWER FAILURE. POWERFAIL IS HANDLED
; VIA THE DEVICE TI      MEOUT FACILITY AND THEREFORE CAUSES NO IMMEDIATE ACTION ON
; THE DEVICE. THE UNIT CONTROL BLOCK ADDRESS IS STORED IN THE DRIVER CONTROLLER
; TABLE.
;
; INPUTS:
;
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	THE UNIT CONTROL BLOCK ADDRESS IS STORED IN THE DRIVER CONTROLLER TABLE.
;-
 
ARPWF:	MOV	R5,CNTBL(R3)	;SET ADDRESS OF UNIT CONTROL BLOCK
	RETURN			;
 
;
; FORK REQUESTED AND NO FORK IN PROGRESS
;
 
ENDRQ1:	      BISB	#US.FRK,U.STS(R5) ;;;SET FORK IN PROGRESS FLAG
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	BICB	#US.FRK,U.STS(R5) ;CLEAR FORK IN PROGRESS FLAG
 
;
; SCAN SAMPLE QUEUE FOR EVENT FLAG AND TERMINATION REQUESTS
;
 
ENDRQ2:	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOVB	S.PRI(R4),PS	;;;LOCK OUT DEVICE INTERRUPTS
	MOV	R5,R4		;;;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R4	;;;
10$:	MOV	R4,R3		;;;SAVE ADDRESS OF PREVIOUS ENTRY
	MOV	(R3),R4		;;;GET ADDRESS OF NEXT ENTRY
	BEQ	70$		;;;IF EQ NO      NE
	BITB	#STPRQ,RSTAT(R4) ;;;TERMINATE REQUEST?
	BNE	20$		;;;IF NE YES
	BITB	#RQEFN,RSTAT(R4) ;;;REQUEST EFN SETTING?
	BEQ	10$		;;;IF EQ NO
	BICB	#RQEFN,RSTAT(R4) ;;;CLEAR EFN REQUEST FLAG
	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	MOV	RQPKT(R4),R3	;GET ADDRESS OF I/O PACKET
	MOV	I.TCB(R3),R0	;GET TCB ADDRESS OF REQUESTING TASK
	BIT	#T2.ABO,T.ST2(R0) ;TASK BEING ABORTED?
	BNE	ENDRQ2		;IF NE YES
	BIS	I.PRM+14(R3),@I.PRM+16(R3) ;SET SPECIFIED EVENT FLAG
	CALL	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST      
	BR	ENDRQ2		;TRY AGAIN
20$:	MOV	(R4),(R3)	;;;REMOVE ENTRY FROM QUEUE
30$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
 
 
	.IF DF	D$$R11
 
	MOV	DATAW(R4),R3	;GET DATA MASK WORD
	COM	R3		;CONVERT MASK TO IN USE BITS
	CMP	#SYNDO,STRST(R4) ;SYNCRHONOUS DIGITAL OUTPUT?
	BEQ	40$		;IF EQ YES
	CMP	#SYNDI,STRST(R4) ;SYNCHRONOUS DIGITAL INPUT
	BNE	50$		;IF NE NO
	BIC	R3,U.CNT(R5)	;CLEAR INPUT BITS IN USE MASK
	BR	50$		;
40$:	BIC	R3,U.CNT+2(R5)	;CLEAR OUTPUT BITS IN USE MASK
50$:	BITB	#STROT,RSTAT(R4) ;SET       DIGITAL OUTPUT BIT ON START?
	BEQ	60$		;IF EQ NO
	BIC	DBMSK(R4),U.CNT+2(R5) ;CLEAR OUTPUT BIT IN USE MASK
 
	.ENDC
 
 
60$:	CLR	R0		;PICKUP FINAL I/O STATUS
	BISB	FINST(R4),R0	;
 
 
	.IF DF	M$$MGE
 
	MOV	KISAR6,-(SP)	;SAVE CURRENT APR6 MAPPING
	MOV	IOSB2(R4),KISAR6  ;MAP TO SECOND I/O STATUS WORD
	
	.IFTF
 
	MOV	@IOSB2+2(R4),R1	;RETRIEVE CONTENTS OF SECOND I/O STATUS WORD
 
	.IFT
 
	MOV	(SP)+,KISAR6	;RESTORE CURRENT APR6 MAPPING
	
	.ENDC
 
 
	MOV	RQPKT(R4),R3	;GET ADDRESS OF I/O P      ACKET
	MOV	R4,-(SP)	;SAVE ADDRESS OF SECONDARY CONTROL BLOCK
	CLR	I.PRM+16(R3)	;CLEAR BLOCK LOCKING WORD FOR $IOFIN
	CALL	$IOFIN		;FINISH I/O OPERATION
	MOV	(SP)+,R0	;RETRIEVE ADDRESS OF SECONDARY CONTROL BLOCK
	MOV	#SLGTH,R1	;SET LENGTH OF SECONDARY CONTROL BLOCK
	CALL	$DEACB		;RELEASE SECONDARY CONTROL BLOCK
	BR	ENDRQ2		;GO AGAIN
 
;
; SCAN OF SAMPLE QUEUE COMPLETE--CHECK IF ANYTHING IS STILL ACTIVE
;
 
70$:	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET DEVICE TIM      EOUT COUNT
	TST	U.BUF(R5)	;;;ANY REQUESTS IN SAMPLE QUEUE
	BNE	80$		;;;IF NE YES
	MOV	S.CSR(R4),R3	;;;GET ADDRESS OF CONTROL STATUS REGISTER
	CLR	(R3)		;;;CLEAR A/D INTERRUPTS
	CLR	4(R3)		;;;CLEAR CLOCK INTERRUPTS
	BICB	#US.BSY,U.STS(R5) ;;;CLEAR UNIT BUSY
	CLRB	S.STS(R4)	;;;CLEAR CONTROLLER BUSY
80$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	RETURN			;
 
;
; SUBROUTINE TO READ A VALUE FROM USER BUFFER
;
 
	.ENABL	LSB
 
RDWRD:				;;;REF LABEL
 
 
	.IF DF	M$$MGE
 
	MOV	IOSB2(R3),KISAR6  ;;;M      AP TO SECOND I/O STATUS WORD
 
	.IFTF
 
	INC	@IOSB2+2(R3)	;;;INCREMENT FREE POSITIONS IN BUFFER
	CMP	FULBF(R3),@IOSB2+2(R3) ;;;BUFFER OVERRUN?
	BLO	70$		;;;IF LO YES
 
	.IFT
 
	MOV	CURBF(R3),KISAR6   ;;;MAP TO USER BUFFER
 
	.IFTF
 
	MOV	@CURBF+4(R3),R2	;;;READ VALUE FROM USER BUFFER
	BR	10$		;;;FINISH IN COMMON CODE
 
;
; SUBROUTINE TO WRITE A VALUE INTO USER BUFFER
;
 
WRWRD:				;;;REF LABEL
 
	.IFT
 
	MOV	IOSB2(R3),KISAR6   ;;;MAP TO SECOND I/O STATUS WORD
 
	.IFTF
 
	INC	@IO      SB2+2(R3)	;;;INCREMENT NUMBER OF ENTRIES IN BUFFER
	CMP	FULBF(R3),@IOSB2+2(R3) ;;;BUFFER OVERRUN?
	BLO	70$		;;;IF LO YES
 
	.IFT
 
	MOV	CURBF(R3),KISAR6  ;;;MAP TO USER BUFFER
 
	.IFTF
 
	MOV	R2,@CURBF+4(R3)	;;;WRITE VALUE INTO USER BUFFER
10$:	ADD	#2,CURBF+4(R3)	;;;UPDATE USER BUFFER ADDRESS
 
	.IFT
	
	BIT	#20000,CURBF+4(R3) ;;;OVERFLOW 4K BOUNDRY?
	BEQ	20$		;;;IF EQ NO
	BIC	#20000,CURBF+4(R3) ;;;CLEAR OVERFLOW BIT
	ADD	#200,CURBF(R3)	;;;ADVANCE TO NEXT 4K BOUNDRY
	
	.IFTF
 
20$:	DEC	      SMCNT(R3)	;;;END OF BUFFER?
	BNE	30$		;;;IF NE NO
 
	.IFT
 
	MOV	STRBF(R3),CURBF(R3) ;;;RESET RELOCATION BIAS
	
	.ENDC
 
 
	MOV	STRBF+4(R3),CURBF+4(R3) ;;;RESET BUFFER ADDRESS
	MOV	FULBF(R3),SMCNT(R3) ;;;RESET SAMPLE BUFFER COUNT
	BITB	#STPBR,RSTAT(R3) ;;;STOP ON BUFFER RUNOUT?
	BEQ	40$		;;;IF EQ NO
	DEC	SAMCT(R3)	;;;DECREMENT BUFFER COUNT
	BEQ	60$		;;;IF EQ BUFFER RUNOUT
	BR	40$		;;;
30$:	CMP	SMCNT(R3),HAFBF(R3) ;;;EXACTLY AT HALF BUFFER?
	BNE	50$		;;;IF NE NO
40$:	BISB	#RQEFN,RSTAT(R3)       ;;;REQUEST EFN SETTING
	INC	FKFLG		;;;SET FORK REQUEST
50$:	CLC			;;;CLEAR OVERRUN INDICATOR
 
 
	.IF DF	D$$R11
 
	BIT	DSMSK(R3),TEMP	;;;STOP BIT CLEAR?
	BEQ	90$		;;;IF EQ NO
 
	.IFF
 
	BR	90$		;;;
 
	.ENDC
 
 
60$:	MOVB	#IS.SUC,FINST(R3) ;;;SET SUCCESSFUL COMPLETION STATUS
	BR	TERMS		;;;
70$:	MOVB	#IE.DAO,FINST(R3) ;;;SET FINAL STATUS TO BUFFER OVERRUN
	DEC	@IOSB2+2(R3)	;;;READJUST BUFFER FREE COUNT
TERMS:	BISB	#STPRQ,RSTAT(R3) ;;;SET TO TERMINATE SAMPLE REQUEST
	MOV	#NXTRQ,STATE(R3)    ¢   ;;;SET STATE TO TERMINATION IN PROGRESS
	INC	FKFLG		;;;SET FORK REQUEST
	SEC			;;;SET OVERRUN/TERMINATION INDICATOR
90$:	RETURN			;;;
	.DSABL	LSB
 
	.END
 ¢          sà~kQ	› c,        	.TITLE	BFCTL
	.IDENT	/08.03/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 08.03
;
; D. N. CUTLER 26-DEC-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	G. H. KUENNING
;	H. D. COFFMAN
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	5-NOV-79
;		MSH071 -- CORRECT CONDITIONAL ASSEMBLY COMM      AND
;
;
; BUFFER CONTROL ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS

;+
; **-$GTBYT-GET NEXT BYTE FROM USER BUFFER
;
; THIS ROUTINE IS CALLED TO GET THE NEXT BYTE FROM THE USER BUFFER
; AND RETURN IT TO THE CALLER ON THE STACK. AFTER THE BYTE HAS BEEN
; FETCHED, THE NEXT BYTE ADDRESS IS INCREMENTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB THAT CONTAINS THE BUFFER POINTERS.
;
; OUTPUTS:
;
;	THE NEXT BYTE IS FETCHED FROM THE USER BUFFER AND RE      TURNED
;	TO THE CALLER ON THE STACK. THE NEXT BYTE ADDRESS IS INCREMENTED.
;
;	ALL REGISTERS ARE PRESERVED ACROSS CALL.
;-

	.ENABL	LSB
$GTBYT::MOV	(SP),-(SP)	;DUPLICATE RETURN ADDRESS


	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING
	MOV	U.BUF(R5),KISAR6 ;MAP TO USER BUFFER
	MOVB	@U.BUF+2(R5),4(SP) ;GET NEXT BYTE FROM USER BUFFER
	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.IFF

	MOVB	@U.BUF+2(R5),2(SP) ;GET NEXT BYTE FROM USER BUFFER

	.ENDC


	BR	20$		;TAKE COMMON EXIT F      OR ADDRESS UPDATE

;+
; **-$PTBYT-PUT NEXT BYTE IN USER BUFFER
;
; THIS ROUTINE IS CALLED TO PUT A BYTE IN THE NEXT LOCATION IN
; USER BUFFER. AFTER THE BYTE HAS BEEN STORED, THE NEXT BYTE ADDRESS
; IS INCREMENTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB THAT CONTAINS THE BUFFER POINTERS.
;	2(SP)=BYTE TO BE STORED IN THE NEXT LOCATION OF THE USER BUFFER.
;
; OUTPUTS:
;
;	THE BYTE IS STORED IN THE USER BUFFER AND REMOVED FROM
;	THE STACK. THE NEXT BYTE ADDRESS IS INCREMENTED.
;
;	ALL REGISTE      RS ARE PRESERVED ACROSS CALL.
;-

$PTBYT::			;REF LABEL


	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING
	MOV	U.BUF(R5),KISAR6 ;MAP TO USER BUFFER
	MOVB	4(SP),@U.BUF+2(R5) ;STORE BYTE IN USER BUFFER
	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.IFF

	MOVB	2(SP),@U.BUF+2(R5) ;STORE BYTE IN USER BUFFER

	.ENDC


	MOV	(SP)+,(SP)	;COLLAPSE STACK REMOVING BYTE


	.IF DF	G$$WRD!P$$WRD

	BR	20$		;TAKE COMMON EXIT FOR ADDRESS UPDATE

;+
; **-$GTWRD-GET NEXT WORD FROM USER BUFFER      
;
; THIS ROUTINE IS CALLED TO GET THE NEXT WORD FROM THE USER BUFFER
; AND RETURN IT TO THE CALLER ON THE STACK. AFTER THE WORD HAS BEEN
; FETCHED, THE NEXT WORD ADDRESS IS CALCULATED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB THAT CONTAINS THE BUFFER POINTERS.
;
; OUTPUTS:
;
;	THE NEXT WORD IS FETCHED FROM THE USER BUFFER AND RETURNED
;	TO THE CALLER ON THE STACK. THE NEXT WORD ADDRESS IS CALCULATED.
;
;	ALL REGISTERS ARE PRESERVED ACROSS CALL.
;-

	.IFTF

	.IF DF	G$$WRD

$GTWRD::			;REF       LABEL
	MOV	(SP),-(SP)	;DUPLICATE RETURN ADDRESS


	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING
	MOV	U.BUF(R5),KISAR6 ;MAP TO USER BUFFER
	MOV	@U.BUF+2(R5),4(SP) ;GET NEXT WORD FROM USER BUFFER
	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.IFF

	MOV	@U.BUF+2(R5),2(SP) ;GET NEXT WORD FROM USER BUFFER

	.ENDC


	BR	10$		;TAKE COMMON EXIT FOR ADDRESS UPDATE

	.IFF

$GTWRD==-1			;CRASH IF REFERENCED

	.ENDC


;+
; **-$PTWRD-PUT NEXT WORD IN USER BUFFER
;
; THIS ROUTINE I      S CALED TO PUT A WORD IN THE NEXT LOCATION IN
; USER BUFFER. AFTER THE WORD HAS BEEN STORED, THE NEXT WORD ADDRESS
; IS CALCULATED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB THAT CONTAINS THE BUFFER POINTERS.
;	2(SP)=WORD TO BE STORED IN THE NEXT LOCATION OF THE BUFFER.
;
; OUTPUTS:
;
;	THE WORD IS STORED IN THE USER BUFFER AND REMOVED FROM
;	THE STACK. THE NEXT WORD ADDRESS IS CALCULATED.
;
;	ALL REGISTERS ARE PRESERVED ACROSS CALL.
;-


	.IF DF	P$$WRD

$PTWRD::			;REF LABEL
	.IF DF	M$$MGE      

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING
	MOV	U.BUF(R5),KISAR6 ;MAP TO USER BUFFER
	MOV	4(SP),@U.BUF+2(R5);STORE WORD IN USER BUFFER
	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.IFF

	MOV	2(SP),@U.BUF+2(R5) ;STORE WORD IN USER BUFFER

	.ENDC


	MOV	(SP)+,(SP)	;COLLAPSE STACK REMOVING WORD

	.IFF

$PTWRD==-1			;CRASH IF REFERENCED

	.ENDC


	.IFT

10$:	INC	U.BUF+2(R5)	;CALCULATE ADDRESS OF NEXT WORD

	.ENDC


20$:	INC	U.BUF+2(R5)	;INCREMENT NEXT BYTE ADDRESS


	.IF DF	M$$MG      E

	CMP	U.BUF+2(R5),#160000 ;OVERFLOW 28K BOUNDARY?
	BLO	30$		;IF LO NO
	SUB	#20000,U.BUF+2(R5) ;REDUCE BY 4K
	ADD	#200,U.BUF(R5)	;ADJUST RELOCATION BIAS

	.ENDC


30$:	RETURN
	.DSABL	LSB

;+
; **-$GTCWD-GET NEXT WORD FROM USER CONTROL BUFFER
;
; THIS ROUTINE IS CALLED TO GET THE NEXT WORD FROM THE USER CONTROL
; BUFFER AND RETURN IT TO THE CALLER ON THE STACK. AFTER THE WORD HAS
; BEEN FETCHED, THE NEXT WORD ADDRESS IS CALCULATED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB THAT CONTAINS TH      E BUFFER POINTERS.
;
; OUTPUTS:
;
;	THE NEXT WORD IS FETCHED FROM THE USER CONTROL BUFFER AND RETURNED
;	TO THE CALLER ON THE STACK. THE NEXT WORD ADDRESS IS CALCULATED.
;
;	ALL REGISTERS ARE PRESERVED ACROSS CALL.
;-


	.IF DF	A$$D01!A$$F11!I$$CAD!I$$PAD!I$$P14!U$$ADM		;MSH071
									;**-1
$GTCWD::MOV	(SP),-(SP)	;DUPLICATE RETURN ADDRESS


	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING
	MOV	U.CBF(R5),KISAR6 ;MAP TO USER CONTROL BUFFER
	MOV	@U.CBF+2(R5),4(SP) ;GET NEXT WORD FR      OM USER BUFFER
	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.IFF

	MOV	@U.CBF+2(R5),2(SP) ;GET NEXT WORD FROM USER BUFFER

	.IFTF

	ADD	#2,U.CBF+2(R5)	;CALCULATE ADDRESS OF NEXT WORD

	.IFT

	BIT	#20000,U.CBF+2(R5) ;OVERFLOW 4K BOUNDRY?
	BEQ	10$		;IF EQ NO
	BIC	#20000,U.CBF+2(R5) ;CLEAR OVERFLOW BIT
	ADD	#200,U.CBF(R5)	;ADJUST RELOCATION BIAS

	.ENDC


10$:	RETURN			;

	.ENDC


;+
; **-$BLXIO-MOVE BLOCK OF DATA.
;
; THIS ROUTINE IS CALLED TO MOVE DATA IN MEMORY IN A MAPPED SYSTE      M.
;
; INPUTS:
;
;	R0=NUMBER OF BYTES TO MOVE.
;	R1=SOURCE APR5 BIAS.
;	R2=SOURCE DISPLACEMENT.
;	R3=DESTINATION APR6 BIAS.
;	R4=DESTINATION DISPLACEMENT.
;
; OUTPUTS:
;
;	DESCRIBED MOVE IS ACCOMPLISHED.
;	R0 ALTERED.
;	R1,R3 PRESERVED
;	R2,R4 POINT TO LAST BYTE OF SOURCE AND DESTINATION + 1
;
;	NOTE:	THE COUNT INPUT IN R0 MUST NOT BE ZERO AND IT MUST NOT
;		BE LARGE ENOUGH TO CROSS APR BOUNDARIES (THIS TYPICALLY
;		MEANS A MAXIMUM OF 4K-63).
;
;	NOTE2:	IF THE COUNT IN R0 EQUALS ZERO OR       IS GREATER THAN
;		4K-63. WORDS, A RETURN IS EXECUTED WITH NO REGISTERS
;		ALTERED.
;-


	.IF DF	M$$MGE

$BLXIO::TST	R0		;ZERO BYTES TO MOVE?
	BEQ	100$		;IF EQ YES -- RETURN
	CMP	#17701,R0	;MOVING MORE THAN AN APR-63. WORDS?
	BLOS	100$		;IF LOS YES -- RETURN
	MOV	R5,-(SP)	;SAVE R5
	MOV	#KISAR6,R5	;POINT TO KERNEL APR6
	MOV	(R5),-(SP)	;SAVE KERNEL APR6
	MOV	R3,(R5)		;SET UP KERNEL APR6 FOR TRANSFER
	MOV	-(R5),-(SP)	;SAVE KERNEL APR5
	MOV	R1,(R5)		;SET UP KERNEL APR5 FOR TRANSFER


	.IF N      DF	N$$MOV

10$:	MOVB	(R2)+,(R4)+	;MOVE NEXT BYTE
	DEC	R0		;MORE TO MOVE?
	BNE	10$		;IF NE YES

	.IFF

	MOV	#1,-(SP)	;PUSH LOW BIT MASK
	BIT	(SP),R2		;SOURCE ADDRESS ODD?
	BEQ	10$		;IF EQ NO
	MOVB	(R2)+,(R4)+	;MOVE FIRST BYTE
	DEC	R0		;REDUCE COUNT
10$:	BIT	(SP),R4		;DESTINATION ADDRESS ODD?
	BNE	50$		;IF NE YES, PERFORM BYTE MOVES
20$:	SUB	#N$$MOV*2,R0	;MOVE ENTIRE BLOCK?
	BCC	40$		;IF CC YES
	BIC	R0,(SP)		;REMAINING COUNT ODD?
	BNE	30$		;IF NE NO
	DEC	R0		;ADJUST NEGATIVE COUNT
30$:	SUB      	R0,PC		;INDEX INTO MOVE INSTRUCTIONS
40$:				;REF LABEL


	.REPT	N$$MOV

	MOV	(R2)+,(R4)+	;MOVE A WORD

	.ENDR


	BCC	20$		;IF CC MORE TO GO
	BR	80$		;EXIT THROUGH COMMON CODE
50$:	ASL	R0		;DOUBLE COUNT
60$:	SUB	#N$$MOV*2,R0	;MOVE ENTIRE BLOCK?
	BCC	70$		;IF CC YES
	SUB	R0,PC		;ELSE INDEX INTO MOVE INSTRUCTIONS
70$:				;REF LABEL


	.REPT	N$$MOV

	MOVB	(R2)+,(R4)+	;MOVE A BYTE

	.ENDR


	BCC	60$		;IF CC MORE TO GO
80$:	TST	(SP)+		;POP CONSTANT
	BNE	90$		;IF NE NO MORE TO MOVE
   Ô   	MOVB	(R2)+,(R4)+	;MOVE LAST BYTE
90$:				;REF LABEL

	.ENDC


	MOV	(SP)+,(R5)+	;RESTORE KERNEL APR5
	MOV	(SP)+,(R5)	;RESTORE KENREN APR6
	MOV	(SP)+,R5	;RESTORE R5
100$:	RETURN			;

	.ENDC


	.END
Ô          YqwkQ	› c,        	.TITLE	REQSB
	.IDENT	/13.64/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 13.64
;
; D. N. CUTLER 10-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	P. WANNHEDEN
;	CHUCK SPITZ
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	23-JUL-79
;		MSH008 -- CORRECT CONDITIONAL FOR NO SEND/REC       BY REF
;
;	M. S. HARVEY	3-AUG-79
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	13-AUG-79
;		MSH048 -- CLEAR CHECKPOINT REQUEST FOR TASKS THAT
;			  ARE NOT ELIGIBLE FOR CHECKPOINTING
;
;	M. S. HARVEY	16-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	8-OCT-79
;		MSH021 -- CONDITIONALIZE ACP TEST
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	23-APR-80
;		MSH06      9 -- ALLOW STOPPING FOR GLOBAL EVENT FLAGS
;
;	M. S. HARVEY	25-APR-80
;		MSH096 -- SUPPORT ALTERNATE HEADER REFRESH AREAS
;			  FOR SYSTEM-CONTROLLED PARTITIONS
;
;	M. S. HARVEY	2-JUN-80
;		MSH102 -- STORE SENDER'S TASK NAME WHEN CLEARING
;			  TCB POINTER FROM RREF PACKET
;
;	E. A. FLOYD	9-JUN-80
;		EF012 -- CONDITIONALIZE $FNDSP FOR ASSEMBLY
;			 WITH RSX11S V3.0
;
;	M. S. HARVEY	30-JUN-80
;		MSH091 -- USE KERNEL AST SYMBOL
;
;	M. S. HARVEY	19-AUG-80
;		MSH111 -- PROPERLY CONDITIONALIZE       TKTN SPECIFIC CODE
;
;	M. S. HARVEY	6-OCT-80
;		MSH121 -- SUPPORT REQUESTED EXIT ASTS
;
;	M. S. HARVEY	10-OCT-80
;		MSH122 -- EXTERNALLY BLOCKED TASKS MUST BE
;			  INELIGIBLE FOR MEMORY RESIDENCE
;
;	M. S. HARVEY	24-NOV-80
;		MSH129 -- RETURN SECONDARY EXIT STATUS CODE IN ESB
;
;	M. S. FOX	07-JAN-81
;		MF203 -- INITIAL ALTERNATE CLI SUPPORT
;
;	M. S. FOX	30-JAN-81
;		MF208 -- SUPPORT COMMAND ARRIVAL ASTS FOR CLIS
;
;	M. S. HARVEY	23-MAR-81
;		MSH142 -- DON'T REQUEST CERTAIN TASKS DURING       LOW
;			  POOL CONTROL
;
;	M. S. HARVEY	30-APR-81
;		MSH166 -- ELIMINATE THRASHING CAUSED BY OVERLAPPING
;			  SWAPPING PRIORITY RANGES OF TASKS BEING
;			  CHECKPOINTED WITH OUTSTANDING I/O
;
;	M. S. HARVEY	6-MAY-81
;		MSH168 -- REDUCE THE CHANCES OF DEADLOCK IN SYSTEM-
;			  CONTROLLED PARTITIONS WITH CHECKPOINTABLE
;			  TASKS WITH OUTSTANDING I/O
;
;	M. S. HARVEY	6-AUG-81
;		MSH184 -- DO NOT REQUEST MEMORY SHUFFLER TOO OFTEN
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZAT      ION
;
;	M. S. HARVEY	22-SEP-81
;		MSH172 -- STOPFOR STATE CANNOT EXIST AT AST STATE
;
;	M. S. HARVEY	13-OCT-81
;		MSH196 -- MOVE $CLSRF CODE DIRECTLY INTO DREIF.
;			  THIS INCLUDES MSH008 AND MSH102.
;
;	M. S. HARVEY	13-NOV-81
;		MSH205 -- GENERALIZE AST SEARCH MECHANISM TO ALLOW
;			  MCR TO HANDLE ABORT ASTS CORRECTLY
;
;
; TASK REQUEST RELATED SUBROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,ITBDF$,PCBDF$,TCBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	ITBDF$			;DEFINE INTERRUPT       TRANSFER BLOCK OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$ABCTK-ABORT CURRENT TASK
; **-$ABTSK-ABORT TASK
;
; THIS ROUTINE IS CALLED TO MARK A TASK FOR ABORT AND TO FORCE A TASK EXIT.
; THE REASON FOR ABORT AND THE CURRENT OUTSTANDING I/O COUNT ARE STORED
; IN THE FIRST TASK EVENT FLAG WORD.
;
; INPUTS:
;
;	R0=REASON FOR ABORT.
;	R1=ADDRESS OF THE TCB OF THE TASK TO BE ABORTED (ENTRY AT $ABTSK ONLY).
;	R2=EXTENDED ABORTER       INFORMATION (ONLY IF R0=S.CABO OR S.CPMD)	;MSH121
;
; OUTPUTS:
;
;	THE TASK IS MARKED FOR ABORT OR AN ABORT AST IS DECLARED.	;MSH121
;	THE TASK IS UNBLOCKED AND A CONDITIONAL SCHEDULE REQUEST	;MSH121
;	IS SET.								;MSH121
;-									;**-2

$ABCTK::MOV	$TKTCB,R1	;SET TCB ADDRESS TO CURRENT TASK
$ABTSK::BIC	#TS.STP,T.STAT(R1) ;UNBLOCK THE TASK			;MSH122
									;MSH121
;									;MSH121
; IF THE TASK WAS REQUESTED TO EXIT AND A REQUESTED EXIT AST WAS	;MSH121
; SPECIFIED BY THE TASK, THAT AST       MUST BE DECLARED INSTEAD OF		;MSH121
; ACTUALLY ABORTING THE TASK. IF A NONPRIVILEGED TASK HAS ALREADY	;MSH121
; HAD SUCH AN AST DECLARED PREVIOUSLY, ALWAYS ABORT THE TASK.		;MSH121
;									;MSH121
									;MSH121
	.IF DF	A$$TRP&A$$BRT						;MSH121
									;MSH121
	CMP	R0,#S.CABO	;ABORT BY DIRECTIVE OR CLI?		;MSH121
	BEQ	2$		;IF EQ YES				;MSH121
	CMP	R0,#S.CPMD	;ABORT WITH PMD?			;MSH121
	BNE	5$		;IF NE NO, ABORT THE TASK		;MSH121
2$:	SAVNR			;SAVE R4 AND R5				;MSH121
	MOV	#AS.REA,R4	;GET       CODE FOR REQUESTED EXIT AST	;MSH121
	MOV	R1,-(SP)	;SAVE TCB ADDRESS			;MSH121
	MOV	R0,-(SP)	;SAVE ABORT CODE			;MSH121
	MOV	R1,R5		;COPY TCB ADDRESS			;MSH121
	MOV	R2,-(SP)	;SAVE ABORTER INFORMATION		;MSH121
	CALL	$DASTT		;DECLARE REQUESTED EXIT AST FOR TASK	;MSH121
	MOV	(SP)+,R2	;RESTORE ABORTER INFORMATION		;MSH121
	MOV	(SP)+,R0	;RESTORE ABORT CODE			;MSH121
	BCC	3$		;IF CC AST SET UP			;MSH121
	MOV	(SP)+,R1	;RESTORE TCB ADDRESS			;MSH121
	BIT	#T3.PRV,T.ST3(R1) ;ABORTED TASK PRIVILEGED?		;MSH12      1
	BEQ	5$		;IF EQ NO, ABORT IT			;MSH121
	BIT	#T2.REX,T.ST2(R1) ;ABORT AST IN PROGRESS ALREADY?	;MSH121
	BEQ	5$		;IF EQ NO, ABORT IT			;MSH121
	MOV	R1,R0		;COPY TCB ADDRESS			;MSH121
	BR	10$		;RESCHEDULE TASK			;MSH121
3$:	TST	(SP)+		;CLEAN STACK				;MSH121
	MOV	#4,A.PRM(R1)	;STORE NUMBER OF AST PARAMETER BYTES	;MSH121
	MOV	R2,A.PRM+2(R1)	;STORE ABORTER INFORMATION		;MSH121
	RETURN			;$NXTSK ALREADY CALLED, SIMPLY RETURN	;MSH121
									;MSH121
	.ENDC								;MSH121
									;MSH121
;									      ;MSH121
; COME HERE TO ACTUALLY ABORT THE TASK. NOTE THAT ABORTED ACPS DO	;MSH121
; NOT GET AN ABORT STATUS STUFFED INTO T.EFLG+2 BECAUSE SOME USE	;MSH121
; THAT OFFSET FOR OTHER USES (SUCH AS MOUNTED VOLUME COUNTS).		;MSH121
;									;MSH121
									;MSH121
5$:									;MSH046
	.IF DF	T$$BUF							;MSH046
									;MSH046
	BIS	#177400,R0	;DEFAULT TO MAXIMUM I/O COUNT		;MSH046
	MOV	R0,T.EFLG(R1)	;INSERT REASON TO ABORT AND I/O COUNT	;MSH046
									;MSH046
; THE FOLLOWING DEPENDS ON THE LOW B      YTE OF T.TIO-1 BEING ZERO.		;MSH046
									;MSH046
	MOV	T.TIO-1(R1),R0	;GET BUFFERED I/O COUNT (T.TIO)		;MSH046
	ADD	T.PRI(R1),R0	;ADD NON-BUFFERED I/O (T.IOC)		;MSH046
	BCS	7$		;IF CS BYTE NOT LARGE ENUFF, USE MAX	;MSH046
	SWAB	R0		;ISOLATE TOTAL I/O COUNT		;MSH046
	MOVB	R0,T.EFLG+1(R1)	;SAVE OUTSTANDING I/O COUNT		;MSH046
7$:									;MSH046
									;MSH046
	.IFF								;MSH046
									;MSH046
	MOV	R0,T.EFLG(R1)	;INSERT REASON FOR ABORT		;MSH046
	MOVB	T.IOC(R1),T.EFLG+1(R1) ;SAVE OUTSTANDI      NG I/O COUNT	;**-1
									;MSH046
	.ENDC								;MSH046

	.IF DF	P$$OFF

	.IF DF	A$$CPS							;MSH021
									;MSH021
	BIT	#T3.ACP,T.ST3(R1) ;IS THIS AN ACP?
	BNE	9$		;IF NE YES
									;MSH021
	.ENDC								;MSH021
									;MSH021
	MOV	#EX$SEV,T.EFLG+2(R1) ;SET SEVERE ERROR EXIT STATUS
9$:				;REF LABEL

	.ENDC

	MOV	R1,R0		;COPY TCB ADDRESS
	ADD	#T.STAT,R1	;POINT TO FIRST TASK STATUS WORD
	BIC	#TS.CKR,(R1)+	;CLEAR STATUS BITS
	BIC	#T2.SEF!T2.STP!T2.SPN,(R1) ;MAKE TASK RUNNABLE
	      BIS	#T2.AST!T2.DST!T2.HLT!T2.ABO,(R1) ;DSBL AST'S & FRC EXIT
	TST	-(R1)		;OUT FOR INITIAL LOAD OR OTHERWISE BLKD?
	BNE	10$		;IF NE YES
	CALL	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST
10$:	MOV	T.PCB(R0),R0	;POINT TO TASK PCB


	.IF DF	D$$ISK

	CALLR	$NXTSK		;REALLOCATE TASK PARTITION IF NECESSARY

	.IFF

	RETURN			;

	.ENDC


;+
; **-$BILDS-BUILD STACK AND INITIALIZE HEADER
;
; THIS ROUTINE SETS UP THE TASK STACK AND INITIALIZES THE HEADER. IT IS
; CALLED PRIOR TO PLACING A TASK INTO       CONTENTION FOR THE PROCESSOR WHEN
; AN EXECUTION REQUEST IS MADE FOR A TASK THAT IS FIXED IN MEMORY OR
; WHEN A DISK RESIDENT TASK HAS FINISHED LOADING.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TASK TO INITIALIZE.
;
; OUTPUTS:
;
;	1-TASK LOCAL EVENT FLAGS 1.-32. ARE CLEARED.
;	2-CURRENT UIC IS SETUP IN THE HEADER.
;	3-TASK CONTEXT IS SETUP TO CAUSE THE TASK TO START EXECUTION AT ITS ENTR
;	4-REDISPATCHING OF THE PROCESSOR IS CONDITIONALLY REQUESTED.
;
;	R3 IS PRESERVED ACROSS CALL.
;-
      
$BILDS::MOV	T.PCB(R0),R1	;GET ADDRESS OF TASK PCB
	MOV	P.HDR(R1),R1	;POINT TO TASK HEADER
	MOV	T.EFLG(R0),H.CUIC(R1) ;SET SPECIFIED UIC
	BNE	10$		;IF NE UIC WAS SPECIFIED
	MOV	H.DUIC(R1),H.CUIC(R1) ;SET DEFAULT UIC


	.IF DF	M$$MUP

	BR	15$		;

	.IFTF

10$:				;REF LABEL

	.IFT

	MOV	T.ACTL(R0),H.DUIC(R1) ;SET DEFAULT UIC

	.ENDC


15$:	BIT	#T2.ABO,T.ST2(R0) ;TASK MARKED FOR ABORT?
	BNE	20$		;IF NE YES
	CLR	T.EFLG(R0)	;CLEAR TASK LOCAL EVENT FLAGS
									;MSH021
	.IF DF	A$$CPS		      					;MSH021
									;MSH021
	BIT	#T3.ACP,T.ST3(R0) ;TASK ACP?
	BNE	20$		;IF NE YES
									;MSH021
	.ENDC								;MSH021
									;MSH021
	CLR	T.EFLG+2(R0)	;
20$:				;REF LABEL


	.IF DF	M$$MGE

	MOV	H.ISP(R1),(R1)	;SET INITIAL STACK POINTER
	MOV	H.GARD(R1),R2	;POINT TO CONTEXT SAVE AREA
	SUB	#16,R2		;POINT TO SAVED PC
	MOV	H.IPC(R1),(R2)	;SET INITIAL PC WORD
	MOV	H.IPS(R1),-(R2)	;SET INITIAL PS WORD

	.IFF

	MOV	H.ISP(R1),R2	;GET INITIAL STACK POINTER
	MOV	H.IPS(R1),-(R2)	;SET INIT      IAL PS WORD
	MOV	H.IPC(R1),-(R2)	;SET INITIAL PC WORD
	CMP	-(R2),-(R2)	;ADJUST TO BOTTOM OF STACK
	MOV	R2,(R1)		;SET INITIAL STACK POINTER

	.ENDC


;+
; **-$ACTTK-PUT TASK IN ACTIVE TASK LIST
;
; THIS ROUTINE IS CALLED TO PUT AN ACTIVE TASK IN THE ACTIVE TASK LIST.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TASK TO PUT IN THE ACTIVE LIST.
;
; OUTPUTS:

;	THE SPECIFIED TASK IS MERGED INTO THE ACTIVE TASK LIST BY
;	PRIORITY.
;
;	R3 IS PRESERVED ACROSS CALL.
;-

$ACTTK::MOV	#$ACTHD-      T.ACTL,R1 ;SET ADDRESS OF PREVIOUS TCB
10$:	MOV	R1,R2		;SAVE ADDRESS OF PREVIOUS TCB
	MOV	T.ACTL(R2),R1	;GET ADDRESS OF NEXT TCB
	CMPB	T.PRI(R1),T.PRI(R0) ;TASK HIGHER OR SAME PRIORITY?
	BHIS	10$		;IF HIS YES
	MOV	R0,T.ACTL(R2)	;LINK NEW TASK TO PREVIOUS
	MOV	R1,T.ACTL(R0)	;SET LINK TO NEXT IN NEW TASK

;+
; **-$SETCR-SET CONDITIONAL SCHEDULE REQUEST
; **-$SETRQ-SET SCHEDULE REQUEST
; **-$SETRT-SET SCHEDULE REQUEST FOR CURRENT TASK
;
; THIS ROUTINE IS CALLED TO FORCE REDISPATCHING OF THE PROCES      SOR
; FROM A SPECIFIED POSITION IN THE TASK LIST. IF A PREVIOUS REQUEST
; HAS BEEN SET, THEN REDISPATCHING STARTS AT WHICH EVER REQUEST
; HAS THE HIGHEST PRIORITY.
;
; INPUTS:
;
;	IF ENTRY AT $SETRT, THEN
;		R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;	IF ENTRY AT $SETRQ OR $SETCR, THEN
;		R0=ADDRESS OF THE TCB TO START DISPATCHING AT.
;
; OUTPUTS:
;
;	A SCHEDULE REQUEST IS SET WHICH WILL FORCE A REDISPATCH-
;	ING OF THE PROCESSOR WHEN A SYSTEM EXIT IS EXECUTED.
;
;	R2 AND R3 ARE PRESERVED       ACROSS CALL.
;	R0 IS PRESERVED ACROSS CALL IF ENTRY IS NOT AT $SETRT.
;-

	.ENABL	LSB
$SETCR::CMP	R0,$TKTCB	;REQUESTED TASK SAME AS CURRENT?
	BEQ	$SETRQ		;IF EQ YES
	CMPB	$CURPR,T.PRI(R0) ;CURRENT TASK HIGHER PRIORITY?
	BHI	30$		;IF HI YES
	BLO	$SETRQ		;IF LO NO
10$:	CALLR	$DRDSE		;SAME PRIORITY-DECLARE SIGNIFICANT EVENT
$SETRT::MOV	R5,R0		;SET ADDRESS OF DISPATCH TCB
$SETRQ::MOV	$RQSCH,R1	;GET PREVIOUS SCHEDULE REQUEST
	BEQ	20$		;IF EQ NO PREVIOUS REQUEST
	CMP	R0,R1		;TASK ALREADY RESCHEDULED      ?
	BEQ	30$		;IF EQ YES
	CMPB	T.PRI(R1),T.PRI(R0) ;COMPARE PRIORITIES
	BHI	30$		;IF HI PREVIOUS IS HIGHER PRIORITY
	BEQ	10$		;IF EQ SAME PRIORITY
20$:	MOV	R0,$RQSCH	;SET SCHEDULE REQUEST
30$:	RETURN			;
	.DSABL	LSB
									;MSH049
;+									;MSH049
; **-$SETMG/$SETFG-SET EVENT FLAG AND UNLOCK IF GROUP GLOBAL		;MSH049
;									;MSH049
; THESE ROUTINES SET AN EVENT FLAG AND TAKE CARE OF THE REQUIRED	;MSH049
; SCHEDULING. IF THE EVENT FLAG WAS GROUP GLOBAL, THE USE COUNT		;MSH049
; FOR THAT FLA      G'S GROUP GLOBAL CONTROL BLOCK IS DECREMENTED. IF		;MSH049
; THE CONTROL BLOCK IS MARKED FOR DELETE AND THE COUNT GOES TO		;MSH049
; ZERO, IT WILL BE DEALLOCATED.						;MSH049
;									;MSH049
; INPUTS:								;MSH049
;									;MSH049
;	R0=EVENT FLAG NUMBER ($SETFG) OR EVENT FLAG MASK ($SETMG).	;MSH049
;	R1=EVENT FLAG WORD ADDRESS ($SETMG ONLY).			;MSH049
;	R5=TCB ADDRESS FOR WHICH FLAG IS BEING SET.			;MSH049
;									;MSH049
; OUTPUTS:								;MSH049
;									;MSH049
;	R0=TCB ADDRESS OF TA      SK WHOSE FLAG WAS SET			;MSH049
;	R3 IS PRESERVED.						;MSH049
;									;MSH049
;-									;MSH049
									;MSH049
	.ENABL	LSB							;MSH049
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
$SETMG::CALL	$SETM		;SET THE EVENT FLAG			;MSH049
	BR	5$		;JOIN COMMON CODE			;MSH049
$SETFG::CALL	$SETF		;SET THE EVENT FLAG			;MSH049
5$:	BNE	15$		;IF NE FLAG WAS COMMON OR LOCAL		;MSH049
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	DECB	T.GGF(R5)	;DECR GRP GLOB      AL USE COUNT FOR TASK	;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH076
	ASR	R1		;ISOLATE SECOND EVENT FLAG WORD INDICATO;MSH049
	SBC	R1		;SUBTRACT FOR IT IF IT EXISTS		;MSH049
	ASL	R1		;RESTORE TO WORD ADDRESS (G.EFLG)	;MSH049
	DEC	-(R1)		;DECR GROUP GLOBAL USE COUNT (G.CNT)	;MSH049
	BNE	15$		;IF NE THESE EVENT FLAGS STILL IN USE	;MSH049
;									;MSH049
; THIS CODE DEPENDS ON THE FACT THAT GS.DEL IS THE ONLY DEFINED STATUS	;MSH049
; BIT IN G.STAT AND ITS VALUE IS '1'.					;MSH049      
;									;MSH049
	ASSUME	1,GS.DEL						;MSH049
	ASRB	-(R1)		;FLAGS MARKED FOR DELETE?		;MSH049
	BCC	15$		;IF CC NO				;MSH049
	MOV	R0,-(SP)	;SAVE TCB ADDRESS			;MSH049
	MOV	R3,-(SP)	;SAVE R3				;MSH049
	MOV	R4,-(SP)	;SAVE R4				;MSH049
	MOVB	-(R1),R4	;GET GROUP NUMBER (G.GRP)		;MSH049
	CALL	$SRGEF		;FIND THESE FLAGS IN GROUP GLOBAL LIST	;MSH049
	CALL	$ELGEF		;ELIMINATE THIS GROUP GLOBAL CONTROL BLK;MSH049
	MOV	(SP)+,R4	;RESTORE R4				;MSH049
	MOV	(SP)+,R3	;RESTORE R3				;MSH049
	MOV	(SP)+,R0	      ;RESTORE TCB ADDRESS			;MSH049
15$:	RETURN								;MSH049
									;MSH049
	.DSABL	LSB							;MSH049

;+
; **-$SETF/$SETM-SET EVENT FLAG
;
; THESE ROUTINES SET AN EVENT FLAG AND TAKE CARE OF THE REQUIRED
; RESCHEDULING.
;
; INPUTS:
;
;	R0=EVENT FLAG NUMBER ($SETF) OR EVENT FLAG MASK ($SETM).
;	R1=EVENT FLAG WORD ADDRESS ($SETM ONLY).
;	R5=TCB ADDRESS FOR WHICH FLAG IS BEING SET.
;
; OUTPUTS:
;
;	R0=TCB ADDRESS OF TASK WHOSE FLAG WAS SET
;	R1=EVENT FLAG WORD ADDRESS (IF GROUP GLOBALS SUPP      ORTED)		;MSH049
;	R3 IS PRESERVED.
;									;MSH049
;	IF GROUP GLOBAL EVENT FLAGS ARE SUPPORTED:			;MSH049
;		Z=0 IF LOCAL OR COMMON EVENT FLAG SET			;MSH049
;		Z=1 IF GROUP GLOBAL EVENT FLAG SET			;MSH049
;									;MSH049
;-

	.IFF								;MSH049
									;MSH049
$SETFG::			;REF LABEL				;MSH049
									;MSH049
	.IFTF								;MSH049
									;MSH049
$SETF::	CALL	$CEFI		;CONVERT EVENT FLAG TO MASK AND ADDRESS
									;MSH049
	.IFF								;MSH049
									;MSH049
$SETMG::			;REF LABEL	      			;MSH049
									;MSH049
	.IFTF								;MSH049
									;MSH049
$SETM::				;REF LABEL				;MSH049
									;MSH049
	.IFT								;MSH049
									;MSH049
	CLR	-(SP)		;CLR GROUP GLOBAL INDICATOR		;MSH049
	MOV	R1,-(SP)	;SAVE EVENT FLAG WORD ADDRESS		;MSH049
	BIC	#1,R1		;CLEAR GROUP GLOBAL SECOND WORD FLAG	;MSH049
									;MSH049
	.IFTF								;MSH049
									;MSH049
	BIT	#T2.ABO,T.ST2(R5) ;IS TASK MARKED FOR ABORT?		;MSH049
	BNE	10$		;IF NE YES, DO NOT TOUCH EVENT FLAG WORD;**-1
	BIS	R0,(R1      )		;SET THE EVENT FLAG
10$:	MOV	R5,R0		;COPY TCB ADDRESS FOR $SETCR
	TST	R1		;WAS AN EVENT FLAG SPECIFIED?		;MSH049
	BEQ	19$		;IF EQ NO, PREVENT UNNECESSARY SCHEDULIN;MSH049
	CMP	R1,#$COMEF+2	;IS IT A COMMON EVENT FLAG?		;**-1
	BLOS	20$		;IF LOS YES
									;MSH049
	.IFT								;MSH049
									;MSH049
	SUB	R5,R1		;IS IT GROUP GLOBAL?			;MSH049
	BLO	15$		;IF LO YES				;MSH049
	SUB	#T.EFLG+2,R1	;IS IT LOCAL?				;MSH049
	BLE	18$		;IF LE YES				;MSH049
15$:	DEC	2(SP)		;INDICATE SETTING GROUP GLOB      AL FLAG	;MSH049
	BR	20$		;JOIN COMMON CODE			;MSH049
18$:				;REF LABEL				;MSH049
	.IFTF								;MSH049
									;MSH172
;									;MSH172
; NOTE THAT IF THE TASK IS IN A STOPFOR STATE, IT WILL ONLY BE		;MSH172
; UNSTOPPED IF THE EVENT FLAG BEING SET IS LOCAL. IF IT IS LOCAL,	;MSH172
; PERFORMANCE CAN BE ENHANCED IF THE TASK IS IMMEDIATELY UNSTOPPED,	;MSH172
; RATHER THAN WAITING FOR THE SCHEDULER TO DO IT.			;MSH172
;									;MSH172
; IF THE EVENT FLAG IS COMMON OR GROUP GLOBAL, THEN A SIGNIFI      CANT	;MSH172
; EVENT IS DECLARED. SINCE ACCESS TO THESE FLAGS SHOULD BE ALLOWED	;MSH172
; IN A STRICTLY PRIORITY ORIENTED ORDER, THE UNSTOP PROCEDURE WILL	;MSH172
; BE DEFERRED TO THE SCHEDULER. THE SCHEDULER WILL START WITH THE	;MSH172
; HIGHEST PRIORITY TASK AND GIVE IT FIRST ACCESS TO THE GLOBAL FLAG.	;MSH172
; UNSTOPPING THE CURRENT TASK NOW MIGHT UPSET THE NATURAL FLOW OF	;MSH172
; FLAG ACCESS IN CASE A HIGHER PRIORITY TASK HAPPENS TO BE STOPPED	;MSH172
; FOR THE SAME EVENT FLAG. WE CANNOT ALLOW       A LOWER PRIORITY TASK	;MSH172
; (THIS ONE) TO PERHAPS ERASE THE EVENT FLAG BEFORE THE HIGHER		;MSH172
; PRIORITY TASK HAS A CHANCE TO AT LEAST RECOGNISE THAT THE EVENT	;MSH172
; FLAG WAS SET. THIS IS PREVENTED BY NOT UNSTOPPING THE CURRENT TASK	;MSH172
; HERE AND NOW.								;MSH172
;									;MSH172
									;MSH046
	.IF DF	S$$TOP!T$$BUF						;MSH046
									;MSH046
	BIT	#T2.AST!T2.SEF,T.ST2(R0) ;TASK IN STOPFOR STATE?	;MSH172
									;MSH172
	.IF DF	A$$TRP							;MSH172
									;MSH172
	B      MI	30$		;IF MI NO, TASK IN AST STATE		;MSH172
									;MSH172
	.ENDC								;MSH172
									;MSH046
	.IF DF	T$$BUF							;MSH046
									;MSH046
	BNE	185$		;IF NE YES				;MSH046
	TSTB	T.TIO(R0)	;OUTSTANDING BUFFERED I/O?		;MSH046
	BEQ	30$		;IF EQ NO, NO STOPFOR POSSIBLE		;MSH172
	BIT	#T2.WFR,T.ST2(R0) ;TASK STOPPED FOR BUFFERED I/O?	;MSH172
									;MSH046
	.ENDC								;MSH046
									;MSH046
	BEQ	30$		;IF EQ NO, DON'T UNSTOP IT		;MSH046
185$:	BIT	T.EFLM(R0),@T.EFLM+2(R0) ;STOPFOR CONDIT      ION SATISFIED?	;MSH046
	BEQ	30$		;IF EQ NO				;MSH046
	MOV	R3,-(SP)	;SAVE R3				;MSH046
	MOV	R0,-(SP)	;SAVE TCB				;MSH046
	CALL	$EXRQN		;UNSTOP AND REQUEST TASK TO RUN		;MSH046
	MOV	(SP)+,R0	;RESTORE TCB				;MSH046
	MOV	(SP)+,R3	;RESTORE R3				;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH049
19$:	TST	$SIGFL		;TASK WAITING FOR SIGNIFICANT EVENT?	;MSH049
	BEQ	30$		;IF EQ NO				;MSH049
									;MSH049
	.IFF								;MSH049
									;MSH049
20$:	CALLR	$DRDSE		;DECLARE SIGNIFICANT       EVENT		;MSH049
30$:	CALLR	$SETCR		;FORCE CONDITIONAL REDISPATCH		;MSH049
									;MSH049
	.IFT								;MSH049
									;MSH049
20$:	CALL	$DRDSE		;DECLARE SIGNIFICANT EVENT		;MSH049
	BR	40$		;JOIN COMMON CODE			;MSH049
30$:	CALL	$SETCR		;FORCE CONDITIONAL REDISPATCH		;MSH049
40$:	MOV	(SP)+,R1	;RESTORE EVENT FLAG WORD ADDRESS	;MSH049
	INC	(SP)+		;CLEAN STACK AND SET Z-BIT FOR RETURN	;MSH049
	RETURN			;					;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
;+									; MF208
; **-      $DCAST-DECLARE COMMAND ARRIVAL AST TRAP FOR CLIS			; MF208
;									; MF208
; THIS ROUTINE IS CALLED BY THE COMMAND QUEUEING ROUTINE $QCLIL		; MF208
; WHEN IT IS QUEUEING A COMMAND TO A CLI TASK. IF THE CLI		; MF208
; HAS SPECIFIED THE COMMAND ARRIVAL AST, AN ATTEMPT IS MADE TO		; MF208
; ALLOCATE A NEW AST BLOCK FROM THE POOL. THIS IS DONE IN ORDER		; MF208
; TO ELIMINATE THE WINDOW THAT OCCURS WHEN THE AST BLOCK WOULD		; MF208
; NORMALLY BE UNLINKED FROM T.SAST AND LINKED INTO T.ASTL.		; MF208
;       IT WOULD BE UNACCEPTABLE FOR A CLI TO LOSE A COMMAND DURING THIS	; MF208
; WINDOW. IF THE ALLOCATION FAILS HOWEVER, THE CURRENT EXISTING		; MF208
; AST BLOCK IS USED. THE WORD AT A.PRM+2 IN THE AST BLOCK IS USED	; MF208
; AS A FLAG TO THE SYSXT CODE TO INFORM IT IF IT SHOULD DEALLOCATE	; MF208
; OR RELINK THE AST BLOCK.						; MF208
;									; MF208
; INPUTS:								; MF208
;									; MF208
;	R0=TCB ADDRESS OF CLI						; MF208
;	R1=ADDRESS OF COMMAND BUFFER					; MF208
;									; MF208
; OUTPU      TS:								; MF208
;									; MF208
;	C=1 IF THE TASK IS NOT SETUP FOR THE SPECIFIED AST		; MF208
;	C=0 IF THE TASK IS SETUP FOR THE AST AND THE AST HAS		; MF208
;		BEEN DECLARED						; MF208
;		R1=ADDRESS OF THE AST CONTROL BLOCK			; MF208
;									; MF208
;-									; MF208
									; MF208
									; MF208
	.IF DF	A$$CLI							; MF208
									; MF208
	.IF DF	A$$TRP							; MF208
									; MF208
$DCAST::SAVNR			;SAVE R4 AND R5				; MF208
	MOV	#AS.CAA,R4	;SET AST TYPE				; MF208
	MOV	R0      ,R5		;COPY CLI'S TCB ADDRESS			; MF208
	MOV	R1,R3		;COPY COMMAND ADDRESS			; MF208
									; MF208
	.IFF	;A$$TRP							; MF208
									; MF208
$DCAST::.WORD	SEC!SEZ		;SET C AND Z				; MF208
	RETURN								; MF208
									; MF208
	.ENDC	;A$$TRP							; MF208
									; MF208
									; MF208
	.IFF	;A$$CLI							; MF208
									; MF208
$DCAST::			;DEFINE FOR MCR				; MF208
									; MF208
	.ENDC	;A$$CLI							; MF208
									; MF208
									; MF208
									;**-19
;+
; **-$DASTT-DEC      LARE AST TRAP
;
; THIS ROUTINE IS CALLED TO DECLARE A NON-I/O RELATED AST TRAP. THE
; TCB OF THE SPECIFIED TASK IS EXAMINED TO DETERMINE IF THE SPECIFIED
; AST IS ENABLED (SETUP). IF IT IS THEN THE AST IS DECLARED.
;
; INPUTS:
;
;	R3=COMMAND BUFFER ADDRESS IF AST TYPE IS AS.CAA			; MF208
;	R4=AST TYPE
;	R5=ADDRESS OF THE TCB OF THE TASK TO DECLARE THE AST FOR.
;
; OUTPUTS:
;
;	C=1 IF THE TASK IS NOT SETUP FOR THE SPECIFIED AST.
;	C=0 IF THE TASK IS SETUP FOR THE AST AND THE AST HAS BEEN DECLA      RED.
;		R1=ADDRESS OF THE AST CONTROL BLOCK.
;
;-


	.IF DF	A$$TRP!F$$LPP!P$$RFL!R$$SND!P$$SRF!A$$BRT		;MSH121
									;**-1
	.ENABL	LSB
$DASTT::CALL	$SRAST		;SEARCH FOR SPECIFIED AST BLOCK
	BCS	10$		;IF CS, THERE IS NONE
									; MF208
									; MF208
	.IF DF	A$$CLI&A$$TRP						; MF208
									; MF208
	CMP	A.CBL(R0),#<AS.CAA*256.> ;DECLARING CMD ARRIVAL AST	; MF208
	BNE	1$		;IF NE NO				; MF208
	MOV	R1,-(SP)	;SAVE POINTER TO AST BLOCK ADDRESS	; MF208
	MOV	#C.LGTH,R1	;GET LENGTH OF AN       AST BLOCK		; MF208
	CALL	$ALOCB		;ALLOCATE ONE FROM THE POOL		; MF208
	MOV	(SP)+,R4	;RESTORE POINTER TO AST BLOCK ADDRESS	; MF208
	MOV	(R4),R1		;GET ADDRESS OF EXISTING AST BLOCK	; MF208
	BCC	105$		;IF CC, SUCCESSFUL ALLOCATION		; MF208
	MOV	SP,A.PRM+2(R1)	;NON-ZERO TO FORCE SYSXT TO RELINK	; MF208
	MOV	(R1),(R4)	;REMOVE AST BLOCK FROM LIST		; MF208
	BR	107$		;					; MF208
105$:	MOV	R1,R4		;COPY POINTER TO OLD BLOCK		; MF208
	MOV	R0,R1		;COPY NEW AST BLOCK ADDR		; MF208
	CMP	(R4)+,(R0)+	;SKIP LIN      K WORDS			; MF208
	MOV	(R4)+,(R0)+	;COPY A.CBL				; MF208
	MOV	(R4)+,(R0)+	;COPY A.BYT				; MF208
	MOV	(R4)+,(R0)+	;COPY A.AST				; MF208
	MOV	(R4)+,(R0)+	;COPY A.NPR				; MF208
	CLR	A.PRM+2(R1)	;ZERO TO FORCE SYSXT TO DEALLOCATE	; MF208
107$:	MOV	R3,A.PRM(R1)	;SET COMMAND ADDRESS IN AST BLOCK	; MF208
	MOV	R5,R0		;SET TCB ADDRESS OF CLI			; MF208
	BR	$QASTT		;QUEUE AST				; MF208
1$:									; MF208
									; MF208
	.ENDC	;A$$CLI&A$$TRP						; MF208
									; MF208
									;MSH121
	.IF DF	A      $$TRP&A$$BRT						;MSH121
									;MSH121
	CMP	A.CBL(R0),#<AS.REA*256.> ;DECLARING ABORT AST?		;MSH121
	BNE	2$		;IF NE NO				;MSH121
	BIS	#T2.REX,T.ST2(R5) ;SET ABORT AST IN PROGRESS		;MSH121
									;MSH121
	.ENDC								;MSH121
									;MSH121
2$:	MOV	(R0),(R1)	;REMOVE CONTROL BLOCK FROM THE LIST	;MSH121
	MOV	R0,R1		;SAVE ADDRESS OF THE AST CONTROL BLOCK	;**-1
	MOV	R5,R0		;COPY TCB ADDRESS

	.IF DF	C$$INT&A$$TRP

	BR	$QASTT		;GO QUEUE THE AST

;+
; **-$DQAC-DEQUEUE AST BLOCK QUEUED BY       $QASTC.
;	(TO BE CALLED FROM SYSXT ONLY).
;
; INPUT:
;	R0	POINTER TO AST BLOCK
;
; OUTPUT:
;	A.CBL SET TO 1 TO INDICATE AST BLOCK FREE
;	(NOT IN AST QUEUE).
;
; REGISTERS ALTERED: NONE
;-


$DQAC::	INC	A.CBL(R0)	; SET AST BLOCK FREE
	RETURN


;+
; **-$QASTC-QUEUE AST TO TASK.
;
; THIS IS A VARIANT OF $QASTT TO BE USED BY A TASK ISR, ENTERED
; VIA A VECTOR CONNECTED TO VIA THE CINT$ DIRECTIVE.
;
; INPUT:
;	R5	POINTER TO FORK BLOCK IN ITB
;
; OUTPUT:
;	CC-C	0 IF OK, 1 IF AST ADDRES      S NOT SPECIFIED IN CINT$ CALL.
;
; NOTE - IF THE AST BLOCK IS ALREADY QUEUED FOR THE TASK,
; NO ACTION IS TAKEN. RETURN CC-C = 0.
;
; REGISTERS ALTERED: R0,R1,R2,R3
;-


$QASTC::MOV	R5,R1
	ADD	#X.AST-X.FORK,R1 ;GET AST BLOCK
	TST	A.CBL(R1)	;AST BLOCK ALREADY IN AST QUEUE?
	BEQ	10$		;Y - EXIT WITH CC-C = 0
	TST	A.AST(R1)	;AST ADDRESS SPECIFIED?
	SEC			;ASSUME NO
	BEQ	10$		;N - EXIT WITH CC-C = 1
	CLR	A.CBL(R1)	;INDICATE AST BLOCK IN USE
	MOV	X.TCB-X.FORK(R5),R0 ;GET TCB ADDRESS
				;FALL TH      RU TO $QASTT

	.ENDC	;C$$INT&A$$TRP



;+
; **-$QASTT-QUEUE AST TO TASK
;
; THIS ROUTINE IS USED TO QUEUE AN AST TO A TASK AND INSURE THE TASK
; WILL BE SCHEDULED AND RECONSIDERED FOR ELIGIBILITY IN THE PARTITION.
;
; INPUTS:
;
;	R0=TCB ADDRESS OF TASK TO RECEIVE AST
;	R1=ADDRESS OF AST CONTROL BLOCK TO BE USED
;
; OUTPUTS:
;
;	C=0
;	R1 IS PRESERVED
;-

$QASTT::ADD	#T.ASTL,R0	;POINT TO TASK AST LISTHEAD
	MOV	R1,-(SP)	;SAVE ADDRESS OF AST CONTROL BLOCK
	CALL	$QINSF		;INSERT CONTROL B      LOCK IN AST QUEUE
	SUB	#T.ASTL,R0	;POINT BACK TO TCB ADDRESS
	CALL	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST


	.IF DF	D$$ISK&C$$CKP

	BIT	#T2.STP,T.ST2(R0) ;IS TASK STOPPED?
	BEQ	5$		;IF EQ NO
	MOV	T.PCB(R0),R0	;POINT TO TASK PCB
	CALL	$NXTSK		;REALLOCATE TASK PARTITION

	.ENDC


5$:	MOV	(SP)+,R1	;RESTORE AST CONTROL BLOCK ADDRESS
	CLC			;RETURN CARRY CLEAR
10$:	RETURN			;
	.DSABL	LSB

;+
; **-$SRAST-SEARCH SPECIFIED AST QUEUE FOR SPECIFIED AST BLOCK		;MSH205
; **-$SASTQ-SEARCH QUEU      E FOR SPECIFIED AST BLOCK			;MSH205
;									;**-1
; THIS ROUTINE IS CALLED TO SEARCH FOR A SPECIFIED TYPE OF AST CONTROL
; BLOCK ON THE REQUESTED QUEUE.						;MSH205
;									;**-1
; INPUTS:
;
;	R0=POSITION IN QUEUE TO SEARCH FROM (IF CALLED AT $SASTQ ONLY)	;MSH205
;	R4=CODE INDICATING TYPE OF BLOCK TO BE SEARCHED FOR
;	R5=TCB ADDRESS OF TASK WHOSE SAST LIST IS TO BE SEARCHED
;
; OUTPUTS:
;
;	C=1 IF SPECIFED TYPE OF AST BLOCK NOT FOUND
;	C=0 IF SPECIFIED TYPE OF AST BLOCK IS FOUND
;		R0=AD      DRESS OF THE BLOCK
;		R1=ADDRESS OF WORD POINTING TO THE BLOCK
;-

	.IFTF								;MSH121
									;MSH121
$SRAST::			;DEFINE FOR MCR				;MSH121
									;MSH121
	.IFT								;MSH121
									;MSH121
	MOV	R5,R0		;GET TCB ADDRESS			;MSH121
	ADD	#T.SAST,R0	;POINT TO SPECIFIED AST BLOCK ADDRESS	;**-1
									;MSH205
	.IFTF								;MSH205
									;MSH205
$SASTQ::			;DEFINE FOR MCR				;MSH205
									;MSH205
	.IFT								;MSH205
									;MSH205
	SEC			;ASSUME FAILURE				;MSH205
	MOV	R0,R1	      	;GET POINTER TO NEXT BLOCK		;**-1
	MOV	(R0),R0		;GET LINK WORD
	BEQ	20$		;IF EQ, END OF LIST
	CMPB	R4,A.CBL+1(R0)	;IS THIS THE BLOCK OF THE SPECIFIED TYPE
	BNE	$SASTQ		;IF NE NO, CONTINUE SEARCH		;MSH205
20$:	RETURN								;**-1

	.ENDC


;+
; **-$SRSTD-SEARCH SYSTEM TASK DIRECTORY
;
; THIS ROUTINE IS CALLED TO SEARCH THE TASK DIRECTORY FOR A TASK OF THE
; SPECIFIED NAME.
;
; INPUTS:
;
;	R3=ADDRESS OF THE TASK NAME TO SEARCH FOR.
;
; OUTPUTS:
;
;	C=1 IF SPECIFIED TASK IS NOT FOUND.
;      	C=0 IF SPECIFIED TASK IS FOUND.
;		R0=ADDRESS OF THE TCB.
;
;	R1,R2, AND R3 ARE PRESERVED ACROSS CALL.
;-

	.ENABL	LSB
$SRSTD::								; MF203
									; MF203
									; MF203
	.IF DF	A$$CLI!P$$OFF						; MF203
									; MF203
	CMP	#^RCLI,(R3)	;SEARCHING FOR CLI...			; MF203
	BNE	5$		;IF NE NO				; MF203
	CMP	#^R...,2(R3)	;MAY HAVE IT				; MF203
	BNE	5$		;IF NE NO				; MF203
	MOV	$MCRPT,R0	;TCB FOR MCR... IS DESIRED		; MF203
	RETURN								; MF203
									; MF203
	.ENDC	;A$$CLI!P$$OFF      						; MF203
									; MF203
									; MF203
5$:	MOV	$TSKHD,R0	;POINT TO START OF TASK LIST		; MF203
10$:	CMP	T.NAM(R0),(R3)	;FIRST HALF OF NAME MATCH?		;**-1
	BNE	20$		;IF NE NO
	CMP	T.NAM+2(R0),2(R3) ;SECOND HALF OF NAME MATCH?
	BEQ	30$		;IF EQ YES
20$:	MOV	T.TCBL(R0),R0	;GET LINK TO NEXT TCB
	TST	T.TCBL(R0)	;NULL TASK?
	BNE	10$		;IF NE NO
25$:	SEC			;INDICATE FAILURE
30$:	RETURN			;

;+
; **-$ACTRM-REMOVE TASK FROM THE ACTIVE TASK LIST
;
; THIS ROUTINE IS CALLED TO REMOVE A TCB FROM T      HE ACTIVE TASK LIST.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB TO REMOVE.
;
; OUTPUTS:
;
;	C=1 IF THERE IS NO ENTRY IN THE LIST THAT MATCHES THE TCB ADDRES
;	C=0 IF A MATCHING ENTRY IS REMOVED FROM THE LIST.
;
;	R0 IS PRESERVED ACROSS THE CALL.
;
;-

$ACTRM::MOV	#$ACTHD-T.ACTL,R1 ;GET ADDR OF LISTHEAD
40$:	MOV	R1,R2		;SAVE PREVIOUS TCB ADDR
	MOV	T.ACTL(R2),R1	;GET NEXT TCB ADDR
	BEQ	25$		;IF EQ END OF LIST FOUND
	CMP	R0,R1		;DOES NEXT TCB ADDR EQ OURS?
	BNE	40$		;IF NE NO -- KEEP LOOKING
	M      OV	T.ACTL(R0),T.ACTL(R2) ;REMOVE ENTRY
	RETURN			;EXIT
	.DSABL	LSB
									;**-45

;+
; **-$DRTHR/$ERTHR-DIRECTIVE ERROR AND GENERAL ERROR THREADING ROUTINES
;
; THESE ROUTINES ARE USED IN CONJUNCTION WITH THE FOLLOWING ERROR
; RECOVERY ROUTINE TO DYNAMICALLY THREAD ERROR RECOVERY INFORMATION
; ONTO THE STACK.  AFTER INITIALIZATION, THE INTERFACE IS VIA A
; COROUTINE CALL (CALL @(SP)+) FOLLOWED BY TWO ROUTINE ADDRESSES.
; THE FIRST ROUTINE IS CALLED AND THEN THE SECOND ROUTINE ADDRESS IS
; PUS      HED ONTO THE STACK ALONG WITH THE CONTENTS OF R0 AND R1.  IT IS
; INTENDED THAT THE SECOND ROUTINE, ALONG WITH THE SAVED CONTENTS OF
; R0 AND R1, CAN UNDO THE ACTION OF THE FIRST ROUTINE IF AN ERROR
; CONDITION IS ENCOUNTERED LATER.  ANOTHER POSSIBILITY IS THAT THE FIRST
; ROUTINE IS NULL, AND THE SECOND ROUTINE CAN UNDO SOME PREVIOUS ACTION.
; $DRTHR MAY BE CALLED WHEN THE FINAL DESIRED ACTION ON ERROR WILL BE
; TO RETURN A DIRECTIVE STATUS PASSED IN R5 (IN THE FORM 'DRSTS D.RSX').
; $ERTHR IS A GEN      ERAL ERROR RECOVERY THREADING ROUTINE.  EXAMPLE USES OF
; THESE ROUTINES MAY BE FOUND IN THE MODULE DRSPW.
;
; INPUTS:
;
;	AS REQUIRED FOR CALL TO FIRST ROUTINE.
;
; OUTPUTS:
;
;	C-BIT AND R0-R3 ARE PRESERVED FROM RETURN OF FIRST ROUTINE.
;	R4 IS DESTROYED.
;-


	.IF DF	P$$OFF

	.ENABL	LSB
$DRTHR::MOV	(SP),R4		;PICK UP RETURN PC
	MOV	#10$,(SP)	;SET ADDRESS OF ROUTINE TO RETURN STATUS
	CMP	-(SP),-(SP)	;ALLOCATE WORDS FOR R0 AND R1
	MOV	R4,-(SP)	;RESTORE RETURN PC ADDRESS
$ERTHR::MOV	(SP)      ,R4		;PICK UP RETURN PC
	CALL	@(R4)+		;CALL THE FIRST ROUTINE ADDRESS
	MOV	(R4)+,(SP)	;SAVE THE RECOVERY ROUTINE ADDRESS
	MOV	R1,-(SP)	;SAVE CURRENT CONTENTS OF R1
	MOV	R0,-(SP)	;SAVE CURRENT CONTENTS OF R0
	CALL	(R4)		;CALL THE CALLER BACK
	BR	$ERTHR		;DO IT AGAIN
10$:	MOV	R5,-(SP)	;PUSH DIRECTIVE STATUS TRAP INSTRUCTION
	JMP	(SP)		;EXECUTE TRAP
	.DSABL	LSB

;+
; **-$ERREC-ERROR RECOVERY ROUTINE
;
; THIS ROUTINE IS USED IN CONJUNCTION WITH THE ABOVE ROUTINES TO
; EFFECT A SERIES OF SUBROUTIN      E CALLS STORED ON THE STACK FOR ERROR
; RECOVERY.  THE NORMAL CALLING SEQUENCE IS VIA A JUMP.  SUCCESSIVE
; R0 AND R1 CONTENTS ARE POPPED FROM THE STACK WITH CALLS TO THE
; SAVED ROUTINE ADDRESSES.  THE LAST ROUTINE ON THE STACK MUST FORCE
; THE PROCESS TO STOP.
;
; INPUTS:
;
;	R5=DIRECTIVE STATUS (IF INITIALIZED BY $DRTHR).
;
; OUTPUTS:
;
;	NONE.
;-

$ERREC::TST	(SP)+		;POP COROUTINE ADDRESS
10$:	MOV	(SP)+,R0	;PICK UP SAVED R0
	MOV	(SP)+,R1	;PICK UP SAVED R1
	CALL	@(SP)+		;CALL THE RECOVE      RY ROUTINE
	BR	10$		;

;+
; **-$QUEXT-QUEUE EXIT "AST" BLOCK
;
; THIS ROUTINE FILLS IN THE STATUS IN AN OFFSPRING CONTROL BLOCK,
; AND QUEUES IT AS A SPECIAL AST BLOCK TO THE PARENT TASK TCB.
;
; INPUTS:
;
;	R0=EXIT STATUS WORD.
;	R1=OCB ADDRESS.
;	R2=SECONDARY EXIT STATUS CODE (BYTE)				;MSH129
;
; OUTPUTS:
;
;	R3 IS PRESERVED.
;-

	.IFTF	;P$$OFF

$QUEXT::			;ALWAYS DEFINE FOR MCR

	.IFT	;P$$OFF

	MOV	R2,-(SP)	;SAVE SECONDARY EXIT STATUS CODE	;MSH129
	MOV	O.PTCB(R1),R2	;PICK UP P      ARENT TCB ADDRESS
	BEQ	30$		;IF EQ PARENT HAS EXITTED
	DEC	T.RDCT(R2)	;DECREMENT RUNDOWN COUNT
	MOV	T.ASTL(R2),(R1)	;LINK OCB TO FRONT OF AST LIST
	BNE	10$		;
	MOV	R1,T.ASTL+2(R2)	;
10$:	MOV	R1,T.ASTL(R2)	;
	MOV	#AK.OCB,A.CBL(R1) ;SET EXIT "AST" KERNEL AST TYPE	;MSH091
	MOV	R0,O.STAT(R1)	;SET EXIT STATUS			;**-1
	MOV	(SP)+,O.STAT+2(R1) ;STORE SECONDARY EXIT STATUS CODE	;MSH129
	MOV	R2,R0		;COPY PARENT TCB POINTER

	.IF DF D$$ISK&C$$CKP

	CALL	$SETCR		;SET CONDITIONAL SCHEDULE REQUEST
	MOV	T.P      CB(R0),R0	;POINT TO PARENT PCB
	CALLR	$NXTSK		;REALLOCATE (AST ENTRY CAN UNSTOP)

	.IFF	;D$$ISK&C$$CKP

	CALLR	$SETCR		;SET CONDITIONAL SCHEDULE REQUEST

	.ENDC	;D$$ISK&C$$CKP

30$:	MOV	R1,R0		;COPY OCB POINTER TO DEALLOCATE
	TST	(SP)+		;CLEAN STACK				;MSH129
	MOV	#O.LGTH,R1	;SET LENGTH TO DEALLOCATE
	CALLR	$DEACB		;DEALLOCATE OCB

	.ENDC	;P$$OFF

;+
; **-$STPCT-STOP CURRENT TASK
; **-$STPTK-STOP TASK
;
; THESE ROUTINES ARE CALLED TO STOP A TASK AND REALLOCATE THE TASK'S
; PARTITION.
      ;
; INPUTS:
;
;	R0=TCB ADDRESS OF TASK TO STOP (IF ENTRY AT $STPTK)
;
; OUTPUTS:
;
;	NONE
;-

$STPCT::MOV	$TKTCB,R0	;PICK UP ADDRESS OF CURRENT TASK TCB
$STPTK::BIS	#T2.STP,T.ST2(R0) ;SET STOP BIT IN TASK'S TCB


	.IF DF	D$$ISK

	CALL	$SETCR		;INSURE THAT TASK WILL STOP
	MOV	T.PCB(R0),R0	;POINT TO TASK PCB
	BR	$NXTSK		;REALLOCATE TASK PARTITION

	.IFF

	CALLR	$SETCR		;INSURE THAT TASK WILL STOP

	.IFT

;+
; **-$RLPAR-RELEASE TASK PARTITION
; **-$RLPR1-RELEASE PARTITION
;
; THIS       ROUTINE IS CALLED TO RELEASE A PARTITION OWNED BY A TASK AND TO
; ASSIGN THE PARTITION TO THE NEXT HIGHEST PRIORITY TASK WAITING TO
; OCCUPY THE PARTITION.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE OWNER TASK (IF ENTRY AT $RLPAR)
;	R1=ADDR OF SUBPARTITION PCB TO RELEASE (IF ENTRY AT $RLPR1)
;	R3=ADDRESS OF MAIN PARTITION PCB (IF ENTRY AT $RLPR1)
;
; OUTPUTS:
;
;	THE PARTITION IS RELEASED AND ASSIGNED TO THE NEXT HIGHEST
;	PRIORITY TASK WAITING TO OCCUPY THE PARTITION.
;-

$RLPAR::MOV	T.P      CB(R0),R1	;GET ADDRESS OF PARTITION PCB
	MOV	P.MAIN(R1),R0	;GET MAIN PCB ADDRESS
	MOV	R0,R3		;COPY MAIN PCB ADDRESS


	.IF DF	D$$YNM&M$$MGE

	BIT	#PS.SYS,P.STAT(R0) ;SYSTEM CONTROLLED PARTITION?
	BEQ	$RLPR1		;IF EQ NO
10$:	MOV	R0,R2		;SAVE ADDRESS OF PREVIOUS PCB
	MOV	P.SUB(R2),R0	;GET ADDRESS OF NEXT PCB
	CMP	R0,R1		;TASK PCB?
	BNE	10$		;IF NE NO
	MOV	P.SUB(R0),P.SUB(R2) ;REMOVE PCB FROM LIST

	.ENDC


$RLPR1::ADD	#P.BUSY,R1	;POINT TO BUSY FLAG
	BICB	(R1)+,(R1)	;CLEAR SUBPARTITION BUSY
      	BICB	-(R1),P.BUSY+1(R3) ;CLEAR MAIN PARTITION BUSY

;+
; **-$NXTSK-ASSIGN NEXT TASK TO PARTITION
;
; THIS ROUTINE IS CALLED TO ASSIGN A PARTITION TO THE HIGHEST PRIORITY
; TASK WAITING TO OCCUPY THE PARTITION. A TASK IS CONSIDERED ELIGIBLE	;MSH168
; TO BE ASSIGNED A PARTITION IF IT IS NOT STOPPED OR EXTERNALLY		;MSH168
; BLOCKED, IT IS STOPPED BUT HAS A PENDING AST, OR IT IS NOT WAITING	;MSH168
; FOR A PARTITION AS A RESULT OF A PREVIOUS CHECKPOINT OPERATION AND	;MSH168
; THE LOW POOL FLAG CONTRO      LLING TASK REQUESTS IS NOT SET.		;MSH168
;									;**-1
; INPUTS:
;
;	R0=ADDRESS OF THE PCB OF THE PARTITION TO ASSIGN.
;
; OUTPUTS:
;
;	FOR TASK-CONTROLLED PARTITIONS, THERE ARE FIVE POSSIBLE OUTPUTS:;MSH168
;									;**-1
;	1-THE PARTITION IS NOT CURRENTLY BUSY AND A TASK IS WAITING TO
;		OCCUPY THE PARTITION. THE PARTITION IS ASSIGNED TO THE
;		WAITING TASK AND A REQUEST IS PLACED IN THE LOADER
;		QUEUE TO LOAD THE TASK.
;
;	2-THE PARTITION IS CURRENTLY OCCUPIED BY A TASK THAT IS EITHER       OF
;		HIGHER PRIORITY THAN ALL WAITING TASKS OR IS NOT CHECK-	;MSH168
;		POINTABLE. THE PARTITION CANNOT BE ASSIGNED TO ANOTHER	;**-1
;		TASK.
;
;	3-THE PARTITION IS CURRENTLY OCCUPIED BY A LOWER PRIORITY CHECK-
;		POINTABLE TASK. A REQUEST IS PLACED IN THE LOADER QUEUE
;		TO CHECKPOINT THE OWNER TASK.
;
;	4-THE HIGHEST PRIORITY TASK WAITING TO OCCUPY THE PARTITION
;		REQUIRES THE MAIN PARTITION WHICH IS CURRENTLY		;MSH168
;		OCCUPIED BY ONE OR MORE TASKS THAT ARE EITHER OF	;MSH168
;		HIGHER PRI      ORITY OR ARE NOT CHECKPOINTABLE. THE PARTITION;**-2
;		CANNOT BE ASSIGNED.
;
;	5-THE HIGHEST PRIORITY TASK WAITING TO OCCUPY THE PARTITION
;		REQUIRES THE MAIN PARTITION WHICH IS CURRENTLY
;		OCCUPIED BY ONE OR MORE TASKS OF LOWER PRIORITY
;		THAT ARE CHECKPOINTABLE. A REQUEST IS PLACED IN THE
;		LOADER QUEUE TO CHECKPOINT EACH TASK.
;									;MSH168
;	FOR SYSTEM-CONTROLLED PARTITIONS, THERE ARE THREE POSSIBLE OUTPU;MSH168
;									;MSH168
;	1-THERE IS ENOUGH CONTIGUOUS UNALLOCATED SPACE IN THE       PARTITION	;MSH168
;		IN WHICH TO FIT THE WAITING TASK. THE REQUIRED MEMORY	;MSH168
;		SPACE IS ALLOCATED FOR THE TASK AND A REQUEST IS PLACED	;MSH168
;		IN THE LOADER QUEUE TO LOAD THE TASK.			;MSH168
;									;MSH168
;	2-THERE IS NOT ENOUGH CONTIGUOUS UNALLOCATED SPACE IN THE	;MSH168
;		PARTITION TO ALLOCATE FOR THE WAITING TASK, BUT A	;MSH168
;		BLOCK OF MEMORY WITHIN THE PARTITION OCCUPIED BY ONE	;MSH168
;		OR MORE CHECKPOINTABLE TASKS OF LOWER PRIORITY EXISTS	;MSH168
;		THAT IS SUFFICIENTLY L      ARGE TO MAKE ROOM FOR THE		;MSH168
;		WAITING TASK. A REQUEST IS PLACED IN THE LOADER QUEUE	;MSH168
;		FOR EACH TASK OCCUPYING THAT BLOCK TO BE CHECKPOINTED.	;MSH168
;									;MSH168
;	3-THERE IS NOT ENOUGH CONTIGUOUS UNALLOCATED SPACE IN THE	;MSH168
;		PARTITION TO ALLOCATE FOR THE WAITING TASK AND THERE	;MSH168
;		IS NO SUFFICIENTLY LARGE BLOCK OF MEMORY WITHIN THE	;MSH168
;		PARTITION CONTAINING CHECKPOINTABLE TASKS OF LOWER	;MSH168
;		PRIORITY TO MAKE ROOM FOR THE WAITING TASK. THE		;MSH168
;	      	MEMORY SHUFFLER IS REQUESTED TO RUN IN AN ATTEMPT	;MSH168
;		TO COMPACT THE PARTITIONS'S CONTENTS.			;MSH168
;-

$NXTSK::SAVNR			;SAVE R4 AND R5
	MOV	P.MAIN(R0),R5	;GET MAIN PARTITION PCB ADDRESS
10$:	MOV	P.WAIT(R5),R4	;GET 1ST TCB IN WAIT LIST
20$:	BEQ	100$		;IF EQ END OF LIST
									;MSH142
	.IF DF	P$$CTL							;MSH142
									;MSH142
	TSTB	$POLFL		;LOW POOL CONTROL IN EFFECT? (PF.REQ)	;MSH142
	BPL	204$		;IF PL NO				;MSH142
	TSTB	T.STAT(R4)	;INITIAL TASK REQUEST? (TS.CKP)		;MSH142
	BMI	      204$		;IF MI NO, TASK CHECKPOINTED		;MSH142
	BIT	#T3.PRV,T.ST3(R4) ;PRIVILEGED TASK REQUEST?		;MSH142
	BNE	204$		;IF NE YES				;MSH142
	BIT	#T2.ABO!T2.REX,T.ST2(R4) ;TASK BEING ABORTED?		;MSH142
	BNE	204$		;IF NE YES, ELIGIBLE FOR MEMORY		;MSH142
	CMPB	T.PRI(R4),$POLBP ;TASK OF MINIMUM PRIORITY?		;MSH142
	BLO	40$		;IF LO NO, SKIP THIS TASK		;MSH142
									;MSH142
	.ENDC								;MSH142
									;MSH142
204$:	BIT	#TS.STP,T.STAT(R4) ;TASK BLOCKED FROM EXECUTION?	;MSH122
	BNE	40$		;IF NE YES, SKIP       IT			;MSH122
	BIT	#T2.STP,T.ST2(R4) ;TASK STOPPED?


	.IF DF	A$$TRP

	BEQ	21$		;IF EQ NO
	TST	T.ASTL(R4)	;DOES TASK HAVE PENDING AST?
	BEQ	40$		;IF EQ NO
21$:				;REF LABEL

	.IFF

	BNE	40$		;IF NE YES

	.ENDC


	.IF DF	D$$YNM&M$$MGE

	BIT	#PS.SYS,P.STAT(R5) ;SYSTEM CONTROLLED PARTITION?
	BNE	110$		;IF NE YES

	.ENDC


	TSTB	P.BUSY+1(R5)	;MAIN PARTITION OCCUPIED?
	BMI	50$		;IF MI YES
	MOV	T.PCB(R4),R2	;GET REQUESTED PARTITION PCB ADDRESS
	TSTB	P.BUSY+1(R2)	;REQUESTED PARTITION B      USY?
	BNE	30$		;IF NE YES
25$:	MOV	R5,R0		;COPY MAIN PARTITION PCB ADDRESS
	ADD	#P.WAIT,R0	;CALCULATE PCB LISTHEAD ADDRESS
	MOV	R4,R1		;COPY TCB ADDRESS
	CALL	$QRMVT		;REMOVE TCB FROM LIST
	MOV	T.PCB(R4),R0	;GET PCB ADDRESS
	MOV	R4,P.TCB(R0)	;PUT TCB ADDRESS IN PCB
	ADD	#P.BUSY,R0	;POINT TO BUSY FLAG
	BISB	(R0)+,(R0)	;SET SUBPARTITION BUSY
	BISB	-(R0),P.BUSY+1(R5) ;SET MAIN PARTITION BUSY
	CALL	$LOADT		;PUT TASK IN LOADER QUEUE
	BR	10$		;GO AGAIN
30$:				;REF LABEL


	.IF DF	C$$CKP

	TSTB	      P.BUSY(R2)	;MAIN PARTITION REQUESTED
	BMI	50$		;IF MI YES
	MOV	P.TCB(R2),R1	;GET OWNER TASK TCB ADDRESS
	CALL	$TSTCP		;SHOULD TASK BE CHECKPOINTED?
	BCS	40$		;IF CS NO
	CALL	$ICHKP		;INITIATE CHECKPOINT

	.IFTF

40$:	MOV	(R4),R4		;POINT TO NEXT TCB
	BR	20$		;

	.IFT

50$:	MOV	R5,R0		;COPY MAIN PCB ADDRESS
60$:	BITB	P.BUSY(R0),P.BUSY+1(R0) ;IS THIS PARTITION BUSY?
	BEQ	70$		;IF EQ NO
	MOV	P.TCB(R0),R1	;GET OWNER TCB ADDRESS
	CALL	$TSTCP		;SHOULD TASK BE CHECKPOINTED?
	BCS	100$		;IF CS NO
      70$:	MOV	P.SUB(R0),R0	;GET NEXT PARTITION PCB ADDRESS
	BNE	60$		;IF NE MORE TO GO
80$:	BITB	P.BUSY(R5),P.BUSY+1(R5) ;IS THIS PARTITION BUSY?
	BEQ	90$		;IF EQ NO
	MOV	P.TCB(R5),R1	;GET OWNER TCB ADDRESS
	CALL	$ICHKP		;INITIATE CHECKPOINT
90$:	MOV	P.SUB(R5),R5	;GET NEXT SUBPARTITION PCB
	BNE	80$		;IF NE MORE TO GO

	.IFF

50$:				;REF LABEL

	.IFTF

100$:	RETURN			;EXIT

;									;MSH168
; THE FOLLOWING STEPS ARE TAKEN TO ASSIGN A PIECE OF THE SYSTEM		;MSH168
; CONTROLLED PARTITION TO THE       WAITING TASK:				;MSH168
;									;MSH168
;	1-TRY TO FIND ENOUGH FREE SPACE TO ALLOCATE FOR THE TASK.	;MSH168
;									;MSH168
;	2A-TRY TO FIND A BLOCK OF MEMORY WITHIN THE PARTITION		;MSH168
;		CONTAINING CHECKPOINTABLE TASKS OF LOWER PRIORITY	;MSH168
;		WITHOUT OUTSTANDING I/O THAT IS SUFFICIENTLY LARGE	;MSH168
;		TO MAKE ROOM FOR THE WAITING TASK.			;MSH168
;									;MSH168
;	2B-TRY TO FIND A BLOCK OF MEMORY WITHIN THE PARTITION		;MSH168
;		CONTAINING CHECKPOINTABLE TASKS OF LOWER PRIORITY	;      MSH168
;		THAT IS SUFFICIENTLY LARGE TO MAKE ROOM FOR THE		;MSH168
;		WAITING TASK.						;MSH168
;									;MSH168
;	3-INVOKE THE MEMORY SHUFFLER TO COMPACT THE CONTENTS OF THE	;MSH168
;		SYSTEM-CONTROLLED PARTITION.				;MSH168
;									;MSH168

	.IF DF	D$$YNM&M$$MGE

110$:	MOV	T.PCB(R4),R4	;POINT TO TASK PCB
	CALL	$FNDSP		;ATTEMPT TO FIND SPACE IN PARTITION
	MOV	P.SIZE(R4),R0	;SAVE SIZE OF PARTITION
	MOV	P.TCB(R4),R4	;RESTORE TCB ADDRESS
	BCC	25$		;IF CC SPACE WAS FOUND


	.IF DF	C$$CKP
      
	MOV	P.REL(R5),R3	;SET BASE ADDRESS OF FIRST HOLE		;MSH168
	MOV	R5,R2		;SET ADDRESS OF PREVIOUS PCB		;**-1
	MOV	#$TCPIO,-(SP)	;FIRST SCAN, I/O IS BLOCKING FACTOR	;MSH168
	CALL	160$		;TRY TO ALLOCATE SOME SPACE		;MSH168
	MOV	P.MAIN(R5),R5	;POINT TO MAIN PCB			;MSH168
	MOV	P.REL(R5),R3	;SET BASE ADDRESS OF FIRST HOLE		;MSH168
	MOV	R5,R2		;SET ADDRESS OF PREVIOUS PCB		;MSH168
	MOV	#$TSTCP,(SP)	;SECOND SCAN, IGNORE I/O COUNTS		;MSH168
	CALL	160$		;TRY TO ALLOCATE SOME SPACE AGAIN	;MSH168
	TST	(SP)+		      ;CLEAN STACK - ALLOCATION FAILURE	;MSH168
									;MSH168
	.IF DF	D$$SHF							;MSH168
									;MSH168
	TST	$SHFTM		;TOO SOON TO REQUEST SHUFFLER		;MSH184
	BNE	210$		;IF NE YES, FORGET IT FOR NOW		;MSH184
	MOV	$SHFPT,R0	;GET MEMORY SHUFFLER TCB ADDRESS	;MSH168
	BEQ	210$		;IF EQ SHUFFLER NOT INSTALLED		;MSH168
	CALLR	$EXRQC		;REQUEST SHUFFLER TO RUN		;MSH168
									;MSH168
	.IFF								;MSH168
									;MSH168
	RETURN			;					;MSH168
									;MSH168
	.ENDC								;MSH168
									;MSH168      
160$:	MOV	P.SUB(R2),R2	;GET ADDRESS OF NEXT PCB
	BEQ	210$		;IF EQ ALLOCATION FAILURE


	.IF DF	L$$DRV!P$$LAS

	BIT	#PS.DRV!PS.COM,P.STAT(R2) ;DRIVER OR COMMON PARTITION?
	BNE	165$		;IF NE YES

	.ENDC


	MOV	P.TCB(R2),R1	;GET TCB ADDRESS OF OWNER TASK
	CALL	@2(SP)		;CAN TASK BE CHECKPOINTED?		;MSH168
	BCC	170$		;IF CC YES				;**-1
165$:	MOV	R2,R5		;SAVE ADDRESS OF PREVIOUS PCB
	MOV	P.REL(R5),R3	;CALCULATE NEW HOLE BASE ADDRESS
	ADD	P.SIZE(R5),R3	;
	BR	160$		;
170$:	CLR	-(SP)		;INITIALIZE       TOP OF HOLE
	MOV	P.SUB(R2),R1	;GET ADDRESS OF NEXT PCB
	BNE	180$		;IF NE ONE EXISTS
	MOV	P.MAIN(R2),R1	;RETRIEVE ADDRESS OF MAIN PCB
	ADD	P.SIZE(R1),(SP)	;CALCULATE ADDRESS OF TOP OF HOLE
180$:	ADD	P.REL(R1),(SP)	;
	SUB	R3,(SP)		;CALCULATE SIZE OF HOLE			;MSH168
	CMP	(SP)+,R0	;HOLE BIG ENOUGH?			;**-1
	BLO	160$		;IF LO NO
	MOV	R2,R4		;SAVE ADDRESS OF LAST PCB
200$:	MOV	P.SUB(R5),R5	;GET ADDRESS OF NEXT PCB
	MOV	P.TCB(R5),R1	;GET ADDRESS OF TASK TCB
	CALL	$ICHKP		;INITIATE CHECKPOINT
	CMP	R4,R5	      	;LAST PCB TO EXAMINE?
	BNE	200$		;IF NE NO
	CMP	(SP)+,(SP)+	;CLEAN STACK				;MSH168
									;MSH168
	.ENDC	;C$$CKP							;MSH168
									;MSH168
210$:	RETURN			;					;MSH168
									;**-22
	.ENDC


;+
; **-$FNDSP-FIND SPACE IN PCB LIST
;
; THIS ROUTINE IS CALLED TO FIND SPACE WITHIN A DYNAMICALLY ALLOCATED
; PCB LIST REPRESENTING THE ALLOCATION STATE OF A SYSTEM CONTROLLED
; PARTITION OR DYNAMIC CHECKPOINT FILE.
;
; INPUTS:
;
;	R4=ADDRESS OF PCB TO FIND SPACE FOR
;	R5=ADDRESS OF MAI      N PCB FOR SPACE IN WHICH TO ALLOCATE
;
; OUTPUTS:
;
;	C=0 IF ALLOCATION WAS SUCCESSFUL
;		SUB PCB IS LINKED INTO ALLOCATION LIST
;	C=1 IF ALLOCATION FAILURE
;
;	R0,R1,R2 ARE MODIFIED.
;-


									;EF012
	.ENDC	;C$$CKP							;EF012
									;EF012
	.IFTF	;D$$ISK							;EF012
									;EF012
	.IF DF	D$$YNM&M$$MGE!D$$YNC

$FNDSP::MOV	R5,R0		;COPY ADDRESS OF MAIN PCB
	MOV	P.REL(R5),R2	;SET HIGHEST ADDRESS IN LAST PARTITION
10$:	MOV	P.SUB(R0),R1	;GET ADDRESS OF NEXT PCB
	BEQ	20$		;IF EQ E      ND OF LIST
	MOV	P.REL(R1),-(SP)	;CALCULATE SIZE OF HOLE
	SUB	R2,(SP)		;
	CMP	(SP)+,P.SIZE(R4) ;HOLE BIG ENOUGH?
	BHIS	30$		;IF HIS YES
	MOV	R1,R0		;SAVE ADDRESS OF PREVIOUS PCB
	MOV	P.REL(R1),R2	;CALCULATE BASE ADDRESS OF NEXT HOLE
	ADD	P.SIZE(R1),R2	;
	BR	10$		;
20$:	MOV	P.REL(R5),-(SP)	;CALCULATE SIZE OF LAST HOLE
	ADD	P.SIZE(R5),(SP)	;
	SUB	R2,(SP)		;
	CMP	(SP)+,P.SIZE(R4) ;HOLE BIG ENOUGH?
	BLO	40$		;IF LO NO
30$:	MOV	R2,P.REL(R4)	;SET ADDRESS OF TASK PARTITION
	MOV	R4,P.SUB(R0)	;LINK ALL      OCATED PARTITION TO PREVIOUS
	MOV	R1,P.SUB(R4)	;LINK NEXT TO TASK PCB
40$:	RETURN			;

	.ENDC


	.IFT	;D$$ISK							;EF012
									;EF012
	.IF DF	C$$CKP							;EF012
									;MSH168
	.ENABL	LSB							;MSH168
									;MSH168
	.IF DF	D$$YNM&M$$MGE						;MSH168
									;MSH168
;+									;MSH168
; **-$TCPIO-TEST IF CHECKPOINT SHOULD BE INITIATED IF NO I/O		;MSH168
;									;MSH168
; INPUTS:								;MSH168
;									;MSH168
;	R1=ADDRESS OF THE TCB OF THE OWNER TASK.			;MSH168
;	R4=ADDR      ESS OF THE TCB OF THE REQUESTED TASK.			;MSH168
;									;MSH168
; OUTPUTS:								;MSH168
;									;MSH168
;	C=0 IF CHECKPOINT SHOULD BE INITIATED.				;MSH168
;	C=1 IF CHECKPOINT SHOULD NOT BE INITIATED.			;MSH168
;-									;MSH168
									;MSH168
$TCPIO::TSTB	T.IOC(R1)	;OUTSTANDING I/O?			;MSH168
									;MSH168
	.IF DF	S$$WPC&D$$ISK						;MSH168
									;MSH168
	BEQ	$TSTCP		;IF EQ NO, JOIN COMMON CODE		;MSH168
	SEC			;TASK NOT CHECKPOINTABLE WITH		;MSH168
	RETURN			;OUTSTANDING I/O			      ;MSH168
									;MSH168
	.IFF								;MSH168
									;MSH168
	BNE	15$		;IF NE YES, TASK NOT ELIGIBLE FOR CKP	;MSH168
									;MSH168
	.ENDC								;MSH168
									;MSH168
	.ENDC	;D$$YNM&M$$MGE						;MSH168
									;**-1
;+
; **-$TSTCP-TEST IF CHECKPOINT SHOULD BE INITIATED
;
; INPUTS:
;
;	R1=ADDRESS OF THE TCB OF THE OWNER TASK.
;	R4=ADDRESS OF THE TCB OF THE REQUESTED TASK.
;
; OUTPUTS:
;
;	C=0 IF CHECKPOINT SHOULD BE INITIATED.
;	C=1 IF CHECKPOINT SHOULD NOT BE INITIATED.
;-

      $TSTCP::			;


	.IF DF	S$$WPC&D$$ISK

	MOV	R5,-(SP)	;SAVE R5

	.IFTF

	BIT	#TS.STP,T.STAT(R1) ;TASK BLOCKED FROM EXECUTION?	;MSH122
	BNE	5$		;IF NE YES, EFFECTIVE PRIORITY OF ZERO	;MSH122
	BIT	#T2.STP,T.ST2(R1) ;TASK STOPPED FOR TERMINAL INPUT?


	.IF DF	A$$TRP

	BEQ	3$		;IF EQ NO
	TST	T.ASTL(R1)	;TASK HAVE PENDING AST?
	BEQ	5$		;IF EQ NO
3$:				;REF LABEL

	.IFF

	BNE	5$		;IF NE YES

	.ENDC


	.IFT

	MOV	#S$$WPR,R5	;PICK UP INITIAL PRIORITY DIFFERENCE
	BIT	#TS.CKP!TS.OUT,T.ST      AT(R1) ;TASK IN MEMORY?		;MSH166
	BNE	4$		;IF NE NO				;**-1
	MOV	T.PCB(R1),R5	;POINT TO TASK PCB
	MOV	P.HDR(R5),R5	;POINT TO TASK HEADER
	MOVB	H.SPRI(R5),R5	;PICK UP SWAPPING PRIORITY
4$:	CLR	-(SP)		;EXTRACT TASK PRIORITY BYTE
	BISB	T.PRI(R1),(SP)	;
	ADD	(SP)+,R5	;CALCULATE EFFECTIVE PRIORITY
	CMP	T.PRI(R4),R5	;REQUESTED TASK HIGHER PRIORITY?
	BLE	10$		;IF LE NO

	.IFF

	CMPB	T.PRI(R4),T.PRI(R1) ;REQUESTED TASK HIGHER PRIORITY?
	BLOS	10$		;IF LOS NO

	.IFTF

5$:	CLC			;ASSUME TASK CHECKPO      INTABLE
	BIT	#T2.CKD!T2.CHK!T2.FXD!T2.HLT,T.ST2(R1) ;IS IT?
	BEQ	20$		;IF EQ TASK CAN BE CHECKPOINTED
10$:	BIC	#TS.CKR,T.STAT(R1) ;CLEAR PENDING CHECKPOINT REQUESTS	;MSH048
15$:	SEC			;INDICATE NO CHECKPOINT			;MSH048
20$:				;REF LABEL				;**-1

	.IFT

	MOV	(SP)+,R5	;RESTORE R5

	.ENDC


	RETURN			;

									;MSH168
	.DSABL	LSB							;MSH168
;+
; **-$ICHKP-INITIATE CHECKPOINT
;
; INPUTS:
;
;	R1=ADDRESS OF THE TCB OF THE TASK TO BE CHECKPOINTED.
;-

$ICHKP::BIT	#TS.OUT,T.STAT(R1)       ;TASK BEING READ IN?
	BNE	20$		;IF NE YES
	BIT	#TS.CKP,T.STAT(R1) ;TASK ALREADY BEING CHECKPOINTED?
	BNE	30$		;IF NE YES
	MOV	R1,R0		;SET ADDRESS OF TCB
	CALL	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST
	MOV	R0,R1		;RESTORE ADDRESS OF TCB
	TSTB	T.IOC(R1)	;I/O IN PROGRESS
	BEQ	$CHKPT		;IF EQ NO
20$:	BIS	#TS.CKR,T.STAT(R1) ;SET CHECKPOINT REQUEST
30$:	RETURN			;

;+
; ***-$CHKPT-CHECKPOINT TASK
;
; THIS ROUTINE IS CALLED TO CHECKPOINT A TASK.
;
; INPUTS:
;
;	R1=ADDRESS OF THE TCB OF THE TAS      K TO BE CHECKPOINTED.
;
; OUTPUTS:
;
;	THE CHECKPOINT FLAG IS SET IN THE TASK STATUS WORD, THE TASK
;	IS PLACED IN THE LOADER QUEUE, AND THE LOADER IS REQUESTED
;	TO CHECKPOINT THE TASK.
;-

$CHKPT::			;


	.IF DF	D$$YNC

	SAVNR			;SAVE R4 AND R5
	BIC	#T2.CAF,T.ST2(R1) ;CLEAR CHECKPOINT ALLOCATION FAILURE
	MOV	R1,R3		;COPY TCB ADDRESS
	MOV	#P.SIZE+2,R1	;SET SIZE OF CHECKPOINT PCB
	CALL	$ALOCB		;ATTEMPT TO ALLOCATE PCB
	BCS	20$		;IF CS ALLOCATION FAILURE
	MOV	R0,R4		;COPY ADDRESS OF ALLOC      ATED PCB
	ADD	R1,R0		;POINT TO END OF ALLOCATED PCB
	MOV	T.PCB(R3),R1	;POINT TO TASK PCB
	MOV	P.SIZE(R1),-(R0) ;SET SIZE OF TASK PCB


	.IF DF	M$$MGE

	ADD	#7,(R0)		;ROUND TO NEXT DISK BLOCK
	ROR	(R0)		;CONVERT TO DISK BLOCKS
	ASR	(R0)		;
	ASR	(R0)		;

	.IFF

	ADD	#777,(R0)	;ROUND TO NEXT BLOCK BOUNDARY
	CLRB	(R0)		;CLEAR EXCESS BITS
	SWAB	(R0)		;CONVERT TO 256. WORD BLOCKS
	ASR	(R0)		;

	.ENDC


	MOV	#$CFLPT,R5	;POINT TO FIRST CHECKPOINT FILE PTR
10$:	MOV	(R5),R5		;GET NEXT CHECKPOI      NT FILE PCB ADDRESS
	BNE	30$		;IF NE THERE IS ONE
	MOV	R4,R0		;ELSE GET ADDRESS OF CHECKPOINT PCB
	MOV	#P.SIZE+2,R1	;SET ITS SIZE
	MOV	R3,R5		;SAVE TCB ADDRESS
	CALL	$DEACB		;DEALLOCATE CHECKPOINT PCB
	MOV	R5,R3		;RESTORE TCB ADDRESS
20$:	MOV	R3,R1		;RESTORE TCB ADDRESS
	BIS	#T2.CAF,T.ST2(R3) ;SET CHECKPOINT ALLOCATION FAILURE
	BIT	#T3.CAL,T.ST3(R3) ;CHECKPOINT SPACE ALLOCATED WITH TASK?
	BNE	50$		;IF NE YES
									;MSH111
	.IF DF	T$$KMG							;MSH111
									;MSH111
	MOV	$TKNPT,R0	;ELSE PO      INT TO TKTN TCB
	BEQ	25$		;IF EQ TKTN NOT INSTALLED
	TST	T.STAT(R0)	;TKTN ALREADY ACTIVE?
	BMI	$EXRQN		;IF MI NO
									;MSH111
	.ENDC								;MSH111
									;MSH111
25$:	RETURN			;
30$:	TST	P.REL(R5)	;ALLOCATION IN THIS FILE TURNED OFF?
	BNE	10$		;IF NE YES
	CALL	$FNDSP		;ATTEMPT TO ALLOCATE SPACE IN FILE
	BCS	10$		;IF CS ALLOCATION FAILURE
	MOV	R5,P.MAIN(R4)	;SET MAIN PCB POINTER
	MOV	R3,R1		;COPY TCB POINTER
	MOV	R4,T.CPCB(R1)	;SET ADDRESS OF CHECKPOINT PCB
50$:				;REF LABEL

	.ENDC      


	BIS	#TS.CKP,T.STAT(R1) ;SET CHECKPOINT IN PROGRESS BIT

	.ENDC


;+
; **-$LOADT-PUT TASK IN LOADER QUEUE
;
; THIS ROUTINE PUTS A TASK IN THE LOADER QUEUE FOR AN INITIAL LOAD OR
; A CHECKPOINT OPERATION.
;
; INPUTS:
;
;	R1=ADDRESS OF TASK CONTROL BLOCK
;
; OUTPUTS:
;
;	NONE
;-

$LOADT::MOV	$LDRPT,R0	;PICK UP TCB ADDRESS OF LOADER

	.ENDC


;+
; **-$EXRQP-EXECUTIVE REQUEST WITH QUEUE INSERT BY PRIORITY
; **-$EXRQF-EXECUTIVE REQUEST WITH QUEUE INSERT FIFO
; **-$EXRQN-EXECUTIVE       REQUEST WITH NO QUEUE INSERTION
; **-$EXRQU-EXECUTIVE UNSTOP AND REQUEST WITH NO QUEUE INSERTION	;MSH046
; **-$EXRQC-EXECUTIVE REQUEST - NO UNSTOP, W/CONDITIONAL SCHEDULE REQ	;MSH168
; **-$EXRQS-EXECUTIVE REQUEST WITH NO CONDITIONAL SCHEDULE REQUEST	;MSH069
;
; THESE ROUTINES PROVIDE A STANDARD INTERFACE TO ALL TASKS REQUESTED BY
; THE EXECUTIVE.
;
; INPUTS:
;
;	R0=TCB ADDRESS OF TASK TO REQUEST
;	R1=ADDR OF PACKET TO QUEUE TO TASK (IF ENTRY AT $EXRQP/$EXRQF)
;
; OUTPUTS:
;
;	C=0 IF THE REQU      EST WAS SUCCESSFULLY COMPLETED.
;	C=1 IF THE TASK WAS NOT SUCCESSFULLY REQUESTED.
;		Z=0 IF PCB ALLOCATION FAILURE.
;		Z=1 IF TASK ACTIVE, BEING REMOVED, OR BEING FIXED.
;-

	.ENABL	LSB
$EXRQP::MOV	#$QINSP,-(SP)	;PUSH ADDR OF QUEUE INSERT BY PRIORITY
	BR	1$		;JOIN COMMON CODE
$EXRQF::MOV	#$QINSF,-(SP)	;PUSH ADDR OF QUEUE INSERT FIFO
1$:	ADD	#T.RCVL,R0	;POINT TO TASK RECEIVE LIST
	CALL	@(SP)+		;INSERT PACKET IN RECEIVE QUEUE
	SUB	#T.RCVL,R0	;POINT BACK TO START OF TCB
$EXRQN::BIT	#T2.STP*2!T2.ST      P,T.ST2(R0) ;TASK STOPPED?
	BEQ	$EXRQS		;IF EQ NO				;MSH069
$EXRQU::BIC	#T2.STP*2!T2.STP,T.ST2(R0) ;CLEAR TASK STOP BIT		;MSH046
$EXRQC::CALL	$SETCR		;SET CONDITIONAL SCHEDULE REQUEST	;MSH168
$EXRQS::CLR	R1		;USE DEFAULT UIC			;MSH069
	.DSABL	LSB							;**-4

;+
; **-$TSKRT-TASK REQUEST (DEFAULT UCB)
; **-$TSKRQ-TASK REQUEST (SPECIFY UCB)
; **-$TSKRP-TASK REQUEST (SPECIFY DEFAULT UIC)
;
; THIS ROUTINE IS CALLED TO REQUEST THE EXECUTION OF A TASK.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE       TASK TO BE REQUESTED.
;	R1=REQUEST UIC.
;	R2=UCB ADDRESS IF ENTRY AT $TSKRQ.
;	R3=DEFAULT UIC IF ENTRY AT $TSKRP.
;
; OUTPUTS:
;
;	C=1 IF TASK IS ALREADY ACTIVE OR IS BEING FIXED IN MEMORY.
;		Z=1 IF TASK ACTIVE OR BEING FIXED.
;		Z=0 IF PCB ALLOCATION FAILURE.
;	C=0 IF THE REQUEST IS SUCCESSFULLY COMPLETED.
;-


	.IF NDF	M$$MUP

$TSKRT::MOV	$COPT,R2	;GET ADDRESS OF COMMAND OUTPUT UCB
$TSKRP::			;REF LABEL
$TSKRQ::MOV	R0,R3		;POINT TO TASK STATUS WORD
	ADD	#T.STAT,R3	;
	MOV	#TS.EXE,-(SP      )	;ASSUME TASK IS ACTIVE OR BEING FIXED
	BIT	(SP),(R3)+	;TASK ALREADY ACTIVE?
	BEQ	10$		;IF EQ YES
	BIT	#T2.FXD,(R3)+	;TASK POSSIBLY BEING FIXED?
	BEQ	1$		;IF EQ NO
	BIT	#TS.OUT,T.STAT(R0) ;TASK BEING FIXED?
	BNE	10$		;IF NE YES
1$:	BIT	#T3.REM,(R3)	;TASK BEING REMOVED BY MCR?		; MF203
	BNE	10$		;IF NE YES				;**-1
	CMP	-(R3),-(R3)	;POINT BACK TO FIRST STATUS WORD

	.IFF

$TSKRT::MOV	$COPT,R2	;GET ADDRESS OF COMMAND OUTPUT UCB
$TSKRQ::MOV	R1,R3		;MAKE CURRENT UIC DEFAULT UIC
$TSKRP::MOV	#TS.E      XE,-(SP)	;ASSUME TASK IS ACTIVE OR BEING FIXED
	BIT	(SP),T.STAT(R0)	;TASK ALREADY ACTIVE?
	BEQ	10$		;IF EQ YES
	BIT	#TS.OUT,T.STAT(R0) ;TASK POSSIBLY BEING FIXED?
	BEQ	1$		;NO
	BIT	#T2.FXD,T.ST2(R0) ;TASK BEING FIXED?
	BNE	10$		;IF NE YES
1$:	BIT	#T3.REM,T.ST3(R0) ;TASK BEING REMOVED BY MCR?		; MF203
	BNE	10$		;IF NE YES				;**-1
	MOV	R3,T.ACTL(R0)	;SET DEFAULT UIC
	MOV	R0,R3		;POINT TO TASK STATUS WORD
	ADD	#T.STAT,R3	;

	.ENDC


	BIC	(SP),(R3)+	;SET TASK ACTIVE
	CLR	(SP)		;CLEAR FAILURE I      NDICATOR
	MOV	R1,T.EFLG(R0)	;SAVE REQUEST UIC
	MOV	R2,T.UCB(R0)	;SET ADDRESS OF 'TI' UCB


	.IF DF	D$$ISK

	BIT	#T2.FXD,(R3)	;TASK FIXED IN MEMORY?
	BNE	20$		;IF NE YES


	.IF DF	D$$YNM&M$$MGE

	MOV	T.PCB(R0),R1	;GET ADDRESS OF TASK PCB
	BIT	#PS.SYS,P.STAT(R1) ;SYSTEM CONTROLLED PARTITION?
	BEQ	7$		;IF EQ NO
	MOV	R0,-(SP)	;SAVE TASK TCB ADDRESS
	MOV	#P.LGTH,R1	;SET LENGTH OF BLOCK NEEDED
	CALL	$ALOCB		;ALLOCATE PCB
	MOV	R0,R2		;SAVE ADDRESS OF ALLOCATED BLOCK
	MOV	(SP)+,R0	;RETRIEVE TASK       TCB ADDRESS
	ROR	(SP)		;CAPTURE CARRY BIT
	BEQ	3$		;IF EQ ALLOCATION WAS SUCCESSFUL
	BIS	(SP),T.STAT(R0)	;SET TASK INACTIVE
	INC	(SP)		;SET ALLOCATION FAILURE
									;MSH111
	.IF DF	T$$KMG							;MSH111
									;MSH111
	CMP	R0,$TKNPT	;TRYING TO BRING IN TKTN?
	BEQ	30$		;YES, EXIT RECURSIVE LOOP
									;MSH111
	.ENDC								;MSH111
									;MSH111
	BR	10$		;
3$:	MOV	T.PCB(R0),R1	;GET MAIN PARTITION PCB ADDRESS
	MOV	R2,T.PCB(R0)	;SET ADDRESS OF ALLOCATED PCB
	TST	(R2)+		;SKIP OVER LINK       WORD
	MOV	T.PRI(R0),(R2)+	;SET PRIORITY AND I/O COUNT
	MOV	P.NAM(R1),(R2)+	;INSERT PARTITION NAME
	MOV	P.NAM+2(R1),(R2)+ ;
	CLR	(R2)+		;CLEAR POINTER TO NEXT SUBPARTITION
	MOV	R1,(R2)+	;SET BACK POINTER TO MAIN PARTITION PCB
	CLR	(R2)+		;CLEAR RELOCATION BASE
	MOV	T.MXSZ(R0),(R2)+ ;SET PARTITION SIZE IN 32W BLOCKS
	CLR	(R2)+		;CLEAR WAIT QUEUE POINTER
	MOV	T.MXSZ(R0),(R2)+ ;INITIALLIZE SWAP SIZE
	CLR	(R2)+		;CLEAR PARTITION BUSY FLAGS
	MOV	R0,(R2)+	;SET OWNER TCB ADDRESS
	MOV	#PS.SYS!PS.DEL,(R2)      + ;SYSTEM CONTROLLED, MARKED FOR DEL
	CLR	(R2)+		;INITIALLY CLEAR HEADER POINTER


	.IF DF	P$$LAS

	CLR	(R2)+		;CLEAR PROTECTION WORD
	MOV	R2,R1		;SAVE POINTER TO ATTACHMENT LISTHEAD
	CLR	(R2)+		;SET UP ATTACHMENT LISTHEAD
	MOV	R1,(R2)+	;

	.ENDC


	.ENDC


7$:	MOV	R0,R1		;COPY TASK TCB ADDRESS
	MOV	T.PCB(R0),R0	;GET ADDRESS OF TASK PCB
	MOV	P.MAIN(R0),R0	;GET ADDRESS OF MAIN PARTITION PCB
	ADD	#P.WAIT,R0	;POINT TO PARTITION WAIT QUEUE LISTHEAD
	CALL	$QINSP		;PUT TASK IN PARTITION WAIT       QUEUE
	MOV	R1,R0		;RESTORE TCB ADDRESS
10$:	MOV	T.PCB(R0),R0	;GET ADDRESS OF TASK PARTITION PCB
	CALL	$NXTSK		;SELECT NEXT TASK
	BR	30$		;

	.IFTF

20$:	CALL	$BILDS		;BUILD A STACK FOR TASK

	.IFT

30$:	ASL	(SP)+		;SET SUCCESS/FAILURE INDICATION

	.IFF

10$:	ASL	(SP)+		;SET SUCCESS/FAILURE INDICATION

	.ENDC


	RETURN			;

;+
; **-$UISET-ESTABLISH DEFAULT UIC AND CURRENT UIC
;
; THIS ROUTINE ESTABLISHES DEFAULT AND CURRENT FOR REQUESTED TASKS
; IN MULTI-USER SYSTEMS.
;
; INPUTS:      
;
;	R1=REQUEST UIC
;	R2=ADDRESS OF SECOND STATUS WORD OF CURRENT TASK
;	R4=ADDRESS OF HEADER OF CURRENT TASK
;
; OUTPUTS:
;
;	R1=CURRENT UIC
;	R3=DEFAULT UIC
;		C=1 IF NONPRIVILEGED TASK IS TRYING TO CHANGE UIC
;		C=0 OTHERWISE
;-

	.IF DF	M$$MUP

$UISET::MOV	H.DUIC(R4),R3	;PROPAGATE DEFAULT UIC
	TST	R1		;UIC SPECIFIED?
	BEQ	10$		;IF EQ NO
	MOV	R1,R3		;USE SPECIFIED UIC
	BIT	#T3.PRV,2(R2)	;CURRENT TASK PRIVILEGED?
	BNE	20$		;IF NE YES
	CMP	R1,H.CUIC(R4)	;NONPRIVILEGED TASK CHANGING UI      C?
	BEQ	10$		;IF EQ NO
	SEC			;ELSE RETURN C-BIT SET
10$:	MOV	H.CUIC(R4),R1	;FORCE PROPAGATION OF CURRENT UIC
20$:	RETURN			;

	.ENDC


;+
; **-$MAPTK-MAP TASK ADDRESS WINDOW
;
; THIS ROUTINE IS CALLED TO MAP THE FIRST WINDOW BLOCK IN A TASK'S
; HEADER IN A MAPPED SYSTEM FROM ITS PCB AND TCB.
;
; INPUTS:
;
;	R1=POINTER TO NUMBER OF WINDOW BLOCKS IN THE TASK HEADER.
;	R5=ADDRESS OF THE TASK CONTROL BLOCK FOR THE TASK.
;
; OUTPUTS:
;
;	R1=ADDRESS OF LAST PDR IMAGE IN TASK HEADER.
;	R2 I      S MODIFIED.
;	R3 IS PRESERVED.						;MSH096
;-


	.IF DF	M$$MGE

$MAPTK::TST	(R1)+		;POINT TO TASK WINDOW BLOCK
	MOV	T.PCB(R5),R2	;PICK UP TASK PCB ADDRESS
	MOV	R2,(R1)+	;SET TASK PCB ADDRESS (W.BPCB)


	.IF DF	P$$LAS

	BIT	#T3.ROV,T.ST3(R5) ;TASK HAVE RESIDENT OVERLAYS?
	BNE	20$		;IF NE YES, DON'T CHANGE WINDOW BLOCK

	.IFTF

	MOV	(R1)+,(R1)	;INIT HIGH VIRT ADDR (W.BLVR)(W.BHVR)
	MOV	P.SIZE(R2),R2	;PICK UP PARTITION SIZE
									;MSH096
	.IFF								;MSH096
									;MSH096
	.IF DF      	A$$HDR							;MSH096
									;MSH096
	MOV	R3,-(SP)	;PRESERVE R3				;MSH096
	CLR	R3		;INITIALIZE WINDOW OFFSET		;MSH096
	BIT	#T2.CHK,T.ST2(R5) ;TASK HAVE ALTERNATE HEADER AREA	;MSH096
	BNE	5$		;IF NE NO, NONCHECKPOINTABLE TASK	;MSH096
	MOVB	T.HDLN(R5),R3	;GET ALTERNATE HEADER REFRESH AREA LNGTH;MSH096
	SUB	R3,R2		;REDUCE BY ALT. HDR REFRESH AREA LENGTH	;MSH096
5$:									;MSH096
	.ENDC								;MSH096

	.IFT

	SUB	T.OFF(R5),R2	;REDUCE BY TASK OFFSET IN PARTITION

	.IFTF

	MOV	R2,-(SP)	;PUS      H REQUIRED WINDOW SIZE
	SWAB	(SP)		;CONVERT TO BYTES
	RORB	(SP)		;
	ROR	(SP)		;
	ROR	(SP)		;
	ADD	(SP)+,(R1)	;COMPLETE HIGH VIRTUAL ADDRESS (W.BHVR)
	DEC	(R1)+		;

	.IF DF	P$$LAS!A$$HDR						;MSH096
									;**-1
	TST	(R1)+		;POINT TO WINDOW SIZE (W.BATT)
	MOV	R2,(R1)+	;SET WINDOW SIZE (W.BSIZ)
									;MSH096
	.IF DF	P$$LAS							;MSH096
									;MSH096
	MOV	T.OFF(R5),(R1)+	;SET OFFSET IN PARTITION (W.BOFF)
									;MSH096
	.IFF								;MSH096
									;MSH096
	MOV	R3,(R1)+	;SET OFFS      ET IN PARTITION (W.BOFF)	;MSH096
									;MSH096
	.ENDC								;MSH096
									;MSH096
	INC	R1		;POINT TO NUMBER OF PDR'S

	.IFF

	ADD	#W.BNPD-W.BATT,R1 ;POINT TO NUMBER OF PDR'S BYTE
									;MSH096
	.ENDC	;P$$LAS!A$$HDR						;MSH096
									;MSH096
	.IFF								;MSH096
									;MSH096
	.IF DF	A$$HDR							;MSH096
									;MSH096
	MOV	(SP)+,R3	;RESTORE CONTENTS OF R3			;MSH096
									;MSH096
	.ENDC								;MSH096

	.IFTF

	ASL	R2		;SHIFT # PDR'S TO HIGH BYTE
	SWAB	R2		;# PDR'   ¶  S TO LO BYTE, LAST PDR SIZE TO HI
	SUB	#377,R2		;INC # PDR'S & DEC LAST PDR SIZE
	SBC	R2		;IF CS, EVEN BOUNDARY, REDUCE # PDR'S
	MOVB	R2,(R1)+	;SET NUMBER OF PDR'S (W.BNPD)
	ROR	R2		;ADJUST CORRECT SIZE
	MOV	R2,(R1)		;SET SIZE FOR LAST PDR (W.BLPD)
	MOVB	#6,(R1)		;SET FOR READ/WRITE ACCESS (W.BLPD)
10$:	RETURN			;

	.IFT

20$:	ADD	#W.BLPD-W.BLVR,R1 ;POINT TO LAST WORD OF WINDOW BLOCK
	RETURN

	.ENDC

	.ENDC

	.END
 ¶         «:�ƒkQ	› c,        	.TITLE	IOSUB
	.IDENT	/11.49/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 11.49
;
; D. N. CUTLER 4-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	C. SPITZ
;	M. S. HARVEY
;	B. S. MCCARTHY
;	B. A. O'CONNELL
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-JUN-79      
;		MSH037 -- CLEAN UP COMMENTS A BIT.
;
;	M. S. HARVEY	25-JUL-79
;		MSH046 -- IMPLEMENT ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	15-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	25-OCT-79
;		MSH070 -- ALLOW LOAD OVERLAYS FOR TASKS INSTALLED FROM
;			  AN UNMOUNTED DISK, EVEN IF ANOTHER TASK HAS
;			  THE DISK ATTACHED.
;
;	M. S. HARVEY	19-DEC-79
;		MSH073 -- CORRECT NORMALIZATION CONSTANT
;
;	M. S. HARVEY	7-APR-80
;		MSH090 -- REMOVE UNNECESSARY R      ESTRICTIONS ON BUFFERED I/O
;
;	M. S. HARVEY	30-JUN-80
;		MSH091 -- USE KERNEL AST SYMBOL
;
;	M. S. HARVEY	20-AUG-80
;		MSH096 -- ADD ALTERNATE HEADER REFRESH SUPPORT
;
;	M. S. HARVEY	21-AUG-80
;		MSH112 -- SPLIT IOSUB INTO THE FOLLOWING MODULES:
;				IOSUB - GENERAL I/O FUNCTIONS
;				MDSUB - MASS STORAGE DRIVER FUNCTIONS
;				MEMAP - MEMORY MAPPING FUNCTIONS
;				EXESB - EXEC-I/O FUNCTIONS
;
;	M. S. HARVEY	8-SEP-80
;		MSH114 -- REMOVE SCS-11 SPECIFIC CODE
; 
; 	C. H. FRANKS	18-NOV-80
;       		CHF020 -- ADD SOFTWARE WRITE LOCK TO $GTPKT
;
;	R. T. PERRON	21-NOV-80
;		RP041 -- CHANGE INTERFACE TO COMMON ECC ROUTINE
;
;	DAN BROWN	7-JAN-81
;		DTB006 -- MODIFY FOR NEW ERROR LOG INTERFACE
; 
; 	C. H. FRANKS	20-FEB-81
; 		CHF021 -- CONDITIONALIZE SOFTWARE WRITE LOCK
; 
; 	C. H. FRANKS	11-MAR-81
; 		CHF023 -- MOVE SOFTWARE WRITE LOCK FROM $GTPKT TO $DRQIO
;
;	R. T. PERRON	13-MAR-81
;		RP053 -- CHANGE CONDITIONALIZATION OF $GTPKT/$GSPKT FOR 
;			 UDA50 SUPPORT
;
;	P. J. BEZEREDI 05-MAY      -81
;		PB241 -- ENHANCE ERROR LOG FUNCTIONALITY.
;
;	M. S. HARVEY	7-MAY-81
;		MSH169 -- ALLOW TASKS TO BE SHUFFLED IF NECESSARY
;			  AFTER BUFFERING AN I/O REQUEST
;
;	M. S. HARVEY	18-MAY-81
;		MSH170 -- ADD CODE TO TRAP DIVERGENT I/O PROCESSING
;
;	M. S. HARVEY	17-JUN-81
;		MSH164 -- ALLOW QUEUE FLUSH FOR FOREIGN MOUNTED
;			  DEVICES WITH NO ASSOCIATED ACP
;
;	T. M. MARTIN	16-DEC-81
;		TMM087 -- ALLOW CLI TASKS WHICH MAY BE NON-PRIV
;			  TO BREAK-THRU ATTACHES
;
;
;
; I/O RELATED ROU      TINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,HWDDF$,PCBDF$,PKTDF$,TCBDF$,EPKDF$		;MSH112
	EPKDF$			;DEFINE ERROR PACKET OFFSETS		;DTB006
	HDRDF$			;DEFINE TASK HEADER OFFSETS		;**-2
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

									;**-260
;+
; **-$GTPKT-GET I/O PACKET FROM REQUEST QUEUE
; **-$GSPKT-GET SELECTIVE I/O PACKET FROM REQUEST QUEUE
;
; THIS ROUTINE       IS CALLED BY DEVICE DRIVERS TO DEQUEUE THE NEXT I/O REQUEST TO
; PROCESS. IF THE DEVICE CONTROLLER IS BUSY, THEN A CARRY SET INDICATION IS
; RETURNED TO THE CALLER. ELSE AN ATTEMPT IS MADE TO DEQUEUE THE NEXT REQUEST
; FROM THE CONTROLLER QUEUE. IF NO REQUEST CAN BE DEQUEUED, THEN A CARRY
; SET INDICATION IS RETURNED TO THE CALLER. ELSE THE CONTROLLER IS SET BUSY AND
; A CARRY CLEAR INDICATION IS RETURNED TO THE CALLER.
;
; THE ALTERNATE ENTRY POINT $GSPKT IS INTENDED FOR USE BY DRIVERS WHICH
; SUPP      ORT PARALLEL OPERATIONS ON A SINGLE UNIT, A COMMON EXAMPLE BEING
; FULL DUPLEX.  SUCH DRIVERS ARE EXPECTED TO LOOK TO THE SYSTEM AS IF
; THEY ARE ALWAYS FREE, WHILE MAINTAINING THE STATUS OF ALL PARALLEL
; OPERATIONS INTERNALLY WITHIN THEIR OWN DEVICE DATA STRUCTURES.
; PARALLELISM IS ACCOMPLISHED BY HANDLING DRIVER-DEFINED CLASSES OF I/O
; FUNCTION CODES IN PARALLEL WITH EACH OTHER.  FOR EXAMPLE A FULL-DUPLEX
; DRIVER WOULD HANDLE INPUT REQUESTS IN PARALLEL WITH OUTPUT REQUESTS.
; A DRIVER CALLS $GS      PKT WHEN IT WANTS TO DEQUEUE A PACKET WHOSE I/O
; FUNCTION CODE BELONGS TO A CERTAIN CLASS.  WHICH FUNCTIONS QUALIFY IS
; DETERMINED BY AN ACCEPTANCE ROUTINE IN THE DRIVER WHOSE ADDRESS IS
; PASSED TO $GSPKT IN R2.  THE ACCEPTANCE ROUTINE IS CALLED BY $GSPKT
; EACH TIME A PACKET IS FOUND IN THE QUEUE WHICH IS ELIGIBLE TO BE
; DEQUEUED.  THE ACCEPTANCE ROUTINE IS THEN EXPECTED TO TAKE ONE OF THE
; FOLLOWING THREE ACTIONS:
;
;	    1.	RETURN WITH CARRY CLEAR IF THE PACKET SHOULD BE
;		DEQUEUED.  IN TH      IS CASE $GSPKT PROCEEDS AS $GTPKT
;		NORMALLY WOULD ON DEQUEUEING THE PACKET.
;
;	    2.	RETURN WITH CARRY SET IF THE PACKET SHOULD NOT BE
;		DEQUEUED.  IN THIS CASE $GSPKT WILL CONTINUE THE SCAN
;		OF THE I/O QUEUE.
;
;	    3.	ADD THE CONSTANT G$$SPA TO THE STACK POINTER TO ABORT	;MSH037
;		THE SCAN WITH NO FURTHER ACTION.			;**-1
;
; THE ACCEPTANCE ROUTINE MUST SAVE AND RESTORE ANY REGISTERS WHICH IT
; INTENDS TO MODIFY.  WHEN A PACKET IS DEQUEUED VIA $GSPKT, THE
; FOLLOWING NORMAL $GTPKT ACTI      ONS DO NOT OCCUR:
;
;	    1.	FILLING IN OF U.BUF, U.BUF+2 AND U.CNT.  THESE FIELDS
;		ARE AVAILABLE FOR DRIVER-SPECIFIC USE.
;
;	    2.	BUSYING OF UCB AND SCB.
;
; INPUTS:								;**-3
;
;	R2=ADDRESS OF DRIVER'S ACCEPTANCE ROUTINE (IF CALL AT $GSPKT).
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO GET A PACKET FOR.
;
; OUTPUTS:
;
;	C=1 IF CONTROLLER IS BUSY OR NO REQUEST CAN BE DEQUEUED.
;	C=0 IF A REQUEST WAS SUCCESSFULLY DEQUEUED.
;		R1=ADDRESS OF THE I/O PACKET.
;		R2=PHYSICAL UNIT NUMBER.      
;		R3=CONTROLLER INDEX.
;		R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;		R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
;	NOTE: R4 AND R5 ARE DESTROYED BY THIS ROUTINE.
;-

	.ENABL	LSB

	.IF DF	A$$BIO!R$$UDA						; RP053
									;**-1
G$$SPA==4			;CONSTANT TO ADD TO SP TO ABORT SCAN

$GTPKT::MOV	#128$,R2	;ACCEPT ALL PACKETS
$GSPKT::MOV	R2,$TEMP2	;SAVE ADDRESS OF ACCEPTANCE ROUTINE
5$:	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB

	.IFF

$GTPKT::MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB

	.ENDC	;A$$BIO!R$$U      DA						; RP053
									;**-1
	TSTB	S.STS(R4)	;CONTROLLER BUSY?
	BNE	70$		;IF NE CONTROLLER IS BUSY


	.IF DF	E$$LOG							;DTB006
									;**-1
	BICB	#SP.EIP,S.PRI(R4) ;CLEAR ERROR IN PROGRESS

	.ENDC


	MOV	R4,R1		;SET POINTER TO I/O QUEUE LISTHEAD
10$:	MOV	R1,R0		;SAVE ADDRESS OF PREVIOUS PACKET
	MOV	(R0),R1		;GET ADDRESS OF NEXT PACKET
	BEQ	70$		;IF EQ NO MORE PACKETS TO SCAN
	MOV	I.UCB(R1),R5	;GET ADDRESS OF UNIT CONTROL BLOCK
	MOV	U.ATT(R5),R3	;UNIT ATTACHED?
	BEQ	20$		;IF EQ NO
      	CMP	#IO.LOV,I.FCN(R1) ;LOAD OVERLAY I/O FUNCTION?		;MSH070
	BNE	12$		;IF NE NO				;MSH070
	TST	U.CW1(R5)	;IS IT A MOUNTABLE DEVICE?		;MSH070
	BMI	20$		;IF MI YES, BREAK THRU ATTACH		;MSH070
12$:	MOV	I.TCB(R1),R2	;GET ADDRESS OF REQUESTOR TASK TCB	;MSH070
	BIT	#T3.PRV!T3.CLI,T.ST3(R2) ;TASK PRIVILEGED OR CLI?	;TMM087
	BEQ	15$		;IF EQ NO				;**-2


	.IF DF	D$$ISK

	CMP	R2,$LDRPT	;REQUESTING TASK THE LOADER?
	BEQ	20$		;IF EQ YES-ALWAYS BREAK THRU ATTACH

	.ENDC


	BIT	#DV.TTY,U.CW1(R5) ;DEVIC      E A TERMINAL?
	BEQ	15$		;IF EQ NO
	CMPB	#IO.WLB/256.,I.FCN+1(R1) ;WRITE LOGICAL FUNCTION	;**-8
	BEQ	20$		;IF EQ YES-BREAK THRU ATTACH
15$:	CMP	R2,R3		;IS THIS THE APPROPRIATE TASK?		;**-3
	BNE	10$		;IF NE NO

	.IF DF	A$$BIO!R$$UDA						; RP053
									;**-1
20$:	CALL	@$TEMP2		;CALL DRIVER ACCEPTANCE ROUTINE
	BCS	10$		;IF CS PACKET NOT ACCEPTED
	MOV	(R1),(R0)	;CLOSE UP LIST REMOVING ENTRY

	.IFF

20$:	MOV	(R1),(R0)	;CLOSE UP LIST REMOVING ENTRY

	.ENDC	;A$$BIO!R$$UDA						; RP053
									      ;**-1
	BNE	30$		;IF NE LAST ENTRY WAS NOT REMOVED
	MOV	R0,2(R4)	;SET ADDRESS OF NEW LAST IN LIST
30$:	MOV	R1,S.PKT(R4)	;SET ADDRESS OF CURRENT I/O PACKET
	MOVB	I.FCN+1(R1),R2	;GET I/O FUNCTION CODE
	CMPB	#IO.ATT/256.,R2	;ATTACH FUNCTION?
	BNE	40$		;IF NE NO


	.IF DF	A$$CPS

	MOV	#IE.PRI&377,R0	;ASSUME PRIVILEGE VIOLATION
	TST	U.CW1(R5)	;MOUNTABLE DEVICE?
	BPL	35$		;IF PL NO
	BITB	#US.MNT!US.FOR,U.STS(R5) ;NOT MOUNTED OR FOREIGN?
	BEQ	60$		;IF EQ NO

	.IFTF

35$:	MOV	I.TCB(R1),R0	;ASSUME       SUCCESSFUL ATTACH
	TST	R3		;UNIT ALREADY ATTACHED?


	.IF DF	D$$IAG

	BEQ	36$		;IF EQ NO

	.IFF

	BEQ	50$		;IF EQ NO

	.IFTF

	MOV	#IE.DAA&377,R0	;SET STATUS OF DEVICE ALREADY ATTACHED
	BR	60$		;


	.IFT

36$:	BITB	#IQ.UMD,I.FCN(R1) ;IS THIS A DIAGNOSTIC ATTACH?
	BEQ	50$		;IF EQ NO
	BIT	#DV.UMD,U.CW1(R5) ;USER MODE DIAGNOSTICS SUPPORTED?
	BEQ	37$		;IF EQ NO
	BISB	#US.UMD,U.ST2(R5) ;INDICATE DIAGNOSTIC ATTACH
	BR	50$		;
37$:	MOV	#IE.IFC&377,R0	;SET STATUS OF ILLEGAL FUNCTION
	BR	60      $		;

	.IFTF

40$:	CMPB	#IO.DET/256.,R2	;DETACH FUNCTION
	BNE	80$		;IF NE NO
	MOV	#IE.DNA&377,R0	;ASSUME DEVICE NOT ATTCHED
	TST	R3		;UNIT ATTACHED?
	BEQ	60$		;IF EQ NO
	CLR	R0		;SET TO DETACH UNIT

	.IFT

	BICB	#US.UMD,U.ST2(R5) ;RESET DIAGNOSTIC BIT

	.ENDC


50$:	MOV	R0,U.ATT(R5)	;ATTACH/DETACH UNIT
	BITB	#UC.ATT,U.CTL(R5) ;DOES DRIVER WANT CONTROL ON ATTACH/DETACH?
	BNE	120$		;IF NE YES
	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS
60$:	CALL	$IOALT		;FINISH I/O OPERATION
      
	.IF DF	A$$BIO!R$$UDA						; RP053
									;**-1
65$:	BR	5$		;GO AGAIN

	.IFF

65$:	BR	$GTPKT		;GO AGAIN

	.ENDC	;A$$BIO!R$$UDA						; RP053
									;**-1
70$:	SEC			;SET CONTROLLER BUSY OR NO REQUEST
	BR	130$		;
80$:				;REF LABEL

	.IFT

	TST	U.CW1(R5) 	;DEVICE MOUNTABLE?
	BPL	120$		;IF PL NO


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;IS THIS A DIAGNOSTIC FUNCTION?
	BNE	120$		;IF NE YES, IT CAN'T BE AN ACP FUNCTION

	.ENDC

;
; DETERMINE IF FUNCTION IS ACP FUNCTION
;	APPLI      CABLE TO ALL MOUNTED DEVICES - NATIVE AND FOREIGN
;	FILES 11 - MAPPING OF VIRTUAL TO LOGICAL NOW DONE BY
;		DRQIO.  ONLY VIRTUAL & ACP FUNCTIONS THAT
;		NEED CORRECT SEQUENCING ARE ROUTED THRU DRIVER.
;
	MOV	U.ACP(R5),R0	;GET ADDRESS OF ACP
	BEQ	120$		;NO ACP - PASS IT ON TO DRIVER
;
;	NATIVE REQUESTS ARE ROUTED TO THE ACP IF THE FCTN CODE > 7.
;	THIS IS REQUIRED BECAUSE IO.CLN IS NOT CURRENTLY DEFINED
;	IN DCB BITS.  HOPEFULLY THIS WILL BE FIXED.
;

	BITB	#US.MNT!US.FOR,U.STS(R5)	;MOUNTED NATI      VE?
	BNE	85$		;BRANCH IF MOUNTED FOREIGN
	CMP	#7,R2		;NATIVE-IS IT ACP FCTN?
	BHI	120$		;IF HI NO -DRIVER FCTN
	BR	95$		;ACP
85$:	MOV	(R5),R3		;GET DCB ADDRESS
	CMP	R2,#15.		;NORMALIZE FCTN CODE
	BLOS	90$		;
	SUB	#16.,R2		;NORMALIZE				;MSH073
	ADD	#10,R3		;ADJUST PTR TO 2ND MASK SET		;**-1
90$:	ASL	R2		;CONVERT TO WORD INDEX
	BIT	$BTMSK(R2),D.MSK+6(R3)	;IS IT ACP FUNCTION?
	BEQ	120$		;NO - DRIVER
95$:				;
	CALL	$EXRQP		;INSURE FILE SYSTEM IS ACTIVE
	BR	65$		;GO AGAIN


	.ENDC


	.IF D      F	A$$BIO!R$$UDA						; RP053
									;**-1
120$:	CMP	$TEMP2,#128$	;$GSPKT CALL?
	BNE	127$		;IF NE YES, SKIP TO DRIVER CALL

	.IFF

120$:

	.ENDC	;A$$BIO!R$$UDA						; RP053
									;**-1
	MOV	I.PRM(R1),U.BUF(R5) ;INSERT RELOCATION BIAS IN UCB
	MOV	I.PRM+2(R1),U.BUF+2(R5) ;INSERT BUFFER ADDRESS IN UCB
	MOV	I.PRM+4(R1),U.CNT(R5) ;INSERT BYTE COUNT IN UCB
126$:	INCB	S.STS(R4)	;SET CONTROLLER BUSY
	BISB	#US.BSY,U.STS(R5) ;SET UNIT BUSY
127$:	MOVB	S.CON(R4),R3	;GET CONTROLLER INDEX
	MOVB	U.UNI      T(R5),R2	;SET PHYSICAL UNIT NUMBER
									;DTB006
	.IF DF	E$$LOG							;DTB006
									;DTB006
	BIT	#DV.MSD,U.CW1(R5) ;IS IT A MASS STORAGE DEVICE?		;DTB006
	BEQ	128$		;IF EQ NOT A MASS STORAGE DEVICE	;DTB006
	ADD	#1,U.IOC(R5)	;COUNT ANOTHER I/O			;DTB006
	ADC	U.IOC+2(R5)	; AND INCREMENT THE HIGH ORDER		;DTB006
									;DTB006
	.ENDC								;DTB006
									;DTB006
128$:	CLC			;INDICATE PACKET BEING RETURNED
130$:	RETURN			;

	.DSABL	LSB


	.IF DF	A$$BIO							;MSH046
									;**-1
;      +
; **-$TSTBF-TEST IF I/O BUFFERING CAN BE INITIATED
;
; THIS ROUTINE DETERMINES IF A GIVEN I/O REQUEST IS ELIGIBLE FOR I/O
; BUFFERING, AND IF SO (FOR SYSTEMS THAT SUPPORT SYSTEM-CONTROLLED	;MSH046
; PARTITIONS) IT STORES THE PCB ADDRESS OF THE REGION INTO WHICH	;MSH046
; THE TRANSFER IS TO OCCUR IN I.PRM+16 OF THE I/O PACKET.		;MSH046
;									;**-2
; INPUTS:
;
;	R3=ADDRESS OF I/O PACKET FOR I/O REQUEST
;
; OUTPUTS:
;
;	R3 IS PRESERVED.
;
;	C=0 IF I/O BUFFERING CAN BE INITIATED.
;
;	C=1       IF I/O BUFFERING CAN NOT BE INITIATED.
;-

$TSTBF::MOV	I.TCB(R3),R0	;GET ADDRESS OF REQUESTOR TCB
	SEC			;ASSUME TASK CANNOT BE STOPPED?
	BIT	#T2.CHK!T2.CKD,T.ST2(R0) ;STOP IT?			;MSH090
	BNE	20$		;IF NE NO				;**-1
									;MSH046
	.IF DF	M$$MGE&D$$YNM						;MSH046
									;MSH046
	SAVNR			;SAVE R4 AND R5
	MOV	T.PCB(R0),R1	;GET ADDRESS OF REQUESTER HEADER
	MOV	P.HDR(R1),R1	;
	MOV	H.WND(R1),R1	;POINT TO NUMBER OF WINDOW BLOCKS
	MOV	(R1)+,R2	;GET COUNT OF WINDOWS
10$:	SEC			;ASSUME NO MORE       WINDOWS
	DEC	R2		;ANY MORE WINDOWS TO EXAMINE?
	BLT	20$		;IF LT NO, DON'T CHECKPOINT
	MOV	(R1)+,R4	;GET ADDRESS OF DESCRIPTOR PCB
	BEQ	30$		;IF EQ WINDOW NOT MAPPED
	MOV	(R1)+,-(SP)	;GET LOW VIRTUAL ADDRESS
	MOV	(R1)+,R5	;GET HIGH VIRTUAL ADDRESS
	SUB	(SP),R5		;CALCULATE NUMBER OF BYTES MINUS 1
	SUB	#77,R5		;REDUCE TO ACTUAL NUMBER OF BYTES - 64B
	ASL	R5		;CONVERT TO 32W BLOCKS
	ROL	R5		;
	ROLB	R5		;
	SWAB	R5		;
	MOV	P.REL(R4),(SP)	;GET RELOCATION BIAS OF PCB


	.IF DF	P$$LAS!A$$HDR						;MS      H096
									;**-1
	ADD	W.BOFF-W.BATT(R1),(SP) ;ADD IN OFFSET IN PARTITION

	.ENDC


	ADD	(SP),R5		;CALCULATE HIGHEST 32W BLOCK
	ADD	#W.BLGH-W.BATT,R1 ;POINT TO NEXT DESCRIPTOR
	CMP	I.PRM(R3),(SP)+ ;TRANSFER IN THIS PARTITION?
	BLO	10$		;IF LO NO
	CMP	R5,I.PRM(R3)	;TRANSFER IN THIS PARTITION?
	BLO	10$		;IF LO NO
	MOV	R4,I.PRM+16(R3)	;STORE PCB ADDRESS IN I/O PACKET
									;MSH046
	.IFF	;M$$MGE&D$$YNM						;MSH046
									;MSH046
	CLC			;I/O BUFFERING CAN BE INITIATED		;MSH046
									      ;MSH046
	.IFTF								;MSH046
									;MSH046
20$:	RETURN			;
									;MSH046
	.IFT								;MSH046
									;MSH046
30$:	ADD	#W.BLGH-W.BLVR,R1 ;POINT TO NEXT WINDOW BLOCK
	BR	10$		;					;MSH046
									;MSH046
	.IFTF								;MSH046
									;**-1

;+
; **-$INIBF-INITIATE I/O BUFFERING
;
; THIS ROUTINE INITIATES I/O BUFFERING BY DOING THE FOLLOWING:
;
;	    1.	DECREMENT THE TASK'S I/O COUNT.
;	    2.	INCREMENT THE TASK'S BUFFERED I/O COUNT.		;MSH046
;	    3.	INITIATE CHECKPOINTING IF A       REQUEST IS PENDING.		;MSH046
;	    4.	REENABLE SHUFFLING OF THE TASK				;MSH169
;									;**-6
; INPUTS:
;
;	R3=ADDRESS OF I/O PACKET FOR I/O REQUEST.
;
; OUTPUTS:
;
;	R3 IS PRESERVED.
;-

$INIBF::MOV	R5,-(SP)	;SAVE R5				;MSH046
	MOV	I.TCB(R3),R5	;POINT TO ISSUING TASK'S TCB		;MSH046
	INCB	T.TIO(R5)	;TALLY THE BUFFERED I/O			;MSH046
	DECB	T.IOC(R5)	;ADJUST OUTSTANDING I/O REQUEST COUNT	;MSH046
									;MSH046
	.IFT								;MSH046
									;MSH046
	MOV	I.PRM+16(R3),R1	;GET PCB				;**-4      
	SUB	P.REL(R1),I.PRM(R3) ;CONVERT TO RELATIVE RELOCATION BIAS
									;MSH046
	.ENDC	;M$$MGE&D$$YNM						;MSH046
									;**-1
	.IF DF	D$$ISK&C$$CKP						;MSH046
									;**-1
	BIT	#TS.CKR,T.STAT(R5) ;CHECKPOINT REQUEST PENDING?		;MSH046
	BEQ	20$		;IF EQ NO				;**-1
	BIC	#TS.CKR,T.STAT(R5) ;CLEAR CHECKPOINT REQUEST		;MSH046
	MOV	R5,R1		;COPY TCB ADDRESS			;MSH046
	MOV	R3,-(SP)	;SAVE PACKET ADDRESS			;MSH046
									;MSH169
	.IF DF	D$$YNM&D$$SHF						;MSH169
									;MSH169
	MOV	R5,-(SP)      	;SAVE THE TCB ADDRESS			;MSH169
									;MSH169
	.IFTF								;MSH169
									;MSH169
	CALL	$ICHKP		;INITIATE CHECKPOINT OF TASK		;MSH169
									;MSH169
	.IFT								;MSH169
									;MSH169
	MOV	(SP)+,R5	;RESTORE TCB ADDRESS			;MSH169
	TSTB	T.IOC(R5)	;I/O COUNT NOW ZERO?			;MSH169
	BNE	15$		;IF NE NO				;MSH169
	MOV	T.PCB(R5),R0	;GET TASK'S PCB ADDRESS			;MSH169
	BIT	#PS.LIO,P.STAT(R0) ;DID SHUFFLER DETECT LONG I/O?	;MSH169
	BEQ	15$		;IF EQ NO				;MSH169
	BIC	#PS.LIO,P.STAT(R0) ;CLEAR LO      NG I/O BIT			;MSH169
	CALL	$NXTSK		;REALLOCATE PARTITION			;MSH169
									;MSH169
	.ENDC								;MSH169
									;MSH169
15$:	MOV	(SP)+,R3	;RESTORE PACKET ADDRESS IN R3		;MSH046
									;**-5
	.ENDC

20$:	MOV	(SP)+,R5	;RESTORE R5				;MSH046
	RETURN			;					;**-2

;+
; **-$QUEBF-QUEUE BUFFERED I/O FOR COMPLETION
;
; THIS ROUTINE QUEUES A SPECIAL ENTRY TO A TASK'S AST QUEUE TO COMPLETE
; A BUFFERED I/O REQUEST THE NEXT TIME THE TASK IS SCHEDULED.  IT ALSO
; DECREMENTS THE TASK'S BUFFERED I      /O COUNT.				;MSH046
;									;**-1
; NOTE: THIS ROUTINE IS EQUIVALENT TO CALLING $IOFIN AND IT DOES NOT
;	UNBUSY THE DEVICE.
;
; INPUTS:
;
;	R0=FIRST WORD OF I/O STATUS
;	R1=SECOND WORD OF I/O STATUS
;	R3=ADDRESS OF I/O PACKET
;
; OUTPUTS:
;
;	NONE
;-

$QUEBF::MOV	R0,I.PRM+6(R3)	;STORE OFFSPRING I/O RETURN STATUS
	MOV	R1,I.PRM+10(R3)	;
	MOV	I.TCB(R3),R0	;PICK UP OFFSPRING TCB ADDRESS
	BIC	#TS.RDN,T.STAT(R0) ;CLEAR RUNDOWN IN PROG
	MOV	R0,R2		;COPY TCB ADDRESS
	ADD	#T.ASTL,R2	;POINT TO       AST LISTHEAD
	MOV	(R2),(R3)	;LINK PACKET TO FRONT OF LIST
	BNE	10$		;
	MOV	R3,2(R2)	;
10$:	MOV	R3,(R2)		;
	MOVB	#AK.BUF,A.CBL(R3) ;SET BUFFERED I/O KERNEL AST TYPE	;MSH091
	DECB	T.TIO(R0)	;DECREMENT BUFFERED I/O COUNT		;MSH046
	BIT	#T2.WFR,T.ST2(R0) ;TASK STOPPED FOR BUFFERED I/O?	;MSH046
	BNE	12$		;IF NE YES				;MSH046
	CALLR	$SETCR		;SET CONDITIONAL SCHEDULE REQUEST	;MSH046
									;MSH046
12$:	CALLR	$EXRQU		;UNSTOP TASK AND RETURN			;MSH046
									;**-3
	.ENDC	;A$$BIO							;MSH046
				      					;**-1
									;**-59

;+
; **-$IOALT-I/O DONE (ALTERNATE ENTRY)
; **-$IODON-I/O DONE
;
; THIS ROUTINE IS CALLED BY DEVICE DRIVERS AT THE COMPLETION OF AN I/O REQUEST
; TO DO FINAL PROCESSING. THE UNIT AND CONTROLLER ARE SET IDLE AND $IOFIN IS
; ENTERED TO FINISH THE PROCESSING.
;
; INPUTS:
;
;	R0=FIRST I/O STATUS WORD.
;	R1=SECOND I/O STATUS WORD.
;	R2=STARTING AND FINAL ERROR RETRY COUNTS IF ERROR LOGGING
;		DEVICE.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK OF THE UNIT BEING COMPLETED.      
;	(SP)=RETURN ADDRESS TO DRIVER'S CALLER.
;
;	NOTE: IF ENTRY IS AT $IOALT, THEN R1 IS CLEAR TO SIGNIFY THAT THE
;		SECOND STATUS WORD IS ZERO.
;
; OUTPUTS:
;
;	THE UNIT AND CONTROLLER ARE SET IDLE.
;
;	R3=ADDRESS OF THE CURRENT I/O PACKET.
;-

$IOALT::CLR	R1		;ZERO SECOND I/O STATUS WORD
$IODON::MOV	U.SCB(R5),R4	;GET ADDRESS OF STATUS CONTROL BLOCK
	BICB	#US.BSY,U.STS(R5) ;CLEAR UNIT BUSY
	CLRB	S.STS(R4)	;CLEAR CONTROLLER BUSY


	.IF DF	E$$LOG							;DTB006
									;**-1
	BITB	#SP.EIP,      S.PRI(R4) ;ERROR IN PROGRESS?
	BEQ	15$		;IF EQ NO
	MOV	R1,-(SP)	;SAVE SECOND I/O STATUS WORD
	CALL	$FNERL		;FINISH ERROR LOGGING PROCESS		; PB241
	MOV	(SP)+,R1	;RESTORE I/O STATUS CODE		; PB241
15$:				;REF LABEL				;**-10

	.ENDC


	.IF DF	M$$EXT

	BITB	#UC.NPR,U.CTL(R5) ;IS IT AN NPR DEVICE?
	BEQ	20$		;IF EQ NO, DOES NOT USE UMR'S
	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP041
	BNE	20$		;IF NE YES				;**-1
	MOV	R4,R2		;COPY SCB POINTER
	ADD	#S.MPR,R2	;POINT TO MAPPING A      SSIGNMENT BLOCK
	CALL	$DEUMR		;DEASSIGN ANY UMR'S
	MOV	#$DQUMR,-(SP)	;PUSH ADDRESS TO CHECK FOR UMR WAIT

	.ENDC


20$:	MOV	S.PKT(R4),R3	;RETRIEVE ADDRESS OF I/O PACKET


	.IF DF	Q$$OPT

	TST	(R4)		;ANY OTHER I/O REQUESTS TO INITIATE?
	BEQ	$IOFIN		;IF EQ NO
	MOV	R3,R4		;COPY I/O PACKET POINTER
	ADD	#I.PRM+14,R4	;POINT TO LAST WORD FOR FORK BLOCK
	MOV	R0,(R4)		;STORE I/O STATUS BLOCK CONTENTS
	MOV	R1,-(R4)	;
	CALL	$FORK0		;FORK HERE TO ALLOW NEXT I/O INITIATION
	MOV	R4,R0		;RESTORE I/O STA      TUS BLOCK CONTENTS
	MOV	R5,R1		;
	SUB	#I.PRM+10,R3	;POINT TO BEGINNING OF FORK BLOCK

	.ENDC


;+
; **-$IOFIN-I/O FINISH
;
; THIS ROUTINE IS CALLED TO FINISH I/O PROCESSING IN CASES WHERE THE UNIT AND
; CONTROLLER ARE NOT TO BE DECLARED IDLE.
;
; INPUTS:
;
;	R0=FIRST I/O STATUS WORD.
;	R1=SECOND I/O STATUS WORD.
;	R3=ADDRESS OF THE I/O REQUEST PACKET.
;
; OUTPUTS:
;
;	THE FOLLOWING ACTIONS ARE PERFORMED
;
;	1-THE FINAL I/O STATUS VALUES ARE STORED IN THE I/O STATUS BLOCK IF
;		ONE WA      S SPECIFIED.
;
;	2-THE I/O COUNT IS DECREMENTED AND TS.RDN IS CLEARED IN CASE
;		THE TASK WAS BLOCKED FOR I/O RUNDOWN.
;
;	3-IF 'TS.CKR' IS SET, THEN IT IS CLEARED AND CHECKPOINTING OF
;		THE TASK IS INITIATED.
;
;	4-IF AN AST SERVICE ROUTINE WAS SPECIFIED, THEN AN AST IS QUEUED
;		FOR THE TASK. ELSE THE I/O PACKET IS DEALLOCATED.
;
;	5-A SIGNIFICANT EVENT OR EQUIVALENT IS DECLARED.
;
;	NOTE: R4 IS DESTROYED BY THIS ROUTINE.
;-

$IOFIN::			;					;MSH170
									;MSH170
	.IF DF	A$$TRP&R$$D      ER						;MSH170
									;MSH170
	CMP	I.TCB(R3),#8.*2	;PACKET CONVERTED TO AST CONTROL BLOCK?	;MSH170
	BNE	5$		;IF NE NO				;MSH170
	CRASH			;DOUBLE PROCESSING OF I/O PACKET	;MSH170
									;MSH170
	.ENDC								;MSH170
									;MSH170
5$:	MOV	I.IOSB+4(R3),R2	;GET ADDRESS OF I/O STATUS BLOCK	;MSH170
	BEQ	10$		;IF EQ NO I/O STATUS BLOCK SPECIFIED	;**-1


	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING
	MOV	I.IOSB+2(R3),KISAR6 ;MAP TO I/O STATUS BLOCK

	.IFTF

	MOV	R0,(R2)+	;SET F      INAL I/O STATUS VALUES
	MOV	R1,(R2)		;

	.IFT

	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.ENDC


10$:	MOV	I.TCB(R3),R1	;GET ADDRESS OF TASK CONTROL BLOCK
	MOV	R1,R2		;POINT TO FIRST TASK STATUS WORD
	ADD	#T.STAT,R2	;
	DECB	T.IOC(R1)	;DECREMENT I/O REQUEST COUNT
	BIC	#TS.RDN,(R2)	;FREE TASK IF I/O RUNDOWN IS IN PROGRESS


	.IF DF	R$$LKL

	MOV	I.PRM+16(R3),R0	;PICK UP LOCK BLOCK ADDRESS
	BEQ	20$		;IF EQ THERE IS NONE
	CMP	R0,#140000	;IS IT A RELOCATED USER ADDRESS?
	BHIS	20$		;IF HIS       YES
	DEC	(R0)		;FREE LOCK FOR UNLOCKING
20$:				;REF LABEL

	.ENDC


	.IF DF	C$$CKP&D$$ISK

	MOV	R3,R4		;SAVE PACKET ADDRESS
	BIT	#TS.CKR,(R2)	;CHECKPOINT REQUESTED?
	BEQ	30$		;IF EQ NO
	BIC	#TS.CKR,(R2)	;CLEAR CHECKPOINT REQUEST FLAG
	CALL	$ICHKP		;INITIATE TASK CHECKPOINTING
30$:				;REF LABEL


	.IF DF	D$$YNM&D$$SHF

	MOV	I.TCB(R4),R1	;PICK UP ISSUING TASK'S TCB ADDRESS
	MOV	T.PCB(R1),R0	;POINT TO TASK PCB
	BIT	#PS.LIO,P.STAT(R0) ;DID SHUFFLER DETECT A LONG I/O?
	BEQ	35$		;IF EQ NO      
	TSTB	T.IOC(R1)	;IS I/O COUNT NOW ZERO?
	BNE	35$		;IF NE NO
	BIC	#PS.LIO,P.STAT(R0) ;CLEAR LONG I/O BIT
	CALL	$NXTSK		;REALLOCATE PARTITION
35$:				;REF LABEL

	.ENDC


	MOV	R4,R3		;RESTORE PACKET ADDRESS

	.ENDC


	MOV	R5,-(SP)	;SAVE UCB ADDRESS
	MOV	I.TCB(R3),R5	;SET TCB ADDRESS
	MOVB	I.EFN(R3),R0	;GET EVENT FLAG NUMBER
	CALL	$SETFG		;SET EFN AND UNLOCK IF GROUP GLOBAL	;MSH049
	MOV	R3,R0		;COPY I/O PACKET ADDRESS		;**-1


	.IF DF	A$$TRP

	TST	(R3)+		;POINT TO SECOND WORD
	MOV	#I.L      GTH,(R3)+	;INSERT LENGTH OF BLOCK IN BYTES
	MOV	#8.*2,(R3)+	;SET NUMBER OF BYTES TO ALLOCATE ON USER STACK
	MOV	I.AST(R0),(R3)+	;INSERT AST ADDRESS
	BEQ	70$		;IF EQ NONE SPECIFIED
	MOV	#1,(R3)+	;INSERT NUMBER OF AST PARAMETERS
	MOV	I.IOSB(R0),(R3)	;INSERT VIRTUAL ADDRESS OF I/O STATUS BLOCK
	MOV	R0,R1		;COPY ADDRESS OF I/O PACKET
	MOV	R5,R0		;CALCULATE ADDRESS OF AST LISTHEAD
	ADD	#T.ASTL,R0	;
	CALL	$QINSF		;INSERT AST IN QUEUE
	MOV	R5,R0		;COPY TCB ADDRESS
	CALL	$SETCR		;SET A SCHEDULE REQUEST F      OR THE TASK
	BR	80$		;

	.ENDC


70$:	CALL	$DEPKT		;DEALLOCATE I/O PACKET
80$:	MOV	(SP)+,R5	;RESTORE UCB ADDRESS
	RETURN			;

;+
; **-$IOKIL-I/O KILL
;
; THIS ROUTINE IS CALLED TO FLUSH ALL I/O REQUESTS FOR THE CURRENT TASK FROM
; A DEVICE QUEUE AND TO CANCEL THE CURRENT I/O OPERATION IN PROGRESS IF IT
; IS ALSO FOR THE CURRENT TASK.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE DEVICE TO FLUSH REQUESTS FOR.
;
; OUTPUTS:
;
;	IF THE SPECIFIED DEVICE IS NOT FILE STRUCTURED, THEN THE I/O       RE-
;	REQUEST QUEUE IS FLUSHED AND THE CURRENT I/O OPERATION IN PROGRESS
;	IS CANCELLED.
;
;	NOTE: R4 IS DESTROYED BY THIS ROUTINE.
;-

$IOKIL::MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOV	$TKTCB,R1	;GET TCB ADDRESS OF CURRENT TASK
	TST	U.CW1(R5)	;DEVICE-UNIT MOUNTABLE?
	BPL	10$		;IF PL NO
	BITB	#US.MNT,U.STS(R5) ;DEVICE-UNIT MOUNTED?
									;MSH164
	.IF DF	A$$CPS							;MSH164
									;MSH164
	BNE	10$		;IF NE NO, FLUSH I/O QUEUE		;MSH164
	TST	U.ACP(R5)	;ACP ASSOCIATED WITH DEVICE?		;MSH164      
	BNE	40$		;IF NE YES, CAN'T FLUSH QUEUE		;MSH164
									;MSH164
	.IFF								;MSH164
									;MSH164
	BEQ	40$		;IF EQ YES
									;MSH164
	.ENDC								;MSH164
									;MSH164
10$:	MOV	R4,R3		;COPY ADDRESS OF I/O QUEUE LISTHEAD
20$:	MOV	R3,R2		;SAVE ADDRESS OF CURRENT ENTRY
	MOV	(R2),R3		;GET ADDRESS OF NEXT ENTRY
	BEQ	40$		;IF EQ END OF LIST
	CMP	R1,I.TCB(R3) 	;REQUEST FOR CURRENT TASK?
	BNE	20$		;IF NE NO
	CMP	R5,I.UCB(R3)	;REQUEST FOR SPECIFIED UCB?
	BNE	20$		;IF NE NO
	MOV	(R3),(R2      )	;CLOSE UP LIST
	BNE	30$		;IF NE NO NEW LAST
	MOV	R2,2(R4)	;SET ADDRESS OF NEW LAST
30$:	MOV	#IE.ABO&377,R0	;SET FINAL STATUS TO ABORT
	CLR	I.AST(R3)	;MAKE SURE THERE IS NO AST DECLARED
	CALL	$IOFIN		;FINISH I/O REQUEST
	BR	$IOKIL		;GO AGAIN
40$:	BITB	#UC.KIL,U.CTL(R5) ;CALL DRIVER REGARDLESS OF ACTIVITY?
	BNE	45$		;IF NE YES
	TSTB	U.STS(R5)	;UNIT BUSY?
	BPL	50$		;IF PL NO
45$:	MOV	S.PKT(R4),R0	;GET ADDRESS OF CURRENT I/O PACKET
	MOV	(R5),R2		;RETRIEVE ADDRESS OF DEVICE CONTROL BLOCK


	.IF       DF	L$$DRV&M$$MGE

	MOV	KISAR5,-(SP)	;SAVE APR5
	MOV	D.PCB(R2),R3	;GET DRIVER PCB ADDRESS
	BEQ	47$		;IF EQ DRIVER IS PART OF EXEC
	MOV	P.REL(R3),KISAR5  ;MAP THE DRIVER
47$:				;

	.ENDC

	MOV	D.DSP(R2),R2	;GET ADDRESS OF DRIVER DISPATCH TABLE

	.IF DF	L$$DRV

	BEQ	49$		;IF EQ DRIVER IS UNLOADED

	.ENDC	;L$$DRV

	MOVB	S.CON(R4),R3	;GET CONTROLLER INDEX

;
; CALL DRIVER AT CANCEL I/O OPERATION ENTRY POINT WITH THE ARGUMENTS:
;
;	R0=ADDRESS OF THE CURRENT I/O PACKET.
;	R1=ADDRESS OF THE       TCB OF THE CURRENT TASK.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;

	MTPS	S.PRI(R4)	;;;LOCK OUT DEVICE INTERRUPTS
	CALL	@D.VCAN(R2)	;;;CANCEL CURRENT REQUEST
	MTPS	#0		;;;ALLOW DEVICE INTERRUPTS
49$:
	.IF DF	L$$DRV&M$$MGE

	MOV	(SP)+,KISAR5	;RESTORE APR5

	.ENDC


50$:	RETURN			;

									;**-709

;+
; **-$SCDVT-SCAN DEVICE TABLES
; **-$SCDV1-SCAN DEVICE TABLES (ALTERNATE ENTRY)
;
; THIS ROUTINE IS A CO-ROUTINE THAT       IS CALLED TO SCAN THE DEVICE TABLES. FOR EAC
; UNIT CONTROL BLOCK THE CALLER IS RECALLED.
;
; INPUTS:
;
;	R3=LIST POINTER (IF ENTRY AT $SCDV1)
;
; OUTPUTS:
;
;	C=1 IF NO MORE ENTRIES EXIST IN THE DEVICE TABLES.
;	C=0 IF THE NEXT DEVICE TABLE ENTRY IS BEING RETURNED.
;		R3=ADDRESS OF THE DEVICE CONTROL BLOCK.
;		R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;		R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;-

S$$SPA==10			;SYMBOL TO ADD TO SP TO ABORT SCAN
S$$SPC==6			;OFFSET ON SP TO SET TO 1 TO SKIP CUR      RENT DCB

$SCDVT::MOV	#$DEVHD,R3	;GET ADDRESS OF FIRST DCB ADDRESS
$SCDV1::MOV	(SP)+,R4	;REMOVE RETURN ADDRESS FROM STACK
10$:	MOV	(R3),R3		;GET ADDRESS OF NEXT DCB
	BEQ	30$		;IF EQ NO MORE
	MOV	D.UCB(R3),R5	;POINT TO FIRST UCB
	BIT	#DV.PSE,U.CW1(R5) ;PSEUDO DEVICE?
	BNE	10$		;IF NE YES
	MOVB	D.UNIT+1(R3),-(SP) ;CALCULATE NUMBER OF UCB'S TO SCAN
	SUB	D.UNIT(R3),(SP) ;
	INCB	(SP)		;
20$:	MOV	R3,-(SP)	;SAVE DCB ADDRESS
	MOV	R5,-(SP)	;SAVE UCB ADDRESS
	MOV	R4,-(SP)	;SET RETURN ADDRESS
	MOV	U.SCB   ¾  (R5),R4	;GET ADDRESS OF STATUS CONTROL BLOCK
	CLC			;INDICATE ENTRY
	CALL	@(SP)+		;CALL THE CALLER
	MOV	(SP)+,R4	;REMOVE RETURN ADDRESS
	MOV	(SP)+,R5	;RESTORE UCB ADDRESS
	MOV	(SP)+,R3	;RESTORE DCB ADDRESS
	ADD	D.UCBL(R3),R5	;POINT TO NEXT UCB
	DECB	(SP)		;ANY MORE UCB'S TO SCAN?
	BNE	20$		;IF NE YES
	TST	(SP)+		;CLEAN STACK
	BR	10$		;GO AGAIN
30$:	SEC			;INDICATE NO ENTRY
	JMP	(R4)		;RETURN TO CALLER

									;**-601
	.END
 ¾         ðskQ	› c,        	.TITLE	DMDRV
	.IDENT	/05.10/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 05.10
;
; P. J. BEZEREDI   23-SEP-76
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;
; MODIFIED BY:
;
;	R. T. PERRON 03-AUG-79
;
;		RP020 -- CORRECT ECC AND OFFSET RECOVERY ERROR HANDLING
;
;	R. T. PERRON 06-AUG-79
;
;		RP021 -- CORRECT E      RROR RECOVERY FOR LAST BLOCK TRANSFERED
;
;	R. T. PERRON 17-AUG-79
;
;		RP022 -- CORRECT BRANCH OUT OF RANGE
;
;	P. J. CARR	4-APR-80
;
;		PJC002 -- CORRECT WRITE CHECK FUNCTION
;
;	R. T. PERRON 21-NOV-80
;
;		RP041 -- CHANGE INTERFACE TO COMMON ECC ROUTINE
;
;	P. J. CARR	12-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
;	P. J. CARR	15-JUN-81
;
;		PJC030 -- OPTIMIZE DATA LATE RECOVERY
;
;	R. T. PERRON	16-OCT-81
;
;		RP075 -- CORRECT NON-EIS ADDRESS CALCULATION IN ECC CODE
;
;	P      . J. CARR	27-OCT-81
;
;		PJC038 -- CLEAN UP CODE
;
;	P. J. CARR	16-DEC-81
;
;		PJC041 -- CORRECT ECC CORRECTION REGISTER USAGE
;
; RK611-RK06/RK07 DISK CARTRIDGE DRIVER
;
;
.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
;
;****************
;
; EQUATED SYMBOLS
;
RETRY=	^D<8>			;CONTROLLER ERROR RETRY COUNT
OFFTRY=	^D<2>			;OFFSET POSITION RETRY COUNT
RMCNT=	^D<22>			;NUMBER OF REGISTERS TO LOG ON ERROR
RCL=	1			;RECALIBRATE IN PROGRESS (1=      YES)	; RP020
OFS=	2			;OFFSET IN PROGRESS (1=YES)		; RP020
OFM=	10			;IN OFFSET MODE (1=YES)			; RP020
POP=	20			;POSITIONING OPERATION (1=YES)		; RP020
DLT=	40			;DATA LATE OCCURRED (1=YES)		; RP020
;
;****************
;
; RK611 DEVICE REGISTER OFFSETS
;
RMCS1=	0			;CONTROL STATUS REGISTER 1
RMWC=	2			;WORD COUNT
RMBA=	4			;BUS ADDRESS
RMDA=	6			;DISK ADDRESS
RMCS2=	10			;CONTROL STATUS REGISTER 2
RMDS=	12			;DRIVE STATUS
RMER=	14			;ERROR REGISTER
RMOF=	16			;OFFSET/ATTENTION REGISTER
RM      DC=	20			;DESIRED CYLINDER
RMDB=	24			;DATA BUFFER
RMMR1=	26			;MAINTENANCE REGISTER 1
RMECPS=	30			;ECC POSITION
RMECPT=	32			;ECC PATTERN
RMMR2=	34			;MAINTENANCE REGISTER 2
RMMR3=	36			;MAINTENANCE REGISTER 3
;
;****************
;
; RMCS1 BIT ASSIGNMENTS
;
SD=	1			;SELECT DRIVE & GET STATUS
WRT=	2			;WRITE OFFSET
ACK=	3			;PACK ACKNOWLEDGE
DC=	5			;DRIVE CLEAR
IE=	100			;INTERRUPT ENABLE
RDY=	200			;CONTROLLER READY
HMS=	113			;IE + RECALIBRATE + GO
OFF=	115			;IE + OFFSET + GO
BLS=	1      17			;IE + SEEK + GO
READ=	121			;IE + READ + GO
RDH=	125			;IE + READ HEADER + GO
WDH=	127			;IE + WRITE HEADER + GO
WCK=	131			;IE + WRITE CHECK + GO
CERR=	100000			;CONTROLLER ERROR/CONTROLLER CLEAR
DI=	040000			;DRIVE INTERRUPT
DCPAR=	020000			;DRIVE TO CONTROLLER PARITY ERROR
CTO=	004000			;CONTROLLER TIMEOUT
CDT=	002000			;CONTROLLER DRIVE TYPE
;
;****************
;
; RMCS2 BIT ASSIGNMENTS
;
DLT=	100000			;DATA LATE
WCE=	040000			;WRITE CHECK ERROR
UPE=	020000			;UNIBUS PARITY
NED=	0      10000			;NON EXISTANT DISK
NEM=	004000			;NON EXISTANT MEMORY
PGE=	002000			;PROGRAMMING ERROR
MDS=	001000			;MULTIPLE DRIVE SELECT
UFE=	000400			;UNIT FIELD ERROR
SCLR=	000040			;RESET CONTROLLER AND ALL DRIVES
;
;****************
;
; RMDS BIT ASSIGNMENTS
;
SVAL=	100000			;STATUS VALID
DDT=	000400			;DISK DRIVE TYPE
DRDY=	000200			;DRIVE READY
VV=	000100			;VOLUME VALID
DRA=	000001			;DRIVE AVAILABLE
;
;****************
;
; RMER BIT ASSIGNMENTS
;
DCK=	100000			;DATA CHECK ERROR
UNS=	0      40000			;DRIVE UNSAFE
OPI=	020000			;OPERATION INCOMPLETE
DTE=	010000			;DRIVE TIMING ERROR
WLE=	004000			;WRITE LOCK ERROR
IDAE=	002000			;INVALID DISK ADDRESS
COE=	001000			;CYLINDER OVERFLOW
HVRC=	000400			;HEADER VRC ERROR
BSE=	000200			;BAD SECTOR ERROR
ECH=	000100			;ERROR CORRECTION HARD
FMTE=	000020			;FORMAT ERROR
CDPAR=	000010			;CONTROLLER TO DRIVE PARITY ERROR
NXF=	000004			;NON-EXECUTABLE FUNCTION
SKI=	000002			;SEEK INCOMPLETE
ILF=	000001			;ILLEGAL FUNCTION
;
;****************      
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES
; THESE ARE INDEXED BY THE CONTROLLER NUMBER
;
CNTBL:	.BLKW	R$$611		;ADRS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$611		;RETRY COUNT FOR CURRENT OPERATION


	.IF GT	R$$611-1

TEMP:	.BLKW	1		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC


	.IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

;
; DIAGNOSTIC FUNCTION TABLE
;
FUNTBL:	.BYTE	HMS, IO.HMS!IQ.UMD&377
	.BYTE	BLS, IO.BLS!IQ.UMD&377
	.BYTE	OFF,       IO.OFF!IQ.UMD&377
	.BYTE	RDH, IO.RDH!IQ.UMD&377
	.BYTE	WDH, IO.WDH!IQ.UMD&377
	.BYTE	WCK, IO.WCK!IQ.UMD&377
FUNTBE:

	.ENDC


	.IF DF	R$$6OF

;
; OFFSET POSITIONING DATA
;
OFFTB:				;POSITIONING VALUE TABLE
	.BYTE	000		;RETURN TO CENTERLINE
	.BYTE	020		; +400
	.BYTE	220		; -400
	.BYTE	040		; +800
	.BYTE	240		; -800
	.BYTE	060		; +1200
	.BYTE	260		; -1200
OFFTBE:	.BYTE	000		;RETURN TO CENTERLINE
				;
OFFAD:	.BLKW	R$$611		;ADRS OF CURRENT OFFSET VALUE

	.ENDC


;
;**************      **
;
;DRIVER DISPATCH TABLE
;
$DMTBL::.WORD	DMINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DMCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DMOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DMPWF		;POWERFAIL ENTRY POINT
;
;****************
;
;+
; **-DMINI-RK611-RK06/RK07 DISK CARTRIDGE CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O
; REQUEST IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO
; PROPAGATE THE EXECUTION OF THE DRIVER.  IF THE SPECIFIED CONTRO      LLER
; IS NOT BUSY, THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST.
; ELSE A RETURN TO THE CALLER IS EXECUTED.  IF THE DEQUEUE ATTEMPT
; IS SUCCESSFUL, THEN THE NEXT I/O OPERATION IS INITIATED.  A RETURN
; TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;	R5= ADRS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS
;	WAITING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE
;	DRIVER INITIATES THE REQUESTED I/O FUNCTI      ON
;-
	.ENABL	LSB
10$:	RETURN			;RETURN TO CALLER			; PJC038
DMINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS		;**-1
	BCS	10$		;IF CS, CONTROLLER IS BUSY OR NO REQUEST; PJC038
;									;**-1
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1= ADRS OF THE I/O REQUEST PACKET
;	R2= PHYSICAL UNIT NUMBER OF THE REQUESTED DRIVE
;	R3= CONTROLLER INDEX
;	R4= ADRS OF THE STATUS CONTROL BLOCK (SCB)
;	R5= ADRS OF THE UCB OF THE DRIVE TO BE INITIATED
;
; RK611-RK06/RK07 DISK CARTRIDGE CONTROLLER       I/O REQUEST PACKET FORMAT
;
;	WD. 00 -- I/O QUEUE THREAD WORD
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER
;	WD. 02 -- ADRS OF THE TCB OF THE REQUESTOR TASK
;	WD. 03 -- POINTER TO 2ND LUN WORD IN REQUESTOR TASK HEADER
;	WD. 04 -- CONTENTS OF FIRST LUN WORD (UCB ADRS)
;	WD. 05 -- I/O FUNCTION CODE
;	WD. 06 -- VIRTUAL ADRS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O STATUS BLOCK ADRS (REAL OR DISPL.+140000)
;	WD. 11 -- VIRTUAL ADRS OF AST SERVICE ROUTINE
      ;	WD. 12 -- MEMORY EXTENSION BITS OF I/O TRANSFER
;	WD. 13 -- BUFFER ADRS OF I/O TRANSFER
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED
;	WD. 15 -- DIAGNOSTIC SUPPLIMENTAL PARAMETER OR TEMP. STORAGE
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE IS NOT USED
;	WD. 17 -- LOW PART OF LOGICAL BLK NUMBER OF I/O REQUEST
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLK ADRS
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000)
;
;****************
;
; THIS SECTION CALCULATES THE ACTUAL DISK ADDR      ESS FROM THE
; LOGIGAL BLOCK INFORMATION SUPPLIED IN THE I/O PACKET.  IT ALSO
; DETERMINES THE FUNCTION TO PERFORM (DIAGNOSTIC OR READ/WRITE).
;
	MOV	R5,CNTBL(R3)	;SAVE ADRS OF REQUEST UCB


	.IF DF	M$$EXT&M$$MGE


	CALL	$STMAP		;SET UP 11/70 UNIBUS MAPPING ADRS

	.ENDC


	.IF DF	M$$MGE

	ASL	U.BUF(R5)	;POSITION EXTENDED MEMORY BITS
	ASL	U.BUF(R5)
	ASL	U.BUF(R5)
	ASL	U.BUF(R5)

	.ENDC


	.IF DF	D$$IAG

20$:	CMPB	#<IO.HMS/^D<256>>,I.FCN+1(R1) ;DIAGNOSTIC FUNCTION?	; PJC038
	BNE	40      $		;IF NE NO				; PJC038
	MOV	#FUNTBL,R0	;GET ADDRESS OF FUNCTION TABLE		;**-2
30$:	MOVB	(R0)+,U.BUF(R5)	;LOAD CONTROLLER FUNCTION CODE		; PJC038
	CMPB	(R0)+,I.FCN(R1)	;IS IT THE CORRECT CODE?		;**-1
	BEQ	60$		;IF EQ YES				; PJC038
	CMP	#FUNTBE,R0	;END OF FUNCTION TABLE?			;**-1
	BNE	30$		;IF NE NO				; PJC038
									;**-1
	.ENDC


40$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION		; PJC038
	MOVB	#READ,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION		;**-1
	CMPB	#<IO.RLB/^D<256>>,I.FCN+1(R1)  ;REALLY      ?
	BHIS	50$		;IF HIS FUNCTION IS LEGAL		; PJC038
	JMP	310$		;FUNCTION IS ILLEGAL			; PJC038
50$:	BEQ	60$		;IF EQ FUNCTION WAS A READ		; PJC038
	ADD	#WRT,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION	;**-3
60$:	MOV	#RETRY,RTTBL(R3) ;SET INITIAL RETRY COUNT		; PJC038
									;**-1

	.IF DF	R$$6OF

	CALL	530$		;RESET OFFSET RECOVERY VALUES		; PJC038
									;**-1
	.ENDC


	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER
	CMPB	#IO.WLB/^D<256>,I.FCN+1(R3)  ;WRITE FUNCTION?
	BNE	70$		;IF NE NO				; PJC      038
	BITB	#IO.WLT&377,I.FCN(R3)  ;OK TO WRITE ON LAST TRACK?	;**-1
	BNE	70$		;IF NE YES				; PJC038
	MOV	R0,I.PRM+6(R3)	;YES, SAVE STARTING BLOCK NUMBER	;**-1
	ADD	#^D<22>,I.PRM+12(R3)  ;ADD 1 TRACK'S WORTH OF BLOCKS
	CALL	$BLKC1		;CHECK IF WRITE ON LAST TRACK OF DISK
	MOV	I.PRM+6(R3),R0	;RESTORE ORIGINAL STARTING BLOCK NUMBER
70$:	MOV	#^D<22>*3,R1	;SET DIVISOR=BLOCKS PER CYLINDER	; PJC038
	CALL	$DIV		;FIND CYLINDER ADDRESS (R0=LBN)		;**-1
	MOV	R0,I.PRM+10(R3)	;SAVE DESIRED CYLINDER ADRS
	MOV	R1,R      0		;SET DIVIDEND=TRACK/SECTOR (REMAINDER)
	MOV	#^D<22>,R1	;SET DIVISOR=BLOCKS PER TRACK
	CALL	$DIV		;FIND TRACK AND SECTOR ADDRESS
	SWAB	R0		;SWAP TRACK TO HIGH BYTE
	BIS	R1,R0		;MERGE SECTOR WITH TRACK
	MOV	R0,I.PRM+12(R3)	;SAVE TRACK AND SECTOR ADRS
;
; THIS NEXT SECTION WILL INITIATE THE I/O OPERATION
;
DMINIO:				;REF LABEL


	.IF DF	M$$EXT&M$$MGE

	CALL	$MPUBM		;MAP 11/70 UNIBUS TO TRANSFER

	.ENDC


80$:	CLRB	U.CW2+1(R5)	;CLEAR ALL POSITIONING OPERATION FLAGS	; PJC038
	MOV	S.CSR(R4      ),R2	;GET CSR ADRS				;**-1
	MOV	S.PKT(R4),R3	;GET ADRS OF I/O PACKET
	MOVB	S.ITM(R4),S.CTM(R4)  ;SET TIMEOUT COUNT
	ADD	#RMCS2,R2	;POINT TO RMCS2
	MOV	#SCLR,(R2)	;CLEAR CONTROLLER AND INIT ALL DRIVES
	MOVB	U.UNIT(R5),R0	;FETCH DRIVE UNIT NUMBER
	MOV	R0,(R2)		;SELECT THE DRIVE
	MOV	I.PRM+12(R3),-(R2)  ;SET TRACK AND SECTOR ADRS
	MOV	U.BUF+2(R5),-(R2)   ;SET USER BUFFER ADRS
	MOV	U.CNT(R5),-(R2)	;SET BYTES TO TRANSFER
	ROR	(R2)		;MAKE THAT WORDS TO TRANSFER
	NEG	(R2)		;MAKE IT A NEGATIVE WORD COUN      T
	TST	-(R2)		;POINT TO CSR
	MOV	#ACK,R0		;GET PACK ACKNOWLEDGE FUNCTION
	CALL	XCUTE		;EXECUTE PACK ACK TO SET VV		; PJC038
90$:	TSTB	(R2)		;WAIT FOR THE SERIAL MESSAGE ...	; PJC038
	BPL	90$		;... TO RETURN				; PJC038
	MOV	#IE.DNR&377,R0	;ASSUME SELECTED UNIT NOT READY		;**-3
	MOV	I.PRM+10(R3),RMDC(R2)  ;SET CYLINDER ADDRESS
	MOV	RMDS(R2),R1	;GET CURRENT DRIVE STATUS
	COM	R1		;COMPLEMENT STATUS
	BIT	#SVAL!DRDY!VV!DRA,R1  ;DRIVE READY?
	BNE	100$		;IF NE NO				; PJC038
	BIT	#UNS,RMER(R2)	;DRIVE U      NSAFE?				;**-1
	BEQ	120$		;IF EQ NO				; PJC038
100$:				;REF LABEL				; PJC038
									;**-2

	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	150$		;IF NE YES				; PJC038
									;**-1
	.IFTF


	.IF DF	D$$IAG

	CALL	DMDINT		;TEST FOR DIAGNOSTIC DRIVE NOT READY
	BCS	110$		;IF CS DIAGNOSTIC			; PJC038
									;**-1
	.ENDC


	.IF DF	E$$DVC

	CALL	DMDVER		;LOG DRIVE NOT READY ERROR

	.ENDC


110$:	JMP	290$		;FINISH I/O				; PJC038
120$:				;REF LABEL				; P      JC038
									;**-2
	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC


	.IF DF	D$$IAG

	CMPB	U.BUF(R5),#BLS	;IS THIS A POSITIONING FUNCTION?
	BHI	130$		;IF HI NO				; PJC038
	BISB	#POP!OFM,U.CW2+1(R5)  ;ASSUME OFFSET OR POSITIONING OPER; RP020
	CMPB	U.BUF(R5),#OFF	;IS IT AN OFFSET OPERATION?		; RP020
	BNE	130$		;IF NE NO				; PJC038
	MOV	I.PRM+6(R3),RMOF(R2)  ;YES, SET OFFSET VALUE		;**-4
130$:				;REF LABEL				; PJC038
									;**-1
	.ENDC


	.IF DF	E$$DVC

	CALL	$      BMSET		;SET I/O ACTIVE BIT IN MAP

	.ENDC


140$:	MOV	U.BUF(R5),R0	;;;GET FUNCTION AND MEMORY BITS		; PJC038
	CALLR	XCUTE		;;;SET CDT, LOAD FUNCTION AND GO	; PJC038
									;**-2
;+
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;-

DMCAN:	RETURN			;;;NOP FOR THE RK611

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO       SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DMPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS DRIVE CURRENTLY BUSY?
	BEQ	160$		;IF EQ NO				; PJC038
150$:	MOVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC038
160$:	BISB	#US.SPU,U.STS(R5) ;SET UNIT SPINNING UP			; PJC038
									;**-4
	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND

;+
; **-$DMINT-RK611-RK06/RK07 DIS      K CARTRIDGE CONTROLLER
;	INTERRUPT AND ERROR SERVICE ROUTINES
;
; HARD ERRORS ---> $IODON
; SOFT ERRORS ---> RETRY LAST FUNCTION
; DATA ERRORS ---> RETRY FUNCTION AND CORRECT IF POSSIBLE
;-
	INTSE$	DM,PR5,R$$611	;;;SAVE REGISTERS AND SET PRIORITY
	MOV	R3,-(SP)	;;;SAVE REGISTER 3
	MOV	U.SCB(R5),R3	;;;GET ADDRESS OF SCB
	MOV	S.CSR(R3),R3	;;;GET ADDRESS OF CSR
	BITB	#POP,U.CW2+1(R5)  ;;;POSITIONING OPERATION?		; RP020
	BEQ	170$		;;;IF EQ NO				; PJC038
	BIT	#CERR!DI,(R3)	;;;POSITIONING COMPLETE OR       ERROR?	;**-2
	BNE	170$		;;;IF NE YES				; PJC038
	MOV	(SP)+,R3	;;;RESTORE R3				;**-1
	RETURN			;;;WAIT FOR POSITIONING TO COMPLETE
170$:	BIC	#CERR!IE,(R3)	;;;KILL IE WITHOUT HURTING CERR		; PJC038
	MOV	(SP)+,R3	;;;RESTORE R3				;**-2
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADRS OF SCB
	MOV	S.CSR(R4),R2	;GET CSR ADDRESS
	TST	(R2)		;ERRORS ALREADY PRESENT?
	BMI	180$		;IF MI YES, FORGET STATUS UPDATE	; PJC038
	TST	RMDS(R2)	;IS THE CURRENT       STATUS VALID?		;**-1
	BMI	180$		;IF MI YES				; PJC038
	CALL	560$		;NO, SELECT DRIVE TO GET FRESH STATUS	; PJC038
180$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER		; PJC038
									;**-3

	.IF DF	D$$IAG

	CALL	DMDINT		;PROCESS DIAGNOSTIC INTERRUPT
	BCS	260$		;IF CS, INTERRUPT PROCESSING COMPLETE	; PJC038
									;**-1
	.ENDC


	BITB	#OFM,U.CW2+1(R5)  ;OFFSET POSITIONING OPERATION?	; RP020
	BEQ	190$		;IF EQ NO				; PJC038
	MOVB	U.CW2+1(R5),R0	;GET POSITIONING FLAGS			; RP020
	COM	R0		;      TOGGLE THEM				; RP020
	BIT	#OFM!RCL,R0	;IN OFFSET MODE AND DOING A RECAL?	; RP020
	BNE	210$		;IF NE NO				; PJC038
	CLR	R0		;GET READY FOR THE BISB			; RP020
	BISB	RTTBL+1(R3),R0	;RETRIEVE ERROR/SUCCESS CODE (?)	; RP020
	BICB	#OFM!RCL,U.CW2+1(R5)  ;CLEAR FLAGS			; RP020
	JMP	DMDONE		;NOW SAY GOOD-BYE			; RP020
190$:	TST	(R2)		;ANY ERRORS?				; PJC038
	BPL	240$		;IF PL NO				; PJC038
									;**-4

	.IF DF	E$$DVC

	CALL	DMDVER		;YES, LOG THE DEVICE ERROR

	.ENDC


	MOV	RMER(R2),R1	;COPY E      RROR REGISTER BITS
	MOV	#IE.WLK&377,R0	;ASSUME WRITE LOCK ERROR
	BIT	#WLE,R1		;WRITE LOCK ERROR?
	BNE	200$		;IF NE YES				; PJC038
	MOV	#IE.BBE&377,R0	;ASSUME BAD BLOCK ERROR			;**-1
	BIT	#BSE,R1		;BAD BLOCK ERROR?
	BNE	200$		;IF NE YES				; PJC038
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		;**-1
	BIT	#UNS!DTE!IDAE!COE!FMTE!NXF!ILF,R1  ;HARD ERROR?
	BNE	200$		;IF NE YES				; PJC028
	BIT	#UPE!NED!NEM!PGE!MDS!UFE,RMCS2(R2)  ;HARD ERROR?	;**-1
	BNE	200$		;IF NE YES				; PJC028
	MOV	S.PKT(R4),      R3	;RETREIVE I/O PACKET ADDRESS		;**-1
	BITB	#IQ.X,I.FCN(R3)	;INHIBIT RETRIES?
	BNE	290$		;IF NE YES, FINISH UP			; PJC038
	JMP	320$		;NO, TRY FOR SOFT/DATA ERRORS		; PJC038
200$:	BR	290$		;FINISH UP				; PJC038
210$:	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		; PJC038
									;**-3

	.IF DF	R$$6OF

	BITB	#RCL,U.CW2+1(R5)  ;RECALIBRATE FUNCTION?		; RP020
	BEQ	220$		;IF EQ NO				; PJC038
									;**-2
	.IFTF

	TST	(R2)		;ERRORS DURING RECALIBRATE?
	BPL	280$		;IF PL NO				; PJC038
	BR	      290$		;YES, FINISH UP				; PJC038
									;**-2
	.IFT

220$:	CMP	#OFFTBE,OFFAD(R3) ;FINAL OFFSET TRIED?			; PJC038
	BEQ	290$		;IF EQ YES, ALL DONE			; PJC038
	TST	(R2)		;ERRORS ATTEMPTING TO OFFSET HEADS?	;**-2
	BMI	280$		;IF MI YES				; PJC038
									;**-1
	.ENDC


230$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	E$$DVC

	CALL	720$		;DEALLOCATE REGISTER CORE BLOCK		; PJC038
									;**-1
	.ENDC


	JMP	DMINIO		;RETRY ORIGINAL FUNCTION
240$:				;REF LABEL				; PJC038
						      			;**-1

	.IF DF	D$$WCK

	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IO.WLC&377,I.FCN(R1) ;WRITE FOLLOWED BY WRITE CHECK?	; PJC002
	BNE	250$		;IF NE YES				; PJC038
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED BY MCR?		;**-2
	BEQ	260$		;IF EQ NO				; PJC038
250$:	CMPB	#READ,U.BUF(R5)	;WAS LAST FUNCTION A READ?		; PJC038
	BEQ	260$		;IF EQ YES				; PJC038
	CMPB	#READ+WRT,U.BUF(R5)  ;WAS LAST FUNCTION A WRITE?	;**-3
	BNE	260$		;IF NE NO				; PJC038
	MOVB	#WCK,U.BUF(R5)	;SET WRITE CHECK FUNC      TION		;**-1
	MOV	#RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT
	BR	230$		;START WRITE CHECK OPERATION		; PJC038
									;**-1
	.ENDC


260$:	CLR	U.CNT(R5)	;NO ERRORS, SET ALL BYTES TRANSFERRED	; PJC038
	JMP	DMDONE		;FINISH I/O				; RP020
									;**-2
;+
; **-DMOUT-RK611-RK06/RK07 DISK CARTRIDGE CONTROLLER
;	DEVICE TIMEOUT ROUTINE
;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED
; UNLESS THE OPERATION WAS DIAGNOSTIC.  TIMEOUTS ARE USUALLY CAUSED
; BY POWER FAILURE BUT MAY ALS      O BE THE RESULT OF NO RESPONSE
; FROM THE HARDWARE.
;-

DMOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	270$		;;;IF EQ NO				; PJC038
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#16.,S.STS(R4)	;;;HAVE WE WAITED 1 MINUTE YET?		; PJC029
	BEQ	270$		;;;IF EQ YES				; PJC038
	MTPS	#0		;;;ALLOW INTERRUPTS			;**-3
	JMP	DMINIO		;RETRY ENTIRE OPERATION
270$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC038
	BICB	#US.SPU,U.STS(R5)        ;;;RESET DRIVE SPINNING UP		;**-1

	.ENDC


	.IF DF	D$$IAG

	CALL	DMDINT		;;;TEST FOR DIAGNOSTIC TIMEOUT
	BCS	290$		;IF CS IT WAS				; PJC038
									;**-1
	.ENDC


	.IF DF	E$$DVC

	CALL	DMDVTO		;;;LOG DEVICE TIMEOUT

	.IFF

	CALL	$DTOER		;;;LOG DEVICE TIMEOUT

	.ENDC


	BITB	#POP,U.CW2+1(R5)  ;TIMEOUT DURING POSITIONING OPERATION	; RP020
	BNE	290$		;IF NE YES				; PJC038
280$:	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS			; PJC038
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?			;**-3
	B      NE	290$		;IF NE YES				; PJC038
	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX		;**-1
	DECB	RTTBL(R3)	;RETRY FUNCTION?
	BGT	230$		;IF GT YES				; PJC038
;									;**-1
;****************
;
; AT THIS POINT ALL I/O IS FINISHED. WE WILL CALCULATE THE
; BYTES ACTUALLY TRANSFERED AND SET THE ERROR LOGGING RETRY COUNTS.
; THEN $IODON IS CALLED TO TERMINATE THE I/O OPERATION.
;
290$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	D$$WCK

	BIT	#WCE,RMCS2(R2)	;WRITE CHECK ERROR?
	BEQ	300$		;IF EQ       NO				; PJC038
	MOV	#IE.WCK&377,R0	;SET WRITE CHECK ERROR			;**-1

	.ENDC


300$:	MOV	RMWC(R2),R1	;GET RESIDUAL WORD COUNT		; PJC038
	ASL	R1		;CONVERT TO BYTE COUNT			;**-1
	NEG	R1		;CONVERT TO POSITIVE BYTES REMAINING
	MOV	R1,U.CNT(R5)	;SAVE BYTES REMAINING TO TRANSFER
	BITB	#OFM,U.CW2+1(R5)  ;IN OFFSET MODE?			; RP020
	BEQ	DMDONE		;IF EQ NO				; RP020
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX		; RP020
	MOVB	R0,RTTBL+1(R3)	;SAVE ERROR/SUCCESS CODE		; RP020
	BR	340$		;NOW DO A RECALIBRATE	      		; PJC038
DMDONE:				;REF LABEL				; RP020
									;**-1

	.IF DF	E$$DVC

	CALL	720$		;DEALLOCATE REGISTER CORE BLOCK		; PJC038
	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX		;**-1
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#<RETRY*^D<256>>,R2  ;MERGE STARTING RETRY COUNT

	.ENDC


310$:	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS			; PJC038
	MOV	I.PRM+4(R1),R1	;GET ACTUAL BYTES TO TRANSFER		;**-1
	SUB	U.CNT(R5),R1	;CALCULATE BYTES ACTUALLY TRANSFERED
	CALL	$IODON		;FINISH I/O OPER      ATION
	JMP	DMINI		;PROCESS NEXT REQUEST
;
;****************
;
320$:	BIT	#WCE,RMCS2(R2)	;WRITE CHECK ERROR?			; PJC038
	BNE	280$		;IF NE YES				; PJC038
									; PJC030
									; PJC030
	.IF DF	R$$6OF							; PJC030
									; PJC030
	TST	RMCS2(R2)	;DATA LATE ERROR?			; PJC030
	BPL	330$		;IF PL NO				; PJC038
	JMP	DMDLT		;YES					; PJC030
									; PJC030
	.ENDC								; PJC030
									; PJC030
									; PJC030
330$:	BIT	#DCPAR!CTO,(R2) ;CONTROLLER TIMEOUT OR PARITY ERROR?	; PJC038
	      BNE	280$		;IF NE YES				; PJC038
	BIT	#CDPAR,R1	;CONTROLLER TO DRIVE PARITY ERROR?	;**-4
	BNE	280$		;IF NE YES				; PJC038
	BIT	#OPI!SKI,R1	;DRIVE POSITIONING ERROR?		;**-1
	BEQ	360$		;IF EQ NO				; PJC038
									;**-1

	.IF DF	E$$DVC

	CALL	720$		;DEALLOCATE REGISTER CORE BLOCK		; PJC038
									;**-1
	.ENDC


	CALL	590$		;CLEAR CONTROLLER			; PJC038
	CALL	550$		;ISSUE DRIVE CLEAR FUNCTION		; PJC038
340$:	MOV	#HMS,R0		;SET RECALIBRATE FUNCTION		; PJC038
	BISB	#RCL,U.CW2+1(R5) ;INDICATE       RECALIBRATE OPERATION	; PJC038
350$:	MOVB	S.ITM(R4),S.CTM(R4) ;RESET TIMEOUT COUNT		; PJC038
	CALLR	XCUTE		;ISSUE FUNCTION				; PJC038
360$:				;REF LABEL				; PJC038
									;**-7

	.IF DF	R$$6OF

	BIT	#HVRC,R1	;HEADER VRC ERROR?
	BNE	DMECC		;YES, DO ECC

	.IFTF

	TST	R1		;DATA CHECK ERROR?
	BPL	280$		;IF PL NO, MUST BE SOFT ERROR		; PJC038
									;**-1
	.IFF

	BIT	#ECH,R1		;ECC HARD ERROR?
	BNE	280$		;IF NE YES, RETRY IT			; PJC038
									;**-1
	.ENDC


;
; START ECC CORRECTI      ON PROCEDURE					; RP041
;									;**-11
DMECC:	CMPB	#READ,U.BUF(R5)	;IS THIS A READ OPERATION?
	BNE	280$		;IF NE NO				; PJC038
	MOV	S.PKT(R4),R3	;RETRIEVE I/O PACKET ADDRESS		; RP020
	BITB	#IQ.X,I.FCN(R3)  ;INHIBIT RETRIES?			; RP020
	BNE	290$		;IF NE YES				; PJC038
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX		; PJC038
	DECB	RTTBL(R3)	;RE-READ THE DATA?			; PJC038
	BLE	370$		;IF LE NO				; PJC038
	JMP	230$		;YES					; PJC038
370$:	MOVB	#RETRY,RTTBL(R3)  ;RESET RETRY COUNT			; PJC038
	MOV	R      MWC(R2),R0	;GET NEGATIVE WORDS REMAINING		; RP041
	ASL	R0		;CONVERT TO BYTES			; RP041
	ADD	U.CNT(R5),R0	;CALCULATE BYTES ACTUALLY TRANSFERRED	; RP041
									; RP041
									; RP041
	.IF DF	R$$6OF							; RP041
									; RP041
	BEQ	DMOFST		;IF EQ NONE TRANSFERRED			; RP041
									; RP041
	.IFF	;R$$6OF							; RP041
									; RP041
	BEQ	280$		;IF EQ NONE TRANSFERRED			; PJC038
									; RP041
	.ENDC	;R$$6OF							; RP041
									; RP041
									; RP041
	CMP	#DCK,R1		;ONLY DATA CHECK       ERROR?			; RP041
									; RP041
	.IF DF	R$$6OF							; RP041
									; RP041
	BNE	DMOFST		;IF NE NO				; RP041
									; RP041
	.IFF	;R$$6OF							; RP041
									; RP041
	BNE	280$		;IF NE NO				; PJC038
									; RP041
	.ENDC	;R$$6OF							; RP041
									; RP041
									; RP041
	MOV	R2,-(SP)	;SAVE CORE BLOCK ADDRESS		; PJC041
	MOV	RMECPS,R1	;GET ECC ERROR POSITION			; RP041
	MOV	RMECPT,R3	;GET ECC CORRECTION PATTERN		; RP041
	MOV	RMWC(R2),R2	;GET REMAINING WORD COUNT		; RP041
			      						;**-1

	.IF DF	S$$ECC

	CALL	$ECCOR		;CALL SHARED ECC ROUTINE		;**-2
									;**-8
	.IFF

	MOV	R0,-(SP)	;SAVE BYTE COUNT			; RP041
	CLR	R0		;CLEAR HIGH ORDER ERROR POSITION	; RP041
	DEC	R1		;CONVERT TO RELATIVE BIT NUMBER		; RP041
									; RP041
									; RP041
	.IF DF	 M$$EIS							; RP041
									; RP041
	DIV	#20,R0		;DIVIDE FOR:				; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
									; RP041
	.IFF	;M$$EIS							; RP041
									; RP      041
	MOV	R1,R0		;COPY ECC ERROR POSITION		; RP041
	MOV	#20,R1		;SET DIVISOR TO CALCULATE:		; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
	CALL	$DIV		;PERFORM DIVISION			; RP041
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
	MOV	R0,-(SP)	;SAVE WORD POSITION			; RP041
	MOV	R2,-(SP)	;SAVE REMAINING WORD COUNT		; RP041
	CLR	R2		;CLEAR HIGH ORDER ERROR PATTERN		; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							;       RP041
									; RP041
380$:	ASHC	R1,R2		;SHIFT PATTERN INTO CORRECT POSITION	; PJC038
									; RP041
	.IFF	;M$$EIS							; RP041
									; RP041
380$:	DEC	R1		;ANY MORE SHIFTS LEFT TO PERFORM	; PJC038
	BLT	390$		;IF LT NO				; PJC038
	ASL	R3		;DOUBLE LEFT SHIFT			; RP041
	ROL	R2		;					; RP041
	BR	380$		;					; PJC038
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
390$:	MOV	4(SP),R0	;RETRIEVE ACTUALL BYTE TRANSFERRED	; PJC038
	SUB	#510.,R0	;BACKUP TO BLO      CK IN ERROR ...		; RP041
				;... OFFSET TO HIGH WORD IN ERROR	; RP041
									; RP041
									; RP041
	.IF DF	D$$IAG							; RP041
									; RP041
	CALL	$RELOP		;COMPUTE LOCATION IN PHYSICAL MEMORY	; RP041
									; RP041
	.IFF	;D$$IAG							; RP041
									; RP041
	MOV	R0,-(SP)	;SAVE BYTE OFFSET ON STACK		; RP041
	MOV	U.BUF+2(R5),R1	;GET LOW 16 BITS OF ADDRESS		; RP041
									; RP041
									; RP041
	.IF DF	M$$MGE							; RP041
									; RP041
	MOVB	U.BUF+1(R5),R0	;GET HIGH BITS O      F REAL ADDRESS		; RP041
									; RP041
									; RP041
	.IF DF	M$$EXT							; RP041
									; RP041
	ADD	#<S.MPR+M.LGTH>,R4  ;POINT PAST PHYSICAL BUFFER ADDRESS	; RP041
				;CONTAINED IN UMR AREA			; RP041
	MOV	-(R4),R1	;GET LOW 16 BITS OF PHYSICAL BUFFER ADDR; RP041
	TSTB	-(R4)		;SKIP NEXT BYTE				; RP041
	MOVB	-(R4),R0	;GET HIGH 6 BITS OF PHYSICAL BUFFER ADDR; RP041
	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			; RP041
									; RP041
	.ENDC	;M$$EXT							; RP041
									; RP041
									;       RP041
	.IFF	;M$$MGE							; RP041
									; RP041
	CLR	R0		;					; RP041
									; RP041
	.ENDC	;M$$MGE							; RP041
									; RP041
									; RP041
400$:	ADD	(SP)+,R1	;CALCULATE NEW STARTING ADDRESS ...	; PJC038
	ADC	R0		;...					; RP041
									; RP041
									; RP041
	.IF DF	M$$MGE							; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
	ASHC	#10.,R0		;CALCULATE DISPLACEMENT AND BIAS	; RP041
	ASHC	#-10.,R1	;...					; RP041
									; RP041
      	.IFF	;M$$EIS							; RP041
									; RP041
	MOV	#10.,-(SP)	;SET COUNT FOR 10 SHIFTS		; RP041
410$:	DEC	(SP)		;ANY MORE SHIFTS TO PERFORM		; PJC038
	BLT	420$		;IF LT NO				; PJC038
	ASL	R1		;DOUBLE LEFT SHIFT R1 ...		; RP075
	ROL	R0		;... INTO R0				; RP075
	BR	410$		;					; PJC038
420$:	SWAB	R1		;SWAP BYTES				; PJC038
	ASR	R1		;SHIFT RIGHT R1				; RP075
	ASR	R1		;...					; RP075
	TST	(SP)+		;CLR THE STACK				; RP075
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									;       RP041
	MOV	R0,KISAR6	;SET RELOCATION BIAS			; RP041
	ADD	#140000,R1	;SET DISPLACEMENT			; RP041
									; RP041
	.ENDC	;M$$MGE							; RP041
									; RP041
									; RP041
	.ENDC	;D$$IAG							; RP041
									; RP041
									; RP041
	MOV	(SP)+,R0	;RETRIEVE REMAINING WORD COUNT		; RP041
	BPL	430$		;IF PL, THIS MAY HAVE BEEN A PARTIAL BLO; PJC038
				;TRANSFER				; PJC038
	CLR	R0		;ASSUME A WHOLE BLOCK WAS TRANSFERRED	; RP041
430$:	ADD	(SP),R1		;ADD IN ERROR WORD POSITION OFFSET ...	; PJC0      38
	ADD	(SP),R1		;... FOR BYTE ADDRESSING		; RP041
	ADD	(SP)+,R0	;ADD CORECTION OFFSET TO CORRECTION LIMI; RP041
	CMP	R0,#377		;IS THE CORRECTION ENTRELY IN THIS BLOCK; RP041
	BHI	450$		;IF HI, NOT AT ALL			; PJC038
	BEQ	440$		;IF EQ, THEN ONLY ONE WORD		; PJC038
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
	XOR	R2,(R1)		;CORRECT HIGH ORDER WORD		; RP041
440$:	XOR	R3,-(R1)	;CORRECT LOW ORDER WORD			; PJC038
									; RP041
	.IFF	;M$$EIS							; RP041
							      		; RP041
	MOV	(R1),R0		;COPY HIGH ORDER DATA WORD		; RP041
	BIC	R2,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R2		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R2,(R1)		;PATTERN.OR.DATA WORD			; RP041
440$:	MOV	-(R1),R0	;COPY LOW ORDER DATA WORD		; PJC038
	BIC	R3,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R3		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R3,(R1)		;PATTERN.OR.DATA WORD			; RP041
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
450$:	MOV	#I      S.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER		; PJC038
	MOV	(SP)+,R1	;RESTORE BYTES TRANSFERRED		; RP041
	MOV	S.CSR(R4),R2	;RESTORE CSR ADDRESS			; RP041
	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX		; RP041
									;**-49
	.ENDC


	.IF DF	R$$6OF

	CALL	530$		;RESET OFFSET RECOVERY PARAMETERS	; PJC038
									;**-1
	.ENDC


	MOV	(SP)+,R2	;GET CORE BLOCK ADDRESS			; PJC041
	SUB	R1,U.CNT(R5)	;ANY MORE BYTES TO TRANSFER?
	BNE	460$		;IF NE YES				; PJC038
	JMP	290$		;NO					; PJC038
460$:				;R      EF LABEL				; PJC038
									;**-1

	.IF DF	M$$MGE

	MOV	(R2),R1		;RETREIVE RMCS1 CONTENTS
	SWAB	R1		;REPOSITION BYTES
	BICB	#^C<3>,R1	;ISOLATE MEMORY EXTENSION BITS
	MOVB	R1,U.BUF+1(R5)	;SAVE FOR NEXT FUNCTION

	.ENDC


	MOV	RMBA(R2),U.BUF+2(R5)  ;SAVE BUFFER ADRS
	MOV	S.PKT(R4),R1	;GET ADRS OF I/O PACKET
	MOV	RMDC(R2),I.PRM+10(R1)  ;SAVE CYLINDER ADRS
	MOV	RMDA(R2),I.PRM+12(R1)  ;SAVE TRACK/SECTOR ADRS


	.IF DF	E$$DVC

	CALL	720$		;DEALLOCATE REGISTER CORE BLOCK		; PJC038
									      ;**-1
	.IFTF

	CALL	590$		;CLEAR CONTROLLER			; PJC038
	CALL	550$		;ISSUE DRIVE CLEAR FUNCTION		; PJC038
	MOV	U.BUF+2(R5),RMBA(R2)  ;SET PREVIOUS BUFFER ADDRESS	;**-2

	.IFT

	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS

	.ENDC


	MOV	I.PRM+10(R1),RMDC(R2)  ;SET PREVIOUS CYLINDER ADDRESS
	MOV	I.PRM+12(R1),RMDA(R2)  ;SET PREVIOUS DISK ADDRESS
	JMP	140$		;RESTART FROM WHERE WE LEFT OFF		; PJC038
									;**-1
	.IF DF	R$$6OF							;**-71

;+
; OFFSET POSITIONING READ RECOVERY
;
; THE TRANS      FER ENDED IN AN ECC HARD ERROR BUT THERE WERE SECTORS
; TRANSFERED THAT CONTAINED GOOD DATA.  SINCE THE ECC HARD ERROR
; COULD HAVE BEEN CAUSED BY A CYLINDER CROSSING, THE GOOD DATA IS
; SAVED AND THE TRANSFER IS RETRIED FROM THE POINT OF ERROR.
;-
DMOFST:	TST	R0		;ANY GOOD SECTORS TRANSFERRED?		; RP020
	BEQ	490$		;IF EQ NO				; PJC038
	SUB	R0,U.CNT(R5)	;REDUCE BYTES REMAINING TO TRANSFER	; RP021
	BNE	470$		;IF NE, MORE SECTORS TO TRANSFER	; PJC038
	ADD	R0,U.CNT(R5)	;LAST SECTOR TO TRANSFER, CORREC      T BYTES ; RP021
	BR	500$		;AND CONTINUE				; PJC038
470$:	ADD	R0,U.BUF+2(R5)	;UPDATE STARTING BUFFER ADRS		; PJC038
	ADCB	U.BUF+1(R5)	;PROPAGATE CARRY INTO EXTENSION BITS	; RP021
	SWAB	R0		;CALCULATE THE NUMBER OF...		;**-6
	ASR	R0		;...SECTORS TRANSFERED
	CALL	DMCALC		;UPDATE THE DISK ADDRESS		; PJC030
480$:	CALL	540$		;RESET OFFSET TABLE ADRS		; PJC038
	BR	500$		;					; PJC038
;									;**-14
; NO GOOD DATA WAS TRANSFERED SO CHECK TO SEE IF THE OFFSET
; FROM TRACK CENTERLINE SHOULD BE CHANGED.      
;
490$:	DECB	RTTBL+1(R3)	;CHANGE OFFSET?				; PJC038
	BGT	520$		;IF GT NO				; PJC038
	MOVB	#OFFTRY,RTTBL+1(R3)  ;SET RECOVERY RETRY COUNT		;**-2
500$:	INC	OFFAD(R3)	;UPDATE OFFSET POINTER			; PJC038
									;**-1

	.IF DF	E$$DVC

	CALL	720$		;DEALLOCATE REGISTER CORE BLOCK		; PJC038
									;**-1
	.ENDC


	MOVB	@OFFAD(R3),R0	;GET NEXT OFFSET VALUE
	BNE	510$		;IF NE, NOT RETURNING TO CENTERLINE	; PJC038
	MOVB	#RETRY*2,RTTBL+1(R3)  ;TRY 16 TIMES AT CENTERLINE	;**-1
510$:	CALL	590$		;CLEA      R CONTROLLER			; PJC038
	CALL	550$		;ISSUE DRIVE CLEAR FUNCTION		; PJC038
	MOV	R0,RMOF(R2)	;LOAD NEXT OFFSET VALUE			;**-2
	MOV	#OFF,R0		;SET OFFSET FUNCTION
	BISB	#OFS!OFM,U.CW2+1(R5)  ;INDICATE OFFSET FUNCTION		; RP020
	JMP	350$		;					; PJC038
520$:	JMP	230$		;RETRY FUNCTION				; PJC038
;									;**-2
;****************
;
; RESET THE OFFSET RECOVERY PARAMETERS
;
530$:	MOVB	#1,RTTBL+1(R3)	;SET RECOVERY COUNT TO ONE		; PJC038
540$:	MOV	#OFFTB-1,OFFAD(R3) ;SET OFFSET TABLE POINTER		; PJC038
	R      ETURN								;**-2

	.ENDC


;+
; INITIATE A CONTROLLER/DRIVE CLEAR OR SELECT DRIVE FUNCTION
; AND WAIT FOR THE SERIAL MESSAGE.
;
; NOTE:	THE TIMING LOOP AT 153$ IS TO ALLOW TIME FOR THE
;	SERIAL MESSAGE TO BE SENT TO THE DRIVE AND THE STATUS
;	TO BE RECEIVED BY THE RK611.  AVERAGE TIME = 15US.
;-
550$:	MOV	R0,-(SP)	;SAVE REGISTER				; PJC038
	MOV	#DC,R0		;ISSUE DRIVE CLEAR FUNCTION		;**-1
	BR	570$		;					; PJC038
560$:	MOV	R0,-(SP)	;SAVE REGISTER				; PJC038
	MOV	#SD,R0		;ISSUE SELECT DRIV      E FUNCTION		;**-2
570$:	CALL	XCUTE		;LOAD RMCS1				; PJC038
580$:	TSTB	(R2)		;WAIT FOR THE SERIAL MESSAGE ...	; PJC038
	BPL	580$		;... TO DO ITS THING			; PJC038
	MOV	(SP)+,R0	;RESTORE REGISTER			;**-3
	RETURN			;
590$:	MOV	#CERR,(R2)	;CLEAR CONTROLLER			; PJC038
	MOVB	U.UNIT(R5),-(SP)  ;GET CURRENT UNIT NUMBER		;**-1
	MOV	(SP)+,RMCS2(R2)	;RE-SELECT THE UNIT
	RETURN
XCUTE:	TST	U.CW3(R5)	;RK07 BLOCK NUMBER?			; PJC038
	BPL	600$		;IF PL NO, IT'S AN RK06			; PJC038
	BIS	#CDT,R0		;SET CDT FOR RK07		      	;**-2
600$:	MOV	R0,(R2)		;EXECUTE THE FUNCTION			; PJC038
	RETURN			;					;**-1


	.IF DF	R$$6OF							; PJC030
									; PJC030
;+									; PJC030
; DATA LATE RECOVERY							; PJC030
;									; PJC030
; THIS ROUTINE IS ENTERED IF A DATA LATE ERROR IS DETECTED. WE WILL	; PJC030
; BACK UP THE WORD COUNT, BUS ADDRESS AND CYLINDER/TRACK/SECTOR		; PJC030
; ADDRESS TO THE POINT OF ERROR AND RETRY THE TRANSFER FROM THERE. THIS	; PJC030
; IS DONE TO PREVENT A RECURRING DATA LATE ERROR DUE TO A LON      G TRANSFER.; PJC030
;-									; PJC030
DMDLT:	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX		; PJC030
	DECB	RTTBL(R3)	;ANY RETRIES LEFT?			; PJC030
	BGT	610$		;IF GT YES				; PJC038
	JMP	300$		;NO					; PJC038
610$:	MOV	RMWC(R2),R0	;GET NEGATIVE WORDS REMAINING		; PJC038
	BNE	620$		;IF NE, WE HAD A PARTIAL TRANSFER	; PJC038
	MOV	#-1,R0		;FAKE A PARTIAL TRANSFER		; PJC030
620$:	ASL	R0		;CONVERT TO NEGATIVE BYTES		; PJC038
	ADD	U.CNT(R5),R0	;CALCULATE BYTES ACTUALLY TRANSFERRED	; PJC030
	BIC	#777,R      0		;GET BLOCKS ACTUALLY TRANSFERRED	; PJC030
	SUB	R0,U.CNT(R5)	;REDUCE BYTES REMAINING TO TRANSFER	; PJC030
	BEQ	630$		;IF EQ, NONE LEFT			; PJC038
	ADD	R0,U.BUF+2(R5)	;UPDATE STARTING BUFFER ADDRESS		; PJC030
	ADCB	U.BUF+1(R5)	;PROPAGATE CARRY INTO EXTENSION BITS	; PJC030
									; PJC030
									; PJC030
	.IF DF	M$$EXT							; PJC030
									; PJC030
	ADD	#<S.MPR+M.LGTH>,R4 ;POINT PAST PHYSICAL BUFFER ADDRESS	; PJC030
				;CONTAINED IN UMR AREA			; PJC030
	ADD	R0,-(R4)	;CALCULATE NEW REAL AD      DRESS		; PJC030
	ADCB	-(R4)		;...					; PJC030
	MOV	U.SCB(R5),R4	;RESTORE ADDRESS OF SCB			; PJC030
									; PJC030
	.ENDC	;M$$EXT							; PJC030
									; PJC030
									; PJC030
	SWAB	R0		;CALCULATE THE NUMBER OF...		; PJC030
	ASR	R0		;... SECTORS TRANSFERRED		; PJC030
	CALL	DMCALC		;UPDATE THE DISK ADDRESS		; PJC030
	TST	U.CNT(R5)	;LAST BLOCK TRANSFERRED?		; PJC030
	BNE	640$		;IF NE NO				; PJC038
630$:	ADD	R0,U.CNT(R5)	;NORMALIZE BYTE COUNT			; PJC038
640$:				;REF LABEL				; PJC038
		      							; PJC030
									; PJC030
	.IF DF	E$$DVC							; PJC030
									; PJC030
	CALL	720$		;DEALLOCATE REGISTER CORE BLOCK		; PJC038
									; PJC030
	.ENDC								; PJC030
									; PJC030
									; PJC030
	JMP	80$		;FINISH THE I/O OPERATION		; PJC038
									; PJC030
;+									; PJC030
; CALCULATE UPDATED DISK ADDRESS					; PJC030
;									; PJC030
; THIS ROUTINE WILL CALCULATE THE NEW DISK ADDRESS BASED ON THE NUMBER	; PJC030
; OF BYTES ACTUALLY TRANSFERRED.					; PJC030
;-						      			; PJC030
DMCALC:	MOV	S.PKT(R4),R1	;GET ADRS OF I/O PACKET			; PJC030
	ADD	I.PRM+12(R1),R0	;UPDATE TRACK/SECTOR ADRS		; PJC030
650$:	CMPB	#22.,R0		;SECTOR OVERFLOW?			; PJC038
	BHI	660$		;IF HI NO				; PJC038
	SUB	#22.,R0		;SUBTRACT OUT A SECTOR			; PJC030
	ADD	#400,R0		;ADD IN A TRACK				; PJC030
	CMP	#3*400,R0	;TRACK OVERFLOW?			; PJC030
	BHI	650$		;IF HI NO				; PJC038
	SUB	#3*400,R0	;SUBTRACT OUT A TRACK			; PJC030
	INC	I.PRM+10(R1)	;UPDATE CYLINDER ADRS			; PJC030
	BR	650$		;					; PJC038      
660$:	MOV	R0,I.PRM+12(R1)	;SET UPDATED TRACK/SECTOR ADRS		; PJC038
	RETURN			;					; PJC030
									; PJC030
	.ENDC	;R$$6OF							; PJC030
									; PJC030
									; PJC030
	.IF DF	E$$DVC

;+
; **-DMDVXX-RK611-RK06/RK07 DISK CARTRIDGE CONTROLLER
;	ERROR LOGGING ROUTINES
;
; THIS ROUTINE IS CALLED WHENEVER A DEVICE ERROR OR DEVICE TIMEOUT
; OCCURS.  A CORE BLOCK THE SIZE OF THE REGISTER BUFFER IS
; ALLOCATED AND THE REGISTERS (INCLUDING THE SIX EXTRA MAINTENANCE
; REGISTERS) ARE TRANSFERED       INTO THE CORE BLOCK.  THEN THE CSR
; ADDRESS IN THE SCB IS SET TO THE CORE BLOCK ADDRESS AND THE
; APPROPRIATE EXECUTIVE ERROR LOGGING ROUTINE IS CALLED.  THE CORE
; BLOCK ADDRESS IS THEN USED AS A PSEUDO REGISTER BASE ADDRESS BY
; THE ERROR HANDLING ROUTINES.  BEFORE THE NEXT FUNCTION IS ISSUED,
; THE DEALLOCATION ROUTINE AT 190$ MUST BE CALLED TO DEALLOCATE THE
; CORE BLOCK AND RESTORE THE REAL CSR BASE ADDRESS.
;
; IF FOR ANY REASON THE CORE BLOCK CANNOT BE ALLOCATED THEN
; THE EXECUTIVE ERROR       LOGGING ROUTINE WILL NOT BE CALLED AND
; THE ERROR SEQUENCE NUMBER WILL BE UPDATED TO INDICATE THAT
; A MISSED ERROR CONDITION OCCURRED.
;
; NOTE:	IF ENTRY IS THE RESULT OF A DEVICE TIMEOUT THEN THIS
;	ROUTINE IS EXECUTED AT THE RK611 DEVICE PRIORITY LEVEL (PR5)
;	UNTIL THE EXEC ERROR LOGGING ROUTINE IS CALLED.
;
; INPUTS:
;	 R2 = CSR ADDRESS
;	 R4 = SCB ADDRESS
;
; OUTPUTS:
;	 R2 = ADDRESS OF REGISTER CORE BLOCK IF ONE WAS ALLOCATED
;	      OR CSR ADDRESS IF ONE WAS NOT.
;	 R4 = SCB ADDRESS      
;
;	 R0,R3 ARE PRESERVED ACROSS CALL
;-
DMDVER:	MOV	#$DVERR,R1	;GET ADRS OF DEVICE ERROR ROUTINE
	BR	670$		;					; PJC038
DMDVTO:	MOV	#$DTOER,R1	;;;GET ADRS OF DEVICE TIMEOUT ROUTINE	;**-1
670$:	MOV	R3,-(SP)	;PRESERVE CONTROLLER INDEX		; PJC038
	MOV	R0,-(SP)	;SAVE I/O STATUS CODE			;**-1
	MOV	R2,-(SP)	;SAVE CSR ADDRESS
	MOV	R1,-(SP)	;SET CO-ROUTINE ADDRESS
	MOV	#RMCNT*2,R1	;GET NUMBER OF BYTES TO ALLOCATE
	CALL	$ALOCB		;ALLOCATE A CORE BLOCK
	BCC	680$		;IF CC, BLOCK WAS ALLOCATED		; PJC038
	IN      C	$ERRSQ		;INDICATE A MISSED ERROR CONDITION	;**-1
	CMP	(SP)+,#$DTOER	;ALLOCATION FAILURE, TIMEOUT IN PROGRESS?
	BNE	690$		;IF NE, DON'T LOG ERROR			; PJC038
	BIC	#CERR!IE,@S.CSR(R4)  ;;;CLEAR IE WITHOUT DOING A CCLR	;**-1
	MTPS	#0		;;;ALLOW INTERRUPTS
	BR	690$		;DON'T LOG ERROR IF ALLOCATION FAILURE	; PJC038
680$:	MOV	R0,S.CSR(R4)	;REPLACE CSR WITH ADDRESS OF CORE BLOCK	; PJC038
	MOV	2(SP),R2	;GET REAL CSR ADDRESS			;**-2
	CALL	DMRPAS		;XFER THE REGISTERS
	CALL	@(SP)+		;CALL THE EXEC ERROR LOGGING       ROUTINE
	MOV	S.CSR(R4),R0	;GET ADDRESS OF CORE BLOCK
	MOV	(SP),S.CSR(R4)	;RESTORE CSR ADDRESS
	MOV	R0,(SP)		;PUT CORE BLOCK ADRS IN SAVED CSR ADRS
690$:	MOV	(SP)+,R2	;RESTORE CSR ADDRESS			; PJC038
700$:	MOV	(SP)+,R0	;RESTORE I/O STATUS CODE		; PJC038
	MOV	(SP)+,R3	;RESTORE CONTROLLER INDEX		;**-2
710$:	RETURN			;					; PJC038
720$:	CMP	R2,S.CSR(R4)	;SHOULD WE DEALLOCATE?			; PJC038
	BEQ	710$		;IF EQ NO				; PJC038
	MOV	R3,-(SP)	;SAVE CONTROLLER INDEX			;**-4
	MOV	R0,-(SP)	;SAVE POSSIBLE I/O STA      TUS CODE
	MOV	#RMCNT*2,R1	;GET NUMBER OF BYTES TO DEALLOCATE
	MOV	R2,R0		;SET ADDRESS OF CORE BLOCK IN R0
	CALL	$DEACB		;DEALLOCATE THE BLOCK
	MOV	S.CSR(R4),R2	;RESET REAL CSR ADDRESS
	BR	700$		;					; PJC038
									;**-1
	.ENDC


	.IF DF	E$$DVC!D$$IAG

;+
; **-DMRPAS-RK611-RK06/RK07 DISK CARTRIDGE CONTROLLER
;	CONTROLLER REGISTER PASS ROUTINE
;
; THIS ROUTINE WILL TRANSFER THE CONTENTS OF THE CONTROLLER
; REGISTERS (INCLUDING THE SIX EXTRA MAINTENANCE REGISTERS)
; INTO A PREVIOUSLY ALLO      CATED BUFFER.
;
; INPUTS:
;	 R0 = BUFFER ADDRESS
;	 R2 = CSR ADDRESS
;	 R5 = UCB ADDRESS
; OUTPUTS:
;	 R2 = CSR ADDRESS
;	 R3 = DESTROYED
;-
DMRPAS:	MOV	#^D<14>,R3	;LOOP COUNT FOR MAJOR REGISTERS
	MOV	R2,-(SP)	;SAVE CSR ADDRESS
730$:	MOV	(R2)+,(R0)+	;TRANSFER THE REGISTER			; PJC038
	DEC	R3		;HAVE TRANSFERRED ONE MORE		; PJC038
	BNE	730$		;IF NE, KEEP GOING			; PJC038
	MOV	(SP)+,R2	;RESTORE CSR ADDRESS			;**-3
740$:	CALL	590$		;CLEAR CONTROLLER			; PJC038
	MOV	R3,RMMR1(R2)	;SELECT DRIVE SER      IAL MESSAGE		;**-1
	CALL	560$		;SELECT DRIVE TO GET PROPER MESSAGE	; PJC038
	MOV	RMMR2(R2),(R0)+	;SAVE CONTENTS OF MR2			;**-1
	MOV	RMMR3(R2),(R0)+	;SAVE CONTENTS OF MR3
	INC	R3		;INCREMENT DRIVE SERIAL MESSAGE COUNT
	CMP	R3,#4		;DONE FOUR MESSAGES YET?
	BNE	740$		;NO, LOOP				; PJC038
	CALL	590$		;CLEAR CONTROLLER			; PJC038
	CALLR	550$		;FINISH UP BY CLEARING THE DRIVE	; PJC038
									;**-3
	.ENDC


	.IF DF	D$$IAG

;+
; **-DMDINT-RK611-RK06/RK07 DISK CARTRIDGE CONTROLLER
;	DIAGNOSTIC IN      TERRUPT HANDLER
;
; THIS SUBROUTINE HANDLES INTERUPTS FROM DIAGNOSTIC OPERATIONS.
; IF THE FUNCTION WAS DIAGNOSTIC THEN THE DEVICE REGISTERS
; ARE PASSED BACK TO THE DIAGNOSTIC TASK, THE CONTROLLER (VIA DMRPAS)
; AND THE DRIVE ARE CLEARED AND THE I/O STATUS IS RETURNED.
;
; INPUTS:
;	R2 = ADRS OF CSR
;	R4 = ADRS OF SCB
;	R5 = ADRS OF UCB
;
; OUTPUTS:
;	R1 = I/O PACKET ADDRESS (IF DIAGNOSTIC FUNCTION)
;	R2 = ADDRESS OF CSR
;	R4 = ADDRESS OF SCB
;	C = 1 IF INTERRUPT WAS FROM DIAGNOSTIC FUNCTIO      N
;
;	R0,R3 ARE PRESERVED ACROSS CALL
;-
DMDINT:	MOV	R3,-(SP)	;PRESERVE CONTROLLER INDEX
	MOV	S.PKT(R4),R3	;GET ADRS OF I/O PACKET
	CLC			;ASSUME NOT DIAGNOSTIC INTERRUPT
	BITB	#IQ.UMD,I.FCN(R3)  ;DIAGNOSTIC FUNCTION?
	BEQ	770$		;IF EQ NO, EXIT				; PJC038
	MOV	R0,-(SP)	;SAVE CURRENT I/O STATUS CODE		;**-1
	TSTB	R0		;WAS THIS A SUCCESSFUL INTERRUPT?
	BPL	750$		;IF PL YES				; PJC038
	CALL	$DTOER		;;;TIMEOUT, CLEAN-UP AFTER IT		;**-1
	BR	760$		;JUST PASS THE REGISTERS		; PJC038
750$:	CMP	#IO.RD      H!IQ.UMD,I.FCN(R3) ;READ HEADERS?			; PJC038
	BNE	760$		;IF NE NO, PROCESS NORMAL		; PJC038
	CLR	R0		;CLEAR BYTE OFFSET INTO BUFFER		;**-3
	CALL	$RELOP		;RELOCATE PHYSICAL ADDRESS
	MOV	RMDB(R2),(R1)+	;TRANSFER FIRST HEADER WORD
	MOV	RMDB(R2),(R1)+	;TRANSFER SECOND HEADER WORD
	MOV	RMDB(R2),(R1)+	;TRANSFER THIRD HEADER WORD
760$:	MOV	R3,R1		;SAVE I/O PACKET ADDRESS		; PJC038
									;**-1

	.IF DF	M$$MGE

	MOV	I.PRM+14(R3),KISAR6  ;SET BUFFER RELOCATION BIAS

	.ENDC


	MOV	I.PRM+16(R3),R0	;     GET REGISTER BUFFER ADDRESS
	CALL	DMRPAS		;PASS THE CONTROLLER REGISTERS
	SEC			;SET DIAGNOSTIC INTERRUPT RETURN
	MOV	(SP)+,R0	;RESTORE I/O STATUS CODE
770$:	MOV	(SP)+,R3	;RESTORE CONTROLLER INDEX		; PJC038
	RETURN								;**-1

	.ENDC


	.DSABL	LSB
	.END

         Óp:kQ	› c,        	.TITLE	DRCIN
	.IDENT	/02.02/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 02.02
;
; P. WANNHEDEN 24-MAY-77
;
; PREVIOUSLY MODIFIED BY:
;
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	1-OCT-79
;		MSH045 -- ENSURE THAT ENABLE/DISABLE ROUTINE IS CALLED
;			  FROM EXECUTIVE SPACE RATHER THAN DIRECTIVE
;			        COMMON SPACE
;
;	M. S. HARVEY	26-JUN-81
;		MSH147 -- CORRECT ERROR LOGGING CONDITIONAL SYMBOL
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,TCBDF$,PCBDF$,ITBDF$
	HWDDF$			; DEFINE HARDWARE REGISTERS
	TCBDF$			; DEFINE TCB OFFSETS
	PCBDF$			; DEFINE PCB OFFSETS
	ITBDF$			; DEFINE ITB OFFSETS

;+
; **-$DRCIN-CONNECT TO INTERRUPT.
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CONNECT A SPECIFIED INTERRUPT
; VECTOR TO AN INTERRUPT SERVICE ROUTINE (ISR) IN THE TASK'S OWN SPACE,
; OR TO DISCONNECT A       PREVIOUSLY CONNECTED INTERRUPT VECTOR.
;
; IF THE FUNCTION "CONNECT" IS REQUESTED, THE OPERATION IS AS FOLLOWS:
; A BLOCK OF DYNAMIC MEMORY IS ALLOCATED AND SET UP AS AN INTERRUPT
; TRANSFER BLOCK (ITB). THE ITB IS LINKED TO THE ITB LIST OF THE
; TASK WITH LISTHEAD (SINGLE WORD!!) IN T.CPCB OF THE TCB.
; CHECKPOINTING AND SHUFFLING IS DISABLED FOR THE TASK.
; THE VECTOR IS SET UP TO POINT TO THE OFFSET X.JSR IN THE ITB,
; WHICH CONTAINS A SUBROUTINE CALL TO THE SPECIAL INTERRUPT SAVE
; ROUTINE $INT      SC.
;
; IF THE FUNCTION "DISCONNECT" IS REQUESTED, THE OPERATION IS
; ESSENTIALLY THE REVERSE OF WHAT IS DESCRIBED FOR "CONNECT".
;
;	*************************************************
;	*   NOTE - THE DISCONNECT FUNCTION, WHEN	*
;	*   DISCONNECTING THE LAST VECTOR (OR		*
;	*   ONLY), CLEARS THE CHECKPOINT-DISABLE	*
;	*   BIT (T2.CKD) AND NO-SHUFFLE BIT (PS.NSF)	*
;	*   REGARDLESS OF WHAT THE STATE WAS BEFORE	*
;	*   VECTORS WERE CONNECTED OR ANY CHANGE IN	*
;	*   STATE WHILE VECTORS WERE CONNECT      ED.		*
;	*   (EXCEPTION - IF THE TASK IS MARKED FOR	*
;	*   ABORT BECAUSE OF MEMORY PARITY ERROR,	*
;	*   IT IS NOT MADE SHUFFLABLE).			*
;	*************************************************
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(129.),DPB SIZE(7.).
;	WD. 01 -- INTERRUPT VECTOR ADDRESS.
;	WD. 02 -- BASE ADDRESS FOR MAPPING OF ISR AND
;		  ENABLE/DISABLE-INTERRUPT ROUTINES.
;		  IGNORED IN AN UNMAPPED SYSTEM.
;	WD. 03 -- ADDRESS OF INTERRUPT SERVICE ROUTINE. IF ZERO, DIRECTIVE
;		  IS "DISCONNECT FRO      M INTERRUPTS" AND REMAINING ARGUMENTS
;		  ARE IGNORED.
;	WD. 04 -- ADDRESS OF ENABLE/DISABLE-INTERRUPT ROUTINE.
;	WD. 05 -- (LOW BYTE) LOW BYTE OF PSW TO BE SET
;		  BEFORE CALLING ISR.
;	WD. 06 -- ADDRESS OF AST ROUTINE.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=POINTER TO WD. 01 IN DPB
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK).
;
;	IF SUCCESSFUL COM      PLETION:
;	CC-C	0
;	DIRECTIVE STATUS:
;		+1
;	BEFORE RETURN, THE ENABLE/DISABLE-INTERRUPTS ROUTINE
;	(IF SPECIFIED) IS CALLED IN KERNEL MODE WITH CC-C CLEAR.
;
;	IF DIRECTIVE IS REJECTED:
;	CC-C	1
;	DIRECTIVE STATUS:
;		D.RS1	AN ITB COULD NOT BE ALLOCATED (NO POOL SPACE).
;		D.RS8	THE FUNCTION REQUESTED IS "DISCONNECT"
;			AND THE TASK IS NOT OWNER OF THE VECTOR.
;		D.RS16	ISSUING TASK IS NOT PRIVILEGED.
;		D.RS17	THE SPECIFIED VECTOR IS ALREADY IN USE.
;		D.RS19	THE SPECIFIED VECTOR IS ILLEG      AL (LOWER THAN 60
;			OR HIGHER THAN HIGHEST VECTOR SPECIFIED AT SYSGEN,
;			OR NOT A MULTIPLE OF 4).
;		D.RS81	ISR OR ENABLE/DISABLE-INTERRUPT ROUTINE IS NOT
;			WITHIN 4K WORDS FROM (BASE ADDRESS & 177700).
;-

	.IF DF	C$$INT

	.ENABL	LSB

$DRCIN::

	.IF DF	M$$MGE

	BIT	#T3.PRV,T.ST3(R5) ; IS TASK PRIVILEGED?
	BEQ	95$		; N - ILLEGAL, JUMP

	.ENDC


	MOV	(R3)+,R4	; GET VECTOR ADDRESS
	BIT	#3,R4		; MULTIPLE OF 4?
	BNE	60$		; N - ILLEGAL VECTOR, JUMP
	CMP	R4,#60		; VECTOR IN RANGE?
	      BLO	60$		; N - JUMP
	CMP	R4,#V$$CTR
	BHIS	60$		; N - JUMP
	MOV	(R3)+,R0	; GET BASE ADDRESS
	MOV	(R3)+,-(SP)	; GET ISR ADDRESS
	BEQ	40$		; ZERO - DISCONNECT, JUMP
;
; DIRECTIVE IS "CONNECT"
;

	.IF NDF	E$$LOG							;MSH147
									;**-1
	CMP	@R4,#$NONSI	; VECTOR IN USE?
	BNE	70$		; Y - ILLEGAL, JUMP

	.IFF

	CMP	@R4,#$NONSI	;VECTOR IN USE?
	BEQ	10$		;IF EQ NO, CONTINUE PROCESSING
	CMP	@R4,#$NS0	; VECTOR IN USE?
	BLO	70$		; Y - ILLEGAL, JUMP
	CMP	@R4,#$NS7
	BHI	70$		; Y - ILLEGAL, JUMP      

	.ENDC

10$:	BIT	#T2.CKD,@R2	; CHECKPOINTING DISABLED?
	BNE	15$		; Y - JUMP
	BIS	#T2.CKD,@R2	; N - DO IT
	CLR	T.CPCB(R5)	; INITIALIZE LIST OF ITB'S
15$:

	.IF DF	D$$YNM & D$$SHF

	MOV	T.PCB(R5),R1	; GET PCB
	BIT	#PS.SYS,P.STAT(R1) ; SYSTEM CONTROLLED?
	BEQ	20$		; N - JUMP
	BIS	#PS.NSF,P.STAT(R1) ; SET NON-SHUFFLABLE
20$:

	.ENDC


	.IF DF	M$$MGE

	BIC	#77,R0		; CLEAR LOWER 6 BITS IN BASE ADDRESS
	CALL	$RELOC		; RELOCATE TO APR 6 ADDRESS
	SUB	#20000,R2	; RELOCATE TO APR 5 ADDRESS
	      BCS	90$		; OUT OF RANGE - JUMP
	SUB	R0,@SP		; GET DISPLACEMENT FROM "BASE" TO "ISR"
	CMP	@SP,#20000	; .GT. 4K WORDS?
	BHIS	90$		; Y - ILLEGAL, JUMP

	.IFTF

	MOV	(R3)+,-(SP)	; GET ENB./DIS.INT. ROUTINE ADDRESS

	.IFT

	BEQ	30$		; NO SUCH ROUTINE - JUMP
	SUB	R0,@SP		; GET DISPLACEMENT FROM BASE
	BCS	90$		; OUT OF RANGE - JUMP
	CMP	@SP,#20000	; .GT. 4K WORDS?
	BHIS	90$		; Y - ILLEGAL, JUMP
	ADD	R2,@SP		; MAKE APR 5 ADDRESSES
30$:	ADD	R2,2(SP)
	MOV	R1,-(SP)	; SAVE APR 5 VALUE

	.IFTF

	MO      V	#X.LEN,R1	; GET SIZE OF ITB IN BYTES
	CALL	$ALOCB		; ALLOCATE AN ITB
	BCS	80$		; FAILURE - JUMP
	MOV	T.CPCB(R5),@R0	; LINK ITB TO ITB LIST IN TCB (X.LNK)
	MOV	R0,T.CPCB(R5)
	TST	(R0)+		; STEP PAST LINK WORD IN ITB
	MOV	R0,R1		; SAVE INTERRUPT ENTRY POINT
	MOV	#4537,(R0)+	; "JSR R5,@#$INTSC" (X.JSR)
	MOV	#$INTSC,(R0)+	; (X.JSR+2)
	MOV	(R3)+,@R0	; PSW AND UNUSED BYTE (X.PSW)

	.IFT

	ADD	#X.REL-X.PSW,R0	; POINT TO X.REL IN ITB
	MOV	(SP)+,(R0)+	; STORE APR 5 VALUE (X.REL)

	.IFF

	ADD	#X.DS      I-X.PSW,R0	; POINT TO X.DSI IN ITB

	.ENDC								;MSH045
									;**-1
	MOV	(SP)+,(R0)+	; STORE ENB./DIS.INT. ROUTINE ADDRESS (X.DSI)
	MOV	R5,(R0)+	; STORE TCB ADDRESS (X.TCB)
	MOV	(SP)+,X.ISR-<X.TCB+2>(R0) ; STORE ISR ADDRESS (X.ISR)
	CLR	X.FORK+2-<X.TCB+2>(R0) ; CLEAR FORK PC WORD (X.FORK+2)

	.IF DF	A$$TRP

	MOV	#$DQAC,(R0)+	; STORE ADDRESS OF ROUTINE TO DEQUEUE
				; AST BLOCK QUEUED BY $QASTC
	TST	(R0)+		; STEP PAST AST QUEUE THREAD WORD
	MOV	PC,(R0)+	; SET NON-ZERO TO INDICATE
				; A      ST BLOCK FREE (A.CBL)
	MOV	#7*2+2,(R0)+	; NUMBER OF WORDS TO ALLOCATE ON AST STACK
				; (A.BYT)
	MOV	@R3,(R0)+	; AST ADDRESS (A.AST)
	MOV	#1,(R0)+	; NUMBER OF AST PARAMETERS = 1 (A.NPR)

	.ENDC

	MOV	R4,(R0)+	; AST PARAMETER = VECTOR ADDRESS (X.VEC)
	MOV	@R4,@R0		; SAVE VECTOR PC (X.VPC)
	MOV	R1,@R4		; SET VECTOR TO POINT TO ITB
	TST	-(R1)		; BACK UP TO START OF ITB AND CLEAR CC-C
35$:	MOV	X.DSI(R1),R2	; GET ADDRESS OF USER ROUTINE TO
				; ENABLE/DISABLE INTERRUPTS
	BEQ	130$		; NONE - EXIT
      	CALLR	$CITFR		;CALL ROUTINE FROM EXEC SPACE		;MSH045
;									;**-11
;
; DIRECTIVE IS "DISCONNECT"
;
40$:	MOV	@R4,R1		; GET PC FROM VECTOR
	SUB	#X.JSR,R1	; GET START OF ITB (X.LNK)
	BIT	#T2.CKD,@R2	; CHECKPOINTING DISABLED?
	BEQ	100$		; N - TASK HAS NO ITB'S, JUMP
	CALL	$DISIN		; DISABLE INTERRUPTS, DEALLOCATE THE
				; ITB ETCETERA
	BCS	100$		; ERROR (TASK IS NOT OWNER OF VECTOR) - JUMP
	DRSTS	+1		; EXIT WITH SUCCESS

60$:	DRSTS	D.RS19		; ILLEGAL VECTOR
70$:	DRSTS	D.RS17		; VECTOR ALREADY       IN USE
80$:	DRSTS	D.RS1		; NO POOL SPACE

	.IF DF	M$$MGE

90$:	DRSTS	D.RS81		; ISR OR ENB./DIS.INT. ROUTINE ADDRESS NOT
				; WITHIN RANGE (BASE&177700, BASE&177700+4K)
95$:	DRSTS	D.RS16		; PRIVILEGE VIOLATION

	.ENDC

100$:	DRSTS	D.RS8		; DISCONNECT - TASK IS NOT OWNER OF VECTOR
;
;
;+
; **-$DISIN-DISCONNECT INTERRUPT VECTOR.
;
; INPUT:
;	R1	POINTER TO ITB
;	R5	POINTER TO TASK TCB
;
; OUTPUT:
;	IF SUCCESS:
;	CC-C	0
;	THE FOLLOWING OPERATIONS ARE PERFORMED:
;	1. THE ITB IS REMOVED F      ROM THE ITB LIST STARTING
;	   IN T.CPCB OF THE TASK'S TCB.
;	2. IF A USER ROUTINE TO DISABLE INTERRUPTS WAS SUPPLIED
;	   WHEN THE VECTOR WAS CONNECTED TO, THAT ROUTINE IS CALLED
;	   IN KERNEL MODE WITH CC-C SET.
;	3. VECTOR PC IS RESTORED TO POINT TO THE NONSENSE INTERRUPT ROUTINE.
;	4. IF THE FORK BLOCK OF THE ITB IS IN THE FORK QUEUE, IT
;	   IS REMOVED.
;	5. IF THE AST BLOCK OF THE ITB IS IN THE AST QUEUE FOR THE TASK,
;	   IT IS REMOVED.
;	6. IF THIS WAS THE ONLY VECTOR CONNECTED TO THE TAS      K,
;	   CHECKPOINTING IS ENABLED FOR THE TASK. IF THE TASK RUNS IN
;	   A SYSTEM CONTROLLED PARTITION, THE TASK IS MADE SHUFFLABLE.
;	7. FINALLY, THE ITB IS DEALLOCATED.
;
;	IF ERROR (TASK IS NOT OWNER OF VECTOR):
;	CC-C	1
;
; REGISTERS ALTERED: R0,R1,R2,R3
;-
;
;
$DISIN::MOV	R5,R0		; GET TCB
	ADD	#T.CPCB,R0	; POINT TO ITB LISTHEAD
	MOV	2(R0),-(SP)	; SAVE WORD FOLLOWING LISTHEAD
	CALL	$QRMVT		; REMOVE FROM ITB LIST
	MOV	(SP)+,2(R0)	; RESTORE WORD FOLLOWING LISTHEAD
	BCS	130$		; ITB NOT IN L      IST - EXIT WITH ERROR
	SEC
	CALL	35$		; CALL USER ROUTINE TO DISABLE INTERRUPTS
				; WITH CC-C SET
	MOV	X.VPC(R1),@X.VEC(R1) ; RESTORE VECTOR PC
	ADD	#X.FORK,R1	; POINT AT FORK BLOCK IN ITB
	MOV	#$FRKHD,R0	; GET FORK LISTHEAD
	MTPS	#PR7		; DISABLE INTERRUPTS
	CALL	$QRMVT		;;; REMOVE FROM FORK LIST IF IT IS THERE
	MTPS	#0		;;; ENABLE INTERRUPTS

	.IF DF	A$$TRP

	ADD	#X.AST-X.FORK,R1 ; POINT AT AST BLOCK IN ITB
	MOV	R5,R0
	ADD	#T.ASTL,R0	; GET AST LIST LISTHEAD
	CALL	$QRMVT		; REMOVE FROM AST       LIST IF IT IS THERE
	SUB	#X.AST,R1	; RESTORE ITB POINTER

	.IFF

	SUB	#X.FORK,R1	; RESTORE ITB POINTER

	.ENDC

	MOV	R1,R0		; GET ITB POINTER IN R0
	TST	T.CPCB(R5)	; ITB LIST NOW EMPTY?
	BNE	120$		; N - JUMP
	BIC	#T2.CKD,T.ST2(R5) ; Y - ENABLE CHECKPOINTING

	.IF DF	D$$YNM & D$$SHF

	MOV	T.PCB(R5),R1	; GET PCB
	BIT	#PS.SYS,P.STAT(R1) ; SYSTEM CONTROLLED PARTITION?
	BEQ	120$		; N - JUMP
	BIT	#T2.ABO,T.ST2(R5) ; TASK MARKED FOR ABORT?
	BEQ	110$		; N - JUMP
	CMP	T.EFLG(R5),#S.PRTY ; Y - I     S REASON MEMORY PARITY ERROR?
	BEQ	120$		; Y - DON'T MAKE SHUFFLABLE
110$:	BIC	#PS.NSF,P.STAT(R1) ; MAKE SHUFFLABLE

	.ENDC

120$:	MOV	#X.LEN,R1	; GET LENGTH OF ITB
	CALL	$DEACB		; DEALLOCATE ITB
	CLC			; SUCCESS
130$:	RETURN

	.DSABL	LSB

	.ENDC


	.END
         äðskQ	› c,        	.TITLE	DLDRV
	.IDENT	/02.11/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 02.11
;
; P. J. BEZEREDI   07-OCT-77
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;
; MODIFIED BY:
;
;	P. J. BEZEREDI 03-DEC-79
;
;		PB141 -- CONDITIONALIZE WRITE CHECK SUPPORT.
;
;	P. J. BEZEREDI 06-DEC-79
;
;		PB144 -- RETURN IE.BBE IF       MANUFACTURER BAD HEADER IS FOUND.
;
;	R. T. PERRON 12-DEC-79
;
;		RP026 -- CORRECT MULTI-CONTROLLER OPERATION
;
;	R. T. PERRON 15-JAN-80
;
;		RP027 -- CORRECT OPERATION WHEN WRITE CHECK SUPPORT DISABLED
;
;	P. J. CARR	25-NOV-80
;
;		PJC008 -- ADD SUPPORT FOR 22-BIT SYSTEMS WITHOUT
;			  AN I/O MAP
;
;	P. J. CARR	3-APR-81
;
;		PJC021 -- ADD EIS SUPPORT
;
;	P. J. CARR	8-APR-81
;
;		PJC028 -- CORRECT ISR HANDLING OF REVERSE SEEKS
;
;	P. J. CARR	11-MAY-81
;
;		PJC018 -- CHANGE SUPPORT       FOR NEW ERROR LOGGER
;
;	P. J. CARR	12-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
;	P. J. CARR	8-SEP-81
;
;		PJC017 -- ADD VOLUME CHECKING FOR RTEM-11
;
;	P. J. CARR	22-OCT-81
;
;		PJC038 -- CLEAN UP CODE
;
; RL11/RL01 DISK DRIVER
;
;
.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
;
;****************
;
; EQUATED SYMBOLS
;
RETRY=	^D<8>			;CONTROLLER ERROR RETRY COUNT
									; PJC018
									; PJC018
	.IF DF	M$$EXT							;       PJC018
									; PJC018
RLCNT=	^D<7>			;ERROR LOGGING REGISTER COUNT		; PJC018
									; PJC018
	.IFF								; PJC018
									; PJC018
RLCNT=	^D<5>			;ERROR LOGGING REGISTER COUNT		; PJC018
									; PJC018
	.ENDC								; PJC018
									; PJC018
									; PJC018
RLBPT=	^D<512*20>		;BYTES PER RL01 SURFACE			;**-1


	.IF DF	D$$IAG


				;NO DIAGNOSTIC FUNCTIONS YET

	.ENDC


;
;****************
;
; RL11 DEVICE REGISTER OFFSETS
;
RLCS=	0			;CONTROL STATUS REGISTER
RLBA=	2			;      BUS ADDRESS REGISTER
RLDA=	4			;DISK ADDRESS REGISTER
RLMP=	6			;MULTI-PURPOSE REGISTER
RLBAE=	10			;ADRS EXT REGISTER FOR Q22 SYSTEM	; PJC008
;
;****************
;
; RLCS BIT ASSIGNMENTS
;
ERR=	100000			;COMPOSITE ERROR
DE=	040000			;DRIVE ERROR
NXM=	020000			;NON-EXISTANT MEMORY
DLT=	010000			;DATA LATE
HNF=	010000			;HEADER NOT FOUND
DCK=	004000			;DATA CHECK ERROR
HCRC=	004000			;HEADER CRC ERROR
OPI=	002000			;OPERATION INCOMPLETE
DRDY=	1			;DRIVE READY
WCHK=	2			;WRITE CHECK FUNCTION      
WRITE=	2			;WRITE OFFSET
GSTS=	4			;GET DRIVE STATUS FUNCTION
SEEK=	6			;SEEK FUNCTION
RDH=	10			;READ HEADERS FUNCTION
READ=	14			;READ DATA FUNCTION
IE=	100			;INTERRUPT ENABLE
CRDY=	200			;CONTROLLER READY
;
;****************
;
; RLDA STATUS CODES
;
MRK=	1			;MARKER BIT
STS=	2			;GET STATUS BIT
SN=	4			;SIGN BIT FOR SEEK
RST=	10			;DRIVE RESET BIT
HS=	20			;HEAD SELECT BIT FOR DIFFERENCE
REV=	200!MRK			;REVERSE SEEK DIFFERENCE WORD
;
;****************
;
; RLMP GET STATUS BIT ASSIGN      MENTS
;
WDE=	100000			;WRITE DATA ERROR
CHE=	040000			;CURRENT HEAD ERROR
WLS=	020000			;WRITE LOCK STATUS
SKTO=	010000			;SEEK TIMEOUT ERROR
SPD=	004000			;SPEED ERROR
WGE=	002000			;WRITE GATE ERROR
VC=	001000			;VOLUME CHECK
DSE=	000400			;DRIVE SELECT ERROR
DT=	000200			;DRIVE TYPE
HSS=	000100			;HEAD SELECT STATUS
CO=	000040			;COVER OPEN
HH=	000020			;HEADS HOME
BH=	000010			;BRUSHES HOME
SLM=	000005			;DRIVE IN SEEK-LINEAR MODE STATE
;
;****************
;
; LOCAL DATA
;
; CONTROL      LER IMPURE DATA TABLES
; THESE ARE INDEXED BY THE CONTROLLER NUMBER
;
CNTBL:	.BLKW	R$$L11		;ADRS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$L11		;RETRY COUNT FOR CURRENT OPERATION
									; PB141
									; PB141
	.IF DF	D$$WCK							; PB141
									; PB141
PRMSV:	.BLKW	R$$L11*6	;PARAMETER SAVE AREA FOR WRITE CHECK	; PJC008
									; PB141
	.ENDC								; PB141
									;**-1

	.IF GT	R$$L11-1

TEMP:	.BLKW	1		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC


;
;****************
;
;      DRIVER DISPATCH TABLE
;
$DLTBL::.WORD	DLINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DLCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DLOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DLPWF		;POWERFAIL ENTRY POINT
;
;****************
;
;+
; **-DLINI-RL11/RL01 DISK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O
; REQUEST IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO
; PROPAGATE THE EXECUTION OF THE DRIVER.  IF THE SPECIFIED CONTROLLER
; IS NOT BUSY, THE      N AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST.
; ELSE A RETURN TO THE CALLER IS EXECUTED.  IF THE DEQUEUE ATTEMPT
; IS SUCCESSFUL, THEN THE NEXT I/O OPERATION IS INITIATED.  A RETURN
; TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;	R5= ADRS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS
;	WAITING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE
;	DRIVER INITIATES THE REQUESTED I/O FUNCTION
;-
	.ENABL	LSB
DLI      NI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCC	10$		;IF CC PROCESS REQUEST			; PJC038
	RETURN			;RETURN IF BUSY OR NO REQUEST		;**-1
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1= ADRS OF THE I/O REQUEST PACKET
;	R2= PHYSICAL UNIT NUMBER OF THE REQUESTED DRIVE
;	R3= CONTROLLER INDEX
;	R4= ADRS OF THE STATUS CONTROL BLOCK (SCB)
;	R5= ADRS OF THE UCB OF THE DRIVE TO BE INITIATED
;
; RL11/RL01 DISK CONTROLLER I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD
;	WD.       01 -- REQUEST PRIORITY, EVENT FLAG NUMBER
;	WD. 02 -- ADRS OF THE TCB OF THE REQUESTOR TASK
;	WD. 03 -- POINTER TO 2ND LUN WORD IN REQUESTOR TASK HEADER
;	WD. 04 -- CONTENTS OF FIRST LUN WORD (UCB ADRS)
;	WD. 05 -- I/O FUNCTION CODE
;	WD. 06 -- VIRTUAL ADRS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O STATUS BLOCK ADRS (REAL OR DISPL.+140000)
;	WD. 11 -- VIRTUAL ADRS OF AST SERVICE ROUTINE
;	WD. 12 -- MEMORY EXTENSION BITS OF I/O TRANSFER
;	WD. 13 -- BUFFER A      DRS OF I/O TRANSFER
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED
;	WD. 15 -- NOT USED.
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE IS NOT USED
;	WD. 17 -- LOW PART OF LOGICAL BLK NUMBER OF I/O REQUEST
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLK. ELSE NOT USED
;	WD. 21 -- DIAGNOSTIC REG BLK ADR (REAL OR DSPL+140000) ELSE NOT USED
;
; DRIVER USAGE OF WORDS IN I/O PACKET:
;	I.PRM+6	 (WD. 15) - EXTENDED ADDRESS BITS			; PJC018
;	I.PRM+10 (WD. 16) - STARTING DISK ADDRESS FOR THIS TRANSFER	;*      *-1
;	I.PRM+12 (WD. 17) - BYTES REMAINING TO TRANSFER			; PJC018
;									;**-1
;****************
;
; THIS SECTION CALCULATES THE ACTUAL DISK ADDRESS FROM THE
; LOGIGAL BLOCK INFORMATION SUPPLIED IN THE I/O PACKET.  IT ALSO
; DETERMINES THE FUNCTION TO PERFORM (DIAGNOSTIC OR READ/WRITE).
;
10$:	MOV	R5,CNTBL(R3)	;SAVE ADRS OF REQUEST UCB		; PJC038
	MOV	#RETRY,RTTBL(R3) ;SET INITIAL RETRY COUNT		; PJC018
									; PJC017
									; PJC017
	.IF DF	A$$HDR							; PJC017
									; PJC017
	CALL	      DLVOL		;SET CHARACTERISTICS (IO.STC) FUNCTION?	; PJC017
	BCS	40$		;IF CS YES				; PJC038
									; PJC017
	.ENDC								; PJC017
									;**-1

	.IF DF	M$$EXT							; PJC008
									; PJC008
	BIT	#DV.EXT,U.CW1(R5) ;BAE EXIST?				; PJC008
	BEQ	20$		;IF EQ NO				; PJC038
	MOVB	U.BUF+1(R5),R0	;GET ADRS EXT BITS			; PJC008
	MOVB	R0,I.PRM+6(R1)	;STORE FOR BUS ADRS EXT REGISTER	; PJC018
									; PJC021
									; PJC021
	.IF DF	M$$EIS							; PJC021
									; PJC021
	ASH	#4,R0		;SHIFT ADRS E      XT BITS			; PJC021
									; PJC021
	.IFF								; PJC021
									; PJC021
	.REPT	4							; PJC008
	ASL	R0		;SHIFT ADRS EXT BITS			; PJC008
	.ENDR								; PJC008
									; PJC021
	.ENDC								; PJC021
									; PJC021
									; PJC021
	BICB	#^C<60>,R0	;ISOLATE AE BITS 16 AND 17		; PJC008
	MOVB	R0,U.BUF(R5)	;STORE IN FUNCTION CODE WORD		; PJC008
	BR	30$		;DON'T CALL $STMAP			; PJC038
20$:	CALL	$STMAP		;SET UP 11/70 UNIBUS MAPPING REGISTERS	; PJC038
									; PJC008
	.ENDC								; PJC      008
									; PJC008
									; PJC008
30$:	MOVB	R2,U.BUF+1(R5)	;SET CURRENT UNIT NUMBER		; PJC038
	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION		;**-8
	BIS	#READ!IE,U.BUF(R5)  ;ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/^D<256>,I.FCN+1(R1)  ;REALLY?
	BHIS	50$		;IF HIS FUNCTION IS LEGAL		; PJC038
40$:	JMP	350$		;EXIT					; PJC038
50$:	BEQ	60$		;IF EQ YES				; PJC038
	SUB	#WRITE,U.BUF(R5)  ;CONVERT TO WRITE LOGICAL FUNCTION	;**-3
60$:	MOV	I.PRM+12(R1),R0	;RETRIEVE BLOCK NUMBER			; PJC038
	CLR	R2	      	;CLEAR HIGH ORDER BLOCK NUMBER		;**-2
	BITB	#IO.WPB&377,I.FCN(R1)  ;PHYSICAL BLOCK FUNCTION?
	BNE	80$		;IF NE YES				; PJC038
	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER		;**-1
	CMPB	#IO.WLB/^D<256>,I.FCN+1(R3)  ;WRITE FUNCTION?
	BNE	70$		;IF NE NO				; PJC038
	BITB	#IO.WLT&377,I.FCN(R3)  ;OK TO WRITE ON LAST TRACK?	;**-1
	BNE	70$		;IF NE YES				; PJC038
	MOV	R0,R4		;SAVE ORIGINAL BLOCK NUMBER		; PJC018
	ADD	#^D<20>,I.PRM+12(R3)  ;ADD 1 TRACK'S WORTH OF BLOCKS	;**-2
	CALL	$BLKC1		;CHECK IF WRITE ON       LAST TRACK OF DISK
	MOV	R4,R0		;RESTORE ORIGINAL BLOCK NUMBER		; PJC018
70$:	ASL	R0		;CONVERT BLOCKS TO SECTORS		; PJC038
80$:	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			; PJC038
	MOV	S.PKT(R4),R3	;RESTORE I/O PACKET ADDRESS		; PJC018
	MOV	#^D<40>,R1	;DIVIDE BY SECTORS/SURFACE		;**-3
	CALL	$DIV		;CALCULATE CYLINDER NUMBER
									; PJC021
									; PJC021
	.IF DF	M$$EIS							; PJC021
									; PJC021
	ASH	#6,R0		;POSITION CYLINDER AND SURFACE		; PJC021
									; PJC021
	.IFF								; PJC021      
									; PJC021
	.REPT	6.
	ASL	R0		;POSITION CYLINDER AND SURFACE
	.ENDR
									; PJC021
	.ENDC								; PJC021
									; PJC021
									; PJC021
	BIS	R1,R0		;MERGE SECTOR WITH CYLINDER AND SURFACE
	MOV	R0,I.PRM+10(R3)	;SAVE STARTING DISK ADDRESS
	MOV	U.CNT(R5),I.PRM+12(R3)	;ASSUME ONLY ONE XFER NEEDED
	MOV	#^D<40>,R0	;SET SECTORS/SURFACE
	SUB	R1,R0		;CALCULATE SECTORS LEFT ON SURFACE
	SWAB	R0		;GET BYTES LEFT ON SURFACE
	CMP	U.CNT(R5),R0	;ARE ADDITIONAL TRANSFERS REQUIRED?
	BLOS	90$		      ;IF LOS NO				; PJC038
	MOV	R0,U.CNT(R5)	;SET BYTE COUNT FOR FIRST TRANSFER	; PJC018
90$:				;REF LABEL				; PJC038
									; PB141
	.IF DF	D$$WCK							; PB141
									; PB141
	MOVB	S.CON(R4),R0	;RETRIEVE CONTROLLER INDEX		; PB141
	MOV	#6,R1		;SET UP REGISTER R1			; PJC008
	CALL	$MUL		;FORM INDEX INTO PARAMETER SAVE AREA	;**-4
	ADD	#PRMSV,R1	;POINT TO THIS ENTRY
	MOV	U.BUF(R5),(R1)+	;SAVE INITIAL PARAMETERS
	MOV	U.BUF+2(R5),(R1)+  ;...
	MOV	U.CNT(R5),(R1)+ ;...
	MOV	I.PRM+10(R3),(R1)+  ;...      
	MOV	I.PRM+12(R3),(R1)+  ;...
	MOV	I.PRM+6(R3),(R1) ;...					; PJC018
									; PB141
	.ENDC								; PB141
									; PB141

;+
; THIS SECTION WILL INITIATE THE OPERATION
;-

DLINIO:				;REF LABEL


	.IF DF 	M$$EXT							; PJC008
									; PJC008
	BIT	#DV.EXT,U.CW1(R5) ;BAE EXIST?				; PJC008
	BNE	110$		;IF NE YES				; PJC038
100$:	CALL	$MPUBM		;MAP 11/70 UNIBUS TO TRANSFER		; PJC038
									; PJC008
	.ENDC								; PJC008
									; PJC008
									; PJC008
110$:	MOV	S.CSR(R4),R2      	;GET CSR ADDRESS			; PJC038
	MOV	S.PKT(R4),R3	;GET ADDRESS OF I/O PACKET		;**-8


	.IF DF	E$$DVC

	CLRB	U.CW2+1(R5)	;RESET DRIVE SETTLE DOWN FLAG
									;**-1
	.ENDC


	MOVB	S.ITM(R4),S.CTM(R4)  ;SET DEVICE TIMEOUT COUNTER
									; PJC017
									; PJC017
	.IF DF	A$$HDR							; PJC017
									; PJC017
	BITB	#US.VV,U.STS(R5) ;DO HARDWARE VOLUME CHECKING?		; PJC017
	BEQ	120$		;IF EQ NO				; PJC038
	CALL	DLGST		;GET STATUS				; PJC017
	BR	130$		;SKIP RESET				; PJC038
									; PJC0      17
	.IFTF								; PJC017
									; PJC017
120$:	CALL	DLRST		;RESET DRIVE AND GET STATUS		; PJC038
130$:	MOV	RLMP(R2),R1	;GET THE STATUS INFO			; PJC038
	MOV	#IE.DNR&377,R0	;ASSUME DRIVE NOT READY			;**-2
	BIC	#WLS!DT!HSS,R1	;REMOVE IRRELEVANT BITS
	BIT	#DRDY,(R2)	;IS THE DRIVE READY?
	BEQ	150$		;IF EQ NO				; PJC038
									; PJC017
	.IFT								; PJC017
									; PJC017
	BITB	#US.VV,U.STS(R5) ;DO HARDWARE VOLUME CHECKING?		; PJC017
	BEQ	140$		;IF EQ NO				; PJC038
	BIT	#VC,R1		;VOLUME CHE      CK?				; PJC017
	BNE	160$		;IF NE YES				; PJC038
	CALL 	DLRST		;CLEAR ANY OTHER DRIVE ERROR CONDITIONS	; PJC017
	MOV	RLMP(R2),R1	;GET THE STATUS INFO			; PJC017
	BIC	#WLS!DT!HSS,R1	;REMOVE IRRELEVANT BITS			; PJC017
	BIT	#DRDY,(R2)	;IS THE DRIVE READY?			; PJC017
	BEQ	150$		;IF EQ NO				; PJC038
									; PJC017
	.ENDC								; PJC017
									; PJC017
									; PJC017
140$:	CMP	#HH!BH!SLM,R1	;HEADS, BRUSHES AND STATE OK?		; PJC038
	BEQ	170$		;IF EQ YES				; PJC038
150$:				;REF LABEL				; P      JC038
									;**-4

	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	210$		;IF NE YES				; PJC038
									;**-1
	.IFTF


	.IF DF	E$$DVC

	CALL	DLDVER		;LOG THE DEVICE NOT READY

	.ENDC


160$:	JMP	350$		;EXIT					; PJC038
									;**-1
170$:				;REF LABEL				; PJC038
									;**-1
	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC


	MOV	I.PRM+10(R3),R0	;RETREIVE STARTING DISK ADDRESS
	CALL	DLDIFF		;CALCULATE DIFFERENCE WORD
180$:	BEQ	190      $		;IF EQ, NO SEEK IS NECESSARY		; PJC038
	MOV	#SEEK,R1	;GET CODE FOR SEEK FUNCTION		;**-1
	CALL	DLXCT		;EXECUTE THE SEEK
	BMI	250$		;IF MI, ERROR DURING SEEK FUNCTION	; PJC038
190$:				;REF LABEL				; PJC038
									; PJC008
									; PJC008
	.IF DF	M$$EXT							; PJC008
									; PJC008
	BIT	#DV.EXT,U.CW1(R5) ;BAE EXIST?				; PJC008
	BEQ	200$		;IF EQ NO				; PJC038
	MOV	I.PRM+6(R3),RLBAE(R2) ;LOAD ADDRESS EXTENSION BITS	; PJC018
									; PJC008
	.ENDC								; PJC008
									; PJC008
      									; PJC008
200$:	ADD	#RLMP,R2	;POINT TO RLMP				; PJC038
	MOV	U.CNT(R5),R1	;GET BYTE COUNT				; PJC018
	ROR	R1		;MAKE IT A WORD COUNT			;**-3
	NEG	R1		;ALSO NEGATIVE
	MOV	R1,(R2)		;LOAD WORD COUNT
	MOV	I.PRM+10(R3),-(R2)  ;LOAD STARTING DISK ADDRESS
	MOV	U.BUF+2(R5),-(R2)   ;LOAD BUS ADDRESS


	.IF DF	E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE BIT IN MAP

	.ENDC


	MOV	U.BUF(R5),-(R2)	;LOAD FUNCTION AND GO

;+
;+
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;-

DLCA      N:	RETURN			;;;NOP FOR RL11

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DLPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS DRIVE CURRENTLY BUSY?
	BEQ	220$		;IF EQ NO			      	; PJC038
210$:	MOVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC038
220$:	BISB	#US.SPU,U.STS(R5) ;SET UNIT SPINNING UP			; PJC038
									;**-4
	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND

;+
; **-$DLINT-RL11/RL01 DISK CONTROLLER
;	INTERRUPT AND ERROR SERVICE ROUTINES
;-
	INTSE$	DL,PR5,R$$L11	;;;SAVE REGISTERS AND SET PRIORITY
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB			; PJC028
	ASRB	RTTBL+1(R3)	;REVERSE SEEK       IN PROGRESS?		; PJC028
	BCS	DLINIO		;IF CS YES				;**-1
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR			;**-1
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL OPERATION
	MOV	(R2),R1		;GET CONTENTS OF RLCS
	BMI	250$		;IF MI, AN ERROR OCCURRED		; PJC038
	MOV	S.PKT(R4),R3	;GET ADDRESS OF I/O PACKET		;**-1
	SUB	U.CNT(R5),I.PRM+12(R3) ;CALCULATE BYTES LEFT TO XFER	; PJC018
	BEQ	310$		;IF EQ, NONE LEFT - COMPLETE WRITE CHECK; PJC038
	MOV	I.PRM+12(R3),U.CNT(R5) ;ASSUME LAST XFER COMING		; PJC018
	CMP	I.PRM+12(R3),#RLBPT ;      IS THIS THE LAST TRANSFER?		; PJC018
	BLOS	230$		;IF LOS YES				; PJC038
	MOV	#RLBPT,U.CNT(R5) ;TRANSFER A WHOLE TRACKS WORTH		; PJC018
230$:	BIC	#CRDY,R1	;CLEAR CRDY TO START FUNCTION		; PJC038
	MOV	R1,U.BUF(R5)	;SAVE CURRENT FUNCTION AND ADDRESS BITS	;**-7
	MOV	RLBA(R2),U.BUF+2(R5)  ;SAVE CURRENT BUS ADDRESS
									; PJC008
									; PJC008
	.IF DF	M$$EXT							; PJC008
									; PJC008
	BIT	#DV.EXT,U.CW1(R5) ;BAE EXIST?				; PJC008
	BEQ	240$		;IF EQ NO				; PJC038
	MOV	RLBAE(R2),I.PRM+6(R      3) ;SAVE CURRENT BUS ADRS EXT	; PJC018
									; PJC008
	.ENDC								; PJC008
									; PJC008
									; PJC008
240$:	MOV	I.PRM+10(R3),R0 ;GET INITIAL DISK ADDRESS		; PJC038
	MOV	R0,R1		;COPY DISK ADDRESS			;**-1
	BIC	#77,R0		;ISOLATE CYLINDER AND SURFACE
	ADD	#100,R0		;UPDATE SURFACE/CYLINDER ADDRESS
	MOV	R0,I.PRM+10(R3)	;SAVE NEW DISK ADDRESS
	CALL	DLDIF0		;CALCULATE MID-TRANSFER DIFFERENCE
	JMP	180$		;GO DO THE OPERATION			; PJC038
250$:	BIT	#DRDY,R1	;IS THE DRIVE READY?			; PJC038
	BNE	      270$		;IF NE YES				; PJC038
260$:	MOVB	#3,S.CTM(R4)	;SET 3 SECOND TIMEOUT FOR DRIVE		; PJC038
	INCB	U.CW2+1(R5)	;FLAG DRIVE IS SETTLING DOWN		;**-5
	RETURN			;
270$:	MOV	(R2),R1		;RETRIEVE RLCS CONTENTS			; PJC038
									;**-2

	.IF DF	E$$DVC

	MOV	R1,-(SP)	;SAVE CONTENTS OF RLCS
	CALL	DLDVER		;LOG DEVICE ERROR
	MOV	(SP)+,R1	;RESTORE RLCS CONTENTS

	.ENDC


	MOV	#IE.BBE&377,R0	;ASSUME BAD BLOCK ERROR			; PB144
	MOV	R1,-(SP)	;COPY CONTENTS OF RLCS			; PB144
	COM	(SP)		;TOGGLE THE BITS			      ; PB144
	BIT	#HCRC!OPI,(SP)+	;BAD BLOCK ERROR?			; PB144
	BEQ	350$		;IF EQ YES				; PJC038
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR
	BIT	#NXM,R1		;NON-EXISTANT MEMORY?
	BNE	340$		;IF NE YES				; PJC038
	BIT	#DE,R1		;DRIVE PROBLEMS?			;**-1
	BEQ	280$		;IF EQ NO				; PJC038
	CALL	DLGST		;EXECUTE GET DRIVE STATUS FUNCTION	;**-1
	BIT	#WGE,RLMP(R2)	;WRITE GATE ERROR?
	BEQ	340$		;IF EQ NO				; PJC038
	BIT	#WLS,RLMP(R2)	;IS DRIVE WRITE LOCKED?			;**-1
	BEQ	290$		;IF EQ NO				; PJC038
	MOV	#IE.W      LK&377,R0	;SET WRITE LOCK ERROR CODE		;**-1
	BR	350$		;					; PJC038
280$:				;REF LABEL				; PJC038
									; PB141
									; PB141
	.IF DF	D$$WCK							; PB141
									; PB141
	BIT	#10,U.BUF(R5)	;WRITE CHECK FUNCTION?			; PB141
	BNE	290$		;IF NE NO				; PJC038
	BIT	#OPI,R1		;OPERATION INCOMPLETE?			;**-3
	BNE	290$		;IF NE YES				; PJC038
	BIT	#DCK,R1		;WRITE CHECK ERROR?			;**-1
	BEQ	290$		;IF EQ NO				; PJC038
	MOV	#IE.WCK&377,R0	;YES, SET WRITE CHECK ERROR CODE	;**-1
									; PB141
	      .IFTF								; PB141
									; PB141
290$:	MOV	S.PKT(R4),R1	;RETRIEVE I/O PACKET ADDRESS		; PJC038
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?			;**-1
	BNE	350$		;IF NE YES				; PJC038
	DECB	RTTBL(R3)	;ANY MORE RETRIES LEFT?			;**-1
	BLE	350$		;IF LE NO				; PJC038
300$:	JMP	DLINIO		;RETRY ENTIRE OPERATION			; PJC038
310$:				;REF LABEL				; PJC038
									; PB141
	.IFT								; PB141
									; PB141
	BITB	#IO.WLC&377,I.FCN(R3)  ;WRITE WITH WRITE CHECK?		; PB141
	BNE	320$		;IF NE YES				; PJC038      
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED?		;**-4
	BEQ	350$		;IF EQ NO				; PJC038
320$:	MOV	U.BUF(R5),R1	;GET CURRENT FUNCTION CODE		; PJC038
	BIT	#WCHK,R1	;WRITE OR WRITE CHECK FUNCTION?		;**-2
	BEQ	350$		;IF EQ NO				; PJC038
	BIT	#10,R1		;WAS FUNCTION WRITE CHECK?		;**-1
	BEQ	350$		;IF EQ YES				; PJC038
	MOVB	S.CON(R4),R1	;RETREIVE CONTROLLER INDEX		;**-1
	MOV	#RETRY,RTTBL(R1);RESET RETRY COUNT
	MOV	#6,R0		;SET UP R0				; PJC008
	CALL	$MUL		;FORM INDEX INTO PARAMETER SAVE AREA	;**-1
	A      DD	#PRMSV,R1	;...
	MOV	(R1)+,U.BUF(R5) ;RESTORE STARTING PARAMETERS
	MOV	(R1)+,U.BUF+2(R5)  ;...
	MOV	(R1)+,U.CNT(R5)  ;...
	MOV	(R1)+,I.PRM+10(R3) ;...
	MOV	(R1)+,I.PRM+12(R3) ;...
	MOV	(R1),I.PRM+6(R3) ;...					; PJC018
	BIC	#10,U.BUF(R5)	;CONVERT TO WRITE CHECK FUNCTION
	BR	300$		;START THE WRITE CHECK OPERATION	; PJC038
									; PB141
	.ENDC								; PB141
									; PB141
330$:	BEQ	350$		;IF EQ, COMPLETED TRANSFER SUCCESSFULLY	; PJC038
340$:	MOV	#IE.VER&377,R0	;SET UNSUCCESSFUL OPERATION      		; PJC038
350$:	MOV	S.PKT(R4),R2	;GET ADDRESS OF I/O PACKET		; PJC038
	MOV	I.PRM+4(R2),R1	;GET TOTAL TRANSFER SIZE		;**-3
	SUB	I.PRM+12(R2),R1	;CALCULATE BYTES TRANSFERRED		; PJC018
									;**-1

	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL RETRY COUNT
	BIS	#RETRY*^D<256>,R2  ;MERGE STARTING RETRY COUNT

	.ENDC


	CALL	$IODON		;FINISH I/O OPERATION
	JMP	DLINI		;PROCESS NEXT REQUEST

;+
; **-DLOUT-RL11/RL01 DISK CONTROLLER
;	DEVICE TIMEOUT       ROUTINE
;
; DEVICE TIMEOUT RESULTS IN THE OPERATION BEING REPEATED.
; TIMEOUTS ARE USUALLY CAUSED BY A POWER FAILURE BUT MAY ALSO
; BE THE RESULT OF A HARDWARE MALFUNCTION.
;-

DLOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	370$		;;;IF EQ NO				; PJC038
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#16.,S.STS(R4)	;;;HAVE WE WAITED 1 MINUTE YET?		; PJC029
	BEQ	360$		;;;IF EQ YES				; PJC038
	MTPS	#0		;;;ALLOW INTERRUPTS			; PJC      029
	JMP	DLINIO		;RETRY ENTIRE OPERATION			; PJC029
360$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC038
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP		;**-4
	BR	380$		;;;					; PJC038
									;**-3
	.ENDC


370$:	TSTB	U.CW2+1(R5)	;;;IS THE DRIVE SETTLING DOWN?		; PJC038
	BEQ	380$		;;;IF EQ NO				; PJC038
	MTPS	#0		;;;YES, ALLOW INTERRUPTS		;**-2
	JMP	270$		;PROCESS THE ERROR			; PJC038
380$:				;;;REF LABEL				; PJC038
									;**-2

	.IF DF	E$$DVC

	CALL	DLDTER		;;;LOG DEVI      CE TIMEOUT

	.IFF

	CALL	$DTOER		;;;LOG DEVICE TIMEOUT

	.ENDC


	CALL	DLRST		;RESET DRIVE
	BR	290$		;REPEAT THE OPERATION			; PJC038
									;**-1
;+
; **-DLXCT,DLGST,DLRST-RL11/RL01 DISK CONTROLLER
;	FUNCTION EXECUTION ROUTINES
;
; THIS ROUTINE WILL EXECUTE A GET DRIVE STATUS OR ANY
; NON-INTERRUPTABLE FUNCTION AND WAIT FOR ITS COMPLETION.
;
; INPUTS:
;	R1 = FUNCTION CODE
;	R2 = CSR ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;	R1 = CONTENTS OF RLCS (TESTED)
;	FUNCTION EXECUTED
;-      

DLRST:	MOV	#RST!STS!MRK,RLDA(R2)  ;SET MESSAGE CODES IN RLDA
	CALL	390$		;DO THE DRIVE RESET FIRST		; PJC038
DLGST:	MOV	#STS!MRK,RLDA(R2)  ;SET MESSAGE CODES IN RLDA		;**-1
390$:	MOV	#GSTS,R1	;SET GET STATUS OPERATION		; PJC038
DLXCT:	MOV	R1,-(SP)	;SAVE FUNCTION CODE			;**-1
	MOVB	U.UNIT(R5),1(SP);MERGE CURRENT DRIVE BITS
	MOV	(SP)+,(R2)	;LOAD RLCS
400$:	TSTB	(R2)		;FUNCTION COMPLETED?			; PJC038
	BPL	400$		;IF PL NO				; PJC038
	MOV	(R2),R1		;SAVE RLCS AND TEST FOR ERRORS		;**-2
	RETURN			;
      
;+
; **-DLDIFF-RL11/RL01 DISK CONTROLLER
;	CYLINDER ADDRESS DIFFERENCE CALCULATOR
;
; THIS SUBROUTINE CALCULATES THE DIFFERENCE WORD USED IN THE
; SEEK OPERATION.  IF A HEADER CANNOT BE READ AFTER 16. RETRIES,
; AN ERROR WILL BE LOGGEN AND A ONE CYLINDER REVERSE SEEK WILL
; BE ISSUED.  THE SEEK IS FOLLOWED BY A READ HEADERS TO CAUSE AN
; INTERRUPT.
;
; INPUTS:
;	R0 = DESIRED DISK ADDRESS
;	R3 = I/O PACKET ADDRESS
;
; OUTPUTS:
;	R1 = DIFFERENCE WORD
;	RLDA = LOADED WITH DIFFERENCE WORD
;	IF       EQ NO SEEK IS NECESSARY					;**-1
;-

DLDIFF:	MOV	#RETRY*2,-(SP)	;SET READ HEADER RETRY COUNT
410$:	MOV	#RDH,R1		;SET CODE FOR READ HEADERS FUNCTION	; PJC038
	CALL	DLXCT		;EXECUTE THE FUNCTION			;**-1
	BPL	420$		;IF PL, FUNCTION EXECUTED OK		; PJC038
	DEC	(SP)		;ANY RETRIES LEFT?			;**-1
	BGT	410$		;IF GT YES				; PJC038
	CMP	(SP)+,(SP)+	;REMOVE RETRY COUNT AND CALLERS ADDRESS	;**-1


	.IF DF	E$$DVC

	CALL	DLDVER		;LOG HEADER ERROR

	.IFF

	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX

      	.ENDC								; PJC018
									;**-1
	CALL	DLRST		;RESET DRIVE
	MOV	#REV,RLDA(R2)	;LOAD REVERSE SEEK DIFFERENCE WORD
	MOV	#SEEK,R1	;GET CODE FOR SEEK FUNCTION
	CALL	DLXCT		;EXECUTE THE SEEK
	BMI	340$		;IF MI IT FAILED			; PJC038
	BIC	#377,R1		;CLEAR OUT FUNCTION BITS		;**-1
	BIS	#IE!RDH,R1	;LOAD CODES FOR READ HEADER
	MOVB	#1,RTTBL+1(R3)	;INDICATE REVERSE SEEK IN PROGRESS
	MOVB	S.ITM(R4),S.CTM(R4)  ;SET DEVICE TIMEOUT COUNTER
	MOV	R1,(R2)		;LOAD FUNCTION AND GO
	RETURN			;WAIT FOR THE INTERRUPT      
420$:	TST	(SP)+		;REMOVE RETRY COUNT			; PJC038
	MOV	RLMP(R2),R1	;RETREIVE HEADER WORD			;**-1
DLDIF0:	BIC	#77,R0		;MASK OUT SECTOR BITS			; PJC018
	BIC	#77,R1		;...					;**-9
	CMP	R0,R1		;DO WE NEED TO DO A SEEK?
	BEQ	440$		;IF EQ NO				; PJC038
	MOV	R0,-(SP)	;SAVE DESIRED DISK ADDRESS		;**-1
	BIC	#^C<100>,(SP)	;ISOLATE SURFACE BIT
	ASR	(SP)		;PUT INTO THE PROPER POSITION
	ASR	(SP)		;...
	BIC	#100,R0		;REMOVE SURFACE BIT
	BIC	#100,R1		;...
	SUB	R0,R1		;SUBTRACT DESIRED FROM ACTUAL
;	BEQ	430$      		;IF EQ, ONLY CHANGE SURFACE		; PJC038
	BCC	430$		;IF CC, ACTUAL >= DESIRED		; PJC038
	NEG	R1		;ACTUAL < DESIRED, MAKE POSITIVE DIFFERE;**-2
	BIS	#SN,R1		;SET SIGN FOR MOVE TO CENTER OF DISK
430$:	INC	R1		;SET MARKER BIT				; PJC038
	BIS	(SP)+,R1	;MERGE IN SURFACE BIT			;**-1
	MOV	R1,RLDA(R2)	;LOAD DIFFERENCE WORD
440$:	RETURN			;					; PJC038
									;**-9

	.IF DF	E$$DVC

;+
; **-DLDXXX-RL11/RL01 DISK CONTROLLER
;	ERROR LOGGING ROUTINES
;
; THIS ROUTINE IS CALLED WHENEVER A DEVICE ERROR       OR DEVICE TIMEOUT
; OCCURS.  A CORE BLOCK THE SIZE OF THE REGISTER BUFFER IS ALLOCATED
; AND THE UNIBUS REGISTERS ALONG WITH THE DRIVE STATUS INFORMATION
; ARE TRANSFERED INTO THE CORE BLOCK.  THEN THE CSR ADDRESS IN THE
; SCB IS SET TO THE CORE BLOCK ADDRESS AND THE APPROPRIATE EXECUTIVE
; ERROR LOGGING ROUTINE IS CALLED.  THE CORE BLOCK IS THEN
; DEALLOCATED AND THE CSR ADRESS IN THE SCB RESTORED.
;
; IF FOR ANY REASON THE CORE BLOCK CANNOT BE ALLOCATED THEN THE
; EXECUTIVE ERROR LOGGING ROUTINE       WILL NOT BE CALLED AND THE ERROR
; SEQUENCE NUMBER WILL BE UPDATED TO INDICATE THAT A MISSED ERROR
; CONDITION OCCURRED.
;
; INPUTS:
;	R2 = CSR ADDRESS
;	R4 = SCB ADDRESS
;
; OUTPUTS:
;	R1 = DESTROYED
;	R3 = CONTROLLER INDEX
;-

DLDVER:	MOV	#$DVERR,R1	;GET ADRS OF DEVICE ERROR ROUTINE
	BR	450$		;					; PJC038
DLDTER:	MOV	#$DTOER,R1	;;;GET ADRS OF DEVICE TIMEOUT ROUTINE	;**-1
450$:	MOV	R0,-(SP)	;SAVE I/O STATUS CODE			; PJC038
	MOV	R1,-(SP)	;SET CO-ROUTINE ADDRESS			;**-1
	MOV	#RLCNT*2,R1	;      GET NUMBER OF BYTES TO ALLOCATE
	CALL	$ALOCB		;ALLOCATE A CORE BLOCK
	BCC	460$		;IF CC, BLOCK WAS ALLOCATED		; PJC038
	INC	$ERRSQ		;INDICATE A MISSED ERROR CONDITION	;**-1
	CMP	(SP)+,#$DTOER	;ALLOCATION FAILURE, TIMEOUT IN PROGRESS?
	BNE	480$		;IF NE NO				; PJC038
	BIC	#IE,@S.CSR(R4)	;;;CLEAR INTERRUPT ENABLE		;**-1
	MTPS	#0		;;;ALLOW INTERRUPTS
	BR	480$		;DON'T LOG ERROR IS ALLOCATION FAILURE	; PJC038
460$:	MOV	R0,R3		;SET POINTER TO CORE BLOCK		; PJC038
	MOV	S.CSR(R4),R2	;GET REAL CSR ADDRESS		      	;**-2
	MOV	(R2),(R3)+	;TRANSFER RLCS				; PJC018
	MOV	RLBA(R2),(R3)+	;TRANSFER RLBA				; PJC018
	MOV	RLDA(R2),(R3)+	;TRANSFER RLDA				; PJC018
	MOV	RLMP(R2),(R3)+	;TRANSFER RLMP				; PJC018
									; PJC018
									; PJC018
	.IF DF M$$EXT							; PJC018
									; PJC018
	BIT	#DV.EXT,U.CW1(R5) ;BAE EXIST?				; PJC018
	BEQ	470$		;IF EQ NO				; PJC038
	MOV	RLBAE(R2),(R3)+	;TRANSFER RLBAE				; PJC018
	CLR	(R3)+		;ZERO EXTRA STORAGE WORD		; PJC018
									; PJC018
	.ENDC								; PJC018
					      				; PJC018
									; PJC018
470$:	CALL	DLGST		;EXECUTE GET DRIVE STATUS FUNCTION	; PJC038
	MOV	RLMP(R2),(R3)	;SAVE DRIVE STATUS			; PJC018
	MOV	R0,S.CSR(R4)	;REPLACE CSR WITH CORE BLOCK ADDRESS	;**-6
	CALL	@(SP)+		;CALL EXEC ERROR LOGGING ROUTINE
	MOV	R2,S.CSR(R4)	;RESTORE CSR ADDRESS
	MOV	#RLCNT*2,R1	;GET NUMBER OF BYTES TO DEALLOCATE
	CALL	$DEACB		;DEALLOCATE THE CORE BLOCK
480$:	MOV	S.CSR(R4),R2	;RESTORE CSR ADDRESS			; PJC038
	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX		;**-1
	MOV	(SP)+,      R0	;RESTORE I/O STATUS CODE
	RETURN

	.ENDC


	.DSABL	LSB
									; PJC017
									; PJC017
	.IF DF	A$$HDR							; PJC017
									; PJC017
;+									; PJC017
; **-DLVOL-PREPROCESS VOLUME VALID CHECKING				; PJC017
;									; PJC017
; THIS ROUTINE WILL DETERMINE IF VOLUME CHECKING IS TO BE DONE.		; PJC017
;									; PJC017
; INPUTS:								; PJC017
;									; PJC017
;	R1=I/O PACKET ADDRESS						; PJC017
;		I.PRM+2=0 TO DESELECT VOLUME CHECKING			; PJC017
;			1 TO SELECT VOLUME CHEC      KING			; PJC017
;									; PJC017
;	R4=SCB ADDRESS							; PJC017
;	R5=UCB ADDRESS							; PJC017
;									; PJC017
; OUTPUTS:								; PJC017
;									; PJC017
;	C=0 THEN THE FUNCTION WAS NOT A SET CHARACTERISTICS (IO.STC)	; PJC017
;									; PJC017
;	C=1 THEN THE FUNCTION WAS A SET CHARACTERISTICS (IO.STC)	; PJC017
;		US.VV=0 DO NOT DO VOLUME CHECKING			; PJC017
;		US.VV=1 DO VOLUME CHECKING				; PJC017
;		R0=IS.SUC&377 OR ERROR CODE				; PJC017
;-									; PJC017
	VV$SET=	1		;SET/CLEAR       VOLUME VALID			; PJC017
DLVOL:	MOV	I.FCN(R1),-(SP)	;GET FUNCTION CODE			; PJC017
	BIC	#7,(SP)		;REMOVE QUALIFIER BITS			; PJC017
	CMP	#IO.STC,(SP)+	;SET CHARACTERISTICS?			; PJC017
	BEQ	10$		;IF EQ YES				; PJC038
	CLC			;SHOW NOT AN IO.STC FUNCTION		; PJC017
	RETURN			;					; PJC017
10$:	MOV	I.PRM+2(R1),R0	;GET PARAMETER SPECIFICATION		; PJC038
	BIT	#VV$SET,R0	;SET VOLUME VALID?			; PJC017
	BNE	30$		;IF NE YES				; PJC038
	BIT	#^C<VV$SET>,R0	;BAD PARAMETERS?			; PJC017
	BNE	20$		;IF NE YES				;       PJC038
	BICB	#US.VV,U.STS(R5) ;TURN OFF VOLUME CHECKING		; PJC017
	BR	40$		;					; PJC038
20$:	MOV	#IE.BAD&377,R0	;SET BAD PARAMETERS ERROR		; PJC038
	BR	60$		;					; PJC038
30$:	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR			; PJC038
	CALL	DLRST		;RESET DRIVE AND GET STATUS		; PJC017
	MOV	RLMP(R2),R3	;GET THE STATUS INFO			; PJC018
	BIT	#DRDY,(R2)	;DRIVE READY?				; PJC017
	BEQ	50$		;IF EQ NO				; PJC038
	BIC	#WLS!DT!HSS,R3	;REMOVE IRRELEVANT BITS			; PJC018
	CMP	#HH!BH!SLM,R3	;HEADS, BRUSHES AND STATE   ’   OK?		; PJC018
	BNE	50$		;IF NE NO				; PJC038
	BISB	#US.VV,U.STS(R5) ;TURN ON VOLUME CHECKING		; PJC017
40$:	MOV	#IS.SUC&377,R0	;SHOW SUCCESSFUL I/O CODE		; PJC038
	BR	60$		;					; PJC038
50$:	MOV	#IE.DNR&377,R0	;SET DRIVE NOT READY ERROR		; PJC038
60$:	SEC			;SHOW AN IO.STC FUNCTION		; PJC038
	RETURN			;					; PJC017
									; PJC017
	.ENDC								; PJC017
									; PJC017

	.END

’         »zÈkQ	› c,        	.TITLE	SYSCM
	.IDENT	/16.69/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 16.69
;
; D. N. CUTLER 11-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	B. SCHREIBER
;	CHUCK SPITZ
;	J. E. PROVINO
;
; MODIFIED BY:
; 
;	M. S. HARVEY	15-JAN-81
;		MSH043 -- USE SYSGEN SYMBOLS       TO DRIVE THE SYSTEM ID
;
;	M. S. HARVEY	23-JUL-79
;		MSH045 -- ADD DIRECTIVE PARTITION SUPPORT
;
;	M. S. HARVEY	17-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	30-SEP-79
;		MSH065 -- SET APPROPRIATE FEATURE MASK BIT IF INSTALL,
;			  REQUEST AND REMOVE SUPPORT IS DEFINED
;
;	M. S. HARVEY	30-OCT-79
;		MSH069 -- UPDATE NULL TASK TCB. DEFINE F2.STP TO BE ZERO
;			  IF EVENT FLAG MASKS IN HEADER, ONE IF IN TCB.
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT       GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	2-JAN-80
;		MSH079 -- STORE THE NODE NAME FOR A SYSTEM IN $SYSNM
;
;	M. S. HARVEY	2-JAN-80
;		MSH080 -- ADD A WORD CONTAINING THE NETWORK UIC
;
;	M. S. HARVEY	25-APR-80
;		MSH096 -- IF ALTERNATE HEADER REFRESH SUPPORT IS
;			  CHOSEN, SET F2.AHR IN THE FEATURE MASK
;
;	M. S. HARVEY	30-APR-80
;		MSH097 -- ADD THE HARDWARE FEATURE MASK AND SUPPORT FOR
;			  NON-UNIBUS 22-BIT SYSTEMS
;
;	M. S. HARVEY	1-MAY-80
;		MSH098       -- ADD DYNAMIC SYSTEM TUNING SUPPORT
;
;	M. S. HARVEY	5-JUN-80
;		MSH105 -- ADD MULTIPLE CLI SUPPORT
;
;	M. S. HARVEY	20-AUG-80
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	20-AUG-80
;		MSH112 -- ADD SUPPORT FOR EXTENDED INST. SET
;
;	M. S. HARVEY	15-SEP-80
;		MSH118 -- ADD SUPPORT OF SYSTEM-CONTROLLED PARTITIONS
;			  FOR RSX-11S SYSTEMS
;
;	M. S. HARVEY	17-OCT-80
;		MSH123 -- ADD SUPPORT OF THE SET SYSTEM TIME DIRECTIVE
;
;	M. S. HARVEY	30-OCT-80
;		MSH121 -- EXT      ERNALLY DEFINE AST SUPPORT IF THERE
;
;	M. S. HARVEY	13-NOV-80
;		MSH128 -- ADD SUPPORT FOR NETWORK POWERFAIL RECOVERY
;
;	M. S. FOX	07-JAN-81
;		MF203 -- INITIAL ALTERNATE CLI SUPPORT
;
;	DAN BROWN	07-JAN-81
;		DTB004 -- ADD SUPPORT FOR NEW ERROR LOGGER
;
;	M. S. FOX	26-JAN-81
;		MF207 -- ADD RPOI$ AND SDRP$ DIRECTIVES
;
;	M. S. HARVEY	3-FEB-81
;		MSH141 -- CLEAN UP IDLE PATTERN STORAGE
;
;	M. S. HARVEY	12-FEB-81
;		MSH149 -- ASSUME NO FLOATING POINT PROCESSOR PRESENT
;
;	M. S. HARVEY	1      3-FEB-81
;		MSH142 -- DEFINE POOL MONITORING DATA ELEMENTS
;
;	M. S. HARVEY	28-FEB-81
;		MSH150 -- DEFINE AVR LISTHEAD FOR ANSI MAGTAPE CONTROL
;
;	M. S. HARVEY	5-MAR-81
;		MSH156 -- ADD TRANSPORTABILITY SUPPORT FOR THE
;			  WATCHDOG TIMER
;
;	M. S. HARVEY	14-MAR-81
;		MSH158 -- ADD SYMBOL FOR THE LIBRARY UIC
;
;	M. S. HARVEY	15-MAR-81
;		MSH159 -- ADD SUPPORT FOR THE UDA
;
;	M. S. HARVEY	31-MAR-81
;		MSH160 -- SET F3.RLK FOR 'RMS' RECORD LOCKING
;
;	M. S. HARVEY	21-APR-81
;		MSH165 --       ADD OFFSET POINTER FOR SECOND DIRECTIVE COMMON
;
;	D. R. DONCHIN	09-JUN-81
;		DD098 -- ADD LISTHEAD FOR ANCILLARY CONTROL DRIVER
;
;	M. S. HARVEY	16-JUN-81
;		MSH177 -- ADD NETWORK SUPPORT FEATURE MASK BIT
;
;	M. S. HARVEY	6-AUG-81
;		MSH184 -- ADD SUPPORT FOR SHUFFLER RUN LIMITING
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
; SYSTEM COMMON DATA AREA
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,HWDDF$,TCBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HA      RDWARE REGISTERS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;
; MAKE CLOCK PARAMETERS GLOBAL
;

S$$RTZ==H$$RTZ			;LINE FREQUENCY
S$$IEN==K$$IEN			;ENABLE BITS PATTERN
S$$LDC==K$$LDC			;LOAD VALUE FOR COUNT REGISTER
S$$TPS==K$$TPS			;TICKS PER SECOND ON P CLOCK

;
; LOCAL SYMBOL DEFINITIONS
;
									;MSH080
; DEFAULT SYSTEM AND NETWORK UIC					;MSH080
									;MSH080
	.IF DF	M$$MGE							;MSH080
									;MSH080
SYUIC=454			;MAPPED UIC = [1,54]			;MSH080
									;MSH080
	.IFF				      				;MSH080
									;MSH080
SYUIC=450			;UNMAPPED UIC = [1,50]			;MSH080
									;MSH080
	.ENDC								;MSH080
									;MSH080
;									;MSH080
; FUNCTION MASK LITERAL
;

FMASK=	0			;INITIALIZE FUNCTION MASK


	.IF DF	M$$EXT&M$$MGE

FMASK=	FMASK!FE.EXT		;INCLUDE EXTENDED MEMORY MASK

	.ENDC


	.IF DF	M$$MUP

FMASK=	FMASK!FE.MUP		;INCLUDE MULTI-USER PROTECTION MASK

	.ENDC


	.IF DF	R$$EXV

FMASK=	FMASK!FE.EXV		;INCLUDE EXTENDED VIRT ADDR MASK

	.ENDC


	.IF DF	L$$DRV
      
FMASK=	FMASK!FE.DRV		;LOADABLE DRIVER SUPPORT		;MSH069
									;**-1
	.ENDC


	.IF DF	P$$LAS

FMASK=	FMASK!FE.PLA		;PLAS SUPPORT

	.ENDC


	.IF DF	Q$$OPT

FMASK=	FMASK!FE.PKT		;QIO PACKET PREALLOCATION

	.ENDC


	.IF DF	C$$CKP&D$$YNC

FMASK=	FMASK!FE.CAL		;DYNAMIC CHECKPOINT SPACE ALLOCATION

	.ENDC


	.IF DF	E$$XPR&M$$MGE&D$$YNM

FMASK=	FMASK!FE.EXP		;EXTEND TASK DIRECTIVE

	.ENDC


	.IF DF	L$$SI1

FMASK=	FMASK!FE.LSI		;PROCESSOR IS AN LSI-11

	.ENDC

	.IF DF P$$OFF      

FMASK=	FMASK!FE.OFF		;PARENT OFFSPRING TASKING

	.ENDC

	.IF DF T$$CPW

FMASK=	FMASK!FE.FDT		;FULL DUPLEX TERMINAL DRIVER

	.ENDC

	.IF DF M$$MGE&D$$YNM

FMASK=	FMASK!FE.DYM		;DYNAMIC MEMORY ALLOCATION

	.ENDC

;									;MSH045
; FUNCTION MASK LITERAL (2ND WORD)					;MSH045
;									;MSH045
									;MSH045
FMASK2=	0			;INITIALIZE FUNCTION MASK (2ND WORD)	;MSH045
									;MSH045
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
FMASK2=	FMASK2!F2.DPR		;DIRECTIVE P      ARTITION SUPPORT		;MSH045
									;MSH045
	.ENDC								;MSH045
									;MSH045
	.IF DF	I$$RAR							;MSH065
									;MSH065
FMASK2=	FMASK2!F2.IRR		;INSTALL, REQUEST AND REMOVE TASKS	;MSH065
									;MSH065
	.ENDC								;MSH065
									;MSH065
	.IF DF	G$$EFN							;MSH049
									;MSH049
FMASK2= FMASK2!F2.GGF		;GROUP GLOBAL EVENT FLAG SUPPORT	;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
	.IF DF	R$$SND							;MSH076
									;MSH076
FMASK2=FMASK2!F2.RAS		;RECEIVE/S      END DATA PACKET SUPPORT	;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH076
	.IF DF	A$$HDR							;MSH096
									;MSH096
FMASK2=FMASK2!F2.AHR		;ALT. HEADER REFRESH AREAS SUPPORTED	;MSH096
									;MSH096
	.ENDC								;MSH096
									;MSH096
	.IF DF	R$$NDC							;MSH098
									;MSH098
FMASK2=FMASK2!F2.RBN		;ROUND ROBIN SCHEDULING			;MSH098
									;MSH098
	.ENDC								;MSH098
									;MSH098
	.IF DF	S$$WPC							;MSH098
									;MSH098
FMASK2=FMASK2!F2.SWP		;EXECUTIVE       LEVEL DISK SWAPPING		;MSH098
									;MSH098
	.ENDC								;MSH098
									;MSH098
	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
FMASK2=FMASK2!F2.STP		;EVENT FLAG MASK AND MASK ADDR. IN TCBS	;MSH069
									;MSH069
	.ENDC	;S$$TOP!T$$BUF						;MSH069
									;MSH069
									;MSH112
;									;MSH112
; FUNCTION MASK LITERAL (3RD WORD)					;MSH112
;									;MSH112
									;MSH112
FMASK3=	0			;INITIALIZE FUNCTION MASK (3RD WORD)	;MSH112
									;MSH112
									;MSH112
	.IF DF	M$      $NET							;MSH177
									;MSH177
FMASK3=FMASK3!F3.NWK		;NETWORK SUPPORT			;MSH177
									;MSH177
	.ENDC								;MSH177
									;MSH177
	.IF DF	M$$EIS							;MSH112
									;MSH112
FMASK3=FMASK3!F3.EIS		;EXTENDED INSTRUCTION SET REQUIRED	;MSH112
									;MSH112
	.ENDC								;MSH112
									;MSH112
	.IF DF	S$$TIM							;MSH123
									;MSH123
FMASK3=FMASK3!F3.STM		;SET SYSTEM TIME DIRECTIVE		;MSH123
									;MSH123
	.ENDC								;MSH123
									;MSH123
	.IF DF	A$$TRP							;MSH1      21
									;MSH121
FMASK3=FMASK3!F3.AST		;SYSTEM HAS AST SUPPORT			;MSH121
									;MSH121
	.ENDC								;MSH121
									;MSH121
	.IF DF	R$$11S							;MSH118
									;MSH118
FMASK3=FMASK3!F3.11S		;RSX-11S SYSTEM				;MSH118
									;MSH118
	.ENDC								;MSH118
									;MSH118
	.IF DF	A$$CLI							; MF203
									; MF203
FMASK3=FMASK3!F3.CLI		;ALTERNATE CLI SUPPORT			; MF203
									; MF203
	.ENDC								; MF203
									; MF203
	.IF DF	P$$CTL							;MSH142
									;MSH142
FMASK3      =FMASK3!F3.PMN		;POOL MONITOR SUPPORT			;MSH142
									;MSH142
	.ENDC								;MSH142
									;MSH142
	.IF DF	K$$W11							;MSH156
									;MSH156
FMASK3=FMASK3!F3.WAT		;WATCHDOG TIMER SUPPORTED		;MSH156
									;MSH156
	.ENDC								;MSH156
									;MSH156
	.IF DF	R$$LKL							;MSH160
									;MSH160
FMASK3=FMASK3!F3.RLK		;RECORD LOCKING SUPPORT			;MSH160
									;MSH160
	.ENDC								;MSH160
									;MSH160
	.IF DF	D$$SHF							;MSH184
									;MSH184
FMASK3=FMASK3!F3.SHF		;SYST      EM SUPPORTS THE MEMORY SHUFFLER	;MSH184
									;MSH184
	.ENDC								;MSH184
									;MSH184


;
; NULL TASK CONTROL BLOCK
;
; THIS TCB TERMINATES THE SYSTEM AND ACTIVE TASK LISTS.  IT MUST HAVE
; A PRIORITY OF ZERO AND ALWAYS BE BLOCKED.  REQUIRED POSITIONS ARE
; ENFORCED BY THE "ASSUME" MACRO.
;

$CMBEG::			;BEGINNING OF SYSCM AREA FOR CDA
$HEADR::.WORD	0		;T.LNK-POINTER TO CURRENT TASK HEADER
	ASSUME	.-$HEADR,T.PRI	;T.PRI MUST BE ZERO
	.BYTE	0		;T.PRI-NULL TASK PRIORITY IS ZERO
$CURP      R::.BYTE	0		;T.IOC-CURRENT TASK PRIORITY
$COMEF::.WORD	0		;T.TCB-COMMON EVENT FLAGS 1-16
	.WORD	0		;T.NAM-COMMON EVENT FLAGS 17-32
$SYSID::.WORD	B$$LV1		;T.NAME+2-SYSTEM IDENTIFICATION		;MSH043
	.WORD	B$$LV2		;T.RCVL-SYSTEM IDENTIFICATION		;MSH043
$TKNPT::.WORD	0		;T.RCVL+2-POINTER TO TKTN TCB		;**-1
$SHFPT::.WORD	0		;T.ASTL-POINTER TO SHUFFLER TCB
$CKCNT::.WORD	K$$CNT		;T.ASTL+2-ADDRESS OF CLOCK COUNT REG
$CKCSR::.WORD	K$$CSR		;T.EFLG-ADDR OF CLOCK CNTRL STATUS REG


	.IF EQ	K$$CSR-177546

$CK      LDC::.WORD	0		;T.EFLG+2-CLOCK LOAD COUNT

	.IFF

$CKLDC::.WORD	K$$LDC		;T.EFLG+2-CLOCK LOAD COUNT

	.ENDC


	.IF NDF	M$$NET							;MSH080
									;MSH080
$NTUIC::			;DEFINED FOR MCR			;MSH080
									;MSH080
	.ENDC								;MSH080
									;MSH080
$LBUIC::			;LIBRARY UIC				;MSH158
$SYUIC::.WORD	SYUIC		;T.UCB-DEFAULT SYSTEM UIC		;MSH080
									;**-12

	ASSUME	.-$HEADR,T.TCBL	;T.TCBL MUST BE ZERO


	.IF NDF E$$LOG							;DTB004
									;**-1
$ERRSQ::			;ERROR SEQ # ALWAYS ZERO IF       NO LOGGING

	.ENDC


	.WORD	0		;T.TCBL-LINK TO NEXT TCB
	ASSUME	.-$HEADR,T.STAT	;T.STAT MUST BE NONZERO
$EXSIZ::.WORD	$SYTOP		;T.STAT-ADDR OF LAST BYTE IN EXEC
$PWRFL::.WORD	1		;T.ST2-POWERFAIL RECOVERY REQUEST FLAG
$SIGFL::.WORD	0		;T.ST3-TASK WAITING FOR SIG EVENT
$LOGHD::.WORD	0		;T.DPRI-LOGICAL DEVICE ASSIGNMENT LIST	;MSH069
$MCRCB::.WORD	0		;T.LBN+1-MCR COMMAND BLOCK ADDRESS	;**-1
$LSTLK::.WORD	0		;T.LDV-LOCK WORD (TCB ADDRESS OF OWNER)
	.WORD	3		;T.PCB-CONSTANT FOR ALLOCATION ROUTINES
$C      RAVL::.WORD	$SYBEG		;T.MXSZ-POOL FREE BLOCK LISTHEAD	;MSH069
	ASSUME	.-$HEADR,T.ACTL	;T.ACTL MUST BE ZERO			;**-1
	.WORD	0		;T.ACTL-NEXT ACTIVE TASK-DUMMY BLK SIZE
$ACTHD::.WORD	$HEADR		;T.SAST-ACTIVE TASK LIST LISTHEAD	;MSH069
$DICSV::.WORD	1		;    ,T.TIO-SAVED DIC AND DPB LENGTH	;MSH069
$TKTCB::.WORD	$HEADR		;T.TKSZ-POINTER TO CURRENT TASK TCB	;MSH069
	ASSUME	.-$HEADR,T.TKSZ+2					;MSH069

;
; END OF SUPERIMPOSED AREA-REMAINING SYSTEM COMMON AREA
;

$ABTIM::.WORD	0		;ABSOLUTE TIME COUNTER			;*      *-1
$RQSCH::.WORD	$HEADR		;SCHEDULE REQUEST TCB ADDRESS		;**-1
$STKDP::.WORD	0		;STACK DEPTH INDICATOR
$DEVHD::.WORD	$DEVTB		;POINTER TO FIRST DEVICE CONTROL BLOCK
$RNDCT::			;DEFINE FOR MCR				;MSH098
									;MSH098
	.IF DF	R$$NDC							;MSH098
									;MSH098
	.WORD	R$$NDC		;ROUND ROBIN SCHEDULING INTERVAL	;MSH098
									;MSH098
	.ENDC								;MSH098
									;MSH098
$SWPCT::			;DEFINE FOR MCR				;MSH098
									;MSH098
	.IF DF	S$$WPC&D$$ISK						;MSH098
									;MSH098
	.WORD	S$$WP      C		;DISK SWAPPING INTERVAL			;MSH098
									;MSH098
	.ENDC								;MSH098
									; MF203
	.IF NDF A$$CLI							; MF203
									; MF203
$MCRPT::.WORD	0		;POINTER TO MCR TCB

	.IF DF M$$CLI

	.ASCIZ	<15><12>/MCR>/	;MCR PROMPT STRING
	.EVEN

	.ENDC	;M$$CLI
									; MF203
	.ENDC	;A$$CLI							; MF203

$ERRPT::.WORD	0		;POINTER TO ERROR LOGGER TCB
$CFLPT::.WORD	0		;POINTER TO FIRST CHECKPOINT FILE PCB
	.BLKW	1		;CLOCK INTERRUPT FORK BLOCK LINK
	.BLKW	1		;CLOCK INTERRUPT FORK BLOCK PC
      $INTCT::.WORD	-1		;CLOCK INTERRUPT TICKS COUNT
$FRKHD::.WORD	0		;FORK QUEUE LISTHEAD
	.WORD	$FRKHD		;(LAST POINTS TO FIRST INITIALLY)
$FMASK::.WORD	FMASK		;SYSTEM FEATURE MASK
	.WORD	FMASK2		;SYSTEM FEATURE MASK (2ND WORD)		;MSH045
	.WORD	FMASK3		;SYSTEM FEATURE MASK (3RD WORD)		;MSH097
$HFMSK::			;HARDWARE FEATURE MASK			;MSH149
									;MSH149
	.IF DF	M$$EIS							;MSH149
									;MSH149
	.WORD	HF.FPP!HF.EIS	;EIS, NO FPP ASSUMED			;MSH149
									;MSH149
	.IFF								;MSH149
									;MSH1      49
	.WORD	HF.FPP		;NO FPP ASSUMED				;MSH149
									;MSH149
	.ENDC								;MSH149
									;MSH142
;									;MSH142
; THE FOLLOWING WORDS ARE USED FOR THE POOL MONITOR INTERFACE.		;MSH142
; THE ORDERING OF THESE WORDS CANNOT BE CHANGED BECAUSE PMT AND VMR	;MSH142
; ARE WRITTEN TO DEPEND ON IT.						;MSH142
;									;MSH142
									;MSH142
	.IF DF	P$$CTL							;MSH142
									;MSH142
$PTTCB::.WORD	0		;TCB ADDRESS OF POOL RECOVERY TASK	;MSH142
$PRISZ::.WORD	0		;TOTAL SIZE OF FREE POOL		;MS      H142
$POLST::.WORD	0		;EXEC/POOL TASK COMMUNICATIONS WORD	;MSH142
$PRIHL::.WORD	P$$HIL		;HIGH WATER MARK FOR POOL MONITORING	;MSH142
$PRILL::.WORD	P$$LOL		;LOW WATER MARK FOR POOL MONITORING	;MSH142
$PFRSZ::.WORD	P$$FRS		;MINIMUM SIZE OF LARGEST FRAGMENT	;MSH142
$POLBP::.WORD	P$$BPR		;MINIMUM PRIORITY OF NONPRIVILEGED	;MSH142
				;TASKS TO EXECUTE DURING LOW POOL	;MSH142
$POLFL::.WORD	0		;EXECUTIVE POOL USAGE CONTROL FLAGS	;MSH142
									;MSH142
	.IFF								;MSH142
									;MSH142
$PTTCB::			      ;ALWAYS DEFINE THESE LABELS		;MSH142
$PRISZ::								;MSH142
$POLST::								;MSH142
$PRIHL::								;MSH142
$PRILL::								;MSH142
$PFRSZ::								;MSH142
$POLBP::								;MSH142
$POLFL::								;MSH142
									;MSH142
	.ENDC								;MSH142
									;MSH156
$WTDUM::								;MSH156
									;MSH156
	.IF DF	K$$W11							;MSH156
									;MSH156
	.WORD	0		;DUMMY WATCHDOG TIMER CSR BLOCK		;MSH156
	.WORD	0		;					;MSH156
									;MSH156
	.IFTF								;MSH156
									;MSH156
$WTCSR::					      			;MSH156
									;MSH156
	.IFT								;MSH156
									;MSH156
	.WORD	$WTDUM		;WATCHDOG TIMER CSR POINTER		;MSH156
	.WORD	0		;					;MSH156
									;MSH156
	.ENDC								;MSH156


	.IF DF	P$$RTY

$PARPT::.WORD	$PARTB		;PARITY ADDRESS VECTOR TABLE POINTER

	.IFF

$PARPT::.WORD	0		;PARITY ADDRESS VECTOR TABLE POINTER

	.ENDC


$CLKHD::.WORD	0		;CLOCK QUEUE
$COPT::	.WORD	.CO0		;POINTER TO COMMAND OUTPUT UCB


	.IF NDF	L$$LDR&R$$11S

$PARHD::.WORD	$PCBS		;POINTER TO PARTITION LIST      
$LDRPT::.WORD	.LDR		;POINTER TO LOADER TCB
$TSKHD::.WORD	$STD		;POINTER TO SYSTEM TASK DIRECTORY

	.IFF

$PARHD::.WORD	0		;POINTER TO PARTITION LIST
$LDRPT::.WORD	0		;POINTER TO LOADER TCB
$TSKHD::.WORD	$HEADR		;POINTER TO SYSTEM TASK DIRECTORY

	.ENDC

;									;MSH045
; IF D$$PAR IS DEFINED, THEN A SIGNIFICANT AMOUNT OF EXECUTIVE		;MSH045
; CODE IS PLACED IN TWO EXTERNAL 'EXECUTIVE COMMONS' IN AN EFFORT	;MSH045
; TO MAXIMIZE THE AMOUNT OF ADDRESS SPACE TO BE DEVOTED TO MAPPING	;MSH045
; T      HE DYNAMIC STORAGE REGION (POOL). THE FOLLOWING TWO POINTERS		;MSH045
; CONTAIN THE OFFSET IN 32-WORD BLOCKS OF EACH EXECUTIVE COMMON.	;MSH045
; THESE TWO POINTERS ARE ASSUMED TO BE CONTIGUOUS BY PRIVILEGED		;MSH045
; CODE SUCH AS VMR. 							;MSH045
;									;MSH045
; IF THESE POINTERS ARE ZERO, THEN THE EXECUTIVE COMMONS CANNOT		;MSH045
; BE MAPPED (THROUGH KERNEL APR5) AND THE OPERATING SYSTEM CANNOT	;MSH045
; FUNCTION.								;MSH045
;									;MSH045
$XCOM1::			;REF LABEL				;MSH045
								      	;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
	.WORD	0		;DIRECTIVE PARTITION RELOCATION BIAS	;MSH045
									;MSH045
	.IFTF								;MSH165
									;MSH165
$XCOM2::			;REF LABEL				;MSH165
									;MSH165
	.IFT								;MSH165
									;MSH165
	.WORD	0		;SECOND DIRECTIVE PAR RELOCATION BIAS	;MSH165
									;MSH165
	.ENDC								;MSH045
									;MSH045
$GGEF::				;REF LABEL				;MSH049
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
	.WORD	0		;GROUP GLOBAL CONTROL       BLOCKS LISTHEAD	;MSH049
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
$GFTCB::.WORD	$GEFDM		;GRP GLOBAL USER TCB POINTER		;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH076
$GEFPT::.WORD	$GEFDM		;GROUP GLOBAL MASK ADDRESS POINTER	;MSH049
$GEFDM::.WORD	0		;DUMMY MASK ADDRESS WORD		;MSH049
									;MSH049
	.ENDC								;MSH049
									;**-1
$IDLCT::.BYTE	0		;IDLE PATTERN COUNT BYTE
$IDLFL::.BYTE	0		;IDLE PATTERN FLAG BYTE
$IDLPT::								;MSH141
									      ;MSH141
	.IF DF	P$$P45							;MSH141
									;MSH141
	.WORD	7760		;IDLE PATTERN WORD			;MSH141
									;MSH141
	.ENDC								;MSH141
									;**-1
;
; DAYS PER MONTH TABLE (ENTRY CONTAINS DAYS PER MONTH + 1)
;

$DYPMN::.BYTE	29.,32.		;FEBRUARY, MARCH
	.BYTE	31.,32.		;APRIL, MAY
	.BYTE	31.,32.		;JUNE, JULY
	.BYTE	32.,31.		;AUGUST, SEPTEMBER
	.BYTE	32.,31.		;OCTOBER, NOVEMBER
	.BYTE	32.,32.		;DECEMBER, JANUARY

;
; BIT MASK TABLE
;

$BTMSK::.WORD	1		;BIT 0.
	.WORD	2		;BIT 1.
	.WORD	      4		;BIT 2.
	.WORD	10		;BIT 3.
	.WORD	20		;BIT 4.
	.WORD	40		;BIT 5.
	.WORD	100		;BIT 6.
	.WORD	200		;BIT 7.
	.WORD	400		;BIT 8.
	.WORD	1000		;BIT 9.
	.WORD	2000		;BIT 10.
	.WORD	4000		;BIT 11.
	.WORD	10000		;BIT 12.
	.WORD	20000		;BIT 13.
	.WORD	40000		;BIT 14.
	.WORD	100000		;BIT 15.
									;MSH184
;									;MSH184
; MEMORY SHUFFLER RUN LIMITER SCRATCH AREA. $SHFTM IS LOADED WITH	;MSH184
; THE NUMBER OF TICKS STORED IN $SHFCT WHENEVER THE SHUFFLER ENDS	;MSH184
; EXECUTION. THIS VALUE R      EPRESENTS THE AMOUNT OF TIME THAT MUST		;MSH184
; EXPIRE BEFORE THE EXECUTIVE CAN AGAIN REQUEST THE SHUFFLER.		;MSH184
;									;MSH184
									;MSH184
$SHFTM::								;MSH184
									;MSH184
	.IF DF	D$$YNM&D$$SHF						;MSH184
									;MSH184
	.WORD	0		;SHUFFLER RUN LIMITING TIMER		;MSH184
									;MSH184
	.IFTF								;MSH184
									;MSH184
$SHFCT::								;MSH184
									;MSH184
	.IFT								;MSH184
									;MSH184
	.WORD	S$$HFC		;MINIMUM TICKS BETWEEN SHUFFLER REQUESTS;MSH184
		      							;MSH184
	.ENDC								;MSH184

;
; ONLINE ERROR LOGGING DATA BASE
;


	.IF DF E$$LOG							;DTB004
									;DTB004
$ERHEA::.WORD	0		;ERROR LOGGING MESSAGE QUEUE LISTHEAD	;DTB004
	.WORD	$ERHEA		;					;DTB004
									;DTB004
$ENTSQ::.WORD	0		;ENTRY SEQUENCE NUMBER			;DTB004
$ERRSQ::.WORD	0		;ERROR SEQUENCE NUMBER			;DTB004
									;DTB004
$ERFLA::.BYTE	0		;FLAG BYTE				;DTB004
									;DTB004
	ES.INI	==	1	;ERRLOG INITIALIZED			;DTB004
	ES.DAT	==	2	;ERRLOG RECEIVING DATA PACKETS		      ;DTB004
	ES.LIM	==	4	;ERRLOG LIMITING			;DTB004
	ES.LOG	==	10	;ERRLOG LOGGING				;DTB004
									;DTB004
$ERLOF::.BYTE	0		;LOG FILE NAME LENGTH			;DTB004
	.BLKB	34.		;LOG FILE NAME				;DTB004
									;DTB004
$ERBAF::.BYTE	0		;BACKUP FILE NAME LENGTH		;DTB004
	.BLKB	34.		;BACKUP FILE NAME			;DTB004
									;DTB004
	.EVEN								;DTB004
									;DTB004
$ERFID::.BLKW	1		;DEVICE NAME FOR LOG FILE		;DTB004
	.BLKB	2		;UNIT NUMBER AND RESERVED BYTE		;DTB004
	.BLKW	3		;FILE ID OF LOG FILE			;DTB00      4
									;DTB004
	.ENDC								;DTB004
									;DTB004
$PRMOD::.WORD	0		;PROCESSOR MODEL NUMBER			;DTB004
									;**-11

;
; SYSTEM BOOTSTRAP AND SAVE CONFIGURATION VECTOR
;

$SYSIZ::.WORD	S$$YSZ		;SIZE OF MEMORY IN 32W BLOCKS
	.BLKB	1		;PHYSICAL UNIT NUMBER OF LOAD DEVICE
	.BLKB	3		;LBN OF LOAD/SAVE IMAGE ON DISK
	.BLKW	1		;NAME OF LOAD DEVICE IN ASCII
	.BLKW	1		;SIZE OF LOAD IMAGE IN 256W BLOCKS

;
; TIME LIMIT PARAMETERS
;

	.WORD	-1		;YEARS PER UNIVERSE
	.WORD	13.		;MONTHS PER       YEAR
$DPM::	.WORD	31.		;DAYS PER MONTH (CALCULATED)		;MSH123
	.WORD	24.		;HOURS PER DAY				;**-1
	.WORD	60.		;MINUTES PER HOUR
	.WORD	60.		;SECONDS PER MINUTE


	.IF EQ	K$$CSR-177546

$TKPS::	.WORD	H$$RTZ		;TICKS PER SECOND

	.IFF

$TKPS::	.WORD	K$$TPS		;TICKS PER SECOND

	.ENDC


;
; CURRENT TIME VECTOR
;

	.WORD	74.		;YEAR OF UNIVERSE
	.WORD	4		;MONTH OF YEAR
	.WORD	29.		;DAY OF MONTH
	.WORD	0		;HOUR OF DAY
	.WORD	0		;MINUTE OF HOUR
	.WORD	0		;SECOND OF MINUTE
$TTNS::	.WORD	0	      	;TICK OF SECOND
									;MSH123
;									;MSH123
; SET SYSTEM TIME DIRECTIVE PARAMETER VALIDATION TABLE. NOTE THAT	;MSH123
; THE HIGH LIMIT FOR THE YEAR PARAMETER CORRESPONDS TO THE		;MSH123
; YEAR 2128. THIS SEEMINGLY RESTRICTIVE HIGH LIMIT PREVENTS USERS	;MSH123
; FROM SPECIFYING THEIR YEAR PARAMETER BASED ON ZERO, RATHER THAN	;MSH123
; THE YEAR 1900.							;MSH123
;									;MSH123
									;MSH123
	.IF DF	S$$TIM							;MSH123
									;MSH123
$TLMTS::.WORD	200,0		;YEAR LIMITS (BASED ON 19      00)		;MSH123
	.WORD	12.,1		;MONTH LIMITS				;MSH123
	.WORD	0,1		;DAY LIMITS (HIGH DYNAMICALLY DETERMINED;MSH123
	.WORD	23.,0		;HOUR LIMITS				;MSH123
	.WORD	59.,0		;MINUTE LIMITS				;MSH123
	.WORD	59.,0		;SECOND LIMITS				;MSH123
$TIKLM::.WORD	0,0		;TICK LIMITS (HIGH DETERMINED AT BOOT)	;MSH123
									;MSH123
	.IFF								;MSH123
									;MSH123
$TIKLM::			;REF LABEL FOR SAV			;MSH123
									;MSH123
	.ENDC								;MSH123

;
; LIFO SEND AND I/O PREALLOCATION LIST POINTER AND PARAMETERS
;      


	.IF DF	Q$$OPT

$PKAVL::.WORD	0		;POINTER TO FIRST PACKET IN LIST
$PKNUM::.BYTE	0		;NUMBER OF PACKETS CURRENTLY IN LIST
$PKMAX::.BYTE	Q$$OPT		;MAXIMUM NUMBER ALLOWED IN LIST

	.IFF

$PKNUM::			;REF LABEL FOR MCR
$PKMAX::			;REF LABEL FOR MCR

	.ENDC


;
; GLOBAL TASK SIZE LIMIT FOR EXTEND TASK DIRECTIVE
;


	.IF DF	E$$XPR&M$$MGE&D$$YNM

$MXEXT::.WORD	177777		;INITIALIZE TO NO LIMIT

	.IFF

$MXEXT::			;REF LABEL

	.ENDC


;
; UMR ALLOCATION LISTHEAD AND WAIT QUEUE LISTHEA      D.  THE ALLOCATION
; LISTHEAD DOUBLES AS A DESCRIPTOR OF THE UMR'S STATICLY ALLOCATED TO
; THE EXEC AND ANYONE ELSE.
;


	.IF DF	M$$EXT

$UMRHD::.WORD	0		;MAPPING ASSIGNMENT BLOCK LISTHEAD
$UMRPT::.WORD	UBMPR		;ADDRESS OF FIRST ASSIGNED UMR		;MSH097
	.WORD	N$$UMR		;NUMBER OF UMR'S STATICLY ASSIGNED * 4	;**-1
$UMRWT::.WORD	0,.-2		;UMR WAIT QUEUE LISTHEAD
									;MSH097
	.IFF								;MSH097
									;MSH097
$UMRPT::			;REF LABEL FOR MAPPED SAV		;MSH097

	.ENDC

;									;**-11
; TEMPORA      RY STORAGE FOR SPAWN
;

	.IF DF P$$OFF

$TEMP0::.WORD	0
$TEMP1::.WORD	0

	.ENDC	;P$$OFF

;									;MSH046
; TEMPORARY STORAGE AREA FOR $GSPKT AND GCCI$ DIRECTIVE			;MSH046
;									;MSH046
									;MSH046
	.IF DF	A$$BIO!A$$CLI!R$$POI!R$$UDA				;MSH159
									;MSH046
$TEMP2::.BLKW	1		;TEMPORARY STORAGE			;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
;									; MF207
; TEMPORARY STORAGE FOR THE RPOI$ AND SDRP$ DIRECTIVES			; MF207
;									; MF207
									; MF2      07
									; MF207
	.IF DF	R$$POI&P$$OFF						; MF207
									; MF207
$TEMP4::.WORD	0							; MF207
									; MF207
	.ENDC	;R$$POI&P$$OFF						; MF207
									; MF207

	.IF DF	A$$NSI							;MSH150
									;MSH150
$AVRHD::.WORD	0		;AVR UNIT TABLE LISTHEAD		;MSH150
									;MSH150
	.ENDC								;MSH150
									;MSH150
$MOULS::.WORD	0		;MOUNTED DEVICE LISTHEAD		;**-1

$CXDBL::.BYTE	0		;CONTEXT SWITCHING DISABLED FLAG (0=NO)
	.BYTE	0		;UNUSED BYTE				;MSH079
									;MSH079
$SYSNM::.      WORD	S$$NM1,S$$NM2,S$$NM3 ;SYSTEM NAME			;MSH079
									;MSH079
	.IF DF	M$$NET							;MSH079
									;MSH080
$NTUIC::.WORD	SYUIC		;NETWORK UIC				;MSH080
$NETPF::.WORD	0		;NETWORK POWERFAIL RECOVERY ROUTINE	;MSH128
									;MSH128
	.ENDC								;MSH079
									; MF203
	.IF DF	A$$CLI							; MF203
									; MF203
;									; MF203
; THE FOLLOWING STRUCTURES FORM THE DATA BASE FOR ALTERNATE CLI SUPPORT	; MF203
;									; MF203
									; MF203
$CLICQ::.WORD	0		;COMMAND QUEUE FOR CLIS			;       MF203
	.WORD	$CLICQ		;					; MF203
;									; MF203
; THE FOLLOWING TABLE CONTAINS POINTERS TO THE CPB BLOCKS FOR CLIS THAT	; MF203
; THE SYSTEM KNOWS ABOUT. THIS TABLE IS INDEXED BY BITS 1 - 4 OF U.MUP I; MF203
; THE TERMINALS UCB, TO DETERMINE THE CLI ASSOCIATED WITH THAT TERMINAL	; MF203
									; MF203
$CPTBL::.WORD	$MCRPT		;ENTRY FOR MCR TERMINALS		; MF203
									; MF203
	.REPT	A$$CLI-1						; MF203
									; MF203
	.WORD	0		;SPACE FOR USER WRITTEN CLIS		; MF203
									; MF203
	.EN      DR								; MF203
									; MF203
$NMCLI==A$$CLI			;NUMBER OF CLIS SYSTEM WILL SUPPORT	; MF203
									; MF203
;									; MF203
; CLI PARSER BLOCK (CPB) FOR THE MCR CLI				; MF203
;									; MF203
$MCRPT::.WORD	0		;POINTER TO MCR TCB			; MF203
	.RAD50	/MCR   /	;NAME OF CLI				; MF203
	.WORD	CP.SGL!CP.LGO	;NO CONT. LINES, ALLOW LOGGED OFF TT'S	; MF203
	.BYTE	MDPL		;LENGTH OF DEFAULT PROMPT		; MF203
	.BYTE	MCPL		;LENGTH OF CNTRL/C PROMPT		; MF203
$$$=.									; MF203
	.ASCIZ	<15><12>/>/	;DEF      AULT PROMPT STRING			; MF203
MDPL=.-$$$								; MF203
$$$=.									; MF203
	.ASCIZ	<15><12>/MCR>/	;CNTRL/C PROMPT STRING			; MF203
MCPL=.-$$$								; MF203
									; MF203
	.EVEN								; MF203
									; MF203
	.IFF	;A$$CLI							; MF203
									; MF203
$CLICQ::								; MF203
$CPTBL::								; MF203
$NMCLI==0			;NO ALTERNATE CLI SUPPORT		; MF203
									; MF203
	.ENDC	;A$$CLI							; MF203
									; DD098
	.IF DF	T$$CPW&T$$ACD						; DD098
									; DD098
$ACDHD::.WORD	0		;ANCILL       ARY CONTROL DRIVER BLOCK LISTHEAD; DD098
									; DD098
	.ENDC	;T$$CPW&T$$ACD						; DD098
									;**-1

$CMFIN::			;END OF SYSCM AREA FOR CDA
	.END
           ¼8ðskQ	› c,        	.TITLE	ICDRV
	.IDENT	/02.05/
 
;
; COPYRIGHT (C) 1975,1978,1979,1980
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 02.05
;
; C. MONIA 05-APR-75
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;	C. A. MONIA
;
; MODIFIED BY:
;
;	G. H. KUENNING 09-AUG-77
;
;		GK001 -- CHECK FOR EXISTENCE OF CIRCULAR BUFFER
;			BEFORE USING IT.  (SPR # 11-12905).
;
;      	G. H. KUENNING 13-OCT-77
;
;		GK002 -- WHEN UNLINKING INTERRUPTS FROM TASKS, DON'T
;			RESTORE REGISTERS THAT WEREN'T SAVED.
;
;	G. H. KUENNING 17-JAN-78
;
;		GK004 -- MOVE A MISPLACED LABEL THAT CAUSES A SYSTEM
;			CRASH WHEN AN I/O CANCEL IS DONE ON AN ICS/ICR.
;
;	G. H. KUENNING 30-JAN-79
;
;		GK005 -- ON STARTUP, READ THE CURRENT STATE OF THE
;			DIGITAL INTERRUPT POINTS RATHER THAN SETTING THE
;			CURRENT STATE TO ZERO.
;
;	J. H. MATTHEWS	1-OCT-79
;
;		JM043 -- RESTORE R4 AT END OF "      READDI" (FROM S. HIMMELSTEIN)
;
;	T. LEKAS 27-MAY-80
;
;		TL045 -- FIX CONDITIONAL ASSEMBLY
;
;	H. BERNSTEIN 8-DEC-80
;
;		HB001 -- FIX CONDITIONAL ASSEMBLY
;
; ICR/ICS-11 INDUSTRIAL CONTROL SUBSYSTEM DRIVER
;
; EQUATED SYMBOLS
;
; A/D CONVERTER TABLE OFFSETS
;

	.ASECT

.=0
ADMXC:	.BLKW	1		; MAXIMUM A/D CHANNEL NUMBER
ADFR:	.BLKB	1		; FORK REQUEST FLAG
ADIP:	.BLKB	1		; I/O CONVERSIONS IN-PROGRESS COUNT
ADNXT:	.BLKW	1		; TABLE ADDRESS OF NEXT ADU02
ADNXA:	.BLKW	2		; USER BUFFER ADDRE      SS DOUBLEWORD OF NEXT
ADNXB:	.BLKW	1		; BYTE COUNT FOR NEXT TRANSFER
ADNXC:	.BLKW	1		; CONTROL WORD FOR NEXT TRANSFER
ADFBC:	.BLKW	1		; FINAL BYTE COUNT
ADSTS:	.BLKW	1		; I/O COMPLETION STATUS

;
; A/D CONVERTER TABLE ENTRY OFFSETS
;

.=0
ADHCH:	.BLKB	1		; HIGHEST CHANNEL NUMBER ON THIS MODULE
ADBSY:	.BLKB	1		; ADU02 BUSY FLAG
ADUAD:	.BLKW	2		; ADDRESS DOUBLEWORD
ADBTC:	.BLKW	1		; BYTE COUNT FOR THIS CONVERSION
ADMBA:	.BLKW	1		; ADU02 BUS ADDRESS
ADLGH:	.BLKW	0		; LENGTH OF A/D MODULE ENTRY      

;
; CIRCULAR BUFFER HEADER OFFSETS
;

.=0
CBSY:	.BLKW	1		; BUSY COUNT
COUT:	.BLKW	1		; OUTPUT POINTER
CIN:	.BLKW	1		; INPUT POINTER
CMAX:	.BLKW	1		; ADDRESS OF END OF BUFFER
CDAT:	.BLKW	16.		; DATA AREA
CLGH:	.BLKW	0		; LENGTH OF CIRCULAR BUFFER

;
; ICR DEVICE TABLE OFFSETS
;

.=0
ICMAX:	.BLKW	1		; MAXIMUM PHYSICAL UNIT NUMBER
ICRES:	.BLKW	1		; ERROR RESOURCE MASK
ICELH:	.BLKW	2		; ERROR INTERRUPT LISTHEAD
ICLTL:	.BLKW	2		; LINKED TASK LISTHEAD

;
; INTERRUPT LINKAGE ENTRY OFFSETS      
;

.=0
ILNXT:	.BLKW	1		; LINK TO NEXT
ILMSK:	.BLKW	1		; RESOURCE MASK WORD
ILTE:	.BLKW	1		; ADDRESS OF LINKED TASK ENTRY
ILEVM:	.BLKW	1		; EVENT FLAG MASK WORD
ILEVA:	.BLKW	1		; EVENT FLAG MASK ADDRESS
ILRUN:	.BLKW	1		; RUN FLAG
ILGH:	.BLKW	0		; LENGTH OF ENTRY

;
; UNSOLICITED INTERRUPTING MODULE OFFSETS
;

.=0
IMAX:	.BLKW	1		; HIGHEST POINT OR CHANNEL
IMBPE:	.BLKB	1		; BYTES PER CIRCULAR BUFFER ENTRY
IMFIP:	.BLKB	1		; FORK-IN-PROGRESS FLAG
IMSBF:	.BLKW	1		; STARTING BUFFER RELOCATION       BIAS
IMCBF:	.BLKW	1		; CURRENT BUFFER RELOCATION BIAS
IMSAD:	.BLKW	1		; ADDRESS OF START OF BUFFER
IMSDA:	.BLKW	1		; ADDRESS OF START OF DATA
IMCUR:	.BLKW	1		; ADDRESS OF CURRENT ENTRY
IMFIL:	.BLKW	1		; CURRENT FORTRAN FILL INDEX
IMLGH:	.BLKW	1		; LENGTH OF CIRCULAR BUFFER IN WORDS
IMEVM:	.BLKW	1		; EVENT FLAG MASK WORD
IMEVA:	.BLKW	1		; EVENT FLAG MASK ADDRESS
IMLST:	.BLKW	1		; LOST DATA COUNT
IMTCB:	.BLKW	1		; TCB ADDRESS OF CONNECTED TASK
IMFRK:	.BLKW	3		; INTERRUPT FORK BLOCK
IMSCB:	.BLKW	1	      	; SCB BACKPOINTER

IMDAT:	.BLKW	0		; OFFSET TO MODULE DATA

;
; INTERRUPT MODULE ENTRY OFFSETS
;

.=0
IMRES:	.BLKW	1		; DIGITAL INTERRUPT RESOURCE MASK
IMLH:	.BLKW	2		; INTERRUPT LINK LISTHEAD
IMPRV:	.BLKW	1		; PREVIOUS STATE OF MODULE
RTLGH:	.BLKW	0		; LENGTH OF REMOTE TERMINAL ENTRY
IMBA:	.BLKW	1		; BUS ADDRESS OF MODULE
CILGH:	.BLKW	0		; LENGTH OF DIGITAL INTERRUPT ENTRY
CTLGH:	.BLKW	0		; LENGTH OF COUNTER MODULE ENTRY

;
; LINKED TASK ENTRY OFFSETS
;

.=0
LNEXT:	.BLKW	1		; LINK TO       NEXT (0=NONE)
LUSE:	.BLKW	1		; NUMBER OF LINKAGES IN USE
LTCB:	.BLKW	1		; TASK TCB ADDRESS
LACT:	.BLKW	1		; ACTIVITY COUNT
LPHY:	.BLKW	1		; PHYSICAL UNIT NUMBER
LGEN:	.BLKW	1		; GENERIC CODE
LREL:	.BLKW	1		; RELATIVE MODULE NUMBER
LHWR:	.BLKW	2		; HARDWARE DEPENDANT DATA
LPAD:	.BLKW	1		; PAD ENTRY TO MULTIPLE OF ALLOCATION INCREMENT
LLGH:	.BLKW	0		; LENGTH OF ENTRY

;
; QIO ADDRESS CHECKING FLAGS
;

CHADR=000001			; BUFFER ADDRESS MUST BE ON WORD BOUNDARY (1=YES)
CHBYT=000002			; BYTE COUNT       MUST BE EVEN(1=YES)

;
; SCB FLAGS WORD BIT DEFINITIONS
;

UFL=000001			; UNIT OFFLINE (1=YES)
UNR=000002			; UNIT NOT-READY (1=YES)
TUND=000004			; TERMINAL OUTPUT UNDERWAY (1=YES)
TUSE=000010			; TERMINAL IN USE (1=YES)
NORSP=000020			; NO RESPONSE FROM CONTROLLER (1=YES)
TABO=000040			; ABORT TERMINAL OUTPUT (1=YES)

;
; ICS/ICR INTERRUPT TIMEOUT COUNT
;

TMOUT=50.			;

;
; FIRST EXTERNAL PAGE ADDRESS
;

ICMD=171000			;

	.PSECT

;
; LOCAL DATA
;
; DRIVER DISPATCH TABLE
;      

$ICTBL::.WORD	ICHK		; DEVICE INITIATOR ENTRY POINT
	.WORD	ICAN		; CANCEL I/O OPERATION ENTRY POINT
	.WORD	ICOUT		; DEVICE TIMEOUT ENTRY POINT
	.WORD	ICPWF		; POWER RECOVERY ENTRY POINT

;
; UCB ADDRESSES
;

	.IF DF	I$$CAD!I$$CIM!I$$CTI!I$$CR


CNTBL:	.BLKW	I$$C11		;

;
; ADDRESS OF CURRENT CSR
;

CSR:	.BLKW	1		;

;
; ICR DEVICE TABLE
;

	.IF DF	I$$CLK

ICDVT:	.WORD	I$$C11-1	; MAXIMUM PHYSICAL UNIT NUMBER
	.WORD	0		; ERROR INTERRUPT RESOURCE MASK
	.WORD	0		; ERROR INTERRUPT LIS      THEAD
	.WORD	.-2		; LAST POINTS TO FIRST INITIALLY
	.WORD	0		; LINKED TASK LISTHEAD
	.WORD	.-2		; LAST POINTS TO FIRST INITIALLY

	.ENDC

	.ENDC

;
; LEGAL FUNCTION CODES AND DISPATCH TABLE
;
; EACH ENTRY CONSISTS OF TWO WORDS CONTAINING THE FOLLOWING
; INFORMATION:
;
;	WD. 00 -- QIO FUNCTION CODE.
;	WD. 01 -- ADDRESS OF PROCESSOR/2 ! CONTROL FUNCTION FLAG (MSB).
;
; IF MSB .EQ. 1 THEN THE FUNCTION REQUIRES THE TRANSMISSION OF DATA
; TO OR FROM THE DEVICE.
;

ICDIS:				;

	.IF DF	I$$      CDA

	.WORD	IO.SAO,100000!<AOUT/2&77777> ; ANALOG OUTPUT

	.ENDC

	.IF DF	I$$CSS

	.WORD	IO.MSO,100000!<SSOUT/2&77777> ; MOMENTARY DIGITAL OUTPUTS

	.ENDC

	.IF DF	I$$CLT

	.WORD	IO.MLO,100000!<LTOUT/2&77777> ; LATCHING OUTPUTS

	.ENDC

	.IF DF	I$$CAD

	.WORD	IO.RBC!CHADR!CHBYT,100000!<ADINI/2&77777> ; READ MULTIPLE A/D CHANNELS

	.ENDC

	.IF DF	I$$CIM

	.WORD	IO.CCI!CHADR!CHBYT,CICNT/2&77777 ; CONTACT INTERRUPT CONNECT
	.WORD	IO.DCI,CIDCT/2&77777 ; CONTACT INTERRUPT DISCONNECT
      
	.IF DF	I$$CLK

	.WORD	IO.LDI,CILNK/2&77777 ; LINK TO DIGITAL INTERRUPTS
	.WORD	IO.UDI,CIUNL/2&77777 ; UNLINK DIGITIAL INTERRUPTS

	.ENDC


	.ENDC

	.IF DF	I$$CTI

	.WORD	IO.CTI!CHADR!CHBYT,100000!<CTCNT/2&77777> ; COUNTER MODULE CONNECT
	.WORD	IO.DTI,CTDCT/2&77777 ; COUNTER MODULE DISCONNECT

	.IF DF	I$$CLK

	.WORD	IO.LTI,CTLNK/2&77777 ; LINK TO COUNTER MODULE INTERRUPTS
	.WORD	IO.UTI,CTUNL/2&77777 ; UNLINK FROM COUNTER INTERRUPTS

	.ENDC

	.WORD	IO.ITI,100000!<CTINI/2&77777> ; INITI      ALIZE COUNTER

	.ENDC

	.IF DF	I$$CR

	.WORD	IO.WLB,100000!<RTINI/2&77777> ; OUTPUT TO REMOTE TERMINAL
	.WORD	IO.CTY!CHADR!CHBYT,RTCNT/2&77777 ; REMOTE TERMINAL CONNECT
	.WORD	IO.DTY,RTDCT/2&77777 ; REMOTE TERMINAL DISCONNECT

	.IF DF	I$$CLK

	.WORD	IO.LTY,RTLNK/2&77777 ; LINK TO REMOTE TERMINAL INTERRUPTS
	.WORD	IO.UTY,RTUNL/2&77777 ; UNLINK REMOTE TERMINAL INTERRUPTS
	.WORD	IO.LKE,ERLNK/2&77777 ; LINK TO ERROR INTERRUPTS
	.WORD	IO.UER,ERUNL/2&77777 ; UNLINK ERROR INTERRUPTS

	.ENDC


	      .ENDC

	.IF DF	I$$CIM!I$$CTI!I$$CR&I$$CLK

	.WORD	IO.NLK,UNLNK/2&77777 ; UNLINK FROM ALL INTERRUPTS

	.IFTF

	.WORD	IO.ONL,ICONL/2&77777 ; UNIT TO ONLINE
	.WORD	IO.FLN,ICFLN/2&77777 ; UNIT TO OFFLINE

	.IFT

	.WORD	IO.RAD,RDACT/2&77777 ; READ ACTIVATING DATA

	.ENDC

	.IF DF	I$$CDB

	.WORD	IO.ATT,ICDON/2&77777 ; NO-OP THE ATTACH FUNCTION
	.WORD	IO.DET,ICDON/2&77777 ; NO-OP THE DETACH FUNCTION

	.ENDC

	.WORD	0		; END OF TABLE

;
; ADDRESS OF CURRENT UCB
;

	.IF DF	I$$CAD!I$$CIM      !I$$CR!I$$CTI

	.IF GT	I$$C11-1

ICUCB:	.BLKW	1		;

	.ENDC

;
; FLAG TO INTIATE FORK PROCESSING FOR UNSOLICITED INTERRUPTS
;

RUN:	.BLKW	1		;

;
; NAME OF TASK BEING UNLINKED
;

	.IF DF	I$$CLK

TASK:	.BLKW	2		;

	.ENDC



;
; TEMPORARY INTERRUPT PSW STORAGE
;

TMP:	.WORD	0		;

;
; WATCHDOG TIMER FLAG
;

	.IF DF	I$$CR

WDFLG:	.WORD	0		; IF NE 0 THEN TIMER SCHEDULED
	.BLKW	5		; CLOCK QUEUE ENTRY
	.WORD	ICWDT		; ADDRESS OF INTERNAL SUBROUTINE

	.IF DF	L$$DRV&M$$MGE

      	.WORD	0		;

	.ENDC

	.ENDC

	.ENDC

;+
;
; **-ICHK-ICS/ICR-11 INDUSTRIAL CONTROL SUBSYSTEM PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM QIO DIRECTIVE PROCESSING WHEN AN
; I/O REQUEST IS RECIEVED FOR THE ICS/ICR-11 INDUSTRIAL CONTROL
; SUBSYSTEMS DEVICES. ICS/ICR-11 REQUESTS CONTAIN PARAMETERS THAT
; MUST BE CHECKED IN THE CONTEXT OF THE ISSUING TASK. THEREFORE
; THE I/O REQUEST IS NOT QUEUED BEFORE CALLING THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET
;	R4=ADD      RESS OF THE STATUS CONTROL BLOCK
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	DEPENDANT UPON FUNCTION TO BE PERFORMED
;
; ICS/ICR-11 FUNCTION INDEPENDANT I/O PACKET
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF REQUESTER TASK TCB.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE.
;	WD. 06 -- VIRTUAL A      DDRESS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;
;-

ICHK:				;
	MOV	R1,-(SP)	; SAVE I/O PACKET ADDRESS
	MOV	I.FCN(R1),R2	; GET FUNCTION CODE
	BIC	#7,R2		; CLEAR UNRECOGNIZED FLAGS
	ADD	#I.PRM,R1	; POINT TO PARAMETER BLOCK
	MOV	#ICDIS-2,R3	; POINT TO DISPATCH TABLE
10$:				;
	TST	(R3)+		; STEP TO NEXT ENTRY
	TST	(R3)		; AT END OF LIST?
	BEQ	ICIF	      	; IF EQ YES - ILLEGAL FUNCTION
	MOV	(R3)+,-(SP)	; PUSH FUNCTION CODE
	BIC	#7,(SP)		; CLEAR FLAGS
	CMP	(SP)+,R2	; TEST FUNCTION CODE
	BNE	10$		; IF NE TRY NEXT FUNCTION
	MOV	R1,R0		; COPY PARAMETER BLOCK ADDRESS
	MOV	-2(R3),R2	; GET FUNCTION CODE AGAIN
12$:				;
	BIC	#^C<7>,R2	; CLEAR ALL BUT ALIGNMENT FLAGS
	BEQ	15$		; IF EQ NO MORE TESTS TO MAKE
	TST	(R0)+		; STEP TO NEXT PARAMETER
	ROR	R2		; ROTATE ALIGNMENT FLAGS
	BCC	12$		; IF C/C BYPASS CHECK
	BIT	#1,(R0)		; PARAMETER WORD ALIGNED?
	BNE	      ICBY		; IF NE NO
	BR	12$		; GO AGAIN
15$:				;
	MOV	(R3),R3		; GET ADDRESS OF PROCESSOR
	ASL	R3		; CONVERT TO WORD ADDRESS, PUT CONTROL FLAG IN C
	MOV	I.TCB-I.PRM(R1),R0 ; GET TCB ADDRESS
	BCC	20$		; IF C/C NOT A CONTROLLER FUNCTION
	BIT	#UFL,S.FLG(R4)	; UNIT OFFLINE?

	.IF DF	I$$CR

	BNE	17$		; IF NE YES
	BIT	#UNR,S.FLG(R4)	; UNIT NOT READY?
	BNE	ICDN		; IF NE YES
	BR	20$		; ALLOW I/O

	.IFF

	BEQ	20$		; IF EQ NOT OFFLINE

	.ENDC

17$:				;
	BIT	#T3.PRV,T.ST3(R0) ; TASK PRIVILEGED?
      	BEQ	ICPR		; IF EQ NO, PRIVELEGE VIOLATION
20$:				;
	JMP	(R3)		; TRANSFER CONTROL TO PROCESSOR


;+
;
; **-ICFLN-PUT CONTROLLER OFFLINE
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- UNUSED
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

ICFLN:				;
	BIT	#T3.PRV,T.ST3(R0) ; TASK PRIVILEGED?
	BEQ	ICPR		; IF EQ NO
	BIT	#UFL,S.FLG(R4)	; UNIT ALREADY OFFLINE?
	BNE	ICFLE		; IF NE YES
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUP      TS
	BIC	#22,@S.CSR(R4)	;;; DISABLE ERROR INTERRUPTS
	BIS	#UFL,S.FLG(R4)	;;; SET UNIT OFFLINE
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	BR	ICD		;

;+
;
; **-ICONL-PLACE CONTROLLER ONLINE
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- UNUSED
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

ICONL:				;
	BIT	#T3.PRV,T.ST3(R0) ; TASK PRIVILEGED?
	BEQ	ICPR		; IF EQ NO
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUPTS
	BIS	#26,@S.CSR(R4)	;      ;; ENABLE INTERRUPTS
	BIC	#UFL!UNR,S.FLG(R4) ;;; CLEAR NOT-READY, OFFLINE BITS
	CLRB	PS		; ALLOW DEVICE INTERRUPTS

;
; INTERMEDIATE BRANCH POINTS TO ERROR EXITS
;

ICD:	JMP	ICDON		; SUCCESSFUL COMPLETION
ICBY:	JMP	ICBYT		; BUFFER BYTE ALIGNED
ICIF:	JMP	ICIFC		; ILLEGAL FUNCTION CODE
ICDN:	JMP	ICDNR		; DEVICE NOT READY
ICPR:	JMP	ICPRI		; PRIVELEGE VIOLATION
ICMO:	JMP	ICMOD		; ILLEGAL MODULE NUMBER

	.IF DF	I$$CLK

ICIE:	JMP	ICIEF		; ILLEGAL EVENT FLAG

	.ENDC

;
; REQUEST HAS BAD PARAM      ETERS
;

ICBAD:				;
	MOV	#IE.BAD&377,R0	;
	BR	ICFLE1		;

;
; RESOURCE IN USE
;

	.IF DF	I$$CIM!I$$CR!I$$CTI&I$$CLK

ICRSU:				;
	MOV	#IE.RSU&377,R0	;
	BR	ICFLE1		;

	.ENDC

;
; DEVICE ALREADY OFFLINE
;

ICFLE:				;
	MOV	#IE.FLN&377,R0	;
ICFLE1:				;
	JMP	ICOMN		;

;+
;
; **-CILNK-LINK TO CONTACT INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- EVENT FLAG NUM      BER
;	WD. 16 -- POINT NUMBER
;	WD. 17 -- CHANGE OF STATE MASK
;
;-

	.ENABL	LSB

	.IF DF	I$$CLK


	.IF DF	I$$CIM

CILNK:				;
	MOV	S.DI(R4),R0	; GET ADDRESS OF CONTACT INTERRUPT TABLE
	MOV	10(R1),R2	; GET POINT NUMBER
	BIT	#17,R2		; POINT ON MODULE BOUNDARY?
	BNE	ICMO		; IF NE NO
	ASR	R2		; COMPUTE TABLE INDEX
	ASR	R2		; ...
	ADD	10(R1),R2	; ...
	ASR	R2		; ...
	MOV	12(R1),4(R1)	; SET RESOURCE MASK
	BEQ	ICBAD		; IF EQ BAD PARAMETERS
	CLR	12(R1)		; CLEAR COUNTER FLAG
	BR	20$		;

	.E      NDC

;+
;
; **-CTLNK-LINK TO COUNTER MODULE INTERRUPTS:
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- EVENT FLAG NUMBER
;	WD. 16 -- RELATIVE COUNTER NUMBER
;	WD. 17 -- COUNTER INITIAL VALUE
;
;-

	.IF DF	I$$CTI

CTLNK:				;
	MOV	S.CT(R4),R0	; GET ADDRESS OF COUNTER TABLES
	MOV	10(R1),R2	; GET COUNTER NUMBER
	ASL	R2		; COMPUTE TABLE INDEX
	ASL	R2		; ...
	ADD	10(R1),R2	; ...
      	ASL	R2		; ...
	BR	10$		;

	.ENDC

;+
;
; **-ERLNK-LINK TO ERROR INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- EVENT FLAG NUMBER
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CR

ERLNK:				;
	MOV	#ICDVT+ICRES,R2	; POINT TO RESOURCE MASK
	MOV	#-1,4(R1)	; SET RESOURCE MASK FOR REQUEST
	CLR	12(R1)		; CLEAR COUNTER FLAG
	BR	30$		;

;+
;
; **-RTLNK-LINK       TO REMOTE TERMINAL INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 __ WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- EVENT FLAG NUMBER
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

RTLNK:				;
	MOV	S.RTI(R4),R0	; GET REMOTE TERMINAL TABLE ADDRESS
	CLR	R2		; CLEAR OFFSET TO MODULE ENTRY
	CLR	10(R1)		; CLEAR MODULE NUMBER
	CLR	12(R1)		; CLEAR COUNTER FLAG

	.ENDC

	.IF DF	I$$CIM!I$$CR!I$$CTI

10$:				;
	MOV	#-1,4(R1)	;       SET RESOURCE MASK
20$:				;
	TST	R0		; MODULE EXIST
	BEQ	ICMO		; IF EQ NO
	CMP	10(R1),(R0)	; LEGAL POINT NUMBER
	BHI	ICMO		; IF HI NO
	ADD	R0,R2		; COMPUTE MODULE ENTRY ADDRESS
	ADD	#IMDAT+IMRES,R2	; POINT TO RESOURCE MASK
30$:				;
	BIT	4(R1),(R2)+	; RESOURCE IN USE?
	BNE	ICRSU		; IF NE YES
	MOV	R1,R3		; COPY ADDRESS OF TASK NAME
	CALL	$SRSTD		; SEARCH TCB LIST FOR TASK
	BCS	ICNST		; IF C/S TASK NOT INSTALLED
	CMP	6(R1),#64.	; LEGAL EVENT FLAG SPECIFIED?
	BHI	ICIE		; IF HI NO
	MOV	R2,(R1)+      	; SAVE LISTHEAD ADDRESS
	MOV	R5,-(SP)	; SAVE R5
	MOV	R1,-(SP)	; SAVE ADDRESS OF PARAMETER BLOCK
	MOV	R0,R5		; COPY TCB ADDRESS
	MOV	4(R1),R0	; GET EVENT FLAG NUMBER
	CALL	$CEFI		; CONVERT TO MASK AND ADDRESS
	MOV	(SP),R3		; COPY PARAMETER BLOCK ADDRESS
	MOV	R0,(R3)+	; SAVE MASK
	MOV	(R3)+,(R3)	; MOVE RESOURCE MASK OUT OF THE WAY
	MOV	R1,-(R3)	; SAVE ADDRESS
	MOV	#LLGH+ILGH,R1	; GET LENGTH OF LINKED TASK+INTERRUPT LINK ENTRIES
	MOV	#ICDVT+ICLTL,R3	; POINT TO INTERRUPT LINK LISTHEAD
40$:				;
	M      OV	(R3),R3		; GET ADDRESS OF NEXT ENTRY
	BEQ	50$		; IF EQ REACHED END OF LIST
	CMP	R5,LTCB(R3)	; THIS TASK LINKED ONCE?
	BEQ	60$		; IF EQ YES
	BR	40$		; GO AGAIN
50$:				;
	CALL	$ALOCB		; ALLOCATE BLOCK
	BCS	ICNOD		; IF C/S NO MORE STORAGE
	CLR	(R0)		; CLEAR LINK TO NEXT
	MOV	R0,@ICDVT+ICLTL+2 ; LINK TO LAST ENTRY
	MOV	R0,ICDVT+ICLTL+2 ; SET NEW LAST
	MOV	R5,LTCB(R0)	; SET TCB ADDRESS
	CLR	LUSE(R0)	; CLEAR USE COUNT
	CLR	LACT(R0)	; CLEAR ACTIVITY COUNT
	MOV	R0,R5		; COPY LINKED TASK ENTRY ADDR      ESS
	ADD	#LLGH,R0	; POINT TO INTERRUPT LINK ENTRY
	BR	70$		;
60$:				;
	MOV	R3,R5		; COPY LINKED TASK ENTRY
	MOV	#ILGH,R1	; SET LENGTH OF INTERRUPT LINK ENTRY
	CALL	$ALOCB		; ALLOCATE BLOCK
	BCS	ICNOD		; IF C/S NO STORAGE AVAILABLE
70$:				;
	INC	LUSE(R5)	; INCREMENT USE COUNT
	MOV	R5,ILTE(R0)	; SET POINTER TO LINKED ENTRY
	MOV	(SP)+,R1	; RESTORE R1
	MOV	(SP)+,R5	; RESTORE R5
	MOV	-2(R1),R2	; RETRIEVE INTERRUPT LINK LISTHEAD
	MOV	R0,R3		; COPY ADDRESS OF INTERRUPT LINK ENTRY
	CLR	(R3)+		; CLE      AR LINK TO NEXT
	CMP	(R3)+,(R3)+	; POINT TO EVENT FLAG MASK
	MOV	(R1)+,(R3)+	; SAVE EVENT FLAG MASK
	MOV	(R1)+,(R3)+	; SAVE EVENT FLAG ADDRESS
	CLR	(R3)		; CLEAR RUN FLAG
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUPTS
	MOV	R0,@2(R2)	;;; LINK THIS ENTRY AS LAST
	MOV	R0,2(R2)	;;; SET NEW LAST
	BIS	(R1),-(R2)	;;; SET RESOURCE MASK
	MOV	(R1)+,ILMSK(R0)	;;; SET INTERRUPT MASK
	CLRB	PS		; ALLOW DEVICE INTERRUPTS

	.IF DF	I$$CTI

	MOV	IMBA(R2),(R1)	; COPY BUS ADDRESS
	MOV	2(R1),-(R1)	; COPY COUNTER VA      LUE
	BEQ	80$		; IF EQ COUNTER NOT TO BE SET
	MOV	(R1),IMPRV(R2)	; RESET PREVIOUS STATE
	MOV	R1,R3		; SET ADDRESS OF MODULE ENTRY
	CALL	SETCT		; INITIALIZE COUNTER
80$:				;

	.ENDC

	BR	ICDO		;

	.ENDC



	.ENDC

	.DSABL	LSB

;
; TASK NOT INSTALLED
;

	.IF DF	I$$CIM!I$$CR!I$$CTI&I$$CLK

ICNST:				;
	MOV	#IE.NST&377,R0	;
	BR	ICOM		;

	.ENDC


;+
;
; **-RDACT-READ ACTIVATING DATA
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- ADDRESS OF BUFFER TO RECEIVE ACTIVATI      NG INFORMATION
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CIM!I$$CR!I$$CTI&I$$CLK

RDACT:				;
	BIT	#1,(R1)		; BUFFER WORD ALIGNED?
	BNE	ICBYT		; IF NE NO
	MOV	#ICDVT+ICLTL,R4	; GET ADDRESS OF LINKED TASK LISTHEAD
10$:				;
	MOV	(R4),R4		; GET ADDRESS OF NEXT ENTRY
	BEQ	ICNLK		; IF EQ TASK NOT LINKED TO INTERRUPTS
	CMP	LTCB(R4),R0	; THIS ENTRY BELONG TO TASK?
	BNE	10$		; IF NE NO
	MOV	(R1),R0		; GET ADDRESS OF BUFFER TO       RECEIVE DATA
	MOV	#LPAD-LACT,R3	; SET BYTE COUNT

	.IF DF	A$$CHK!M$$MGE

	MOV	R3,R1		; COPY BYTE COUNT
	CALL	$ACHCK		; ADDRESS CHECK BUFFER
	BCS	ICSP		; IF C/S BUFFER NOT IN REQUESTORS SPACE

	.ENDC

	.IF DF	M$$MGE

	CALL	$RELOM		; RELOCATE AND MAP BUFFER

	.ENDC

	ADD	#LACT,R4	; POINT TO ACTIVITY COUNT
	ASR	R3		; SHIFT BYTE COUNT TO WORD COUNT
	MOVB	#PR6,PS		;;; INHIBIT INTERRUPTS
20$:				;;;
	MOV	(R4),(R0)+	;;; COPY ENTRY
	CLR	(R4)+		;;; CLEAR ENTRY
	DEC	R3		;;; DECREMENT COUNT
	B      NE	20$		;;; IF NE GO AGAIN
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	BR	ICDO		;

	.ENDC

;
; TASK NOT LINKED TO INTERRUPTS
;

	.IF DF	I$$CIM!I$$CR!I$$CTI&I$$CLK

ICNLK:				;
	MOV	#IE.NLK&377,R0	;
	BR	ICOM		;


;
; BUFFER IS BYTE ALIGNED
;

	.IFTF

ICBYT:				;
	MOV	#IE.BYT&377,R0	;

	.IFT

	BR	ICOM		;

;
; INSUFFICIENT DYNAMIC STORAGE AVAILABLE TO ALLOCATE SECODARY CONTROL BLOCK
;
;	NOTE: AT THIS POINT THE STACK CONTAINS:
;
;		(SP)+00 - PREVIOUS CONTENTS OF R1 (MAY BE DISCARDED)      ,
;		(SP)+02 - PREVIOUS CONTENTS OF R5 (MUST BE RESTORED).
;
;

ICNOD:				;
	MOV	(SP)+,R1	; RESTORE R1
	MOV	(SP)+,R5	; RESTORE UCB ADDRESS
	MOV	#IE.NOD&377,R0	;

;
; INTERMEDIATE BRANCH POINTS TO ERROR EXITS
;

	.IFTF

ICOM:	JMP	ICOMN		; COMMON ERROR EXIT

	.IFT

ICDO:	JMP	ICDON		; SUCCESFUL COMPLETION
ICSP:	JMP	ICSPC		; BUFFER OUT OF REQUESTORS ADDRESSS SPACE

	.ENDC

;+
;
; **-UNLNK-UNLINK A TASK FROM ALL INTERRUPTS ON UNIT
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 1      2 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CIM!I$$CR!I$$CTI&I$$CLK

UNLNK:				;
	CLR	-(SP)		; RESET SUCCESS FLAG

	.IF DF	I$$CIM

	CALL	CIUNL1		; UNLINK FROM CONTACT INTERRUPTS
	BCS	40$		; IF C/S NOT LINKED TO ANY INTERRUPTS
	BMI	10$		; IF MI NOT LINKED TO THIS TYPE
	INC	(SP)		; SET SUCCESS FLAG
10$:				;

	.ENDC

	.IF DF	I$$CTI

	CALL	CTUNL1		; UNLINK FROM C      OUNTER MODULE INTERRUPTS
	BCS	40$		; IF C/S NOT LINKED TO ANY INTERRUPTS
	BMI	20$		; IF MI NOT LINKED TO THIS TYPE
	INC	(SP)		; SET SUCCESS
20$:				;

	.ENDC

	.IF DF	I$$CR

	CALL	RTUNL1		; UNLINK FROM REMOTE TERMINAL INTERRUPTS
	BCS	40$		; IF C/S NOT LINKED TO ANY INTERRUPTS
	BMI	30$		; IF MI NOT LINKED TO THIS TYPE
	INC	(SP)		; SET SUCCESS
30$:				;
	CALL	ERUNL1		; UNLINK FROM ERRORS
	BMI	40$		; IF MI NOT LINKED TO ERRORS
	INC	(SP)		; SET SUCCESS

	.ENDC

40$:				;
	MOV	#IE.NLK&377,R      0	; ASSUME NOT LINKED TO ANY INTERRUPTS
	TST	(SP)+		; TEST SUCCESS FLAG
	BEQ	ICOM		; IF EQ NOT LINKED TO ANY INTERRUPTS
	BR	ICDO		; SUCCESFUL EXIT

;+
;
; **-CIUNL-UNLINK TASK FROM CONTACT INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.ENABL LSB

	.IF DF	I$$CIM

CIUNL:				;
	MOV	#ICOMN,-(SP)	; SET TRANSFER ADDRE      SS
CIUNL1:				;
	MOV	#IE.MOD&377,-(SP) ; ASSUME NON-EXISTENT MODULE TYPE
	MOV	S.DI(R4),R4	; GET TABLE ADDRESS
	BEQ	80$		; IF EQ MODULE NOT INSTALLED
	MOV	(R4),R2		; GET POINT COUNT-15.
	ASR	R2		; CONVERT TO NUMBER OF MODULES
	ASR	R2		; ...
	ASR	R2		; ...
	ASR	R2		; ...
	MOV	R2,6(R1) 	; SAVE MODULE-1 COUNT
	MOV	#CILGH,4(R1)	; SAVE ENTRY SIZE
	BR	UNL		; TO COMMON UNLINK CODE

	.ENDC

;+
;
; **-CTUNL-UNLINK TASK FROM COUNTER INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12       -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 O F RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CTI

CTUNL:				;
	MOV	#ICOMN,-(SP)	; PUSH TRANSFER ADDRESS
CTUNL1:				;
	MOV	#IE.MOD&377,-(SP) ; ASSUME NON-EXISTENT MODULE TYPE
	MOV	S.CT(R4),R4	; GET ADDRESS OF TABLES
	BEQ	80$		; IF EQ NONE
	MOV	(R4),6(R1)	; SET NUMBER OF HIGHEST MODULE
	MOV	#CTLGH,4(R1)	; SET ENTRY SIZE
	BR	UNL		;

	.ENDC

;+
;
; **-RTUNL-UNLINK TA      SK FROM REMOTE TERMINAL
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CR

RTUNL:				;
	MOV	#ICOMN,-(SP)	; PUSH TRANSFER ADDRESS
RTUNL1:				;
	MOV	#IE.MOD&377,-(SP) ; ASSUME NONEXISTENT MODULE TYPE
	MOV	S.RTI(R4),R4	; GET MODULE TABLE ADDRESS
	BEQ	80$		; IF EQ NON-EXISTENT MODULE
	BR	ERUNL2		;

;+
;
; **-ERUNL-UNL      INK FROM ERROR INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- WORD 0 OF RADIX-50 TASK NAME
;	WD. 13 -- WORD 1 OF RADIX-50 TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

ERUNL:				;
	MOV	#ICOMN,-(SP)	; PUSH TRANSFER ADDRESS
ERUNL1:				;
	MOV	#ICDVT+ICRES-IMDAT,R4 ; POINT TO ERROR RESOURCE MASK MINUS OFFSET
	CLR	-(SP)		; RESERVE A WORD ON THE STACK
ERUNL2:				;
	CLR	6(R1)		; SET MODULE-1 COUNT TO ZERO

	.ENDC

UNL:				;
	      MOV	#TASK,R2	; POINT TO TASK NAME STORAGE
	MOV	R1,R3		; COPY ADDRESS OF PARAMETER BLOCK
	MOV	(R1)+,(R2)+	; SAVE TASK NAME
	MOV	(R1)+,(R2)+	; ...
	MOV	R3,U.CW2(R5)	; SAVE ADDRESS OF PARAMETER LIST
	ADD	#IMDAT,R4	; POINT TO MODULE ENTRIES
	MOV	#IE.NST&377,(SP) ; ASSUME TASK NOT INSTALLED
	CALL	$SRSTD		; SEARCH TCB LIST FOR TASK
	BCS	60$		; IF C/S TASK NOT INSTALLED
	MOV	R3,R1		; RESTORE ADDRESS OF PARAMETER LIST
	MOV	#IE.NLK&377,(SP) ; ASSUME TASK NOT LINKED
	MOV	#ICDVT+ICLTL,R2	; POINT TO LINKED T      ASK LISTHEAD
10$:				;
	MOV	R2,10(R1)	; SAVE LINK TO PREVIOUS
	MOV	(R2),R2		; GET LINK TO NEXT
	SEC			; ASSUME TASK NOT LINKED ANYWHERE
	BEQ	60$		; IF EQ TASK NOT LINKED ANYWHERE
	CMP	LTCB(R2),R0	; THIS ENTRY BELONG TO TASK?
	BNE	10$		; IF NE NO
	MOV	R2,(R1)+	; SAVE ADDRESS OF LINKED TASK ENTRY
	MOV	R4,(R1)		; SAVE ADDRESS OF FIRST ENTRY
	MOV	R1,R4		; SAVE PARAMETER LIST ADDRESS
20$:				;
	MOV	(R4),R0		; GET ADDRESS OF CURRENT ENTRY
	TST	(R0)+		; POINT TO INTERRUPT LINKAGE LISTHEAD
	MOV	-(R4),      R1	; GET ADDRESS OF LINKED TASK ENTRY
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUPTS
	CALL	$QRMVT		;;; ATTEMPT TO REMOVE AN ENTRY FROM LIST
	BCS	40$		;;; IF C/S NO ENTRY IN LIST THIS TIME
	BIC	ILMSK(R1),-(R0)	;;; CLEAR RESOURCE MASK BITS
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	MOV	#IS.SUC&377,(SP) ; SET SUCCESS
	MOV	R1,R0		; COPY ADDRESS OF NODE
	MOV	#ILGH,R1	; SET LENGTH OF NODE
	CALL	$DEACB		; DEALLOCATE BLOCK
	MOV	(R4)+,R0	; GET ADDRESS OF LINKED TASK ENTRY
	DEC	LUSE(R0)	; DECREMENT USE COUNT
	BNE      	20$		; IF NE GO AGAIN
	MOV	10-2(R4),R1	; GET ADDRESS OF PREVIOUS
	MOV	(R0),(R1)	; RELINK REMAINING ENTRIES
	BNE	30$		; IF NE NO NEW LAST
	MOV	R1,ICDVT+ICLTL+2 ; SET NEW LAST
30$:				;
	MOV	#LLGH,R1	; SET LENGTH OF ENTRY
	CALL	$DEACB		; DEALLOCATE BLOCK
	BR	50$		; EXIT
40$:				;
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	CMP	(R4)+,(R4)+	; POINT TO ENTRY SIZE
	ADD	(R4),-(R4)	; OFFSET TO NEXT ENTRY
	DEC	4(R4)		; DECREMENT ENTRY COUNT
	BPL	20$		; IF PL GO AGAIN
50$:				;
	CLC			; SET SUCCESS
60$:			      	;
	MOV	U.CW2(R5),R1	; RESTORE ADDRESS OF PARAMETER LIST
	MOV	TASK,(R1)	; RESTORE TASK NAME
	MOV	TASK+2,2(R1)	; ...
70$:				;
	MOV	U.SCB(R5),R4	; RESTORE ADDRESS OF SCB
	MOV	(SP)+,R0	; RETRIEVE STATUS
	BISB	R0,R0		; SET CONDITION CODES
	RETURN			;
80$:
	CLC			; SET SUCCESS
	BR	70$		; GO GET STATUS AND EXIT

	.DSABL	LSB

	.ENDC


;+
;
; **-CICNT-CONNECT TO CONTACT INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF CIRCULAR BUFFER
;	WD. 13 -- ADDRESS       OF CIRCULAR BUFFER
;	WD. 14 -- LENGTH OF BUFFER
;	WD. 15 -- EVENT FLAG NUMBER
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.ENABL	LSB

	.IF DF	I$$CIM

CICNT:				;
	MOV	S.DI(R4),R3	; GET ADDRESS OF DIGITAL INTERRUPT TABLES
	BR	CNCT		;

	.ENDC

;+
;
;**-CTCNT-CONNECT TO COUNTER MODULE INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF CIRCULAR BUFFER
;	WD. 13 -- ADDRESS OF CIRCULAR BUFFER
;	WD. 14 -- LENGTH OF CIRCULAR BUFFER
;	WD. 15 -- EVENT FLA      G NUMBER
;	WD. 16 -- ADDRESS OF COUNTER INITIAL VALUE TABLE
;	WD. 17 -- UNUSED
;
;+

	.IF DF	I$$CTI

CTCNT:				;
	MOV	S.CT(R4),R3	; GET ADDRESS OF COUNTER TABLES
	BR	CNCT		;

	.ENDC

;+
;
; **-RTCNT-CONNECT REMOTE TERMINAL INPUTS TO CIRCULAR BUFFER
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF CIRCULAR BUFFER
;	WD. 13 -- ADDRESS OF CIRCULAR BUFFER
;	WD. 14 -- LENGTH OF CIRCULAR BUFFER
;	WD. 15 -- EVENT FLAG NUMBER
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;      
;-

	.IF DF	I$$CR

RTCNT:				;
	MOV	S.RTI(R4),R3	; GET ADDRESS OF REMOTE TERMINAL TABLE

	.ENDC

	.IF DF	I$$CIM!I$$CR!I$$CTI

CNCT:				;
	BEQ	ICM		; IF EQ MODULE DOESN'T EXIST
	BIT	#T2.CHK!T2.FXD,T.ST2(R0) ; TASK NOT CHKPOINTABLE OR FXD?
	BEQ	ICPRI		; IF EQ NO
	TST	IMTCB(R3)	; OTHER TASK CONNECTED?
	BNE	ICON		; IF NE YES
	CMP	(R1)+,(R1)+	; POINT TO DATA BUFFER SIZE
	MOVB	IMBPE(R3),R0	; GET SIZE OF ENTRY
	CMP	(R0)+,(R0)+	; ADJUST FOR BUFFER HEADER
	CMP	(R1)+,R0	; BUFFER BIG ENOUGH
	BLO      	ICSPC		; IF LO NO
	MOV	(R1)+,R0	; GET EVENT FLAG NUMBER
	BEQ	ICIEF		; IF EQ ILLEGAL EFN
	CMP	R0,#64.		; LEGAL EFN?
	BHI	ICIEF		; IF HI NO

	.IF DF	I$$CTI

	CLR	2(R1)		; CLEAR COUNTER FLAG
	CMP	R3,S.CT(R4)	; PROCESSING COUNTERS?
	BNE	20$		; IF NE NO
	MOV	(R1)+,R0	; GET ADDRESS OF COUNTER INITIAL VALUE TABLE
	MOV	R3,(R1)		; SET COUNTER FLAG
	MOV	(R3),R4		; GET NUMBER OF HIGHEST COUNTER
	INC	R4		; CONVERT TO NUMBER OF COUNTERS

	.IF DF	A$$CHK!M$$MGE

	MOV	R4,R1		; COPY NUMBER OF COUNTERS
	A      SL	R1		; CONVERT TO BYTE COUNT
	CALL	$ACHCK		; ADDRESS CHECK TABLE
	BCS	ICSPC		; IF C/S OUT OF REQUESTOR'S TASK SPACE

	.ENDC

	.IF DF	M$$MGE

	CALL	$RELOM		; RELOCATE AND MAP TO INITIAL VALUE TABLE

	.ENDC

	MOV	R3,R1		; COPY MODULE TABLE ADDRESS
	ADD	#IMDAT+IMPRV,R1	; POINT TO INITIAL VALUE CELL
10$:				;
	MOV	(R0)+,(R1)	; SET INITIAL VALUE
	ADD	#CTLGH,R1	; POINT TO NEXT ENTRY
	DEC	R4		; DECREMENT COUNT
	BNE	10$		; IF NE GO AGAIN

	.ENDC

20$:				;
	MOV	(SP),R4		; RETRIEVE I/O PACKE      T ADDRESS
	MOV	R5,-(SP)	; SAVE ADDRESS OF UCB
	MOV	I.TCB(R4),R5	; GET REQUESTER TASK TCB ADDRESS
	ADD	#I.PRM,R4	; POINT TO I/O PACKET ADDRESS
	TST	(R3)+		; POINT TO BYTES OF INTERRUPT DATA
	MOVB	(R3)+,(R3)	; SET FORK NOT IN PROGRESS
	MOVB	(R3)+,-(SP)	; SAVE BYTES PER ENTRY
	MOV	(R4)+,(R3)	; INSERT STARTING BUFFER RELOCATION BIAS
	MOV	(R3)+,(R3)+	; INSERT CURRENT BUFFER RELOCATION BIAS
	MOV	(R4)+,(R3)	; INSERT STARTING ADDRESS OF BUFFER
	MOV	(R3)+,(R3)	; COPY STARTING ADDRESS OF BUFFER
	ADD	#4,(R3      )		; COMPUTE STARTING ADDRESS OF DATA
	MOV	(R3)+,(R3)+	; SET CURRENT BUFFER ADDRESS
	MOV	#3,(R3)+	; SET CURRENT FORTRAN FILL INDEX
	MOV	(R4)+,(R3)	; SET LENGTH OF BUFFER IN BYTES
	ROR	(R3)+		; CONVERT TO LENGTH IN WORDS
	MOV	(R4)+,R0	; GET EVENT FLAG NUMBER
	CALL	$CEFI		; CONVERT TO MASK AND ADDRESS
	MOV	R0,(R3)+	; INSERT EVENT FLAG MASK
	MOV	R1,(R3)+	; INSERT EVENT FLAG ADDRESS
	CLR	(R3)+		; CLEAR LOST DATA COUNT
	MOV	R5,(R3)		; CONNECT TASK TO INTERRUPTS
	INCB	T.IOC(R5)	; BIAS TASK'S OUTSTANDIN      G I/O COUNT

	.IF DF	D$$SHF

	MOV	T.PCB(R5),R0	; GET ADDRESS OF PCB
	BIS	#PS.NSF,P.STAT(R0) ; DISABLE TASK SHUFFLING

	.ENDC

	MOVB	(SP)+,R0	; RETRIEVE BYTES PASSED PER INTERRUPT
	MOV	(SP)+,R5	; RETRIEVE ADDRESS OF UCB

	.IF DF	I$$CTI

	MOV	2(R4),R3	; GET COUNTER FLAG
	BEQ	30$		; IF EQ NOT CONNECTING TO COUNTERS
	CALL	RSETC		; INITIALIZE ALL COUNTERS
30$:				;

	.ENDC

	ASR	R0		; CONVERT BYTES TO WORD COUNT
	DEC	R0		; ADJUST FOR EXISTENCE INDICATOR
	BIS	#3*256.,R0	; INCLUDE INITIAL FO      RTRAN INDEX
	MOV	R0,R1		; COPY RESULT
	BR	ICDON1		; COMPLETE REQUEST

;
; INTERMEDIATE ERROR BRANCH POINTS
;

ICB:	JMP	ICBYT		; BUFFER BYTE ALIGNED
ICM:	JMP	ICMOD		; ILLEGAL MODULE NUMBER SPECIFIED

	.ENDC

	.DSABL	LSB

;+
;
; **-DISCONNECT CIRCULAR BUFFER FROM CONTACT INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- UNUSED
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.ENABL	LSB

	.IF DF	I$$CIM

CIDC      T:				;
	MOV	S.DI(R4),R3	; GET ADDRESS OF CONTACT INTERRUPT TABLES
	BR	10$		;

	.ENDC

;+
;
; **-CTDCT-DISCONNECT CIRCULAR BUFFER FROM COUNTER INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- UNUSED
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CTI

CTDCT:				;
	MOV	S.CT(R4),R3	; GET ADDRESS OF COUNTER TABLES
	BR	10$		;

	.ENDC

;+
;
; **-RTDCT-DISCONNECT REMOTE TERMINAL FROM CIRCULAR BUFFER
;      
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- UNUSED
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CR


RTDCT:				;
	MOV	S.RTI(R4),R3	; GET ADDRESS OF REMOTE TERMINAL TABLES

	.ENDC

	.IF DF	I$$CIM!I$$CR!I$$CTI

10$:				;
	CALL	ICAN1		; DISCONNECT TASK FROM INTERRUPTS
	BCC	ICDON		; IF C/C DISCONNECT SUCCEEDED
	BEQ	ICMOD		; IF EQ MODULE DOESN'T EXIST

;
; TASK NOT CONNECTED OR OTHER TASK CONNECTED
;

ICO      N:				;
	MOV	#IE.CON&377,R0	;
	BR	ICOMN		;

	.ENDC

;
; ILLEGAL OR NONEXISTENT EVENT FLAG SPECIFIED
;

	.IF DF	I$$CLK!I$$CIM!I$$CR!I$$CTI

ICIEF:				;
	MOV	#IE.IEF&377,R0	;
	BR	ICOMN		;

	.ENDC

;
; PRIVELEGE VIOLATION - TASK REQUESTING CONNECTION WAS
; CHECKPOINTABLE BUT NOT FIXED
;

ICPRI:				;
	MOV	#IE.PRI&377,R0	;
	BR	ICOMN		;

;
; INVALID FUNCTION CODE ISSUED OR NONEXISTENT MODULE
; TYPE REFERENCED
;

ICIFC:				;
	MOV	#IE.IFC&377,R0	;
	BR	ICOMN		;

;
; BUFFER OUT OF       REQUESTORS ADDRESS SPACE
;

ICSPC:				;
	MOV	#IE.SPC&377,R0	;
	BR	ICOMN		;

;
; DEVICE NOT READY
;

ICNRD:				;
	MOV	#IE.DNR&377,R0	;
	BR	ICOMN		;


;+
;
; **-CTINI-INITIALIZE COUNTER MODULE
;
; FUNCTION DEPENDANT I/O PACKET FORMAT
;
;	WD. 12 -- COUNTER NUMBER
;	WD. 13 -- COUNTER INITIAL VALUE
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

	.IF DF	I$$CTI

CTINI:				;
	MOV	S.CT(R4),R3	; GET ADDRESS OF COUNTER TABLES
	BEQ	ICMOD		; IF EQ MO      DULE DOES NOT EXIST
	CMP	(R1),(R3)	; LEGAL COUNTER NUMBER?
	BHI	ICMOD		; IF HI NO
	MOV	(R1),R2		; GET COUNTER NUMBER
	ASL	R2		; CONVERT TO TABLE INDEX
	ASL	R2		; ...
	ADD	(R1)+,R2	; ...
	ASL	R2		; ...
	ADD	R2,R3		; POINT TO MODULE ENTRY
	ADD	#IMDAT+IMPRV,R3	; ...
	MOV	(R1),(R3)	; SET NEW INITIAL VALUE
	CALL	SETCT		; RE-INITIALIZE COUNTERS
	BR	ICDON		; EXIT

	.ENDC

;+
;
; **-AOUT-SINGLE CHANNEL ANALOG OUTPUT
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELATIVE CHANNEL NUMBE      R
;	WD. 13 -- OUTPUT VOLTAGE REPRESENTATION
;
;-


	.IF DF	I$$CDA

AOUT:				;
	MOV	R4,R3		; COPY ADDRESS OF SCB
	ADD	#S.DAC,R3	; POINT TO D/A ENTRY
	TST	(R3)+		; ANY D/A CONVERTER MODULES?
	BEQ	ICMOD		; IF EQ NO
	MOV	R1,R2		; COPY PARAMETER BLOCK ADDRESS
	CMP	(R2)+,2(R3)	; LEGAL CHANNEL?
	BHI	ICMOD		; IF HI NO
	TST	(R2)+		; POINT TO PARAMETER WORD 3
	MOV	(R1),(R2)	; COPY CHANNEL NUMBER
	ASL	(R2)		; CONVERT TO WORD OFFSET
	ADD	(R3),(R2)	; COMPUTE CONTEXT SAVE LOCATION
	SWAB	-(R2)		; SWAP       DATA WORD BYTES
	RORB	(R2)		; LEFT JUSTIFY DATA
	ROR	(R2)		; ...
	ROR	(R2)		; ...
	ASR	(R1)		; INCLUDE CHANNEL NUMBER WITHIN MODULE
	ROR	(R2)		; ...
	ASR	(R1)		; ...
	ROR	(R2)		; ...
	MOV	(R2)+,@(R2)+	; SAVE CONTROL WORD
	BR	OUTCM		; TO COMMON OUTPUT CODE

	.ENDC

;+
;
; **-LTOUT-BI-STABLE DIGITAL OUTPUT
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- STARTING RELATIVE POINT NUMBER
;	WD. 13 -- DATA MASK WORD
;	WD. 14 -- DATA VALUE
;
;-

	.IF DF	I$$CLT

LTOUT:				;
	MOV	R4      ,R3		; COPY SCB ADDRESS
	ADD	#S.LTO,R3	; POINT TO BI-STABLE SCB ENTRY
	TST	(R3)+		; ANY BI-STABLE OUTPUTS ON THIS CONTROLLER?
	BEQ	ICMOD		; IF EQ NO
	CMP	(R1),2(R3)	; LEGAL POINT NUMBER?
	BHI	ICMOD		; IF HI NO
	BIT	#17,(R1)	; POINT ON MODULE BOUNDARY?
	BNE	ICMOD		; IF EQ NO
	ASR	(R1)		; CONVERT POINT TO WORD INDEX
	ASR	(R1)		; ...
	ASR	(R1)		; ...
	MOV	(R1)+,R2	; GET INDEX
	ADD	(R3),R2		; COMPUTE ADDRESS OF PREVIOUS STATE ENTRY
	BIC	(R1),(R2)	; CLEAR ALL BITS THAT WILL CHANGE STATE
	COM	(R1)		      ; COMPLEMENT MASK
	BIC	(R1)+,(R1)	; CLEAR ALL BITS THAT WILL NOT CHANGE STATE
	BIS	(R1),(R2)	; ESTABLISH NEW 'CURRENT STATE'
	MOV	(R2),-(R1)	; COPY NEW STATE
	ASR	-(R1)		; CONVERT WORD OFFSET TO BYTE OFFSET
	BR	OUTCM		; TO COMMON CODE

	.ENDC

;+
;
; **-SSOUT-MOMENTARY DIGITAL OUTPUTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- STARTING RELATIVE POINT NUMBER
;	WD. 13 -- DATA VALUE
;
;-

	.IF DF	I$$CSS

SSOUT:				;
	MOV	R4,R3		; COPY SCB ADDRESS
	ADD	#S.SSO,R3	; POINT TO '      MOMENTARY' ENTRY
	TST	(R3)+		; ANY MOMENTARY OUTPUTS?
	BEQ	ICMOD		; IF EQ NO
	CMP	(R1),2(R3)	; LEGAL POINT NUMBER?
	BHI	ICMOD		; IF HI NO
	BIT	#17,(R1)	; POINT ON MODULE BOUNDARY?
	BNE	ICMOD		; IF NE NO
	ASR	(R1)		; CONVERT TO MODULE NUMBER
	ASR	(R1)		; ...
	ASR	(R1)		; ...
	ASR	(R1)		; ...

	.ENDC

;
; COMMON CODE TO PERFORM OUTPUT FOR NON-
; INTERRUPTING FUNCTIONS
;

	.IF DF	I$$CDA!I$$CLT!I$$CSS

OUTCM:				;
	ADD	-(R3),(R1)+	; COMPUTE MODULE MAPPING TABLE ENTRY ADDRESS
	MOVB	@-(R1),      (R1)+	; CONVERT LOGICAL TO PHYSICAL SLOT NUMBER
	CLRB	(R1)+		; CLEAR HIGH BYTE
	ADD	#ICMD/2&77777,-(R1) ; COMPUTE BUS ADDRESS/2
	CALL	CBINS		; ATTEMPT TO INSERT IN CIRCULAR BUFFER

	.IF DF	I$$CR

	BCS	ICDNR		; IF C/S UNIT NOT READY

	.ENDC

	BR	ICDON		; SET SUCCESFUL COMPLETION STATUS

	.ENDC

;
; ILLEGAL OR NONEXISTENT MODULE SPECIFIED
;

ICMOD:				;
	MOV	#IE.MOD&377,R0	;
	BR	ICOMN			;

;
; RETURN SUCCESS STATUS, SET WORD 2 OF I/O STATUS BLOCK
; TO ZERO
;

ICDON:				;
	CLR	R1		      ; CLEAR SECOND WORD OF I/O STATUS
ICDON1:				;
	MOV	#IS.SUC&377,R0	; SET STATUS
	BR	ICOMN1		;

;
; DEVICE NOT READY
;

ICDNR:				;
	MOV	#IE.DNR&377,R0		;

;
; COMMON EXIT FROM ALL FUNCTION CODE PROCESSING
;

ICOMN:				;
	CLR	R1		; CLEAR SECOND WORD OF I/O STATUS
ICOMN1:				;
	MOV	(SP)+,R3	; RESTORE ADDRESS OF I/O PACKET
	CALLR	$IOFIN		; TERMINATE REQUEST


;+
;
; **-ADINI-INITIATE BUFFERED A/D CONVERSION
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF       DATA BUFFER
;	WD. 13 -- DATA BUFFER ADDRESS
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER
;	WD. 15 -- CONTROL BUFFER ADDRESS
;
;-

	.ENABL	LSB

	.IF DF	I$$CAD

ADINI:				;
	TST	S.ADC(R4)	; ANY A/D CONVERTERS ON THIS CONTROLLER?
	BEQ	ICMOD		; IF EQ NO
	MOV	6(R1),R0	; GET VIRTUAL ADDRESS OF CONTROL BUFFER

	.IF DF	A$$CHK!M$$MGE

	MOV	4(R1),R1	; GET LENGTH OF BUFFER TO CHECK
	CALL	$ACHCK		; ADDRESS CHECK CONTROL BUFFER
	BCS	ICSPC		; IF C/S ADDRESS CHECK FAILURE

	.ENDC

	MOV	(SP),R3		; GET       ADDRESS OF I/O PACKET
	CALL	$RELOC		; RELOCATE AND MAP BUFFER
	ADD	#I.PRM+4,R3	; POINT TO BYTE COUNT (C/CLEAR)
	ROR	(R3)+		; CONVERT TO NUMBER OF CHANNELS
	MOV	R1,(R3)+	; SAVE CONTROL BUFFER ADDRESS BIAS
	MOV	R2,(R3)		; SAVE CONTROL BUFFER ADDRESS

	.ENDC

;+
;
; **-RTINI-INITIATE REMOTE TERMINAL I/O
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF CONTROL BUFFER
;	WD. 13 -- DATA BUFFER ADDRESS
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER
;
;-

	.IF DF	I$$CAD!I$      $CR

RTINI:				;
	MOV	(SP)+,R1	; RETRIEVE I/O PACKET ADDRESS
	MOV	R4,R0		; SET ADDRESS OF I/O LISTHEAD
	CALL	$QINSP		; INSERT I/O PACKET IN REQUEST QUEUE

	.ENDC

	.DSABL	LSB

;+
;
; **-IMRQ-ICS/ICR-11 INTERRUPT MODULE REQUEST PROCESSING
;
; THIS ROUTINE IS ENTERED FROM QIO DIRECTIVE PROCESSING
; WHEN AN I/O REQUEST IS QUEUED AND AT THE END OF A PRE-
; VIOUS I/O REQUEST TO CONTINUE REQUEST PROCESSING. IF
; THE SPECIFIED CONTROLLER IS NOT BUSY THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT       REQUEST. OTHERWISE A RE-
; TURN TO THE CALLER IS EXECUTED. IF THE DEQUEUE ATTEMPT
; IS SUCCESFUL THE NEXT I/O OPERATION IS INITIATED, A  RE-
; TURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	IF THE CONTROLLER IS NOT BUSY AND AN I/O REQUEST
;	IS WAITING TO BE PROCESSED, THEN THE REQUEST IS DE-
;	QUEUED AND THE I/O OPERATION IS INITIATED.
;
;-

	.ENABL	LSB

	.IF DF	I$$CAD!I$$CR

IMRQ:				;
	CALL	$GTPKT		; DEQUEUE AN I/O PACKET
      

	.IF DF	I$$CR

	BCS	20$		; IF C/S NO WORK OR CONTROLLER BUSY

	.IFF

	BCC	ADRQ		; IF C/CLEAR HAVE PACKET TO PROCESS

	.ENDC

	.ENDC

;+
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=I/O REQUEST PACKET ADDRESS
;	R2=REQUEST UCB PHYSICAL UNIT NUMBER
;	R3=CONTROLLER INDEX
;	R4=STATUS CONTROL BLOCK ADDRESS
;	R5=UNIT CONTROL BLOCK ADDRESS
;
; ICR/ICS-11 INTERRUPT MODULE REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER      
;	WD. 02 -- ADDRESS OF REQUESTING TASK TCB
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB)
;	WD. 05 -- I/O FUNCTION CODE (IO.RBC OR IO.WLB)
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT+140000)
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER
;	WD. 13 -- DAT      A BUFFER ADDRESS
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER
;	WD. 15 -- RELOCATION BIAS OF CONTROL BUFFER (ADU02 INPUT ONLY)
;	WD. 16 -- CONTROL BUFFER ADDRESS (ADU02 ONLY)
;	WD. 17 -- NOT USED
;	WD. 20 -- NOT USED
;
;-

	.IF DF	I$$CAD&I$$CR

	CMPB	#IO.WLB/256.,I.FCN+1(R1) ; REMOTE TERMINAL OUTPUT?
	BNE	ADRQ		; IF NE A/D CONVERSION REQUEST

	.ENDC

	.IF DF	I$$CR

	MOV	#IE.MOD&377,R0	; ASSUME DEVICE IS ICS11
	TST	S.RTI(R4)	; DEVICE ICS11 CONTROLLER?
	BEQ	27$		; IF EQ YES
10$:				;
	MOV	      #IE.ABO&377,R0	; ASSUME I/O CANCEL IS ASSERTED
	BIT	#TABO,S.FLG(R4)	; ABORT TRANSFER?
	BNE	25$		; IF NE YES
	CALL	$GTBYT		; GET AN OUTPUT BYTE
	MOV	#ICMD/2,-(SP)	; PUSH BUS ADDRESS/2!TERMINAL FLAG
	BISB	S.CON(R4),(SP)	; MERGE WITH CONTROLLER INDEX
	ASLB	(SP)		; MULTIPLY CONTROLLER INDEX BY 8
	ASLB	(SP)		; ...
	ASLB	(SP)		; ...
	MOV	SP,R1		; COPY STACK ADDRESS
	BIS	#TUND!TUSE,S.FLG(R4) ; SET TERMINAL BUSY AND IN USE
	MOVB	S.ITM(R4),S.CTM(R4) ; ENABLE DEVICE TIME-OUTS
	CALL	CBINS		; INSERT IN CIRC      ULAR BUFFER
	MOV	(SP)+,(SP)+	; CLEAN STACK

	.IFTF

	.IF DF	I$$CAD!I$$CR

20$:				;
	RETURN			;

	.ENDC

;+
;
; **-RTINT-REMOTE TERMINAL INTERRUPT PROCESSING
;
;-

	.IFT

RTINT:				;;;
	BIC	#1000,@S.CSR(R4) ;;; DISABLE TERMINAL OUTPUT INTERRUPTS
	ADD	#6,SP		;;; REMOVE DATA, MOD. NO., GENERIC CODE FROM STACK
	TSTB	R2		;;; TERMINAL BUFFER EMPTY?
	BPL	30$		;;; IF PL NO, ERROR

	.IF GT	I$$C11-1

	MOV	ICUCB,R5	;;; GET UCB ADDRESS


	.IFF

	MOV	CNTBL,R5	;;; GET UCB ADDRESS

	.EN      DC

	BIT	#TUND,S.FLG(R4)	;;; TERMINAL INTERRUPTS EXPECTED?
	BEQ	30$		;;; IF EQ NO
	BIC	#TUND,S.FLG(R4)	;;; CLEAR UNDERWAY FLAG
	CLRB	S.CTM(R4)	;;; DISABLE DEVICE TIMEOUTS
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS
	DEC	U.CNT(R5)	; DECREMENT BYTE COUNT
	BGT	10$		; IF GT MORE TO OUTPUT
	MOV	#IS.SUC&377,R0	; SET SUCCESFUL COMPLETION STATUS
25$:				;
	BIC	#TABO!TUSE,S.FLG(R4) ; CLEAR TERMINAL IN USE FLAG, ABORT FLAG
27$:				;
	JMP	IMFIN		; COMPLETE REQUEST PROCESSING
30$:				;
	RETURN			;;; EXIT IS      R

	.ENDC

	.DSABL	LSB

;+
;
; **-ADRQ-INITIATE BUFFERED, PARALLEL A/D CONVERSION
;
; THIS ROUTINE IS INVOKED TO INITIATE BUFFERED, PARALLEL A/D
; CONVERSION ON THE ICS/ICR-11 INDUSTRIAL CONTROL SUBSYSTEM
; CONVERSIONS ARE INITIATED UNTIL A BUSY CHANNEL IS ENCOUNTERED
; WHEREUPON PROCESSING IS SUSPENDED UNTIL THE CHANNEL BECOMES
; IDLE. SCANNING IS THEN RESUMED AND TERMINATES WHEN ALL TRANS-
; FERS HAVE BEEN COMPLETED OR UPON DETECTION OF AN ERROR.
;
; INPUTS:
;
;	R1=I/O REQUEST PACKET AD      DRESS
;	R2=REQUEST UCB PHYSICAL UNIT NUMBER
;	R3=CONTROLLER INDEX
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;	R5=ADDRESS OF UNIT CONTROL BLOCK
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER
;	WD. 13 -- DATA BUFFER ADDRESS
;	WD. 14 -- BYTE COUNT
;	WD. 15 -- RELOCATION BIAS OF CONTROL BUFFER
;	WD. 16 -- CONTROL BUFFER ADDRESS
;
; THE DATA BUFFER RECEIVES VALUES THAT ARE CONVERTED IN
; ACCORDANCE WITH THE GAIN AND CHANNEL SPECIFIED IN THE
; CORRESPONDING CONTR      OL WORD. EACH WORD IN THE CONTROL BUFF-
; ER CONSISTS OF CHANNEL AND GAIN IN THE FOLLOWING FORMAT:
;
;	BITS 15 - 12 -- GAIN CODE.
;
;		LEGAL GAIN CODES ARE
;
;		0000=GAIN OF 1.
;		0001=GAIN OF 2.
;		0100=GAIN OF 10.
;		0101=GAIN OF 20.
;		1000=GAIN OF 50.
;		1001=GAIN OF 100.
;		1100=GAIN OF 200.
;		1101=GAIN OF 1000.
;
;	BITS 11-0 -- CHANNEL NUMBER.
;
;		EACH ICS/ICR-11 CONTROLLER MAY HAVE UP TO 240
;		PHYSICAL CHANNELS INSTALLED. HOWEVER SINCE EACH
;		ADU02 OCCUPIES A BLOCK OF 120 ADDR      ESSES THE MAX-
;		IMUM NUMBER OF LOGICAL CHANNELS PER CONTROLLER
;		IS 1920. THE LEGALITY OF A PARTICULAR CHANNEL
;		IS DETERMINED BY THE ENTRIES IN THE A/D MODULE
;		DESCRIPTOR TABLES.
;
;-

	.ENABL	LSB

	.IF DF	I$$CAD

ADRQ:				;
	MOV	I.PRM+6(R1),U.CBF(R5) ; SET RELOCATION BIAS OF CONTROL BUFFER
	MOV	I.PRM+10(R1),U.CBF+2(R5) ; SET ADDRESS OF CONTROL BUFFER
	MOV	S.ADC(R4),R3	; GET ADDRESS OF A/D DESCRIPTOR TABLE
	CLR	ADFBC(R3)	; CLEAR FINAL BYTE COUNT
10$:				;
	CALL	$GTCWD		; GET CONTROL       WORD
	MOV	(SP)+,R0	; POP CONTROL WORD
	MOV	R0,R2		; COPY WORD
	BIC	#7777,R2	; CLEAR ALL BUT GAIN CODE
	BIC	R2,R0		; CLEAR ALL BUT CHANNEL NUMBER
	CMP	R0,(R3)		; LEGAL CHANNEL NUMBER?
	BHI	50$		; IF HIGH NO
	MOV	#120.,R1	; GET NUMBER OF CHANNELS PER MODULE
	CALL	$DIV		; GET MODULE NUMBER IN R0, CHANNEL IN R1
	MOV	R0,-(SP)	; COPY CHANNEL NUMBER
	ASL	R0		; COMPUTE OFFSET INTO DESCRIPTOR ABLE
	ASL	R0		; ...
	ADD	(SP)+,R0	; ...
	ASL	R0		; ...
	ADD	#ADSTS+2,R0	; COMPUTE ADDRESS OF DESCRIPTOR ENTRY      
	ADD	R3,R0		; ...
	CMPB	R1,(R0)+	; LEGAL MODULE NUMBER?
	BHI	50$		; IF HI NO
	INC	R2		; SET CONVERT BIT
	SWAB	R2		; POSITION GAIN CODE TO LOW BYTE
	ASL	R2		; BIT 15 TO HIGH BYTE
	ASL	R2		; BIT 14 TO HIGH BYTE
	ASLB	R2		; DROP BIT 13
	BCS	50$		; IF C/S ILLEGAL GAIN CODE
	ASL	R2		; BIT 12 TO HIGH BYTE
	ADD	#8.,R1		; BIAS CHANNEL NUMBER
	BISB	R1,R2		; MERGE CHANNEL AND GAIN
	ASL	R2		; POSITION CONTROL INFORMATION
	ASL	R2		; ...
	ASL	R2		; ...
	ASL	R2		; ...
	MOV	R2,-(SP)	; PLACE CONTROL WORD O      N STACK
	MOV	R0,R1		; COPY ENTRY ADDRESS
	MOVB	#PR6,PS		;;; LOCKOUT DEVICE INTERRUPTS
	MOVB	(R1)+,-(SP)	;;; MODULE BUSY?
	BEQ	20$		;;; IF EQ NO
	INCB	ADFR(R3)	;;; REQUEST FORK ON COMPLETION
	MOV	R3,R1		;;; COPY TABLE ADDRESS
	ADD	#ADNXT,R1	;;; POINT TO DESCRIPTOR CONTEXT ADDRESS
	MOV	R0,(R1)+	;;; SAVE ENTRY+1 ADDRESS
20$:				;;;
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	MOV	R5,R2		; COPY UCB ADDRESS
	ADD	#U.BUF,R2	; POINT TO BUFFER ADDRESS
30$:				;
	MOV	(R2)+,(R1)+	; SAVE BUFFER ADDRESS
	MOV	(R2)      +,(R1)+	; ...
	MOV	(R2),(R1)+	; SAVE CHANNEL COUNT
	TSTB	(SP)+		; FIND MODULE BUSY?
	BEQ	40$		; IF EQ NO
	MOV	(SP)+,(R1)+	; SAVE CONTROL WORD
	BR	90$		; EXIT
40$:				;
	INCB	(R0)+		; SET MODULE BUSY
	MOVB	S.ITM(R4),S.CTM(R4) ; ENABLE DEVICE TIMEOUTS
	MOV	ADMBA-2(R0),-(SP) ; PUSH BUS ADDRESS
	MOV	SP,R1		; SET ADDRESS OF BLOCK
	INCB	ADIP(R3)	; INCREMENT IN-PROGRESS COUNT
	MOV	R3,R0		; SAVE TABLE ADDRESS
	CALL	CBINS		; INSERT IN CIRCULAR BUFFER
	MOV	R0,R3		; RESTORE TABLE ADDRESS
	MOV	(SP)+,(SP)      +	; CLEAN STACK
	MOV	R5,R2		; COPY ADDRESS OF UCB
	ADD	#U.BUF+2,R2	; POINT TO BUFFER ADDRESS
	ADD	#2,(R2)+	; UPDATE ADDRESS
	DEC	(R2)		; ANY MORE TO CONVERT?
	BLE	60$		; IF LE NO

	.IF DF	M$$MGE

	BIT	#20000,-(R2)	; OVERFLOW 4K BOUNDARY?
	BEQ	10$		; IF EQ NO
	BIC	#20000,(R2)	; CLEAR APR 7 OFFSET
	ADD	#200,-(R2)	; ADJUST ADDRESS BIAS

	.ENDC

	BR	10$		; PROCESS NEXT REQUEST
50$:				;
	MOV	#IE.BAD&377,R0	; GET ERROR CODE
	BR	70$		;
60$:				;
	MOV	#IS.SUC&377,R0	; GET STATUS
70$:				;
	M      OV	U.CNT(R5),R1	; GET CHANNEL COUNT
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUPTS
	MOV	ADFR(R3),R2	;;; GET FORK REQUEST, IN-PROGRESS COUNT
	BEQ	80$		;;; IF EQ NO INTERRUPTS PENDING
	INCB	ADFR(R3)	;;; POST FORK REQUEST
80$:				;;;
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	TST	R2		; INTERRUPTS PENDING?
	BNE	85$		; IF NE YES, SET STATUS, EXIT
	MOV	#130$,-(SP)	; SET RETURN ADDRESS
85$:				;
	CMP	R1,ADFBC(R3)	; COMPARE AGAINST CURRENT RETURN COUNT
	BLO	90$		; IF LO DO NOT OVERRIDE STATUS
	MOV	R1,ADFBC(R3)      	; SET NEW COUNT
	MOV	R0,ADSTS(R3)	; SET NEW STATUS
90$:				;
	RETURN			;

;+
;
; **-ADINT-A/D INTERRUPT SERVICE ROUTINE
;
;-

ADINT:				;;;
	MOV	(SP)+,R1	;;; GET CONVERTED DATA
	MOV	S.ADC(R4),R5	;;; GET ADDRESS OF A/D TABLES
	BEQ	140$		;;; IF EQ NONE
	TSTB	ADIP(R5)	;;; A/D IN PROGRESS?
	BEQ	140$		;;; IF EQ NO, EXIT ISR
	ASL	R3		;;; COMPUTE MODULE ENTRY OFFSET
	ASL	R3		;;; ...
	ADD	(SP)+,R3	;;; ...
	ASL	R3		;;; ...
	ADD	#ADSTS+ADBSY+2,R3 ;;; COMPUTE OFFSET TO BUSY FLAG
	ADD	R5,R3		;;;       CONVERT TO ADDRESS
	TSTB	(R3)		;;; MODULE BUSY?
	BEQ	150$		;;; IF EQ NO
	CLRB	(R3)+		;;; CLEAR BUSY FLAG

	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;;; SAVE ASR 6 CONTENTS
	MOV	(R3)+,KISAR6	;;; MAP TO USER BUFFER
	MOV	R1,@(R3)+	;;; TRANSFER DATA TO USER
	MOV	(SP)+,KISAR6	;;; RESTORE ASR 6

	.IFF

	MOV	R1,@2(R3)	;;; TRANSFER DATA TO USER

	.ENDC

	DECB	ADIP(R5)	;;; DECREMENT IN PROGRESS COUNT
	BNE	150$		;;; IF NE MORE INTERRUPTS PENDING
	TSTB	ADFR(R5)	;;; INITIATE FORK ON COMPLETION?
	BEQ	150$		      ;;; IF EQ NO
	CLRB	ADFR(R5)	;;; CLEAR FORK REQUEST FLAG
	CLRB	S.CTM(R4)	;;; DISABLE DEVICE TIMEOUTS

	.IF GT	I$$C11-1

	MOV	ICUCB,R5	;;; GET ADDRESS OF UCB

	.IFF

	MOV	CNTBL,R5	;;; GET ADDRESS OF UCB

	.ENDC

	INC	(SP)+		;;; CLEAN THE STACK
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS
	MOV	S.ADC(R4),R3	; GET ADDRESS OF A/D TABLES
	TST	U.CNT(R5)	; MORE TO PROCESS?
	BEQ	130$		; IF EQ NO
	MOV	R3,R2		; COPY ADDRESS OF A/D TABLES
	ADD	#ADNXT,R2	; POINT TO ENTRY+1 ADDRESS
	MOV	(R2)+,R0	; RESTORE       ENTRY+1 ADDDRESS
	MOV	R0,R1		; COPY ADDRESS
	INC	R1		; POINT TO MODULE CONTEXT
	MOV	ADNXC(R3),-(SP)	; RESTORE CONTROL WORD
	CLR	-(SP)		; SET 'NOT BUSY' CONDITION
	BR	30$		; INITIATE DEVICE

;+
;
; **-ICOUT-ICS/ICR-11 DEVICE TIMEOUT PROCESSING
;
; THIS ROUTINE IS CALLED AT DEVICE PRIORITY BY THE EXEC-
; UTIVE WHEN AN INTERRUPT RESPONSE WAS NOT RECEIVED FROM
; THE A/D OR TERMINAL DEVICES WITHIN THE SPECIFIED INTER-
; VAL AFTER INITIATION. TIMEOUT CAUSES THE CURRENT OPERA-
; TION TO BE TERMINAT      ED WITH A FINAL STATUS OF DEVICE NOT
; READY. IF THE CONTROLLER WAS PLACED OFFLINE MANUALLY THE
; REQUEST IS TERMINATED WITH A STATUS OF REQUEST ABORTED. IN
; EITHER CASE A COUNT OF THE NUMBER OF CHANNELS SAMPLED OR
; THE NUMBER OF BYTES TRANSFERRED IS PLACED IN THE SECOND
; STATUS WORD.
;
;-

	.IFTF

ICOUT:				;;;

	.IF DF	I$$CR

	MOV	S.FLG(R4),R2	;;; GET DEVICE FLAGS
	BIC	#TABO!TUND!TUSE,S.FLG(R4) ;;; CLEAR TERMINAL BUSY, IN-USE, ABORT FLAGS

	.ENDC


	.IF DF	I$$CAD!I$$CR

	CLRB	PS	      	; ALLOW INTERRUPTS
	MOV	#IE.DNR&377,R0	; ASSUME DEVICE NOT READY
	BIT	#UFL,R2		; UNIT OFFLINE?
	BEQ	100$		; IF EQ NO
	MOV	#IE.ABO&377,R0	; GET ABORT STATUS
100$:				;

	.ENDC

	.IFT

	.IF DF	I$$CR

	BIT	#TUND,R2	; TERMINAL UNDERWAY?
	BNE	IMFIN		; IF NE YES, TERMINATE REQUEST

	.ENDC

	CLR	R1		; CLEAR CHANNEL COUNT
	MOV	S.ADC(R4),R3	; GET ADDRESS OF A/D TABLES
	MOV	R3,R2		; COPY A/D TABLE ADDRESS
	MOV	(R2)+,-(SP)	; PUSH HIGHEST CHANNEL NUMBER
	CLR	(R2)		; CLEAR IN-PROGRESS, FORK REQUES      T FLAGS
	ADD	#ADSTS,R2	; POINT TO FIRST MODULE ENTRY
110$:				;
	TSTB	ADBSY(R2)	; THIS MODULE BUSY?
	BEQ	120$		; IF EQ NO
	CLRB	ADBSY(R2)	; RESET BUSY FLAG
	MOV	ADBTC(R2),R1	; GET BYTE COUNT
	CALL	85$		; UPDATE FINAL STATUS
120$:				;
	ADD	#ADLGH,R2	; POINT TO NEXT ENTRY
	SUB	#120.,(SP)	; DECREMENT CHANNEL COUNT BY ONE BLOCK
	BPL	110$		; IF PL GO AGAIN
	INC	(SP)+		; CLEAN THE STACK
130$:				;
	MOV	ADSTS(R3),R0	; SET FINAL STATUS
	MOV	ADFBC(R3),U.CNT(R5) ; SET FINAL BYTE COUNT

	.IFTF

	.I      F DF	I$$CAD!I$$CR

IMFIN:				;
	MOV	S.PKT(R4),R3	; GET ADDRESS OF I/O PACKET
	MOV	I.PRM+4(R3),R1	; GET INITIAL BYTE COUNT
	SUB	U.CNT(R5),R1	; COMPUTE NUMBER OF BYTES TRANSFERRED
	CALL	$IODON		; TERMINATE REQUEST
	JMP	IMRQ		; LOOK FOR MORE WORK

	.ENDC

	.IFT

140$:				;;;
	INC	(SP)+		;;; POP RELATIVE MODULE NUMBER
150$:				;;;
	INC	(SP)+		;;; POP GENERIC CODE

	.ENDC

	RETURN			;;; EXIT ISR

	.DSABL	LSB
;+
;
; **-$ICINT-ICS/ICR-11 INTERRUPT SERVICE ROUTINE
;
;-

$ICINT::			;;;
      
	.IF NDF	I$$CAD&I$$CIM&I$$CR&I$$CTI

	RTI			;;; DISMISS SPURIOUS INTERRUPT

	.IFF


	.ENABL	LSB


	.IF GT	I$$C11-1

	MOVB	PS,TMP		;;; SAVE CONTROLLER INDEX

	.IFTF

	CALL	$INTSV,PR6	;;; SAVE R4,R5, SET PRIORITY
	JSR	R3,SAVE		;;; SAVE R3 - R0

	.IFT

	MOV	TMP,R5		;;; GET INDEX
	BIC	#^C<17>,R5	;;; CLEAR ALL BUT INDEX BITS
	MOV	R5,TMP		;;; SAVE PHYSICAL UNIT NUMBER
	ASL	R5		;;; CONVERT TO WORD INDEX

	.IFF

	CLR	R5		;;; SET INDEX TO CONTROLLER 0

	.IFTF

	MOV	CNTBL(R5),R5	;;;       GET UCB ADDRESS

	.IFT

	MOV	R5,ICUCB	;;; SAVE UCB ADDRESS

	.ENDC

	MOV	U.SCB(R5),R4	;;; GET SCB ADDRESS
	MOV	S.CSR(R4),R5	;;; GET ADDRESS OF CSR
	MOV	R5,CSR		;;; SAVE ADDRESS OF CSR

	.IF DF	I$$CR

	MOV	(R5),R0		;;; GET CSR CONTENTS
	BIT	#22,R0		;;; ERROR INTERRUPTS RECOGNIZED?
	BEQ	50$		;;; IF EQ NO
	BIT	#12000,R0	;;; ANY ERRORS?
	BEQ	50$		;;; IF EQ NO
	BIT	#2000,R0	;;; POWER FAIL?
	BNE	10$		;;; IF NE YES
	TST	-2(R5)		;;; CLEAR ERROR FLAGS
	INC	S.ERR(R4)	;;; INCREMENT ERROR COUNT
	      BMI	50$		;;; IF MI ERROR NOT FATAL
10$:				;;;
	BIS	#UNR,S.FLG(R4)	;;; MARK UNIT NOT READY
	MOV	TMP,R1		;;; GET CONTROLLER NUMBER
	CALL	STERR		;;; INITIATE ERROR PROCESSORS

	.IF GT	I$$C11-1

	MOV	ICUCB,R5	;;; GET ADDRESS OF CURRENT UCB

	.IFF

	MOV	CNTBL,R5	;;; GET ADDRESS OF UCB

	.ENDC

	TSTB	U.EIP(R5)	;;; FORK IN PROGRESS?
	BNE	40$		;;; IF NE YES
	INCB	U.EIP(R5)	;;; SET FORK UNDERWAY
	MOV	R5,R4		;;; COPY ADDRESS OF UCB
	ADD	#U.EFB+6,R4	;;; POINT TO ERROR FORK BLOCK
	CALL	$FORK1		;;;       CREATE A SYSTEM PROCESS
	CLRB	U.EIP(R5)	; CLEAR IN-PROGRESS FLAG

;+
; **-INIER-INITIATE ERROR PROCESSES
;
; THIS ROUTINE IS CALLED AT FORK LEVEL AFTER A FATAL ERROR
; HAS BEEN DETECTED TO INITIATE ALL TASKS THAT HAVE RECEIVED
; 'ALARM' INFORMATION FOR PROCESSING. SUCH INFORMATION IS CON-
; VEYED TO ALL TASKS THAT ARE CONNECTED TO INTERRUPTS ON THE
; PHYSICAL UNIT AND TO A SINGLE TASK THAT IS LINKED TO ERROR
; INTERRUPTS FROM ALL UNITS
;
; INPUTS:
;
;	R5=UCB ADDRESS OF FAULTY UNIT
;
; OUTP      UTS:
;
;	THE UNIT IS PLACED IN THE 'NOT READY' STATE AND
;	ALL SPECIFIED TASKS ARE ACTIVATED.
;
; REGISTERS MODIFIED:
;
; R0 - R5
;
;-

INIER:				;
	MOV	U.SCB(R5),R4	; GET ADDRESS OF SCB

	.IF DF	I$$CLK

	MOV	#ICDVT+ICELH,R3	; POINT TO ERROR INTERRUPT LISTHEAD
	CALL	ALINK		; ACTIVATE THE LINKED TASK

	.ENDC

	ADD	#S.DI,R4	; POINT TO MODULE TABLES
	MOV	#3,-(SP)	; SET TABLE COUNT
20$:				;
	MOV	(R4)+,R5	; GET TABLE ADDRESS
	BEQ	25$		; IF EQ NONE
	CALL	ACBUF		; ACTIVATE CONNECTED TASK      
25$:				;
	DEC	(SP)		; DECREMENT TABLE COUNT
	BNE	20$		; IF NE GO AGAIN
	INC	(SP)+		; CLEAN STACK
40$:				;;; REF. LABEL
	RETURN			;;; EXIT INTERRUPT SERVICE ROUTINE
50$:				;;;
	TST	R0		;;; SERIAL LINE BUFFER EMPTY?
	BMI	60$		;;; IF MI NO
	MOVB	S.ITMC(R4),R2	;;; SET INITIAL TIMEOUT COUNT
	MOV	S.CBF(R4),R3	;;; GET ADDRESS OF CIRCULAR BUFFER
	BEQ	60$		;;; IF EQ, NO CIRCULAR BUFFER
	TST	(R3)		;;; ANY DATA SENT?
	BMI	60$		;;; IF MI NO
	BIC	#NORSP,S.FLG(R4) ;;; CLEAR NO-RESPONSE CONDITION
	DEC	      (R3)		;;; ACKNOWLEDGE INTERRUPTS
	BGT	55$		;;; IF GT MORE THAN ONE OUTPUT QUEUED
	BMI	60$		;;; IF MI BUFFER NOW EMPTY
	BIC	#10,(R5)	;;; DISABLE BUFFER EMPTY INTERRUPTS
	CLR	R2		;;; CLEAR TIMEOUT COUNT
55$:				;;;
	MOVB	R2,S.CTMC(R4)	;;; SET DEVICE TIMEOUT COUNT
	CALL	CBOUT		;;; OUTPUT DATA TO CONTROLLER
60$:				;;;
	TSTB	R0		;;; MODULE INTERRUPTS?
	BPL	40$		;;; IF PL NO

	.IFF

	MOV	(R5),R0		;;; GET CSR CONTENTS
	TSTB	R0		;;; MODULE INTERRUPTS?
	BMI	60$		;;; IF MI YES
	RETURN			;;; EXIT ISR      
60$:				;;;

	.ENDC

	MOV	-2(R5),R2	;;; GET ICAR CONTENTS
	CLR	R1		;;; SET FOR MOVB WITHOUT SIGN EXTENSION
	BISB	R2,R1		;;; GET MODULE OFFSET
	CLRB	R2		;;; CLEAR LOW BYTE OF ICAR COPY
	SWAB	R2		;;; POSITION GENERIC CODE AND FLAGS TO LOW BYTE

	.IF DF	I$$CAD!I$$CIM!I$$CTI

	MOV	R1,R3		;;; COPY MODULE OFFSET
	BIC	#^C<17>,R3	;;; CONVERT TO MODULO 16.
	MOV	R2,-(SP)	;;; PUSH GENERIC CODE
	BIC	#^C<7>,(SP)	;;; CLEAR EXTRANEOUS BITS

	.IF DF	I$$CR

	BEQ	70$		;;; IF EQ REMOTE TERMINAL

	.ENDC      

	ADD	S.IM(R4),R3	;;; COMPUTE MAPPING TABLE ADDRESS
	MOVB	(R3),R3		;;; GET RELATIVE MODULE NUMBER
	BR	80$		;;;

	.IFF

	CLR	-(SP)		;;; CLEAR GENERIC CODE

	.ENDC

	.IF DF	I$$CR

70$:				;;;
	CLR	R3		;;; FORCE RELATIVE MODULE NUMBER OF ZERO
	BIS	#40,(R5)	;;; SET TERMINAL MODE

	.IFTF

80$:				;;;
	MOV	R3,-(SP)	;;; PUSH RELATIVE MODULE NUMBER
	ASL	R1		;;; CONVERT MODULE OFFSET TO WORD BIAS
	BIS	#1,(R5)		;;; SET THE RIF BIT
	MOV	ICMD(R1),-(SP)	;;; PUSH MODULE DATA

	.IFT

	BIC	#40,(      R5)	;;; CLEAR TERMINAL MODE

	.IF DF	I$$CAD!I$$CIM!I$$CTI

	BIT	#7,R2		;;; TERMINAL INPUT?
	BNE	83$		;;; IF NE NO

	.ENDC

	BIT	#20,R2		;;; TERMINAL DATA AVAILABLE?
	BNE	82$		;;; IF NE YES
	JMP	RTINT		;;; PROCESS OUTPUT INTERRUPT
82$:				;;;
	BICB	#200,(SP)	;;; CLEAR PARITY BIT
	MOV	S.RTI(R4),R5	;;; GET ADDRESS OF REMOTE TERMINAL TABLE
	BR	90$		;;;
83$:				;;;

	.ENDC

	.IF DF	I$$CIM!I$$CTI&I$$CAD

	CMP	#7,4(SP)	;;; A/D INPUT?
	BNE	85$		;;; IF NE NO

	.ENDC

	.IF DF	I$$CAD

	JMP      	ADINT		;;; PROCESS A/D INPUT
85$:				;;;

	.ENDC

	.IF DF	I$$CIM

	MOV	S.DI(R4),R5	;;; GET DIGITAL INTERRUPT TABLE ADDRESS

	.ENDC

	.IF DF	I$$CTI&I$$CIM

	BIT	#4,R2		;;; CONTACT INTERRUPT MODULE?
	BEQ	90$		;;; IF EQ YES

	.ENDC

	.IF DF	I$$CTI

	MOV	S.CT(R4),R5	;;; GET COUNTER TABLES

	.ENDC

90$:				;;;

	.IF DF	I$$CIM!I$$CR!I$$CTI

	CLR	RUN		;;; RESET RUN FLAG
	MOV	#6,R1		;;; SET NUMBER OF BYTES CURRENTLY ON STACK
	TST	R5		;;; SPURIOUS INTERRUPT?
	BEQ	172$		;;; IF EQ YES
      
	.IF DF	I$$CIM!I$$CTI&I$$CR

	CLR	-(SP)		;;; CLEAR A WORD
	CMP	R5,S.RTI(R4)	;;; PROCESSING TERMINAL INTERRUPTS?
	BEQ	100$		;;; IF EQ YES
	MOV	R3,(SP)		;;; COPY RELATIVE MODULE NUMBER

	.IFF

	.IF DF	I$$CTI!I$$CIM							;HB001
										;HB001
	MOV	R3,-(SP)	;;; COPY RELATIVE MODULE NUMBER
										;TL045
	.ENDC									;TL045

	.ENDC

100$:				;;;

	.IF DF	I$$CIM!I$$CTI

	ASL	R3		;;; MULTIPLY BY TABLE ENTRY SIZE
	ASL	R3		;;; ...
	ADD	(SP)+,R3	;;;
	ASL	R3		;;; ...

	.ENDC

	ADD	      #IMDAT,R3	;;; OFFSET TO MODULE DATA ENTRIES
	ADD	R5,R3		;;;

	.IF DF	I$$CR!I$$CTI&I$$CIM

	CMP	R5,S.DI(R4)	;;; DIGITAL INTERRUPTS?
	BNE	130$		;;; IF NE NO

	.ENDC

	.IF DF	I$$CIM

	MOV	(SP),R1		;;; COPY DATA WORD
	MOV	IMPRV(R3),R0	;;; COPY PREVIOUS STATE
	MOV	R1,IMPRV(R3)	;;; SET NEW 'PREVIOUS'
	BIC	R0,R1		;;; CLEAR ALL NEW BITS THAT DID NOT CHANGE
	BIC	(SP),R0		;;; CLEAR ALL OLD BITS THAT DID NOT CHANGE
	BIS	R0,R1		;;; COMBINE ALL THAT CHANGED STATE
	CLR	R0		;;; ASSUME ALL COS WANTED
	CO      M	R2		;;; COMPLEMENT PCL, POP FLAGS
	BIT	#140,R2		;;; BOTH PCL AND POP WANTED
	BEQ	110$		;;; IF EQ YES
	MOV	(SP),R0		;;; GET DATA AGAIN
	BIT	#100,R2		;;; PCL WANTED?
	BNE	110$		;;; IF NE NO
	COM	R0		;;; SET ALL OPEN POINTS
110$:				;;;
	BIC	R0,R1		;;; CLEAR UNWANTED COS BITS
	BNE	120$		;;; IF NE SOME CHANGED STATE
	ADD	#6,SP		;;; CLEAN STACK
	BR	175$		;;; EXIT ISR
120$:				;;;
	MOV	R1,-(SP)	;;; SAVE CHANGE OF STATE
	MOV	R1,-(SP)	;;; SET RESOURCE MASK

	.IF DF	I$$CLK

	CALL	SLINK		;;; ACTIV      ATE ANY LINKED TASKS
	ADC	RUN		;;; UPDATE RUN FLAG

	.ENDC

	BR	170$		;;; CONTINUE

	.ENDC

130$:				;;;

	.IF DF	I$$CR!I$$CTI

	CLR	-(SP)		;;; CLEAR SECOND HARDWARE WORD

	.IF DF	I$$CLK

	MOV	#-1,-(SP)	;;; SET RESOURCE MASK

	.IFTF

	.IF DF	I$$CTI&I$$CR

	CMP	R5,S.CT(R4)	;;; PROCESSING COUNTERS?
	BNE	140$		;;; IF NE NO

	.ENDC

	.IF DF	I$$CTI

	TST	IMTCB(R5)	;;; TASK CONNECTED?
	BEQ	150$		;;; IF EQ NO
	MOV	4(SP),R1	;;; COPY COUNTER DATA
	ROL	R1		;;; TIME TO UPDATE COUNTER?      
	BVS	150$		;;; IF VS NO (INTERRUPTED ON HALF-COUNT)

	.IF DF	I$$CR

	BIS	#100000,IMBA(R3) ;;; SET 'REFRESH' FLAG
	INC	RUN		;;; FORCE PASS THROUGH FORK PROCESSOR

	.IFF

	MOV	IMBA(R3),R1	;;; GET BUS ADDRESS/2
	ASL	R1		;;; CONVERT TO BUS ADDRESS
	MOV	IMPRV(R3),(R1)	;;; REFRESH COUNTER

	.ENDC

	BR	150$		;;;

	.ENDC

140$:				;;; REF. LABEL

	.IF DF	I$$CR

	CMPB	4(SP),#3	;;; CONTROL-C?
	BNE	160$		;;; IF NE NO

	.ENDC

150$:				;;; REF. LABEL

	.IFT

	CALL	SLINK		;;; ACTIVATE LI      NKED TASKS
	ADC	RUN		;;; UPDATE RUN FLAG

	.IFTF

160$:				;;; REF. LABEL

	.IFT

	MOV	(SP)+,(SP)	;;; COLLAPSE STACK

	.ENDC

	.ENDC

170$:				;;; REF. LABEL
	CLR	R2		;;; FLAG ENTRY NOT FORCED
	CALL	CENTR		;;; ENTER DATA IN CIRCULAR BUFFER
	ADC	RUN		;;; UPDATE RUN FLAG
	MOV	R5,R4		;;; COPY TABLE ADDRESS
	MOVB	IMBPE(R4),R1	;;; GET BYTES PER ENTRY
172$:				;;;
	ADD	R1,SP		;;; CLEAN STACK
175$:				;;;
	TST	RUN		;;; FORK PROCESSING REQUIRED?
	BEQ	220$		;;; IF EQ NO, EXIT ISR
	TSTB	IMFI      P(R4)	;;; FORK NOW IN PROGRESS?
	BEQ	220$		;;; IF EQ YES
	CLRB	IMFIP(R4)	;;; SET FORK PENDING
	ADD	#IMFRK+6,R4	;;; POINT TO FORK BLOCK
	CALL	$FORK1		;;; CREATE A SYSTEM PROCESS
	INCB	IMFIP(R5)	; CLEAR FORK-PENDING FLAG

	.IF DF	I$$CLK!I$$CR

	MOV	IMSCB(R5),R4	; GET SCB ADDRESS

	.ENDC

	.IF DF	I$$CLK

	CMP	-(SP),-(SP)	; RESERVE TWO WORDS ON THE STACK

	.ENDC

	.IF DF	I$$CIM!I$$CR&I$$CLK

	MOV	#CILGH,2(SP)	; SET LENGTH OF CONTACT INTERRUPT ENTRY
	MOV	(R5),(SP)	; PUSH MAX POINT OR CHANNE      L

	.ENDC

	.IF DF	I$$CIM&I$$CLK

	ASR	(SP)		; CONVERT TO NUMBER OF HIGHEST MODULE
	ASR	(SP)		; ...
	ASR	(SP)		; ...
	ASR	(SP)		; ...

	.ENDC

	.IF DF	I$$CLK!I$$CR

	.IF DF	I$$CIM!I$$CR&I$$CTI

	CMP	S.CT(R4),R5	; PROCESSING COUNTERS?
	BNE	200$		; IF NE NO

	.ENDC

	.ENDC

	.IF DF	I$$CLK&I$$CTI

	MOV	#CTLGH,2(SP)	; SET LENGTH OF COUNTER ENTRY
	MOV	(R5),(SP)	; SET NUMBER OF HIGHEST COUNTER

	.ENDC

	.IF DF	I$$CR&I$$CTI

	MOV	R5,R3		; SET ADDRESS OF COUNTER TABLES
	TST	IMTCB(R      3)	; ANY TASK CONNECTED?
	BEQ	200$		; IF EQ NO
	MOV	(R3),R0		; GET HIGHEST COUNTER NUMBER
	ADD	#IMDAT+IMPRV,R3	; POINT TO PREVIOUS STATE ENTRY
180$:				;
	TST	IMBA-IMPRV(R3)	; REFRESH BIT SET?
	BPL	190$		; IF PL NO
	CALL	SETCT		; REFRESH COUNTER
190$:				;
	ADD	#CTLGH,R3	; STEP TO NEXT MODULE ENTRY
	DEC	R0		; DECREMENT COUNT
	BPL	180$		; IF PL GO AGAIN

	.ENDC

200$:				; REF. LABEL

	.IF DF	I$$CLK

	MOV	R5,R4		; COPY TABLE ADDRESS
	ADD	#IMDAT+IMLH,R4	; POINT TO MODULE ENTRIES
210$:				      ;
	MOV	R4,R3		; COPY ADDRESS OF ENTRY
	CALL	ALINK		; ACTIVATE LINKED TASK
	ADD	2(SP),R4	; POINT TO NEXT ENTRY
	DEC	(SP)		; DECREMENT MODULE COUNT
	BPL	210$		; IF PL GO AGAIN
	CMP	(SP)+,(SP)+	; CLEAN STACK

	.ENDC

;+
; **-ACBUF-ACTIVATE TASK CONNECTED TO CIRCULAR BUFFER
;
; THIS SUBROUTINE IS CALLED TO ACTIVATE A TASK THAT IS
; CONNECTED TO A CIRCULAR BUFFER AND SET THE TRIGGER
; EVENT FLAG.
;
; INPUTS:
;
;	R5=INTERRUPT MODULE TABLE ADDRESS
;
; OUTPUTS:
;
;	IF A TASK IS CONNECTED THE       TRIGGER EVENT FLAG IS SET
;	AND THE TASK IS MADE ACTIVE.
;
; REGISTERS MODIFIED:
;
; RO - R3
;
;-

ACBUF:				;
	MOV	IMTCB(R5),R0	; GET TCB ADDRESS
	BEQ	220$		; IF EQ NONE, EXIT
	BIS	IMEVM(R5),@IMEVA(R5) ; SET EVENT FLAG MASK
	CALL	$SETCR		; CONDITIONALY SCHEDULE TASK
220$:				;;;
	RETURN			;;; EXIT INTERRUPT SERVICE ROUTINE

	.ENDC

	.ENDC

	.DSABL	LSB

;+
; **-ICAN-CANCEL I/O OPERATION
;
; THIS ROUTINE IS CALLED BY THE EXECUTIVE TO CANCEL ALL I/O IN
; PROGRESS FOR THE CURRENT TAS      K. IF THE TASK IS CONNECTED TO
; EITHER CONTACT INTERRUPTS, COUNTERS OR REMOTE TERMINAL
; INTERRUPTS IT IS DISCONNECTED. ALL A/D INPUT IS ALLOWED TO
; COMPLETE SINCE IT WILL DO SO WITHIN A REASONABLE AMOUNT OF TIME.
; ALL TERMINAL OUTPUT IS SET TO TERMINATE ON THE OCCURENCE OF THE
; NEXT OUTPUT INTERRUPT.
;
;-

	.ENABL	LSB

ICAN:				;;;

	.IF DF	I$$CIM!I$$CR!I$$CTI

	MOV	R1,R0		;;; SET TCB ADDRESS OF CURRENT TASK

	.IF DF	I$$CIM

	MOV	S.DI(R4),R3	;;; GET ADDRESS OF CONTACT INTERRUPT TABLE      S

	.ENDC

	.IF DF	I$$CR!I$$CTI&I$$CIM

	CALL	ICAN1		;;; DISCONNECT TASK

	.ENDC

	.IF DF	I$$CTI

	MOV	S.CT(R4),R3	;;; GET ADDRESS OF COUNTER TABLES

	.ENDC

	.IF DF	I$$CR&I$$CTI

	CALL	ICAN1		;;; DISCONNECT TASK

	.ENDC

	.IF DF	I$$CR

	BIT	#TUSE,S.FLG(R4)	;;; TERMINAL IN USE?
	BEQ	5$		;;; IF EQ NO
	MOV	S.PKT(R4),R1	;;; GET ADDRESS OF I/O PACKET
	CMP	R0,I.TCB(R1)	;;; TERMINAL IN USE BY THIS TASK?
	BNE	5$		;;; IF NE NO
	BIS	#TABO,S.FLG(R4)	;;; FORCE I/O COMPLETION ON NEXT TERMIN      AL INTERRUPT
5$:				;;;
	MOV	S.RTI(R4),R3	;;; GET ADDRESS OF REMOTE TERMINAL TABLES

	.ENDC

;+
;
; **-ICAN1-CONDITIONALLY DISCONNECT A TASK FROM INTERRUPTS
;
; THIS SUBROUTINE IS CALLED TO CONDITIONALLY DISCONNECT A TASK FROM
; ICS/ICR UNSOLICITED INTERRUPTS. IF THE MODULE IS INSTALLED ON THE
; CONTROLLER AND THE TCB ADDRESS MATCHES THAT OF THE CONNECTED TASK THEN
; THE TASK IS DISCONNECTED.
;
; INPUTS:
;
;	Z/CLEAR IF SPECIFIED MODULE TYPE IS INSTALLED ON THIS CONTROLLER
;
;	R0 = TCB ADD      RESS OF TASK TO BE DISCONNECTED
;	R3 = MODULE TABLE ADDRESS
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	C/CLEAR: TASK DISCONNECTED FROM INTERRUPTS
;
;	THE TCB ADDRESS, EVENT FLAG MASK AND ADDRESS IN THE DEVICE TABLE
;	ARE CLEARED.
;
;
;	C/SET: TASK NOT CONNECTED OR NON-EXISTENT MODULE TYPE SPECIFIED.
;	Z/SET: NON EXISTENT MODULE TYPE SPECIFIED.
;
; REGISTERS MODIFIED:
;
; R1
;
;-

ICAN1:				;;;
	BEQ	10$		;;; IF EQ MODULE DOES NOT EXIST
	CMP	R0,IMTCB(R3)	;;; THIS TASK CONNE      CTED?
	BNE	10$		;;; IF NE NO
	CLR	IMTCB(R3)	;;; DISCONNECT TASK
	CLR	IMEVA(R3)	;;; CLEAR ADDRESS OF EVENT FLAG MASK
	CLR	IMEVM(R3)	;;; CLEAR EVENT FLAG MASK
	DECB	T.IOC(R0)	;;; DECREMENT OUTSTANDING I/O COUNT

	.IF DF	D$$SHF

	MOV	T.PCB(R0),R1	;;; GET ADDRESS OF PCB
	BIC	#PS.NSF,P.STAT(R1) ;;; ENABLE SHUFFLING

	.ENDC

	BR	20$		;;;
10$:				;;;
	SEC			;;; SET NO-CONNECT FLAG
20$:				;;;

	.ENDC

	RETURN			;;;

	.DSABL	LSB

;+
;
; **-ICPWF-DEVICE DEPENDANT POWER RECOVERY CODE
;
;       POWER FAILURE IS HANDLED VIA THE DEVICE TIMEOUT FACILITIES AND
; THEREFORE CAUSES NO IMMEDIATE ACTION. THE ICS/ICR-11 CONTROL BLOCK
; ADDRESS IS STORED, THE STATE OF ALL VOLATILE OUTPUT MODULES IS
; RESTORED AND ALL ICS/ICR-11 INTERRUPTS ARE ENABLED.
;-
	.ENABL	LSB

ICPWF:				;

	.IF DF	I$$CAD!I$$CIM!I$$CTI!I$$CR

	MOV	R5,CNTBL(R3)	; SAVE ADDRESS OF UCB

	.ENDC


	.IF DF	I$$CR

	MOV	#WDFLG,R0	; GET ADDRESS OF WATCHDOG FLAG
	TST	(R0)		; WATCHDOG TIMER SCHEDULED?
	BNE	RSTOR		; IF NE YES
	      MOV	PC,(R0)+	; SET TIMER FLAG
	CALL	SWDT		; INITIATE WATCHDOG TIMER

	.IFTF

	MOV	U.SCB(R5),R4	; RESTORE ADDRESS OF SCB

;+
; **-RSTOR-RESTORE THE STATE OF THE ICS/ICR CONTROLLER
;
; THIS SUBROUTINE IS CALLED TO RESTORE THE STATE OF THE ICR CIRCULAR
; OUTPUT BUFFER, ANALOG OUTPUTS, COUNTER MODULES AND LATCHING OUTPUTS
; FOLLOWING A POWER FAIL AT THE PROCESSOR OR A FAULT AT THE REMOTE SITE.
; THE STATE OF EACH COUNTER IS RESTORED PROVIDED THAT:
;
;	(1) A TASK IS CONNECTED OR,
;	(2) A TASK IS       LINKED TO RECEIVE COUNTER INTERRUPTS AND
;	    A NON-ZERO COUNTER VALUE WAS SPECIFIED.
;
; INPUTS:
;
;	R4=SCB ADDRESS
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	THE CIRCULAR OUTPUT BUFFER IS PLACED IN THE EMPTY STATE AND
;	THE STATE OF EACH COUNTER MODULE, ANALOG OUTPUT CHANNEL AND
;	LATCHING OUTPUT MODULE IS RESTORED AS PREVIOUSLY DESCRIBED.
;
; REGISTERS MODIFIED:
;
;  R0 - R3
;
;-

RSTOR:				;

	.IFT

	MOV	S.CBF(R4),R3	; GET ADDRESS OF CIRCULAR BUFFER
	BEQ	5$		; IF EQ, NO CIRC. BFR (ICS11      )
	MOV	#-1,(R3)+	; SET BUFFER EMPTY
	MOV	R3,(R3)		; SET ADDRESS OF BUFFER+2
	ADD	#CDAT-2,(R3)	; COMPUTE ADDRESS OF OUTPUT POINTER
	MOV	(R3)+,(R3)	; INSERT ADDRESS OF INPUT POINTER
	MOV	(R3)+,(R3)	; COPY ADDRESS OF INPUT POINTER
	ADD	#CLGH-CDAT-2,(R3) ; COMPUTE END ADDRESS
5$:				;
	BIT	#UFL,S.FLG(R4)	; ERROR INTERRUPTS RECOGNIZED?
	BNE	10$		; IF NE NO
	BIS	#22,@S.CSR(R4)	; ENABLE ERROR INTERRUPTS
	BIT	#UNR,S.FLG(R4)	; UNIT READY?
	BNE	60$		; IF NE NO

	.ENDC

10$:				; REF. LABEL
	BIS	#4,@S      .CSR(R4)	; ENABLE MODULE INTERRUPTS

	.IF DF	I$$CIM!I$$CLT!I$$CDA

	TSTB	U.RST(R5)	; RESTORE STATE OF THIS CONTROLLER?
	BEQ	60$		; IF EQ NO

	.ENDC

	.IF DF	I$$CTI

	MOV	S.CT(R4),R3	; GET ADDRESS OF COUNTER TABLES
	BEQ	20$		; IF EQ NONE
	CALL	RSETC		; RESET ALL COUNTERS
20$:				;

	.ENDC

	.IF DF	I$$CIM

	MOV	S.DI(R4),R3	; GET ADDRESS OF DIGITAL INTERRUPT TABLE
	BEQ	25$		; IF EQ NONE
	CALL	READDI		; READ IN CURRENT STATES
25$:

	.ENDC

	.IF DF	I$$CDA

	MOV	R4,R0		; COPY SCB ADDR      ESS
	ADD	#S.DAC,R0	; POINT TO D/A TABLES
	MOV	(R0)+,R3	; GET MAPPING TABLE ADDRESS
	BEQ	40$		; IF EQ NONE
	MOV	2(R0),-(SP)	; PUSH NUMBER OF CHANNELS-1
	MOV	(R0),R0		; POINT TO PREVIOUS STATE TABLE
	CLR	-(SP)		; RESERVE SPACE ON THE STACK
30$:				;
	MOV	(R0)+,R1	; GET PREVIOUS STATE
	BIC	#140000,R1	; CLEAR CHANNEL NUMBER
	BIC	#37777,(SP)	; CLEAR VOLTAGE REPRESENTATION
	BIS	R1,(SP)		; MERGE CHANNEL AND VOLTAGE
	MOV	#ICMD/2&77777,-(SP) ; PUSH BUS ADDRESS OF ICR/2
	BISB	(R3),(SP)	; MERGE MODULE OFF      SET
	MOV	SP,R1		; SET ADDRESS OF BLOCK
	CALL	CBINS		; OUTPUT TO DEVICE
	TST	(SP)+		; CLEAN STACK
	ADD	#40000,(SP)	; INCREMENT CHANNEL NUMBER
	ADC	R3		; STEP TO NEXT MODULE ON OVERFLOW
	DEC	2(SP)		; DECREMENT COUNT
	BPL	30$		; IF PL GO AGAIN
	CMP	(SP)+,(SP)+	; CLEAN STACK
40$:				;

	.ENDC

	.IF DF	I$$CLT

	MOV	R4,R0		; COPY ADDRESS OF SCB
	ADD	#S.LTO,R0	; POINT TO LATCHING OUTPUT TABLE ADDRESSES
	MOV	(R0)+,R3	; GET MAPPING TABLE ADDRESS
	BEQ	60$		; IF EQ NONE
	MOV	2(R0),-(SP)	; SET POINT       COUNT-1
	MOV	(R0),R0		; GET ADDRESS OF PREVIOUS STATE TABLE
50$:				;
	MOV	(R0)+,-(SP)	; PUSH PREVIOUS STATE
	MOV	#ICMD/2&77777,-(SP) ; PUSH BUS ADDRESS/2
	BISB	(R3)+,(SP)	; COMBINE WITH MODULE OFFSET BIAS
	MOV	SP,R1		; COPY ADDRESS OF BLOCK
	CALL	CBINS		; INSERT IN CIRCULAR BUFFER
	CMP	(SP)+,(SP)+	; CLEAN STACK
	SUB	#16.,(SP)	; DECREMENT POINT COUNT
	BPL	50$		; IF PL GO AGAIN
	INC	(SP)+		; CLEAN THE STACK

	.ENDC
60$:				;
	RETURN

	.DSABL	LSB

;+
; **-ICWDT-WATCHDOG TIMER ROUTINE
;
;       THIS ROUTINE IS SCHEDULED BY THE DRIVER TO PERIODICALY RE-
; SET THE SOFTWARE WATCHDOG TIMERS FOR ALL CONTROLLERS AND PER-
; FORM ERROR RECOVERY FOR ANY CONTROLLER THAT IS IN THE NOT-READY
; STATE.
;
;-
	.ENABL	LSB

	.IF DF	I$$CR

ICWDT:				;
	MOV	#I$$C11,-(SP)	; SET COUNT OF CONTROLLERS
10$:				;
	MOV	#CNTBL-2,R5	; GET ADDRESS OF UCB TABLE
	ADD	(SP),R5		; OFFSET TO CONTROLLER SLOT
	ADD	(SP),R5		; ...
	MOV	(R5),R5		; GET UCB ADDRESS
	BEQ	40$		; IF EQ CONTROLLER OFFLINE
	BITB	#US.OFL,U.ST2      (R5) ; CONTROLLER OFFLINE?
	BNE	40$		; IF NE YES
	MOV	U.SCB(R5),R4	; GET ADDRESS OF SCB
	MOV	#-I$$CWD,S.ERR(R4) ; RESET WATCHDOG TIMER
	TSTB	S.CTMC(R4)	; CONTROLLER TIMEOUT ACTIVE?
	BEQ	20$		; IF EQ NO
	DECB	S.CTMC(R4)	; DECREMENT TIMEOUT COUNT
	BNE	40$		; IF NE OK
	CALL	CTOUT		; INITIATE TIMEOUT PROCESSING
	BR	40$		;
20$:				;
	MOV	S.CSR(R4),R2	; GET CSR ADDRESS
	BIT	#UNR,S.FLG(R4)	; DEVICE NOT READY?
	BEQ	40$		; IF EQ NO
	BIT	#12000,(R2)	; ERROR CONDITIONS PRESENT?
	BNE	30$		; IF NE YES
	B      IC	#UNR,S.FLG(R4)	; CLEAR NOT-READY FLAG
	CALL	RSTOR		; RESTORE CONTROLLER
	BR	40$		;
30$:				;
	MOV	-(R2),R2	; CLEAR ERROR FLAGS
40$:				;
	DEC	(SP)		; DECREMENT CONTROLLER COUNT
	BGT	10$		; IF GT MORE TO GO
	INC	(SP)+		; CLEAN STACK
	MOV	#WDFLG+2,R0	; GET ADDRESS OF TIMER PACKET
SWDT:				;
	CLR	R1		; CLEAR HIGH ORDER DELTA TIME
	MOV	$TKPS,R2	; GET TICKS PER SECOND
	MOV	#C.SYST,R4	; SET REQUEST TYPE
	CALLR	$CLINS		; INSERT IN CLOCK QUEUE

	.ENDC


	.DSABL	LSB


;+
;
; **-ALINK-ACTIV      ATE A LINKED TASK
;
; THIS SUBROUTINE IS CALLED TO ACTIVATE ALL TASKS LINKED
; TO A GIVEN INTERRUPT LIST. IF THE SPECIFIED TASK IS AC-
; TIVE THEN THE EVENT FLAG DEFINED THROUGH THE LINK FUNC-
; TION IS SET ELSE THE TASK IS REQUESTED TO RUN.
;
; INPUTS:
;
;	R3=ADDRESS OF INTERRUPT LINK LIST
;
; OUTPUTS:
;
;	IF THE 'RUN' FLAG IS SET IN THE ENTRY, THEN THE
;	TASK IS MADE ACTIVE AS DESCRIBED ABOVE ELSE THE
;	SPECIFIED EVENT FLAG IS SET.
;
; REGISTERS MODIFIED:
;
; R0 - R3
;
;-

	.IF DF	I      $$CIM!I$$CR!I$$CTI&I$$CLK

ALINK:				;
	MOV	R3,-(SP)	; SAVE LISTHEAD ADDRESS
10$:				;
	MOV	@(SP)+,R3	; GET LINK TO NEXT
	BEQ	30$		; IF EQ DONE WITH LIST
	MOV	R3,-(SP)	; SAVE ADDRESS OF THIS ENTRY
 	TST	ILRUN(R3)	; RUN FLAG SET?
	BEQ	10$		; IF EQ NO
	CLR	ILRUN(R3)	; CLEAR RUN FLAG
	MOV	ILTE(R3),R0	; GET ADDRESS OF LINKED TASK ENTRY
	MOV	LTCB(R0),R0	; GET ADDRESS OF TCB
	MOV	T.STAT(R0),R1	; GET TASK STATUS FLAGS
	BIT	#TS.EXE,R1  	; TASK ACTIVE?
	BNE	20$		; IF NE NO
	BIT	#T2.ABO,T.ST2(R0) ; TA      SK BEING ABORTED?
	BNE	10$		; IF NE YES
	BIT	#TS.OUT,R1	; TASK OUT OF MEMORY?
	BEQ	15$		; IF EQ NO
	BIT	#TS.CKP,R1	; TASK CHECKPOINTED?
	BEQ	10$		; IF EQ NO
15$:				;
	MOV	ILEVA(R3),R2	; GET ADDRESS OF EVENT FLAG MASK
	BEQ	10$		; IF EQ NONE
	BIS	ILEVM(R3),(R2)	; SET EVENT FLAG
	CALL	$SETCR		; ISSUE CONDITIONAL SCHEDULE REQUEST
	BR	10$		; GO AGAIN
20$:				;
	CLR	R1		; SET DEFAULT UIC
	CALL	$TSKRT		; REQUEST TASK
	BR	10$		; GO AGAIN
30$:				;
	RETURN			;

	.ENDC

;+
;
; **-CBINS-INSERT       AN ENTRY IN THE CIRCULAR BUFFER
;
; INPUTS:
;
;	R1=ADDRESS OF TWO-WORD DATA BLOCK CONTAINING THE
;	   FOLLOWING:
;
;	   WD. 00 -- BUS ADDRESS/2!REMOTE TERMINAL BIT(MSB)
;	   WD. 01 -- BUS DATA
;
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;
; OUTPUTS:
;
;	C/CLEAR: ENTRY INSERTED IN BUFFER
;
;	C/SET: CONTROLLER TIME-OUT DETECTED.
;
;
; IF CONTROLLER TIME-OUT IS DETECTED THE APPROPRIATE ERROR
; PROCESSING IS INITIATED.
;
; R1 AND R2 ARE MODIFIED
;
;-

CBINS:				;

	.IF DF	I$$CR

	MOV	R3      ,-(SP)	; SAVE R3
	MOV	S.CBF(R4),R3	; GET ADDRESS OF CIRCULAR BUFFER
	BEQ	60$		; IF EQ 0, NO CBF (THIS IS ICS11)
	MOV	#TMOUT,-(SP)	; SET DEVICE TIME-OUT COUNT
10$:				;
	CMP	#<CLGH-CDAT>/4-1,(R3) ; ROOM IN BUFFER?
	BGT	20$		; IF GT YES
	DEC	(SP)		; DECREMENT TIME-OUT COUNT
	BNE	10$		; IF NE TRY AGAIN
	MOV	R0,(SP)		; SAVE R0
	CALL	CTOUT		; INITIATE DEVICE TIME-OUT PROCESSING
	MOV	(SP),R0		; RESTORE R0
	BR	50$		; EXIT
20$:				;
	CMP	(R3)+,(R3)+	; POINT TO INPUT POINTER
	MOVB	#PR6,PS		;;; LOCKOUT       DEVICE INTERRUPTS
	MOV	(R3)+,R2	;;; GET INPUT POINTER
	MOV	2(R1),(R2)+	;;; SET OUTPUT DATA
	MOV	(R1),(R2)+	;;; SET BUS ADDRESS
	CMP	R2,(R3)+	;;; AT END OF BUFFER?
	BLO	30$		;;; IF LO NO
	MOV	R3,R2		;;; RESET POINTER TO START OF DATA
30$:				;;;
	MOV	R2,CIN-CDAT(R3)	;;; SAVE INPUT POINTER
	INC	CBSY-CDAT(R3)	;;; INCREMENT BUSY COUNT
	BEQ	35$		;;; IF EQ NO INTERRUPTS WANTED
	BIS	#10,@S.CSR(R4)	;;; ENABLE INTERRUPTS
	MOVB	S.ITMC(R4),S.CTMC(R4) ;;; ENABLE CONTROLLER TIMEOUTS
	BR	40$		;;;
35$:				;      ;;
	CALL	CBOUT		;;; STARTUP INTERRUPTS
40$:				;;;
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
50$:				;
	INC	(SP)+		; CLEAN STACK
	MOV	(SP)+,R3	; RESTORE R3
	RETURN			;
60$:				;
	MOV	(SP)+,R3	; RESTORE R3

	.IFTF

	MOV	(R1)+,R2	; GET BUS ADDRESS/2
	ASL	R2		; CONVERT TO BUS ADDRESS
	MOV	(R1),(R2)	; TRANSFER MODULE DATA
	RETURN			;

;+
; **-CBOUT-TRANSMIT CIRCULAR BUFFER DATA TO DEVICE
;
; THIS SUBROUTINE IS CALLED AT DEVICE PRIORITY LEVEL TO TRANS-
; FER DATA FROM THE CIRCULAR BUFFER TO THE S      PECIFIED BUS AD-
; DRESS.
;
; INPUTS:
;
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;
; OUTPUTS:
;
;	DATA (IF PRESENT) IS TRANSMITTED TO THE BUS ADDRESS
;	CONTAINED IN THE BUFFER.
;
; R1, R2, AND R3 ARE MODIFIED
;
;-

	.IFT


CBOUT:				;;;
	MOV	S.CSR(R4),R1	;;; GET CSR ADDRESS
	MOV	S.CBF(R4),R3	;;; GET CIRCULAR BUFFER ADDRESS
	BEQ	40$		;;; IF EQ, ICS-11 & THUS NO CBF
	TST	(R3)+		;;; POINT TO OUTPUT POINTER
	MOV	(R3)+,R2	;;; GET OUTPUT POINTER
	ASL	2(R2)		;;; SHIFT BUS ADDRESS
	BCC	10$		;;      ; IF C/CLEAR NO REMOTE TERMINAL OUTPUT
	BIS	#40,(R1)	;;; ENABLE REMOTE TERMINAL I/O
10$:				;;;
	MOV	(R2)+,@(R2)+	;;; MOVE DATA TO DEVICE
	BCC	15$		;;; IF C/C NOT REMOTE TERMINAL I/O
	BIS	#1000,(R1)	;;; ENABLE REMOTE TERMINAL OUTPUT INTERRUPT
	BIC	#40,(R1)	;;; DISABLE REMOTE TERMINAL MODE
15$:				;;;
	TST	(R3)+		;;; POINT TO END ADDRESS OF BUFFER
	CMP	R2,(R3)+	;;; REACHED END OF BUFFER?
	BLO	20$		;;; IF LO NO
	MOV	R3,R2		;;; RESET OUTPUT POINTER
20$:				;;;
	MOV	R2,COUT-CDAT(R3) ;;; SAVE OUTPUT       POINTER
30$:				;;;
	RETURN			;;;
40$:				;
	CRASH			;;; CBOUT CALLED ON AN ICS-11

	.ENDC

;+
;
; **-CENTR-CONDITIONALLY ENTER DATA IN A CIRCULAR BUFFER
;
; THIS ROUTINE IS CALLED AT DEVICE PRIORITY LEVEL TO CONDITIONALLY
; INSERT AN ENTRY IN A CIRCULAR BUFFER.
;
; INPUTS:
;
;	R2=FORCE ENTRY FLAG
;
;		R2=0 - INSERT NEW ENTRY ONLY IF BUFFER IS FREE
;		R2=-1 - INSERT NEW ENTRY EVEN IF BUFFER NOT READ BY TASK
;
;	R5=MODULE TABLE ADDRESS
;
;	STACK CONTENTS:
;
;	(SP)+00 -- RETURN TO C      ALLER
;	(SP)+02 -- UNDEFINED
;	(SP)+04 -- CIRCULAR BUFFER ENTRY WD. 01
;	.		.
;	.		.
;	(SP)+NN -- CIRCULAR BUFFER ENTRY WD. NN
;
; OUTPUTS:
;
;	C/SET: A TASK IS CONNECTED TO INTERRUPTS
;
;	IF R2 WAS NEGATIVE, THE ENTRY IS UNCONDITIONALLY
;	INSERTED IN THE CIRCULAR BUFFER. ELSE THE ENTRY
;	EXISTENCE INDICATOR IS TESTED. IF NON-ZERO THE
;	ENTRY IS DISCARDED AND A COUNT OF OVERRUNS IS
;	INCREMENTED AND PLACED IN THE BUFFER. IF ZERO
;	THE ENTRY IS PLACED IN THE BUFFER AND THE INDI-
;	CATOR IS S      ET TO +1
;
;
;	C/CLEAR: NO TASK CONNECTED OR OVERRUN EXISTS
;
; REGISTERS MODIFIED:
;
; R0 - R2
;
;-

	.IF DF	I$$CIM!I$$CR!I$$CTI

CENTR:				;;;
	MOV	SP,R0		;;; GET ADDRESS OF STACK
	TST	(R0)+		;;; POINT TO FIRST WORD OF BUFFER ENTRY
	MOV	#1,(R0)		;;; ASSUME NO FORCED ENTRY

	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;;; SAVE ASR 6
	MOV	IMCBF(R5),KISAR6 ;;; MAP TO USER'S BUFFER

	.IFTF

	TST	IMTCB(R5)	;;; TASK CONNECTED?
	BEQ	60$		;;; IF EQ NO
	MOV	IMCUR(R5),R1	;;; GET CURRENT BUFFER ADDRE      SS
	TST	(R1)		;;; ENTRY FREE
	BEQ	10$		;;; IF EQ YES
	TST	R2		;;; FORCED ENTRY?
	BPL	50$		;;; IF PL NO
10$:				;;;
	SUB	R2,(R0)		;;; INCLUDE FORCED ENTRY CONDITION
	MOVB	IMBPE(R5),R2	;;; GET BYTES PER ENTRY
	ASR	R2		;;; CONVERT TO WORD BIAS
	CLR	IMLST(R5)	;;; CLEAR LOST DATA COUNT
20$:				;;;
	MOV	(R0)+,(R1)+	;;; MOVE A WORD TO USERS'S BUFFER

	.IFT

	BIT	#20000,R1	;;; CROSS 4K BOUNDARY?
	BEQ	30$		;;; IF EQ NO
	BIC	#20000,R1	;;; RESET BUFFER ADDRESS
	ADD	#200,KISAR6	;;; RESET ADDRESS BIAS      
	ADD	#200,IMCBF(R5)	;;; ...

	.IFTF

30$:				;;;
	INC	IMFIL(R5)	;;; INCREMENT FILL INDEX
	CMP	IMLGH(R5),IMFIL(R5) ;;; REACHED END OF BUFFER?
	BHIS	40$		;;; IF HIS NO
	MOV	#3,IMFIL(R5)	;;; RESET FILL INDEX

	.IFT

	MOV	IMSBF(R5),IMCBF(R5) ;;; RESET ADDRESS TO START
	MOV	IMCBF(R5),KISAR6 ;;; ...

	.IFTF

	MOV	IMSDA(R5),R1	;;; POINT TO START OF DATA
40$:				;;;
	DEC	R2		;;; DECREMENT WORD COUNT
	BGT	20$		;;; IF GT MORE TO MOVE
	MOV	R1,IMCUR(R5)	;;; SAVE CURRENT ADDRESS

	.IFT

	MOV	IM      SBF(R5),KISAR6 ;;; POINT TO START OF BUFFER

	.IFTF

	MOV	IMFIL(R5),@IMSAD(R5) ;;; RESET FILL INDEX
	SEC			;;; SET SUCCESS
	BR	70$		;;;
50$:				;;;
	CMP	IMLST(R5),#100001 ;;; OVERRUN COUNT PEGGED?
	BEQ	55$		;;; IF EQ YES
	DEC	IMLST(R5)	;;; 'INCREMENT' LOST DATA COUNT
55$:				;;;
	MOV	IMLST(R5),(R1)	;;; SET OVERRUN COUNT
60$:				;;;
	CLC			;;; SET FAILURE
70$:				;;;

	.IFT

	MOV	(SP)+,KISAR6	;;; RESTORE ASR 6

	.ENDC

	RETURN			;;;

	.ENDC


;+
;
; **-CTOUT-ACTIVATE ERROR PROCE      SSING ON CONTROLLER TIME-OUT
;
; THIS SUBROUTINE IS CALLED WHENEVER CONTROLLER TIMEOUT IS DE-
; TECTED. IF THE UNIT IS ONLINE ERROR ALARMING IS INITIATED.
;
; INPUTS:
;
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;	R5=ADDRESS OF UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	C BIT CLEAR: UNIT ONLINE.
;
;	C BIT CLEAR: UNIT OFFLINE OR PREVIOUS NO-RESPONSE CONDITION IN EFFECT.
;
;	IF THE UNIT IS ON-LINE ALL ERROR ALARMING TASKS ARE
;	INITIATED. THE UNIT IS PLACED IN THE NOT READY STATE.
;
; REGISTERS MODIFIED      
; R0 - R3
;
;-

	.IF DF	I$$CR

CTOUT:				;
	CLC			; ASSUME UNIT OFFLINE
	MOV	U.UNIT(R5),R1	; GET UNIT NUMBER
	MOV	R4,-(SP)	; SAVE SCB ADDRESS
	MOV	R5,-(SP)	; SAVE UCB ADDRESS
	MOV	S.CSR(R4),R5	; GET ADDRESS OF CSR
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUPTS
	BIT	#UNR!NORSP,S.FLG(R4) ;;; UNIT NOT READY OR NO RESPONSE?
	BNE	5$		;;; IF NE YES
	BIS	#UNR!NORSP,S.FLG(R4) ;;; SET NOT-READY, NO RESPONSE CONDITIONS
	MOV	(R5),R0		;;; GET ICSR CONTENTS
	CALL	STERR		;;; INITIATE ERROR PROCESSING
	C      LRB	PS		; ALLOW DEVICE INTERRUPTS
	MOV	(SP),R5		; SET UCB ADDRESS
	CALL	INIER		; INITIATE ERROR PROCESSING
5$:				;;;
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	MOV	(SP)+,R5	; RESTORE UCB ADDRESS
	MOV	(SP)+,R4	; RESTORE SCB ADDRESS
	SEC			; FLAG UNIT ONLINE
10$:				;
	RETURN			;

	.ENDC

;+
;
; **-RSETC-SUBROUTINE TO RESET ALL COUNTER MODULES
;
; THIS ROUTINE IS CALLED WHENEVER IT IS NECESSARY TO UNCONDITIONALLY
; RESET THE STATE OF ALL COUNTERS ON A CONTROLLER.
;
; INPUTS:
;
;	R3=ADDRESS OF       COUNTER TABLE
;	R5=ADDRESS OF UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;	ALL COUNTERS ARE RESET WITH THE CURRENT STATE
;
; REGISTERS MODIFIED:
;
; R1 - R3
;
;-

	.IF DF	I$$CTI

RSETC:				;
	MOV	U.SCB(R5),R4	; GET ADDRESS OF SCB
	MOV	IMTCB(R3),-(SP)	; PUSH TCB ADDRESS OF CONNECTED TASK
	MOV	(R3),-(SP)	; SET NUMBER OF COUNTERS-1
	ADD	#IMDAT+IMPRV,R3	; OFFSET TO MODULE DATA
10$:				;
	TST	2(SP)		; TASK CONNECTED?
	BNE	20$		; IF NE YES
	TST	IMRES-IMPRV(R3)	      ; TASK LINKED?
	BEQ	30$		; IF EQ NO
	TST	(R3)		; PREVIOUS STATE 0
	BEQ	30$		; IF EQ YES - DON'T RESET COUNTER
20$:				;
	CALL	SETCT		; INITIALIZE THE COUNTER
30$:				;
	ADD	#CTLGH,R3	; POINT TO NEXT ENTRY
	DEC	(SP)		; DECREMENT COUNT
	BPL	10$		; IF PL GO AGAIN
	MOV	(SP)+,(SP)+	; CLEAN STACK
	RETURN			;

	.ENDC

;+
;
; **-READDI-SUBROUTINE TO READ THE CURRENT STATE OF ALL DI MODULES
;
; THIS ROUTINE IS CALLED WHEN POWER IS APPLIED, IN ORDER TO READ IN THE
; CURRENT STATE OF ALL THE DIGITA      L INTERRUPT MODULES ON A CONTROLLER.
;
; INPUTS:
;
;	R3=ADDRESS OF DIGITAL INTERRUPT TABLE
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;	R5=ADDRESS OF UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	ALL "IMPRV" ENTRIES IN THE MODULE DATA FOR THE CONTROLLER HAVE
;	BEEN FILLED IN.
;
; REGISTERS MODIFIED:
;
; R2 - R3
;
;-

	.IF DF	I$$CIM

READDI:				;
	MOV	R4,-(SP)	; SAVE R4
	MOV	(R3),R2		; GET HIGHEST POINT - 15
	ASR	R2		; CONVERT TO NO. MODULES - 1
	ASR	R2		; ...
	ASR	R2		; ...
	ASR	R2		; ...
	ADD	#      IMDAT,R3	; POINT AT MODULE DATA
10$:	MOV	IMBA(R3),R4	; GET MODULE BUS ADDRESS / 2
	ASL	R4		; CALCULATE BUS ADDRESS
	MOV	(R4),IMPRV(R3)	; READ CURRENT MODULE STATE
	DEC	R2		; COUNT PASSES
	BPL	10$		; ...
	MOV	(SP)+,R4	; RESTORE SCB TO R4				;JM043
	RETURN

	.ENDC

;+
;
; **-SAVE-SAVE REGISTERS R3 - R0
;
; THIS SUBROUTINE IS CALLED VIA A 'JSR R3,SAVE' TO SAVE
; REGISTERS R3 - R0. A CO-ROUTINE CALL IS THEN MADE TO
; THE CALLER. A SUBSEQUENT RETURN WILL CAUSE THE REGISTERS
; TO BE RESTORED AND       THE INTERRUPT ENABLE BITS TO BE TOGGLED
; IN ORDER TO PERMIT THE ASSERTION OF ANY PENDING BUT UNRE-
; COGNIZED INTERRUPTS. EXIT IS VIA A RETURN.
;
;-

	.IF DF	I$$CAD!I$$CIM!I$$CTI!I$$CR


SAVE:				;;;
	MOV	R2,-(SP)	;;; SAVE R2
	MOV	R1,-(SP)	;;; SAVE R1
	MOV	R0,-(SP)	;;; SAVE R0
	CALL	(R3)		;;; CALL THE CALLER
	MOV	CSR,R0		;;; GET THE CSR ADDRESS
	MOV	(R0),R1		;;; READ THE CSR CONTENTS
	BIC	#^C<1036>,R1	;;; CLEAR ALL BUT THE INTERRUPT ENABLE BITS
	BIC	R1,(R0)		;;; DISABLE ALL ENABLED INTERR      UPTS
	BIS	R1,(R0)		;;; RE-ENABLE APPROPRIATE INTERRUPTS
	MOV	(SP)+,R0	;;; RESTORE R0
	MOV	(SP)+,R1	;;; RESTORE R1
	MOV	(SP)+,R2	;;; RESTORE R2
	MOV	(SP)+,R3	;;; RESTORE R3
	RETURN			;;; EXIT

	.ENDC


;+
;
; **-SETCT-INITIALIZE A COUNTER MODULE
;
; THIS SUBROUTINE IS CALLED TO INITIALIZE A SINGLE COUNTER MODULE.
;
; INPUTS:
;
;	R3=ADDRESS OF COUNTER MODULE ENTRY IN MODULE TABLE
;	R4=ADDRESS OF STATUS CONTROL BLOCK
;
; OUTPUTS:
;
;	THE SPECIFIED COUNTER IS INITIALIZED WITH THE VALUE
      ;	CONTAINED IN THE INITIAL VALUE CELL WITHIN THE TABLE.
;
; REGISTERS MODIFIED:
;
; R1 - R2
;
;-

	.IF DF	I$$CTI

SETCT:				;

	.IF DF	I$$CR

	MOV	(R3)+,-(SP)	; PUSH MODULE DATA
	MOV	#100000,R1	; GET REFRESH FLAG
	MOV	(R3),-(SP)	; PUSH BUS ADDRESS/2
	BIC	R1,(R3)		; CLEAR POSSIBLE REFRESH FLAG
	BIC	R1,(SP)		; ...

	.IFF

	MOV	(R3)+,-(SP)	; PUSH MODULE DATA
	MOV	(R3),-(SP)	; PUSH BUS ADDRESS

	.IFTF

	MOV	SP,R1		; COPY ADDRESS OF BLOCK

	.IFT

	TST	S.RTI(R4)	; ICS-11 CONTROLLER?      
	BEQ	10$		; IF EQ YES
	CALL	CBINS		; TRANSMIT DATA TO DEVICE
	BR	20$		; EXIT
10$:				;

	.IFTF

	ASL	(R1)+		; SHIFT BUS ADDRESS
	MOVB	#PR6,PS		;;; INHIBIT DEVICE INTERRUPTS
	BIS	#1,@S.CSR(R4)	;;; SET RIF BIT
	MOV	(R1),@-(R1)	;;; RESET COUNTER
	CLRB	PS		; ALLOW DEVICE INTERRUPTS

	.ENDC

20$:				;
	MOV	(SP)+,(SP)+	; CLEAN STACK
	TST	-(R3)		; RESET R3
	RETURN			;

	.ENDC
;+
;
; **-SLINK-SCAN LINKED INTERRUPT LIST FOR A MATCH
;
; THIS SUBROUTINE IS CALLED AT DEVICE PRIORITY LEVEL TO      
; SCAN A LINKED INTERRUPT LIST FOR A MATCH. IF A MATCH
; IS FOUND THE ENTRY IS FLAGGED FOR SCHEDULING AT FORK
; LEVEL.
;
; INPUTS:
;
;	R3=ADDRESS OF ENTRY IN MODULE TABLE
;	TMP=PHYSICAL UNIT NUMBER
;
;	STACK CONTENTS AS FOLLOWS:
;
;	(SP)+00 -- RETURN TO CALLER
;	(SP)+02 -- RESOURCE MASK
;	(SP)+04 -- HARDWARE DEPENDANT DATA - WD. 01
;	(SP)+06 -- HARDWARE DEPENDANT DATA - WD. 00
;	(SP)+10 -- RELATIVE MODULE NUMBER
;	(SP)+12 -- GENERIC CODE
;
; OUTPUTS:
;
;	C/SET: ONE OR MORE ENTRIES LINKE      D TO THE RESOURCE WERE
;		 FOUND. THE LINKED TASK ENTRY FOR EACH SUCH TASK
;		 IS CONDITIONALLY UPDATED AND THE 'SCHEDULE' FLAG
;		  IS SET IN THE INTERRUPT LINKAGE LIST.
;
;	C/CLEAR: NO TASKS ARE LINKED TO THE RESOURCE
;
; REGISTERS MODIFIED:
;
; R0 - R3
;
;-

	.IF DF	I$$CIM!I$$CR!I$$CTI&I$$CLK

SLINK:				;;;
	CLR	R0		;;; ASSUME NO LINKED ENTRIES
	BIT	2(SP),(R3)+	;;; ANY TASKS LINKED?
	BEQ	30$		;;; IF EQ NO
10$:				;;;
	MOV	(R3),R3		;;; GET NEXT ENTRY
	BEQ	30$		;;; IF EQ REACHED END OF       LIST
	BIT	2(SP),ILMSK(R3)	;;; THIS TASK LINKED?
	BEQ	10$		;;; IF EQ NO
	MOV	PC,R0		;;; ASSUME NO LINKED ENTRIES
	MOV	ILTE(R3),R1	;;; GET ADDRESS OF LINKED TASK ENTRY
	INC	ILRUN(R3)	;;; SET RUN FLAG
	ADD	#LACT,R1	;;; POINT TO ACTIVITY COUNT
	TST	(R1)		;;; PREVIOUS ENTRY READ BY USER?
	BNE	20$		;;; IF NE NO
	INC	(R1)+		;;; SET COUNT TO +1
	MOV	SP,R2		;;; GET STACK ADDRESS
	ADD	#12,R2		;;; POINT TO GENERIC CODE
	MOV	TMP,(R1)+	;;; RECORD PHYSICAL UNIT NUMBER
	MOV	(R2),(R1)+	;;; RECORD GENERIC CODE      
	MOV	-(R2),(R1)+	;;; RECORD RELATIVE MODULE NUMBER
	MOV	-(R2),(R1)+	;;; SAVE HARDWARE DEPENDANT DATA
	MOV	-(R2),(R1)+	;;; ...
	BR	10$		;;; LOOK FOR ANOTHER LINKED ENTRY
20$:				;;;
	DEC	(R1)		;;; DECREMENT ACTIVATION COUNT
	BMI	10$		;;; IF MI ALREADY MISSED AT LEAST ONE
	DEC	(R1)		;;; SET COUNT NEGATIVE
	BR	10$		;;; GO AGAIN
30$:				;;;
	NEG	R0		;;; SET SUCCESS/FAIL FLAG
	RETURN			;;;

	.ENDC


;+
;
; **-STERR-PERFORM ERROR ALARMING FUNCTIONS
;
; THIS SUBROUTINE IS CALLED AT DEVICE PRI      ORITY TO INITIATE
; PROCESSING FOR ALL TASKS THAT ARE TO BE NOTIFIED WHEN-
; EVER A FATAL CONTROLLER ERROR IS DETECTED.
;
; INPUTS:
;
;	R0=ICSR CONTENTS
;	R1=PHYSICAL UNIT NUMBER
;	R4=ADDRESS OF SCB
;	R5=ADDRESS OF ICSR
;
; OUTPUTS:
;
;	ALL ICS/ICR INTERRUPTS ARE DISABLED. ERROR DATA IS
;	SUPPLIED TO ALL CONNECTED TASKS AND THE ALARMING
;	TASK IS FLAGGED FOR SCHEDULING AT FORK LEVEL.
;
; REGISTERS MODIFIED:
;
; R0, R1, R2, R3, AND R5
;-


	.IF DF	I$$CR

STERR:				;;;
	CLRB	S.CTMC(R      4)	;;; DISABLE DEVICE TIME-OUTS
	MOV	R1,TMP		;;; SET PHYSICAL UNIT NUMBER
	MOV	#177770,-(SP)	;;; SET GENERIC CODE
	MOV	R1,-(SP)	;;; SET PHYSICAL UNIT NUMBER
	MOV	R0,-(SP)	;;; SET ICSR CONTENTS
	BIC	#22,(R5)	;;; DISABLE ERROR INTERRUPTS
	MOV	-(R5),-(SP)	;;; SAVE ICAR CONTERNTS
	MOV	#-1,-(SP)	;;; SET RESOURCE MASK

	.IF DF	I$$CLK

	MOV	#ICDVT+ICRES,R3	;;; POINT TO RESOURCE MASK FOR ERRORS
	CALL	SLINK		;;; SET ALARMING TASK FOR SCHEDULING

	.ENDC

	.IF DF	I$$CIM

	MOV	S.DI(R4),R5	;;; GET ADDR      ESS OF DIGITAL INTERRUPT TABLES
	BEQ	10$		;;; IF EQ NONE
	CALL	40$		;;; ENTER DATA IN CIRCULAR BUFFER

	.ENDC

10$:				;;;
	MOV	(SP)+,(SP)	;;; COLLAPSE STACK

	.IF DF	I$$CTI

	MOV	S.CT(R4),R5	;;; GET ADDRESS OF COUNTER TABLES
	BEQ	20$		;;; IF EQ NONE
	CALL	40$		;;; ENTER DATA IN CIRCULAR BUFFER

	.ENDC

20$:				;;;
	MOV	S.RTI(R4),R5	;;; GET ADDRESS OF REMOTE TERMINAL TABLES
	BEQ	30$		;;; IF EQ NONE
	CALL	40$		;;; ENTER DATA IN CIRCULAR BUFFER
30$:				;;;
	ADD	#10,SP		;;; CLEAN STACK
	   ˆ   RETURN			;;;
40$:				;;;
	MOV	#-1,R2		;;; SET FORCED ENTRY FLAG
	CALLR	CENTR		;;; MOVE ENTRY TO CIRCULAR BUFFER

	.ENDC

	.END
 ˆ          ãàkQ	› c,        	.TITLE	DRSED
	.IDENT	/10.21/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 10.21
;
; D. N. CUTLER 2-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	9-JUL-79
;		MSH040 -- CORRECT BUG READING GROUP GLOBAL EFN'S
;
;	M. S. HARVEY	19-AUG-79
;      		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	10-SEP-79
;		MSH061 -- PUT TASK IN WAITFOR USING BIS INSTEAD OF INC.
;
;	M. S. HARVEY	25-SEP-79
;		MSH063 -- PRESERVE SEF BIT IF STOP FOR EVENT FLAG
;			  DIRECTIVE ISSUED AT AST STATE
;
;	M. S. HARVEY	30-SEP-79
;		MSH045 -- MOVE SIGNIFICANT EVENT ROUTINES INTO DRSUB
;
;	M. S. HARVEY	9-OCT-79
;		MSH069 -- ALLOW TASKS TO STOP FOR GLOBAL EVENT FLAGS
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG US      E CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	22-JUL-80
;		MSH106 -- RECOGNIZE 'READ ALL EVENT FLAGS' DIRECTIVE
;			  FOR UNMAPPED SYSTEMS WITH GROUP GLOBAL EFNS
;
;	M. S. HARVEY	8-JAN-81
;		MSH139 -- MAP STOPFOR DIRECTIVES INTO WAITFOR DIRECTIVES
;			  IF STOP-BIT SYNCHRONIZATION NOT SUPPORTED
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
;	M. S. HARVEY	6-OCT-81
;		MSH194 -- EXTERNALIZE WAITFOR ROUTINE
;
; SIGNIFICANT EVENT AND EVENT FLAG DIRECTIVES
;
; MACRO LIB      RARY CALLS
;

	.MCALL	HDRDF$,TCBDF$,PKTDF$
	PKTDF$			;DEFINE EVENT FLAG GROUP OFFSETS
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRCEF-CLEAR EVENT FLAG
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CLEAR AN EVENT FLAG AND
; REPORT ITS POLARITY BEFORE CLEARING.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(31.),DPB SIZE(2.).
;	WD. 01 -- EVENT FLAG NUMBER OF FLAG TO BE CLEARED.
;
; INPUTS:
;
;	R0=EVENT FLAG MASK WORD.
;	R1=EVENT FLAG MASK ADDRESS.
;	R2      =ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF 'D.RS00' IF THE FLAG WAS
;		CLEAR OR 'D.RS22' IF THE FLAG WAS SET.
;-

	.ENABL	LSB
$DRCEF::BIT	R0,(R1)		;TEST FLAG
	BEQ	20$		;IF EQ FLAG IS CLEAR
	BIC	R0,(R1)		;CLEAR FLAG
10$:	DRSTS	D.RS22		;SET DIRECTIVE STATUS
      
;+									;**-27
; **$DRRAF-READ ALL EVENT FLAGS OR READ EXTENDED EVENT FLAGS
;
; THESE DIRECTIVES INSTRUCT THE SYSTEM TO FILL A FOUR (OR SIX) WORD
; BUFFER WITH THE ISSUING TASKS LOCAL, COMMON, AND GROUP GLOBAL
; EVENT FLAGS.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(39.),DPB SIZE(2. OR 3.).
;	WD. 01 -- ADDRESS OF A FOUR OR SIX WORD BUFFER.
;
;	BUFFER FORMAT (DPB SIZE=2.):					;MSH106
;									;MSH106
;	WD. 00 -- TASK LOCAL EVENT FLAGS 1-16.				;MSH106
;	WD. 01 -- TASK LOCAL EVENT FLAGS 17-32.			      	;MSH106
;	WD. 02 -- COMMON EVENT FLAGS 33-48.				;MSH106
;	WD. 03 -- COMMON EVENT FLAGS 49-64.				;MSH106
;									;MSH106
;	BUFFER FORMAT (DPB SIZE=3.):					;MSH106
;									;**-1
;	WD. 00 -- TASK LOCAL EVENT FLAGS 1-16.
;	WD. 01 -- TASK LOCAL EVENT FLAGS 17-32.
;	WD. 02 -- COMMON EVENT FLAGS 33-48.
;	WD. 03 -- COMMON EVENT FLAGS 49-64.
;	WD. 04 -- GROUP GLOBAL EVENT FLAGS 65.-80.
;	WD. 05 -- GROUP GLOBAL EVENT FLAGS 81.-96.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURREN      T TASK.
;	R3=ADDRESS OF THE BUFFER ADDRESS IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED FOR READ ALL EVENT
;			FLAGS.
;		DIRECTIVE STATUS OF +1 IS RETURNED FOR READ EXTENDED
;			EVENT FLAGS IF THE ISSUING TASKS GROUP GLOBAL
;			EVENT FLAGS EXIST.
;		DIRECTIVE STATUS OF 'D.RS00' IS RETURNED FOR RE      AD
;			EXTENDED EVENT FLAGS IF THE ISSUING TASK'S GROUP
;			GLOBAL EVENT FLAGS DO NOT EXIST.  IN THIS CASE,
;			WORDS 4 AND 5 OF THE BUFFER ARE CLEARED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF BUFFER IS
;			OUTSIDE OF ISSUING TASK'S ADDRESS SPACE.
;-

$DRRAF::			;					;MSH106
									;**-2
	.IF DF	A$$CHK!M$$MGE

	MOV	#4*2,R1		;SET LENGTH OF BUFFER IN BYTES

	.IFTF								;MSH106
									;MSH106
	.IF DF G$$EFN

	MOVB	-(R3),R4	;GET DPB SIZE				;MSH10      6
	CMPB	(R3)+,#2	;READ ALL EVENT FLAGS DIRECTIVE?	;MSH106
	BEQ	12$		;IF EQ, YES				;**-2
	CMPB	#3,R4		;READ EXTENDED EVENT FLAGS DIRECTIVE?
	BNE	14$		;IF NE, NO, INVALID DPB SIZE
									;MSH106
	.IF DF	A$$CHK!M$$MGE						;MSH106
									;MSH106
	CMP	(R1)+,(R1)+	;ADD 2 TO SIZE OF BUFFER
									;MSH106
	.ENDC								;MSH106
									;MSH106
	.ENDC	;G$$EFN							;MSH106
									;MSH106
12$:	MOV	(R3),R3		;GET ADDRESS OF EVENT FLAG BUFFER	;MSH106
									;**-1
	.IFT								;MSH106
							      		;**-1
	CALL	$ACHKP		;ADDRESS CHECK PARAMETER BUFFER

	.ENDC


	MOV	T.EFLG(R5),(R3)+ ;INSERT LOCAL FLAGS 1-16
	MOV	T.EFLG+2(R5),(R3)+ ;INSERT LOCAL FLAGS 17-32
	MOV	$COMEF,(R3)+	;INSERT COMMON FLAGS 33-48
	MOV	$COMEF+2,(R3)+	;INSERT COMMON FLAGS 49.-64.

	.IF DF	G$$EFN

	CMPB	#2,R4		;READ ALL EVENT FLAGS DIRECTIVE?
	BEQ	13$		;IF EQ, YES
	CLR	(R3)+		;CLEAR WORD 4 OF BUFFER
	CLR	(R3)		;CLEAR WORD 5 OF BUFFER
	MOV	$HEADR,R4	;GET CURRENT TASK HEADER
	MOVB	H.CUIC+1(R4),R4	;GET TASK'S GROUP NUM      BER		;MSH040
	CALL	$SRGEF		;SEARCH FOR GROUP GLOBAL EVENT FLAGS	;**-1
	BCS	20$		;IF CS, THEY DON'T EXIST
	MOV	G.EFLG+2(R1),(R3) ;MOVE FLAGS 81.-96. TO BUFFER
	MOV	G.EFLG(R1),-(R3) ;MOVE FLAGS 65.-80. TO BUFFER
13$:				;REF LABEL

	.IFTF	;G$$EFN

	RETURN			;

	.IFT	;G$$EFN

14$:	DRSTS	D.RS99		;INVALID DPB SIZE

	.ENDC	;G$$EFN


;+
; **-$DRSEF-SET EVENT FLAG
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SET AN EVENT FLAG AND
; REPORT IS POLARITY BEFORE SETTING.
;
; DPB FORMAT:
;
;	WD. 0      0 -- DIC(33.),DPB SIZE(2.).
;	WD. 01 -- EVENT FLAG NUMBER OF FLAG TO BE SET.
;
; INPUTS:
;
;	R0=EVENT FLAG MASK WORD.
;	R1=EVENT FLAG MASK ADDRESS.
;	R3=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF 'D.RS00' IF THE FLAG WAS
;		CLEAR OR 'D.RS22' IF THE FLAG WAS S      ET.
;-

$DRSEF::BIT	R0,(R1)		;TEST FLAG				;MSH069
	BNE	10$		;IF NE FLAG IS SET			;**-14
	BIS	R0,(R1)		;SET FLAG
20$:	DRSTS	D.RS00		;SET DIRECTIVE STATUS
	.DSABL	LSB

;+									;**-47
; **-$DRSTS-STOP FOR SINGLE EVENT FLAG
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO STOP THE ISSUING TASK UNTIL
; A SPECIFIED EVENT FLAG IS SET.					;MSH069
;									;**-1
; DPB FORMAT:
;
;	WD. 00 -- DIC(135.),DPB SIZE(2.).
;	WD. 01 -- EVENT FLAG NUMBER OF FLAG TO WAITFOR.
;
; INPUTS:
;
;	R0=EVENT FLAG MA      SK WORD.
;	R1=EVENT FLAG MASK ADDRESS.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF THE ISSUING
;			TASK IS AT AST STATE.
;-		      							;**-3

	.ENABL	LSB

$DRSTS::TST	(R2)		;TASK AT AST STATE?			;MSH063
	BPL	27$		;IF PL NO, PUT TASK IN STOPFOR STATE	;MSH063
1$:	DRSTS	D.RS80		;ISSUEING TASK AT AST STATE		;MSH063
									;**-16
;+
; **-$DRSTL-STOP FOR LOGICAL OR OF EVENT FLAGS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO STOP THE ISSUING TASK UNTIL
; ANY OF THE SPECIFIED EVENT FLAGS IS SET.				;MSH069
;									;**-1
; DPB FORMAT:
;
;	WD. 00 -- DIC(137.),DPB SIZE(3.).
;	WD. 01 -- EVENT FLAG SET INDICATOR.
;	WD. 02 --       EVENT FLAG MASK WORD.
;
;	EVENT FLAG SETS:
;
;	SET 0 -- EVENT FLAGS 1.-16.	LOCAL
;	SET 1 -- EVENT FLAGS 17.-32.	LOCAL
;	SET 2 -- EVENT FLAGS 33.-48.	GLOBAL				;MSH069
;	SET 3 -- EVENT FLAGS 49.-64.	GLOBAL				;MSH069
;	SET 4 -- EVENT FLAGS 65.-80.	GROUP GLOBAL			;MSH069
;	SET 5 -- EVENT FLAGS 81.-96.	GROUP GLOBAL			;MSH069
;									;**-4
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT T      ASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF THE
;			ISSUING TASK IS AT AST STATE.
;		DIRECTIVE STATUS OF 'D.RS97' IS RETURNED IF AN
;			ILLEGAL EVENT FLAG SET OR A ZERO EVENT
;			FLAG MASK IS SPECIFIED.
;-

$DRSTL::TST	(R2)		;TASK AT AST STATE?			;MSH063
	BMI	1$		;IF       MI YES, CANCEL DIRECTIVE		;MSH063
									;**-7
;+									;**-1
; **-$DRWFL-WAIT FOR LOGICAL OR OF EVENT FLAGS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SUSPEND THE EXECUTION OF THE
; ISSUING TASK UNTIL ANY OF THE SPECIFIED EVENT FLAGS IS SET.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(43.),DPB SIZE(3.).
;	WD. 01 -- EVENT FLAG SET INDICATOR.
;	WD. 02 -- EVENT FLAG MASK WORD.
;
;	EVENT FLAG SETS:
;
;	SET 0 -- EVENT FLAGS 1.-16.
;	SET 1 -- EVENT FLAGS 17.-32.
;	SET 2 -- EVENT FLAGS 33.-48.
;	SET       3 -- EVENT FLAGS 49.-64.
;	SET 4 -- EVENT FLAGS 65.-80.
;	SET 5 -- EVENT FLAGS 81.-96.

;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF       'D.RS97' IS RETURNED IF AN
;			ILLEGAL EVENT FLAG SET OR A ZERO EVENT
;			FLAG MASK IS SPECIFIED.
;-

$DRWFL::MOV	(R3)+,R1	;GET EVENT FLAG SET			;**-1

	.IF DF G$$EFN

	CMP	R1,#5		;LEGAL SET?

	.IFF	;G$$EFN

	CMP	R1,#3		;LEGAL SET?

	.ENDC	;G$$EFN

	BHI	10$		;IF HI NO
	ASL	R1		;CONVERT TO WORD INDEX
	MOV	(R3),R0		;GET EVENT FLAG MASK WORD
	BEQ	10$		;IF EQ NO FLAGS SPECIFIED
	CMP	R1,#3		;COMMON GLOBAL FLAG SET?
	BLT	20$		;IF LT NO

	.IF DF G$$EFN

	CMP	R1,#7		;GROUP GLOBAL SET?
	BL      T	5$		;IF LT NO, COMMON GLOBAL
	MOV	R4,-(SP)	;SAVE REGISTERS
	MOV	R0,-(SP)	;
	MOV	R1,-(SP)	;SAVE EVENT FLAG SET INDEX
	MOVB	H.CUIC+1(R4),R4	;GET GROUP NUMBER
	CALL	$SRGEF		;SEARCH FOR GROUP GLOBAL EVENT FLAGS
	BCS	10$		;IF CS GROUP NOT FOUND
	ADD	(SP)+,R1	;POINT TO PROPER GROUP GLOBAL EF WORD
	ADD	#G.EFLG-10,R1	;  IN THE GROUP GLOBAL EVENT FLAG BLOCK
	MOV	(SP)+,R0	;RESTORE REGISTERS
	MOV	(SP)+,R4	;
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	INCB	T.GGF(R5)	;INC GRP GL      OBAL USE COUNT FOR TASK	;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH076
	CMP	-2(R3),#4	;IN FIRST SIXTEEN GROUP GLOBAL FLAGS?
	BEQ	3$		;IF EQ YES				;MSH049
	INC	G.CNT-<G.EFLG+2>(R1) ;INC GROUPS ACCESS COUNT		;MSH049
	BR	25$		;JOIN COMMON CODE			;MSH049
3$:	INC	G.CNT-G.EFLG(R1) ;INC GROUPS ACCESS COUNT		;MSH049
	BR	25$		;JOIN COMMON CODE			;MSH049
5$:				;REF LABEL				;**-2

	.ENDC	;G$$EFN

	ADD	#$COMEF-4,R1	;POINT TO PROPER COMMON FLAG WORD
	BR	25$		;FINISH UP AS IF SINGLE FLA      G		;MSH049
10$:	DRSTS	D.RS97		;SET DIRECTIVE STATUS			;**-1
20$:	ADD	R5,R1		;ADD ADDRESS OF TASK TCB
	ADD	#T.EFLG,R1	;POINT TO PROPER TASK FLAGS WORD
25$:				;					;MSH069
									;MSH069
	.IF DF	S$$TOP							;MSH069
									;MSH069
	CMPB	#137.,$DICSV	;STOP FOR LOGICAL 'OR' DIRECTIVE?	;MSH069
	BNE	50$		;IF NE NO, DON'T STOP TASK		;MSH069
									;MSH069
	.IFTF								;MSH069
									;MSH069
27$:				;REF LABEL				;MSH069
									;MSH069
	.IFT								;MSH069
									;MSH069
	BIS	#T2.SEF      ,(R2)	;PUT TASK IN STOPFOR STATE		;MSH069
									;MSH069
	.ENDC	;S$$TOP							;MSH069

;+
; **-$DRWFD-WAITFOR SINGLE EVENT FLAG FOR DIRECTIVE			;MSH194
; **-$DRWFS-WAITFOR SINGLE EVENT FLAG (NON-EXEC COMMON SYSTEM ONLY)	;MSH194
;									;**-1
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SUSPEND THE EXECUTION OF THE
; ISSUING TASK UNTIL A SPECIFIED EVENT FLAG IS SET.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(41.),DPB SIZE(2.).
;	WD. 01 -- EVENT FLAG NUMBER OF FLAG TO WAITFOR.
;
; INPUTS:
;
;	R0=EVEN      T FLAG MASK WORD.
;	R1=EVENT FLAG MASK ADDRESS.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF +1.
;-

$DRWFD::			;REF LABEL				;MSH194
									;MSH194
	.IF DF	M$$NET							;MSH194
	.IF NDF	D$$PAR							;MSH194
									;MSH194
$DRWFS::			;REF LABEL
				      					;MSH194
	.ENDC								;MSH194
	.ENDC								;MSH194

	.IF DF G$$EFN

	BIC	#1,R1		;CLR GRP GLOBAL 2ND WORD INDICATOR	;MSH049
									;**-7
	.ENDC	;G$$EFN

50$:	BIS	#T2.WFR,T.ST2(R5) ;PUT TASK IN WAIT FOR STATE		;MSH061
									;MSH069
	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
	MOV	R0,T.EFLM(R5)	;SET WAITFOR MASK			;MSH069
	MOV	R1,T.EFLM+2(R5)	;SET WAITFOR MASK ADDRESS		;MSH069
									;MSH069
	.IFF								;MSH069
									;MSH069
	MOV	R0,H.EFLM(R4)	;SET WAITFOR MASK WORD	   ´   		;**-1
	MOV	R1,H.EFLM+2(R4)	;SET WAITFOR MASK ADDRESS
									;MSH069
	.ENDC								;MSH069
									;MSH069
	CALLR	$SETRT		;SET A SCHEDULE REQUEST
	.DSABLE LSB

	.END
 ´          ”.ðskQ	› c,        	.TITLE	GRDRV
	.IDENT	/03.02/
 
;
; COPYRIGHT (C) 1976, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VT11/VS60 DISPLAY PROCESSOR DRIVER
;
; VERSION 01
;
; NOTE:	THIS IS A SINGLE CONTROLLER DRIVER
;
; WRITTEN  BY HANK MAURER 13-JUL-75
;
; PREVIOUSLY MODIFIED BY:
;
;	E. L. BAATZ
;	H. MAURER
;
; MODIFIED BY:
;
;	HANK MAURER 11-JUN-78
;	HM002 -- CORR      ECT DPUERR MACRO
;
;	HANK MAURER 11-JUN-78
;	HM003 -- MOVE TRACKING CROSS ONLY WHEN TIP SWITCH IS ON
;
;	ERIC BAATZ 20-JAN-79
;	EB189 -- SET PS.NSF WHEN CONNECTING
;										;**NEW**
; EQUATED SYMBOLS
;
 
	DNR=20			;DPU NAME REGISTER
	DOS=36			;DPU OFFSET SIGN REGISTER
	BFHDR=52.		;DISPLAY BUFFER HEADER SIZE
	NAMSIZ=18.		;NAME LIST SIZE
	DPC=172000		;DPU PROGRAM COUNTER ADDRESS
	DSR=2			;DPU STATUS REGISTER
	DRB=10			;DPU RELOCATION REGISTER
	DSRX=12			;DPU EXTENDED STATUS REGISTER
	DST=      26			;DPU STACK READ REGISTER
	DSP=32			;DPU STACK POINTER
	DCS=22			;DPU CONSOLE STATUS REGISTER
	DJSR=173400		;DPU JSR INSTRUCTION
	DJMPA=160000		;DPU JMP INSTRUCTION
	DJMP=173500		;DPU JMP RELATIVE INSTRUCTION
	DHALT=173400		;DPU HALT AND INTERRUPT
	LSRA=170000		;DPU LOAD STATUS REGISTER A
	LPINT=200		;DPU INTENSIFY LP HITS
	NOITAL=40		;DPU NON-ITALICS
	LINE0=4			;DPU SOLID LINE TYPE
	EXTSTP=200		;DPU EXTERNAL STOP BIT (VS60)
	LVECT=110000		;DPU LONG VECTOR INSTRUCTION
	NBLINK=20		;DPU BLINK       OFF
	MINUS=20000		;DPU LONG VECTOR SIGN BIT
	POINT=114000		;DPU ABSOLUTE POINT INSTRUCTION
	LPOFF=100		;DPU LIGHT PEN INTERRUPT OFF
	BLINK=30		;DPU BLINK ON
	INT3=2600		;DPU INTENSITY LEVEL 3
	CHAR=100000		;DPU CHARACTER MODE
	NOMENU=2		;DPU MENU OFF
	OFFSET=10000		;DPU SET OFFSET MODE BIT
	S1=164000		;DPU SELECT SCOPE 1
	S2=164400		;DPU SELECT SCOPE 2
	SON=300			;DPU TURN SCOPE ON (INTENSIFY)
	SOFF=200		;DPU TYURN SCOPE OFF
	TIPION=14		;DPU TURN ON TIP SWITCH INTERRUPTS
	LPIOFF=40		;DPU TURN       LIGHT PEN INTERRUPTS OFF
	LSRC=154000		;DPU LOAD STATUS REGISTER C
	CROFF=1000		;DPU TURN CHARACTER ROTATE OFF
	CSNORM=240		;DPU CHARACTER SCALE NORMAL
	VSNORM=24		;DPU VECTOR SCALE NORMAL
	SRESET=40		;DPU STACK POINTER RESET
	LP0=40000		;DPU LIGHT PEN INTERRUPT FOR SCOPE 1
	TON0=20000		;DPU TIP SWITCH ON FOR SCOPE 1
	TOFF0=10000		;DPU TIP SWITCH OFF FOR SCOPE 1
	LP1=400			;DPU LIGHT PEN INTERRUPT FOR SCOPE 2
	TON1=200		;DPU TIP SWITCH ON FOR SCOPE 2
	TOFF1=100		;DPU TIP SWITCH OFF FOR SCOPE 2
       
;
; LOCAL DATA  *** WARNING *** THE ORDER OF THE LOCAL DATA IS FIXED
;
 
 
	.IF DF	V$$S60
	
GR.PC:	.WORD	0		;DPU PROGRAM COUNTER ADDRESS
LOCAL:				;REFERENCE TAG
BUFST:	.WORD	0		;DISPLAY BUFFER
 
	.IF DF	M$$MGE
 
BUFRB:	.WORD	0		;DISPLAY BUFFER RELOCATION BIAS
BUFDB:	.WORD	0		;DISPLAY BUFFER DIB
TASRB:	.WORD	0		;EQUIVALENT TASK RELOCATION BIAS
DPCFIX:	.WORD	0		;LOW 16 BITS OF PHYSICAL TASK ORIGIN
				; (FOR FUDGING DPC ON LP)
	
	.ENDC
 
	.IFF
 
GRSTK:	.BLKW	16.		;DPU JSR STACK
	
      	.IF DF	M$$MGE
 
TASK0:	.WORD	0		;PHYSICAL ADDRESS OF USER VIRTUAL 0
				; (FOR RELOCATION)
	
	.IFTF
 
GR.PC:	.WORD	0		;DPU PROGRAM COUNTER
GR.SP:	.WORD	GRSTK		;DPU STACK POINTER
LOCAL:				;REFERENCE TAG
 
	.IFT
 
BUFRB:	.WORD	0		;RELOCATION BIAS FOR DISPLAY BUFFER
 
	.IFTF
 
BUFST:	.WORD	0		;PHYSICAL ADDRESS OF DISPLAY BUFFER
BUFSZ:	.WORD	0		;SIZE OF DISPLAY BUFFER IN BYTES
 
	.IFT
 
BUFDB:	.WORD	0		;DISPLAY BUFFER DIB (FOR SAR6)
 
	.ENDC
 
	.IFTF			; DF V$$S60
	
 
	.IF DF	A$$T      RP
 
LPAST:	.WORD	0		;LIGHT PEN AST VIRTUAL ADDRESS
 
	.ENDC
 
EFNAD:	.WORD	0		;EVENT FLAG ADDRESS WORD
EFNMK:	.WORD	0		;EVENT FLAG MASK WORD (FOR LP HITS)
CONTK:	.WORD	0		;TCB ADDRESS OF CONNECTED TASK
FRKIP:	.WORD	0		;LP FORK IN PROGRESS
TIP1:	.WORD	0		;TIP SWITCH 1 STATUS
 
	.IF DF	V$$S2S
	
TIP2:	.WORD	0		;TIP SWITCH 2 STATUS
LPFLAG:	.WORD	0		;SCOPE 1 OR 2 FLAG ON LP HIT
 
	.ENDC
 
HLTFLG:	.WORD	100001		;LEAVE DPU HALTED FLAG
 
;
; DELAY IN CASE THE USER'S DISPLAY LIST IS VERY SHORT      
;
 
DELAY:	.WORD	POINT+LPOFF+NBLINK+INT3+LINE0
 
	.IFT			; DF V$$S60
	
	.WORD	OFFSET,0
	
	.IFTF
 
	.WORD	1023.,1023.
	.WORD	LVECT
	.WORD	MINUS+1023.,MINUS+1023.
 
	.IFT
 
	.WORD	1023.,1023.,MINUS+1023.,MINUS+1023.
	.WORD	1023.,1023.,MINUS+1023.,MINUS+1023.
	.WORD	1023.,1023.,MINUS+1023.,MINUS+1023.
 
	.IFTF
 
	.WORD	CHAR
	.BYTE	17,17
	.WORD	LSRA+LPINT+NOITAL+NOMENU
 
	.IFT
 
	.WORD	S1+SON+LPIOFF+TIPION
	.WORD	S2+SOFF+LPIOFF+TIPION
	.WORD	LSRC+CROFF+CSNORM+VSNORM
 
	.IF DF	M      $$MGE
 
DSTART:	.WORD	DHALT,0
 
	.IFF
 
DSTART:	DJMPA,0
 
	.ENDC
 
	.IFF
 
DSTART:	.WORD	DJMPA,0
 
	.ENDC			; DF V$$S60
 
;
; COUNT LIGHT PEN INTERRUPTS THAT ARE NOT LIGHT PEN INTERRUPTS
;
 
LPERRS:	.WORD	0		;
	
;
; DRIVER DISPATCH TABLE
;
 
$GRTBL::.WORD	GRCHK		;DEVICE INITIATOR ENTRY POINT
	.WORD	GRCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	GROUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	GRPWF		;POWERFAIL ENTRY POINT
 
 
;
; MACRO DEFINITIONS
;
 
	.MACRO	DPUERR	TEXT,?X
	M      OV	#X,DSTART+2
	BR	90$
X:	.WORD	CHAR
	.ASCII	"TEXT"
	.EVEN
	.WORD	DJMPA,DELAY
	.ENDM
;+
; **-GRCHK-VT11/VS60 DISPLAY PROCESSOR PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O
; REQUEST IS RECEIVED FOR THE VT11/VS60 DISPLAY PROCESSOR.
; VT11/VS60 I/O REQUESTS CONTAIN DEVICE DEPENDENT INFORMA-
; ATION THAT MUST BE CHECKED IN THE CONTEXT OF THE ISSUING TASK.
; THEREFORE THE I/O REQUEST IS NOT QUEUED BEFORE CALLING THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS       OF THE I/O REQUEST PACKET.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	DEPENDENT UPON FUNCTION TO BE PERFORMED.
;
; VT11/VS60 FUNCTION INDEPENDENT I/O PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UC      B).
;	WD. 05 -- I/O FUNCTION CODE .
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;-
 
GRCHK:	MOV	R1,-(SP)	;SAVE I/O PACKET ADDRESS
	MOV	I.FCN(R1),R2	;GET I/O FUNCTION CODE
	MOV	I.PRM(R1),R0	;GET VIRTUAL BUFFER ADDRESS (IF IO.CON)
	MOV	I.TCB(R1),R1	;GET REQUESTING TASK'S TCB ADDRESS
	CMP	R2,#IO.CON	;CONNECT ?
	BEQ	GRCON		;Y      ES
	CMP	R1,CONTK	;IS THE REQUESTING TASK CONNECTED ?
	BNE	GRNCN		;NO, IT CAN'T REQUEST THINGS
	CMP	R2,#IO.STP	;STOP ?
	BEQ	GRSTP		;YES
	CMP	R2,#IO.DIS	;DISCONNECT ?
	BEQ	GRDIS		;YES
	BR	GRCNT		;NO, CONTINUE
;+
; **-GRSTP-STOP VT11/VS60 (SO USER CAN MODIFY HIS DISPLAY BUFFER)
;
; FUNCTION DEPENDENT IO PACKET FORMAT:
;
;	WD. 12 -- NOT USED
;	WD. 13 -- NOT USED
;	WD. 14 -- NOT USED
;	WD. 15 -- NOT USED
;	WD. 16 -- NOT USED
;	WD. 17 -- NOT USED
;	WD. 20 -- NOT USED
;-
 
GRSTP:	CALL	GRHLT	      	;HALT DPU
	BR	GRSUC		;TAKE COMMON SUCCESS EXIT
;+
; **-GRCON-CONNECT DISPLAY BUFFER TO DRIVER
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- USER VIRTUAL ADDRESS OF DISPLAY BUFFER.
;	WD. 13 -- SIZE OF DISPLAY BUFFER IN BYTES.
;	WD. 14 -- LIGHT PEN HIT TRIGGER EVENT FLAG.
;	WD. 15 -- LIGHT PEN AST ADDRESS.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
GRCON:	TST	CONTK		;ANOTHER TASK ALREADY CONNECTED?
	BNE	GRNCN		;IF NE YES
	MOV	#LOCAL,R3	;SET UP       POINTER TO LOCAL DATA BASE
	BIT	#1,R0		;IS VIRTUAL BUFFER ADDRESS ODD ?
	BNE	GRSPC		;YES, ILLEGAL
 
	.IF DF	V$$S60
	
	MOV	R0,(R3)+	;SAVE BUFFER ADDRESS
 
	.IF DF	M$$MGE
 
	CALL	$RELOC		;MAP BUFFER ADDRESS
	MOV	R1,(R3)+	;SAVE RELOCATION BIAS
	MOV	R2,(R3)+	;AND DIB
	ASR	R0		;GET RB OF BUFFER VIRTUAL ADDRESS
	ASR	R0
	ASR	R0
	ASR	R0
	ASR	R0
	ASR	R0
	BIC	#176000,R0	;CLEAN IT OFF
	SUB	R0,R1		;GET EQUIVALENT RB OF TASK 0
	MOV	R1,(R3)+	;AND SAVE IT
	ASL	R1		;GET LOW 16 BITS OF PHYSICAL
	ASL	R      1		; START OF TASK ADDRESS
	ASL	R1
	ASL	R1
	ASL	R1
	ASL	R1
	MOV	R1,(R3)+	;SAVE IT
 
	.IFF
 
	MOV	R0,DSTART+2	;PUT BUFFER ADDRESS INTO STARTER
	ADD	#BFHDR,DSTART+2	;SKIPPING HEADER
 
	.ENDC
 
	MOV	(SP),R1		;RESTORE PACKET POINTER
	ADD	#I.PRM+4,R1	;POINT TO LIGHT PEN EFN PARAMETER
 
	.IFF
 
	.IF DF	M$$MGE
 
	CALL	$RELOC		;MAP BUFFER ADDRESS
	MOV	R1,(R3)+	;SAVE RELOCATION BIAS
	MOV	R2,R4		;SAVE DIB FOR BUFFER
	CALL	$MPPHY		;MAP INTO PHYSICAL ADDRESS (2 WORDS)
	MOV	R2,(R3)		;SAVE LOW 16       BITS OF PHYSICAL ADDRESS
	MOV	(R3)+,DSTART+2	;PHYSICAL BUFFER ADDRESS TO STARTER
	ADD	#BFHDR,DSTART+2	;SKIPPING HEADER
	SUB	R2,R0		;VIRTUAL-PHYSICAL BUFFER ADDRESS
	NEG	R0		;PHYSICAL-VIRTUAL (TO RELOCATE DJSR, DJMP)
	MOV	R0,TASK0	;SAVE IT
	TST	R1		;ANY HIGH ORDER PHYSICAL ADDR. BITS ?
	BNE	GRSPC		;YES, BUFFER OUT OF 32K
 
	.IFF
 
	MOV	R0,(R3)+	;SAVE BUFFER ADDRESS
	MOV	R0,DSTART+2	;PHYSICAL ADDRESS TO STARTER
	ADD	#BFHDR,DSTART+2	;SKIPPING HEADER
 
	.IFTF
 
	MOV	(SP),R1		;RESTORE PACKET PO      INTER
	ADD	#I.PRM+2,R1	;POINT TO BUFFER SIZE PARAMETER
 
	.IFT
 
	MOV	(R1)+,(R3)	;SAVE SIZE
	ADD	(R3)+,R2	;GET ADDRESS OF BUFFER END
	BCS	GRSPC		;END IS OUT OF 32K
	CMP	R2,#160000	;ABOVE 28K ?
	BHIS	GRSPC		;YES, ERROR
	MOV	R4,(R3)+	;SAVE DIB FOR BUFFER START (SAR6)
 
	.IFF
 
	MOV	(R1)+,(R3)+	;SAVE SIZE
 
	.ENDC
 
	.ENDC			; DF V$$S60
	
	MOV	(R1)+,R0	;GET LP TRIGGER EFN
	BEQ	GRIEF		;ZERO IS ILLEGAL
	CMP	R0,#64.		;CHECK AGAINST MAX
	BGT	GRIEF		;>64 IS ILLEGAL
	MOV	R5,-(SP)	;SAVE UCB AD      DRESS
 
	.IF DF	A$$TRP
 
	MOV	(R1),(R3)+	;SAVE AST ADDRESS
 
	.ENDC
 
	MOV	I.TCB-I.PRM-6(R1),R5 ;GET CONNECTING TASK'S TCB ADDRESS
	CALL	$CEFI		;CONVERT EFN TO MASK AND POINTER
	MOV	R1,(R3)+	;SAVE EFN ADDRESS
	MOV	R0,(R3)+	;SAVE EFN MASK
	BIC	R0,(R1)		;CLEAR THE USER'S EVENT FLAG
	INCB	T.IOC(R5)	;INCREMENT IO PENDING COUNT
	MOV	R5,(R3)		;CONNECT TASK TO DRIVER
	MOV	T.PCB(R5),R5	;GET TASK'S PCB ADDRESS
	BIS	#PS.NSF,P.STAT(R5) ;DISABLE SHUFFLING
	MOV	(SP)+,R5	;RESTORE UCB ADDRESS
;+
; **-G      RCNT-CONTINUE AFTER STOP
;
; FUNCTION DEPENDENT IO PACKET FORMAT:
;
;	WD. 12 -- NOT USED.
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
GRCNT:	TST	HLTFLG		;IS DISPLAY RUNNING ?
	BEQ	GRSUC		;YES
 
	.IF DF	V$$S60
	
	MOV	GR.PC,R0	;GET DPU PC ADDRESS
	MOV	#SRESET,DSP(R0)	;RESET DPU STACK
 
	.IF DF	M$$MGE
 
	CLR	DRB(R0)		;CLEAR RELOCATION BIAS
 
	.ENDC
 
	CLR	HLTFLG		;CLEAR HALT FLAG
	MOV	#DELAY      ,(R0)	;START UP THE DISPLAY
 
	.IFF
 
	MOV	#GRSTK,GR.SP	;RESET DPU STACK
	CLR	HLTFLG		;CLEAR HALT FLAG
	MOV	#DELAY,@GR.PC	;START UP THE DISPLAY
 
	.ENDC
 
 
	BR	GRSUC		;TAKE COMMON EXIT
 
;+
; **-GRDIS-DISCONNECT TASK FROM DRIVER
;
; FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- NOT USED.
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
GRDIS:	CALL	GRCAN		;DISCONNECT TASK FROM DRIVER
	BR      	GRSUC		;TAKE COMMON EXIT
;
; EXITS FROM VT11/VS60 DRIVER
;
;
; ILLEGAL CONNECT/DISCONNECT TO/FROM DRIVER
;
 
GRNCN:	MOV	#IE.CNR&377,R0	;SET CONNECT REFUSED STATUS
	BR	GRCMN		;BUT DON'T DISTURB THE DISPLAY
 
;
; ILLEGAL EVENT FLAG NUMBER
;
 
GRIEF:	MOV	#IE.IEF&377,R0	;SET ILLEGAL EVENT FLAG STATUS
	BR	GRCMN		;
 
;
; ILLEGAL BUFFER SPECIFICATION
;
 
GRSPC:	MOV	#IE.SPC&377,R0	;SET ILLEGAL BUFFER STATUS
	BR	GRCMN		;TAKE COMMON EXIT
 
;
; SUCCESSFUL COMPLETION
;
 
GRSUC:	MOV	#IS.SU      C&377,R0	;SET SUCCESSFUL COMPLETION STATUS
 
;
; COMMON FUNCTION EXIT
;
 
GRCMN:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
	MOV	(SP)+,R3	;RETRIEVE I/O PACKET ADDRESS
	CALLR	$IOFIN		;FINISH I/O OPERATION
;
; CANCEL I/O OPERATION
;
; THIS ROUTINE IS CALLED TO CANCEL ALL I/O IN PROGRESS FOR THE CURRENT
; TASK. IF THE TASK IS CONNECTED TO THE DRIVER, IT WILL BE
; DISCONNECTED AND THE DPU WILL BE SET TO THE IDLE DISPLAY.
;
; INPUTS:
;
;	R1=ADDRESS OF TCB OF CURRENT TASK
;	R4=ADDRESS OF SCB
;	R5=      ADDRESS OF UCB
;
 
GRCAN:	MOV	#CONTK,R2	;;;POINT AT LOCAL DATA
	CMP	R1,(R2)		;;;IS THIS THE CONNECTED TASK ?
	BNE	GROUT		;;;NO, DON'T DO ANYTHING
	CLR	(R2)		;;;YES, DISCONNECT IT
	CLR	-(R2)		;;;CLEAR EFN MASK
	CLR	-(R2)		;;;AND ADDRESS IN CASE FORK ALREADY QUEUED
 
	.IF DF	A$$TRP
 
	CLR	-(R2)		;;;AND AST ADDRESS
 
	.ENDC
 
	DECB	T.IOC(R1)	;;;DECREMENT OUTSTANDING I/O COUNT
	MOV	T.PCB(R1),R3	;;;GET TASK'S PCB ADDRESS
	BIC	#PS.NSF,P.STAT(R3) ;;;ENABLE SHUFFLING
	MTPS	#0		;;;ALLOW DEVICE INT      ERRUPTS
 
;
; SUBROUTINE TO HALT DPU
;
; INPUTS:
;
;	R4=ADDRESS OF SCB
;	R5=ADDRESS OF UCB
;
 
GRHLT:	MOV	#HLTFLG,R3	;;;OFT USED
	TST	(R3)		;;;ALREADY HALTED ?
	BNE	30$		;;;YES
	MOV	#1,(R3)		;;;SET THE 'PLEASE HALT' INDICATOR
5$:	MOV	#1000.,-(SP)	;;;PUSH DELAY COUNTER
	MOV	(SP),-(SP)	;;;TWICE
10$:	TST	(R3)		;;;HALTED YET ?
	BMI	20$		;;;YES, EXIT
	DEC	(SP)		;;;INNER COUNTER
	BGT	10$		;;;INNER LOOP
	MOV	2(SP),(SP)	;;;RESTORE INNER COUNTER
	DEC	2(SP)		;;;OUTER COUNTER
	BGT	10$		;;;OUTER       LOOP
	CMP	(SP)+,(SP)+	;;;PURGE DEPLETED COUNTERS
 
	.IF DF	V$$S60
	
	MOV	GR.PC,R2	;;;GET DPC ADDRESS
	BIS	#EXTSTP,DSRX(R2);;;DO AN EXTERNAL STOP
 
	.IFF
 
	MOV	#DELAY,@GR.PC	;;;FORCE DPC AND TRY AGAIN
 
	.ENDC
 
	BR	5$		;;;TRY AGAIN
20$:	CMP	(SP)+,(SP)+	;;;PURGE COUNTERS
30$:	RETURN
;
; POWERFAILURE
;
;
; POWERFAILURE MERELY CAUSES THE DPU TO BE RESTARTED AT THE START OF
; THE DISPLAY BUFFER WITH THE DPU STACK RESET.
;
; INPUTS:
;
;	R3=ADDRESS OF CONTROLLER INDEX (ALWAYS ZERO)
;	      R4=ADDRESS OF SCB
;	R5=ADDRESS OF UCB
;
 
 
GRPWF:	MOV	S.CSR(R4),R2	;;;GET VT11/VS60 DPC ADDRESS
	MOV	R2,GR.PC	;;;SAVE DPC ADDRESS
 
	.IF DF	V$$S60
	
	MOV	#SRESET,DSP(R2) ;;;RESET THE DPU STACK
	CLR	DRB(R2)		;;;CLEAR THE DPU RB
 
	.IFF
 
	MOV	#GRSTK,GR.SP	;;;SET UP THE STACK POINTER
 
	.ENDC
 
	TST	HLTFLG		;;;SHOULD DISPLAY REMAIN HALTED ?
	BNE	GROUT		;;;YES
	MOV	#DELAY,(R2)	;;;NO, START IT UP
 
;
; DEVICE TIMEOUT
;
; DEVICE TIMEOUT CANNOT OCCUR SINCE THE TIMEOUT COUNT IS NEVER SET      .
;
 
GROUT:	RETURN			;;;
;
; BUS-ERROR / SHIFT-OUT INTERRUPT
;
; A BUS ERROR OCCURS WHEN THE DPU ATTEMPTS TO EXECUTE DISPLAY
; INSTRUCTIONS FROM NON-EXISTENT MEMORY.  A SHIFT OUT INTERRUPT OCCURS
; WHEN A CHARACTER >40(8) IS ENCOUNTERED WHILE IN THE SHIFT OUT MODE.
; IN EITHER CASE, MERELY RESTART THE DPU AT THE BEGINNING OF THE BUFFER
;
 
	.IF DF	V$$S60
$GRBSE::
	.ENDC
;
; DPU STOP INTERRUPT
;
; THE DPU STOP INTERRUPT OCCURS IN THE VT11 ON EITHER A DJSR, DJMP,
; OR DRET PSEUDO INSTRU      CTION.  IN EACH CASE THE INTERRUPT HANDLER
; PERFORMS THE NECESSARY FUNCTIONS.  FOR THE VS60, IT OCCURS ONLY
; AT THE END OF THE DELAY LIST AND AT THE END OF THE DISPLAY LIST
;
 
$GRSTP::CALL	$INTSV,PR4	;;;START INTERRUPT ROUTINE
 
	.IF DF	V$$S60
	
	MOV	GR.PC,R4	;;;GET THE DPC ADDRESS
 
	.IF DF	M$$MGE
 
	TST	DRB(R4)		;;;END OF DELAY OR LIST ?
	BNE	10$		;;;END OF MAIN LIST
	MOV	#SRESET,DSP(R4)	;;;RESET DPU STACK
	MOV	TASRB,DRB(R4)	;;;GET EQUIVALENT RB FOR MAIN LIST
	MOV	BUFST,R5	;;;ADDRESS O      F USER'S SPACE
	ADD	#BFHDR,R5	;;;PLUS HEADER SIZE
	MOV	R5,(R4)		;;;START IN USER'S LIST
	RETURN			;;;EXIT FROM INTERRUPT
10$:	CLR	DRB(R4)		;;;CLEAR DPU RB
	TST	HLTFLG		;;;SHOULD WE REMAIN HALTED ?
	BEQ	20$		;;;NO
	BIS	#100000,HLTFLG	;;;YES, SET INDICATOR THAT WE SUCCEEDED
	RETURN			;;;EXIT FROM INTERRUPT
20$:	MOV	#DELAY,(R4)	;;;START DPU IN DELAY LIST
	RETURN			;;;EXIT FROM INTERRUPT
	
	.IFF
 
	MOV	#SRESET,DSP(R4)	;;;RESET DPU STACK
	TST	HLTFLG		;;;REMAIN HALTED ?
	BEQ	20$		;;;NO
	BIS	#1000      00,HLTFLG	;;;YES, SET SUCCESS BIT
	RETURN			;;;EXIT FROM INTERRUPT
20$:	MOV	#DELAY,(R4)	;;;RESTART IN DELAY LIST
	RETURN			;;;EXIT FROM INTERRUPT
	
	.ENDC
 
	.IFF			;;; DF V$$S60
	
	MOV	R2,-(SP)	;;;SAVE ADDITIONAL REGISTERS
	MOV	R3,-(SP)
	MOV	#GR.PC,R4	;;;POINT AT LOCAL DATA BASE
	MOV	(R4)+,R2	;;;GET DPC ADDRESS
	MOV	(R4)+,R3	;;;GET DPU STACK POINTER
 
	.IF DF	M$$MGE
 
	MOV	KISAR6,-(SP)	;;;SAVE SAR6
	MOV	(R4)+,KISAR6	;;;AND SET UP FOR USER'S BUFFER
 
	.IFTF
 
	MOV	(R2),R5		;;;GET PHYSI      CAL ADDRESS OF DHALT +2
	SUB	(R4)+,R5	;;;SUBTRACT PHYSICAL START OF BUFFER
	BCS	70$		;;;UNDER BUFFER
	CMP	(R4)+,R5	;;;COMPARE WITH MAX BUFFER SIZE
	BLO	70$		;;;ABOVE BUFFER
 
	.IFT
 
	ADD	(R4)+,R5	;;;ADD DIB
10$:	CMP	R5,#157700	;;;AT THE END OF THE SAR ?
	BLOS	15$		;;;NO, WE'RE IN RANGE
	SUB	#17700,R5	;;;MOVE IT UP BY ABOUT 4000. WDS
	ADD	#177,KISAR6	;;;AND ALSO FIX THE RB
	BR	10$		;;;TEST AGAIN
15$:
 
	.IFF
 
	MOV	(R2),R5		;;;RESTORE ADDRESS OF DHALT+2
 
	.IFTF
 
	MOV	-2(R5),R4	;;;GET       PSEUDO INSTRUCTION
	BIC	#13,R4		;;;IGNORE SPARE BITS
	CMP	R4,#DJSR	;;;DJSR ?
	BNE	80$		;;;NO
	MOV	(R5)+,R4	;;;GET RETURN ADDRESS
	BEQ	40$		;;;0 MEANS DRET
	CMP	#GRSTK+32.,R3	;;;FULL STACK ?
	BLOS	50$		;;;YES
	MOV	(R2),(R3)+	;;;PUSH PHYSICAL ADDR OF DHALT+2
				;;; FOR LP STUFF
	MOV	R4,(R3)+	;;;PUSH VIRTUAL RETURN ADDRESS
	MOV	(R5)+,R4	;;;GET SUBPICTURE VIRTUAL ADDRESS
17$:
 
	.IFT
 
	ADD	TASK0,R4	;;;MAKE ADDRESS PHYSICAL
 
	.IFTF
 
	MOV	R4,(R2)		;;;JUMP TO ADDRESS AND RESTART DPU
20$:      
 
	.IFT
 
	MOV	(SP)+,KISAR6	;;;RESTORE MAPPING
 
	.ENDC			;;; DF M$$MGE
	
	MOV	R3,GR.SP	;;;SAVE DPU STACK POINTER
	MOV	(SP)+,R3	;;;RESTORE REGS
	MOV	(SP)+,R2	;;;
	RETURN			;;;EXIT FROM INTERRUPT
	
40$:	CMP	R3,#GRSTK	;;;STACK EMPTY ?
	BLOS	90$		;;;YES, RESTART AT THE TOP
	MOV	-(R3),R4	;;;GET VIRTUAL RETURN ADDRESS
	TST	-(R3)		;;;WASTE PHYSICAL ADDR OF DHALT+2
	BR	17$		;;;GO RELOCATE IT AND RESTART THERE
 
50$:	DPUERR	<DPU STACK OVERFLOW>
 
70$:	DPUERR	<DPC OUT OF DISPLAY BUFFER>
 
80$:      	CMP	R4,#DJMP	;;;IS IT A RELATIVE DJMP ?
	BNE	90$		;;;NO, UNKNOWN DHALT
	MOV	(R5),R4		;;;GET ADDRESS
	BR	17$		;;;GO RELOCATE IT AND RESTART THERE
 
90$:	MOV	#GRSTK,R3	;;;UNRECOGNIZED DHALT, RESET STACK
	TST	HLTFLG		;;;REMAIN HALTED ?
	BEQ	100$		;;;NO
	BIS	#100000,HLTFLG	;;;SET SUCCESS BIT
	BR	20$		;;;EXIT
100$:	MOV	#DELAY,(R2)	;;;RESTART DISPLAY AT THE BEGINNING
	BR	20$
 
	.ENDC			;;; DF V$$S60
	.ENABL	LSB
 
60$:				;;;REF LABEL
 
	.IF DF	M$$MGE
 
	MOV	(SP)+,KISAR6	;;;RESTORE MAPPING
       
	.ENDC
 
65$:	INC	(R5)		;;;RESTART DPU
66$:	RETURN			;;;EXIT
67$:	INC	LPERRS		;;;COUNT UNKNOWN INTERRUPTS
	BR	65$		;;;
 
;
; LIGHT PEN INTERRUPT
;
; THE LIGHT PEN SERVICE ROUTINE STORES THE STATUS OF THE DPU AT THE
; LIGHT PEN HIT INTO THE USER'S DISPLAY BUFFER HEADER, SETS THE LIGHT
; PEN TRIGGER EVENT FLAG, AND INITIATES THE AST.
;
 
$GRLPI::CALL	$INTSV,PR4	;;;START INTERRUPT CODE
	MOV	GR.PC,R5	;;;GET DPC ADDRESS
 
	.IF DF	V$$S60
	
	MOV	DCS(R5),R4	;;;GET THE CONSOLE STATUS REG
	BIT	      #TON0,R4	;;;TIP SWITCH FOR SCOPE 1 ON ?
	BEQ	10$		;;;NO
	INC	TIP1		;;;YES, SET FLAG
	BR	65$		;;;EXIT
10$:	BIT	#TOFF0,R4	;;;TIP SWITCH FOR SCOPE 1 OFF ?
	BEQ	15$		;;;NO
	CLR	TIP1		;;;YES, CLEAR FLAG
	BR	65$		;;;EXIT
15$:
 
	.IF DF	V$$S2S
	
	BIT	#TON1,R4	;;;TIP SWITCH FOR SCOPE 2 ON ?
	BEQ	20$		;;;NO
	INC	TIP2		;;;YES SET FLAG
	BR	65$		;;;EXIT
20$:	BIT	#TOFF1,R4	;;;TIP SWITCH FOR SCOPE 2 OFF ?
	BEQ	25$		;;;NO
	CLR	TIP2		;;;YES, CLEAR FLAG
	BR	65$		;;;EXIT
25$:	BIT	#LP0+LP1,R4	;;;LIGHT PEN       INTERRUPT ?
	BEQ	67$		;;;NO, WHAT INTERRUPT ?
	MOV	#1,LPFLAG	;;;YES, SET FLAG
	BIT	#LP1,R4		;;;WAS IT SCOPE 2
	BEQ	30$		;;;NO, MUST HAVE BEEN 1
	INC	LPFLAG		;;;YES, SET FLAG TO 2
30$:
 
	.IFF
 
	BIT	#LP0,R4		;;;LP INTERRUPT ?
	BEQ	67$		;;;NO, WHAT INTERRUPT ?
	
	.ENDC
 
	.ENDC			;;; DF V$$S60
 
	TST	FRKIP		;;;FORK CURRENTLY IN PROGRESS ?
	BNE	65$		;;;YES, FORGET INTERRUPT
	
	.IF DF	M$$MGE
 
	MOV	KISAR6,-(SP)	;;;SAVE SAR6
	MOV	BUFRB,KISAR6	;;;SETUP SAR FOR BUFFER
	MOV	BUFDB,R4	;;;ALSO       DIB
 
	.IFF
 
	MOV	BUFST,R4	;;;GET ADDRESS OF LP STUFF
 
	.IFTF
 
	TST	(R4)+		;;;IS THE LOCK SET ?
	BNE	60$		;;;YES, DON'T CHANGE INFO WHILE ITS BEING READ
	MOV	R4,-(SP)	;;;SAVE NAME LIST  ADDRESS
	ADD	#NAMSIZ,R4	;;;SKIP OVER IT FOR NOW
 
	.IF DF	V$$S60
	
 
	.IF DF	M$$MGE
 
	MOV	(R5)+,(R4)	;;;PUT IN DPC AT HIT
	SUB	DPCFIX,(R4)+	;;;SUBTRACT LOW BITS OF RELOCATION VALUE
 
	.IFF
 
 
	MOV	(R5)+,(R4)+	;;;PUT IN DPC AT HIT
 
	.ENDC
 
	MOV	(R5)+,(R4)+	;;;PUT IN CSR AT HIT
	MOV	(R5)+,(      R4)+	;;;PUT IN X POS AT HIT
	MOV	(R5)+,(R4)+	;;;PUT IN Y POS AT HIT
	TST	(R5)+		;;;SKIP DPU RB
	MOV	(R5)+,(R4)+	;;;COPY EXTENDED STATUS
	MOV	(R5)+,(R4)+	;;;X OFFSET
	MOV	(R5)+,(R4)+	;;;Y OFFSET
	MOV	DOS-DNR(R5),(R4)+ ;;;OFFSET SIGNS
 
	.IFF
 
	.IF DF	M$$MGE
 
	MOV	(R5)+,(R4)	;;;RETRIEVE DPC AT HIT
	SUB	TASK0,(R4)+	;;;CONVERT TO PHYSICAL AND STORE
 
	.IFF
 
	MOV	(R5)+,(R4)+	;;;PUT IN DPC AT HIT
 
	.ENDC
 
	MOV	(R5)+,(R4)+	;;;PUT IN CSR AT HIT
	MOV	(R5)+,(R4)+	;;;PUT IN X POS AT HIT
	MO      V	(R5)+,(R4)+	;;;PUT IN Y POS AT HIT
	CLR	(R4)+		;;;NO EXTENDED STATUS FOR VT11
	CLR	(R4)+		;;;ALSO NO X OFFSET
	CLR	(R4)+		;;;ALSO NO Y OFFSET
	CLR	(R4)+		;;;ALSO NO XY OFFSET SIGNS
 
	.IFTF
 
	MOV	TIP1,(R4)+	;;;COPY TIP SWITCH 1 STATUS
 
	.IF NDF	V$$S2S
	
	CLR	(R4)+		;;;NO TIP SWITCH 2
	MOV	#1,(R4)		;;;SET LP FLAG
 
	.IFF
 
	MOV	TIP2,(R4)+	;;;COPY TIP SWITCH 2
	MOV	LPFLAG,(R4)	;;;COPY IN LP FLAG
 
	.ENDC
 
	MOV	(SP),R4		;;;RESTORE NAME LIST ADDRESS
	MOV	R3,(SP)		;;;SAVE R3
 
	.IFT      			;;; DF V$$S60
	
	MOV	DSP-DNR(R5),R3	;;;GET CURRENT STACK POINTER
	BIC	#177703,R3	;;;ISOLATE WORD SELECT BITS
	MOV	R3,-(SP)	;;;SAVE 'EM
40$:	CMP	R3,#SRESET	;;;TOP OF STACK ?
	BHIS	45$		;;;YES
	MOV	R3,DSP-DNR(R5)	;;;NO, SELECT THIS LEVEL
	MOV	DST-DNR(R5),(R4)+ ;;;COPY DPC FOR THIS LEVEL
	ADD	#4,R3		;;;MOVE UP ONE LEVEL
	BR	40$		;;;LOOP
45$:	MOV	(SP)+,DSP-DNR(R5) ;;;RESTORE ORIGINAL LEVEL
	
	.IFF
 
	MOV	GR.SP,R3	;;;GET DPU STACK POINTER
40$:	CMP	R3,#GRSTK	;;;AT TOP YET ?
	BLOS	45$		;;;YES
      	TST	-(R3)		;;;SKIP VIRTUAL RETURN ADDRESS
 
	.IF NDF	M$$MGE
 
	MOV	-(R3),(R4)+	;;;POINT TO VIRTUAL RETURN ADDR
 
	.IFF
 
	MOV	-(R3),(R4)	;;;PHYSICAL POINTER TO VRA
	SUB	TASK0,(R4)+	;;;VIRTUAL POINTER TO VRA
 
	.ENDC
 
	BR	40$		;;;LOOP
45$:
 
	.ENDC			;;; DF V$$S60
	
	.ENDC			;;; DF M$$MGE
	
	MOV	(SP)+,R3	;;;RESTORE R3
	MOV	#-2,(R4)	;;;INSERT TERMINATOR
 
	.IF DF	M$$MGE
 
	MOV	(SP)+,KISAR6	;;;RESTORE MAPPING
 
	.IFTF
 
	MOV	#$GRFRK+6,R4	;;;SET ADDRESS OF FORK BLOCK
	MOV	#FRKIP,      R5	;;;POINT AT LOCAL DATA
	INC	(R5)		;;;SET FORK IN PROGRESS FLAG
	INC	@GR.PC		;;;RESTART DPU
	CALL	$FORK1		;;;FORK
 
 
	CLR	(R5)		;CLEAR FORK IN PROGRESS FLAG
	MOV	-(R5),R4	;GET TCB ADDRESS OF CONNECTED TASK
	BIT	#T2.ABO,T.ST2(R4) ;TASK CURRENTLY BEING ABORTED ?
	BNE	66$		;YES, DON'T MEDDLE
	BIS	-(R5),@-(R5)	;SET LIGHT PEN TRIGGER EVENT FLAG
 
	.IF DF	A$$TRP
 
	TST	-(R5)		;AST DEFINED ?
	BEQ	50$		;NO, COOL IT
	BIT	#T2.AST!T2.DST,T.ST2(R4) ;AST IN PROGRESS OR DISABLED ?
	BNE	50$		;YES, DON'      T START ANOTHER (Q MIGHT GET FULL)
	TST	T.ASTL(R4)	;AST QUEUED ALREADY ?
	BNE	50$		;YES, ASSUME ITS OURS AND COOL IT
	MOV	#5*2,R1		;SIZE OF AST CONTROL BLOCK
	CALL	$ALOCB		;ALLOCATE SOME CORE
	BCS	50$		;NONE AVAILABLE, FORGET IT
	MOV	R0,R1		;COPY ADDRESS OF BLOCK
	CLR	(R0)+		;SKIP LINK WORD
	MOV	#5*2,(R0)+	;SAVE BLOCK SIZE
	MOV	#7*2,(R0)+	;SPACE TO ALLOCATE ON USER STACK
	MOV	(R5),(R0)+	;AST ADDRESS
	CLR	(R0)		;NO PARAMETERS
	MOV	R4,R0		;GET TCB ADDRESS
	ADD	#T.ASTL,R0	;MAKE IT POINTER TO AST L      ISTHEAD
	CALL	$QINSF		;INSERT AST IN Q
 
	.ENDC
 
50$:	MOV	R4,R0		;COPY TCB ADDRESS
	CALLR	$SETCR		;REQUEST USER'S TASK
 
	.ENDC			; DF M$$MGE
 
	.DSABL	LSB
;
; BUS-ERROR / SHIFT-OUT INTERRUPT
;
; A BUS ERROR OCCURS WHEN THE DPU ATTEMPTS TO EXECUTE DISPLAY
; INSTRUCTIONS FROM NON-EXISTENT MEMORY.  A SHIFT OUT INTERRUPT OCCURS
; WHEN A CHARACTER >40(8) IS ENCOUNTERED WHILE IN SHIFT OUT MODE.
; IN EITHER CASE, MERELY RESTART THE DPU AT THE BEGINNING OF THE BUFFER
;
 
	.IF DF	V$$T11
 
$G   ¤   RBSE::
	
	MOV	#GRSTK,GR.SP	;;;RESET DPU STACK POINTER
	MOV	#DELAY,@GR.PC	;;;RESTART DISPLAY AT THE BEGINNING
	RTI			;;;INTERRUPT FINISHED
 
	.ENDC
 
	.END
¤          Ô@kQ	› c,        	.TITLE	DRDCP
	.IDENT	/05.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 05.00
;
; D. N. CUTLER 5-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;
; MODIFIED BY:
;
;	T. J. MILLER 6-JUN-77
;
;		TM088 -- CLEAR CHECKPOINT PCB WORD ON DISABLE CHECK-
;			POINTING.
;
;	H. D. COFFMAN	6-NOV-78
;
;		HDC0      21 -- CHECK CHECKPOINTABILITY OF TASKS BEFORE
;			  ENABLING CHECKPOINTING. ENSURE TASKS
;			  CONNECTED TO INTERRUPTS CANNOT BE CHECKPOINTED.
;
;	CHUCK SPITZ	6-MAR-79
;		CS037 -- ALWAYS DEFINE $DRECP AND $DRDCP FOR MCR
;
; DISABLE/ENABLE CHECKPOINTING DIRECTIVES
;
; MACRO LIBRARY CALLS
;

	.MCALL	TCBDF$
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRDCP-DISABLE CHECKPOINTING
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO DISABLE THE CHECKPOINTABILITY
; OF THE ISSUING TASK.
;
; DP      B FORMAT:
;
;	WD. 00 -- DIC(95.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK).
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF CHECKPOINTING
;		      	IS ALREADY DISABLED FOR ISSUING TASK.
;		DIRECTIVE STATUS OF 'D.RS10' IS RETURNED IF THE ISSUING
;			TASK IS NOT CHECKPOINTABLE.
;-


	.IF DF	C$$CKP&D$$ISK

	.ENABL	LSB
$DRDCP::BIT	#T2.CHK,(R2)	;TASK CHECKPOINTABLE?
	BNE	20$		;IF NE NO
	BIT	#T2.CKD,(R2)	;CHECKPOINTING ALREADY DISABLED?
	BNE	30$		;IF NE YES
	BIS	#T2.CKD,(R2)	;DISABLE CHECKPOINTING


	.IF DF	C$$INT

	CLR	T.CPCB(R5)	;CLEAR CHECKPOINT PCB PTR (ICB LISTHEAD)

	.ENDC


10$:	RETURN			;RETURN DIRECTIVE STATUS OF +1
20$:	DRS      TS	D.RS10		;SET DIRECTIVE STATUS

;+
; **-$DRECP-ENABLE CHECKPOINTING
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO ENABLE THE CHECKPOINTABILITY
; OF THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(97.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0       IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF CHECKPOINTING
;		 IS ALREADY DISABLED FOR THE ISSUING TASK  OR
;		  THE ISSUING TASK IS CONNECTED TO INTERRUPTS
;		DIRECTIVE STATUS OF 'D.RS10' IS RETURNED IF THE
;		  ISSUING TASK IS NOT CHECKPOINTABLE.
;
;-
$DRECP::BIT	#T2.CHK,(R2)	;IS TASK CHECKPOINTABLE?
	BNE	20$		;IF NE NO
	BIT	#T2.CKD,(R2)	;CHECKPOINTING DISABLED?
	BEQ	30$		;IF EQ YES      

	.IF DF	C$$INT

	MOV	T.CPCB(R5),R0	;TASK CONNECTED TO INTERRUPTS?
	BNE	30$		;IF NE YES, CANNOT ENABLE CHECKPOINTING

	.ENDC	;C$$INT

	BIC	#T2.CKD,(R2)	;ENABLE CHECKPOINTING
	MOV	T.PCB(R5),R0	;GET ADDRESS OF TASK PARTITION PCB
	CALLR	$NXTSK		;REASSIGN PARTITION IF NECESSARY
30$:	DRSTS	D.RS8		;SET DIRECTIVE STATUS
	.DSABL	LSB

	.IFF	;C$$CKP&D$$ISK

	.IF DF M$$CRX

$DRECP::
$DRDCP::RETURN		;IF NO CHECKPOINTING, JUST RETURN FOR MCR

	.ENDC	;M$$CRX

	.ENDC	;C$$CKP&D$$ISK



	.END
           ¼z�kQ	› c,        	.TITLE	SYTAB
	.IDENT	/10.11/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 10.11
;
; H. LEV 23-AUG-75
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	13-AUG-79
;		MSH042 -- ADD TASK IMAGE SIZE WORD TO LOADER TCB
;
;	M. S. HARVEY	13-AUG-79
;		MS      H046 -- ADD BUFFERED I/O COUNT BYTE TO LOADER TCB
;
;	M. S. HARVEY	9-OCT-79
;		MSH069 -- ADD EVENT FLAG MASK AND MASK ADDRESS WORDS
;			  TO THE LOADER'S TCB
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	29-APR-80
;		MSH096 -- ADD ALTERNATE HEADER REFRESH AREA SUPPORT
;
;	M. S. HARVEY	14-SEP-81
;		MSH190 -- ADD ALTERNATE CLI CONDITIONALIZATION TO THE
;			  GROUP GLOBAL CONTEXT BYTE
;
; SYSTEM TABLES NEEDED TO BOO      TSTRAP SYSTEM AND FOR RESIDENT TASKS
;
; MACRO LIBRARY CALLS
;


	.IF NDF	L$$LDR&R$$11S

	.MCALL	HWDDF$,PCBDF$,TCBDF$
	HWDDF$			; DEFINE HARDWARE REGISTERS
	PCBDF$
	TCBDF$			; DEFINE TASK CONTROL BLOCK OFFSETS

;
; LOCAL DATA
;
; LOADER TASK HEADER
;

.LDRHD::.BLKW	1		;H.CSP-CURRENT STACK POINTER
	.WORD	$PCBS-.LDRHD	;H.HDLN-HEADER LENGTH IN BYTES
	.BLKW	2		;H.EFLM-EVENT FLAG MASK WORD AND ADDRESS
	.BYTE	1,1		;H.CUIC-CURRENT TASK UIC
	.BYTE	1,1		;H.DUIC-DEFAULT TASK UIC


	.IF DF	M$      $MGE

	.WORD	170000		;H.IPS-INITIAL PROCESSOR STATUS WORD

	.IFF

	.WORD	0		;H.IPS-INITIAL PROCESSOR STATUS WORD

	.IFTF

	.WORD	$LOADR		;H.IPC-INITIAL PROGRAM COUNTER
	.WORD	20$		;H.ISP-INITIAL STACK POINTER
10$:	.WORD	1		;H.ODVA-NUMBER OF WINDOW BLOCKS
	.WORD	$PCBS		;H.ODVL-W.BPCB-PARTITION CNTRL BLK ADDR
	.WORD	2		;H.TKVA-W.BLVR-LOW VIRTUAL ADDRESS
	.WORD	117777		;H.TKVL-W.BHVR-HIGH VIRTUAL ADDRESS
	.BLKW	1		;H.PFVA-W.BATT-ATTACHMENT DESCR ADDRESS
	.BLKW	1		;H.FPVA-W.BSIZ-WINDOW SIZE
	.      BLKW	1		;H.RCVA-W.BOFF-OFFSET IN PARTITION
	.BYTE	UISDR5		;H.EFSV-W.BFPD-FIRST USER PDR
	.BYTE	1		;H.EFSV+1-W.BNPD-NUMBER OF PDR'S
	.WORD	0		;H.FPSA-W.BLPD-CONTENTS OF LAST PDR
	.WORD	10$		;H.WND-POINTER TO NUMBER OF WINDOW BLKS
	.BLKW	1		;H.DSW-DIRECTIVE STATUS WORD
	.BLKW	9.		;H.FCS THRU H.GARD-2-LOADER'S STACK
20$:	.WORD	30$		;H.GARD-POINTER TO HEADER GUARD WORD
	.WORD	1		;H.NLUN-NUMBER OF LUNS
	.WORD	.SY0		;UCB POINTER FOR FIRST LUN
	.WORD	0		;WINDOW POINTER FOR FIRST LUN

	.IFT

	.BLKW	4	      	;SAVE AREA FOR R4,R5,PC,PS

	.IFTF

	.BLKW	4		;SAVE AREA FOR R0,R1,R2,R3
30$:	.WORD	0		;HEADER GUARD WORD

;
; LOADER PARTITION CONTROL BLOCK
;

$PCBS::	.WORD	0		;P.LNK-LINK TO NEXT PARTITION PCB
	.BYTE	248.		;P.PRI-PRIORITY
	.BYTE	0		;P.IOC-I/O COUNT
	.RAD50	/LDR/		;P.NAM-FIRST WORD OF PARTITION NAME
	.WORD	0		;P.NAM+2-SECOND WORD OF PARTITION NAME
	.WORD	0		;P.SUB-SUBPARTITION LINK
	.WORD	$PCBS		;P.MAIN-LINK TO MAIN PARTITION

	.IFT

	.WORD	0		;P.REL-RELOCATION BIAS OF PARTITION

	      .IFF

	.WORD	.LDRHD		;P.HDR-POINTER TO LOADER HEADER

	.IFTF

	.BLKW	4		;P.SIZE THRU P.BUSY-UNUSED
	.WORD	$STD		;P.TCB-LOADER TCB ADDRESS
	.WORD	0		;P.STAT-PARTITION STATUS

	.IFT

	.WORD	.LDRHD		;P.HDR-POINT TO LOADER TASK HEADER

	.ENDC


;
; LOADER TASK CONTROL BLOCK
;

$STD::				;START OF TASK LIST
.LDR::	.WORD	0		;T.LNK-UTILITY LINK WORD
	.BYTE	248.		;T.PRI-TASK PRIORITY
	.BYTE	0		;T.IOC-TASK I/O COUNT
	.WORD	$STD		;T.TCB-POINTER TO THIS TCB
	.RAD50	/. LDR./	;T.NAM-TASK NAME
      	.WORD	0,.-2		;T.RCVL-RECEIVE LISTHEAD
	.WORD	0,.-2		;T.ASTL-AST QUEUE LISTHEAD
	.WORD	0,0		;T.EFLG-TASK LOCAL EVENT FLAGS
	.WORD	0		;T.UCB-TI UCB ADDRESS
	.WORD	$HEADR		;T.TCBL-TASK LIST THREAD WORD
	.WORD	TS.EXE		;T.STAT-BLOCKING BITS
	.WORD	T2.CHK!T2.FXD	;T.ST2-STATE BITS
	.WORD	T3.PRV!T3.NSD	;T.ST3-ATTRIBUTE BITS
	.BYTE	248.		;T.DPRI-NONRESIDENT PARTITION COUNTER
	.BLKB	3		;T.LBN-LBN OF TASK IMAGE
	.WORD	.LB0		;T.LDV-LOAD DEVICE UCB
	.WORD	$PCBS		;T.PCB-TASK PCB ADDRESS
	.WORD	0		;T.MXSZ-MAX      IMUM SIZE OF TASK IMAGE
	.WORD	0		;T.ACTL-ACTIVE TASK LIST THREAD
	.WORD	0		;T.SAST-SPECIFIED AST LISTHEAD		;MSH046
	.BYTE	0		; UNUSED BYTE				;MSH046
	.BYTE	0		;T.TIO-BUFFERED I/O COUNT		;MSH046
	.WORD	0		;T.TKSZ-TASK IMAGE SIZE			;MSH042
									;**-1
	.IF DF	P$$LAS

	.WORD	0,.-2		;T.ATT-ATTACHMENT DESCRIPTOR LISTHEAD
	.WORD	0		;T.OFF-OFFSET IN TASK PARTITION
	.BYTE	0		;(UNUSED)
	.BYTE	0		;T.SRCT-SEND BY REF WITH EFN COUNT
	.WORD	0,.-2		;T.RRFL-RECEIVE BY REFERENCE LISTHEAD

	.ENDC



      	.IF DF P$$OFF

	.WORD	0,.-2		;T.OCBH-OFFSPRING CONTROL BLOCK LIST
	.WORD	0		;T.RDCT-OFFSPRING RUNDOWN COUNT

	.ENDC	;P$$OFF

	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
	.WORD	0,0		;T.EFLM-EVENT FLAG MASK WORD		;MSH069
				;T.EFLM+2-EVENT FLAG MASK ADDRESS WORD	;MSH069
									;MSH069
	.ENDC								;MSH069
									;MSH096
	.IF DF	A$$HDR							;MSH096
									;MSH096
	.BYTE	0		;T.HDLN-TASK HEADER LENGTH (32W BLOCKS)	;MSH096
									;MSH096
	.ENDC								;MSH096
									;MSH09   ô   6
	.IF DF	R$$SND&G$$EFN!A$$CLI&G$$EFN				;MSH190
									;MSH076
	.BYTE	0		;T.GGF-GRP GBL EVENT FLAG USE COUNTER	;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH096
	.EVEN								;MSH096
									;**-1
	.ENDC


	.END
 ô          üMðskQ	› c,        	.TITLE	LSDRV
	.IDENT	/09.1/
 
;
; COPYRIGHT (C) 1974, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 08
;
; D. N. CUTLER 7-JAN-74
;
; PREVIOUSLY MODIFIED BY:
;
;	C. A. D'ELIA
;	T. J. MILLER
;
; MODIFIED BY:
;
;	B. SCHREIBER	30-NOV-77
;
;		BS033 -- CLEAR I.PRM+16 BEFORE CALLING $IOFIN
;			 (IN CASE RMS BLOCK LOCKING).
;
;	B. SCHREIBER	19-MA      Y-78
;
;		BS049 -- FIX HANDLING OF DIGITAL INPUT WD. AT INTERRUPT
;
; LPS11 LABORATORY PERIPHERAL SYSTEM CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	HWDDF$,PKTDF$,TCBDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
 
;
; EQUATED SYMBOLS
;
; SAMPLE CONTROL BLOCK OFFSET DEFINITIONS
;
 
 
	.PSECT	LSCTLQ,D,ABS
 
SLINK:	.BLKW	1		;SAMPLE QUEUE THREAD WORD
RQPKT:	.BLKW	1		;ADDRESS OF I/O REQUEST PACKET
STAT      E:	.BLKW	1		;CURRENT SAMPLE STATE
RSTAT:	.BLKB	1		;SAMPLE STATUS BYTE
FINST:	.BLKB	1		;FINAL I/O STATUS
IOSB2:	.BLKW	2		;SECOND I/O STATUS WORD ADDR & REL BIAS
STRBF:	.BLKW	1		;STARTING BUFFER ADDR & RELOCATION BIAS
CURBF:	.BLKW	3		;CURRENT BUFFER ADDR & RELOCATION BIAS
FULBF:	.BLKW	1		;SIZE OF FULL BUFFER IN WORDS
SMCNT:	.BLKW	1		;SPACE REMAINING TO END OF BUFFER
HAFBF:	.BLKW	1		;SIZE OF HALF BUFFER IN WORDS
 
 
	.IF DF	L$$SDR
 
DBMSK:	.BLKW	1		;DIGITAL INPUT/OUTPUT START MASK
DSMSK:	.BLKW	1	      	;DIGITAL INPUT STOP MASK
 
	.ENDC
 
 
CYCNT:	.BLKW	1		;NUMBER OF CLOCK TICKS TO NEXT SAMPLE
CRSET:	.BLKW	1		;CLOCK TICKS RESET VALUE TO NEXT SAMPLE
SAMCT:	.BLKW	1		;# OF SAMPLE BUFFERS REMAINING IN RQST
DATAW:	.BLKW	1		;FUNCTION DEPENDENT DATA WORD
STRST:	.BLKW	1		;STARTING SAMPLE STATE
 
 
	.IF DF	L$$SBF
 
STKSAV:	.BLKW	1		;CHANNEL (DATAW) SAVE WORD
 
	.ENDC
 
 
SLGTH:				;LENGTH OF SYNCH SAMPLE CONTROL BLOCK
 
 
	.PSECT
 
 
	
;
; SAMPLE CONTROL BLOCK STATUS BYTE BIT DEFINITIONS      
;
 
SPARE=200			;SPARE BIT
STROT=100			;SET DIGITAL OUTPUT BIT AT START (1=YES)
STPIN=40			;STOP ON DIGITAL INPUT BIT CLEAR (1=YES)
STPBR=20			;STOP ON BUFFER RUNOUT (1=YES)
GAINR=10			;AUTOGAIN RANGING REQUESTED (1=YES)
SPARE=4				;SPARE BIT
RQEFN=2				;REQUEST EFN SETTING (1=YES)
STPRQ=1				;STOP SAMPLE REQUEST (1=YES)
 
;
; A/D TIMEOUT LOOP COUNT
;
 
TMOCNT=20.
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
 
CNTBL:	.BLKW	L$$PS1		;ADDRESS OF C      URRENT UNIT CONTROL BLOCK
 
 
	.IF DF	L$$SDR
 
DGIWD:	.BLKW	L$$PS1		;DIGITAL INPUT WORD LAST SYNCHRONOUS SAMPLE
 
	.ENDC
 
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE
 
 
	.IF DF	L$$SBF
 
DLYCNT:	.BLKW	L$$PS1		;CLOCK COUNT FOR A/D DELAY
ADCHN:				;CURRENT A/D CHANNEL NUMBER
ADFLG=ADCHN+1			;A/D CONVERSION ENABLE FLAG
	.REPT	L$$PS1
	.BYTE	377,0
	.ENDR
 
	.ENDC
 
 
 
;
; FORK REQUEST FLAG
;
 
FKFLG:	.WORD	0
 
;
; LEGAL FUNCTION VECTOR
;
 
LGFCN:	.BYTE	IO.SDO/256.	;WRITE DIGITAL OUT      PUT REGISTER
	.BYTE	IO.LED/256.	;WRITE LED DISPLAY LIGHTS
	.BYTE	IO.REL/256.	;WRITE RELAY
	.BYTE	IO.SDI/256.	;READ DIGITAL INPUT REGISTER
	.BYTE	IO.STP/256.	;STOP IN PROGRESS REQUEST
	.BYTE	IO.HIS/256.	;SYNCHRONOUS HISTOGRAM SAMPLING
	.BYTE	IO.MDO/256.	;SYNCHRONOUS DIGITAL OUTPUT
	.BYTE	IO.ADS/256.	;SYNCHRONOUS A/D SAMPLING
	.BYTE	IO.MDA/256.	;SYNCHRONOUS D/A OUTPUT
	.EVEN
 
;
; DRIVER DISPATCH TABLE
;
 
$LSTBL::.WORD	LSINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	LSCAN		;CANCEL I/O OPERATION E      NTRY POINT
	.WORD	LSOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	LSPWF		;POWERFAIL ENTRY POINT
 
;+
; **-LSINI-LPS11 LABORATORY PERIPHERAL SYSTEM CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS RECEIVED FOR THE LPS11 LABORATORY PERIPHERAL SYSTEM. NINE FUNCTIONS ARE
; RECOGNIZED BY THE LPS11 DRIVER. FUNCTIONS ARE EITHER EXECUTED IMMEDITATELY
; OR PLACED IN A SAMPLE REQUEST QUEUE THAT IS MAINTAINED BY THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE       I/O REQUEST PACKET.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE.
;	WD. 06 -- VIR      TUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;
; OUTPUTS:
;
;	IF THE FUNCTION IS READ SINGLE A/D CHANNEL, WRITE DIGITAL OUTPUT
;	REGISTER, WRITE LED DISPLAY LIGHTS, OR WRITE RELAY, THEN THE
;	FUNCTION IS EXECUTED IMMEDIATEDLY. ELSE A SECONDARY CONTROL BLOCK
;	IS CONSTRUCTED AND LINKED INTO THE SAMPLE REQUEST QUEUE.
;-
 
LSINI:	MOV	U.SCB(      R5),R2	;GET ADDRESS OF SCB
	MOV	R1,R3		;SAVE I/O PACKET ADDRESS
	ADD	#I.PRM,R1	;POINT TO FIRST PARAMETER
	MOV	S.CSR(R2),R4	;GET ADDRESS OF CONTROL STATUS REGISTER
	MOV	#LGFCN,R0	;POINT TO LEGAL FUNCTION VECTOR
	MOVB	I.FCN+1(R3),-(SP) ;GET I/O FUNCTION CODE
	CMPB	(SP),(R0)+	;WRITE DIGITAL OUTPUT REGISTER?
 
 
	.IF DF	L$$SDR
 
	BEQ	DIGIO		;IF EQ YES
 
	.IFF
 
	BEQ	LSONP		;IF EQ YES
 
	.IFTF
 
	CMPB	(SP),(R0)+	;WRITE LED DISPLAY LIGHTS?
	BEQ	WRLED		;IF EQ YES
	CMPB	(SP),(R0)+	;WRITE RELAY?      
 
	.IFT
 
	BEQ	WRRLY		;IF EQ YES
	CMPB	(SP),(R0)+	;READ DIGITAL INPUT REGISTER?
	BEQ	RDDIN		;IF EQ YES
 
	.IFF
 
	BEQ	LSONP		;IF EQ YES
	CMPB	(SP),(R0)+	;READ DIGITAL INPUT REGISTER?
	BEQ	LSONP		;IF EQ YES
 
	.ENDC
 
 
	CMPB	(SP),(R0)+	;STOP IN PROGRESS REQUEST?
	BEQ	STOPR		;IF EQ YES
	JMP	LSFCN		;ELSE HANDLE FUNCTION
	
;
; **-STOPR-STOP IN PROGRESS REQUST
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- BUFFER ADDRESS OF PREVIOUS REQUEST.
;	WD. 13 -- NOT USED.
;	      WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
STOPR:	MOV	(R1),R0		;GET ADDRESS OF BUFFER
	MOV	R2,R4		;SAVE ADDRESS OF SCB
	CALL	$RELOC		;RELOCATE BUFFER ADDRESS
	MOV	R3,-(SP)	;SAVE I/O PACKET ADDRESS
	MOV	R5,R3		;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R3	;
	MOVB	S.PRI(R4),PS	;;;LOCK OUT DEVICE INTERRUPTS
10$:	MOV	(R3),R3		;;;GET ADDRESS OF NEXT ENTRY
	BEQ	20$		;;;IF EQ DONE
	MOV	RQPKT(R3),R0	;;;GET ADDRESS OF I      /O PACKET
	CMP	$TKTCB,I.TCB(R0) ;;;REQUEST FOR CURRENT TASK?
	BNE	10$		;;;IF NE NO
	CMP	R1,STRBF(R3)	;;;RELOCATION BIAS MATCH?
	BNE	10$		;;;IF NE NO
	CMP	R2,STRBF+4(R3)	;;;BUFFER ADDRESS MATCH?
	BNE	10$		;;;IF NE NO
	MOVB	#IE.ABO,FINST(R3) ;;;SET FINAL STATUS ABORT
	CALL	TERMS		;;;TERMINATE SAMPLE REQUEST
20$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	MOV	(SP)+,R3	;RESTORE I/O PACKET ADDRESS
	BR	LSSUC		;TAKE COMMON EXIT
 
 
	.IF DF	L$$SDR
 
;
; **-RDDIN-READ DIGITAL INPUT REGISTER
;
; FUNCTION       DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- DIGITAL INPUT MASK WORD.
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
RDDIN:	SEC			;INDICATE DIGITAL INPUT REQUEST
DIGIO:	BITB	#20,U.CW2+1(R5)	;LPSDR-A PRESENT?
	BEQ	LSONP		;IF EQ NO
	BCC	WRDOT		;BRANCH IF DIGITAL OUTPUT REQUEST
 
 
	.IF GT	L$$PS1-1
 
	MOVB	S.CON(R2),R2	;GET CONTROLLER INDEX
	MOV	DGIWD(R2),R2	;GET DIGITAL INPUT WORD LAST SYNCHRONO      US
 
	.IFF
 
	MOV	DGIWD,R2	;GET DIGITAL INPUT OF LAST SYNCH SAMPLE
	
	.ENDC
 
 
	TSTB	U.STS(R5)	;UNIT BUSY?
	BMI	10$		;IF MI YES
	MOV	12(R4),R2	;READ DIGITAL INPUT REGISTER
	MOV	R2,12(R4)	;CLEAR BITS IN DIGITAL INPUT REGISTER
10$:	COM	(R1)		;COMPLEMENT MASK WORD
	BIC	(R1),R2		;CLEAR UNWANTED BITS IN DATA WORD
	MOV	R2,R1		;SET SECOND I/O STATUS WORD
	BR	LSSUC1		;TAKE COMMON EXIT
 
;
; **-WRDOT-WRITE DIGITAL OUTPUT REGISTER
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 --       DIGITAL OUTPUT MASK WORD.
;	WD. 13 -- DIGITAL OUTPUT VALUE.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
WRDOT:	BIT	(R1),U.CNT+2(R5) ;DIGITAL OUTPUT BITS IN USE?
	BNE	LSRSU		;IF NE YES
	ADD	#14,R4		;POINT TO DIGITAL OUTPUT REGISTER
	COM	(R1)		;COMPLEMENT MASK WORD
	BIC	(R1)+,(R1)	;CLEAR EXCESS BITS IN DATA WORD
	BIS	(R1),(R4)	;SET BITS IN DIGITAL OUTPUT REGISTER
	COM	(R1)		;COMPLEMENT DATA WORD
	BIC	-2(R1),(R1)	;CLEAR EXCE      SS BITS IN DATA WORD
	BIC	(R1),(R4)	;CLEAR BITS IN DIGITAL OUTPUT REGISTER
	MOV	(R4),R1		;SET SECOND I/O STATUS WORD
	BR	LSSUC1		;TAKE COMMON EXIT
 
	.ENDC
 
 
;
; **-WRLED-WRITE LED DISPLAY LIGHTS
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- 16 BIT SIGNED BINARY NUMBER TO BE DISPLAYED IN LED LIGHTS.
;	WD. 13 -- LED DIGIT NUMBER OF DECIMAL POINT.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
WRLED:	T      ST	(R4)+		;POINT TO LED DISPLAY REGISTER
	MOV	R1,R2		;COPY ADDRESS OF FIRST PARAMETER WORD
	MOV	#16,-(SP)	;ASSUME POSITIVE NUMBER
	MOV	(R2)+,R0	;GET NUMBER TO BE DISPLAYED
	BPL	10$		;IF PL POSITIVE NUMBER
	DEC	(SP)		;SET MINUS SIGN AS LAST DIGIT
	NEG	R0		;CONVERT TO POSITIVE NUMBER
10$:	CLR	-(SP)		;CLEAR DIGIT COUNTER
	DEC	(R2)		;CALCULATE ACTUAL DIGIT POSITION
	SWAB	(R2)		;SWAP POSITION INTO LEFT BYTE
	CLRB	(R2)		;CLEAR LOW BYTE OF POSITION
20$:	MOV	#10.,R1		;SET DIVISOR
	CALL	$DIV		;CONVERT DI      GIT
	BIS	(SP),R1		;MERGE DIGIT AND DIGIT COUNTER
	CMP	(SP),(R2)	;DIGIT POSITION MATCH?
	BNE	30$		;IF NE NO
	BIS	#20,R1		;SET TO DISPLAY DECIMAL POINT
30$:	MOV	R1,(R4)		;OUTPUT DISPLAY DIGIT
	ADD	#1*400,(SP)	;INCREMENT DIGIT COUNTER
	CMP	#5*400,(SP)	;NUMBER CONVERTED?
	BGT	20$		;IF GT NO
	BIS	(SP)+,(SP)	;MERGE LAST DIGIT WITH DIGIT COUNTER
	MOV	(SP)+,(R4)	;OUTPUT LAST DIGIT (MINUS OR BLANK)
 
 
	.IF DF	L$$SDR
 
	BR	LSSUC		;TAKE COMMON EXIT
 
;
; **-WRRLY-WRITE RELAY
;
; FUNCTION DEPENDENT       I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- RELAY NUMBER (0 OR 1).
;	WD. 13 -- POLARITY DESIRED (ZERO=OPEN, NONZERO=CLOSED).
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
WRRLY:				;REF LABEL
	BITB	#20,U.CW2+1(R5)	;LPSDR-A PRESENT?
	BEQ	LSONP		;IF EQ NO
	ADD	#10,R4		;POINT TO RELAY 1
	ASR	(R1)+		;TEST RELAY NUMBER
	BNE	LSBAD		;IF NE ILLEGAL RELAY NUMBER
	BCC	10$		;IF CC RELAY 1
	INC	R4		;POINT TO  RELAY 2
10$:	TST	(R1)		;ZE      RO POLARITY?
	BEQ	20$		;IF EQ YES
	BISB	#1,(R4)		;SET POLARITY TO ONE
	BR	LSSUC		;
20$:	BICB	#1,(R4)		;SET POLARITY TO ZERO
 
	.IFTF
 
;
; SUCCESS COMPLETION OF FUNCTION
;
 
LSSUC:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
LSSUC1:	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS CODE
	BR	LSCMN1		;
 
;
; BAD PARAMETER
;
 
LSBAD:	MOV	#IE.BAD&377,R0	;SET BAD PARAMETER STATUS CODE
	BR	LSCMN		;
 
	.IFT
 
;
; RESOURCE IN USE
;
 
LSRSU:	MOV	#IE.RSU&377,R0	;SET RESOURCE IN USE STATUS CO      DE
	BR	LSCMN		;
 
	.ENDC
 
 
;
; PRIVILEGE VIOLATION
;
 
LSPRI:	MOV	#IE.PRI&377,R0	;SET PRIVILEGE VIOLATION STATUS
	BR	LSCMN		;
 
;
; OPTION NOT PRESENT
;
 
LSONP:	MOV	#IE.ONP&377,R0	;SET OPTION NOT PRESENT STATUS
	BR	LSCMN		;
 
;
; DYNAMIC MEMORY NOT AVAILABLE
;
 
LSNOD:	MOV	#IE.NOD&377,R0	;SET MEMORY NOT AVAILABLE STATUS
 
;
; COMMON STATUS EXIT
;
 
LSCMN:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
LSCMN1:	TST	(SP)+		;REMOVE FUNCTION CODE FROM STACK
	CLR	I.PRM+16(R3)	;CLEAR BLOC      K LOCKING WORD FOR $IOFIN
	CALLR	$IOFIN		;FINISH I/O OPERATION
 
;
; ALL REMAINING FUNCTIONS REQUIRE THE REQUESTING TASK TO BE EITHER FIXED
; IN MEMORY OR NOT CHECKPOINTABLE AND AN I/O STATUS DOUBLEWORD TO BE
; SPECIFIED.
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF BUFFER.
;	WD. 13 -- BUFFER ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 14 -- BUFFER SIZE IN BYTES.
;	WD. 15 -- DIGITAL INPUT/OUTPUT POINT NUMBERS.
;	WD. 16 -- LPS CLOCK TICKS BETWEEN SAMPLES      .
;	WD. 17 -- NUMBER OF BUFFERS.
;	WD. 20 -- FUNCTION DEPENDENT DATA WORD.
;
 
LSFCN:	MOV	I.TCB(R3),R2	;GET REQUESTING TASK TCB ADDRESS
	BIT	#T2.CHK!T2.FXD,T.ST2(R2) ;TASK FXD OR NOT CHKPOINTABLE?
	BEQ	LSPRI		;IF EQ NO
	TST	I.IOSB+4(R3)	;I/O STATUS DOUBLEWORD SPECIFIED?
	BEQ	LSBAD		;IF EQ NO
	ADD	#6,R1		;POINT TO DIGITAL POINT NUMBERS
	BITB	#340,I.FCN(R3)	;DIGITAL I/O SUB-FUNCTION REQUESTED?
 
 
	.IF DF	L$$SDR
 
	BEQ	35$		;IF EQ NO
	BITB	#20,U.CW2+1(R5)	;LPSDR-A PRESENT?
	BEQ	LSONP		;IF EQ       NO
	MOVB	I.FCN(R3),R2	;GET SUBFUNCTION MODIFIER BITS
	BPL	10$		;IF PL START IMMEDIATELY
	CMPB	(R1),#16.	;LEGAL DIGITAL POINT NUMBER?
	BHIS	LSBAD		;IF HIS NO
10$:	ASLB	R2		;SET DIGITAL OUTPUT ON START?
	BPL	20$		;IF PL NO
	CMPB	(R1),#16.	;LEGAL DIGITAL POINT NUMBER?
	BHIS	LSBAD		;IF HIS NO
	MOVB	(R1),R4		;GET DIGITAL OUTPUT POINT NUMBER
	ASL	R4		;CONVERT TO WORD INDEX
	BIT	$BTMSK(R4),U.CNT+2(R5) ;DIGITAL OUTPUT BIT IN USE?
	BNE	LSRSU		;IF NE YES
20$:	ASLB	R2		;STOP ON DIGITAL INPUT?
	BPL	30$		      ;IF PL NO
	CMPB	1(R1),#16.	;LEGAL DIGITAL POINT NUMBER?
	BHIS	LSBAD		;IF HIS NO
30$:	ASL	(R1)		;CONVERT BOTH POINT NUMBERS TO WORD INDICES
 
	.IFF
 
	BNE	LSONP		;IF NE YES
 
	.IFTF
 
35$:				;REF LABEL
	ADD	#8.,R1		;POINT TO LAST WORD IN I/O PACKET
	CMPB	(SP),(R0)+	;SYNCHRONOUS HISTOGRAM SAMPLING?
	BEQ	40$		;IF EQ YES
	CMPB	(SP),(R0)+	;SYNCHRONOUS DIGITAL OUTPUT?
 
	.IFT
 
	BEQ	50$		;IF EQ YES
 
	.IFF
 
	BEQ	LSONP		;IF EQ YES
 
	.IFTF
 
	CMPB	(SP),(R0)+	;SYNCHRONOUS A/D SAMPLING?      
	BEQ	60$		;IF EQ YES
	CMPB	(SP),(R0)+	;SYNCHRONOUS D/A OUTPUT?
 
	.IFT
 
	BNE	100$		;IF NE NO
 
	.IFF
 
	BNE	LSONP		;IF NE NO (NO DIGITAL INPUT)
 
	.ENDC
 
 
	.IF DF	L$$SDA
 
;
; SYNCHRONOUS D/A OUTPUT
;
 
	MOV	#SYNDA,(R1)	;SET SYNCHRONOUS D/A OUTPUT STATE
	MOVB	U.CW2+1(R5),R0	;GET OPTION FLAGS AND NUMBER OF D/A'S
	BIT	#100,R0		;D/A OPTION PRESENT?
	BEQ	LSONP		;IF EQ NO
	BIC	#^C<37>,R0	;CLEAR ALL BUT NUMBER OF D/A'S
	MOVB	-(R1),R2	;GET NUMBER OF OUTPUT D/A'S
	MOVB	-(R1),R4	;GET ST      ARTING D/A NUMBER
	BR	90$		;FINISH IN COMMON CODE
 
	.IFF
 
	BR	LSONP		;D/A OPTION NOT PRESENT
 
	.ENDC
 
 
;
; SYNCHRONOUS HISTOGRAM SAMPLING
;
 
40$:	MOV	#SYNHS,(R1)	;SET SYNCHRONOUS HISTOGRAM SAMPLING STATE
	CLR	-(R1)		;CLEAR DATA WORD
	BR	120$		;
 
 
	.IF DF	L$$SDR
 
;
; SYNCHRONOUS DIGITAL OUTPUT
;
 
50$:	MOV	#SYNDO,(R1)	;SET SYNCHRONOUS DIGITAL OUTPUT STATE
	BIT	-(R1),U.CNT+2(R5) ;ANY DIGITAL OUTPUT BITS IN USE?
	BR	110$		;FINISH IN COMMON CODE
 
	.IFTF
 
;
; SYNCHRONOU      S A/D SAMPLING
;
 
60$:	MOV	#SYNAD,(R1)	;SET SYNCHRONOUS A/D SAMPLING STATE
	MOVB	-(R1),R2	;GET NUMBER OF CHANNELS
	MOVB	-(R1),R4	;GET STARTING CHANNEL AND GAIN
	BITB	#GAINR,I.FCN(R3) ;AUTOGAIN RANGING SPECIFIED?
	BNE	70$		;IF NE YES
	BIT	#60,R4		;GAIN OTHER THAN 1 SPECIFIED?
	BEQ	80$		;IF EQ NO
	TST	U.CW2(R5)	;GAIN OPTION PRESENT?
	BPL	80$		;IF PL NO
	BIC	#60,R4		;CLEAR GAIN CODE BITS
70$:	TST	U.CW2(R5)	;GAIN OPTION PRESENT?
	BPL	LSONP		;IF PL NO
80$:	MOVB	U.CW2(R5),R0	;GET NUMBER OF A/D CHA      NNELS
	BIC	#^C<177>,R0	;
90$:	DEC	R2		;REDUCE NUMBER OF CHANNELS
	ADD	R2,R4		;CALCULATE HIGHEST CHANNEL
	BCS	LSBAD		;IF CS BAD RANGE
	CMP	R4,R0		;LEGAL CHANNEL?
	BHIS	LSBAD		;IF HIS NO
 
	.IFT
 
	BR	120$		;FINISH IN COMMON CODE
 
;
; SYNCHRONOUS DIGITAL INPUT
;
 
100$:	MOV	#SYNDI,(R1)	;SET SYNCHRONOUS DIGITAL INPUT STATE
	BIT	-(R1),U.CNT(R5)	;ANY DIGITAL INPUT BITS IN USE?
110$:	BNE	LSRSU		;IF NE YES
 
	.IFTF
 
120$:	MOV	R3,R4		;SAVE I/O PACKET ADDRESS
	MOV	#SLGTH,R1	;SET LENGTH OF SE      CONDARY CONTROL BLOCK
	CALL	$ALOCB		;ALLOCATE SECONDARY CONTROL BLOCK
	MOV	R4,R3		;RESTORE I/O PACKET ADDRESS
	BCS	LSNOD		;IF CS NO MEMORY AVAILABLE
	MOV	R0,R1		;COPY SECONDARY CONTROL BLOCK ADDRESS
	CLR	(R1)+		;CLEAR LINK WORD
	MOV	R3,(R1)+	;INSERT I/O PACKET ADDRESS
	ADD	#I.FCN,R3	;POINT TO SUBFUNCTION MODIFIER BITS
 
	.IFT
 
	MOV	#SDOUT,(R1)+	;SET INITIAL STATE TO DIGITAL OUTPUT
 
	.IFF
 
	MOV	I.PRM+14.(R4),(R1)+  ;SET INITIAL SAMPLING STATE
 
	.IFTF
 
	MOV	(R3),(R1)	;INSERT SUBFUNCTIO      N MODIFIER BITS
	BIC	#^C<STROT!STPIN!STPBR!GAINR>,(R1)+ ;CLEAR EXTRANEOUS BITS
	ADD	#I.IOSB+2,R4	;POINT TO I/O STATUS DOUBLEWORD ADDRESS
	MOV	(R4)+,(R1)+	;INSERT RELOCATION BIAS
	MOV	(R4)+,(R1)	;INSERT DISPLACEMENT ADDRESS
	ADD	#2,(R1)+	;CALCULATE ADDRESS OF SECOND I/O STATUS
	TST	(R4)+		;BYPASS AST ADDRESS AND CLEAR CARRY
	MOV	(R4),(R1)+	;INSERT BUFFER RELOCATION BIAS
	MOV	(R4)+,(R1)+	;
	MOV	(R4),(R1)+	;INSERT BUFFER DISPLACEMENT ADDRESS
	MOV	(R4)+,(R1)+	;
	MOV	(R4)+,(R1)	;INSERT SIZE OF BUFFER       IN BYTES
	ROR	(R1)		;CONVERT TO SIZE IN WORDS
	MOV	(R1)+,(R1)	;INSERT SIZE OF BUFFER IN WORDS
	MOV	(R1)+,(R1)	;INSERT SIZE OF BUFFER IN WORDS
	ASR	(R1)+		;CONVERT TO SIZE IN DOUBLEWORDS
 
	.IFT
 
	MOVB	(R4)+,R2	;GET DIGITAL INPUT/OUTPUT POINT INDEX
	CLR	(R1)		;ASSUME NO DIGITAL INPUT/OUTPUT POINT
	ASLB	(R3)		;START ON DIGITAL INPUT POINT?
	BCC	130$		;IF CC NO
	MOV	#SWAIT,STATE(R0) ;ALTER STATE TO WAIT ON DIGITAL INPUT
	BR	140$		;
130$:	BPL	150$		;IF PL NO DIGITAL OUTPUT ON START
140$:	MOV	$BT      MSK(R2),(R1)	;INSERT DIGITAL INPUT/OUTPUT POINT MASK
	TSTB	(R3)		;SET DIGITAL OUTPUT POINT AT START?
	BPL	150$		;IF PL NO
	BIS	(R1),U.CNT+2(R5) ;SET DIGITAL OUTPUT POINT IN USE
150$:	TST	(R1)+		;ADVANCE TO NEXT WORD
	CLR	(R1)		;ASSUME NO DIGITAL INPUT POINT
	MOVB	(R4)+,R2	;GET DIGITAL INPUT POINT INDEX
	ASLB	(R3)		;STOP ON DIGITAL INPUT POINT?
	BPL	160$		;IF PL NO
	MOV	$BTMSK(R2),(R1)	;INSERT DIGITAL INPUT POINT MASK
160$:	CMP	(R1)+,(SP)+	;ADVANCE TO NEXT WORD AND CLEAN STACK
 
	.IFF
 
	CMP	(R      4)+,(SP)+	;SKIP DIGITAL I/O WORD AND CLEAN STACK
 
	.IFTF
 
	MOV	#1,(R1)+	;INSERT INITIAL CLOCK TICKS TO NEXT SAMPLE
	MOV	(R4)+,(R1)+	;INSERT CLOCK TICKS RESET VALUE
	MOV	(R4)+,(R1)+	;INSERT NUMBER OF BUFFERS TO COLLECT
	MOV	(R4)+,(R1)+	;INSERT FUNCTION DEPENDENT DATA WORD
	MOV	(R4),(R1)	;INSERT STARTING SAMPLE STATE
 
	.IFT
 
	CMP	#SYNDO,(R1)	;SYNCHRONOUS DIGITAL OUTPUT?
	BEQ	170$		;IF EQ YES
	CMP	#SYNDI,(R1)	;SYNCHRONOUS DIGITAL INPUT?
	BNE	190$		;IF NE NO
	BIS	-(R1),U.CNT(R5)	;SET DIGITAL       INPUT BITS IN USE
	BR	180$		;
170$:	BIS	-(R1),U.CNT+2(R5) ;SET DIGITAL OUTPUT BITS IN USE
180$:	COM	(R1)		;COMPLEMENT MASK WORD
 
	.ENDC
 
 
190$:	MOV	U.BUF(R5),(R0)	;INSERT REQUEST IN SAMPLE QUEUE
	MOV	R0,U.BUF(R5)	;
	MOVB	I.EFN-<I.PRM+16>(R4),R0 ;GET SPECIFIED EVENT FLAG NUMBER
	MOV	R5,-(SP)	;SAVE UCB ADDRESS
	MOV	I.TCB-<I.PRM+16>(R4),R5 ;GET TCB ADDRESS OF REQUESTOR TASK
	CALL	$CEFI		;CONVERT EFN TO MASK AND ADDRESS
	MOV	R1,(R4)		;INSERT EFN MASK ADDRESS
	MOV	R0,-(R4)	;INSERT EFN MASK WOR      D
	MOV	(SP)+,R5	;RETRIEVE UCB ADDRESS
	MOV	U.SCB(R5),R3	;GET ADDRESS OF SCB
	TSTB	U.STS(R5)	;UNIT BUSY?
	BMI	200$		;IF MI YES
 
 
	.IF DF	L$$SBF
 
	TSTB	U.CW2(R5)	;BANDWIDTH FILTERS IN USE?
	BPL	198$		;IF PL NO
	MOV	U.BUF+2(R5),R0	;GET DELAY COUNTDOWN FOR 10KHZ
	MOV	U.CW4(R5),R1	;GET CLOCK INTERRUPT COUNTDOWN
	CALL	$DIV		;CALCULATE INTERRUPT COUNT
	TST	R1		;WAS THERE A REMAINDER?
	BEQ	195$		;IF EQ NO
	INC	R0		;ELSE, INCREMENT COUNT
195$:				;REF LABEL
 
 
	.IF GT	L$$PS1-1
 
	MOVB	S.CON      (R3),R1	;GET CONTROLLER INDEX
	MOV	R0,DLYCNT(R1)	;STORE DELAY COUNT
 
	.IFF
 
	MOV	R0,DLYCNT	;STORE DELAY COUNT
 
	.ENDC
 
198$:				;REF LABEL
 
	.ENDC
 
 
	MOV	S.CSR(R3),R2	;GET ADDRESS OF CONTROL STATUS REGISTER
	CMP	(R2)+,(R2)+	;POINT TO CLOCK STATUS REGISTER
	MOV	#506,(R2)+	;SET REPEAT MODE, 10KHZ, AND ENABLE INT
	MOV	U.CW4(R5),(R2)	;LOAD COUNTER PRESET REGISTER
	NEG	(R2)		;NEGATE PRESET VALUE
	INC	-(R2)		;START CLOCK RUNNING
200$:	BISB	#US.BSY,U.STS(R5) ;SET UNIT BUSY
	MOVB	#1,S.ST      S(R3)	;SET CONTROLLER BUSY
	MOVB	S.ITM(R3),S.CTM(R3) ;SET CURRENT TIMEOUT COUNT
	RETURN			;
 
;+
; **-$LSCLK-LPS11 LABORATORY PERIPHERAL SYSTEM CLOCK INTERRUPT
;-
 
$LSCLK::			;;;REF LABEL
$LSINT::			;;;REF LABEL
	INTSV$	LS,PR6,L$$PS1	;;;GENERATE INTERRUPT SAVE CODE
	MOV	R3,-(SP)	;;;SAVE R3 AND R2
	MOV	R2,-(SP)	;;;
 
 
	.IF GT	L$$PS1-1
 
	MOV	R1,-(SP)	;;;SAVE R1
	MOV	R4,R1		;;;PUT CONTROLLER INDEX IN R1
	
	.ENDC
 
	
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOVB	S.ITM(R4),S.CTM(R4) ;;      ;RESET TIMEOUT COUNT
	MOV	S.CSR(R4),R4	;;;GET ADDRESS OF CONTROL STATUS REGISTER
 
 
	.IF DF	L$$SDR
 
 
	.IF GT	L$$PS1-1
 
	BITB	#20,U.CW2+1(R5)	;;;LPSDR-A PRESENT?
	BEQ	10$		;;;IF EQ NO
 
	.IFTF
 
	MOV	12(R4),R3	;;;READ DIGITAL INPUT REGISTER
 
	.IFT
 
	MOV	R3,DGIWD(R1)	;;;SAVE DIGITAL INPUT WORD
 
	.IFF
 
	MOV	R3,DGIWD	;;;SAVE DIGITAL INPUT WORD
 
	.ENDC
 
	
	MOV	R3,TEMP		;;;SAVE COMPLEMENT OF DIGITAL INPUT WORD
	COM	TEMP		;;;
	MOV	R3,12(R4)	;;;CLEAR BITS IN DIGITAL INPUT REGI      STER
10$:				;;;REF LABEL
 
	.ENDC
 
 
	MOV	R5,R3		;;;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R3	;;;
 
 
	.IF DF	M$$MGE
 
	MOV	KISAR6,-(SP)	;;;SAVE CURRENT APR6 MAPPING
	
	.ENDC
 
 
;
; GET NEXT REQUEST FROM SAMPLE QUEUE AND PROCESS
;
 
	.ENABL	LSB
NXTRQ:	MOV	(R3),R3		;;;GET ADDRESS OF NEXT SAMPLE REQUEST
	BEQ	20$		;;;IF EQ END OF REQUEST QUEUE
	DEC	CYCNT(R3)	;;;TIME TO SAMPLE?
	BNE	NXTRQ		;;;IF NE NO
10$:	MOV	CRSET(R3),CYCNT(R3) ;;;RESET SAMPLE CYCLE COUNT
	JMP	@ST      ATE(R3)	;;;PROCESS SAMPLE REQUEST
20$:	JMP	ENDRQ		;;;
 
 
	.IF DF	L$$SDR
 
;
; START SAMPLING IF DIGITAL INPUT BIT SET
;
 
SWAIT:	MOV	#1,CYCNT(R3)	;;;SET TO REPEAT TEST AT NEXT INTERVAL
	BIT	DBMSK(R3),TEMP	;;;START SAMPLING?
	BNE	NXTRQ		;;;IF NE NO
	BITB	#STROT,RSTAT(R3) ;;;SET DIGITAL OUTPUT BIT AT START?
	BEQ	30$		;;;IF EQ NO
 
;
; SET DIGITAL OUTPUT BIT
;
 
SDOUT:	BIS	DBMSK(R3),14(R4) ;;;SET DIGITAL OUTPUT BIT
30$:	MOV	STRST(R3),STATE(R3) ;;;CHANGE STATE TO STARTING VALUE
	BR	10$		;      ;;DISPATCH ON NEW STATE
 
	.IFTF
 
	.DSABL	LSB
 
;
; SYNCHRONOUS HISTOGRAM SAMPLING
;
 
SYNHS:	INC	DATAW(R3)	;;;INCREMENT EVENT COUNTER
	BEQ	10$		;;;IF EQ COUNTER OVERFLOW
	TST	4(R4)		;;;SCHMITT TRIGGER 1 FIRE?
	BPL	NXTRQ		;;;IF PL NO
10$:	BIC	#100000,4(R4)	;;;CLEAR SCHMITT TRIGGER 1 FLAG
	MOV	DATAW(R3),R2	;;;GET EVENT COUNTER
	CLR	DATAW(R3)	;;;CLEAR EVENT COUNTER
	CALL	WRWRD		;;;WRITE WORD INTO USER BUFFER
	BR	NXTRQ		;;;CONTINUE SCAN
 
	.IFT
 
 
;
; SYNCHRONOUS DIGITAL OUTPUT
;
       
SYNDO:				;;;REF LABEL
	CALL	RDWRD		;;;READ WORD FROM USER BUFFER
	BCS	NXTRQ		;;;IF CS BUFFER OVERRUN
	MOV	14(R4),-(SP)	;;;READ DIGITAL OUTPUT REGISTER
	MOV	DATAW(R3),-(SP)	;;;GET OUTPUT MASK WORD
	BIC	(SP),R2		;;;CLEAR EXCESS BITS IN DATA WORD
	COM	(SP)		;;;COMPLEMENT MASK WORD
	BIC	(SP)+,(SP)	;;;CLEAR FIELD BITS IN OUTPUT WORD
	BIS	(SP)+,R2	;;;MERGE DATA AND OUTPUT WORD
	MOV	R2,14(R4)	;;;WRITE VALUE INTO DIGITAL OUTPUT REGISTER
	BR	NXTRQ		;;;CONTINUE SCAN
 
	.ENDC
 
 
;
; SYNCHRONOUS A/D       SAMPLING
;
 
SYNAD:				;;;REF LABEL
 
 
	.IF DF	L$$SBF
 
 
	.IF GT	L$$PS1-1
 
	TSTB	ADFLG(R1)	;;;A/D CONVERSIONS DISABLED?
 
	.IFF
 
	TSTB	ADFLG		;;;A/D CONVERSIONS DISABLED?
 
	.ENDC
 
 
	BNE	NXTRQ		;;;IF NE YES -- IGNORE REQUEST
 
	.ENDC
 
 
	MOV	DATAW(R3),-(SP)	;;;SET COUNT & STARTING CHANNEL
ADSLCT:				;;;REF LABEL
 
 
	.IF DF	L$$SBF
 
 
	.IF GT	L$$PS1-1
 
	TSTB	U.CW2(R5)	;;;BANDWIDTH FILTERING ENABLED?
	BPL	10$		;;;IF PL NO
	CMPB	(SP),ADCHN(R1)	;;;IS A/D CHANNEL SELE      CTED?
 
	.IFF
 
	CMPB	(SP),ADCHN	;;;IS A/D CHANNEL SELECTED?
 
	.ENDC
 
 
	BEQ	ADSMPL		;;;IF EQ YES
	JMP	SDELAY		;;;SELECT CHANNEL AND DELAY
 
	.ENDC
 
 
10$:	MOVB	(SP),1(R4)	;;;SET NUMBER OF CHANNEL TO CONVERT
ADSMPL:				;;;REF LABEL
	MOVB	#1,(R4)		;;;START CONVERSION
	MOV	#TMOCNT,R2	;;;SET TIMEOUT LOOP COUNT
20$:	BIT	#100200,(R4)	;;;ERROR OR DONE?
	BMI	80$		;;;IF MI ERROR
 
 
	.IF DF	L$$SGR
 
	BNE	30$		;;;IF NE DONE
 
	.IFF
 
	BNE	90$		;;;IF NE DONE
 
	.IFTF
 
	DEC	R2		;;;      TIMEOUT?
	BGT	20$		;;;IF GT NO
 
	.IFT
 
	BR	70$		;;;TIMEOUT
30$:	BITB	#GAINR,RSTAT(R3) ;;;GAIN RANGING REQUESTED?
	BEQ	90$		;;;IF EQ NO
	MOVB	(SP),R2		;;;GET A/D CHANNEL NUMBER
	ASL	R2		;;;CONVERT TO WORD INDEX
	MOV	2(R4),-(SP)	;;;READ CONVERTED VALUE
	BIT	$BTMSK(R2),U.CW3(R5) ;;;UNIPOLAR CHANNEL?
	BNE	40$		;;;IF NE YES
	SUB	#4000,(SP)	;;;SUBTRACT OUT OFFSET BIAS
	BPL	35$		;;;IF PL OKAY
	NEG	(SP)		;;;NEGATE RESULT
35$:	ASL	(SP)		;;;NORMALIZE RESULT
40$:	MOV	(SP)+,R2	;;;COPY NORMALIZED VALU      E
	BIT	#6000,R2	;;;SAMPLE AT GAIN 1?
	BNE	90$		;;;IF NE YES
	ADD	#<1*20>*400,(R4) ;;;SET TO SAMPLE AT GAIN 4
	BIT	#1400,R2	;;;SAMPLE AT GAIN 4?
	BNE	50$		;;;IF NE YES
	ADD	#<1*20>*400,(R4) ;;;SET TO SAMPLE AT GAIN 16.
	BIT	#300,R2		;;;SAMPLE AT GAIN 16.?
	BNE	50$		;;;IF NE YES
	ADD	#<1*20>*400,(R4) ;;;SET TO SAMPLE AT GAIN 64.
50$:	INC	(R4)		;;;START CONVERSION
	MOV	#TMOCNT,R2	;;;SET TIMEOUT LOOP COUNT
60$:	BIT	#100200,(R4)	;;;ERROR OR DONE?
	BMI	80$		;;;IF MI ERROR
	BNE	90$		;;;IF NE DONE
	D      EC	R2		;;;TIMEOUT?
	BGT	60$		;;;IF GT NO
 
	.IFTF
 
70$:	MOV	#177777,R2	;;;SET TIMEOUT ERROR VALUE
	BR	100$		;;;
80$:	MOV	#177776,R2	;;;SET CONVERSION ERROR VALUE
	BR	100$		;;;
90$:	MOV	2(R4),R2	;;;READ CONVERTED VALUE
 
	.IFT
 
	BIC	#147777,(R4)	;;;CLEAR ALL BUT GAIN BITS
	BIS	(R4),R2		;;;INSERT GAIN CODE
 
	.ENDC
 
 
100$:	CALL	WRWRD		;;;WRITE WORD INTO USER BUFFER
	BCS	110$		;;;IF CS BUFFER OVERRUN
	INCB	(SP)		;;;INCREMENT CHANNEL NUMBER
	DECB	1(SP)		;;;ANY MORE CHANNELS TO SAMPLE?      
	BGT	ADSLCT		;;;IF GT YES
110$:	TST	(SP)+		;;;CLEAN STACK
	JMP	NXTRQ		;;;CONTINUE SCAN
 
 
	.IF DF	L$$SDA
 
;
; SYNCHRONOUS D/A OUTPUT
;
 
SYNDA:				;;;REF LABEL
	MOV	DATAW(R3),-(SP)	;;;SET COUNT AND STARTING D/A NUMBER
10$:	CALL	RDWRD		;;;READ WORD FROM USER BUFFER
	BCS	60$		;;;IF CS BUFFER OVERRUN
	BIC	#170000,R2	;;;CLEAR D/A NUMBER FIELD
	MOVB	(SP),-(SP)	;;;COPY D/A NUMBER
	DECB	(SP)		;;;D/A 0 OR 1?
	BMI	20$		;;;IF MI D/A 0 (X-REG)
	BEQ	30$		;;;IF EQ D/A 1 (Y-REG)
	DECB	(SP)		;;;NORM      ALIZE EXTERNAL D/A NUMBER
	RORB	(SP)		;;;ROTATE D/A NUMBER INTO PLACE
	RORB	(SP)		;;;
	RORB	(SP)		;;;
	RORB	(SP)		;;;
	SWAB	R2		;;;SWAP DATA BYTES
	BISB	(SP)+,R2	;;;MERGE D/A NUMBER WITH DATA
	SWAB	R2		;;;SWAP BACK DATA BYTES
	MOV	R2,24(R4)	;;;OUTPUT DATA TO PROPER D/A
	BR	50$		;;;
20$:	MOV	R2,20(R4)	;;;OUTPUT TO X-REG D/A
	BR	40$		;;;
30$:	MOV	R2,22(R4)	;;;OUTPUT TO Y-REG D/A
40$:	TST	(SP)+		;;;CLEAN STACK
50$:	INC	(SP)		;;;INCREMENT D/A NUMBER
	DECB	1(SP)		;;;ANY MORE TO GO?
	BGT	10$		;;;I      F GT YES
60$:	TST	(SP)+		;;;CLEAN STACK
	JMP	NXTRQ		;;;CONTINUE SCAN
 
	.ENDC
 
 
	.IF DF	L$$SDR
 
;
; SYNCHRONOUS DIGITAL INPUT SAMPLING
;
 
SYNDI:				;;;REF LABEL
	
 
	.IF GT	L$$PS1-1
	
	MOV	DGIWD(R1),R2	;;;GET SAVED DIGITAL INPUT WORD
 
	.IFF
 
	MOV	DGIWD,R2	;;;GET SAVED DIGITAL INPUT WORD
 
	.ENDC
 
	
	MOV	DATAW(R3),-(SP) ;;;GET INPUT MASK WORD
	BIC	(SP)+,R2	;;;CLEAR EXCESS BITS IN DATA WORD
	CALL	WRWRD		;;;WRITE WORD INTO USER BUFFER
	JMP	NXTRQ		;;;CONTINUE SCAN
 
	.ENDC      
 
 
;
; END OF REQUEST QUEUE-CHECK IF FORK REQUIRED
;
 
ENDRQ:				;;;REF LABEL
 
 
	.IF DF M$$MGE
 
	MOV	(SP)+,KISAR6	;;;RESTORE APR6 MAPPING
 
	.ENDC
 
 
	.IF GT	L$$PS1-1
	
	MOV	(SP)+,R1	;;;RESTORE R1
 
	.ENDC
 
 
	MOV	(SP)+,R2	;;;RESTORE R2 AND R3
	MOV	(SP)+,R3	;;;
	TST	FKFLG		;;;FORK REQUESTED?
	BEQ	10$		;;;IF EQ NO
	CLR	FKFLG		;;;CLEAR FORK REQUESTED FLAG
	BITB	#US.FRK,U.STS(R5) ;;;FORK ALREADY IN PROGRESS?
	BEQ	ENDRQ1		;;;IF EQ NO
10$:	JMP	$INTXT		;;;EXIT INTERRUPT
 
;      +
; **-LSCAN-CANCEL I/O REQUESTS
;
; THIS ROUTINE IS ENTERED TO CANCEL ALL I/O REQUESTS THAT ARE IN PROGRESS FOR
; THE CURRENT TASK. THE SAMPLE QUEUE IS SCANNED AND ALL REQUESTS FOR THE CURRENT
; TASK ARE MARKED FOR TERMINATION WITH A FINAL REQUEST STATUS OF 'IE.ABO'.
;
; INPUTS:
;
;	R0=ADDRESS OF THE CURRENT I/O PACKET (MEANINGLESS).
;	R1=ADDRESS OF THE TCB OF THE CURRENT TASK.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUT      S:
;
;	ALL REQUESTS FOR THE CURRENT TASK ARE MARKED FOR TERMINATION WITH
;	A FINAL STATUS OF 'IE.ABO'.
;-
 
	.ENABL	LSB
LSCAN:	MOV	#IE.ABO&377,R0	;;;SET FINAL STATUS CODE TO ABORT
	BR	10$		;;;FINISH IN COMMON CODE
 
;+
; **-LSOUT-DEVICE TIMEOUT
;
; THIS ROUTINE IS ENTERED WHEN AN LPS11 OPERATION TIMES OUT. ALL REQUESTS IN THE
; SAMPLE QUEUE ARE MARKED FOR TERMINATION WITH A FINAL STATUS OF 'IE.DNR'.
; TIMEOUTS ARE USUALLY CAUSED BY A POWERFAILURE BUT MAY ALSO BE THE RESULT
; OF A HARDWARE FA      ILURE.
;
; INPUTS:
;
;	R0=DEVICE TIMEOUT STATUS 'IE.DNR'.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	ALL REQUESTS ARE MARKED FOR TERMINATION WITH A FINAL STATUS OF
;	'IE.DNR'.
;-
 
LSOUT:	MOV	S.CSR(R4),R2	;;;GET ADDRESS OF CONTROL STATUS REGISTER
	CLR	(R2)		;;;CLEAR A/D INTERRUPTS
	CLR	4(R2)		;;;CLEAR CLOCK INTERRUPTS
10$:	MOV	R5,R2		;;;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	ADD	#U.BUF,R2	;;;
20$:	MOV	(R2      ),R2		;;;GET ADDRESS OF NEXT ENTRY
	BEQ	40$		;;;IF EQ NONE
	CMPB	#IE.ABO,R0	;;;CANCEL I/O?
	BNE	30$		;;;IF NE NO
	MOV	RQPKT(R2),R3	;;;GET ADDRESS OF I/O PACKET
	CMP	R1,I.TCB(R3)	;;;REQUEST FOR CURRENT TASK?
	BNE	20$		;;;IF NE NO
30$:	BISB	#STPRQ,RSTAT(R2) ;;;SET TO TERMINATE SAMPLE REQUEST
	MOVB	R0,FINST(R2)	;;;SET FINAL REQUEST STATUS
	MOV	#NXTRQ,STATE(R2) ;;;SET STATE TO TERMINATION IN PROGRESS
	BR	20$		;;;
40$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	BR	ENDRQ2		;FINISH IN COMMON CODE
	.DSABL	LS      B
 
;+
; **-LSPWF-POWERFAIL
;
; THIS ROUTINE IS ENTERED AS THE RESULT OF A POWERFAILURE. POWERFAIL IS HANDLED
; VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES NO IMMEDIATE ACTION ON
; THE DEVICE. THE UNIT CONTROL BLOCK ADDRESS IS STORED IN THE DRIVER CONTROLLER
; TABLE.
;
; INPUTS:
;
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	THE UNIT CONTROL BLOCK ADDRESS IS STORED IN THE DRIVER CONTROLLER TABLE.
;-
 
      LSPWF:	MOV	R5,CNTBL(R3)	;SET ADDRESS OF UNIT CONTROL BLOCK
	RETURN			;
 
;
; FORK REQUESTED AND NO FORK IN PROGRESS
;
 
ENDRQ1:	BISB	#US.FRK,U.STS(R5) ;;;SET FORK IN PROGRESS FLAG
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	BICB	#US.FRK,U.STS(R5) ;CLEAR FORK IN PROGRESS FLAG
 
;
; SCAN SAMPLE QUEUE FOR EVENT FLAG AND TERMINATION REQUESTS
;
 
ENDRQ2:	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOVB	S.PRI(R4),PS	;;;LOCK OUT DEVICE INTERRUPTS
	MOV	R5,R4		;;;CALCULATE ADDRESS OF SAMPLE QUEUE LISTHEAD
	      ADD	#U.BUF,R4	;;;
10$:	MOV	R4,R3		;;;SAVE ADDRESS OF PREVIOUS ENTRY
	MOV	(R3),R4		;;;GET ADDRESS OF NEXT ENTRY
	BEQ	70$		;;;IF EQ NONE
	BITB	#STPRQ,RSTAT(R4) ;;;TERMINATE REQUEST?
	BNE	20$		;;;IF NE YES
	BITB	#RQEFN,RSTAT(R4) ;;;REQUEST EFN SETTING?
	BEQ	10$		;;;IF EQ NO
	BICB	#RQEFN,RSTAT(R4) ;;;CLEAR EFN REQUEST FLAG
	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	MOV	RQPKT(R4),R3	;GET ADDRESS OF I/O PACKET
	MOV	I.TCB(R3),R0	;GET TCB ADDRESS OF REQUESTING TASK
	BIT	#T2.ABO,T.ST2(R0) ;TASK BEING ABORTED?      
	BNE	ENDRQ2		;IF NE YES
	BIS	I.PRM+14(R3),@I.PRM+16(R3) ;SET SPECIFIED EVENT FLAG
	CALL	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST
	BR	ENDRQ2		;TRY AGAIN
20$:	MOV	(R4),(R3)	;;;REMOVE ENTRY FROM QUEUE
30$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
 
 
	.IF DF	L$$SDR
 
	MOV	DATAW(R4),R3	;GET DATA MASK WORD
	COM	R3		;CONVERT MASK TO IN USE BITS
	CMP	#SYNDO,STRST(R4) ;SYNCRHONOUS DIGITAL OUTPUT?
	BEQ	40$		;IF EQ YES
	CMP	#SYNDI,STRST(R4) ;SYNCHRONOUS DIGITAL INPUT
	BNE	50$		;IF NE NO
	BIC	R3,U.CNT(      R5)	;CLEAR INPUT BITS IN USE MASK
	BR	50$		;
40$:	BIC	R3,U.CNT+2(R5)	;CLEAR OUTPUT BITS IN USE MASK
50$:	BITB	#STROT,RSTAT(R4) ;SET DIGITAL OUTPUT BIT ON START?
	BEQ	60$		;IF EQ NO
	BIC	DBMSK(R4),U.CNT+2(R5) ;CLEAR OUTPUT BIT IN USE MASK
 
	.ENDC
 
 
60$:	CLR	R0		;PICKUP FINAL I/O STATUS
	BISB	FINST(R4),R0	;
 
 
	.IF DF	M$$MGE
 
	MOV	KISAR6,-(SP)	;SAVE CURRENT APR6 MAPPING
	MOV	IOSB2(R4),KISAR6  ;MAP TO SECOND I/O STATUS WORD
	
	.IFTF
 
	MOV	@IOSB2+2(R4),R1	;RETRIEVE CONTENTS OF SECOND       I/O STATUS WORD
 
	.IFT
 
	MOV	(SP)+,KISAR6	;RESTORE APR6
	
	.ENDC
 
 
	MOV	RQPKT(R4),R3	;GET ADDRESS OF I/O PACKET
	MOV	R4,-(SP)	;SAVE ADDRESS OF SECONDARY CONTROL BLOCK
	CLR	I.PRM+16(R3)	;CLEAR BLOCK LOCKING WORD FOR $IOFIN
	CALL	$IOFIN		;FINISH I/O OPERATION
	MOV	(SP)+,R0	;RETRIEVE ADDRESS OF SECONDARY CONTROL BLOCK
	MOV	#SLGTH,R1	;SET LENGTH OF SECONDARY CONTROL BLOCK
	CALL	$DEACB		;RELEASE SECONDARY CONTROL BLOCK
	BR	ENDRQ2		;GO AGAIN
 
;
; SCAN OF SAMPLE QUEUE COMPLETE-CHECK IF ANYT      HING IS STILL ACTIVE
;
 
70$:	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET DEVICE TIMEOUT COUNT
	TST	U.BUF(R5)	;;;ANY REQUESTS IN SAMPLE QUEUE
	BNE	80$		;;;IF NE YES
	MOV	S.CSR(R4),R3	;;;GET ADDRESS OF CONTROL STATUS REGISTER
	CLR	(R3)		;;;CLEAR A/D INTERRUPTS
	CLR	4(R3)		;;;CLEAR CLOCK INTERRUPTS
	BICB	#US.BSY,U.STS(R5) ;;;CLEAR UNIT BUSY
	CLRB	S.STS(R4)	;;;CLEAR CONTROLLER BUSY
 
 
	.IF DF	L$$SBF
 
 
	.IF GT	L$$PS1-1
 
	MOVB	S.CON(R4),R1	;;;GET CONTROLLER IN      DEX
	MOV	#377,ADCHN(R1)	;;;INVALIDATE A/D CHANNEL INFO
 
	.IFF
 
	MOV	#377,ADCHN	;;;INVALIDATE A/D CHANNEL INFO
 
	.ENDC
 
	.ENDC
 
 
80$:	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	RETURN			;
 
;
; SUBROUTINE TO READ A VALUE FROM USER BUFFER
;
 
	.ENABL	LSB
 
RDWRD:				;;;REF LABEL
 
 
	.IF DF	M$$MGE
 
	MOV	IOSB2(R3),KISAR6  ;;;MAP TO SECOND I/O STATUS WORD
 
	.IFTF
 
	INC	@IOSB2+2(R3)	;;;INCREMENT FREE POSITIONS IN BUFFER
	CMP	FULBF(R3),@IOSB2+2(R3) ;;;BUFFER OVERRUN?
	BLO	70$		;      ;;IF LO YES
 
	.IFT
 
	MOV	CURBF(R3),KISAR6  ;;;MAP TO USER BUFFER
 
	.IFTF
 
	MOV	@CURBF+4(R3),R2	;;;READ VALUE FROM USER BUFFER
	BR	10$		;;;FINISH IN COMMON CODE
 
;
; SUBROUTINE TO WRITE A VALUE INTO USER BUFFER
;
 
WRWRD:				;;;REF LABEL
 
	.IFT
 
	MOV	IOSB2(R3),KISAR6  ;;;MAP TO SECOND I/O STATUS WORD
 
	.IFTF
 
	INC	@IOSB2+2(R3)	;;;INCREMENT NUMBER OF ENTRIES IN BUFFER
	CMP	FULBF(R3),@IOSB2+2(R3) ;;;BUFFER OVERRUN?
	BLO	70$		;;;IF LO YES
 
	.IFT
 
	MOV	CURBF(R3),KISAR6  ;;      ;MAP TO USER BUFFER
 
	.IFTF
 
	MOV	R2,@CURBF+4(R3)	;;;WRITE VALUE INTO USER BUFFER
10$:	ADD	#2,CURBF+4(R3)	;;;UPDATE USER BUFFER ADDRESS
 
	.IFT
	
	BIT	#20000,CURBF+4(R3) ;;;OVERFLOW 4K BOUNDRY?
	BEQ	20$		;;;IF EQ NO
	BIC	#20000,CURBF+4(R3) ;;;CLEAR OVERFLOW BIT
	ADD	#200,CURBF(R3)	;;;ADVANCE TO NEXT 4K BOUNDRY
	
	.IFTF
 
20$:	DEC	SMCNT(R3)	;;;END OF BUFFER?
	BNE	30$		;;;IF NE NO
 
	.IFT
 
	MOV	STRBF(R3),CURBF(R3) ;;;RESET RELOCATION BIAS
	
	.ENDC
 
 
	MOV	STRBF+4(R3),CURBF+4(R3)       ;;;RESET BUFFER ADDRESS
	MOV	FULBF(R3),SMCNT(R3) ;;;RESET SAMPLE BUFFER COUNT
	BITB	#STPBR,RSTAT(R3) ;;;STOP ON BUFFER RUNOUT?
	BEQ	40$		;;;IF EQ NO
	DEC	SAMCT(R3)	;;;DECREMENT BUFFER COUNT
	BEQ	60$		;;;IF EQ BUFFER RUNOUT
	BR	40$		;;;
30$:	CMP	SMCNT(R3),HAFBF(R3) ;;;EXACTLY AT HALF BUFFER?
	BNE	50$		;;;IF NE NO
40$:	BISB	#RQEFN,RSTAT(R3) ;;;REQUEST EFN SETTING
	INC	FKFLG		;;;SET FORK REQUEST
50$:	CLC			;;;CLEAR OVERRUN INDICATOR
 
 
	.IF DF	L$$SDR
 
	BIT	DSMSK(R3),TEMP	;;;STOP BIT CLEAR?
	      BEQ	90$		;;;IF EQ NO
 
	.IFF
 
	BR	90$		;;;RETURN
 
	.ENDC
 
 
60$:	MOVB	#IS.SUC,FINST(R3) ;;;SET SUCCESSFUL COMPLETION STATUS
	BR	TERMS		;;;
70$:	MOVB	#IE.DAO,FINST(R3) ;;;SET FINAL STATUS TO BUFFER OVERRUN
	DEC	@IOSB2+2(R3)	;;;READJUST BUFFER FREE COUNT
TERMS:	BISB	#STPRQ,RSTAT(R3) ;;;SET TO TERMINATE SAMPLE REQUEST
	MOV	#NXTRQ,STATE(R3) ;;;SET STATE TO TERMINATION IN PROGRESS
	INC	FKFLG		;;;SET FORK REQUEST
	SEC			;;;SET OVERRUN/TERMINATION INDICATOR
90$:	RETURN			;;;
	.DSABL	LSB
 
       
;
; SELECT A/D CHANNEL AND SETUP A DELAY
;
 
 
	.IF DF	L$$SBF
 
SDELAY:	MOVB	(SP),1(R4)	;;;SELECT THE A/D CHANNEL
	MOV	(SP),STKSAV(R3)	;;;SAVE CHANNEL (DATAW) INFO
	MOV	#ENDLAY,STATE(R3)  ;;;SET NEW DISPATCH ADDRESS
 
 
	.IF GT	L$$PS1-1
 
	MOV	DLYCNT(R1),CYCNT(R3)  ;;;SET DELAY COUNT
	MOV	(SP)+,ADCHN(R1)	;;;STORE A/D CHANNEL NUMBER AND
				;;;   DISABLE A/D CONVERSIONS
 
	.IFF
 
	MOV	DLYCNT,CYCNT(R3)  ;;;SET DELAY COUNT
	MOV	(SP)+,ADCHN	;;;STORE A/D CHANNEL NUMBER AND
				;;;   DISABL   ¸  E A/D CONVERSIONS
 
	.ENDC
 
 
	JMP	NXTRQ		;;;DEQUEUE NEXT REQUEST
 
;
; END OF CHANNEL SELECT DELAY PERIOD
;
 
ENDLAY:	MOV	STKSAV(R3),-(SP)  ;;;PUT CHANNEL INFO ON STACK
	MOV	#SYNAD,STATE(R3)  ;;;RESTORE A/D DISPATCH ADDR
 
 
	.IF GT	L$$PS1-1
 
	CLRB	ADFLG(R1)	;;;ENABLE A/D SAMPLING
 
	.IFF
 
	CLRB	ADFLG		;;;ENABLE A/D SAMPLING
 
	.ENDC
 
 
	JMP	ADSMPL		;;;CONTINUE A/D SAMPLING
 
 
	.ENDC
 
 
 
	.END
 ¸         â8"kQ	› c,        	.TITLE	DRRES
	.IDENT	/07.08/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 07.08
;
; D. N. CUTLER 31-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	25-JUL-79
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	5-OCT-79
;		MSH045 -- ADD       DIRECTIVE PARTITION SUPPORT
;
;	M. S. HARVEY	4-JUN-81
;		MSH172 -- BUFFERED I/O STOPFOR STATE CAN ONLY
;			  EXIST AT PRE-AST LEVEL
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,PKTDF$,PCBDF$,TCBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

	.ENABL	LSB

	.IF DF S$$TOP

;+
; **-$DRUNS-UNSTOP TASK
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO UNSTOP A TASK THAT HAS ST      OPPED
; ITSELF VIA A STOP DIRECTIVE OR A RECEIVE OR STOP DIRECTIVE.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(133.),DPB SIZE(3.).
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TASK TO BE UNSTOPPED.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO BE UNSTOPPED.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF       THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS7' IS RETURNED IF THE SPECIFIED
;			TASK IS NOT ACTIVE.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF THE SPECIFIED
;			TASK IS NOT STOPPED, OR STOPPED FOR EVENT
;			FLAG(S) OR BUFFERED I/O.
;-

$DRUNS::TST	(R1)+		;SPECIFIED TASK ACTIVE?
	BMI	20$		;IF MI NO
	MOV	#      T2.STP,R2	;PICK UP STOP BIT			;MSH046
	BIT	#T2.SEF,(R1)	;TASK IN A STOPFOR STATE?		;MSH046
	BNE	30$		;IF NE YES				;MSH046
									;MSH046
	.IF DF	T$$BUF							;MSH046
									;MSH046
	TSTB	T.TIO(R0)	;OUTSTANDING BUFFERED I/O?		;MSH046
	BEQ	5$		;IF EQ NO, UNSTOP TASK			;MSH046
	MOV	#T2.AST!T2.WFR,R3 ;GET STOPFOR TEST MASK		;MSH172
	BIT	R3,(R1)		;TASK AT AST STATE?			;MSH172
	BPL	3$		;IF PL NO				;MSH172
	ASL	R3		;CONVERT TO PRE-AST WFR MASK		;MSH172
	BIT	R3,(R1)		;TASK IN BUFFERED I/O STOPFOR       STATE?	;MSH172
3$:	BNE	30$		;IF NE TASK IN STOPFOR STATE		;MSH172
									;MSH046
	.ENDC								;MSH046
									;MSH046
	BR	5$		;UNSTOP THE TASK			;MSH046
									;**-4
	.IFTF	;S$$TOP

;+
; **-$DRRES-RESUME TASK EXECUTION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO RESUME THE EXECUTION OF A TASK THAT
; HAS ISSUED A SUSPEND DIRECTIVE.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(47.),DPB SIZE(3.).
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;
; INPUTS:
;
;	R0=ADDR      ESS OF THE TCB OF THE TASK TO BE RESUMED.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO BE RESUMED.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF '      D.RS7 IS RETURNED IF THE SPECIFIED
;			TASK IS NOT ACTIVE.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF THE SPECIFIED
;			TASK IS NOT SUSPENDED.
;-

$DRRES::TST	(R1)+		;TASK ACTIVE?
	BMI	20$		;IF MI NO
	MOV	#T2.SPN,R2	;GET SUSPEND BIT
5$:	BIT	R2,(R1)		;TASK CURRENTLY SUSPENDED?
	BNE	10$		;IF NE YES
	TST	(R1)		;AST IN PROGRESS?
	BPL	30$		;IF PL NO
	ASL	R2		;SET PRE AST SUSPEND BIT
	BIT	R2,(R1)		;WAS TASK SUSPENDED?
	BEQ	30$		;IF EQ NO

10$:				;REF LABEL

	.IFT	;S$$TOP

	CMPB	$DICSV,#13      3.	;IS THIS AN UNSTOP DIRECTIVE?
	BEQ	15$		;IF EQ YES

	.IFTF	;S$$TOP

	BIC	R2,(R1)		;CLEAR TASK'S SUSPEND BIT
	CALLR	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST

	.IFT	;S$$TOP

15$:	CALLR	$EXRQN		;UNSTOP SPECIFIED TASK

	.IFTF	;S$$TOP

20$:	DRSTS	D.RS7		;SET DIRECTIVE STATUS
30$:	DRSTS	D.RS8		;SET DIRECTIVE STATUS


	.IFT	;S$$TOP

;+
; **-$DRSTP-STOP TASK
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO STOP THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(131.),DPB SIZE(1.).
;
;       INPUTS:
;
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF 'D.RS22' IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF THE ISSUING
;			TASK IS AT AST STATE.
;-

$DRSTP::TST	(R2)	      	;IS ISSUING TASK AT AST STATE?
	BMI	33$		;IF MI YES
	CALL	$STPCT		;STOP ISSUING TASK
	DRSTS	D.RS22		;RETURN SUCCESS WITH +2
33$:	DRSTS	D.RS80		;ISSUING TASK IS AT AST STATE

	.ENDC	;S$$TOP

;+
; **-$DRSPN-SUSPEND EXECUTION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SUSPEND THE EXECUTION OF THE ISSUING
; TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(45.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDR   x  ESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF 'D.RS22'.
;-

$DRSPN::BIS	#T2.SPN,(R2)	;SUSPEND CURRENT TASK
	CALL	$SETRT		;FORCE A REDISPATCHING OF PROCESSOR
	DRSTS	D.RS22		;SET DIRECTIVE STATUS

									;**-156
	.DSABL	LSB

	.END
x         $ðskQ	› c,        	.TITLE	DTDRV
	.IDENT	/08.02/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 08.02
;
; D. N. CUTLER 1-DEC-73
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	F. L. STRAIGHT
;
; MODIFIED BY:
;
;	E. L. BAATZ 18-JUN-78
;
;	DAN BROWN	20-JAN-81
;
;		DTB013 -- REMOVE REFEREN      CES TO S.BMSK FOR NEW
;			ERROR LOG.
;
; TC11 DECTAPE CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$,HWDDF$,PKTDF$
	ABODF$			;DEFINE TASK ABORT CODES
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;

WAIT=100000			;WAITING TO SELECT UNIT (1=YES)
ABRT=40000			;ABORT CURRENT FUNCTION (1=YES)
RETRY=5.			;ERROR RETRY COUNT


	.IF DF  D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

	.ENDC


;
;       LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
; DIAGNOSTIC FUNCTIONS IO.RNF AND IO.RNR USE BIT 7 OF RTTBL AS
; A FLAG FOR INTERRUPT SERVICING.

CNTBL:	.BLKW	T$$C11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	T$$C11		;ERROR RETRY COUNT AND DRIVE RESET FLAG


	.IF GT	T$$C11-1

TEMP:	.BLKW	1		;TEMPORY STORAGE FOR CONTROLLER NUMBER

	.ENDC

;
; DRIVER DISPATCH TABLE
;

$DTTBL::.WORD	DTINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DTCAN		;CANCEL I/O OPER      ATION ENTRY POINT
	.WORD	DTOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DTPWF		;POWERFAIL ENTRY POINT

;+
; **-DTINI-TC11 DECTAPE CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSF      UL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
DTINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	DTPWF		;IF CS CONTROLLER BUSY OR NO REQUEST

;
; THE FOLLOWING ARGUMENTS ARE RETU      RNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R3=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; TC11 DECTAPE I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS       OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB,IO.RLV,IO.WLB, OR IO.WLV).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15       -- NOT USED.
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED.
;	WD. 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLK. ADDRESS
;	WD. 21 -- DIAGNOSTIC REG. BLK. ADDRESS (REAL OR DISPL. + 140000)
;

	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB


	.IF DF	M$$EXT&M$$MGE

	CALL	$STMAP		;SET UP UNIBUS MAPPING ADDRESS

	.ENDC


	MOV	#<8.*256.>+RETRY,RTTBL(R3) ;SET ROCK AND RETRY COUNTS


	.IF DF  D$$IAG

	MOV	R1,R0		;COPY I/O PACKET ADDRE      SS
	ADD	#I.FCN,R0	;POINT TO FUNCTION CODE
	BITB	#IQ.UMD,(R0)	;DIAGNOSTIC FUNCTION CALL?
	BEQ	4$		;IF EQ NO
	CLRB	RTTBL(R3)	;NO RETRIES FOR DIAGNOSTIC OPERATIONS
	CMP	#IO.RNF!IQ.UMD,(R0)  ;READ BLOCK FORWARD?
	BNE	2$		;IF NE NO
	MOV	#IO.RLB!IQ.UMD,(R0)  ;CONVERT TO READ LOGICAL FORWARD
	BR	3$		;
2$:	CMP	#IO.RNR!IQ.UMD,(R0)  ;READ BLOCK REVERSE?
	BNE	4$		;IF NE NO
	MOV	#IO.RLV!IQ.UMD,(R0)  ;CONVERT TO READ LOGICAL REVERSE
3$:	BIS	#200,RTTBL(R3)	;SET READ BLOCK NUMBER FLAG

	.ENDC


4$:	MOV	#I      E.IFC&377,R0	;ASSUME ILLEGAL FUNCTION
	MOV	R5,R3		;COPY ADDRESS OF UCB
	ADD	#U.BUF+1,R3	;POINT TO HIGH BYTE OF MEM.EXT WORD
	MOVB	R2,(R3)		;INSERT DRIVE NUMBER
	BISB	#105,-(R3)	;ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/256.,I.FCN+1(R1)  ;READ LOGICAL FUNCTION?
	BHIS	5$		;IF HIS FUNCTION IS LEGAL
	JMP	195$		;ILLEGAL FUNCTION
5$:	BEQ	10$		;IF EQ FUNCTION IS READ
	BIS	#10,(R3)	;CONVERT TO WRITE LOGICAL FUNCTION
10$:	BIT	#IO.WLV&377,I.FCN(R1)  ;REVERSE DIRECTION?
	BEQ	20$		;IF EQ NO
	BIS	#4000,(R3      )	;SET REVERSE DIRECTION BIT
20$:	CLRB	U.CW2+1(R5)	;CLEAR ABORT FLAG
	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER
	MOV	R0,U.VCB+2(R5)	;SAVE LOGICAL BLOCK NUMBER

;
; INITIATE I/O OPERATION
;

30$:				;REF LABEL


	.IF DF	M$$EXT&M$$MGE

	CALL	$MPUBM		;MAP UNIBUS TO TRANSFER

	.ENDC


	MOV	S.CSR(R4),R0	;GET ADDRESS OF CSR
	CMP	(R0)+,(R0)+	;POINT TO BUFFER ADDRESS REGISTER
	MOV	U.BUF+2(R5),(R0) ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R0) ;INSERT LENGTH OF TRANSFER IN BYTES
	CLR	U.VCB+4(R5)	      ;CLEAR FINAL ERROR STATUS
	ROR	(R0)		;CONVERT LENGTH TO WORD COUNT
	NEG	(R0)		;MAKE NEGATIVE WORD COUNT
	MOVB	U.BUF+1(R5),-(R0) ;INSERT UNIT AND DIRECTION BIT
	BIS	#WAIT,U.CW2(R5)	;SET WAITING TO SELECT UNIT
	MOVB	#11,-(R0)	;STOP TRANSPORT (SELECT UNIT)
35$:	BIT	#100200,(R0)	;SELECT ERROR?
	BMI	40$		;IF MI YES
	BEQ	35$		;IF EQ DRIVE NOT SELECTED
	BIC	#WAIT,U.CW2(R5)	;CLEAR WAITING TO SELECT UNIT
	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	MOVB	#103,(R0)	;START SEARCH FOR BLOCK.
      
;
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION.
;

DTPWF:	RETURN			;

;
; OUTPUT SELECT ERROR MESSAGE
;

40$:	MOV	#T.NDSE,R0	;SET FOR DEVICE SELECT ERROR MESSAGE
	MOVB	#1,S.CTM(R4)	;RESET CURRENT DEVICE TIMEOUT COUNT
	DECB	S.STS(R4)	;TIME TO OUTPUT MESSAGE?
	BNE	DTPWF		;IF NE NO
	MOVB	#15.,S.STS(R4)	;SET TO OUTPUT NEXT MESSAGE IN 15.       SECONDS
	CALLR	$DVMSG		;OUTPUT MESSAGE

;
; CANCEL I/O OPERATION - FORCE I/O TO COMPLETE IF DEVICE NOT READY
;

DTCAN:	CMP	R1,I.TCB(R0)	;;;REQUEST FOR CURRENT TASK?
	BNE	50$		;;;IF NE NO
	BIS	#ABRT,U.CW2(R5)	;;;SET FOR ABORT IF DEVICE NOT READY
50$:	RETURN			;;;

;
; DEVICE TIMEOUT USUALLY OCCURS BECAUSE THE DRIVER IS WAITING TO
; SELECT A UNIT. TIMEOUTS MAY ALSO OCCUR AS A RESULT OF A HARDWARE
; FAILURE OR A POWERFAILURE.
;

DTOUT:				;REF LABEL


	.IF DF  D$$IAG

	MOV	S.PKT(R4),R1	;      ;;GET I/O PACKET ADDRESS
	BITB	#IQ.UMD,I.FCN(R1) ;;;DIAGNOSTIC FUNCTION CALL?
	BNE	165$		;;;IF NE YES

	.ENDC


	MOV	U.CW2(R5),R1	;;;WAITING TO SELECT A UNIT?
	BMI	55$		;;;IF MI YES
	CALL	$DTOER		;;;LOG DEVICE TIMEOUT
55$:	MTPS	#0		;;;ALLOW DEVICE INTERRUPTS
	MOV	#IE.ABO&377,R0	;ASSUME REQUEST IS TO BE ABORTED
	ASL	R1		;ABORT REQUEST?
	BPL	30$		;IF PL NO


	.IF DF  D$$IAG

	JMP	190$		;ABORT REQUEST

	.IFF

	BR	190$		;

	.ENDC


;+
; **-$DTINT-TC11 DECTAPE CONTROLLER INTERUPTS
;-      

	INTSE$	DT,PR6,T$$C11	;;;SAVE REGISTERS AND SET PRIORITY
	MOV	R3,-(SP)	;;;SAVE R3
	MOV	U.SCB(R5),R3	;;;GET ADDRESS OF STATUS CONTROL BLOCK
	MOVB	S.ITM(R3),S.CTM(R3) ;;;RESET CURRENT DEVICE TIMEOUT COUNT
	MOV	S.CSR(R3),R3	;;;GET ADDRESS OF COMMAND REGISTER


	.IF DF  D$$IAG

	TSTB	RTTBL(R4)	;DIAGNOSTIC READ BLOCK NO.?
	BMI	150$		;IF MI YES

	.ENDC


	BIT	#2,(R3)		;;;BLOCK SEARCH IN PROGRESS?
	BEQ	150$		;;;IF EQ NO
	TST	(R3)		;;;SEARCH ERROR?
	BPL	70$		;;;IF PL NO
	TST	-(R3)		;;;END ZON      E?
	BMI	110$		;;;IF MI YES
	BIT	#20000,(R3)+	;;;MARK TRACK ERROR?
	BNE	120$		;;;IF NE YES-TRY TO BYPASS IT
60$:	MOV	#100000,U.VCB+4(R5) ;;;SET UNRECOVERABLE ERROR
	BIC	#100,(R3)	;;;CLEAR INTERRUPT ENABLE
	BR	160$		;;;
70$:	MOV	6(R3),-(SP)	;;;GET CURRENT BLOCK NUMBER
	CMPB	U.BUF+1(R5),1(R3) ;;;MOVING IN FINAL DIRECTION?
	BNE	80$		;;;IF NE NO
	CMP	(SP),U.VCB+2(R5) ;;;BLOCK NUMBER MATCH?
	BEQ	130$		;;;IF EQ YES
80$:	BIT	#4000,(R3)	;;;MOVING IN FORWARD DIRECTION?
	BEQ	90$		;;;IF EQ YES
	ADD	#2,(SP      )		;;;ADD TURN AROUND BIAS
	CMP	U.VCB+2(R5),(SP)+ ;;;TURN AROUND NECESSARY?
	BR	100$		;;;
90$:	SUB	#2,(SP)		;;;SUBTRACT TURN AROUND BIAS
	CMP	(SP)+,U.VCB+2(R5) ;;;TURN AROUND NECESSARY?
100$:	BLE	120$		;;;IF LE NO
	TST	-(R3)		;;;POINT TO ERROR REGISTER
110$:	TST	(R3)+		;;;POINT TO COMMAND REGISTER
	DECB	RTTBL+1(R4)	;;;DRIVE HUNG?
	BLT	60$		;;;IF LT YES
	MOV	#4000,-(SP)	;;;GET DIRECTION BIT
	BIC	(R3),(SP)	;;;.NOT.COMMAND REGISTER.AND.DIRECTION BIT
	BIC	#4000,(R3)	;;;.NOT.DIRECTION BIT.AND.COMMAND       REGISTER
	BIS	(SP)+,(R3)	;;;DIRECTION BIT.OR.COMMAND REGISTER
120$:	INC	(R3)		;;;CONTINUE SEARCH
	BR	140$		;;;
130$:	TST	(SP)+		;;;REMOVE BLOCK NUMBER FROM STACK

	MOV	U.BUF(R5),(R3)	;;;START READ/WRITE FUNCTION		;**-8
140$:	MOV	(SP)+,R3	;;;RESTORE R3
	RETURN			;;;
150$:	BICB	#100,(R3)	;;;CLEAR INTERRUPT ENABLE
	TST	(R3)		;;;ANY ERRORS?
	BPL	160$		;;;IF PL NO ERRORS
	MOV	-(R3),U.VCB+4(R5) ;;;SAVE ERROR STATUS
160$:	MOV	(SP)+,R3	;;;RESTORE R3
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3      		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF STATUS CONTROL BLOCK
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL COMPLETION


	.IF DF  D$$IAG

	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL?
165$:	BNE	180$		;IF NE YES

	.ENDC


	MOV	U.VCB+4(R5),R2	;RETRIEVE ERROR STATUS
	BEQ	180$		;IF EQ SUCCESS

	.IF DF	E$$DVC							; DTB013
									;**-1
	CALL	$DVERR		;LOG DEVICE ERROR

	.IFTF

	BIT	#63000,R2	;RECOVERABLE ERROR?
	BEQ	170$		;IF EQ       NO
	DECB	RTTBL(R3)	;ANY MORE RETRIES?
	BLE	170$		;IF LE NO
	MOVB	#8.,RTTBL+1(R3) ;RESET ROCK COUNT
	JMP	30$		;TRY AGAIN
170$:	MOV	#IE.WLK&377,R0	;ASSUME DRIVE WRITE LOCKED
	BIT	#10000,R2	;DRIVE WRITE LOCKED?
	BNE	180$		;IF NE YES
	MOV	#IE.VER&377,R0	;UNRECOVERABLE ERROR
180$:	MOV	S.CSR(R4),R2	;GET ADDRESS OF COMMAND REGISTER


	.IF DF  D$$IAG

185$:	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL?
	BEQ	187$		;IF EQ NO
	CALL	$CRPAS		;PASS UNIBUS DEV      ICE REGISTERS
187$:				;REF. LABEL

	.ENDC


	MOV	U.CNT(R5),R1	;GET ORIGINAL BYTE COUNT
	ADD	2(R2),R1	;CALCULATE NUMBER OF BYTES TRANSFERED
	ADD	2(R2),R1	;
190$:	MOVB	#11,(R2)	;STOP TAPE MOTION

	.IFT

	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE STARTING RETRY COUNT

	.ENDC


195$:	CALL	$IODON		;FINISH I/O OPERATION
	JMP	DTINI		;GO AGAIN
	.DSABL	LSB

	.END

          „fðskQ	› c,        	.TITLE	PPDRV
	.IDENT	/02.01/
 
;
; COPYRIGHT (C) 1975, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 02.01
;
; THOMAS J. MILLER 25-NOV-74
;
; PREVIOUSLY MODIFIED BY:
;
;	C. A. D'ELIA
;	T. J. MILLER
;
; MODIFIED BY:
;
;	E. L. BAATZ 18-JUN-78
;
;		EB148 -- REMOVE EXPLICIT PS REFERENCE
;
; PC11 PAPER TAPE PUNCH DRIVER
;
; MACRO LIBRARY CALL      S
;
 
	.MCALL	ABODF$,HWDDF$,PKTDF$,TCBDF$
	ABODF$			;DEFINE TASK ABORT CODES
	HWDDF$			;DEFINE HARDWARE REGISTER SYMBOLS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
 
;
; EQUATED SYMBOLS
;
; PAPER TAPE PUNCH STATUS WORD BIT DEFINITIONS (U.CW2)
;
 
WAIT=100000			;WAITING FOR DEVICE TO COME ON-LINE (1=YES)
ABORT=40000			;ABORT CURRENT I/O REQUEST (1=YES)
TRAIL=200			;CURRENTLY PUNCHING TRAILER (1=YES)
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLE      S (INDEXED BY CONTROLLER NUMBER)
;
 
CNTBL:	.BLKW	P$$P11		;ADDRESS OF UNIT CONTROL BLOCK
 
 
	.IF GT	P$$P11-1
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER
 
	.ENDC
 
	
;
; DRIVER DISPATCH TABLE
;
 
$PPTBL::.WORD	PPINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	PPCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	PPOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	PPPWF		;POWERFAIL ENTRY POINT
 
;+
; **-PPINI-PC11 PAPER TAPE PUNCH CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QU      EUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF       THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-
 
	.ENABL	LSB
PPINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	PPPWF		;IF CS CONTROLLER BUSY OR NO REQUEST
 
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF       THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; PAPER TAPE PUNCH I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.WLB, IO.ATT OR IO.DET).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION       BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCATION BIAS OF I/O BUFFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
	MOV	R5,CNTBL(R3)	;SAVE UCB POINTER FOR INTERRUPT ROUTINE
	CLR	U.CW2(R5)	;CLEAR ALL SWITCHES
	CMPB	I.FCN+1(R1),#IO.WLB/256.       ;WRITE LOGICAL BLOCK FUNCTION?
	BEQ	10$		;IF EQ YES
	MOV	I.TCB(R1),R0	;GET REQUESTOR TCB ADDRESS
	BIT	#T2.ABO,T.ST2(R0) ;TASK BEING ABORTED?
	BNE	65$		;IF NE YES - DON'T PUNCH TRAILER
	BIS	#TRAIL,U.CW2(R5) ;OTHERWISE FUNCTION IS ATTACH OR DETACH
				 ;   SET FLAG TO PUNCH TRAILER
	MOV	#170.,U.CNT(R5)	;SET COUNT FOR 170 NULLS
10$:	BIS	#WAIT,U.CW2(R5)	;ASSUME WAIT FOR DEVICE OFF LINE
	TST	@S.CSR(R4)	;DEVICE OFF LINE?
	BMI	80$		;IF MI YES
20$:	BIC	#WAIT,U.CW2(R5)	;DEVICE ON LINE, CLEAR WAIT CONDITIO      N
	MOVB	S.ITM(R4),S.CTM(R4) ;SET TIMEOUT COUNT
	MOV	#100,@S.CSR(R4)	;ENABLE INTERRUPTS
 
;
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION
;
 
PPPWF:	RETURN			;
 
;+
; **-$PPINT-PC11 PAPER TAPE PUNCH CONTROLLER INTERUPTS
;-
 
$PPINT::			;;;REF LABEL
	INTSV$	PP,PR4,P$$P11	;;;GENERATE INTERRUPT SAVE CODE
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF       STATUS CONTROL BLOCK
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
	MOV	S.CSR(R4),R4	;;;POINT R4 TO CONTROL STATUS REGISTER
	MOV	(R4)+,U.CW3(R5)	;;;SAVE STATUS
	BMI	60$		;;;IF MI, ERROR
	SUB	#1,U.CNT(R5)	;;;DECREMENT CHARACTER COUNT
	BCS	50$		;;;IF CS, THEN DONE
	TSTB	U.CW2(R5)	;;;CURRENTLY PUNCHING TRAILER?
	BPL	30$		;;;IF PL NO
	CLRB	(R4)		;;;LOAD NULL INTO OUTPUT REGISTER
	BR	40$		;;;BRANCH TO LOAD IT
30$:	CALL	$GTBYT		;;;GET NEXT BYTE FROM USER BUFFER
	MOVB	(SP)+,(R4)	;;;LOAD BYTE INTO O      UTPUT REGISTER
40$:	JMP	$INTXT		;;;EXIT FROM INTERRUPT
50$:	INC	U.CNT(R5)	;;;RESET BYTE COUNT
60$:	CLR	-(R4)		;;;DISABLE PUNCH INTERRUPTS
	CALL	$FORK		;;;CREATE SYSTEM PROCESS
	MOV	U.SCB(R5),R4	;POINT R4 TO SCB
	MOV	S.PKT(R4),R1	;POINT R1 TO I/O PACKET
	MOV	I.PRM+4(R1),R1	;   AND PICK UP CHARACTER COUNT
	SUB	U.CNT(R5),R1	;CALCULATE CHARACTERS TRANSFERRED
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER
	TST	U.CW3(R5)	;DEVICE ERROR?
	BPL	70$		;IF PL NO
65$:	MOV	#IE.VER&377,R0	;UNRECOVERABLE HARDWA      RE ERROR CODE
70$:	CALL	$IODON		;INITIATE I/O COMPLETION
	BR	PPINI		;BRANCH BACK FOR NEXT REQUEST
 
;
; DEVICE TIMEOUT RESULTS IN A NOT READY MESSAGE BEING PUT OUT 4 TIMES A
; MINUTE. TIMEOUTS ARE CAUSED BY POWERFAILURE AND PUNCH FAULT CONDITIONS.
;
 
PPOUT:	CLRB	@S.CSR(R4)	;;;DISABLE PUNCH INTERRUPT
	MTPS	#0		;;;ALLOW INTERRUPTS
80$:	MOV	#IE.DNR&377,R0	;ASSUME DEVICE NOT READY ERROR
	MOV	U.CW2(R5),R1	;ARE WE WAITING FOR DEVICE READY?
	BPL	70$		;IF PL NO, TERMINATE I/O REQUEST
	MOV	#IE.ABO&377      ,R0	;ASSUME REQUEST IS TO BE ABORTED
	ASL	R1		;ABORT REQUEST?
	BMI	70$		;IF MI YES
	TST	@S.CSR(R4)	;PUNCH READY?
	BPL	20$		;IF PL YES
	MOV	#T.NDNR,R0	;SET FOR NOT READY MESSAGE
	MOVB	#1,S.CTM(R4)	;SET TIMEOUT FOR 1 SECOND
	DECB	S.STS(R4)	;TIME TO OUTPUT MESSAGE?
	BNE	PPPWF		;IF NE NO
	MOVB	#15.,S.STS(R4) ;SET TO OUTPUT NEXT MESSAGE IN 15. SECONDS
	CALLR	$DVMSG		;OUTPUT MESSAGE
	.DSABL	LSB
 
;
; CANCEL I/O OPERATION-FORCE I/O TO COMPLETE IF DEVICE IS NOT READY
;
 
PPCAN:	CMP	R1,I.TCB(R0)	;;;   Œ   REQUEST FOR CURRENT TASK?
	BNE	10$		;;;IF NE NO
	BIS	#ABORT,U.CW2(R5) ;;;SET FOR ABORT IF DEVICE NOT READY
10$:	RETURN			;;;
 
	.END
 Œ          ‘ xkQ	› c,        	.TITLE	CRASH
	.IDENT	/05.20/
;
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 05.20
;
; J. MASSE / P. J. BEZEREDI  24-OCT-77
;
; PREVIOUSLY MODIFIED BY:
;
;	M. B. GROSSMAN
;	A. PROTIN
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	2-JUL-79
;		MSH038 -- DON'T WASTE 159. WORDS IF PANIC DUMP
;			  SUPPORT IS       CHOSEN OVER CDA SUPPORT
;
;	M. S. HARVEY	2-JUL-79
;		MSH039 -- DON'T RELY ON NXM TRAPS TO STOP RL11
;			  MEMORY DUMPING FOR QBUS MACHINES
;
;	M. S. HARVEY	7-SEP-79
;		MSH054 -- CLEAN UP AND IMPROVE DOCUMENTATION
;
;	M. S. HARVEY	7-SEP-79
;		MSH055 -- DON'T ALLOW DUMPING OFF THE END OF RK05
;
;	M. S. HARVEY	7-SEP-79
;		MSH056 -- SHORTEN SETTLING TIME FOR MT:
;
;	M. S. HARVEY	9-SEP-79
;		MSH057 -- PREVENT RK06 ROUTINE FROM CORRUPTING THE
;			  DISK BY A NXM TRAP
;
;	M. S. HARVEY	9-SEP-79
      ;		MSH058 -- WRITE MEMORY TO TU58 IN 1K WORD SEGMENTS
;			  AND DO NOT ATTEMPT TO CLEAR R-ONLY REGISTER
;
;	M. S. HARVEY	9-SEP-79
;		MSH059 -- FIX TS04 BUGS
;
;	M. S. HARVEY	9-SEP-79
;		MSH060 -- CATCH NXM TRAPS FROM CPUS WHERE THE MEMORY
;			  SIZE REGISTER IS SET HIGHER THAN THE TOP
;			  OF MEMORY
;
;	M. S. HARVEY	2-JUN-80
;		MSH101 -- ENSURE THAT CURRENT MODE IS KERNEL AND
;			  PREVIOUS MODE IS USER BEFORE ATTEMPTING
;			  TO READ THE USER MODE STACK POINTER
;
;	M. S. HARVEY	20-AUG-80
      ;		MSH112 -- GLOBALLY DEFINE TRAP INTERCEPT ROUTINE
;
;	M. S. HARVEY	22-AUG-80
;		MSH113 -- USE UMR#1 FOR TS11 MEMORY DUMPING
;
;	M. S. HARVEY	13-NOV-80
;		MSH125 -- GLOBALIZE $CRALT
;
;	M. S. HARVEY	3-MAR-81
;		MSH154 -- CONSOLIDATE POWERFAIL AND CRASH STACKS
;
;	P. J. CARR	13-MAR-81
;		PJC015 -- ADD RX01/02 SUPPORT
;
;	R. T. PERRON	22-JUL-81
;		RP066 -- CORRECT CRASHING OF EXTENDED MEMORY SYSTEMS 
;			THRU CONTROLLERS WITHOUT BAE REGISTERS
;
;	R. T. PERRON	22-JUL-81
;		RP067 -- CORRECT       CONDITIONALIZATION OF TS11 CRASH 
;			 DRIVER TO WORK IN UNMAPPED SYSTEMS
;
;	M. S. HARVEY	27-JUL-81
;		MSH181 -- PROVIDE POWERFAIL STACK SPACE FOR SAVING THE
;			  BPT/T-BIT VECTOR ON LSI11/02 PROCESSORS
;
;	M. S. HARVEY	6-NOV-81
;		MSH203 -- ENSURE MULTIPLE DUMP CAPABILITY ON RLV12
;
;	P. J. CARR	23-NOV-81
;		PJC040 -- CORRECT CRASHING TO RX02 FLOPPY DRIVE UNIT #1
;
;
; CRASH DUMP ROUTINES
;


	.IF DF	C$$RSH

;
; MACRO LIBRARY CALLS
;
	.MCALL	HWDDF$
	HWDDF$

;
; LOCAL DATA
;
      
;
;
$CRUPC::.WORD	0		; USER PC IS STORED HERE
$CRUST::.WORD	0		; USER PS IS STORED HERE

	.IF DF	C$$CDA

	.NLIST	BEX							; RP066
									;MSH203
	.IIF EQ	C$$CDA-5	ILDVM=0					;MSH203
	.IIF EQ C$$CDA-11	ILDVM=0					;MSH203
									;MSH203
	.IF DF	ILDVM							;MSH203
									;MSH203
ILDEV:	.ASCIZ	<15><12><12>/CRASH -- ILLEGAL CRASH DEVICE/		;MSH203
									;MSH203
	.ENDC								;MSH203
									;MSH203
IOERR:	.ASCIZ	<15><12><12>! I/O DEVICE ERROR!
CRSMSG:	.ASCII	<15><12><12>/CRASH --       CONT WITH SCRATCH MEDIA ON /

.IIF EQ C$$CDA-1,	.ASCII	/DT/
.IIF EQ C$$CDA-2,	.ASCII	/DK/
.IIF EQ C$$CDA-3,	.ASCII	/MT/
.IIF EQ C$$CDA-4,	.ASCII	/MM/
.IIF EQ C$$CDA-5,	.ASCII  /DB/
.IIF EQ C$$CDA-6,	.ASCII  /DM/
.IIF EQ C$$CDA-7,	.ASCII  /DL/
.IIF EQ C$$CDA-10,	.ASCII  /DD/
.IIF EQ C$$CDA-11,	.ASCII  /DR/
.IIF EQ C$$CDA-12,	.ASCII  /MS/
.IIF EQ	C$$CDA-13,	.ASCII	/DX/					; PJC015
.IIF EQ	C$$CDA-14,	.ASCII	/DY/					; PJC015

UNIT:	.ASCIZ	/0/<15><12><12>
	.EVEN
	.LIST	BEX							; RP066
				      					;MSH203
	.IF EQ	C$$CDA-4						;MSH203
									;MSH203
CRBAE:	.WORD	C$$CSR+34	;BUS ADDRESS EXTENSION REGISTER ADDR.	;MSH203
									;MSH203
	.ENDC								;MSH203
									;MSH203
	.IF DF	ILDVM							;MSH203
									;MSH203
CRBAE:	.WORD	C$$CSR+50	;BUS ADDRESS EXTENSION REGISTER ADDR.	;MSH203
									;MSH203
	.ENDC								;MSH203

	.ENDC


	.IF DF	C$$TTY

	.NLIST	BEX							; RP066
MSG1:	.ASCIZ	<15><12><12>/SYSTEM CRASH AT LOCATION /
MSG2:	.ASCII	<15><12><12>/REGISTERS/<15><12><12>      
	.ASCIZ	/ R0=/
MSG3:	.ASCIZ	/R1=/
MSG4:	.ASCIZ	/R2=/
MSG5:	.ASCIZ	/R3=/
MSG6:	.ASCIZ	<15><12><12>/ R4=/
MSG7:	.ASCIZ	/R5=/
MSG8:	.ASCIZ	/SP=/
MSG9:	.ASCIZ	/PS=/<0>
MSG10:	.ASCII	<15><12><12>/SYSTEM STACK DUMP/
	.ASCIZ	<15><12><12>/ LOCATION CONTENTS/<15><12><12>
	.EVEN
	.LIST	BEX							; RP066

	.ENDC


				; *** THE FOLLOWING MUST BE ADJACENT
$CRPBF::.BLKW	4		;STACK AREA FOR SUBROUTINE CALLS
$CRSBF::.BLKW	14.		;INTERNAL CRASH STACK ...
$CRPST::			;TOP OF PANIC STACK

	.IF DF C$$CDA			      				;MSH038

	.IF DF	M$$MGE

	.BLKW	159.		;... MAPPED STACK IS THIS LARGE

	.IFF								;MSH154
									;MSH154
	UNMAP=0			;ALLOCATE POWERFAIL STACK IF NECESSARY	;MSH154
									;MSH154
	.ENDC	;M$$MGE							;MSH154
									;MSH154
	.IFF								;MSH154
									;MSH154
	UNMAP=0			;ALLOCATE POWERFAIL STACK IF NECESSARY	;MSH154
									;MSH154
	.ENDC	;C$$CDA							;MSH154
									;MSH154
	.IF DF UNMAP&P$$RFL						;MSH154
									;MSH154
.=$CRPBF			;RESET TOP OF POWERFAIL STACK		;MSH15      4
									;MSH154
	.BLKW	7		;R0 THRU R5 AND SP			;MSH154
									;MSH181
	.IF DF	L$$SI1							;MSH181
									;MSH181
	.BLKW	1		;SAVED BPT/T-BIT VECTOR CONTENTS	;MSH181
									;MSH181
	.ENDC								;MSH181
									;MSH154
	.IF DF	M$$MGE							;MSH154
									;MSH154
	.IF DF	M$$EXT							;MSH154
									;MSH154
	.BLKW	<31.-5.>*2	;UNIBUS MAPPING REGISTERS		;MSH154
									;MSH154
	.ENDC								;MSH154
									;MSH154
	.BLKW	25.		;MEMORY MANAGEMENT REGISTERS		;MSH154
									;MSH1      54
	.IFF								;MSH154
									;MSH154
	.IF DF	E$$EAE							;MSH154
									;MSH154
	.BLKW	3		;EAE REGISTERS				;MSH154
									;MSH154
	.ENDC								;MSH154
									;MSH154
	.ENDC								;MSH154
									;MSH154
	.IF DF	F$$LPP							;MSH154
									;MSH154
	.BLKW	27.		;FLOATING POINT REGISTERS		;MSH154
									;MSH154
	.ENDC								;MSH154
									;MSH154
	.ENDC	;UNMAP&P$$RFL						;MSH154
									;MSH154
									;MSH154
	.IF DF	C$$CDA							;MSH154
									;**-2
$CRSST==.-2      			;TOP OF CRASH STACK
				; *** ABOVE MUST BE ADJACENT

									;**-2
$CRSBN::.WORD	PBNH,PBNL	;STARTING DEVICE ADDRESS
$CRSCS::.WORD	PBNH+PBNL	;CHECKSUM OF DEVICE ADDRESS

;
; LOCAL MACROS
;
	.MACRO	PUSH	ARG
	SUB	#2,SP
	MOV	ARG,(SP)
	.ENDM	PUSH

	.ENDC


	.ENDC

;+									;MSH112
; **-$TRINT-TRAP INTERCEPT ROUTINE					;MSH112
;									;MSH112
; THE ENTRY POINT OF THIS ROUTINE IS USED TO PLUG VECTORS TO TRAP	;MSH112
; ANY TRAPS THROUGH 4, ILLEGAL INSTRUCTION TRAPS, ETC.			;MSH112      
;									;MSH112
; INPUTS:								;MSH112
;									;MSH112
;	NONE								;MSH112
;									;MSH112
; OUTPUTS:								;MSH112
;									;MSH112
;	2(SP) = PS OF TRAP. THIS ROUTINE SETS THE C-BIT, THEN		;MSH112
;		RETURNS FROM THE TRAP WITH AN RTI.			;MSH112
;-									;MSH112
									;MSH112
$TRINT::BIS	#1,2(SP)	;SET CARRY IN TRAP PS			;MSH112
	RTI			;RETURN FROM TRAP			;MSH112
									;MSH112

;+
; **-$CRASH-SYSTEM CRASH DUMP ROUTINE
;
; THIS ROUTINE IS ENTERED VIA A JUMP WHENEVER A FA      TAL SYSTEM ERROR
; (IOT) IS DETECTED.
;
; THIS ROUTINE PERFORMS A MEMORY DUMP THAT CAN BE DIRECTED TO A
; HARD COPY DEVICE, DECTAPE, RK05, TU10, TU/E16 OR TU45/77, RP04/5/6, 	; RP066
; RK06/7, RL01/2, TU58, RM02/3/5, TS11, OR RX01/2.			; RP066
; 	ONCE THE DUMP IS FINISHED THE SYSTEM MAY BE			;**-2
; RE-BOOTED OR ANOTHER DUMP MAY BE TAKEN.  IF THE DUMP IS DIRECTED
; TO A HARD COPY DEVICE THE DUMP WILL CONTAIN ONLY THE REGISTER
; CONTENTS AND THE SYSTEM STACK.
;
; INPUTS:
;
;	02(SP)=PS WORD AT CR      ASH.
;	00(SP)=PC WORD AT CRASH.
;
; OUTPUTS:
;
;	THE INTERNAL CRASH STACK AND A CORE IMAGE OF THE SYSTEM,
;	UP TO 128K, ARE DUMPED ONTO THE MASS STORAGE CRASH DUMP DEVICE.
;	THE REGISTER CONTENTS AND THE SYSTEM STACK ARE DUMPED IF A
;	HARD COPY DUMP IS REGUESTED.
;-

									;**-6
$CRASH::			;CRASH DUMP ROUTINE
									;**-1
	.IF DF	C$$RSH
									;MSH125
	MOV	(SP)+,$CRUPC	; SAVE USER PC FROM THE STACK		;**-1
	MOV	(SP)+,$CRUST	; SAVE USER PS FROM THE STACK
									;MSH125
	.IFTF						      		;MSH125
									;MSH125
$CRALT::
									;MSH125
	.IFT								;MSH125
									;**-2
	.IF DF	C$$TTY

	MOV	$CRUPC,$CRPBF	;
	MOV	R0,$CRPBF+2	;SAVE R0
	MOV	#$CRPBF+4,R0	;SET UP SAVE AREA
	MOV	R1,(R0)+	;SAVE R1 THRU R5
	MOV	R2,(R0)+	;
	MOV	R3,(R0)+	;
	MOV	R4,(R0)+	;
	MOV	R5,(R0)+	;
	MOV	$CRUST,2(R0)	;
	MOV	SP,(R0)		;SAVE SP
	MOV	#$CRPST,SP	;SETUP TEMPORARY STACK
	MOV	#C$$TTY,R5	;SPECIFY OUTPUT DEVICE CSR
	MOV	#$CRPBF,R1	;POINT TO DATA VECTOR
	MOV	#MSG1,R4	;POINT TO MESSAGE TEXT
1$:	MOV      B	(R4)+,R2	;GET A BYTE OF MESSAGE
	BEQ	5$		;IF EQ AT MESSAGE BREAK
	BR	3$		;ELSE ALREADY HAVE A BYTE
2$:	MOVB	(R4)+,R2	;GET A BYTE OF MESSAGE
	BEQ	4$		;IF EQ END OF THIS MESSAGE
3$:	CALL	$OUT		;OUTPUT THIS CHARACTER
	BR	2$		;GO AGAIN
4$:	MOV	(R1)+,R3	;GET DATA WORD
	CALL	$EDIT		;PRINT IN PLACE
	BR	1$		;GET NEXT MESSAGE
5$:	MOVB	(R4)+,R2	;GET NEXT CHARACTER TO OUTPUT
	BEQ	6$		;IF EQ END OF STRING
	CALL	$OUT		;OUTPUT CHARACTER
	BR	5$		;GO AGAIN
6$:	MOV	$CRPBF+16,R1	;POINT TO BOTTOM OF SYSTEM STA      CK
7$:	MOV	R1,R3		;SET ADDRESS OF LOCATION TO EDIT
	CALL	8$		;EDIT ADDRESS
	MOV	(R1)+,R3	;GET CONTENTS OF LOCATION
	CALL	8$		;EDIT CONTENTS
	CALL	$CRLF		;ISSUE CARRIAGE RETURN, LINE FEED
	CMP	R1,#$STACK	;END OF SYSTEM STACK?
	BLO	7$		;IF LO NO
	MOV	#$CRPBF+16,R0	;POINT TO SAVED STACK POINTER
	MOV	(R0),SP		;RESTORE SP
	MOV	-(R0),R5	;RESTORE R5 THRU R0
	MOV	-(R0),R4	;
	MOV	-(R0),R3	;
	MOV	-(R0),R2	;
	MOV	-(R0),R1	;
	MOV	-(R0),R0	;
	BR	9$		;BR AROUND SUBROUTINE
8$:	CALL	$OUTB		;OUTPUT TWO BLAN      KS
	CALL	$OUTB		;
	CALLR	$EDIT		;PRINT CONTENTS OF R3 AND RETURN
9$:				;REF LABEL

	.ENDC


	.IF DF	C$$CDA

	MOV	#$TRINT,@#4	;SET UP TO SET CARRY ON TRAPS THRU 4	;MSH112
									;**-2
	.IF DF	L$$SI1

	CLR	$CRSST		;CLEAR PS STORAGE WORD
	MFPS	$CRSST		;STORE LOW BYTE OF PS
	MTPS	#PR7		;LOCK OUT INTERRUPTS

	.IFF

	MOV	PS,$CRSST	;STORE FULL PS
									;MSH101
	.IF DF	M$$MGE							;MSH101
									;MSH101
	MOV	#PMODE!PR7,@#PS	;LOCK OUT INTERRUPTS AND SET		;MSH101
				;PREVIOUS MODE=U      SER, CURRENT MODE=KERNEL;MSH101
	.IFF								;MSH101
									;MSH101
	MOVB	#PR7,PS		;LOCK OUT INTERRUPTS
									;MSH101
	.ENDC								;MSH101

	.ENDC


	MOV	SP,$CRSST-2	;;;SAVE SP
	MOV	$CRUPC,$CRSST-4	;;;SAVE PC BEFORE IOT CRASH
	MOV	$CRUST,$CRSST-6	;;;SAVE PS BEFORE IOT CRASH
	MOV	#$CRSST-6,SP	;;;RESET SP TO INTERNAL STACK


	.IF DF	M$$MGE

	MFPI	SP		;;;SAVE USER'S SP

	.IFF

	CLR	-(SP)		;;;NO USER SP IF UNMAPPED

	.IFTF

	MOV	R0,-(SP)	;;;SAVE REGISTER SET 1
	MOV	R1,-(SP)	;;;      
	MOV	R2,-(SP)	;;;
	MOV	R3,-(SP)	;;;
	MOV	R4,-(SP)	;;;
	MOV	R5,-(SP)	;;;

	.IFT

	PUSH	SR0		;;;SAVE MEMORY MANAGEMENT REGISTERS
	PUSH	SR0+2		;;;
	PUSH	SR0+4		;;;
	PUSH	SR3		;;;
	BIC	#67,SR3		;;;DISABLE UNIBUS MAP AND D-SPACE
	MOV	#UISDR0,R0	;;;SETUP TO SAVE FIRST SET OF APR'S
	MOV	#32.,R1		;;;
10$:	PUSH	(R0)		;;;SAVE APR
	ADD	#2,R0		;;;MOVE TO NEXT ONE
	DEC	R1		;;;DONE YET?
	BNE	10$		;;;IF NE NO
	MOV	#SISDR0,R0	;;;SETUP TO SAVE SECOND SET OF APR'S
	MOV	#64.,R1		;;;
20$:	PUSH	(R0)		;;;SAV      E APR
	ADD	#2,R0		;;;MOVE TO NEXT ONE
	DEC	R1		;;;DONE YET?
	BNE	20$		;;;IF NE NO
	MOV	#UBMPR,R0	;;;GET ADDRESS OF FIRST UMR
	MOV	#62.,R1		;;;NUMBER OF UMR'S TO SAVE
30$:	PUSH	(R0)		;;;SAVE A UMR
	ADD	#2,R0		;;;MOVE TO NEXT ONE
	DEC	R1		;;;DONE YET?
	BNE	30$		;;;IF NE NO

	.ENDC


;
; TYPE MESSAGE AND WAIT FOR USER
;

AGAIN:	MOV	$CRSUN,R0	;;;GET CRASH UNIT NUMBER
	ADD	#'0,R0		;;;ADD ASCII BIAS
	MOVB	R0,UNIT		;;;MOVE IT INTO TEXT STRING
	MOV	#CRSMSG,R1	;;;TYPE USER MESSAGE
	CALL	TYPE		;      ;;TYPE OUT MESSAGE
	BR	$CRSHT		;;;BRANCH TO BEFORE UNIT # STORAGE

TYPE:	MOV	#C$$RSH,R5	;;;GET CSR ADD. OF PRINT DEVICE
10$:	MOVB	(R1)+,R2	;;;GET CHARACTER
	BEQ	20$		;;;IF EQ FINISHED
	CALL	$OUT		;;;OUTPUT THE CHARACTER
	BR	10$		;;;LOOP FOR MORE
20$:	RETURN			;;;RETURN TO CALLER


$CRSHT::	HALT		;;;WAIT FOR USER
	BR	DUMP		;;;AFTER CONTINUE - PROCEED WITH DUMP

;
; FOR CONVENIENCE THE CRASH DEVICE UNIT NUMBER IS STORED
; HERE SO THAT THE CONSOLE DISPLAY +2 WILL GIVE THE
; ADDRESS OF THE NEXT       WORD, THUS ALLOWING THE USER TO PATCH
; A DIFFERENT UNIT NUMBER (IGNORING THE PRINTOUT).
;

$CRSUN::.WORD	C$$RUN		;;;CRASH UNIT NUMBER (DEFAULT=0)


;+
; **-CKSUM-VERIFY CHECKSUM OF DEVICE ADDRESS
;
; THIS ROUTINE WILL VERIFY THAT THE DEVICE ADDRESS FOR THE RK11
; AND TC11 HAS NOT BEEN CORRUPTED BY THE CRASH.
;-

CKSUM:	MOV	$CRSBN,-(SP)	;;;GET HIGH ORDER BITS
	ADD	$CRSBN+2,(SP)	;;;ADD LOW ORDER BITS
	CMP	(SP)+,$CRSCS	;;;COMPARE WITH CHECKSUM
	BEQ	10$		;;;IF EQ OK
	HALT			;;;WAIT FOR USER      
	BR	CKSUM		;;;TRY AGAIN
10$:	RETURN			;;;

;+
; **-DUMP-DUMP THE SYSTEM IMAGE
;
; THIS ROUTINE IS USED TO DUMP THE INTERNAL CRASH STACK
; AND THE SYSTEM IMAGE ONTO A SCTATCH DUMP MEDIA.  WHEN THE DUMP
; IS FINISHED THE SYSTEM IS EITHER RE-BOOTED OR THE USER IS ASKED
; IF HE WANTS TO DUMP ANOTHER COPY OF THE IMAGE.
;
; INPUTS:
;	NONE.
;
; OUTUTS:
;	IMAGE DUMPED.
;-

DUMP:				;;;DUMP IMAGE ONTO MEDIA
	MOV	#C$$CSR,R0	;;;GET CSR ADDRESS OF DUMP DEVICE
	MOV	$CRSUN,R3	;;;GET UNIT NUMBER


      	.IF EQ	C$$CDA-1

;									;MSH054
;	DT								;MSH054
;									;MSH054
; THIS ROUTINE DUMPS ALL OF PHYSICAL MEMORY UP TO A MAXIMUM OF		;MSH054
; 124K WORDS								;MSH054
;									;MSH054

PBNH=	0			;;;HIGH ORDER TC11 BLOCK NUMBER
PBNL=	1			;;;LOW ORDER TC11 BLOCK NUMBER

	CALL	CKSUM		;;;CHECK BLOCK NUMBER AGAINST CHECKSUM
	SWAB	R3		;;;POSITION UNIT BITS
	MOV	R3,R1		;;;COPY
	BIS	#4003,R1	;;;SET FOR READ LBN IN REVERSE
	MOV	R1,(R0)		;;;START THE TAPE
10$:	BIT	#100200,(R0)	;;;ERROR OR REA      DY?
	BEQ	10$		;;;IF EQ NO
	BPL	DUMP		;;;IF PL MOVE UNTIL ENDZONE
20$:	MOV	R3,R1		;;;RETREIVE UNIT BITS
	BIS	#3,R1		;;;SET TO READ LBN FORWARD
	MOV	R1,(R0)		;;;START THE TAPE
30$:	BIT	#100200,(R0)	;;;ERROR OR READY?
	BMI	DUMP		;;;IF MI ERROR, RESTART
	BEQ	30$		;;;IF EQ WAIT
	SUB	$CRSBN+2,6(R0)	;;;ARE WE AT THE BLOCK WE WANT?
	BNE	20$		;;;IF NE NO
	CLR	2(R0)		;;;SET TO WRITE ALL MEMORY
	CLR	4(R0)		;;;
	MOV	R3,R1		;;;RETREIVE UNIT BITS
	BIS	#15,R1		;;;SET TO WRITE DATA FORWARD
	MOV	R1,(R0)		;;;W      RITE THE BLOCK
50$:	CLR	2(R0)		;;;KEEP WRITING
	TST	(R0)		;;;ANY ERRORS?
	BPL	50$		;;;IF PL NO
	BIT	#400,-2(R0)	;;;NON-EXISTANT MEMORY?
	BEQ	WERR		;;;IF EQ NO, RETRY
	BIS	#1,R3		;;;SET TO STOP TAPE
	MOV	R3,(R0)		;;;STOP TAPE
	BR	$CRCMP		;;;SUCCESS, FINISH

	.ENDC


	.IF EQ	C$$CDA-2
									;MSH054
;									;MSH054
;	DK								;MSH054
;									;MSH054
; IF THE EXECUTIVE DOES NOT SUPPORT 22-BIT ADDRESSING, THIS		;MSH054
; ROUTINE DUMPS ALL OF PHYSICAL MEMORY UP TO A MAXIMUM OF		;MSH054
      ; 124K WORDS.								;MSH054
;									;MSH054
; IF THE EXECUTIVE SUPPORTS 22-BIT ADDRESSING, THIS ROUTINE		;MSH054
; DUMPS ALL OF PHYSICAL MEMORY UP TO A MAXIMUM OF APPROXIMATELY		;MSH054
; 1.2 MEGAWORDS OF MEMORY (FILLS UP THE RK05).				;MSH054
;									;MSH054

PBNH=	0			;;;HIGH ORDER RK11 DISK ADDRESS
PBNL=	001			;;;LOW ORDER RK11 DISK ADDRESS

	CALL	CKSUM		;;;CHECK DISK ADDRESS AGAINST CHECKSUM
	CLC			;;;SET TO POSITION UNIT BITS
	ROR	R3		;;;
	ROR	R3		;;;
	ROR	R3		;;;
	ROR	R3		;;;
	MOV      	#401,(R0)	;;;RESET RK11 CONTROLLER
	BIS	$CRSBN+2,R3	;;;SET STARTING DISK ADDRESS
	MOV	R3,6(R0)	;;;SET DISK ADDRESS

	.IF NDF	M$$EXT

	CLR	4(R0)		;;;SETUP TO WRITE ALL MEMORY
	CLR	2(R0)		;;;
	MOV	#403,(R0)	;;;START THE WRITE
20$:	CLR	2(R0)		;;;KEEP WRITING
	TST	(R0)		;;;ANY ERROR BITS SET?
	BPL	20$		;;;IF PL NO
	BIT	#2000,-2(R0)	;;;NON-EXISTANT MEMORY?
	BNE	$CRCMP		;;;IF NE YES, FINISHED

	.IFF

	CLR	UBMPR		;;;INITIALIZE FIRST UNIBUS MAPPING REGISTER
	CLR	UBMPR+2		;;;
	CLR	KISAR0		;;;
	B      IS	#60,SR3		;;;ENABLE 22 BIT MAPPING AND UNIBUS MAP
	BIS	#1,SR0		;;;MAKE SURE MEM MGMT IS ON
40$:	MOV	6(R0),R3	;;;GET DISK ADDRESS			;MSH055
	BIC	#160017,R3	;;;EXTRACT CYLINDER AND SURFACE		;MSH055
	CMP	#14420,R3	;;;ABOUT TO WRITE TO CYLINDER THAT	;MSH055
				;;;CANNOT ORDINARILY BE READ?		;MSH055
	BEQ	$CRCMP		;;;IF EQ YES, STOP WRITING		;MSH055
	CLR	4(R0)		;;;INITIALIZE TRANSFER ADDRESS		;MSH055
	MOV	#-6000,2(R0)	;;;WRITE 3K WORDS (1 CYLINDER)		;MSH055
	MOV	#403,(R0)	;;;START THE WRITE			;**-2
45      $:	BIT	#100200,(R0)	;;;ERROR OR READY?
	BEQ	45$		;;;IF EQ NO
	BMI	50$		;;;IF MI ERROR
	ADD	#14000,@#UBMPR	;;;POINT TO NEXT 3K WORD SEGMENT	;MSH055
	ADC	UBMPR+2		;;;DOUBLE WORD ADD			;**-1
	BR	40$		;;;GO AGAIN UNTIL END OF MEMORY
50$:	BIT	#2000,-2(R0)	;;;NON EXISTENT MEMORY?
	BNE	$CRCMP		;;;YES IF NE HALT

	.ENDC


	.ENDC


	.IF EQ	C$$CDA-3
									;MSH054
;									;MSH054
;	MT								;MSH054
;									;MSH054
; THIS ROUTINE DUMPS ALL OF PHYSICAL MEMORY (UP TO A MAXIMUM		;MSH054
; OF 1      24K WORDS) IN 512 BYTE RECORDS AT 800 BPI (9-TRACK)		;MSH054
;									;MSH054

PBNH=	0			;BLOCK NUMBER IGNORED FOR TM11
PBNL=	0			;

	SWAB	R3		;;;POSITION UNIT SELECT BITS
	BIS	#60001,R3	;;;MERGE DENSITY AND GO BITS
	MOV	R3,R2		;;;COPY
	BIS	#16,R2		;;;SET REWIND FUNCTION
	MOV	R2,(R0)		;;;START THE REWIND
10$:	BIT	#100200,(R0)	;;;ERROR OR READY?
	BMI	WERR		;;;IF MI ERROR, RETRY
	BEQ	10$		;;;IF EQ NO
	CLR	(R0)		;;;CLEAR MTC REGISTER
	CLR	4(R0)		;;;START TO WRITE ALL OF MEMORY
	MOV	R3,R2		;;;R      ETREIVE MTC BITS
	BIS	#4,R2		;;;SET WRITE DATA FUNCTION
	BIC	#1,R2		;;;CLEAR GO BIT
	MOV	R2,(R0)		;;;START THE WRITE
30$:	MOV	#500,R1		;;;WAIT FOR TAPE TO SETTLE DOWN		;MSH056
35$:	DEC	R1		;;;WAIT					;**-1
	BNE	35$		;;;IF NE LOOP
	MOV	#-512.,2(R0)	;;;SET 512. BYTE RECORDS
	BIS	#1,(R0)		;;;START THE WRITE
40$:	BIT	#100200,(R0)	;;;ERROR OR READY?
	BEQ	40$		;;;IF EQ NO
	BPL	30$		;;;IF PL WRITE FINISHED
	TSTB	-2(R0)		;;;NON-EXISTANT MEMORY?
	BPL	WERR		;;;IF PL NO, RETRY
	MOV	R3,R2		;;;RETREIVE MT      C BITS
	BIS	#10000,R2	;;;SET CLEAR FUNCTION
	MOV	R2,(R0)		;;;LOAD FUNCTION
50$:	TSTB	(R0)		;;;READY?
	BPL	50$		;;;IF PL NO
	BIS	#6,R3		;;;SET WRITE EOF FUNCTION
	MOV	R3,(R0)		;;;DO THE WRITE EOF
60$:	TSTB	(R0)		;;;READY?
	BPL	60$		;;;IF PL NO
	CLR	(R0)		;;;CLEAR MTC REGISTER
	BR	$CRCMP		;;;SUCCESSFUL COMPLETION

	.ENDC


	.IF EQ	C$$CDA-4
									;MSH054
;									;MSH054
;	MM								;MSH054
;									;MSH054
; THIS ROUTINE DUMPS ALL OF PHYSICAL MEMORY IN 512 BYTE			;MSH054
; RECORDS AT       800 BPI							;MSH054
;									;MSH054

PBNH=	0			;BLOCK NUMBER IGNORED FOR TJU16
PBNL=	0			;

									; RP066
									; RP066
	.IF DF	M$$EXT							; RP066
									; RP066
	MOV	CRBAE,R1	;;;GET BAE REGISTER ADDRESS		;MSH203
	BEQ	3$		;;;IF EQ DOES NOT EXIST			;MSH203
	TST	(R1)		;;;DOES IT EXIST			;MSH203
	BCC	5$		;;;IF CC YES, USE IT			;MSH203
	CLR	CRBAE		;;;INHIBIT REFERENCING OF REGISTER	;MSH203
3$:	CLR	@#UBMPR		;;;INITIALIZE FIRST UNIBUS ...		;MSH203
	CLR	@#UBMPR+2	;;;... MAPPING REGIS      TERS		; RP066
5$:	BIS	#60,@#SR3	;;;ENABLE 22 BIT MAPPING AND UNIBUS MAP	; RP066
	BIS	#1,@#SR0	;;;MAKE SURE MEM MGNT IS ON		; RP066
	MOV	#<4*4>,R5	;;;NUMBER OF 512 BYTE RECORDS/4K BLOCK	; RP066
									; RP066
	.ENDC	;M$$EXT							; RP066
									; RP066
									; RP066
	BIS	(PC)+,R3	;;;SET MODE AND DENSITY
$TDNSY::.WORD	1300		;;;DEFAULT TO 800 BPI, NORMAL MODE	;MSH054
	BIS	#40,10(R0)	;;;RESET CONTROLLER			;**-1
10$:	TSTB	12(R0)		;;;IS THE TAPE DRIVE READY?
	BPL	10$		;;;IF PL NO
	MOV	R3,32(R0      )	;;;SET FORMAT BITS
	MOV	#7,(R0)		;;;START THE TAPE REWINDING
	MOV	#40000,R1	;;;DELAY UNTIL REWIND OPERATION		;MSH054
15$:	DEC	R1		;;;IS ACTUALLY IN PROGRESS		;MSH054
	BNE	15$		;;;					;**-2
20$:	BIT	#20000,12(R0)	;;;POSITIONING STILL IN PROGRESS?
	BNE	20$		;;;IF NE YES
	TSTB	12(R0)		;;;DRIVE READY?
	BPL	20$		;;;IF PL NO
	MOV	#60,(R0)	;;;LOAD THE WRITE FUNCTION
	CLR	4(R0)		;;;SET TO WRITE ALL OF MEMORY
40$:	MOV	#-256.,2(R0)	;;;SET WORD COUNT
	MOV	#-512.,6(R0)	;;;SET FRAME COUNT
	BIS	#1,(R0)		;      ;;START TO WRITE ALL OF MEMORY
50$:	TSTB	12(R0)		;;;DRIVE READY?
	BPL	50$		;;;IF PL NO
	BIT	#40000,(R0)	;;;TRANSFER ERRORS?
	BNE	60$		;;;IF NE YES				; RP066
									; RP066
									; RP066
	.IF DF	M$$EXT							; RP066
									; RP066
	DEC	R5		;;;DECREMENT BLOCK COUNT		; RP066
	BNE	40$		;;;IF NE USE SAME UMR			; RP066
	TST	CRBAE		;;;IS THE BAE REGISTER THERE?		;MSH203
	BNE	55$		;;;IF NE YES				;MSH203
	ADD	#20000,@#UBMPR	;;;NO, POINT UMR TO NEXT 4K OF MEMORY	; RP066
	ADC	@#UBMPR+2	;;;DOUBLE       WORD ADD			; RP066
	CLR	4(R0)		;;;AND RESET BUS ADDRESS		; RP066
55$:	MOV	#<4*4>,R5	;;;RESET TO # BLOCKS PER 4K		; RP066
									; RP066
	.ENDC	;M$$EXT							; RP066
									; RP066
									; RP066
	BR	40$		;;;CONTINUE XFER			; RP066
60$:	BIT	#4000,10(R0)	;;;NONEXISTENT MEMORY			; RP066
	BEQ	WERR		;;;IF EQ NO, RETRY			; RP066
	BIS	#40,10(R0)	;;;RESET CONTROLLER			;**-3
65$:	TSTB	12(R0)		;;;DRIVE READY?				; RP066
	BPL	65$		;;;IF PL NO				; RP066
	MOV	R3,32(R0)	;;;RESET FORMAT BITS			;**-2
      	MOV	#27,(R0)	;;;WRITE EOF ON TAPE
70$:	TSTB	12(R0)		;;;IS DRIVE READY?
	BPL	70$		;;;IF PL NO
	CLR	(R0)		;;;CLEAR CONTROLLER REGISTER
	BR	$CRCMP		;;;SUCCESSFUL COMPLETION

	.ENDC
									; RP066
									; RP066
	.IIF EQ C$$CDA-5    CDA$DB=0					; RP066
									; RP066
	.IIF EQ C$$CDA-11   CDA$DR=0					; RP066

	.IF DF	CDA$DB!CDA$DR						; RP066
									;MSH054
;									;MSH054
;	DB AND DR							;MSH054
;									;MSH054
; THIS ROUTINE DUMPS ALL OF PHYSICAL MEMORY				;MSH054
;								      	;MSH054
									;MSH054
									;**-1
PBNH=	0			;;;RP04/5/6 OR RM02/3/5 DEFAULT CYL. ADD; RP066
PBNL=	1			;;;DEFAULT TRACK AND SECTOR ADD.	;**-1

	CALL	CKSUM		;;;CHECK DISK ADDRESS AGAINST CHECKSUM
	MOV	26(R0),R1	;;;RETRIEVE DEVICE TYPE REGISTER	; RP066
	BIC	#^C<777>,R1	;;;CLR EXTRANEOUS BITS			; RP066
	CMP	#25,R1		;;;IS IT RP04/5/6 OR RM02/3?		; RP066
	BHIS	10$		;;;IF HIS YES				; RP066
	CMP	#27,R1		;;;IS IT RM05?				; RP066
	BEQ	10$		;;;IF EQ YES				; RP066
	MOV	#ILDEV,R1	;;;NO, ILLEGAL DE      VICE			; RP066
	CALL	TYPE		;;;PRINT MESSAGE			; RP066
	BR	AGAIN		;;;TRY AGAIN				; RP066
10$:				;;;REF LABEL				; RP066
									; RP066
									; RP066
	.IF DF	M$$EXT							; RP066
									; RP066
	MOV	CRBAE,R1	;;;GET BAE REGISTER ADDRESS		;MSH203
	BEQ	18$		;;;IF EQ DOES NOT EXIST			;MSH203
	TST	(R1)		;;;BAE REGISTER EXIST?			;MSH203
	BCC	20$		;;;IF CC YES, USE IT			;MSH203
	CLR	CRBAE		;;;INHIBIT REFERENCING OF REGISTER	;MSH203
18$:	CLR	@#UBMPR		;;;INITIALIZE FIRST UNIBUS ...		;MSH203
	CLR      	@#UBMPR+2	;;;... MAPPING REGISTERS		; RP066
20$:	BIS	#60,@#SR3	;;;ENABLE 22 BIT MAPPING AND UNIBUS MAP	; RP066
	BIS	#1,@#SR0	;;;MAKE SURE MEM MGNT IS ON		; RP066
	MOV	#<4*4>,R5	;;;NUMBER OF 512 BYTE SECTORS/4K BLOCK	; RP066
									; RP066
	.ENDC	;M$$EXT							; RP066
									; RP066
									; RP066
	ADD	#10,R0		;;;POINT TO RCS2
	MOV	#40,(R0)	;;;CLEAR CONTROLLER
	BIS	R3,(R0)		;;;SELECT UNIT
	MOV	#23,-10(R0)	;;;DO A PACK ACKNOWLEDGE
	MOV	$CRSBN,24(R0)	;;;SELECT CYLINDER
	MOV	$CRSBN+2,-(R0)	;      ;;SET SECTOR AND TRACK
	CLR	-(R0)		;;;ZERO BUFFER ADDRESS
	MOV	#14000,26(R0)	;;;SET 16 BIT FORMAT
	CMP	-(R0),-(R0)	;;;POINT TO CSR
30$:	MOV	#-256.,2(R0)	;;;WORD COUNT = 1 SECTOR		; RP066
	BIC	#77,(R0)	;;;CLEAR FUNCTION CODE			;**-1
	BIS	#61,(R0)	;;;EXECUTE A WRITE
40$:	BIT	#100200,(R0)	;;;READY OR ERROR?			; RP066
	BEQ	40$		;;;IF EQ NO				; RP066
	BIT	#40000,(R0)	;;;TRANSFER ERROR?			; RP066
	BNE	60$		;;;IF NE YES				; RP066
									; RP066
	.IF DF	M$$EXT							; RP066
									; RP066
	DEC	R      5		;;;DECREMENT BLOCK COUNT		; RP066
	BNE	30$		;;;IF NE USE SAME UMR			; RP066
	TST	CRBAE		;;;BAE REGISTER THERE?			;MSH203
	BNE	50$		;;;IF NE YES				;MSH203
	ADD	#20000,@#UBMPR	;;;NO, POINT UMR TO NEXT 4K OF MEMORY	; RP066
	ADC	@#UBMPR+2	;;;DOUBLE WORD ADD			; RP066
	CLR	4(R0)		;;;AND RESET BUS ADDRESS		; RP066
50$:	MOV	#<4*4>,R5	;;;RESET TO # SECTORS PER 4K 		; RP066
									; RP066
	.ENDC	;M$$EXT							; RP066
									; RP066
									; RP066
	BR	30$		;;;CONTINUE XFER			; RP066
60$:	BIT	#4      000,10(R0)	;;;NON-EXISTENT MEMORY ERROR?		; RP066
	BNE	$CRCMP		;;;IF NE YES, ELSE I/O ERROR		; RP066
									;**-6
	.ENDC


	.IF EQ	C$$CDA-6
									;MSH054
;									;MSH054
;	DM								;MSH054
;									;MSH054
; IF THE EXECUTIVE DOES NOT SUPPORT 22-BIT ADDRESSING, THIS		;MSH054
; ROUTINE DUMPS ALL OOF PHYSICAL MEMORY UP TO A MAXIMUM OF		;MSH054
; 124K WORDS.								;MSH054
;									;MSH054
; IF THE EXECUTIVE SUPPORTS 22-BIT ADDRESSING, THIS ROUTINE		;MSH054
; DUMPS ALL OF PHYSICAL MEMO      RY.						;MSH054
;									;MSH054
; NOTE THAT THE STANDARD METHOD OF DUMPING ALL OF PHYSICAL		;MSH057
; MEMORY (DUMPING UNTIL THE CONTROLLER DETECTS NONEXISTENT		;MSH057
; MEMORY) DOES NOT WORK, BECAUSE THE RK611 WRITES AN UNCORRECTABLE	;MSH057
; ECC ERROR IN THE LAST SECTOR IT WRITES UNDER THOSE CONDITIONS.	;MSH057
;									;MSH057

PBNH=	0			;;;RK06 DEFAULT CYLINDER ADDRESS
PBNL=	1			;;;DEFAULT SECTOR AND TRACK ADDRESS

	MOV	#$TRINT,@#114	;;;POSITION TRAP CATCHER FOR NON-	;MSH060
				;;;EXIS      TENT MEMORY TRAPS WHEN SIZE	;MSH060
				;;;REGISTER > SIZE OF MEMORY		;MSH060
	CALL	CKSUM		;;;CHECK BLOCK NUMBER AGAINST CHECKSUM
	CLR	R2		;;;ASSUME DRIVE IS AN RK06
	MOV	#40,10(R0)	;;;CLEAR THE RK611 SUBSYSTEM
	MOV	R3,10(R0)	;;;SELECT THE UNIT
	MOV	#1,(R0)		;;;SELECT THE DRIVE FUNCTION
10$:	TSTB	(R0)		;;;READY?
	BPL	10$		;;;IF PL NO
	BIT	#400,12(R0)	;;;IF THIS AN RK07?
	BEQ	20$		;;;IF EQ NO, IT'S AN RK06
	BIS	#2000,R2	;;;SET RK07 BIT
20$:	MOV	#40,10(R0)	;;;CLEAR THE RK611 SUBSYSTEM
	MOV	R3,10(      R0)	;;;SELECT THE UNIT
	MOV	R2,R1		;;;COPY DRIVE TYPE BIT
	BIS	#3,R1		;;;GET PACK ACK FUNCTION CODE
	MOV	R1,(R0)		;;;DO A PACK ACKNOWLEDGE
30$:	TSTB	(R0)		;;;READY?
	BPL	30$		;;;IF PL NO
	MOV	12(R0),R1	;;;GET DRIVE STATUS
	COM	R1		;;;COMPLEMENT
	BIT	#100301,R1	;;;DRIVE READY TO GO?
	BNE	WERR		;;;IF NE NO, TRY AGAIN
	MOV	$CRSBN,20(R0)	;;;LOAD CYLINDER
	MOV	$CRSBN+2,6(R0)	;;;LOAD SECTOR/TRACK
	BIS	#23,R2		;;;SET WRITE FUNCTION


	.IF DF	M$$EXT

	CLR	UBMPR		;;;INITIALIZE FIRST UNIBUS MAPPING R      EG.
	CLR	UBMPR+2		;;;
	CLR	KISAR0		;;;
	BIS	#60,SR3		;;;ENABLE 22 BIT MAPPING AND UNIBUS MAP
	BIS	#1,SR0		;;;MAKE SURE MEM MGMT IS ON
									;MSH057
	.IFTF	;M$$EXT							;MSH057
									;MSH057
	.IF DF	M$$MGE							;MSH057
									;MSH057
	MOV	#140000,R5	;;;SET TO MAP THROUGH APR6		;MSH057
	CLR	@#KISAR6	;;;POINT TO FIRST BYTE OF 1K SEGMENT	;MSH057
									;MSH057
	.IFF	;M$$MGE							;MSH057
									;MSH057
	CLR	R5		;;;R5 TRACKS THE DUMP PROCESS		;MSH057
									;MSH057
	.ENDC	;M$$MGE      							;MSH057
									;MSH057
	.IFT	;M$$EXT							;MSH057
									;MSH057
50$:	CLR	4(R0)		;;;START AT BEGINNING OF UNIBUS MAP	;MSH057
									;MSH057
	.IFF	;M$$EXT							;MSH057
									;MSH057
	CLR	4(R0)		;;;START AT BEGINNING OF MEMORY		;MSH057
50$:				;;;REF LABEL				;MSH057
									;MSH057
	.IFTF	;M$$EXT							;MSH057
									;MSH057
	MOV	#-2000,2(R0)	;;;WRITE 1K WORDS PER TRANSFER		;MSH057
	BIS	R2,(R0)		;;;START WRITING			;**-10
60$:	BIT	#100200,(R0)	;;;READY OR ERROR?
	BEQ	60$		      ;;;IF EQ NEITHER
	BMI	80$		;;;IF MI ERROR				;MSH057
									;MSH057
	.IFT	;M$$EXT							;MSH057
									;MSH057
	ADD	#4000,@#UBMPR	;;;POINT TO NEXT 1K WORD BOUNDARY	;MSH057
	ADC	@#UBMPR+2	;;;DON'T FORGET THE CARRY		;MSH057
	ADD	#40,@#KISAR6	;;;ADJUST DUMP TRACKING POINTER		;MSH057
	CMP	#170000,@#KISAR6 ;;;HAVE WE HIT THE I/O PAGE?		;MSH057
									;MSH057
	.IFF	;M$$EXT							;MSH057
									;MSH057
	.IF DF	M$$MGE							;MSH057
									;MSH057
	ADD	#40,@#KISAR6	;;;ADJUST DUMP TRACKING POI      NTER		;MSH057
	CMP	#7600,@#KISAR6	;;;HAVE WE HIT THE I/O PAGE?		;MSH057
									;MSH057
	.IFF	;M$$MGE							;MSH057
									;MSH057
	ADD	#4000,R5	;;;ADJUST DUMP TRACKING POINTER		;MSH057
	CMP	#160000,R5	;;;HAVE WE HIT THE I/O PAGE?		;MSH057
									;MSH057
	.ENDC	;M$$MGE							;MSH057
									;MSH057
	.ENDC	;M$$EXT							;MSH057
									;MSH057
	BEQ	$CRCMP		;;;IF EQ YES, DUMP IS DONE		;MSH057
	TST	(R5)		;;;DOES FIRST WORD OF NEXT TRANSFER EXIS;MSH057
	BCC	50$		;;;IF CC YES				;MSH057
	BR      	$CRCMP		;;;IF CS NO, DUMP IS DONE		;MSH057
80$:				;;;REF LABEL				;MSH057
									;**-14

	.ENDC


	.IF EQ	C$$CDA-7
									;MSH054
;									;MSH054
;	DL								;MSH054
;									;MSH054
; IF THE EXECUTIVE DOES NOT SUPPORT 22-BIT ADDRESSING, THIS ROUTINE	;MSH054
; DUMPS ALL OF PHYSICAL MEMORY UP TO A MAXIMUM OF 124K WORDS FOR A	;MSH054
; MAPPED SYSTEM AND 28K WORDS FOR AN UNMAPPED SYSTEM.			;MSH054
;									;MSH054
; IF THE EXECUTIVE SUPPORTS 22-BIT ADDRESSING, THIS ROUTINE		;MSH054
;       DUMPS ALL OF PHYSICAL MEMORY.						;MSH054
;									;MSH054
; NOTE THAT THE STANDARD METHOD OF DUMPING ALL OF PHYSICAL		;MSH039
; MEMORY (DUMP MEMORY UNTIL THE CONTROLLER DETECTS NONEXISTENT		;MSH039
; MEMORY) DOES NOT WORK ON A Q-BUS CPU WHERE SOME MEMORY IS UNUSED	;MSH039
; BECAUSE IT "OVERLAPS" THE I/O PAGE. FOR EXAMPLE, A 124K WORD CPU	;MSH039
; WITH FOUR 32K WORD MEMORY BOARDS. UNDER THOSE CIRCUMSTANCES,		;MSH039
; BECAUSE THE RL01/02 CONTROLLER DOES NOT ASSERT THE Q-BUS SIGNAL	;MSH039
; DECL      ARING AN I/O PAGE ADDRESS TO BE AN I/O PAGE ADDRESS, THE		;MSH039
; MEMORY WILL ANSWER I/O PAGE ADDRESSES.				;MSH039
;									;MSH039

PBNH=	0			;;;NOT USED
PBNL=	2			;;;DEFAULT CYLINDER,TRACK AND SECTOR -RL11
CREXT=	10			;;;BAE OFFSET FROM CSR			;MSH203

	CALL CKSUM


	.IF DF	M$$EXT

	CLR	CREXT(R0)	;;;CLEAR AND TEST FOR BAE REGISTER	;MSH203
	BCC	5$		;;;IF CC IT EXISTS			;MSH203
	CLR	@#UBMPR		;;;INITIALIZE FIRST UNIBUS ...		; RP066
	CLR	@#UBMPR+2	;;;... MAPPING REGISTERS		; RP066
5$:	BIS	      #60,@#SR3	;;;ENABLE 22 BIT MAPPING AND UNIBUS MAP	; RP066
	BIS	#1,SR0		;;;MAKE SURE MEM MGMT IS ON		;**-4
	MOV	#4*4,R5		;;;STORE BLOCKS PER 4K WORDS
	MOV	#1920.*4,-(SP)	;;;DUMP MAXIMUM 1920.K WORDS		;MSH039
									;MSH039
	.IFF								;MSH039
									;MSH039
	.IF DF M$$MGE							;MSH039
									;MSH039
	MOV	#124.*4,-(SP)	;;;DUMP MAXIMUM 124.K WORDS		;MSH039
									;MSH039
	.IFF	;M$$MGE							;MSH039
									;MSH039
	MOV	#28.*4,-(SP)	;;;DUMP MAXIMUM 28.K WORDS		;MSH039
									;MSH039
      	.ENDC								;MSH039

	.ENDC


	SWAB	R3		;;;MOVE UNIT NUMBER TO HIGH BYTE
	BIS	#4,R3		;;;SET GET STATUS FUNCTION
	MOV	#13,4(R0)	;;;SET CODES TO CLEAR DRIVER
	MOV	R3,(R0)		;;;EXECUTE THE FUNCTION
10$:	BIT	#100200,(R0)	;;;READY OR ERROR?
	BEQ	10$		;;;IF EQ NEITHER
	BMI	WERRX		;;;IF MINUS I/O ERROR			;MSH039
	ADD	#4,R3		;;;CONVERT TO READ HEADER FUNCTION	;**-1
	MOV	$CRSBN+2,R4	;;;SAVE STARTING DISK ADDRESS
	CLR	2(R0)		;;;SET BUFFER ADDRESS FOR FIRST WRITE
15$:	MOV	R3,(R0)		;;;READ HEADER
20$:	      BIT	#100200,(R0)	;;;DONE OR ERROR?
	BEQ	20$		;;;IF EQ NEITHER
	BMI	WERRX		;;;IF MINUS I/O ERROR			;MSH039
	MOV	6(R0),R1	;;;GET HEADER INFORMATION		;**-1
	MOV	R4,R2		;;;COPY DESIRED DISK ADDRESS
	MOV	R1,-(SP)	;;;STORE VALUE
	MOV	R2,-(SP)	;;; FORM A DIFF. XOR
	BIC	R1,R2		;;;
	BIC	(SP)+,R1	;;;
	BIS	R1,R2		;;;
	MOV	(SP)+,R1	;;;RESTORE R1
	BIC	#77,R2		;;;IGNORE SECTOR BITS
	BEQ	40$		;;;IF EQ NO SEEK REQUIRED
	MOV	R4,R2		;;;COPY DESIRED DISK ADDRESS
	BIC	#177,R1		;;;ISOLATE CYLINDER ADDRESS
	BIC	#1      77,R2		;;;ISOLATE CYLINDER ADDRESS DESIRED
	SUB	R2,R1		;;;SUBTRACT DESIRED FROM ACTUAL
	BHIS	25$		;;;IF HIS ACTUAL >=DESIRED
	NEG	R1		;;;ACTUAL < DESIRED, MAKE POS. DIFF.
	BIS	#4,R1		;;;SET SIGN FOR MOVE TO CENTER OF DISK
25$:	INC	R1		;;;SET MARKER BIT
	BIT	#100,R4		;;;WHICH HEAD DO WE WANT
	BEQ	30$		;;;IF EQ IT'S HEAD 0
	BIS	#20,R1		;;;SET HEAD 1
30$:	MOV	R1,4(R0)	;;;LOAD DIFFERENCE WORD
	SUB	#2,R3		;;;CONVERT TO SEEK FUNCTION
	MOV	R3,(R0)		;;;START THE SEEK
35$:	BIT	#100200,(R0)	;;;READY OR ER      ROR?
	BEQ	35$		;;;IF EQ NEITHER
	BMI	WERRX		;;;IF MINUS I/O ERROR			;MSH039
40$:	MOV	R4,4(R0)	;;;LOAD DESIRED DISK ADDRESS		;**-1
	MOV	#-256.,6(R0)	;;;LOAD ONE BLOCK WORD COUNT
	BIC	#17,R3		;;;REMOVE FUNCTION BITS
	BIS	#12,R3		;;;SET WRITE FUNCTION
	MOV	R3,(R0)		;;;START THE WRITE
45$:	BIT	#100200,(R0)	;;;ERROR OR READY?
	BEQ	45$		;;;IF EQ NEITHER
	BMI	70$		;;;IF MINUS, ERROR
	DEC	(SP)		;;;DECREMENT MAXIMUM BLOCK DUMP		;MSH039
	BEQ	75$		;;;IF EQ, DUMP IS DONE			;MSH039


	.IF DF 	M$$EXT

	D      EC	R5		;;;DECREMENT BLOCK COUNT
	BNE	60$		;;;IF NE USE SAME UMR
	TST	CREXT(R0)	;;;IS THE BAE REGISTER THERE?		;MSH203
	BCC	50$		;;;IF CC YES				;MSH203
	ADD	#20000,@#UBMPR	;;;NO, POINT UMR TO NEXT 4K OF MEMORY	; RP066
	ADC	@#UBMPR+2	;;;DOUBLE WORD ADD			; RP066
	CLR	2(R0)		;;;AND RESET BUS ADDRESS		; RP066
50$:	MOV	#4*4,R5		;;;RESET TO # BLOCKS PER 4K		; RP066
									;**-4
	.ENDC


60$:	MOV	(R0),R3		;;;GET CSR
	BIC	#^C<1460>,R3	;;;ISOLATE UNIT AND EX MEM BITS
	ADD	#2,R4		;;;MOVE TO NEXT SECT      OR
	MOV	R4,R1		;;;COPY DISK ADDRESS
	BIC	#^C<77>,R1	;;;GET THE SECTOR BITS
	CMP	#50,R1		;;;OVERRUN COMING?
	BNE	40$		;;;IF NE, NO
	BIS	#77,R4		;;;INCREMENT TRACK...
	INC	R4		;;;...SET SECTOR TO 0
	BIS	#10,R3		;;;SET READ HEADER FUNCTION
	BR	15$		;;;AND GO AGAIN
70$:	BIT	#20000,(R0)	;;;NON-EXISTENT MEMORY?
	BEQ	WERRX		;;;IF EQ NO, I/O ERROR			;MSH039
75$:	TST	(SP)+		;;;CLEAN STACK				;MSH039
	BR	$CRCMP		;;;DUMP DONE				;MSH039
									;MSH039
WERRX:	TST	(SP)+		;;;CLEAN STACK				;MSH039
						      			;**-1
	.ENDC


	.IF EQ	C$$CDA-10
									;MSH054
;									;MSH054
;	DD								;MSH054
;									;MSH054
; THIS ROUTINE DUMPS ALL OF PHYSICAL MEMORY UP TO A LIMIT OF 124K WORDS.;MSH054
;									;MSH054

PBNH=	0			;;;NOT USED BY TU-58 TAPE CARTRIDGE
PBNL=	1			;;;STARTING BLOCK NUMBER

;THIS CODE INTERFACES WITH A TU-58 VIA A DL-11 ASYNCHRONOUS INTERFACE

	CALL	CKSUM
	MOV	#$TRINT,@#114	;;;POSITION NONEXISTENT MEMORY TRAP	;MSH060
				;;;CATCHER FOR CPUS WHERE MEMORY SIZE	;MSH060
				;;      ;REGISTER > SIZE OF MEMORY		;MSH060
									;**-1
	.IF NDF	M$$MGE

	CLR	R1		;;;POINT TO BEGINNING OF MEM.

	.IFF

	CLR	KISAR6		;;;CLEAR MAPPING REG.
	CLR	KISAR0		;;;
	BIS	#1,SR0		;;;ENSURE MAPPING TURNED ON		;**-2

	.ENDC


;INITIALIZE TU-58

	CLR	-(SP)		;;;RESERVE SPACE ON STACK		;MSH058
	MOV	R3,-(SP)	;;;SAVE UNIT NUMBER
	BIS	#1,4(R0)	;;;SEND BREAK
	MOV	#6,R2		;;;SET TO SEND 6 NULLS
5$:	CLRB	6(R0)		;;;SEND A NULL
	CALL	XWAIT
	DEC	R2		;;;6 NULLS SENT?
	BNE	5$		;;;IF NE, NO
	CLR	4(R      0)		;;;CLEAR BREAK
	TST	2(R0)		;;;DUMP REC. BUFFER
	MOVB	#4,6(R0)	;;;SEND INIT.
	CALL	XWAIT
	MOVB	#4,6(R0)	;;;SEND ANOTHER INIT.
	CALL	XWAIT
10$:	TSTB	(R0)		;;;RECEIVED A BYTE?
	BPL	10$		;;;IF PL NO
	CMPB	#20,2(R0)	;;;RECEIVED A CONTINUE?
	BNE	35$		;;;IF NE NO, I/O ERROR			;MSH058
									;**-2
;SEND COMMAND PACKET

	MOV	$CRSBN+2,R2	;;;SAVE STARTING TU-58 ADDRESS		;MSH058
15$:				;;;REF LABEL				;MSH058
	.IF DF	M$$MGE							;MSH058
									;MSH058
	MOV	#140000,R1	;;;RESET CURRENT MEMORY A      DDRESS		;MSH058
									;MSH058
	.ENDC								;MSH058
									;MSH058
	CALL	XWAIT							;MSH058
	MOVB	#2,6(R0)	;;;SEND COMMAND FLAG			;**-2
	CALL	XWAIT
	MOVB	#12,6(R0)	;;;SEND PACKET BYTE COUNT
	MOV	#5002,R4	;;;CREATE 1ST CHECKSUM WD.
	CALL	XWAIT
	MOVB	#3,6(R0)	;;;SEND WRITE OP CODE
	CALL	XWAIT
	CLRB	6(R0)
	MOV	#3,R5		;;;CREATE 2ND CHECKSUM WD.
	CALL	CKSM
	MOVB	(SP),6(R0)	;;;SEND UNIT NUMBER
	MOV	#4,R3		;;;SET COUNTER TO SEND 3 CLRS
20$:	CALL	XWAIT
	CLR	6(R0)
	DEC	R3
	BNE	20$
	MOV	(SP      ),R5		;;;CHECKSUM
	CALL	CKSM
	MOVB	#<1024.*2/400>,6(R0) ;;;SEND HIGH ORDER BYTE OF		;MSH058
				     ;;;NUMBER OF BYTES TO TRANSFER	;MSH058
	MOV	#<1024.*2>,R5	;;;UPDATE PACKET CHECKSUM FOR TRANSFER	;MSH058
	CALL	CKSM		;;;BYTE COUNT AND THEN WAIT		;MSH058
	MOV	R2,R3		;;;COPY TU-58 BLOCK NO.			;**-3
	MOVB	R3,6(R0)	;;;SEND LOW ORDER BLOCK NO.
	SWAB	R3		;;;SWAP BYTES
	CALL	XWAIT
	MOVB	R3,6(R0)	;;;SEND HIGH ORDER BLOCK NO.
	MOV	R2,R5		;;;CHECKSUM
	CALL	CKSM
	MOVB	R4,6(R0)	;;;SEND LOW ORDER BYTE OF C      KSM
	SWAB	R4		;;;SWAP BYTES
	CALL	XWAIT
	MOVB	R4,6(R0)	;;;SEND HIGH ORDER CKSM BYTE

; SEND WRITE DATA TO TU-58

	MOV	#<1024.*2/128.>,2(SP) ;;;NUMBER PACKETS/1K WORDS	;MSH058
30$:	BIT	#200,(R0)	;;;RECEIVED A CHARACTER?		;**-1
	BEQ	30$		;;;IF EQ NO
	CMPB	#20,2(R0)	;;;REC. A CONTINUE?
35$:	BNE	DEND		;;;IF NE NO				;MSH058
	MOV	#64.,R3		;;;STORE WORDS/PACKET			;**-1
	CALL	XWAIT
	MOVB	#1,6(R0)	;;;SEND DATA PACKET COMMAND FLAG
	CALL	XWAIT
	MOVB	#200,6(R0)	;;;SEND PACKET BYTE COUNT
	MOV	#100001,R      4	;;;CREATE FIRST CHECKSUM WORD
	CALL	XWAIT
40$:	MOV	(R1),R5		;;;WILL USE DATA WORD IN CHECKSUM	;MSH058
	MOVB	(R1)+,6(R0)	;;;WRITE FIRST BYTE			;MSH058
	CALL	XWAIT							;**-9
	MOVB	(R1)+,6(R0)	;;;SEND SECOND BYTE
	CALL	CKSM
	DEC	R3		;;;DECREMENT PACKET COUNT
	BNE	40$		;;;IF NE TRANSFER ANOTHER 2 BYTES
	MOVB	R4,6(R0)	;;;SEND LOW ORDER CHECKSUM
	SWAB	R4		;;;SWAP BYTES
	CALL	XWAIT
	MOVB	R4,6(R0)	;;;SEND HIGH ORDER CHECKSUM
	DEC	2(SP)		;;;DECREMENT PACKET COUNT		;MSH058
	BNE	30$		;;;IF NE SEND AN      OTHER PACKET		;**-1
									;**-1
;CLEAR OUT END PACKET MESSAGE FROM TU-58

	MOV	#14.,R3		;;;SET DUMP REC. BYTE COUNTER
50$:	BIT	#200,(R0)	;;;RECEIVE END PACKET CHAR.
	BEQ	50$		;;;IF EQ NO
	TST	2(R0)		;;;DUMP CHAR.				;MSH058
	DEC	R3		;;;DECREMENT COUNT			;**-1
	BNE	50$		;;;IF NE DUMP AGAIN
									;MSH058
	.IF DF	M$$MGE							;MSH058
									;MSH058
	CMP	#<7600-40>,@#KISAR6 ;;;HAVE WE HIT THE I/O PAGE?	;MSH058
									;MSH058
	.IFF	;M$$MGE							;MSH058
									;MSH058
	CMP	#<28.*4-3>      ,R2	;;;HAVE WE HIT THE I/O PAGE?		;MSH058
									;MSH058
	.IFTF	;M$$MGE							;MSH058
									;MSH058
	BNE	70$		;;;IF NE NO, MORE TO DUMP		;MSH058
60$:	CMP	(SP)+,(SP)+	;;;CLEAN STACK				;MSH058
	BR	$CRCMP		;;;DUMP IS DONE				;MSH058
70$:	TST	(R1)		;;;DOES NEXT MEMORY LOCATION EXIST?	;MSH058
	BCS	60$		;;;IF CS NO, DUMP IS DONE		;MSH058
									;MSH058
	.IFT	;M$$MGE							;MSH058
									;MSH058
	ADD	#40,@#KISAR6	;;;POINT TO NEXT 1K WORD SEGMENT	;MSH058
									;MSH058
	.IFTF	;M$$MGE						      	;MSH058
									;MSH058
	ADD	#4,R2		;;;ADJUST TU-58 BLOCK ADDRESS		;MSH058
	JMP	15$							;MSH058
									;**-14
CKSM:	ADD	R5,R4		;;;ADD 2ND WORD TO FIRST
	ADC	R4		;;;ADD CARRY -END AROUND CARRY CHECKSUM
XWAIT:	BIT	#200,4(R0)	;;;DL-11 TRANSMIT READY?
	BEQ	XWAIT		;;;IF EQ NO
	RETURN
DEND:	CMP	(SP)+,(SP)+	;;;CLEAN STACK				;MSH058
									;**-2
	.IFT	;M$$MGE							;MSH058
									;**-2
	CMP	R2,#497.	;;;HAVE WE TRANSFERED ENOUGH DATA
				;;;TO PUT US AT THE END OF THE TAPE
	BEQ	$CRCMP		;;;      IF EQ YES, SUCCESSFUL TRANSFER
				;;;OF ALL MEMORY THAT WILL FIT ON TAPE


	.ENDC


	.ENDC

									;**-30
	.IF EQ	C$$CDA-12
									;MSH054
;									;MSH054
;	MS								;MSH054
;									;MSH054
; IF THE EXECUTIVE DOES NOT SUPPORT 22-BIT ADDRESSING, THIS		;MSH054
; ROUTINE DUMPS ALL OF PHYSICAL MEMORY (UP TO A MAXIMUM OF		;MSH054
; 124K WORDS MAPPED OR 28K WORDS UMAPPED) IN 512 BYTE BLOCKS 		;MSH054
; AT 1600 BPI.								;MSH054
;									;MSH054
; IF THE EXECUTIVE SUPPORTS 22-BIT A      DDRESSING, THIS ROUTINE		;MSH054
; DUMPS ALL OF PHYSICAL MEMORY IN 512 BYTE BLOCKS AT 1600 BPI.		;MSH054
;									;MSH054

PBNH=	0
PBNL=	0


	BR	100$

1$:	.BLKW	5.		;;;THE COMMAND BUFFER PLUS ONE.

2$:				;;;THE CHARACTERISTICS DATA.
	.WORD	3$		;;; LSW OF MESSAGE BUFFER ADDRESS.
	.WORD	0		;;; MSW OF     "     "      "
	.WORD	14.		;;; THE SIZE OF THE MESSAGE BUFFER.
	.WORD	0		;;; THE FLAG WORD.

3$:	.BLKW	3		;;;THE MESSAGE BUFFER.
4$:	.BLKW	4		;;; XSTAT0 WITHIN MESSAGE BUFFER.

100$:	MO      V	#<1$+12>,R5	;;;WE NOW COMPUTE ADDRESS OF COMMAND	;MSH059
	BIC	#3,R5		;;;BUFFER. (NEEDS DOUBLE WORD BOUNDARY)	;MSH059
	MOV	#8.,-(R5)	;;;LENGTH OF COMMAND PACKET IN BYTES	;MSH059
	CLR	-(R5)		;;;UPPER 2 BITS OF COMMAND PACKET ADDRES;MSH059
	MOV	#2$,-(R5)	;;;LOW ORDER 16 BITS			;MSH059
	MOV	#100004,-(R5)	;;;WANT TO "WRITE CHARACTERISTICS"	;MSH059
	MOV	R5,R4		;;;COPY POINTER TO COMMAND PACKET.	;MSH059
				;;;R4=R5 IS FLAG THAT TS11 IS		;MSH059
				;;;BEING INITIALIZED (SEE 180$)		;MSH059
	MOV	R0,R1		;      ;;COPY CSR POINTER TO CONVERT IT TO	;**-7
	TST	-(R1)		;;; COMMAND REGISTER ADDRESS.
	CALL	200$		;;;ISSUE COMMAND, WAIT FOR SSR, TREAT ER;**-1
	MOV	#142010,(R5)	;;;REWIND AND CLEAR VOLUME CHECK	;MSH059
	CALL	200$		;;;ISSUE, WAIT, TREAT ERRORS.		;**-1
	MOV	#100005,(R5)+	;;; MAKE A WRITE COMMAND WITH HEADER	;**-1
									;MSH113
	.IF DF	M$$EXT							;MSH113
									;MSH113
	MOV	#20000,(R5)+	;;;POINT BUFFER TO SECOND UMR		;MSH113
									;MSH113
	.IFF								;MSH113
									;MSH113
	CLR	(R5)+		      ;;;START AT LOCATION 0			;MSH113
									;MSH113
	.ENDC								;MSH113
									;MSH113
	CLR	(R5)+		;;;					;MSH113
	MOV	#512.,(R5)	;;;NUMBER OF BYTES IN A RECORD		;MSH059
				;;;(R5 NOT EQUAL R4 AS FLAG !!)		;**-3


	.IF DF	M$$EXT

	CLR	@#UBMPR+4	;;;INITIALIZE SECOND UMR TO ADDRESS 0	;MSH113
	CLR	@#UBMPR+6	;;;					;MSH113
	BIS	#60,SR3		;;;ENABLE 22 BIT MAPPING AND UNIBUS MAP.;**-3
	BIS	#1,SR0		;;;MAKE SURE MEMORY MANAGEMENT ENABLED.
	MOV	#<1920./4>,R3	;;;MAXIMUM NUMBER OF 4K WORD BLOCKS	;MS      H059
40$:	MOV	#<1024.*4*2/512.>,R2 ;;;NUMBER OF 512 BYTE RECORDS/BLOCK;MSH059
									;**-2
	.IFF

									; RP067
	.IF DF	M$$MGE							; RP067
									; RP067
	MOV	#<124.*4>,R2	;;;NUMBER OF 512 BYTE RECORDS		; RP067
									; RP067
	.IFF	;M$$MGE							; RP067
									; RP067
	MOV	#<28.*4>,R2	;;;NUMBER OF 512 BYTE RECORDS		; RP067
									; RP067
	.ENDC	;M$$MGE							; RP067
									; RP067
									;**-1
	.IFTF

50$:	MOV	#9.,R5		;;;RETRY COUNT+1			;MSH059
	CALL	200$		;;;ISSUE WRI      TE AND WAIT			;MSH059
	ADD	#512.,2(R4)	;;;BUMP START ADDRESS OF DATA.		;**-1
	ADC	4(R4)		;;; (DOUBLE PRECISION ADDRESS.)
	DEC	R2		;;;LIMIT CHECK ON RECORDS COUNT ?
	BNE	50$		;;; LOOP TILL LIMIT (OR ERR IN 200$)


	.IFT

	ADD	#<1024.*4*2>,@#UBMPR+4 ;;;BUMP ADDRESS OF UMR 1 BY	;MSH113
	ADC	@#UBMPR+6       ;;; 4K WORDS				;MSH113
	MOV	#20000,2(R4)	;;;REINITIALIZE POINTER WITHIN 4K	;MSH113
				;;; WINDOW TO START OF UMR 1		;MSH113
	DEC	R3		;;;LIMIT CHECK ON BLOCK COUNT ?		;**-3
	BNE	40$		;;;IF NE       BLOCK LIMIT NOT REACHED	;MSH059
									;MSH059
	.IFTF								;MSH059
									;MSH059
;									;MSH059
; NOTE THAT THE FOLLOWING BRANCH IS NEVER TAKEN IF 180$ IS FALLEN	;MSH059
; INTO (R5 IS NEVER EQUAL TO R4, BECAUSE R5 IS A RETRY COUNT AND	;MSH059
; R4 IS AN ADDRESS, UNLESS 180$ IS BRANCHED TO FROM BELOW).		;MSH059
;									;MSH059
									;MSH059
180$:	CMP	R4,R5		;;;IS TS11 BEING INITIALIZED?		;MSH059
	BEQ	280$		;;;IF EQ YES, ERROR EXIT		;MSH059
	MOV	#100011,(R4)	;;;WANT TO FORMAT (WRITE       TAPE MARK)	;MSH059
	MOV	R4,(R1)		;;;ISSUE COMMAND			;MSH059
190$:	TSTB	(R0)		;;;SUBSYSTEM READY?			;MSH059
	BPL	190$		;;;IF PL NO				;MSH059
	BR	$CRCMP		;;;SUCCESSFUL TERMINATION		;MSH059
									;MSH059
200$:				;;;REF LABEL				;MSH059
	.IFT								;MSH059
									;MSH059
	MOV	R3,-(SP)	;;;SAVE BLOCK COUNTER			;MSH059
									;MSH059
	.IFTF								;MSH059
									;MSH059
210$:	MOV	R4,(R1)		;;;ISSUE COMMAND			;MSH059
225$:	TSTB	(R0)		;;;TEST FOR SSR (SUBSYSTEM READY) ?	;**-11
	BPL	225$		;      ;;NO=> LOOP; ELSE ....
	MOV	(R0),R3		;;;GET STATUS				;MSH059
	BMI	250$		;;;PROBLEM=> GO CHECK OUT; ELSE ...	;**-1
									;MSH059
	.IFT								;MSH059
									;MSH059
	MOV	(SP)+,R3	;;;RESTORE BLOCK COUNTER		;MSH059
									;MSH059
	.ENDC								;MSH059
									;MSH059
	BIC	#1000,(R4)	;;;CLEAR "WRITE DATA RETRY" BIT		;MSH059
	RETURN			;;;  GO ON WITH THE DUMP.

250$:	BIT	#1,4$		;;;EOT SEEN ON THIS OPERATION ?
	BNE	180$		;;;IF NE YES				;MSH059
	BIT	#4000,R3	;;;NONEXISTENT MEMORY?			;MSH05      9
	BNE	180$		;;;IF NE YES				;MSH059
	BIC	#^C<16>,R3	;;;ISOLATE TERMINATION CODE		;MSH059
	CMP	#12,R3		;;;RECOVERABLE ERROR (TAPE HAS NOT MOVED;MSH059
	BEQ	270$		;;;IF EQ YES				;MSH059
	CMP	#10,R3		;;;RECOVERABLE ERROR (TAPE HAS MOVED ONE;MSH059
				;;;RECORD?				;MSH059
	BNE	280$		;;;IF NE NO, I/O ERROR			;MSH059
	BIS	#1000,(R4)	;;;CHANGE COMMAND TO "SPACE REVERSE,	;MSH059
				;;;ERASE, WRITE DATA"			;MSH059
270$:	DEC	R5		;;;EXHAUSTED RETRY COUNT?		;MSH059
	BNE	210$		;;;IF NE NO				;MSH059
280      $:	TST	(SP)+		;;;DISCARD RETURN ADDRESS		;MSH059
									;**-20
	.ENDC


	.IIF EQ	C$$CDA-13,	CDA$DX=0				; PJC015
									; PJC015
									; PJC015
	.IIF EQ	C$$CDA-14,	CDA$DY=0				; PJC015
									; PJC015
									; PJC015
	.IF DF	CDA$DX!CDA$DY						; PJC015
									; PJC015
									; PJC015
;									; PJC015
;	DX AND DY							; PJC015
;									; PJC015
; THE LOCAL SYMBOLS REFERENCED ABOVE, CDA$DX AND CDA$DY, ARE		; PJC015
; USED WITHIN THE FOLLOWING COMMON CODE DRIVER BELOW TO			      ; PJC015
; DIFFERENTIATE BETWEEN RX01 AND RX02 TYPE DRIVES.			; PJC015
;									; PJC015
; IF THE EXECUTIVE DOES NOT SUPPORT 22-BIT ADDRESSING, THIS		; PJC015
; ROUTINE DUMPS A MAXIMUM OF 123K WORDS FOR A MAPPED SYSTEM		; PJC015
; AND 28K WORDS FOR AN UNMAPPED SYSTEM.					; PJC015
;									; PJC015
; IF THE EXECUTIVE DOES SUPPORT 22-BIT ADDRESSING, THIS ROUTINE		; PJC015
; DUMPS A MAXIMUM OF 123K WORDS TO A SINGLE DENSITY FLOPPY, BE		; PJC015
; IT A DX OR DY, AND UP TO A MAXIMUM OF 246K WORDS TO       A DOUBLE		; PJC015
; DENSITY DY FLOPPY.							; PJC015
;									; PJC015
									; PJC015
PBNH=	0			;;;HIGH ORDER RX11/211 BLOCK NUMBER	; PJC015
PBNL=	1			;;;LOW ORDER RX11/211 BLOCK NUMBER	; PJC015
									; PJC015
	CALL	CKSUM		;;;CHECK LBN AGAINST CHECKSUM		; PJC015
	MOV	#$TRINT,@#114	;;;SET UP NXM TRAP CATCHER		; PJC015
									; PJC015
									; PJC015
	.IF DF	M$$MGE							; PJC015
									; PJC015
									; PJC015
	.IF NDF	CDA$DY							; PJC015
									; PJC015
	MOV	#123.*4,-(SP      )	;;;DUMP 123.K WORDS MAX			; PJC015
	CLR	@#KISAR6	;;;POINT TO FIRST BYTE TO TRANSFER	; PJC015
	BIS	#1,@#SR0	;;;ENSURE MEM MGMT IS ON		; PJC015
									; PJC015
	.IFF	;CDA$DY							; PJC015
									; PJC015
									; PJC015
	.IF DF	M$$EXT							; PJC015
									; PJC015
	MOV	#256.*4,-(SP)	;;;DUMP 256.K WORDS MAX			; PJC015
	CLR	@#UBMPR		;;;INITIALIZE FIRST UNIBUS MAPPING REGS.; PJC015
	CLR	@#UBMPR+2	;;;					; PJC015
	CLR	@#KISAR0	;;;					; PJC015
	BIS	#60,@#SR3	;;;ENABLE 22-BIT MAPPING AND       UNIBUS MAP	; PJC015
	BIS	#1,@#SR0	;;;ENSURE MEM MGMT IS ON		; PJC015
									; PJC015
	.IFF	;M$$EXT							; PJC015
									; PJC015
	MOV	#123.*4,-(SP)	;;;DUMP 123.K WORDS MAX			; PJC015
									; PJC015
	.ENDC	;M$$EXT							; PJC015
									; PJC015
									; PJC015
	.ENDC	;CDA$DY							; PJC015
									; PJC015
									; PJC015
	.IFF	;M$$MGE							; PJC015
									; PJC015
	MOV	#28.*4,-(SP)	;;;DUMP 28.K WORDS MAX			; PJC015
									; PJC015
	.ENDC	;M$$MGE							; PJC015
									      ; PJC015
									; PJC015
	ASL	R3		;;;POSITION UNIT SELECT BITS		; PJC015
	ASL	R3		;;;					; PJC015
	ASL	R3		;;;					; PJC015
	ASL	R3		;;;					; PJC039
	MOV	#13,R5		;;;READ STATUS FUNCTION CODE		; PJC015
	BIS	R3,R5		;;;MERGE UNIT NUMBER			; PJC015
	MOV	R5,(R0)		;;;DO A READ STATUS			; PJC015
5$:	BITB	#40,(R0)	;;;DONE?				; PJC015
	BEQ	5$		;;;IF EQ NO				; PJC015
	TST	(R0)		;;;ANY ERRORS?				; PJC015
									; PJC015
									; PJC015
	.IF DF	CDA$DY							; PJC015
									; PJC015
	BPL	15$      		;;;IF PL NO				; PJC015
	BITB	#20,2(R0)	;;;DENSITY ERROR?			; PJC015
	BEQ	105$		;;;IF EQ NO				; PJC015
10$:	MOV	#40000,(R0)	;;;INITIALIZE RX211 SUBSYSTEM		; PJC015
	BIS	#400,R3		;;;SHOW DOUBLE DENSITY			; PJC039
	BR	5$		;;;OK NOW?				; PJC015
									; PJC015
	.IFF	;CDA$DY							; PJC015
									; PJC015
	BMI	105$		;;;IF MI YES				; PJC015
									; PJC015
	.IFTF	;CDA$DY							; PJC015
									; PJC015
15$:	MOV	#128.,R1	;;;WORD TRANSFER COUNT			; PJC015
	CLR	R2		;;;STARTING BUFFER ADDRE      SS		; PJC015
	MOV	$CRSBN+2,R4	;;;GET LOGICAL BLOCK #			; PJC015
									; PJC015
	.IFT	;CDA$DY							; PJC015
									; PJC015
	BIT	#400,R3		;;;DOUBLE DENSITY?			; PJC039
	BNE	20$		;;;IF NE YES				; PJC015
	ASR	R1		;;;POSITION WC FOR SINGLE DENSITY	; PJC015
	BR	25$		;;;					; PJC015
20$:	ASR	(SP)		;;;BLOCK COUNT FOR MAX MEMORY DUMP	; PJC039
	BR	30$		;;;					; PJC015
									; PJC015
	.IFTF	;CDA$DY							; PJC015
									; PJC015
25$:	ASL	R4		;;;SHIFT STARTING LBN...		; PJC015
30$:	ASL	R4	      	;;;...FOR CORRECT DENSITY		; PJC015
									; PJC015
;									; PJC015
; THE ABOVE CODE IS EXECUTED ONLY ONCE DURING A CRASH DUMP.		; PJC015
;									; PJC015
									; PJC015
35$:	CALL	TRKSEC		;;;CONVERT LBN TO TRACK/SECTOR		; PJC015
40$:	MOV	#1,R5		;;;FILL SILO				; PJC015
	BIS	R3,R5		;;;MERGE UNIT AND DENSITY BIT		; PJC015
	MOV	R5,(R0)		;;;INITIATE FILL SILO			; PJC015
									; PJC015
	.IFT	;CDA$DY							; PJC015
									; PJC015
45$:	CALL	TRWAIT		;;;WAIT					; PJC015
	MOV	R1,2(R0)	      ;;;LOAD WORD COUNT			; PJC015
	CALL	TRWAIT		;;;WAIT					; PJC015
	MOV	R2,2(R0)	;;;LOAD BUFFER ADDRESS			; PJC015
50$:	BITB	#40,(R0)	;;;DONE?				; PJC015
	BEQ	50$		;;;IF EQ NO				; PJC015
	TST	(R0)		;;;ANY ERRORS?				; PJC015
	BMI	105$		;;;IF MI YES				; PJC015
									; PJC015
	.IFF	;CDA$DY							; PJC015
									; PJC015
									; PJC015
	.IF DF	M$$MGE							; PJC015
									; PJC015
	MOV	#140000,R2	;;;SET TO USE APR6			; PJC015
									; PJC015
	.IFTF	;M$$MGE							; PJC015
									;       PJC015
55$:	TST	(R2)		;;;DOES NEXT MEMORY LOCATION EXIST?	; PJC015
	BCC	60$		;;;IF CC YES				; PJC015
	CMP	(SP)+,(SP)+	;;;NO, CLEAN STACK			; PJC015
	BR	135$		;;;					; PJC015
60$:	BITB	#240,(R0)	;;;TRANSFER REQUEST?			; PJC015
	BMI	65$		;;;IF MI YES				; PJC015
	BEQ	60$		;;;IF EQ NO				; PJC015
	BR	70$		;;;SILO IS FULL				; PJC015
65$:	MOVB	(R2)+,2(R0)	;;;PUT NEXT BYTE IN SILO		; PJC015
	DEC	R1		;;;DONE?				; PJC015
	BR	60$		;;;WAIT TILL IT'S ACCEPTED		; PJC015
70$:	TSTB	R1		;;;ALL BYTES TRANS      FERRED?		; PJC015
	BNE	105$		;;;IF PL NO, ERROR			; PJC015
									; PJC015
	.IFT	;M$$MGE							; PJC015
									; PJC015
	ADD	#2,@#KISAR6	;;;UPDATE BUFFER POINTER		; PJC015
									; PJC015
	.ENDC	;M$$MGE							; PJC015
									; PJC015
									; PJC015
	.IFTF	;CDA$DY							; PJC015
									; PJC015
75$:	MOV	#5,R5		;;;SET WITH WRITE FUNCTION		; PJC015
	BIS	R3,R5		;;;MERGE UNIT NUMBER			; PJC015
	MOV	R5,(R0)		;;;INITIATE WRITE			; PJC015
80$:	CALL	TRWAIT		;;;WAIT					; PJC015
85$:	MOVB      	SECTOR,2(R0)	;;;LOAD SECTOR				; PJC015
90$:	CALL	TRWAIT		;;;WAIT					; PJC015
95$:	MOVB	TRACK,2(R0)	;;;LOAD TRACK				; PJC015
100$:	BITB	#40,(R0)	;;;DONE?				; PJC015
	BEQ	100$		;;;IF EQ NO				; PJC015
	TST	(R0)		;;;ANY ERRORS?				; PJC015
	BPL	110$		;;;IF PL NO				; PJC015
									; PJC015
	.IFT	;CDA$DY							; PJC015
									; PJC015
	BIT	#4000,2(R0)	;;;NON-EXISTANT MEMORY?			; PJC015
	BNE	135$		;;;IF NE YES				; PJC015
									; PJC015
	.IFTF	;CDA$DY							; PJC015
									; PJC015
1      05$:	JMP	WERR		;;;ERROR				; PJC015
110$:	DEC	(SP)		;;;DONE?				; PJC015
	BEQ	135$		;;;IF EQ YES				; PJC015
									; PJC015
	.IFT	;CDA$DY							; PJC015
									; PJC015
									; PJC015
	.IF DF	M$$EXT							; PJC015
									; PJC015
	DEC	BLKCNT		;;;DECREMENT LBN COUNT			; PJC015
	BNE	115$		;;;IF NE USE SAME UMR			; PJC015
	ADD	#20000,@#UBMPR	;;;POINT TO NEXT 4K OF MEMORY		; PJC015
	ADC	@#UBMPR+2	;;;DOUBLE WORD ADD			; PJC015
	MOV	#16.*2,BLKCNT	;;;LBN'S PER 4K WORDS			; PJC015
	CLR	R2		;      ;;RESET BUFFER ADDRESS			; PJC015
	BR	130$		;;;					; PJC015
									; PJC015
	.ENDC	;M$$EXT							; PJC015
									; PJC015
									; PJC015
115$:	BIT	#400,R3		;;;DOUBLE DENSITY?			; PJC015
	BEQ	120$		;;;IF EQ NO				; PJC015
	ADD	#256.,R2	;;;UPDATE BUFFER ADDRESS FOR DOUBLE DENS; PJC015
	BR	125$		;;;					; PJC015
120$:	ADD	#128.,R2	;;;UPDATE BUFFER ADDRESS FOR SINGLE DENS; PJC015
125$:	BCC	130$		;;;IF CC, NO OVERFLOW			; PJC015
									; PJC015
									; PJC015
	.IF DF	M$$MGE							; PJC      015
									; PJC015
	ADD	#10000,R3	;;;CARRY INTO EXTENDED MEMORY BITS	; PJC015
									; PJC015
	.ENDC	;M$$MGE							; PJC015
									; PJC015
									; PJC015
	.IFF	;CDA$DY							; PJC015
									; PJC015
	MOV	#128.,R1	;;;SET UP WC AGAIN			; PJC015
									; PJC015
	.IFTF	;CDA$DY							; PJC015
									; PJC015
130$:	MOV	#1,R5		;;;FILL SILO				; PJC015
	INC	R4		;;;INCREMENT LBN			; PJC015
	BR	35$		;;;GO AGAIN				; PJC015
135$:	TST	(SP)+		;;;CLEAN STACK				; PJC015
	BR	$CRCMP		;;;DU      MP IS DONE				; PJC015
									; PJC015
SECTOR:	.WORD	0		;;;SECTOR NUMBER			; PJC015
TRACK:	.WORD	0		;;;TRACK NUMBER				; PJC015
									; PJC015
	.IFT	;CDA$DY							; PJC015
									; PJC015
									; PJC015
	.IF DF	M$$EXT							; PJC015
									; PJC015
BLKCNT:	.WORD	16.*2		;;;LBN'S PER 4K WORDS			; PJC015
									; PJC015
	.ENDC	;M$$EXT							; PJC015
									; PJC015
									; PJC015
	.ENDC	;CDA$DY							; PJC015
									; PJC015
									; PJC015
TRWAIT:	BITB	#240,(R0)	;;;TRA      NSFER REQUEST?			; PJC015
	BMI	5$		;;;IF MI YES				; PJC015
	BEQ	TRWAIT		;;;IF EQ NEITHER			; PJC015
	BR	WERR		;;;ERROR				; PJC015
5$:	RETURN			;;;					; PJC015
									; PJC015
;									; PJC015
; CONVERT LOGICAL BLOCK NUMBER TO PHYSICAL TRACK/SECTOR PAIR		; PJC015
;									; PJC015
; INPUT:								; PJC015
;	R4 = LOGICAL BLOCK NUMBER					; PJC015
;									; PJC015
; OUTPUT:								; PJC015
;	SECTOR - SECTOR (1-26.)						; PJC015
;	TRACK - TRACK (0-76.)						; PJC015
;									; PJC015      
									; PJC015
TRKSEC:	MOV	R0,-(SP)	;;;SAVE REGISTERS			; PJC015
	MOV	R1,-(SP)	;;;					; PJC015
	MOV	R2,-(SP)	;;;					; PJC015
	MOV	R4,R1		;;;GET LOGICAL BLOCK #			; PJC015
	MOV	#8.,R0		;;;SET LOOP COUNT			; PJC015
	MOV	#6400,R2	;;;AND DIVISOR				; PJC015
5$:	CMP	R2,R1		;;;DOES 26. GO INTO DIVIDEND?		; PJC015
	BHI	10$		;;;IF HI NO, C=0			; PJC015
	SUB	R2,R1		;;;SUBTRACT 26.				; PJC015
	SEC			;;;					; PJC015
10$:	ROL	R1		;;;SHIFT DIVIDEND AND QUOTIENT		; PJC015
	DEC	R0		;;;DONE?				; PJC015      
	BGT	5$		;;;IF GT NO				; PJC015
	BISB	R1,R0		;;;GET TRACK NUMBER			; PJC015
15$:	CLRB	R1		;;;CLEAR TRACK NUMBER			; PJC015
	SWAB	R1		;;;POSITION SECTOR NUMBER		; PJC015
	CMP	#12.,R1		;;;C=1 IF 13<=R1<=25			; PJC015
	ROL	R1		;;;DOUBLE FOR INTERLEAVE FACTOR		; PJC015
	ASL	R0		;;;ADD TRACK - TRACK SKEW		; PJC015
	ADD	R0,R1		;;;SKEW BY 2*TRACK			; PJC015
	ADD	R0,R1		;;;SKEW BY 4*TRACK			; PJC015
	ADD	R0,R1		;;;SKEW BY 6*TRACK			; PJC015
	ASR	R0		;;;RESTORE TRACK NUMBER			; PJC015
	MOV	#26.,R2		;;;      SET MODULUS				; PJC015
20$:	SUB	R2,R1		;;;MODULO SECTOR INTO RANGE -26. TO -1.	; PJC015
	BGE	20$		;;;IF GE LOOP TIL NEGATIVE		; PJC015
	ADD	R2,R1		;;;CONVERT TO RANGE 0-25.		; PJC015
	INC	R0		;;;LBN0 STARTS ON TRACK 1		; PJC015
25$:	INC	R1		;;;CONVERT TO RANGE 1-26.		; PJC015
	MOVB	R1,SECTOR	;;;SAVE SECTOR NUMBER			; PJC015
	MOVB	R0,TRACK	;;;SAVE TRACK NUMBER			; PJC015
	MOV	(SP)+,R2	;;;RESTORE REGISTERS			; PJC015
	MOV	(SP)+,R1	;;;					; PJC015
	MOV	(SP)+,R0	;;;					; PJC015
	RETURN								; PJ      C015
									; PJC015
									; PJC015
	.ENDC	;CDA$DX!CDA$DY						; PJC015
									; PJC015
									; PJC015
WERR:	MOV	#IOERR,R1	;;;INDICATE I/O ERROR
	CALL	TYPE		;;;TYPE OUT MESSAGE
	JMP	AGAIN		;;;WAIT FOR THE USER
$CRCMP:
	.ENDC


	.IF DF P$$NIC

	JMP	$PANIC		;;;JUMP TO PANIC DUMP ROUTINE

	.ENDC

	.ENDC	;C$$RSH							;MSH054
									;**-1

;+
; IF B$$OOT IS DEFINED, RE-BOOT THE SYSTEM BY JUMPING TO THE
; BOOTSTRAP ROM ADDRESS SPECIFIED BY B$$OOT.  ELSE, RE-ISSUE
; THE CRASH    ä  MESSAGE IF THE USER WISHES ANOTHER DUMP.  IF NO
; CRASH DUMP WAS CONFIGURED, SIMPLY RE-BOOT OR HALT FOREVER.
;-

$BTSTP::			;;;RE-BOOT THE SYSTEM


	.IF DF	B$$OOT

	HALT			;;;WAIT FOR THE USER BEFORE BOOTING
	RESET			;;;RESET THE WORLD
	JMP	@#B$$OOT	;RE-BOOT THE SYSTEM

	.IFF

	HALT			;;;WAIT FOR THE USER


	.IF DF	C$$RSH


	.IF DF	C$$CDA

	JMP	AGAIN		;;;DO IT ALL OVER AGAIN

	.ENDC


	.IFF

	BR	.-2		;;;LOOP FOREVER

	.ENDC


	.ENDC


	.END
ä         ÔfðskQ	› c,        	.TITLE	PRDRV
	.IDENT	/02.01/
 
;
; COPYRIGHT (C) 1975, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 02.01
;
; THOMAS J. MILLER 2-DEC-74
;
; PREVIOUSLY MODIFIED BY:
;
;	C. A. D'ELIA
;
; MODIFIED BY:
;
;	E. L. BAATZ 18-JUN-78
;
;		EB148 -- REMOVE EXPLICIT PS REFERENCE
;
; PC11/PR11 PAPER TAPE READER DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.      MCALL	ABODF$,HWDDF$,PKTDF$
	ABODF$			;DEFINE TASK ABORT CODES
	HWDDF$			;DEFINE HARDWARE REGISTER SYMBOLS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
 
;
; EQUATED SYMBOLS
;
; PAPER TAPE READER STATUS WORD BIT DEFINITIONS (U.CW2)
;
 
TRAIL=100000			;CURRENTLY READING TRAILER
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
 
CNTBL:	.BLKW	P$$R11		;ADDRESS OF UNIT CONTROL BLOCK
 
 
	.IF GT	P$$R11-1
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER
       
	.ENDC
 
	
;
; DRIVER DISPATCH TABLE
;
 
$PRTBL::.WORD	PRINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	PRCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	PROUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	PRPWF		;POWERFAIL ENTRY POINT
 
;+
; **-PRINI-PC11/PR11 PAPER TAPE READER CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS       NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-
 
	.EN      ABL	LSB
PRINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	PRPWF		;IF CS CONTROLLER BUSY OR NO REQUEST
 
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; PAPER TAPE READER I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT F      LAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB, IO.ATT OR IO.DET).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCAT      ION BIAS OF I/O BUFFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
 
	MOV	R5,CNTBL(R3)	;SAVE UCB POINTER FOR INTERRUPT ROUTINE
	MOVB	I.FCN+1(R1),R2	;MOVE FUNCTION CODE TO R2
	CMPB	R2,#IO.RLB/256.	;READ LOGICAL BLOCK FUNCTION?
	BEQ	10$		;IF EQ YES
	MOV	#IS.SUC&377,R0	;OTHER FUNCTIONS ALWAYS SUCCEED
	CLR	R1		;RETURN 0 IN SECOND WORD OF STATUS BUFFER
	CMPB	R2,#      IO.ATT/256.	;ATTACH FUNCTION?
	BNE	50$		;IF NE NO, CALL $IODON
	BIS	#TRAIL,U.CW2(R5) ;SET FLAG TO READ TRAILER IF ATTACH
	BR	60$		;CALL $IODON
10$:	MOVB	S.ITM(R4),S.CTM(R4) ;SET TIMEOUT COUNT
	TST	@S.CSR(R4)	;ERROR BIT SET IN STATUS REGISTER?
	BPL	15$		;IF PL NO, INITIATE IO
	TST	U.CW2(R5)	;IS THIS THE FIRST READ FOR ATTACHED PROCESS?
	BMI	70$		;IF MI YES, RETURN DEVICE NOT READY CODE
				;   (OTHERWISE HANDLE AS EOF UPON INTERRUPT)
15$:	MOV	#101,@S.CSR(R4)	;ENABLE READER WITH INTERRUPTS
 
;
;       IN-PROGRESS TRANSFERS ARE NOT TERMINATED.
;
 
PRCAN:
 
;
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION
;
 
PRPWF:	RETURN			;
 
;+
; **-$PRINT-PC11/PR11 PAPER TAPE READER CONTROLLER INTERUPTS
;-
 
$PRINT::			;;;REF LABEL
	INTSV$	PR,PR4,P$$R11	;;;GENERATE INTERRUPT SAVE CODE
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF STATUS CONTROL BLOCK
	MOV      B	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
	MOV	S.CSR(R4),R4	;;;POINT R4 TO CONTROL STATUS REGISTER
	MOV	(R4)+,U.CW3(R5)	;;;SAVE STATUS
	BMI	40$		;;;IF MI, ERROR
	TST	U.CW2(R5)	;;;READING TRAILER?
	BPL	20$		;;;IF PL NO
	TSTB	(R4)		;;;IS BYTE READ A NULL?
	BEQ	30$		;;;IF EQ YES
	CLR	U.CW2(R5)	;;;NO LONGER READING TRAILER
20$:	MOVB	(R4),-(SP)	;;;PUSH BYTE READ
	CALL	$PTBYT		;;;PLACE IT IN USER BUFFER
	DEC	U.CNT(R5)	;;;DECREMENT BYTE COUNT
	BEQ	40$		;;;IF EQ READ COMPLETE
30$:	INC	-(R4)		;;;ENAB      LE READER
	JMP	$INTXT		;;;EXIT FROM INTERRUPT
 
 
40$:	CLR	-(R4)		;;;DISABLE INTERRUPTS
	CALL	$FORK		;;;CREATE SYSTEM PROCESS
	MOV	U.SCB(R5),R4	;POINT R4 TO SCB
	MOV	S.PKT(R4),R1	;POINT R1 TO I/O PACKET
	MOV	I.PRM+4(R1),R1	;   AND PICK UP CHARACTER COUNT
	SUB	U.CNT(R5),R1	;CALCULATE CHARACTERS TRANSFERRED
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER
	TST	U.CW3(R5)	;DEVICE ERROR?
	BPL	50$		;IF PL NO
	MOV	#IE.EOF&377,R0	;RETURN END OF FILE CODE
50$:	CLR	U.CW2(R5)	;CLEAR FLAG WORD
60$:	CALL	$   R  IODON		;INITIATE I/O COMPLETION
	BR	PRINI		;BRANCH BACK FOR NEXT REQUEST
 
;
; DEVICE TIMEOUT RESULTS IN THE RETURN OF A DEVICE NOT READY ERROR CODE.
;
 
PROUT:	CLR	@S.CSR(R4)	;;;DISABLE READER INTERRUPTS
	MTPS	#0		;;;ALLOW INTERRUPTS
70$:	MOV	#IE.DNR&377,R0	;DEVICE NOT READY CODE
	BR	50$		;CALL $IODON
	.DSABL	LSB
 
	.END
R         äðskQ	› c,        	.TITLE	CTDRV
	.IDENT	/07/
 
;
; COPYRIGHT (C) 1974, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 07
;
; D. N. CUTLER 13-MAR-74
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	B. LYONS
;
; MODIFIED BY:
; 
;	P. J. BEZEREDI 04-MAR-77
;
;		PB019 -- FIX A BUG IN THE ERROR LOGGING LOGIC.
;
; TA11 TAPE CASSETTE CONTROLLER DRIVER
      ;
; NOTE: THIS IS A MINIMAL DRIVER AND CONTAINS NO ERROR RECOVERY.
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER)
;
 
CNTBL:	.BLKW	T$$A11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
 
 
	.IF GT	T$$A11-1
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER
 
	.ENDC
 
	
;
; ERROR PROCESSING CONTROL TABLE
;
	
ERRTB:	.BYTE	IE      .DNR&377,1000/400 ;DEVICE NOT READY
	.BYTE	IE.WLK&377,10000/400 ;DRIVE WRITE LOCKED
	.BYTE	IE.EOT&377,20000/400 ;END OF TAPE
	.BYTE	IE.EOF&377,4000/400 ;END OF FILE
	.BYTE	IE.DAO&377,2000/400 ;DATA OVERRUN
	.BYTE	IE.VER&377,377	;BLOCK CHECK ERROR
	
;
; LEGAL FUNCTION DISPATCH TABLE
;
 
LGFCN:	.WORD	IO.RLB		;READ LOGICAL BLOCK
	.BYTE	105,10.		;
	.WORD	RDBLK		;
	.WORD	IO.WLB		;WRITE LOGICAL BLOCK
	.BYTE	103,10.		;
	.WORD	WRBLK		;
	.WORD	IO.EOF		;WRITE END OF FILE
	.BYTE	101,10.		;
	.WORD	WR      EOF		;
	.WORD	IO.RWD		;REWIND
	.BYTE	117,34.		;
	.WORD	WREOF		;
	.WORD	IO.SPB		;SPACE BLOCK
	.BYTE	115,128.	;
	.WORD	SPCBK		;
	.WORD	IO.SPF		;SPACE FILE
	.BYTE	113,128.	;
	.WORD	SPCBK		;
 
;
; DRIVER DISPATCH TABLE
;
 
$CTTBL::.WORD	CTINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	CTCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	CTOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	CTPWF		;POWERFAIL ENTRY POINT
 
;+
; **-CTINI-TA11 TAPE CASSETTE CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE       QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;      	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-
 
	.ENABL	LSB
CTINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	CTPWF		;IF CS CONTROLLER BUSY OR NO REQUEST
 
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS       OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; TA11 TAPE CASSETTE FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO. RLB 1 IO.RWD/IO.SPB/IO.SPF/IO.EOF).
;	WD. 06 -- VIRTUAL ADDRESS OF I/      O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;
 
	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB
	MOV	#LGFCN,R3	;POINT TO LEGAL FUNCTION TABLE
	MOV	#6,R0		;SET NUMBER OF ENTRIES IN TABLE
10$:	CMP	I.FCN(R1),(R3)+	;FUNCTION CODE MATCH?
	BEQ	20$		;IF EQ YES
	CMP	(R3)+,(R3)+	;POINT TO NEXT TABLE ENTRY
	DEC	R0		;ANY MORE TABLE ENTRIES?
	BGT	10$		;IF GT YES
	MO      V	#IE.IFC&377,R0	;SET ILLEGAL FUNCTION STATUS
	BR	50$		;FINISH IN COMMON CODE
 
;
; FUNCTION CODE MATCH FOUND
;
 
20$:	SWAB	R2		;SWAP UNIT NUMBER TO LEFT BYTE
	BISB	(R3)+,R2	;MERGE FUNCTION CODE WITH UNIT
	MOVB	(R3)+,S.ITM(R4)	;SPACING FUNCTION?
	BPL	30$		;IF PL NO
 
;
; SPACING FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- SPACING COUNT (POSITIVE=FORWARD, NEGATIVE=BACKWARD).
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USE      D.
;	WD. 20 -- NOT USED.
;
 
	MOV	U.BUF(R5),I.PRM+4(R1) ;MOVE SPACING COUNT TO COMMON PLACE
	MOV	U.BUF(R5),U.CNT(R5) ;MOVE SPACING COUNT TO COMMON PLACE
	BEQ	40$		;IF EQ NO SPACING REQUIRED
	BPL	30$		;IF PL SPACE FORWARD
	NEG	U.CNT(R5)	;CONVERT TO POSITIVE COUNT
	NEG	I.PRM+4(R1)	;CONVERT TO POSITIVE COUNT
	SUB	#4,R2		;CONVERT TO REVERSE FUNCTION
 
;
; READ/WRITE LOGICAL FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD.       14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
; NO FUNCTION DEPENDENT PARAMETERS ARE REQUIRED FOR REWIND AND WRITE EOF
;
 
30$:	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	MOV	(R3),U.CW2(R5)	;SET INITIAL INTERRUPT ADDRESS
 

	.IF DF	E$$DVC
 
	CALL	$BMSET		; SET I/O ACTIVE IN BITMAP
 
	.ENDC
 

	MOV	R2,@S.CSR(R4)	;INITIATE FUNCTION
 
;
; CANCEL I/O OPERATION IS A NOP FOR TA11 TAPE CASSE      TTES.
;
 
CTCAN:				;REF LABEL
 
;
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION.
;
 
CTPWF:	RETURN			;
 
;
; NO SPACING REQUIRED
;
 
40$:	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS
50$:	BR	110$		;
 
;+
; **-$CTINT-TA11 TAPE CASSETTE CONTROLLER INTERRUPTS
;-
 
	INTSE$	CT,PR6,T$$A11	;;;GENERATE INTERRUPT SAVE CODE
	MOV	      R3,-(SP)	;;;SAVE R3
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET CURRENT DEVICE TIMEOUT COUNT
	MOV	S.CSR(R4),R3	;;;GET ADDRESS OF CSR
	BIT	#200,(R3)+	;;;TRANSFER REQUEST?
	BNE	60$		;;;IF NE YES
	MOV	-2(R3),U.CW3(R5) ;;;SAVE CURRENT STATUS
60$:	CALL	@U.CW2(R5)	;;;CALL INTERRUPT ROUTINE
	MOV	(SP)+,U.CW2(R5) ;;;SAVE INTERRUPT RETURN ADDRESS
	MOV	(SP)+,R3	;;;RESTORE R3
	JMP	$INTXT		;;;EXIT FROM INTERRUPT
 
;
; SPACING FUNCTION (FILE AND BLOCK)
;
 
SPCBK:	BMI	70$		;;      ;IF MI ERROR
	DEC	U.CNT(R5)	;;;DECREMENT SPACING COUNT
	BLE	70$		;;;IF LE DONE
	INC	-(R3)		;;;INITIATE NEXT OPERATION
	CALL	@(SP)+		;;;SET INTERRUPT RETURN ADDRESS
	BR	SPCBK		;;;GO AGAIN
70$:	CLR	-(R3)		;;;CLEAR INTERRUPT ENABLE
	TST	(SP)+		;;;REMOVE RETURN FROM STACK
	MOV	(SP)+,R3	;;;RESTORE R3
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	U.CW3(R5),R1	;GET FINAL STATUS
	BPL	90$		;IF PL SUCCESS
	BICB	#^C<7*2>,R1	;CLEAR ALL BUT FUNCTION CODE
	CMPB	#5*2,R1		;FORWARD OR REVERSE FUNCTION?
	BLE	100      $		;IF LE FORWARD
	BIC	#120777,R1	;CLEAR ERROR, BOT, UNIT, AND FUNCTION
	BEQ	40$		;IF EQ NO ERRORS
	BR	100$		;ANALYZE ERROR
 
;
; READ LOGICAL FUNCTION
;
 
RDBLK:	BMI	WREOF		;;;IF MI ERROR
	DEC	U.CNT(R5)	;;;DECREMENT BYTE COUNT
	BLT	80$		;;;IF LT NO MORE TO READ
	MOV	(R3),-(SP)	;;;READ BYTE FROM DATA REGISTER
	CALL	$PTBYT		;;;PUT BYTE IN USER BUFFER
	CALL	@(SP)+		;;;SET INTERRUPT RETURN ADDRESS
	BR	RDBLK		;;;GO AGAIN
 
;
; WRITE LOGICAL FUNCTION
;
 
WRBLK:	BMI	WREOF		;;;IF MI ERROR
	DE      C	U.CNT(R5)	;;;DECREMENT BYTE COUNT
	BLT	80$		;;;IF LT NO MORE TO WRITE
	CALL	$GTBYT		;;;GET BYTE FROM USER BUFFER
	MOVB	(SP)+,(R3)	;;;WRITE BYTE INTO DATA REGISTER
	CALL	@(SP)+		;;;SET INTERRUPT RETURN ADDRESS
	BR	WRBLK		;;;GO AGAIN
80$:	INC	U.CNT(R5)	;;;ADJUST BYTE COUNT
	BIS	#20,-(R3)	;;;INITIATE LAST BYTE SEQUENCE
	CALL	@(SP)+		;;;SET INTERRUPT RETURN ADDRESS
 
;
; REWIND AND WRITE END OF FILE FUNCTIONS
;
 
WREOF:	CLR	-(R3)		;;;CLEAR INTERRUPT ENABLE
	TST	(SP)+		;;;REMOVE RETURN FROM STAC      K
	MOV	(SP)+,R3	;;;RESTORE R3
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
90$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL COMPLETION STATUS
	MOV	U.CW3(R5),R1	;GET FINAL STATUS
	BPL	110$		;IF PL SUCCESS
100$:	SWAB	R1		;SWAP ERROR BITS TO LOW BYTE
	MOV	#ERRTB,R2	;GET ADDRESS OF ERROR CONTROL TABLE
105$:	CLR	R0		;PICKUP NEXT ERROR STATUS CODE
	BISB	(R2)+,R0	;
	BITB	(R2)+,R1	;ERROR BIT SET?
	BEQ	105$		;IF EQ NO


	.IF DF	E$$DVC

	BITB	#26,R1		;WRITE LOCK, TIMING OR OFF-LINE?
	BEQ	110$		;IF EQ NO
	CALL	      $DVERR		;LOG DEVICE ERROR

	.ENDC


	BR	110$		;FINISH I/O
 
;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED. TIMEOUTS ARE
; USUALLY CAUSED BY POWERFAILURE BUT ALSO MAY BE THE RESULT OF A HARD-
; WARE FAILURE.
;
 
CTOUT:	CALL	$DTOER		;;;LOG DEVICE TIMEOUT
110$:	MOV	S.PKT(R4),R1	;RETRIEVE ADDRESS OF I/O PACKET
	MOV	I.PRM+4(R1),R1	;GET ORIGINAL COUNT VALUE
	SUB	U.CNT(R5),R1	;SUBTRACT COUNT REMAINING
 

	.IF DF	E$$DVC
 
	MOV	#401,R2		; SET CURRENT & FINAL RETRY COUNT TO   h    1
 
	.ENDC

 
	CALL	$IODON		;FINISH I/O OPERATION
	JMP	CTINI		;GO AGAIN
	.DSABL	LSB
 
	.END
 h          BkQ	› c,        	.TITLE	CVRTM
	.IDENT	/03.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 03.00
;
; D. N. CUTLER 12-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;
; MODIFIED BY:
;
;+
; **-$CVRTM-CONVERT TIME
;
; THIS ROUTINE IS CALLED TO CONVERT A TIME INTERVAL-TIME UNITS PAIR
; TO A CLOCK TICKS COUNT.
;
; INPU      TS:
;
;	R3=ADDRESS OF TIME INTERVAL-TIME UNITS PAIR.
;
; OUTPUTS:
;
;	IF AN ILLEGAL TIME INTERVAL (GREATER THAN 15 BITS) OR
;	ILLEGAL TIME UNITS (ZERO OR GREATER THAN 4) IS SPECIFIED,
;	THEN A DIRECTIVE STATUS OF 'D.RS93' IS RETURNED. ELSE THE
;	TICKS COUNT IS RETURNED WITH THE HIGH ORDER PART IN R0 AND
;	THE LOW ORDER PART IN R1. R3 IS ADVANCED BY 4 THUS POINTING
;	PAST THE TIME INTERVAL-TIME UNITS PAIR.
;-

$CVRTM::MOV	(R3)+,R1	;GET TIME INTERVAL
	BMI	70$		;IF MI ILLEGAL TIME INTERVAL
	MOV      	(R3)+,R0	;GET TIME UNITS
	DEC	R0		;BACK OFF BY ONE
	CMP	R0,#3		;LEGAL UNITS?
	BHI	70$		;IF HI NO
	ASL	R0		;CONVERT TO DISPATCH INDEX
	ADD	R0,PC		;DISPATCH
10$:	BR	50$		;1=TICKS
	BR	30$		;2=SECONDS
	BR	20$		;3=MINUTES
	MOV	#60.,R0		;4=HOURS
	CALL	$MUL		;CALCULATE NUMBER OF MINUTES
	TST	R0		;OVERFLOW 16 BITS?
	BNE	70$		;IF NE YES
20$:	CMP	R1,#1440.	;MORE THAN ONE DAY OF MINUTES?
	BHI	70$		;IF HI YES
	MOV	#30.,R0		;MULTIPLY BY 60. SECONDS/2
	CALL	$MUL		;PRODUCT CANNOT OVERFLOW 16 BITS.
	MOV	$   @  TKPS,R0	;GET TICKS PER SECOND
	ASL	R0		;MULTIPLY BY 2
	BR	40$		;
30$:	MOV	$TKPS,R0	;GET TICKS PER SECOND
40$:	CALL	$MUL		;CALCULATE TICKS COUNT
50$:	MOV	R0,R2		;TICKS COUNT ZERO?
	BIS	R1,R2		;
	BNE	60$		;IF NE NO
	INC	R1		;MAKE TICKS COUNT 1
60$:	RETURN			;
70$:	DRSTS	D.RS93		;SET DIRECTIVE STATUS

	.END
 @         TðskQ	› c,        	.TITLE	DBDRV
	.IDENT	/06.10/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 06.10
;
; D. N. CUTLER 2-JUL-74
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;	R. T. PERRON
;
; MODIFIED BY:
;
;	R. T. PERRON 25-JUN-79
;
;		RP015 -- CORRECTION TO OFFSET RECOVERY AND HEADER
;			COMPARE ERRO      RS FIX
;
;	R. T. PERRON 06-AUG-79
;
;		RP021 -- CORRECT ERROR RECOVERY FOR LAST BLOCK TRANSFERED
;
;	R. T. PERRON 01-APR-80
;
;		RP030 -- CORRECT ECC ERROR RECOVERY ON RH11 CONTROLLERS
;
;	P. J. CARR	18-APR-80
;
;		PJC003 -- REMOVE M$$IXD STUFF
;
;	R. T. PERRON 21-NOV-80
;
;		RP041 -- CHANGE INTERFACE TO COMMON ECC ROUTINE
;
;	P. J. CARR	1-APR-81
;
;		PJC026 -- CORRECT MORE ERROR RECOVERY PROCEDURES
;
;	P. J. BEZEREDI 15-APR-81
;
;		PB237 -- MAKE BETTER USE OF EIS.
;
;	P. J. CARR	1      2-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
;	R. T. PERRON	16-OCT-81
;
;		RP075 -- CORRECT NON-EIS ADDRESS CALCULATION IN ECC CODE
;
;	P. J. CARR	27-OCT-81
;
;		PJC038 -- CLEAN UP CODE
;
; RH11-RP04/05/06 DISK PACK DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;
; DEVICE REGISTER AND STATUS BIT DEFINITIONS
;

RPCS1=0				;CONTROL STATUS REGISTER 1

TRE=40000			;TRANSF      ER ERROR
MCPE=20000			;MASSBUS CONTROL PARITY ERROR


RPWC=2				;WORD COUNT REGISTER
RPBA=4				;BUFFER ADDRESS REGISTER
RPDA=6				;DESIRED TRACK/SECTOR REGISTER

RPCS2=10			;CONTROL STATUS REGISTER 2

DLT=100000			;DATA LATE ERROR
WCE=40000			;WRITE CHECK ERROR
UPE=20000			;UNIBUS PARITY ERROR
NED=10000			;NONEXISTENT DISK ERROR
NEM=4000			;NONEXISTENT MEMORY ERROR
PGE=2000			;PROGRAMMING ERROR
MXF=1000			;MISSED TRANSFER ERROR
MDPE=400			;MASSBUS DATA PARITY ERROR

RPDS=12				;DRIVE STAT      US REGISTER

ERR=40000			;ERROR SUMMARY BIT
PIP=20000			;POSITIONING IN PROGRESS		; PJC026
MOL=10000			;MEDIUM ONLINE
WRL=4000			;WRITE LOCKED DRIVE
DRY=200				;DRIVE READY
VV=100				;VOLUME VALID


RPER1=14			;ERROR SUMMARY REGISTER

DCK=100000			;DATA CHECK ERROR
UNS=40000			;DRIVE UNSAFE
OPI=20000			;OPERATION INCOMPLETE
DTE=10000			;DRIVE TIMING ERROR
WLE=4000			;WRITE LOCK ERROR
IAE=2000			;INVALID DISK ADDRESS
AOE=1000			;ADDRESS OVERFLOW
HCRC=400			;HEADER CRC ERROR
HCE=200				;HE      ADER COMPARE ERROR
ECH=100				;ECC HARD ERROR
WCF=40				;WRITE CLOCK FAILURE
FER=20				;FORMAT ERROR
CPE=10				;CONTROL BUS PARITY ERROR
RMR=4				;REGISTER MODIFY REFUSED
ILR=2				;ILLEGAL REGISTER
ILF=1				;ILLEGAL FUNCTION


RPAS=16				;ATTENTION SUMMARY REGISTER
RPLA=20				;LOOKAHEAD REGISTER
RPDBR=22			;DATA BUFFER REGISTER
RPMR=24				;MAINTENENCE REGISTER
RPDT=26				;DRIVE TYPE REGISTER
RPSN=30				;DRIVE SERIAL NUMBER

RPOF=32				;DRIVE OFFSET REGISTER

FMT22=10000			;FORMAT (1=16 BI      T)
ECI=4000			;ECC INHIBIT
HCI=2000			;HEADER COMPARE INHIBIT


RPDC=34				;DESIRED CYLINDER NUMBER
RPER2=40			;ERROR REGISTER 2
RPEC1=44			;ECC POSITION REGISTER
RPEC2=46			;ECC PATTERN REGISTER
RPBAE=50			;BUS ADDRESS EXTENSION REGISTER
									;**-7

;
; LOCAL EQUATED SYMBOLS
;
RETRY=8.			;CONTROLLER ERROR RETRY COUNT
IHC=1				;INHIBIT HEADER COMPARE
OFA=10				;OFFSET ACTIVE BIT

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER)
;

CNTBL:	.BLKW	R$$JP      1		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$JP1		;RETRY COUNT FOR CURRENT OPERATION


	.IF GT	R$$JP1-1

TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC


	.IF DF	R$$JPO

OFFAD:	.BLKW	R$$JP1		;ADDRESS OF CURRENT OFFSET VALUE

;
; OFFSET POSITIONING VALUE TABLE
;

OFFTB:	.WORD	FMT22!20	;+400
	.WORD	FMT22!220	;-400
	.WORD	FMT22!40	;+800
	.WORD	FMT22!240	;-800
	.WORD	FMT22!60	;+1200
	.WORD	FMT22!260	;-1200
	.WORD	0		;RETURN TO CENTERLINE

	.ENDC


	.IF       DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

;
; DIAGNOSTIC FUNCTION TABLE
;
FUNTBL:	.BYTE	107, IO.HMS!IQ.UMD&377
	.BYTE	105, IO.BLS!IQ.UMD&377
	.BYTE	115, IO.OFF!IQ.UMD&377
	.BYTE	173, IO.RDH!IQ.UMD&377
	.BYTE	163, IO.WDH!IQ.UMD&377
	.BYTE	151, IO.WCK!IQ.UMD&377
FUNTBE:

	.ENDC


;
; DRIVER DISPATCH TABLE
;

$DBTBL::.WORD	DBINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DBCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DBOUT		;DEVICE TIMEOUT ENTRY POINT
      	.WORD	DBPWF		;POWERFAIL ENTRY POINT

;+
; **-DBINI-RH11-RP04/05/06 DISK PACK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED      . A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
10$:	RETURN			;RETURN TO CALLER			; PJC038
DBINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS		;**-1
	BCS	10$		;IF CS, CONTROLLER BUSY OR NO REQUEST	; PJC038
									;**-1
;
; THE FOLL      OWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RH11-RP04/05/06 DISK PACK I/O REQUEST PACKET FORMAT
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR       TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE       TRANSFERED.
;	WD. 15 -- DIAGNOSTIC SUPPLIMENTAL PARAMETER ELSE NOT USED.
;	WD. 16 -- HIGH PART OF LOGICAL BLOCK NUMBER AND HIGH BYTE NOT US
;	WD. 17 -- LOW PART OF LOGICAL BLOCK NUMBER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLK ADRS.
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000).
;

	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB


	.IF DF	M$$EXT

	BIT	#DV.MBC,U.CW1(R5)  ;IS IT A MASS BUS DEVICE?
	BNE	20$		;IF NE YES -- DOES NOT USE UMR'S	; PJC038
	CALL	$      STMAP		;SET UP UNIBUS MAPPING ADDRESS		;**-1

	.ENDC


	ASL	U.BUF(R5)	;SHIFT ADDRESS EXTENSION BITS INTO PLACE
	ASL	U.BUF(R5)	;
	ASL	U.BUF(R5)	;
	ASL	U.BUF(R5)	;
20$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	D$$IAG

	CMPB	#IO.HMS/^D<256>,I.FCN+1(R1)  ;DIAGNOSTIC FUNCTION?
	BNE	40$		;IF NE NO				; PJC038
	MOV	#FUNTBL,R0	;GET ADDRESS OF FUNCTION TABLE		;**-1
30$:	MOVB	(R0)+,U.BUF(R5)	;LOAD CONTROLLER FUNCTION CODE		; PJC038
	CMPB	(R0)+,I.FCN(R1)	;IS IT THE CORRECT CODE?		;**-1
	BEQ      	60$		;IF EQ YES				; PJC038
	CMP	#FUNTBE,R0	;END OF FUNCTION TABLE?			;**-1
	BNE	30$		;IF NE NO				; PJC038
									;**-1
	.ENDC


40$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION		; PJC038
	MOVB	#171,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION		;**-1
	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION?
	BHIS	50$		;IF HIS, FUNCTION IS LEGAL		; PJC038
	JMP	300$		;FUNCTION IS ILLEGAL			; PJC038
50$:	BEQ	60$		;IF EQ, FUNCTION IS READ		; PJC038
	SUB	#10,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION	      ;**-3
60$:	MOV	#RETRY,RTTBL(R3) ;SET RETRY COUNT			; PJC038
									;**-1

	.IF DF	R$$JPO

	CLRB	U.CW2+1(R5)	;INITIALIZE RECOVERY VALUES
	CALL	540$		;SET INITIAL OFFSET RECOVERY VALUES	; PJC038
									;**-1
	.ENDC


	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER
									; PB237
									; PB237
	.IF DF	M$$EIS							; PB237
									; PB237
	MOV	R0,R1		;REPOSITION LBN				; PB237
	MOV	R2,R0		;...					; PB237
	DIV	#22.,R0		;CALCULATE SECTOR NUMBER		; PB237
	MOVB	R1,I.PRM+12(R3)	;SAVE SECTOR       NUMBER			; PB237
	MOV	R0,R1		;SET NEW DIVIDEND			; PB237
	CLR	R0		;CLEAR HIGH BITS			; PB237
	DIV	#19.,R0		;CALCULATE CYLINDER AND TRACK		; PB237
	MOV	R0,I.PRM+10(R3)	;SAVE CYLINDER NUMBER			; PB237
	MOVB	R1,I.PRM+13(R3)	;SAVE TRACK NUMBER			; PB237
									; PB237
	.IFF								; PB237
									; PB237
	MOV	#16.,R1		;SET DIVIDE LOOP COUNT
70$:	ASL	R0		;DOUBLE LEFT SHIFT			; PJC038
	ROL	R2		;					;**-1
	CMP	R2,#19.*22.	;PARTIAL REMAINDER LARGER THAN DIVISOR?
	BLO	80$		;IF LO NO				; PJC038
	SU      B	#19.*22.,R2	;SUBTRACT OUT DIVISOR			;**-1
	INC	R0		;ACCUMULATE QUOTIENT
80$:	DEC	R1		;ANY MORE PARTIAL DIVIDES?		; PJC038
	BGT	70$		;IF GT YES				; PJC038
	MOV	R0,I.PRM+10(R3)	;SAVE DESIRED CYLINDER ADDRESS		;**-2
	MOV	R2,R0		;SET DIVIDEND TO TRACK/SECTOR REMAINDER
	MOV	#22.,R1		;SET DIVISOR TO NUMBER OF SECTORS/TRACK
	CALL	$DIV		;CALCULATE TRACK AND SECTOR
	SWAB	R0		;SWAP TRACK TO HIGH BYTE
	BIS	R1,R0		;MERGE TRACK
	MOV	R0,I.PRM+12(R3)	;SAVE DESIRED TRACK AND SECTOR ADDRESS
									; PB237
	      .ENDC								; PB237
									;**-7

;
; INITIATE I/O OPERATION
;

90$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	M$$EXT

	BIT	#DV.MBC,U.CW1(R5)  ;IS IT A MASS BUS DEVIS?
	BNE	100$		;IF NE YES -- DOES NOT USE UMR'S	; PJC038
	CALL	$MPUBM		;MAP UNIBUS TO MEMORY			;**-1
100$:				;REF LABEL				; PJC038
									;**-1
	.ENDC


	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	ADD	#10,R2		;POI      NT TO SECOND CSR
	MOV	#40,(R2)	;CLEAR RH11 CONTROLLER AND ALL DRIVES
	MOVB	U.UNIT(R5),(R2)	;SELECT PROPER DRIVE
	MOV	I.PRM+12(R1),-(R2)  ;INSERT TRACK/SECTOR ADDRESS
	MOV	U.BUF+2(R5),-(R2)  ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	;INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		;CONVERT TO WORD COUNT
	NEG	(R2)		;MAKE NEGATIVE WORD COUNT
	MOV	#23,-(R2)	;EXECUTE PACK ACK FUNCTION TO SET VV


	.IF NDF	R$$JPO!D$$IAG

	MOV	#FMT22,RPOF(R2)	;SET 16 BIT FORMAT

	.IFF

	MOV	#FMT22,-(SP)	;GET FORMA      T BIT


	.IF DF	D$$IAG

	CMP	#IO.OFF!IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OFFSET FUNCTION?
	BNE	110$		;IF NE NO				; PJC038
	BIS	I.PRM+6(R1),(SP)  ;YES, SET OFFSET VALUE		;**-1
110$:				;REF LABEL				; PJC038
									;**-1
	.ENDC


	.IF DF	R$$JPO

	BITB	#IHC,U.CW2+1(R5)  ;INHIBIT HEADER COMPARE
	BEQ	120$		;IF EQ NO				; PJC038
	BIS	#HCI,(SP)	;SET HEADER COMPARE INHIBIT		;**-1

	.ENDC


120$:	MOV	(SP)+,RPOF(R2)	;SET OFFSET REGISTER			; PJC038
									;**-1
	.ENDC


	MOV	#IE.DNR&377,R0	;      ASSUME DRIVE NOT READY
	MOV	I.PRM+10(R1),RPDC(R2)  ;SET DESIRED CYLINDER ADDRESS
	MOV	RPDS(R2),R3	;GET CURRENT DRIVE STATUS
	COM	R3		;COMPLEMENT STATUS
	BIT	#MOL!DRY!VV,R3	;DRIVE READY AND ON-LINE?
	BNE	130$		;IF NE NO				; PJC038
	BIT	#UNS,RPER1(R2)	;DRIVE UNSAFE?				;**-1
	BEQ	150$		;IF EQ NO				; PJC038
130$:				;REF LABEL				; PJC038
									;**-2

	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	170$		;IF NE YES				; PJC038
									;**-1
	.IFTF


	.IF DF	D$$IAG      

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPERATION?
	BEQ	140$		;IF EQ NO				; PJC038
	JMP	230$		;PROCESS DIAGNOSTIC NOT READY		; PJC038
140$:				;REF LABEL				; PJC038
									;**-3
	.ENDC


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DRIVE NOT READY ERROR

	.ENDC


	JMP	300$		;FINISH UP				; PJC038
150$:				;REF LABEL				; PJC038
									;**-2
	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC


	.IF DF E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE IN BIT MAP

	.ENDC


	.IF DF       M$$EXT

	BIT	#DV.MBC,U.CW1(R5)  ;;;IS IT A MASS BUS DEVICE?
	BEQ	160$		;;;IF EQ NO -- DOES NOT USE UMR'S	; PJC038
	MOVB	U.BUF+1(R5),RPBAE(R2)  ;;;SET ADDRESS EXTENSION BITS	;**-1
	MOVB	U.BUF(R5),(R2)	;;;START FUNCTION
	RETURN			;;;

	.ENDC


160$:	MOV	U.BUF(R5),(R2)	;;;START FUNCTION			; PJC038
									;**-1

;
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;

DBCAN:	RETURN			;;;NOP FOR RP04/05/06

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES N      O IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DBPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS THIS UNIT CURRENTLY BUSY?
	BEQ	180$		;IF EQ NO				; PJC038
170$:	MOVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC038
180$:	BISB	#US.SPU,U.ST      S(R5) ;SET UNIT SPINNING UP			; PJC038
									;**-4
	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND

;+
; **-$DBINT-RH11-RP04/05/06 DISK PACK CONTROLLER
;	INTERRUPT HANDLER
;-

	INTSE$	DB,PR5,R$$JP1	;;;SAVE REGISTERS AND SET PRIORITY
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER


	.IF DF	D$$IAG      

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC FUNCTION EXECUTED?
	BNE	230$		;IF NE YES				; PJC038
									;**-1
	.ENDC


	.IF DF	R$$JPO

	BIT	#40,(R2)	;OFFSET OR RTC FUNCTION?
	BEQ	200$		;IF EQ YES				; PJC038
									;**-1
	.ENDC


	BIT	#TRE!MCPE,(R2)	;ANY ERRORS?
	BEQ	260$		;IF EQ NO				; PJC038
									;**-1

	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DEVICE ERROR

	.ENDC


190$:	BIT	#PIP,RPDS(R2)	;POSITIONING IN PROGRESS?		; PJC038
	BNE	190$		;IF NE YES, WAIT TIL DONE		; PJC038
	MOV	#IE      .WLK&377,R0	;ASSUME WRITE LOCK ERROR
	BIT	#WLE,RPER1(R2)	;WRITE LOCK ERROR?
	BNE	290$		;IF NE YES				; PJC038
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		;**-1
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?
	BNE	280$		;IF NE YES				; PJC038
	MOV	RPER1(R2),R1	;GET CONTENTS OF ERROR REGISTER		;**-1
	BIT	#UNS!IAE!AOE!RMR!ILR!ILF,R1  ;HARD ERROR?
	BNE	290$		;IF NE YES				; PJC038
	BIT	#NED!NEM,RPCS2(R2) ;HARD ERROR?				;**-1
	BNE	290$		;IF NE YES				; PJC038
	      BIT	#DLT!WCE!UPE!PGE!MXF!MDPE,RPCS2(R2)  ;CONTROLLER ERROR?	;**-1
	BNE	240$		;IF NE YES, RETRY OPERATION		; PJC038
	BIT	#HCE,R1		;HEADER COMPARE ERROR?			; RP041
	BEQ	320$		;IF EQ NO				; PJC038
									;**-2

	.IF DF	R$$JPO

	DEC	RTTBL(R3)	;ANY RETRIES LEFT?			; PJC026
	BLE	290$		;IF LE NO				; PJC038
	JMP	560$		;GO ISSUE RECALIBRATE TO RECOVER	; PJC038
200$:	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		; PJC038
	CMP	#OFFTB+14,OFFAD(R3)  ;FINAL OFFSET TRIED?		;**-1
	BEQ	290$		;IF EQ YES, A      LL DONE			; PJC038
	BIT	#ERR,RPDS(R2)	;ANY ERRORS?				;**-1
	BNE	250$		;IF NE YES				; PJC038
									;**-1
	.ENDC


210$:	JMP	90$		;RETRY ORIGINAL FUNCTION		; PJC038
									;**-1

;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED
; UNLESS THE OPERATION WAS DIAGNOSTIC.  TIMEOUTS ARE USUALLY CAUSED
; BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE.
;

DBOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?      
	BEQ	220$		;;;IF EQ NO				; PJC038
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#16.,S.STS(R4)	;;;HAVE WE WAITED 1 MINUTE YET?		; PJC029
	BEQ	220$		;;;IF EQ YES				; PJC038
	MTPS	#0		;;;ALLOW INTERRUPTS			;**-3
	BR	210$		;RETRY OPERATION			; PJC038
220$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC038
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP		;**-2

	.ENDC


	CALL	$DTOER		;;;LOG DEVICE TIMEOUT


	.IF DF	D$$IAG

	BCC	240$		;IF CC, TIMEOUT DURING NORMAL FUNCTION	; PJC03      8
230$:	CALL	$CRPAS		;PASS CONTROLLER REGISTER TO TASK	; PJC038
	BR	290$		;DIAGNOSTIC PROCESSING COMPLETE		; PJC038
									;**-3
	.ENDC


240$:	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET		; PJC038
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?			;**-1
	BNE	280$		;IF NE YES				; PJC038
									;**-1

	.IF DF	R$$JPO

	BITB	#OFA,U.CW2+1(R5)  ;TEST OFFSET ACTIVE?
	BEQ	250$		;IF EQ NO				; PJC038
	JMP	510$		;CONTINUE OFFSET RECOVERY		; PJC038
250$:	DECB	RTTBL(R3)	;RETRY FUNCTION?			; PJC038
	BGT	3      10$		;IF GT YES				; PJC038
									;**-4
	.IFF

	DECB	RTTBL(R3)	;RETRY FUNCTION?
	BGT	210$		;IF GT YES				; PJC038
									;**-1
	.ENDC


	.IF DF	D$$WCK

	BR	280$		;FINISH UP				; PJC038
									;**-1
	.IFTF

260$:				;REF LABEL				; PJC038
									;**-1
	.IFT

	BITB	#IO.WLC&377,I.FCN(R1)  ;WRITE FOLLOWED BY WRITE CHECK?
	BNE	270$		;IF NE YES				; PJC038
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED BY MCR?		;**-1
	BEQ	290$		;IF EQ NO				; PJC038
270$:	CMPB	#171,U.BUF(R5)	;WAS L      AST FUNCTION A READ?		; PJC038
	BEQ	290$		;IF EQ YES				; PJC038
	CMPB	#161,U.BUF(R5)	;WAS LAST FUNCTION A WRITE?		;**-3
	BNE	290$		;IF NE NO				; PJC038
	MOVB	#151,U.BUF(R5)	;SET WRITE CHECK FUNCTION		;**-1
	MOV	#RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT
	BR	210$		;START WRITE CHECK OPERATION		; PJC038
									;**-1
	.IFTF

280$:				;REF LABEL				; PJC038
									;**-1
	.IFT

	BIT	#WCE,RPCS2(R2)	;WRITE CHECK ERROR?
	BEQ	290$		;IF EQ NO				; PJC038
	MOV	#IE.WCK&377,R0	;SET WRITE CHECK ERROR      			;**-1

	.ENDC


290$:	MOV	S.PKT(R4),R3	;GET I/O PACKET ADDRESS			; PJC038
	MOV	RPWC(R2),R1	;GET WORDS REMAINING TO TRANSFER	;**-1
	ASL	R1		;CONVERT TO BYTES LEFT TO TRANSFER
	ADD	I.PRM+4(R3),R1	;CALCULATE BYTES ACTUALLY TRANSFERED
	MOV	#40011,(R2)	;CLEAR CONTROLLER AND DRIVE
300$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE STARTING RETRY COUNT

	.ENDC      
									;**-7

	CALL	$IODON		;FINISH I/O OPERATION
	JMP	DBINI		;PROCESS NEXT REQUEST


	.IF DF	R$$JPO

310$:	CMPB	#171,U.BUF(R5)	;IS THIS A READ OPERATION?		; PJC038
	BNE	210$		;IF NE NO				; PJC038
	BISB	#OFA,U.CW2+1(R5)  ;SET OFFSET ACTIVE			;**-2
	JMP	480$		;RESET OFFSET TO ZERO			; PJC038
									;**-24
	.ENDC

;
; START ECC CORRECTION PROCEDURE
;
;									;**-1

320$:	CMPB	#171,U.BUF(R5)	;IS THIS A READ OPERATION?		; PJC038
	BNE	240$		;IF NE NO				; PJC038
	BIS	RPER2(R2),R1	;.      OR.ERROR REGISTER 2			; RP015
	BISB	RPCS2+1(R2),R1	;.OR.HIGH BYTE OF STATUS REGISTER 2	; RP015
	CMP	#DCK,R1		;IS IT ONLY A DATA CHECK ERROR ?	; RP015
	BNE	240$		;IF NE NO, SOME OTHER ERROR		; PJC038
	MOV	RPWC(R2),R0	;GET NEGATIVE # OF WORDS REMAINING	; RP041
	ASL	R0		;CONVERT TO BYTES			; RP041
	ADD	U.CNT(R5),R0	;CALCULATE BYTES ACTUALLY TRANSFERED	; RP041
									; RP041
									; RP041
	.IF DF	R$$JPO							; RP041
									; RP041
	BEQ	440$		;IF EQ NONE TRANSFERED, TRY OFFSET RECOV; PJC038
	      								; RP041
	.IFF								; RP041
									; RP041
	BNE	330$		;IF NE SOME TRANSFERED			; PJC038
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		; RP041
	BR	240$		;AND GO ON				; PJC038
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
330$:	MOV	RPEC1,R1	;GET ECC ERROR POSITION			; PJC038
	MOV	RPEC2,R3	;GET ECC CORRECTION PATTERN		; RP041
	MOV	RPWC(R2),R2	;GET REMAINING WORD COUNT		; RP041
									;**-7

	.IF DF	S$$ECC

	CALL	$ECCOR		;CALL SHARED ECC ROUTINE		;**-      2
									;**-8
	.IFF

	MOV	R0,-(SP)	;SAVE BYTE COUNT			; RP041
	CLR	R0		;CLEAR HIGH ORDER ERROR POSITION	; RP041
	DEC	R1		;CONVERT TO RELATIVE BIT NUMBER		; RP041
									; RP041
									; RP041
	.IF DF	 M$$EIS							; RP041
									; RP041
	DIV	#20,R0		;DIVIDE FOR:				; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
									; RP041
	.IFF								; RP041
									; RP041
	MOV	R1,R0		;COPY ECC ERROR POSITION		; RP041
	MOV	#20,R1		;SET DIVISOR TO CAL      CULATE:		; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
	CALL	$DIV		;PERFORM DIVISION			; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	MOV	R0,-(SP)	;SAVE WORD POSITION			; RP041
	MOV	R2,-(SP)	;SAVE REMAINING WORD COUNT		; RP041
	CLR	R2		;CLEAR HIGH ORDER ERROR PATTERN		; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
340$:	ASHC	R1,R2		;SHIFT PATTERN INTO CORRECT POSITION	; PJC038
      									; RP041
	.IFF								; RP041
									; RP041
340$:	DEC	R1		;ANY MORE SHIFTS LEFT TO PERFORM	; PJC038
	BLT	350$		;IF LT NO				; PJC038
	ASL	R3		;DOUBLE LEFT SHIFT			; RP041
	ROL	R2		;					; RP041
	BR	340$		;					; PJC038
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
350$:	MOV	4(SP),R0	;RETRIEVE BYTES ACTUALLY TRANSFERED	; PJC038
	SUB	#510.,R0	;BACKUP TO BLOCK IN ERROR ...		; RP041
				;... OFFSET TO HIGH WORD IN ERROR	; RP041
									; RP041
									; RP      041
	.IF DF	D$$IAG							; RP041
									; RP041
	CALL	$RELOP		;COMPUTE LOCATION IN PHYSICAL MEMORY	; RP041
									; RP041
	.IFF								; RP041
									; RP041
	MOV	R0,-(SP)	;SAVE BYTE OFFSET ON STACK		; RP041
	MOV	U.BUF+2(R5),R1	;GET LOW 16 BITS OF ADDRESS		; RP041
									; RP041
									; RP041
	.IF DF	M$$MGE							; RP041
									; RP041
	MOVB	U.BUF+1(R5),R0	;GET HIGH BITS OF REAL ADDRESS		; RP041
									; RP041
									; RP041
	.IF DF	M$$EXT							; RP041
									; RP041
	B      IT	#DV.MBC,U.CW1(R5)  ;CAN THIS CONTROLLER/UNIT DIRECTLY ..; RP041
				;... ADDRESS ALL OF PHYSICAL MEMORY	; RP041
	BNE	360$		;IF NE YES				; PJC038
	ADD	#<S.MPR+M.LGTH>,R4  ;POINT PAST PHYSICAL BUFFER ADDRESS	; RP041
				;CONTAINED IN THE UMR AREA		; RP041
	MOV	-(R4),R1	;GET LOW 16 BITS OF PHYSICAL BUFFER ADDR; RP041
	TSTB	-(R4)		;SKIP THE NEXT BYTE			; RP041
	MOVB	-(R4),R0	;GET HIGH 6 BITS OF PHYSICAL BUFFER ADDR; RP041
360$:	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			; PJC038
									; RP041
	.EN      DC								; RP041
									; RP041
									; RP041
	.IFF								; RP041
									; RP041
	CLR	R0		;					; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	ADD	(SP)+,R1	;CALCULATE NEW STARTING ADDRESS ...	; RP041
	ADC	R0		;...					; RP041
									; RP041
									; RP041
	.IF DF	M$$MGE							; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
	ASHC	#10.,R0		;CALCULATE DISPLACEMENT AND BIAS	; RP041
	ASHC	#-10.,R1	;...				      	; RP041
									; RP041
	.IFF								; RP041
									; RP041
	MOV	#10.,-(SP)	;SET COUNT FOR 10 SHIFTS		; RP041
370$:	DEC	(SP)		;ANY MORE SHIFTS TO PERFORM		; PJC038
	BLT	380$		;IF LT NO				; PJC038
	ASL	R1		;DOUBLE LEFT SHIFT R1 ...		; RP075
	ROL	R0		;... INTO R0				; RP075
	BR	370$		;					; PJC038
380$:	SWAB	R1		;SWAP BYTES				; PJC038
	ASR	R1		;SHIFT RIGHT R1				; RP075
	ASR	R1		;...					; RP075
	TST	(SP)+		;CLR THE STACK				; RP075
									; RP041
	.ENDC								; RP041
									; RP04      1
									; RP041
	MOV	R0,KISAR6	;SET RELOCATION BIAS			; RP041
	ADD	#140000,R1	;SET DISPLACEMENT			; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	MOV	(SP)+,R0	;RETRIEVE REMAINING WORD COUNT		; RP041
	BPL	390$		;IF PL, THIS MAY HAVE BEEN A PARTIAL BLO; PJC038
				;TRANSFER				; PJC038
	CLR	R0		;ASSUME A WHOLE BLOCK WAS TRANSFERRED	; RP041
390$:	ADD	(SP),R1		;ADD IN ERROR WORD POSITION OFFSET ...	; PJC0      38
	ADD	(SP),R1		;... FOR BYTE ADDRESSING		; RP041
	ADD	(SP)+,R0	;ADD CORRECTION OFFSET TO CORRECTION LIM; RP041
	CMP	R0,#377		;IS THE CORRECTION ENTIRELY IN THIS BLOC; RP041
	BHI	410$		;IF HI NOT AT ALL			; PJC038
	BEQ	400$		;IF EQ THEN ONLY ONE WORD		; PJC038
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
	XOR	R2,(R1)		;CORRECT HIGH ORDER WORD		; RP041
400$:	XOR	R3,-(R1)	;CORRECT LOW ORDER WORD			; PJC038
									; RP041
	.IFF								; RP041
									; RP041      
	MOV	(R1),R0		;COPY HIGH ORDER DATA WORD		; RP041
	BIC	R2,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R2		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R2,(R1)		;PATTERN.OR.DATA WORD			; RP041
400$:	MOV	-(R1),R0	;COPY LOW ORDER DATA WORD		; PJC038
	BIC	R3,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R3		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R3,(R1)		;PATTERN.OR.DATA WORD			; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
410$:	MOV	(SP)+,R1	;RESTORE       BYTES TRANSFERRED		; PJC038
	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX		; RP041
	MOV	S.CSR(R4),R2	;RESTORE CSR ADDRESS			; RP041
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER		;**-70
									;**-8

	.ENDC

									; RP041
	MOVB	#11,(R2)	;CLEAR DRIVE ERRORS			; RP041
									; RP041

	.IF DF	R$$JPO

	CALL	540$		;RESET RECOVERY PARAMETERS		; PJC038
	SUB	R1,U.CNT(R5)	;ANY MORE WORDS TO TRANSFER?		;**-2

	.IFF

	TST	RPWC(R2)	;ANY MORE WORDS TO TRANSFER?

	.IFTF

	BEQ	290$		;IF EQ N      O				; PJC038
									;**-1
	.IFT


	.IF DF	M$$MGE


	.IF DF	M$$EXT

	BIT	#DV.MBC,U.CW1(R5)  ;IS IT A MASS BUS DEVICE?
	BEQ	420$		;IF EQ NO -- DOES USE UMR'S		; PJC038
	MOVB	RPBAE(R2),U.BUF+1(R5)  ;SAVE MEMORY EXTENSION BITS	;**-1
	BR	430$		;					; PJC038
									;**-1
	.ENDC


420$:	MOVB	RPCS1+1(R2),U.BUF+1(R5)  ;SAVE MEMORY EXTENSION BITS	; PJC038
	BICB	#^C<3>,U.BUF+1(R5)  ;CLEAR EXCESS BITS			;**-1
430$:				;REF LABEL				; PJC038
									;**-1

	.ENDC


	MOV	RPBA(R2),U.BUF+2(      R5) ;SAVE BUFFER ADDRESS
	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET
	MOV	RPDC(R2),I.PRM+10(R1) ;SAVE CYLINDER ADDRESS
	MOV	RPDA(R2),I.PRM+12(R1) ;SAVE TRACK/SECTOR ADDRESS

	.ENDC


	MOVB	U.BUF(R5),(R2)	;RESTART PREVIOUS OPERATION
	RETURN			;

									;**-70
;
; OFFSET RECOVERY
;


	.IF DF	R$$JPO

440$:	TST	R0		;ANY GOOD SECTORS TRANSFERRED?		; PJC038
	BEQ	500$		;IF EQ NO				; PJC038
									;**-3
;
; THE TRANSFER ENDED IN AN ECC HARD ERROR BUT THERE WERE SECTORS
; TRANSFERED THA      T CONTAINED GOOD DATA. SINCE THE ECC HARD ERROR COULD
; HAVE BEEN CAUSED BY A CYLINDER CROSSING, THE GOOD DATA IS SAVED
; AND THE TRANSFER IS RETRIED FROM THE POINT OF ERROR.
;

	SUB	R0,U.CNT(R5)	;REDUCE BYTES REMAINING TO TRANSFER	; RP021
	BNE	450$		;IF NE MORE SECTORS TO TRANSFER		; PJC038
	ADD	R0,U.CNT(R5)	;LAST SECTOR, CORRECT BYTES REMAINING	; RP021
	BR	480$		;AND CONTINUE				; PJC038
450$:	ADD	R0,U.BUF+2(R5)	;UPDATE STARTING BUFFER ADDRESS		; PJC038
	ADCB	U.BUF+1(R5)	;PROPAGATE CARRY INTO EX      TENSION BITS	; RP021
	SWAB	R0		;CALCULATE NUMBER OF SECTORS TRANSFERED	;**-3
	ASR	R0		;
	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET
	ADD	I.PRM+12(R1),R0	;UPDATE TRACK/SECTOR ADDRESS
460$:	CMPB	#22.,R0		;SECTOR OVERFLOW?			; PJC038
	BHI	470$		;IF HI NO				; PJC038
	SUB	#22.,R0		;SUBTRACT OUT A SECTOR			;**-2
	ADD	#1*256.,R0	;ADD IN A TRACK
	CMP	#19.*256.,R0	;TRACK OVERFLOW?
	BHI	460$		;IF HI NO				; PJC038
	SUB	#19.*256.,R0	;NORMALIZE TRACK ADDRESS		;**-1
	INC	I.PRM+10(R1)	;UPDATE CYLINDER ADDRE      SS
	BR	460$		;					; PJC038
470$:	MOV	R0,I.PRM+12(R1)	;SET UPDATED TRACK/SECTOR ADDRESS	; PJC038
480$:	CALL	550$		;RESET OFFSET TABLE ADDRESS		; PJC038
490$:	MOV	#117,R1		;SET RTC FUNCTION			; PJC038
	MOVB	#16.,RTTBL+1(R3) ;TRY 16. TIMES AT CENTERLINE		;**-4
	MOV	#FMT22,R0	;RESET OFFSET VALUE TO ZERO
	BR	520$		;					; PJC038
									;**-1
;
; NO GOOD DATA WAS TRANSFERED - CHECK IF OFFSET SHOULD BE CHANGED
;

500$:	BIT	#DCK!DTE!ECH,R1	;DATA CHECK OR DRIVE TIMING ERROR?	; PJC038
	BNE	510$		;IF       NE YES				; PJC038
	BISB	#IHC,U.CW2+1(R5)  ;SET HEADER COMPARE INHIBIT FLAG	;**-2
510$:	DECB	RTTBL+1(R3)	;CHANGE OFFSET?				; PJC038
	BGT	530$		;IF GT NO				; PJC038
	ADD	#2,OFFAD(R3)	;UPDATE OFFSET POINTER			;**-2
	MOV	@OFFAD(R3),R0	;GET NEXT OFFSET VALUE
	BEQ	490$		;IF EQ, RETURN TO CENTERLINE		; PJC038
	MOV	#115,R1		;SET OFFSET FUNCTION			;**-1
	MOVB	#2,RTTBL+1(R3)	;SET RECOVERY RETRY COUNT
	BIT	#2,RPDT(R2)	;IS THIS DRIVE AN RP04?
	BEQ	520$		;IF EQ YES				; PJC038
	ASRB	R0		;NO, IT'S AN RP06 S      O ADJUST OFFSET ...	;**-1
	BIC	#100,R0		;... VALUE AND SIGN ACCORDINGLY
520$:	MOV	#TRE!11,(R2)	;CLEAR CONTROLLER AND DRIVE		; PJC038
	MOV	R0,RPOF(R2)	;LOAD NEXT OFFSET VALUE			;**-1
	BICB	#IHC,U.CW2+1(R5)  ;CLEAR HEADER COMPARE INHIBIT FLAG
	MOVB	S.ITM(R4),S.CTM(R4) ;RESET TIMEOUT COUNT
	MOVB	R1,(R2)		;INITIATE OFFSET FUNCTION
	RETURN			;
530$:	JMP	90$		;RETRY FUNCTION				; PJC038
									;**-1
;
; SET OFFSET RECOVERY PARAMETERS
;

540$:	MOVB	#1,RTTBL+1(R3)	;SET RECOVERY COUNT TO ONE		; PJC03   j  8
550$:	MOV	#OFFTB-2,OFFAD(R3) ;SET OFFSET TABLE POINTER		; PJC038
	RETURN			;					;**-2

;
; SET RECOVERY RECALIBRATION FOR 'HCE' ERROR
;

560$:	MOV	#TRE!11,(R2)	;CLEAR CONTROLLER AND DRIVE		; PJC038
	MOVB	S.ITM(R4),S.CTM(R4)  ;RESET TIMEOUT COUNT		;**-1
	MOV	#107,(R2)	;LOAD THE RECALIBRATE COMMAND
	RETURN			;

	.ENDC


	.DSABL	LSB

	.END
 j         ¤ðskQ	› c,        	.TITLE	DDDRV
	.IDENT	/01.06/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 01.06
;
; M. B. GROSSMAN 9/15/78
;
; MODIFIED BY:
;
;	P. J. CARR	5-AUG-80
;
;		PJC013 -- CORRECT MULTI-CONTROLLER OPERATION
;
;	DAN BROWN	20-JAN-81
;
;		DTB012 -- REMOVE REFERENCES TO S.BMSK FOR NEW
;			ERROR LOG.
;
;	P. J. CARR	2-APR-81
;      
;		PJC024 -- CLEAN UP INEFFICIENT CODE
;
;	P. J. CARR	2-APR-81
;
;		PJC025 -- CORRECT TYPOGRAPHICAL ERRORS
;
;	P. J. CARR	1-SEP-81
;
;		PJC031 -- CORRECT I/O PROCESSING DURING RETRIES
;
;	P. J. CARR	28-DEC-81
;
;		PJC039 -- MODIFY ERROR LOGGING ROUTINE FOR
;			  NEW ERROR LOGGER
;
; TU58 TAPE CARTRIDGE DRIVER
;
; THIS DRIVER INTERFACES WITH THE TU58 VIA A DL11 AT 9600 BAUD.		; PJC025
; COMMANDS, DATA AND DEVICE STATUS ARE FORMATTED INTO STRUCTURED	; PJC025
; PACKETS OF BYTES IN ACCORDAN      CE WITH RADIAL SERIAL PROTOCOL.		; PJC025
;									;**-4
; MACRO LIBRARY CALLS
;
	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
;
; EQUATED SYMBOLS
;
RTRY=	2			;RETRY COUNT				; PJC031
DDNUM=	6			;NUMBER OF REGISTERS TO LOG ON ERROR	; PJC039
;									;**-1
; TU58 RADIAL SERIAL PROTOCOL SYMBOLS					; PJC025
;									;**-1
; INSTRUCITON SET							; PJC025
;									; PJC025
READ=	2			;READ INSTRUCTION			;**-1
WRITE=	3			;WRITE INSTRUCTION
      POSIT=	5			;POSITION INSTRUCTION -USER MODE DIAG.
DIAG=	7			;DIAGONOSE INSTRUCTION -USER MODE DIAG.
;									; PJC025
; FLAGS									; PJC025
;									; PJC025
DATA=	1			;DATA FLAG				;**-1
CNTL=	2			;CONTROL FLAG
INIT=	4			;INITIALIZE FLAG
CONT=	20			;CONTINUE FLAG
;
; THE TU58 NORMALLY INTERFACES VIA A DL11. AN EXCEPTION TO THIS IS	; PJC025
; THE PDT 130. IN THE CASE OF THE PDT (R$$PDT DEFINED) THE NUMBER AND	;**-2
; LOCATION OF THE DEVICE REGISTERS ARE DIFFERENT FROM THOSE OF THE
; DL11.	      								; PJC025
;									; PJC025
;*** NOTE: AT THIS TIME THE PDT 130 TU58 CODE IS INTESTED!		; PJC025
;									; PJC025
									; PJC025
									;**-2
	.IF DF	R$$PDT

DDRCS=  0			;RECEIVE CONTROL STATUS REGISTER
DDRBF=  2			;BUFFER REGISTER FOR BOTH RECEIVE
DDXBF=  2			;	AND TRANSMIT
DDXCS=  4			;TRANSMITTER CONTROL STATUS REGISTER

	.IFF

;									; PJC025
; DL11 INTERFACE REGISTER OFFSETS					; PJC025
;									; PJC025
DDRCS=	0			;RECEIVE CONTROL STATUS REGISTER	;**-2
DDRBF=	2		      	;RECEIVE BUFFER REGISTER
DDXCS=	4			;TRANSMITTER CONTROL STATUS REGISTER
DDXBF=	6			;TRANSMITTER BUFFER REGISTER
									;**-1
	.ENDC
									; PJC025

;
; DL11 BIT ASSIGNMENTS							; PJC025
;									;**-1
RDONE=	200			;RECEIVER DONE
RIE=	100			;RECEIVER INTERRUPT ENABLE
ERR=	100000			;RECEIVER DATA ERROR
TRDY=	200			;TRANSMITTER READY
TIE=	100			;TRANSMITTER INTERRUPT ENABLE
BRK=	1			;TRANSMIT BREAK
;
; LOCAL DATA
;									; PJC025
CNTBL:	.BLKW	T$$U58		;ADDRESS OF UCB
									; P      JC025

	.IF GT	T$$U58-1

TEMP:	.BLKW	1		;TEMP STORAGE FOR CONTROLLER NUMBER

	.ENDC
									; PJC025

	.IF DF	E$$DVC							; PJC039
									; PJC039
WORD1:	.BLKW	T$$U58		;STORAGE FOR LAST THREE WORDS THAT ARE	; PJC039
WORD2:	.BLKW	T$$U58		;TO GO IN ERROR PACKET			; PJC039
WORD3:	.BLKW	T$$U58		;					; PJC039
									; PJC039
	.ENDC								; PJC039
									; PJC039
									; PJC039
;
;DRIVER DISPATCH TABLE
;
$DDTBL::.WORD	DDINI							; PJC025
	.WORD	DDCAN							;**-1
	.WORD	DDOUT
      	.WORD	DDPWF
;									; PJC025
; PROGRAM SEQUENCE CONTROL						; PJC025
;									; PJC025
; PROGRAM FLOW IS CONTROLLED BY A POINTER TO A TABLE OF			; PJC025
; ADDRESSES. THIS SEQUENCE CREATES AND DECODES THE RADIAL		; PJC025
; SERIAL PACKET INFORMATION. THE ACTUAL USER DATA IS			; PJC025
; TRANSFERRED WITHIN THE INTERRUPT SERVICE ROUTINE (ISR).		; PJC025
; THIS METHOD PERMITS US TO WAIT FOR INTERRUPTS WITHOUT			; PJC025
; HAVING TO PRESERVE ANY PROCESSOR REGISTERS (INCLUDING THE		; PJC025
; STAC      K). REPETITIVE SECTIONS OF CODE CAN BE EXECUTED A			; PJC025
; NUMBER OF TIMES WITHOUT LOOP COUNTERS. THIS METHOD ALSO		; PJC025
; DECREASES PROGRAM SIZE BY ALLOWING US TO USE BRANCHES			; PJC025
; RATHER THAN JSR'S.							; PJC025
;									; PJC025
; THE POINTER (LOCATION RADD) IS INCREMENTED VIA THE CODE		; PJC025
; IN RTBK (RETURN BACK). RTBK THEN SHIFTS CONTROL TO THE		;**-14
; ADDRESS POINTED TO BY RADD. RTBK IS CALLED BY RMSG/SMSG OR
; THE INTERRUPT SERVICE ROUTINE WHENEVER THE DL11 IS READY	      	; PJC025
; TO PERFORM THE NEXT NON-DATA TRANSFER OPERATION.			;**-1
;									; PJC025
;									; PJC025
; CTAB- COMMAND PACKET SEQUENCE						; PJC025
;									; PJC025
; CONE IS THE ADDRESS RETURNED TO WHEN THE DL11 IS READY TO		; PJC025
; SEND THE FIRST BYTE OF THE 14. BYTE COMMAND PACKET. CTWO		; PJC025
; IS THE ADDRESS RETURNED TO WHEN READY FOR THE SECOND BYTE,		; PJC025
; ETC. CFIF IS EXECUTED AFTER ALL BYTES IN THE COMMAND PACKET		; PJC025
; ARE SENT.								; PJC025
;									;**-8
CT      AB:	.WORD	CONE,CTWO,CTHR,CFOUA,CFOUB,CFIV,CSIX,CSEV
	.WORD	CEIG,CNIN,CTEN,CELE,CTWE,CTHI,CFOR,CFIF
;
; ITAB- INITIALIZATION SEQUENCE
;
ITAB:	.WORD	IONE,ITWOA,ITWOB,ITWOC,ITWOD,ITWOE,ITHR,IFOU,IFIV,ISIX ;INIT. SEQ.
;
; TTAB- TRANSMIT DATA SEQUENCE
;
TTAB:	.WORD	TONE,TTWO,TTHR,TFOU,TFIV,TSIX 	;OUTGOING (WRITE) DATA P; PJC025
;									;**-1
; RTAB- RECEIVE DATA SEQUENCE
;
RTAB:	.WORD	RONE,RTWO,RTHR,RFOU ;INCOMING (READ) DATA PACKET ADDRESSES
;
; ETAB- END PACKET DECODE SEQUENCE
;
ETAB:	.WORD	      EONE,ETWO,ETHR,EFOU,EFIV,ESIX,ESEV ;READ END PACKET
	.WORD	EEIG,ENIN,ETEN,EELE,ETWE,ETHI	;FROM TU58		; PJC025
;									;**-1
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
RDAT:	.BLKW	T$$U58		;RECEIVED DATA
RADD:	.BLKW	T$$U58		;RETURN ADDRESS POINTER
DBUF:	.BLKW	T$$U58		;DL11 BUFFER ADDRESS			; PJC025
CKSM1:	.BLKW	T$$U58		;CHECKSUM STORAGE-1ST WORD		;**-1
				;ALSO TEMPORARY DRIVER STORAGE		; PJC025
CKSM2:	.BLKW	T$$U58		;CHECKSUM STORAGE-2ND WORD		;**-1
				;ALSO TEMPORARY DRIV      ER STORAGE		; PJC025
FLAG:	.BLKW	T$$U58		;LOW BYTE-BYTE COUNT			;**-1
				;HIGH BYTE-SEND/REC. FLAG
WCNT:	.BLKW	T$$U58		;BYTES LEFT TO BE WRITTEN
				;ALSO USED FOR RETURN ADDRESS
				;DURING IOPKT SUBROUTINE
				;ALSO USED FOR INITIALIZATION RETRY COUN; PJC025
									;**-1
;+
; **-DDINI- TU58 TAPE CARTRIDGE INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN		; PJC025
; I/O REQUEST IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION	; PJC025
; TO PROPAGATE THE EXECUTI      ON OF THE DRIVER. IF THE SPECIFIED		; PJC025
; CONNTROLLER IS NOT BUSY, THEN AN ATTEPMT IS MADE TO DEQUEUE THE	; PJC025
; NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS EXECUTED. IF		; PJC025
; THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPERATION	; PJC025
; IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.		; PJC025
;									; PJC025
; INPUT:								; PJC025
;									; PJC025
;	R5 = ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED	; PJC025
;									; PJC025
; OUTPUT:							      	; PJC025
;									; PJC025
;	IF THE SPECIFIED CONTROLLER IS NOT BUST AND AN I/O REQUEST	; PJC025
;	IS WAITING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED	; PJC025
;	AND THE DRIVER INITIATES THE REQUESTED I/O FUNCTION		; PJC025
;-									;**-19
	.ENABL	LSB							; PJC025
DDINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS		;**-1
	BCC	10$
	RETURN			;IF CS CONTROLLER BUSY OR NO REQUEST
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:			;**-1
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PH      YSICAL UNIT NUMBER.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; TU58 TAPE CARTRIDGE DRIVE I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO 2ND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF 1ST LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 05 -- I/O FUNCTION CODE (IO.      RLB, IO.WLB, IO.DGN, IO.BLS)
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER
;	WD. 14 -- NUMBER OF BYTES TO TRANSFER
;	WD. 15 -- NOT USED
;	WD. 16 -- LOW BYTE MUST BE ZERO, HIGH BYTE NOT USED
;	WD. 17 -- LOGICAL OR PHYSICAL BLOCK NUMBER
;	WD. 20 -- NOT USED
;
; DRIVER USAGE       OF UCB:							; PJC025
;									; PJC025
;	U.CW2+1 --- STORES DRIVER'S RETRY COUNT				;**-1
;
; THE TU58 UTILIZES RADIAL SERIAL PROTOCOL. ALL I/O			;**-1
; COMMANDS ARE INITIATED BY SENDING A COMMAND MESSAGE
; PACKET CONSISTING OF 14. BYTES OF INFORMATION. DATA
; IS THEN TRANSFERRED TO THE UNIT (WRITE) OR TO THE
; USER'S BUFFER (READ) IN MESSAGE PACKETS OF UP TO 128
; BYTES EACH. TERMINATION OF AN OPERATION BY THE TU58
; IS SIGNALED BY THE UNIT'S SENDING AN END MESSAGE
; PACKET WHICH CONTAINS IN      FORMATION CONCERNING THE
; SUCCESS OF THE TRANSFER.
;									;**-1
10$:	MOV	R5,CNTBL(R3)	;STORE UCB ADDRESS
	MOVB	#RTRY,U.CW2+1(R5) ;STORE RETRY COUNT
	MOV	S.CSR(R4),DBUF(R3) ;STORE CONTROLLER NUMBER		; PJC024
	MOV 	R3,R4		;R4 IS USED FOR CONTROLLER INDEXING	; PJC024
	CALL	$BLKCK		;CHECK PARAMETERS			;**-3
	ADD	#DDXBF,DBUF(R4)	;SAVE DL11 XMITTER BUFFER		; PJC025
;									;**-1
; ENTRY POINT FOR FUNCTION RETRY					; PJC025
;									;**-1
RINI:	MOV	#CTAB-2,RADD(R4) ;POINT TO WORD PRIOR TO COMMA      ND TABLE
	CLR	FLAG(R4)	;SET FLAG FOR TRANSMIT INTERRUPTS
	BR	145$		;PREPARE TO SEND BYTE
;
; SEND COMMAND PACKET
;
CONE:	MOVB	#CNTL,@DBUF(R4)	;SEND COMMAND FLAG BYTE
	BR	145$		;PREPARE TO SEND BYTE
CTWO:	MOV	#10.,@DBUF(R4)	;SEND BYTE COUNT
	MOVB	#10.,CKSM1+1(R4) ;CREATE CHECKSUM WORD FROM
	MOVB	#CNTL,CKSM1(R4)	; FIRST TWO BYTES
	BR	145$
CTHR:	CALL	IOPKT		;STORE I/O PKT ADDRESS IN R1
;
; POSITION AND DIAGNOSE FUNCTIONS ARE USER MODE DIAGNOSTIC FUNCTIONS
;

									; PJC025
	.IF DF	D$$IAG
      
	CMP	#IO.DGN!IQ.UMD,I.FCN(R1) ;TU58 INTERNAL DIAGNOSTICS?	; PJC025
	BNE	40$		;IF NE NO				;**-1
	MOV	#DIAG,CKSM2(R4)	;CREATE NEXT CHECKSUM WORD
	MOVB	#DIAG,@DBUF(R4)	;SEND DIAGNOSTIC OP CODE
	BR	140$		;CONTINUE OPERATION
40$:	CMP	#IO.BLS!IQ.UMD,I.FCN(R1) ;POSITION FUNCTION?
	BNE	60$		;IF NE NO
	MOV	#POSIT,CKSM2(R4) ;CREATE NEXT CHECKSUM WORD
	MOVB	#POSIT,@DBUF(R4) ;SEND OP CODE
	BR	140$		;CONTINUE

	.ENDC
									; PJC025

60$:	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL BLOCK?
	BNE	70$		;      IF NE NO
	MOV	#READ,CKSM2(R4)	;CREATE NEXT CHECKSUM WORD
	MOVB	#READ,@DBUF(R4)	;SEND READ OPCODE
	BR	110$		;CONTINUE
70$:	CMPB	#IO.WLB/256.,I.FCN+1(R1) ;WRITE LOGICAL BLOCK?
	BEQ	100$		;IF EQ YES
	MOV	(SP)+,R1	;RESTORE R1
	CALL	$FORK		;ENSURE PRIORITY=0 AND REGISTERS SAVED
	MOV	#IE.IFC&377,R0	;ILLEGAL FUNCTION CODE
	CLR	CKSM2(R4)	;CLEAR BYTES TRANSFERRED
	JMP	IOCMP		;EXIT
100$:	MOV	#WRITE,CKSM2(R4) ;CREATE NEXT CHECKSUM WORD
	MOVB	#WRITE,@DBUF(R4) ;SEND WRITE OPCODE
110$:	BITB	#US.WCK,U.STS(R5)       ;WRITE CHECK SET?
	BNE	141$
	CMPB	#20,I.FCN(R1)	;IS WLC OR RLC REQUESTED?
	BNE	140$		;IF NE NO
	BR	141$
;
; SEND A MODIFIER BYTE OF ONE FOR WRITECHECKS AND READCHECKS		; PJC025
;									;**-1
CFOUA:	MOVB	#1,CKSM2+1(R4)	;ALTER CHECKSUM
	MOVB	#1,@DBUF(R4)	;SEND MODIFIER
	ADD	#2,RADD(R4)	;SKIP OVER NEXT RETURN ADDRESS
	BR	160$		;CONTINUE
140$:	ADD	#2,RADD(R4)	;SKIP OVER NEXT RETURN ADDRESS
141$:	MOV	(SP)+,R1	;RESTORE R1
									; PJC039
									; PJC039
	.IF DF	E$$DVC							; PJC039
						      			; PJC039
	MOV	CKSM2(R4),WORD1(R4) ;STORE OP CODE AND COMMAND MODIFIER	; PJC039
									; PJC039
	.ENDC								; PJC039
									; PJC039
									; PJC039
145$:	JMP	SMSG
;
; SEND A ZERO MODIFIER BYTE FOR READS AND WRITES			; PJC025
;									;**-1
CFOUB:	CLRB	@DBUF(R4)	;SEND MODIFIER
160$:	CALL	CHKPT		;CHECKSUM CALCULATION
	BR	145$
CFIV:	MOVB	U.UNIT(R5),@DBUF(R4) ;SEND UNIT #			; PJC013
	MOVB	U.UNIT(R5),CKSM2(R4)					;**-1
	BR	145$
CSIX:	CLRB	@DBUF(R4)	;SEND 0
	CLRB	CKSM2+1(R4)
	BR	160      $
CSEV:
CEIG:	CLRB	@DBUF(R4)	;SEND TWO ZERO BYTES
	BR	145$
CNIN:	CALL	IOPKT		;STORE I/O PACKET ADDRESS IN R1		; PJC031
	ADD	#I.PRM,R1	;POINT TO PARAMETER LIST		; PJC031
	MOV	(R1)+,U.BUF(R5)	;INSERT RELOCATION BIAS			; PJC031
	MOV	(R1)+,U.BUF+2(R5) ;INSERT BUFFER ADDRESS		; PJC031
	MOV	(R1),CKSM2(R4)	;CREATE CHECKSUM			; PJC031
	MOVB	(R1),@DBUF(R4)	;SEND LOW BYTE COUNT			; PJC031
	BR	141$							;**-3
;
; NOTE:									; PJC025
;									; PJC025
; THE TU58 REQUIRES THAT THE NUMBER OF BYTES TO B      E TRANSFERRED		; PJC025
; BE EVEN AND THAT THE STARTING ADDRESS OF THE DATA TRANSFER BE		; PJC025
; ON A WORD BOUNDARY.							; PJC025
;									;**-3
CTWE:				;SEND HIGH BLOCK NO.
CTEN:	MOVB	CKSM2+1(R4),@DBUF(R4) ;SEND HIGH BYTE COUNT
	BR	160$
CELE:	CALL	IOPKT		;STORE I/O PKT ADDRESS IN R1
	MOVB	I.PRM+12(R1),@DBUF(R4)	;SEND LOW BLOCK NO.
	MOV	I.PRM+12(R1),CKSM2(R4)
	BR	141$
CTHI:	MOVB	CKSM1(R4),@DBUF(R4) ;SEND LOW CHECKSUM
	BR	145$
CFOR:	MOVB	CKSM1+1(R4),@DBUF(R4) ;SEND HIGH CHECKSUM
	.DSABL	      LSB
;									; PJC025
; AFTER THE COMMAND PACKET IS SENT THE TU58 RESPONDS.			;**-1
; ITS RESPONSE DEPENDS ON THE OPERATION REQUESTED.
; A CONTINUE IS SENT IN RESPONSE TO A WRITE, THE FIRST
; DATA PACKET IS SENT IN RESPONSE TO A READ, AND AN
; END PACKET IS SENT IN RESPONSE TO A DIAGNOSTIC OR
; POSITION COMMAND. ALSO AN END PACKET MAY BE RECEIVED
; ON A FAILURE TO READ THE FIRST RECORD PROPERLY.
;									; PJC025
; DETERMINE THE APPROPRIATE INITIAL RESPONSE FROM THE TU58		; PJC025
; AND RECEIVE       THE FIRST BYTE FROM THE UNIT.				; PJC025
;									;**-5
	.ENABL	LSB							; PJC025
	INCB	FLAG+1(R4)	;SET FLAG FOR RECEIVE
	SUB	#DDXBF-DDRBF,DBUF(R4) ;SET RECEIVE BUFFER
	BR	25$		;READ RESPONSE BYTE FROM TU58		; PJC025
CFIF:	CALL	IOPKT		;STORE I/O PKT ADDRESS IN R1		;**-1

									; PJC025
	.IF DF	D$$IAG

	CMPB	#IO.DGN/256.,I.FCN+1(R1) ;DIAGNOSTIC?
	BEQ	10$		;IF EQ YES

	.ENDC
									; PJC025

	JMP	DPACK		;ELSE RECEIVE DATA PACKET OR CONTINUE
10$:	MOV	(SP)+,R1	;RESTORE R1
;									;       PJC025
; RECEIVE AND MANUPILATE THE TU58'S END PACKET INFORMATION		; PJC025
;									; PJC025
ENDP:	MOV	#ETAB-2,RADD(R4) ;POINT TO END PACKET SEQUENCE		;**-4
	CMPB	RDAT(R4),#CNTL	;COMMAND/END PACKET?
	BR	24$
;
; AT EONE WE SHOULD HAVE RECEIVED THE BYTE COUNT OF AN END PACKET
; WHICH IS ALWAYS EQUAL TO 10.
;
EONE:	CMPB	RDAT(R4),#10.	;BYTE COUNT=10.?
24$:	BEQ	25$		;IF EQ YES				; PJC039
	JMP	NTRY		;					; PJC039
25$:	JMP	RMSG		;READ A BYTE				;**-1
ETWO:	CMPB	RDAT(R4),#100	;OP CODE=END PACKET?      
	BR	24$
ETHR:	MOVB	RDAT(R4),CKSM1(R4) ;STORE SUCCESS CODE
									; PJC039
									; PJC039
	.IF DF	E$$DVC							; PJC039
									; PJC039
	MOVB	RDAT(R4),WORD2(R4) ;					; PJC039
	BR	25$		;					; PJC039
EFOU:	MOVB	RDAT(R4),WORD2+1(R4) ;STORE UNIT SELECT			; PJC039
									; PJC039
	.IFF								; PJC039
									; PJC039
EFOU:				;DUMP BYTES				; PJC039
									; PJC039
	.ENDC								; PJC039
									; PJC039
									; PJC039
EFIV:				;DUMP BYTES				; PJC039
ESIX:									;**-2
ES      EV:	BR	25$
EEIG:	MOVB	RDAT(R4),CKSM2(R4) ;STORE BYTE TRANSFERRED COUNT -LOW
									; PJC039
									; PJC039
	.IF DF	E$$DVC							; PJC039
									; PJC039
	MOVB	RDAT(R4),WORD3(R4) ;					; PJC039
									; PJC039
	.ENDC								; PJC039
									; PJC039
									; PJC039
	BR	25$
ENIN:	MOVB	RDAT(R4),CKSM2+1(R4) ;STORE BYTE TRANSFERRED COUNT -HIGH
									; PJC039
									; PJC039
	.IF DF	E$$DVC							; PJC039
									; PJC039
	MOVB	RDAT(R4),WORD3+1(R4) ;					; PJC039
									; PJC0      39
	.ENDC								; PJC039
									; PJC039
									; PJC039
ETEN:
EELE:
ETWE:	BR	25$		;DUMP BYTES
ETHI:	CALL	$FORK		;ENSURE PRIORITY=0 AND REGISTERS SAVED
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESS
	TSTB	CKSM1(R4)	;SUCCESSFUL?
	BGT	ERRPT		;IF GT YES, BUT HAD RETRIES
	BEQ	ENDOP		;IF EQ, COMPLETE SUCCESS		; PJC039
	MOV	#IE.DNR&377,R0	;ASSUME DEVICE NOT READY		;**-1
	CMPB	CKSM1(R4),#-9.	;CARTRIDGE NOT IN PLACE?
	BEQ	ERRPT		;IF EQ YES				; PJC039
	MOV	#IE.WLK&377,R0	;ASSUME WRITE-LOCKED			;**-1
	CMPB      	CKSM1(R4),#-11.	;WRITE-LOCKED?
	BEQ	ERRPT		;IF EQ YES				; PJC039
	MOV	#IE.FHE,R0	;ASSUME FATAL HARDWARE ERROR		;**-1
	CMPB	CKSM1(R4),#-33.	;MOTOR STOPPED?
	BEQ	ERRPT		;IF EQ YES
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR
ERRPT:									; PJC039
									; PJC039
									; PJC039
	.IF DF	E$$DVC							; PJC039
									; PJC039
	CALL	LOGERR		;LOG DEVICE ERROR			; PJC039
									; PJC039
	.ENDC								; PJC039
									; PJC039
									; PJC039
	BR	ENDOP		;					; PJC039
									; PJ      C025
									; PJC025
	.IF DF	E$$DVC							;**-1

;+									; PJC039
; **-LOGERR-LOG DEVICE ERROR						; PJC039
; **-LOGTMO-LOG DEVICE TIMEOUT						; PJC039
;									; PJC039
; THESE ROUTINES WILL ALLOCATE A CORE BLOCK, FILL IT WITH THE		; PJC039
; APPROPRIATE INFORMATION, CALL THE APPROPRIATE EXECUTIVE ERROR		; PJC039
; LOGGING ROUTINE, DEALLOCATE THE CORE BLOCK, AND RETURN BACK		; PJC039
; TO THE CALLER.							; PJC039
;									;**-7
; IF FOR ANY REASON THE CORE BLOCK CANNOT BE ALLOCATED       THEN
; THE EXECUTIVE ERROR LOGGING ROUTINE WILL NOT BE CALLED
; AND THE ERROR SEQUENCE NUMBER WILL BE UPDATED TO INDICATE
; THAT A MISSED ERROR CONDITION OCCURRED.
;-									; PJC025
LOGERR:	MOV	R0,-(SP)	;SAVE STATUS CODE			; PJC039
	MOV	#$DVERR,-(SP)	;LOG DEVICE ERROR			; PJC039
	BR	70$		;					; PJC039
LOGTMO:	MOV	R0,-(SP)	;SAVE STATUS CODE			; PJC039
	MOV	#$DTOER,-(SP)	;LOG TIMEOUT ERROR			; PJC039
70$:	MOV	#DDNUM*2,R1	;NUMBER OF BYTES TO ALLOCATE		; PJC039
	CALL	$ALOCB		;ALLOCATE A CORE BLOCK      			;**-3
	BCC	80$		;IF CC BLOCK WAS ALLOCATED
	INC	$ERRSQ		;INDICATE A MISSED ERROR CONDITION
	BR	90$		;END I/O ROUTINE
80$:	MOV	R0,R1		;COPY CORE BUFFER POINTER
	MOV	DBUF(R4),R3	;STORE BUFFER ADDRESS
	TST	-(R3)		;POINT TO DL11 CSR			; PJC025
	MOV	(R3)+,(R1)+	;MOVE DL11 RECEIVE CSR INTO CORE BUFFER	; PJC025
	MOV	(R3)+,(R1)+	;...DL11 RECEIVE BUFFER			; PJC025
	MOV	(R3),(R1)+	;...DL11 TRANSMITTER CSR		; PJC039
	MOV	WORD1(R4),(R1)+	;OPCODE AND COMMAND MODIFIER		; PJC025
	MOV	WORD2(R4),(R1)+	;SUCCESS       CODE AND UNIT SELECT		; PJC025
	MOV	WORD3(R4),(R1)	;BYTE COUNT LOW AND BYTE COUNT HIGH	; PJC039
	MOV	R4,R3		;SAVE CONTROLLER INDEX			; PJC039
	MOV	U.SCB(R5),R4	;GET SCB ADDRESS			; PJC039
	MOV	R0,S.CSR(R4)	;COPY CORE BUFFER POINTER		; PJC039
	CALL	@(SP)+		;CALL ERROR LOGGING ROUTINE		; PJC039
	MOV	DBUF(R3),R2	;GET DL11 BUFFER ADDRESS		; PJC039
	TST	-(R2)		;POINT TO DL11 CSR REGISTER ADDRESS	; PJC039
	MOV	R2,S.CSR(R4)	;RESTORE CSR ADDRESS			; PJC039
	MOV	R3,R4		;RESTORE CONTROLLER INDEX		; PJC039
      	MOV	#DDNUM*2,R1	;GET NUMER OF BYTES TO DEALLOCATE	; PJC039
	CALL	$DEACB		;DEALLOCATE CORE BLOCK			;**-11
90$:	MOV	(SP)+,R0	;RESTORE I/O STATUS CODE
	RETURN			;					; PJC039

	.ENDC
									; PJC025

ENDOP:

									; PJC025
	.IF DF	D$$IAG

	CALL	IOPKT
	CMPB	#IO.DGN/256.,I.FCN+1(R1) ;DIAGNOSTIC?
	BNE	100$		;IF NE NO

									; PJC025
	.IF DF	M$$MGE

	MOV	I.PRM+14(R1),KISAR6 ;SET BUFFER RELOCATION BIAS

	.ENDC
									; PJC025

	MOV	I.PRM+16(R1),R0	;GET REGISTER BUFFER ADDRESS
	      MOV	DBUF(R4),R3	;GET DL11 RECEIVE BUFFER ADDRESS	; PJC025
	TST	-(R3)		;POINT TO REC. CSR ADDRESS		;**-1
	MOV	(R3)+,(R0)+	;MOV REC. CSR CONTENTS TO USER BUFF.
	MOV	(R3)+,(R0)+	;MOV REC. BUFF CONTENTS
	MOV	(R3)+,(R0)+	;MOV TRANS. CSR CONTENTS
	MOV	(R3)+,(R0)+	;MOV TRANS. BUFF CONTENTS
	MOV	CKSM1(R4),R1	;MOV TU58 END PACKET INFO		; PJC025
	MOV	#IS.SUC&377,R0	;STORE I/O COMPLETION STATUS		;**-1
100$:	TST	(SP)+		;RESTORE STACK

	.ENDC
									; PJC025

;
; COMMON EXIT CODE- ALL OPERATIONS COMPLETE       HERE
;									;**-4
IOCMP:	MOV	CKSM2(R4),R1	;PICKUP BYTES TRANSFERRED COUNT

									; PJC025
	.IF DF	E$$DVC

	MOVB	U.CW2+1(R5),R2	;STORE FINAL RETRY COUNT
	BIS	#RTRY*^D<256>,R2 ;MERGE INITIAL RETRY COUNT

	.ENDC
									; PJC025

	CALL	$IODON
	JMP	DDINI		;NEXT I/O PACKET
	.DSABL	LSB							; PJC025
;									; PJC025
; WE ENTER HERE WHEN AN UNEXPECTED AND UNDESIRED BYTE IS RECEIVED.	; PJC025
; THE TU58 IS REINITIALIZED AND IF THE RETRY COUNT IS => 0, THE		; PJC025
; I/O FUNCTION IS ST      ARTED OVER. OTHERWISE, AN ERROR IS LOGGED AND	; PJC025
; THE OPERATION IS ABORTED.						; PJC025
;									; PJC025
	.ENABL	LSB							; PJC025
NTRY:	DECB	U.CW2+1(R5)	;DECREMENT RETRY COUNT			;**-10
	ADD	#DDXBF-DDRBF,DBUF(R4)  ;POINT TO TRANS. BUFFER
;
; TINIT TRIES TO REINITIALIZE THE TU58. IT WILL ATTEMPT THE		; PJC025
; INITIALIZATION ROUTINE OF SENDING BREAK, CLEARING BREAK,		; PJC025
; SENDING TWO INIT'S, AND RECEIVING A CONTINUE.				; PJC025
;									;**-4
TINIT:	CLR	FLAG(R4)	;SET FOR TRANS      MIT WITH NO USER DATA TRANSFER
	MOV	#ITAB-2,RADD(R4) ;POINT TO INITIALIZE TABLE
	BR	50$		;WAIT
;
; NULL TIMING CHARACTERS ARE SENT AT IONE AND ITWO TO ALLOW
; ENOUGH TIME FOR THE BREAK BIT TO CAUSE A FRAMING ERROR. THIS
; SIGNALS THE TU58 TO STOP TRANSMITTING AND LISTEN.			; PJC025
;									;**-1
IONE:	MOV	DBUF(R4),CKSM1(R4) ;TEMP. STORE BUFFER
	SUB	#DDXBF-DDXCS,CKSM1(R4)	;POINT TO XCSR
	BIS	#BRK,@CKSM1(R4)	;SEND BREAK TO TU58			; PJC025
ITWOA:				;SEND TIMING NULLS			;**-1
ITWOB:
ITWOC:
ITWO      D:
ITWOE:	CLRB	@DBUF(R4)	;
50$:	JMP	SMSG		;WAIT
;
; ITHR AND IFOU WILL CLEAR THE BREAK CONDITION AND ISSUE
; TWO INITIALIZE COMMANDS TO THE TU58. (THE FIRST IS IGNORED		; PJC025
; BY THE CONTROLLER).							;**-1
;
ITHR:	BIC	#BRK,@CKSM1(R4) ;CLEAR BREAK
	SUB	#DDXCS-DDRBF,CKSM1(R4)  ;TEMP. STORE REC. BUFFER
	TSTB	@CKSM1(R4)		;DUMP REC. BUFFER
IFOU:	MOVB	#INIT,@DBUF(R4)	;SEND ANOTHER INIT.
	BR	50$		;WAIT
;
; A CHARACTER IS RECEIVED AT ISIX. IF IT IS A CONTINUE, WE		; PJC025
; HAVE SUCCESSFULLY I      NITIALIZED THE DEVICE.				; PJC025
;									;**-3
IFIV:	SUB	#DDXBF-DDRBF,DBUF(R4) ;POINT TO REC. BUFF.
	INCB	FLAG+1(R4)	;SET FLAG FOR RECEIVE
	JMP	RMSG		;WAIT
ISIX:	ADD	#DDXBF-DDRBF,DBUF(R4) ;POINT TO XBUF
	TSTB	U.CW2+1(R5)	;RETRY?					;**-1
	BGT	60$		;IF GT YES				; PJC031
	CALL	$FORK		;ENSURE PRIORITY=0 AND REGISTERS SAVED	;**-1
	MOV	#IE.FHE&377,R0	;FATAL ERROR
	CLR	CKSM2(R4)	;CLEAR BYTE TRANSFER COUNT

									; PJC025
	.IF DF	E$$DVC

	MOV	#200,CKSM1(R4)	;SET ERROR CODE

	.ENDC
						      			; PJC025

	JMP	ERRPT		;ERROR LOG AND EXIT			; PJC039
60$:	JMP	RINI		;RETRY					;**-1
;									; PJC025
; HERE DATA PACKETS SENT BY THE TU58 ARE READ. THE NUMBER OF		; PJC025
; DATA BYTES IN THE PACKET IS RECEIVED AT RONE. IT IS STORED		; PJC025
; IN LOCATION FLAG AND THE CHECKSUM IS INITIALIZED. THE DATA		; PJC025
; IS TRANSFERRED WITHIN THE INTERRUPT SERVICE ROUTINE WHERE		; PJC025
; THE CHECKSUM IS ALSO VERIFIED. THE FIRST BYTE OF THE NEXT		; PJC025
; PACKET IS RECEIVED AT RFOU AND IF IT IS       A DATA FLAG, THIS		; PJC025
; CODE IS ENTERED AGAIN.						; PJC025
;									; PJC025
DPACK:	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ?				;**-11
	BNE	102$		;IF NE NO -IT'S A WRITE
	MOV	(SP)+,R1	;RESTORE R1
RFOU:	CMPB	RDAT(R4),#DATA	;DATA PACKET?
	BEQ	96$		;IF EQ YES
94$:	JMP	ENDP
96$:	MOVB	#DATA,CKSM1(R4)	;START CHECKSUM
	MOV	#RTAB-2,RADD(R4) ;POINT TO READ TABLE
	BR	100$		;READ A BYTE
RONE:	MOVB	RDAT(R4),FLAG(R4) ;STORE BYTE COUNT
	MOVB	RDAT(R4),CKSM1+1(R4)	;STORE HIGH BYTE OF FIRST CHECKSUM
100$:      	JMP	RMSG
;									; PJC025
; AT THIS POINT WE SEND A DATA PACKET TO THE TU58.			; PJC025
; THE DATA FLAG BYTE IS SENT AT TONE. THE NUMBER OF DATA		;**-3
; BYTES IN THIS PACKET IS SENT AT TTWO. DATA IS THEN
; TRANSFERRED ALONG WITH THE CHECKSUM WITHIN THE INTERRUPT
; SERVICE ROUTINE. RETURN TO THIS SEGMENT IS MADE AT TFIV
; AND THE FIRST BYTE OF THE NEXT PACKET IS RECEIVED AT
; TSIX, IF IT IS A CONTINUE ANOTHER PACKET IS SENT.
; WHEN THE TU58 HAS RECEIVED ALL THE DATA, IT SENDS AN			; PJC025
; EN      D PACKET FLAG INSTEAD OF A CONTINUE (THIS ALSO OCCURS		;**-1
; IF THE TU58 ENCOUNTERS AN ERROR WRITING THE DATA).			; PJC025
;									; PJC025
102$:	MOV	I.PRM+4(R1),WCNT(R4) ;DUPLICATE BYTE COUNT		;**-3
	MOV	(SP)+,R1	;RESTORE R1
TSIX:	CMPB	RDAT(R4),#CONT	;CONTINUE FLAG?
	BNE	94$		;IF NE NO
	MOV	#TTAB-2,RADD(R4) ;POINT TO TRANSMIT (WRITE) TABLE	; PJC025
	CLRB	FLAG+1(R4)	;SET TRANSMIT FLAG			;**-1
	ADD	#DDXBF-DDRBF,DBUF(R4) ;SET TRANSMIT BUFFER
	BR	130$		;PREPARE TO SEND FIRST BYTE
TONE:	MOVB	#DAT      A,@DBUF(R4)	;SEND FLAG BYTE
	MOVB	#DATA,CKSM1(R4)	;START CHECKSUM
	CMP	#128.,WCNT(R4) ;MORE THAN 1 PACKET LEFT?
	BLO	120$		;IF L0 YES
125$:	MOVB	WCNT(R4),CKSM1+1(R4) ;CREATE HIGH BYTE OF CHECKSUM
	CLRB	WCNT(R4)	;ZERO REMAINING BYTE COUNT
	BR	130$
120$:	MOVB	#128.,CKSM1+1(R4) ;CREATE HIGH BYTE OF CHECKSUM
	SUB	#128.,WCNT(R4) 	;ADJUST REMAINING COUNT
130$:	JMP	SMSG
TTWO:	MOVB	CKSM1+1(R4),@DBUF(R4) ;SEND BYTE COUNT
	MOVB	CKSM1+1(R4),FLAG(R4) ;SET UP FLAG BYTE COUNT
	BR	130$
TFIV:	INCB	FLAG+1(R4)	;      SET RECEIVE BYTE
	SUB	#DDXBF-DDRBF,DBUF(R4) ;SET RECEIVE BUFFER
	BR	100$		;READ A BYTE
	.DSABL	LSB							; PJC025
;									; PJC025
; IOPKT PUTS I/O PACKET ADDRESS IN R1					;**-7
;									; PJC025
; OUTPUT:								; PJC025
;									; PJC025
;	R1 = I/O PACKET ADDRESS						; PJC025
;	(SP) = FORMER CONTENTS OF R1 TO BE RESTORED BY THE CALLER	; PJC025
;									; PJC025
IOPKT:	MOV	(SP)+,WCNT(R4)	;SAVE RETURN ADDRESS			;**-5
	MOV	R1,-(SP)	;PRESERVE R1
	MOV	R4,-(SP)	;PRESERVE R4
	MOV	U.SCB(R5),      R4	;GET SCB ADDRESS
	MOV	S.PKT(R4),R1	;GET I/O PKT ADDRESS
	MOV	(SP)+,R4	;RESTORE R4
	JMP	@WCNT(R4)	;NOTE R1 WILL BE RESTORED BY PROGRAM
;									; PJC025
; RTBK (RETURN BACK) INCREMENTS THE RETURN ADDRESS POINTER AND		; PJC025
; THEN JUMPS THERE.							; PJC025
;									; PJC025
RTBK:	ADD	#2,RADD(R4)	;POINT TO NEXT LOCATION			;**-6
	MOV	@RADD(R4),-(SP)	;MOVE RETURN ADDRESS LOCATION ONTO STACK
	JMP	@(SP)+		;RETURN TO ADDRESS IN TABLE
;									; PJC025
; THIS ROUTINE IS JUMPED TO IN ORDER TO S      END INFORMATION.		; PJC025
; THE MAIN PROGRAM CONTINUES VIA THE INTERRUPT SERVICE ROUTINE		; PJC025
; CODE (SPT), UNLESS WRITE DATA IS TO BE TRANSFERRED (DATA COUNT 	; PJC025
; FLAG = NON-ZERO).							; PJC025
;									; PJC025
	.ENABL	LSB							;**-12
SMSG:	SUB	#DDXBF-DDXCS,DBUF(R4) ;POINT TO CSR
	BIT	#TRDY,@DBUF(R4)	;IS TRANSMITTER READY
	BEQ	20$
SREC:	ADD	#DDXBF-DDXCS,DBUF(R4) ;POINT TO BUFFER
	TSTB	FLAG(R4)	;BYTE COUNT 0
	BEQ	RTBK		;IF EQ YES
	JMP	SPT		;GO TO SEND DATA ROUTINE
20$:	BIS	#TI      E,@DBUF(R4)	;SET XMITTER INTERRUPT ENABLE		; PJC024
	MOV	U.SCB(R5),R4	;STORE SCB ADDRESS			;**-9
	MOVB	S.ITM(R4),S.CTM(R4) ;SET TIMEOUT
	RETURN
	.DSABL	LSB
;									; PJC025
; THIS ROUTINE IS JUMPED TO IN ORDER TO RECEIVE INFORMATION VIA		; PJC025
; THE DL11. IF RECEIVER DONE IS SET, THEN A RETURN TO THE MAIN		; PJC025
; PROGRAM IS INITIATED VIA THE INTERRUPT SERVICE ROUTINE (RPT).		; PJC025
; IF THE DL11 DONE BIT IS CLEAR, A RETURN IS EXECUTED AND THE		; PJC025
; INTERRUPT SERVICE ROUTINE WILL R      ETURN CONTROL TO THE PROGRAM		; PJC025
; WHEN THE DONE BIT IS SET AND WHEN ALL READ DATA HAS BEEN		; PJC025
; TRANSFERRED TO THE USER'S BUFFER.					; PJC025
;									; PJC025
	.ENABL	LSB							;**-14
RMSG:	SUB	#DDRBF-DDRCS,DBUF(R4) ;POINT TO CSR
	BIT	#RDONE,@DBUF(R4) ; READY?
	BEQ	20$		;IF EQ NO
RREC:	JMP	RPT		;IF YES ENTER READ ROUTINE
20$:	BIS	#RIE,@DBUF(R4)	;SET RE. INTERRUPT ENABLE		; PJC024
	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			;**-9
	MOVB	#40.,S.CTM(R4)	;SET TIMEOUT
	RETURN
	.DSABL LS      B
;									; PJC025
; CHPKT CREATES A CHECKSUM						; PJC025
;									; PJC025
; INPUT:								; PJC025
;									; PJC025
;	CKSM2(R4) = WORD TO BE ADDED					; PJC025
;	CKSM1(R4) = OLD CHECKSUM					; PJC025
;									; PJC025
; OUTPUT:								; PJC025
;									; PJC025
;	CKSM1(R4) = NEW CHECKSUM					; PJC025
;									; PJC025
CHKPT:	ADD	CKSM2(R4),CKSM1(R4) ;ADD TWO WORDS			;**-7
	ADC	CKSM1(R4)	;ADD CARRY
				;FALL THROUGH AND RETURN
;									; PJC025
;	END LOCAL ROUTINES						;**-1
;	      								; PJC025
;+									;**-1
; DDCAN-CANCEL I/O ENTRY POINT
;									; PJC025
; CANCEL I/O IS A NOP FOR FILE STRUCTURED DEVICES.			; PJC025
;-									;**-1
DDCAN:
;+									;**-1
; POWERFAIL REQUIRES NO OPERATION. REINITIALIZATION
; OF THE TU58 WILL OCCUR DURING NORMAL OPERATION IF REQUIRED.		; PJC025
;-									;**-1
DDPWF:	RETURN

;+
; **-$DDINT TU58 INTERRUPT SERVICE ROUTINE				; PJC025
;-									;**-8
	.ENABL LSB
$DDOUT::			;;;OUTPUT AS WELL AS INPUT ($DDINT)
				;;;INTERRUPT       ENTRY POINT
	INTSE$	DD,PR4,T$$U58	;;;SAVE REGISTERS & SET PRIORITY
	BIC	#<RIE!TIE>,@DBUF(R4)	;;;CLEAR INTERRUPTS		;**-3
	MOV	R1,-(SP)	;;;SAVE R1
	MOV	U.SCB(R5),R1	;;;GET SCB ADDRESS
	CLRB	S.CTM(R1)	;;;CLEAR TIMEOUT
	MOV	(SP)+,R1	;;;RESTORE R1
;
; FLAG+1 IS SET FOR A TRANSMIT OPERATION AND CLEARED FOR A		; PJC025
; A RECEIVE OPERATION. FLAG IS CHECKED TO DETERMINE IF WE		; PJC025
; HAVE DATA TO TRANSFER.						; PJC025
;									;**-4
	TSTB	FLAG+1(R4)	;;;RECEIVE INTERRUPT?
	BNE	RPT		;;;IF NE YES      
	ADD	#DDXBF-DDXCS,DBUF(R4)	;;;POINT TO BUFFER
	TSTB	FLAG(R4)	;;;TRANSMIT DATA PACKET?
	BNE	SPT		;;;IF NE YES
5$:	JMP	RTBK		;;;ELSE RETURN
;
; SPT IS THE CODE USED TO SEND USER DATA TO THE TU58. A RUNNING		; PJC025
; CHECKSUM IS KEPT AND IS SENT AS THE LAST TWO CHARACTERS OF A		; PJC025
; DATA PACKET (TTHR,TFOU). AFTER ALL DATA HAS BEEN SENT, CONTROL	; PJC025
; IS PASSED TO THE MAIN PROGRAM.					; PJC025
;									;**-5
SPT:	CALL	$GTBYT		;;;PUT USER'S DATA BYTE ON STACK
	BITB	#1,FLAG(R4)	;;;CHECK       FOR EVEN OR ODD BYTE NO.
	BNE	20$		;;;IF NE ODD,THEREFORE HIGH ORDER
				;;;BYTE IN CHECKSUM
	MOVB	(SP)+,CKSM2(R4)	;;;SAVE LOW ORDER CHECKSUM BYTE
	MOVB	CKSM2(R4),@DBUF(R4) ;;;TRANSMIT BYTE
	BR	30$
20$:	MOVB	(SP)+,CKSM2+1(R4) ;;;SAVE HIGH ORDER CHECKSUM BYTE
	MOVB	CKSM2+1(R4),@DBUF(R4) ;;;TRANSMIT BYTE
	CALL	CHKPT		;;;GENERATE CHECKSUM
30$:	DECB	FLAG(R4)	;;;DECREMENT DATA COUNT
35$:	JMP	SMSG
TTHR:	MOVB	CKSM1(R4),@DBUF(R4) ;;;SEND LOW ORDER CHECKSUM BYTE
	BR	35$
TFOU:	MOVB	CKSM1+1(R4),@DBUF(R4)       ;;;SEND HIGH ORDER BYTE
	BR	35$
;
; RPT CHECKS FOR AN ERROR CONDITION IN THE DL11'S RECEIVE		; PJC025
; TIMEOUT IS ENTERED WHEN THE DL11 DOES NOT RESPOND WITHIN		; PJC025
; BUFFER. IF DATA IS TO BE RECEIVED THIS ROUTINE			;**-1
; TRANSFERS THE CHARACTER IN THE USER'S BUFFER AND KEEPS
; A RUNNING CHECKSUM. AFTER ALL DATA IS RECEIVED THE FINAL
; TWO BYTES OF THE PACKET ARE PRESENT AT RTWO AND RTHR AND
; IF THEY EQUAL THE CHECKSUM THEN CONTROL IS RETURNED TO
; THE MAIN PROGRAM.
;
RPT:	ADD	#DDRBF-D      DRCS,DBUF(R4)  ;;;POINT TO RECEIVE BUFFER
	MOV	@DBUF(R4),RDAT(R4) ;;;STORE RECEIVED INFO.
	BPL	80$		;;;IF PL NO ERROR
40$:	JMP	NTRY		;;;ATTEMPT RETRY
80$:	TSTB	FLAG(R4)	;;;DATA TO RECEIVE
	BEQ	5$		;;;IF EQ NO
	MOVB	RDAT(R4),-(SP)	;;;PUT DATA ON STACK
	CALL	$PTBYT		;;;PUT DATA INTO USER'S BUFFER
	BITB	#1,FLAG(R4)	;;;ODD OR EVEN BYTE (FOR CHECKSUM)
	BNE	90$		;;;IF NE ODD (HIGH ORDER CHECKSUM BYTE)
	MOVB	RDAT(R4),CKSM2(R4) ;;;LOW ORDER CHECKSUM BYTE
	BR	100$
90$:	MOVB	RDAT(R4),CKSM2+1(R4) ;;;HIGH O      RDER CHECKSUM BYTE
	CALL	CHKPT
100$:	DECB	FLAG(R4)	;;;DECREMENT DATA COUNT
	BR	160$
RTWO:	MOVB	RDAT(R4),CKSM2(R4) ;;;RECEIVE LOW ORDER CHECKSUM
	BR	160$
RTHR:	MOVB	RDAT(R4),CKSM2+1(R4) ;;;RECEIVE HIGH ORDER
	CMP	CKSM1(R4),CKSM2(R4) ;;;ARE CHECKSUMS CORRECT?
	BNE	40$		;;;IF NE NO
160$:	JMP	RMSG		;;;READ FIRST BYTE OF NEXT PACKET
	.DSABL	LSB
;+									;**-1
; TIMEOUT IS ENTERED WHEN THE DL11 DOES NOT RESPOND WITHIN		; PJC025
; A CERTAIN PRESET TIME TO THE  SUBROUTINES SMSG AND RMSG		;**-1
; SET      TING INTERRUPT ENABLE AND ISSUING A RETURN. THIS
; INDICATES A HARDWARE FAILURE OF THE DL11 OR TU58.			; PJC025
;-									;**-2
DDOUT:	BIC	#<RIE!TIE>,@DBUF(R3) ;;;CLEAR INTERRUPTS		; PJC025
	MOV	R3,R4		;COPY CONTROLLER INDEX			; PJC039
									; PJC039
									; PJC039
	.IF DF	E$$DVC							; PJC039
									; PJC039
	ADD	#DDRBF-DDRCS,DBUF(R4) ;;;POINT TO DL11 BUFFER ADDRESS	; PJC039
	CALL	LOGTMO		;;;LOG TIMEOUT ERROR			; PJC039
	MOV	R4,R3		;COPY CONTROLLER INDEX			; PJC039
	SUB	#DDRBF-DDRCS,D      BUF(R4) ;POINT TO DL11 CSR ADDRESS	; PJC039
									; PJC039
	.ENDC								; PJC039
									; PJC039
									; PJC039
	TSTB	FLAG+1(R4)	;RECEIVE TIME OUT?			;**-4
	BNE	2$		;IF NE YES
	ADD	#DDXBF-DDXCS,DBUF(R4)  ;POINT TO TRANSMIT BUFFER
	BR	4$		;
2$:	ADD	#DDXBF-DDRCS,DBUF(R4)  ;POINT TO TRANSMIT BUFFER
4$:	DECB	U.CW2+1(R5)	;DECREMENT RETRY COUNT
	BLE	10$		;IN LE, NO RETRIES LEFT			; PJC031
	JMP 	TINIT		;RE-INIT AND RETRY			;**-1
10$:	CLR	CKSM2(R3)	;CLEAR BYTE TRANSFERRED COUNT
	MOV	#IE.TMO&3   >   77,R0	;TIMEOUT ERROR
	JMP	ENDOP

									; PJC025
	.END
>          ôðskQ	› c,        	.TITLE	DFDRV
	.IDENT	/09/
 
;
; COPYRIGHT (C) 1974, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 09
;
; D. N. CUTLER 19-OCT-73
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;
; MODIFIED BY:
;
;	P. J. BEZEREDI 30-NOV-76
;
;		PB009 -- CORRECT OUT OF RANGE BRANCHES WHEN A
;			MULTI-CONTROLLER DRIVER IS GENERATE      D.
;
;	P. J. BEZEREDI 07-FEB-77
;
;		PB013 -- ADDITION OF EXPANDED WRITE CHECK CAPABILITY.
;
;	P. J. BEZEREDI 14-FEB-77
;
;		PB014 -- LOAD SECOND STATUS WORD WITH BYTES ACTUALLY
;			TRANSFERED BEFORE CALLING $IODON.

;	P. J. BEZEREDI 16-MAY-77
;
;		PB030 -- POWERFAIL RECOVERY SUPPORT.
;
; RF11 FIXED HEAD DISK DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	
	
	.IF DF	D$$IAG
	
	.MCALL	UMDIO$
	UMDIO      $			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS
	
	.ENDC
	
 
;
; EQUATED SYMBOLS
;
 
RETRY=8.			;ERROR RETRY COUNT
 
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER)
;
 
CNTBL:	.BLKW	R$$F11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$F11		;RETRY COUNT FOR CURRENT OPERATION
 
 
	.IF GT	R$$F11-1
 
TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER
 
	.ENDC
 
;
; DRIVER DISPATCH TABLE
;
 
$DFTBL::.WORD	DFINI		;DEVICE INITIATOR ENTRY POI      NT
	.WORD	DFCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DFOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DFPWF		;POWERFAIL ENTRY POINT
 
;+
; **-DFINI-RF11 FIXED HEAD DISK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; E      XECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-
 
	.ENABL	LSB
DFINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	DFCAN		;IF CS CONTROLLER BUSY OR NO REQU      EST
 
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RF11 FIXED HEAD DISK I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN       WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBE      R OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED.
;	WD. 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. ADRS ELSE NOT USED
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000)
;
 
	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB
	
	
	.IF DF	M$$EXT&M$$MGE
	
	CALL	$STMAP		;SET UP UNIBUS MAPPING ADDRESS
	
	.ENDC
	
	
	.IF DF	D$$IAG
	
	CMP	#IO.WCK!IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC WRITE CHEC      K?
	BNE	5$		;IF NE NO
	BIS	#107,U.BUF(R5)	;YES, SET WRITE CHECK FUNCTION
	BR	10$		;
	
	.ENDC
	
	
5$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION
	BIS	#105,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION?
	BHIS	7$		;IF HIS FUNCTION IS LEGAL
6$:	JMP	70$		;FUNCTION IS ILLEGAL
7$:	BEQ	10$		;IF EQ FUNCTION IS READ
	SUB	#2,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION
10$:	MOV	#RETRY,RTTBL(R3) ;SET RETRY COUNT
	MOV	#IE.BLK&377,R0	;ASSUME ILLEGAL BLOCK N      UMBER
	MOVB	I.PRM+10(R1),R2	;GET HIGH BYTE OF LOGICAL BLOCK NUMBER
	BNE	6$		;IF NE ILLEGAL BLOCK NUMBER
	MOV	I.PRM+12(R1),R3	;GET LOW PART OF LOGICAL BLOCK NUMBER
	SWAB	R3		;MULTIPLY LOW BYTE BY 256.
	BISB	R3,R2		;SET HIGH BITS OF DISK ADDRESS
	CLRB	R3		;CLEAR EXCESS BITS FROM LOW PART
	BIT	#177740,R2	;HIGH PART OF ADDRESS TOO BIG?
	BNE	6$		;IF NE YES
	MOV	R2,I.PRM+10(R1) ;SAVE HIGH PART OF DISK ADDRESS
	MOV	R3,I.PRM+12(R1)	;SAVE LOW PART OF DISK ADDRESS
 
;
; INITIATE I/O OPERATION
;
 
20$:      				;REF LABEL
	
	
	.IF DF	M$$EXT&M$$MGE
	
	CALL	$MPUBM		;MAP UNIBUS TO TRANSFER
	
	.ENDC
	
	
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET
	MOV	#401,(R2)	;CLEAR RF11 CONTROLLER
	MOVB	S.ITM(R4),S.CTM(R4)  ;SET CURRENT TIMEOUT COUNT
	ADD	#10,R2		;POINT TO DISK ADDRESS EXT. REGISTER
	MOV	I.PRM+10(R1),(R2)  ;INSERT HIGH PART OF DISK ADDRESS
	MOV	I.PRM+12(R1),-(R2)  ;INSERT LOW PART OF DISK ADDRESS
	MOV	U.BUF+2(R5),-(R2)  ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R      5),-(R2)	;INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		;CONVERT TO WORD COUNT
	NEG	(R2)		;CONVERT TO NEGATIVE WORD COUNT
	MOV	#IE.DNR&377,R0	;ASSUME DRIVE NOT READY
	BIT	#200,-(R2)	;DISK READY TO ACCEPT COMMAND?
	BNE	21$		;IF NE YES


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	23$		;IF NE YES

	.IFTF


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPERATION?
	BNE	45$		;IF NE YES

	.ENDC


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DRIVE NOT READY ERROR

      	.ENDC


	JMP	60$		;FINISH I/O
21$:				;REF LABEL

	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC
	
	
	.IF DF	E$$DVC
	
	CALL	$BMSET		;SET I/O ACTIVE BIT IN MAP
	
	.ENDC

	
	MOV	U.BUF(R5),(R2)	;LOAD FUNCTION AND GO
	
;
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;
 
DFCAN:	RETURN			;;;NOP FOR RF11

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO       THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DFPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS THE DRIVE CURRENTLY BUSY?
	BEQ	23$		;IF EQ NO
	MOVB	#2,S.STS(R4)	;WAIT A MAXIMUM OF 30 SECONDS
22$:	MOVB	#15.,S.CTM(R4)	;15 SECONDS AT A TIME
23$:	BISB	#US.SPU,U.STS(R5)  ;SET UNIT SPINNING UP

	.ENDC


	RETURN			;WAIT       FOR UNIT TO RESPOND
 
;+
; **-$DFINT-RF11 DISK CONTROLLER INTERRUPTS
;-
 
	INTSE$	DF,PR5,R$$F11	;;;SAVE REGISTERS AND SET PRIORITY
	CALL	$FORK		;;;CREATES A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF STATUS CONTROL BLOCK
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	
	
	.IF DF	D$$IAG
	
	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC FUNCTION EXECUTED?
	BNE	45$		;IF NE YES
	
	      .ENDC
	
	
	TST	(R2)		;ANY ERRORS?
	BPL	50$		;IF PL NO
	

	.IF DF	E$$DVC
	
	CALL	$DVERR		;LOG DEVICE ERROR
	
	.ENDC

	
	MOV	(R2),R1		;GET CONTENTS OF CSR
	MOV	#IE.WLK&377,R0	;ASSUME WRITE LOCK
	BIT	#2000,R1	;WRITE LOCK?
	BNE	60$		;IF NE YES
	MOV	#IE.BLK&377,R0	;ASSUME NONEXISTENT DISK
	BIT	#4000,R1	;NONEXISTENT DISK?
	BNE	60$		;IF NE YES
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR
	BIT	#40000,R1	;UNRECOVERBLE ERROR?
	BNE	60$		;IF NE YES
	BR	46$		;FINISH IN COMMON CODE
 
	
;
;       DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED
; UNLESS THE REQUEST WAS DIAGNOSTIC.  TIMEOUTS ARE USUALLY CAUSED
; BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE.
;
 
DFOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	40$		;;;IF EQ NO
	DECB	S.STS(R4)	;;;HAVE WE WAITED ENOUGH YET?
	BEQ	40$		;;;IF EQ YES
	MTPS	#0		;;;ALLOW INTERRUPTS
	JMP	20$		;RETRY ENTIRE OPERATION
40$:	INCB	S.STS(R4)	;;;LEAVE CONTROLLER       BUSY
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP

	.ENDC


	CALL	$DTOER		;;;LOG DEVICE TIMEOUT
	
	
	.IF DF	D$$IAG
	
	BCC	46$		;IF CC TIMEOUT DURING NORMAL FUNCTION
45$:	CALL	$CRPAS		;PASS CONTROLLER REGISTERS TO TASK
	BR	60$		;DIAGNOSTIC PROCESSING COMPLETE
	
	.ENDC
	
	
46$:	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?
	BNE	52$		;IF NE YES
	DECB	RTTBL(R3)	;RETRY FUNCTION?
	BLE	52$		;IF LE NO
47$:	JMP	20$		;RETRY OPERATION

50$:				;REF LA      BEL


	.IF DF	D$$WCK

	BITB	#IO.WLC&377,I.FCN(R1)  ;WRITE FOLLOWED BY WRITE CHECK?
	BNE	51$		;IF NE YES
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED BY MCR?
	BEQ	60$		;IF EQ NO
51$:	MOVB	U.BUF(R5),R1	;GET LAST FUNCTION
	BIT	#1*2,R1		;WRITE OR WRITE CHECK FUNCTION?
	BEQ	60$		;IF EQ NO
	BIS	#2*2,U.BUF(R5)	;SET WRITE CHECK FUNCTION
	BIT	#2*2,R1		;WAS LAST FUNCTION A WRITE CHECK?
	BNE	60$		;IF NE YES
	MOV	#RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT
	BR	47$		;START WRITE CHECK OPERATION

	.IFTF      

52$:				;REF LABEL

	.IFT

	BIT	#20000,(R2)	;WRITE CHECK ERROR?
	BEQ	60$		;IF EQ NO
	MOV	#IE.WCK&377,R0	;SET WRITE CHECK ERROR

	.ENDC


60$:	MOV	2(R2),R1	;GET WORDS REMAINING TO TRANSFER
	ASL	R1		;CONVERT TO BYTES LEFT TO TRANSFER
	ADD	U.CNT(R5),R1	;CALCULATE BYTES ACTUALLY TRANSFERED
	MOV	#401,(R2)	;CLEAR RF11 CONTROLLER
70$:				;REF LABEL
	

	.IF DF	E$$DVC
	
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE ST   Š   ARTING ERROR RETRY COUNT
	
	.ENDC
	
	
	CALL	$IODON		;FINISH I/O OPERATION
	JMP	DFINI		;PROCESS NEXT REQUEST
	.DSABL	LSB
 
	.END
Š          ¼ðskQ	› c,        	.TITLE	DKDRV
	.IDENT	/08.01/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 08.01
;
; D. N. CUTLER 19-OCT-73
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;
; MODIFIED BY:	
;
;	P. J. CARR	12-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
; RK11 CARTRIDGE DISK DRIVER
;
; MACRO L      IBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;

RETRY=8.			;ERROR RETRY COUNT

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;

CNTBL:	.BLKW	R$$K11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$K11		;ERROR RETRY COUNT AND DRIVE RESET FLAG


	.IF GT	R$$K11-1

TEMP:	.BLKW	1		;TEMPORY STORAGE FOR CONTROLLER NUMBER

	.ENDC


	.IF DF	D$$IAG

	.MCALL	U      MDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

;
; DIAGNOSTIC FUNCTION TABLE
;
FUNTBL:	.WORD	IO.HMS!IQ.UMD, 0515
	.WORD	IO.BLS!IQ.UMD, 0511
FUNTB0:	.WORD	IO.RDH!IQ.UMD, 2505
	.WORD	IO.WDH!IQ.UMD, 2503
	.WORD	IO.WCK!IQ.UMD, 0507
FUNTBE:

	.ENDC


;
; DRIVER DISPATCH TABLE
;

$DKTBL::.WORD	DKINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DKCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DKOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DKPWF		;POWERFAIL ENTRY POINT

;+
; **-DKINI-RK11 CA      RTRIDGE DISK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=AD      DRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
1$:	RETURN			;CONTROLLER BUSY OR NO REQUEST
DKINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	1$		;IF CS NO PACKET

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE R      EQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RK11 CARTRIDGE DISK I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.      RLB OR IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED.
;	WD. 17 -- LOGICAL BLOCK NUMB      ER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. ADRS ELSE NOT USED
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000)
;

	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB


	.IF DF	M$$EXT&M$$MGE

	CALL	$STMAP		;SET UP UNIBUS MAPPING ADDRESS

	.ENDC


	MOV	#RETRY&377,RTTBL(R3)  ;CLEAR POSITIONING & SET RETRIES


	.IF DF	D$$IAG

	CMPB	#IO.HMS/^D<256>,I.FCN+1(R1)  ;DIAGNOSTIC FUNCTION?
	BNE	5$		;IF NE NO
	MOV	#FUNTBL,R0	;GET ADDRESS OF FUNCTION TABLE
2$:	CMP	(R0)      +,I.FCN(R1)	;FUNCTION CODE MATCH?
	BEQ	3$		;IF EQ YES
	TST	(R0)+		;BYPASS CONTROLLER CODE
	CMP	#FUNTBE,R0	;END OF FUNCTION TABLE?
	BEQ	5$		;IF EQ YES
	BR	2$		;TRY AGAIN
3$:	CMP	R0,#FUNTB0	;POSITIONING FUNCTION?
	BHI	4$		;IF HI NO
	INCB	RTTBL+1(R3)	;YES, INDICATE POSITIONING OPERATION
4$:	BIS	(R0),U.BUF(R5)	;SET CONTROLLER FUNCTION BITS
	BR	10$		;GO CHECK BLOCK NUMBER

	.ENDC


5$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION
	BIS	#505,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/256      .,I.FCN+1(R1) ;READ LOGICAL FUNCTION?
	BHIS	6$		;IF HIS FUNCTION IS LEGAL
	JMP	120$		;FUNCTION IS ILLEGAL
6$:	BEQ	10$		;IF EQ FUNCTION IS READ
	SUB	#2,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION
10$:	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER
	MOV	#12.,R1		;SET DIVISOR
	CALL	$DIV		;CALCULATE SECTOR NUMBER
	ASR	R0		;WHICH SURFACE?
	BCC	20$		;IF CC SURFACE 0
	BIS	#20,R1		;SET SURFACE 1 BIT
20$:	SWAB	R0		;SWAP CYLINDER TO HIGH BYTE
	MOVB	U.UNIT(R5),R2	;RETRIEVE DRIVE NUMBER
	ASR	R2		;COLLECT DRIVE       NUMBER AND CYLINDER
	ROR	R0		;
	ASR	R2		;
	ROR	R0		;
	ASR	R2		;
	ROR	R0		;
	BIS	R1,R0		;MERGE SURFACE AND SECTOR
	MOV	R0,I.PRM+10(R3) ;SAVE DISK ADDRESS

;
; INITIATE I/O OPERATION
;

30$:				;REF LABEL


	.IF DF	M$$EXT&M$$MGE

	CALL	$MPUBM		;MAP UNIBUS TO TRANSFER

	.ENDC


	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;RETRIEVE ADDRESS OF I/O REQUEST PACKET
	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	ADD	#6,R2		;POINT TO DISK ADDRESS REGISTER
	MOV	I.PR      M+10(R1),(R2)  ;INSERT DISK ADDRESS
	MOV	U.BUF+2(R5),-(R2)  ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	;INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		;CONVERT TO WORD COUNT
	NEG	(R2)		;MAKE NEGATIVE WORD COUNT
	TST	-(R2)		;POINT BACK TO CSR
	MOV	#IE.DNR&377,R0	;ASSUME DRIVE NOT READY
	TSTB	-4(R2)		;IS DRIVE READY?
	BMI	31$		;IF MI YES


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	35$		;IF NE YES

	.IFTF


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPE      RATION?
	BNE	51$		;IF NE YES

	.ENDC


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DRIVE NOT READY ERROR

	.ENDC


	JMP	110$		;FINISH UP
31$:				;REF LABEL

	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC


	.IF DF	E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE BIT IN MAP

	.ENDC


	MOV	U.BUF(R5),(R2)	;SET FUNCTION AND GO

;
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;

DKCAN:	RETURN			;;;NOP FOR RK11

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT F      ACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DKPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS THE DRIVE CURRENTLY BUSY?
	BEQ	36$		;IF EQ NO
35$:	MOVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC029
36$:	BISB	#US.      SPU,U.STS(R5)  ;SET UNIT SPINNING UP		;**-2

	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND

;+
; **-$DKINT-RK11 DISK CONTROLLER INTERUPTS
;-

	INTSE$	DK,PR5,R$$K11	;;;SAVE REGISTERS AND SET PRIORITY
	TSTB	RTTBL+1(R4)	;;;DRIVE RESET IN PROGRESS?
	BEQ	50$		;;;IF EQ NO
	MOV	R4,-(SP)	;;;SAVE CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOV	@S.CSR(R4),R4	;;;GET CONTENTS OF CSR
	BMI	40$		;;;IF MI DRIVE RESET ERROR
	BIT	#20000,R4	;;;DRIVE RESET COMPLETE?
	BNE	40$		;;;IF NE YES
	TST	      (SP)+		;;;CLEAN STACK
	RETURN			;;;
40$:	MOV	(SP)+,R4	;;;RESTORE CONTROLLER INDEX
50$:	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC FUNCTION EXECUTED?
51$:	BNE	130$		;IF NE YES

	.ENDC


	TST	(R2)		;ANY ERRORS?
	BPL	65$		;IF PL NO


	.IF D      F	E$$DVC

	CALL	$DVERR		;LOG DEVICE ERROR

	.ENDC


	MOV	-2(R2),R1	;SAVE ERROR STATUS REGISTER
53$:	MOV	S.PKT(R4),R0	;GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R0)	;INHIBIT RETRIES
	BNE	80$		;IF NE YES
	DECB	RTTBL(R3)	;ANY MORE RETRIES?
	BLE	80$		;IF LE NO
	MOV	#1,(R2)		;CLEAR CONTROLLER
	CLRB	RTTBL+1(R3)	;CLEAR POSSIBLE DRIVE RESET IN PROGRESS
55$:	BIT	#110000,R1	;DRIVE RESET REQUIRED?
	BEQ	70$		;IF EQ NO
60$:	MOVB	#1,RTTBL+1(R3)	;SET DRIVE RESET IN PROGRESS
	MOVB	S.ITM(R4),S.CTM(R4) ;RESE      T TIMEOUT COUNT
	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET
	MOV	I.PRM+10(R1),6(R2) ;SET PROPER DRIVE NUMBER
	MOV	#515,(R2)	;RESET DRIVE
	RETURN			;
65$:	ASRB	RTTBL+1(R3)	;DRIVE RESET IN PROGRESS?
	BCC	75$		;IF CC NO
70$:	JMP	30$		;RETRY FUNCTION
75$:				;REF LABEL


	.IF DF	D$$WCK

	BITB	#IO.WLC&377,I.FCN(R1)  ;WRITE WITH WRITE CHECK?
	BNE	76$		;IF NE YES
	BITB	#US.WCK,U.STS(R5) ;WRITE CHECK ENABLED?
	BEQ	110$		;IF EQ NO
76$:	MOV	U.BUF(R5),R1	;GET CURRENT FUNCTION CODE
	BIT	#1*2,R1		;WRI      TE OR WRITE CHECK FUNCTION?
	BEQ	110$		;IF EQ NO
	BIS	#2*2,U.BUF(R5)	;SET WRITE CHECK FUNCTION
	BIT	#2*2,R1		;WAS FUNCTION A WRITE CHECK?
	BNE	110$		;IF NE YES
	MOV	#RETRY&377,RTTBL(R3)  ;REINITIALIZE RETRY COUNT
	BR	70$		;START WRITE CHECK OPERATION

	.IFF

	BR	110$		;FINISH OPERATION

	.ENDC


80$:	MOV	#IE.WLK&377,R0	;ASSUME WRITE LOCK ERROR
	BIT	#20000,R1	;WRITE LOCK ERROR?
	BNE	110$		;IF NE YES


	.IF DF	D$$WCK

	MOV	#IE.WCK&377,R0	;ASSUME WRITE CHECK ERROR
	ASR	R1		;GOOD ASSUMPTI      ON?
	BCS	110$		;IF CS WRITE CHECK ERROR

	.ENDC


	MOV	#IE.VER&377,R0	;SET UNRECOVERABLE ERROR
110$:	MOV	2(R2),R1	;GET WORDS LEFT TO TRANSFER
	ASL	R1		;CONVERT TO BYTES LEFT TO TRANSFER
	ADD	U.CNT(R5),R1	;CALCULATE BYTES ACTUALLY TRANSFERED
	MOV	#1,(R2)		;CLEAR CONTROLLER
120$:				;REF LABEL


	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE STARTING RETRY COUNT

	.ENDC


	CALL	$IODON		;FINISH I/O       OPERATION
	JMP	DKINI		;PROCESS NEXT REQUEST

;
; DEVICE TIMEOUT RESULTS IN A CONTROL AND DRIVE RESET FOLLOWED BY THE
; I/O OPERATION BEING REPEATED UNLESS THE OPERATION WAS DIAGNOSTIC.
; TIMEOUTS ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE
; RESULT OF A HARDWARE FAILURE.
;

DKOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	125$		;;;IF EQ NO
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#12.,S.STS(R4)	;;;HAVE WE WAITED       44 SECONDS YET?	; PJC029
	BEQ	125$		;;;IF EQ YES				;**-1
	MTPS	#0		;;;ALLOW INTERRUPTS
	JMP	30$		;RETRY OPERATION
125$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC029
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP		;**-1

	.ENDC


	CALL	$DTOER		;;;LOG DEVICE TIMEOUT


	.IF DF	D$$IAG

	BCC	140$		;IF CC TIMEOUT DURING NORMAL FUNCTION
130$:	CALL	$CRPAS		;PASS CONTROLLER REGISTERS TO TASK
	BR	110$		;DIAGNOSTIC PROCESSING COMPLETE
140$:				;REF LABEL

	.ENDC


	MOV	#110000,R1	;   8   SET FOR DRIVE RESET
	BR	53$		;
	.DSABL	LSB

	.END
 8          6d¸8kQ	› c,        	.TITLE PANIC
	.IDENT	/05.07/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 05.07
;
; D. N. CUTLER 4-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	J. M. GILBERT
;	D. N. CUTLER
;	K. E. KINNEAR
;	P. J. BEZEREDI
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	D. R. DONCHIN	09-OCT-80
;		DD080 -- ADD ^S/^Q SUPPORT TO CRASH AND P      ANIC
;
;
; PANIC DUMP ROUTINE
;


	.IF DF	P$$NIC

;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS

;
; LOCAL DATA
;


	.IF NDF	C$$RSH

$CRPBF::.BLKW	18.		;PANIC'S REGISTER BUFFER AND STACK
$CRPST::			;TOP OF PANIC'S TEMPORARY STACK

	.ENDC


	.ENDC


;+
; **-$PANIC-PANIC DUMP
;
; THIS ROUTINE IS ENTERED WHEN THE SYSTEM CRASHES OR BY FORCING AN
; ENTRY VIA THE CONSOLE SWITCHES. ON ENTRY THE PROCESSOR STATUS AND
; REGISTERS ARE SAVED IN A TEM      PORARY STORAGE AREA. PANIC THEN HALTS
; AWAITING A SET OF DUMP LIMITS TO BE ENTERED IN THE SWITCH REGISTER.
; THE FOLLOWING PROCEDURE IS USED TO OBTAIN A DUMP:
;
;	1-WITH THE PROCESSOR HALTED ENTER THE LOW DUMP LIMIT IN THE
;		SWITCH REGISTER.
;	2-DEPRESS CONTINUE. THE PROCESSOR WILL AGAIN HALT.
;	3-WITH THE PROCESSOR HALTED ENTER THE HIGH DUMP LIMIT IN THE
;		SWITCH REGISTER.
;	4-DEPRESS CONTINUE. THE DUMP WILL BE OUTPUT ON THE DEVICE
;		'P$$NIC'.
;
; THE FIRST LINE OF OUTPUT IS THE DUMP OF PS,      R0,R1,R2,R3,R4,R5, AND SP.
; SUCCEEDING LINES OF OUTPUT ARE THE ACTUAL DUMP. WHEN THE DUMP IS
; FINISHED, PANIC AGAIN HALTS AWAITING A NEW SET OF DUMP LIMITS TO
; BE INPUT.
;-

	.ENABL	LSB
$PANIC::			;PANIC DUMP ROUTINE


	.IF NDF	P$$NIC

	JMP	$BTSTP		;RE-BOOT SYSTEM IF NO PANIC DUMP

	.IFF



	.IF DF	M$$MGE

	MOV	PS,$CRPBF	;SAVE PS WORD

	.IFF

	MFPS	$CRPBF		;SAVE PS WORD

	.ENDC


	MTPS	#PR7		;LOCK OUT INTERRUPTS
	MOV	R0,$CRPBF+2	;;;SAVE RR0
	MOV	#$CRPBF+4,R0	;;;POINT TO SAV      E AREA
	MOV	R1,(R0)+	;SAVE REGISTER R1 TO SP
	MOV	R2,(R0)+	;
	MOV	R3,(R0)+	;
	MOV	R4,(R0)+	;
	MOV	R5,(R0)+	;
	MOV	SP,(R0)		;
10$:	HALT			;GET LOWER DUMP LIMIT
	MOV	#$CRPST,SP	;SET NEW STACK POINTER


	.IF NDF	S$$WRG

	MOV	@#0,-(SP)	;

	.IFF

	MOV	SWR,-(SP)	;

	.IFTF

	HALT			;GET ENDING DUMP LIMIT
	MOV	#$CRPBF,R0	;ALWAYS DUMP REGISTERS FIRST
	MOV	#$CRPBF+16,R1	;
	CALL	$PDMP		;DUMP REGISTERS

	.IFT

	MOV	@#0,R1		;GET LAST WORD ADDRESS

	.IFF

	MOV	SWR,R1		;GET LAST WORD ADDRES      S

	.ENDC


	MOV	(SP)+,R0	;AND FIRST WORD ADDRESS
	BIC	#1,R0		;MAKE SURE START IS EVEN
	CALL	20$		;DUMP MEMORY
	BR	10$		;GO AGAIN

;
; DUMP SELECTED BLOCK OF MEMORY
;

$PDMP::	MOV	#P$$NIC,R5	;SET OUTPUT DEVICE CSR
	MOV	#14,R2		;OUTPUT A FORM FEED
	CALL	$OUT		;
20$:	MOV	R0,-(SP)	;SAVE FOR RELATIVE ADDRESS
30$:	MOV	R0,-(SP)	;SAVE START OF LINE ADDRESS
	MOV	R0,R2		;SAVE CURRENT LINE
40$:	MOV	#8.,R4		;COUNT FOR 1 LINE
50$:	CMP	(R0)+,@(SP)	;ARE WORDS EQUAL?
	BNE	60$		;IF NOT, PRINT LINE
	D      EC	R4		;COUNT THROUGH LINE
	BGT	50$		;IF GT, NOT THROUGH YET
	MOV	R0,R2		;UPDATE LINE STARTING ADDRESS
	CMP	R0,R1		;AT END OF DUMP?
	BLOS	40$		;IF NOT, CHECK NEXT LINE
60$:	CMP	R2,(SP)		;ANY LINES SUPPRESSED?
	BEQ	70$		;NO, IF STARTING ADDRESS SAME
	MOV	(SP),R3		;EDIT OUT OLD STARTING ADDRESS
	MOV	@(SP),R0	;GET MASTER WORD
	MOV	R2,(SP)		;NOW HAVE NEW STARTING ADDRESS
	CALL	$EDIT		;WORD EDIT
	MOV	#'-,R2		;SEPARATE ADDRESSES WITH MINUS
	CALL	$OUT		;OUTPUT MINUS
	CALL	$OUTB		;AND NOW A BLANK
	MOV      	(SP),R3		;NOW OUTPUT LAST SUPPRESSED WORD ADDRESS
	TST	-(R3)		;2 LESS THAN NEW START OF LINE
	CALL	$EDIT		;OUTPUT LAST WORD OF IDENTICAL BLOCK
	CALL	$OUTB		;ISSUE ANOTHER BLANK
	MOV	R0,R3		;NOW GET REPEATED WORD
	CALL	$EDIT		;OUTPUT REPEATED WORD
	CALL	$CRLF		;ISSUE CARRIAGE RETURN/LINE FEED
	CALL	$OUT		;OUTPUT ANOTHER LINE FEED
	MOV	(SP)+,R0	;PUT START OF LINE IN R0
	CMP	R0,R1		;AT END OF DUMP?
	BHI	110$		;IF HI, AT END
	MOV	R0,-(SP)	;GET BACK IN SYNC WITH NEXT ROUTINE
70$:	MOV	(SP),R0		;RECAP      TURE NEW START OF LINE
	CALL	WORD		;EDIT WORDS
	MOV	(SP),R0		;RETRIEVE STARTING ADDRESS
	CALL	BYTE		;EDIT BYTES
	MOV	(SP)+,R0	;RETRIEVE STARTING ADDRESS
	MOV	#5,R4		;SET LOOP COUNT
80$:	CALL	$OUTB		;OUTPUT A BLANK
	DEC	R4		;ANY MORE?
	BGT	80$		;IF GT YES
	MOV	#8.,R4		;SET REPEAT COUNT
90$:	MOV	(R0)+,R3	;GET NEXT WORD
	CALL	120$		;OUTPUT LOW BYTE
	SWAB	R3		;SWAP BYTES
	CALL	120$		;OUTPUT HIGH BYTE
	DEC	R4		;ANY MORE THIS LINE?
	BGT	90$		;IF GT YES
100$:	CALL	$CRLF		;OUTPUT A CR-LF
	CALL	$OUT      		;OUTPUT ANOTHER LF
	CMP	R0,R1		;END OF EDIT YET?
	BLOS	30$		;IF NOT, GO AGAIN
110$:	TST	(SP)+		;REMOVE START FOR RELATIVE ADDRESS
	CALL	$OUT		;OUTPUT 2 MORE LINE FEEDS
	BR	$OUT		;AND DON'T RETURN HERE
120$:	CALL	$OUTB		;OUTPUT TWO BLANKS
	CALL	$OUTB		;
	BICB	#200,R3		;CLEAR PARITY BIT
	CMPB	R2,R3		;CONTROL CHARACTER?
	BLOS	130$		;IF LOS NO
	BISB	#100,R3		;CONVERT TO CHARACTER
	MOVB	#136,R2		;SET TO OUTPUT CARET
130$:	CALL	$OUT		;OUTPUT BLANK OR CARET
	MOVB	R3,R2		;SET BYTE TO OUTPUT
	INCB	R      3		;CHARACTER A RUBOUT?
	BMI	$OUTB		;IF MI YES OUTPUT A BLANK
	BR	$OUT		;OUTPUT CHARACTER
	.DSABL	LSB

;
; WORD EDIT
;

WORD:	MOV	R0,R3		;EDIT LINE ADDRESS
	MOV	#9.,R4		;SET LOOP COUNT
	BR	20$		;
10$:	MOV	(R0)+,R3	;GET NEXT WORD
20$:	CALL	$EDIT		;EDIT WORD
	CALL	$OUTB		;OUTPUT ANOTHER BLANK
	DEC	R4		;ANY MORE THIS LINE?
	BGT	10$		;IF GT YES
	BR	$CRLF		;

;
; BYTE EDIT
;

BYTE:	MOV	R0,R3		;COPY ADDRESS OF LINE
	SUB	4(SP),R3	;CALCULATE BLOCK OFFSET
	CALL	$EDIT		;EDIT OFFSET FROM START       OF BLOCK
	MOV	#8.,R4		;SET LOOP COUNT
10$:	MOV	(R0)+,R3	;GET NEXT WORD
	CALL	EBYT		;EDIT HIGH BYTE
	CALL	EBYT		;EDIT LOW BYTE
	DEC	R4		;ANY MORE THIS LINE?
	BGT	10$		;IF GT YES

	.ENDC


	.IF DF	C$$TTY!P$$NIC


;
; SUBROUTINE TO OUTPUT CR-LF
;

$CRLF::	MOVB	#15,R2		;OUTPUT CR
	CALL	$OUT		;
	MOVB	#12,R2		;OUTPUT A LF
	BR	$OUT		;

;
; SUBROUTINE TO EDIT ONE BYTE
;

EBYT:	CLR	R2		;CLEAR CHARACTER ACCUMULATOR
	MOV	#3,-(SP)	;SET CHARACTER COUNT
	BR	EDT2		;COLLECT HIGH ORDER 2 BITS
      
;
; SUBROUTINE TO EDIT ONE WORD
;

$EDIT::	CLR	R2		;CLEAR CHARACTER ACCUMULATOR
	MOV	#6,-(SP)	;SET CHARACTER COUNT
	BR	EDT3		;COLLECT HIGH ORDER BIT
EDT1:	CLR	R2		;COLLECT NEXT 3 BITS
	ASL	R3		;
	ROL	R2		;
EDT2:	ASL	R3		;
	ROL	R2		;
EDT3:	ASL	R3		;
	ROL	R2		;
	ADD	#'0,R2		;ADD DIGIT BIAS
	CALL	$OUT		;OUTPUT CHARACTER
	DEC	(SP)		;ANY MORE?
	BGT	EDT1		;IF GT YES
	TST	(SP)+		;CLEAR STACK

;
; OUTPUT SUBROUTINES
;

$OUTB::	MOVB	#40,R2		;SET TO OUTPUT BLANK

	.ENDC


	.IF DF	C$$RSH      !P$$NIC

$OUT::	CMP	#177564,R5	;OUTPUT DEVICE A TERMINAL?		; DD080
	BNE	6$		;IF NE NO				; DD080
	TSTB	-4(R5)		;WAS A CHARACTER ENTERED FROM TERMINAL?	; DD080
	BPL	6$		;IF PL NO				; DD080
	MOVB	-2(R5),-(SP)	;GET CHARACTER				; DD080
	BICB	#200,(SP)	;CLEAR POSSIBLE PARITY BIT		; DD080
	CMPB	(SP)+,#23	;IS CHARACTER A CONTROL-S?		; DD080
	BNE	6$		;IF NE NO, IGNORE IT			; DD080
4$:	TSTB	-4(R5)		;WAIT FOR NEXT CHARACTER TO BE INPUT	; DD080
	BPL	4$		;IF PL NOT YET				; DD080
	MOVB	-2(R5),-(SP)	;GET C      HARACTER				; DD080
	BICB	#200,(SP)	;CLEAR POSSIBLE PARITY BIT		; DD080
	CMPB	(SP)+,#21	;IS CHARACTER A CONTROL-Q?		; DD080
	BNE	4$		;IF NE NO, IGNORE IT			; DD080
6$:	TSTB	(R5)		;OUTPUT DEVICE READY?			; DD080
	BPL	$OUT		;IF PL NO				;**-1
	MOVB	R2,2(R5)	;OUTPUT CHARACTER
	CMPB	#15,R2		;CARRIAGE RETURN?
	BNE	20$		;IF NE NO
	CMP	#177514,R5	;OUTPUT DEVICE LINE PRINTER?
	BEQ	20$		;IF EQ YES
	CLR	R2		;SET ZERO FILL CHARACTER
	MOV	#5,-(SP)	;SET FILL COUNT
10$:	CALL	$OUT		;OUTPUT A FILL CHARACTER
	   t   DEC	(SP)		;ANY MORE TO FILL?
	BGT	10$		;IF GT YES
	TST	(SP)+		;CLEAN STACK
20$:	RETURN			;

	.ENDC


	.END
t          „ðskQ	› c,        	.TITLE	DPDRV
	.IDENT	/07.01/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 07.01
;
; D. N. CUTLER 9-FEB-74
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;
; MODIFIED BY:
; 
;	P. J. CARR	12-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
; RP11-C/E DISK PACK CONTRO      LLER DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;

RETRY=8.			;ERROR RETRY COUNT

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;

CNTBL:	.BLKW	R$$P11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$P11		;ERROR RETRY COUNT AND POSITIONING FLAG


	.IF GT	R$$P11-1

TEMP:	.BLKW	1		;TEMPORY STORAGE FOR CONTROLLER NUMBER

	.ENDC


	.      IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

;
; DIAGNOSTIC FUNCTION CODE TABLE
;
FUNTBL:	.WORD	IO.HMS!IQ.UMD, 20015
	.WORD	IO.BLS!IQ.UMD, 20011
	.WORD	IO.RDH!IQ.UMD, 14105
	.WORD	IO.WDH!IQ.UMD, 14103
	.WORD	IO.WCK!IQ.UMD, 00107
FUNTBE:

	.ENDC


;
; DRIVER DISPATCH TABLE
;

$DPTBL::.WORD	DPINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DPCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DPOUT		;DEVICE TIMEOUT
	.WORD	DPPWF		;POWERFAIL ENTRY POINT

;+
;       **-DPINI-RP11-C/E DISK PACK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPU      TS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
1$:	RETURN			;CONTROLLER BUSY OR NO REQUEST
DPINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	1$		;IF CS NO PACKET

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT       NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R3=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RP11-C/E DISK PACK CONTROLLER I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05       -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED.
;	WD      . 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. ADRS ELSE NOT USED
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000)
;

	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB


	.IF DF	M$$EXT&M$$MGE

	CALL	$STMAP		;SET UP UNIBUS MAPPING ADDRESS

	.ENDC


	MOVB	R2,U.BUF+1(R5)	;INSERT DRIVE NUMBER


	.IF DF	D$$IAG

	CMPB	#IO.HMS/^D<256>,I.FCN+1(R1)  ;DIAGNOSTIC FUNCTION?
	BNE	5$		;IF NE NO
	MOV	#FUNTBL,R0	;GET ADDRESS OF FUNCTION TABLE
3$:	      CMP	(R0)+,I.FCN(R1)	;FUNCTION CODE MATCH?
	BEQ	4$		;IF EQ YES
	TST	(R0)+		;BYPASS CONTROLLER CODE
	CMP	#FUNTBE,R0	;END OF FUNCTION TABLE?
	BEQ	5$		;IF EQ YES
	BR	3$		;TRY AGAIN
4$:	BIS	(R0),U.BUF(R5)	;SET CONTROLLER FUNCTION BITS
	BR	10$		;GO CHECK LOGICAL BLOCK NUMBER

	.ENDC


5$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION
	BIS	#105,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION?
	BHIS	6$		;IF HIS FUNCTION IS LEGAL
	JMP	100$		;FUNCTION IS ILL      EGAL
6$:	BEQ	10$		;IF EQ FUNCTION WAS READ
	SUB	#2,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION
10$:	MOV	#RETRY&377,RTTBL(R3) ;CLEAR HOME SEEK FLAG AND SET RETRY COUNT
	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER
	ASR	R2		;DIVIDE LOGICAL BLOCK NUMBER BY 2
	ROR	R0		;
	ROL	R2		;SAVE 1 BIT REMAINDER
	MOV	#100.,R1	;SET CYLINDER DIVISOR
	CALL	$DIV		;CALCULATE CYLINDER NUMBER
	MOV	R0,I.PRM+10(R3)	;SAVE CYLINDER NUMBER
	ASL	R1		;MULTIPLY REMAINDER BY 2
	BIS	R2,R1		;MERGE PREVIOUS 1 BIT REMAINDER
	MOV	R1,      R0		;SET DIVIDEND
	MOV	#10.,R1		;SET TRACK DIVISOR
	CALL	$DIV		;CALCULATE TRACK AND SECTOR
	SWAB	R0		;SWAP TRACK NUMBER TO LEFT BYTE
	BIS	R1,R0		;MERGE SECTOR NUMBER
	MOV	R0,I.PRM+12(R3)	;SAVE TRACK AND SECTOR ADDRESS

;
; INITIATE I/O OPERATION
;

30$:				;REF LABEL


	.IF DF	M$$EXT&M$$MGE

	CALL	$MPUBM		;MAP UNIBUS TO TRANSFER

	.ENDC


	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;RETRIEVE ADDRESS OF I/O REQUEST PACKET
	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOU      T COUNT
	CALL	200$		;ABORT CONTROLLER AND SELECT UNIT
	ADD	#10,R2		;POINT TO DISK ADDRESS REGISTER
	MOV	I.PRM+12(R1),(R2)  ;INSERT TRACK AND SECTOR ADDRESS
	MOV	I.PRM+10(R1),-(R2)  ;INSERT CYLINDER ADDRESS
	MOV	U.BUF+2(R5),-(R2)  ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	;INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		;CONVERT TO WORD COUNT
	NEG	(R2)		;MAKE NEGATIVE WORD COUNT
	TST	-(R2)		;POINT BACK TO CSR
	MOV	#IE.DNR&377,R0	;ASSUME DRIVE NOT READY
	MOV	-4(R2),-(SP)	;GET CONTENTS OF DRIVE STAT      US REGISTER
	COM	(SP)		;COMPLEMENT STATUS
	BIT	#140000,(SP)+	;DRIVE READY AND ON-LINE?
	BEQ	31$		;IF EQ YES


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	35$		;IF NE YES

	.IFTF


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPERATION?
	BNE	39$		;IF NE YES

	.ENDC


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DRIVE NOT READY ERROR

	.ENDC


	JMP	90$		;FINISH I/O
31$:				;REF LABEL

	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC
      

	.IF DF	D$$IAG

	CMPB	#IO.RDH!IQ.UMD&377,I.FCN(R1)  ;READ HEADER FUNCTION?
	BEQ	33$		;IF EQ YES
	CMPB	#IO.WDH!IQ.UMD&377,I.FCN(R1)  ;WRITE HEADER FUNCTION?
	BNE	34$		;IF NE NO
33$:	BIT	#360,10(R2)	;SYNCHRONIZE THE SECTOR COUNTER ...
	BNE	33$		;... ON THE NEXT INDEX PULSE IN CASE ...
	BIT	#360,10(R2)	;... A UNIT OTHER THAN 0 WAS ...
	BNE	33$		;... SELECTED FOR HEADER OPERATIONS.
34$:				;REF LABEL

	.ENDC


	.IF DF	E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE BIT IN MAP

	.ENDC


	MOVB	U.BU      F(R5),(R2)	;LOAD FUNCTION AND GO

;
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;

DPCAN:	RETURN			;;;NOP FOR RP11

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DPPWF:				;P      OWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS DRIVE CURRENTLY BUSY?
	BEQ	36$		;IF EQ NO
35$:	MOVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC029
36$:	BISB	#US.SPU,U.STS(R5)  ;SET UNIT SPINNING UP		;**-2

	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND

;+
; **-$DPINT-RP11-C/E DISK PACK CONTROLLER INTERRUPTS
;-

	INTSE$	DP,PR5,R$$P11	;;;SAVE REGISTERS AND SET PRIORITY
	MOV	U.SCB(R5),R4	;;;GET ADDRESS OF SCB
	MOV	S.CSR(R4),R4	;;;GET ADDRESS OF CSR
	BIC	#20100,(R4)	;;;CL      EAR INTERRUPT ENABLE
	MOVB	#377,-4(R4)	;;;CLEAR ATTENTION SUMMARY BITS ON
	CLRB	-4(R4)		;;;BOTH OLD AND ECO'D CONTROLLERS
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R2		;COPY ADDRESS OF CSR
	MOV	U.SCB(R5),R4	;RETRIEVE ADDRESS OF SCB
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC FUNCTION EXECUTED?
39$:	BNE	105$		;IF NE YES

	.ENDC


	ASRB	RTT      BL+1(R3)	;HOME SEEK IN PROGRESS?
	BCS	59$		;IF CS YES
	TST	(R2)		;ANY ERRORS?
	BPL	50$		;IF PL NO


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DEVICE ERROR

	.ENDC


40$:	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?
	BNE	60$		;IF NE YES
	DECB	RTTBL(R3)	;ANY MORE RETRIES?
	BLE	60$		;IF LE NO
	BIT	#1371,-2(R2)	;RECOVERABLE ERROR?
	BEQ	60$		;IF EQ NO
	BIT	#14000,-4(R2)	;SKI OR HNF ERRORS?
	BEQ	46$		;IF EQ NO
45$:	MOVB	#1,RTTBL+1(R3)	;SET HOME SEEK IN PROGRESS FLAG
	MOVB	S.ITM(R4),S.CTM(R4) ;RESET DEVIC      E TIMEOUT COUNT
	CALL	200$		;ABORT CONTROLLER AND SELECT UNIT
	BIS	#20015,(R2)	;INITIATE HOME SEEK FUNCTION
	RETURN			;
46$:	JMP	30$		;RETRY ENTIRE OPERATION
50$:				;REF LABEL


	.IF DF	D$$WCK

	BITB	#IO.WLC&377,I.FCN(R1)  ;WRITE FOLLOWED BY WRITE CHECK?
	BNE	51$		;IF NE YES
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED BY MCR?
	BEQ	90$		;IF EQ NO
51$:	MOVB	U.BUF(R5),R1	;GET LAST FUNCTION
	BIT	#1*2,R1		;WRITE OR WRITE CHECK FUNCTION?
	BEQ	90$		;IF EQ NO
	BIS	#2*2,U.BUF(R5)	;SET WRITE CHECK       FUNCTION
	BIT	#2*2,R1		;WAS LAST FUNCTION A WRITE CHECK?
	BNE	90$		;IF NE YES
	MOV	#RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT
	BR	46$		;START WRITE CHECK OPERATION

	.IFF

	BR	90$		;FINISH OPERATION

	.ENDC


59$:	TST	(R2)		;HOME SEEK SUCCESSFUL?
	BPL	46$		;IF PL YES
60$:	MOV	#IE.WLK&377,R0	;ASSUME DRIVE WRITE LOCKED
	MOV	-2(R2),R1	;GET CONTENTS OF ERROR REGISTER
	BMI	90$		;IF MI WRITE LOCK ERROR


	.IF DF	D$$WCK

	MOV	#IE.WCK&377,R0	;ASSUME WRITE CHECK ERROR
	BIT	#10,R1		;WRITE CHECK       ERROR?
	BNE	90$		;IF NE YES

	.ENDC


	MOV	#IE.VER&377,R0	;UNRECOVERABLE ERROR
90$:	MOV	2(R2),R1	;GET WORDS REMAINING TO TRANSFER
	ASL	R1		;CONVERT TO BYTES LEFT TO TRANSFER
	ADD	U.CNT(R5),R1	;CALCULATE BYTES ACTUALLY TRANSFERED
	CALL	200$		;ABORT THE CONTROLLER
100$:				;REF LABEL


	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE STARTING RETRY COUNT

	.ENDC


	CALL	$IODON		;FINISH I/O OPERATION      
	JMP	DPINI		;PROCESS NEXT REQUEST

;
; DEVICE TIMEOUT RESULTS IN A HOME SEEK FOLLOWED BY THE I/O OPERATION
; BEING REPEATED UNLESS THE OPERATION WAS DIAGNOSTIC.  TIMEOUTS ARE
; USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A
; HARDWARE FAILURE.
;

DPOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	104$		;;;IF EQ NO
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#20.,S.STS(R4)	;;;HAVE WE WAITED 76 SECONDS YET?	; PJC0      29
	BEQ	104$		;;;IF EQ YES				;**-1
	MTPS	#0		;;;ALLOW INTERRUPTS
	BR	46$		;RETRY ENTIRE OPERATION
104$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC029
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP		;**-1

	.ENDC


	CALL	$DTOER		;;;LOG DEVICE TIMEOUT


	.IF DF	D$$IAG

	BCC	110$		;IF CC TIMEOUT DURING NORMAL FUNCTION
105$:	CALL	$CRPAS		;PASS CONTROLLER REGISTERS TO TASK
	BR	90$		;DIAGNOSTIC PROCESSING COMPLETE
110$:				;REF LABEL

	.ENDC


	MOVB	U.UNIT(R5),1(R2) ;SET CURREN      T UNIT NUMBER
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?
	BNE	90$		;IF NE YES
	DECB	RTTBL(R3)	;ANY RETRIES LEFT?
	BLE	90$		;IF LE NO
	BR	45$		;

;+
; THIS ROUTINE WILL ABORT THE CONTROLLER AND SELECT THE CURRENT
; UNIT.  A DELAY IS INITIATED BETWEEN EACH CONTROLLER ABORT TO
; ALLOW THE HARDWARE TIME TO SETTLE DOWN ON FAST PROCESSORS.
;-

200$:	MOV	#1,(R2)		;ABORT THE CONTROLLER
	BICB	-(SP),(SP)+	;DELAY TO ALLOW THE HARDWARE ...
	BICB	-(SP),(SP)+	;... TI   ø   ME TO SETTLE DOWN
	MOV	#1,(R2)		;CLEAR ANY ERRORS CAUSED BY THE ABORT
	BICB	-(SP),(SP)+	;DELAY TO ALLOW THE HARDWARE ...
	BICB	-(SP),(SP)+	;... TIME TO SETTLE DOWN
	MOVB	U.BUF+1(R5),1(R2)  ;SELECT THE UNIT
	RETURN			;

	.DSABL	LSB

	.END
ø          ÑØkQ	› c,        	.TITLE	DRABO
	.IDENT	/04.02/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 04.02
;
; D. N. CUTLER 11-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	6-OCT-80
;		MSH121 -- ADD SUPPORT FOR REQUESTED EXIT ASTS
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$
	ABODF$			;DEFIN      E TASK ABORT CODES

;+
; **-$DRABO-ABORT TASK
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO TERMINATE THE EXECUTION OF A
; SPECIFIED TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(83.),DPB SIZE(3.).
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TASK TO TERMINATE.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO TERMINATE.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.      
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS7' IS RETURNED IF THE SPECIFIED
;			TASK IS NOT ACTIVE.
;-

$DRABO::TST	(R1)+		;SPECIFIED TASK ACTIVE? (T.STAT)	;MSH121
	BMI	10$		;IF MI NO				;**-1
	TSTB	(R1)		;TASK ALREADY BEING TERMINATED? (T2.HLT)      ;MSH121
	BMI	10$		;IF MI YES				;**-1
									;MSH121
	.IF DF	A$$TRP&A$$BRT						;MSH121
									;MSH121
	CLR	R2		;INIT SUB-CODE (AB.TYP!AB.NPV=0)	;MSH121
	BIT	#T3.PRV,T.ST3(R5) ;ISSUING TASK PRIVILEGED?		;MSH121
	BNE	5$		;IF NE YES, R2 OK			;MSH121
	INC	R2		;NONPRIVILEGED TASK'S DIRECTIVE (AB.NPV);MSH121
									;MSH121
	.ENDC								;MSH121
									;MSH121
5$:	MOV	R0,R1		;SET TCB ADDRESS OF TASK TO ABORT	;MSH121
	MOV	#S.CABO,R0	;SET REASON FOR ABORT			;**-1
	CALLR	$ABTSK		;ABORT TASK
10   0   $:	DRSTS	D.RS7		;SET DIRECTIVE STATUS

	.END
0          ÑÀ€kQ	› c,        	.TITLE	DRATX
	.IDENT	/07.04/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 07.04
;
; D. N. CUTLER 31-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	9-OCT-79
;		MSH069 -- EVENT FLAG MASK AND MASK ADDRESS NOW
;			  RESIDE IN THE TCB INSTEAD OF THE HEADER      
;
;	M. S. HARVEY	12-SEP-80
;		MSH115 -- CLEAR PRE-AST STOP,SUSPEND AND WAITFOR BITS
;			  FOR GROUP GLOBAL RUNDOWN OF ABORTED TASKS
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$,HDRDF$,HWDDF$,TCBDF$
	ABODF$			;DEFINE TASK ABORT CODES
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRATX-AST SERVICE EXIT
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO TERMINATE THE EXECUTION OF AN
; ASYNCHRONOUS SYSTEM TRAP SERVICE RO      UTINE. IF ANOTHER AST IS QUEUED AND
; AST'S ARE NOT DISABLED, THEN THE NEXT AST IS EFFECTED IMMEDIATELY.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(115.),DPB SIZE(1.).
;
;	AT ISSUANCE THE TASK STACK CONTAINS:
;
;	14(SP)=EVENT FLAG MASK WORD FOR FLAGS 1.-16.
;	12(SP)=EVENT FLAG MASK WORD FOR FLAGS 17.-32.
;	10(SP)=EVENT FLAG MASK WORD FOR FLAGS 33.-48.
;	06(SP)=EVENT FLAG MASK WORD FOR FLAGS 49.-64.
;	04(SP)=PRE AST TASK PS.
;	02(SP)=PRE AST TASK PC.
;	00(SP)=PRE AST TASK DIRECTIVE STATUS WORD.
;
; I      NPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS WORD RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF PRE AST STATE IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF THE DIRECTIVE
;			WAS NOT EXECUTED FROM AN AST SERVICE RO      UTINE.
;
;	NOTE: IF AN ADDRESS CHECK FAILURE OCCURS WHILE REMOVING ARGU-
;		MENTS FROM THE TASK STACK, THEN THE ISSUING TASK IS
;		ABORTED.
;-


	.IF DF	A$$TRP

$DRATX::MOV	(R2),-(SP)	;DIRECTIVE EXECUTED FROM AST?
	BPL	10$		;IF PL NO
	BIC	#^C<T2.AST!<<T2.STP!T2.SPN!T2.WFR>*2>>,(SP) ;ISOLATE BIT;MSH115
	BIC	(SP),(R2)	;CLEAR AST STATE AND PRE-AST BITS	;MSH115
	ASR	(SP)		;SET UP TASK'S CURRENT STATUS BITS	;MSH115
	BISB	(SP)+,(R2)	;RESTORE PRE AST STATE			;**-3


	.IF DF	C$$CKP&D$$ISK

	BIT	      #T2.STP,(R2)	;WAS TASK STOPPED?
	BEQ	5$		;IF EQ NO
	MOV	T.PCB(R5),R0	;POINT TO TASK PCB
	CALL	$NXTSK		;REALLOCATE TASK PARTITION

	.ENDC


5$:	MOV	@$HEADR,R3	;GET SAVED STACK POINTER


	.IF DF	M$$MGE

	MFPI	SP		;GET USER STACK POINTER
	MOV	(SP),R0		;COPY STACK POINTER
	ADD	#2,R0		;STEP OVER DPB WORD
	ADD	#16,(SP)	;ADJUST TO NEW TOP OF STACK
	MTPI	SP		;RESTORE USER STACK POINTER

	.IFF

	MOV	R3,R0		;COPY SAVED STACK POINTER
	ADD	#4*2+2,R0	;POINT TO FIRST USER STACK WORD

	.IFTF


	      .IF DF	A$$CHK!M$$MGE

	MOV	#7*2,R1		;SET NUMBER OF BYTES TO CHECK
	CALL	$ACHCK		;ADDRESS CHECK TASK STACK WORDS
	BCS	20$		;IF CS ADDRESS CHECK FAILURE

	.ENDC


	.IFT

	CALL	$RELOM		;RELOCATE AND MAP STACK ADDRESS

	.IFTF

	MOV	(R0)+,2(SP)	;SET DIRECTIVE STATUS TO RETURN
	CMP	(R3)+,(R3)+	;POINT TO SAVED PC
	MOV	(R0)+,(R3)+	;RESTORE PRE AST PC
	MOV	(R0)+,(R3)+	;RESTORE PRE AST PS

	.IFT

	BIS	#CMODE!PMODE,-(R3) ;MAKE SURE CURRENT AND PREVIOUS IS USER
	BIC	#PR7,(R3)+	;MAKE SURE PRIORITY       IS ZERO

	.IFTF

	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
	MOV	(R0)+,T.EFLM(R5) ;RESTORE WAITFOR MASK WORD		;MSH069
	MOV	H.EFSV(R4),T.EFLM+2(R5) ;RESTORE WAITFOR MASK ADDRESS	;MSH069
									;MSH069
	.IFF								;MSH069
									;MSH069
	MOV	(R0)+,H.EFLM(R4) ;RESTORE WAITFOR MASK WORD
	MOV	H.EFSV(R4),H.EFLM+2(R4) ;RESTORE WAITFOR MASK ADDRESS
									;MSH069
	.ENDC								;MSH069

	.IFF

	TST	(R0)+		;ADJUST TO PROPER LOCATION
	MOV	-(R3),(R0)	;MOVE TASK PS WORD
	MOV	-(R3),-(   „  R0)	;MOVE TASK PC WORD
	MOV	-(R3),-(R0)	;MOVE SAVED R5
	MOV	-(R3),-(R0)	;MOVE SAVED R4
	MOV	R0,@$HEADR	;SET ADDRESS OF NEW TASK STACK POINTER

	.ENDC


	CALLR	$SETRT		;FORCE A REDISPATCHING OF PROCESSOR
10$:	DRSTS	D.RS80		;SET DIRECTIVE STATUS


	.IF DF	A$$CHK!M$$MGE

20$:	MOV	#S.CAST,R0	;SET AST ABORT
	CALLR	$ABCTK		;ABORT CURRENT TASK

	.ENDC


	.ENDC


	.END
„         Ô	kQ	› c,        	.TITLE	DRDAR
	.IDENT	/04.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 04.00
;
; D. N. CUTLER 30-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;
; MODIFIED BY:
;
; DISABLE/ENABLE AST RECOGNITION DIRECTIVES
;
; MACRO LIBRARY CALLS
;

	.MCALL	TCBDF$
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
      
;+
; **-$DRDAR-DISABLE AST RECOGNITION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO DISABLE RECOGNITION OF ASYNCHRONOUS
; SYSTEM TRAPS FOR THE ISSUING TASK. FURTHER AST'S ARE QUEUED AS THEY OCCUR
; AND WILL BE EFFECTED WHEN AST RECOGNITION IS ENABLED.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(99.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF       THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST RECOG-
;			NITION IS ALREADY DISABLED.
;-


	.IF DF	A$$TRP

	.ENABL	LSB
$DRDAR::BIT	#T2.DST,(R2)	;AST RECOGNITION ALREADY DISABLED?
	BNE	10$		;IF NE YES
	BIS	#T2.DST,(R2)	;DISABLE AST RECOGNITION
	RETURN			;RETURN DIRECTIVE STATUS OF +1

;+
; **-$DREA      R-ENABLE AST RECOGNITION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO RECOGNIZE ASYNCHORONOUS SYSTEM
; TRAPS FOR THE ISSUING TASK. AST'S THAT HAVE BEEN QUEUED WHILE AST RECOG-
; NITION WAS DISABLED ARE EFFECTED IMMEDIATELY.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(101.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUT   ü  S: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST RECOG-
;			NITION IS NOT DISABLED.
;-

$DREAR::BIT	#T2.DST,(R2)	;AST RECOGNITION DISABLED?
	BEQ	10$		;IF EQ NO
	BIC	#T2.DST,(R2)	;ENABLE AST RECOGNITION
	CALLR	$SETRT		;FORCE A REDISPATCHING OF PROCESSOR
10$:	DRSTS	D.RS8		;SET DIRECTIVE STATUS
	.DSABL	LSB

	.ENDC


	.END
 ü         ìðskQ	› c,        	.TITLE	DYDRV
	.IDENT	/02.16/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 02.16
;
; M. BAGGETT/R. PERRON 22-MAR-79
;
; MODIFIED BY:
;
;	R. T. PERRON  12-DEC-79
;
;		RP025 -- CORRECT BUFFER OVERFLOW DETECTION
;
;	P. J. CARR	4-MAR-80
;
;		PJC001 -- CORRECT INVALID DEVICE NOT READY (IE.DNR) ERROR
;
;	P. J. CARR	29-AP      R-80
;
;		PJC006 -- REMOVE SECOND-SIDE SUPPORT
;
;	P. J. CARR 	11-JUN-80
;
;		PJC007 -- CORRECT REGISTER USAGE
;
;	P. J. CARR	23-JUN-80
;
;		PJC009 -- CORRECT THE ROUTINE WHICH DETERMINES THE
;			I/O ERROR CODE (REPLACES PJC001)
;
;	P. J. CARR	24-JUN-80
;
;		PJC010 -- CORRECT IO.SEC FUNCTION
;
;	P. J. CARR	25-JUN-80
;
;		PJC011 -- DON'T ALLOW IO.SMD IF DEVICE IS MOUNTED FILES-11
;
;	P. J. CARR	2-JUL-80
;
;		PJC012 -- FIX PHYSICAL BLOCK TRANSFERS TO TRACKS
;			GREATER THAN 64.
;
;	P      . J. CARR	13-MAR-81
;
;		PJC014 -- CORRECT DETECTION OF DELETED DATA
;
;	DAN BROWN	25-MAR-81
;
;		DTB012 -- REMOVE REFERENCES TO $IOABM FOR NEW ERROR LOG
;
;	P. J. CARR	27-MAR-81
;
;		PJC022 -- CORRECT DENSITY ERROR RECOVERY
;
;	D. S. SUMMERS	15-APR-81
;
;		DS004 -- ADD INIT AFTER SEEK ERROR
;
;	P. J. CARR	9-NOV-81
;
;		PJC037 -- ADD ROUTINE TO LOG ERROR PACKET
;
;	P. J. CARR	9-NOV-81
;
;		PJC038 -- CLEAN UP CODE
;
;	D. S. SUMMERS	9-NOV-81
;
;		DS010  --  CORRECT ERROR AND RETRY CO      DE
;
; RX211- NPR FLOPPY DISK DRIVER
;
; FUNCTIONS RECOGNIZED:
;	IO.RPB	- READ PHYSICAL BLOCK (MAY READ ANY SECTOR ON DISK)
;	IO.WPB	- WRITE PHYSICAL BLOCK (MAY WRITE ANY SECTOR ON DISK)
;	IO.WDD	- WRITE DELETED DATA - WRITE ANY SECTOR ON DISK
;		  SETTING THE DELETED DATA MARK IN SECTOR HEADER
;
; THE FOLLOWING FUNCTION CODES OPERATE ON 256. WORD BLOCKS OF DATA
; (4 SECTORS FOR SINGLE DENSITY OR 2 SECTORS FOR DOUBLE DENSITY).
; THE DRIVER AUTOMATICALLY INTERLEAVES AND SKEWS SECTORS TO OPTIMIZE      
; THE TRANSFER OF DATA SO THAT A LONG TRANSFER MAY BE DONE WITHOUT
; LOOSING A REVOLUTION OF THE DISK.  THE INTERLEAVE FACTOR IS 2 AND
; THE SKEW FACTOR IS 6.
;	IO.RLB	- READ LOGICAL BLOCKS OF 256. WORDS
;	IO.WLB	- WRITE LOGICAL BLOCKS OF 256. WORDS.
;
; THE FOLLOWING FUNCTION CODES ARE USED TO INITIALIZE THE FLOPPY
; TO SINGLE OR DOUBLE DENSITY AND TO REPORT WHICH DENSITY THE CURRENT
; FLOPPY IS.
;	IO.SMD - SET MEDIA DENSITY
;	IO.SEC - SENSE MEDIA CHARACTERISTICS
;
; IF DELETED DATA IS READ, T      HE STATUS CODE RETURNED WILL BE IS.RDD,
; OTHERWISE IT WILL BE IS.SUC.
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			; DEFINE HARDWARE REGISTERS
	PKTDF$			; DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;

RETRY	=	10		; ERROR RETRY COUNT
DYNUM	=	6		; REGISTERS TO LOG ON ERROR		; PJC037
									; PJC038
;									; PJC038
; U.CW2 BITS USAGE							; PJC038
;									; PJC038
									; PJC038
DELDAT	=	100		; DELETED DATA READ			; PJC038
ERR1	=	2000		; TIMEOUT ERROR				; PJC038
DEN	=	4000		; DENSIT      Y BIT (1=DOUBLE)		; PJC038
RSAE	=	10000		; READ STATUS AFTER ERROR		; PJC038
SCHAR	=	40000		; SENSE MEDIA CHARACTERISTICS FUNTION	; PJC038
SILO	=	100000		; FCN ISSUED WAS A SILO FUNCTION	; PJC038
									; PJC038
;									; PJC038
; U.CW3 WORD USAGE							; PJC038
;									; PJC038
									; PJC038
SINGLE	=	494.		; SINGLE DENSITY			; PJC038
DOUBLE	=	988.		; DOUBLE DENSITY			; PJC038
									; PJC038
									;**-8
;
; DEVICE REGISTER OFFSETS AND BIT DEFINITIONS
;

RXCS=	0			; CONTROL S      TATUS REGISTER

GO	=	1		; GO BIT
UNIT	=	20		; UNIT SELECT BIT
DONE	=	40		; DONE BIT
INTEBL	=	100		; INTERRUPT ENABLE
TR	=	200		; TRANSFER READY BIT (CPU-SILO)
SDEN	=	400		; DENSITY BIT
RX211	=	4000		; RX211 INDICATOR BIT			;**-1
INIT	=	40000		; INITIALIZATION BIT
ERR	=	100000		; ERROR BIT

RXDB	=	2		; DATA BUFFER REGISTER

RXES	=	2		; RX211 ERROR STATUS REGISTER

CRCERR	=	1		; CRC ERROR BIT
INITDN	=	4		; INITIALIZE DONE BIT			;**-1
RXACLO	=	10		; RX221 AC LOW BIT
DENERR	=	20		; DENSITY ER      ROR BIT
DRVDEN	=	40		; SELECTED DRIVE'S DENSITY BIT
DELDAT	=	100		; DELETED DATA BIT (USED IN U.CW2 ALSO)	; PJC014
DRVRDY	=	200		; SELECTED DRIVE READY BIT		;**-1
UNTSEL	=	400		; UNIT SELECTED BIT
WCOVFL	=	2000		; WORD COUNT OVERFLOW BIT
NXM	=	4000		; NON-EXISTENT MEMORY BIT

;
; FUNCTION CODES
;

FILL	=	INTEBL!0!GO	; FILL SILO
EMPTY	=	INTEBL!2!GO	; EMPTY SILO
WRITE	=	INTEBL!4!GO	; WRITE A SECTOR
READ	=	INTEBL!6!GO	; READ A SECTOR
SETDEN	=	INTEBL!10!GO	; SET MEDIA DENSITY
MRDS	=	INTEBL!12!G      O	; MAINTENANCE READ STATUS
WRTDD	=	INTEBL!14!GO	; WRITE DELETED DATA
RDERC	=	INTEBL!16!GO	; READ ERROR CODE

;
; LOCAL DATA
;
; IMPURE DATA TABLES INDEXED BY CONTROLLER NUMBER
;
CNTBL:	.BLKW	R$$X21		; ADDRESS OF CURRENT UCB FOR CONTROLLER
RTTBL:	.BLKW	R$$X21		; ERROR RETRY COUNT FOR CURRENT UNIT
									; PJC037
									; PJC037
	.IF DF	E$$DVC							; PJC037
									; PJC037
CSRSV:	.BLKW	R$$X21		; WORD TO SAVE CSR FUNCTION CODE	; PJC037
									; PJC037
	.ENDC								; PJC037


	.IF      	GT R$$X21-1

TEMP:	.BLKW	1		; TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC


;
; DRIVER DISPATCH TABLE
;
$DYTBL::.WORD	DYINI		; DEVICE INITIATOR ENTRY
	.WORD	DYCAN		; CANCEL I/O OPERATION ENTRY
	.WORD	DYOUT		; DEVICE TIME OUT ENTRY
	.WORD	DYPWF		; POWERFAIL ENTRY POINT

;+
; *** - DYINI  FLOPPY DISK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QIO DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPOGATE THE
; EXECUTION OF THE DRIV      ER.  IF THE SPECIFIED CONTROLLER IS NOT BUSY,
; THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST.  OTHERWISE
; A RETURN TO THE CALLER IS EXECUTED.  IF THE DEQUEUE ATTEMPT IS SUCCESSFUL
; THE NEXT I/O OPERATION IS INITIATED.  A RETURN TO THE CALLER IS THEN
; EXECUTED.
;
; INPUTS:
;	R5 - ADDRESS OF UCB OF CONTROLLER TO BE INITIATED
;
; OUTPUTS:
;	IF THE CONTROLLER ASSOCIATED WITH THE SPECIFIED UCB IS NOT
;	BUSY AND AN I/O REQUEST IS WAITING TO BE PROCESSED, THE REQUEST
;	IS DEQUEUED AND THE       DRIVER INITIATES THE REQUESTED FUNCTION.
;
;-
	.ENABL	LSB
DYINI:	CALL	$GTPKT			; TRY TO GET AN I/O PACKET
	BCC	10$		;					; PJC038
	JMP	DYPWF			; IF CS BUSY OR NO PACKET	;**-1

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT
;
;	R1 - ADDRESS OF THE I/O PACKET
;	R2 - PHYSICAL UNIT NUMBER OF DEVICE TO BE INITIATED
;	R3 - CONTROLLER INDEX
;	R4 - ADDRESS OF SCB
;	R5 - ADDRESS OF THE UCB
;
;	FLOPPY DISK I/O REQUEST PACKET FORMAT
;
;	WD. 00 -- I/O QUEUE THREAD WORD
;	WD. 01 -- REQUEST PRIO      RITY, EVENT FLAG NUMBER
;	WD. 02 -- ADDRESS OF TCB OF THE REQUESTING TASK
;	WD. 03 -- POINTER TO SECOND LUN WORD OF REQUESTING TASKS HEADER
;	WD. 04 -- CONTENTS OF FIRST LUN WORD ( UCB ADDRESS)
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB, IO.RPB, IO.WLB, IO.WPB,
;		  IO.WDD, IO.SMD OR IO.SEC)
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE      
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER
;	WD. 14 -- NUMBER OF BYTES TO TRANSFER
;	WD. 15 -- NOT USED (IGNORED)
;	WD. 16 -- LOW BYTE MUST BE ZERO, HIGH BYTE NOT USED
;	WD. 17 -- LOGICAL OR PHYSICAL BLOCK NUMBER
;	WD. 20 -- NOT USED
;
; DRIVER USAGE OF WORDS IN I/O PACKET
;	I.PRM+6  (WD. 15) - STATUS REGISTER AFTER INTERRUPT
;	I.PRM+10 (WD. 16) - LOGICAL OR PHYSICAL BLOCK NUMBER
;	I.PRM+12 (WD. 17) - SIZE OF "THIS" TRANSFER
;	I.PRM+14 (WD. 20) - PHYSI      CAL SECTOR NUMBER (1-26.)
;	I.PRM+15 (WD. 20) - PHYSICAL TRACK NUMBER (0-76.)
;
;
; INITIALIZE DRIVER
;
10$:	MOV	R5,CNTBL(R3)	; SAVE UCB ADDRESS OF CURRENT REQUEST	; PJC038
	MOV	#RETRY,RTTBL(R3); SET RETRY COUNT			;**-1
	TSTB	I.PRM+10(R1)	; HIGH BLOCK SPECIFIED?
	BEQ	30$		; IF EQ NO				; PJC038
20$:	JMP	360$		; YES, ERROR				; PJC038
;									;**-2
; CHECK FOR A VALID FUNCTION
;
30$:	MOV	S.CSR(R4),R2	; GET CSR ADDRESS			; PJC038
	CMPB	#IO.SEC/256.,I.FCN+1(R1)  ; VALID FUNCTION?		;**-1
	BNE	      60$		; IF NE, IT MUST BE A READ OR WRITE	; PJC038
	MOV	#4,RTTBL(R3)	; SET AND SMD FUNC'S ONLY 4 RETRIES	; DS010
	MOV	I.FCN(R1),R0	; GET FUNCTION CODE			;**-1
	BIC	#7,R0		; REMOVE QUALIFIER BITS
	CMP	#IO.SEC,R0	; SENSE CHARACTERISTICS?
	BNE	40$		; IF NE NO				; PJC038
	JMP	DYSEC		; GET DISKETTE CHARACTERISTICS		;**-1
40$:	CMP	#IO.SMD,R0	; SET MEDIA DENSITY?			; PJC038
	BNE	50$		; IF NE NO				; PJC038
	BITB	#US.MNT!US.FOR,U.STS(R5) ; DEVICE MOUNTED?		; PJC011
	BEQ	50$		; IF EQ YES				; PJC038
	MOV	      R0,I.FCN(R1)	; SET FUNCTION CODE WITHOUT MODIFIERS	;**-2
	JMP	DYSMD		; SET DISKETTE DENSITY
50$:	MOV	#IE.IFC&377,R0	; RETURN ERROR CODE			; PJC038
	JMP	400$		; EXIT					; PJC038
60$:				; REF LABEL				; PJC038
;									;**-3
; SET UP MAPPING AND FIRST DISK ADDRESS
;


	.IF DF	M$$EXT&M$$MGE

	CALL	$STMAP		; SET UP 11/70 UNIBUS MAPPING ADDRS

	.ENDC


	.IF DF	M$$MGE

	SWAB	U.BUF(R5)	; POSITION EXTENDED MEMORY BITS

	.ENDC


	MOV	I.PRM+12(R1),R0	; GET PHYSICAL OR LOGICAL BLOCK NUMBER
      	BITB	#IO.RPB&377,I.FCN(R1)  ; IS IT READ/WRITE PHYSICAL?
	BNE	70$		; IF NE YES				; PJC038
	ASL	R0		; CONVERT TO LOGICAL SECTOR NO. (LBN*2)	;**-1
	BIT	#DEN,U.CW2(R5)	; DOUBLE DENSITY?
	BNE	70$		; IF NE YES				; PJC038
	ASL	R0		; SINGLE DEN - LBN*4			;**-1
70$:	MOV	R0,I.PRM+10(R1)	; STORE IT				; PJC038
80$:	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS		; PJC038
	CALL	TRKSEC		; CONVERT BLOCK # TO TRACK/SECTOR	;**-2
	BCS	20$		; IF CS, BAD BLOCK ERROR		; PJC038
	MOV	S.CSR(R4),R2	; GET ADDRESS OF CSR			      ;**-1
	CMPB	#IO.WLB/256.,I.FCN+1(R3)  ; WRITE FUNCTION?
	BNE	190$		; IF NE NO				; PJC038
;									;**-1
; FILL SILO BEFORE WRITE
;
	MOVB	#FILL,U.BUF(R5)	; SET FILL SILO FUNCTION
90$:	BIT	#DEN,U.CW2(R5)	; DOUBLE DENSITY?			; PJC038
	BEQ	100$		; IF EQ NO				; PJC038
	BIS	#SDEN,U.BUF(R5)	; YES-SET DOUBLE DENSITY BIT		;**-2
100$:	BIS	#SILO,U.CW2(R5)	; SILO FUNCTION FLAG			; PJC038
	MOV	U.BUF(R5),(R2)	; INITIATE FUNCTION			;**-1


	.IF DF	M$$MGE&M$$EXT

	MOV	R2,-(SP)	; SAVE REGISTER
	CALL	$MPU      BM		; MAP 11/70 UNIBUS TO TRANSFER
	MOV	(SP)+,R2	; RESTORE REGISTER

	.ENDC


	MOV	U.BUF+2(R5),R0	; GET BUFFER ADDRESS
	MOV	#128.,R1	; DEFAULT TO A 128. BYTE TRANSFER
	BIT	#DEN,U.CW2(R5)	; DOUBLE DENSITY DISKETTE?
	BEQ	110$		; IF EQ NO				; PJC038
	ASL	R1		; CHANGE DEFAULT TO 256. BYTES		;**-1
110$:	CMP	U.CNT(R5),R1	; FULL TRANSFER LEFT?			; PJC038
	BHIS	120$		; IF HIS YES				; PJC038
	MOV	U.CNT(R5),R1	; NO, GET RESIDUAL COUNT		;**-2
120$:	MOV	R1,I.PRM+12(R3)	; STORE BYTES BEING TRANSFERRED		;       PJC038
130$:	BITB	#TR!DONE,(R2)	; TRANSFERRED?				; PJC038
	BMI	140$		; IF MI YES				; PJC038
	BEQ	130$		; IF EQ LOOP				; PJC038
	BR	160$		; ERROR					; PJC038
140$:	ASR	R1		; WORD COUNT				; PJC038
	MOV	R1,RXDB(R2)	; LOAD WORD COUNT			;**-6
150$:	BITB	#TR!DONE,(R2)	; TRANSFERRED?				; DS010
	BMI	162$		; IF MI YES - R0 HAS BUFFER ADRS	; DS010
	BEQ	150$		; IF EQ LOOP				; DS010
160$:	MOV	S.PKT(R4),R3	; GET IO PKT ADDRESS			; DS010
	MOV	RXES(R2),I.PRM+6(R3); SAVE RXES IN SAVE WORD		; DS010
161$:      	JMP	DYRTY		; RETRY					; DS010
162$:	MOV	S.PKT(R4),R3	; GET IO PKT ADDRESS			; DS010
	BR	270$							; DS010
;									;**-5
; EMPTY SILO AFTER READ
;
170$:	MOVB	#EMPTY,U.BUF(R5) ; SET EMPTY SILO FUNCTION		; PJC038
	BR	90$		; SAME AS FILL SILO			; PJC038
;									;**-2
; INITIATE TRANSFER BETWEEN SILO AND DISK
;
180$:	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS		; PJC038
	MOV	S.CSR(R4),R2	; GET CSR ADDR				;**-1
	MOVB	#WRITE,U.BUF(R5);ASSUME WRITE FUNCTION
	MOV	I.FCN(R3),R1	; GET FUNCTION CODE      
	BIC	#7,R1		; REMOVE QUALIFIER BITS
	CMP	#IO.WDD,R1	; WRITE WITH DELETED DATA?
	BNE	200$		; IF NE NO				; PJC038
	MOVB	#WRTDD,U.BUF(R5) ; SET "WRITE DELETED DATA" FUNCTION	;**-1
	BR	200$		; SKIP					; PJC038
190$:	MOVB	#READ,U.BUF(R5)	; SET READ FUNCTION			; PJC038
200$:	BIT	#DEN,U.CW2(R5)	; DOUBLE DENSITY?			; PJC038
	BEQ	210$		; IF EQ NO				; PJC038
	BIS	#SDEN,U.BUF(R5)	; YES-SET DENSITY BIT			;**-4
210$:	TSTB	U.UNIT(R5)	; UNIT 1?				; PJC038
	BEQ	220$		; IF EQ NO				; PJC038
	BIS	#UNIT,U.BUF(      R5)	; YES, SET TO SELECT UNIT 1		;**-2
220$:				; REF LABEL				; PJC038
									; PJC037
									; PJC037
	.IF DF	E$$DVC							; PJC037
									; PJC037
	MOVB	S.CON(R4),R1	; RETRIEVE CONTROLLER INDEX		; PJC037
	MOV	U.BUF(R5),CSRSV(R1) ; SAVE FUNCTION CODE		; PJC037
									; PJC037
	.ENDC								; PJC037
									; PJC037
									; PJC037
	MOV	U.BUF(R5),(R2)	; INITIATE FUNCTION			; PJC037
230$:	BITB	#TR!DONE,(R2)	; TRANSFER READY OR DONE?		; PJC038
	BMI	240$		; IF MI, TRANSFER READY			; P      JC038
	BEQ	230$		; IF EQ LOOP				; PJC038
240$:	MOVB	I.PRM+14(R3),RXDB(R2) ; LOAD SECTOR NUMBER		; PJC038
250$:	BITB	#TR!DONE,(R2)	; TRANSFER READY OR DONE?		; PJC038
	BMI	260$		; IF MI, TRANSFER READY			; PJC038
	BEQ	250$		; IF EQ LOOP				; PJC038
	BR	160$		; ERROR					; PJC038
260$:	MOVB	I.PRM+15(R3),R0	; LOAD TRACK NUMBER IN R0		; PJC038
270$:	MOVB	S.ITM(R4),S.CTM(R4) ; SET TIMEOUT COUNT			; PJC038
280$:	MOV	R0,RXDB(R2)	; LOAD TRACK, BUFFER ADDRESS OR ASCII I	; PJC038
;									;**-26
; DYPWF       - POWER FAIL ENTRY POINT
;	POWER FAIL IS HANDLED BY THE DEVICE TIMING OUT, THEREFORE
;	NO WORK IS DONE HERE.  IT WILL BE HANDLED WHEN THE DEVICE
;	TIME OUT ENTRY IS EXECUTED.
;
DYPWF:				;;;					; PJC038
;
; DYCAN - CANCEL I/O ENTRY POINT
;	CANCEL I/O IS A NOP OP FOR FILE STRUCTURED DEVICES
;
DYCAN:	RETURN			;;;					;**-1

;+
; *** - $DYINT  - RX11 FLOPPY DISK INTERRUPT ENTRY POINT
;
;-
	INTSE$	DY,PR5,R$$X21	;;; GENERATE INTERRUPT SAVE CODE
	MOV	R3,-(SP)	;;; SAVE REGISTER
	MOV	U.SCB(R5),R4      	;;; GET SCB ADDRESS
	MOV	S.PKT(R4),R3	;;; GET I/O PACKET ADDRESS
	MOV	S.CSR(R4),R4	;;; GET CSR ADDRESS
	MOV	RXDB(R4),I.PRM+6(R3)  ;;; SAVE CONTROLLER STATUS
	MOV	(SP)+,R3	;;; RESTORE REGISTER
	CLR	(R4)		;;; DISABLE INTERRUPTS
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS
	MOV	R4,R2		; COPY CSR ADDRESS
	MOV	U.SCB(R5),R4	; GET SCB ADDRESS
	MOVB	S.CON(R4),R3	; GET CONTROLLER INDEX
	TSTB	RTTBL(R3)	; RETRIES ZERO				; DS010
	BNE	281$		; IF NE NO				; DS010
	BIT	#RSAE,U.CW2(R5) ; READ STATUS AFTER ERROR		      ; DS010
	BNE	281$		; IF NE YES				; DS010
	JMP	DYINI		; TREAT AS SPURIOUS			; DS010
281$:	BIT	#SCHAR,U.CW2(R5); SENSE CHARACTERICS			; DS010
	BNE	DYSEN		; IF NE YES				;**-1
	TST	(R2)		; ANY ERRORS?
	BPL	290$		; IF PL, NO ERRORS			; PJC038
									; PJC037
									; PJC037
	.IF DF	E$$DVC							; PJC037
									; PJC037
	CALL	LOGERR		; LOG DEVICE ERROR			; PJC037
									; PJC037
	.ENDC								; PJC037
									; PJC037
									; PJC037
	JMP	DYRTY		; RETRY FUNCTION			; PJC037
290$:	ASRB      	RTTBL+1(R3)	; INITIALIZE IN PROGRESS?		; PJC038
	BCS	350$		; IF CS YES				; PJC038
	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS		;**-4
	CMP	#IO.SMD,I.FCN(R3)  ; SET MEDIA DENSITY?
	BNE	300$		; IF NE NO				; PJC038
	JMP	390$		; YES, FINISH I/O			; PJC038
300$:	CMPB	#IO.RLB/256.,I.FCN+1(R3) ; READ?			; PJC038
	BNE	330$		; IF NE NO				; PJC038
	TST	U.CW2(R5)	; SILO FUNCTION?			;**-4
	BMI	320$		; IF MI YES				; PJC038
	BITB	#DELDAT,I.PRM+6(R3) ; DELETED DATA READ?		; PJC014
	BEQ	310$		; IF EQ NO				;       PJC038
	BISB	#DELDAT,U.CW2(R5) ; YES					; PJC014
310$:	JMP	170$		; GO EMPTY SILO				; PJC038
320$:	BIC	#SILO,U.CW2(R5)	; CLEAR SILO BIT			; PJC038
	CALL	NXTSEC		; UPDATE TO NEXT SECTOR			;**-3
	BEQ	380$		; IF EQ, ALL FINISHED			; PJC038
	BR	350$		; INITIATE NEXT READ			; PJC038
330$:	TST	U.CW2(R5)	; FILL SILO FUNCTION?			; PJC038
	BPL	340$		; IF PL NO				; PJC038
	BIC	#SILO,U.CW2(R5)	; YES - CLEAR SILO BIT			;**-4
	JMP	180$		; GO WRITE SECTOR			; PJC038
340$:	CALL	NXTSEC		; UPDATE TO NEXT SECTOR      			; PJC038
	BEQ	390$		; IF EQ, ALL FINISHED			; PJC038
350$:	BIC	#ERR1,U.CW2(R5)	; CLEAR TIMEOUT ERROR BIT		; DS010
	MOV	S.PKT(R4),R3	; GET IO PACKET ADR			; DS010
	CMP	#IO.SMD,I.FCN(R3); IO.SMD FUNC				; DS010
	BNE	351$		; IF NE NO				; DS010
	JMP	DYSMD		; RETRY FUNC				; DS010
351$:	JMP	80$		; RETRY CURRENT OPERATION NOW		; PJC038
360$:	MOV	#IE.BLK&377,R0	; SET BAD BLOCK ERROR			; PJC038
	BR	420$		;					; PJC038
370$:	MOV	#IE.VER&377,R0	; SET UNRECOVERABLE ERROR		; PJC038
	BR	400$		;					; PJC      038
380$:	MOV	I.FCN(R3),R1	; GET FUNCTION CODE			; PJC038
	BIC	#7,R1		; REMOVE QUAILFIER BITS			;**-10
	CMP	#IO.RPB,R1	; READ PHYSICAL BLOCK?
	BNE	390$		; IF NE NO				; PJC038
	BITB	#DELDAT,U.CW2(R5) ; DELETED DATA READ?			; PJC014
	BEQ	390$		; IF EQ NO				; PJC038
	BICB	#DELDAT,U.CW2(R5) ; YES					; PJC014
	MOV	#IS.RDD&377,R0	; READ DELETED DATA			; PJC038
	BR	400$		;					; PJC038
390$:	MOV	#IS.SUC&377,R0	; SET SUCCESSFUL COMPLETION		; PJC038
400$:	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS		; PJ      C038
	MOV	I.PRM+4(R1),R1	; SET BYTES TRANSFERED			;**-6
	SUB	U.CNT(R5),R1	; CALCULATE BYTES ACTUALLY TRANSFERED
410$:									; PJC038
									;**-1

	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	; RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	; SET FINAL RETRY COUNT
	MOV	R1,-(SP)	; SAVE R1				; DS010
	MOV	S.PKT(R4),R1	; GET IO PKT ADDRESS			; DS010
	CMPB	#IO.SEC,I.FCN+1(R1); IO.SEC OR IO.SMD FUNC'S		; DS010
	BNE	411$		; IF NE NO				; DS010
	BIS	#4*256.,R2	; SET INIT RETRY COUNT IO.SEC/SMD'S	; DS010
	BR      	412$							; DS010
411$:	BIS	#RETRY*256.,R2	; SET INIT RETRY COU T FOR READ WRITE FU; DS010
412$:	MOV	(SP)+,R1	; RESTORE R1				; DS010
	.ENDC								;**-2


420$:	BIC	#SILO!SCHAR!ERR1,U.CW2(R5) ; CLEAR ALL BUT DENSITY BITS	; PJC038
	CALL	$IODON		; SET DONE				;**-2
	JMP	DYINI		; TRY FOR ANOTHER REQUEST

;
; INTERRUPT PROCESSING POINT FOR DETERMINING THE
; DISKETTE UNIT STATUS.
;

DYSEN:	MOV	S.PKT(R4),R1 	; RETRIEVE I/O PACKET ADDRESS		; PJC007
	BIT	#RSAE,U.CW2(R5)	; READ STATUS AFTER ERROR?      		; PJC009
	BEQ	430$		; IF EQ NO				; PJC038
	BIC	#RSAE,U.CW2(R5)	; CLEAR FLAG				; PJC009
	JMP	590$		; GO DETERMINE ERROR TYPE		; PJC038
430$:	ASRB	RTTBL+1(R3)	; INIT IN PROGRESS			; DS010
	BCC	431$		; IF CC NO				; DS010
	BIT	#RXACLO,I.PRM+6(R1); AC LOW				; DS010
	BEQ	DYSEC		; IF EQ NO - RETRY IO.SEC		; DS010
	JMP	590$		; EXIT					; DS010
431$:	BIT	#DRVRDY,I.PRM+6(R1) ; DRIVE READY?			; DS010
	BEQ 	DYRTY		; IF EQ NO				; PJC010
	TST	(R2)		; ANY ERRORS ?				;**-1
	BPL	440$		; IF PL NO				; PJC      038
	BIT	#DENERR,I.PRM+6(R1) ; IS IT A DENSITY ERROR?		; PJC007
	BEQ	DYRTY		; IF EQ NO				;**-2
440$:	BIC	#SCHAR!DEN,U.CW2(R5) ; CLEAR FLAGS			; PJC038
	MOV	#SINGLE,U.CW3(R5) ; ASSUME SINGLE DENSITY		; PJC038
	BIT	#DRVDEN,I.PRM+6(R1) ; IS IT DOUBLE DENSITY?		; PJC007
	BEQ	450$		; IF EQ NO				; PJC038
	ASL	U.CW3(R5)	; DOUBLE THE MAXIMUM LBN'S		;**-4
	BIS	#DEN,U.CW2(R5)	; SET THE DENSITY BIT
450$:	MOV	#IS.SUC&377,R0	; SET SUCCESS				; PJC038
	MOV	U.CW2(R5),R1	; RETURN DEVICE CHARACTERISTICS		;**-5
      	BR	410$		;					; PJC038
;									;**-1
;	SENSE CHARACTERISTIC PROCESSING
;
DYSEC:	BIS	#SCHAR,U.CW2(R5) ; INDICATE SENSE CHARACTERISTIC
	MOV	#MRDS,R0	; SET MAINTENANCE READ STATUS
	TSTB	U.UNIT(R5)	; UNIT 1 ?
	BEQ	460$		; IF EQ NO				; PJC038
	BIS	#UNIT,R0	; YES SELECT UNIT 1			;**-1
460$:	MOV	R0,(R2)		; INITIATE FUNCTION			; PJC038
	MOVB	S.ITM(R4),S.CTM(R4)  ; SET TIMEOUT COUNT		;**-1
	RETURN			;					;**-9

;
; SET MEDIA DENSITY
;
DYSMD:	MOV	#SETDEN,R0	; SET FUNCTION CODE
	BIC	#DEN,U.CW2(R      5)	; CLEAR FLAG
	MOV	#SINGLE,U.CW3(R5) ; ASSUME SINGLE DENSITY		; PJC038
	TST	I.PRM(R1)	; SINGLE DENSITY?			;**-1
	BEQ	470$		; IF EQ YES				; PJC038
	CMP	#2,I.PRM(R1)	; DOUBLE DENSITY?			;**-1
	BNE	470$		; IF NE NO, TREAT AS SINGLE DENSITY	; PJC038
	BIS	#SDEN,R0	; DOUBLE DENSITY			;**-1
	BIS	#DEN,U.CW2(R5)	; UPDATE STATUS
	ASL	U.CW3(R5)	; DOUBLE MAXIMUM LBN'S
470$:	TSTB	U.UNIT(R5)	; UNIT 1?				; PJC038
	BEQ	480$		; IF EQ NO				; PJC038
	BIS	#UNIT,R0	; YES SELECT UNIT 1			;**-2
480$:	MOV	R0,(R2)	      	; INITIATE FUNCTION			; PJC038
	MOV	S.PKT(R4),R3	; GET IO PKT ADR			; DS010
490$:	BITB	#TR!DONE,(R2)	; TRANSFERRED?				; DS010
	BMI	500$		; IF MI YES				; DS010
	BEQ	490$		; IF EQ LOOP				; DS010
	JMP	160$		; SAVE STATUS REG AND RETRY		; DS010
500$:	MOV	#'I,R0		; ASCII "I"				; PJC038
	MOVB	#30.,S.CTM(R4)	; TIMEOUT COUNT				;**-8
	JMP	280$		;					; PJC038
									;**-1
;+
; **-DYOUT-FLOPPY DISK TIMEOUT ENTRY POINT
;-

DYOUT:	BIS	#ERR1,U.CW2(R5)	;;; TIMEOUT ENTRY POINT			; PJC037
									;       PJC037
									; PJC037
	.IF DF	E$$DVC							; PJC037
									; PJC037
	CALL	LOGTMO		;;; LOG DEVICE TIMEOUT			; PJC037
									; PJC037
	.ENDC								; PJC037
									; PJC037
									; PJC037
DYRTY:	MOVB	S.CON(R4),R3	; RESTORE CONTROLLER INDEX		; PJC037
	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS		;**-18
	BITB	#RSAE,U.CW2(R5)	; READ STATUS AFTER ERROR?		; DS010
	BNE	600$		; IF NE YES				; DS010
	BITB	#IQ.X,I.FCN(R1)	; INHIBIT RETRIES ?
	BEQ	510$		; IF EQ NO				; PJC038
	CMP	#IO.SEC,I.FCN      (R1); IO.SEC FUNC				; DS010
	BEQ	590$		; IF EQ YES				; DS010
	BIS	#RSAE,U.CW2(R5)	; SET READ STATUS AFTER ERROR FLAG	; PJC009
	JMP	DYSEC		; GO DO READ STATUS			; PJC009
510$:	DECB	RTTBL(R3)	; ANY RETRIES LEFT?			; PJC038
	BNE	520$		; IF NE YES				; PJC038
	CMP	#IO.SEC,I.FCN(R1); DONT'T REPEAT IO.SEC			; DS010
	BEQ	590$		; IF EQ EXIT				; DS010
	BIS	#RSAE,U.CW2(R5)	; SET READ STATUS AFTER ERROR FLAG	; PJC009
	JMP	DYSEC		; GO DO READ STATUS			; PJC009
520$:	BIT	#ERR1,U.CW2(R5)	; TIMEOUT ERROR?			;       PJC038
	BNE	580$		; IF NE YES				; PJC038
	ASRB	RTTBL+1(R3)	; INIT IN PROGRESS			; DS010
	BCC	530$		; IF CC NO				; DS010
	BIT	#RXACLO,I.PRM+6(R1); AC LOW				; DS010
	BNE	590$		; IF NE YES - EXIT			; DS010
530$:	BIT	#SCHAR,U.CW2(R3); SENCE CHARACTERICS			; DS010
	BNE	580$		; IF NE YES				; DS010
	CMP	#IO.SMD,I.FCN(R1); SET MEDIA DENSITY			; DS010
	BEQ	580$		; IF EQ YES				; DS010
	BIT	#CRCERR,I.PRM+6(R1); CRC ERROR				; DS010
	BNE	570$		; IF NE YES				; PJC038
540$:	MOV	I.PRM+10(R1),R0	; GET LO      GICAL SECTOR NUMBER		; PJC038
	BIT	#WCOVFL!DENERR,I.PRM+6(R1)  ; WORD COUNT OVERFLOW OR	;**-11
				; DENSITY ERROR ?
	BEQ	580$		; IF EQ NO				; PJC038
	BIT	#DRVDEN,I.PRM+6(R1)  ; IS IT DOUBLE DENSITY ?		;**-1
	BNE	550$		; IF NE YES				; PJC038
	BIC	#DEN,U.CW2(R5)	; CORRECT IT TO SINGLE DENSITY		;**-1
	BIC	#SDEN,U.BUF(R5)	; HERE TOO				; PJC022
	ASL	R0		; MULTIPLY LSN BY 2
	MOV	#SINGLE,U.CW3(R5) ; CHANGE MAX LBN'S TO SINGLE DENSITY	; PJC038
	BR	560$		; 					; PJC038
550$:	BIS	#DEN,U.CW2(R5)	; CHAN      GE TO DOUBLE DENSITY		; PJC038
	ASR	R0		; DIVIDE LSN BY 2			;**-4
	MOV	#DOUBLE,U.CW3(R5) ; CHANGE MAX LBN'S TO DOUBLE DENSITY	; PJC038
560$:	MOV	R0,I.PRM+10(R1)	; STORE LOGICAL SECTOR NUMBER		; PJC038
570$:	BIC	#ERR1,U.CW2(R5)	; CLEAR TIMEOUT ERROR			; PJC038
	JMP	80$		; RETRY FUNCTION			; PJC038
580$:	BIC	#ERR1,U.CW2(R5)	; CLR TIMEOUT ERROR			; PJC038
	MOVB	#1,RTTBL+1(R3)	; SET INITIALIZE IN PROGRESS		; PJC038
									; PJC037
									; PJC037
	.IF DF	E$$DVC							; PJC037
									; PJC037
	      MOV	#INIT!INTEBL,CSRSV(R3) ; SAVE FUNCTION CODE		; PJC037
									; PJC037
	.ENDC								; PJC037
									; PJC037
									; PJC037
	MOV	#INIT!INTEBL,(R2) ; INITIALIZE RX211 DRIVES		;**-10
	MOVB	S.ITM(R4),S.CTM(R4) ; SET TIMEOUT COUNTER
	RETURN			;
590$:	BIT	#DRVRDY,I.PRM+6(R1) ; DRIVE READY?			; PJC038
	BEQ	600$		; IF EQ NO				; PJC038
	JMP	370$		; EXIT WITH IE.VER			; PJC038
600$:	MOV	#IE.DNR&377,R0	; SET DEVICE NOT READY ERROR		; PJC038
	JMP	400$		; EXIT WITH IE.DNR			; PJC038
	.DSABL	LSB      							;**-7
									; PJC037
									; PJC037
	.IF DF	E$$DVC							; PJC037
									; PJC037
;									; PJC037
; **LOGERR-LOG DEVICE ERROR						; PJC037
; **LOGTM0-LOG TIMEOUT ERROR						; PJC037
;									; PJC037
; THESE ROUTINES ARE CALLED IN THE CASE OF EITHER A DEVICE ERROR	; PJC037
; OR TIMEOUT ERROR. WE WILL ALLOCATE A CORE BLOCK, FILL IT WITH		; PJC037
; THE APPROPRIATE REGISTER INFORMATION, CALL THE EXECUTIVE		; PJC037
; ERROR LOGGING ROUTINE, DEALLOCATE THE CORE BLOCK, AND RETURN	      	; PJC037
; BACK TO THE CALLER.							; PJC037
;									; PJC037
; INPUT:								; PJC037
;	R3 = CONTROLLER INDEX						; PJC037
;	R4 = SCB ADDRESS						; PJC037
;	R5 = UCB ADDRESS						; PJC037
;									; PJC037
; OUTPUT:								; PJC037
;	R2 = CSR ADDRESS						; PJC037
;	R4 = SCB ADDRESS						; PJC037
;	R5 = UCB ADDRESS						; PJC037
;									; PJC037
; R0, R1 AND R3 ARE DESTROYED.						; PJC037
;									; PJC037
	.ENABL	LSB							; PJC037
LOGERR:	MOV	#$DVERR,-(SP)	; LOG DEVICE ERROR			      ; PJC037
	BR	10$		;					; PJC037
LOGTMO:	MOV	#$DTOER,-(SP)	;;; LOG TIMEOUT ERROR			; PJC037
10$:	MOV	#DYNUM*2,R1	; NUMBER OF BYTES TO ALLOCATE		; PJC037
	CALL	$ALOCB		; ALLOCATE THE ERROR BLOCK		; PJC037
	BCC	20$		; IF CC OK				; PJC037
	INC	$ERRSQ		; INDICATE A MISSED ERROR		; PJC037
	CMP	(SP)+,#$DTOER	; TIMEOUT?				; PJC037
	BNE	80$		; IF NE NO				; PJC037
	BIC	#INTEBL,@S.CSR(R4) ;;; CLEAR INTERRUPT ENABLE		; PJC037
	MTPS	#0		;;; ALLOW INTERRUPTS			; PJC037
20$:	MOV	R0,R1		; COPY CORE BLOCK ADD      RESS		; PJC037
	MOV	S.CSR(R4),R2	; RETRIEVE CSR ADDRESS			; PJC037
	MOV	(R2),(R1)	; SAVE CSR CONTENTS			; PJC037
	BIC	#^C<17>,CSRSV(R3) ; ISOLATE BITS 0-4			; PJC037
	BIS	CSRSV(R3),(R1)+	; INCLUDE FUNCTION CODE			; PJC037
	MOV	RXDB(R2),(R1)+	; SAVE RXDB				; PJC037
	MOV	#17,(R2)	; EXECUTE READ ERROR CODE FUNCTION	; PJC037
30$:	MOV	#5,R3		; SET UP LOOP COUNT			; PJC037
40$:	BIT	#TR,(R2)	; TRANSFER REQUEST?			; PJC037
	BNE	60$		; IF NE YES				; PJC037
	BMI	50$		; IF MI ERROR				; PJC037
	DEC	R3		;       IF EQ, DECREMENT LOOP COUNT		; PJC037
	BEQ	50$		; TIMED OUT				; PJC037
	BR	40$		; KEEP CHECKING				; PJC037
50$:				; REF LABEL				; PJC037
									; PJC037
	.REPT	4							; PJC037
									; PJC037
	CLR	(R1)+		; ZERO 4 WORDS WHEN ERROR ON RDERC	; PJC037
									; PJC037
	.ENDR								; PJC037
									; PJC037
	BR	70$		; SKIP REST OF RDERC FUNCTION		; PJC037
60$:	MOV	R1,RXDB(R2)	; GIVE ADRS TO FILL WITH ERROR STATUS	; PJC037
	BITB	#DONE,(R2)	; DONE?					; PJC037
	BEQ	60$		; IF EQ NO				; P      JC037
70$:	MOV	R0,S.CSR(R4)	; FAKE CSR ADRS WITH ERROR BLOCK ADRS	; PJC037
	CALL	@(SP)+		; LOG THE ERROR				; PJC037
	MOV	R2,S.CSR(R4)	; RESTORE THE CSR ADRS IN SCB		; PJC037
	MOV	#DYNUM*2,R1	; NUMBER OF BYTES TO DEALLOCATE		; PJC037
	CALL	$DEACB		; DEALLOCATE THE ERROR BLOCK		; PJC037
80$:	MOV	S.CSR(R4),R2	; RETRIEVE CSR ADDRESS			; PJC037
	RETURN			;					; PJC037
	.DSABL	LSB							; PJC037
									; PJC037
	.ENDC	;E$$DVC							; PJC037
									; PJC037

;+
; *** - TRKSEC  -  CONVERT LOGICA      L OR PHYSICAL BLOCK NUMBER TO
;	TRACK-SECTOR PAIR
;
; INPUT:
;	R3 - I/O PACKET ADDRESS
;	I.PRM+10(R3) - LOGICAL OR PHYSICAL SECTOR
;
; OUTPUT:
;	I.PRM+14(R3) - SECTOR (1-26.)
;	I.PRM+15(R3) - TRACK (0-76.)
;	R3 - UNCHANGED
;	C CLEAR - VALID BLOCK
;	C SET - BAD BLOCK NUMBER (PHYSICAL OR LOGICAL)
;
;-

TRKSEC:	MOV	I.PRM+10(R3),R1	; GET LOGICAL OR PHYSICAL BLOCK
	MOV	#8.,R0		; SET LOOP COUNT
	MOV	#6400,R2	; SET DIVISOR
10$:	CMP	R2,R1		; DOES 26 GO INTO DIVIDEND?		; PJC038
	BHI	20$		; IF HI       NO (C=0)			; PJC038
	SUB	R2,R1		; SUBTRACT 26 FROM DIVIDEND		;**-2
	SEC			; SET CARRY
20$:	ROL	R1		; SHIFT DIVIDEND AND QUOTIENT		; PJC038
	DEC	R0		; DONE?					;**-1
	BGT	10$		; IF GT NO				; PJC038
	BISB	R1,R0		; GET TRACK NUMBER			; PJC012
	CMP	R0,#77.		; IS IT A LEGITIMATE TRACK NUMBER?	; PJC006
	BHI	60$		; IF HI NO				; PJC038
	BLO	30$		; IF LO YES				; PJC038
	BITB	#IO.RPB&377,I.FCN(R3) ; PHYSICAL BLOCK FUNCTION?	; PJC006
	BEQ	60$		; IF EQ NO, BAD BLOCK ERROR		; PJC038
30$:	CLRB	R1		; CLEAR       TRACK NUMBER			; PJC038
	SWAB	R1		; SHIFT DONE SECTOR NUMBER		;**-15
	BITB	#IO.RPB&377,I.FCN(R3) ; IS IT A PHYSICAL BLOCK NUMBER?
	BNE	50$		; IF NE YES				; PJC038
	CMP	#12.,R1		; NO, C=1 IF 13<=R1<=25			;**-1
	ROL	R1		; DOUBLE FOR INTERLEAVE FACTOR
	ASL	R0		; ADD TRACK -TRACK SKEW
	ADD	R0,R1		; SKEW BY 2*TRACK
	ADD	R0,R1		; SKEW BY 4*TRACK
	ADD	R0,R1		; SKEW BY 6*TRACK
	ASR	R0		; RESTORE TRACK NUMBER
	MOV	#26.,R2		; SET MODULUS
40$:	SUB	R2,R1		; MODULO SECTOR INTO RANGE -26. TO -1.	; PJC038
	      BGE	40$		; IF GE, LOOP UNTIL NEGATIVE		; PJC038
	ADD	R2,R1		; CONVERT TO RANGE 0-25.		;**-2
	INC	R0		; LBN0 STARTS ON TRACK 1
50$:	INC	R1		; CONVERT TO RANGE 1-26.		; PJC038
	MOV	R1,I.PRM+14(R3)	; SAVE SECTOR NUMBER			;**-1
	BR	70$		;					; PJC038
60$:	SEC			; SIGNAL BAD BLOCK ERROR		; PJC038
	MOVB	R0,I.PRM+15(R3) ; SAVE TRACK NUMBER			;**-2
	BR	80$		;					; PJC038
70$:	MOVB	R0,I.PRM+15(R3)	; SAVE TRACK NUMBER			; PJC038
	CMP	#77.*256.,I.PRM+14(R3)	; IS IT A VALID TRACK/SECTOR?	;**-2
80$:	RETURN	      		;					; PJC038
									;**-1
;+
; *** - NXTSEC  -  UPDATE BLOCK NUMBER , BUFFER ADDRESS
;			AND BUFFER POINTER
;
; INPUT:
;	R3 - I/O PACKET ADDRESS
;	R5 - UCB ADDRESS
;	I.PRM+10(R3) - CURRENT BLOCK NUMBER
;	I.PRM+12(R3) - BYTES TRANSFERED DURING LAST FUNCTION
;	U.CNT(R5) - BYTES LEFT TO TRANSFER
;	U.BUF(R5) - BUFFER ADDRESS
;
; OUTPUT:
;	I.PRM+10(R3) - UPDATED BLOCK NUMBER
;	U.BUF(R5) - UPDATED BY 128./256. BYTES
;	U.CNT(R5) - UPDATED BY NUMBER OF WORDS TRANSFERED
;	Z SET - ALL BYTES TR      ANSFERED
;	Z CLEAR - MORE BYTES TO TRANSFER
;	C CLEAR - VALID TRACK/SECTOR
;	C SET - BAD BLOCK NUMBER
;
;+

NXTSEC:	INC	I.PRM+10(R3)	; UPDATE BLOCK NUMBER
	BIT	#DEN,U.CW2(R5)	; SINGLE DENSITY?			; RP025
	BEQ	5$		; IF EQ YES				; RP025
	ADD	#256.,U.BUF+2(R5)  ; UPDATE BUFFER ADDRESS FOR DOUBLE DE; RP025
	BR	10$		; AND CONTINUE				; RP025
5$:	ADD	#128.,U.BUF+2(R5)  ; UPDATE BUFFER ADDRESS FOR SINGLE DE; RP025
10$:	BCC	15$		; IF CC, NO OVERFLOW			; RP025
									;**-5

	.IF DF	M$$MGE

	ADD	#   š   10000,U.BUF(R5) ; CARRY INTO EXTENDED MEMORY BITS

	.ENDC


15$:	SUB	I.PRM+12(R3),U.CNT(R5)  ; UPDATE BYTES LEFT TO TRANSFER
	RETURN			;

	.END
 š          ×0 kQ	› c,        	.TITLE	DRGEF
	.IDENT	/02.10/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 02.10
;
; J. E. PROVINO 21-SEP-78
;
; FOR RSX-11M:	CHUCK SPITZ 8-DEC-78
;
; MODIFIED BY:
;
;	M. S. HARVEY	15-AUG-79
;		MSH049 -- DON'T RETURN DIRECTIVE STATUS FROM $GTGEF.
;			  ALSO, CLEAN UP $DRCRE CODE.
;
;	M. S. HARVEY	30-SEP-79      
;		MSH045 -- MOVE COMMONLY USED SUBROUTINES TO DRSUB
;
;	M. S. HARVEY	11-FEB-81
;		MSH148 -- ADD LOCK/UNLOCK GROUP GLOBAL CONTROL
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
; GROUP GLOBAL EVENT FLAG ROUTINES
;
; MACRO LIBRARY CALLS
;
	.MCALL	PKTDF$,TCBDF$,HDRDF$,PCBDF$
	PKTDF$			;DEFINE GROUP GLOBAL OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS


;+
; **-$DRCRE-CREATE       GROUP GLOBAL EVENT FLAGS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CREATE GROUP GLOBAL EVENT
; FLAGS FOR A SPECIFIED GROUP. IF THE SPECIFIED GROUP MATCHES THE	;MSH148
; TASK'S OWN GROUP, THE EVENT FLAG USE COUNT IS INCREMENTED, EFFECTING	;MSH148
; A 'LOCK' OPERATION FOR THE FLAGS WHICH PREVENTS PREMATURE ELIMINATION	;MSH148
; OF THE FLAGS BY A TASK THAT SHARES THEM.				;MSH148
;									;MSH148
; IF THE EVENT FLAGS ALREADY EXIST, THE SPECIFIED GROUP IS EQUAL TO	;MSH148
; THE TASK'S OWN GROUP, AND       THE EVENT FLAGS ARE UNLOCKED, THIS		;MSH148
; DIRECTIVE WILL LOCK THE EVENT FLAGS FOR THE ISSUING TASK.		;MSH148
;									;**-1
; DPB FORMAT:
;
;	WD. 00 -- DIC(157.),DPB SIZE(2.).
;	WD. 01 -- GROUP NUMBER
;
; INPUTS:
;
;	R2=ADDRESS OF SECOND STATUS WORD OF CURRENT TASK
;	R3=POINTER TO WD. 1 IN THE DPB
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPL      ETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IF ALLOCATION FAILURE.
;		DIRECTIVE STATUS OF 'D.RS16' IF NON-PRIVILEGED TASK
;			ATTEMPTS TO CREATE EVENT FLAGS FOR ANOTHER GROUP.
;		DIRECTIVE STATUS OF 'D.RS17' IS RETURNED IF GROUP GLOBAL
;			EVENT FLAGS ALREADY EXIST.
;		DIRECTIVE STATUS OF 'D.RS91' IS RETURNED IF GROUP IS
;			INVALID.
;-

	.IF DF G$$EFN

	.ENABL	LSB
$DRCRE::CALL	300$		;DO FLAGS ALREADY EXIST?		;MSH148
	BCC	40$		;      IF CC YES				;MSH148
	MOV	R0,-(SP)	;SAVE CONTROL BLOCK LIST POSITION	;MSH148
	MOV	#G.LGTH,R1	;GET LENGTH OF GROUP GLOBAL CONTROL BLK	;MSH148
	MOV	R2,R3		;COPY TASK'S GROUP NUMBER		;MSH148
	CALL	$ALOCB		;ALLOCATE A BLOCK FOR GROUP GLOBAL FLAGS;**-15
	BCS	70$		;IF CS ALLOCATION FAILURE
	MOV	@(SP),(R0)	;POINT NEW BLOCK TO REMAINDER OF LIST	;MSH049
	MOV	R0,@(SP)+	;LINK NEW BLOCK INTO LIST		;MSH049
	TST	(R0)+		;POINT PAST LINK WORD (G.LNK)		;MSH049
	MOVB	R4,(R0)+	;STORE GROUP NUMBER (G.GRP)		;MSH049
	C      LRB	(R0)+		;CLEAR STATUS BYTE (G.STAT)		;MSH049
	CLR	(R0)+		;INITIALIZE ACCESS COUNT (G.CNT)	;MSH049
	CMP	R3,R4		;ARE THESE FLAGS FOR THE TASK'S OWN GRP?;MSH148
	BNE	20$		;IF NE NO, DO NOT LOCK THEM		;MSH148
	INC	-2(R0)		;LOCK THE FLAGS IN POOL BY ACCESSING THE;MSH148
	BIS	#T3.GFL,(R5)	;MARK TCB AS HAVING THE FLAGS LOCKED	;MSH148
									;MSH148
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH148
	INCB	T.GGF-T.ST3(R5)	;RECORD THIS ACCESS			;MSH148
									;MSH148
	.ENDC								;MSH148
								      	;MSH148
20$:	CLR	(R0)+		;CLR FIRST EVENT FLAG WORD (G.EFLG)	;MSH148
	CLR	(R0)		;CLR SECOND EVENT FLAG WORD (G.EFLG+2)	;MSH049
30$:	RETURN			;					;**-9
40$:	CLRB	G.STAT(R1)	;CLEAR MARKED FOR DELETE		;MSH148
	CMP	R2,R4		;TASK'S OWN GROUP?			;MSH148
	BNE	110$		;IF NE NO				;MSH148
	BIT	#T3.GFL,(R5)	;ALREADY LOCKED?			;MSH148
	BNE	110$		;IF NE YES				;MSH148
	BIS	#T3.GFL,(R5)	;MARK TCB AS HAVING LOCKED EVENT FLAGS	;MSH148
	INC	G.CNT(R1)	;LOCK THESE EVENT FLAGS IN POOL		;MSH148
									;MSH148
	.I      F DF	R$$SND!A$$CLI						;MSH190
									;MSH148
	INCB	T.GGF-T.ST3(R5)	;RECORD ACCESS				;MSH148
									;MSH148
	.ENDC								;MSH148
									;MSH148
	BR	110$		;INDICATE FLAGS ALREADY EXIST		;**-1

;+
; **-$DRELE-ELIMINATE/UNLOCK GROUP GLOBAL EVENT FLAGS FOR DIRECTIVE	;MSH148
; **-$ELIM-ELIMINATE GROUP GLOBAL EVENT FLAGS FOR EXECUTIVE		;MSH148
;									;**-1
; THE ELIMINATE GROUP GLOBAL EVENT FLAGS DIRECTIVE ELIMINATES THE	;MSH148
; GROUP GLOBAL EVENT FLAGS FOR A SPECIFIED GROUP. IF THE ISS      UING	;MSH148
; TASK HAD LOCKED THE EVENT FLAGS VIA A PREVIOUSLY ISSUED CREATE	;MSH148
; GROUP GLOBAL EVENT FLAGS DIRECTIVE, THEY WILL ALSO BE UNLOCKED.	;MSH148
;									;MSH148
; THE UNLOCK GROUP GLOBAL EVENT FLAGS DIRECTIVE UNLOCKS THE EVENT	;MSH148
; FLAGS FOR THE ISSUING TASK'S GROUP.					;MSH148
;									;**-1
; DPB FORMAT FOR THE ELIMINATE DIRECTIVE:				;MSH148
;									;**-1
;	WD. 0 -- DIC. (159.),DBP SIZE(2.)
;	WD. 1 -- GROUP NUMBER
;									;MSH148
; DPB FORMAT FOR THE UNLOCK DIRECTI      VE:					;MSH148
;									;MSH148
;	WD. 0 -- DIC(159.),DPB SIZE(1.)					;MSH148
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK
;	R3=ADDRESS OF THE DBP + 2
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF NON-P      RIVILEGED
;			TASK ATTEMPTS TO ELIMINATE FLAGS FOR ANOTHER GROUP.
;		DIRECTIVE STATUS OF 'D.RS17' IS RETURNED IF EVENT FLAG
;			BLOCK IS ALREADY MARKED FOR DELETE, OR		;MSH148
;			ALREADY UNLOCKED.				;MSH148
;		DIRECTIVE STATUS OF 'D.RS91' IS RETURNED IF THE SPECIFIE;**-1
;			EVENT FLAG GROUP IS GREATER THAN 377.
;		DIRECTIVE STATUS OF 'D.RS97' IS RETURNED IF THE SPECIFIED
;			EVENT FLAG GROUP DOES NOT EXIST.
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF THE		;MSH148
;			DPB SIZE IS ILLEGAL.				      ;MSH148
;-

$DRELE::MOVB	-(R3),R0	;GET DPB SIZE				;MSH148
	CMPB	(R3)+,#2	;IS THIS THE ELIMINATE DIRECTIVE?	;MSH148
	BEQ	50$		;IF EQ YES				;MSH148
	ASR	R0		;IS THIS THE UNLOCK DIRECTIVE?		;MSH148
	BNE	120$		;IF NE NO, ILLEGAL DPB SIZE		;MSH148
	CALL	$UNLCK		;ATTEMPT TO UNLOCK THE EVENT FLAGS	;MSH148
	BCS	110$		;IF CS ALREADY UNLOCKED			;MSH148
$ELIM::	BNE	45$		;IF NE G.CNT<>0, DON'T ELIMINATE FLAGS	;MSH148
	TSTB	G.STAT(R1)	;MARKED FOR ELIMINATION?		;MSH148
	BNE	65$		;IF NE YES, ELIMINATE THE FL      AGS		;MSH148
45$:	RETURN			;					;MSH148
									;MSH148
50$:	CALL	300$		;LOOK FOR THE SPECIFIED EVENT FLAGS	;MSH148
	BCS	100$		;IF CS NOT FOUND			;**-12
	CMP	R2,R4		;ELIMINATING TASK'S OWN GROUP?		;MSH148
	BNE	60$		;IF NE NO, DON'T UNLOCK THEM		;MSH148
	BIT	#T3.GFL,(R5)	;ARE THE EVENT FLAGS LOCKED?		;MSH148
	BEQ	60$		;IF EQ NO				;MSH148
	BISB	#GS.DEL,G.STAT(R1) ;MARK THE FLAGS FOR DELETION		;MSH148
	CALL	200$		;UNLOCK THE EVENT FLAGS			;MSH148
	BEQ	65$		;IF EQ G.CNT=0, ELIMINATE THE FLAGS	;MSH      148
	RETURN			;CAN'T ELIMINATE THEM WHILE STILL USED	;MSH148
									;MSH148
60$:	TSTB	G.STAT(R1)	;ALREADY MARKED FOR DELETE?		;MSH148
	BNE	110$		;IF NE YES				;**-1
	ASSUME	1,GS.DEL						;MSH049
	INCB	G.STAT(R1)	;MARK IT FOR DELETE (GS.DEL)		;MSH049
	TST	G.CNT(R1)	;STILL BEING USED?			;**-1
	BNE	210$		;IF NE YES, DON'T ELIMINATE THEM YET	;MSH148
65$:	CALLR	$ELGEF		;ELIMINATE IT NOW			;MSH148
70$:	DRSTS	D.RS1		;ALLOCATION FAILURE			;**-2
80$:	DRSTS	D.RS91		;INVALID GROUP
90$:	DRSTS	D.RS16		;PRI      VILEGE VIOLATION
100$:	DRSTS	D.RS97		;GROUP NOT FOUND
110$:	DRSTS	D.RS17		;FLAGS ALREADY EXIST OR MARKED FOR DELETE
120$:	DRSTS	D.RS99		;ILLEGAL DPB SIZE			;MSH148
									;MSH148
200$:	BIC	#T3.GFL,(R5)	;MARK TCB AS NOT HAVING LOCKED EFNS	;MSH148
									;MSH148
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH148
	DECB	T.GGF-T.ST3(R5)	;UNLOCK					;MSH148
									;MSH148
	.ENDC								;MSH148
									;MSH148
	DEC	G.CNT(R1)	;UNLOCK THE EVENT FLAGS			;MSH148
210$:	RETURN			;					;MSH148
				      					;MSH148
300$:	ADD	#T.ST3,R5	;POINT TO THIRD STATUS WORD OF TCB	;MSH148
	MOVB	H.CUIC+1(R4),R2	;GET TASK'S GROUP NUMBER		;MSH148
	MOV	(R3),R4		;GET SPECIFIED GROUP NUMBER		;MSH148
	BNE	310$		;IF NE ONE WAS SPECIFIED		;MSH148
	MOV	R2,R4		;ASSUME TASK'S OWN GROUP		;MSH148
	BR	325$		;JOIN COMMON CODE			;MSH148
310$:	BIT	#T3.PRV,(R5)	;ALLOWED TO SPECIFY ANY GROUP?		;MSH148
	BNE	320$		;IF NE YES				;MSH148
	CMPB	R4,R2		;ATTEMPTING TO SPECIFY ANOTHER GROUP?	;MSH148
	BNE	90$		;IF NE YES				;MSH148
32      0$:	CMP	R4,#377		;LEGAL GROUP NUMBER?			;MSH148
	BHI	80$		;IF HI NO				;MSH148
325$:	CALLR	$SRGEF		;TRY TO FIND THE GROUP'S CONTROL BLOCK	;MSH148
									;MSH148
;+									;MSH148
; **-$UNLCK-UNLOCK GROUP GLOBAL EVENT FLAGS				;MSH148
;									;MSH148
; THIS ROUTINE WILL UNLOCK THE GROUP GLOBAL EVENT FLAGS FOR THE		;MSH148
; TASK'S GROUP IF THE TASK HAS THEM LOCKED FROM A PREVIOUSLY		;MSH148
; ISSUED CREATE GROUP GLOBAL EVENT FLAGS DIRECTIVE.			;MSH148
;									;MSH148
; INPUTS:								;MSH14      8
;									;MSH148
;	R4=ADDRESS OF THE CURRENT TASK'S HEADER				;MSH148
;	R5=ADDRESS OF THE CURRENT TASK'S TCB				;MSH148
;									;MSH148
; OUTPUTS:								;MSH148
;									;MSH148
;	C=1 IF THE EVENT FLAGS FOR THE TASK'S GROUP WERE NOT		;MSH148
;		LOCKED BY THE TASK					;MSH148
;	C=0 IF THE EVENT FLAGS ARE SUCCESSFULLY UNLOCKED.		;MSH148
;									;MSH148
;		R4 IS DESTROYED BY THIS ROUTINE				;MSH148
;		R5 HAS #T.ST3 ADDED TO IT				;MSH148
;									;MSH148
;-									;MSH148
									;MS      H148
$UNLCK::ADD	#T.ST3,R5	;POINT TO THIRD TASK STATUS WORD	;MSH148
	BIT	#T3.GFL,(R5)	;ARE THE TASK'S GRP GLOBALS LOCKED?	;MSH148
	BEQ	400$		;IF EQ NO, DON'T UNLOCK THEM		;MSH148
	MOVB	H.CUIC+1(R4),R4	;GET TASK'S GROUP CODE			;MSH148
	CALL	$SRGEF		;FIND THE EVENT FLAG CONTROL BLOCK	;MSH148
	BCC	200$		;JOIN COMMON CODE WITH DIRECTIVE	;MSH148
	CRASH			;ERROR-TASK LOCKED TO NONEXISTENT FLAGS	;MSH148
									;MSH148
400$:	SEC			;TASK NOT LOCKED TO EVENT FLAGS		;MSH148
	RETURN			;					;MSH148
	.DSABL      	LSB

;+									;**-56
; **-$GTGEF-GET ADDRESS OF GROUP GLOBAL EVENT FLAGS
;
; THIS ROUTINE SEARCHES FOR THE GROUP GLOBAL EVENT FLAGS ASSOCIATED WITH
; A TASK. IF THE EVENT FLAGS EXIST, THE ADDRESS OF THE EVENT FLAG	;MSH049
; WORD IS RETURNED IN R1.						;MSH049
;									;**-2
; INPUTS:
;
;	R5=TCB ADDRESS OF TASK.
;
; OUTPUTS:
;
;	C=0 IF GROUP GLOBAL EVENT FLAGS WERE FOUND
;		R1=ADDRESS OF GROUP GLOBAL EVENT FLAGS
;
;	C=1 IF EVENT FLAGS WERE NOT FOUND OR IF THE SPECIFIED		;MSH049
;	          TASK IS CHECKPOINTED.					;MSH049
;									;**-2
;-									;**-2

$GTGEF::MOV	R0,-(SP)	;SAVE REGISTERS
	MOV	R4,-(SP)	;
	MOV	T.PCB(R5),R4	;GET TASK REGION PCB ADDRESS
	BIT	#TS.OUT,T.STAT(R5) ;TASK CHECKPOINTED?
	SEC			;ASSUME IT WAS				;MSH049
	BNE	10$		;IF NE YES				;MSH049
	MOV	P.HDR(R4),R4	;GET TASK HEADER ADDRESS		;**-3
	MOVB	H.CUIC+1(R4),R4	;GET GROUP NUMBER
	CALL	$SRGEF		;SEARCH FOR GROUP GLOBAL EVENT FLAGS
	BCS	10$		;IF CS NOT FOUND			;MSH049
	ADD	#6,R1		;POINT TO FIRST EVENT FLAG WORD   ”   		;**-1
10$:	MOV	(SP)+,R4	;RESTORE REGISTERS			;MSH049
	MOV	(SP)+,R0	;					;**-1
	RETURN
									;**-1
	.ENDC	;G$$EFN							;**-28

	.END
 ”          ÔðskQ	› c,        	.TITLE	DRDRV
	.IDENT	/02.14/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 02.14
;
; P. J. BEZEREDI 08-SEP-77
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	R. T. PERRON
;
; MODIFIED BY:
;
;	R. T. PERRON 13-JUN-79
;
;		RP014 -- CORRECT RH11 SUPPORT FOR 22-BIT ADDRESSING
;
;	R. T. PERRON 02-JUL-79
;
;		RP016 --       ADD RM80 SUPPORT
;
;	R. T. PERRON 01-AUG-79
;
;		RP017 -- ADD RM05 SUPPORT
;
;	R. T. PERRON 02-AUG-79
;
;		RP018 -- CORRECT RP07 SUPPORT
;
;	R. T. PERRON 06-AUG-79
;
;		RP021 -- CORRECT ERROR RECOVERY FOR LAST BLOCK TRANSFERED
;
;	R. T. PERRON 12-DEC-79
;
;		RP024 -- CORRECT REGISTER USAGE FOR FORMAT ERROR
;
;	P. J. CARR	18-APR-80
;
;		PJC004 -- REMOVE M$$IXD STUFF
;
;	P. J. CARR	28-APR-80
;
;		PJC005 -- CORRECT ERROR RECOVERY FOR CLASS B ERRORS
;			  DURING HEADER
;
;	R. T. PERR      ON 21-NOV-80
;
;		RP041 -- CHANGE INTERFACE TO COMMON ECC ROUTINE
;
;	P. J. CARR	27-MAR-81
;
;		PJC023 -- CORRECT ILLEGAL FUNCTION CODE (IE.IFC) HANDLING
;
;	P. J. BEZEREDI 15-APR-81
;
;		PB237 -- MAKE BETTER USE OF EIS.
;
;	P. J. CARR	12-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
;	R. T. PERRON	16-OCT-81
;
;		RP075 -- CORRECT NON-EIS ADDRESS CALCULATION IN ECC CODE
;
;	P. J. CARR	19-OCT-81
;
;		PJC038 -- CLEAN UP CODE
;
; RH70/11 - RM03/RM05/RP07/RM80 DISK PACK DRIVER
;
;       MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;
; DEVICE REGISTER AND STATUS BIT DEFINITIONS
;

RMCS1=0				;CONTROL STATUS REGISTER 1

TRE=40000			;TRANSFER ERROR
MCPE=20000			;MASSBUS CONTROL PARITY ERROR


RMWC=2				;WORD COUNT REGISTER
RMBA=4				;BUFFER ADDRESS REGISTER
RMDA=6				;DESIRED TRACK/SECTOR REGISTER

RMCS2=10			;CONTROL STATUS REGISTER 2

DLT=100000			;DATA LATE ERROR
WCE=400      00			;WRITE CHECK ERROR
UPE=20000			;UNIBUS PARITY ERROR
NED=10000			;NONEXISTENT DISK ERROR
NEM=4000			;NONEXISTENT MEMORY ERROR
PGE=2000			;PROGRAMMING ERROR
MXF=1000			;MISSED TRANSFER ERROR
MDPE=400			;MASSBUS DATA PARITY ERROR

RMDS=12				;DRIVE STATUS REGISTER

ERR=40000			;ERROR SUMMARY BIT
MOL=10000			;MEDIUM ONLINE
WRL=4000			;WRITE LOCKED DRIVE
DRY=200				;DRIVE READY
VV=100				;VOLUME VALID
OM=1				;OFFSET MODE ACTIVE


RMER1=14			;ERROR SUMMARY REGISTER

DCK=100000			;DATA CH      ECK ERROR
UNS=40000			;DRIVE UNSAFE
OPI=20000			;OPERATION INCOMPLETE
DTE=10000			;DRIVE TIMING ERROR
WLE=4000			;WRITE LOCK ERROR
IAE=2000			;INVALID DISK ADDRESS
AOE=1000			;ADDRESS OVERFLOW
HCRC=400			;HEADER CRC ERROR
HCE=200				;HEADER COMPARE ERROR
ECH=100				;ECC HARD ERROR
WCF=40				;WRITE CLOCK FAILURE
FER=20				;FORMAT ERROR
PAR=10				;MASSBUS CONTROL/DATA BUS PARITY ERROR
RMR=4				;REGISTER MODIFY REFUSED
ILR=2				;ILLEGAL REGISTER
ILF=1				;ILLEGAL FUNCTION


RMAS=16				;ATTENT      ION SUMMARY REGISTER
RMLA=20				;LOOKAHEAD REGISTER
RMDBR=22			;DATA BUFFER REGISTER
RMMR=24				;MAINTENENCE REGISTER
RMDT=26				;DRIVE TYPE REGISTER
RMSN=30				;DRIVE SERIAL NUMBER

RMOF=32				;DRIVE OFFSET REGISTER

CMOD=100000			;COMMAND MODIFIER
MTD=40000			;MOVE TRACK DESCRIPTOR
FMT16=10000			;FORMAT (1=16 BIT)
ECI=4000			;ECC INHIBIT
HCI=2000			;HEADER COMPARE INHIBIT
SSEI=1000			;SKIP SECTOR ERROR INHIBIT		; RP016


RMDC=34				;DESIRED CYLINDER NUMBER

RMER2=42			;ERROR REGISTER #2      

BSE=100000			;BAD SECTOR ERROR
SKI=40000			;SEEK INCOMPLETE ERROR
IVC=10000			;INVALID COMMAND ERROR
LSC=4000			;LOSS OF SECTOR CLOCK ERROR
LBC=2000			;LOSS OF BIT CLOCK ERROR
DVC=200				;DEVICE CHECK ERROR
SSE=40				;SKIP SECTOR ERROR			; RP016
DPE=10				;MASSBUS DATA PARITY ERROR

RMEC1=44			;ECC POSITION REGISTER
RMEC2=46			;ECC PATTERN REGISTER
RMBAE=50			;BUS ADDRESS EXTENSION REGISTER


;									;**-7
; ERROR RETRY COUNT
;

RETRY=8.			;CONTROLLER ERROR RETRY COUNT (NON-ECC ERROR      S)

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER)
;

CNTBL:	.BLKW	R$$M11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$M11		;RETRY COUNT FOR CURRENT OPERATION


	.IF DF D$$IAG

DGTBL:	.BLKW	R$$M11		;DIAGNOSTIC PARAMETER TABLE

	.ENDC




	.IF GT	R$$M11-1

TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC


	.IF DF	R$$MOF

OFFAD:	.BLKW	R$$M11		;ADDRESS OF CURRENT OFFSET VALUE

;
; OFFSET POSITIONING VALUE TABLE
;

OF      FTB:	.WORD	FMT16!0		;PLUS OFFSET
	.WORD	FMT16!200	;MINUS OFFSET
	.WORD	0		;TERMINATOR

	.ENDC


;+									; RP016
; **-PRMTBL-DEVICE SPECIFIC PARAMETER TABLE				; RP016
;									; RP016
; MACRO FORMAT: LBN, TRK, SEC, CE					; RP016
; WHERE:								; RP016
;	LBN 	-	MAXIMUM NUMBER OF BLOCKS ON DEVICE (DOUBLE WORD); RP016
;	TRK	-	NUMBER OF TRACKS PER CYLINDER			; RP016
;	SEC	-	NUMBER OF SECTORS PER TRACK			; RP016
;	CE	-	MAXIMUM NUMBER OF BLOCKS IN CE CYLINDERS	; RP016
;-									; RP016
	.M      ACRO	DVPRM	LBN, TRK, SEC, CE				; RP016
	.WORD	LBN							; RP016
	.BYTE	SEC							; RP016
	.BYTE	TRK							; RP016
	.WORD	CE							; RP016
	.ENDM	DVPRM							; RP016
									; RP016
	.WORD	0		;POINTER TO DEVICE SPECIFIC PARAMETERS	; RP016
PRMTBL:				;DEVICE SPECIFIC PARAMETER TABLE	; RP016
DVPRM	<2,1140>, 5, 32., 0		; RM03				; RP016
DVPRM	<2,1140>, 5, 32., 0		; RM03 PHYSICAL GEOMETRY	; RP016
DVPRM	<3,131656>, 14., 31., 2*14.*31.	; RM80				; RP016
DVPRM	<3,152700>, 14., 32., 2*14.*32.	; RM80 PH      YSICAL GEOMETRY	; RP016
DVPRM	<7,121240>, 19., 32., 0		; RM05				; RP017
DVPRM	<7,121240>, 19., 32., 0		; RM05 PHYSICAL GEOMETRY	; RP017
DVPRM	<17,60600>, 32., 50., 2*32.*50.	; RP07				; RP018
DVPRM	<17,60600>, 32., 50., 2*32.*50.	; RP07 PHYSCIAL GEOMETRY	; RP018
	.WORD	0		;END OF TABLE				; RP018
									; RP018
									; RP018
	.IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

;
; DIAGNOSTIC FUNCTION TABLE
;
FUNTBL:	.BYTE	107, IO.HMS!IQ.UMD&377
	.BYTE	105      , IO.BLS!IQ.UMD&377
FUNTB0:	.BYTE	115, IO.OFF!IQ.UMD&377
	.BYTE	135, IO.DGN!IQ.UMD&377
	.BYTE	151, IO.WCK!IQ.UMD&377
FUNTB1:	.BYTE	171, IO.RPD!IQ.UMD&377					; RP016
	.BYTE	161, IO.WPD!IQ.UMD&377					; RP016
	.BYTE	171, IO.CER!IQ.UMD&377					; RP016
	.BYTE	161, IO.CEW!IQ.UMD&377					; RP016
FUNTB2:	.BYTE	173, IO.RDH!IQ.UMD&377					; RP016
	.BYTE	163, IO.WDH!IQ.UMD&377					;**-1
	.BYTE	175, IO.RTD!IQ.UMD&377
	.BYTE	165, IO.WTD!IQ.UMD&377
FUNTB3:	.BYTE	165, IO.TDD!IQ.UMD&377					; RP016
FUNTBE:
      
	.ENDC


;
; DRIVER DISPATCH TABLE
;

$DRTBL::.WORD	DRINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	DRCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DROUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DRPWF		;POWER FAIL ENTRY POINT

;+
; **-DRINI-RH70/11 - RM03/RM05/RP07/RM80 DISK PACK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTR      OLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-      

	.ENABL	LSB
10$:	RETURN			;REF LABEL
DRINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	10$		;IF CS, CONTROLLER BUSY OR NO REQUEST

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RH70/11 - RM03/RM05/RP07/RM80 DISK PACK I/O REQUEST PACKET FORMAT
;
;	WD. 00 -- I/O QUEU      E THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS       OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- DIAGNOSTIC SUPPLIMENTAL PARAMETER ELSE NOT USED.
;	WD. 16 -- HIGH PART OF LOGICAL BLOCK NUMBER AND HIGH BYTE NOT USED
;	WD. 17 -- LOW PART OF LOGICAL BLOCK NUMBER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLK ADRS.
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000).
;

	MOV	R5      ,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB


	.IF DF D$$IAG

	MOV	I.PRM+6(R1),DGTBL(R3) ;SAVE DIAGNOSTIC PARAMETERS

	.ENDC


	CLR	I.PRM+6(R1)	;INITIALIZE FLAGS
	CALL	660$		;DETERMINE DEVICE TYPE			; PJC038


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP041
	BNE	20$		;IF NE YES -- DOES NOT UMR'S		; PJC038
	CALL	$STMAP		;MAP UNIBUS TO MEMORY			;**-2

	.ENDC


	ASL	U.BUF(R5)	;SHIFT ADDRESS EXTENSION BITS INTO PLACE
	ASL	U.BUF(R5)	;
	ASL	U.BUF(R5)	;
	ASL	      U.BUF(R5)	;
20$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	D$$IAG

	CMPB	#IO.HMS/256.,I.FCN+1(R1)  ;DIAGNOSTIC FUNCTION?
	BNE	50$		;IF NE NO				; PJC038
	MOV	#FUNTBL,R0	;GET ADDRESS OF FUNCTION TABLE		;**-1
	MOV	#RETRY,RTTBL(R3)  ;SET RETRY COUNT			; RP016
	CALL	600$		;SET OTHER RECOVERY PARAMETERS		; PJC038
30$:	MOVB	(R0)+,U.BUF(R5)	;LOAD CONTROLLER FUNCTION CODE		; PJC038
	CMPB	(R0)+,I.FCN(R1)	;IS IT THE CORRECT CODE?		;**-1
	BEQ	40$		;IF EQ YES				; PJC038
	CMP	#FUNTBE,R0	;END OF TA      BLE?				;**-1
	BNE	30$		;IF NE NO				; PJC038
	MOV	#IE.IFC&377,R0	;FUNCTION IS ILLEGAL			;**-1
	JMP	390$		;GO REPORT IT				; PJC038
40$:	CMPB	#10,U.CW2(R5)	;IS IT AN RP07?				; PJC038
	BNE	80$		;IF NE NO				; PJC038
	CMP	#FUNTB2,R0	;IS IT A HEADER FUNCTION?		; RP016
	BLO	80$		;IF LO NO				; PJC038
	BIS	#CMOD,I.PRM+6(R1)  ;SET COMMAND MODIFIER		; RP016
	CMP	#FUNTB3,R0	;IS TRACK DESCRIPTOR DISPLACED?		; RP016
	BNE	80$		;IF NE NO				; PJC038
	BIS	#MTD,I.PRM+6(R1)  ;SET MOVE TRACK DESCRIPTOR BIT	; RP      016
	BR	80$		;					; PJC038
									;**-10
	.ENDC


50$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION		; PJC038
	MOVB	#171,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION		;**-1
	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION?
	BHIS	60$		;IF HIS, FUNCTION IS LEGAL		; PJC038
	JMP	390$		;FUNCTION IS ILLEGAL			; PJC038
60$:	BEQ	70$		;IF EQ, FUNCTION IS READ		; PJC038
	SUB	#10,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION	;**-3
70$:	MOV	#RETRY,RTTBL(R3) ;SET RETRY COUNT			; PJC038
	CALL	600$		;SET OT      HER RECOVERY PARAMETERS		; PJC038
	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER		;**-2
	CMPB	#IO.WLB/256.,I.FCN+1(R3)  ;WRITE COMMAND ?
	BNE	100$		;IF NE NO				; PJC038
	BITB	#IO.WLT&377,I.FCN(R3)  ;WRITE LAST TRACK FUNCTION ?	;**-1
	BNE	100$		;IF NE YES				; PJC038
	MOV	R1,-(SP)	;SAVE POINTER FOR $BLKC1		; RP016
	MOV	PRMTBL-2,R1	;GET POINTER FOR PROPER DEVICE		; RP016
	CLR	-(SP)		;GET A WORKING REGISTER			; RP016
	BISB	4(R1),(SP)	;GET SETORS/TRACK			; RP016
	ADD	(SP)+,I.PRM+12(R3)  ;INCREMENT BLOCK N      UMBER BY 1 TRACK	; RP016
	ADCB	I.PRM+10(R3)	;ADD THE CARRY				; RP016
	MOV	(SP)+,R1	;RETIEVE POINTER FOR $BLKC1		; RP016
	CALL	$BLKC1		;SEE IF WRITE IS TO BAD SECTOR FILE	; RP016
	MOV	PRMTBL-2,R1	;GET POINTER FOR PROPER DEVICE		; RP016
	CLR	-(SP)		;GET A WORKING REGISTER			; RP016
	BISB	4(R1),(SP)	;GET SECTORS/TRACK			; RP016
	SUB	(SP)+,R0	;CORRECT THE BLOCK NUMBER		; RP016
	SBC	R2		;AND THE HIGH BLOCK NUMBER		; RP016
	BR	100$		;CONTINUE				; PJC038
80$:	CALL	760$		;CHECK FOR DIAGNOSTIC FUNCTION		      ; PJC038
	BCC	90$		;IF CC NO				; PJC038
	BIS	#SSEI,I.PRM+6(R1)  ;SET SKIP SECTOR INHIBIT BIT		; RP016
90$:	MOV	R1,R3		;SAVE I/O PACKET ADDRESS		; PJC038
	ADD	#I.PRM+11,R1	;POINT PAST HIGH PART OF LBN		; RP016
	CLRB	(R1)+		;CLEAR EXCESS BYTE			; RP016
	MOV	(R1),R0		;GET LOW PART OF LBN			; RP016
	MOV	-(R1),R2	;GET HIGH PART OF LBN			; RP016
100$:	CALL	630$		;SPECIAL ADDRESS CALCULATION ROUTINE	; PJC038
									;**-26

	.IF DF	R$$MOF

	BIS	#1,I.PRM+6(R3)	;SET OFFSET MODE INACTIVE

	.ENDC

      
;									;**-7
; INITIATE I/O OPERATION
;

110$:				;REF LABEL				; PJC038
									;**-2

	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP041
	BNE	120$		;IF NE YES -- DOES NOT USE UMR'S	; PJC038
	CALL	$MPUBM		;MAP UNIBUS TO MEMORY			;**-2
120$:				;REF LABEL				; PJC038
									;**-1
	.ENDC


	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR			; RP014
	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET
	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	ADD	#10,R2      		;POINT TO SECOND CSR
	MOV	#40,(R2)	;CLEAR RH11 CONTROLLER AND ALL DRIVES
	MOVB	U.UNIT(R5),(R2)	;SELECT PROPER DRIVE
	MOV	I.PRM+12(R1),-(R2)  ;INSERT TRACK/SECTOR ADDRESS
	MOV	U.BUF+2(R5),-(R2)  ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	;INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		;CONVERT TO WORD COUNT
	NEG	(R2)		;MAKE NEGATIVE WORD COUNT
	MOV	#23,-(R2)	;EXECUTE PACK ACK FUNCTION TO SET VV


	.IF DF D$$IAG

	BIT	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPERATION?		; RP016
	BEQ	130$		;IF EQ NO				;       PJC038
	MOVB	S.CON(R4),R0	;GET CONTROLLER NUMBER			;**-2
	MOV	DGTBL(R0),RMMR(R2)  ;SET DIAGNOSTIC PARAMETERS		; RP016
130$:				;REF LABEL				; PJC038
									;**-2
	.ENDC


	MOV	#IE.DNR&377,R0	;ASSUME DRIVE NOT READY
	MOV	I.PRM+10(R1),RMDC(R2)  ;SET DESIRED CYLINDER ADDRESS
	MOV	RMDS(R2),R3	;GET CURRENT DRIVE STATUS
	COM	R3		;COMPLEMENT STATUS
	BIT	#MOL!DRY!VV,R3	;DRIVE READY?
	BNE	140$		;IF NE NO				; PJC038
	BIT	#UNS,RMER1(R2)	;DRIVE UNSAFE?				;**-1
	BEQ	160$		;IF EQ NO				; PJC038
140$      :				;REF LABEL				; PJC038
									;**-2

	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	190$		;IF NE YES				; PJC038
									;**-1
	.IFTF


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPERATION?
	BEQ	150$		;IF EQ NO				; PJC038
	JMP	320$		;PROCESS DIAGNOSTIC NOT READY		; PJC038
150$:				;REF LABEL				; PJC038
									;**-3
	.ENDC


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DRIVE NOT READY ERROR

	.ENDC


	JMP	380$		;FINSH I/O				; PJC038
160$:				;RE      F LABEL				; PJC038
									;**-2
	.IFT

	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC


	MOV	#FMT16,-(SP)	;GET FORMAT BIT


	.IF DF	R$$MOF!D$$IAG

	BIT	#40,RMDT(R2)	;IS IT AN RP07?
	BNE	170$		;IF NE YES				; PJC038
	BITB	#1,I.PRM+6(R1)	;WAS OFFSET ACTIVE ?			;**-1
	BNE	170$		;IF NE NO				; PJC038
	MOVB	#15,(R2)	;LOAD OFFSET FUNCTION			;**-1
170$:	BIS	I.PRM+6(R1),(SP) ;SET OTHER BITS			; PJC038
									;**-1
	.ENDC


	MOV	(SP)+,RMOF(R2)	;LOAD THE OFFSET REGISTER


	.      IF DF	E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE IN BIT MAP

	.ENDC


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP041
	BEQ	180$		;;;IF EQ NO -- DOES USE UMR'S		; PJC038
	MOVB	U.BUF+1(R5),RMBAE(R2)  ;;;SET ADDRESS EXTENSION BITS	;**-2
	MOVB	U.BUF(R5),(R2)	;;;START FUNCTION
	RETURN			;;;;

	.ENDC


180$:	MOV	U.BUF(R5),(R2)	;;;START FUNCTION			; PJC038


;
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;

DRCAN::	RETURN			;;;NOP FOR RM03/RM05/      RP07/RM80

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPIN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DRPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS DRIVE CURRENTLY BUSY?
	BEQ	200$		;IF EQ NO				; PJC038
190$:	M      OVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC038
200$:	BISB	#US.SPU,U.STS(R5) ;SET DRIVE SPINNING UP		; PJC038

	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND

;+
; **-$DRINT RH70/RH11 - RM03/RM05/RP07/RM80 DISK PACK CONTROLLER
;	INTERRUPT HANDLER
;-

	INTSE$	DR,PR5,R$$M11	;;;SAVE REGISTERS AND SET PRIORITY
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	#IS.SUC&377,R0	;ASSUM      E SUCCESSFUL TRANSFER
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BIT	#HCRC!HCE,RMER1(R2) ;HEADER CRC OR HEADER COMPARE ERROR?; PJC005
	BNE	240$		;IF NE YES				; PJC038
	BIT	#SSE,RMER2(R2)	;SKIP SECTOR ERROR?			; PJC005
	BEQ	240$		;IF EQ NO				; PJC038
	BIS	#SSEI,I.PRM+6(R1)  ;SET SKIP SECTOR ERROR INHIBIT	; RP016
	MOVB	#11,(R2)	;CLEAR SELECTED DRIVE ERRORS		; RP016
	MOV	RMOF(R2),-(SP)	;GET OFFSET REGISTER			; RP016
	BIS	I.PRM+6(R1),(SP)  ;SET REMAINING BITS IN REGISTER	; RP016
	MOV	(SP)+,RMOF(R2)	      ;RE-LOAD OFFSET REGISTER		; RP016
	MOV	RMWC(R2),R0	;GET NEGATIVE WORDS REMAINING		; RP016
	BNE	210$		;IF NE WE HAD A PARTIAL TRANSFER	; PJC038
	MOV	#-1,R0		;FAKE A PARTIAL TRANSFER		; PJC005
210$:	ASL	R0		;CONVERT TO NEGATIVE BYTES		; PJC038
	ADD	U.CNT(R5),R0	;CALCULATE BYTES ACTUALLY TRANSFERRED	; PJC005
	BIC	#777,R0		;GET BLOCKS ACTUALLY TRANSFERRED	; PJC005
	CALL	700$		;BACKUP TO START OF BLOCK IN ERROR	; PJC038
	CALL	760$		;CHECK FOR DIAGNOSTIC FUNCTION		; PJC038
	BCS	230$		;IF CS YES				; PJC0      38
220$:	INCB	I.PRM+12(R1)	;INC TO NEXT SEQUENTIAL SECTOR		; PJC038
230$:	JMP	110$		;RESTART FUNCTION			; PJC038
240$:	BIT	#SSEI,RMOF(R2)	;SKIP SECTOR ERROR INHIBIT SET?		; PJC038
	BNE	250$		;IF NE YES				; PJC038
	BIC	#SSEI,I.PRM+6(R1)  ;RESET SKIP SECTOR ERROR INHIBIT	; PJC005
250$:				;REF LABEL				; PJC038


	.IF DF	D$$IAG

	CALL	760$		;CHECK FOR DIAGNOSTIC FUNCTION		; PJC038
	BCS	320$		;IF CS YES				; PJC038
									;**-2
	.ENDC


	BIT	#70,(R2)	;RECALIBRATE COMMAND ?
	BNE	260$		;IF N      E NO				; PJC038
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		;**-1
	BITB	#IQ.X,I.FCN(R1)  ;RETIRES INHIBITED ?
	BNE	340$		;IF NE YES				; PJC038
	BIT	#ERR,RMDS(R2)	;ERROR SET ?				;**-1
	BEQ	330$		;IF EQ NO				; PJC038
	CLR	R1		;SHOW NO BYTES TRANSFERED		;**-1
	JMP	390$		;FINSH UP				; PJC038
260$:	BIT	#TRE!MCPE,(R2)	;ANY ERRORS DURING TRANSFER?		; PJC038
	BEQ	350$		;IF EQ NO				; PJC038
									;**-3

	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DEVICE ERROR

	.ENDC


	MOV	#IE.VER&377,R0	;AS      SUME UNRECOVERABLE ERROR
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETIRES ?
	BNE	270$		;IF NE YES, SEE IF DRIVE NEEDS A RECAL	; PJC038
	BIT	#IVC!LSC!LBC!DVC!DPE,RMER2(R2)  ;CLOCK ERROR OR OTHER SE;**-1
	BNE	330$		;IF NE YES				; PJC038
	BIT	#NED!NEM!PGE,RMCS2(R2)  ;HARD ERROR ?			;**-1
	BNE	380$		;IF NE YES				; PJC038
	MOV	RMER1(R2),R1	;COPY ERROR REGISTER 1			; PJC005
	BIT	#UNS!IAE!AOE!RMR!ILR!ILF,R1  ;HARD ERROR?		; PJC005
	BNE	380$		;IF NE YES				; PJC038
270$:	BIT	#SKI,RMER2(R2)	;SEEK INCOMPLETE?			; P      JC038
	BNE	280$		;IF NE YES				; PJC038
	BIT	#HCRC,R1	;HEADER CRC ERROR?			; PJC005
	BNE	410$		;IF NE YES				; PJC038
	BIT	#HCE,R1		;HEADER COMPARE ERROR?			; PJC005
	BNE	280$		;IF NE YES				; PJC038
	BIT	#FER,R1		;FORMAT ERROR?				; RP024
	BEQ	290$		;IF EQ NO				; PJC038
	BR	380$		;YES					; PJC038
280$:	JMP	620$		;PROCESS SKI OR HCE ERRORS		; PJC038
290$:	BIT	#BSE,RMER2(R2)	;BAD SECTOR ERROR?			; PJC038
	BEQ	300$		;IF EQ NO				; PJC038
	MOV	#IE.BBE&377,R0	;BAD BLOCK ERROR			;**-19
	BR	380$		;      HARD ERROR				; PJC038
300$:	BIT	#WLE,RMER1(R2)	;WRITE LOCK ERROR?			; PJC038
	BEQ	330$		;IF EQ NO				; PJC038
	CLR	R1		;					; PJC005
	BR	390$		;					; PJC038
									;**-5

;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED
; UNLESS THE OPERATION WAS DIAGNOSTIC.  TIMEOUTS ARE USUALLY CAUSED
; BY POWER FAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE.
;

DROUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	310$      		;;;IF EQ NO				; PJC038
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#16.,S.STS(R4)	;;;HAVE WE WAITED 1 MINUTE YET?		; PJC029
	BEQ	310$		;;;IF EQ YES				; PJC038
	MTPS	#0		;;;ALLOW INTERRUPTS			;**-3
	JMP	110$		;RETRY ENTIRE OPERATION			; PJC038
310$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC038
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP		;**-2

	.ENDC


	CALL	$DTOER		;;;LOG DEVICE TIMEOUT


	.IF DF	D$$IAG

	BCC	330$		;IF CC, TIMEOUT DURING NORMAL FUNCTION	; PJC038      
320$:	CALL	$CRPAS		;PASS CONTROLLER REGISTERS TO TASK	; PJC038
	BR	380$		;DIAGNOSTIC PROCESSING COMPLETE		; PJC038
									;**-3
	.ENDC


330$:	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET		; PJC038
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?			;**-1
340$:	BNE	370$		;IF NE YES				; PJC038
	DECB	RTTBL(R3)	;ANY MORE RETRIES ?			;**-1


	.IF DF	R$$MOF

	BGT	400$		;IF GT YES				; PJC038
									;**-1
	.IFF

	BLE	370$		;IF LE NO				; PJC038
	JMP	110$		;					; PJC038
									;**-2
	.ENDC


      350$:				;REF LABEL				; PJC038
									;**-1
	.IF DF	D$$WCK

	BITB	#IO.WLC&377,I.FCN(R1)  ;WRITE FOLLOWED BY WRITE CHECK ?
	BNE	360$		;IF NE YES				; PJC038
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED BY MCR ?	;**-1
	BEQ	380$		;IF EQ NO				; PJC038
360$:	CMPB	#171,U.BUF(R5)	;WAS LAST FUNCTION A READ?		; PJC038
	BEQ	380$		;IF EQ YES				; PJC038
	CMPB	#161,U.BUF(R5)	;WAS LAST OPERATION A WRITE ?		;**-3
	BNE	380$		;IF NE NO				; PJC038
	MOVB	#151,U.BUF(R5)	;CHANGE OPERATION TO WRITE CHECK	;**-1      
	MOV	#RETRY,RTTBL(R3)  ;REINITIALIZE RETRY COUNT
	JMP	110$		;START WRITE CHECK			; PJC038
									;**-1
	.IFTF

370$:				;REF LABEL				; PJC038
									;**-1
	.IFT

	BIT	#WCE,RMCS2(R2)	; WRITE CHECK ERROR ?
	BEQ	380$		;IF EQ NO				; PJC038
	MOV	#IE.WCK&377,R0	;SET WRITE CHECK ERROR			;**-1

	.ENDC


380$:	MOV	S.PKT(R4),R3	;GET ADDRESS OF I/O PACKET		; PJC038
	MOV	RMWC(R2),R1	;WORDS NOT TRANSFER (2'S COMPLEMENT)	;**-1
	ASL	R1		;MAKE INTO A BYTE COUNT
	ADD	I.PRM+4(R3),R1	;CALCULATE BYTE      S TRANSFERED
	MOV	#TRE!11,(R2)	;CLEAR RH11 CONTROLLER AND DRIVE
390$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE STARTING RETRY COUNT

	.ENDC


	CALL	$IODON		;FINISH I/O OPERATION			;**-7
	JMP	DRINI		;PROCESS NEXT REQUEST


	.IF DF	R$$MOF

400$:	JMP	540$		;RETURN TO CENTERLINE			; PJC038
									;**-1
	.ENDC


;
; START ECC CORRECTION PROCEDURE
;      									;**-2

410$:				;REF LABEL				; PJC038
	CMPB	#171,U.BUF(R5)	;IS THIS A READ FUNCTION?		; RP041
	BEQ	330$		;IF EQ NO				; PJC038
	BIS	RMER2(R2),R1	;.OR. ERROR REGISTER 2			; RP041
	BISB	RMCS2+1,R1	;.OR. CONTROLLER REGISTERS		; RP041
	CMP	#DCK,R1		;ONLY DATA CHECK ERROR?			; RP041
	BNE	330$		;IF NE NO				; PJC038
	MOV	RMWC(R2),R0	;GET NEGATIVE NUMBER OF WORDS REMAINING	;**-12
	ASL	R0		;CONVERT TO NEGATIVE BYTES REMAINING
	ADD	U.CNT(R5),R0	;CALCULATE NUMBER OF BYTES TRANSFERED
									; R      P041
									; RP041
	.IF DF	R$$MOF							; RP041
									; RP041
	BEQ	530$		;IF EQ NONE TRANSFERED, TRY OFFSET RECOV; PJC038
									; RP041
	.IFF								; RP041
									; RP041
	BNE	420$		;IF NE SOME TRANSFERED			; PJC038
	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR		; RP041
	BR	330$		;AND GO ON				; PJC038
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
420$:	MOV	RMEC1,R1	;GET ECC ERROR POSITION			; PJC038
	MOV	RMEC2,R3	;GET ECC CORRECTION PATTERN		; PJC038      
	MOV	RMWC(R2),R2	;GET REMAINING WORD COUNT		; PJC038
									; PJC038
	.IF DF	S$$ECC							; PJC038
									; PJC038
	CALL	$ECCOR		;CALL SHARED ECC ROUTINE		; PJC038
									; PJC038
	.IFF								; PJC038
									; PJC038
									;**-8
;
; SECOND CALCULATE BYTE OFFSET IN BLOCK AND POSITION PATTERN SHIFT COUNT
;

	MOV	R0,-(SP)	;SAVE BYTE COUNT			; RP041
	CLR	R0		;CLEAR HIGH ORDER ERROR POSITION	; RP041
	DEC	R1		;CONVERT TO RELATIVE BIT NUMBER		; RP041
									; RP041
									; RP041      
	.IF DF	 M$$EIS							; RP041
									; RP041
	DIV	#20,R0		;DIVIDE FOR:				; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
									; RP041
	.IFF								; RP041
									; RP041
	MOV	R1,R0		;COPY ECC ERROR POSITION		; RP041
	MOV	#20,R1		;SET DIVISOR TO CALCULATE:		; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
	CALL	$DIV		;PERFORM DIVISION			; RP041
									; RP041
	.ENDC								; RP041
									; RP041
								      	; RP041
	MOV	R0,-(SP)	;SAVE WORD POSITION			; RP041
	MOV	R2,-(SP)	;SAVE REMAINING WORD COUNT		; RP041
	CLR	R2		;CLEAR HIGH ORDER ERROR PATTERN		; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
430$:	ASHC	R1,R2		;SHIFT PATTERN INTO CORRECT POSITION	; PJC038
									; RP041
	.IFF								; RP041
									; RP041
430$:	DEC	R1		;ANY MORE SHIFTS LEFT TO PERFORM	; PJC038
	BLT	440$		;IF LT NO				; PJC038
	ASL	R3		;DOUBLE LEFT SHIFT			; RP041
	ROL	R2		;					; R      P041
	BR	430$		;					; PJC038
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
440$:	MOV	4(SP),R0	;RETRIEVE BYTES ACTUALLY TRANSFERED	; PJC038
	SUB	#510.,R0	;BACKUP TO BLOCK IN ERROR ...		; RP041
				;... OFFSET TO HIGH WORD IN ERROR	; RP041
									; RP041
									; RP041
	.IF DF	D$$IAG							; RP041
									; RP041
	CALL	$RELOP		;COMPUTE LOCATION IN PHYSICAL MEMORY	; RP041
									; RP041
	.IFF								; RP041
									; RP041
	MOV	R0,-(SP)	;SAVE BYTE OFFSET ON       STACK		; RP041
	MOV	U.BUF+2(R5),R1	;GET LOW 16 BITS OF ADDRESS		; RP041
									; RP041
									; RP041
	.IF DF	M$$MGE							; RP041
									; RP041
	MOVB	U.BUF+1(R5),R0	;GET HIGH BITS OF REAL ADDRESS		; RP041
									; RP041
									; RP041
	.IF DF	M$$EXT							; RP041
									; RP041
	BIT	#DV.EXT,U.CW1(R5)  ;CAN THIS CONTROLLER/UNIT DIRECTLY ..; RP041
				;... ADDRESS ALL OF PHYSICAL MEMORY	; RP041
	BNE	450$		;IF NE YES				; PJC038
	ADD	#<S.MPR+M.LGTH>,R4  ;POINT PAST PHYSCIAL BUFFER A      DDRESS	; RP041
				;CONTAINED IN UMR AREA			; RP041
	MOV	-(R4),R1	;GET LOW 16 BITS OF PHYSICAL BUFFER ADDR; RP041
	TSTB	-(R4)		;SKIP NEXT BYTE				; RP041
	MOVB	-(R4),R0	;GET HIGH 6 BITS OF PHYSICAL BUFFER ADDR; RP041
450$:	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			; PJC038
									; RP041
	.ENDC								; RP041
									; RP041
	.IFF								; RP041
									; RP041
	CLR	R0		;					; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	ADD	(SP)+,R1	;CALCULATE NEW START      ING ADDRESS ...	; RP041
	ADC	R0		;...					; RP041
									; RP041
									; RP041
	.IF DF	M$$MGE							; RP041
									; RP041
									; RP041
	.IF DF 	M$$EIS							; RP041
									; RP041
	ASHC	#10.,R0		;CALCULATE DISPLACEMENT AND BIAS	; RP041
	ASHC	#-10.,R1	;...					; RP041
									; RP041
	.IFF								; RP041
									; RP041
	MOV	#10.,-(SP)	;SET COUNT FOR 10 SHIFTS		; RP041
460$:	DEC	(SP)		;ANY MORE SHIFTS TO PERFORM		; PJC038
	BLT	470$		;IF LT NO				; PJC038
	ASL	R1		;DOUBLE LEFT       SHIFT R1 ...		; RP075
	ROL	R0		;... INTO R0				; RP075
	BR	460$		;					; PJC038
470$:	SWAB	R1		;SWAP BYTS				; PJC038
	ASR	R1		;SHIFT RIGHT R1				; RP075
	ASR	R1		;...					; RP075
	TST	(SP)+		;CLR THE STACK				; RP075
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	MOV	R0,KISAR6	;SET RELOCATION BIAS			; RP041
	ADD	#140000,R1	;SET DISPLACEMENT			; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
	.ENDC								; RP041
									; RP041      
									; RP041
	MOV	(SP)+,R0	;RETRIEVE REMAINING WORD COUNT		; RP041
	BPL	480$		;IF PL THIS MAY HAVE BEEN A PARTIAL BLOC; PJC038
				;TRANSFER				; PJC038
	CLR	R0		;ASSUME A WHOLE BLOCK WAS TRANSFERRED	; RP041
480$:	ADD	(SP),R1		;ADD IN ERROR WORD POSITION OFFSET ...	; PJC038
	ADD	(SP),R1		;... FOR BYTE ADDRESSING		; RP041
	ADD	(SP)+,R0	;ADD CORECTION OFFSET TO CORRECTION LIMI; RP041
	CMP	R0,#377		;					; RP041
	BHI	500$		;IF HI NOT AT ALL			; PJC038
	BEQ	490$		;IF EQ THEN ONLY ONE WORD		; PJC0      38
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
	XOR	R2,(R1)		;CORRECT HIGH ORDER WORD		; RP041
490$:	XOR	R3,-(R1)	;CORRECT LOW ORDER WORD			; PJC038
									; RP041
	.IFF								; RP041
									; RP041
	MOV	(R1),R0		;COPY HIGH ORDER DATA WORD		; RP041
	BIC	R2,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R2		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R2,(R1)		;PATTERN.OR.DATA WORD			; RP041
490$:	MOV	-(R1),R0	;COPY LOW ORDER DATA WORD		; PJC038
	BIC	R      3,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R3		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R3,(R1)		;PATTERN.OR.DATA WORD			; RP041
									; RP041
	.ENDC								; RP041
									; RP041
									; RP041
500$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER		; PJC038
	MOV	(SP)+,R1	;RESTORE BYTES TRANSFERRED		; RP041
	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX		; RP041
	MOV	S.CSR(R4),R2	;RESTORE CSR ADDRESS			; RP041
									;**-44
	.ENDC


	MOVB	#11,(R2)	;CLEAR DRIVE ERRORS
	CALL	6      00$		;RESET RECOVERY PARAMETERS		; PJC038
	SUB	R1,U.CNT(R5)	;ANY MORE WORDS TO TRANSFER?		;**-1
	BEQ	380$		;IF EQ NO				; PJC038
									;**-1

	.IF DF	M$$MGE


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP041
	BEQ	510$		;IF EQ NO -- DOES USE UMR'S		; PJC038
	MOVB	RMBAE(R2),U.BUF+1(R5)  ;SAVE MEMORY EXTENSION BITS	;**-2
	BR	520$		;					; PJC038
									;**-1
	.ENDC


510$:	MOVB	RMCS1+1(R2),U.BUF+1(R5)  ;SAVE MEMORY EXTENSION BITS	; PJC038
	BICB	#^C<3>,U.      BUF+1(R5)  ;CLEAR EXCESS BITS			;**-1
520$:				;REF LABEL				; PJC038
									;**-1

	.ENDC


	MOV	RMBA(R2),U.BUF+2(R5) ;SAVE BUFFER ADDRESS
	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET
	MOV	RMDC(R2),I.PRM+10(R1) ;SAVE CYLINDER ADDRESS
	MOV	RMDA(R2),I.PRM+12(R1) ;SAVE TRACK/SECTOR ADDRESS
	MOVB	U.BUF(R5),(R2)	;RESTART PREVIOUS OPERATION
	RETURN			;
									;**-71
;
; DATA ERROR & HEADER ERROR RECOVERY
;

530$:	MOV	S.PKT(R4),R1	;GET ADDRESS OF I/O PACKET		; PJC038
	TST	R0		;ANY GOOD SECT      ORS TRANSFERED ?		;**-2
	BEQ	550$		;IF EQ NO				; PJC038
									;**-1
;
; THE TRANSFER ENDED IN A DATA ERROR (EG, ECH, DTE, OR HCRC) BUT THERE
; WERE SECTORS TRANSFERED THAT CONTAINED GOOD DATA; THE GOOD DATA
; IS SAVED AND THE TRANSFER IS RETRIED FROM THE POINT OF ERROR.
;

	CALL	700$		;CALCULATE UPDATED DISK ADDRESS		; PJC038
540$:	BISB	#1,I.PRM+6(R1)	;SET UP RTC FLAG			; PJC038
	CALL	600$		;RESTORE OFFSET TABLE AND RETRY COUNT	; PJC038
	BR	590$		;					; PJC038
									;**-29
;
; NO GOOD       DATA WAS TRANSFERED - CHECK IF OFFSET SHOULD BE CHANGED
;

550$:				;REF LABEL				; PJC038
									;**-1

	.IF DF	R$$MOF

	BIT	#DCK!DTE!ECH,RMER1(R2)  ;DATA CHECK OR DRIVE TIMING ERROR?
	BNE	560$		;IF NE YES				; PJC038
	CMP	OFFAD(R3),#OFFTB  ;AT OFFSET ALREADY ?			;**-1
	BLO	560$		;IF LO NO				; PJC038
	BIS	#HCI,I.PRM+6(R1)  ;SET 'HCI' BIT			;**-1

	.IFTF

560$:	DECB	RTTBL+1(R3)	;CHANGE OFFSET?				; PJC038
	BGT	590$		;IF GT NO				; PJC038
	BIT	#40,RMDT(R2)	;IS IT AN RP07?				;**-2
	BNE      	570$		;IF NE YES				; PJC038
									;**-1
	.IFT

	ADD	#2,OFFAD(R3)	;UPDATE OFFSET POINTER
	CMP	#OFFTB+4,OFFAD(R3)  ;FINISHED ?
	BNE	580$		;IF NE NO				; PJC038
									;**-1
	.IFTF

570$:	MOV	#IE.VER&377,R0	;SET UNRECOVERABLE ERROR COUNT		; PJC038
	CLRB	RTTBL(R3)	;ZERO RETRY COUNT			; RP016
	JMP	380$		;DONE					; PJC038
									;**-3
	.IFT

580$:	MOVB	#2,RTTBL+1(R3)	;SET RECOVERY RETRY COUNT		; PJC038
									;**-2
	.ENDC


590$:	JMP	110$		;RETRY FUNCTION				; PJC038
									;**      -1
;
; SET RECOVERY & OFFSET PARAMETERS
;

600$:	MOVB	#16.,RTTBL+1(R3) ;INITIALIZE THE RETRY COUNT		; PJC038
									;**-1

	.IF DF	R$$MOF

610$:	MOV	#OFFTB-2,OFFAD(R3) ;SET OFFSET TABLE POINTER		; PJC038
									;**-1
	.ENDC


	RETURN			;

;
;SET RECOVERY RECALIBRATION FOR 'HCE' AND 'SKI' ERRORS
;

620$:	MOV	#TRE!11,(R2)	;CLEAR CONTROLLER AND DRIVE		; PJC038
	MOVB	S.ITM(R4),S.CTM(R4)  ;RESET TIMEOUT COUNT		;**-1
	MOVB	#107,(R2)	;LOAD THE RECALIBRATE COMMAND
	RETURN			;

;							      		; RP016
;	SPECIAL ADDRESS CALCULATION ROUTINE				; RP016
;									; RP016
630$:									; PJC038
									; RP016
	.IF DF	M$$EIS							; PB237
									; PB237
	MOV	R0,R1		;REPOSITION LBN				; PB237
	MOV	R2,R0		;...					; PB237
	MOV	PRMTBL-2,R2	;GET POINTER FOR PROPER DEVICE		; PB237
	CLR	R4		;GET A WORKING REGISTER			; PB237
	BISB	4(R2),R4	;GET SECTORS PER TRACK			; PB237
	DIV	R4,R0		;CALCULATE SECTOR NUMBER		; PB237
	MOVB	R1,I.PRM+12(R3)	;SAVE SECTOR NUMBER			; PB237
	MOV	R0,R1		;SET NEW       DIVIDEND			; PB237
	CLR	R0		;CLEAR HIGH BITS			; PB237
	CLR	R4		;GET READY FOR THE BISB			; PB237
	BISB	5(R2),R4	;GET TRACKS PER CYLINDER		; PB237
	DIV	R4,R0		;CALCULATE CYLINDER AND TRACK		; PB237
	MOV	R0,I.PRM+10(R3)	;SAVE CYLINDER  NUMBER			; PB237
	MOVB	R1,I.PRM+13(R3)	;SAVE TRACK NUMBER			; PB237
	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			; PB237
									; PB237
	.IFF								; PB237
									; PB237
	MOV	PRMTBL-2,R1	;GET POINTER FOR PROPER DEVICE		; RP016
	CLR	-(SP)		;GET A WORKING REGISTER	      		; RP016
	BISB	4(R1),(SP)	;GET TRACKS/CYLINDER			; RP016
	MOV	(SP)+,R1	;					; RP016
;
;	SPECIAL 32-BIT INTEGER DIVIDE ROUTINE
;
;	INPUTS:
;		R0=LOW-ORDER PART OF DIVIDEND
;		R1=POSITIVE DIVISOR
;		R2=HIGH-ORDER PART OF DIVIDEND
;
;	OUTPUTS:
;		R0=LOW-ORDER PART OF QUOTIENT
;		R1=UNDEFINED, FOR POSSIBLE FUTURE USE
;		R2=REMAINDER
;
	MOV	#16.,-(SP)	;SET DIVIDE LOOP COUNT			; RP016
640$:	ASL	R0		;DOUBLE LEFT SHIFT			; PJC038
	ROL	R2		;THESE TWO INSTRUCTIONS			;**-2
	CMP	R2,R1		;PARTIAL REM      AINDER LARGER THAN DIVISOR?
	BLO	650$		;IF LO NO				; PJC038
	SUB	R1,R2		;SUBTRACT OUT DIVISOR			;**-1
	INC	R0		;ACCUMULATE QUOTIENT
650$:	DEC	(SP)		;ANY MORE PARTIAL DIVIDES?		; PJC038
	BGT	640$		;IF GT YES				; PJC038
	TST	(SP)+		;PRUNE THE STACK			;**-2
;									; RP016
;	FINISH UP CALCULATING DEVICE ADDRESSING				; RP016
;									; RP016
	MOV	PRMTBL-2,R1	;GET POINTER TO PARAMETER TABLE		; RP016
	CLR	-(SP)		;GET A WORKING REGISTER			; RP016
	BISB	5(R1),(SP)	;GET TRACKS/CYLINDER			; RP016
	      MOV	(SP)+,R1	;					; RP016
	CALL	$DIV		;CALCULATE TRACK AND CYLINDER		; RP016
	MOV	R0,I.PRM+10(R3)  ;SAVE DESIRED CYLINDER ADDRESS		; RP016
	SWAB	R1		;SWAP TRACK ADDRESS TO HIGH BYTE	; RP016
	BIS	R1,R2		;MERGE TRACK ADDRESS WITH SECTOR ADDRESS; RP016
	MOV	R2,I.PRM+12(R3)  ;SAVED DESIRED TRACK AND SECTOR ADDRESS; RP016
									; PB237
	.ENDC								; PB237
									; PB237
									; PB237
	RETURN								;**-2
;									; RP016
;	SPECIAL ROUTINE TO DETERMINE DEVICE PARAMETERS			; RP016
;							      		; RP016
660$:	MOV	#PRMTBL,R0	;GET POINTER TO PARAMETER TABLE		; PJC038
670$:	CMPB	(R0),U.CW2(R5)	;IS THIS THE PROPER DEVICE?		; PJC038
	BNE	690$		;IF NE NO				; PJC038
	CALL	760$		;CHECK FOR DIAGNOSTIC FUNCTION		; PJC038
	BCC	680$		;IF CC NO				; PJC038
	ADD	#10,R0		;POINT TO DEVICE'S PHYSICAL GEOMETRY	; RP016
680$:	MOV	R0,PRMTBL-2	;SAVE POINTER FOR LATER USE		; PJC038
	RETURN			;					; RP016
690$:	ADD	#10,R0		;INC TO NEXT DEVICE			; PJC038
	TST	(R0)		;END OF TABLE?				; RP016
	BNE	670$		;IF NE       NO				; PJC038
	MOV	#IE.BAD&377,R0	;DEVICE NOT IN TABLE, BAD PARAMETERS	; RP016
	TST	(SP)+		;PRUNE RETURN FROM STACK		; RP016
	JMP	390$		;GO REPORT IT				; PJC038
;									; RP016
;	CALCULATE UPDATED DISK ADDRESS					; RP016
;									; RP016
700$:	SUB	R0,U.CNT(R5)	;REDUCE BYTES REMAINING TO TRANSFER	; PJC038
	BNE	710$		;IF NE MORE SECTORS TO TRANSFER		; PJC038
	ADD	R0,U.CNT(R5)	;LAST SECTOR TO TRANSFER, CORRECT BYTES ; RP021
	RETURN			;AND EXIT				; RP021
710$:	ADD	R0,U.BUF+2(R5)	;UPDATE START      ING BUFFER ADDRESS		; PJC038
									; RP016
									; RP016
	.IF DF	M$$MGE							; RP016
									; RP016
									; RP016
	.IF DF	M$$EXT							; RP016
									; RP016
	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP016
	BEQ	720$		;IF EQ NO				; PJC038
	ADCB	U.BUF+1(R5)	;UPDATE MEMORY EXTENSION BITS		; RP016
	BR	730$		;					; PJC038
									; RP016
	.ENDC								; RP016
									; RP016
									; RP016
720$:	ADCB	U.BUF+1(R5)	;UPDATE MEMORY EXTENSION BITS		; PJC038
	BICB	      #^C<3>,U.BUF+1(R5)  ;CLEAR EXCESS BITS			; RP016
730$:				;REF LABEL				; PJC038
									; RP016
	.ENDC								; RP016
									; RP016
									; RP016
	SWAB	R0		;CALCULATE NUMBER OF SECTORS TRANSFERED	; RP016
	ASR	R0		;					; RP016
	ADD	I.PRM+12(R1),R0  ;UPDATE TRACK/SECTOR ADDRESS		; RP016
	CLR	-(SP)		;GET A WORKING REGISTER			; RP016
	MOV	PRMTBL-2,R3	;GET POINTER TO PROPER DEVICE		; RP016
740$:	CMPB	4(R3),R0	;SECTOR OVERFLOW			; PJC038
	BHI	750$		;IF HI NO				; PJC038
	BISB	4(R3),(SP)	;COP      Y SECTORS/TRACK			; RP016
	SUB	(SP),R0		;SUBTRACT A TRACKS WORTH OF SECTORS	; RP016
	ADD	#1*256.,R0	;ADD IN A TRACK				; RP016
	MOV	4(R3),(SP)	;GET TRACKS AND SECTORS			; RP016
	CLRB	(SP)		;ISOLATE TRACKS/CYLINDER		; RP016
	CMP	(SP),R0		;TRACK OVERFLOW ?			; RP016
	BHI	740$		;IF HI NO				; PJC038
	SUB	(SP),R0		;NORMALIZE TRACK ADDRESS		; RP016
	INC	I.PRM+10(R1)	;UPDATE CYLINDER ADDRESS		; RP016
	BR	740$		;					; PJC038
750$:	MOV	R0,I.PRM+12(R1)  ;SET UPDATED SECTOR/TRACK ADDRESS	; PJC038
	TST	(SP      )+		;PRUNE STACK				; RP016
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX		; RP016
	RETURN			;					; RP016
;									; RP016
; SPECIAL ROUTINE TO CHECK FOR DIAGNOSTIC FUNCTIONS			; RP016
; TWO EXCEPTIONS: IO.CER AND IO.CEW					; RP016
;									; RP016
; INPUTS:								; RP016
;									; RP016
;	R1=ADDRESS OF I/O PACKET					; RP016
;									; RP016
; OUTPUTS:								; RP016
;									; RP016
;	C/S=DIAGNOSTIC FUNCTION (EXCEPT AS NOTED)			; RP016
;	C/C=NORMAL FUNCTION						; RP016
;									;   À   RP016
760$:	CMPB	#IO.CER!IQ.UMD&377,I.FCN(R1)  ;IS IT READ CE CYLINDER ?	; PJC038
	BEQ	770$		;IF EQ YES				; PJC038
	CMPB	#IO.CEW!IQ.UMD&377,I.FCN(R1)  ;IS IT WRITE CE CYLINDER ?; RP016
	BEQ	770$		;IF EQ YES				; PJC038
	BIT	#IQ.UMD,I.FCN(R1)  ;IS IT A DIAGNOSTIC FUNCTION ?	; RP016
	BEQ	770$		;IF EQ NO				; PJC038
	SEC			;					; RP016
	RETURN			;					; RP016
770$:	CLC			;					; PJC038
	RETURN			;					; RP016

	.DSABL	LSB

	.END
À         Õ€˜kQ	› c,        	.TITLE	DREXP
	.IDENT	/03.15/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 03.15
;
; T. J. MILLER 8-JUL-76
;
; PREVIOUSLY MODIFIED BY:
;
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	25-JUL-79
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	27-AUG-79
;		MSH050 -- ALLOW RESIDENT OVERL      AID TASKS TO REDUCE SIZE
;
;	M. S. HARVEY	7-SEP-79
;		MSH053 -- RETURN DIFFERENT STATUS FOR EACH TYPE ERROR
;
;	M. S. HARVEY	30-JAN-80
;		MSH086 -- EXTEND TASK REGION FROM TASK VIRTUAL ZERO,
;			  NOT FROM START OF MAPPED ARRAY AREA
;
;	M. S. HARVEY	28-APR-80
;		MSH096 -- SUPPORT THE ALTERNATE HEADER REFRESH AREA
;
;	M. S. HARVEY	15-SEP-80
;		MSH118 -- DON'T ASSEMBLE THIS DIRECTIVE FOR RSX-11S
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,HDRDF$,PCBDF$,TCBDF$
	HWDDF$			;DEFINE HARDWARE OFFSET      S
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DREXP-EXTEND PARTITION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EXTEND THE PARTITION OF THE
; ISSUING TASK BY A POSITIVE OR NEGATIVE INCREMENT.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(89.),DPB SIZE(3.).
;	WD. 01 -- EXTEND INCREMENT.
;	WD. 02 -- RESERVED.
;
; INPUTS:
;
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF T      HE EXTEND INCREMENT IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF '+1' IS RETURNED.
;
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IF INSUFFICIENT DYNAMIC	;MSH053
;			MEMORY, OR INSUFFICIENT SPACE IN A SYSTEM	;MSH053
;			CHECKPOINT FILE.				;MSH053
;		DIRECTIVE STATUS OF 'D.RS8' IF TASK NOT IN       SYSTEM CON-
;			TROLLED PARTITION.				;MSH053
;		DIRECTIVE STATUS OF 'D.RS10' IF TASK IS NOT CHECK-	;MSH053
;			POINTABLE AND SPECIFIED A POSITIVE INCREMENT.	;MSH053
;		DIRECTIVE STATUS OF 'D.RS18' IF TASK HAS PREALLOCATED	;MSH053
;			CHECKPOINT SPACE AND IS EXTENDING GREATER THAN	;MSH053
;			INSTALLED SIZE.					;MSH053
;		DIRECTIVE STATUS OF 'D.RS83' IF TASK HAS I/O IN		;MSH053
;			PROGRESS.					;MSH053
;		DIRECTIVE STATUS OF 'D.RS84' IF SPECIFIED INCREMENT IS	;MSH053
;			INVALID.					;**-5
;-
      

	.IF DF	D$$YNM&E$$XPR&M$$MGE&D$$ISK&C$$CKP			;MSH118
									;**-1
$DREXP::TSTB	T.IOC(R5)	;TASK HAVE OUTSTANDING I/O?
	BEQ	7$		;IF EQ NO				;MSH053
5$:	DRSTS	D.RS83		;I/O IN PROGRESS FOR TASK		;MSH053
7$:	MOV	T.PCB(R5),R0	;POINT TO TASK PCB			;MSH053
	BIT	#PS.SYS,P.STAT(R0) ;IS IT A SYSTEM CONTROLLED PARTITION?;**-12
	BEQ	15$		;IF EQ NO				;MSH053
	MOV	T.MXSZ(R5),R1	;ASSUME RETURNING TO INSTALLED SIZE	;**-1
	MOV	(R3),R3		;PICK UP SPECIFIED INCREMENT
	BEQ	10$		;IF EQ DEFAULT TO INSTALLED SIZE      
	ADD	P.SWSZ(R0),R3	;CALCULATE NEW SIZE
	MOV	R3,R1		;COPY NEW SIZE
10$:	CMP	R1,P.SWSZ(R0)	;TASK INCREASING SIZE?
	BLOS	25$		;IF LOS NO				;MSH046
	BIT	#T2.CHK!T2.CKD!T2.FXD,(R2) ;TASK CHECKPOINTABLE?	;**-3
	BEQ	20$		;IF EQ YES				;MSH053
	DRSTS	D.RS10		;NOT CHECKPOINTABLE, CAN'T INCREASE SIZE;MSH053
15$:	DRSTS	D.RS8		;NOT IN SYSTEM CONTROLLED PARTITION	;MSH053
20$:				;REF LABEL				;**-1


	.IF DF	D$$YNC

	BIT	#T3.CAL,2(R2)	;TASK HAVE CHECKPOINT SPACE ALLOCATED?
	BEQ	30$		;IF EQ NO

	.ENDC
      

	CMP	R1,T.MXSZ(R5)	;EXTENDING TO LARGER THAN INSTALLED SIZE?
	BLOS	30$		;IF LOS NO				;MSH053
	DRSTS	D.RS18		;EXTENDING TO LARGER THAN INSTALLED SIZE;MSH053
									;MSH046
25$:				;					;MSH046
									;MSH046
	.IF DF	A$$TRP&C$$CKP&T$$BUF					;MSH046
									;MSH046
	TSTB	T.TIO(R5)	;TASK HAVE OUTSTANDING BUFFERED I/O?	;MSH046
	BNE	5$		;IF NE YES, MIGHT WIPE OUT BUFFERS	;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
30$:				;					;MSH096
									;MSH096
	.IF DF	P$$LAS      !A$$HDR						;MSH096
									;MSH096
	MOV	R1,-(SP)	;SAVE NEW TASK REGION SIZE		;MSH096
									;MSH096
	.IF DF	P$$LAS							;MSH086
									;MSH086
	SUB	T.OFF(R5),R1	;NORMALIZE TO TASK REGION ZERO		;MSH086
									;MSH096
	.IFF								;MSH096
									;MSH096
	BIT	#T2.CHK,(R2)	;TASK HAVE ALTERNATE HEADER AREA?	;MSH096
	BNE	32$		;IF NE NO, NONCHECKPOINTABLE TASK	;MSH096
	MOVB	T.HDLN(R5),R2	;GET LENGTH OF ALT. HEADER REFRESH AREA	;MSH096
	SUB	R2,R1		;NORMALIZE TO TASK REGION ZERO		;MSH096
32      $:									;MSH096
	.ENDC								;MSH086
									;MSH086
	.ENDC	;P$$LAS!A$$HDR						;MSH086
									;MSH086
	CMP	R1,$MXEXT	;NEW SIZE GREATER THAN MAXIMUM?		;MSH086
	BHI	45$		;IF HI YES				;MSH086
	MOV	R1,-(SP)	;COPY NEW SIZE FROM VIRTUAL ZERO	;MSH086
	SWAB	(SP)		;CONVERT SIZE TO BYTES			;**-2
	RORB	(SP)		;
	ROR	(SP)		;
	ROR	(SP)		;


	.IF DF	P$$LAS

	CMP	R1,#200		;NEW SIZE GREATER THAN 4K?
	BHI	35$		;IF HI YES

	.ENDC								;MSH050
									;**-1
	CMP	(SP),H.HDLN(R4)	;NEW TASK SIZE S      MALLER THAN HEADER?
	BLO	45$		;IF LO YES				;MSH086
35$:	MOV	H.WND(R4),R4	;POINT TO NUMBER OF WINDOW BLOCKS	;MSH050
	MOV	(R4)+,R2	;PICK UP NUMBER OF WINDOW BLOCKS	;**-11
	TST	(R4)+		;POINT TO TASK LOW VIRTUAL ADDRESS
									;MSH050
	.IF DF	P$$LAS							;MSH050
									;MSH050
	BIT	#T3.ROV,T.ST3(R5) ;IS TASK RESIDENT OVERLAID?		;MSH050
	BNE	42$		;IF NE YES, KEEP WINDOW ZERO INTACT	;MSH050
									;MSH050
	.ENDC								;MSH050
									;MSH050
	MOV	(R4),R3		;PICK UP TASK LOW VIRTUAL ADDRESS
      	ASL	R3		;CONVERT TO 32W BLOCKS
	ROL	R3		;
	ROLB	R3		;
	SWAB	R3		;
	ADD	R1,R3		;CALC HIGH VIRTUAL ADDRESS IN 32W BLOCKS
	CMP	R3,#2000	;LEGAL SIZE?
	BHIS	90$		;IF HIS NO
	ADD	(R4),(SP)	;CALCULATE NEW TOP VIRTUAL ADDRESS
40$:	DEC	R2		;MORE WINDOW BLOCKS TO GO?
	BLE	50$		;IF LE NO
	ADD	#W.BLGH,R4	;POINT TO LOW VIRTUAL ADDRESS OF NEXT
	TST	W.BSIZ-W.BLVR(R4) ;ESTABLISHED WINDOW?
	BEQ	40$		;IF EQ NO


	.IF DF	P$$LAS

	CMP	-2(R4),R0	;WINDOW MAPPED TO TASK REGION? (W.BPCB)
	BNE	44$		;IF NE NO
42$      :	MOV	2(R4),R3	;PICK UP HIGH VIRTUAL ADDRESS (W.BHVR)	;MSH050
	SUB	(R4),R3		;CALCULATE LENGTH OF MAP - 1 (W.BLVR)	;**-1
	INC	R3		;CALCULATE LENGTH OF MAP
	ASL	R3		;CONVERT TO 32W BLOCKS
	ROL	R3		;
	ROLB	R3		;
	SWAB	R3		;
	ADD	W.BOFF-W.BLVR(R4),R3 ;CALCULATE LAST 32W BLOCK MAPPED
				;  (OFFSET FROM START OF TASK REGION)	;MSH086
	CMP	2(SP),R3	;WINDOW STILL BOUNDED BY REGION?	;MSH086
	BLO	90$		;IF LO NO, WINDOW ILLEGALLY MAPPED	;MSH086
44$:	BIT	#T3.ROV,T.ST3(R5) ;IS TASK RESIDENT OVERLAID?		;MSH050      
	BNE	40$		;IF NE YES, UNCHANGED VIRTUAL ADDRESSING;MSH050
									;MSH050
	.ENDC								;**-3

	CMP	(SP),(R4)	;VIRTUAL ADDRESS OVERLAP? (W.BLVR)	;MSH050
	BLOS	40$		;IF LOS NO				;**-2
45$:	BR	90$		;ILLEGAL SIZE
50$:	TST	(SP)+		;CLEAN STACK
									;MSH096
	.IF DF	P$$LAS!A$$HDR						;MSH096
									;MSH096
	MOV	(SP)+,R1	;RESTORE NEW TASK REGION SIZE		;MSH096
									;MSH096
	.ENDC								;MSH096
									;MSH096
	MOV	P.MAIN(R0),R2	;POINT TO MAIN PARTITION PCB
	CMP	R1,P.SIZE(R2)	;MAIN PA      RTITION LARGE ENOUGH?
	BHI	90$		;IF HI NO
	MOV	R1,P.SWSZ(R0)	;SET SWAP SIZE FOR TASK PARTITION
	CLR	R4		;INITIALIZE END OF HOLE CALCULATION
	MOV	P.SUB(R0),R3	;POINT TO NEXT SUBPAR AFTER TASK PAR
	BNE	60$		;IF NE THERE IS ONE
	MOV	R2,R3		;ELSE POINT TO MAIN PARTITION
	ADD	P.SIZE(R3),R4	;CALCULATE END OF HOLE
60$:	ADD	P.REL(R3),R4	;
	MOV	P.REL(R0),R3	;CALCULATE END OF DESIRED SPACE
	ADD	R1,R3		;
	CMP	R3,R4		;WILL EXTEND WORK IN PLACE?
	BLOS	70$		;IF LOS YES
	CALL	$SETRT		;FORCE RESCHEDULING
	MOV      	R5,R1		;COPY TASK TCB ADDRESS


	.IF DF	D$$YNC

	CALL	$CHKPT		;ATTEMPT TO CHECKPOINT TASK
	TSTB	T.STAT(R5)	;WAS THE CHECKPOINT INITIATED? (TS.CKP)	;MSH086
	BPL	65$		;IF PL NO				;MSH086
	RETURN			;					;**-2
65$:	MOV	T.PCB(R5),R4	;PICK UP TASK PCB ADDRESS
	MOV	P.SIZE(R4),P.SWSZ(R4) ;RESET SWAP SIZE
	DRSTS	D.RS1		;POOL OR CHECKPOINT FILE ALLOC FAILURE

	.IFF

	CALLR	$CHKPT		;INITIATE CHECKPOINT OF TASK

	.ENDC


70$:	CMP	R1,P.SIZE(R0)	;DECREASING TASK SIZE?			;**-1
	BHIS	71$		;IF HIS NO      
	MOV	#$NXTSK,-(SP)	;INSURE PARTITION WILL BE REALLOCATED
71$:	MOV	R1,P.SIZE(R0)	;EXTEND TASK IN PLACE


	.IF DF	P$$LAS

	BIT	#T3.ROV,T.ST3(R5) ;TASK HAVE RESIDENT OVERLAYS?
	BNE	80$		;IF NE YES, DO NOT CHANGE MAPPING

	.ENDC


	MOV	P.HDR(R0),R1	;POINT TO TASK'S HEADER
	MOV	H.WND(R1),R1	;POINT TO NUMBER OF WINDOW BLOCKS
	MOVB	W.BFPD+2(R1),R3	;PICK UP FIRST PDR ADDRESS
74$:	CLR	(R3)+		;UNMAP NEXT PDR
	DECB	W.BNPD+2(R1)	;MORE TO GO?
	BNE	74$		;IF NE YES
	CALL	$MAPTK		;MAP TASK ADDRESS WINDO      W
	MOV	P.REL(R0),R3	;CALCULATE FIRST APR OFFSET


	.IF DF	P$$LAS!A$$HDR						;MSH096
									;**-1
	ADD	W.BOFF-W.BLPD(R1),R3 ;

	.ENDC


	MOV	(R1),R2		;PICK UP LAST PDR IMAGE
	MOVB	-(R1),R4	;PICK UP NUMBER OF PDR'S
	MOVB	-(R1),R1	;PICK UP FIRST PDR ADDRESS
75$:	MOV	R3,UISAR0-UISDR0(R1) ;LOAD NEXT APR
	MOVB	R2,(R1)+	;SET ACCESS NEXT PDR
	MOVB	#177,(R1)+	;SET SIZE NEXT PDR
	ADD	#200,R3		;ADVANCE APR BASE
	DEC	R4		;MORE TO GO?
	BNE	75$		;IF NE YES
	MOV	R2,-(R1)	;SET LAST PDR
80$:	RETURN		   J   	;
90$:	DRSTS	D.RS84		;INVALID INCREMENT SPECIFIED

	.ENDC


	.END
J          × kQ	› c,        	.TITLE	DRGCL
	.IDENT	/03.11/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 03.11
;
; D. N. CUTLER 20-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	30-SEP-79
;		MSH066 -- BRING THE COMMENTS BACK UP TO SNUFF
;
;	M. S. FOX	07-JAN-81
;		MF204 -- ADD GCCI$ DIRECTIVE
;
      ;	M. S. FOX	03-FEB-81
;		MF210 -- ADD $SRCCQ ROUTINE TO SEARCH COMMAND QUEUE
;
;	M. S. HARVEY	24-AUG-81
;		MSH186 -- CLI MUST ASSUME THE PROTECTION AND DEFAULT
;			  UICS OF THE TERMINAL ISSUING THE COMMAND
;			  IN CASE THE CLI WAS NOT ACTIVATED IN RESPONSE
;			  TO THE COMMAND
;
;	M. S. HARVEY	10-SEP-81
;		MSH188 -- ALWAYS RETURN VALID PROTECTION UIC, REGARDLESS
;			  OF THE PRESENCE OF MULTI-USER PROTECTION
;
;	M. S. HARVEY	14-SEP-81
;		MSH190 -- RETURN ERROR BEFORE CLI WITH ACTIVE GROUP
;      			  GLOBAL CONTEXT IS FORCED TO CHANGE ITS GROUP
;
;+
; **-$DRGCL-GET MCR/CLI COMMAND LINE					;MSH066
;									;MSH066
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SEARCH FOR A CLI COMMAND	;MSH066
; BUFFER AND TRANSFER IT BACK TO THE ISSUING TASK.			;MSH066
;									;MSH066
; TWO FORMS OF THIS DIRECTIVE ARE AVAILABLE. ONE FORM ALWAYS ASSUMES	;MSH066
; THAT THE CLI IS MCR AND IF A COMMAND IS FOUND, IT IS TRANSFERED	;MSH066
; TO THE ISSUING TASK VIA THE DPB. THE OTHER FORM, ONLY AVAILABLE TO	;MSH066      
; CLI TASKS, WILL TRANSFER THE COMMAND BACK TO A BUFFER WITHIN THE	;MSH066
; TASK'S ADDRESS SPACE. ALSO, THE SECOND FORM CAN RETURN INFORMATION	;MSH066
; ABOUT THE ISSUING TERMINAL.						;MSH066
;									;MSH066
; DPB FORMAT FOR GET MCR COMMAND:					;MSH066
;									;MSH066
;	WD. 00 -- DIC(127.),DPB SIZE(41.).				;MSH066
;	WD. 01 -- FIRST WORD OF 80. BYTE BUFFER.			;MSH066
;	    .								;MSH066
;	    .								;MSH066
;	    .								;MSH066
;	WD. 50 -- LAST WORD OF 80. BYTE BUFFER.				;MSH066      
;									; MF204
; DPB FORMAT FOR GET CLI COMMAND:					; MF204
;									; MF204
;	WD. 00 -- DIC(127.),DPB SIZE(7.).				; MF204
;	WD. 01 -- NO COMMAND PRESENT ACTION, HIGH BYTE RESERVED.	; MF204
;	WD. 02 -- ADDRESS OF COMMAND TO BE RETURNED.			; MF204
;	WD. 03 -- ADDRESS OF COMMAND BUFFER INSIDE TASK.		; MF204
;	WD. 04 -- LENGTH OF TASK'S COMMAND BUFFER.			; MF204
;	WD. 05 -- ADDRESS OF OPTIONAL INFORMATION BUFFER IN TASK.	; MF204
;	WD. 06 -- LENGTH OF TASK'S INFORMATION BUFFER.			; MF204
;				      					; MF204
; INPUTS:								; MF204
;									; MF204
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.	; MF204
;	R3=ADDRESS OF THE SECOND WORD OF THE DPB.			; MF204
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.			; MF204
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.			; MF204
;									; MF204
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)			; MF204
;									; MF204
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.			; MF204
;		DIRECTIVE STATUS OF +1 IS RETURNED IF A COMMAN      D HAS	; MF204
;			BEEN SUCCESSFULLY RETURNED TO THE CLI		; MF204
;		DIRECTIVE STATUS OF 'D.RS00' IS RETURNED IF NO COMMAND	; MF204
;			IS QUEUED FOR THE CLI, AND THE CLI INDICATED	; MF204
;			THAT IT WANTED TO BE STOPPED. THE CLI WILL GET	; MF204
;			THIS STATUS AFTER IT IS UNSTOPPED.		; MF204
;	C=1 IF DIRECTIVE IS REJECTED.					; MF204
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF AN ILLEGAL	; MF204
;			DPB SIZE IS SPECIFIED.				; MF204
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF EITHER	; MF20      4
;			BUFFER OR THE DPB ARE NOT ENTIRELY WITHING	; MF204
;			THE TASK'S ADDRESS SPACE.			; MF204
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF THERE IS	; MF204
;			NO MCR COMMAND FOR THE ISSUING TASK, OR IF	; MF204
;			A GCCI$ WITH STOP ON NO COMMAND OPTION WAS ISSUE; MF204
;			FROM AST STATE					; MF204
;		DIRECTIVE STATUS OF 'D.RS17' IS RETURNED IF THE		;MSH190
;			ISSUING CLI TASK ATTEMPTED TO RECEIVE A COMMAND	;MSH190
;			FROM A TERMINAL WITH A DIFFERENT PROTECTION	;MSH190
;			GROUP FROM THE       CLI'S CURRENT GROUP (WHICH CAUSES;MSH190
;			THE CLI TO ASSUME THE TERMINAL'S GROUP) AND	;MSH190
;			THE TASK HAD ACTIVE GROUP GLOBAL CONTEXT FOR	;MSH190
;			THE FORMER GROUP.				;MSH190
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF A TASK	; MF204
;			WHICH IS NOT A CLI ATTEMPTED TO GET A CLI	; MF204
;			COMMAND LINE.					; MF204
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED FROM A GCCI$	; MF204
;			DIRECTIVE IF THERE IS NO COMMAND QUEUED FOR THE	; MF204
;			CLI, AND THE TASK WANTED AN ERROR RETURNED       IN	; MF204
;			THIS CASE.					; MF204
;-									;**-30


	.IF DF	M$$CRX

	.ENABL	LSB
$DRGCL::								; MF204
									; MF204
	.IF DF	A$$CLI							; MF204
									; MF204
	MOVB	-(R3),R0	;GET THE DPB SIZE OF THIS DIRECTIVE	; MF204
	CMPB	(R3)+,#41.	;GET MCR COMMAND DIRECTIVE?		; MF204
	BEQ	5$		;IF EQ YES				; MF204
	CMPB	R0,#7.		;GET CLI COMMAND DIRECTIVE?		; MF204
	BEQ	GCCI		;IF EQ YES				; MF204
	DRSTS	D.RS99		;ILLEGAL DPB SIZE			; MF204
5$:				;REFERENCE LABEL			; MF204
									; MF2      04
	.ENDC	;A$$CLI							; MF204
									; MF204
									; MF204
	CALL	30$		;SEARCH FOR TASK COMMAND BUFFER		; MF204
	BCC	10$		;IF CC ONE FOUND			;**-1
	DRSTS	D.RS80		;SET DIRECTIVE STATUS
10$:	CMP	(R0)+,(R0)+	;POINT TO COMMAND TEXT
20$:	INC	2(SP)		;INCREMENT BYTE COUNT
	MOVB	(R0),(R3)	;INSERT BYTE INTO USER BUFFER
	CMPB	#33,(R0)+	;ALTMODE TERMINATOR?
	BEQ	25$		;IF EQ YES
	CMPB	#15,(R3)+	;CARRIAGE RETURN?
	BNE	20$		;IF NE NO
25$:	SUB	#2,2(SP)	;ADJUST TO PROPER BYTE COUNT

;+
; **-$RLMCB-RE      LEASE MCR COMMAND BUFFER
;
; INPUTS:
;
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS:
;
;	IF THERE IS A COMMAND BUFFER IN THE LIST FOR THE CURRENT	;MSH066
;	TASK, THEN IT IS REMOVED FROM THE LIST AND DEALLOCATED.		;MSH066
;-									;**-3

$RLMCB::CALL	30$		;SEARCH FOR TASK COMMAND BUFFER
	BCS	50$		;IF CS NONE FOUND
	MOV	(R0),(R1)	;REMOVE BUFFER FROM LIST
	MOV	#84.,R1		;SET LENGTH OF BUFFER TO RELEASE
	CALLR	$DEACB		;DEALLOCATE BUFFER

;
; SUBROUTINE TO SEARCH FOR COMMAND BUFFE      R FOR CURRENT TASK
;

30$:	MOV	#$MCRCB,R0	;POINT TO COMMAND BUFFER LISTHEAD
	CALLR	$SRCCQ		;SEARCH FOR COMMAND			; MF210
50$:	RETURN								; MF210
									; MF204
;+									; MF204
; **-$RLCIB-RELEASE ALL COMMANDS FOR A CLI TASK				; MF204
;									; MF204
; INPUTS:								; MF204
;									; MF204
;	R5=ADDRESS OF TCB OF THE CURRENT TASK (ALWAYS A CLI)		; MF204
;									; MF204
; OUTPUTS:								; MF204
;									; MF204
;	ALL COMMAND BUFFERS IN THE $CLICQ LIST FOR THIS CLIS		; MF204
;      	ARE REMOVED FROM THE LIST AND DEALLOCATED			; MF204
;									; MF204
;-									; MF204
									; MF204
	.IF DF	A$$CLI							; MF204
									; MF204
$RLCIB::MOV	$CLICQ,R1	;POINT TO FIRST ENTRY			; MF204
	BEQ	50$		;IF EQ, LIST EMPTY			; MF204
	TST	2(R1)		;IS THERE A ELIMINATE ALL PACKET	; MF204
	BNE	60$		;IF NE NO				; MF204
	CALL	ELIMCD		;PROCESS IT				; MF204
60$:	MOV	#$CLICQ,R0	;POINT TO LISTHEAD			; MF204
	CALL	$SRCCQ		;SEARCH FOR A COMMAND			; MF204
	BCS	50$		;IF CS, NO COMMANDS LEFT		;       MF204
	MOV	R0,R1		;COPY COMMAND BUFFER ADDRESS		; MF204
	CALL	ELIMCD		;ELIMINATE COMMAND			; MF204
	BR	60$		;TRY FOR ANOTHER ONE			; MF204
	.DSABL	LSB							; MF204
									; MF204
;									; MF204
; THE FOLLOWING CODE EXECUTES THE GCCI$ DIRECTIVE			; MF204
;									; MF204
; THIS DIRECTIVE CAN ONLY BE ISSUED BY CLI TASKS ON SYSTEMS THAT SUPPORT; MF204
; ALTERNATE CLIS (A$$CLI). IT COPIES A COMMAND BUFFER FROM THE POOL INTO; MF204
; THE CLI TASK, AND EITHER DEALLOCATES IT OR LEAVES IT QUEUED       FOR	; MF204
; RETREIVAL BY A SUBSEQUENT GCCI$ DIRECTIVE AT THE CLI'S OPTION.	; MF204
; IT CAN ALSO FILL IN AN INFORMATION BUFFER IN THE CLI WITH DATA	; MF204
; ABOUT THE TERMINAL AND TASK FROM WHICH THE COMMAND ORIGINATED.	; MF204
;									; MF204
; THE FORMAT OF THE COMMAND BUFFER IN THE POOL IS SHOWN BELOW. THE	; MF204
; LISTHEAD IS AT $CLICQ.						; MF204
;									; MF204
;	+---------------------------------------+			; MF204
;	!	LINK				!			; MF204
;	!---------------------------------------!	      		; MF204
;	!	TCB ADDR OF CLI TO RECEIVE CMD	!			; MF204
;	!---------------------------------------!			; MF204
;	!	UCB ADDR OF ISSUING TERMINAL	! OR ZERO ON SYSTEM MESS; MF204
;	!---------------------------------------!			; MF204
;	!	SIZE OF THIS BUFFER IN POOL	!			; MF204
;	!---------------------------------------!			; MF204
;	!  STATUS	!	TERMINATOR	! ZERO ON SYSTEM MESSAGE; MF204
;	!---------------------------------------!			; MF204
;	!					!			; MF204
;	!	COMMAND TEXT IN ASCII		!			; MF204
;	!      					!			; MF204
;	!					!			; MF204
;	+---------------------------------------+			; MF204
;									; MF204
; THE SYSTEM MESSAGE THAT RESULTS FROM A CLI /ELIM=* COMMAND		; MF204
; (ELIMINATE ALL CLIS FOR SYSTEM SHUTDOWN) HAS A DIFFERENT FORMAT.	; MF204
; THE TCB ADDRESS FIELD IS ZERO, SINCE ONE PACKET IS USED FOR ALL	; MF204
; CLIS THAT HAVE THE CP.MSG ATTRIBUTE. THE TEXT PART OF THE PACKET	; MF204
; IS VARIABLE LENGTH, AND CONTAINS A LIST OF TCB ADDRESSES THAT SHOULD	; MF204
; RECEIVE IT. THE NUM      BER OF TCB ADDRESS INITIALLY PRESENT IS AT OFFSET	; MF204
; 12 FROM THE BEGINNING. THIS IS USED IN DETERMINING THE NUMBER OF	; MF204
; WORDS TO SCAN TO DETERMINE IF THE CURRENT CLI SHOULD GET THIS PACKET.	; MF204
; OFFSET 14 CONTAINS A COUNT WHICH IS DECREMENTED EVERY TIME THIS	; MF204
; PACKET IS GIVEN TO A CLI. THE WORD CONTAINING THE TCB ADDRESS FOR	; MF204
; THIS CLI IS THEN CLEARED SO IT WILL NOT SEE THIS PACKET AGAIN.	; MF204
; WHEN THIS COUNT GOES TO ZERO, THE PACKET IS DEALLOCATED.		; MF204
;      									; MF204
; THE FORMAT OF THE COMMAND BUFFER SET UP IN THE CLI TASK SPACE IS:	; MF204
;									; MF204
;	+---------------------------------------+			; MF204
;	!	ASCII DEV NAME OF ISSUING TTY	!			; MF204
;	!---------------------------------------!			; MF204
;	! NUM OF CHAR RETURNED ! OCTAL UNIT NUM.!			; MF204
;	!---------------------------------------!			; MF204
;	!	COMMAND SIZE			!			; MF204
;	!---------------------------------------!			; MF204
;	!    STATUS	!	TERMINATOR	!			; MF204
;	!-      --------------------------------------!			; MF204
;	!					!			; MF204
;	!	COMMAND TEXT IN ASCII		!			; MF204
;	!					!			; MF204
;	+---------------------------------------+			; MF204
;									; MF204
;									; MF204
; THE FORMAT OF THE INFORMATION BUFFER IN THE CLI TASK SPACE IS:	; MF204
;									; MF204
;	+---------------------------------------+			; MF204
;	!	U.CW2 OF ISSUING TERMINAL	!			; MF204
;	!---------------------------------------!			; MF204
;	!	NAME OF PARENT TASK (IF ANY)	!			; M      F204
;	!		(2 WORDS)		!			; MF204
;	!---------------------------------------!			; MF204
;	!	ADDRESS OF OCB FROM PARENT	!			; MF204
;	!---------------------------------------!			; MF204
;	!	LOGIN UIC OF ISSUING TERMINAL	!			; MF204
;	!---------------------------------------!			; MF204
;	!	CURRENT UIC OF ISSUING TERMINAL	!			; MF204
;	!---------------------------------------!			; MF204
;	!	ADDR OF CMD. IF NOT DEQUEUED	!			; MF204
;	+---------------------------------------+			; MF204
;									; MF20      4
; EXTRA FIELDS CAN BE ADDED TO THE END OFF THIS BUFFER IF REQUIRED, BECA; MF204
; THE TASK SUPPLIES BOTH THE ADDR AND LENGTH OF ITS TASK BUFFER. ONLY	; MF204
; THAT MUCH DATA IS COPIED BACK TO THE TASK. THE TASK BUFFER IS FILLED	; MF204
; FROM THE FRONT WITH THE FIELDS IN THE ABOVE ORDER. IF THE BUFFER	; MF204
; IS NOT LONG ENOUGH TO HOLD ALL OF THE DATA, THE FIELDS THAT WOULD	; MF204
; NOT FIT ARE NOT SUPPLIED, BUT NO INDICATION OF THIS DATA TRUNCATION	; MF204
; IS GIVEN TO THE TASK. THUS IF MORE       FIELDS ARE ADDED IN A FUTURE RELEAS; MF204
; OLD TASKS WOULD STILL WORK SINCE THEY WILL GET EXACTLY WHAT THEY GOT	; MF204
; BEFORE, THEY JUST WOULD NOT GET THE NEW DATA.				; MF204
;									; MF204
									; MF204
	.ENABL	LSB							; MF204
GCCI:	BIT	#T3.CLI,T.ST3(R5) ;IS TASK A CLI			; MF204
	BNE	100$		;IF NE YES				; MF204
	DRSTS	D.RS16		;SET DIRECTIVE STATUS			; MF204
100$:	MOV	(R3)+,-(SP)	;SAVE NO CMD ACTION			; MF204
	TST	T.ST2(R5)	;TASK AT AST STATE??			; MF204
	BPL	103$		;IF PL NO				; MF      204
	BIT	#2,(SP)		;IS STOP ON NO COMMAND OPTION SPECIFIED	; MF204
	BEQ	103$		;IF EQ NO				; MF204
	DRSTS	D.RS80		;SET DIRECTIVE STATUS			; MF204
103$:	MOV	(R3)+,R4	;SAVE DESIRED CMD ADDR			; MF204
	MOV	(R3)+,R0	;GET CMD BUFFER ADDRESS			; MF204
	BNE	110$		;IF NE, THERE IS A BUFFER		; MF204
105$:	DRSTS	D.RS98		;SET DIRECTIVE STATUS			; MF204
110$:	MOV	(R3)+,R1	;GET LENGTH				; MF204
	CMP	#11,R1		;IS IT ABOVE MINIMUM  LENGTH		; MF204
	BHI	105$		;IF HI NO				; MF204
	MOV	R1,-(SP)	;SAVE LENGTH OF TAS      K CMD BUFFER		; MF204
	MOV	R0,-(SP)	;SAVE ADDRESS OF TASK CMD BUFFER	; MF204
	CALL	$ACHKW		;ADDRESS CHECK COMMAND BUFFER		; MF204
	CLR	R2		;ASSUME NO INFO BUFFER			; MF204
	MOV	(R3)+,R0	;GET INFO BUFFER ADDRESS		; MF204
	BEQ	120$		;IF EQ, NO BUFFER			; MF204
	MOV	(R3)+,R1	;GET INFO BUFFER LENGTH			; MF204
	BMI	105$		;IF MI, ILLEGAL LENGTH			; MF204
	MOV	R1,R3		;SAVE BUFFER LENGTH			; MF204
	CALL	$ACHKW		;ADDRESS CHECK INFO BUFFER		; MF204
	CALL	$RELOC		;RELOCATE INFO BUFFER ADDRESS		; MF204
	MOV	      R1,KISAR6	;MAP INFO BUFFER			; MF204
120$:	MOV	#$CLICQ,R0	;POINT TO COMMAND LISTHEAD		; MF204
	MOV	(R0),R1		;POINT TO FIRST PACKET IN LIST		; MF204
	BEQ	130$		;IF EQ, LIST EMPTY			; MF204
	TST	2(R1)		;IS THIS AN ELIMINATE ALL?		; MF204
	BNE	130$		;IF NE NO				; MF204
	ADD	#12,R1		;POINT TO NUMBER OF TCB COUNT		; MF204
	MOV	(R1)+,R4	;GET NUMBER OF SLOTS			; MF204
	TST	(R1)+		;SKIP OVER REMAINING TCB COUNT		; MF204
125$:	CMP	R5,(R1)+	;DOES CURRENT CLI GET THIS PACKET	; MF204
	BEQ	137$		;IF EQ YES			      	; MF204
	DEC	R4		;MORE SLOTS TO CHECK			; MF204
	BNE	125$		;IF NE YES				; MF204
130$:	CALL	$SRCCQ		;FIND A COMMAND FOR THIS CLI		; MF204
	BCC	140$		;IF CC, FOUND ONE			; MF204
;									; MF204
; NO COMMAND EXISTS FOR THIS CLI					; MF204
;									; MF204
	CMP	(SP)+,(SP)+	;CLEAN STACK				; MF204
	MOV	(SP)+,R0	;GET DESIRED ACTION CODE		; MF204
	BEQ	135$		;IF EQ, RETURN ERROR			; MF204
	ASR	R0		;FORCE TASK TO EXIT??			; MF204
	BCS	133$		;IF CS YES				; MF204
	ASR	R0		;FORCE TASK TO STOP			; MF      204
	BCC	135$		;IF CC NO, RETURN ERROR			; MF204
	CALL	$STPCT		;STOP THE TASK				; MF204
	DRSTS	D.RS00		;SET IS.CLR				; MF204
133$:	JMP	$DREXT		;FORCE THE TASK TO EXIT			; MF204
135$:	DRSTS	D.RS8		;SET ERROR CONDITION			; MF204
;									; MF204
; FIND A COMMAND FOR THE CLI						; MF204
;									; MF204
137$:	MOV	(R0),R0		;POINT TO ELIMINATE ALL PACKET		; MF204
	BR	190$		;USE IT					; MF204
;									; MF204
140$:	CMP	R4,R0		;IS IT THE DESIRED ONE?			; MF204
	BEQ	150$		;IF EQ YES				; MF204
      	TST	R4		;TAKE ANY ONE?				; MF204
	BNE	130$		;IF NE NO				; MF204
150$:	MOV	4(R0),R4	;GET ADDRESS OF ISSUING TERMINAL UCB	;MSH186
	BEQ	155$		;IF EQ BUFFER IS A MESSAGE		;MSH186
	MOV	$HEADR,R1	;POINT TO CLI TASK'S HEADER		;MSH186
									;MSH190
	.IF DF	G$$EFN							;MSH190
									;MSH190
	TSTB	T.GGF(R5)	;TASK HAVE ACTIVE GROUP GLOBAL CONTEXT?	;MSH190
	BEQ	152$		;IF EQ NO				;MSH190
									;MSH190
	.IF DF	M$$MUP							;MSH190
									;MSH190
	CMPB	U.LUIC+1(R4),H.CUIC+1(R1) ;WILL TASK CHAN      GE GROUP?	;MSH190
									;MSH190
	.IFF								;MSH190
									;MSH190
	CMPB	U.UIC+1(R4),H.CUIC+1(R1)  ;WILL TASK CHANGE GROUP?	;MSH190
									;MSH190
	.ENDC								;MSH190
									;MSH190
	BEQ	152$		;IF EQ NO, ALLOW COMMAND RECEPTION	;MSH190
	DRSTS	D.RS17		;CLI TASK HAS GRP GBL CONTEXT ACTIVE	;MSH190
152$:				;					;MSH190
	.ENDC	;G$$EFN							;MSH190
									;MSH186
	.IF DF	M$$MUP							;MSH186
									;MSH186
	MOV	U.LUIC(R4),H.CUIC(R1) ;ESTABLISH PROTECTION UIC		;MSH186
									;M      SH186
	.IFF								;MSH186
									;MSH186
	MOV	U.UIC(R4),H.CUIC(R1)  ;ESTABLISH PROTECTION UIC		;MSH186
									;MSH186
	.ENDC								;MSH186
									;MSH186
	MOV	U.UIC(R4),H.DUIC(R1)  ;ESTABLISH DEFAULT UIC		;MSH186
155$:	TST	R2		;INFO BUFFER PRESENT			;MSH186
	BEQ	190$		;IF EQ NO				; MF204
;									; MF204
; FILL INFORMATION BUFFER IN TASK SPACE;				; MF204
;									; MF204
	ASR	R3		;CONVERT TO WORD COUNT			; MF204
	BCS	105$		;IF CS, LENGTH IS NOT EVEN		; MF204
	BEQ	190$		;IF EQ, BUF      FER HAS LENGTH ZERO		; MF204
	TST	R4		;IS THIS A MESSAGE BUFFER?		;MSH186
	BEQ	190$		;IF EQ, BUFFER IS A MESSAGE SO IGNORE IN; MF204
	MOV	U.CW2(R4),(R2)+	;GET U.CW2				; MF204
	SUB	#3,R3		;ARE THERE 3 WORDS LEFT IN INFO BUFFER	; MF204
	BLT	190$		;IF LT NO				; MF204
									; MF204
									; MF204
	.IF DF	P$$OFF							; MF204
									; MF204
	MOV	T.OCBH(R5),R1	;POINT TO OCB LIST			; MF204
	BR	164$		;					; MF204
160$:	MOV	(R1),R1		;POINT TO NEXT OCB			; MF204
164$:	BEQ	170$		;IF EQ, END OF O      CB LIST			; MF204
	CMP	O.MCRL(R1),R0	;IS THIS OCB FOR THIS COMMAND		; MF204
	BNE	160$		;IF NE NO				; MF204
	MOV	O.STAT(R1),(R2)+ ;COPY FIRST HALF OF PARENT NAME	; MF204
	MOV	O.STAT+2(R1),(R2)+ ;COPY SECOND HALF OF PARENT NAME	; MF204
	DEC	R3		;ANOTHER WORD IN BUFFER			; MF204
	BLT	190$		;IF LT NO				; MF204
	MOV	R1,(R2)+	;SAVE OCB ADDRESS			; MF204
	BR	180$		;					; MF204
									; MF204
	.ENDC								; MF204
									; MF204
									; MF204
170$:	CLR	(R2)+		;CLEAR PARENT NAME FIELD		; MF204      
	CLR	(R2)+		;					; MF204
	DEC	R3		;ANOTHER WORD IN BUFFER			; MF204
	BLT	190$		;IF LT NO				; MF204
	CLR	(R2)+		;CLEAR OCB ADDRESS FIELD		; MF204
180$:	DEC	R3		;ANOTHER WORD IN BUFFER			; MF204
	BLT	190$		;IF LT NO				; MF204
									; MF204
									; MF204
	.IF DF	M$$MUP							; MF204
									; MF204
	MOV	U.LUIC(R4),(R2)+ ;COPY PROTECTION UIC			; MF204
									; MF204
	.IFF	;M$$MUP							; MF204
									; MF204
	MOV	U.UIC(R4),(R2)+	;ESTABLISH PROTECTION UIC		;MSH188
									; MF204      
	.ENDC								; MF204
									; MF204
									; MF204
	DEC	R3		;ROOM LEFT IN BUFFER			; MF204
	BLT	190$		;IF LT NO				; MF204
	MOV	U.UIC(R4),(R2)+	;COPY CURRENT UIC CODE			; MF204
	DEC	R3		;ROOM LEFT IN BUFFER			; MF204
	BLT	190$		;IF LT NO				; MF204
	CLR	(R2)		;ASSUME DO NOT SUPPLY COMMAND ADDRESS	; MF204
	TSTB	4(SP)		;IS COMMAND TO BE DEQUEUED		; MF204
	BPL	190$		;IF PL YES				; MF204
	MOV	R0,(R2)		;SUPPLY ADDRESS OF COMMAND BUFFER	; MF204
;									; MF204
; COPY COMMAND FROM POOL INTO T      HE TASK'S BUFFER				; MF204
;									; MF204
190$:	BIC	#T3.MCR,T.ST3(R5) ;ASSUME CLI SHOULD NOT PROMPT ON EXIT	; MF204
	MOV	R0,R5		;COPY POINTER TO BUFFER IN POOL		; MF204
	CMP	(R5)+,(R5)+	;SKIP LINK AND TCB ADDRESS		; MF204
	MOV	(SP)+,R0	;GET ADDRESS OF BUFFER IN TASK		; MF204
	CALL	$RELOC		;RELOCATE BUFFER ADDRESS		; MF204
	MOV	R1,KISAR6	;MAP BUFFER				; MF204
	MOV	R2,R4		;SAVE DESTINATION DISPLACEMENT		; MF204
	MOV	R1,R3		;SAVE APR BIAS				; MF204
	ADD	#10,R4		;POINT TO WHERE COMMAND WILL STAR      T	; MF204
	MOV	(R5)+,R0	;GET UCB THAT ISSUED COMMAND		; MF204
	BEQ	200$		;IF EQ, BUFFER IS A SYSTEM MESSAGE	; MF204
	MOV	(R0),R1		;POINT TO DCB				; MF204
	TST	(R1)+		;POINT TO ADDRESS OF FIRST UCB		; MF204
	SUB	(R1)+,R0	;CALC RELATIVE ADDRESS OF UCB		; MF204
	MOV	(R1)+,(R2)+	;COPY DEVICE NAME			; MF204
	MOV	(R1)+,(R2)	;GET LOW UNIT NUMBER FOR DCB		; MF204
	MOV	(R1),R1		;GET LENGTH OF UCB			; MF204
	CALL	$DIV		;CALC RELATIVE UNIT NUMBER		; MF204
	ADD	R0,(R2)+	;CALC LOGICAL UNIT NUMBER IN LOW BYTE	      ; MF204
	BR	210$		;					; MF204
200$:	CLR	(R2)+		;ZERO TO INDICATE MESSAGE		; MF204
	MOV	(R5),(R2)	;COPY MESSAGE CODE			; MF204
	SWAB	(R2)+		;PUT CODE IN LOW BYTE IN USER BUFFER	; MF204
	CLR	2(SP)		;FORCE MESSAGE BUFFER TO BE DEQUEUED	; MF204
	TST	-4(R5)		;IS MESSAGE AN ELIMINATE ALL		; MF204
	BNE	210$		;IF NE NO				; MF204
	CLR	R1		;DO NOT RETURN ANY TEXT			; MF204
	TST	(R5)+		;SKIP SIZE WORD IN BUFFER		; MF204
	BR	214$		;					; MF204
210$:	MOV	(R5)+,R1	;GET SIZE OF BUFFER IN POOL		; MF204
	SUB      	#12,R1		;GET NUMBER OF CHARACTERS TO COPY	; MF204
	BIC	#177400,R1	;CLEAR HIGH BYTE			; MF204
214$:	MOV	(SP)+,R0	;GET LENGTH OF TASK'S BUFFER		; MF204
	SUB	#10,R0		;CALC SPACE AVAILABLE FOR COMMAND	; MF204
	CLR	-(SP)		;ASSUME LENGTHS WILL BE CORRECT		; MF204
	CMP	R0,R1		;COMPARE SIZE OF POOL AND TASK BUFFERS	; MF204
	BLO	220$		;IF LO, USE TASK BUFFER SIZE		; MF204
	MOV	R1,R0		;USE POOL BUFFER SIZE			; MF204
	MOV	#400,(SP)	;HAVE TO DECREMENT COUNT IN UPPER BYTE	; MF204
220$:	MOVB	R0,-1(R2)	;PUT ACTU      AL COUNT IN TASK BUFFER	; MF204
	MOV	R1,(R2)+	;PUT BUFFER SIZE IN TASK BUFFER		; MF204
	TST	-10(R4)		;SYSTEM MESSAGE?			; MF204
	BEQ	230$		;IF EQ YES				; MF204
	DEC	-2(R2)		;REMOVE TERMINATOR FROM BUFFER SIZE	; MF204
	SUB	(SP),-4(R2)	;POSSIBLY DECREMENT SUPPLIED CHAR COUNT	; MF204
230$:	TST	(SP)+		;CLEAN STACK				; MF204
	MOV	(R5)+,(R2)	;INSERT TERMINATOR AND STATUS BYTE	; MF204
	TST	R0		;ANY CHARACTERS TO COPY			; MF204
	BEQ	240$		;IF EQ NO				; MF204
	MOV	R5,R2		;POINT TO START OF CMD TEXT IN P      OOL	; MF204
	CALL	$BLXIO		;COPY COMMAND INTO TASK'S BUFFER	; MF204
240$:	SUB	#6,R5		;POINT TO UCB ADDRESS IN POOL BUFFER	; MF204
	TST	(R5)+		;IS THIS A SYSTEM MESSAGE		; MF204
	BEQ	250$		;IF EQ YES				; MF204
	CMP	#13,(R5)	;DOES PACKET JUST CONTAIN A TERMINATOR	; MF204
	BEQ	250$		;IF EQ YES, NEVER PROMPT		; MF204
	CMPB	#33,2(R5)	;IS TERMINATOR AN ESCAPE		; MF204
	BEQ	250$		;IF EQ YES				; MF204
	MOV	$TKTCB,R1	;POINT TO CURRENT TASKS TCB		; MF204
	BIS	#T3.MCR,T.ST3(R1) ;FORCE PROMPT ON EXIT			; MF2      04
250$:	SUB	#6,R5		;POINT TO START OF POOL BUFFER		; MF204
	TSTB	(SP)+		;LEAVE POOL BUFFER QUEUED		; MF204
	BMI	310$		;IF MI YES				; MF204
260$:	MOV	R5,R1		;POINT TO BUFFER IN POOL		; MF204
ELIMCD:	MOV	#$CLICQ,R0	;POINT TO COMMAND QUEUE LISTHEAD	; MF204
	TST	2(R1)		;ELIMINATE ALL PACKET?			; MF204
	BNE	280$		;IF NE NO				; MF204
	ADD	#12,R1		;POINT TO SLOT COUNT			; MF204
	MOV	(R1)+,R2	;GET NUMBER OF SLOTS			; MF204
	TST	(R1)+		;SKIP REMAINING TCB COUNT		; MF204
270$:	CMP	$TKTCB,(R1)+	;DOES THI      S CLI GET THE ELIMINATE ALL	; MF204
	BEQ	300$		;IF EQ YES				; MF204
	DEC	R2		;ANOTHER SLOT TO CHECK			; MF204
	BGT	270$		;IF GT YES				; MF204
	RETURN								; MF204
280$:	CALL	$QRMVT		;DEQUEUE BUFFER				; MF204
	MOV	R1,R0		;POINT TO BUFFER AGAIN			; MF204
	MOV	6(R1),R1	;GET LENGTH OF BUFFER			; MF204
	TST	4(R0)		;DOES BUFFER CONTAIN A SYSTEM MESSAGE	; MF204
	BNE	290$		;IF NE NO				; MF204
	BIC	#177400,R1	;CLEAR OUT MESSAGE CODE			; MF204
290$:	CALLR	$DEACB		;DEALLOCATE IT				; MF204
300$:	CLR	   R  -(R1)		;CLEAR POINTER TO TCB			; MF204
	MOV	(R0),R1		;POINT TO PACKET AGAIN			; MF204
	DEC	14(R1)		;DECREMENT REMAINING TCB COUNT		; MF204
	BEQ	280$		;IF EQ, ALL TCBS HAVE SEEN PACKET	; MF204
310$:	RETURN								; MF204
									; MF204
	.ENDC	;A$$CLI							; MF204
									; MF204
	.DSABL	LSB							;**-7

	.ENDC


	.END
 R         ×hLkQ	› c,        	.TITLE	DRGLI
	.IDENT	/07.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 07.00
;
; D. N. CUTLER 18-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;
; MODIFIED BY:
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS

;+
; **-$DRGLI-GET LUN INFORMATION
;      
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO FILL A SIX WORD BUFFER WITH
; INFORMATION ABOUT A DEVICE THAT IS ASSIGNED TO A SPECIFIED LUN. IF RE-
; QUESTS TO THE DEVICE HAVE BEEN RE-DIRECTED, THEN THE INFORMATION RETURN-
; ED PERTAINS TO THE RE-DIRECT DEVICE.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(5.),DPB SIZE(3.).
;	WD. 01 -- LUN TO RETURN INFORMATION FOR.
;	WD. 02 -- ADDRESS OF A SIX WORD BUFFER.
;
;	BUFFER FORMAT:
;
;	WD. 00 -- NAME OF ASSIGNED DEVICE.
;	WD. 01 -- UNIT NUMBER OF ASSIGNED DEVICE AN      D FLAGS BYTE.
;	WD. 02 -- FIRST DEVICE CHARACTERISTICS WORD.
;	WD. 03 -- SECOND DEVICE CHARACTERISTICS WORD.
;	WD. 04 -- THIRD DEVICE CHARACTERISTICS WORD.
;	WD. 05 -- FOURTH DEVICE CHARACTERISTICS WORD.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LUN IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY       COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS5' IS RETURNED IF NO DEVICE
;			IS ASSIGNED TO THE SPECIFIED LUN.
;-

$DRGLI::CALL	$MPLUN		;MAP LUN TO UCB ADDRESS
	BCS	10$		;IF CS NO DEVICE ASSIGNED
	MOV	R0,R4		;SAVE ADDRESS OF DEVICE UCB
	MOV	(R3),R3		;GET ADDRESS OF BUFFER


	.IF DF	A$$CHK!M$$MGE

	MOV	#6*2,R1		;SET LENGTH OF BUFFER
	CALL	$ACHKP		;ADDRESS CHECK BUFFER

	.ENDC


	MOV	(R4),R2		;GET ADDRESS OF DEVICE DCB
	TS      T	(R2)+		;POINT TO ADDRESS OF FIRST UCB
	MOV	R4,R0		;COPY ADDRESS OF UCB
	SUB	(R2)+,R0	;CALCULATE RELATIVE ADDRESS OF UCB
	MOV	(R2)+,(R3)+	;INSERT GENERIC DEVICE NAME
	MOV	(R2)+,(R3)	;PICK UP LOW UNIT NUMBER FOR DCB
	MOV	(R2)+,R1	;PICK UP UCB LENGTH
	CALL	$DIV		;CALCULATE RELATIVE UNIT NUMBER
	ADD	R0,(R3)+	;CALCULATE LOGICAL UNIT NUMBER
	MOVB	#200,-(R3)	;ASSUME RESIDENT DRIVER


	.IF DF	L$$DRV

	TST	(R2)		;DRIVER RESIDENT?
	BNE	5$		;IF NE YES
	CLRB	(R3)		;ELSE INDICATE DRIVER IS NONRESIDENT
   0  
	.ENDC


5$:	INC	R3		;ADVANCE POINTER
	ADD	#U.CW1,R4	;POINT TO FIRST CHARACTERISTICS WORD
	MOV	(R4)+,(R3)+	;INSERT DEVICE CHARACTERISTICS WORDS
	MOV	(R4)+,(R3)+	;
	MOV	(R4)+,(R3)+	;
	MOV	(R4),(R3) 	;
	RETURN			;RETURN DIRECTIVE STATUS OF +1
10$:	DRSTS	D.RS5		;SET DIRECTIVE STATUS

	.END
 0         ×€fkQ	› c,        	.TITLE	DRGPP
	.IDENT	/06.06/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 06.06
;
; D. N. CUTLER 3-JAN-74
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	1-JUL-80
;		MSH096 -- IGNORE ALTERNATE HEADER REFRESH AREA WHEN
;			  RETURNING PARTITION PARAMETERS
;
;      	M. S. HARVEY	23-JUL-81
;		MSH182 -- RETURN CORRECT VIRTUAL STARTING ADDRESS
;			  FOR THE TASK REGION
;
; MACRO LIBRARY CALLS
;

	.MCALL	PCBDF$,TCBDF$
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRGPP-GET PARTITION PARAMETERS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO FILL A THREE WORD BUFFER WITH
; PARTITION PARAMETERS.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(65.),DPB SIZE(4.).
;	WD. 01 -- FIRST HALF OF OPTIONAL PARTITION NAME.
;	      WD. 02 -- SECOND HALF OF OPTIONAL PARTITION NAME.
;	WD. 03 -- ADDRESS OF A THREE WORD BUFFER.
;
;	BUFFER FORMAT:
;
;	WD. 00 -- BASE ADDRESS OF PARTITION IN 32W BLOCKS.
;	WD. 01 -- SIZE OF PARTITION IN 32W BLOCKS.
;	WD. 02 -- PARTITION FLAGS WORD.
;
; INPUTS:
;
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.	;MSH096
;	R3=ADDRESS OF THE PARTITION NAME IN THE DPB.			;**-1
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (      DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS EQUAL TO THE STARTING VIRTUAL ADDRESS
;			OF THE SPECIFIED PARTITION IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF SPECIFIED
;			PARTITION IS NOT IN SYSTEM.
;-


	.IF DF	G$$TPP

$DRGPP::			;					;MSH182
									;MSH182
	.IF DF	M$$MGE							;MSH182
									;MSH182
	MOV	H.WND(R4),-(SP)	;SAVE POINTER TO WINDOW BLOCKS		;MSH182
									;MS      H182
	.ENDC								;MSH182

	.IF DF	P$$LAS

	TST	(R3)+		;PARTITION NAME SPECIFIED?		;MSH182
	BNE	10$		;IF NE YES				;**-1
									;MSH096
	.IF DF	A$$HDR							;MSH096
									;MSH096
	MOV	R5,-(SP)	;SAVE TCB ADDRESS			;MSH096
									;MSH096
	.IFTF								;MSH096
									;MSH096
	CALL	$SRATT		;SEARCH FOR REGION ID
	MOV	A.PCB(R5),R2	;PICK UP PCB ADDRESS
									;MSH096
	.IFT								;MSH096
									;MSH096
	MOV	(SP)+,R5	;RESTORE TCB ADDRESS			;MSH096
									;MSH096
	.ENDC	;A$$HDR		      					;MSH096
									;MSH096
	BR	30$		;
10$:	TST	-(R3)		;POINT TO FIRST WORD OF PARTITION NAME
	CALL	$SRNAM		;SEARCH FOR NAMED PARTITION
	BCC	20$		;IF CC NAMED PARTITION FOUND
	DRSTS	D.RS2		;INVALID PARTITION NAME
20$:	TST	(R3)+		;ADVANCE POINTER
30$:	MOV	R2,R4		;COPY PCB POINTER

	.IFF

	MOV	(R3)+,R0	;PARTITION SPECIFIED?			;MSH182
	BEQ	30$		;IF EQ NO				;**-1
	MOV	$PARHD,R4	;GET ADDRESS OF FIRST PARTITION PCB
10$:	CMP	R0,P.NAM(R4)	;FIRST HALF OF NAME MATCH?
	BNE	20$		;IF NE NO
	CMP	(R3),      P.NAM+2(R4) ;SECOND HALF OF NAME MATCH?
	BEQ	40$		;IF EQ YES
20$:	MOV	(R4),R4		;GET ADDRESS OF NEXT PCB
	BNE	10$		;IF NE MORE TO SCAN
	DRSTS	D.RS2		;SET DIRECTIVE STATUS
30$:	MOV	T.PCB(R5),R4	;GET PCB ADDRESS OF CURRENT TASK

	.ENDC


40$:	MOV	2(R3),R3	;GET ADDRESS OF 3 WORD BUFFER


	.IF DF	A$$CHK!M$$MGE

	MOV	#3*2,R1		;SET LENGTH OF BUFFER
	CALL	$ACHKP		;ADDRESS CHECK BUFFER

	.ENDC


;									;MSH096
; IF THE PARTITION IS A TASK PARTITION, THE ALTERNATE HEADER		;MSH096
; REFRESH A      REA MUST NOT BE INCLUDED IN THE PARTITION PARAMETERS		;MSH096
; BECAUSE IT IS NOT MAPPED BY THE TASK. THE ALTERNATE HEADER		;MSH096
; REFRESH AREA IS TOTALLY TRANSPARENT TO THE TASK'S EXECUTION.		;MSH096
; TO DO THIS, SIMPLY ADD THE LENGTH OF THE ALTERNATE HEADER REFRESH	;MSH096
; AREA TO THE STARTING ADDRESS OF THE TASK PARTITION AND SUBTRACT	;MSH096
; IT FROM THAT PARTITION'S LENGTH.					;MSH096
;									;MSH096
; THE ALTERNATE HEADER REFRESH AREA CANNOT EXIST FOR NONCHECKPOINTABLE	;MSH096
; TASK      S.								;MSH096
;									;MSH096
									;MSH096
	.IF DF	M$$MGE

	MOV	(SP)+,R2	;GET POINTER TO WINDOW BLOCKS (H.WND)	;MSH182
	TST	(R2)+		;POINT TO WINDOW ZERO			;MSH182
	CLR	2(SP)		;SET DIRECTIVE STATUS WORD		;**-1
									;MSH096
	.IF DF	A$$HDR							;MSH096
									;MSH096
	MOV	P.REL(R4),(R3)	;INSERT PHYSICAL ADDRESS OF PARTITION	;MSH096
	CLR	R1		;INIT ALTERNATE HEADER AREA LENGTH	;MSH096
									;MSH182
	.IFTF								;MSH182
									;MSH182
	CMP	(R2)+,R4	;IS THIS THE TASK REGION?       (W.BPCB)	;MSH182
	BNE	45$		;IF NE NO, DON'T WORRY ABOUT ALT HDR	;MSH096
	MOV	(R2),2(SP)	;RETURN VIRTUAL STARTING ADDRESS (W.BLVR;MSH182
									;MSH182
	.IFT								;MSH182
									;MSH182
	BIT	#T2.CHK,T.ST2(R5) ;DOES THE TASK HAVE ONE?		;MSH096
	BNE	45$		;IF NE NO, TASK IS NONCHECKPOINTABLE	;MSH096
	MOVB	T.HDLN(R5),R1	;GET ALT HEADER REFRESH AREA LENGTH	;MSH096
									;MSH182
	.IFTF								;MSH182
									;MSH182
45$:				;					;MSH182
									;MSH182
	.IFT								;MSH182
									;MSH1      82
	ADD	R1,(R3)+	;CORRECT REPORTED STARTING ADDRESS	;MSH182
	MOV	P.SIZE(R4),(R3)	;INSERT SIZE OF PARTITION		;MSH096
	SUB	R1,(R3)+	;CORRECT REPORTED SIZE OF PARTITION	;MSH096
									;MSH096
	.IFF	;A$$HDR							;MSH096
									;MSH096
	MOV	P.REL(R4),(R3)+	;INSERT PHYSICAL ADDRESS OF PARTITION	;MSH096
	MOV	P.SIZE(R4),(R3)+ ;INSERT SIZE OF PARTITION		;MSH096
									;MSH096
	.ENDC	;A$$HDR							;MSH096

	.IFF

	MOV	P.REL(R4),R1	;GET STARTING VIRTUAL ADDRESS OF PARTITION
	MOV	R1,(R3)+	;INSERT       PHYSICAL ADDRESS OF PARTITION
	MOV	R1,2(SP)	;SET DIRECTIVE STATUS WORD
	MOV	P.SIZE(R4),(R3)+ ;INSERT SIZE OF PARTITION		;MSH096

	.IFTF

	CLR	(R3)		;ASSUME SYSTEM CONTROLLED PARTITION	;**-1


	.IF DF	D$$YNM&M$$MGE

	BIT	#PS.SYS,P.STAT(R4) ;SYSTEM CONTROLLED PARTITION?
	BNE	60$		;IF NE YES

	.ENDC


	INC	(R3)		;SET USER CONTROLLED PARTITION

	.IFF

	CALL	(PC)		;CONVERT LENGTH TO 32W BLOCKS
	SWAB	-(R3)		;CONVERT TO 32W BLOCKS
	ASLB	1(R3)		;
	ROL	(R3)		;
	ROL	(R3)		;

	.ENDC


60$       :	RETURN

	.ENDC


	.END
            ×¸ykQ	› c,        	.TITLE	DRGSS
	.IDENT	/04.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 04.00
;
; D. N. CUTLER 31-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;
; MODIFIED BY:
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS

;+
; **-$DRGSS-GET SENSE SWITCHES
;
; THIS DIRECTIV      E INSTRUCTS THE SYSTEM TO STORE THE CONTENTS OF THE CONSOLE
; SWITCH REGISTER IN THE ISSUING TASK'S DIRECTIVE STATUS WORD.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(125.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS EQUAL TO THE CONTENTS    ¸   OF THE
;		CONSOLE SWITCH REGISTER.
;-


	.IF DF	G$$TSS

$DRGSS::MOV	SWR,2(SP)	;SET CONTENTS OF CONSOLE SWITCH REGISTER
	RETURN			;RETURN DIRECTIVE STATUS

	.ENDC


	.END
¸          ×¸~kQ	› c,        	.TITLE	DRGTK
	.IDENT	/06.03/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 06.03
;
; D. N. CUTLER 27-MAR-74
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-SEP-80
;		MSH120 -- DON'T RETURN NON-BUFFERED I/O COUNT TO TASK
;
;	DAN BROWN	7-JAN-80
;		DTB005 --       RETURN PROCESSOR MODEL
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,PCBDF$,TCBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRGTK-GET TASK PARAMETERS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO FILL A SIXTEEN WORD BUFFER WITH
; TASK PARAMETERS.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(63.),DPB SIZE(2.).
;	WD. 01 -- ADDRESS OF A SIXTEEN WORD BUFFER.
;
;	BUFFER FORMAT:
;
;	WD. 00 -- FIRST HALF OF I      SSUING TASK'S NAME.
;	WD. 01 -- SECOND HALF OF ISSUING TASK'S NAME.
;	WD. 02 -- FIRST HALF OF TASK'S PARTITION NAME.
;	WD. 03 -- SECOND HALF OF TASK'S PARTITION NAME.
;	WD. 04 -- FIRST HALF OF REQUESTER TASK NAME (NOT SUPPORTED).
;	WD. 05 -- SECOND HALF OF REQUESTER TASK NAME (NOT SUPPORTED).
;	WD. 06 -- TASK PRIORITY.
;	WD. 07 -- CURRENT TASK UIC.
;	WD. 10 -- NUMBER OF LOGICAL UNITS.
;	WD. 11 -- MACHINE TYPE INDICATOR.				;DTB005
;	WD. 12 -- STD FLAGS WORD (NOT SUPPORTED).			;**-1
;	WD. 13 -- AD      DRESS OF TASK SST VECTOR TABLE.
;	WD. 14 -- SIZE OF TASK SST VECTOR TABLE IN WORDS.
;	WD. 15 -- SIZE OF TASK IN BYTES.
;	WD. 16 -- SYSTEM TYPE CODE.
;	WD. 17 -- PROTECTION UIC WORD.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SIXTEEN WORD BUFFER IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF +1.
;-      


	.IF DF	G$$TTK

$DRGTK::MOV	(R3),R3		;GET ADDRESS OF 16. WORD BUFFER


	.IF DF	A$$CHK!M$$MGE

	MOV	#16.*2,R1	;SET LENGTH OF BUFFER IN BYTES
	CALL	$ACHKP		;ADDRESS CHECK PARAMETER BLOCK

	.ENDC


	MOV	T.NAM(R5),(R3)+	;INSERT NAME OF TASK
	MOV	T.NAM+2(R5),(R3)+ ;
	MOV	T.PCB(R5),R0	;GET ADDRESS OF TASK PCB
	MOV	P.NAM(R0),(R3)+	;INSERT NAME OF PARTITION
	MOV	P.NAM+2(R0),(R3)+ ;
	CMP	(R3)+,(R3)+	;POINT TO TASK PRIORITY ADDRESS
	MOVB	T.PRI(R5),(R3)+	;INSERT TASK PRIORITY			;MSH120
	CLRB	      (R3)+		;POINT TO CURRENT UIC WORD		;MSH120
									;**-1

	.IF DF	M$$MUP

	MOV	H.DUIC(R4),(R3)+ ;INSERT DEFAULT UIC

	.IFF

	MOV	H.CUIC(R4),(R3)+ ;INSERT CURRENT UIC

	.ENDC


	MOV	H.NLUN(R4),(R3)+ ;INSERT NUMBER OF LUNS
	MOV	$PRMOD,(R3)+	;INSERT PROCESSOR TYPE			;DTB005
	CLR	(R3)+		;POINT TO TASK SST VECTOR ADDRESS	;DTB005
	MOV	H.TKVA(R4),(R3)+ ;INSERT TASK SST VECTOR ADDRESS	;**-1
	MOV	H.TKVL(R4),(R3)	;INSERT LENGTH OF SST VECTOR IN WORDS
	ASR	(R3)+		;CONVERT TO LENGTH IN WORDS
	MOV	H   X  .WND(R4),R1	;POINT TO NUMBER OF WINDOW BLOCKS
	MOV	W.BHVR+2(R1),(R3) ;CALCULATE TASK SIZE IN BYTES
	SUB	W.BLVR+2(R1),(R3) ;
	INC	(R3)+		;


	.IF NDF	R$$11S

	MOV	#1,(R3)+	;SET CODE FOR RSX-11M

	.IFF

	MOV	#2,(R3)+	;SET CODE FOR RSX-11S

	.ENDC


	MOV	H.CUIC(R4),(R3)	;RETURN PROTECTION UIC
	RETURN			;

	.ENDC


	.END
 X         ×€kQ	› c,        	.TITLE	DRGTP
	.IDENT	/04.07/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 04.07
;
; D. N. CUTLER 30-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	16-OCT-80
;		MSH123 -- ADD SET SYSTEM TIME DIRECTIVE
;
;	DAN BROWN	8-JAN-81
;		DTB008 -- ADD ERROR LOG       HANDLING TO SET SYSTEM TIME


;+
; **-$DRGTP-GET TIME PARAMETERS / SET SYSTEM TIME			;MSH123
;									;**-1
; THE GET TIME PARAMETERS DIRECTIVE INSTRUCTS THE SYSTEM TO FILL	;MSH123
; A SPECIFIED EIGHT WORD BUFFER WITH THE CURRENT TIME PARAMETERS.	;MSH123
;									;MSH123
; THE SET SYSTEM TIME DIRECTIVE INSTRUCTS THE SYSTEM TO OPTIONALLY	;MSH123
; FILL A SPECIFIED EIGHT WORD BUFFER WITH THE CURRENT TIME		;MSH123
; PARAMETERS, AND TO RESET THE SYSTEM TIME PARAMETERS USING A		;MSH123
; SPECIFIED       TIME AND DATE.						;MSH123
;									;**-2
; DPB FORMAT FOR GET TIME PARAMETERS DIRECTIVE:				;MSH123
;									;**-1
;	WD. 00 -- DIC(61.),DPB SIZE(2.).
;	WD. 01 -- ADDRESS OF AN EIGHT WORD BUFFER.
;									;MSH123
; DPB FORMAT FOR SET SYSTEM TIME DIRECTIVE:				;MSH123
;									;MSH123
;	WD. 00 -- DIC(61.),DBP SIZE(3.)					;MSH123
;	WD. 01 -- ADDRESS OF AN EIGHT WORD NEW TIME SPECIFICATION	;MSH123
;	WD. 02 -- ADDRESS OF AN EIGHT WORD OUTPUT BUFFER		;MSH123
;
;	BUFFER FORMAT:
;
;	WD. 00 --       YEAR SINCE 1900.
;	WD. 01 -- MONTH OF YEAR.
;	WD. 02 -- DAY OF MONTH.
;	WD. 03 -- HOUR OF DAY.
;	WD. 04 -- MINUTE OF HOUR.
;	WD. 05 -- SECOND OF MINUTE.
;	WD. 06 -- TICK OF SECOND.
;	WD. 07 -- TICKS PER SECOND.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTI      VE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF A		;MSH123
;			NONPRIVILEGED TASK ATTEMPTED TO SET THE		;MSH123
;			SYSTEM TIME TO A SPECIFIED VALUE.		;MSH123
;		DIRECTIVE STATUS OF 'D.RS93' IS RETURNED IF ONE OF	;MSH123
;			THE SPECIFIED TIME PARAMETERS IS OUT OF RANGE,	;MSH123
;			OR BOTH THE 'TICK OF SECOND' PARAMETER AND	;MSH123
;			THE 'TICKS PER SECOND' PARAMETER WERE SPECIFIED	;MSH123
;			AND       THE 'TICKS PER SECOND' PARAMETER DOES NOT	;MSH123
;			MATCH THE SYSTEM'S CLOCK FREQUENCY.		;MSH123
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF ONE OF THE	;MSH123
;			BUFFERS IS OUTSIDE OF THE ISSUING TASK'S	;MSH123
;			ADDRESS SPACE.					;MSH123
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF THE DPB	;MSH123
;			LENGTH IS ILLEGAL.				;MSH123
;-									;**-2

	.IF DF	E$$LOG&S$$TIM						;DTB008
									;DTB008
	.MCALL	EPKDF$							;DTB008
	EPKDF$			;ERROR LOG PACKET OFFSETS		;DTB008
								      	;DTB008
	.ENDC								;DTB008
									;DTB008
$DRGTP::			;					;MSH123
									;MSH123
	.IF DF	S$$TIM							;MSH123
									;MSH123
	MOVB	-(R3),R4	;GET DBP LENGTH				;MSH123
	CMPB	(R3)+,#2	;GET TIME PARAMETERS DIRECTIVE?		;MSH123
	BEQ	5$		;IF EQ YES, COMPLETE THE DIRECTIVE	;MSH123
	CMPB	R4,#3		;SET SYSTEM TIME DIRECTIVE?		;MSH123
	BNE	65$		;IF NE NO, ILLEGAL DPB LENGTH		;MSH123
	BIT	#T3.PRV,T.ST3(R5) ;TASK PRIVILEGED?			;MSH123
	BNE	3$		;IF NE YES, OK TO USE THIS DIRECTIVE	;MSH123
	DRSTS	D      .RS16		;PRIVILEGE VIOLATION			;MSH123
									;MSH123
3$:	MOV	(R3)+,R5	;COPY NEW TIME ARRAY ADDRESS		;MSH123
									;MSH123
	.IFTF								;MSH123
									;MSH123
5$:	MOV	(R3),R3		;GET PREVIOUS TIME BUFFER ADDRESS	;MSH123
									;MSH123
	.IFT								;MSH123
									;MSH123
	BNE	7$		;IF NE THERE IS ONE			;MSH123
	CMPB	R4,#2		;LEGAL TO DEFAULT THIS BUFFER?		;MSH123
	BNE	15$		;IF NE YES				;MSH123
7$:				;					;MSH123
									;MSH123
	.IFTF								;MSH123
									;**-1

	.IF DF	A$$CHK      !M$$MGE

	MOV	#8.*2,R1	;SET LENGTH OF BUFFER IN BYTES
	CALL	$ACHKP		;ADDRESS CHECK AND MAP PARAMETER BUFFER	;MSH123
									;**-1
	.ENDC


	MOV	#$TTNS-14,R1	;POINT TO CURRENT TIME VECTOR
10$:	MOV	(R1)+,(R3)+	;INSERT TIME PARAMETER IN TASK BUFFER
	CMP	R1,#$TTNS	;ANY MORE TO INSERT?
	BLOS	10$		;IF LOS YES
	MOV	$TKPS,(R3)	;SET TICKS PER SECOND
									;MSH123
	.IFT								;MSH123
									;MSH123
15$:	ROR	R4		;SET SYSTEM TIME DIRECTIVE?		;MSH123
	BCC	48$		;IF CC NO, DIRECTIVE FINISHED		;MSH1      23
	MOV	R5,R3		;GET NEW TIME ARRAY ADDRESS		;MSH123
									;MSH123
	.IF DF	A$$CHK!M$$MGE						;MSH123
									;MSH123
	MOV	#8.*2,R1	;SET LENGTH OF BUFFER IN BYTES		;MSH123
	CALL	$ACHKP		;ADDRESS CHECK AND MAP PARAMETER BUFFER	;MSH123
									;MSH123
	.ENDC								;MSH123
									;MSH123
	MOV	#$TTNS+2,R4	;POINT TO CURRENT TIME VECTOR		;MSH123
	MOV	SP,R2		;SAVE TOP-OF-STACK POINTER		;MSH123
20$:	MOV	-(R4),-(SP)	;COPY TIME PARAMETER			;MSH123
	CMP	R4,#$TTNS-14	;ANY MORE TO COPY?			;MSH123
	B      HI	20$		;IF HI YES				;MSH123
;									;MSH123
; WE NOW HAVE A WORKING COPY OF THE TIME VECTOR ON THE STACK. USING	;MSH123
; THIS TO SUPPLY VALUES FOR USER DEFAULTED TIME PARAMETERS, AN		;MSH123
; ATTEMPT TO BUILD A VALID TIME VECTOR WILL NOW BE MADE.		;MSH123
;									;MSH123
	MOV	#$TLMTS,R1	;POINT TO PARAMETER VALIDATION TABLE	;MSH123
	MOV	SP,R5		;POINT TO CURRENT YEAR PARAMETER	;MSH123
	MOV	R2,-(SP)	;SAVE OLD TOP-OF-STACK POINTER		;MSH123
	CLR	R2		;ASSUME NO LEAP YEAR			;MSH123
	CALL	50$		;VA      LIDATE USER-SPECIFIED YEAR		;MSH123
	BIC	#^C<3>,R0	;IS THIS A LEAP YEAR?			;MSH123
	BNE	25$		;IF NE NO				;MSH123
	INC	R2		;SET THE FEBRUARY CONSTANT		;MSH123
25$:	CALL	50$		;VALIDATE USER-SPECIFIED MONTH		;MSH123
	DEC	R0		;NORMALIZE TO ZERO			;MSH123
	DEC	R0		;IS THIS FEBRUARY?			;MSH123
	BEQ	30$		;IF EQ YES, MAINTAIN FEBRUARY CONSTANT	;MSH123
	CLR	R2		;IF NE NO, ELIMINATE FEBRUARY CONSTANT	;MSH123
30$:	INC	R0		;IS THIS JANUARY?			;MSH123
	BNE	35$		;IF NE NO				;MSH123
	ADD	#12.,R0		;ADJUST FOR       DAYS-PER-MONTH TABLE	;MSH123
35$:	MOVB	$DYPMN-1(R0),R4	;GET NUMBER OF DAYS FOR THIS MONTH	;MSH123
	ADD	R2,R4		;ADD THE FEBRUARY CONSTANT		;MSH123
	DEC	R4		;CORRECT DAYS-PER-MONTH ENTRY BIAS	;MSH123
	MOV	R4,(R1)		;ESTABLISH UPPER LIMIT FOR DAY		;MSH123
	MOV	#4,R2		;SET VALIDATION LOOP COUNT		;MSH123
40$:	CALL	50$		;VALIDATE DAY,HOUR,MINUTE AND SECOND	;MSH123
	DEC	R2		;DONE?					;MSH123
	BGT	40$		;IF GT NO				;MSH123
	MOV	2(R3),R2	;GET USER'S INTENDED FREQUENCY		;MSH123
	BLT	43$		;IF LT, DEFAULTED.       DEFAULT TICK OF SEC	;MSH123
	DEC	R2		;CONVERT TO TICK-OF-SEC HIGH LIMIT	;MSH123
	CMP	R2,(R1)		;CORRECT TICK GRANULARITY?		;MSH123
	BNE	60$		;IF NE SURPRISE!, UNEXPECTED FREQUENCY	;MSH123
	CALL	50$		;VALIDATE TICK OF SECOND		;MSH123
;									;MSH123
; AT THIS POINT, THE ENTIRE SPECIFIED TIME VECTOR HAS BEEN		;MSH123
; VALIDATED AND INCORPORATED INTO THE CURRENT TIME VECTOR		;MSH123
; STORED ON THE STACK. IT'S TIME TO MOVE THE NEW SYSTEM			;MSH123
; TIME VECTOR INTO PLACE, THUS ESTABLISHING THE SYST      EM'S TIME.		;MSH123
;									;MSH123
43$:	INC	R4		;BIAS FOR DAYS-PER-MONTH ENTRY		;MSH123
	MOV	R4,$DPM		;ESTABLISH CURRENT DAYS/MONTH		;MSH123
	MOV	(SP)+,R5	;RESTORE TOP-OF-STACK POINTER		;MSH123
									;DTB008
	.IF DF	E$$LOG							;DTB008
									;DTB008
	BIT	#ES.DAT,$ERFLA	;CHECK TO SEE IF LOGGING TURNED ON	;DTB008
	BEQ	44$		;IF EQ NO				;DTB008
	MOV	#E$CCTL+<400*E$STIM>,R0 ;GET THE ENTRY CODE		;DTB008
	MOV	#12.,R1		;DATA SUBPACKET IS 12 BYTES LONG	;DTB008
	MOV	#SM.HDR!SM.TSK!SM.DAT,R2 ;GE      T INFORMATION TO RECORD	;DTB008
	MOV	SP,R3		;GET POINTER TO DATA ON STACK		;DTB008
	MOV	$TKTCB,R4	;GET THE CURRENT TASK TCB		;DTB008
	CALL	$CRPKT		;CREATE THE PACKET			;DTB008
	BCS	44$		;FAILURE				;DTB008
	CALL	$QUPKT		;AND QUEUE IT				;DTB008
44$:				;REF LABEL				;DTB008
									;DTB008
	.ENDC	; E$$LOG						;DTB008
									;DTB008
	MOV	#$TTNS-14,R4	;POINT PAST CURRENT TIME VECTOR		;MSH123
45$:	MOV	(SP)+,(R4)+	;SET NEW TIME PARAMETER			;MSH123
	CMP	SP,R5		;VECTOR IN PLACE?			;MSH123
	BLO	45      $		;IF LO NOT YET				;MSH123
									;MSH123
	.IFTF								;MSH123
									;MSH123
48$:	RETURN			;DONE!					;MSH123
									;MSH123
	.IFT								;MSH123
									;MSH123
;									;MSH123
; SUBROUTINE CALLED FOR EACH TIME PARAMETER. IF THE USER		;MSH123
; DEFAULTED ANY GIVEN PARAMETER, THE CURRENT SYSTEM'S PARAMETER		;MSH123
; IS SUBSTITUTED. THEN THE PARAMETER MUST PASS THE HIGH/LOW		;MSH123
; LIMITS ESTABLISHED FOR IT STATICALLY OR DYNAMICALLY.			;MSH123
;									;MSH123
50$:	MOV	(R3)+,R      0	;GET USER-SPECIFIED TIME PARAMETER	;MSH123
	BPL	55$		;IF PL PARAMETER NOT DEFAULTED		;MSH123
	MOV	(R5),R0		;PULL IN VALUE FROM CURRENT TIME VECTOR	;MSH123
55$:	CMP	R0,(R1)+	;VALUE TOO HIGH?			;MSH123
	BGT	60$		;IF GT YES				;MSH123
	CMP	R0,(R1)+	;VALUE TOO LOW?				;MSH123
	BLT	60$		;IF LT YES				;MSH123
	MOV	R0,(R5)+	;MOV PARAMETER TO VECTOR ON THE STACK	;MSH123
	RETURN			;PARAMETER IS VALID			;MSH123
									;MSH123
60$:	DRSTS	D.RS93		;PARAMETER OUT OF RANGE			;MSH123
65$:	DRSTS	D.RS99		;ILLE   b   GAL DPB LENGTH			;MSH123
									;MSH123
	.ENDC	;S$$TIM							;MSH123
									;**-1
	.END
 b          ÝÀkQ	› c,        	.TITLE	DRMAP
	.IDENT	/04.02/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 04.02
;
; T. J. MILLER 8-MAR-76
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;	CHUCK SPITZ
;	JOHN COVERT
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	16-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. H      ARVEY	28-APR-80
;		MSH096 -- DON'T ALLOW TASKS TO MAP TO THE ALTERNATE
;			  HEADER REFRESH AREA OF THE TASK REGION
;
	.PAGE
;
; THE FOLLOWING DIRECTIVES RECEIVE AS INPUT POINTERS TO A WINDOW DEFINITION
; BLOCK, WHICH SERVES AS A COMMUNICATION AREA BETWEEN THE ISSUING TASK AND
; THE EXECUTIVE. THE FORMAT OF THE WINDOW DEFINITION BLOCK IS:
;
;		-------------------------------------------------
;	W.NID	!			!			!
;	W.NAPR	!	BASE APR	!	WINDOW ID	!
;		!			!			!
;		!---------------------------------      --------------!
;		!						!
;	W.NBAS	!	VIRTUAL BASE ADDRESS (BYTES)		!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	W.NSIZ	!	WINDOW SIZE (32W BLOCKS)		!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	W.NRID	!	REGION ID				!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	W.NOFF	!	OFFSET IN PARTITION (32W BLOCKS)	!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	W.      NLEN	!	LENGTH TO MAP (32W BLOCKS)		!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	W.NSTS	!	STATUS WORD				!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	W.NSRB	!	SEND/RECEIVE BUFFER ADDR (BYTES)	!
;		!						!
;		-------------------------------------------------
;
; MACRO LIBRARY CALLS
;


	.IF DF	P$$LAS

	.MCALL	HDRDF$,PCBDF$,TCBDF$,WDBDF$
	HDRDF$			;DEFINE HEADER AND WINDOW BLOCK OFFSETS
	PCBDF$			;DEFINE PCB AND ATTACH      MENT DESCR OFFSETS
	TCBDF$			;DEFINE TCB OFFSETS
	WDBDF$			;DEFINE WINDOW DEFINITION BLOCK OFFSETS

;+
; **-$DRCRW-CREATE ADDRESS WINDOW
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO ALLOCATE AN ADDRESS WINDOW IN THE
; HEADER OF THE ISSUING TASK, UNMAPPING AND ELIMINATING ANY OVERLAPPING
; ADDRESS WINDOWS, AND OPTIONALLY TO MAP THE NEW WINDOW.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(117.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF WINDOW DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD       OF THE CURRENT TASK.
;	R3=ADDRESS OF THE WINDOW DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NAPR=BASE APR OF REGION.
;		W.NSIZ=DESIRED SIZE OF ADDRESS WINDOW.
;		W.NRID=ID OF REGION TO MAP OR 0 FOR TASK REGION (IF WS.MAP=1).
;		W.NOFF=OFFSET WITHIN REGION TO MAP (IF WS.MAP=1).
;		W.NLEN=LENGTH TO MAP OR 0 TO DEFAULT TO SMALLER OF WINDOW SIZE
;			OR SIZE LEFT IN PARTITION (I      F WS.MAP=1).
;		W.NSTS=CONTROL INFORMATION.
;			WS.MAP=1 IF MAPPING IS TO OCCUR.
;			WS.WRT=1 IF MAPPING IS TO OCCUR WITH WRITE ACCESS.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF THE SPECIFIED
;			ACCESS IS DENIED IN THE MAPPING STAGE.
;		DIRECTIVE STATUS OF 'D.RS84' IS RETURNED IF AN INVALID APR-
;			WINDOW SIZE COMBI      NATION IS SPECIFIED OR IF AN
;			INVALID REGION OFFSET-LENGTH COMBINATION IS SPECIFIED
;			IN THE MAPPING STAGE.
;		DIRECTIVE STATUS OF 'D.RS85' IS RETURNED IF THERE ARE NO
;			AVAILABLE WINDOW BLOCKS.
;		DIRECTIVE STATUS OF 'D.RS86' IS RETURNED IF AN INVALID REGION
;			ID IS SPECIFIED IN THE MAPPING STAGE.
;
;	OUTPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NID=ASSIGNED WINDOW ID.
;		W.NBAS=VIRTUAL BASE ADDRESS OF WINDOW.
;		W.NLEN=LENGTH ACTUALLY MAPPED.
;		W.NSTS=INDICATION OF ANY CHAN      GES IN MAPPING STATUS.
;			WS.CRW=1 IF ADDRESS WINDOW SUCCESSFULLY ESTABLISHED.
;			WS.ELW=1 IF ANY ADDRESS WINDOWS WERE ELIMINATED.
;			WS.UNM=1 IF ANY ADDRESS WINDOWS WERE UNMAPPED.
;-

$DRCRW::MOV	R4,-(SP)	;SAVE ADDRESS OF TASK HEADER
	MOV	H.WND(R4),R4	;POINT TO NUMBER OF WINDOW BLOCKS
	MOV	(R4)+,R1	;PICK UP NUMBER OF WINDOW BLOCKS
	MOV	(R3)+,R2	;PICK UP APR NUMBER IN HIGH BYTE (W.NID)
	CLRB	R2		;CLEAR OUT LOW BYTE
	CMP	R2,#7*256.	;LEGAL APR NUMBER?
	BHI	40$		;IF HI NO
	ASR	R2		;CONVERT TO B      ASE ADDRESS IN 32W BLOCKS
	MOV	R2,(R3)		;STORE VIRTUAL BASE ADDRESS (W.NBAS)
	ASR	(R3)		;CONVERT TO BYTES (W.NBAS)
	ASR	(R3)		;
	SWAB	(R3)+		;
	TST	(R3)		;IS W.NSIZ=0 (NOT A VALID WINDOW SIZE)
	BEQ	40$		;IF EQ YES -- RETURN ALIGNMENT ERROR
	MOV	R2,-(SP)	;CALCULATE HIGH ADDRESS
	ADD	(R3),(SP)	;(W.NSIZ)
	BCS	40$		;IF CS ILLEGAL SIZE
	CMP	(SP),#2000	;LEGAL TOP ADDRESS?
	BHI	40$		;IF HI NO
	MOV	R1,-(SP)	;SAVE NUMBER OF WINDOWS
	CMP	-(R3),-(R3)	;POINT TO START OF WINDOW BLOCK (W.NBAS)(W.NID)
10$:	T      ST	W.BSIZ(R4)	;POINTING TO AN ESTABLISHED ADDRESS WINDOW?
	BEQ	20$		;IF EQ NO
	MOV	W.BLVR(R4),R0	;PICK UP LOW VIRTUAL ADDRESS
	SWAB	R0		;CONVERT TO 32W BLOCKS
	ASL	R0		;
	ASL	R0		;
	CMP	2(SP),R0	;POSSIBLE VIRTUAL ADDRESS OVERLAP?
	BLOS	30$		;IF LOS NO
	ADD	W.BSIZ(R4),R0	;CALCULATE HIGH ADDRESS
	CMP	R2,R0		;VIRTUAL ADDRESS OVERLAP?
	BHIS	30$		;IF HIS NO
	CMP	R1,(SP)		;OVERLAPPING WINDOW 0?
	BEQ	40$		;IF EQ YES
	CALL	ELAW		;ELIMINATE ADDRESS WINDOW
20$:	TST	(SP)		;HAS A WINDOW BEEN ESTABLISHED?      
	BEQ	30$		;IF EQ YES
	CMP	(R3)+,(R3)+	;POINT TO WINDOW SIZE IN BLOCK (W.NID)(W.NBAS)
	MOV	(R3),W.BSIZ(R4)	;STORE SIZE, ESTABLISHING WINDOW (W.NSIZ)
	MOV	-(R3),W.BLVR(R4) ;SET LOW VIRTUAL ADDRESS (W.NBAS)
	MOVB	-(R3),R0	;PICK UP FIRST APR NUMBER (W.NAPR)
	ASL	R0		;CONVERT APR NUMBER TO WORD OFFSET
	ADD	#UISDR0,R0	;POINT TO FIRST PDR
	MOVB	R0,W.BFPD(R4)	;SET FIRST PDR ADDRESS
	MOVB	(SP),-(R3)	;PICK UP TOTAL NUMBER OF WINDOWS (W.NID)
	SUB	R1,(R3)		;SET ADDRESS WINDOW ID (W.NID)
	CLR	(SP)		;INDICATE       WINDOW HAS BEEN ESTABLISHED
30$:	ADD	#W.BLGH,R4	;POINT TO NEXT WINDOW BLOCK
	DEC	R1		;MORE WINDOW BLOCKS?
	BGT	10$		;IF GT YES
	TST	(SP)+		;WAS AN ADDRESS WINDOW ESTABLISHED?
	BNE	50$		;IF NE NO
	TST	(SP)+		;POP CALCULATED HIGH ADDRESS
	MOV	(SP)+,R4	;RESTORE TASK HEADER ADDRESS
	BIS	#WS.CRW,W.NSTS(R3) ;INDICATE ADDRESS WINDOW WAS CREATED
	BIT	#WS.MAP,W.NSTS(R3) ;IS WINDOW TO BE MAPPED?
	BNE	$DRMAP		;MAP ADDRESS WINDOW AND EXIT
	RETURN			;
40$:	DRSTS	D.RS84		;ALIGNMENT ERROR
50$:	DRSTS	D.RS85		;      NO AVAILABLE WINDOWS

;+
; **-$DRELW-ELIMINATE ADDRESS WINDOW
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO ELIMINATE THE SPECIFIED ADDRESS
; WINDOW, UNMAPPING IT FIRST IF NECESSARY.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(119.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF WINDOW DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE WINDOW DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
      ;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NID=ID OF ADDRESS WINDOW TO ELIMINATE.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS87' IS RETURNED IF AN INVALID
;			ADDRESS WINDOW WAS SPECIFIED.
;
;	OUTPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NSTS=INDICATION OF ANY CHANGES IN MAPPING STATUS.
;			WS.ELW=1 IF ADDRESS WIND      OW SUCCESSFULLY ELIMINATED.
;			WS.UNM=1 IF THE ADDRESS WINDOW WAS UNMAPPED.
;-

$DRELW::CALL	$SRWND		;SEARCH FOR AND VERIFY SPECIFIED WINDOW
ELAW:	CALL	$UNMAP		;UNMAP IF NECESSARY
	BCC	10$		;IF CC UNMAPPING WAS NOT PERFORMED
	BIS	#WS.UNM,W.NSTS(R3) ;INDICATE A WINDOW WAS UNMAPPED
10$:	CLR	W.BSIZ(R4)	;INDICATE ADDRESS WINDOW IS ELIMINATED
	BIS	#WS.ELW,W.NSTS(R3) ;INDICATE ADDRESS WINDOW ELIMINATED
	RETURN			;

;+
; **-$DRMAP-MAP WINDOW TO REGION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO MAP       THE SPECIFIED ADDRESS
; WINDOW TO AN OFFSET IN THE SPECIFIED REGION, UNMAPPING IF NECESSARY.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(121.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF WINDOW DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE WINDOW DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NID=ID OF WINDOW TO MAP.
;		W.NRID      =ID OF REGION TO MAP TO OR 0 TO DEFAULT TO TASK REGION.
;		W.NOFF=OFFSET WITHIN REGION TO MAP TO.
;		W.NLEN=LENGTH TO MAP OR 0 TO DEFAULT TO SMALLER OF WINDOW
;			SIZE OR SIZE LEFT IN PARTITION.
;		W.NSTS=CONTROL INFORMATION.
;			WS.WRT=1 IF WRITE ACCESS IS DESIRED.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF THE DESIRED      
;			ACCESS TO THE REGION IS DENIED.
;		DIRECTIVE STATUS OF 'D.RS84' IS RETURNED IF AN INVALID
;			REGION OFFSET-SIZE COMBINATION IS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS86' IS RETURNED IF AN INVALID
;			REGION ID IS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS87' IS RETURNED IF AN INVALID
;			ADDRESS WINDOW ID IS SPECIFIED.
;
;	OUTPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NLEN=LENGTH ACTUALLY MAPPED.
;		W.NSTS=INDICATION OF ANY CHANGES IN MAPPING STATUS.
;			WS.UNM=1 IF THE WINDOW WAS UN      MAPPED FIRST.
;
; THIS DIRECTIVE FIRST BUILDS AN IMAGE OF A MAPPED WINDOW BLOCK ON THE
; STACK.  THEN IF NO ERRORS ARE ENCOUNTERED, THE CORRESPONDING WINDOW IS
; UNMAPPED, IF NECESSARY, AND SET UP FROM THE STACK IMAGE.
;-

$DRMAP::CALL	$SRWND		;SEARCH FOR AND VERIFY ADDRESS WINDOW ID
	ADD	#W.NRID,R3	;POINT TO SPECIFIED REGION ID
	CALL	$SRATT		;SEARCH FOR MATCHING ATTACHMENT DESCRIPTOR
	MOV	A.PCB(R5),R2	;POINT TO ATTACHED PCB
	MOV	R2,-(SP)	;SET PCB ADDRESS (W.BPCB)
	MOV	W.BLVR(R4),-(SP) ;COPY LOW       VIRTUAL ADDRESS (W.BLVR)
	TST	(R3)+		;POINT TO OFFSET (W.NRID)
	MOV	(R3)+,R0	;PICK UP SPECIFIED OFFSET (W.NOFF)
									;MSH096
	.IF DF	A$$HDR							;MSH096
									;MSH096
	MOV	$TKTCB,R1	;RETRIEVE CURRENT TCB ADDRESS		;MSH096
	CMP	R2,T.PCB(R1)	;MAPPING TO THE TASK REGION?		;MSH096
	BNE	15$		;IF NE NO				;MSH096
	BIT	#T2.CHK,T.ST2(R5) ;TASK HAVE ALTERNATE HEADER AREA?	;MSH096
	BNE	15$		;IF NE NO, NONCHECKPOINTABLE TASK	;MSH096
	MOVB	T.HDLN(R1),R1	;GET ALTERNATE HEADER REFRESH AREA SIZE	;MSH096      
	ADD	R1,R0		;ADD OFFSET PAST THIS AREA		;MSH096
15$:									;MSH096
	.ENDC	;A$$HDR							;MSH096
									;MSH096
	CMP	R0,P.SIZE(R2)	;WITHIN PARTITION?
	BHIS	70$		;IF HIS NO
	MOV	(R3),R1		;PICK UP LENGTH TO MAP (W.NLEN)
	BNE	20$		;IF NE ONE WAS SPECIFIED
	MOV	P.SIZE(R2),R1	;CALCULATE SIZE TO END OF PARTITION
	SUB	R0,R1		;
	CMP	R1,W.BSIZ(R4)	;SIZE TO END GREATER THAN WINDOW SIZE? (W.BSIZ)
	BLOS	20$		;IF LOS NO
	MOV	W.BSIZ(R4),R1	;DEFAULT TO WINDOW SIZE (W.BSIZ)
20$:	MOV	R1,(R3)+	;PASS BACK SI      ZE USED (W.NLEN)
	MOV	R1,-(SP)	;CALCULATE HIGH VIRTUAL ADDRESS (W.BHVR)
	SWAB	(SP)		;MULTIPLY BY 64
	RORB	(SP)		;
	ROR	(SP)		;
	ROR	(SP)		;
	DEC	(SP)		;POINT TO LAST ADDRESSABLE BYTE
	ADD	2(SP),(SP)	;
	MOV	R5,-(SP)	;STORE ADDR OF ATTACHMENT DESCRIPTOR (W.BATT)
	MOV	W.BSIZ(R4),-(SP) ;COPY WINDOW SIZE (W.BSIZ)
	CMP	R1,(SP)		;LEGAL SIZE? (W.BSIZ)
	BHI	70$		;IF HI NO
	BIT	#7,R0		;64-BYTE ALIGNMENT?
	BEQ	30$		;IF EQ NO
	BIT	#WS.64B,(R3)	;64-BYTE ALIGNMENT BEING ALLOWED?
	BEQ	70$		;IF EQ NO
30$:	M      OV	R0,-(SP)	;SET OFFSET IN PARTITION (W.BOFF)
	ADD	R1,R0		;POINT PAST LAST 32W BLOCK MAPPED TO
	CMP	R0,P.SIZE(R2)	;WITHIN PARTITION?
	BHI	70$		;IF HI NO
	MOV	W.BFPD(R4),-(SP) ;SAVE FIRST PDR ADDRESS (W.BFPD)
	BITB	#AS.RED!AS.WRT,A.STAT(R5) ;READ ACCESS ALLOWED?
	BEQ	80$		;IF NE NO
	MOV	#77402,-(SP)	;SET FOR READ ACCESS, 4K SIZE (W.BLPD)
	BIT	#WS.WRT,(R3)	;WRITE ACCESS DESIRED? (W.NSTS)
	BEQ	40$		;IF EQ NO
	BIT	#AS.WRT,A.STAT(R5) ;WRITE ACCESS ALLOWED?
	BEQ	80$		;IF NE NO
	MOV	#77406,(SP)	;SET FO      R 4K SIZE, READ/WRITE ACCESS (W.BLPD)
40$:	INCB	A.MPCT(R5)	;INC MAP COUNT IN ATTACHMENT DESCRIPTOR
	CALL	$UNMAP		;UNMAP WINDOW IF NECESSARY
	BCC	45$		;IF CC WINDOW WAS NOT MAPPED
	BIS	#WS.UNM,(R3)	;INDICATE A WINDOW WAS UNMAPPED (W.NSTS)
45$:	MOVB	W.BFPD(R4),R0	;POINT TO FIRST PDR
	MOV	P.REL(R2),R2	;CALCULATE OFFSET FOR FIRST PDR
	ADD	4(SP),R2	;(W.BOFF)
	CLRB	3(SP)		;INIT NUMBER OF PDR'S (W.BNPD)
50$:	INCB	3(SP)		;INC NUMBER OF PDR'S (W.BNPD)
	MOV	R2,UISAR0-UISDR0(R0) ;SET UP USER APR
	MOV	(SP),(      R0)+	;SET UP NEXT USER PDR
	ADD	#200,R2		;ADVANCE APR OFFSET
	SUB	#200,R1		;DONE YET?
	BGT	50$		;IF GT NO
	SWAB	R1		;SHIFT UNUSED SIZE TO HIGH BYTE
	CLRB	R1		;CLEAR LOW BYTE
	ADD	R1,(SP)		;CALCULATE SIZE IN LAST PDR
	ADD	R1,-(R0)	;SET LAST PDR
	MOV	R4,R3		;COPY POINTER TO WINDOW BLOCK
	ADD	#W.BLGH,R3	;POINT PAST END OF WINDOW BLOCK
60$:	MOV	(SP)+,-(R3)	;COPY IMAGE OF WINDOW BLOCK INTO REAL BLOCK
	CMP	R3,R4		;DONE YET?
	BHI	60$		;IF HI NO
	RETURN			;
70$:	DRSTS	D.RS84		;INVALID OFFSET-LENGTH CO      MBINATION
80$:	DRSTS	D.RS16		;DESIRED ACCESS TO REGION DENIED

;+
; **-$DRUNM-UNMAP ADDRESS WINDOW
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO UNMAP THE SPECIFIED ADDRESS
; WINDOW.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(123.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF WINDOW DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE WINDOW DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;      
;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NID=ID OF WINDOW TO UNMAP.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS WORD RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF THE SPECIFIED
;			ADDRESS WINDOW NOT MAPPED.
;		DIRECTIVE STATUS OF 'D.RS87' IS RETURNED IF AN INVALID
;			ADDRESS WINDOW ID IS SPECIFIED.
;
;	OUTPUT FIELDS IN THE WINDOW DEFINITION BLOCK A      RE:
;		W.NSTS=INDICATION OF ANY CHANGES IN MAPPING STATUS.
;			WS.UNM=1 IF THE WINDOW WAS SUCCESSFULLY UNMAPPED.
;-

$DRUNM::CALL	$SRWND		;SEARCH FOR AND VERIFY WINDOW ID
	CALL	$UNMAP		;UNMAP IF NECESSARY
	BCC	10$		;IF CC WINDOW WAS NOT MAPPED
	BIS	#WS.UNM,W.NSTS(R3) ;INDICATE ADDRESS WINDOW WAS UNMAPPED
	RETURN			;
10$:	DRSTS	D.RS8		;ADDRESS WINDOW WAS NOT MAPPED

;+
; **-$DRSRF-SEND BY REFERENCE
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CREATE A SPECIALLY FORMATTED
; PACKET INCLUDING A RE      FERENCE TO A SPECIFIED REGION WITH ADDITIONAL
; OPTIONAL INFORMATION SUPPLIED BY THE ISSUING TASK.  THE SENDER TASK
; MUST ITSELF HAVE THE ACCESS SPECIFIED IN THE REFERENCE.  THE REFERENCED
; REGION IS ATTACHED TO THE RECEIVING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(69.),DPB SIZE(5.)
;	WD. 01 -- FIRST HALF OF RECEIVER TASK NAME
;	WD. 02 -- SECOND HALF OF RECEIVER TASK NAME
;	WD. 03 -- OPTIONAL EVENT FLAG TO SET WHEN RECEIVE OCCURS
;	WD. 04 -- ADDRESS OF WINDOW DEFINITION BLOCK
;
; INPUTS:
;
      ;	R0=ADDRESS OF THE TCB OF THE RECEIVER TASK
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE RECEIVER TASK
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE EFN NUMBER IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NRID=ID OF REGION TO BE SENT BY REFERENCE.
;		W.NOFF=OFFSET WORD PASSED WITHOUT CHECKING.
;		W.NLEN=LENGTH WORD PASSED WITHOUT CHECKING.
;		W.NSTS      =ALLOWED ACCESS (DEFAULTS TO ACCESS OF SENDER TASK).
;			WS.RED=1 IF READ ACCESS IS TO BE ALLOWED.
;			WS.WRT=1 IF WRITE ACCESS IS TO BE ALLOWED.
;			WS.EXT=1 IF EXTEND ACCESS IS TO BE ALLOWED.
;			WS.DEL=1 IF DELETE ACCESS IS TO BE ALLOWED.
;		W.NSRB=OPTIONAL ADDRESS OF 8 WORD BUFFER OF ADDITIONAL INFO.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS       OF 'D.RS1' IS RETURNED IF A SEND PACKET
;			OR ATTACHMENT DESCRIPTOR COULD NOT BE ALLOCATED.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF AN ATTEMPT IS
;			MADE TO SEND TO AN ACP TASK.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF THE DESIRED
;			ACCESS TO THE REGION IS DENIED.
;		DIRECTIVE STATUS OF 'D.RS86' IS RETURNED IF AN INVALID
;			REGION ID WAS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS97' IS RETURNED IF AN INVALID EFN
;			NUMBER IS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF       THE ADDRESS
;			CHECK OF THE WINDOW DEF BLOCK OR SEND BUFFER FAILS.
;
;	OUTPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		NONE.
;
;	THE FORMAT OF THE SEND BY REFERENCE PACKET IS:
;		WD. 00 -- RECEIVE QUEUE THREAD.
;		WD. 01 -- TCB ADDRESS IF EFN SPECIFIED / 0 IF NOT.
;		WD. 02 -- EFN MASK / FIRST WORD OF SENDER TASK NAME.
;		WD. 03 -- EFN ADDRESS / SECOND WORD OF SENDER TASK NAME.
;		WD. 04 -- REGION ID (ATTACHMENT DESCRIPTOR ADDRESS).
;		WD. 05 -- OFFSET IN REGION WORD.
;		WD. 06 -- LENGTH       OF MAP WORD.
;		WD. 07 -- STATUS WORD.
;		WD. 08 THRU WD. 017 -- CONTENTS OF SEND BUFFER.
;-


	.IF DF	P$$SRF

$DRSRF::BIT	#T3.ACP!T3.NSD,T.ST3(R0) ;SENDS LEGAL TO RECEIVER?
	BNE	60$		;IF NE NO
	MOV	R0,-(SP)	;SAVE RECEIVER TASK TCB ADDRESS
	CALL	$CEFNG		;CONVERT EFN AND LOCK IF GROUP GLOBAL	;MSH049
	BCS	4$		;IF CS NO EFN WAS SPECIFIED		;**-1
	INCB	T.SRCT(R5)	;INCREMENT NUMBER OF INCOMPLETE SREFS
	MOV	R5,-(SP)	;SAVE SENDER TCB ADDRESS
	MOV	R0,-(SP)	;SAVE EFN MASK
	MOV	R1,-(SP)	;SAVE EFN ADDR      ESS
	BR	5$		;
4$:	CLR	-(SP)		;INDICATE NO EFN SPECIFIED
	MOV	T.NAM(R5),-(SP)	;SAVE SENDER TASK NAME
	MOV	T.NAM+2(R5),-(SP) ;
5$:	MOV	(R3),R3		;PICK UP ADDRESS OF WINDOW DEF BLOCK
	MOV	#8.*2,R1	;SET SIZE TO ADDRESS CHECK
	CALL	$ACHKP		;ADDRESS CHECK AND MAP WINDOW DEF BLOCK
	ADD	#W.NRID,R3	;POINT TO REGION ID IN BLOCK
	CALL	$SRATT		;SEARCH FOR SPECIFIED ATTACHMENT DESCRIPTOR
	CMP	(R3)+,-(SP)	;BUMP POINTERS FOR REGION ID (W.NRID)
	MOV	(R3)+,-(SP)	;SAVE OFFSET WORD (W.NOFF)
	MOV	(R3)+,-(SP)	;SAVE L      ENGTH WORD (W.NLEN)
	MOV	(R3)+,-(SP)	;SAVE STATUS WORD (W.NSTS)
	BIC	#^C17,(SP)	;CLEAR ALL BUT ACCESS
	BNE	6$		;IF NE ACCESS SPECIFIED
	MOVB	A.STAT(R5),(SP)	;DEFAULT TO ACCESS OF SENDER TASK
6$:	MOVB	A.STAT(R5),-(SP) ;PUSH ATTACHMENT DESCRIPTOR ADDRESS
	COMB	(SP)		;COMPUTE ACCESS DENIED MASK
	BITB	(SP)+,(SP)	;CHECK SPECIFIED ACCESS AGAINST SENDER TASK
	BNE	70$		;IF NE ACCESS DENIED
	MOV	(R3),R3		;POINT TO SEND BUFFER
	BEQ	10$		;IF EQ THERE IS NONE
	MOV	#8.*2,R1	;SET SIZE TO ADDRESS CHECK
	CALL	$      ACHKP		;ADDRESS CHECK AND MAP SEND BUFFER
	ADD	#8.*2,R3	;POINT TO END OF SEND BUFFER
10$:	CALL	$ALPKT		;ALLOCATE A SEND PACKET
	ADD	#16.*2,R0	;POINT PAST END OF SEND BY REFERENCE DATA
	MOV	#8.,R1		;SET LOOP COUNT FOR COPY
	MOV	R1,R2		;COPY LOOP COUNT
20$:	MOV	R3,-(R0)	;WAS A SEND BUFFER SPECIFIED?
	BEQ	30$		;IF EQ NO
	MOV	-(R3),(R0)	;ELSE COPY NEXT WORD
30$:	DEC	R2		;DONE YET?
	BGT	20$		;IF GT NO
	MOV	(SP),R4		;PICK UP STATUS WORD
40$:	MOV	(SP)+,-(R0)	;INSERT SAVED WORDS ON STACK
	DEC	R1		;DONE       YET?
	BGT	40$		;IF GT NO
	MOV	A.PCB(R5),R2	;PICK UP PCB ADDRESS FROM ATT DESCRIPTOR
	BIT	#PS.COM,P.STAT(R2) ;COMMON PARTITION?
	BEQ	90$		;IF EQ NO, TASK PARTITION IS ILLEGAL
	MOV	(R0),R5		;PICK UP SAVED RECEIVER TASK ADDRESS
	MOV	R0,-(SP)	;SAVE ADDRESS OF SEND PACKET
	CALL	$CRATT		;ATTACH RECEIVER TASK TO REGION
	MOV	(SP)+,R0	;RETRIEVE ADDRESS OF PACKET
	BCS	80$		;IF CS ALLOCATION FAILURE
	MOV	R1,10(R0)	;SET REGION ID IN PACKET
	MOV	R0,R1		;COPY POINTER TO PACKET
	TST	(R0)+		;POINT TO TCB ADDRE      SS
	TST	(R0)+		;EFN SPECIFIED?
	BEQ	50$		;IF EQ NO
									;MSH049
	.IF NDF	G$$EFN							;MSH049
									;MSH049
	BIC	(R0)+,@(R0)+	;CLEAR SPECIFIED EVENT FLAG NOW
									;MSH049
	.IFF								;MSH049
									;MSH049
	MOV	(R0)+,-(SP)	;GET EVENT FLAG MASK			;MSH049
	MOV	(R0),R0		;GET EVENT FLAG MASK ADDRESS		;MSH049
	BIC	#1,R0		;CLR GRP GLOBAL 2ND WORD INDICATOR	;MSH049
	BIC	(SP)+,(R0)	;CLEAR SPECIFIED EVENT FLAG NOW		;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
50$:	MO      V	R5,R0		;POINT TO RECEIVE BY REFERENCE LISTHEAD
	ADD	#T.RRFL,R0	;


	.IF DF	A$$TRP

	CALL	$QINSF		;INSERT IN RECEIVE QUEUE
	MOV	#AS.RRA,R4	;SET RECEIVE BY REF AST TYPE
	CALL	$DASTT		;DECLARE RECEIVE BY REFERENCE AST
	CALLR	$DRDSE		;DECLARE A SIGNIFICANT EVENT

	.IFF

	CALLR	$QINSF		;INSERT IN RECEIVE QUEUE AND EXIT

	.ENDC


60$:	DRSTS	D.RS2		;ATTEMPT TO SEND TO AN ACP TASK
70$:	DRSTS	D.RS16		;PRIVILEGE VIOLATION
80$:	CALL	$DEPKT		;DEALLOCATE SEND PACKET
	DRSTS	D.RS1		;ALLOCATION FAILU      RE
90$:	CALL	$DEPKT		;DEALLOCATE SEND PACKET
	DRSTS	D.RS86		;INVALID REGION ID (NOT COMMON BLOCK)

;+
; **-$DRRRF-RECEIVE BY REFERENCE
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO DEQUEUE THE NEXT RECEIVE BY
; REFERENCE PACKET IN THE RECEIVE QUEUE, OPTIONALLY EXITING IF THERE IS
; NOT ONE THERE.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(81.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF WINDOW DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE WINDOW       DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NSTS=CONTROL INFORMATION.
;			WS.MAP=1 IF RECEIVED REFERENCE IS TO BE MAPPED.
;			WS.RCX=1 IF TASK EXIT DESIRED IF NO PACKET FOUND.
;		W.NSRB=OPTIONAL ADDRESS OF 10 WORD BUFFER FOR ADDITIONAL INFO.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS       RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF THERE IS NO
;			RECEIVE BY REFERENCE ENTRY IN THE QUEUE.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF THE ADDRESS
;			CHECK OF THE RECEIVE BUFFER FAILS.
;
;	OUTPUT FIELDS IN THE WINDOW DEFINITION BLOCK ARE:
;		W.NRID=ASSIGNED REGION ID OF THE REFERENCED REGION.
;		W.NOFF=OFFSET WORD SPECIFIED BY SENDER TASK.
;		W.NLEN=LENGTH WORD SPECIFIED BY SENDER TASK.
;		W.NSTS=STATUS WORD SPECIFIED BY SENDER TASK.
;		      	WS.RED=1 IF ATTACHED WITH READ ACCESS.
;			WS.WRT=1 IF ATTACHED WITH WRITE ACCESS.
;			WS.EXT=1 IF ATTACHED WITH EXTEND ACCESS.
;			WS.DEL=1 IF ATTACHED WITH DELETE ACCESS.
;			WS.RRF=1 IF RECEIVE WAS SUCCESSFUL.
;-

$DRRRF::MOV	KISAR6,-(SP)	;SAVE APR6 BIAS
	MOV	R3,-(SP)	;SAVE WINDOW DEFINITION BLOCK POINTER
	MOV	T.RRFL(R5),R2	;PICK UP FIRST RECEIVE BY REF PACKET
	BEQ	60$		;IF EQ THERE IS NONE
	CLR	-(SP)		;INIT EFN ADDRESS
	CLR	-(SP)		;INIT EFN MASK
	TST	(R2)+		;POINT TO RECEIVER TCB ADDRESS I      N PACKET
	MOV	(R2)+,R0	;PICK UP TCB ADDRESS
	BEQ	20$		;IF EQ NONE SPECIFIED
	DECB	T.SRCT(R0)	;DECREMENT SENDER'S OUTSTANDING SREFS
	MOV	(R2),(SP)	;SET REAL EFN MASK
	MOV	2(R2),2(SP)	;SET REAL EFN ADDRESS
20$:	MOV	R0,-(SP)	;SAVE TCB ADDRESS
	CMP	(R2)+,(R2)+	;SKIP TO REGION ID
	ADD	#W.NRID,R3	;POINT TO REGION ID WORD IN DEF BLOCK
	MOV	(R2)+,(R3)+	;STORE REGION ID
	MOV	(R2)+,(R3)+	;STORE OFFSET
	MOV	(R2)+,(R3)+	;STORE LENGTH
	BIS	(R2)+,(R3)+	;STORE ACCESS
	MOV	(R3),R3		;PICK UP VIRTUAL ADDR OF EXT      ENDED INFO BUFFER
	BEQ	40$		;IF EQ THERE ONE WAS NOT SPECIFIED
	MOV	#10.*2,R1	;SET SIZE TO ADDRESS CHECK
	MOV	R2,-(SP)	;SAVE R2
	CALL	$ACHKP		;ADDRESS CHECK THE BUFFER
	MOV	(SP)+,R2	;RESTORE R2
	MOV	-14(R2),(R3)+	;STORE THE TASK NAME IN THE BUFFER
	MOV	-12(R2),(R3)+	;
	MOV	-16(R2),R0	;PICK UP SENDER TCB ADDRESS
	BEQ	25$		;IF EQ THERE IS NONE
	MOV	T.NAM+2(R0),-(R3) ;SET REAL TASK NAME
	MOV	T.NAM(R0),-(R3)	;
	CMP	(R3)+,(R3)+	;POINT PAST TASK NAME
25$:	MOV	#8.,R0		;SET LOOP COUNT FOR REST OF INFO      
30$:	MOV	(R2)+,(R3)+	;MOVE REST OF EXTRA INFO
	DEC	R0		;DONE YET?
	BGT	30$		;IF GT NO
40$:	MOV	R5,R3		;SAVE RECEIVER TASK TCB ADDRESS
	MOV	(SP)+,R5	;RETRIEVE SENDER TASK TCB ADDRESS
	MOV	(SP)+,R0	;RETRIEVE EVENT FLAG MASK
	MOV	(SP)+,R1	;RETRIEVE EVENT FLAG WORD ADDRESS
	BEQ	50$		;IF EQ NO FLAG TO SET
	CALL	$SETMG		;SET EFN AND UNLOCK IF GROUP GLOBAL	;MSH049
50$:	MOV	R3,R5		;RESTORE TCB ADDRESS			;**-1
	MOV	R5,R0		;POINT TO RECEIVE BY REFERENCE LISTHEAD
	ADD	#T.RRFL,R0	;
	CALL	$QRMVF		;REMOVE PR      OCESSED PACKET
	MOV	R1,R0		;COPY POINTER TO PACKET
	CALL	$DEPKT		;DEALLOCATE PACKET
	MOV	(SP)+,R3	;RESTORE WINDOW DEFINITION POINTER
	MOV	(SP)+,KISAR6	;RESTORE KERNAL APR6 BIAS
	BIS	#WS.RRF,W.NSTS(R3) ;INDICATE SUCCESSFUL RECEIVE BY REFERENCE
	BIT	#WS.MAP,W.NSTS(R3) ;WINDOW MAP DESIRED?
	BEQ	80$		;IF EQ NO
	CALLR	$DRMAP		;MAP WINDOW
60$:	BIT	#WS.RCX,W.NSTS(R3) ;DOES TASK WISH TO EXIT?
	BEQ	70$		;IF EQ NO
	CMP	(SP)+,(SP)+	;CLEAN STACK
	JMP	$DREXT		;PERFORM TASK EXIT
70$:	DRSTS	D.RS8		;NO REFEREN      CES IN QUEUE
80$:	RETURN			;

	.ENDC


;+
; **-$DRGMX-GET MAPPING CONTEXT
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO RETURN THE MAPPING CONTEXT OF
; THE TASK, I.E. TO FILL IN UP TO N WINDOW DEFINITION BLOCKS,
; WHERE N IS THE TOTAL NUMBER OF WINDOW BLOCKS IN THE TASK HEADER.
; NO INFORMATION IS RETURNED ON UNUSED WINDOW BLOCKS.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(113.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF THE N WINDOW DEFINITION BLOCKS
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF       THE CURRENT TASK.
;	(R3)=ADDRESS OF N WINDOW DEFINITION BLOCKS
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE WINDOW DEFINITION BLOCKS ARE:
;		NONE.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF THE ADDRESS
;			CHECK OF THE N WINDOW BLOCKS PLUS TERMINA      TOR WORD
;			FAILS.
;
;	OUTPUT FIELDS IN EACH WINDOW DEFINITION BLOCK ARE:
;		W.NID=ADDRESS WINDOW ID OF NEXT ESTABLISHED ADDRESS WINDOW.
;		W.NAPR=BASE APR OF THE WINDOW.
;		W.NBAS=VIRTUAL BASE ADDRESS OF THE WINDOW.
;		W.NSIZ=SIZE OF THE ADDRESS WINDOW.
;		W.NRID=REGION ID IF MAPPED OR UNMODIFIED.
;		W.NOFF=OFFSET IN REGION IF MAPPED OR UNMODIFIED.
;		W.NLEN=LENGTH OF MAP IF MAPPED OR UNMODIFIED.
;		W.NSTS=NECESSARY BITS TO RESTORE MAPPING OR 0 IF NOT MAPPED.
;			WS.MAP=1 IF WINDOW IS MAPPED.      
;			WS.WRT=1 IF WINDOW IS MAPPED WITH WRITE ACCESS.
;-


	.IF DF	P$$GMX

$DRGMX::MOV	H.WND(R4),R4	;POINT TO NUMBER OF WINDOW BLOCKS IN HEADER
	MOV	(R4)+,R1	;PICK UP NUMBER OF WINDOW BLOCKS
	MOV	R1,-(SP)	;SAVE NUMBER OF WINDOW BLOCKS
	ASL	R1		;CONVERT TO BYTES TO ADDRESS CHECK
	ASL	R1		;
	ASL	R1		;
	INC	R1		;(INCLUDE WORD FOR TERMINATOR)
	ASL	R1		;
	MOV	(R3),R3		;PICK UP VIRTUAL ADDRESS OF WINDOW BLOCKS
	CALL	$ACHKP		;ADDRESS CHECK AND MAP TO WINDOW BLOCKS
	CLR	-(SP)		;INITIALIZE WINDOW ID C      OUNTER
10$:	TST	W.BSIZ(R4)	;IS NEXT BLOCK AN ESTABLISHED WINDOW?
	BNE	11$		;IF NE YES
	ADD	#W.BLGH,R4	;POINT TO NEXT WINDOW BLOCK
	BR	40$		;BRANCH TO DETERMINE IF MORE BLOCKS
11$:	MOVB	(SP),(R3)+	;SET WINDOW ID (W.NID)
	MOV	(R4)+,-(SP)	;SAVE PCB ADDRESS (W.BPCB)
	MOV	(R4)+,R1	;PICK UP LOW VIRTUAL ADDRESS (W.BLVR)
	MOVB	-1(R4),(R3)	;GET ITS HIGH BYTE (W.BLVR+1)(W.NAPR)
	ASLB	(R3)		;SHIFT TO FORM APR NUMBER (W.NAPR)
	ROLB	(R3)		;
	ROLB	(R3)		;
	ROLB	(R3)+		;
	MOV	R1,(R3)+	;SET VIRTUAL BASE ADDRES      S (W.NBAS)
	MOV	(R4)+,R2	;PICK UP HIGH VIRTUAL ADDRESS (W.BHVR)
	MOV	(R4)+,R0	;PICK ATT DESCRIPTOR ADDRESS (W.BATT)
	MOV	(R4)+,(R3)+	;SET WINDOW SIZE (W.BSIZ)(W.NSIZ)
	TST	(SP)+		;IS THIS WINDOW MAPPED?
	BEQ	20$		;IF EQ NO
	MOV	R0,(R3)+	;SET REGION ID (W.NRID)
	MOV	T.ATT(R5),-(SP)	;PUSH ADDRESS OF FIRST ATTACHMENT DESCRIPTOR
	SUB	#A.TCBL,(SP)	;POINT TO FIRST WORD
	CMP	R0,(SP)+	;TASK REGION?
	BNE	15$		;IF NE NO
	CLR	-2(R3)		;SET IT TO DEFAULT TO TASK REGION (W.NRID)
15$:	MOV	(R4)+,(R3)+	;SET OFFS      ET (W.BOFF)(W.NOFF)
	SUB	R1,R2		;CALCULATE LENGTH
	ADD	#1,R2		;
	ROL	R2		;CONVERT TO 32W BLOCKS
	ROL	R2		;
	ROLB	R2		;
	SWAB	R2		;
	MOV	R2,(R3)+	;SET THE LENGTH (W.NLEN)
	TST	(R4)+		;ADVANCE TO LAST PDR IMAGE (W.BFPD)
	MOV	(R4)+,(R3)	;PICK UP LAST PDR IMAGE (W.BLPD)(W.NSTS)
	BIC	#^C4,(R3)	;CLEAR ALL BUT WRITE ACCESS BIT (W.NSTS)
	ASR	(R3)		;SHIFT INTO PLACE (W.NSTS)
	BIS	#WS.MAP,(R3)+	;INDICATE WINDOW IS MAPPED (W.NSTS)
	BR	30$		;
20$:	ADD	#W.NSTS-W.NRID,R3 ;POINT TO NEXT WINDOW ID BLOCK
	ADD   €  	#W.BLGH-W.BOFF,R4 ;POINT TO NEXT WINDOW BLOCK
	CLR	(R3)+		;CLEAR STATUS WORD
30$:	TST	(R3)+		;SKIP OVER SEND/RECEIVE BUFFER ADDRESS (W.NSRB)
40$:	INC	(SP)		;BUMP WINDOW ID
	CMP	(SP),2(SP)	;DONE YET?
	BLO	10$		;IF LO NO
	MOV	(SP)+,(R3)	;STORE NUMBER OF HEADER SLOTS AS TERMINATOR
	NEG	(R3)		;AND NEGATE
	TST	(SP)+		;CLEAN STACK
	RETURN			;

	.ENDC


	.ENDC


	.END
 €         ÝàGkQ	› c,        	.TITLE	DRMKT
	.IDENT	/05.01/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 05.01
;
; D. N. CUTLER 5-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	17-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
; MARK TIME AND RUN DIRECTIVES
;
; MACRO LIBRARY CALL      S
;

	.MCALL	CLKDF$
	CLKDF$			;DEFINE CLOCK QUEUE CONTROL BLOCK OFFSETS

;+
; **-$DRMKT-MARK TIME
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO DECLARE A SIGNIFICANT EVENT AT A
; SPECIFIED INTERVAL FROM INSSUANCE.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(23.),DPB SIZE(5.).
;	WD. 01 -- EVENT FLAG NUMBER OF EVENT FLAG TO BE SET.
;	WD. 02 -- TIME INTERVAL MAGNITUDE.
;	WD. 03 -- TIME INTERVAL UNITS.
;	WD. 04 -- AST ENTRY POINT ADDRESS.
;
;	IF AN EVENT FLAG IS SPECIFIED, THEN IT IS CLEARED AT ISSUANCE       AND
;	SET AT THE TIME OF THE SIGNIFICANT EVENT.
;
;	IF AN AST ENTRY POINT IS SPECIFIED, THEN AN ASYNCHRONOUS TRAP
;	WILL OCCUR AT THE TIME OF THE SIGNIFICANT EVENT. PS, PC, THE
;	DIRECTIVE STATUS WORD, AND THE SPECIFIED EVENT FLAG NUMBER
;	ARE PUSHED ONTO THE TASK STACK WHEN THE AST IS EFFECTED.
;
; INPUTS:
;
;	R0=EVENT FLAG MASK WORD.
;	R1=EVENT FLAG MASK ADDRESS.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE THIRD WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF       THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS WORD RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF INSUFFICIENT
;			CORE IS AVAILABLE TO ALLOCATE CLOCK QUEUE ENTRY.
;-

	.ENABL	LSB
$DRMKT::MOV	-2(R3),-(SP)	;SAVE EVENT FLAG NUMBER
	MOV	R1,-(SP)	;SAVE EVENT FLAG MASK ADDRESS		;MSH049
									;MSH049
	.IF       DF	G$$EFN							;MSH049
									;MSH049
	BIC	#1,R1		;CLR GRP GLOBAL EFN 2ND WORD INDICATOR	;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
	BIC	R0,(R1)		;CLEAR EVENT FLAG
	MOV	R0,R4		;SAVE EVENT FLAG MASK			;**-1
	CALL	$CVRTM		;CONVERT TIME TO CLOCK TICKS
	MOV	R0,-(SP)	;SAVE HIGH ORDER PART OF TIME
	MOV	R1,-(SP)	;SAVE LOW ORDER PART OF TIME
	MOV	R4,-(SP)	;SAVE EVENT FLAG MASK
	CLR	R4		;SET TYPE OF CLOCK QUEUE ENTRY
	MOV	(R3),-(SP)	;SAVE AST ENTRY POINT ADDRESS
	BR	20$		;

;+      
; **-$DRRUN-RUN TASK
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO GENERATE A CLOCK QUEUE ENTRY
; TO CAUSE A TASK TO BE REQUESTED AT A SPECIFIED DELTA TIME FROM
; ISSUANCE AND TO OPTIONALLY REPEAT THE REQUEST PERIODICALLY.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(17.),DPB SIZE (11.).
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;	WD. 03 -- PARTITION NAME-NOT SUPPORTED BUT MUST BE PRESENT.
;	WD. 04 -- PARTITION NAME-NOT SUPPORTED BUT MUST BE PRESENT.
;	WD. 05 -- REQUEST PRI      ORITY-NOT SUPPORTED BUT MUST BE PRESENT.
;	WD. 06 -- REQUEST UIC.
;	WD. 07 -- DELTA TIME MAGNITUDE.
;	WD. 10 -- DELTA TIME UNITS.
;	WD. 11 -- RESCHEDULE INTERVAL MAGNITUDE.
;	WD. 12 -- RESCHEDULE INTERVAL UNITS.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE OF THE TASK TO BE RUN.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO BE RUN.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE PARTITION NAME IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=      ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF INSUFFICIENT
;			CORE IS AVAILABLE TO ALLOCATE CLOCK QUEUE ENTRY.
;-

$DRRUN::MOV	R0,R5		;SAVE TCB ADDRESS OF TASK TO RUN
	ADD	#6,R3		;POINT TO REQUEST UIC IN DPB
	CLR	-(SP)		;SET DUMMY EFN NUMBER


	.IF DF	M$$MUP

	MOV	(R3)+,R1	;PIC      K UP SPECIFIED UIC
	MOV	R3,-(SP)	;SAVE R3
	CALL	$UISET		;ESTABLISH DEFAULT AND CURRENT UIC'S
	MOV	(SP)+,R3	;RESTORE R3
	BCS	30$		;IF CS NONPRV TASK SPECIFIED DIFF UIC
	MOV	R1,-(SP)	;SAVE CURRENT UIC

	.IFF

	MOV	(R3)+,-(SP)	;SAVE SPECIFIED UIC

	.ENDC


	CALL	$CVRTM		;CONVERT DELTA TIME TO CLOCK TICKS
	MOV	R0,-(SP)	;SAVE HIGH ORDER PART OF TIME
	MOV	R1,-(SP)	;SAVE LOW ORDER PART OF TIME
	MOV	#C.SSHT,R4	;ASSUME SINGLE SHOT REQUEST
	MOV	(R3)+,R0	;ANY RESCHEDULE INTERNAL SPECIFIED?
	BEQ	10$	      	;IF EQ NO
	CMP	-(R3),-(R4)	;ADJUST DPB ADDRESS AND ENTRY TYPE
	CALL	$CVRTM		;CONVERT RESCHEDULE INTERNAL TO CLOCK TICKS
10$:	MOV	R0,-(SP)	;SAVE HIGH ORDER PART OF TIME
	MOV	R1,-(SP)	;SAVE LOW ORDER PART OF TIME
20$:	CALL	$ALCLK		;ALLOCATE A CLOCK QUEUE CONTROL BLOCK
	MOV	(SP)+,C.RSI(R0)	;INSERT AST ADDRESS/LOW PART OF RSI
	MOV	(SP)+,C.RSI+2(R0) ;INSERT EFN MASK/HIGH PART OF RSI
	MOV	(SP)+,R2	;RETRIEVE DELTA TIME TICKS COUNT
	MOV	(SP)+,R1	;
	MOV	(SP)+,C.UIC(R0)	;INSERT EFN MASK ADDRESS/UIC
	MOVB	   ²   (SP)+,C.EFN(R0)	;INSERT EFN/ZERO BYTE
	CALLR	$CLINS		;INSERT IN CLOCK QUEUE


	.IF DF	M$$MUP

30$:	DRSTS	D.RS16		;PRIVILEGE VIOLATION

	.ENDC


	.DSABL	LSB

	.END
 ²          à`†kQ	› c,        	.TITLE	DRPUT
	.IDENT	/10.03/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 10.03
;
; D. N. CUTLER 6-SEPT-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;	JOHN COVERT
;
; MODIFIED BY:
;
;	M. S. HARVEY	6-OCT-80
;		MSH121 -- ADD SPECIFY REQUESTED EXIT AST DIRECTIVE
;
;	M. S. F      OX	30-JAN-81
;		MF208 -- ADD COMMAND ARRIVAL AST FOR CLIS
;
; SPECIFY FLOATING POINT, POWERFAIL, AND RECEIVE AST TRAPS
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,TCBDF$,PKTDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	PKTDF$			;DEFINE SPECIFIED AST TYPES

;+									;MSH121
; **-$DRREX-SPECIFY REQUESTED EXIT AST					;MSH121
;									;MSH121
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EITHER RECORD THAT		;MSH121
; REQUESTED EXIT ASTS ARE DESIRED OR NOT       DESIRED FOR THE ISSUING	;MSH121
; TASK. WHEN THE AST OCCURS, IT BECOMES DESPECIFIED FOR			;MSH121
; NONPRIVILEGED TASKS. NONPRIVILEGED TASKS MAY NOT RESPECIFY		;MSH121
; THIS AST AFTER IT HAS BEEN EFFECTED ONCE.				;MSH121
;									;MSH121
; DPB FORMAT:								;MSH121
;									;MSH121
;	WD. 00 -- DIC(167.),DPB SIZE(2. OR 3.).				;MSH121
;	WD. 01 -- AST ENTRY POINT ADDRESS OR ZERO.			;MSH121
;	WD. 02 -- RESERVED FOR FUTURE USE.				;MSH121
;									;MSH121
; INPUTS:								;MSH121
;									;MS      H121
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.		;MSH121
;	R3=ADDRESS OF THE AST ADDRESS IN THE DPB			;MSH121
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.			;MSH121
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.			;MSH121
;									;MSH121
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)			;MSH121
;									;MSH121
;	C=0 IF DIRECTIVE SUCCESSFULLY COMPLETED				;MSH121
;		DIRECTIVE STATUS OF +1 IS RETURNED.			;MSH121
;	C=1 IF DIRECTIVE REJECTED.					;MSH121
;		DIRECTIVE STATUS       OF 'D.RS8' IS RETURNED IF ASTS ARE	;MSH121
;			ALREADY NOT DESIRED, OR NONPRIVILEGED TASK	;MSH121
;			ATTEMPTED TO RESPECIFY THIS AST AFTER ONE	;MSH121
;			HAD ALREADY BEEN EFFECTED, OR NONPRIVILEGED	;MSH121
;			TASK ATTEMPTED TO CANCEL A REQUESTED EXIT	;MSH121
;			AST AFTER IT HAD ALREADY BEEN DESPECIFIED	;MSH121
;			WHEN THE AST OCCURRED.				;MSH121
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF		;MSH121
;			DIRECTIVE WAS ISSUED FROM AN AST ROUTINE,	;MSH121
;			OR ISSUING TASK HAD AST RECOGNITION       DISABLED.	;MSH121
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF THE DPB	;MSH121
;			SIZE IS ILLEGAL					;MSH121
;-									;MSH121
									;MSH121
	.ENABL	LSB							;MSH121
									;MSH121
									;MSH121
	.IF DF	A$$TRP&A$$BRT						;MSH121
									;MSH121
$DRREX::BIT	#T2.REX,T.ST2(R5) ;ABORT AST ALREADY EFFECTED?		;MSH121
	BEQ	5$		;IF EQ NO				;MSH121
	BIT	#T3.PRV,T.ST3(R5) ;ISSUING TASK PRIVILEGED?		;MSH121
	BNE	50$		;IF NE YES, TASK AT AST OR DST STATE	;MSH121
	BR	60$		;NON-PRV. TASK C      AN'T REISSUE DIRECTIVE	;MSH121
									;MSH121
5$:	CLR	-(SP)		;ASSUME NO PARAMETERS TO RETURN		;MSH121
	MOV	#7.*2,-(SP)	;SET NUMBER OF BYTES TO ALLOCATE	;MSH121
	MOVB	-(R3),R4	;GET DPB SIZE BYTE			;MSH121
	CMPB	(R3)+,#2	;CORRECT SIZE FOR OLD FORM OF DIRECTIVE?;MSH121
	BEQ	7$		;IF EQ YES, FINISH AST SPECIFICATION	;MSH121
	CMPB	R4,#3		;CORRECT SIZE FOR EXTENDED FORM?	;MSH121
	BNE	9$		;IF NE NO				;MSH121
	ADD	#2.*2,(SP)	;ADJUST NUMBER OF BYTES TO ALLOCATE AND	;MSH121
	MOV	#2,2(SP)	;NUMBER OF PARAMS       FOR EXTENDED DIRECTIVE;MSH121
7$:	MOV	#AS.REA,R4	;SET TYPE FOR ABORT AST			;MSH121
	MOV	#<AS.REA*256.>,-(SP) ;PUSH TYPE FOR ABORT AST		;MSH121
	BR	10$		;JOIN COMMON CODE			;MSH121
									;MSH121
9$:	DRSTS	D.RS99		;ILLEGAL DPB LENGTH			;MSH121
									;MSH121
	.ENDC								;MSH121
									;MSH121
									;MSH121
									; MF208
;+									; MF208
; **-$CAAST-COMMAND ARRIVAL AST FOR CLIS				; MF208
;									; MF208
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EITHER RECORD THAT COMMAND	; MF2      08
; ARRIVAL ASTS ARE DESIRED OR NOT DESIRED FOR THE CLI TASK		; MF208
; THAT ISSUED THE DIRECTIVE. THIS ROUTINE IS ENTERED WHEN THE DRCLI	; MF208
; MODULE DETECTS THIS DIRECTIVE.					; MF208
;									; MF208
; DPB FORMAT:								; MF208
;									; MF208
;	WD. 01 -- DIC(173.),DPB SIZE (2.)				; MF208
;	WD. 02 -- AST ENTRY POINT ADDRESS OR ZERO			; MF208
;									; MF208
; INPUTS:								; MF208
;									; MF208
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK		; MF208
;	R3=ADDRESS O      F THE AST ADDRESS IN THE DPB			; MF208
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK			; MF208
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK			; MF208
;									; MF208
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)			; MF208
;									; MF208
;	C=0 IF DIRECTIVE SUCCESSFULLY COMPLETED.			; MF208
;		DIRECTIVE STATUS OF +1 IS RETURNED			; MF208
;	C=1 IF DIRECTIVE IS REJECTED					; MF208
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST'S ARE	; MF208
;			ALREADY NOT DESIRED.				; MF208
;		DIRE      CTIVE STATUS OF 'D.RS80' IS RETURNED IF DIRECTIVE	; MF208
;			WAS ISSUED FROM AN AST ROUTINE.			; MF208
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF DIRECTIVE	; MF208
;			WAS ISSUED BY A TASK WHICH IS NOT A CLI.	; MF208
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF THERE	; MF208
;			IS INSUFFICIENT POOL TO ALLOCATE AN AST BLOCK	; MF208
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF THE DPB	; MF208
;			SIZE IS ILLEGAL.				; MF208
;									; MF208
;-									; MF208
									; MF208
	.IF DF	A$$C      LI&A$$TRP						; MF208
									; MF208
$CAAST::BIT	#T3.CLI,T.ST3(R5) ;IS CURRENT TASK A CLI		; MF208
	BEQ	70$		;IF EQ NO				; MF208
	MOV	#AS.CAA,R4	;SET TYPE FOR CMD ARRIVAL AST		; MF208
	MOV	#1,-(SP)	;SET NUMBER OF AST PARAMETERS		; MF208
	MOV	#8.*2,-(SP)	;SET NUMBER OF BYTES TO ALLOCATE	; MF208
	MOV	#<AS.CAA*256.>,-(SP) ;PUSH TYPE FOR CMD ARRIVAL AST	; MF208
	BR	10$		;FINISH IN COMMON CODE			; MF208
									; MF208
	.ENDC	;A$$CLI&A$$TRP						; MF208
									; MF208
;+
; **-$DRFEX-SPECIFY F      LOATING POINT EXCEPTION AST
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EITHER RECORD THAT FLOATING POINT
; AST'S ARE DESIRED OR NOT DESIRED FOR THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(111.),DPB SIZE(2.).
;	WD. 01 -- AST ENTRY POINT ADDRESS OR ZERO.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE AST ADDRESS IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE S      TATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST'S ARE ALREADY
;			NOT DESIRED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF DIRECTIVE WAS
;			ISSUED FROM AN AST ROUTINE.
;-

									;**-2
	.IF DF	A$$TRP&F$$LPP

$DRFEX::TST	H.FPSA(R4)	;IS THE TASK BUILT WITH FLOATING POINT
	BEQ	60$		;IF EQ NO  -- BUILT /-FP, GIVE IE.ITS
	MOV	#AS.FPA,R4	;SET TY      PE FOR FLOATING POINT AST
	MOV	#2,-(SP)	;SET NUMBER OF AST PARAMETERS
	MOV	#9.*2,-(SP)	;SET NUMBER OF BYTES TO ALLOCATE
	MOV	#<AS.FPA*256.>,-(SP) ;PUSH TYPE FOR FLOATING POINT AST
	BR	10$		;FINISH IN COMMON CODE

	.ENDC


;+
; **-$DRPUT-SPECIFY POWER RECOVERY AST
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EITHER RECORD THAT POWER RECOVERY
; AST'S ARE DESIRED OR NOT DESIRED FOR THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(109.),DPB SIZE(2.).
;	WD. 01 -- AST ENTRY POINT ADDRESS OR ZER      O.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE AST ADDRESS IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST'S ARE ALREADY
;			NOT DESIRED.
;		DIRECTIVE STATUS OF 'D.RS      80' IS RETURNED IF DIRECTIVE WAS
;			ISSUED FROM AN AST ROUTINE.
;-


	.IF DF	A$$TRP&P$$RFL

$DRPUT::MOV	#AS.PFA,R4	;SET TYPE FOR POWERFAIL AST
	CLR	-(SP)		;SET NUMBER OF AST PARAMETERS
	MOV	#7.*2,-(SP)	;SET NUMBER OF BYTES TO ALLOCATE
	MOV	#<AS.PFA*256.>,-(SP) ;PUSH TYPE FOR POWERFAIL AST
	BR	10$		;FINISH IN COMMON CODE

	.ENDC


;+
; **-$DRRRA-SPECIFY RECEIVE BY REFERENCE AST
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EITHER RECORD THAT RECEIVE
; BY REFERENCE AST'S ARE DESIRED OR NOT D      ESIRED FOR THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(21.),DPB SIZE(2.).
;	WD. 01 -- AST ENTRY POINT ADDRESS OR ZERO.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE AST ADDRESS IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF THE DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF TH      E DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST'S ARE
;			ALREADY NOT DESIRED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF DIRECTIVE
;			WAS ISSUED FROM AN AST ROUTINE.
;-


	.IF DF	A$$TRP&P$$LAS&P$$SRF

$DRRRA::MOV	#AS.RRA,R4	;SET TYPE FOR RECEIVE BY REF AST
	CLR	-(SP)		;SET NUMBER OF AST PARAMETERS
	MOV	#7.*2,-(SP)	;SET NUMBER OF BYTES TO ALLOCATE
	MOV	#<AS.RRA*256.>,-(SP) ;PUSH TYPE FOR RECEIVE BY REF AST
	BR	10$		;FINISH IN COMMON CODE

	.ENDC


;+
; **-      $DRRCV-SPECIFY RECEIVE AST
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EITHER RECORD THAT RECEIVE
; AST'S ARE DESIRED OR NOT DESIRED FOR THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(107.),DPB SIZE(2.).
;	WD. 01 -- AST ENTRY POINT ADDRESS OR ZERO.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE AST ADDRESS IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AN      D PS RETURNED TO TASK)
;
;	C=0 IF THE DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF THE DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AST'S ARE ALREADY
;			NOT DESIRED.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF DIRECTIVE WAS
;			ISSUED FROM AN AST ROUTINE.
;-


	.IF DF	A$$TRP&R$$SND

$DRRCV::MOV	#AS.RCA,R4	;SET TYPE FOR RECEIVE DATA AST
	CLR	-(SP)		;SET NUMBER OF AST PARAMETERS
	MOV	#7.*2,-(SP)	;SET NUMBER OF BYTES TO ALLOCAT      E
	MOV	#<AS.RCA*256.>,-(SP) ;PUSH TYPE FOR RECEIVE DATA AST

	.ENDC


;									;MSH121
; COMMON AST SPECIFICATION AND CANCELLATION CODE			;MSH121
;									;MSH121
									;MSH121
	.IF DF	F$$LPP!P$$RFL!P$$SRF!R$$SND!A$$BRT!A$$CLI		;MSH121
									;**-1

	.IF DF	A$$TRP

10$:	BIT	#T2.AST!T2.DST,(R2) ;ISSUED FROM AST OR AST'S DISABLED?
	BNE	50$		;IF NE YES
	MOV	(R3),R3		;GET AST TRAP ADDRESS
	BEQ	30$		;IF EQ AST'S NOT DESIRED
	CALL	$SRAST		;SEARCH FOR SPECIFIED AST CONTROL BLOCK
	BCC	20$      		;IF CC, ONE ALREADY EXISTS
	CALL	$ALCLK		;ALLOCATE AN AST CONTROL BLOCK
	MOV	R5,R1		;COPY TCB ADDRESS OF CURRENT TASK
	MOV	T.SAST(R1),(R0)	;LINK LIST TO NEW CONTROL BLOCK
	MOV	R0,T.SAST(R1)	;LINK NEW CONTROL BLOCK TO LISTHEAD
20$:	MOV	R0,R1		;COPY CONTROL BLOCK ADDRESS
	TST	(R1)+		;POINT TO AST TYPE IN CONTROL BLOCK
	MOV	(SP)+,(R1)+	;SET AST TYPE
	MOV	(SP)+,(R1)+	;SET NUMBER OF BYTES PER AST
	MOV	R3,(R1)+	;SET AST TRAP ADDRESS
	MOV	(SP)+,(R1)	;SET NUMBER OF PARAMETERS PER AST
	BR	40$		;TAKE COM      MON EXIT
									;MSH121
;									;MSH121
; CANCEL SPECIFIABLE ASTS HERE						;MSH121
;									;MSH121
									;MSH121
30$:	CALL	$SRAST		;SEARCH FOR SPECIFIED AST CONTROL BLOCK
	BCS	60$		;IF CS, THIS TYPE NOT ENABLED
	MOV	(R0),(R1)	;REMOVE THIS TYPE FROM LIST
	CALL	$DECLK		;DEALLOCATE THIS CONTROL BLOCK
40$:	DRSTS	+1		;RETURN SUCCESSFUL DIRECTIVE STATUS
50$:	DRSTS	D.RS80		;SET DIRECTIVE STATUS
60$:	DRSTS	D.RS8		;SET DIRECTIVE STATUS
									; MF208
									; MF208
	.IF DF	A$$CLI							;   À    MF208
									; MF208
70$:	DRSTS	D.RS16		;SET DIRECTIVE STATUS			; MF208
									; MF208
	.ENDC	;A$$CLI							; MF208
									; MF208

	.ENDC


	.ENDC


	.DSABL	LSB

	.END
À          â8	kQ	› c,        	.TITLE	DRRAS
	.IDENT	/09.10/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 09.10
;
; D. N. CUTLER 4-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;	CHUCK SPITZ
;	ALAN GROUPE
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
      ;
;	M. S. HARVEY	8-JAN-80
;		MSH083 -- CORRECT HEADER ADDRESS HANDLING AND CLEAN
;			  UP THE CODE AND COMMENTS
;
;	M. S. HARVEY	20-JAN-81
;		MSH143 -- DON'T SET EVENT FLAG WHEN 'SEND DATA' REJECTED
;			  DUE TO INSUFFICIENT POOL
;
; RECEIVE AND SEND DIRECTIVES
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,TCBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRREC-RECEIVE DATA AND RECEIVE DATA OR EXIT
; **-$DRRCS-RECEIVE DATA OR STOP
;
; THESE       DIRECTIVES INSTRUCT THE SYSTEM TO DEQUEUE A DATA BLOCK FROM THE
; ISSUING TASK'S RECEIVE QUEUE. IF THE DIRECTIVE IS RECEIVE DATA OR EXIT,
; THEN A TASK EXIT WILL BE EFFECTED IF NO DATA IS QUEUED.  IF THE
; DIRECTIVE IS RECEIVE OR STOP, THEN THE ISSUING TASAK WILL BE SUSPENDED
; IF NO DATA IS QUEUED.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(75., 77. OR 139.),DPB SIZE(4.).
;	WD. 01 -- FIRST HALF OF SENDER TASK NAME OR 0 FOR ANY TASK.
;	WD. 02 -- SECOND HALF OF SENDER TASK NAME.
;	WD. 03 -- ADDRESS OF A F      IFTEEN WORD RECEIVE BUFFER.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;		DIRECTIVE STATUS OF 'D.RS22' IS RETURNED IF NO DATA
;			IS RECEIVED ON RECEIVE OR STOP.
;	C=1 IF DIRECTIVE IS REJE      CTED.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF NO DATA
;			IS QUEUED IN TASK'S RECEIVE QUEUE ON RECEIVE
;			DATA DIRECTIVE.
;		DIRECTIVE STATUS OF 'D.RS80' IS RETURNED IF THE ISSUING
;			TASK IS AT AST STATE AND ISSUED THE RECEIVE OR
;			STOP DIRECTIVE.
;		DIRECTIVE STATUS OF 'D.RS17' IS RETURNED IF THE		;MSH076
;			ISSUING TASK IS A SLAVE TASK AND HAS AN		;MSH076
;			ACTIVE GROUP GLOBAL EVENT FLAG CONTEXT		;MSH076
;			AND THE NEXT RECEIVE PACKET WILL CHANGE		;MSH076
;			THE TASK'S GROUP NUM      BER.			;MSH076
;
;-


	.IF DF R$$SND

	.IF DF S$$TOP

$DRRCS::TST	(R2)		;ISSUING TASK AT AST STATE?		;**-2
	BPL	$DRREC		;IF PL NO				;MSH083
	DRSTS	D.RS80		;ISSUING TASK IS AT AST STATE		;MSH083
									;**-1
	.ENDC	;S$$TOP

$DRREC::MOV	R4,-(SP)	;SAVE HEADER ADDRESS			;MSH083
	MOV	(R3)+,-(SP)	;SAVE FIRST HALF OF SENDER TASK NAME	;**-1
	MOV	(R3)+,-(SP)	;SAVE SECOND HALF OF SENDER TASK NAME
	MOV	(R3),R3		;GET ADDRESS OF RECEIVE BUFFER


	.IF DF	A$$CHK!M$$MGE

	MOV	#15.*2,R1	;SET SIZE O      F BUFFER
	CALL	$ACHKP		;ADDRESS CHECK AND RELOCATE RECEIVE BUF	;MSH083
									;**-1
	.ENDC


	MOV	R3,R4		;SAVE APR6 DISPLACEMENT OF RECEIVE BUF	;MSH083
	MOV	(SP)+,R3	;RETRIEVE 2ND HALF OF SENDER TASK NAME	;**-1
	MOV	(SP)+,R2	;RETRIEVE FIRST HALF OF SENDER TASK NAME
	MOV	R5,R0		;CALCULATE ADDRESS OF TASK RECEIVE
	ADD	#T.RCVL,R0	;QUEUE LISTHEAD
	MOV	R0,R1		;COPY LISTHEAD ADDRESS
3$:	MOV	(R1),R1		;POINT TO NEXT ENTRY IN RECEIVE LIST
	BEQ	20$		;IF EQ THERE IS NONE
	TST	R2		;TASK NAME SPECIFIED?      
	BEQ	4$		;IF EQ NO, DEQUEUE FIRST BLOCK
	CMP	2(R1),R2	;MATCH ON FIRST WORD OF TASK NAME?
	BNE	3$		;IF NE NO
	CMP	4(R1),R3	;MATCH ON SECOND WORD OF TASK NAME?
	BNE	3$		;IF NE NO
4$:	MOV	(SP)+,R2	;RETRIEVE HEADER ADDRESS		;MSH083
									;MSH083
	.IF DF	G$$EFN							;MSH076
									;MSH076
	BIT	#T3.SLV,T.ST3(R5) ;IS THIS TASK A SLAVE TASK?		;MSH076
	BEQ	45$		;IF EQ NO				;MSH076
	TSTB	T.GGF(R5)	;TASK HAVE ACTIVE GRP GLOBAL CONTEXT?	;MSH076
	BEQ	45$		;IF EQ NO, ALLOW RECEIVE		;MSH076
	CMPB	H.CU      IC+1(R2),43(R1) ;WILL GROUP CHANGE WITH THIS PACKET?;MSH083
	BEQ	45$		;IF EQ NO, ALLOW RECEIVE		;MSH076
	DRSTS	D.RS17		;SLAVE TASK HAS GRP GBL CONTEXT ACTIVE	;MSH076
									;MSH076
	.ENDC	;G$$EFN							;MSH076
									;MSH076
45$:	CALL	$QRMVT		;DEQUEUE THE APPROPRIATE PACKET		;MSH076
	BIT	#T3.SLV,T.ST3(R5) ;IS RECEIVER A SLAVE TASK?		;**-5
	BEQ	5$		;IF EQ NO
	MOV	40(R1),T.UCB(R5) ;SET TI ADDRESS OF RECEIVER
	MOV	$HEADR,R2	;PICK UP CURRENT TASK HEADER ADDRESS
	MOV	42(R1),H.CUIC(R2) ;SET CURRENT       UIC OF RECEIVER
	MOV	42(R1),H.DUIC(R2) ;SET DEFAULT UIC OF RECEIVER
5$:	MOV	R1,R0		;SAVE ADDRESS OF ENTRY REMOVED		;**-4
	TST	(R1)+		;POINT TO SENDER TASK NAME		;MSH083
	MOV	#15.,R2		;SET LOOP COUNT				;**-1
10$:	MOV	(R1)+,(R4)+	;MOVE DATA BLOCK TO TASK BUFFER
	DEC	R2		;ANY MORE WORDS TO MOVE?
	BGT	10$		;IF GT YES
	CALLR	$DEPKT		;DEALLOCATE RECEIVE QUEUE PACKET

20$:	MOV	(SP)+,R4	;RETRIEVE HEADER ADDRESS		;MSH083
	CMPB	#77.,$DICSV	;RECEIVE DATA OR EXIT DIRECTIVE?	;MSH083
	BNE	30$		;IF NE NO				      ;MSH083
	CALLR	$DREXT		;EXIT TASK				;MSH083
30$:									;MSH083
	.IF DF	S$$TOP							;MSH083
									;MSH083
	CMPB	#139.,$DICSV	;RECEIVE OR STOP DIRECTIVE?		;MSH083
	BNE	50$		;IF NE NO, JUST A RECEIVE DATA		;MSH083
	CALL	$STPCT		;STOP CURRENT TASK			;MSH083
	DRSTS	D.RS22		;RETURN IS.SET				;MSH083
									;MSH083
	.ENDC								;MSH083
									;MSH083
50$:	DRSTS	D.RS8		;NO PACKET TO RECEIVE			;MSH083
									;**-36

;+
; **-$DRSND-SEND DATA
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO Q      UEUE A THIRTEEN WORD DATA BLOCK
; IN A SPECIFIED TASK'S RECEIVE QUEUE.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(71.),DPB SIZE(5.).
;	WD. 01 -- FIRST HALF OF RECEIVER TASK NAME.
;	WD. 02 -- SECOND HALF OF RECEIVER TASK NAME.
;	WD. 03 -- ADDRESS OF THIRTEEN WORD DATA BLOCK.
;	WD. 04 -- EVENT FLAG NUMBER (OPTIONAL).
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE RECEIVER TASK.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE RECEIVER TASK.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRES      S OF THE DATA BLOCK ADDRESS IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF INSUFFICIENT
;			CORE IS AVAILABLE TO QUEUE THE DATA BLOCK.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF RECEIVER
;			TASK IS AN ANCILLARY CONTRO      L PROCESSOR.
;-

$DRSND::BIT	#T3.ACP!T3.NSD,T.ST3(R0) ;SENDS ALLOWED TO RECEIVER?
	BNE	20$		;IF NE NO
	MOV	R0,-(SP)	;SAVE TCB ADDRESS OF RECEIVER TASK
	MOVB	2(R3),-(SP)	;SAVE EVENT FLAG NUMBER
	MOV	(R3),R3		;GET ADDRESS OF DATA BUFFER


	.IF DF	A$$CHK!M$$MGE

	MOV	#13.*2,R1	;SET SIZE OF BUFFER
	CALL	$ACHKP		;ADDRESS CHECK DATA BUFFER

	.ENDC


	CALL	$ALPKT		;ALLOCATE SEND PACKET			;**-2
	MOV	T.UCB(R5),40(R0) ;SET UCB ADDRESS			;**-4
	MOV	H.CUIC(R4),42(R0) ;SET CURRENT (PROTECTION) UIC
	      MOV	R0,R4		;SAVE PACKET ADDRESS			;MSH143
	MOVB	(SP)+,R0	;RETRIEVE OPTIONAL EVENT FLAG NUMBER	;MSH143
	CALL	$SETF		;SET THE EVENT FLAG			;MSH143
	MOV	R3,R0		;SAVE ADDRESS OF DATA BUFFER		;MSH143
	MOV	R4,R1		;COPY ADDRESS OF ALLOCATED PACKET	;MSH143
	TST	(R4)+		;POINT TO SECOND WORD OF PACKET		;MSH143
	MOV	T.NAM(R5),(R4)+ ;INSERT SENDER TASK NAME IN SEND PACKET	;MSH143
	MOV	T.NAM+2(R5),(R4)+ ;					;MSH143
	MOV	#13.,R2		;SET LOOP COUNT				;**-9
10$:	MOV	(R0)+,(R4)+	;MOVE DATA TO SEND PACKET		;MSH143   Æ  
	DEC	R2		;ANY MORE WORDS TO MOVE?		;**-1
	BGT	10$		;IF GT YES
	MOV	(SP),R0		;CALCULATE ADDRESS OF RECEIVER TASK'S
	ADD	#T.RCVL,R0	;RECEIVE QUEUE LISTHEAD
	CALL	$QINSF		;INSERT SEND PACKET IN RECEIVE QUEUE
	MOV	#AS.RCA,R4	;SET CODE FOR RECEIVE DATA AST
	MOV	(SP)+,R5	;RETRIEVE RECEIVER TASK TCB ADDRESS
	CALL	$DASTT		;DECLARE RECEIVE AST
	CALLR	$DRDSE		;DECLARE A SIGNIFICANT EVENT
20$:	DRSTS	D.RS2		;SET DIRECTIVE STATUS

	.ENDC


	.END
 Æ         âè!kQ	› c,        	.TITLE	DRREQ
	.IDENT	/05.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 05.00
;
; D. N. CUTLER 13-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	22-DEC-80
;		MSH066 -- CORRECT COMMENTS
;
; REQUEST TASK DIRECTIVE
;
; MACRO LIBRARY CA      LLS
;


	.IF NDF P$$OFF

	.MCALL	TCBDF$
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRREQ-REQUEST TASK
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO REQUEST THE EXECUTION
; OF A SPECIFIED TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(11.),DPB SIZE(7.).
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;	WD. 03 -- PARTITION NAME-NOT SUPPORTED BUT MUST BE PRESENT.
;	WD. 04 -- PARTITION NAME-NOT SUPPORTED BUT BUST BE PRESENT.
;	WD. 05 -- REQUEST PRIORITY-NOT SUP      PORTED BUT MUST BE PRESENT.
;	WD. 06 -- REQUEST UIC.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TASK TO BE REQUESTED.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO BE REQUESTED.
;	R2=ADDRESS OF SECOND TASK STATUS WORD OF THE CURRENT TASK.	;MSH066
;	R3=ADDRESS OF THE PARTITION NAME IN THE DPB.			;**-1
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY CO      MPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF PARTITION
;			CONTROL BLOCK CANNOT BE ALLOCATED.
;		DIRECTIVE STATUS OF 'D.RS7' IS RETURNED IF SPECIFIED.
;			TASK IS ALREADY ACTIVE.
;-

$DRREQ::MOV	6(R3),R1	;GET REQUEST UIC


	.IF DF	M$$MUP

	CALL	$UISET		;ESTABLISH DEFAULT AND CURRENT UIC'S

	.ENDC


	MOV	T.UCB(R5),R2	;GET ADDRESS OF REQUESTER TI UCB
	CALL	$TSKRP		;REQUEST TASK EXECUTION
	BCS	10$		;IF CS TASK   .   ALREADY ACTIVE
	RETURN			;RETURN DIRECTIVE STATUS OF +1


	.IF DF	D$$YNM&M$$MGE

10$:	BEQ	20$		;IF EQ TASK ALREADY ACTIVE
	DRSTS	D.RS1		;SET DIRECTIVE STATUS
20$:	DRSTS	D.RS7		;SET DIRECTIVE STATUS

	.IFF

10$:	DRSTS	D.RS7		;SET DIRECTIVE STATUS

	.ENDC

	.ENDC	;NDF P$$OFF

	.END
 .         LSðskQ	› c,        	.TITLE	MMDRV
	.IDENT	/5.38/
 
;
; COPYRIGHT (C) 1978, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;VERSION 5.38
;
; JANICE CLEARY 15-SEP-75
;
;	J. CLEARY	27-DEC-78
;
;		JC026 -- ADD CHECK FOR IQ.X IN SELERR
;
;	J. CLEARY	27-DEC-78
;
;		JC027 -- CLEAN UP TIMEOUT FOR CASE WHERE DRIVE HANGS CNTRLR
;
;	J. CLEARY	23-JAN-79
;
;		JC028 -- ADD SUPPORT FOR       MULTI-CONTROLLERS
;
;	J. CLEARY	23-JAN-79
;
;		JC029 -- ADD RH11 SUPPORT FOR 22-BIT ADDRESSING
;
;	J. CLEARY	9-FEB-79
;
;		JC030 -- INCLUDE POWERFAIL CODE
;
;	J. CLEARY	10-MAR-79
;
;		JC033 -- FIX PROBLEM IN CHKEOV
;
;	J. CLEARY	4-APR-79
;
;		JC038 -- FIX DENSITY SELECTION ON TM03
;
;	E. BAATZ	21-APR-79
;
;		EB205 -- INCREASE SIMILARITY WITH M-PLUS MMDRV
;
;	J. CLEARY	24-MAY-79
;
;		JC040 -- FIX PROBLEM WITH EXTRA TAPE MARK COUNT WHEN
;			 EOT ENCOUNTERED ON SPACE FILES
;
;
;		TL      002 -- FIX RH11 SUPPORT
;
;		TL003 -- FIX MULTIPLE FORMATTER SUPPORT
;
;		TL004 -- FIX POWERFAIL RECOVERY
;
;		TL005 -- FIX ERROR RETURNS (IE.BBE)
;
;		TL008 -- FIX IO.SMO FOR THE TM03
;
;		TL009 -- GET AROUND HARDWARE SPACE QUIRKS
;
;		TL010 -- FIX END OF VOLUME STATUS RETURN IN STATUS BITS
;
;		TL011 -- FIX EOT STATUS RETURN FOR SPACE OPERATIONS
;
;			** TL011 -SUPERCEDED BY CS002
;
;		TL026 -- FIX CONTROLLER ERROR RECOVERY
;
;		TL030 -- FIX CANCEL TASK CHECKING
;
;		TL048 -- FIX CON      TROLLER RESET AFTER AN ABORT
;
;		TL049 -- UPDATE DENSITY STATUS FOR THE TM03
;
;		TL063 -- RETURN THE CORRECT BLOCK COUNT FOR IO.SPB,IO.SPF
;
;		TL064 -- RETURN THE CORRECT BYTE COUNT FOR READ TM
;
;		TL093 -- IGNORE OPI ERRORS AFTER A SPACE REVERSE
;			 AT BOT. (TM03 HARDWARE QUIRK)
;
;			** TL093 - SUPERCEDED BY CS002
;
;		TL100 -- USE CURRENT TIMEOUT, NOT INTERNAL VALUE
;			 IGNORE NOISE RECORDS <14 BYTES
;
;		TL120 -- USE U.SPC INSTEAD OF U.CW3 FOR SPACING COUNT
;
;		CS001 -- NO M.PEO      V FOR IO.SMO
;
;		CS002 -- CORRECT ERROR RECOVERY AND OTHER DRIVER PROBLEMS
;
; RH11/RH70 TM02/TM03 MAGNETIC TAPE CONTROLLER DRIVER
.PAGE
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$,ABODF$
	HWDDF$
	PKTDF$
	ABODF$


	.IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

	.ENDC


;
; EQUATED SYMBOLS
;


US.ABO=1			;ABORT IN PROGRESS - U.STS
US.SUP=2			;SUPRESS ERROR RECOVERY
US.PWF=10			;POWER FAIL STATUS
RETRY=12			;RETRY COUNT
RQFLAG=76			;US      ED TO SEE WHETHER $RLCH SHOULD BE CALLED
MINREC=14.			;MINIMUM RECORD SIZE
REV   =	2			;REVERSE BIT FOR SPACE OPERATIONS
NOISE=MINREC			;ANYTHING SMALLER THAN THIS IS NOISE	;TL100
.PAGE									;**-1
;	REGISTER DEFINITION AND OFFSETS					;**-2
;									;**-1
RHCS1	= +0			;RH CONTROL AND STATUS
C1.GO=1				;GO
C1.IE=100			;INTERRUPT ENABLE
C1.RDY=200			;CONTROLLER READY BIT
C1.PSL=2000			;PORT SELECT
C1.DVA=4000			;DEVICE AVAILABLE
C1.TRE=40000			;TRANSFER ERROR
C1.CPE=20000			;CONTROL PARITY E      RROR
C1.SC=100000			;SPECIAL CONDITION
									;**-1
FC.RWU=103			;REWIND, OFF-LINE
FC.RWD=107			;REWIND
FC.ERS=125			;ERASE COMMAND
FC.WEF=127			;WRITE EOF (TAPE MARK)
FC.SPF=131			;SPACE FORWARD
FC.SPR=133			;SPACE REVERSE COMMAND
FC.WRT=161			;WRITE
FC.RED=171			;READ
FC.REV=177			;READ REVERSE
FC.CLR=11			;DRIVE CLEAR

RHWC	= +2			;RH WORD COUNT REGISTER
RHBA	= +4			;RH BUS ADDRESS REGISTER (LOW ORDER 16 BITS)
MTFC	= +6			;TM02/TM03 FRAME COUNT REGISTER
RHCS2	= +10			;RH CONTROL AND ST      ATUS REGISTER 2

C2.CLR= 40			;CONTROLLER CLEAR
C2.IR=	100			;INPUT READY				;CS002
C2.OR=	200			;OUTPUT READY				;CS002
C2.DPE=	400			;PAR ERR ON RH MASSBUS DATA BUS		;CS002
C2.MXF=	1000			;MISSED TRANSFER			;**-3
C2.PGE=	2000			;PROGRAM ERROR
C2.NEM=	4000			;NON-EXISTENT MEMORY
C2.NED=	10000			;NON-EXISTENT DRIVE
C2.UPE=	20000			;UNIBUS PARITY ERROR
C2.WCE=	40000			;WRITE CHECK ERROR
C2.DLT=	100000			;DATA LATE
CS2ERR=	C2.DLT!C2.WCE!C2.UPE!C2.NED!C2.NEM!C2.PGE!C2.MXF!C2.DPE 	;CS002
									      ;CS002
MTDS	= +12			;TM02/TM03 DRIVE STATUS REGISTER	;**-2
DS.SLA=1			;SLAVE ATTENTION
DS.BOT=2			;BEGINNING OF TAPE
DS.TM=4				;TAPE MARK DETECTED
DS.IDB=10			;IDENTIFICATION BURST
DS.SDN=20			;SETTLE DOWN
DS.PES=40			;PHASE ENCODED STATUS
DS.SSC=100			;SLAVE STATUS CHANGE
DS.DRY=200			;DRIVE READY
DS.DPR=400			;DRIVE PRESENT
DS.EOT=2000			;END OF TAPE DETECTED
DS.WRL=4000			;WRITE LOCK
DS.MOL=10000			;MEDIUM ON LINE
DS.PIP=20000			;POSITIONING IN PROGRESS
DS.ERR=40000			;ERROR COMPOSITE
DS      .ATA=100000			;ATTENTION

MTER	= +14			;TM02/TM03 ERROR REGISTER
ER.ILF=1			;ILLEGAL FUNCTION
ER.ILR=2			;ILLEGAL REGISTER
ER.RMR=4			;REGISTER MODIFICATION REFUSED
ER.CPR=10			;CONTROL BUS PARITY ERROR
ER.FMT=20			;FORMAT ERROR
ER.DPR=40			;DATA PARITY ERROR
ER.INC=100			;INCORRECTABLE DATA (PE ONLY)
ER.VPE=ER.INC			;VERTICAL PARITY ERROR (NRZI ONLY)
ER.PEF=200			;FORMAT ERROR (PE ONLY)
ER.LRC=ER.PEF			;LRCC ERROR (NRZI ONLY)
ER.NSG=400			;NON-STANDARD GAP
ER.FCE=1000			;FRAME COUNT ERROR
ER      .CS=2000			;CORRECTABLE SKEW -- PE MODE
ER.ITM=ER.CS			;ILLEGAL TAPE MARK -- NRZI MODE
ER.NEF=4000			;NON-EXECUTABLE FUNCTION
ER.DTE=10000			;DRIVE TIMING ERROR
ER.OPI=20000			;OPERATION INCOMPLETE
ER.UNS=40000			;DRIVE UNSAFE
ER.COR=100000			;CORRECTABLE DATA (PE ONLY)
ER.CRC=ER.COR			;CRC ERROR (NRZI ONLY)

ER.DAT=  ER.CS! ER.NSG! ER.PEF! ER.INC  ;DATA DETECTION ERRORS		;CS002
									;**-1
RHAS	= +16			;RH ATTENTION SUMMARY REGISTER
MTCK	= +20			;TM02/TM03 CRC OR DEAD TRACK REGISTER
MTDB	=       +22			;TM02/TM03 DATA BUFFER
MTMR	= +24			;TM02/TM03 MAINTENANCE REGISTER
MTDT	= +26			;TM02/TM03 DRIVE TYPE REGISTER

DT.SPR=200			;SLAVE PRESENT
DT.DRQ=4000			;DRIVE REGISTER REQUEST
DT.7CH=10000			;SEVEN CHANNEL DRIVE
DT.MOH=20000			;MOVING HEAD DEVICE
DT.TAP=40000			;TAPE
DT.NSA=100000			;NOT SECTOR ADDRESSED

MTSN	= +30			;TM02/TM03 SERIEL NUMBER
MTTC	= +32			;TM02/TM03 TAPE CONTROL REGISTER

TC.1600=2000			;1600 BPI
TC.800=1000			;800 BPI
TC.FMT=300			;FORMATTING BITS - PDP-11 NORMAL
      TC.EVN=10			;EVEN PARITY
									;**-1
	.IF DF	M$$IXD

RHBAE=	74			;MIXED MASSBUS ADDRESS EXT. REGISTER
				;THIS CANNOT BE=74 IF CSR=XXXXXX40
	.IFF								;**-1

RHBAE=	34			;BUS ADDRESS EXTENSION REGISTER

	.ENDC

;									;**-1
; THE FOLLOWING DEFINITIONS ARE THE BIT POSITIONS IN THE MAG TAPE STATUS
; REGISTER.  UNFORTUNATELY, THEY WERE DEFINED ORIGINALLY FOR A TM11 DRIVER,
; SO THAT SOME OF THE BIT POSITIONS REFLECT THE HARDWARE REGISTERS FOR
; THAT CONTROLLER
;

M.PEOV=100000			;TA      PE PAST LOGICAL END OF VOLUME
M.AEOV=40000			;TAPE AT LOGICAL END OF VOLUME
M.BOT=20000			;TAPE AT BOT
M.1600=4000			;1600 BPI PHASE ENCODED (9 CHANNEL ONLY)
M.HWL=2000			;HARDWARE WRITE LOCK
M.RWD=1000			;UNIT IS REWINDING
M.SER=400			;SELECT ERROR HAS OCCURRED
M.IXG=200			;INHIBIT WRITE WITH EXTENDED INTERRECORD
M.SWL=100			;SOFTWARE WRITE LOCK
M.EOF=40			;LAST COMMAND ENCOUNTERED TAPE MARK
M.EOT=20			;LAST COMMAND ENCOUNTERED EOT
M.EVN=10			;EVEN PARITY

USRBTS=4310			;STATUS BITS CONTROLLED       BY THE USER
;	M.1600! M.IXG! M.SWL! M.EVN					;CS002
									;CS002
NEWBTS=M.BOT!M.EOF!M.EOT	;BITS TO BE SET BEFORE $IODON CALLED	;TL010
									;CS002
									;CS002
; LOCAL DATA								;**-35
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
; DIAGNOSTIC FUNCTIONS USE BIT 15 OF RTTBL AS A FLAG FOR INTERRUPT
; SERVICING.

CNTBL:	.BLKW	T$$J16		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	T$$J16		;ERROR RETRY COUNT
SPTBL:	.BLKW	T$$J16		;FOR SPACE CHECKING
SPTOTL:	.      BLKW	T$$J16		;TOTAL BLOCKS SPACED			;TL009
FMTBL:	.BLKW	T$$J16		;FORMAT CODE SAVE AREA
FCCDE:	.BLKW	T$$J16		;FUNCTION CODE SAVE AREA
CMDCNT:	.BLKW	T$$J16		;COMMAND COUNT SAVE AREA
BUFADR:	.BLKW	T$$J16		;U.BUF SAVE AREA
IOFCN:	.BLKW	T$$J16		; > I/O FUNCTION.			;CS002
									;CS002
									;**-1
	.IF GT	T$$J16-1

TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC

.PAGE									;CS002
;+									;CS002
; VALID I/O FUNCTION TABLE						;CS002
;-									;CS002
	.MACRO	DFENT	FUN      C,INDX,RQSTCD,RTRADR,RTRYCD			;CS002
	.WORD	FUNC		;I/O FUNCTION CODE			;CS002
	.BYTE	INDX		;I/O HANDLING (TABLES) INDEX 		;CS002
	.BYTE	RQSTCD		;DEVICE I/O REQUEST CODE		;CS002
	.WORD	RTRADR		;TAPE REPOSITIONED RETURN		;CS002
	.WORD	RTRYCD		;DEVICE ERROR RECOVERY REQUEST CODE	;CS002
	.ENDM	DFENT							;CS002
									;CS002
									;CS002
LGFCN:	DFENT	IO.RLB,FREAD,FC.RED,RTYCMD,FC.SPR  ;READ FORWARD	;CS002
	DFENT	IO.WLB,FWRTE,FC.WRT,RTYCMD,FC.ERS  ;WRITE		;CS002
	DFENT	IO.RLV,FRREV,FC.REV,RTYCMD      ,FC.SPF  ;READ REVERSE	;CS002
	DFENT	IO.EOF,FWEOF,FC.WEF,RTYCMD,FC.ERS  ;WRITE TAPE MARK	;CS002
	DFENT	IO.ERS,FERSE,FC.ERS,   0,    0	   ;ERASE 3" GAP	;CS002
	DFENT	IO.RWD,FRWND,FC.RWD,   0,    0	   ;REWIND		;CS002
	DFENT	IO.RWU,FRWDU,FC.RWU,   0,    0	   ;RWND OFFLINE/UNLOAD	;CS002
	DFENT	IO.SPB,FSPCR,FC.SPF,SPCONT,FC.SPR  ;SPACE BLOCKS	;CS002
	DFENT	IO.SPF,FSPCF,FC.SPF,SPCONT,FC.SPR  ;SPACE FILES 	;CS002
	DFENT	IO.STC,FSETC,	0,     0,    0	   ;SET CHAR		;CS002
	DFENT	IO.SEC,FSENC,	0,     0,    0	         ;SENSE CHAR		;CS002
SMOU:	DFENT	IO.SMO,FSMOU,	0,     0,    0	   ;MOUNT/SET CHAR	;CS002
									;CS002
ENDFCN=.								;CS002
									;CS002
LNGHT=.-SMOU								;CS002
									;CS002
.PAGE									;CS002
;									;**-1
;	FUNCTION CODE INDEX TABLE
;
FREAD	=	0		;READ LOGICAL BLOCK			;**-1
FWRTE	=	2		;WRITE LOGICAL BLOCK
FRREV	=	4		;READ LOGICAL BLOCK REVERSE
FWEOF	=	6		;WRITE TAPE MARK
FERSE	=	10		;ERASE TAPE
FRWND	=	12		;REWIND TAPE
FRWDU	=	14		;REWIND AND UNLOAD
FSPCR	=	16		;SPACE REC      ORDS
FSPCF	=	20		;SPACE FILES
FSETC	=	22		;SET TAPE CHARACTERISTICS
FSENC	=	24		;SENSE TAPE CHARACTERISTICS
FSMOU	=	26		;SET AND MOUNT CHARACTERISTICS
FRTRY	=	30		;RETRY IN PROGRESS
FSPRR	=	22		;SPACE RECORD REVERSE
FSPFR	=	24		;SPACE FILE REVERSE
									;CS002
;									;**-18
;	PRE-INITIATION PROCESSING ROUTINES
;
PRETBL:									;**-1
	.WORD	PRERED		;READ
	.WORD	PREWRT		;WRITE PRE-INITIATION ENTRY
	.WORD	PREREV		;READ REVERSE PRE-INITIATION ROUTINE
	.WORD	PREEOF		;WRITE TAPEMARK PRE-INI      TIATION ENTRY
	.WORD	PREERS		;ERASE PRE-INITIATION ENTRY
	.WORD	PRECOM		;REWIND PRE-INITIATION ENTRY
	.WORD	PRECOM		;REWIND AND UNLOAD PRE-INITIATION ENTRY
	.WORD	PRESPC		;SPACE RECORDS INITIATION
	.WORD	PRESPC		;SPACE FILES INITIATION ENTRY
	.WORD	PRESTC		;SET CHARACTERISTICS FUNCTION ROUTINE
	.WORD	PRESEC		;SENSE CHARACTERISTICS FUNCTION ROUTINE
	.WORD	PRESMO		;MOUNT AND SET CHARACTERISTICS FUNCTION
									;CS002
									;CS002
;									;**-1
;	SUCCESFUL COMPLETION TABLE
;
DONTBL:							      		;**-1
	.WORD	REDDON		;READ FORWARD COMPLETION
	.WORD	WRTDON		;WRITE FORWARD COMPLETION
	.WORD	REVDON		;READ REVERSE COMPLETION
	.WORD	EOFDON		;WRITE TAPE MARK COMPLETION
	.WORD	EXTNST		;ERASE COMPLETION
	.WORD	RWDDON		;REWIND COMPLETION
	.WORD	RWDDON		;REWIND AND UNLOAD COMPLETION
	.WORD	SPFEXT		;SPACE RECORD FORWARD COMPLETION
	.WORD	SPFEXT		;SPACE FILE FORWARD COMPLETION
	.WORD	SPFEXT		;SPACE RECORD REVERSE COMPLETION
	.WORD	SPFEXT		;SPACE FILE REVERSE COMPLETION
	.WORD	SMODON		;IO.SMO REWIN      D COMPLETION (TM03 PROBLEM);CS002
	.WORD	FATAL		;COMPLETION ROUTINE FOR RECOVERY	;**-1
.PAGE
; MASK TABLE - RETRIABLE ERRORS 					;CS002
;		ER.DAT= ER.CS! ER.NSG! ER.PEF! ER.INC			;CS002
ERRMSK:									;CS002
	.WORD	ER.COR! ER.DTE! ER.DAT! ER.FCE! ER.FMT!	ER.CPR	;RD FWD	;CS002
	.WORD	ER.COR!ER.DTE!ER.DAT!ER.FCE!ER.DPR!ER.FMT!ER.CPR ;WRT	;CS002
	.WORD	ER.COR!ER.OPI!ER.DTE!ER.DAT!ER.FCE!ER.FMT!ER.CPR ;RD REV;CS002
	.WORD	ER.COR! ER.DAT! ER.CPR			      	;WTMK	;CS002
	.WORD	0						;ERS	;CS002
	.WORD      	ER.NEF!	ER.FMT					;RWD	;CS002
	.WORD	ER.NEF! ER.FMT					;RWU	;CS002
	.WORD	ER.OPI! ER.FCE				      	;SRFWD	;CS002
	.WORD	ER.OPI! ER.FCE				      	;SFFWD	;CS002
	.WORD	ER.OPI! ER.FCE				      	;SRREV	;CS002
	.WORD	ER.OPI! ER.FCE				      	;SFREV	;CS002
	.WORD	0						;NO FNCT;CS002
	.WORD	0						;RETRY	;CS002
;									;**-20
;	RETRY TABLE
;
RTYTBL:									;**-1
	.WORD	REDRTY		;READ FORWARD RETRY ENTRY POINT
	.WORD	WRTRTY		;WRITE RETRY ENTRY POINT
	.WORD	REVRTY		;READ REVERSE RETRY ENTRY POIN      T
	.WORD	WRTRTY		;WRITE TAPE MARK RETRY ENTRY POINT
	.WORD	FATAL		;ERASE - NOT RETRIABLE
	.WORD	RWDRTY		;REWIND RETRY RETRY ENTRY POINT		;CS002
	.WORD	RWDRTY		;UNLOAD/OFFLINE RETRY ENTRY POINT	;CS002
	.WORD	SPRRTY		;SPACE RECORD RETRY ENTRY POINT		;**-2
	.WORD	SPFRTY		;SPACE FILE FORWARD RETRY ENTRY POINT
	.WORD	SPRRTY		;SPACE RECORD REVERSE RETRY ENTRY POINT
	.WORD	SPFRTY		;SPACE FILE REVERSE RETRY ENTRY POINT
	.WORD	FATAL		;NO RETRY FOR IO.SMO REWIND		;TL008
				;   (FOR TM03 PROBLEM)			;TL008
      	.WORD	FATAL		;RETRY NOT APPLICABLE ON ERROR		;**-1
									;CS002
;	FUNCTION SPECIFIC ERROR CHECK TABLE OF ENTRY POINTS		;**-2
;
CHKTBL:									;**-1
	.WORD	REDERR		;READ FORWARD ERROR CHECKING
	.WORD	COMRTY		;WRITE FORWARD ERROR CHECKING
	.WORD	REVERR		;READ REVERSE ERROR CHECKING
	.WORD	COMRTY		;WRITE TAPE MARK ERROR CHECKING
	.WORD	FATAL		;ERASE - ALL ERRORS FATAL
	.WORD	RWDRTY		;REWIND ERROR CHECKING			;CS002
	.WORD	RWDRTY		;UNLOAD/OFFLINE ERROR CHECKING		;CS002
	.WORD	SPFEXT		;SPACE FWD       BLKS ERR CHECKING		;CS002
	.WORD	SPFEXT		;SPACE FWD FILES ERR CHECKING		;CS002
	.WORD	SPRERR		;SPACE REV BLKS ERR CHECKING		;CS002
	.WORD	SPRERR		;SPACE REV FILES ERR CHECKING		;CS002
	.WORD	FATAL		;IO.SMO REWIND - ALL ERRORS FATAL	;TL008
				;   (FOR TM03 PROBLEM)			;TL008
	.WORD	RTYCON		;CONTINUE RETRY ON FRAME COUNT ERRORS	;**-7
.PAGE
;
; DRIVER DISPATCH TABLE
;

$MMTBL::.WORD	MMINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	MMCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	MMOUT		;DEVICE TIMEOUT       ENTRY POINT
	.WORD	MMPWF		;POWERFAIL ENTRY POINT

;+
; **-MMINI-RH11/RH70 TM02/TM03 MAGNETIC TAPE CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-      
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

MMINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS		;**-1
	BCC	10$		;IF CC PROCESS REQUEST
	RETURN			;NOTHING TO DO OR CONTROLLER BUSY

;
; THE FOLLOWING ARGUMENTS ARE RETURNED       BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RH11/RH70 TM02/TM03 MAGNETIC TAPE FUNCTION INDEPENDENT I/O REQUEST
;	PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUE      STOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB/IO.RWD/IO.SPB/IO.SPF/IO.EOF).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;
10$:	MOV	R5,CNTBL(R3)		;SAVE UCB ADDRESS		;CS002
	MOV	#LGFCN,R2		;RETRIEVE ADDRESS OF LEGAL FUNC ;**-3
	MOV	I.FCN(R1),R      0		;RETREIVE FUNCTION CODE
	BICB	#US.SUP,U.STS(R5)	;CLEAR RETRY SUPPRESS

	.IF DF	D$$IAG

	CLRB	RTTBL+1(R3)		;CLEAR DIAGNOSTIC FLAG
	BITB	#IQ.UMD,R0		;DIAGNOSTIC FUNCTION?
	BEQ	20$			;IF EQ NO
	MOV	#100000,RTTBL(R3)	;STOP RETRIES AND SET DIAG. FLAG
	BISB	#US.SUP,U.STS(R5)	;SUPRESS RETRIES		;**-1
									;CS002
20$:	.ENDC	; D$$IAG						;CS002
									;CS002
	BITB	#IQ.X,R0		;SUPPRESS ERROR RECOVERY?	;**-4
	BEQ	25$			;IF EQ, NO.			;CS002
	BISB	#US.SUP,U.STS(R5)	;SUPPRESS ERROR RECOVERY	;**-1
      25$:	BICB	#IQ.X!IQ.UMD!IQ.Q,R0 	;FUNCTION CODE FOR VALIDATION	;CS002
30$:	CMP	R0,(R2)			;FUNCTION CODE MATCH ?		;CS002
	BEQ	50$			;IF EQ, YES.			;CS002
	ADD	#LNGHT,R2		;NEXT I/O FUNCTION.		;CS002
	CMP	R2,#ENDFCN		;END OF TABLE?			;**-7
	BLO	30$			;NO CHECK NEXT ENTRY
40$:	MOV	#IE.IFC&377,R0		;YES - ILLEGAL FUNCTION
	JMP	EXTNST			;EXIT
									;CS002
50$:	MOV	R2,IOFCN(R3)	;REMEMBER I/O REQUEST			;CS002
	TST	(R2)+		;   AND					;CS002
	MOV	(R2),U.FCDE(R5)	; 	QIO INDEX.			;CS002
	MOVB	U.FCDE(R5),R0      	;SET FUNCTION INDEX IN R0		;**-31
	CLR	SPTBL(R3)	;CLEAR OUT SPACING INDICATOR

	.IF DF	D$$IAG

	TST	RTTBL(R3)	;DIAGNOSTIC FUNCTION?
	BMI	80$		;IF MI YES - NO RETRIES

	.ENDC

	MOV	#RETRY,RTTBL(R3) ;SET RETRY COUNT
80$:	CALL	SELECT		;GET TAPE UNIT STATUS
	CALLR	@PRETBL(R0)	;JMP TO PRE-INITIATION ROUTINE
.PAGE									;**-2
;+
; **-PRESPC - INITIATION ROUTINE FOR SPACE FUNCTIONS
;
;	THIS ROUTINE DOES ALL PRE-PROCESSING FOR SPACE FUNCTIONS.
;	STATUS CONDITIONS ARE CHECKED TO SEE IF SPACEING       SHOULD OCCUR
;	IF NOT THE DRIVER EXITS WITH STATUS RETURN IN R0.
;
;	IF SPACING TO OCCUR U.CNT(R5),I.PRM+4(R1),SPTBL(R3) AND
;	U.SPC(R5) (IF SPACE FILES) ARE SET WITH THE SPACE COUNT.	;TL120
;	THE FUNCTION CODE IS SET IN U.BUF(R5) AND THE FUNCTION INDEX	;**-1
;	SET APPROPRIATLY IN U.FCDE(R5). A BRANCH TO FNCEX IS THEN MADE.
;-									;**-10
									;**-1
PRESPC:	MOV	#IS.SUC&377,R0	;ASSUME 0 SPACE COUNT
	CLR	SPTOTL(R3)	;CLEAR BLOCKS SPACED TABLE ENTRY	;TL009
	MOV	U.BUF(R5),-(SP)	;RETRIEVE SPACE       COUNT
	BEQ	40$		;ZER0 - DONE
	BMI	10$		;IF MI REVERSE SPACE
;SPACE FWD								;CS002
	MOV	#IE.EOV&377,R0	;MAY BE AT EOV				;**-1
	BIT	#M.AEOV,U.CW2(R5)  ;AT EOV?				;TL010
	BNE	40$		;YES CAN'T SPACE FORWARD FROM HERE	;**-1
	NEG	(SP)		;NEED 2'S COMPLEMENT FOR FUNCTION
	BR	20$		;CONTINUE
									;CS002
;SPACE REV								;CS002
10$:	BIC	#M.AEOV,U.CW2(R5)  ;CLEAR AT END OF VOLUME STATUS	;TL010
	MOVB	#FC.SPR,U.FCDE+1(R5) ;SPACE REV FNCTN			;CS002
	ADD	#4,U.FCDE(R5)	;RESET FUNCTION INDEX			;**-2
20      $:	CLR	U.BUF(R5)	;INIT FOR FUNCTION CODE			;CS002
	CMP	#IO.SPF,@IOFCN(R3) ;SPACE FILES?			;CS002
	BNE	30$		;IF NE NO				;**-1
	MOV	(SP),U.SPC(R5)	;YES SAVE REQUESTED COUNT		;TL120
	MOV	(SP),I.PRM+4(R1) ;SAVE FOR LATER CALCULATIONS		;**-1
	MOV	#1,(SP)		;SET FOR MAX SPACE COUNT
30$:	MOV	(SP),U.CNT(R5)	;SET U.CNT
	MOV	(SP)+,SPTBL(R3)	;SAVE FOR TIMEOUT SITUATION
	BR	PWFTST		;INIT REQUEST IF NO PWRFL INDICATION.	;CS002
									;**-3
40$:	TST	(SP)+		;CLEAN UP STACK FOR RETURN
	JMP	EXTNST		;EXIT
.PAGE      
;+									;**-16
;  **-PRESMO - IF TAPE AT BOT, SET TAPE CHARACHTERISTICS 		;CS002
;		 PER USER REQUEST.					;CS002
;-									;**-4
	.ENABL	LSB							;CS002
PRESMO:
	BIT	#M.BOT,U.CW2(R5)	;TAPE AT BOT?			;**-7
	BNE	SMORWD			;YES SET CHARACTERISTICS	;TL008
	MOV	#IE.FHE&377,R0		;NO FATAL ERROR			;**-1
	BR	20$
;+									;TL008
; **-SMORWD - ISSUE REWIND TO CLEAR HUNG EOT STATUS IN TM03'S		;TL008
;	CAUSED BY MANUALLY REWINDING AN ONLINE TAPE PREVIOUSLY AT EOT.	;TL008
;-									;TL008
SMORWD:	      BIC	#M.AEOV,U.CW2(R5)	;CLEAR AT END OF VOLUME STATUS	;TL008
	BIC	#USRBTS!7,U.CW2(R5)	;CLEAR USER BITS		;TL008
	BIC	#^C<USRBTS>,U.BUF(R5)	;CLEAR ALL BUT USER BITS	;TL008
	BIS	U.BUF(R5),U.CW2(R5)	;SET NEW CHARACTERISTICS	;TL008
	MOV	#FC.RWD,U.BUF(R5)	;SET THE FUNCTION CODE (REWIND)	;TL008
	JMP	PRCOM			;DOIT!				;TL008
									;TL008
SMODON:	.IF DF	P$$RFL							;CS002
	BICB	#US.PWF,U.STS(R5)	;CLEAR PWRFLD STATUS		;CS002
	.ENDC								;CS002
									;CS002
	CALL	SELECT							;CS002
	BR	PRESEC					      		;CS002
									;CS002
;+
;
; **-PRESTC - SET CHARACTERISTICS COMMAND
;	SETS THE CHARACTERISTICS DEFINED BY THE USER IN U.CW2(R5)
;
;-
PRESTC:	BIC	#USRBTS!7,U.CW2(R5)	;CLEAR USER BITS
	BIC	#^C<USRBTS>,U.BUF(R5)	;CLEAR ALL BUT USER BITS
	BIS	U.BUF(R5),U.CW2(R5)	;SET NEW CHARACTERISTICS
									;CS002
									;CS002
;+
; **-PRESEC - RETURN TAPE CHARACTERISTIC WORD				;CS002
;-									;**-7
PRESEC:	BIC	#M.PEOV,U.CW2(R5)	;NO M.PEOV FOR IO.SMO REQUEST	;CS001
	MOV	U.CW2(R5),R1		;GET THE STAT      US			;TL049
	MOV	#IS.SUC&377,R0		;SET SUCCESS			;**-9
20$:	JMP	EXIT			;RETRUN
									;CS002
	.DSABL	LSB							;CS002
.PAGE
;+									;**-31
; **-PREWRT - WRITE REQUEST PREPROCESSING:				;CS002
;									;CS002
;	VERIFY AT LEAST MINIMUN RECORD SIZE AND WRITE ENABLED		;CS002
;									;CS002
;-									;**-8
	.ENABL	LSB							;CS002
PREWRT:	MOV	#IE.SPC&377,R0		;ASSUME PARAMETER PROBLEMS
	CMP	#MINREC,I.PRM+4(R1)	;MINIMUM RECORD SIZE?		;**-2
	BHI	30$			;IF HI RECORD TOO SMALL
;+
; **-PREEOF       - INITIATION ROUTINE FOR WRITE TAPE MARK			;**-1
; **-PREERS - INITIATION ROUTINE FOR ERASE
;
;	VERIFY THAT WRITE ENABLED					;CS002
;									;CS002
;-									;**-3
PREEOF:
PREERS:
20$:	MOV	#IE.WLK&377,R0		;ASSUME WRITE LOCKED
	BIT	#M.SWL!M.HWL,U.CW2(R5)	;WRITE LOCKED?
	BNE	30$			;IF EQ YES - EXIT
	CMPB	#FRREV,U.FCDE(R5)	;DATA TRANSFER ?		;CS002
	BLT	PWFTST			;IF LT, NO.			;CS002
;+									;**-1
;
; **-PRERED - INITIATION FOR READ FORWARD
;    PREREV -  READ REVERSE						;CS002
;-							      		;**-7
PRERED:
PREREV:									;CS002
	.IF DF	M$$EXT							;TL002
									;TL002
	BIT	#DV.MBC,U.CW1(R5)	; RH11 ?			;TL002
	BNE	21$			;IF NE, NO - RH70.		;TL002
	CALL	$STMAP			;SET UP UNIBUS MAPPING		;TL002
	ASL	U.BUF(R5)		;SHIFT BITS <4:5>		;TL002
	ASL	U.BUF(R5)		;INTO BITS <8:9>		;TL002
	ASL	U.BUF(R5)		;...				;TL002
	ASL	U.BUF(R5)		;...				;TL002
	CALL	$MPUBM			; SETUP UMR'S FOR TRANSFER	;TL002
	MOV	S.CSR(R4),R2		;RESTORE R2			;TL002
									;TL002
21$:	.ENDC	; M$$EXT						;TL002
						      			;TL002
	MOV	R5,R1			; R1 > 				;CS002
	ADD	#U.BUF,R1		;   U.BUF.			;CS002
									;CS002
	.IF NDF	M$$EXT							;CS002
									;CS002
	.IF DF	M$$MGE							;CS002
									;CS002
	ROL	(R1)			; SETUP				;CS002
	ROL	(R1)			;   A17, A16			;CS002
	ROL	(R1)			;     INTO			;CS002
	ROL	(R1)			;       HI BYTE			;CS002
									;CS002
	.ENDC	; M$$MGE						;CS002
									;CS002
	.ENDC	; M$$EXT						;CS002
									;CS002
	CMPB	#4,U.FCDE(R5)		; READ REVERSE ?		;CS002
	BNE	PWFTST			; IF NE, NO.			      ;CS002
	SUB	#2,U.CNT(R5)		; READ REVERSE -		;CS002
	ADD	U.CNT(R5),2(R1)		;  ADJUST BUFFER POINTER	;CS002
	BCC	22$			;   TO END OF 			;CS002
	ADCB	1(R1)			;    BUFFER AREA.		;CS002
22$:	ADD	#2,U.CNT(R5)		; RESTORE TRANSFER COUNT. 	;CS002
PWFTST:	MOV	#IE.ABO&377,R0		;REQUEST ABORTED IF PWRFLD STATU;CS002
	BITB	#US.PWF,U.STS(R5)	;POWER FAIL OCCUR?		;**-2
	BEQ	PRECOM			;IF EQ NO - CONTINUE
30$:	JMP	EXTNST			;EXIT
									;CS002
	.DSABL LSB							;CS002
									;CS002
;+
; **-PRECOM - COMMON PREP      ROCESSING ENTRY				;**-1
;	AT THIS POINT ALL COMMANDS WHICH REQUIRE HARDWARE
;	PROCESSING AND HAVE SUCCESSFULLY PASSED ALL THE PRE-SCREENING
;	ARE JOINED. A CALL TO SETNDT IS MADE TO SET THE FORMAT,THE
;	FUNCTION CODE IS THEN MOVED TO U.BUF AND WE FALL THROUGH
;	TO FNCEX - FUNCTION EXECUTION.
;-
PRECOM:	MOVB	U.FCDE+1(R5),U.BUF(R5)	;RETRIEVE FUNCTION.		;CS002
PRCOM:	MOVB	U.UNIT(R5),R0		;SET TAPE UNIT #.		;CS002
	BIS	#TC.1600,R0		;ASSUME 1600BPI.		;CS002
	BIT	#M.1600,U.CW2(R5)	;CORRECT ASSUMPTION?		      ;CS002
	BNE	10$			;IF NE, YES.			;CS002
	BIC	#TC.1600,R0		;SETUP FOR			;CS002
	BIS	#TC.800,R0		; 800BPI.			;CS002
	BIT	#M.EVN,U.CW2(R5)	;EVEN PARITY MODE?		;CS002
	BEQ	10$			;IF EQ, NO.			;CS002
	BIS	#TC.EVN,R0		;EVEN PARITY MODE.		;CS002
10$:	BIS	#TC.FMT,R0		;NORMAL ASSY/DISASSY OF DATA	;CS002
	MOV	R0,FMTBL(R3)		;TAPE DRIVE CONTROL MODE.	;CS002
.PAGE									;**-9
;+
; **-FNCEX - FUNCTION EXECUTION						;**-1
;
;	INPUT:	R2 = CSR ADDRESS					;**-3
;		R3 = CONTROLLER NUMBER
;		R4 = SCB ADDRESS      
;		R5 = UCB ADDRESS
;-									;**-1
FNCEX:	BIT	#M.SER,U.CW2(R5)	;SELECT ERROR?
	BNE	SELERR			;IF NE YES SELECT ERROR
	BIT	#DS.PIP,MTDS(R2)	;TAPE MOVING ?			;CS002
	BNE	TIMER			;IF NE YES - WAIT		;**-1
	MOV	U.FNUM(R5),RHCS2(R2)	;SELECT FORMATTER		;TL120
	MOV	FMTBL(R3),MTTC(R2)	;SET FORMAT AND SELECT UNIT	;**-1
	MOV	#C1.TRE!FC.CLR,RHCS1(R2) ;CLEAR DRIVE/CONTROLLER ERRORS	;CS002
	MOV	RHAS(R2),RHAS(R2)	;CLEAR ALL ATTENTION BITS	;TL003
	MOV	U.CNT(R5),MTFC(R2)	;SET COMMAND COUNT		;**-1
	CMPB	#FRREV,      U.FCDE(R5)	;DATA TRANSFER?
	BLT	NDATIO			;IF LE NO
DATAIO:	NEG	MTFC(R2)		;NEGATE BYTE COUNT		;CS002
	MOV	MTFC(R2),RHWC(R2)	;MOVE BYTE COUNT TO RHWC	;**-27
	ROR	RHWC(R2)		;AND MAKE IT A WORD COUNT
	MOV	U.BUF+2(R5),RHBA(R2)	;SET LOW ORDER 16 BIT ADDRESS
NDATIO:	MOVB	S.ITM(R4),S.CTM(R4)	;START TIMER			;CS002
	BIC	#M.PEOV!M.SER!M.RWD,U.CW2(R5)  ;CLEAR STATUS BITS	;TL010
									;CS002
	MTPS	#PR7			; INHIBIT INTERRUPTS		;CS002
									;CS002
	CMPB	#FRREV,U.FCDE(R5) 	;DATA TRANSFER ?		;CS002
	BLT	20      $			;IF LT, NO.			;CS002
									;CS002
									;**-8
	.IF DF	M$$EXT

	BIT	#DV.MBC,U.CW1(R5)	;RH11?
	BEQ	20$			;IF EQ YES
	MOVB	U.BUF+1(R5),RHBAE(R2)	;SET EX MEM BITS
	MOVB	U.BUF(R5),RHCS1(R2)	;INITIATE COMMAND
	BR	30$			; . . CONT			;CS002
									;**-1
	.IFTF

20$:	MOV	U.BUF(R5),RHCS1(R2)	;INITIATE COMMAND
									;**-1
	.ENDC
									;CS002
30$:	MTPS	#0		; ALLOW INTERRUPTS			;CS002
	RETURN								;CS002
.PAGE									;**-22
;+									;**-1
;
; **-SELERR - SELECT ERROR HAS OCCU      RED THIS ROUTINE WILL ISSUE
;		A SLECT ERROR MESSAGE TO THE CONSOLE TERMINAL EVERY
;		15 SECODS. THE UNIT IS CHECKED ONCE A SECOND
;		UNTIL IT COMESREADY OR AN ABORT IS DONE.
;
;-
	.ENABL	LSB							;CS002
SELERR:

	MOV	#IE.DNR&377,R0		;INSURE DNR IS SET
	BITB	#US.SUP,U.STS(R5)	;USER MODE OR IQ.X?
	BNE	10$			;IF NE YES EXIT
	TST	U.ACP(R5)		; ACP WANTS RETURN?
	BNE	10$			; IF NE YES
	BIS	#M.SER,U.CW2(R5)	; SET SELECT ERROR
	DECB	S.STS(R4)		;TIME FOR A MSG?
	BNE	TIMER			;IF NE NO
	MOV	#T.NDSE,      R0		;ERROR MESSAGE CODE
	MOVB	#15.,S.STS(R4)		;SET UP TIMEOUT
	CALL	$DVMSG			;SEND THE MESSAGE
TIMER:	MOVB	#1,S.CTM(R4)		;SET UP A TIMEOUT
	RETURN				;THAT IS ALL FOR NOW
10$:	JMP	EXTNST			; EXIT
									;CS002
	.DSABL	LSB
.PAGE
;+
; **-MMOUT - DEIVE TIMEOUT ENTRY POINT
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED.
; IF THE OPERATION WAS DIAGNOSTIC, THE QIO REQUEST IS TERMINATED.
; TIMEOUTS ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE
; RESULT OF HARDWARE CONSI      DERATIONS.
;
;	INPUTS: R0 = I/O COMPLETION CODE IE.DNR
;		R2 = CSR ADDRESS
;		R3 = CONTROLLER INDEX
;		R4 = SCB ADDRESS
;		R5 = UCB ADDRESS
;-
MMOUT:	BITB	#US.ABO,U.STS(R5) 	;;;ABORTING?			;**-1
	BNE	40$			;;;IF NE YES
	BIT	#M.RWD,U.CW2(R5) 	;;;REWIND IN PROGRESS
	BEQ	10$			;;;IF EQ NO
	BIT	#DS.MOL,MTDS(R2) 	;;;UNIT ONLINE?
	BEQ	SELERR			;;;IF EQ NO SELECT ERROR
	BIT	#DS.PIP,MTDS(R2)	;;;POSITIONING IN PROGRESS?
	BNE	TIMER			;;;IF NE YES - RESET TIMER
	BIT	#DS.BOT,MTDS(R2)	;;;TAPE AT BOT
	BE      Q	TIMER			;;;IF EQ NO RESET TIMER
	BIS	#M.BOT,U.CW2(R5)	;;;SET BOT STATUS
	BIC	#M.RWD,U.CW2(R5)	;;;CLEAR REWINDING BIT
	BIS	#M.SER,U.CW2(R5)	;;;FORCE A RETRY
	BR	30$			;;;ISSUE COMMAND
10$:	MOV	SPTBL(R3),R1		;;;SPACING?
	BEQ	20$			;;;IF EQ NO
	CMP	R1,MTFC(R2)		;;;BLANK TAPE
	BEQ	20$			;;;IF EQ YES EXIT
	MOV	MTFC(R2),SPTBL(R3)	;;;SAVE FOR LATER USE
	MOVB	S.ITM(R4),S.CTM(R4)	;;;RESET TIMEOUT COUNT
	RETURN
									;CS002
20$:	CALL	$DTOER			;;;LOG DEVICE ERROR

	.IF DF D$$IAG
	BCS	40$			;;;IF C      -SETABORT DIAGNOSTIC FUNC;**-1
	.ENDC								;**-1

30$:	MTPS	#0			;;;ALLOW INTERRUPTS
	BIT	#M.SER,U.CW2(R5)	;SELECT ERROR?
	BEQ	50$			;IF EQ NO - ERROR
	CALL	SELECT			;SEE IF RDY YET
	BCS	SELERR			;IF C-SET NO SELECT ERROR
	CALLR	FNCEX			;ALL'S WELL GO EXECUTE FUNCTION
									;CS002
40$:					;;;REFERENCE LABEL
	.IF DF D$$IAG							;**-1
	CALL	MMDINT			;;;PASS DIAGNOSTIC DEVICE REGIST;**-1
	.ENDC								;**-1

	BIS	#C2.CLR,RHCS2(R2)	;;;CLEAR CONTROLLER AND DRIVES	;TL048
	BITB	#US.ABO,U.STS      (R5)	;;;ABORTING?			;TL048
	BEQ	45$			;;;BRANCH IF NOT		;TL048
	JMP	EXTNST			;;;EXIT NO STATUS		;TL048
									;TL048
45$:					;;;REF LABEL			;TL048
	.IF DF D$$IAG							;**-3

	MOV	S.PKT(R4),R1		;;;GET I/O PACKET ADDRESS
	BITB	#IQ.UMD,I.FCN(R1)	;;;USER MODE FUNCTION?
	BEQ	FATAL			;;;IF EQ NO

	.ENDC

50$:	BIS	#C2.CLR,RHCS2(R2)	;INSURE CONTROLLER CLEARED AND
					;ABLE TO ACCEPT A NEW COMMAND
	JMP	EXTNST			;EXIT NO STATUS
									;CS002
;+									;**-1
; **-MMCAN - CANCEL I/O ENTRY POIN      T
; CANCEL I/O OPERATION
;
;	INPUTS:	R0 = I/O PACKET ADDRESS
;		R1 = TCB ADDRESS
;		R3 = CONTROLLER INDEX
;		R4 = SCB ADDRESS
;		R5 = UCB ADDRESS
;-

MMCAN:	CMP	I.TCB(R0),R1	;CANCEL FOR THIS TASK?			;TL030
	BNE	10$		;BRANCH IF NOT				;TL030
	BISB	#US.ABO,U.STS(R5) ;FLAG THE ABORT CONDITION		;TL030
10$:	RETURN								;TL030
									;CS002
									;CS002
;+									;**-2
; **-MMPWF - POWER FAIL RECOVERY ENTRY
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO       IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION.
;-

MMPWF:				;POWERFAIL ENTRY POINT
									;**-1
	.IF DF	P$$RFL

	BISB	#US.PWF,U.STS(R5)  ;SET POWER FAIL INDICATOR

	.ENDC

	RETURN			;					;**-1
.PAGE									;**-2
;+
; **-$MMINT-RH11/RH70 TM02/TM03 MAGNETIC TAPE CONTROLLER INTERRUPTS
;-

	INTSE$	MM,PR5,T$$J16	;;;GENERATE INTERRUPT SAVE CODE
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER       INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOVB	S.ITM(R4),S.CTM(R4) ;RESET TIMOUT COUNT
	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	BITB	#US.ABO,U.STS(R5) ;TOLD TO ABORT ?			;CS002
	BEQ	5$		;IF EQ, NO.				;CS002
	MOV	#IE.ABO&377,R0	; ABORTING 				;CS002
	BR	ENDRQS		;   REQUEST.				;CS002
5$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESS.			;CS002
	MOVB	U.FCDE(R5),R1	;RETRIEVE FUNCTION INDEX		;**-1
	BIT	#M.EOF!M.BOT,U.CW2(R5) ;TAPE MARK SEEN LAST TIME?
	BEQ	10$		;IF EQ NO
	BIS	#M.PEOV,U.CW2(R5)  ;YES SET FOR E      OV CHECK		;TL010
10$:	BIC	#NEWBTS,U.CW2(R5) ;CLEAR STATUS BITS TO DETERMINE	;**-1
	BIT	#C1.TRE,RHCS1(R2) ;TRANSFER TYPE ERROR?			;**-1
	BNE	20$		;IF NE YES
	BIT	#DS.ERR,MTDS(R2) ;DRIVE ERROR?
	BNE	30$		;IF NE YES
	CALLR	@DONTBL(R1)	;NO ERRORS FUNCTION COMPLETE
									;CS002
;									;CS002
;  RH CONTROLLER TRANSFER ERROR - 					;CS002
;									;CS002
20$:	BIT	#C1.CPE,RHCS1(R2) ;PAR ERR, MASSBUS CONTROL BUS ?	;CS002
	BNE	FATAL		;IF NE, YES - UNRECOVERABLE.		;CS002
	MOV	RHCS2(R2),R0	;R0 - POS      SIBLE				;CS002
	BIC	#^C<CS2ERR>,R0	; RH ERROR INDICATION.			;CS002
	BEQ	30$		;IF EQ, NO.				;CS002
	BIT	#C2.DLT!C2.UPE!C2.DPE,R0 ;REPOSITIONING ERROR ?		;CS002
	BNE	37$		;IF NE, YES.				;CS002
	BIT	#C2.PGE!C2.NED!C2.MXF,R0 ;RETRY ERROR ?			;CS002
	BNE	27$		;IF NE, YES.				;CS002
	BIT	#C2.WCE,R0 	;WRITE CHECK ERROR ?			;CS002
	BNE	FATAL		;IF NE, YES.  (ELSE, C2.NEM)		;CS002
25$:	MOV	U.CNT(R5),R0	;R0 - FRAME COUNT			;CS002
	NEG	R0		;      REQUEST.				;CS002
	ADD	MTFC(R2),R0	;FRAME COUNT AS REQUEST      ED?		;CS002
	BNE	37$		;IF NE, MOVED.				;CS002
27$:									;CS002
	.IF DF	E$$DVC							;CS002
	CALL	LOGERR		;LOG ERROR				;CS002
	.ENDC	;E$$DVC							;CS002
									;CS002
	CALLR	FNCEX		;REISSUE REQUEST.			;CS002
									;CS002
;									;CS002
;   DRIVE ERROR INDICATION - DETERMINE IF RECOVERABLE			;CS002
;									;CS002
30$:	MOV	MTER(R2),R0	;R0 - ERROR REG.			;CS002
	BIT	ERRMSK(R1),R0	;RECOVERABLE ERROR ?			;CS002
	BEQ	FATAL		;IF EQ, NO.				;CS002
	BIT	#ER.FMT!ER.CPR!ER.DTE,R0  ;POSITIO      NING KNOWN ?		;CS002
	BNE	25$		;IF NE, NO.				;CS002
35$:	BIT	#DS.MOL,MTDS(R2)  ;DRIVE READY ?			;CS002
	BEQ	FATAL		;IF EQ, NO - FATAL.			;CS002
37$:	CALLR	@CHKTBL(R1)	;RECOVER PER SPECIFIC REQUEST		;CS002
									;CS002
;									;CS002
;   UNRECOVERABLE ERROR - END REQUEST					;CS002
;									;CS002
FATAL:	.IF DF	E$$DVC							;CS002
	CALL	LOGERR		;LOG ERROR				;CS002
	.ENDC	; E$$DVC						;CS002
									;CS002
	MOV	#IE.FHE&377,R0	;UNRECOVERABLE ERROR.			;CS002
ENDRQS:	JMP	EXTNST		;END REQU      EST.				;CS002
.PAGE									;**-36
;+									;**-1
; **-REVERR - READ REVERSE SPECIAL ERROR CHEKING
;
;	TEST FOR READ REVERSE INTO BOT.					;CS002
;	 IF BOT  THEN  IS.SUC AND ZERO BYTE COUNT			;CS002
;-									;CS002
	.ENABL	LSB							;CS002
REVERR:	BIT	#ER.OPI,R0	;OPERATION INCOMPLETE ?			;CS002
	BEQ	REDERR		;IF EQ NO THEREFORE NOT A BOT CONDITION	;**-8
	BIT	#DS.BOT,MTDS(R2) ;TAPE AT BOT?
	BEQ	FATAL		;IF EQ NOT AT BOT IN THAT CASE THESE ERRORS
				;ARE FATAL!
	BIS	#M.BOT,U.CW2(R5) ;SET BOT       STATUS
	CLR	MTFC(R2)	;CLEAR OUT FRAME COUNT FOR RETURN
	BR	50$		;RETURN SUCCESS
;+									;**-1
; **-REDERR - READ ERROR CHECKING
;-									;CS002
REDERR:	BIT	#ER.INC!ER.PEF!ER.NSG!ER.DTE!ER.FMT!ER.CPR,R0  ;RETRY ?	;CS002
	BNE	20$		;IF NE YES				;**-5
	BIT	#ER.FCE,R0	;FRAME COUNT ERROR
	BNE	30$		;IF NE YES
10$:	BIT	#DS.PES,MTDS(R2) ;PE TAPE?
	BNE	40$		;IF NE, PE - CORRECTED DATA 		;CS002
20$:	CALLR	COMRTY		;JMP TO RETRY ENTRY			;**-1
									;CS002
30$:	BIT	#DS.TM,MTDS(R2)	;TAPE MARK?
	BE      Q	50$		;IF EQ NO
	MOV	#IE.EOF&377,R0	;SET EOF STATUS
	BIS	#M.EOF,U.CW2(R5) ;SET IN CHARACTERISTICS WORD
	BR	60$		;GO TO COMPLETION ROUTINE		;**-1
									;CS002
40$:	.IF DF	E$$DVC							;CS002
	CALL	LOGERR		;LOG ERROR				;CS002
	.ENDC								;CS002
									;CS002
50$:	MOV	#IS.SUC&377,R0	;SHORT RECORD IS SUCESS
60$:	CALLR	@DONTBL(R1)	;EXIT
									;CS002
	.DSABL	LSB							;CS002
									;CS002
;+									;CS002
; **-RWDERR/RWDRTY - REWIND.OR.UNLOAD/OFFLINE ERROR RETRY		;CS002
;-									;      CS002
RWDERR:									;CS002
RWDRTY:	BIC	#M.1600,U.CW2(R5)	;SETUP FOR 800BPI.		;CS002
	BIT	#TC.1600,FMTBL(R3)	;LAST REQUEST AT 1600?		;**-16
	BNE	10$			;IF NE YES TRY 800
	BIS	#M.1600,U.CW2(R5)	;SET TO TRY AT 1600
10$:	CMP	#RETRY,RTTBL(R3)	;RETRIED AT LEAST ONCE ?	;CS002
	BNE	FATAL			;IF NE, YES.			;CS002
	DECB	RTTBL(R3)		;RTRY				;CS002
	CALLR	PRCOM			; ONLY ONCE.			;CS002
.PAGE									;**-1
;+
; **-SPRERR - SPACE REVERSE - ERROR HANDLING				;**-1
;-									;**-1
	.ENABL	LSB
SPRERR:	BIT	#D      S.BOT,MTDS(R2) ;BOT ENCOUNTERED?
	BEQ	SPFEXT		;IF EQ NO NOT BOT
	BIS	#M.BOT,U.CW2(R5) ;SET STATUS BIT
	MOV	#IS.SUC&377,R0	;SET SUCCESS
	BR	30$		;DONE
;+
; **-SPERR - SPACE FORWARD - ERROR HANDLING 				;CS002
;	      SPACE FUNCTIONS - COMPLETION ROUTINES			;CS002
;-									;**-1
SPFEXT:	BIT	#ER.OPI,R0		;OPERATION INCOMPLETE?		;CS002
	BNE	FATAL			;IF NE YES FATAL ERROR		;**-1
	MOV	#IS.SUC&377,R0		;SET SUCCESS			;TL009
10$:	BIT	#DS.TM,MTDS(R2)		;TAPEMARK SEEN?			;**-4
	BEQ	30$			;IF EQ NO
	MOV	#      IE.EOF&377,R0		;SET TAPEMARK STATUS
	CALL	CHKEOV			;CHECK FOR END OF VOLUME
	BCC	15$			;IF CC, NOT EOV.		;CS002
	MOV	#FRTRY,U.FCDE(R5)	;SET FOR BACKSPACE		;**-1
	JMP	BACK			;BACKSPACE ONE RECORD.		;CS002
									;CS002
15$:	CALLR	@RTYTBL(R1)	;ANY MORE FILES?			;CS002
									;TL063
;									;TL063
; THIS WORKS BECAUSE WE ONLY GET TO SPRRTY: FOR SUCCESSFUL COMPLETION	;TL063
; OF THE BACKUP  (ALSO MTFC=0), AND IO.SPB CANNOT DETECT EOV AFTER	;TL063
; SPACING OVER ANY BLOCKS. (IO.SPF DOESN'T USE U      .CNT)			;TL063
;									;TL063
SPCONT:	CLR	U.CNT(R5)		;CLEAR REQUESTED COUNT FOR CALC	;TL063
	MOV	#IE.EOV&377,R0		;SET EOV STATUS			;**-4
	BIS	#M.AEOV,U.CW2(R5)	;SET AT EOV IN CHARACTERISTICS	;TL010
30$:	MOV	S.PKT(R4),R1		;GET I/O PACKET ADDRESS		;**-1
	CMPB	#IO.SPF,I.FCN(R1)	;SPACE FILES?
	BEQ	SPFDON			;YES DO FILES COMPLETION
; SPACE BLOCKS - FWD/REV						;CS002
SPRRTY:
	TST	MTFC(R2)		;WERE ENOUGH BLOCKS PASSED?	;TL009
	BEQ	35$			;YES, ALL DONE			;TL009
	BIT	#DS.TM!DS.BOT,MTDS(R2)	;TAPEMARK S      EEN, OR BOT?		;TL009
	BNE	35$			;YES, ALL DONE			;TL009
	MOV	U.CNT(R5),R0		;RETRIEVE REQUESTED COUNT	;TL009
	SUB	MTFC(R2),R0		;CALCULATE ACTUAL NO. SPACED	;TL009
	ADD	R0,SPTOTL(R3)		;ADD IT IN TO THE TOTAL SPACED	;TL009
	MOV	MTFC(R2),U.CNT(R5)	;REMAINING COUNT IS NEW COUNT	;TL009
	MOV	MTFC(R2),SPTBL(R3)	;SAVE IT FOR TIMEOUT		;TL009
	BR	70$			;TRY TO DO SOME MORE		;TL009
									;TL009
35$:	MOV	U.CNT(R5),R1		;RETRIEVE REQUESTED COUNT	;TL009
	SUB	MTFC(R2),R1		;CALCULATE ACTUAL NO. SPACED	;**-1
	AD      D	SPTOTL(R3),R1		;ADDITIONAL SPACE OPERATIONS	;TL009
					;  DONE IF AFTER EOT		;TL009
	BR	60$			;EXIT
									;CS002
									;CS002
;+									;**-1
; **-SPFRTY - SPACE FILES FWD/REV					;CS002
;-									;**-4
SPFRTY:	INC	U.SPC(R5)		;DONE?				;TL120
	BNE	70$			;IF NE NO - CONTINUE		;**-1
	MOV	#IS.SUC&377,R0		;YES - SUCCESS
	BR	50$			;FIX POSITION AND EXIT
									;CS002
									;CS002
SPFDON:	BIT	#DS.BOT!DS.TM,MTDS(R2)	;BOT OR TAPEMARK?		;TL009
	BEQ	70$			;NO - CONTINUE			;TL009
	BIT	#      DS.BOT,MTDS(R2)	;IF WE STOPPED FOR BOT OR EOV	;TL063
	BNE	50$			;DON'T INCREMENT THE FILE	;TL063
	BIT	#M.AEOV,U.CW2(R5)	;COUNT BECAUSE WE DIDN'T	;TL063
	BNE	50$			;PASS A FILE			;TL063
	INC	U.SPC(R5)		;INCREMENT TAPE MARK COUNT	;TL120
50$:	MOV	S.PKT(R4),R1		;GET I/O PACKET ADDRESS		;**-3
	MOV	I.PRM+4(R1),R1		;RETREIVE COUNT REQUESTED
	SUB	U.SPC(R5),R1		;SUBTRACT NUMBER REMAINING	;TL120
60$:	NEG	R1			;SET FOR POSITIVE RETURN VALUE	;**-1
	JMP	EXIT			;EXIT
									;CS002
70$:	CALLR	FNCEX
									      ;CS002
	.DSABL	LSB							;CS002
.PAGE
;+
; **-COMRTY - COMMON RETRY ROUTINE
;
;	THIS ROUTINE CHECKS FOR RETRIES BEING SUPPRESSED
;	IF SO EXIT RETURN STATUS IE.VER. OTHERWISE,
;	SAVE THE REQUEST AND CALL THE FUNCTION SPECIFIC RETRY
;	ROUTINE.
;
;-
	.ENABL	LSB
COMRTY:

	.IF DF	E$$DVC
	CALL	LOGERR			;LOG THE ERROR			;**-1
	.ENDC								;**-1

	BITB	#US.SUP,U.STS(R5)	;RETRIES ENABLED?
	BNE	10$			;IF NE NO EXIT
	DECB	RTTBL(R3)		;RETRIES EXHAUSTED?
	BEQ	10$			;IF EQ YES EXIT
	MOV	U.FCDE(R5)      ,FCCDE(R3)	;SAVE FUNCTION INDEX
	MOV	U.CNT(R5),CMDCNT(R3)	;SAVE COMMAND COUNT
	MOV	U.BUF(R5),BUFADR(R3)	;SAVE BUFFER ADDRESS
	MOV	#FRTRY,U.FCDE(R5)	;SET RETRY COMMAND
	CALLR	@RTYTBL(R1)		;BR TO FUNCTION SPECIFIC RETRY

10$:	BIT	#ER.PEF!ER.NSG!ER.OPI,R0  ;TAPE FORMAT ERROR		;TL005
	BEQ	12$			;NO				;TL005
	MOV	#IE.BBE&377,R0		;RETURN ERROR IN R0		;TL005
RTYCON:	CALLR	@DONTBL(R1)		;EXIT				;TL005
									;TL005
12$:	MOV	#IE.VER&377,R0		;RETURN ERROR IN R0		;TL005
	BR	RTYCON			;EXIT				;TL005
.PA      GE									;**-2
;+									;CS002
; -- WRITE/WTMK RETRY --						;CS002
;-									;CS002
WRTRTY:	MOV	#FRTRY,R1		;R1 - RETRY INDEX.		;CS002
	MOV	#RTNWRT,DONTBL(R1)	;I/O CONT AFTER REPOSITION.	;CS002
	MOV	#FC.SPR,U.BUF(R5) 	;SET UP I/O REQUEST CODE.	;CS002
	BR	15$			;REPOSITION TAPE.		;CS002
									;CS002
RTNWRT:	BIT	#M.IXG,U.CW2(R5)	;NO EXTENDED IRG ?		;CS002
	BNE	RTYCMD			;IF NE, YES.			;CS002
	MOV	#FRTRY,R1		;R1 - RETRY INDEX.		;CS002
	MOV	#BACK,DONTBL(R1)	;I/O CONT AFTER ERASE.		;CS002
	MO      V	#FC.ERS,U.BUF(R5)	;SET UP I/O REQUEST CODE.	;CS002
	BR	15$			;ERASE TAPE.			;CS002
									;CS002
;+									;CS002
; -- READ FWD/REV RETRY --						;CS002
;-									;CS002
REDRTY:									;CS002
REVRTY:	CMP	MTFC(R2),#NOISE 	;800BPI - MIN RECORD?		;CS002
	BLO	RTYCMD			;IF LO, NO - IGNORE IT.		;CS002
									;CS002
									;CS002
BACK:	MOV	#FRTRY,R1		;R1 - RETRY INDEX.		;CS002
	MOV	IOFCN(R3),R0		;R0 > 				;CS002
	ADD	#4,R0			;  REPOSITION RETURN.		;CS002
	MOV	(R0)+,DONTBL(R1)	;I/O CONT AFT      ER REPOSITION.	;CS002
	MOV	(R0),U.BUF(R5)		;SET UP I/O REQUEST CODE.	;CS002
15$:	MOV	#-1,U.CNT(R5)		;REPOSITON BY ONE BLOCK.	;CS002
	BR	20$							;CS002
									;CS002
;+									;CS002
; REISSUE ORIGINAL I/O REQUEST						;CS002
;-									;CS002
RTYCMD:	MOV	FCCDE(R3),U.FCDE(R5)	;RESTORE FUNCTION INDEX		;**-38
	MOV	CMDCNT(R3),U.CNT(R5)	;RESTORE COMMAND COUNT
	MOV	BUFADR(R3),U.BUF(R5)	;RESTORE BUFFER ADDRESS
20$:	CALLR	FNCEX			;EXECUTE FUNCTION
									;CS002
	.DSABL 	LSB							;CS002
.PAGE
      ;+
; **-REDDON - READ FORWARD COMPLETION ROUTINE
;-									;**-3
REVDON:	BIC	#M.EOF!M.AEOV,U.CW2(R5)	;CLEAR OUT INTERNAL STATUS FOR R;TL010
REDDON:	MOV	MTFC(R2),R1	;SET FRAME COUNT FOR REQUESTER		;**-2
;  TM03 FORMATTER AUTO SELECTS DENSITY CONTROL ON READS.		;TL049
;    IF TM03, UPDATE DRIVER INTERNAL DENSITY STATUS FOR THAT TAPE UNIT.	;TL049
TM03DN:	BIT	#40,MTDT(R2)	;TM03?					;TL049
	BEQ	5$		;IF EQ, NO.				;TL049
	BIT	#M.BOT!M.RWD,U.CW2(R5) ;TAPE AT BOT OR REWINDING?	;TL049
	BNE	5$		;IF NE, YE      S.				;TL049
	BIC	#M.1600,U.CW2(R5) ;ASSUME 800BPI.			;TL049
	BIT	#DS.PES,MTDS(R2) ;800 BPI ?				;TL049
	BEQ	5$		;IF EQ, YES.				;TL049
	BIS	#M.1600,U.CW2(R5) ;1600 BPI.				;TL049
5$:	TSTB	R0		;ALREADY RETURNING ERROR?		;TL049
	BMI	EXIT		;YES MUST BE MORE IMPORTANT		;**-1
	BIT	#DS.BOT,MTDS(R2) ;READ REV INTO BOT ?			;CS002
	BNE	EXIT		;IF NE, YES.				;CS002
	CMP	MTFC(R2),#NOISE	;RECORD AT LEAST MIN SIZE ?		;TL100
	BHIS	10$		;IF HIS, YES.				;TL100
	BIT	#M.1600,U.CW2(R5) ;1600BPI TAPE?			;CS002
	B      NE	EXIT		;IF NE, YES - LT MIN ALLOWED FOR 1600BPI;CS002
	JMP	COMRTY		;LT MIN NOT ALLOWED FOR 800BPI.		;TL100
10$:	CMP	R1,U.CNT(R5)	;TAPE DATA - MORE THAN REQUESTED ?	;TL100
	BLOS	EXIT		;NO EXIT SUCCESS			;**-1
	MOV	#IE.DAO&377,R0	;YES INFORM THE USER
	BR	EXIT		;EXIT
;+
; **-EOFDON - WRITE TAPE MARK COMPLETION ROUTINE
; **-WRTDON - WRITE LOGICAL BLOCK COMPLETION ROUTINE
;-									;CS002
EOFDON:	BIS	#M.EOF,U.CW2(R5) ;SET TM STATUS				;**-3
WRTDON:	MOV	U.CNT(R5),R1	;RETREIVE REQUESTED COUNT
	ADD	M      TFC(R2),R1	;CALCULATE ACTUAL LENGTH
	BIT	#DS.EOT,MTDS(R2) ;AT EOT?
	BEQ	EXIT		;IF EQ NO
	MOV	#IE.EOT&377,R0	;SET EOT STATUS
	BIS	#M.EOT,U.CW2(R5) ;SET EOT IN CHARACTERISTICS WORD
	BR	EXIT		;EXIT
									;CS002
RWDDON:	BIT	#DS.PIP,MTDS(R2) ;REWIND IN PROGRESS?			;CS002
	BEQ	10$		;IF EQ, DONE.				;CS002
	BIS	#M.RWD,U.CW2(R5) ;REWIND IN PROGRESS.			;CS002
10$:	BIC	#M.AEOV,U.CW2(R5)  ;CLEAR OUT END OF VOLUME STATUS	;TL010
									;CS002
	.IF DF	P$$RFL							;CS002
	BICB	#US.PWF,U.STS(R5)	;CLEAR P      WRFLD STATUS		;CS002
	.ENDC								;CS002
									;CS002
									;**-1
EXTNST:	CLR	R1			;NO STATUS TO RETURN
EXIT:
	.IF DF	D$$IAG							;**-1
	CALL	MMDINT							;**-1
	.ENDC								;**-1

	.IF DF	E$$DVC
	MOVB	RTTBL(R3),R2		;SET RETRY COUNT		;**-1
	BIS	#RETRY*256.,R2		;SET ORIGINAL COUNT
	.ENDC								;**-1

	BIC	#M.PEOV!7,U.CW2(R5)  ;CLEAR PAST END OF VOLUME STATUS	;CS002
	BICB	#US.ABO,U.STS(R5)	;CLEAR ABORT INDICATION		;CS002
	CALL	$IODON		;FINISH I/O OPERATION			;**-1
	JMP	MMINI		;GO A      GAIN
									;CS002
									;CS002
									;**-1
;+
; **-CHKEOV - CHECK FOR LOGICAL END OF VOLUME
; THIS SUBROUTINE CHECKS FOR THE LOGICAL END-OF-VOLUME CONDITION
;
; RETURNS WITH CC IF NOT EOV.
; RETURNS WITH CS IF EOV.
;-

CHKEOV:	CLC			;CLEAR CARRY FOR RETURN
	BIT	#REV,RHCS1(R2)	; READ REVERSE OPERATION?
	BNE	20$		; IF NE YES CAN'T BE EOV
				; AND DON'T SET EOF
	MOV	MTFC(R2),-(SP)	; RETRIEVE FRAME COUNT
	SUB	U.CNT(R5),(SP)	;GET NUMBER ACTUALLY SPACED
	CMP	(SP)+,#1	;EXACTLY ONE? (STA      RTED WITH 1)
	CLC			;ASSUME NOT EOV
	BNE	10$		;IF NE NO, NOT EOV
	BITB	#US.LAB,U.STS(R5) ;MOUNTED ANSII MAGTAPE?
	BNE	10$		;IF NE YES, DO NOT REPORT EOV
	BIT	#M.PEOV,U.CW2(R5)  ;TAPE MARK OR BOT SEEN LAST TIME?	;TL010
	BEQ	10$		;IF EQ NO - EXIT WITH CC		;**-1
	SEC			;EOV DETECTED
10$:	BIS	#M.EOF,U.CW2(R5) ;SET EOF STATUS
20$:	RETURN			;


.PAGE
;+									;**-1
;
; **-SELECT - TAPE UNIT SELECT ROUTINE
; THIS ROUTINE ATTEMPTS TO SELECT A DRIVE.  IT SETS UP
; THE BOT AND HWL BITS IN THE CHARA      CTERISTICS WORD.
;
; ON RETURN:	CC==>GOOD SELECT
;		CS==>BAD SELECT
;-									;CS002
									;**-1
SELECT:	MOV	S.CSR(R4),R2	;PICK UP CSR ADDRESS
	MOV	U.FNUM(R5),RHCS2(R2)	;SELECT FORMATTER		;TL120
									;TL120
	MOV	MTTC(R2),-(SP)	;SAVE UNIT SELECT REGISTER		;**-1
	MOVB	U.UNIT(R5),(SP)	;SELECT DESIRED UNIT
	MOV	(SP)+,MTTC(R2)	; ...
	BIC	#M.BOT!M.EOT!M.HWL!M.SER,U.CW2(R5) ;STATUS TO BE UPDATED;CS002
	SEC			;ASSUME BAD SELECT			;**-1
	BIT	#DS.MOL,MTDS(R2) ;IS THE DRIVE READY?
	BNE	10$		;IF       NE YES
	BIS	#M.SER,U.CW2(R5) ;SET SELECT ERROR BIT
	BR	40$		; BAD SELECT				;CS002
									;CS002
10$:	BIT	#DS.PIP,MTDS(R2) ;POSITIONING IN PROGRESS?		;**-1
	BNE	20$		;IF NE NO
	BIT	#DS.BOT,MTDS(R2) ;IS DRIVE AT BOT?
	BEQ	20$		;IF EQ NO
	BIS	#M.BOT,U.CW2(R5) ;SET THE BIT
	BIC	#M.RWD,U.CW2(R5) ;IF AT BOT RWD DONE
20$:	BIT	#DS.WRL,MTDS(R2) ;IS DRIVE WRITE-LOCKED?
	BEQ	30$		;IF EQ NO
	BIS	#M.HWL,U.CW2(R5) ;SET THE BIT
30$:	BIT	#DS.EOT,MTDS(R2) ;TAPE AT EOT?				;CS002
	BEQ	35$		;IF EQ, NO.				;CS      002
	BIS	#M.EOT,U.CW2(R5) ;INDICATE EOT STATUS.			;CS002
35$:	CLC			;TAPE DRIVE AVAILABLE.			;CS002
40$:	RETURN								;**-1
									;CS002
;+									;**-45
; **-LOGERR  - SUBROUTINE TO LOG DEVICE ERRORS				;**-1
;-									;**-1
LOGERR:
	.IF DF E$$DVC							;**-1

	.IF DF	D$$IAG
	TST	RTTBL(R3)		;USER MODE FUNCTION?		;**-1
	BMI	10$		;IF MI, YES - THEY HANDLE ERRORS.	;CS002
	.ENDC								;**-2

	CALL	$DVERR			;LOG THE ERROR

10$:	RETURN

	.ENDC
.PAGE
	.IF DF	D$$IAG
;
; **-MMDINT-TU1      6 DIAGNOSTIC INTERRUPT AND TIMEOUT HANDLER
;
; IF ENTRY WAS FROM A DIAGNOSTIC CONTROL FUNCTION THEN MOVE I/O
; PACKET WORDS 17-20 TO WORDS 20-21 FOR $CRPAS ROUTINE.
; FOR ANY DIAGNOSTIC FUNCTION PASS THE UNIBUS DEVICE REGISTERS VIA
; THE $CRPAS ROUTINE.
;
; INPUTS
;	R2= CSR ADDRESS
;	R4= SCB ADDRESS
;
; OUTPUTS
;	R1= IO PACKET ADDRESS
;-

MMDINT:	MOV	R1,-(SP)	;SAVE R1
	MOV	S.PKT(R4),R1	;GET IO PACKET ADDRESS
	BITB	#IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL?
	BEQ	3$		;IF EQ NO
	MOV	R1,-(S      P)	;SAVE IO PACKET ADDRESS
	CMPB	#IO.EOF/256.,I.FCN+1(R1) ;WRITE EOF CONTROL FUNCTION?
	BEQ	1$			;IF EQ YES
	CMPB	#IO.RWD/256.,I.FCN+1(R1) ; CNTRL OTHER THAN IO.EOF?
	BEQ	1$			;IF EQ YES
	CALL	$CRPAS		;PASS DEVICE REGISTERS TO DIAGNOSTIC
	MOV	(SP)+,R1	;RESTORE IO PACKET ADDRESS
	BR	3$		;.. CONT				;CS002
1$:	MOV	I.PRM+14(R1),I.PRM+16(R1) ;MOVE WD20 TO WD21		;**-2
	MOV	I.PRM+12(R1),I.PRM+14(R1) ;MOVE WD17 TO WD20
2$:	CALL	$CRPAS		;PASS DEVICE REGISTERS TO DIAGNOSTIC
	MOV	(SP)+,R1	;RESTORE IO PACKE   ª   T ADDRESS
	MOV	I.PRM+14(R1),I.PRM+12(R1) ;MOVE WD20 BACK TO WD17
	MOV	I.PRM+16(R1),I.PRM+14(R1) ;MOVE WD21 BACK TO WD20
3$:	MOV	(SP)+,R1
	RETURN

	.ENDC

	.END
 ª          ãàykQ	› c,        	.TITLE	DRSST
	.IDENT	/04.01/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 04.01
;
; D. N. CUTLER 30-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	14-SEP-81
;		MSH189 -- ALLOW SST VECTORS TO BE SPECIFIED FROM
;			  READ-ONLY REGIONS
;
; MACRO LIBRARY CALLS
;

	.M      CALL	HDRDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS

;+
; **-$DRSDV-SPECIFY DEBUGGING AID SST VECTOR
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO RECORD THE ADDRESS AND LENGTH
; OF A VECTOR OF SST SERVICE ROUTINE ENTRY POINTS FOR USE BY AN INTRA-
; TASK DEGUGGING AID (E.G. ODT)
;
; DPB FORMAT:
;
;	WD. 00 -- DIC (103.),DPB SIZE(3.).
;	WD. 01 -- ADDRESS OF THE SST VECTOR.
;	WD. 02 -- NUMBER OF ENTRIES IN THE SST VECTOR.
;
;	SST VECTOR FORMAT:
;
;		WD. 00 -- TRAPS TO 4 (ODD ADDRESS, NONEX MEM, ET      C.).
;		WD. 01 -- SEGMENT FAULT.
;		WD. 02 -- TRACE TRAP (T-BIT) OR EXECUTION OF BPT INSTRUCTION.
;		WD. 03 -- EXECUTION OF AN IOT INSTRUCTION.
;		WD. 04 -- EXECUTION OF AN ILLEGAL OR RESERVED INSTRUCTION.
;		WD. 05 -- EXECUTION OF A NON RSX EMT INSTRUCTION.
;		WD. 06 -- EXECUTION OF A TRAP INSTRUCTION.
;		WD. 07 -- PDP 11/40 FLOATING POINT EXCEPTION FAULT.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB.
;	R4=ADDRESS OF THE HEA      DER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF PART OF VECTOR
;			IS OUTSIDE OF ISSUING TASK'S ADDRESS SPACE,
;			VECTOR ADDRESS OF ZERO IS SPECIFIED, OR  THE
;			VECTOR SIZE IS GREATER THAN 31. WORDS.
;-

	.ENABL	LSB
$DRSDV::ADD	#H.ODVL,R4	;POINT TO O      DT VECTOR LENGTH IN HEADER
	BR	10$		;FINISH UP IN COMMON CODE

;+
; **-$DRSTV-SPECIFY TASK SST VECTOR
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO RECORD THE ADDRESS AND LENGTH OF
; A VECTOR OF SST SERVICE ROUTINE ENTRY POINT FOR USE BY THE ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(105.),DPB SIZE(3.).
;	WD. 01 -- ADDRESS OF THE SST VECTOR.
;	WD. 02 -- NUMBER OF ENTRIES IN THE SST VECTOR.
;
;	SST VECTOR FORMAT:
;
;		WD. 00 -- TRAPS TO 4 (ODD ADDRESS, NONEX MEM, ETC.).
;		WD. 01 -- SEGME      NT FAULT.
;		WD. 02 -- TRACE TRAP (T-BIT) OR EXECUTION OF A BPT INSTRUCTION.
;		WD. 03 -- EXECUTION OF AN IOT INSTRUCTION.
;		WD. 04 -- EXECUTION OF AN ILLEGAL OR RESERVED INSTRUCTION.
;		WD. 05 -- EXECUTION OF A NON RSX EMT INSTRUCTION.
;		WD. 06 -- EXECUTION OF A TRAP INSTRUCTION.
;		WD. 07 -- PDP 11/40 FLOATING POINT EXCEPTION FAULT.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TAS      K.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IF RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF PART OF VECTOR
;			IS OUTSIDE OF ISSUING TASK'S ADDRESS SPACE,
;			VECTOR ADDRESS OF ZERO IS SPECIFIED, OR THE
;			VECTOR SIZE IS GREATER THAN 31. WORDS.
;-

$DRSTV::ADD	#H.TKVL,R4	;POINT TO TASK VECTOR LENGTH IN HEADER
10$:	MO      V	(R3)+,R0	;GET ADDRESS OF VECTOR
	BEQ	20$		;IF EQ DEASSIGN VECTOR
	MOV	(R3),R1		;GET LENGTH OF SST VECTOR
	BEQ	15$		;IF EQ DEASSIGN VECTOR
	CMP	(R3),#31.	;VECTOR TOO BIG?
	BHI	30$		;IF HI YES


	.IF DF	A$$CHK!M$$MGE

	ASL	R1		;CONVERT LENGTH TO BYTES
	CALL	$ACHCK		;ADDRESS CHECK SST VECTOR		;MSH189
	BCC	15$		;IF CC, ADDRESS CHECK OK		;MSH189
	BMI	30$		;IF MI, SERIOUS ADDRESS CHECK FAILURE	;MSH189
									;**-1
	.ENDC


15$:	MOV	(R3),(R4)	;SET SST VECTOR LENGTH
	ASL	(R4)		;CONVERT LENGTH   ¤    TO BYTES
20$:	MOV	-(R3),-(R4)	;SET SST VECTOR ADDRESS
	RETURN			;RETURN DIRECTIVE STATUS OF +1
30$:	DRSTS	D.RS98		;SET DIRECTIVE STATUS
	.DSABL	LSB

	.END
 ¤          hkQ	› c,        	.TITLE	DSSDI
	.IDENT	/00/
 
;
; COPYRIGHT (C) 1975, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 00
;
; C. A. MONIA	18-JUL-75
;
; FORTRAN INTERFACE TO READ CONTACT SENSE MODULES
;
; LOCAL DATA
;
; LINK TO DSS11 DEVICE COMMON BLOCK
;
 
	.IF DF	M$$MGE!I$$SCM
 
	.PSECT	ISCOM,RW,GBL,OVR,D
 
	.BLKB	I$$SSC&77	; COMPUTE OFFSET FROM 32W BOUNDARY      
ISCOM:				; REF LABEL
 
	.IFF
 
	.ASECT
 
.=I$$SSC
ISCOM:				; REF LABEL
 
	.ENDC
 
	.PSECT
 
;
; TABLE OF OFFSETS TO DSS11 DATA REGISTERS
;
 
DSSMP:				;
 
OFFST=2
	.REPT	I$$SDS
	.REPT	3
	.BYTE	OFFST
OFFST=OFFST+2
	.ENDR
OFFST=OFFST+2
	.ENDR
 
	.EVEN
 
;+
; **-DI; DIW -	FORTRAN CALLABLE SUBROUTINE TO READ CONTACT SENSE
;		DSS11 MODULES
;
; CALLING SEQUENCE
;
;	CALL	DI(INM,ICNT,IDATA,[ISTS],[IUN])
;
; WHERE:
;
;	INM = INTEGER SPECIFYING NUMBER OF SAMPLES
;	ICNT = IN      TEGER ARRAY. EACH ELEMENT CONTAINS AN INITIAL POINT
;		DEFINING A 16 BIT FIELD.
;
;	IDATA = INTEGER ARRAY TO RECEIVE CONTACT SENSE INFORMATION.
;
;	ISTS = 2-WORD, INTEGER ARRAY TO RECEIVE STATUS.
;
;	ISTS(1) RECEIVES STATUS PER ISA/DEC CONVENTION AS FOLLOWS:
;
;		STATUS		DEFINITION
;		------		-----------
;
;		+1		SUCCESS ALL DATA READ
;		=>3		FAILURE
;		 3		'0' SAMPLES REQUESTED
;		>300		INVALID POINT SPECIFIED
;
;	IUN = UNIT SPECIFICATION (IGNORED)
;
; THIS CALL DOES NOT PERFORM A QIO, I      NSTEAD THE EXTERNAL PAGE IS ACCESSED
; DIRECTLY.
;
; ACCESS IN A MAPPED SYSTEM IS VIA A SPECIAL COMMON AREA. THE UNMAPPED
; SYSTEM MAY ACCESS THE DSS DIRECTLY.
;-
 
DI::				;
DIW::				;
	MOV	#3,R0		; GET ARGUMENT COUNT-2
	CALL	.MLTPH		; SET FOR MULTIPOINT SAMPLE
 
;
; THE ABOVE CALL RETURNS THE FOLLOWING:
;
;	C-CLEAR:
;	R3=NUMBER OF SAMPLES
;	R4=POINTER TO CONTROL ARRAY
;	R5=POINTER TO DATA ARRAY
;
;	(SP)+2=UNDEFINED
;	(SP)  =TWO-WORD I/O STATUS BLOCK ADDRESS
;
;	C-SET:
;
;	NUMBER O      F SAMPLES=0
;
;	STACK SETUP AS DESCRIBED ABOVE
;
 
	BCS	40$		; IF C/S 0 SAMPLES REQUESTED
10$:				;
	MOV	(R4),R0		; GET POINT NUMBER
	CALL	.DIV16		; DIVIDE BY 16
	MOV	R0,R2		; SAVE BUS INDEX
	CALL	RDSS		; READ DSS11 INPUT
	BCS	50$		; IF C/S ILLEGAL POINT OR MODULE
	MOV	R0,(R5)		; RETURN RESULT TO CALLER
	TST	R1		; POINT ON MODULE BOUNDARY?
	BEQ	30$		; IF EQ YES
	MOV	R2,R0		; GET MODULE NUMBER AGAIN
	INC	R0		; INCREMENT TO NEXT IN SEQUENCE
	CALL	RDSS		; READ DSS11 INPUT
	BCS	50$		; IF C/S I      LLEGAL POINT OR MODULE
20$:				;
	ASR	R0		; ROTATE MASK1
	ROR	(R5)		; ROTATE MASK2
	DEC	R1		; DECREMENT REMAINDER
	BGT	20$		; IF GT GO AGAIN
30$:				;
	CMP	(R4)+,(R5)+	; POINT TO NEXT SET OF ARGUMENTS
	DEC	R3		; DECREMENT POINT COUNT
	BNE	10$		; IF NE GO AGAIN
	JMP	.NRMRT		; TAKE NORMAL EXIT
40$:				;
	JMP	.ILCSQ		; ILLEGAL CALLING SEQUENCE
50$:				;
	JMP	.ILMRQ		; NONEXISTENT MODULE REQUESTED
 
;
; READ DSS11 INPUT REGISTER
;
 
RDSS:				;
	CMP	#<I$$SDS*3>-1,R0 ; LEGAL POINT?
	BLO	10$	   „   	; IF LO NO
	MOVB	DSSMP(R0),R0	; GET OFFSET TO BUS ADDRESS
	MOV	ISCOM(R0),R0	; GET MODULE DATA
10$:				;
	RETURN			;
 
	.END
„          ÄðskQ	› c,        	.TITLE	DXDRV
	.IDENT	/03.04/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 03.03
;
; H. LEV 16-JAN-75
;
; PREVIOUSLY MODIFIED BY:
;
;	C. A. D'ELIA
;
; MODIFIED BY:
;
;	P. J. BEZEREDI 30-NOV-76
;
;		PB009 -- CORRECT OUT OF RANGE BRANCHES WHEN A
;			MULTI-CONTROLLER DRIVER IS GENERATED.
;
;	P. J. BEZEREDI 03-FEB-77      
;
;		PB012 -- ADDITION OF ONLINE ERROR LOGGING AND
;			INHIBIT RETRY SUPPORT.
;
;	P. J. BEZEREDI 12-DEC-77
;
;		PB045 - ALLOW ALL RX11 REGISTERS TO BE ERROR LOGGED.
;
;	P. J. BEZEREDI 13-DEC-77
;
;		PB049 -- PRESET BYTES TO TRANSFER TO 128.
;
;	P. J. BEZEREDI 05-APR-78
;
;		PB070 -- REMOVE IO.WDD FUNCTION CODE CONFLICTS.
;
;	D. S. SUMMERS -- 09-JUN-81
;		DS002 -- CORRECT ERRORLOG LOGGING
;
; RX01 - RX11  FLOPPY DISK DRIVER
;
; FUNCTIONS RECOGNIZED:
;	IO.RPB	- READ PHYSICAL BLOCK (MAY       READ ANY SECTOR ON DISK)
;	IO.WPB	- WRITE PHYSICAL BLOCK (MAY WRITE ANY SECTOR ON DISK)
;	IO.WDD	- WRITE DELETED DATA - WRITE ANY SECTOR ON DISK
;		  SETTING THE DELETED DATA MARK IN SECTOR HEADER
;	THE FOLLOWING TWO FUNCTION CODES OPERATE ON 256 WORD BLOCKS
;	OF DATA (4 SECTORS)  THE DRIVER AUTOMATICALLY INTERLEAVES
;	AND SKEWS SECTORS TO OPTIMIZE THE TRANSFER OF DATA
;	SO THAT A LONG READ/WRITE MAY BE DONE WITHOUT LOOSING
;	A REVOLUTION OF THE DISK.  THE INTERLEAVE FACTOR IS 2
;	AND THE SKEW FACT      OR IS 6.
;	IO.RLB	- READ LOGICAL BLOCKS OF 256. WORDS
;	IO.WLB	- WRITE LOGICAL BLOCKS OF 256. WORDS.
;
;	IF DELETED DATA IS READ, THE STATUS CODE RETURNED WILL
;	BE IS.RDD, OTHERWISE IT IS IS.SUC
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			; DEFINE HARDWARE REGISTERS
	PKTDF$			; DEFINE I/O PACKET OFFSETS

;
; EQUATED SYMBOLS
;

RETRY	=	8.		; ERROR RETRY COUNT
DXNUM	=	4		; NUMBER OF REGISTERS TO ERROR LOG	; PB045

;
; RX11 DEVICE REGISTER OFFSETS AND BIT DEFINITIONS
;

RXCS	=	0		; CONTROL STATU      S REGISTER
RXDB	=	2		; DATA BUFFER
UNIT	=	20		; UNIT SELECT BIT
DONE	=	40		; RX11 DONE
INTEBL	=	100		; INTERRUPT ENABLE
TR	=	200		; RX11 TRANSFER READY BIT (CPU-SILO)
INIT	=	40000		; INITIALIZE RX11

;
; FUNCTION CODES
;
GO	=	1		; GO BIT
FILL	=	0+GO		; FILL SILO
EMPTY	=	2+GO		; EMPTY SILO
WRITE	=	4+GO		; WRITE A SECTOR
READ	=	6+GO		; READ A SECTOR
WRTDD	=	14+GO		; WRITE DELETED DATA
RDERC	=	16+GO		; READ ERROR CODE			; PB045

;									; PB070
; STATUS REGISTER BIT DEFINITIONS					; PB07      0
;									; PB070
									; PB070
DD	=	100		; DELETED DATA READ			; PB070
									; PB070
;
; LOCAL DATA
;
;
; CONTROLLER TABLE AND RETRY COUNT TABLE ( INDEXED BY CONTROLLER NUMBER)
;
CNTBL:	.BLKW	R$$X11		; ADDRESS OF CURRENT UCB FOR CONTROLLER
RTTBL:	.BLKW	R$$X11		; ERROR RETRY COUNT FOR CURRENT UNIT
									; PB045
									; PB045
	.IF DF	E$$DVC							; PB045
									; PB045
CSRSV:	.BLKW	R$$X11		; CSR SAVE AREA				; PB045
									; PB045
	.ENDC								; PB045
									; PB045
      									; PB045

	.IF	GT R$$X11-1

TEMP:	.BLKW	1		; TEMPORARY STORAGE FOR CURRENT CONTROLLER NUMBER

	.ENDC


;
; DRIVER DISPATCH TABLE
;
$DXTBL::.WORD	DXINI		; DEVICE INITIATOR ENTRY
	.WORD	DXCAN		; CANCEL I/O OPERATION ENTRY
	.WORD	DXOUT		; DEVICE TIME OUT ENTRY
	.WORD	DXPWF		; POWERFAIL ENTRY POINT

;+
; *** - DXINI  FLOPPY DISK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QIO DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPOG      ATE THE
; EXECUTION OF THE DRIVER.  IF THE SPECIFIED CONTROLLER IS NOT BUSY,
; THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST.  OTHERWISE
; A RETURN TO THE CALLER IS EXECUTED.  IF THE DEQUEUE ATTEMPT IS SUCCESSFUL
; THE NEXT I/O OPERATION IS INITIATED.  A RETURN TO THE CALLER IS THEN
; EXECUTED.
;
; INPUTS:
;	R5 - ADDRESS OF UCB WHICH IS ASSOCIATED WITH CONTROLLER TO BE INITIATED
;
; OUTPUTS:
;	IF THE CONTROLLER ASSOCIATED WITH THE SPECIFIED UCB IS NOT
;	BUSY AND AN I/O REQUEST IS WAITI      NG TO BE PROCESSED, THE REQUEST
;	IS DEQUEUED AND THE DRIVER INITIATES THE REQUESTED FUNCTION.
;
;-
	.ENABL	LSB
1$:	RETURN			;					; PB070
DXINI:	CALL	$GTPKT		; GET NEXT I/O PACKET TO PROCESS	; PB070
	BCS	1$		; IF CS BUSY OR NO PACKET		; PB070

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT
;
;	R1 - ADDRESS OF THE I/O PACKET
;	R2 - PHYSICAL UNIT NUMBER OF THE DEVICE TO PERFORM FUNCTION ON
;	R3 - CONTROLLER NUMBER MULTIPLIED BY TWO
;	R4 - ADDRESS OF SCB
;	R5 - ADDRESS OF UCB FOR DEVICE TO       PERFORM FUNCTION ON
;
; RX11 FLOPPY DISK I/O REQUEST PACKET FORMAT
;
;	WD. 00 -- I/O QUEUE THREAD WORD
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER
;	WD. 02 -- ADDRESS OF TCB OF THE REQUESTING TASK
;	WD. 03 -- POINTER TO SECOND LUN WORD OF REQUESTING TASKS HEADER
;	WD. 04 -- CONTENTS OF FIRST LUN WORD ( UCB ADDRESS)
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB, IO.RPB, IO.WLB, OR IO.WPB)
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O       STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER
;	WD. 14 -- NUMBER OF BYTES TO TRANSFER
;	WD. 15 -- NOT USED (IGNORED)
;	WD. 16 -- LOW BYTE MUST BE ZERO, HIGH BYTE NOT USED
;	WD. 17 -- LOGICAL OR PHYSICAL BLOCK NUMBER
;	WD. 20 -- NOT USED
;
; DRIVER USAGE OF WORDS IN I/O PACKET
;	I.PRM+6  (WD. 15) - STATUS REGISTER AFTER INTERRUPT
;	I.PRM+10 (WD. 16) - LOGI      CAL OR PHYSICAL SECTOR NUMBER
;	I.PRM+12 (WD. 17) - SIZE OF "THIS" TRANSFER
;	I.PRM+14 (WD. 20) - PHYSICAL SECTOR NUMBER (1-26.)
;	I.PRM+15 (WD. 20) - PHYSICAL TRACK NUMBER (0-77.)
;
;
; INITIALIZE DRIVER
;
	MOV	R5,CNTBL(R3)	; SAVE UCB ADDRESS OF CURRENT REQUEST
10$:	MOV	#RETRY,RTTBL(R3) ; SET RETRY COUNT
	TSTB	I.PRM+10(R1)	; HIGH BLOCK SPECIFIED?
	BEQ	20$		; NO
15$:	JMP	180$		; YES, ERROR
;
; SET UP FIRST BLOCK OR SECTOR NUMBER
;
20$:	MOV	I.PRM+12(R1),R0	; GET PHYSICAL OR LOGICAL BLOCK NUMB      ER
	MOV	#128.,I.PRM+12(R1)  ; PRESET TRANSFER SIZE		; PB049
	BITB	#IO.RPB&377,I.FCN(R1)  ; PHYSICAL BLOCK FUNCTION?	; PB070
	BNE	30$		; YES
	ASL	R0		; CONVERT TO LOGICAL SECTOR NUMBER
	ASL	R0		; WHICH IS LBN*4
30$:	MOV	R0,I.PRM+10(R1)	; STORE IT
35$:	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS
	CALL	TRKSEC		; CONVERT BLOCK # TO TRACK/SECTOR
	BCS	15$		; IF CS BAD BLOCK NUMBER
	MOV	S.CSR(R4),R2	; GET ADDRESS OF CSR
	CMPB	#IO.WLB/256.,I.FCN+1(R3)  ; WRITE FUNCTION?
	BNE	140$		;IF NE NO
;
; FILL SIL      O BEFORE WRITE
;
	CALL	SETBUF		; SET UP BUFFER POINTER AND MAPPING REGISTER
	MOV	#FILL,(R2)	; SET "FILL BUFFER" FUNCTION
70$:	CLR	R3		; ASSUME NO DATA TO TRANSFER
	DEC	R1		; MORE DATA TO TRANSFER?
	BLT	74$		; NO
	MOVB	(R0)+,R3	; YES, GET NEXT BYTE
74$:	BITB	#TR!DONE,(R2)	; CONTROLLER DONE?
	BMI	75$		; IF MI YES
	BEQ	74$		; IF EQ NO
	BR	90$		; SILO IS FULL
75$:	MOVB	R3,RXDB(R2)	; PUT NEXT BYTE IN SILO
	BR	70$		; AND WAIT TILL IT'S ACCEPTED
90$:	TST	R1		; ALL BYTES TRANSFERED?
	BMI	130$		; IF M      I YES
95$:	JMP	DXRTY		; RETRY LAST FUNCTION
;
; EMPTY SILO AFTER READ
;
100$:	MOV	#EMPTY,(R2)	; SET "EMPTY BUFFER" FUNCTION
	CALL	SETBUF		; SET BUFFER POINTER AND MAPPING REGISTER
110$:	BITB	#TR!DONE,(R2)	; CONTROLLER DONE?
	BMI	111$		; IF MI YES
	BEQ	110$		; IF EQ NO
	BR	120$		; SILO IS EMPTY
111$:	MOVB	RXDB(R2),R3	; GET NEXT BYTE FROM SILO
	DEC	R1		; DO WE WANT IT?
	BLT	110$		; NO
	MOVB	R3,(R0)+	; YES, PUT IT IN BUFFER
	BR	110$		; GET NEXT BYTE
120$:	TST	R1		; ALL BYTES TRANSFERED?
	BGT	9      5$		; IF GT ERROR
	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS
	CALL	NXTSEC		; UPDATE TO NEXT SECTOR
	BEQ	193$		; ALL DONE
	BR	35$		; CONTINUE
;
; INITIATE TRANSFER BETWEEN SILO AND DISK
;
130$:	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS
	MOV	#WRITE,R0	; ASSUME WRITE FUNCTION
	MOV	I.FCN(R3),R1	; COPY FUNCTION CODE			; PB070
	BIC	#7,R1		; REMOVE QUALIFIER BITS			; PB070
	CMP	#IO.WDD,R1	; WRITE DELETED DATA?			; PB070
	BNE	141$		; IF NE NO				; PB070
	MOV	#WRTDD,R0	; SET "WRITE DELETED DATA" FUNCTI      ON
	BR	141$		;
140$:	MOV	#READ,R0	; SET READ FUNCTION
141$:	TSTB	U.UNIT(R5)	; UNIT 1?
	BEQ	142$		; IF EQ YES
	BIS	#UNIT,R0	; YES, SET TO SELECT UNIT 1
142$:				; REF LABEL				; PB045
									; PB045
									; PB045
	.IF DF	E$$DVC							; PB045
									; PB045
	MOVB	S.CON(R4),R1	; RETREIVE CONTROLLER INDEX		; PB045
	MOV	R0,CSRSV(R1)	; SAVE FUNCTION AND UNIT NUMBER		; PB045
									; PB045
	.ENDC								; PB045
									; PB045
									; PB045
	MOV	R0,(R2)		; INITIATE THE FUNCTION			; PB      045
143$:	BITB	#TR!DONE,(R2)	; TRANSFER READY OR DONE?
	BMI	150$		; IF MI TRANSFER READY
	BEQ	143$		; IF EQ LOOP
	BR	95$		; ERROR, NO TRANSFER REQUEST
150$:	MOVB	I.PRM+14(R3),RXDB(R2)  ; LOAD SECTOR NUMBER
151$:	BITB	#TR!DONE,(R2)	; TRANSFER READY OR DONE?
	BMI	152$		; IF MI TRANSFER READY
	BEQ	151$		; IF EQ LOOP
	BR	95$		; ERROR, NO TRANSFER REQUEST
152$:	MOVB	I.PRM+15(R3),RXDB(R2)  ; LOAD TRACK NUMBER
155$:	MOVB	S.ITM(R4),S.CTM(R4) ; SET TIME OUT COUNT


	.IF DF	E$$DVC

	CALL	$BMSET		; SET       I/O ACTIVE IN BITMAP

	.ENDC


	BIS	#INTEBL,(R2)	; SET INTERRUPT ENABLE
;
; DXPWF - POWER FAIL ENTRY POINT
;	POWER FAIL IS HANDLED BY THE DEVICE TIMING OUT, THEREFORE
;	NO WNRK IS DNNE HERE.  IT WILL BE HANDLED WHEN THE DEVICE
;	TIME OUT ENTRY IS EXECUTED.
;
DXPWF:

;
; DXCAN - CANCEL I/O ENTRY POINT
;	CANCEL I/O IS A NOP OP FOR FILE STRUCTURED DEVICES
;
DXCAN:	RETURN			;

;+
; *** - $DXINT  - RX11 FLOPPY DISK INTERRUPT ENTRY POINT
;
;-
	INTSE$	DX,PR5,R$$X11	;;; GENERATE INTERRUPT S      AVE CODE
	MOV	R3,-(SP)	;;; SAVE REGISTER
	MOV	U.SCB(R5),R4	;;; GET SCB ADDRESS
	MOV	S.PKT(R4),R3	;;; GET I/O PACKET ADDRESS
	MOV	S.CSR(R4),R4	;;; GET CSR ADDRESS
	MOV	RXDB(R4),I.PRM+6(R3)  ;;; SAVE CONTROLLER STATUS
	MOV	(SP)+,R3	;;; RESTORE REGISTER
	BIC	#INTEBL,(R4)	;;; DISABLE INTERRUPTS
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS
	MOV	R4,R2		; COPY CSR ADDRESS
	MOV	U.SCB(R5),R4	; GET SCB ADDRESS
	MOVB	S.CON(R4),R3	; GET CONTROLLER INDEX
	TST	(R2)		; ANY ERRORS?
	BPL	160$		; IF PL NO


	.IF       DF	E$$DVC

	CALL	LOGERR		; LOG DEVICE ERROR			; PB045

	.ENDC


	BR	DXRTY		; RETRY FUNCTION
160$:	ASRB	RTTBL+1(R3)	; INITIALIZE IN PROGRESS?
	BCS	170$		; IF CS YES
	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS
	CMPB	#IO.RLB/256.,I.FCN+1(R3)  ; READ?
	BNE	165$		; IF NE NO
	JMP	100$		; GO EMPTY SILO
165$:	CALL	NXTSEC		; UPDATE TO NEXT SECTOR
	BEQ	195$		; ALL DONE
170$:	JMP	35$		; WRITE MORE DATA
180$:	MOV	#IE.BLK&377,R0	; SET BAD BLOCK ERROR
	BR	210$		;
190$:	MOV	#IE.VER&377,R0	; SET UNRECOVER      ABLE ERROR
	BR	200$		;
193$:	BITB	#IO.RPB&377,I.FCN(R3)  ; READ PHYSICAL BLOCK FUNCTION?	; PB070
	BEQ	195$		; NO, THEN IGNORE DELETED DATA MARK
	MOV	#IS.RDD&377,R0	; YES, DEFAULT ON READ TO DELETED DATA
	BIT	#DD,I.PRM+6(R3)	; WAS DELETED DATA READ?		; PB070
	BNE	200$		; YES
195$:	MOV	#IS.SUC&377,R0	; NO, SET NORMAL SUCCESS
200$:	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS
	MOV	I.PRM+4(R1),R1	; SET BYTES TRANSFERED
	SUB	U.CNT(R5),R1	; CALCULATE BYTES ACTUALLY TRANSFERED


	.IF DF	E$$DVC

	MOVB	S      .CON(R4),R3	; RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	; SET FINAL RETRY COUNT
	BIS	#RETRY*256.,R2	; SET INITIAL RETRY COUNT

	.ENDC


210$:	CALL	$IODON		; SET DONE
	JMP	DXINI		; TRY FOR ANOTHER REQUEST
;
;+
; *** - DXOUT - FLOPPY DISK TIMEOUT ENTRY POINT
;-

DXOUT:				;;; TIMEOUT ENTRY POINT			; PB045
									; PB045
									; PB045
	.IF DF	E$$DVC							; PB045
									; PB045
	CALL	LOGTMO		;;; LOG DEVICE TIMEOUT			; PB045
									; PB045
	.IFF								; PB045
									; PB045      
	CALL	$DTOER		;;; LOG DEVICE TIMEOUT			; PB045
									; PB045
	.ENDC								; PB045
									; PB045

;
; RETRY LAST FUNCTION
;
DXRTY:	MOVB	S.CON(R4),R3	; RESTORE CONTROLLER INDEX
	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	; INHIBIT RETRIES?
	BNE	190$		; IF NE YES
	DECB	RTTBL(R3)	; ANY RETRIES LEFT?
	BEQ	190$		; NO, ERROR
	MOVB	#1,RTTBL+1(R3)	; YES, SET INITIALIZE IN PROGRESS
									; PB045
									; PB045
	.IF DF	E$$DVC							; PB045
									; PB045
	MOV	#INI      T,CSRSV(R3)	; SAVE FUNCTION CODE			; PB045
									; PB045
	.ENDC								; PB045
									; PB045
									; PB045
	MOV	#INIT,(R2)	; INITIALIZE RX01 DRIVES
	JMP	155$		; AND DO IT
	.DSABL	LSB

									; PB045
	.IF DF	E$$DVC							; PB045
									; PB045
;+									; PB045
; **-LOGERR-LOG DEVICE ERROR						; PB045
; **-LOGTMO-LOG DEVICE TIMEOUT						; PB045
;									; PB045
; THESE ROUTINES WILL ALLOCATE A CORE BLOCK, FILL IT WITH THE		; PB045
; REGISTER INFORMATION, CALL THE APPROPRIATE       EXECUTIVE ERROR		; PB045
; LOGGING ROUTINE, DEALLOCATE THE CORE BLOCK, AND RETURN BACK TO	; PB045
; THE CALLER.								; PB045
;									; PB045
; INPUTS:								; PB045
;	R3=CONTROLLER INDEX						; PB045
;	R4=SCB ADDRESS							; PB045
;	R5=UCB ADDRESS							; PB045
;									; PB045
; OUTPUTS:								; PB045
;	R2=CSR ADDRESS							; PB045
;	R4=SCB ADDRESS							; PB045
;	R5=UCB ADDRESS							; PB045
;									; PB045
; R0, R1 AND R3 ARE DESTROYED.						; PB045
;-									; PB045
									;       PB045
	.ENABL	LSB							; PB045
LOGERR:	MOV	#$DVERR,-(SP)	; LOG DEVICE ERROR			; PB045
	BR	10$		;					; PB045
LOGTMO:	MOV	#$DTOER,-(SP)	;;; LOG DEVICE TIMEOUT			; PB045
10$:	MOV	#DXNUM*2,R1	; GET NUMBER OF BYTES TO ALLOCATE	; PB045
	CALL	$ALOCB		; ALLOCATE THE ERROR BLOCK		; PB045
	BCC	20$		; IF CC OK				; PB045
	INC	$ERRSQ		; INDICATE A MISSED ERRO		; PB045
	CMP	(SP)+,#$DTOER	; TIMEOUT?				; PB045
	BNE	30$		; IF NE NO				; PB045
	BIC	#INTEBL,@S.CSR(R4)  ;;; CLEAR INTERRUPT ENABLE		; PB045
	MTPS      	#0		;;; ALLOW INTERRUPTS			; PB045
	BR	30$		;					; PB045
20$:	MOV	R0,R1		; COPY CORE BLOCK ADDRESS		; PB045
	MOV	S.CSR(R4),R2	; RETREIVE CSR ADDRESS			; PB045
	MOV	(R2),(R1)	; SAVE CSR CONTENTS			; PB045
	BIS	CSRSV(R3),(R1)+	; SET BITS 0-4 IN RXCS			; PB045
	MOV	RXDB(R2),(R1)+	; SAVE RXDB				; PB045
	MOV	S.PKT(R4),R3	; GET I/O PACKET ADDRESS		; PB045
	MOV	I.PRM+6(R3),(R1)+  ; SAVE RXES				; PB045
	MOV	#RDERC,(R2)	; EXECUTE READ ERROR CODE FUNCTION	; PB045
25$:	BITB	#DONE,(R2)	; WAIT UNTIL DONE		      	; PB045
	BEQ	25$		; IF EQ NO				; PB045
	MOV	RXDB(R2),(R1)+	; SAVE RXER				; PB045
	MOV	R0,S.CSR(R4)	; FAKE CSR ADR WITH ERR BLOCK ADR	; DS002
	CALL	@(SP)+		; LOG THE ERROR				; DS002
	MOV	R2,S.CSR(R4)	; RESTORE THE CSR ADR IN SCB		; DS002
	MOV	#DXNUM*2,R1	; GET NUMBER OF BYTES TO DEALLOCATE	;**-5
	CALL	$DEACB		; DEALLOCATE THE ERROR BLOCK		; PB045
30$:	MOV	S.CSR(R4),R2	; RETREIVE CSR ADDRESS			; PB045
	RETURN			;					; PB045
	.DSABL	LSB							; PB045
									; PB045
	.ENDC								; PB045
			      						; PB045
									; PB045
;+
; *** - TRKSEC  -  CONVERT LOGICAL OR PHYSICAL BLOCK NUMBER TO
;	TRACK-SECTOR PAIR
; FROM ALGORITHM BY J GILBERT MODIFIED BY H. JACOBS
;
; INPUT:
;	R3 - I/O PACKET ADDRESS
;	I.PRM+10(R3) - LOGICAL OR PHYSICAL SECTOR
;
; OUTPUT:
;	I.PRM+14(R3) - SECTOR (1-26.)
;	I.PRM+15(R3) - TRACK (0-77.)
;	R3 - UNCHANGED
;	C CLEAR - VALID BLOCK
;	C SET - BAD BLOCK NUMBER (PHYSICAL OR LOGICAL)
;
;-
TRKSEC:	MOV	I.PRM+10(R3),R1	; GET LOGICAL OR PHYSICAL BLOCK
	MOV	#8.,R0	      	; SET LOOP COUNT
	MOV	#6400,R2	; SET DIVISOR
1$:	CMP	R2,R1		; DOES 26 GO INTO DIVIDEND?
	BHI	2$		; BRANCH IF NOT, C CLEAR
	SUB	R2,R1		; SUBTRACT 26 FROM DIVIDEND
	SEC			; SET CARRY
2$:	ROL	R1		; SHIFT DIVIDEND AND QUOTIENT
	DEC	R0		; DONE?
	BGT	1$		; NO, LOOP
	MOVB	R1,R0		; GET TRACK NUMBER
	CLRB	R1		; CLEAR TRACK NUMBER
	SWAB	R1		; SHIFT DONE SECTOR NUMBER
	BITB	#IO.RPB&377,I.FCN(R3)  ; PHYSICAL BLOCK WANTED?		; PB070
	BNE	10$		; YES
	CMP	#12.,R1		; NO, C=1 IF 13<=R1<=25
	ROL	R1		; DOUBLE F      OR INTERLEAVE FACTOR
	ASL	R0		; ADD TRACK -TRACK SKEW
	ADD	R0,R1		; SKEW BY 2*TRACK
	ADD	R0,R1		; SKEW BY 4*TRACK
	ADD	R0,R1		; SKEW BY 6*TRACK
	ASR	R0		; RESTORE TRACK NUMBER
	MOV	#26.,R2		; SET MODULUS
5$:	SUB	R2,R1		; MODULO SECTOR INTO RANGE -26. TO -1.
	BGE	5$		; LOOP TILL REMAINDER GOES NEG
	ADD	R2,R1		; CONVERT TO RANGE 0-25.
	INC	R0		; LBN0 STARTS ON TRACK 1
10$:	INC	R1		; CONVERT TO RANGE 1-26.
	MOV	R1,I.PRM+14(R3)	; SAVE SECTOR NUMBER
	MOVB	R0,I.PRM+15(R3)	; SAVE TRACK NUMBER
	CMP	#7      7.*256.,I.PRM+14(R3)  ; IS IT A VALID TRACK/SECTOR?
	RETURN			;

;+
; *** - NXTSEC  -  UPDATE BLOCK NUMBER , BUFFER ADDRESS
;			AND BUFFER POINTER
;
; INPUT:
;	R3 - I/O PACKET ADDRESS
;	R5 - UCB ADDRESS
;	I.PRM+10(R3) - CURRENT BLOCK NUMBER
;	I.PRM+12(R3) - BYTES TRANSFERED DURING LAST FUNCTION
;	U.CNT(R5) - BYTES LEFT TO TRANSFER
;	U.BUF(R5) - BUFFER ADDRESS
;
; OUTPUT:
;	I.PRM+10(R3) - UPDATED BLOCK NUMBER
;	U.BUF(R5) - UPDATED BY 128. BYTES
;	U.CNT(R5) - UPDATED BY NUMBER OF WORDS TRANS      FERED
;	Z SET - ALL BYTES TRANSFERED
;	Z CLEAR - MORE BYTES TO TRANSFER
;	C CLEAR - VALID TRACK/SECTOR
;	C SET - BAD BLOCK NUMBER
;
;+
NXTSEC:	INC	I.PRM+10(R3)	; UPDATE BLOCK NUMBER


	.IF NDF	M$$MGE

	ADD	#128.,U.BUF+2(R5) ; UPDATE BUFFER POINTER

	.IFF

	ADD	#2.,U.BUF(R5)	; UPDATE MEMORY BLOCK NUMBER

	.ENDC


	SUB	I.PRM+12(R3),U.CNT(R5)  ; UPDATE BYTES LEFT TO TRANSFER
	RETURN			;

;+
; *** - SETBUF  -  SET UP BUFFER POINTER FOR CPU - SILO TRANSFERS
;
; INPUT:
;	R3 - I/O PACKE      T ADDRESS
;	R5 - UCB ADDRESS
;
; OUTPUT:
;	I.PRM+12(R3) - BYTES TO TRANSFER
;	R0 - BUFFER ADDRESS
;	R1 - BYTES TO TRANSFER
;	IF MAPPED SYSTEM KISAR6 IS MAPPED TO BUFFER AND R1 IS BASE 140000
;
;-
SETBUF:	MOV	U.BUF+2(R5),R0	; GET BUFFER ADDRESS
	MOV	#128.,R1	; DEFAULT TO 128. BYTE TRANSFER
	CMP	U.CNT(R5),R1	; 128. BYTES LEFT TO TRANSFER?
	BHIS	10$		; YES
	MOV	U.CNT(R5),R1	; NO, GET RESIDUAL COUNT
10$:	MOV	R1,I.PRM+12(R3)	; STORE BYTES TO TRANSFER


	.IF DF	M$$MGE

	MOV	U.BUF(R5),@#KISAR6    :   ; SET MAPPING REGISTER

	.ENDC

	RETURN			;

	.END
:          ""�`kQ	› c,        	.TITLE	ERROR
	.IDENT	/07.07/

;
; COPYRIGHT (C) 1981 BY DIGITAL EQUIPMENT CORPORATION
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 07.07
;
; D. BROWN/P. J. BEZEREDI 15-MAY-81
;
; PREVIOUSLY MODIFIED BY:
;
; MODIFIED BY:
;
;	C. PUTNAM	4-JUN-81
;
;	R. T. PERRON	2-JUL-81
;
;	P. J. BEZEREDI	13-AUG-81
;
;	P. J. BEZEREDI	2-NOV-81
;		UCB ADDRESS NOT VALID DURING NONSENSE INT      ERRUPT
;
;	M. S. HARVEY	6-NOV-81
;		PRESERVE C-BIT ON PACKET CREATION FAILURE
;
; ERROR LOGGING
;
;
; MACRO LIBRARY CALLS
;
	.MCALL	CLKDF$,EPKDF$,HDRDF$,HWDDF$,PKTDF$,F11DF$
	CLKDF$			;DEFINE CLOCK QUEUE OFFSETS
	EPKDF$			;DEFINE ERROR PACKET OFFSETS
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE CPU REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	F11DF$			;DEFINE VCB OFFSETS


	.IF DF	E$$LOG

;
; LOCAL STORAGE
;

DTOTMP:	.BLKW	1		;SAVED CSR CONTENTS FOR DEVICE TIMEOUT

;      
; NONSENSE INTERRUPT STORAGE
;
; ADJACENCY ASSUMED
;
	.BLKW	2		;FORK BLOCK
NSIPSW:	.BLKB	1		;SAVED PS
NSICNT:	.BYTE	-1		;RECURSION COUNTER.
				; RECURSION COUNTER=0 IMPLIES THAT A
				; NONSENSE INTERRUPT IS BEING HANDLED.
				; RECURSION COUNTER=-1 IMPLIES THAT A
				; NONSENSE INTERRUPT IS NOT BEING
				; HANDLED AT THE MOMENT.
				; RECURSION COUNTER=N IMPLIES THAT N
				; NONSENSE INTERRUPTS WERE LOST

;+
; **-$NS0, $NS1, $NS2, $NS3, $NS4, $NS5, $NS6, $NS7-
;	UNEXPECTED INTERRUPT IDE      NTIFIER ROUTINES.
;
; EACH OF THESE ROUTINES IS VECTORED TO BY ONE OF A GROUP OF 16
; UNUSED VECTORS.  THE VECTORS ARE SUB-CODED IN THE PS CONDITION
; CODES.
;-

$NS0::	CALL	NSIER		;;; CALL THE COMMON CODE
	.WORD	000		;;; GROUP 000-017 (VECTORS 000-074)
$NS1::	CALL	NSIER		;;;
	.WORD	020		;;; GROUP 020-037 (VECTORS 100-174)
$NS2::	CALL	NSIER		;;;
	.WORD	040		;;; GROUP 040-057 (VECTORS 200-274)
$NS3::	CALL	NSIER		;;;
	.WORD	060		;;; GROUP 060-077 (VECTORS 300-374)
$NS4::	CALL	NSIER		;;;
	.WORD      	100		;;; GROUP 100-117 (VECTORS 400-474)
$NS5::	CALL	NSIER		;;;
	.WORD	120		;;; GROUP 120-137 (VECTORS 500-574)
$NS6::	CALL	NSIER		;;;
	.WORD	140		;;; GROUP 140-157 (VECTORS 600-674)
$NS7::	CALL	NSIER		;;;
	.WORD	160		;;; GROUP 160-177 (VECTORS 700-774)

;
; TEMPORARY ENTRIES TO NO-OP PREVIOUS ERROR LOGGING SYSTEM CALLS
;

	.IFTF

$ALEMB::
$ALEB1::
	MOV	(SP)+,(SP)	;DISCARD THE ERROR CODE
	SEC			;INDICATE ALLOCATION FAILURE
$QEMB::	RETURN			;DONE.

	.IFT

;+
; **-$BMSET-SET A DRIVER'S       BIT IN THE I/O ACTIVE BITMAP
;
; THIS COROUTINE RAISES THE PROCESSOR PRIORITY TO 7 AND THEN RECALLS
; THE CALLER WHO WILL START THE I/O FUNCTION AND RETURN HERE TO ALLOW
; INTERRUPTS.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	PRIORITY SET TO PR7.
;-

$BMSET::MTPS	#PR7		;LOCK OUT INTERRUPTS
	CALL	@(SP)+		;;;RECALL THE CALLER
	MTPS	#0		;;;ALLOW INTERRUPTS
	RETURN			;EXIT

	.ENDC


;+
; **-$DVTMO-LOG DEVICE TIMEOUT AT PR0
; **-$DTOER-LOG DEVICE TIMEOUTS AT DEVICE PRIORITY
;
; THIS ROUT      INE IS CALLED TO LOG A DEVICE TIMEOUT ERROR CONDITION.  THE
; CONTROLLER'S INTERRUPT ENABLE BIT IS RESET AND THE PROCESSOR PRIORITY
; IS DROPPED TO ZERO.  IF A DIAGNOSTIC FUNCTION WAS IN PROGRESS, NO
; ERROR IS LOGGED.
;
; INPUTS:
;
;	R2=CSR ADDRESS
;	R4=SCB ADDRESS
;
; OUTPUTS:
;
;	R1=ADDRESS OF I/O PACKET (IF DIAGNOSTIC ENABLED)
;
;	C=0 IF FUNCTION WAS NOT A USER MODE DIAGNOSTIC FUNTION.
;		THE ERROR LOG PACKET IS FILLED AND THE SCB CONTAINS
;		A POINTER TO IT.  THE ERROR IN PROGRESS FLAG       IS SET IN
;		THE SCB.
;	C=1 IF FUNCTION WAS A USER MODE DIAGNOSTIC FUNCTION.  IN THIS
;		CASE ONLY THE INTERRUPT ENABLE BIT IS CLEARED AND THE
;		PRIORITY IS LOWERED TO ZERO.
;-

	.ENABL	LSB
$DVTMO::			;LOG DEVICE TIMEOUTS


	.IF DF	E$$LOG

	MOV	(R2),DTOTMP	;SAVE THE CSR CONTENTS

	.ENDC


	BR	5$		;
$DTOER::			;;;LOG DEVICE TIMEOUTS


	.IF DF	E$$LOG

	MOV	(R2),DTOTMP	;;;SAVE THE CSR CONTENTS

	.IFTF

	BIC	#100,(R2)	;;;DISABLE THE DEVICE INTERRUPT
	MTPS	#0		;;;ALLOW INTERRUPTS
5      $:				;REF LABEL


	.IF DF	D$$IAG

	MOV	S.PKT(R4),R1	;PICK UP THE ADDRESS OF THE I/O PACKET
	SEC			;ASSUME IT IS A DIAGNOSTIC FUNCTION
	BITB	#IQ.UMD,I.FCN(R1)  ;IS IT A DIAGNOSTIC FUNCTION?
	BNE	60$		;IF NE IT IS A DIAGNOSTIC FUNCTION

	.ENDC


	.IFT

	MOV	R0,-(SP)	;SAVE FOR THE ERROR CODE
	MOV	#E$CERR+<400*E$STMO>,R0  ;SET PACKET CODE
	BR	10$		;GO PROCESS THE ERROR

;+
; **-$DVCER-LOG A DEVICE ERROR
;
; THIS ROUTINE IS CALLED TO LOG A DEVICE ERROR.  AN ERROR LOG PACKET
; WILL BE ALLO      CATED AND THE CONTEXT OF THE CURRENT TRANSFER WILL BE
; SAVED.  IF AN ERROR IS ALREADY IN PROGRESS FOR THIS DEVICE, THE ERROR
; WILL BE IGNORED.
;
; INPUTS:
;
;	R4=SCB ADDRESS
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	IF THIS IS THE FIRST OCCURENCE OF THE ERROR, THE ERROR LOG
;	PACKET IS FILED AND THE SCB IS SET TO POINT TO THE PACKET
;	ADDRESS AND THE ERROR IN PROGRESS BIT IS SET.
;
; NOTE: ALL REGISTERS ARE PRESERVED.
;-

$DVERR::
$DVCER::MOV	R0,-(SP)	;SAVE FOR USE BY THE ERROR CODE
	MOV	#E$CE      RR+<400*E$SDVH>,R0  ;GET THE HARD ERROR CODE
10$:	CALL	LOGTST		;SEE IF WE CAN LOG THE ERROR
	BCS	50$		;IF CS WE CAN'T
	MOV	R1,-(SP)	;SAVE FOR USE BY ERROR PACKET ROUTINES
	MOV	R2,-(SP)	;
	MOV	R3,-(SP)	;
	MOV	R4,-(SP)	;
	MOVB	S.RCNT(R4),R1	;GET THE NUMBER OF REGISTERS TO SAVE
	ASL	R1		;CONVERT IT INTO A NUMBER OF BYTES


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;BAE REGISTERS PERSENT?
	BEQ	30$		;IF EQ NO
	ADD	#4,R1		;FOUR BYTES FOR THE TWO EXTRA REGISTERS

	.ENDC


30$:	MOVB	S.ROFF(R4),R3	      ;GET THE OFFSET TO THE FIRST REGISTER
	ADD	S.CSR(R4),R3	;COMPUTE THE ACTUAL REGISTER START


	.IF DF	E$$ACT

	MOV	#SM.HDR!SM.DID!SM.DOP!SM.DAT!SM.DAC,R2  ;SET FLAGS

	.IFF

	MOV	#SM.HDR!SM.DID!SM.DOP!SM.DAT,R2  ;SET FLAGS

	.ENDC


;
; AT THIS POINT THE REGISTERS ARE:
;
;	R0 = ENTRY TYPE CODE AND SUBTYPE CODE
;	R1 = LENGTH OF DEVICE REGISTERS IN BYTES
;	R2 = CONTROL MASK WORD
;	R3 = BEGINNING ADDRESS OF DEVICE REGISTERS
;	R4 = SCB ADDRESS (UNUSED BY $CRPKT)
;	R5 = UCB ADDRESS

	CALL      	$CRPKT		;CREATE THE PACKET
	BCS	45$		;IF CS FAILURE
	CMP	R0,#E$CERR+<400*E$STMO>  ;IS IT A TIMEOUT?
	BNE	40$		;IF NE NOT A TIMEOUT
	MOVB	S.ROFF(R4),R2	;GET THE NUMBER OF REGISTERS TO OFFSET
	ASL	R2		;TURN IT INTO A NUMBER OF BYTES
	SUB	R2,R1		;COMPUTE THE ADDRESS OF THE CSR STORAGE
	MOV	DTOTMP,(R1)	;INSERT THE SAVED CSR ADDRESS
40$:	MOV	R3,S.BMSV(R4)	;SAVE THE ERROR LOG PACKET ADDRESS
	BISB	#SP.EIP,S.PRI(R4)  ;SET ERROR IN PROGRESS
45$:	MOV	(SP)+,R4	;RESTORE THE REGISTERS SAVED
	MOV	(SP)+,R3	;
      	MOV	(SP)+,R2	;
	MOV	(SP)+,R1	;
50$:	MOV	(SP)+,R0	;

	.ENDC


	CLC			;SHOW PACKET OK
60$:	RETURN			;DONE
	.DSABL	LSB

;+
; **-NSIER-UNEXPECTED (NONSENSE) INTERRUPT ERRORS
;
; THIS ROUTINE IDENTIFIES THE INTERRUPTING VECTOR AND LOGS THE ERROR.
;
; INPUTS:
;
;	@(SP)=BITS 06:04 OF THE UNUSED VECTOR NUMBER
;
; OUTPUTS:
;
;	AN ERROR LOG PACKET IS ALLOCATED AND QUEUED TO THE ERROR LOGGER.
;-


	.IF DF	E$$LOG

NSIER:	MFPS	-(SP)		;;;SAVE THE VECTOR ID (MODULO 20)
	INCB	NSICNT		;;;NSI IN       PROGRESS?
	BNE	10$		;;;IF NE THEN NSI ALREADY IN PROGRESS
	BIT	#ES.LOG,$ERFLA	;;;LOGGING ERRORS?
	BNE	20$		;;;IF NE THEN OK TO LOG.
	DECB	NSICNT		;;;RESTORE THE COUNTER
10$:	CMP	(SP)+,(SP)+	;;;YES, SO CLEAR THE STACK
	RTI			;;;AND RETURN.

;
; THE NONSENSE INTERRUPT HAS NOT INTERRUPTED THE HANDLING OF A PREVIOUS
; NONSENSE INTERRUPT, SO GO AHEAD AND PROCESS IT.
;

20$:	BIC	#177760,(SP)	;;;ISOLATE THE VECTOR ID IN THE PS
	MOV	(SP)+,NSIPSW	;;;SAVE THE VECTOR ID.
	BIS	@(SP)+,NSIPSW	;;;ADD IN TH      E GROUP BIAS
	CALL	$INTSV,PR7	;;;SWITCH STACKS
	MOV	#NSIPSW,R4	;GET THE POINTER TO THE FORK BLOCK
	CALL	$FORK0		;AND FORK
	MOV	#E$CCPU+<400*E$SINT>,R0  ;GET THE ERROR CODE
	MOV	#2,R1		;THE BUFFER LENGTH IS TWO BYTES


	.IF DF	E$$ACT

	MOV	#SM.HDR!SM.DAT!SM.DAC,R2  ;SET SUBPACKET FLAGS

	.IFF

	MOV	#SM.HDR!SM.DAT,R2  ;SET SUBPACKET FLAGS

	.ENDC


	MOV	#NSIPSW,R3	;GET THE ADDRESS OF THE DATA SUBPACKET
	INC	$ERRSQ		;COUNT ONE MORE ERROR LOGGED
	CALL	$CRPKT		;CREATE THE PACKET
	BCS	30$		;      IF CS FAILURE TO ALLOCATE POOL
	CALL	$QUPKT		;AND QUEUE IT.
30$:	MOVB	#-1,NSICNT	;RESTORE THE COUNTER
	RETURN			;DONE - RETURN TO FORK HANDLING

;+
; **-$FNERL-FINISH ERROR LOGGING PROCESS
;
; THIS ROUTINE IS CALLED AT I/O DONE TIME OR WHEN IT IS NECESSARY
; TO QUEUE AN ERROR LOG PACKET AFTER A SUCCESSFUL RECOVERY OF A
; MID-TRANSFER ERROR.
;
; INPUTS:
;
;	R0=FIRST I/O STATUS WORD
;	R2=STARTING AND FINAL ERROR RETRY COUNTS
;	   (IF R2=0, DO NOT UPDATE HARD/SOFT LIMIT COUNTS)
;	R3=ERROR LOG       PACKET ADDRESS (IF R4=0)
;	R4=SCB ADDRESS OR ZERO
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	THE ERROR PACKET IS QUEUED TO THE ERROR LOGGER.
;	THE ERROR IN PROGRESS BIT IS CLEARED.
;
; R1, R2 AND R3 MAY BE DESTROYED
;-

$FNERL::TST	R4		;DO WE HAVE AN SCB?
	BEQ	10$		;IF EQ NO, R3 HAS PACKET ADDRESS
	MOV	S.BMSV(R4),R3	;YES, GET ADDRESS OF ERROR PACKET
	BEQ	40$		;IF EQ THERE IS NONE
10$:	MOV	R0,-(SP)	;SAVE REGISTER
	MOV	R2,<E$HLEN+E$ILEN+E$ORTY>(R3)  ;INSERT RETRY COUNTS
	BEQ	35$		;IF EQ DON'T UPDATE       HARD/SOFT LIMIT COUNTS
	MOV	R5,R2		;COPY UCB ADDRESS
	ADD	#U.ERHC,R2	;ASSUME THIS IS A HARD ERROR
	TSTB	R0		;SUCCESSFUL FUNCTION?
	BMI	20$		;IF MI NO
	ADD	#U.ERSC-U.ERHC,R2  ;POINT TO SOFT ERROR COUNT
	MOVB	#E$SDVS,E$HTYS+4(R3)  ;SET SOFT ERROR CODE
20$:	INCB	(R2)		;COUNT ANOTHER ERROR
	INCB	(R2)		;ADD ONE MORE FOR OVERFLOW TEST
	BNE	30$		;IF NE NO OVERFLOW
	DECB	(R2)		;NORMALIZE ERROR COUNT
30$:	DECB	(R2)		;...
35$:	CALL	$QUPKT		;QUEUE THE ERROR PACKET
	MOV	(SP)+,R0	;RESTORE REGISTERS
	TST	R4      		;DO WE HAVE AN SCB?
	BEQ	50$		;IF EQ NO
40$:	BICB	#SP.EIP,S.PRI(R4)  ;CLEAR ERROR IN PROGRESS
	CLR	S.BMSV(R4)	;SHOW NO ERROR LOG PACKET
50$:	RETURN			;

;+
; **-$LOGER-LOG AN ERROR LOG PACKET (NO ERROR NEED BE PRESENT)
;
; THIS ROUTINE IS CALLED BY DRIVERS THAT WISH TO CREATE AN ERROR LOG
; PACKET WHEN NO ERROR IS PRESENT, IE. FOR AN UNSOLICITED INTERRUPT.
; THE PACKET WILL BE CREATED AND THE DRIVER IS RESPONSIBLE FOR FILLING
; IN THE NECESSARY DATA INFORMATION.
;
; INPUTS:
;
;	R1=LENGTH O      F DATA TO BE LOGGED IN BYTES
;	R4=SCB ADDRESS (IF ZERO THEN NO I/O PACKET IS PRESENT)
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	C=1 IF ERROR CANNOT BE LOGGED FOR ANY REASON
;	C=0 IF ERROR CAN BE LOGGED
;		R1=ADDRESS OF DATA AREA IN ERROR LOG PACKET
;		R3=ADDRESS OF ERROR LOG PACKET
;
;	R4 AND R5 ARE PRESERVED
;	R0, R2 AND R3 ARE DESTROYED
;-

$LOGER::CALL	LOGTST		;SEE IF WE CAN LOG THE ERROR
	BCS	20$		;IF CS WE CAN'T
	MOV	#E$CDVI+<400*E$SDVI>,R0  ;SET ERROR CODE


	.IF DF	E$$ACT

	MOV	#SM.HDR!      SM.DAT!SM.DAC!SM.DID,R2  ;SET FLAGS

	.IFF

	MOV	#SM.HDR!SM.DAT!SM.DID,R2  ;SET FLAGS

	.ENDC


	TST	R4		;IS THERE AN SCB ADDRESS
	BEQ	10$		;IF EQ NO
	BIS	#SM.DOP,R2	;YES, LOG I/O PACKET INFORMATION
	MOV	#E$CERR+<400*E$SDVH>,R0  ;SET ERROR CODE
10$:	CLR	R3		;DO NOT FILL DATA SUBPACKET AREA
	CALL	$CRPKT		;CREATE THE ERROR LOG PACKET
	BCS	20$		;IF CS FAILURE
	TST	R4		;SCB ADDRESS PRESENT? (C=0)
	BEQ	20$		;IF EQ NO
	MOV	R3,S.BMSV(R4)	;YES, SAVE ERROR LOG PACKET ADDRESS
	BISB	#SP.EIP,S.PRI(R4      )  ;SET ERROR IN PROGRESS
20$:	RETURN			;

;+
; **-LOGTST-SEE IF WE CAN LOG AN ERROR
;
; THIS ROUTINE WILL CHECK AND SEE IF THE ERROR CAN BE SUCCESSFULLY
; LOGGED.  IF IT CAN BE, THEN THE ERROR SEQUENCE NUMBER IS INCREMENTED.
;
; INPUTS:
;
;	R4=SCB ADDRESS OR ZERO IF NO SCB
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	C=0 IF ERROR CAN BE LOGGED
;	C=1 IF ERROR CANNOT BE LOGGED
;-

LOGTST:	BIT	#ES.LOG,$ERFLA	;IS LOGGING OF ERRORS TURNED ON?
	BEQ	20$		;IF EQ NO
	TST	R4		;SCB PRESENT?
	BEQ	5$		;IF E      Q NO
	BITB	#SP.EIP!SP.ENB,S.PRI(R4)  ;ERROR IN PROGRESS/LOGGING OFF?
	BNE	20$		;IF NE YES
5$:	INC	$ERRSQ		;ONE MORE ERROR IN THE SYSTEM
	BITB	#ES.LIM,$ERFLA	;IS LIMITING ENABLED?
	BEQ	10$		;NO, SO DON'T PERFORM LIMITING
	CMPB	U.ERHC(R5),U.ERHL(R5)  ;IS THE HARD THRESHOLD EXCEEDED?
	BHIS	20$		;IF HIS YES
	CMPB	U.ERSC(R5),U.ERSL(R5)  ;IS THE SOFT THRESHOLD EXCEEDED?
	BHIS	20$		;IF HIS YES
10$:	TST	R4		;SCB PRESENT? (C=0)
	BEQ	15$		;IF EQ NO
	CLR	S.BMSV(R4)	;MARK THAT WE DO NOT YET HAVE A PACKET
1      5$:	RETURN			;
20$:	SEC			;TOO BAD
	RETURN			;

;+
; **-$CRPKT-CREATE ERROR LOG PACKET
;
; THIS ROUTINE IS CALLED TO CREATE AN ERROR LOG PACKET, EITHER FROM THE
; SEND MESSAGE DIRECTIVE PROCESSING, OR WITHIN THE EXECUTIVE AS PART OF
; THE PROCESSING OF A MEMORY ERROR, NONSENSE INTERRUPT, TIME CHANGE,
; POWER FAIL RECOVERY, OR DEVICE ERROR.
;
; INPUTS:
;
;	R0=PACKET CODE
;	R1=LENGTH OF DATA SUBPACKET
;	R2=CONTROL MASK WORD
;	R3=BEGINNING ADDRESS OF DATA FOR DATA SUBPACKET
;	R4=TCB ADDRESS (      FOR TASK SUBPACKET)
;	R5=UCB ADDRESS (FOR DEVICE IDENTIFICATION SUBPACKET)
;
; OUTPUTS:
;
;	R0=UNCHANGED
;	R1=BEGINNING ADDRESS OF DATA SUBPACKET DATA
;	R2=UNCHANGED
;	R3=BEGINNING ADDRESS OF PACKET
;	R4=UNCHANGED
;	R5=UNCHANGED
;
;	C=0 IF A PACKET WAS CREATED
;	C=1 IF A PACKET WAS NOT CREATED
;
; OUTPUT PACKET FORMAT:
;
;	+-----------------------------------------------+
;	| RESERVED FOR PACKET LINK WORD			|
;	+-----------------------------------------------+
;	| PACKET LENGTH (LENGTH O      F REMAINDER OF PACKET)	|
;	+-----------------------------------------------+
;	| HEADER SUBPACKET				|
;	.						.
;
;	|						|
;	+-----------------------------------------------+
;	| OTHER SUBPACKETS				|
;	.						.
;
;	|						|
;	+-----------------------------------------------+
;-

$CRPKT::MOV	R5,-(SP)	;SAVE ALL REGISTERS
	MOV	R4,-(SP)	;...
	MOV	R3,-(SP)	;...
	MOV	R2,-(SP)	;...
	MOV	R1,-(SP)	;...
	MOV	R0,-(SP)	;...

;
; CHECK FOR A HEADER SUBPACKET.  BECAUSE THERE WILL ALWAYS BE A HE      ADER
; SUBPACKET, THERE IS NO NEED TO ACTUALLY CHECK FOR WHETHER OR NOT A
; HEADER SUBPACKET HAS BEEN REQUESTED.  NOTE THAT THE ACCUMULATED TOTAL
; LENGTH IS INITIALIZED BY JAMMING IT WITH THE LENGTH OF A HEADER
; SUBPACKET.  THIS SAVES CODE OVER PERFORMING A SEPARATE INITIALIZATION
; SINCE THE HEADER SUBPACKET IS ALWAYS PRESENT.
;
; AN EXTRA FOUR BYTES IS ADDED TO THE LENGTH OF THE HEADER SUBPACKET TO
; ACCOUNT FOR THE PRECEEDING LINK WORD AND PACKET LENGTH.
;

	ROR	R2		;CHECK FOR A HEADER SUBPA      CKET
	BCS	5$		;IF CS IT'S THERE
	CRASH			;CRASH -- SOMEONE GOOFED!!
5$:	MOV	#E$HLEN+4,R1	;ADD IN THE LENGTH OF THE SUBPACKET
	ROR	R2		;CHECK FOR A TASK SUBPACKET
	BCC	10$		;IF CC NO TASK SUBPACKET
	ADD	#E$TLEN,R1	;ADD IN THE SUBPACKET LENGTH
10$:	ROR	R2		;CHECK FOR A DEVICE ID SUBPACKET
	BCC	20$		;IF CC NO DEVICE ID SUBPACKET
	ADD	#E$ILEN,R1	;ADD IN THE SUBPACKET LENGTH
20$:	ROR	R2		;CHECK FOR A DEVICE OP. SUBPACKET
	BCC	30$		;IF CC NO DEVICE OP SUBPACKET
	ADD	#E$OLEN,R1	;ADD IN THE SUBPACKET LE      NGTH

;
; CHECK FOR A DEVICE ACTIVITY SUBPACKET
;
; IF THERE IS A DEVICE ACTIVITY SUBPACKET, THERE WILL BE ONE ENTRY IN
; THE SUBPACKET FOR EACH ACTIVE DEVICE (LESS ONE IF THERE IS ALSO A
; DEVICE OPERATION SUBPACKET) PLUS THE PREFIX HEADER LENGTH WORD.
;

30$:	ROR	R2		;CHECK FOR A DEVICE ACTIVITY SUBPACKET


	.IF DF	E$$ACT

	BCC	60$		;IF CC NO DEVICE ACTIVITY SUBPACKET
	BIT	#SM.DOP,4(SP)	;IS THERE A DEVICE OPERATION SUBPACKET?
	BNE	35$		;IF NE YES
	CLR	R5		;CLEAR FOR NO UCB
35$:	MOV	R5,R      0		;SAVE FOR COMPARISON
	MOV	R2,-(SP)	;SAVE THE MASK FOR FUTURE USE
	MOV	#$SCDVT,-(SP)	;SETUP FOR COROUTINE CALL
40$:	CALL	@(SP)+		;GET THE NEXT UCB
	BCS	50$		;IF CS NO MORE ENTRIES
	BIT	#DV.MSD,U.CW1(R5)  ;IS IT A MASS STORAGE DEVICE?
	BNE	45$		;IF NE NO
	MOV	#1,S$$SPC(SP)	;MARK THAT WE ARE NOT INTERESTED IN THIS DCB
	BR	40$		;GO TRY AGAIN
45$:	TSTB	S.STS(R4)	;CHECK TO SEE IF THE SCB HAS I/O ACTIVE
	BEQ	40$		;IF EQ NO, IGNORE IT
	MOV	S.PKT(R4),R3	;GET THE I/O PACKET ADDRESS
	CMP	I.UCB(R3),R5	;I      S THE I/O QUEUED TO THIS UCB?
	BNE	40$		;IF NE NO, IGNORE IT
	CMP	R5,R0		;IS THIS OUR UCB?
	BEQ	40$		;IF EQ YES, DON'T COUNT IT
	ADD	#E$ALEN,R1	;COUNT THE I/O.
	BR	40$		;LOOP
50$:	ADD	#2,R1		;ADD IN THE LENGTH OF THE PREFIX
	MOV	(SP)+,R2	;RESTORE THE MASK

	.ENDC


;
; CHECK FOR A DATA SUBPACKET
;

60$:	ROR	R2		;CHECK FOR A DATA SUBPACKET
	BCC	70$		;IF CC NO DATA SUBPACKET
	ADD	2(SP),R1	;ADD IN THE LENGTH OF THE SUBPACKET
	ADD	#2,R1		;AND ADD IN THE PREFIX LENGTH WORD

;
; ALLOCATE THE       PACKET
;

70$:	CMP	#512.,R1	;IS THE PACKET A REASONABLE LENGTH?
	BLO	75$		;IF LO NO
	CALL	$ALOCB		;ALLOCATE THE CORE BLOCK
	BCC	80$		;IF CC OK
75$:	CALLR	PKTXIT		;FAILURE, RESTORE REGISTERS AND EXIT
80$:	MOV	R0,-(SP)	;SAVE THE ADDRESS FOR FUTURE USE
	MOV	14(SP),R5	;RETRIEVE POSSIBLE UCB ADDRESS

;
; CREATE THE PACKET
;
; AT THIS POINT:
;
;	R0=ADDRESS OF ALLOCATED BLOCK
;	R1=LENGTH OF ALLOCATED BLOCK
;	R2=UNDEFINED
;	R3=UNDEFINED
;	R4=UNDEFINED
;	R5=UCB ADDRESS
;

CREPKT:	CLR	(R0)+		      ;SETUP THE LINK WORD
	SUB	#4,R1		;THE DATA LENGTH IS LESS THE HEADER
	MOV	R1,(R0)+	;PUT IN THE PACKET LENGTH
	MOV	#E$HLEN,(R0)+	;PUT IN THE SUBPACKET LENGTH
	MOV	6(SP),R2	;GET THE SAVED CONTROL MASK WORD
	MOV	R2,(R0)+	;INSERT IT INTO THE SUBPACKET
	MOV	#1+<EH$FOR*400>,(R0)+  ;INSERT RSX-11M CODE
	MOV	$SYSID,(R0)+	;PUT IN THE FOUR BYTES OF OPERATING
	MOV	$SYSID+2,(R0)+	; SYSTEM IDENTIFICATION


	.IF DF	M$$MGE&M$$EXT

	MOV	#EH$NOR!<<EH$COU!EH$VIR!EH$EXT>*400>,(R0)+  ;SET FLAGS

	.IFF

	.IF DF      	M$$MGE

	MOV	#EH$NOR!<<EH$COU!EH$VIR>*400>,(R0)+  ;SET FLAGS

	.IFF

	MOV	#EH$NOR!<EH$COU*400>,(R0)+  ;INSERT FLAGS

	.ENDC

	.ENDC


	INC	$ENTSQ		;COUNT THE NEXT ENTRY
	MOV	$ENTSQ,(R0)+	;WRITE IT
	MOV	$ERRSQ,(R0)+	;PUT IN THE ERROR SEQUENCE COUNT
	MOV	2(SP),(R0)+	;PUT IN THE ENTRY TYPE CODE AND SUBCODE
	MOV	#$TTNS-<6*2>,R3	;GET THE POINTER TO THE SYSTEM TIME
	MOV	#6,R1		;GET THE NUMBER OF PARAMETERS TO INSERT
10$:	MOVB	(R3)+,(R0)+	;INSERT THE ITEM IN THE TIME STAMP
	TSTB	(R3)+		;MOVE T      O NEXT ITEM
	SOB	R1,10$		;LOOP UNTIL DONE.
	MOVB	$PRMOD,(R0)+	;PUT IN THE PROCESSOR INFORMATION
	CLRB	(R0)+		;CLEAR THE RESERVED BYTE
	MOV	#1,(R0)+	;SETUP THE URM AS CPA
	ROR	R2		;DISCARD THE FLAG FOR THE HEADER

;
; CREATE THE TASK SUBPACKET
;
;
; AT THIS POINT:
;
;	R0=POINTER TO NEXT FREE ENTRY IN ALLOCATED BLOCK
;	R1=UNDEFIED
;	R2=CONTROL MASK WORD, SHIFTED RIGHT 1
;	R3=UNDEFINED
;	R4=UNDEFINED
;	R5=UCB ADDRESS
;

CRETSK:	ROR	R2		;CHECK THE FLAG FOR TASK SUBPACKET
	BCC	CREDID		;IF C      C NO TASK SUBPACKET
	MOV	#E$TLEN,(R0)+	;PUT IN THE SUBPACKET LENGTH
	MOV	12(SP),R1	;GET THE SAVED TCB ADDRESS
	CALL	CRTASP		;CREATE THE TASK SUBPACKET

;
; CREATE THE DEVICE IDENTIFICATION SUBPACKET
;
; AT THIS POINT:
;
;	R0=POINTER TO NEXT FREE ENTRY IN ALLOCATED BLOCK
;	R1=UNDEFINED
;	R2=CONTROL MASK WORD, SHIFTED RIGHT 2
;	R3=UNDEFINED
;	R4=UNDEFINED
;	R5=UCB ADDRESS
;

CREDID:	ROR	R2		;IS THERE A DEVICE ID SUBPACKET?
	BCC	CREDOP		;IF CC NO
	MOV	U.SCB(R5),R4	;RETRIEVE SCB ADDRESS
	MO      V	#E$ILEN,(R0)+	;INSERT THE LENGTH OF THE SUBPACKET
	CALL	CRDEVP		;CREATE DEVICE INFORMATION
	BIT	#DV.DIR,U.CW1(R5) ;IS THIS A DIRECTORY DEVICE?
	BEQ	5$		;IF EQ NO, DON'T INTERPRET VCB
	MOV	U.VCB(R5),R3	;GET A POINTER TO THE VCB
	BNE	15$		;IF NE VCB EXISTS
	ASSUME	V.PKSR,V.LABL+12.
5$:	MOV	#<E$IDEV-E$IVOL>/2,R3  ;GET THE NUMBER OF WORDS TO CLEAR
10$:	CLR	(R0)+		;CLEAR OUT THE VOLUME NAME AND PACK ID.
	SOB	R3,10$		;LOOP UNTIL DONE CLEARING
	BR	30$		;DONE WITH THE VOLUME INFORMATION
15$:	ADD	#V.LAB      L,R3	;POINT AT THE LABEL
	MOV	#<E$IDEV-E$IVOL>/2,R1 ;GET THE NUMBER OF WORDS TO MOVE
20$:	MOV	(R3)+,(R0)+	;TRANSFER VOLUME NAME AND PACK ID.
	SOB	R1,20$		;LOOP UNTIL DONE
	BIT	#DV.SQD,U.CW1(R5)  ;IS THIS A DISK?
	BEQ	30$		;IF EQ YES
	CMP	-(R0),-(R0)	;NO, BACKUP TO PACK SERIAL NUMBER
	CLR	(R0)+		;CLEAR THE PACK SERIAL NUMBER
	CLR	(R0)+		;...
30$:	MOV	#1,(R0)+	;ALL DEVICES ARE OF TYPE 1
	MOV	U.CW3(R5),(R0)+	;GET LOW ORDER BLOCKS IN DEVICE
	MOVB	U.CW2(R5),(R0)+	;GET HIGH ORDER BLOCKS IN DEVICE
	CLR      B	(R0)+		;
	MOV	U.IOC(R5),(R0)+	;INSERT THE I/O COUNT LOW ORDER
	MOV	U.IOC+2(R5),(R0)+  ;INSERT THE I/O COUNT HIGH ORDER
	MOV	U.ERSC(R5),(R0)+;INSERT THE SOFT AND HARD COUNTS
	BIT	#SM.ZER,6(SP)	;ZERO THE COUNTS?
	BEQ	CREDOP		;IF EQ NO


	.IF DF	M$$MUP

	TST	-(R5)		;IGNORE U.OWN

	.ENDC


	CLR	-(R5)		;CLEAR THE HARD AND SOFT COUNTS
	TST	-(R5)		;DON'T TOUCH THE LIMITS
	CLR	-(R5)		;CLEAR THE HIGH ORDER I/O COUNT
	CLR	-(R5)		;CLEAR THE LOW ORDER I/O COUNT


	.IF DF	M$$MUP

	ADD	#2*5.,R5	;      POINT BACK TO THE UCB ITSELF

	.IFF

	ADD	#2*4,R5		;POINT BACK TO THE UCB ITSELF

	.ENDC


;
; CREATE THE DEVICE OPERATION SUBPACKET
;
; AT THIS POINT:
;
;	R0=POINTER TO NEXT FREE ENTRY IN ALLOCATED BLOCK
;	R1=UNDEFINED
;	R2=CONTROL MASK WORD, SHIFTED RIGHT 3
;	R3=UNDEFINED
;	R4=UNDEFINED
;	R5=UCB ADDRESS
;
CREDOP:	ROR	R2		;CHECK FOR PRESENCE OF SUBPACKET
	BCC	CREIOA		;IF CC NO SUCH SUBPACKET
	MOV	#E$OLEN,(R0)+	;INSERT THE SUBPACKET LENGTH
	MOV	U.SCB(R5),R4	;RETRIEVE SCB ADDRESS
	MO      V	S.PKT(R4),R1	;GET THE I/O PACKET POINTER
	MOV	I.TCB(R1),R1	;GET THE TCB POINTER
	CALL	CRTASP		;INSERT THE TASK INFORMATION
	CALL	CRIOPP		;INSERT THE I/O PACKET INFORMATION
	CLR	(R0)+		;NO CURRENT RETRY COUNT

;
; I/O ACTIVITY SUBPACKET
;
; AT THIS POINT:
;
;	R0=POINTER TO NEXT FREE ENTRY IN ALLOCATED BLOCK
;	R1=UNDEFINED
;	R2=CONTROL MASK WORD, SHIFTED RIGHT 4
;	R3=UNDEFINED
;	R4=UNDEFINED
;	R5=UCB ADDRESS
;

CREIOA:	ROR	R2		;CHECK FOR AN I/O ACTIVITY SUBPACKET


	.IF DF	E$$ACT

	B      CC	CREDAT		;IF CC NO I/O ACTIVITY SUBPACKET

;
; THE LENGTH OF THE I/O ACTIVITY SUBPACKET WILL BE COMPUTED WHEN THE
; ENTIRE SUBPACKET HAS BEEN CREATED.  SAVE THE BEGINNING ADDRESS OF
; THE SUBPACKET FOR FUTURE USE.
;

	MOV	R0,-(SP)	;SAVE THE BEGINNING SUBPACKET ADDRESS
	CLR	(R0)+		;GET RID OF ANYTHING IN THE LENGTH WORD
	MOV	R5,R2		;SAVE UCB ADDRESS FOR REFERENCE
	MOV	#$SCDVT,-(SP)	;SETUP FOR THE COROUTINE CALL
10$:	CALL	@(SP)+		;GET THE NEXT DEVICE
	BCS	30$		;IF CS ALL DONE
	BIT	#DV.MSD,U.CW      1(R5) ;IS IT A MASS STORAGE DEVICE?
	BNE	20$		;IF NE YES, PROCESS IT
	MOV	#1,S$$SPC(SP)	;MARK TO SKIP THIS SCB
	BR	10$		;LOOP UNTIL DONE
20$:	CMP	R5,R2		;IS THIS UCB US?
	BEQ	10$		;IF EQ IGNORE IT
	TSTB	S.STS(R4)	;CHECK FOR THE SCB ACTIVE
	BEQ	10$		;IF EQ DEVICE IS NOT ACTIVE
	MOV	S.PKT(R4),R3	;GET A COPY OF THE I/O PACKET ADDRESS
	CMP	I.UCB(R3),R5	;IS THE I/O QUEUED TO THIS UCB?
	BNE	10$		;IF NE NO
	CALL	CRDEVP		;CREATE THE DEVICE INFORMATION
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOV	I.TC      B(R1),R1	;GET ACTIVE TCB ADDRESS
	CALL	CRTASP		;CREATE THE TASK INFORMATION
	TST	-(R0)		;POINT BACK TO THE TI: UNIT NUMBER
	MOVB	(R0),E$ATIU-E$AFNC(R0) ;INSERT THE TI: UNIT NUMBER
	CALL	CRIOPP		;CREATE THE I/O PACKET INFORMATION
	BR	10$		;LOOP UNTIL DONE
30$:	MOV	R0,R2		;GET A COPY OF THE CURRENT PACKET ADDRESS
	SUB	(SP),R2		;COMPUTE THE SUBPACKET LENGTH
	MOV	R2,@(SP)+	;INSERT THE LENGTH IN THE SUBPACKET PREFIX

	.ENDC


;
; CREATE THE DATA SUBPACKET
;
; AT THIS POINT:
;
;	R0=POINTER TO NE      XT FREE ENTRY IN ALLOCATED BLOCK
; ALL AOTHER REGISTERS ARE UNDEFINED
;

CREDAT:	BIT	#SM.DAT,6(SP)	;DO WE HAVE A DATA SUBPACKET?
	BEQ	20$		;IF EQ NO
	MOV	4(SP),R3	;GET THE DATA SUBPACKET LENGTH
	MOV	R3,(R0)		;PUT IN THE LENGTH OF THE DATA ITSELF
	ADD	#2,(R0)+	;ADD IN THE SUBPACKET HEADER LENGTH
	ASR	R3		;CONVERT # OF BYTES TO # OF WORDS
	MOV	R0,R1		;COPY SUBPACKET DATA ADDRESS
	MOV	10(SP),R2	;GET THE DATA ADDRESS
	BEQ	20$		;DON'T MOVE THE DATA IN
10$:	MOV	(R2)+,(R0)+	;MOVE IN A DATA ITEM
	SOB	      R3,10$		;LOOP UNTIL DONE
20$:	CLC			;PACKET COULD BE CREATED
	MOV	(SP)+,R3	;RESTORE THE PACKET ADDRESS
;
; CLEAN STACK WHILE PRESERVING CARRY BIT
;
PKTXIT:	MOV	(SP)+,R0	;RESTORE THE ENTRY CODE
	MOV	(SP)+,R2	;DISCARD THE DATA SUBPACKET LENGTH
	MOV	(SP)+,R2	;RESTORE THE CONTROL MASK WORD
	MOV	(SP)+,R4	;DISCARD THE DATA ADDRESS
	MOV	(SP)+,R4	;RESTORE THE TCB ADDRESS
	MOV	(SP)+,R5	;RESTORE THE UCB ADDRESS
	RETURN			;DONE

;+
; **-CRTASP-CREATE TASK INFORMATION
;
;	CREATES THE FOLLOWING INFORMAT      ION IN THE CURRENT SUBPACKET:
;
;	+-----------------------------------------------+
;	| TASK NAME IN RAD50				|
;	|						|
;	+-----------------------------------------------+
;	| TASK UIC					|
;	+-----------------------------------------------+
;	| TASK TI: DEVICE NAME				|
;	+-----------------------+-----------------------+
;	| FLAGS			| TASK TI: UNIT NUMBER	|
;	+-----------------------+-----------------------+
;
;	FLAGS:
;
;		ET$PRV	TASK IS PRIVILEGED
;		ET$PRI	TERMINAL IS PRIVILEGED
;
      ; INPUTS:
;
;	R0=POINTER TO SUBPACKET FOR INSERTION
;	R1=POINTER TO TASK TCB
;
; OUTPUTS:
;
;	R0=UPDATED
;	R1 AND R3 ARE DESTROYED
;	R4 AND R5 ARE PRESERVED
;-

CRTASP:	SAVNR			;SAVE R4 AND R5
	MOV	T.NAM(R1),(R0)+	;PUT IN THE TASK NAME
	MOV	T.NAM+2(R1),(R0)+  ;...
	MOV	T.PCB(R1),R4	;GET A POINTER TO THE PCB
	MOV	P.HDR(R4),R4	;GET A POINTER TO THE HEADER
	MOV	H.CUIC(R4),(R0)+;INSERT THE UIC
	MOV	T.UCB(R1),R5	;GET THE TI: UCB POINTER
10$:	MOV	U.RED(R5),R5	;FOLLOW THE REDIRECT POINTER
	CMP	      R5,U.RED(R5)	;IS THE DEVICE REDIRECTED?
	BNE	10$		;IF NE YES
	MOV	(R5),R3		;GET THE TI: DCB POINTER
	MOV	D.NAM(R3),(R0)+	;INSERT THE DEVICE NAME
	CLR	(R0)		;INITIALIZE THE FLAG AND UNIT # WORD
	BIT	#U2.PRV,U.CW2(R5)  ;IS THE TI: PRIVILEGED?
	BEQ	20$		;IF EQ NO
	BIS	#ET$PRI*400,(R0); MARK THE TI: PRIVILEGED
20$:	BIT	#T3.PRV,T.ST3(R1)  ;IS THE TASK PRIVILEGED?
	BEQ	25$		;IF EQ NO
	BIS	#ET$PRV*400,(R0);MARK THE TASK PRIVILEGED
25$:	MOVB	D.UNIT(R3),(R0)	;GET THE STARTING UNIT # FOR THIS DCB
	SUB	D.U      CB(R3),R5	;FORM OFFSET TO THIS UCB
	BEQ	40$		;IF EQ THIS IS THE FIRST ONE
30$:	INC	(R0)		;COUNT ONE MORE UNIT NUMBER
	SUB	D.UCBL(R3),R5	;GET THE LENGTH OF A UCB
	BNE	30$		;IF NE LOOP UNTIL WE GET THE RIGHT ONE
40$:	TST	(R0)+		;POINT PAST THE FLAG ENTRY
	RETURN			;DONE

;+
; **-CRDEVP-CREATE DEVICE INFORMATION
;
;	CREATES THE FOLLOWING INFORMATION IN THE CURRENT SUBPACKET:
;
;	+-----------------------------------------------+
;	| LOGICAL DEVICE NAME MNEMONIC			|
;	+-----------------------+----      -------------------+
;	| CONTROLLER NUMBER	| DEVICE UNIT NUMBER	|
;	+-----------------------+-----------------------+
;	| PHYSICAL SUBUNIT #	| PHYSICAL UNIT #	|
;	+-----------------------+-----------------------+
;	| RESERVED		| FLAGS			|
;	+-----------------------+-----------------------+
;
; INPUTS:
;
;	R0=POINTER TO DATA AREA
;	R4=SCB ADDRESS
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	R0=UPDATED
;	R1 AND R3 ARE DESTROYED
;	R4 AND R5 ARE PRESERVED
;-

CRDEVP:	CLR	-(SP)		;CLEAR FLAG WORD
	MOV	      (R5),R3		;GET A POINTER TO OUR DCB
	MOV	D.NAM(R3),(R0)+	;PUT IN THE LOGICAL DEVICE MNEMONIC
	MOVB	D.UNIT(R3),(R0)	;SETUP THE FIRST UNIT COVERED
	MOV	R5,R1		;COPY UCB ADDRESS
	SUB	D.UCB(R3),R1	;GET THE LENGTH OF THE UCB'S
	BEQ	20$		;IF EQ NO MORE UCB'S TO COUNT
10$:	INC	(R0)		;COUNT ANOTHER UCB
	SUB	D.UCBL(R3),R1	;ACCOUNT FOR THE LENGTH
	BNE	10$		;IF NE LOOP
20$:	TSTB	(R0)+		;POINT TO THE CONTROLLER NUMBER
	MOVB	S.CON(R4),(R0)	;GET THE CONTROLLER INDEX
	ASRB	(R0)+		;AND MAKE IT A CONTROLLER NUMBER      
	MOVB	U.UNIT(R5),(R0)+;GET THE PHYSICAL UNIT NUMBER
	CLRB	(R0)+		;CLEAR THE SUBUNIT NUMBER
	CMP	D.NAM(R3),#"MM	;MM MAGTAPE?
	BEQ	30$		;IF EQ YES
	CMP	D.NAM(R3),#"MF	;MF MAGTAPE?
	BNE	40$		;IF NE NO
30$:	MOVB	U.UNIT(R5),-(R0);SET SUBUNIT NUMBER
	MOVB	U.VCB+2(R5),-(R0)  ;SET FORMATTER NUMBER
	BIS	#EI$SUB,(SP)	;FLAG AS A SUBCONTROLLER DEVICE
	TST	(R0)+		;POINT TO FLAG WORD
40$:	MOV	(SP)+,(R0)+	;SET FLAG WORD
	RETURN

;+
; **-CRIOPP-INSERT I/O PACKET PARAMETERS
;
;	INSERTS THE FOLLOWING I/O PA      CKET PARAMETERS:
;
;	+-----------------------------------------------+
;	| I/O FUNCTION CODE				|
;	+-----------------------+-----------------------+
;	| RESERVED		| FLAGS			|
;	+-----------------------+-----------------------+
;	| TRANSFER OPERATION ADDRESS			|
;	|						|
;	+-----------------------------------------------+
;	| TRANSFER OPERATION BYTE COUNT			|
;	+-----------------------------------------------+
;
; INPUTS:
;
;	R0=POINTER TO SUBPACKET DATA
;	R4=SCB ADDRESS
;	R5=UCB ADDRESS      
;
; OUTPUTS:
;
;	R0=UPDATED
;	R1 AND R3 ARE DESTROYED
;	R4 AND R5 ARE PRESERVED
;-

CRIOPP:	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOV	I.FCN(R1),R3	;GET FUNCTION CODE
	MOV	R3,(R0)+	;INSERT IT	
	CLR	(R0)		;SETUP FOR THE FLAGS

;
; OBTAIN A MASK BIT FOR THE I/O FUNCTION CODE
;

	MOV	(R5),R1		;GET THE DCB POINTER
	ADD	#D.MSK+2,R1	;AND POINT TO THE FUNCTION MASK
	CLRB	R3		;CLR MODIFIER FLAGS
	SWAB	R3		;PUT FUNCTION CODE IN LOW BYTE
	CMP	R3,#15.		;IS THE FUNCTION IN THE SECOND MASKS?
	B      LOS	10$		;IF LOS FUNCTION IN FIRST MASK
	SUB	#16.,R3		;FIX THE FUNCTION CODE
	ADD	#8.,R1		;POINT TO THE SECOND SET
10$:	ASL	R3		;MAKE FUNCTION CODE A WORD INDEX
	MOV	$BTMSK(R3),R3	;GET BIT THAT CORRESPONDS TO FUNCTION CODE

;
; SEE IF THE FUNCTION IS OTHER THAN A TRANSFER FUNCTION
;

	BIT	R3,(R1)+	;IS IT A CONTROL FUNCTION?
	BNE	20$		;IF NE IT IS
	BIT	R3,(R1)+	;IS IT A NOOPED FUNCTION?
	BNE	20$		;IF NE IT IS
	BIT	R3,(R1)+	;IS IT AN ACP FUNCTION?
	BNE	20$		;IF NE IT IS
	BIS	#EO$TRA,(R0)	;TRAN      SFER FUNCTION

;
; INSERT THE OTHER FLAGS
;

20$:	BITB	#UC.NPR,U.CTL(R5) ;IS IT A DMA DEVICE?
	BEQ	30$		;IF EQ NO
	BIS	#EO$DMA,(R0)	;DMA DEVICE


	.IF DF	M$$EXT

	BIT	#DV.MBC!DV.EXT,U.CW1(R5)  ;IS IT A 22-BIT DEVICE?
	BEQ	30$		;IF EQ NO
	BIS	#EO$EXT,(R0)	;SET 22-BIT DEVICE

	.IFTF

30$:	MOV	(R0)+,R3	;GET FLAG WORD

	.IFT

	BIT	#EO$EXT,R3	;22-BIT DEVICE?
	BNE	80$		;IF NE YES
	BIT	#EO$DMA,R3	;DMA DEVICE?
	BEQ	90$		;IF EQ NO

;
; INSERT THE TRANSFER OPERATION ADDRESS AND LENGTH
;      

	MOV	R4,R3		;COPY SCB ADDRESS
	ADD	#<S.MPR+M.LGTH>,R3  ;POINT PAST PHYSICAL ADDRESS
	MOV	-(R3),2(R0)	;INSERT LOW BITS OF ADDRESS
	MOVB	-(R3),(R0)+	;INSERT HIGH BITS OF ADDRESS
	CLRB	(R0)+		;FORGET ANY GARBAGE
	TST	(R0)+		;POINT PAST LOW BITS
	BR	100$		;
80$:	MOVB	U.BUF+1(R5),(R0);ASSUME HIGH BITS ARE IN UCB
	MOV	(R5),R1		;GET DCB ADDRESS
	CMP	D.NAM(R1),#"DL	;IS THIS THE RLV12?
	BNE	85$		;IF NE NO
	MOV	S.PKT(R4),R1	;RETRIEVE I/O PACKET ADDRESS
	MOV	I.PRM+6(R1),(R0);GET HIGH BITS OF ADDRESS
85      $:	BIC	#^C<377>,(R0)+	;CLEAR GARBAGE
	BR	95$		;

	.ENDC


90$:	MOV	U.BUF(R5),(R0)+	;MOVE IN THE RELOCATION BIAS
95$:	MOV	U.BUF+2(R5),(R0)+  ;MOVE IN THE BUFFER ADDRESS
100$:	MOV	U.CNT(R5),(R0)+	;MOVE IN THE BYTE COUNT
	RETURN

;+
; **-$QUPKT-QUEUE ERROR LOG PACKET
;
; THIS ROUTINE IS CALLED TO QUEUE AN ERROR LOG PACKET.  IF THERE IS NO
; OTHER PACKET IN THE QUEUE, THE ERROR LOGGER IS REQUESTED WITH A DELAY.
; IF THERE IS ANOTHER PACKET ALREADY IN THE QUEUE, THE ERROR LOGGER IS
; REQUESTED I      MMEDIATLY.
;
; INPUTS:
;
;	R3=POINTER TO PACKET FOR INSERTION IN QUEUE
;
; OUTPUTS:
;
;	R0, R1, R2 AND R3 ARE UPDATED
;-

$QUPKT::SAVNR			;SAVE R5 AND R4
	MOV	R3,R1		;COPY THE POINTER TO THE PACKET
	MOV	$ERRPT,R5	;SAVE FOR USE WHEN REQUESTING THE TASK
	BEQ	40$		;IF EQ NO ERROR LOG TASK
	MOV	#$ERHEA,R0	;GET A POINTER TO THE QUEUE LIST HEAD
	CALL	$QINSF		;INSERT THE ENTRY FIFO IN THE QUEUE
	CMP	(R0)+,(R0)	;WAS LIST EMPTY?
	BNE	20$		;IF NE NO, REQUEST ERRLOG
	BIT	#SM.CMD,4+E$HSBF(R1)  ;IS TH      IS A COMMAND PACKET?
	BNE	20$		;IF NE YES

;
; THERE IS NO OTHER PACKET IN THE QUEUE, SO MAKE UP A DEFERRED REQUEST
;

	MOV	#C.LGTH,R1	;SIZE OF A CLOCK QUEUE ENTRY
	CALL	$ALOCB		;ALLOCATE THE CORE BLOCK
	BCS	20$		;IF CS FAILURE, TRY IMMEDIATE REQUEST
	CLR	C.UIC(R0)	;INDICATE DEFAULT UIC
	CLR	R1		;HIGH TIME = 0
	MOV	#<H$$RTZ*2>,R2	;LOW TIME = 2 SECONDS
	MOV	#C.SSHT,R4	;SINGLE SHOT TASK REQUEST
	CALLR	$CLINS		;INSERT THE ENTRY IN THE QUEUE

;
; THERE IS ANOTHER PACKET IN THE QUEUE, SO IMMEDIA      TLY REQUEST
;

20$:	MOV	R5,R0		;COPY THE ERROR LOG TCB
	TST	T.STAT(R0)	;IS IT ALREADY RUNNING?
	BPL	30$		;IF PL YES, DON'T REQUEST IT
	CLR	R1		;INDICATE DEFAULT UIC
	CALLR	$TSKRT		;REQUEST THE TASK

;
; THE ERROR LOG TASK IS ALREADY RUNNING, SO DISMISS THE REQUEST
;

30$:	RETURN			;EXIT

;
; THE ERROR LOG TASK HAS BEEN REMOVED.  DISCARD THE QUEUED ENTRY
;

40$:	MOV	R1,R0		;COPY THE ERROR LOG PACKET POINTER
	MOV	2(R0),R1	;GET THE SIZE OF THE PACKET
	ADD	#4,R1		;ACCOUNT FOR THE LINK WORD       AND LENGTH
	CALLR	$DEACB		;DEALLOCATE THE SPACE

;+
; **-$QERMV-REMOVE ENTRY FROM ERROR LOG QUEUE
;
; THIS ROUTINE REMOVES AN ENTRY FROM THE ERROR LOG QUEUE AND TRANSFERS
; IT INTO A USER BUFFER.
;
; INPUTS:
;
;	R4=LENGTH OF USER BUFFER
;	R5=ADDRESS OF USER BUFFER
;
; OUTPUTS:
;
;	R1=LENGTH OF PACKET
;	R4=UNCHANGED
;	R5=UNCHANGED
;
;	C=0 PACKET WAS REMOVED SUCCESSFULLY
;	C=1 NO PACKET TO REMOVE OR PACKET TOO LONG.  IF R1<>0 THE
;	    PACKET WAS TOO LONG, AND R1 CONTAINS THE PACKET LENG      TH.
;-
$QERMV::CLR	R1		;SAY THE PACKET HAS A LENGTH OF ZERO
	MOV	#$ERHEA,R0	;GET THE QUEUE POINTER
	CALL	$QRMVF		;REMOVE THE PACKET FROM THE QUEUE
	BCS	30$		;IF CS NO SUCH PACKET
	MOV	R5,R3		;SAVE A COPY OF THE USER BUFFER ADDRESS
	MOV	R1,R0		;COPY THE CORE BLOCK ADDRESS
	TST	(R1)+		;IGNORE THE LINK WORD
	MOV	(R1)+,R2	;GET THE LENGTH OF THE PACKET
	CMP	R2,R4		;IS THE PACKET TOO LONG?
	BHI	20$		;IF HI PACKET IS TOO LONG.
	ASR	R2		;CONVERT THE NUMBER OF BYTES TO WORDS
10$:	MOV	(R1)+,(R3)+	;MOVE T      HE DATA ITEM
	SOB	R2,10$		;LOOP UNTIL DONE
20$:	MOV	2(R0),R1	;GET A COPY OF THE PACKET LENGTH
	MOV	R3,-(SP)	;SAVE THE END USER BLOCK POINTER
	MOV	R1,-(SP)	;SAVE THE PACKET LENGTH
	ADD	#4,R1		;ADD IN THE LINK AND LENGTH WORD
	CALL	$DEACB		;AND DEALLOCATE THE BLOCK
	MOV	(SP)+,R1	;RESTORE THE PACKET LENGTH
	DEC	(SP)		;ADJUST SO THAT IF:
				; (SP)>R5 WE TRANSFERRED DATA
				; (SP)<R5 WE DID NOT TRANSFER DATA
	CMP	(SP)+,R5	;DID WE TRANSFER ANYTHING?
				; THE C BIT IS SET IF (SP) LO R5, WHICH
				;   ”   INDICATES WE DID NOT TRANSFER DATA.
30$:	RETURN			;DONE

	.IFF

;+
; THE FOLLOWING TWO ENTRY POINTS ARE NEEDED IF ERROR LOGGING IS NOT
; IN THE SYSTEM.
;
; **-$CRPKT-CREATE ERROR LOG PACKET
; **-$QUPKT-QUEUE ERROR LOG PACKET
;
; INPUTS:
;	NONE
;
; OUTPUTS:
;	C=1 FOR $CRPKT
;	NONE FOR $QUPKT
;-

$CRPKT::SEC			;SHOW NO PACKET CREATED
$QUPKT::RETURN			;BYE-BYE

	.ENDC


	.END
”         T–ðskQ	› c,        	.TITLE	XBDRV
	.IDENT	/04.6/
 
;
; COPYRIGHT (C) 1974, 1978, 1979, 1980
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 04.6
;
; EARL D. WALDIN 21-NOV-75
;
; PREVIOUSLY MODIFIED BY:
;
;	L. GILLESPIE
;	E. D. WALDIN
;
; MODIFIED BY:
;
; EB083 - MODIFIED 18-SEP-77 TO CORRECT BRANCH OUT OF RANGE FOR
;	MULTICONTROLLER DRIVER
;
; B. SCHREIBER	30-JUN-78
      ;
;	BLS056 -- CORRECT UMR ALLOCATION HANDLING
;
; B. SCHREIBER	15-OCT-78
;
;	BLS069 -- CORRECT ERROR WHEN TRANSMITTING OR RECEIVING
;		AND BUFFER FALLS EXACTLY ON BOUNDARY.
;
;	R. E. CALDWELL	29-OCT-79
;
;		RC024 -- REMOVE UNNEEDED CONDITIONALIZATION.
;
;	T. M. MARTIN	02-MAY-80
;
;		TM001 -- FIX UP UMR DEALLOCATION
;
;	IVAN ZATKOVICH	8-JUL-81
;
;		IZ011 -- ALLOW TRANSFERS > 4K ON 22 BIT SYSTEMS
;
; 	C. H. FRANKS	21-OCT-81
; 
; 		CHF034 -- USE MTPS MACRO
; DA11-B INTERPROCESSOR COMMUNI      CATIONS DRIVER
;
; *****************************************************************************
;
;			KNOWN HACKS FOR THIS DEVICE
;
; 1) 	CYCLE BIT IS READ/WRITE INSTEAD OF WRITE ONLY.  IT IS SET EVERY TIME
;	A WORD IS TRANSFERED FROM ONE SYSTEM TO ANOTHER, AND THEREFORE
;	ITS STATE AT ANY TIME IS INDETERMINATE.  THEREFORE ALL "BIS" AND
;	"BIC" INSTRUCTIONS ARE FORBIDDEN AS THEY CAN REWRITE THE CYCLE BIT
;	INITIATING AN UNWANTED NPR CYCLE OR CYCLES.
;
; 2) 	BOTH SIDES CANNOT TRY TO TRANSMIT AT       THE SAME TIME BECAUSE THIS
;	DEVICE IS HALF DUPLEX ONLY.  THEREFORE A DEVICE PROTOCOL MUST
;	BE WRITEN INTO THE DRIVER TO ARBITRATE THE LINK.
;
; 3)	THE DEVICE NPR LOGIC WILL NOT CROSS 32K WORD BOUNDRIES BECAUSE
;	THE BUFFER REGISTER IS ONLY A 16 BIT COUNTER.  WHEN A 32K WORD
;	BOUNDARY IS CROSSED, THE MEMORY EXTENSION BITS MUST BE INCREMENTED
;	FOR A RESTART.  ALSO, DUE TO THE CYCLE REQUEST LOGIC, THE
;	NEXT TRANSMIT WORD IS PLACED IN THE DATA BUFFER AND MUST BE
;	REMOVED (VIA SOFTWARE) AND STORED       IN THE RECEIVE DATA BUFFER
;	BEFORE RESUMING THE TRANSFER.
;
;
; 4)	ACCESSING THE CSR AFTER SETTING THE GO BIT MAY CAUSE THE
;	DEVICE TO LOSE A CYCLE REQUEST AND THEREBY HALT NPR TRANSFERS
;	WITHOUT SETTING DONE OR ERROR. RECOVERY IN THIS CASE IS
;	BY TIMEOUT ALONE.
;
; *****************************************************************************
;


;
; MACRO LIBRARY CALLS
;

	.MCALL	PKTDF$,HWDDF$
	PKTDF$				;DEFINE I/O PACKET OFFSETS
	HWDDF$				;DEFINE HARDWARE REGISTERS
	.MCALL	UCBD      F$,CUCDF$
	UCBDF$				; DEFINE UCB OFFSETS
	CUCDF$				;COMMUNICATIONS UCB LABELS
;										;**-11
; EQUATED SYMBOLS
;


;
; LOCAL DEFINITIONS
;

DBGO=	1				;SET TO START TRANSFERS (RCV)
MDOUT=	2				;OUTPUT MODE,1= WORD
DROUT=	4				;OUTPUT DIRECT,1= RCV
INTENB=	100				;INTERRUPT ENABLE
IREQO=	10				;SET TO REQ INTR IN COMPANION
RDY=	200				;INDICATES DEVICE READY
CYCLE=	400				;SET W/GO TO START XMIT XFER
MDINP=	1000				;INP MODE, 1= WORD
DRINP=	2000				;INP DIRECT 1= COMPANION IS RCV
IR      EQN=	4000				;INTR REQ FROM COMPANION
NEX=	40000				;NON EXISTENT MEMORY
ERROR=	100000				;=1 WHEN DEVICE ERROR
DIS0=	DROUT!MDOUT!IREQO!CYCLE 	;RESTORE DB TO IDLE STATE
ATTN=	20000
MBIT=60					;MEMORY EXTENSION BIT POSITIONS
BUMP=20					;MEMORY EXTEN BIT INCREMENT

;
; UNIT IMPURE DATA TABLE
;

CNTBL:					;REF LABEL
UNITBL:	.REPT	D$$B11

	.WORD	0

	.ENDM


	.IF GT	D$$B11-1

TEMP:					;REF LABEL
UNIT:	.BLKW	1

	.ENDC


;
; DEVICE DISPATCH TABLE
;

$XBTBL::.WORD	DBINIT			;DEVI      CE INITIATION ENTRY
	.WORD	DBCANC			;I/O CANCELLATION ENTRY
	.WORD	DBTMO			;DEVICE TIMEOUT ENTRY
	.WORD	DBPWRF			;POWERFAIL ENTRY
;+
;**- DBINIT - DA11-B PARALLEL COMMUNICATIONS LINK CONTROLLER I/O INITIATOR
;
; DBINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE
; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE NORMAL
; RSX-11M INPUT/OUTPUT LOGIC FLOW.  IF THE DEVICE IS
; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT, THE
; REQUEST IS INITIATED.
; IF NO REQUEST EXISTS FOR       THAT UNIT OR IF IT IS BUSY,
; AN EXIT IS TAKEN TO THE CALLER.  NOTE THAT BECAUSE OF THE
; NATURE OF THE DA11-B, EACH UNIT IS A CONTROLLER ITSELF, HAS
; ITS OWN SCB, AND THEREFORE ITS OWN QUEUE.
; EACH TIME DBINIT IS CALLED, IT IS CALLED TO SERVICE ONLY
; THE UNIT SPECIFIED IN THE CALL.
;
; INPUTS:
;	R4 = STATUS CONTROL BLOCK ADDRESS
;	R5 = ADDRESS OF THE UCB TO BE INITIATED
;
; OUTPUTS:
;	IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE
;	DEVICE IS INITIATED APPROPRIATELY.
;
;-

	.ENABL	LSB

DB      INIT:					;REFERENCE LABEL
	CALL	$GTPKT			;ANY WORK TO DO?			;**-13
	BCC	20$			;BR IF WORK TO DO
XBRET:					;REFERENCE LABEL			;**-10
	RETURN				;RETURN TO CALLER			;**-7

; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT
;
;	R1= ADDRESS OF I/O REQUEST PACKET
;	R2= PHYSICAL UNIT NUMBER OF THE REQUEST UCB
;	R3= CONTROLLER INDEX
;	R4= ADDRESS OF THE STATUS CONTROL BLOCK
;	R5= ADDRESS OF THE UCB SPECIFIED IN THE DBINIT CALL
;
; DA11-B I/O REQUEST PACKET FORMAT
;
;	WORD		CONTENT
;
;	0	I/O QUEU      E THREAD WORD
;	1	REQUEST PRIORITY, EVENT FLAG NUMBER
;	2	ADDRESS OF THE TCB OF THE REQUESTER TASK
;	3	POINTER TO SECOND LUN WORD IN TASK HEADER
;	4	CONTENTS OF FIRST LUN WORD (UCB)
;	5	I/O FUNCTION CODE
;	6	VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	7	RELOCATION BIAS OF I/O STATUS BLOCK
;      10	I/O STATUS BLOCK ADDR (REAL OF DISPLACEMENT + 140000)
;      11	VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;      12	MEMORY EXTENSION BITS FOR I/O BUFFER
;      13	BUFFER ADDRESS FOR TRANSFER
;      14	TOTAL BY      TE COUNT TO TRANSFER
;      15	NOT USED
;      16	NOT USED
;      17	NOT USED
;      20	NOT USED
;

20$:	MOV	S.CSR(R4),R2		;PUT CSR INTO R2
	ADD	#I.FCN+1,R1		;R1 POINTS TO I/O FUNCTION CODE
	CMPB	#IO.INL/256.,(R1)	;CONTROL FUNCTION?
	BLOS	40$			;BR IF CONTROL FUNCTION
	BIT	#U2.ONL,U.CW2(R5)	;DEVICE ONLINE?
	BEQ	50$			;RETURN IE.DNR IF NOT ONLINE

	.IF DF	M$$MGE&M$$EXT

25$:	CALL	$STMAP			;SET DEVICE'S UNIBUS ADDRESS		;**-5
	MOV	R1,-(SP)		;SAVE R1
	MOV	R2,-(SP)		;AND R2
	CALL	$MPUBM			;SET       UP 11/70 UNIBUS MAPPING
	MOV	(SP)+,R2		;RESTORE R2 AND R1
	MOV	(SP)+,R1

	.ENDC

	CMPB	#IO.RLB/256.,(R1)	;RECEIVE FUNCTION?
	BEQ	30$			;BR IF RECEIVE FUNCTION

; FALL THROUGH ON TRANSMIT REQUEST
	CMP	-(R2),-(R2)		;POINT TO WORD CNT REG			;**-7
	CLR	-(SP)			;INITIALIZE CSR, CLEAR C BIT
	MOV	U.CNT(R5),-(SP)		;GET DATA COUNT IN BYTES
	ROR	(SP)			;CONVERT TO WORD COUNT
	ADC	(SP)			;ADJUST FOR ODD BYTE COUNT
	MOV	(SP),6(R2)		;PASS COUNT IN DATA BUFFER
	NEG	(SP)			;COUNT IN 2'S COMPLEMENT
	MOV	(      SP)+,(R2)+		;LOAD COUNT
	MOV	U.BUF+2(R5),(R2)+	;LOAD ADDRESS
	MOVB	S.ITM(R4),S.CTM(R4)	;SET TIMEOUT COUNT
	INCB	U.CW3(R5)		;SET SENDER STATUS IN UCB

	.IF DF	M$$MGE

	BIS	U.BUF(R5),(SP)		;OR IN MEMORY EXTENSION BITS

	.ENDC

	BIS	#IREQO!INTENB!DBGO,(SP) ;SETUP TO GO
	MOV	(SP)+,(R2)		;START DEVICE
	RETURN				;INTERRUPTS PROPAGATE TRANSMIT

; RECEIVE FUNCTION INITIATION

30$:					;REFERENCE LABEL
	MOV	R5,R0			;R0 POINTS TO UCB			;**-3
	ADD	#U.RBUF,R0		;R0 POINTS TO RCV BUF ADDR AREA
	MOV	U      .BUF(R5),(R0)+		;TRANSFER BUFFER ADDR TO U.RBUF
	MOV	U.BUF+2(R5),(R0)+	;
	MOV	U.CNT(R5),(R0)		;TRANSFER COUNT
	ROR	(R0)			;CHANGE BYTE CONT TO WORD COUNT
	ADC	(R0)			;ADJUST FOR ODD BYTE COUNT
	MOV	#U3.RPD,U.CW3(R5)	;SET RECEIVE PENDING
	MOV	#INTENB,(R2)		;ENABLE INTERRUPTS (CAUSING ONE)
	RETURN				;RETURN, INTERRUPT PROPAGATES RX
; REQUEST WAS CONTROL FUNCTION							;**-8

40$:	BNE	SUCC			;CHANGE MODE IS NO-OP
	TSTB	-(R1)
	BNE	60$			;BR IF FUNCTION WAS TERMINATE

; INITIALIZE  DEVICE FUNCTION      

	MOV	R5,UNITBL(R3)		;PUT UCB ADDR INTO TABLE
	CLR	(R2)			;CLEAR CSR REGISTER
	CLR	-2(R2)			;CLEAR BUFFER ADDR REGISTER
	TST	(R2)			;ERROR BIT SET?
	BMI	50$			;BR IF MODULE NOT IN PLACE
	BIS	#U2.ONL,U.CW2(R5)	;MARK DEVICE ONLINE			;**-3
	BR	70$			;COMPLETE SUCCESSFUL I/O		;**-7

; SIGNAL DEVICE NOT READY

50$:	MOV	#IE.DNR&377,R0		;SIGNAL DEVICE NOT READY
	BR	UNSUCC			;COMPLETE UNSUCCESSFUL I/O

; FUNCTION WAS TERMINATE

60$:	CLR	UNITBL(R3)		;REMOVE UCB ADDR FROM TABLE
	BIC	#U2.ONL,U.CW2(R      5)	;MARK DEVICE OFFLINE
	CLR	(R2)			;CLEAR CSR REGISTER
70$:	CLR	U.CW3(R5)		;CLEAR DEVICE STATUS IN UCB
	CLR	2(R2)			;CLEAR DATA BUFFER REGISTER
	CLR	-(R2)			;CLEAR ADDRESS REGISTER
	CLR	-(R2)			;CLEAR WORD COUNT REGISTER
SUCC:	MOV	#IS.SUC&377,R0		;SUCCESSFUL COMPLETION ENTRY
UNSUCC:	CLRB	S.STS(R4)		;IDLE CONTROLLER
	BICB	#US.BSY,U.STS(R5)	;MARK UNIT IDLE
	MOV	R0,-(SP)		;SAVE STATUS WORD ONE
	MOV	S.PKT(R4),-(SP)		;SAVE OLD PACKET ADDR
										; TM001
	.IF	DF,M$$MGE&M$$EXT						; TM001
	MOV	R4      ,R2			;COPY SCB POINTER			; TM001
	ADD	#S.MPR,R2		;POINT TO MAPPING ASSIGNMENT BLK	; TM001
	CALL	$DEUMR			;DEASSIGN ANY UMR'S			; TM001
	.ENDC									; TM001
	CALL	DBINIT			;TRY TO ACTIVATE NEXT REQUEST
	MOV	(SP)+,R3		;GET OLD I/O PACKET
	MOV	I.PRM+4(R3),R1		;RETURN REQUESTED ITEM COUNT
	MOV	(SP)+,R0		;GET STATUS WORD 1
	CALLR	$IOFIN			;TERMINATE OLD PACKET

	.DSABL	LSB

;
; DEVICE TIMEOUT ENTRY
;
; THIS CODE IS ENTERED WHEN THE TRANSMIT TIMEOUT COUNT GOES TO ZERO.
;

DBTMO:					;;;REFERE      NCE LABEL
	CLR	U.CW3(R5)		;;;CLEAR DEVICE STATUS			;**-10
	CLR	@S.CSR(R4)		;;;DISABLE DEVICE
	MTPS	#0			;;; ENABLE INTERRUPTS			; CHF034
	BR	UNSUCC			;FINISH UNSUCCESSFUL			;**-1

; DEVICE CANCELLATION AND POWERFAIL ENTRYS
;
; FOR NETWORKS CANCELLATION AND POWERFAIL ARE NO-OPED AND THE
; TRANSMIT EITHER COMPLETES OR TIMES OUT. IT IS THEN FINISHED
; IN THE NORMAL MANNER.
; FOR NON-NETWORKS, THE DEVICE IS DISABLED AND A TIMEOUT FORCED SO
; THAT THE PACKET IS FINISHED BY DBTMO, AVOIDING ANY RACE CO      NDITIONS
; ARISING FROM I/O TERMINATION.
;
	.ENABL	LSB								;**-8

DBCANC:	CMP	I.TCB(R0),R1		;;;I/O FOR THIS TASK?
	BNE	5$			;;;RETURN IF NOT
	TSTB	U.CW3(R5)		;;;TRANSFER IN PROGRESS?
	BNE	5$			;;;LET FINISH IF YES
	MOV	#IE.ABO&377,R0		;;;RETURN ABORT STATUS
	BR	DBTMO			;;;FINISH AS TIMEOUT

DBPWRF:	MOVB	#2,S.CTM(R4)		;;;FORCE TIMEOUT
5$:	RETURN				;;;RETURN TO CALLER

	.DSABL	LSB
;										;**-3
; DA11-B INTERRUPT ROUTINE
;

	.ENABL	LSB

$XBINT::				;;;REFERENCE LABEL
	INTSV$	XB,P      R5,D$$B11		;;;GENERATE INTERRUPT SAVE CODE
	CALL	DBSET			;;;PUT CSR ADDRESS IN R4
	TSTB	(R4)			;;;DEVICE READY?
	BMI	5$			;;;CONTINUE IF YES
	RETURN				;;;EXIT INTERRUPT IF NOT

5$:	TSTB	U.CW3(R5)		;;;TX OR RCV ACTIVE
	BEQ	NOTHNG			;;;BR IF NOTHING ACTIVE
	BMI	10$			;;;BR IF RECEIVE ACTIVE

; AM CURRENTLY TRYING TO TRANSMIT, CHECK FOR SUCCESSFUL COMPLETION

	BIT	#IREQN,(R4)		;;;HE INTERRUPTING ME?
	BEQ	10$			;;;CHECK ON IF NOT
	BIT	#MDINP,(R4)		;;;DOES HE WANT ME TO FLUSH TX?
	BNE	IEVER			;;;      RETURN ERROR IF YES

; AM CURRENTLY RECEIVING, CHECK FOR SUCESSFUL COMLETION

10$:	TST	(R4)			;;;ERROR BIT SET?
	BPL	20$			;;;CHECK ON IF NOT
	JMP	ERR			;;;CHECK ON ERROR

20$:	TST	-4(R4)			;;;ALL DATA TRANSFERRED?
	BEQ	SUCDN			;;;RETURN GOOD STAUTS IF YES
IEVER:	MOV	#IE.VER&377,-(SP)	;;;UNRECOVERABLE ERROR FINISH
	BR	INTDN			;;;FINISH I/O

SUCDN:					;;;SUCCESSFUL COMPLETION
	MOV	#IS.SUC&377,-(SP)	;;;RETURN SUCESSFUL STATUS		;**-7
INTDN:					;;;REFERENCE LABEL			;**-3
	CLR	(R4)			;;;DISABLE       DEVICE			;**-3
	MOV	(SP)+,R4		;;;SAVE STATUS IN R4
	CALL	$FORK			;;;GO TO FORK LEVEL
	CLR	U.CW3(R5)		;SAY DEVICE NOT ACTIVE
	MOV	R4,R0			;RETURN STATUS IN R0
	MOV	U.SCB(R5),R4		;GET SCB ADDR FOR I/O DONE
	CALLR	UNSUCC			;FINISH I/O
NOTHNG:	BIT	#IREQN,(R4)		;;;DID HE INTERRUPT ME?			;**-80
	BEQ	EXIT			;;;EXIT IF NOT
	BIT	#MDINP!ERROR,(R4)	;;;ERROR OR FLUSH TX SET?
	BNE	EXIT			;;;EXIT IF YES
	TSTB	U.CW3+1(R5)		;;;IS A RECEIVE PENDING?
	BEQ	EXIT			;;;EXIT IF NOT
	CMP	2(R4),U.RCNT(R5)	;;;TX COUNT       = RECV COUNT/		;**-3
	BNE	VER			;;;RETURN ERR IF NOT
	CMP	-(R4),-(R4)		;;;XFER REQUEST, SET UP TO GO		;**-8
	MOV	U.RCNT(R5),(R4)		;;;GET RECEIVE COUNT
	NEG	(R4)+			;;;COUNT IN 2'S COMPLEMENT
	MOV	U.RBUF+2(R5),(R4)+	;;;ADDR INTO BUFFER ADDR REG
	BIS	#U3.RAC,U.CW3(R5)	;;;SET RECEIVE ACTIVE IN UCB
	MOV	#DROUT!DBGO!INTENB,-(SP) ;;;SETUP TO GO

	.IF DF	M$$MGE

	BIS	U.RBUF(R5),(SP)		;;;OR IN MEMORY EXENSION BITS

	.ENDC

	MOV	(SP)+,(R4)		;;;ENABLE DEVICE
EXIT:	RETURN				;;;WAIT FOR XFER TO FINISH      


	.DSABL	LSB

	.ENABL LSB

ERR:	BIT	#NEX,(R4)		;;;NON EXISTENT MEMORY ERROR?
	BNE	20$			;;;BR IF YES
	BIT	#ATTN,(R4)		;;;POSSIBLE INIT ON OTHER SYSTEM?
	BNE	30$			;;;BR IF YES
	CLR	-2(R4)			;;;REMOVE POSSIBLE OVERFLOW
	TST	(R4)			;;;ERROR STILL SET?
	BMI	30$			;;;BR IF YES

	.IF DF	M$$MGE

	MOV	#DBGO!INTENB!CYCLE,-(SP) ;;;SETUP FOR TRANSMIT CONTINUE
	MOV	(R4),-(SP)		;;;COPY CURRENT CSR BITS
	BIC	#^CMBIT,(SP)		;;;CLEAR ALL BUT EXTENSION BITS
	ADD	#BUMP,(SP)		;;;INCREMENT MEMORY EXTENSION       BITS
	BIS	(SP),2(SP)		;;;OR IN EXTENSION BITS
	TSTB	U.CW3(R5)		;;;WAS I TRANSMITTING?
	BPL	10$			;;;BR IF YES
	SWAB	(SP)			;;;PUT MEMORY EXTENSION BITS		;**-14
	ASR	(SP)			;;;IN POSITIONS 10 & 11
	ASR	(SP)
	MOV	KISAR6,-(SP)		;;;SAVE CURRENT MAPPING
	MOV	2(SP),KISAR6		;;;SET NEW MAPPING
	MOV	2(R4),@#140000		;;;PUT CHAR INTO USER'S BUFFER
	MOV	(SP)+,KISAR6		;;;RESTORE MAPPING
	CMP	-(R4),-(R4)		;;;POINT TO WORD CNT REG
	INC	(R4)+			;;;INCR COUNT
	ADD	#2,(R4)+		;;;INCR BUFFER ADDRESS REG
	BIC	#CY      CLE,2(SP)		;;;CLR CYCLE FOR RECEIVE
	BIS	#DROUT,2(SP)		;;;SET RECEIVE DIRECTION
10$:	TST	-4(R4)			;;;I/O FINISHED?
	BNE	15$			;;;BRANCH IF NOT
	CMP	(SP)+,(SP)+		;;;YES--CLEAN STACK
	JMP	SUCDN			;;;FINISH SUCCESSFULLY
15$:	TST	(SP)+			;;;CLEAN STACK				;**-3
	MOV	(SP)+,(R4)		;;;START UP DEVICE

	.ENDC

	BR	DBEXIT			;;;EXIT FROM INTERRUPT

VER:					;;;REFERENCE LABEL
20$:	JMP	IEVER			;;;RETURN UNRECOVERABLE ERROR

30$:	MOV	#IE.DNR&377,-(SP)	;;;SIGNAL DEVICE NOT READY
40$:	JMP	INTDN			;;;FINIS   È  H I/O

	.DSABL	LSB
DBSET:					;;;REFERENCE LABEL
	TST	R5			;;;CHECK FOR VALID UCB ADDRESS
	BEQ	10$			;;;BR IF NO UCB IN TABLE
	BIT	#U2.ONL,U.CW2(R5)	;;;DEVICE ONLINE?
	BEQ	10$			;;;IGNORE INTERRUPT IF OFFLINE
	MOV	U.SCB(R5),R4		;;;GET SCB ADDR IN R4
	MOV	S.CSR(R4),R4		;;;PUT CSR ADDR INTO R4
	RETURN				;;;RETURN TO CALLER

10$:	TST	(SP)+			;;;CLEAR STACK OF RETURN ADDR
DBEXIT:	JMP	$INTXT			;;;EXIT FROM INTERRUPT
	.END									;**-59

È         »z ™kQ	› c,        	.TITLE	SYSXT
	.IDENT	/12.49/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 12.49
;
; D. N. CUTLER 10-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	P. WANNHEDEN
;	CHUCK SPITZ
;	B. S. MCCARTHY
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-AUG-79
;		MSH049 -- ADD MORE GROUP GLO      BAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	28-AUG-79
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	10-SEP-79
;		MSH061 -- CORRECT MISLEADING COMMENTS
;
;	M. S. HARVEY	9-OCT-79
;		MSH069 -- ADD STOP FOR GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	8-APR-80
;		MSH091 -- CLEANUP AND GENERALIZE KERNEL AST HANDLING.
;			  ADD GENERAL BUFFERED I/O SUPPORT.
;
;	M. S. HARVEY	9-APR-80
;		MSH088 -- CLEAN UP $SGFIN
;
;		MSH092 -- DO NOT USE ILLEGAL INSTRUCTION IN $FINXT
;
;	M. S. H      ARVEY	28-APR-80
;		MSH096 -- SUPPORT ALTERNATE HEADER REFRESH AREAS
;
;	M. S. HARVEY	20-AUG-80
;		MSH112 -- MODIFY $SGFIN TO REFER TO $TRINT
;
;	M. S. HARVEY	12-SEP-80
;		MSH115 -- CLEAN UP GROUP GLOBAL USE FOR ABORTED TASKS
;
;	M. S. HARVEY	6-OCT-80
;		MSH121 -- ADD SUPPORT FOR REQUESTED EXIT ASTS
;
;	M. S. HARVEY	13-NOV-80
;		MSH126 -- DO NOT QUEUE EXIT STATUS AST ON SYSTEMS
;			  WITHOUT AST SUPPORT
;
;		MSH127 -- CLEAN UP CACHE MEMORY CONDITIONALIZATION
;
;	M. S. HARVEY	25-NOV-80
;		M      SH129 -- ALLOW FULL USE OF EXIT STATUS BLOCK
;
;	M. S. HARVEY	19-DEC-80
;		MSH132 -- ENSURE KISAR5 MAPPING OF CONNECT-TO-INTERRUPT
;			  FORK BLOCKS AND REMOVE UNNECESSARY CODE
;
;	M. S. HARVEY	23-DEC-80
;		MSH134 -- PREVENT UNDEFINED VARIABLE INTERRUPTS WHEN
;			  RESTORING FLOATING POINT CONTEXT
;
;	M. S. HARVEY	8-JAN-81
;		MSH140 -- NO NEED TO MAP FLOATING POINT SAVE AREA FOR
;			  EMULATOR TASKS
;
;	DAN BROWN	8-JAN-81
;		DTB011 -- MODIFY FOR NEW ERROR LOGGING SYSTEM
;
;	M. S. FOX	06-FEB      -81
;		MF208 -- SUPPORT COMMAND ARRIVAL ASTS FOR CLIS
;
;	M. S. HARVEY	12-FEB-81
;		MSH149 -- ADD FLOATING POINT TRANSPORTABILITY
;
;	M. S. HARVEY	11-JUN-81
;		MSH175 -- ADD SUPPORT FOR ANCILLARY CONTROL DRIVER
;
;	M. S. HARVEY	15-JUL-81
;		MSH178 -- DO NOT IGNORE LOADER IF REQUESTED AS A
;			  RESULT OF STOPPING A TASK DURING THE
;			  SCHEDULER'S TASK SCAN
;
;	M. S. HARVEY	29-JUL-81
;		MSH183 -- ADD GROUP GLOBAL RUNDOWN KERNEL AST ROUTINE
;
;	M. S. HARVEY	22-SEP-81
;		MSH172 -- STOPFOR S      TATE CANNOT EXIST IN AST STATE
;
;	M. S. HARVEY	3-NOV-81
;		MSH199 -- $FINBF MUST EXIST ON SYSTEMS SUPPORTING
;			  ASYNCHRONOUS BUFFERED I/O
;
;
; SYSTEM ENTRANCE, EXIT, AND PROCESSOR DISPATCHING
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$,HDRDF$,HWDDF$,PCBDF$,TCBDF$
	.MCALL	ITBDF$,DCBDF$
	ABODF$			;DEFINE TASK ABORT CODES
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS      
	ITBDF$			;DEFINE INTERRUPT TRANSFER BLOCK OFFSETS
	DCBDF$			;DEFINE DEVICE CONTROL BLOCK OFFSETS

;									;MSH091
; LOCAL MACROS								;MSH091
;									;MSH091
									;MSH091
; THIS MACRO GENERATES ENTRIES IN THE KERNEL AST DISPATCHING TABLE.	;MSH091
; THE FORMAT OF THE MACRO IS:						;MSH091
;									;MSH091
;	KAST	SYM,COND						;MSH091
;									;MSH091
;		WHERE-	SYM IS THE ADDRESS OF THE KERNEL AST PROCESSING	;MSH091
;			ROUTINE						;MSH091
;									;MSH091
;			COND IS THE CONDI      TIONAL THAT MUST BE DEFINED	;MSH091
;			IF THE KERNEL AST ROUTINE SPECIFIED IN SYM	;MSH091
;			IS TO BE DEFINED				;MSH091
;									;MSH091
; IF COND IS UNDEFINED, AN ENTRY IN THE DISPATCH TABLE IS CREATED	;MSH091
; THAT WILL CAUSE A SYSTEM CRASH SHOULD THE UNDEFINED KERNEL AST	;MSH091
; TYPE BE ENCOUNTERED.							;MSH091
;									;MSH091
									;MSH091
	.MACRO	KAST,SYM,COND						;MSH091
									;MSH091
	.IF DF	'COND'							;MSH091
									;MSH091
	.WORD	SYM		;KERNEL AST PROCESSING ROUTIN      E		;MSH091
									;MSH091
	.IFF	;'COND'							;MSH091
									;MSH091
	.WORD	CRSH		;CRASH - ILLEGAL KERNEL AST FOR SYSTEM	;MSH091
									;MSH091
	.ENDC	;'COND'							;MSH091
									;MSH091
	.ENDM								;MSH091
									;MSH091
;+
; **-$DIRSV-DIRECTIVE SAVE
;
; THIS ROUTINE IS CALLED FROM DIRECTIVE LEVEL TRAP SERVICE ROUTINES. THE
; STACK DEPTH IS +1, THUS A SWITCH TO THE SYSTEM STACK IS ALWAYS NEC-
; ESSARY. AT THE END OF TRAP PROCESSING A RETURN IS EXECUTED TO EXIT
; FROM THE SYSTEM      .
;
; INPUTS:
;
;	4(SP)=PS WORD PUSHED BY TRAP.
;	2(SP)=PC WORD PUSHED BY TRAP.
;	0(SP)=SAVED R5 PUSHED BY 'JSR R5,$DIRSV'.
;
; OUTPUTS:
;
;	REGISTER R4 IS PUSHED ONTO THE CURRENT STACK AND THEN A SWITCH
;	TO THE SYSTEM STACK IS EXECUTED. REGISTERS R3 THRU R0 ARE
;	PUSHED ON THE SYSTEM STACK, THE NEW PROCESSOR PRIORITY IS
;	SET, AND A CALL TO THE CALLER IS EXECUTED.
;-

$DIRSV::MOV	R4,-(SP)	;;;SAVE REGISTER R4
	DEC	$STKDP		;;;SET PROPER STACK DEPTH
	BNE	10$		;;;IF NE DON'T SWITCH STACKS
	      MOV	SP,@$HEADR	;;;SAVE CURRENT STACK POINTER


	.IF NDF	M$$MGE

	MOV	#$STACK,SP	;;;LOAD SYSTEM STACK POINTER

	.ENDC


10$:	MTPS	#0		;;;ALLOW INTERRUPTS
	MOV	R3,-(SP)	;SAVE REGISTERS R3 THRU R0
	MOV	R2,-(SP)	;
	MOV	R1,-(SP)	;
	MOV	R0,-(SP)	;
	CALL	(R5)		;CALL SYNCHRONOUS TRAP ROUTINE
	BR	$DIRXT		;EXIT FROM TRAP

;+
; **-$FORK-FORK AND CREATE SYSTEM PROCESS
;
; THIS ROUTINE IS CALLED FROM AN I/O DRIVER TO CREATE A SYSTEM PROCESS THAT
; WILL RETURN TO THE DRIVER AT STACK DEPTH ZERO TO FI      NISH PROCESSING.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB FOR THE UNIT BEING PROCESSED.
;
; OUTPUTS:
;
;	REGISTERS R5 AND R4 ARE SAVED IN THE CONTROLLER FORK BLOCK AND
;	A SYSTEM PROCESS IS CREATED. THE PROCESS IS LINKED TO THE FORK
;	QUEUE AND A JUMP TO $INTXT IS EXECUTED.
;-

$FORK::	MOV	R4,-(SP)	;SAVE REGISTER R4
	MOV	U.SCB(R5),R4	;POINT TO CONTROLLER STATUS BLOCK
	CLRB	S.CTM(R4)	;DISABLE TIMEOUT
	ADD	#S.FRK+6,R4	;POINT TO END OF FORK BLOCK
	MOV	(SP)+,(R4)	;PUT SAVED R4 IN FORK BLOCK

;+      
; **-$FORK1-FORK AND CREATE SYSTEM PROCESS
;
; THIS ROUTINE IS AN ALTERNATE ENTRY TO CREATE A SYSTEM PROCESS AND
; SAVE REGISTER R5.
;
; INPUTS:
;
;	R4=ADDRESS OF THE LAST WORD OF A 3 WORD FORK BLOCK PLUS 2.
;	R5=REGISTER TO BE SAVED IN THE FORK BLOCK.
;
; OUTPUTS:
;
;	REGISTER R5 IS SAVED IN THE SPECIFIED FORK BLOCK AND A SYSTEM
;	PROCESS IS CREATED. THE PROCESS IS LINKED TO THE FORK QUEUE
;	AND A JUMP TO $INTXT IS EXECUTED.
;-

$FORK1::MOV	R5,-(R4)	;SAVE REGISTER R5

;+
; **-$FORK0-FO      RK AND CREATE SYSTEM PROCESS
;
; THIS ROUTINE IS AN ALTERNATE ENTRY TO CREATE A SYSTEM PROCESS.
;
; INPUTS:
;
;	R4=ADDRESS OF THE LAST WORD OF A 2 WORD FORK BLOCK PLUS 2.
;
; OUTPUTS:
;
;	A SYSTEM PROCESS IS CREATED, LINKED TO THE FORK QUEUE AND A
;	JUMP TO $INTXT IS EXECUTED.
;-

$FORK0::MOV	(SP)+,-(R4)	;SET FORK PC
	CLR	-(R4)		;CLEAR LINK TO NEXT FORK BLOCK
	MFPS	-(SP)		;SAVE CURRENT PROCESSOR PRIORITY
	MTPS	#PR7		;;;LOCK OUT INTERRUPTS
	MOV	R4,@$FRKHD+2	;;;LINK NEW ENTRY TO OLD LAST
	M      OV	R4,$FRKHD+2	;;;SET ADDRESS OF NEW LAST
	MTPS	(SP)+		;;;RESTORE PROCESSOR PRIORITY
	ASRB	$IDLFL		;INTERRUPT OF IDLE LOOP?
	BCC	$INTXT		;IF CC NO


	.IF DF	M$$MGE

	MOV	#$DIRXT,$STACK-24 ;FORCE DEQUEUE FROM FORK LIST

	.IFF

	MOV	#$DIRXT,$STACK-14 ;FORCE DEQUEUE FROM FORK LIST

	.ENDC


	.IF DF	C$$INT

	RETURN			;

;+
; **-$FORK2-FORK ROUTINE FOR USE IN CONJUNCTION WITH
;	THE CINT$ DIRECTIVE.
;
; INPUT:
;	R5	POINTING TO FORK BLOCK IN ITB
;
; OUTPUT:
;	IF THE FORK BLOCK IS NOT A      LREADY IN USE (FORK PC ZERO),		;MSH061
;	A SYSTEM PROCESS IS CREATED, LINKED TO THE FORK QUEUE AND A	;**-1
;	JUMP TO $INTXT IS EXECUTED.
;	ELSE THE INTERRUPT IS DISMISSED (NO RETURN TO CALLER).
;
;	IMMEDIATELY ON RETURN FROM THIS ROUTINE, THE FOLLOWING
;	INSTRUCTION SHOULD BE EXECUTED:
;
;		CLR	@R3
;
;	WHICH DECLARES THE FORK BLOCK FREE.
;-

$FORK2::TST	2(R5)		;;;FORK BLOCK ALREADY IN USE?
	BNE	10$		;;;Y - JUMP
	MOV	R4,6(R5)	;;;SAVE R4 IN FORK BLOCK
	MOV	R5,R4		;;;
	ADD	#6,R4		;;;POINT JUST       AFTER 3-WORD FORK BLOCK
	BR	$FORK1		;;;
10$:	TST	(SP)+		;;;CLEAR STACK
				;;;FALL THRU TO $INTXT

	.ENDC


;+
; **-$INTXT-INTERRUPT EXIT
;
; THIS ROUTINE MAY BE CALLED VIA A JMP TO EXIT FROM AN INTERRUPT.
;
; INPUTS:
;
;	0(SP)=INTERRUPT SAVE RETURN ADDRESS.
;
; OUTPUTS:
;
;	A RETURN TO INTERRUPT SAVE IS EXECUTED.
;-

$INTXT::RETURN			;

;+
; **-$INTSC-INTERRUPT SAVE (INTERRUPT FROM VECTOR CONNECTED
;	TO VIA CINT$ DIRECTIVE).
;
; CALLS ISR WITH R4 AND R5 SAVED AND:
;
;	R5	POIN      TER TO FORK BLOCK IN ITB
;	PRI	TAKEN FROM ITB
;	CONDITION CODES TAKEN FROM ITB
;-

	.IF DF	C$$INT

$INTSC::MOV	R4,-(SP)	;;;SAVE R4
	DEC	$STKDP		;;;SWITCH STACKS?
	BNE	10$		;;;N - JUMP
	MOV	SP,@$HEADR	;;;Y - SAVE STACK POINTER

	.IF NDF	M$$MGE

	MOV	#$STACK,SP	;;;LOAD SYSTEM STACK POINTER

	.IFTF
10$:				;;;REF LABEL

	.IFF

	MOV	KISAR5,-(SP)	;;;SAVE KERNEL APR 5
	MOV	X.REL-X.PSW(R5),KISAR5 ;;;MAP ISR IN KERNEL APR5

	.ENDC

$INTS2:	MTPS	(R5)+		;;;LOAD ISR PRIORITY
	INC	R5		;;;SKIP       OVER UNUSED BYTE
	CALL	@(R5)+		;;;CALL ISR

	.IF DF	M$$MGE

	MOV	(SP)+,KISAR5	;;;RESTORE KERNEL APR 5

	.ENDC

	BR	$INTX1		;;;EXIT FROM INTERRUPT

	.ENDC



;+
; **-$INTSE-INTERRUPT SAVE (ERROR LOGGING DEVICES)
;
; THIS ROUTINE IS CALLED FROM AN INTERRUPT SERVICE ROUTINE WHEN AN
; INTERRUPT IS NOT GOING TO BE IMMEDIATELY DISMISSED. REGISTER R4 IS
; SAVED AND THEN LOADED WITH THE ADDRESS OF THE SCB OF THE CONTROLLER
; THAT CAUSED THE INTERRUPT. A CHECK IS THEN MADE TO SEE IF AN ERROR IS      
; ALREADY IN PROGRESS. IF IT IS NOT, THEN THE CURRENT I/O ACTIVE BITMAP
; IS SAVED IN THE SCB. THE APPROPRIATE BIT IS THEN CLEARED IN THE ACTIVE
; BITMAP AND REGISTER R4 IS LOADED WITH THE CONTROLLER INDEX. A NORMAL
; INTERRUPT SAVE IS THEN EXECUTED.
;
; INPUTS:
;
;	4(SP)=PS WORD PUSHED BY INTERRUPT.
;	2(SP)=PC WORD PUSHED BY INTERRUPT.
;	0(SP)=SAVED R5 PUSHED BY 'JSR R5,$INTSE'.
;	0(R5)=ADDRESS OF THE SCB OF INTERRUPTING CONTROLLER.
;	2(R5)=NEW PROCESSOR PRIORITY.
;
; OUTPUTS:
;
;	REGISTER       R4 IS PUSHED ONTO THE CURRENT STACK AND THEN LOADED
;	WITH THE ADDRESS OF THE SCB OF THE CONTROLLER THAT CAUSED THE
;	INTERRUPT. IF AN ERROR IS NOT IN PROGRESS, THEN THE I/O ACTIVE
;	BITMAP IS SAVE IN THE SCB. THE APPROPRIATE BIT IS CLEARED IN THE
; 	ACTIVE BITMAP AND REGISTER R4 IS LOADED WITH THE CONTROLLER
;	INDEX.
;-

	.ENABL	LSB
$INTSE::MOV	R4,-(SP)	;;;SAVE REGISTER R4
	MOV	(R5)+,R4	;;;GET ADDRESS OF SCB
	MOVB	S.CON(R4),R4	;;;GET CONTROLLER INDEX			;**-12
	BR	2$		;;;FINISH IN COMMON CODE
      
;+
; **-$INTSV-INTERRUPT SAVE
;
; THIS ROUTINE IS CALLED FROM AN INTERRUPT SERVICE ROUTINE WHEN AN
; INTERRUPT IS NOT GOING TO BE IMMEDIATELY DISMISSED. A SWITCH TO
; THE SYSTEM STACK IS EXECUTED IF THE CURRENT STACK DEPTH IS +1. WHEN
; THE INTERRUPT SERVICE ROUTINE FINISHES ITS PROCESSING, IT EITHER FORKS
; , JUMPS TO $INTXT, OR EXECUTES A RETURN.
;
; INPUTS:
;
;	4(SP)=PS WORD PUSHED BY INTERRUPT.
;	2(SP)=PC WORD PUSHED BY INTERRUPT.
;	0(SP)=SAVED R5 PUSHED BY 'JSR R5,$INTSV'.
;	0(R5)=NEW P      ROCESSOR PRIORITY.
;
; OUTPUTS:
;
;	REGISTER R4 IS PUSHED ONTO THE CURRENT STACK AND THE CURRENT
;	STACK DEPTH IS DECREMENTED. IF THE RESULT IS ZERO, THEN
;	A SWITCH TO THE SYSTEM STACK IS EXECUTED. THE NEW PROCESSOR
;	STATUS IS SET AND A CO-ROUTINE CALL TO THE CALLER IS EXECUTED
;-

$INTSV::MOV	R4,-(SP)	;;;SAVE REGISTER R4
2$:	DEC	$STKDP		;;;SWITCH STACKS?
	BNE	3$		;;;IF NE NO
	MOV	SP,@$HEADR	;;;SAVE CURRENT STACK POINTER


	.IF NDF	M$$MGE

	MOV	#$STACK,SP	;;;LOAD SYSTEM STACK POINTER

      	.ENDC


	.IF DF	L$$SI1

3$:	MTPS	(R5)		;;;LOAD NEW PRIORITY
	CALL	2(R5)		;;;CALL THE CALLER BACK

	.IFF

3$:	BIC	(R5)+,PS	;;;LOAD NEW PRIORITY
	CALL	(R5)		;;;CALL THE CALLER BACK

	.ENDC


;+
; **-$INTXT-INTERRUPT EXIT
;
; THIS ROUTINE IS ENTERED VIA A RETURN TO EXIT FROM AN INTERRUPT. IF THE
; STACK DEPTH IS NOT EQUAL TO ZERO, THEN REGISTERS R4 AND R5 ARE
; RESTORED AND AN RTI IS EXECUTED. ELSE A CHECK IS MADE TO SEE
; IF THERE ARE ANY ENTRIES IN THE FORK QUEUE. IF NONE, THEN R4 AND      
; R5 ARE RESTORED AND AN RTI IS EXECUTED. ELSE REGISTERS R3 THRU
; R0 ARE SAVED ON THE CURRENT STACK AND A DIRECTIVE EXIT IS EXECUTED.
;
; INPUTS: (MAPPED SYSTEM)
;
;	06(SP)=PS WORD PUSHED BY INTERRUPT.
;	04(SP)=PC WORD PUSHED BY INTERRUPT.
;	02(SP)=SAVED R5.
;	00(SP)=SAVED R4.
;
; INPUTS: (REAL MEMORY SYSTEM)
;
;	NONE.
;-

$INTX1::MTPS	#PR7		;;;LOCK OUT INTERRUPTS
	TST	$STKDP		;;;STACK DEPTH ZERO?
	BNE	10$		;;;IF NE NO
	TST	$FRKHD		;;;ANYTHING IN FORK QUEUE?
	BEQ	5$		;;;IF EQ NO
	MTPS	      #0		;;;ALLOW INTERRUPTS
	MOV	R3,-(SP)	;SAVE REGISTERS R3 THRU R0
	MOV	R2,-(SP)	;
	MOV	R1,-(SP)	;
	MOV	R0,-(SP)	;

;+
; **-$DIRXT-DIRECTIVE EXIT
;
; THIS ROUTINE IS CALLED VIA A JUMP TO EXIT FROM A DIRECTIVE OR TRAP
; SERVICE ROUTINE. IF THERE ARE ANY ENTRIES IN THE FORK QUEUE, THEN
; THE FIRST ENTRY IS REMOVED AND THE FORK ROUTINE IS EXECUTED. ELSE
; A CHECK IS MADE TO SEE IF REDISPATCHING OF THE PROCESSOR IS NECES-
; SARY. IF NOT, THEN REGISTERS R0 THRU R5 ARE RESTORED AND AN RTI
; IS EXECUTE      D. ELSE THE PROCESSOR IS REDISPATCHED AND THE EXIT
; SEQUENCE IS EXECUTED AGAIN.
;
; INPUTS: (MAPPED SYSTEM)
;
;	16(SP)=PS WORD PUSHED BY INTERRUPT OR TRAP.
;	14(SP)=PC WORD PUSHED BY INTERRUPT OR TRAP.
;	12(SP)=SAVED R5.
;	10(SP)=SAVED R4.
;	06(SP)=SAVED R3.
;	04(SP)=SAVED R2.
;	02(SP)=SAVED R1.
;	00(SP)=SAVED R0.
;
; INPUTS: (REAL MEMORY (SYSTEM)
;
;	06(SP)=SAVED R3.
;	04(SP)=SAVED R2.
;	01(SP)=SAVED R1.
;	00(SP)=SAVED R0.
;-

$DIRXT::MTPS	#PR7		;;;LOCK OUT INTERRUPTS
	MOV	$FRKHD,R3      	;;;ANYTHING IN FORK QUEUE
	BNE	20$		;;;IF NE YES
	TSTB	$CXDBL		;;;IS CONTEXT SWITCHING DISABLED?
	BEQ	31$		;;;IF EQ NO
	MOV	$TKTCB,R5	;;;PICK UP CURRECT TASK TCB
	TSTB	T.ST2(R5)	;;;TASK EXITING?			;MSH061
	BPL	4$		;;;IF PL NO				;**-1
	JMP	TEXIT		;;;INITIATE TASK EXIT
31$:				;;;REF LABEL
	MOV	$RQSCH,R5	;;;SCHEDULING REQUESTED?
	BNE	40$		;;;IF NE YES
4$:				;;;REF LABEL
	MOV	(SP)+,R0	;;;RESTORE REGISTERS R0 THRU R3
	MOV	(SP)+,R1	;;;
	MOV	(SP)+,R2	;;;
	MOV	(SP)+,R3	;;;
5$:				;;;REF LABEL
      
	.IF NDF	M$$MGE

	MOV	@$HEADR,SP	;;;RELOAD USER STACK POINTER

	.ENDC


10$:	INC	$STKDP		;;;INCREMENT STACK DEPTH
	MOV	(SP)+,R4	;;;RESTORE REGISTERS R4 AND R5
	MOV	(SP)+,R5	;;;

;+
; NONSENSE INTERRUPT ENTRY/EXIT
;-


	.IF NDF	E$$LOG							;DTB011
									;**-1
;
; IF ERROR LOGGING OF UNDEFINED INTERRUPTS IS NOT SUPPORTED,
; ALL UNUSED VECTORS POINT TO THE NONSENSE INTERRUPT ADDRESS.
;

$NS0::				;
$NS1::				;
$NS2::				;
$NS3::				;
$NS4::				;
$NS5::				;
$NS6::				;
$NS7::      				;

	.ENDC


$NONSI::RTI			;;;

;
; EXECUTE FORK ROUTINE
;
; FORK ROUTINES ARE ENTERED VIA A CALL WITH THE ARGUMENTS:
;
;	R3=ADDRESS OF THE BEGINNING OF THE FORK BLOCK+2.
;	R4=RESTORED FROM FORK BLOCK.
;	R5=RESTORED FROM FORK BLOCK.
;

20$:	MOV	(R3),$FRKHD	;;;REMOVE ENTRY FROM FORK QUEUE
	BNE	30$		;;;IF NE MORE ENTRIES
	MOV	#$FRKHD,$FRKHD+2 ;;;RESET FORK QUEUE LISTHEAD
30$:	MTPS	#0		;;;ALLOW INTERRUPTS
	ADD	#10,R3		;POINT PAST SAVED R4


	.IF DF	L$$DRV&M$$MGE!C$$INT&M$$MGE				;MSH      132
									;**-1
	MOV	(R3),KISAR5	;MAP DRIVER OR INTERRUPT SERVICE ROUTINE;MSH132
									;**-2
	.ENDC								;MSH132
									;**-1
	MOV	-(R3),R4	;RESTORE REGISTERS R4 AND R5
	MOV	-(R3),R5	;
	CALL	@-(R3)		;CALL FORK ROUTINE
	BR	$DIRXT		;TRY EXIT AGAIN				;**-8

;
; RESCHEDULING OR POWERFAIL
;

40$:	MTPS	#0		;;;ALLOW INTERRUPTS
	TST	$PWRFL		;POWER FAILURE?
	BEQ	RESCH		;IF EQ NO
	CALL	$POWER		;EXECUTE POWER RECOVERY ROUTINES
DIRXT:	BR	$DIRXT		;TRY EXIT AGAIN
	.DSABL	LSB

;
; RESCHED      ULING REQUESTED
;

	.ENABL LSB
RESCH:	CLR	$RQSCH		;CLEAR SCHEDULE REQUEST


	.IF NDF	M$$MGE

	MOV	$HEADR,R4	;GET ADDRESS OF CURRENT HEADER
	BEQ	5$		;IF EQ NO CURRENT TASK
	TST	@H.GARD(R4)	;STACK OVERFLOW?
	BEQ	5$		;IF EQ NO
	CLR	@H.GARD(R4)	;CLEAR HEADER GUARD WORD
	MOV	#S.CSST,R0	;SET SST ABORT-BAD STACK
	CALL	$ABCTK		;ABORT CURRENT TASK

	.ENDC


5$:	MOV	#T2.STP!T2.SPN!T2.WFR,R1 ;SET SUSPEND-WAITFOR MASK
	MOV	#T2.WFR,R4	;SET WAITFOR MASK
10$:	MOV	T.ST2(R5),R0	;GET CONTENTS OF SECOND       STATUS WORD	;MSH069
	MOV	T.STAT(R5),R2	;TASK BLOCKED?				;MSH069
	BNE	25$		;IF NE YES				;MSH069
									;**-3

	.IF DF	K$$AST!A$$TRP						;MSH091
									;**-1
	MOV	T.ASTL(R5),R2	;AST QUEUED?
	BEQ	20$		;IF EQ NO
	BIT	#T2.AST!T2.DST,R0 ;AST IN PROGRESS OR DISABLED?
	BEQ	70$		;IF EQ NO
									;MSH091
	.IF DF	K$$AST							;MSH091
									;MSH091
	TSTB	A.CBL(R2)	;KERNEL AST QUEUED?			;MSH091
	BMI	70$		;IF MI YES				;**-1
									;MSH091
	.ENDC	;K$$AST							;MSH091

	.IFTF

20$:	BIT	      R1,R0		;STOPPED, SUSPENDED OR IN WAITFOR?
	BEQ	60$		;IF EQ NO
	BIT	R4,R0		;IN WAITFOR?
	BEQ	30$		;IF EQ, NO
									;MSH069
	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
	.IFF								;MSH069
									;MSH069
	MOV	T.PCB(R5),R3	;GET PCB ADDRESS OF TASK PARTITION
	MOV	P.HDR(R3),R2	;POINT TO TASK HEADER
									;MSH069
	.IFTF								;MSH069
									;MSH069
	BIT	#T2.ABO,R0	;TASK MARKED FOR ABORT?			;MSH069
	BNE	50$		;IF NE YES, FINISH HIM OFF		;**-1
									;MSH069
	.IFF								;MSH069      
									;MSH069
	BIT	H.EFLM(R2),@H.EFLM+2(R2) ;WAITFOR SATISFIED?
									;MSH069
	.IFT								;MSH069
									;MSH069
	BIT	T.EFLM(R5),@T.EFLM+2(R5) ;WAITFOR SATISFIED?		;MSH069
									;MSH069
	.IFTF								;MSH069
									;MSH069
	BNE	50$		;IF NE YES
									;MSH046
	.IFT								;MSH046
									;MSH046
	BIT	#T2.SEF,R0	;TASK STOPPED FOR EVENT FLAG?		;MSH069
									;MSH046
	.IF DF	T$$BUF							;MSH046
									;MSH046
	BNE	22$		;IF NE YES				;MSH046
	TSTB	T.TIO(R5)	;OUTSTANDING       BUFFERED I/O?		;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
	BEQ	30$		;NO					;**-4
22$:	BIT	#T2.AST!T2.STP,R0 ;TASK ALREADY STOPPED OR AT AST?	;MSH046
	BNE	30$		;IF NE YES, DON'T STOP HIM.		;**-1
	MOV	R5,R0		;COPY TCB ADDRESS			;MSH046
	CALL	$STPTK		;STOP THE TASK				;**-1
									;MSH178
	.IF DF	D$$ISK							;MSH178
									;MSH178
	MOV	$RQSCH,R1	;WAS LOADER REQUESTED TO RUN?		;MSH178
	BEQ	5$		;IF EQ NO, OR CURRENTLY ABOVE LDR IN ATL;MSH178
	MOV	R1,R5		;COPY LOADER'S TCB      			;MSH178
	BR	RESCH		;RESTART ATL SCAN FROM LOADER'S POSITION;MSH178
									;MSH178
	.IFF								;MSH178
									;MSH178
	BR	5$		;RESET REGISTERS AND GO AGAIN
									;MSH178
	.ENDC								;MSH178

	.IFTF								;MSH069
									;MSH069
25$:									;MSH069
									;MSH069
	.IFT								;MSH069
									;MSH069
	BIC	#TS.CKP!TS.OUT,R2 ;TASK BLOCKED BY CHECKPOINT BITS ONLY?;MSH069
	BNE	30$		;IF NE NO, CANNOT REQUEST THIS TASK	;MSH069
	BIT	#T2.AST!T2.STP,R0 ;TASK STOPPED OR IN WAITFOR STA      TE?	;MSH172
									;MSH172
	.IF DF	A$$TRP							;MSH172
									;MSH172
	BMI	30$		;IF MI, STOPFOR STATE IMPOSSIBLE	;MSH172
									;MSH172
	.ENDC								;MSH172
									;MSH172
	BEQ	30$		;IF EQ, NO POINT IN UNSTOPPING ANYWAY	;MSH172
	BIT	#T2.SEF,R0	;TASK STOPPED FOR EVENT FLAG?		;MSH069
									;MSH069
	.IF DF	T$$BUF							;MSH069
									;MSH069
	BNE	27$		;IF NE YES				;MSH069
	TSTB	T.TIO(R5)	;OUTSTANDING BUFFERED I/O?		;MSH069
	BEQ	30$		;IF EQ NO				;MSH172
	BIT	#T2.WFR,R0	;TASK STO      PPED FOR BUFFERED I/O?		;MSH172
									;MSH069
	.ENDC								;MSH069
									;MSH069
	BEQ	30$		;IF EQ NO, DON'T UNSTOP TASK		;MSH069
27$:	BIT	T.EFLM(R5),@T.EFLM+2(R5) ;STOPFOR SATISFIED?		;MSH069
	BEQ	30$		;IF EQ NO, DON'T REQUEST TASK		;MSH069
	MOV	T.ACTL(R5),-(SP) ;GET ADDRESS OF NEXT TCB		;MSH069
	MOV	R5,R0		;COPY TASK TCB				;MSH069
	BIC	#T2.STP*2!T2.STP,T.ST2(R0) ;UNSTOP TASK			;MSH069
	CALL	$EXRQS		;REQUEST TASK TO RUN			;MSH069
	MOV	(SP)+,R5	;LOAD ADDRESS OF NEXT TCB		;MSH069
	BR	RESCH      		;CONTINUE SCAN OF ATL			;MSH069
									;MSH069
	.ENDC	;S$$TOP!T$$BUF						;MSH069
									;**-1
30$:	MOV	T.ACTL(R5),R5	;GET ADDRESS OF NEXT TCB
	BNE	10$		;IF NE OKAY

;
; EXECUTIVE IDLE LOOP
;
; THE EXECUTIVE IDLE LOOP IS ENTERED WHEN THERE ARE NO RUNNABLE TASKS.
; THE NULL TCB AT THE END OF THE TASK LIST IS ALWAYS GUARANTEED TO BE
; BLOCKED.  TWO FLAGS ARE SET FOR OTHER EXECUTIVE ROUTINES IN THE IDLE
; LOOP.
;
;    1.	THE ADDRESS OF THE NULL TCB (#$HEADR) IS SET INTO THE RESCHEDULE
;	P      OINTER ($RQSCH) TO PREVENT $DIRXT FROM EVER RETURNING TO SYSTEM
;	STATE WHILE THE EXEC IS IDLE.  THIS FORCES EXECUTION BACK TO THE
;	IDLE LOOP IN LIEU OF A REAL SCHEDULE REQUEST.
;
;   2.	AN IDLE FLAG IS SET ($IDLFL) FOR THE FORK ROUTINES TO CAUSE THEM
;	TO FORCE CONTROL BACK TO $DIRXT WHEN NECESSARY TO DEQUEUE A
;	FORK.  (IT IS IMPOSSIBLE FOR THE IDLE LOOP TO ALWAYS RETURN TO
;	$DIRXT WHEN NECESSARY BECAUSE OF A WINDOW BETWEEN THE CHECK OF
;	THE FORK LIST AND THE WAIT INSTRUCTION.)
;

	MOV	#$HEA      DR,$RQSCH	;PREVENT $DIRXT RETURN TO USER STATE
	MOV	#$IDLPT,R1	;POINT TO IDLE PATTERN WORD
	CLRB	$CURPR		;CLEAR CURRENT TASK PRIORITY
40$:				;REF LABEL


	.IF DF	P$$P45

	DECB	$IDLCT		;TIME TO MOVE PATTERN?
	BGE	45$		;IF GE NO
	MOVB	#4,$IDLCT	;RESET COUNT
	ASLB	(R1)+		;MOVE PATTERN ($IDLPT)
	RORB	(R1)		;($IDLPT+1)
	ADCB	-(R1)		;($IDLPT)
45$:	MOV	(R1),R0		;PUT IT WHERE IT CAN BE SEEN ($IDLPT)

	.ENDC


	INCB	-(R1)		;INDICATE IN IDLE STATE ($IDLFL)
	TST	$FRKHD		;FORK QUEUED SINCE LAST TIM      E IN $DIRXT?
	BNE	46$		;IF NE YES
	WAIT			;WAIT FOR INTERRUPT
	CLRB	(R1)+		;RESET IDLE FLAG ($IDLFL)
	BR	40$		;
46$:	CLRB	(R1)		;RESET IDLE FLAG ($IDLFL)
	BR	DIRXT		;BR TO DEQUEUE FORK ($DIRXT)

;
; WAITFOR SATISFIED-CLEAR WAIT STATE
;

50$:				;REF LABEL

	.IF DF G$$EFN

	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
	MOV	T.PCB(R5),R4	;GET TASK'S PCB ADDRESS			;MSH069
	MOV	P.HDR(R4),R4	;GET TASK'S HEADER ADDRESS		;MSH069
	MOV	T.EFLM+2(R5),R3	;GET WAITFOR MASK ADDRESS		;MSH069
				      					;MSH069
	.IFF								;MSH069
									;MSH069
	MOV	H.EFLM+2(R2),R3	;GET WAITFOR MASK ADDRESS		;MSH069
	MOV	R2,R4		;GET TASK'S HEADER ADDRESS		;MSH069
									;MSH069
	.ENDC								;MSH069
									;MSH069
	CALL	$DEAGF		;DEACCESS GROUP GLOBAL EF'S

	.ENDC	;G$$EFN

	DEC	T.ST2(R5)	;CLEAR WAITFOR STATE

	.IF DF	S$$TOP!T$$BUF						;MSH046
									;**-1
	BMI	60$		;IF MI, AT AST STATE
	BIC	#T2.SEF!T2.STP,T.ST2(R5) ;CLEAR STOPFOR STATE		;MSH046
									;MSH046
	.ENDC	;S$$TOP!T$$BUF						;      MSH046
									;**-3

;
; RESTART OR CONTINUE A TASK
;

60$:				;REF LABEL

	.IFT

	CLR	R4		;SET FLAG TO SIGNIFY RESTART OF TASK

	.ENDC


70$:	MOV	#H.DSW,R0	;POINT TO DIRECTIVE STATUS WORD
	MOVB	T.PRI(R5),$CURPR ;SET CURRENT TASK PRIORITY
	MOV	$HEADR,R3	;GET ADDRESS OF CURRENT TASK HEADER
	BEQ	80$		;IF EQ NO CURRENT TASK
	CMP	R5,$TKTCB	;NEW TASK SAME AS CURRENT?
	BNE	73$		;IF NE NO
	JMP	130$		;NO CONTEXT SWITCH NECESSARY

;
; SAVE CONTEXT OF CURRENT TASK
;

73$:	MOV	H.GARD(R3),      R2	;POINT TO HEADER GUARD WORD
	MOV	SP,R1		;POINT TO SAVED R0
	MOV	(R1)+,-(R2)	;SAVE R0
	MOV	(R1)+,-(R2)	;SAVE R1
	MOV	(R1)+,-(R2)	;SAVE R2
	MOV	(R1)+,-(R2)	;SAVE R3


	.IF DF	M$$MGE

	MOV	(R1)+,-(R2)	;SAVE R4
	MOV	(R1)+,-(R2)	;SAVE R5
	MOV	(R1)+,-(R2)	;SAVE PC
	MOV	(R1),-(R2)	;SAVE PS
	MFPI	SP		;GET USER STACK POINTER
	MOV	(SP)+,(R3)	;SAVE USER STACK POINTER IN HEADER

	.IFF


	.IF DF	E$$EAE

	MOV	H.FPSA(R3),R2	;POINT TO EAE SAVE AREA
	BEQ	75$		;IF EQ TASK DOES NOT USE EAE
	MOV	SC,(      R2)+	;SAVE EAE REGISTERS
	MOV	AC,(R2)+	;
	MOV	MQ,(R2)		;

	.ENDC


	.IFTF

75$:	MOV	(R0),H.DSW(R3)	;SAVE DIRECTIVE STATUS WORD


	.IF DF	F$$LPP

	MOV	H.FPSA(R3),R2	;POINT TO FLOATING POINT SAVE AREA
	BEQ	80$		;IF EQ TASK DOES NOT USE FLOATING POINT
	TST	$HFMSK		;FLOATING POINT PROCESSOR PRESENT?	;MSH149
	BMI	80$		;IF MI NO, DON'T SAVE FPP CONTEXT	;MSH149


	.IF DF	M$$MGE

	MOV	$TKTCB,R3	;GET TCB ADDRESS OF CURRENT TASK
									;MSH140
	.IF DF	A$$HDR							;MSH140
									;MSH140
      	TSTB	T.HDLN(R3)	;EMULATOR TASK?				;MSH140
	BNE	78$		;IF NE YES, SAVE AREA IN HEADER		;MSH140
									;MSH140
	.ENDC								;MSH140
									;MSH140
	MOV	T.PCB(R3),R1	;GET ADDRESS OF TASK PARTITION PCB
	MOV	P.REL(R1),KISAR6 ;MAP TO TASK PARTITION


	.IF DF	P$$LAS

	ADD	T.OFF(R3),KISAR6 ;ADD IN OFFSET TO TASK IMAGE

	.ENDC

78$:				;					;MSH140

	.ENDC


	STFPS	(R2)+		;SAVE FLOATING POINT STATUS
	SETD			;SET FLOATING DOUBLE MODE
	STD	R0,(R2)+	;SAVE FIRST FL. POINT ACCUMULATOR (FACC);      MSH134
	LDD	R4,R0		;MOVE FIFTH FACC TO FIRST FACC		;MSH134
	STD	R0,(R2)+	;SAVE FIFTH FACC			;MSH134
	LDD	R5,R0		;MOVE SIXTH FACC TO FIRST FACC		;MSH134
	STD	R0,(R2)+	;SAVE SIXTH FACC			;MSH134
	STD	R1,(R2)+	;SAVE SECOND FACC			;MSH134
	STD	R2,(R2)+	;SAVE THIRD FACC			;MSH134
	STD	R3,(R2)+	;SAVE FOURTH FACC			;MSH134
									;**-8
	.ENDC


;
; LOAD CONTEXT OF NEW TASK
;

80$:	MOV	R5,$TKTCB	;SET ADDRESS OF NEW TCB
	MOV	T.PCB(R5),R3	;GET ADDRESS OF TASK PARTITION PCB
	MOV	P.HDR(R3),R2	;GET A      DDRESS OF TASK HEADER
	MOV	R2,$HEADR	;SET ADDRESS OF TASK HEADER

	.IFT


	.IF DF	C$$CKP&T$$BUF!A$$TRP!P$$OFF

	MOV	R4,-(SP)	;SAVE EFFECT AST FLAG

	.ENDC


	MOV	H.WND(R2),R4	;POINT TO NUMBER OF WINDOW BLOCKS
	TST	W.BLVR+2(R4)	;IS TASK MAPPED TO THE EXEC?
	BEQ	85$		;IF EQ NO

	.IFTF

	MOV	R2,R1		;COPY ADDRESS OF TASK HEADER
	ADD	R0,R1		;POINT TO DIRECTIVE STATUS WORD
	MOV	(R1)+,(R0)+	;RESTORE DIRECTIVE STATUS WORD
	MOV	(R1)+,(R0)+	;RESTORE POINTER TO FCS IMPURE AREA
	MOV	(R1)+,(R0)+	;      RESTORE POINTER TO FORTRAN IMPURE AREA
	MOV	(R1)+,(R0)+	;RESTORE POINTER TO OVERLAY IMPURE AREA
	MOV	(R1)+,(R0)+	;RESTORE PTR TO VECTOR OF IMPURE PTRS

	.IFT

	MOV	#UISDR0,R0	;POINT TO USER DESCRIPTOR REGISTER 0
	MOV	#77406,(R0)	;SETUP PRIVILEGED TASK DESCRIPTOR REGISTERS
	MOV	(R0)+,(R0)	;
	MOV	(R0)+,(R0)	;
	MOV	(R0)+,(R0)	;


	.IF DF	R$$EXV

	MOV	(R0)+,(R0)	;

	.ENDC


	MOV	(R0),UISDR0+14.	;ALLOW FULL ACCESS TO I/O PAGE
	MOV	#UISAR0,R1	;POINT TO USER ADDRESS REGISTER 0
	MOV	#KISAR0,R0      	;POINT TO KERNAL ADDRESS REGISTER 0
	MOV	(R0)+,(R1)+	;SETUP PRIVILEGED TASK ADDRESS REGISTERS
	MOV	(R0)+,(R1)+	;
	MOV	(R0)+,(R1)+	;


	.IF DF	R$$EXV

	MOV	(R0)+,(R1)+	;

	.ENDC


	MOV	(R0),(R1)	;
	MOV	#177600,UISAR0+14. ;SET ADDRESS REGISTER 7 FOR I/O PAGE
	BR	90$		;
85$:	MOV	#UISDR0,R0	;POINT TO USER DESCRIPTOR REGISTER 0
	CLR	(R0)+		;CLEAR ALL USER DESCRIPTOR REGISTERS
	CLR	(R0)+		;
	CLR	(R0)+		;
	CLR	(R0)+		;
	CLR	(R0)+		;
	CLR	(R0)+		;
	CLR	(R0)+		;
	CLR	(R0)		;
90$:	MOV	(R4)+,      -(SP)	;PUSH NUMBER OF WINDOW BLOCKS
100$:	ADD	#W.BLGH,R4	;POINT PAST CURRENT WINDOW BLOCK
	MOV	-W.BLGH(R4),R3	;PICK UP NEXT PCB ADDRESS
	BEQ	115$		;IF EQ WINDOW IS NOT MAPPED
	CMP	-(R4),-(R4)	;POINT TO FIRST PDR ADDRESS
	MOV	P.REL(R3),R0	;PICK UP PARTITION RELOCATION BIAS


	.IF DF	P$$LAS!A$$HDR						;MSH096
									;**-1
	ADD	-2(R4),R0	;ADD IN WINDOW OFFSET

	.ENDC


	MOVB	(R4)+,R1	;POINT TO FIRST PDR
	MOVB	(R4)+,R3	;PICK UP NUMBER OF PDR'S TO LOAD
110$:	MOVB	(R4),(R1)+	;SET USER DESCRIPT      OR ACCESS CODE
	MOVB	#177,(R1)+	;SET BLOCK LENGTH
	MOV	R0,UISAR0-UISDR0-2(R1) ;LOAD USER ADDRESS REGISTER
	ADD	#200,R0		;ADVANCE TO NEXT 4K BOUNDARY
	DEC	R3		;ANY MORE TO LOAD?
	BGT	110$		;IF GT NO
	MOV	(R4)+,-(R1)	;LOAD LAST USER DESCRIPTOR REGISTER
115$:	DEC	(SP)		;ANY MORE WINDOW BLOCKS?
	BGT	100$		;IF GT YES
	MOV	(R2),(SP)	;LOAD USER STACK POINTER
	MTPI	SP		;


	.IF DF	C$$CKP&T$$BUF!A$$TRP!P$$OFF

	MOV	(SP)+,R4	;RESTORE EFFECT AST INDICATOR

	.ENDC


	.IFF


	.IF DF	E$$EAE

	MOV      	H.FPSA(R2),R0	;POINT TO EAE SAVE AREA
	BEQ	120$		;IF EQ TASK DOES NOT USE EAE
	CMP	(R0)+,(R0)+	;POINT TO SAVED MQ REGISTER
	MOV	(R0),MQ		;RESTORE EAE REGISTERS
	MOV	-(R0),AC	;
	MOV	-(R0),SC	;

	.ENDC


	.IFTF


	.IF DF	F$$LPP

	MOV	H.FPSA(R2),R0	;POINT TO FLOATING POINT SAVE AREA
	BEQ	120$		;IF EQ TASK DOES NOT USE FLOATING POINT
	TST	$HFMSK		;FLOATING POINT PROCESSOR PRESENT?	;MSH149
	BMI	120$		;IF MI NO, DON'T RESTORE FPP CONTEXT	;MSH149


	.IF DF	M$$MGE

	.IF DF	A$$HDR							;MSH1      40
									;MSH140
	TSTB	T.HDLN(R5)	;EMULATOR TASK?				;MSH140
	BNE	118$		;IF NE YES, SAVE AREA IN HEADER		;MSH140
									;MSH140
	.ENDC								;MSH140
									;MSH140
	MOV	T.PCB(R5),R1	;GET ADDRESS OF TCB OF NEXT TASK
	MOV	P.REL(R1),KISAR6 ;MAP TO TASK PARTITION


	.IF DF	P$$LAS

	ADD	T.OFF(R5),KISAR6 ;ADD IN OFFSET TO TASK IMAGE

	.ENDC

118$:				;					;MSH140

	.ENDC


	TST	(R0)+		;POINT TO SAVED FLOATING POINT REGISTERS
	LDFPS	#200		;SET DOUBLE MODE - CLEAR EXCEPTION INTS.;MSH      134
	LDD	(R0)+,R0	;LOAD FIRST FACC			;MSH134
	LDD	(R0)+,R1	;LOAD FIFTH FACC INTO SECOND FACC	;MSH134
	STD	R1,R4		;MOVE FIFTH FACC INTO POSITION		;MSH134
	LDD	(R0)+,R1	;LOAD SIXTH FACC INTO SECOND FACC	;MSH134
	STD	R1,R5		;MOVE SIXTH FACC INTO POSITION		;MSH134
	LDD	(R0)+,R1	;LOAD SECOND FACC			;MSH134
	LDD	(R0)+,R2	;LOAD THIRD FACC			;MSH134
	LDD	(R0)+,R3	;LOAD FOURTH FACC			;MSH134
	LDFPS	@H.FPSA(R2)	;RESTORE FLOATING POINT STATUS		;**-9

	.ENDC


120$:	MOV	H.GARD(R2),R0	;POINT TO HEADER GUAR      D WORD
	MOV	SP,R1		;POINT TO CURRENT CONTEXT
	MOV	-(R0),(R1)+	;RESTORE R0
	MOV	-(R0),(R1)+	;RESTORE R1
	MOV	-(R0),(R1)+	;RESTORE R2
	MOV	-(R0),(R1)+	;RESTORE R3

	.IFT

	MOV	-(R0),(R1)+	;RESTORE R4
	MOV	-(R0),(R1)+	;RESTORE R5
	MOV	-(R0),(R1)+	;RESTORE PC
	MOV	-(R0),(R1)	;RESTORE PS

	.ENDC


130$:				;REF LABEL


;									;MSH091
; AST CONTROL BLOCKS:							;MSH091
;									;MSH091
; AST CONTROL BLOCKS FALL INTO SEVERAL DISTINCT CATEGORIES BASED	;MSH091
; UPON THE VALUE OF A.CBL.       THE FORMATS OF A.CBL ARE AS FOLLOWS:		;MSH091
;									;MSH091
;	A.CBL+1		A.CBL			DESCRIPTION		;MSH091
;	-------		-----			-----------		;MSH091
;									;MSH091
;	  0		 0	AST DEQUEUED BY A SYSTEM SUBROUTINE. THE;MSH091
;				ROUTINE IS MAPPED BY THE CONTENTS OF	;MSH091
;				A.KSR5 AND CALLED VIA THE ADDRESS IN	;MSH091
;				A.DQSR. DEALLOCATION OF THE CONTROL	;MSH091
;				BLOCK IS THE RESPONSIBILITY OF THE	;MSH091
;				DEQUEUE ROUTINE. AN EXAMPLE IS THE	;MSH091
;				PROCESSING OF UNSOLICITED INPUT       ASTS	;MSH091
;				BY THE FULL DUPLEX TERMINAL DRIVER.	;MSH091
;									;MSH091
;	  N		 0	SPECIFIABLE AST CONTROL BLOCK OF LENGTH	;MSH091
;				C.LGTH. N IS THE SPECIFIED AST TYPE.	;MSH091
;				THESE BLOCKS ARE RELINKED IN THE T.SAST	;MSH091
;				LIST AFTER THE AST IS DECLARED (EXCEPT	;MSH091
;				FOR REQUESTED EXIT ASTS, WHICH ARE	;MSH091
;				DEALLOCATED AFTER USE BY A NON-PRIVILEGE;MSH091
;				TASK).					;MSH091
;									;MSH091
;	  0		 >0	DYNAMIC AST CONTROL BLOCK (I/O COMPLETIO;MSH091
;			      	MARK TIME) OF LENGTH A.CBL. AFTER THE	;MSH091
;				PARAMETERS ARE MOVED TO THE TASK STACK	;MSH091
;				AND THE AST EFFECTED THE BLOCK IS	;MSH091
;				DEALLOCATED.				;MSH091
;									;MSH091
;	  X		 <0	KERNEL AST CONTROL BLOCK. BIT 6 IS SET	;MSH091
;				IF $SGFIN SHOULD NOT BE CALLED PRIOR TO	;MSH091
;				EXECUTING THE KERNEL AST CODE. BITS	;MSH091
;				0 THROUGH 5 REPRESENT A WORD INDEX	;MSH091
;				INTO A KERNEL AST DISPATCH TABLE.	;MSH091
;				DEALLOCATION OF THE CONTROL BLOCK IS	;MSH091
;		      		THE RESPONSIBILITY OF THE PROCESSING	;MSH091
;				ROUTINE. KERNEL ASTS EFFECT EXECUTIVE	;MSH091
;				LEVEL FUNCTIONS THAT MUST OCCUR AFTER	;MSH091
;				THE TASK'S CONTEXT IS RELOADED. AN	;MSH091
;				EXAMPLE IS BUFFERED I/O COMPLETION.	;MSH091
;									;MSH091
									;MSH091
	.IF DF	K$$AST!A$$TRP						;MSH091
									;**-1
	TST	R4		;EFFECT AST?
	BEQ	190$		;IF EQ NO
	MOV	R5,R0		;CALCULATE ADDRESS OF AST LISTHEAD
	ADD	#T.ASTL,R0	;
	CALL	$QRMVF		;REMOVE AST ENTRY FROM QUEUE


	.IF DF	K$$A      ST							;MSH091
									;**-1
	MOVB	A.CBL(R1),R4	;KERNEL AST?				;MSH091
	BMI	210$		;IF MI YES				;**-1

	.ENDC


	.ENDC


	.IF DF	A$$TRP

	MOV	R5,R4		;CALCULATE ADDRESS OF STATUS WORD
	ADD	#T.ST2,R4	;
	MOVB	(R4),-(SP)	;COPY CURRENT EXTENSION BYTE
	BIC	#^C<T2.STP!T2.SPN!T2.WFR>,(SP) ;CLEAR ALL BUT WAIT STATE
	ASL	(SP)		;SHIFT INTO POSITITON FOR SAVE
	BIC	#<T2.STP!T2.SPN!T2.WFR>*2!T2.STP!T2.SPN!T2.WFR,(R4) ;
	BIS	(SP)+,(R4)	;SAVE WAIT STATE
	BIS	#T2.AST,(R4)	;SET AST IN PROGRESS
	MOV	R      1,R3		;COPY AST CONTROL BLOCK ADDRESS
	MOV	R3,-(SP)	;SAVE AST CONTROL BLOCK ADDRESS
	CMP	(R3)+,(R3)+	;POINT TO NUMBER OF BYTES TO ALLOCATE
	MOV	$HEADR,R4	;POINT TO TASK HEADER


	.IF DF	M$$MGE

	MFPI	SP		;GET CURRENT STACK POINTER
	MOV	(SP)+,R0	;

	.IFF

	MOV	(R4),R0		;GET CURRENT STACK POINTER

	.ENDC


	MOV	(R3)+,R1	;GET NUMBER OF BYTES TO ALLOCATE ON TASK STACK
	SUB	R1,R0		;CALCULATE NEW TOP OF STACK


	.IF DF	A$$CHK!M$$MGE

	CALL	$ACHCK		;ADDRESS CHECK STACK SPACE
	BCS	160$		;IS       CS ADDRESS CHECK FAILURE

	.ENDC


	.IF DF	M$$MGE

	MOV	R0,-(SP)	;SET NEW TASK STACK POINTER
	MTPI	SP		;
	CALL	$RELOM		;RELOCATE AND MAP STACK ADDRESS
	MOV	SP,R1		;CALCULATE ADDRESS OF TRAP PC
	ADD	#7*2,R1		;

	.IFF

	MOV	(R4),R1		;RETRIEVE OLD TOP OF STACK
	MOV	R0,(R4)		;SET NEW TASK STACK POINTER
	MOV	(R1)+,(R0)+	;MOVE SAVED R4
	MOV	(R1)+,(R0)+	;MOVE SAVED R5
	MOV	(R3)+,(R0)+	;SET AST TRAP PC
	CLR	(R0)+		;SET AST TRAP PS

	.IFTF

	MOV	(R1)+,-(SP)	;SAVE PC AT TRAP
	MOV	(R1),R2		;S      AVE PS AT TRAP

	.IFT

	MOV	#CMODE!PMODE,(R1) ;SET AST TRAP PS
	MOV	(R3)+,-(R1)	;SET AST TRAP PC

	.IFTF

	MOV	(R3)+,-(SP)	;GET NUMBER OF PARAMETERS TO MOVE
140$:	DEC	(SP)		;ANY MORE PARAMETERS TO MOVE?
	BLT	150$		;IF LT NO
	MOV	(R3)+,(R0)+	;MOVE PARAMETER TO USER STACK
	BR	140$		;
150$:	TST	(SP)+		;CLEAN STACK

	.IFF

	MOV	@.DSW,(R0)+	;MOVE DSW TO TASK STACK

	.IFT

	MFPI	@#H.DSW		;GET USER DSW
	MOV	(SP)+,(R0)+	;MOVE DSW TO TASK STACK

	.ENDC


	MOV	(SP)+,(R0)+	;MOVE PC AT TRAP       TO TASK STACK
	MOV	R2,(R0)+	;MOVE PS AT TRAP TO TASK STACK
									;MSH069
	.IF DF	S$$TOP!T$$BUF						;MSH069
									;MSH069
	MOV	T.EFLM(R5),(R0)	;SAVE WAITFOR MASK WORD			;MSH069
	MOV	T.EFLM+2(R5),H.EFSV(R4) ;SAVE WAITFOR MASK ADDRESS	;MSH069
									;MSH069
	.IFF								;MSH069
									;MSH069
	MOV	H.EFLM(R4),(R0)	;SAVE WAITFOR MASK WORD
	MOV	H.EFLM+2(R4),H.EFSV(R4) ;SAVE WAITFOR MASK ADDRESS
									;MSH069
	.ENDC								;MSH069


	.IF DF	A$$CHK!M$$MGE

	BR	170$		;TAKE COMMON EXIT      
160$:	MOV	#S.CAST,R0	;SET AST ABORT
	CALL	$ABCTK		;ABORT CURRENT TASK

	.ENDC


170$:	MOV	(SP)+,R0	;RETRIEVE AST CONTROL BLOCK ADDRESS
	MOV	A.CBL(R0),R1	;GET LENGTH OF BLOCK TO RELEASE
	BNE	175$		;JUMP IF NON-ZERO

	.IF DF	M$$MGE

	CMP	-(R0),-(R0)	;ZERO - POINT TO A.KSR5
	MOV	(R0)+,KISAR5	;MAP DEQUEUE SUBROUTINE IN APR 5
	CALL	@(R0)+		;CALL DEQUEUE SUBROUTINE

	.IFF

	CALL	@-2(R0)		;CALL DEQUEUE SUBROUTINE

	.ENDC

	BR	200$		;EXIT
175$:	TSTB	R1		;LENGTH NON-ZERO?
	BNE	180$		;Y - JU      MP
									; MF208
	.IF DF	A$$CLI							; MF208
									; MF208
	CMP	R1,#<AS.CAA*256.> ;COMMAND ARRIVAL AST FOR CLI		; MF208
	BNE	176$		;IF NE NO				; MF208
	TST	A.PRM+2(R0)	;SHOULD AST BLOCK BE DEALLOCATED	; MF208
	BNE	178$		;IF NE NO				; MF208
									; MF208
									; MF208
	.IF DF	A$$BRT							; MF208
									; MF208
	BR	1765$		;DEALLOCATE AST BLOCK			; MF208
									; MF208
	.IFF	;A$$BRT							; MF208
									; MF208
	CALL	$DECLK		;DEALLOCATE AST BLOCK			; MF208
	BR	200$		;TRY       EXIT AGAIN				; MF208
									; MF208
	.ENDC	;A$$BRT							; MF208
176$:									; MF208
	.ENDC	;A$$CLI							; MF208
									; MF208
									;MSH121
	.IF DF	A$$BRT							;MSH121
									;MSH121
	CMP	R1,#<AS.REA*256.> ;REQUESTED EXIT AST?			;MSH121
	BNE	178$		;IF NE NO				;MSH121
	BIT	#T3.PRV,T.ST3(R5) ;TASK PRIVILEGED?			;MSH121
	BNE	177$		;IF NE YES, ALLOW RESPECIFICATION	;MSH121
1765$:	CALL	$DECLK		;DEALLOCATE AST CONTROL BLOCK		;MSH121
	BR	200$		;TRY EXIT AGAIN				;MSH121
177$:	BIC	#T      2.REX,T.ST2(R5) ;ALLOW AST RESPECIFICATION		;MSH121
									;MSH121
	.ENDC								;MSH121
									;MSH121
178$:	MOV	T.SAST(R5),(R0)	;LINK SPEC AST CONTROL BLOCK ONTO	;MSH121
	MOV	R0,T.SAST(R5)	; SPEC AST LISTHEAD			;**-1
	BR	200$		;TRY EXIT AGAIN
180$:	CALL	$DEACB		;DEALLOCATE CONTROL BLOCK
	BR	200$		;TRY EXIT AGAIN

	.ENDC


190$:	TSTB	T.ST2(R5)	;TASK BEING HALTED?
	BPL	200$		;IF PL NO
TEXIT:	CALL	$DREX1		;FORCE TASK EXIT			;MSH115
200$:	JMP	$DIRXT		;					;**-1

;									;MSH091
; KER      NEL AST DISPATCHING						;MSH091
;									;MSH091
									;MSH091
	.IF DF	K$$AST							;MSH091
									;**-1
210$:	MOV	#$DIRXT,-(SP)	;SET RETURN ADDRESS
	MOV	R1,R0		;SET ADDRESS OF AST CONTROL BLOCK
	ASLB	R4		;CONVERT AST CODE TO NEGATIVE BYTE INDEX;MSH091
	BMI	215$		;IF MI DO NOT CALL $SGFIN		;MSH091
									;MSH091
	.IF DF	A$$BIO!P$$OFF						;MSH091
									;MSH091
	CALL	$SGFIN		;INGNORE SEGMENT FAULTS			;MSH091
									;MSH091
	.ENDC								;MSH091
									;MSH091
	JMP	@<KTBL+256.>      (R4) ;DISPATCH KERNEL AST (NO $SGFIN BIT)	;MSH091
215$:	JMP	@<KTBL+128.>(R4) ;DISPATCH KERNEL AST (W/ $SGFIN BIT)	;MSH091
									;MSH091
KTBL:	KAST	$FINBF,A$$BIO!C$$CKP&T$$BUF ;TERM I/O COMPLETION (AK.BUF;MSH199
	KAST	$FINXT,P$$OFF		;OFFSPRING EXIT STATUS (AK.OCB)	;MSH091
	KAST	$GENBF,T$$BUF&A$$BIO	;GENERAL BUFFERED I/O (AK.GBI)	;MSH091
	KAST	$GGFRN,P$$SRF&G$$EFN	;GROUP GLOBAL RUNDOWN (AK.GGF)	;MSH183
									;MSH091
CRSH:	CRASH				;CRASH, ILLEGAL KERNEL AST TYPE	;MSH091
									;MSH091
	.ENDC      								;MSH091
									;MSH091
	.DSABL	LSB							;MSH091
									;MSH183
	.IF DF	P$$SRF&G$$EFN						;MSH183
									;MSH183
;+									;MSH183
; **-$GGFRN-GROUP GLOBAL EVENT FLAG USE COUNT RUNDOWN			;MSH183
;									;MSH183
; DEACCESS THIS TASK'S GROUP GLOBAL EVENT FLAGS IF THE EVENT FLAG	;MSH183
; MASK IN THE AST CONTROL BLOCK IS GROUP GLOBAL, AND DEALLOCATE		;MSH183
; THE AST CONTROL BLOCK.						;MSH183
;									;MSH183
; INPUTS:								;MSH183
;									;MSH183
;	R0=ADDRESS OF THE KE      RNEL AST CONTROL BLOCK			;MSH183
;									;MSH183
; OUTPUTS:								;MSH183
;									;MSH183
;	THE GROUP GLOBAL EVENT FLAGS ARE DEACCESSES AND THE CONTROL	;MSH183
;	BLOCK IS DEALLOCATED.						;MSH183
;									;MSH183
; FORMAT OF THE AST CONTROL BLOCK:					;MSH183
;									;MSH183
;	WD.00 -- UNKNOWN						;MSH183
;	WD.01 -- KERNEL AST TYPE = AK.GGF				;MSH183
;	WD.02 -- UNKNOWN						;MSH183
;	WD.04 -- EVENT FLAG MASK ADDRESS				;MSH183
;	WD.05 THRU WD.17 -- UNKNOWN					;MSH183
;									;MSH      183
;-									;MSH183
									;MSH183
$GGFRN::MOV	$HEADR,R4	;GET CURRENT TASK'S HEADER ADDRESS	;MSH183
	MOV	R0,-(SP)	;SAVE CONTROL BLOCK ADDRESS		;MSH183
	MOV	6(R0),R3	;GET EVENT FLAG MASK ADDRESS		;MSH183
	CALL	$DEAGF		;DEACCESS IF GROUP GLOBAL		;MSH183
	MOV	(SP)+,R0	;RESTORE CONTROL BLOCK ADDRESS		;MSH183
	CALL	$DEPKT		;DEALLOCATE THE CONTROL BLOCK		;MSH183
	CALLR	$SETRT		;MAKE SURE ALL KERNEL ASTS ARE FOUND	;MSH183
									;MSH183
	.ENDC	;P$$SRF&G$$EFN						;MSH183
									;MSH091
	.IF D      F	P$$OFF							;MSH091
									;**-24

;+
; **-$FINXT-FINISH OFFSPRING TASK EXIT PROCESSING
;
; QUEUE AST AND RETURN EXIT STATUS TO A PARENT TASK ONCE THAT TASK
; HAS BEEN SCHEDULED. $SGFIN HAS BEEN CALLED.				;MSH091
;									;**-1
; INPUTS:
;
;	R0=ADDRESS OF OFFSPRING CONTROL BLOCK.
;
; OUTPUTS:
;
;	ALL EXIT CONDITIONS ARE EFFECTED AND THE OFFSPRING CONTROL BLOCK
;	IS DEALLOCATED IF IT IS NOT USED AS AN AST CONTROL BLOCK.
;-

$FINXT::MOV	R0,R3		;COPY OCB POINTER
	MOV	R0,R4		;COPY OCB       POINTER
	TST	(R3)+		;SKIP OVER LINK WORD (O.LNK)
	MOV	#O.LGTH,(R3)+	;SET LENGTH TO DEALLOCATE (O.LNK=A.CBL)
	MOV	(R3),R5		;PICK UP PARENT TCB ADDR (O.PTCB=A.BYT)
	MOV	#8.*2,(R3)+	;BYTES ON USER STACK (O.PTCB=A.BYT)
	TST	(R3)+		;SKIP OVER AST WORD (O.AST=A.AST)
	MOV	(R3),R0		;PICK UP EFN NUMBER (O.EFN=A.NPR)
	CALL	$SETFG		;SET EFN AND UNLOCK IF GRP GLOBAL	;MSH049
	MOV	#1,(R3)		;SET NUMBER OF AST PARMS (O.EFN=A.NPR)	;MSH129
	MOV	(R3)+,R2	;ASSUME EXIT STATUS BLOCK LENGTH=1 WORD	;MSH129
	MOV	(R3),R0	      	;PICK UP VIRTUAL EXB ADDR (O.ESB=A.PRM)	;MSH129
	ASR	R0		;FULL LENGTH EXIT STATUS BLOCK?		;MSH129
	BCC	35$		;IF CC NO, 1 WORD LONG			;MSH129
	MOV	#8.,R2		;SET UP FOR FULL LENGTH EXIT STATUS BLK	;MSH129
35$:	ASL	R0		;RESTORE EXIT STATUS BLOCK ADDRESS	;MSH129
	MOV	R0,(R3)+	;RESTORE CORRECTED ESB ADDRESS		;MSH129
	BEQ	40$		;IF EQ THERE IS NONE			;**-3
37$:				;REF LABEL				;MSH129
									;MSH092
	.IF DF	M$$MGE							;MSH092
									;MSH092
	MOV	(R3)+,-(SP)	;PICK UP NEXT WORD OF STATUS		;MSH129
      	MTPI	(R0)+		;STORE WORD IN USER BUFFER (CAN TRAP)	;MSH129
									;MSH092
	.IFF								;MSH092
									;MSH092
	MOV	(R3)+,(R0)+	;STORE WORD IN USER BUFFER		;MSH129
									;MSH092
	.ENDC								;MSH092
									;MSH092
	DEC	R2		;DONE TRANSFERRING EXIT STATUS BLOCK?	;MSH129
	BGT	37$		;IF GT NO				;MSH129
40$:				;REF LABEL				;MSH126
									;MSH126
	.IF DF	A$$TRP							;MSH126
									;MSH126
	TST	O.AST(R4)	;EFFECT AST?				;MSH126
	BEQ	50$		;IF EQ NO				;**-3
	MOV	R5,R0		;SET PARENT TC      B ADDRESS
	MOV	R4,R1		;SET AST BLOCK ADDRESS
	CALLR	$QASTT		;QUEUE AST FOR PARENT AND RETURN
									;MSH126
	.ENDC								;MSH126
									;MSH126
50$:	MOV	R4,R0		;POINT TO BLOCK TO RELEASE
	MOV	#O.LGTH,R1	;PICK UP SIZE TO RELEASE
	CALL	$DEACB		;DEALLOCATE OCB
	CALLR	$SETRT		;INSURE RESCAN OF TASK

	.ENDC	;P$$OFF



	.IF DF	T$$BUF&A$$BIO						;MSH091
									;MSH091
;+									;MSH091
; **-$GENBF-GENERAL BUFFERED I/O COMPLETION				;MSH091
;									;MSH091
; THIS ROUTINE IS CALLED TO       TRANSFER KERNEL AST CONTROL TO A DRIVER	;MSH091
; FOR PROCESSING OF FUNCTIONS WHICH MUST BE DONE WITH TASK CONTEXT	;MSH091
; LOADED. THE KERNEL AST CONTROL BLOCK IS STRUCTURED AS FOLLOWS:	;MSH091
;									;MSH091
;	WD. 00 -- LINK WORD						;MSH091
;	WD. 01 -- KERNEL AST TYPE (A.CBL=AK.GBI)			;MSH091
;	WD. 02 -- SUBROUTINE KISAR5 BIAS				;MSH091
;	WD. 03 -- SUBROUTINE ADDRESS					;MSH091
;									;MSH091
; $SGFIN HAS BEEN CALLED.						;MSH091
;									;MSH091
; INPUTS:								;MSH091
;								      	;MSH091
;	R0=ADDRESS OF KERNEL AST CONTROL BLOCK				;MSH091
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK			;MSH091
;									;MSH091
; OUTPUTS:								;MSH091
;									;MSH091
;-									;MSH091
									;MSH091
									;MSH091
$GENBF::SAVNR			;SAVE NONVOLITILE REGISTERS		;MSH091
	MOV	R0,R3		;COPY AST CONTROL BLOCK ADDRESS		;MSH091
	CALL	$SETRT		;FORCE REDISPATCHING OF PROCESSOR	;MSH091
	MOV	4(R3),KISAR5	;MAP DRIVER ACCEPTANCE ROUTINE		;MSH091
	CALLR	@6(R3)		;CALL DRIVER ACCEPTANCE ROUTINE		;      MSH091
									;MSH091
	.ENDC	;T$$BUF&A$$BIO						;MSH091
									;MSH091
	.IF DF	A$$BIO!C$$CKP&T$$BUF					;MSH199
									;MSH046
;+									;MSH046
; **-$FINBF-FINISH TERMINAL BUFFERED I/O				;MSH046
;									;MSH046
; THIS ROUTINE IS CALLED TO COMPLETE A BUFFERED TERMINAL REQUEST	;MSH046
; THAT HAS BEEN PLACED IN THE AST QUEUE AS A KERNEL AST (TYPE=AK.BUF).	;MSH046
; $SGFIN HAS BEEN CALLED.						;MSH046
;									;MSH046
; INPUTS:								;MSH046
;									;MSH046
;	R0=ADDRESS OF I/O PA      CKET					;MSH046
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK			;MSH046
;									;MSH046
;	THE RELEVENT FIELDS IN THE I/O PACKET ARE AS FOLLOWS:		;MSH046
;									;MSH046
;	I.PRM+00 - KISAR6 BIAS FOR USER I/O BUFFER			;MSH046
;	I.PRM+02 - STARTING ADDRESS OF USER I/O BUFFER			;MSH046
;	I.PRM+04 -							;MSH046
;	I.PRM+06 - FINAL I/O STATUS (FIRST WORD OF IOSB)		;MSH046
;	I.PRM+10 - NUMBER OF BYTES TRANSFERRED (SECOND WORD OF IOSB)	;MSH046
;	I.PRM+12 - FIRST TRANSFER BUFFER ADDRESS			;MSH046
;	I.      PRM+14 -							;MSH046
;	I.PRM+16 - USER BUFFER PCB ADDRESS				;MSH046
;									;MSH046
; OUTPUTS:								;MSH046
;									;MSH046
;	BUFFERED INPUT I/O IS TRANSFERRED TO THE USER TASK AND		;MSH046
;	$IOFIN IS CALLED TO FINISH THE I/O REQUEST. BUFFERED		;MSH046
;	OUTPUT I/O IS SIMPLY FINISHED WITH $IOFIN. THE I/O STATUS	;MSH046
;	BLOCK IS FILLED IN BEFORE CALLING $IOFIN. IT IS ASSUMED THAT	;MSH046
;	THE I/O STATUS BLOCK'S VIRTUAL ADDRESS IS STILL VALID.		;MSH046
;-									;MSH046
									;MSH0      46
									;MSH046
									;MSH046
$FINBF::SAVNR			;SAVE NONVOLITILE REGISTERS		;MSH046
	MOV	R0,R3		;COPY I/O PACKET ADDRESS		;MSH046
	INCB	T.IOC(R5)	;INCREMENT OUTSTANDING I/O COUNT	;MSH046
	MOV	I.IOSB(R3),R5	;GET VIRTUAL I/O STATUS BLOCK ADDRESS	;MSH046
	BEQ	10$		;IF EQ NO I/O STATUS BLOCK TO FILL IN	;MSH046
									;MSH046
	.IF DF	M$$MGE							;MSH046
									;MSH046
	MOV	I.PRM+6(R3),-(SP) ;PUSH FINAL I/O STATUS		;MSH046
	MTPI	(R5)+		;PUT FINAL I/O STATUS IN IOSB (MAY TRAP);MSH046
	MOV	I      .PRM+10(R3),-(SP) ;PUSH NUMBER OF BYTES TRANSFERRED	;MSH046
	MTPI	(R5)		;PUT NUMBER BYTES IN IOSB+2 (MAY TRAP)	;MSH046
									;MSH046
	.IFF								;MSH046
									;MSH046
	MOV	I.PRM+6(R3),(R5)+ ;PUT FINAL I/O STATUS IN IOSB		;MSH046
	MOV	I.PRM+10(R3),(R5) ;PUT NUMBER OF BYTES IN IOSB+2	;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
	CLR	I.IOSB+4(R3)	;PREVENT $IOFIN FROM TOUCHING IOSB	;MSH046
10$:	MOV	R3,-(SP)	;SAVE I/O PACKET ADDRESS		;MSH046
									;MSH046
;									;MSH0      46
; IF SYSTEM-CONTROLLED PARTITIONS EXIST, TASK MAY HAVE MOVED IN MEMORY.	;MSH046
; IF SO, THE PHYSICAL ADDRESS DOUBLEWORD FOR THE USER BUFFER IS RELATIVE;MSH046
; TO THE BASE ADDRESS OF ITS REGION. NOW THAT THE TASK'S CONTEXT IS	;MSH046
; ACTIVE, GET THE PCB ADDRESS OF THAT REGION FROM WHICH THE BASE	;MSH046
; ADDRESS WILL BE EXTRACTED LATER.					;MSH046
;									;MSH046
									;MSH046
	.IF DF	D$$YNM&M$$MGE						;MSH046
									;MSH046
	ADD	#I.PRM+16,R3	;POINT TO USER BUFFER PCB ADDRESS	;MSH      046
	MOV	(R3),R5		;GET USER BUFFER PCB (I.PRM+16)		;MSH046
									;MSH046
	.IF DF	R$$LKL							;MSH046
									;MSH046
	CLR	(R3)		;CLEAR LAST PARAMETER WORD (I.PRM+16)	;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
	TST	-(R3)		;BACKUP POINTER (I.PRM+14)		;MSH046
									;MSH046
	.IFF								;MSH046
									;MSH046
	ADD	#I.PRM+14,R3	;POINT PAST TRANSFER BUFFER ADDRESS	;MSH046
									;MSH046
	.ENDC	;D$$YNM&M$$MGE						;MSH046
									;MSH046
	MOV	-(R3),R2	;GET TRANSFE      R BUFFER ADDRESS (I.PRM+12)	;MSH046
									;MSH046
;									;MSH046
; IF ASYNCHRONOUS BUFFERED I/O IS SUPPORTED, SIMPLY FINISH THE I/O IF IT;MSH046
; WAS AN OUTPUT FUNCTION. ELSE, BUFFERED OUTPUTS DON'T EXIST.		;MSH046
;									;MSH046
									;MSH046
	.IF DF	A$$BIO							;MSH046
									;MSH046
	BEQ	20$		;IF EQ, OUTPUT FUNCTION - TRANSFER DONE	;MSH046
									;MSH046
	.IFF								;MSH046
									;MSH046
	.IF DF	M$$MGE							;MSH046
									;MSH046
	MOV	R3,-(SP)	;SAVE POINTER INTO I/      O PACKET (I.PRM+12);MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
	MOV	<I.PRM+2>-<I.PRM+12>(R3),R4 ;GET USER BUFFER ADDRESS	;MSH046
									;MSH046
;									;MSH046
; IF ASYNCHRONOUS BUFFERED I/O IS SUPPORTED, THE TRANSFER BUFFER MAY BE ;MSH046
; ONE OF TWO PLACES, SYSTEM POOL OR IN THE DRIVER'S PRIVATE BUFFER AREA.;MSH046
; IF NOT IN POOL, THEN THE BUFFER MUST BE MAPPED THRU KISAR5 BEFORE	;MSH046
; ACCESSING IT.								;MSH046
;								      	;MSH046
; NOTE THAT IF THE DRIVER IS RESIDENT, THE BUFFER ADDRESS WILL NOT BE	;MSH046
; KISAR5 RELOCATABLE AND NEED NOT BE MAPPED.				;MSH046
;									;MSH046
; IF THE PCB ADDRESS IN R5 IS ZERO, THEN THE BUFFER STRUCTURE IS	;MSH175
; UNKNOWN AND IT IS LEFT TO THE DRIVER TO COPY THE NECESSARY DATA.	;MSH175
; IT IS ASSUMED THAT SYSTEMS WITH SUCH FOREIGN BUFFER STRUCTURES	;MSH175
; WILL BE USING THE FULL DUPLEX TERMINAL DRIVER (WHICH IS ALWAYS	;MSH175
; LOADABLE AND LOADED).							;MSH175
;									      ;MSH175
									;MSH046
	.IF DF	A$$BIO&M$$MGE						;MSH046
									;MSH046
	MOV	@I.UCB-<I.PRM+12>(R3),R0 ;GET DRIVER'S DCB		;MSH046
	CLR	-(SP)		;ASSUME DRIVER IS RESIDENT		;MSH046
	MOV	D.PCB(R0),R0	;GET DRIVER'S PCB			;MSH046
	BEQ	15$		;IF EQ DRIVER IS RESIDENT		;MSH046
	MOV	P.REL(R0),(SP)	;PUSH DRIVER'S PARTITION BASE		;MSH046
									;MSH175
	.IF DF	T$$ACD&D$$YNM						;MSH175
									;MSH175
	TST	R5		;IS THIS A FOREIGN BUFFER STRUCTURE?	;MSH175
	BEQ	193$		;IF EQ YES, LET THE DRIVER HANDLE       IT	;MSH175
									;MSH175
	.ENDC								;MSH175
									;MSH046
	.IFTF								;MSH046
11$:									;MSH046
	.IFT								;MSH046
									;MSH046
	CMP	R2,#120000	;TRANSFER BUFFER IN DRIVER SPACE?	;MSH046
	BLO	15$		;IF LO NO, MUST BE IN POOL		;MSH046
	MOV	R2,R1		;COPY BUFFER ADDRESS			;MSH046
	BIC	#77,R1		;REMOVE DISPLACEMENT IN BLOCK BITS	;MSH046
	SUB	#120000,R1	;CALC OFFSET IN DRIVER PAR IN BYTES	;MSH046
	SUB	R1,R2		;REDUCE ADDRESS TO FIT IN KERNEL 5	;MSH046
	ASL	R1		;CONVERT BYTE OFFSET T      O 32W BLOCKS	;MSH046
	ASL	R1		;					;MSH046
	SWAB	R1		;					;MSH046
	ADD	(SP),R1		;CALCULATE PHYSICAL MEMORY OFFSET	;MSH046
	MOV	R1,KISAR5	;MAP TRANSFER BUFFER			;MSH046
15$:				;					;MSH046
									;MSH046
	.ENDC	;A$$BIO&M$$MGE						;MSH046
									;MSH046
;									;MSH046
; FOR SYSTEMS THAT DO NOT SUPPORT ASYNCHRONOUS BUFFERED I/O:		;MSH046
;									;MSH046
;	THE FIRST WORD OF THE INPUT TRANFER BUFFER IS EXPECTED TO	;MSH046
;	BE ZERO. SINGLE BUFFERED I/O SYSTEMS (HDX TTDRV ONLY) WILL	;MS      H046
;	NOT HAVE LINKED BUFFERS. THE BUFFER SPECIFIED IN I.PRM+12	;MSH046
;	WILL CONTAIN ALL OF THE INPUT DATA COUNTED BY I.PRM+10.		;MSH046
;									;MSH046
;	I.PRM+10 CONTAINS THE TOTAL BYTE TRANSFER COUNT.		;MSH046
;	THE SECOND WORD OF THE INPUT TRANSFER BUFFER IS IGNORED		;MSH046
;	BY $FINBF. I.PRM+10 IS USED EXCLUSIVELY TO DRIVE $FINBF.	;MSH046
;									;MSH046
; FOR SYSTEMS SUPPORTING ASYNCHRONOUS BUFFERED I/O:			;MSH046
;									;MSH046
;	THE FIRST WORD OF THE INPUT TRANSFER BUFFER IS A L      INK TO	;MSH046
;	CONTINUATION BUFFERS, OR ZERO.					;MSH046
;									;MSH046
;	THE SECOND WORD OF THE INPUT TRANSFER BUFFER CONTAINS THE	;MSH046
;	BUFFER'S LENGTH, INCLUDING THE FIRST TWO WORDS. THIS		;MSH046
;	LENGTH-4 MAY ONLY BE A PART OF THE TOTAL CONTAINED IN		;MSH046
;	I.PRM+10 OF THE I/O PACKET. $FINBF WILL FOLLOW THE BUFFER	;MSH046
;	LINKS UNTIL I.PRM+10 BYTES HAVE BEEN TRANSFERRED TO THE		;MSH046
;	USER'S BUFFER.							;MSH046
;									;MSH046
									;MSH046
	.IF DF	A$$BIO							;MSH      046
									;MSH046
	MOV	(R2)+,-(SP)	;PUSH POINTER TO NEXT BUFFER		;MSH046
	MOV	(R2)+,R0	;GET BLOCK SIZE				;MSH046
									;MSH046
	.IFF	;A$$BIO							;MSH046
									;MSH046
	.IF DF	M$$MGE							;MSH046
									;MSH046
	MOV	-(R3),R0	;GET #BYTES TRANSFERRED (I.PRM+10)	;MSH046
									;MSH046
	.IFF								;MSH046
									;MSH046
	MOV	-2(R3),R0	;GET #BYTES TRANSFERRED (I.PRM+10)	;MSH046
									;MSH046
	.ENDC	;M$$MGE							;MSH046
									;MSH046
	CMP	(R2)+,(R2)+	;SKIP HEADER BYTES		      	;MSH046
									;MSH046
	.IFT	;A$$BIO							;MSH046
									;MSH046
	CMP	-(R0),-(R0)	;REDUCE BY HEADER BYTES (4)		;MSH046
	SUB	R0,-(R3)	;BLOCK OVERSIZED? (I.PRI+10)		;MSH046
	BCC	16$		;IF CC NO				;MSH046
	ADD	(R3),R0		;ELSE, CORRECT COUNT (I.PRM+10)		;MSH046
	CLR	(R3)		;CLEAR REMAINING BYTE COUNT (I.PRM+10)	;MSH046
16$:									;MSH046
	.IFTF								;MSH046
									;MSH046
;									;MSH046
; FINISH RELOCATING THE USER'S BUFFER IF THE TASK MIGHT HAVE MOVED.	;MSH046
;									;MSH046
				      					;MSH046
	.IF DF	M$$MGE							;MSH046
									;MSH046
	MOV	I.PRM-<I.PRM+10>(R3),R3 ;GET USER BUFFER APR6 BIAS	;MSH046
									;MSH046
	.IF DF	D$$YNM							;MSH046
									;MSH046
	ADD	P.REL(R5),R3	;ADD IN PARTITION BASE			;MSH046
									;MSH046
	.ENDC								;MSH046
									;MSH046
;									;MSH046
; EXECUTE THE ACTUAL TRANSFER OF BUFFERED DATA FROM THIS BLOCK TO	;MSH046
; THE USER'S BUFFER. THE REGISTER CONTENTS AT THIS POINT ARE:		;MSH046
;									;MSH046
;	R0=LENGTH OF TRANSFER      						;MSH046
;	R1=BLOCK'S APR5 BIAS (MAPPED SYS W/ ASYNCH. BUFRD. I/O SUPPORT)	;MSH046
;	R2=BLOCK ADDRESS						;MSH046
;	R3=APR6 BIAS OF USER BUFFER (MAPPED ONLY)			;MSH046
;	R4=USER BUFFER ADDRESS						;MSH046
;	R5=USER BUFFER REGION PCB ADDRESS (MAPPED SYSTEMS WITH		;MSH046
;			SYSTEM-CONTROLLED PARTITION SUPPORT ONLY)	;MSH046
;									;MSH046
									;MSH046
	CALL	$BLXIO		;TRANSFER TO USER BUFFER		;MSH046
									;MSH046
	.IFF								;MSH046
									;MSH046
17$:	DEC	R0		;ANY MORE BYTES       TO COPY?		;MSH046
	BLT	19$		;IF LT NO				;MSH046
	MOVB	(R2)+,(R4)+	;TRANSFER BYTE TO USER BUFFER		;MSH046
	BR	17$		;					;MSH046
19$:									;MSH046
	.ENDC	;M$$MGE							;MSH046
									;MSH046
;									;MSH046
; IF ASYNCHRONOUS BUFFERED I/O IS SUPPORTED, THERE MAY BE MORE THAN	;MSH046
; ONE INPUT TRANSFER BUFFER CONTAINING THE DATA FOR THE USER'S		;MSH046
; REQUEST. AT THIS POINT, WE HANDLE MULTIPLE BUFFERS.			;MSH046
;									;MSH046
									;MSH046
	.IFT	;A$$BIO							;MSH046
									      ;MSH046
	MOV	(SP)+,R2	;RETRIEVE NEXT BUFFER POINTER		;MSH046
									;MSH046
	.IF DF	M$$MGE							;MSH046
									;MSH046
	MOV	2(SP),R3	;GET I/O PACKET ADDRESS			;MSH046
	ADD	#I.PRM+10,R3	;POINT TO REMAINING BYTE COUNT		;MSH046
									;MSH046
	.IFTF	;M$$MGE							;MSH046
									;MSH046
	TST	(R3)+		;ANY REMAINING BYTES? (I.PRM+10)	;MSH046
	BNE	11$		;IF NE YES				;MSH046
									;MSH046
;									;MSH046
; THE TRANSFER TO THE USER'S BUFFER IS DONE. SET UP AND CALL THE	;MSH046
; DRIVER'S       TRANSFER BUFFER DEALLOCATION ROUTINE. THE REGISTERS		;MSH046
; AT THE CALL ARE:							;MSH046
;									;MSH046
;	R0=ADDRESS OF FIRST TRANSFER BUFFER (FROM I.PRM+12)		;MSH046
;	R2=DRIVER DISPATCH TABLE					;MSH046
;									;MSH046
; NOTE THAT IF THE BUFFER STRUCTURE IS FOREIGN (R5=0), WE WILL COME	;MSH175
; HERE WITHOUT TRANSFERRING ANY DATA.					;MSH175
;									;MSH175
;									;MSH046
									;MSH046
	.IFT	;M$$MGE							;MSH046
									;MSH046
193$:	MOV	(SP)+,KISAR5	;MAP THE DRIVER				;      MSH046
									;MSH046
	.ENDC	;M$$MGE							;MSH046
									;MSH046
	.IFF	;A$$BIO							;MSH046
									;MSH046
	.IF DF	M$$MGE							;MSH046
									;MSH046
	MOV	(SP)+,R3	;RESTORE XFER BUFFER POINTER (I.PRM+12)	;MSH046
									;MSH046
	.ENDC	;M$$MGE							;MSH046
									;MSH046
	.IFTF	;A$$BIO							;MSH046
									;MSH046
	MOV	(R3),R0		;POINT TO FIRST BUFFER (I.PRM+12)	;MSH046
	MOV	@I.UCB-<I.PRM+12>(R3),R2 ;GET DRIVER DCB		;MSH046
									;MSH046
	.IFF	;A$$BIO							;MSH046
						      			;MSH046
	.IF DF	L$$DRV&M$$MGE						;MSH046
									;MSH046
	MOV	D.PCB(R2),R3	;GET DRIVER'S PCB			;MSH046
	BEQ	195$		;IF EQ DRIVER RESIDENT			;MSH046
	MOV	P.REL(R3),KISAR5 ;MAP BUFFER DEALLOCATION ROUTINE	;MSH046
195$:				;					;MSH046
	.ENDC								;MSH046
									;MSH046
	.ENDC	;A$$BIO							;MSH046
									;MSH046
	MOV	D.DSP(R2),R2	;GET DRIVER DISPATCH TABLE		;MSH046
	CALL	@D.VDEB(R2)	;CALL DRIVER DEALLOCATION ROUTINE	;MSH046
									;MSH046
;									;MSH046
; THE DUTIES OF THE KERN      EL AST FOR BUFFERED I/O ARE NOW			;MSH046
; COMPLETE. CALL $IOFIN TO FINISH THE I/O REQUEST.			;MSH046
;									;MSH046
									;MSH046
20$:	MOV	(SP)+,R3	;GET I/O PACKET ADDRESS			;MSH046
	CALLR	$IOFIN		;FINISH THE I/O				;MSH046
									;MSH046
	.ENDC	;C$$CKP&T$$BUF						;MSH046
									;**-168

									;**-1
;+
; **-$SGFIN-SEGMENT FAULT AND TRAP 4 INTERCEPT ROUTINE
;
; THIS ROUTINE IS A CO-ROUTINE WHICH SETS UP TO IGNORE SEGMENT FAULTS
; AND TRAPS THROUGH 4.
;
; INPUTS:
;
;	NONE.
      ;
; OUTPUTS:
;
;	NONE.
;-

$SGFIN::MOV	@#4,-(SP)	;SAVE CONTENTS OF TRAP 4 VECTOR

	.IF DF	C$$CHE							;MSH127
									;**-2
	MOV	@#114,-(SP)	;SAVE MAIN MEMORY TIMEOUT AND PARITY
	MOV	4(SP),-(SP)	;COPY RETURN ADDRESS
	MOV	@#250,6(SP)	;SAVE SEGMENT TRAP ADDRESS
	MOV	#$TRINT,@#114	;TRAP THESE FAULTS			;MSH112
									;**-1
	.IFF	;C$$CHE							;MSH127
									;**-1
	MOV	2(SP),-(SP)	;COPY RETURN ADDRESS
	MOV	@#250,4(SP)	;SAVE CONTENTS OF SEGMENT FAULT VECTOR

	.IFTF	;C$$CHE							;MSH127      
									;**-1
	MOV	#$TRINT,@#4	;POINT TO ROUTINE TO SET CARRY		;MSH112
	MOV	#$TRINT,@#250	;					;MSH112
									;**-2
;
; CONTENTS OF STACK AT THIS POINT:
;
;	0(SP)=COROUTINE RETURN ADDRESS TO CALLER.
;	2(SP)=CONTENTS OF @#114 (IF PROCESSOR HAS CACHE MEMORY)		;MSH127
;	4(SP)=CONTENTS OF @#4						;**-1
;	6(SP)=CONTENTS OF @#250
;

	CALL	@(SP)+		;RETURN TO CALLER

	.IFT	;C$$CHE							;MSH127
									;**-1
	MOV	(SP)+,@#114	;RESTORE MAIN MEMORY TIMEOUT TRAP

	.ENDC	;C$$CHE							;MSH127
      									;**-1
	MOV	(SP)+,@#4	;RESTORE TRAP 4 VECTOR
									;MSH088
	.IF DF	M$$MGE							;MSH088
									;MSH088
	BIC	#160000,@#SR0	;UNFREEZE MEMORY MANAGEMENT UNIT	;MSH088
									;MSH088
	.ENDC								;MSH088
									;MSH088
	MOV	(SP)+,@#250	;RESTORE SEGMENT FAULT VECTOR
	RETURN			;RETURN TO CALLER'S CALLER

;+									;**-4
; **-$SAVNR-SAVE NONVOLATILE REGISTERS
;
; THIS ROUTINE IS A CO-ROUTINE THAT SAVES REGISTERS R4 AND R5.
;-

$SAVNR::MOV	R4,-(SP)	;SAVE R4
	MOV	R5,-(SP)	;SET RE      TURN ADDRESS
	MOV	4(SP),R5	;RESTORE R5
	CALL	@(SP)+		;CALL THE CALLER
	MOV	(SP)+,R4	;RESTORE R4
	MOV	(SP)+,R5	;RESTORE R5
	RETURN			;RETURN TO ORIGINAL CALLER

;+
; **$SWSTK-SWITCH STACKS
;
; THIS ROUTINE IS CALLED FROM TASK LEVEL TO SWITCH TO THE SYSTEM
; STACK THUS INHIBITING TASK SWITCHING. THE CALLING TASK MUST BE
; PRIVILEGED IF RUNNING IN A MAPPED SYSTEM AND MAPPED TO THE EXEC.
; CONTROL IS PASSED HERE FROM DRDSP AFTER THE TRAP HAS OCCURED AND
; $DIRSV HAS BEEN CALLED.
;
; CALLING SEQU      ENCE:
;
;	EMT	376		;TRAP TO $EMSST IN DRDSP
;	.WORD	ADDR		;ADDRESS FOR RETURN TO USER STATE
;
; INPUTS AT THIS POINT:
;
;	R3=ADDRESS OF PC WORD OF TRAP ON STACK + 2
;
;   MAPPED SYSTEM:
;
;	22(SP)=PS PUSHED BY TRAP
;	20(SP)=PC PUSHED BY TRAP
;	16(SP)=SAVED R5
;	14(SP)=SAVED R4
;	12(SP)=SAVED R3
;	10(SP)=SAVED R2
;	06(SP)=SAVED R1
;	04(SP)=SAVED R0
;	02(SP)=RETURN ADDRESS FOR SYSTEM EXIT
;	00(SP)=104376
;
;   UNMAPPED SYSTEM:
;
;	10(SP)=SAVED R3
;	06(SP)=SAVED R2
;	04(SP)=SAVED R1
      ;	02(SP)=SAVED R0
;	00(SP)=RETURN ADDRESS FOR SYSTEM EXIT
;
; OUTPUTS:
;
;	THE USER IS CALLED BACK ON THE SYSTEM STACK WITH ALL REGISTERS
;	PRESERVED.  TO RETURN TO TASK LEVEL THE CALLER MERELY EXECUTES
;	A RETURN.
;
;-

$SWSTK::CLRB	(R3)		;SET INITIAL PS WORD


	.IF DF	M$$MGE

	MOV	#KISAR6,R5	;POINT TO KERNAL APR 6
	MOV	UISAR6,(R5)	;SET UP KERNAL APR 6
	MOV	UISAR5,-(R5)	;SET UP KERNAL APR 5


	.IF NDF	R$$EXV

	MOV	UISAR4,-(R5)	;SET UP KERNAL APR 4

	.ENDC


	.IFTF

	MOV	-(R3),      R5	;PICK UP TRAP PC WORD
	MOV	(R5)+,(R3)	;SET ADDRESS FOR RETURN TO USER STATE

	.IFT

	MOV	R5,(SP)		;SET CALLER'S ADDRESS

	.IFF

	MOV	R5,-(SP)	;SET CALLER'S ADDRESS

	.ENDC


	MOV	-(R3),R5	;RESTORE R5
	MOV	12(SP),R3	;RESTORE R3
	CALLR	@(SP)+		;CALL THE CALLER

	.END
          Ç8@QkQ	› c,        	.TITLE	ICOM
	.IDENT	/00/
 
;
; COPYRIGHT (C) 1975, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 00
;
; C. MONIA 05-JUN-75
;
; ICS/ICR-11 DEVICE COMMON BLOCK
;
; EQUATED SYMBOLS
;
; DEFINE NUMBER OF ICS/ICR CONTROLLERS GLOBALLY
;
 
	.IF DF	I$$C11
 
	.GLOBL	I$$C11
 
	.ENDC
 
;+
;
; **-.ICOM-ICS/ICR-11 DEVICE COMMON BLOCK
;
;	THIS COMM      ON BLOCK MUST BE BUILT WHENEVER ANY ICS/ICR-11
; MODULES ARE REFERENCED DIRECTLY. IN GENERAL SUCH DIRECT REFERENCES
; OCCUR AS THE RESULT OF CALLS TO THE FORTRAN PROCESS CONTROL SUB-
; ROUTINES THAT PERFORM INPUT FROM CONTACT SENSE, CONTACT INTERRUPT
; AND TIMER MODULES. THE EXTENT OF THE BLOCK IS SET TO
; PREVENT ACCESS TO THE DEVICE CONTROL AND STATUS REGISTERS BY THE TASK.
;
; ASSEMBLING THE COMMON BLOCK:
;
;	THE COMMON BLOCK MUST BE ASSEMBLED WITH THE PREFIX FILE [11,10]
; RSXMC.MAC TO DEFINE        CONDITIONALS THAT CONTROL THE SIZE AND COMMON BLOCK
; ATTRIBUTES AS FOLLOWS:
;
;	CONDITIONAL		EFFECT
;	-----------		------
;
;	I$$C11			CONTROLS EXTENT OF COMMON BLOCK
;	M$$MGE			ESTABLISHES RELOCATABILITY OF COMMON BLOCK.
;				COMMON BLOCK IS RELOCATABLE (PIC) IF DEFINED.
;				OTHERWISE COMMON BLOCK IS ABSOLUTE.
;
;
; THE USER MAY FORCE THE COMMON BLOCK TO BE PIC BY INCLUDING THE
; CONDITIONAL 'I$$COM' IN RSXMC.MAC BY MEANS OF THE TEXT EDITOR.
;
;-
 
	.IF DF	I$$C11
 
	.IF DF	M$$MGE!I$$C   ¤   OM
 
	.PSECT	ICOM,REL,GBL,OVR,D
 
	.IFF
 
	.ASECT
 
.=171000
 
	.ENDC
.ICMD::				;
	.BLKW	I$$C11*16.	; SET LENGTH OF COMMON BLOCK
 
	.ENDC
 
	.END
¤          Ã:È_kQ	› c,        	.TITLE	PCSCOM
	.IDENT	/00/
;		COPYRIGHT (C) 1977 BY
;	DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
; 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.
;
.IF DF	N$$PCS

	.GLOBL	N$$PCS

.IF DF	M$$MGE!I$$POM

	.PSECT	PCSCOM,REL,GBL,OVR,D

.IFF

	.ASECT

.=I$$PB0

.ENDC

.PCSAD:: .BLKW	255.

.ENDC
.END
Ä         �sÖQkQ	› c,        S$$HFC=30.		;MINIMUM TICKS BETWEEN SHUFFLER RUNS
M$$CRB=84.		;MCR COMMAND BUFFER LENGTH
R$$11M=0		;RSX-11M SYSTEM
;
	.IIF DF A$$BIO!C$$CKP&T$$BUF	K$$AST=0
	.IIF DF A$$BIO&T$$BUF		K$$AST=0
	.IIF DF P$$OFF			K$$AST=0
	.IIF DF	P$$SRF&G$$EFN		K$$AST=0
;
;
; EXEC MACROS
;

;
; ASSUME MACRO FOR CHECKING ADJACENCY AND OFFSET VALUE ASSUMPTIONS
;
 
	.MACRO	ASSUME	A,B=0
	.IF NE <A>-<B>
	.ERROR			;EXPRESSION(S) NOT EQUAL
	.ENDC
	.ENDM
 
;
; CALL SUBROUTINE
;

	.MACRO	CALL SUBR ARG
	.IF IDN	      <$INTSV>,<SUBR>
	JSR	R5,$INTSV
	.IF DF	L$$SI1
	.WORD	ARG
	.IFF
	.WORD	^C<ARG>&PR7
	.ENDC
	.IFF
	.IF IDN	<$SAVNR>,<SUBR>
	JSR	R5,$SAVNR
	.IFF
	.IF IDN	<$SWSTK>,<SUBR>
	EMT	376
	.WORD	ARG
	.IFF
	JSR	PC,SUBR
	.ENDC
	.ENDC
	.ENDC
	.ENDM

;
; CALL AND RETURN FROM SUBROUTINE
;

	.MACRO	CALLR SUBR
	JMP	SUBR
	.ENDM

;
; CRASH SYSTEM
;

	.MACRO	CRASH
	IOT
	.ENDM

;
; DIRECTIVE REGISTER SAVE AND SET PRIORITY
;

	.MACRO	DIRSV$
	JSR	R5,$DIRSV
	.ENDM

;
; SET DIRECTIVE STATU      S
;

	.MACRO 	DRSTS VALUE
	TRAP	VALUE
	.ENDM

;
; GENERATE INTERRUPT ROUTINE ENTRY POINT LABEL
;


	.IF DF	E$$DVC
	.MACRO	INTLB NUM,NAM
$'NAM'NUM'T::
	.ENDM
	.ENDC


;
; INTERRUPT SAVE GENERATION MACRO FOR ERROR LOGGING DEVICES
;

	.MACRO	INTSE$ DEV,PRI,NCTRLR,PSWSV,UCBSV,?LAB
	.IF DF	L$$DRV & LD$'DEV & M$$MGE
$'DEV'INT::
	.IF NDF	E$$DVC
	.IF EQ	NCTRLR-1
	CLR	R4
	.ENDC
	.ENDC
	.IFF
	.IF NDF	E$$DVC
$'DEV'INT::INTSV$	DEV,PRI,NCTRLR,PSWSV,UCBSV
	.IF EQ	NCTRLR-1
	CLR	R4
	.END      C
	.MEXIT
	.IFF
$$$=0
	.REPT	NCTRLR
	INTLB	\$$$,DEV
	JSR	R5,$INTSE
	SCBLB	\$$$,DEV
	.IF DF	L$$SI1
	.WORD	PRI
	.IFF
	.WORD	^C<PRI>&PR7
	.ENDC
	.IF GT	NCTRLR-$$$-1
	BR	LAB
	.ENDC
$$$=$$$+1
	.ENDR
LAB:
	.ENDC
	.ENDC
	GTUCB$	UCBSV,NCTRLR
	.ENDM


;
; INTERRUPT SAVE GENERATION FOR NON-ERROR LOGGING DEVICES
;

	.MACRO	INTSV$	DEV,PRI,NCTRLR,PSWSV,UCBSV
	.IF NDF	L$$DRV ! M$$MGE ! LD$'DEV
	.IF GT	NCTRLR-1
	.IF B	<PSWSV>
	MFPS	TEMP
	.IFF
	MFPS	PSWSV
	.ENDC
	.IFTF
	JSR	R5,$INTSV
      	.IF DF	L$$SI1
	.WORD	PRI
	.IFF
	.WORD	^C<PRI>&PR7
	.ENDC
	.IFT
	.IF B	<PSWSV>
	MOV	TEMP,R4
	.IFF
	MOV	PSWSV,R4
	.ENDC
	BIC	#177760,R4
	ASL	R4
	.ENDC
	.ENDC
	GTUCB$	UCBSV,NCTRLR
	.ENDM


;
; GENERATE CODE TO LOAD UCB ADDRESS INTO R5 -- CALLED
; ONLY BY INTSE$ AND INTSV$
;

	.MACRO	GTUCB$	UCBSV,NCTRLR
	.IF NB	<UCBSV>
	.IF GT	NCTRLR-1
	MOV	UCBSV(R4),R5
	.IFF
	MOV	UCBSV,R5
	.ENDC
	.IFF
	.IF GT	NCTRLR-1
	MOV	CNTBL(R4),R5
	.IFF
	MOV	CNTBL,R5
	.ENDC
	.ENDC
	.ENDM


;
; PR      OCESSOR STATUS READ/WRITE
;

	.IF NDF	L$$SI1
	.MACRO	MFPS DST
	MOVB	@#PS,DST
	.ENDM
	.MACRO	MTPS SRC
	.IF IDN	<#0>,<SRC>
	CLRB	@#PS
	.IFF
	MOVB	SRC,@#PS
	.ENDC
	.ENDM
	.ENDC


;
; SAVE NONVOLATILE REGISTERS
;

	.MACRO	SAVNR
	JSR	R5,$SAVNR
	.ENDM

;
; GENERATE STATUS CONTROL BLOCK REFERENCE LABEL
;


	.IF DF	E$$DVC
	.MACRO	SCBLB NUM,NAM
	.WORD	$'NAM'NUM
	.ENDM
	.ENDC


;
; RETURN FROM SUBROUTINE
;

	.MACRO	RETURN
	RTS	PC
	.ENDM

;
; SOB LOOP INSTRUCTION
;


	      .IF NDF	M$$EIS
	.MACRO	SOB	A,B
	DEC	A
	BNE	B
	.ENDM
	.ENDC

;
; STATE SWITCHING MACRO
;

	.MACRO	SWSTK$ ARG
	CALL	$SWSTK,ARG
	.ENDM

;
; GET I/O PACKET MACRO -- USED FOR RSX-11M-PLUS COMPATIBILITY
;
	.MACRO GTPKT$ DEV,NCTRLR,ADDR,UCBSV,SUC
	CALL $GTPKT
	.IF B <ADDR>
	BCC 65535$
	RETURN
65535$:
	.IFF
	BCS ADDR
	.ENDC
	.IF B <UCBSV>
	.IFF
	.IF GT NCTRLR-1
	MOV R5,UCBSV(R3)
	.IFF
	MOV R5,UCBSV
	.ENDC
	.ENDC
	.ENDM
;
; GENERATE THE DRIVER DISPATCH TABLE -- DDT (USED FOR RSX-   T  11M-PLUS COMPATIBILITY)
;
	.MACRO DDT$ DEV,NCTRLR,INY,INX,UCBSV,NEW
$'DEV'TBL::
	.IF B <INX>
	.WORD DEV'INI
	.IFF
	.WORD DEV'INX
	.ENDC
	.WORD DEV'CAN
	.WORD DEV'OUT
	.WORD DEV'PWF
	.IF NB NEW
	.ERR NEW	; UNSUPPORTED RSX-11M-PLUS FEATURE
	.ENDC
	.IF NB <UCBSV>
UCBSV:	.BLKW	NCTRLR
	.ENDC
	.ENDM
	.IIF NDF S$$YDF , .LIST
T         ;;È_kQ	› c,        	.TITLE	ISCOM
	.IDENT	/00/
 
;
; COPYRIGHT (C) 1975, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 00
;
; C. A. MONIA	18-JUL-75
;
; DSS11 DEVICE COMMON BLOCK
;
;+
;
; **-ISCOM-DSS11 DIGITAL INPUT SUBSYSTEM DEVICE COMMON BLOCK
;
; THIS MODULE DEFINES THE DSS11 DEVICE COMMON BLOCK THAT IS REFERENCED
; WHENEVER A TASK READS DSS11 DIGITAL INPUT POI   ¨   NTS.
;
;-
 
	.PSECT	ISCOM,RW,GBL,OVR,D
 
	.BLKB	I$$SSC&77		; COMPUTE OFFSET FROM 32W BOUNDARY
	.BLKW	I$$SDS*4		; ALLOCATE SPACE FOR DEVICE REGISTERS
 
	.END
 ¨          <;ðskQ	› c,        	.TITLE	ISDRV
	.IDENT	/01.01/
 
;
; COPYRIGHT (C) 1975, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 01.01
;
; C. MONIA 17-JUL-75
;
; PREVIOUSLY MODIFIED BY:
;
;	T. J. MILLER
;
; MODIFIED BY:
;
;	T. LEKAS	28-FEB-80
;		TL020 -- SET THE DEVICE OFFLINE IN THE POWERFAIL
;			 ROUTINE IF THE REGISTERS ARE NOT PRESENT
;
; DRS/DSS11 DIGITAL I/O SUB      SYSTEM DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$,TCBDF$

	HWDDF$			; DEFINE HARDWARE OFFSETS
	PKTDF$			; DEFINE I/O PACKET OFFSETS
	TCBDF$			; DEFINE TCB OFFSETS

;
; EQUATED SYMBOLS
;
; INTERRUPT LINK OFFSETS
;

	.ASECT

.=0
ILTE:	.BLKW	1		; ADDRESS OF LINKED TASK ENTRY(0=NONE)
ILEVM:	.BLKW	1		; EVENT FLAG MASK
ILEVA:	.BLKW	1		; EVENT FLAG ADDRESS
ILRUN:	.BLKW	1		; RUN FLAG (1=RUN TASK)
ILCSR:	.BLKW	1		; BUS ADDRESS OF CSR REGISTER
ILGH:	.BLKW	0		; LENGTH OF INTERRUPT       ENTRY

;
; LINKED TASK ENTRY OFFSETS
;

.=0
LNEXT:	.BLKW	1		; LINK TO NEXT (0=NONE)
LTCB:	.BLKW	1		; TCB ADDRESS OF LINKED TASK
LACT:	.BLKW	1		; ACTIVITY COUNT
LHWR:	.BLKW	1		; HARDWARE DEPENDANT DATA
LLGH:	.BLKW	0		; LENGTH OF ENTRY

;
; ILLEGAL INTERRUPT POINT MASK
;

IPMSK=0

	.IF NE	16.-I$$S11

IPMSK=100000

	.REPT	16.-I$$S11-1
IPMSK=IPMSK/2
	.ENDR

	.ENDC


	.PSECT

;
; LOCAL DATA
;
; DRIVER DISPATCH TABLE
;

$ISTBL::.WORD	ISCHK		; DEVICE INITIATOR ENTRY POINT
	.      WORD	ISCAN		; CANCEL I/O ENTRY POINT
	.WORD	ISCAN		; DEVICE TIMEOUT ENTRY POINT
	.WORD	ISPWF		; POWER RECOVERY ENTRY POINT

;
; FORK REQUEST FLAG
;

	.IF DF	I$$SLK

FORK:	.BLKW	1		;


;
; DIGITAL INTERRUPT LINKED TASK LISTHEAD
;

ISLNK:	.WORD	0		; LIST INITIALLY EMPTY
	.WORD	.-2		; LAST POINTS TO FIRST

;
; DIGITAL INTERRUPT RESOURCE MASK
;

ISRES:	.WORD	0		; ALL RESOURCES AVAILABLE INITIALLY.

;
; DIGITAL INTERRUPT LINKAGE TABLE
;

ILTBL:				;


	.IF DF	I$$SDR&I$$SDS

BUS      0=I$$SSC
BUS1=I$$SRC
REP0=I$$SDS
REP1=I$$SDR

	.IF LT	I$$SRC-I$$SSC

BUS0=I$$SRC
BUS1=I$$SSC
REP0=I$$SDR
REP1=I$$SDS

	.ENDC

	.IFF

BUS1=0
REP1=0

	.IF DF	I$$SDR

REP0=I$$SDR
BUS0=I$$SRC

	.IFF

REP0=I$$SDS
BUS0=I$$SSC

	.ENDC

	.ENDC

	.REPT	REP0
	.BLKB	ILGH-2
	.WORD	BUS0
BUS0=BUS0+10
	.ENDR

	.REPT	REP1
	.BLKB	ILGH-2
	.WORD	BUS1
BUS1=BUS1+10
	.ENDR

	.ENDC


;
; DIGITAL OUTPUT PREVIOUS STATE TABLE
;

	.IF DF	I$$SDR

ISPRV:	.BLKW	I$$SDR*3		;

;
; DI      GITAL OUTPUT BUS ADDRESS LIST
;

ISBUS:					;

ADDR=I$$SRC+2
	.REPT	I$$SDR
	.REPT	3
	.WORD	ADDR
ADDR=ADDR+2
	.ENDR
ADDR=ADDR+2
	.ENDR

	.ENDC

;
; ADDRESS OF UCB
;

ISUCB:	.BLKW	1		;

;
; TEMPORARY PSW STORAGE
;

TMP:	.BLKW	1		;


;+
;
; **-ISCHK-DRS/DSS-11 DIGITAL I/O SUBSYSTEM PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM QIO DIRECTIVE PROCESSING WHEN AN
; I/O REQUEST IS RECIEVED FOR THE DRS/DSS-11 DIGITAL INPUT-OUTPUT
; SUBSYSTEMS DEVICES. DRS/DSS-11 REQUESTS CONT      AIN PARAMETERS THAT
; MUST BE CHECKED IN THE CONTEXT OF THE ISSUING TASK. THEREFORE
; THE I/O REQUEST IS NOT QUEUED BEFORE CALLING THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	DEPENDANT UPON FUNCTION TO BE PERFORMED
;
; DRS/DSS-11 FUNCTION INDEPENDANT I/O PACKET
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF REQUE      STER TASK TCB.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE.
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;
;-

ISCHK:				;
	MOV	R1,-(SP)	; SAVE I/O PACKET ADDRESS
	MOV	I.TCB(R1),R0	; GET ADDRESS OF TCB      
	MOV	I.FCN(R1),R2	; GET FUNCTION CODE
	BIC	#7,R2		; CLEAR FUNCTION BITS
	ADD	#I.PRM,R1	; POINT TO PARAMETER BLOCK

	.IF DF	I$$SLK

	CMP	R2,#IO.RAD	; READ ACTIVATING DATA?
	BEQ	ISRAD		; IF EQ YES
	CMP	R2,#IO.LDI	; LINK TO DIGITAL INTERRUPTS?
	BEQ	ISLD		; IF EQ YES
	CMP	R2,#IO.NLK	; UNLINK FROM INTERRUPTS
	BEQ	ISUNL		; IF EQ YES
	CMP	R2,#IO.UDI	; UNLINK FROM DIGITAL INTERRUPTS

	.ENDC

	.IF DF	I$$SDR&I$$SLK

	BEQ	ISUNL		; IF EQ YES

	.ENDC

	.IF DF	I$$SDR

	CMP	R2,#IO.MLO	; LATCHING O      UTPUT?

	.IFTF

	BNE	ISIFC		; IF NE NO ILLEGAL FUNCTION

;+
;
; **-ISLAT-PERFORM BISTABLE DIGITAL OUTPUT
;
; FUNCTION DEPENDANT I/O PACKET FORMAT
;
;	WD. 12 -- INITIAL POINT
;	WD. 13 -- MASK WORD
;	WD. 14 -- DATA WORD
;	WD. 15 -- NOT USED
;	WD. 16 -- NOT USED
;	WD. 17 -- NOT USED
;
;-

	.IFT

ISLAT:				;
	MOV	(R1)+,R2	; GET POINT NUMBER
	BIT	#17,R2		; POINT ON MODULE BOUNDARY?
	BNE	ISMOD		; IF NE NO
	CMP	R2,#<I$$SDR>*48.-1 ; POINT EXIST?
	BHI	ISMOD		; IF HI NO
	ASR	R2		; CONVERT       TO WORD OFFSET
	ASR	R2		; ...
	ASR	R2		; ...
	BIC	(R1),ISPRV(R2)	; CLEAR ALL BITS THAT WILL CHANGE STATE
	COM	(R1)		; SET ALL BITS THAT WILL NOT CHANGE
	BIC	(R1)+,(R1)	; CLEAR ALL BITS THAT WILL NOT CHANGE
	BIS	(R1),ISPRV(R2)	; SET NEW PREVIOUS STATE
	MOV	ISPRV(R2),@ISBUS(R2) ; SET NEW MODULE STATE
	BR	ISSUC		;

	.ENDC


;+
;
; **-ISUNL-UNLINK A TASK FROM INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT
;
;	WD. 12 -- FIRST HALF OF TASK NAME
;	WD. 13 -- SECOND HALF OF TASK NAME
;	WD.       14 -- NOT USED
;	WD. 15 -- NOT USED
;	WD. 16 -- NOT USED
;	WD. 17 -- NOT USED
;
;-

	.IF DF	I$$SLK

ISUNL:				;
	MOV	R1,R3		; COPY ADDRESS OF PARAMETER BLOCK
	CALL	$SRSTD		; SEARCH FOR TASK TCB ADDRESS
	BCS	ISNLK		; IF C/S TASK NOT INSTALLED
	MOV	#ISLNK,R2	; GET ADDRESS OF LINKED TASK LISTHEAD
10$:				;
	MOV	R2,R4		; SAVE ADDRESS OF PREVIOUS FOR RELINK
	MOV	(R2),R2		; GET ADDRESS OF NEXT
	BEQ	ISNLK		; IF EQ TASK NOT LINKED
	CMP	LTCB(R2),R0	; ENTRY BELONG TO THIS TASK?
	BNE	10$		; IF NE N      O
	MOV	#ILTBL,R0	; GET ADDRESS OF INTERRUPT LINK TABLE
	MOV	#I$$S11,R1	; GET NUMBER OF DRS/DSS MODULES
	MOV	#1,R3		; SET 1-BIT MASK
20$:				;
	CMP	(R0),R2		; TASK LINKED TO THIS INTERRUPT?
	BNE	30$		; IF NE NO
	MOVB	#PR4,PS		;;; INHIBIT DEVICE INTERRUPTS
	CLR	(R0)		;;; UNLINK THIS TASK
	BIC	R3,ISRES	;;; FREE UP THE RESOURCE
	CLR	@ILCSR(R0)	;;; DISABLE DEVICE INTERRUPTS
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
30$:				;
	ADD	#ILGH,R0	; POINT TO NEXT ENTRY
	ASL	R3		; SHIFT MASK
	DEC	R1		; DECREMENT       DEVICE COUNT
	BNE	20$		; IF NE GO AGAIN
	MOV	R2,R0		; COPY ADDRESS OF BLOCK
	MOV	(R2),(R4)	; RELINK REMAINING ENTRIES
	BNE	40$		; IF NE NO NEW LAST
	MOV	R4,ISLNK+2	; SET NEW LAST
40$:				;
	MOV	#LLGH,R1	; GET LENGTH OF ENTRY
	CALL	$DEACB		; DEALLOCATE BLOCK

;
; RETURN SUCCESS STATUS
;

	.IFTF

ISSUC:				;
	MOV	#IS.SUC&377,R0	;
	BR	ISCMN		;

;
; BAD PARAMETER SPECIFIED
;

	.IFT

ISBAD:				;
	MOV	#IE.BAD&377,R0	;
	BR	ISCMN		;

;
; BUFFER BYTE ALIGNED
;

ISBYT:				;
	MOV	#IE      .BYT&377,R0	;
	BR	ISCMN

;
; ILLEGAL EVENT FLAG SPECIFIED
;

ISIEF:				;
	MOV	#IE.IEF&377,R0	;
	BR	ISCMN		;

;
; ILLEGAL FUNCTION CODE
;

	.IFTF

ISIFC:				;
	MOV	#IE.IFC&377,R0	;
	BR	ISCMN		;

;
; NON-EXISTENT MODULE OR POINT SPECIFIED
;

ISMOD:				;
	MOV	#IE.MOD&377,R0	;
	BR	ISCMN		;

;
; TASK NOT LINKED
;

	.IFT

ISNLK:				;
	MOV	#IE.NLK&377,R0	;
	BR	ISCMN		;

;
; NO DYNAMIC STORAGE AVAILABLE TO LINK TASK
;

ISNOD:				;
	MOV	#IE.UPN&377,R0	;
	BR	ISCMN		;

;      
; TASK NOT INSTALLED
;

ISNST:				;
	MOV	#IE.NST&377,R0	;
	BR	ISCMN		;

;
; RESOURCE IN USE
;

ISRSU:				;
	MOV	#IE.RSU&377,R0	;
	BR	ISCMN		;

;
; BUFFER OUTSIDE OF TASK'S ADDRESS SPACE
;

ISPC:				;
	MOV	#IE.SPC&377,R0	;

;
; COMMON EXIT FOR ALL FUNCTIONS
;

	.IFTF

ISCMN:				;
	CLR	R1		; CLEAR CONTENTS OF SECOND I/O STATUS WORD
	MOV	(SP)+,R3	; GET ADDRESS OF I/O PACKET
	MOV	ISUCB,R5	; GET UCB ADDRESS
	CALLR	$IOFIN		; COMPLETE REQUEST

;
; BRANCH POINT - LINK TO DIGITAL       INTERRUPT
;

	.IFT

ISLD:				;
	BR	ISLDI		;


;+
;
; **-ISRAD-READ ACTIVATING DATA
;
; FUNCTION DEPENDANT I/O PACKET FORMAT
;
;	WD. 12 -- ADDRESS OF 6-WORD BUFFER TO RECEIVE ACTIVATING DATA
;	WD. 13 -- UNUSED
;	WD. 14 -- UNUSED
;	WD. 15 -- UNUSED
;	WD. 16 -- UNUSED
;	WD. 17 -- UNUSED
;
;-

ISRAD:				;
	BIT	#1,(R1)		; BUFFER ALIGNED PROPERLY?
	BNE	ISBYT		; IF NE NO
	MOV	#ISLNK,R4	; GET ADDRESS OF LINKED TASK LISTHEAD
10$:				;
	MOV	(R4),R4		; GET LINK TO NEXT
	BEQ	ISNLK		; IF EQ       TASK NOT LINKED
	CMP	LTCB(R4),R0	; THIS TASK LINKED?
	BNE	10$		; IF NE NO
	MOV	(R1),R0		; GET BUFFER ADDRESS

	.IF DF	A$$CHK!M$$MGE

	MOV	#12.,R1		; GET SIZE REQUIRED
	CALL	$ACHCK		; ADDRESS-CHECK THE BUFFER
	BCS	ISPC		; IF C/S BUFFER OUTSIDE OF TASK SPACE

	.ENDC

	.IF DF	M$$MGE

	CALL	$RELOM		; RELOCATE AND MAP TO USER SPACE

	.ENDC

	ADD	#LACT,R4	; POINT TO THE ACTIVATION COUNT
	MOVB	#PR4,PS		;;; INHIBIT DEVICE INTERRUPTS
	MOV	(R4),(R0)+	;;; COPY ACTIVATION COUNT
	CLR	(R4)+		;;; RE      SET THE COUNT
	CLR	(R0)+		;;; SET PHYSICAL UNIT TO ZERO
	MOV	#1,(R0)+	;;; RETURN GENERIC CODE FOR DIGITAL INTERRUPTS
	CLR	(R0)+		;;; SET MODULE NUMBER TO ZERO
	MOV	(R4),(R0)+	;;; RETURN MODULE DATA
	MOV	(R4),(R0)	;;; RETURN CHANGE-OF STATE
	CLRB	PS		; ALLOW DEVICE INTERRUPTS
	BR	ISSUC		;

;+
;
; **-ISLDI-LINK TO DIGITAL INTERRUPTS
;
; FUNCTION DEPENDANT I/O PACKET FORMAT:
;
;	WD. 12 -- FIRST HALF OF TASK NAME
;	WD. 13 -- SECOND HALF OF TASK NAME
;	WD. 14 -- UNUSED
;	WD. 15 -- EVENT FLAG NU      MBER
;	WD. 16 -- MODULE NUMBER (MUST BE ZERO)
;	WD. 17 -- CHANGE-OF-STATE MASK
;
;-

ISLDI:				;
	MOV	R1,R3		; COPY ADDRESS OF PARAMETER BLOCK
	CALL	$SRSTD		; SEARCH FOR TCB ADDRESS
	BCS	ISNST		; IF C/S TASK NOT INSTALLED
	MOV	R0,R5		; SAVE TCB ADDRESS
	ADD	#6,R1		; POINT TO EVENT FLAG NUMBER
	MOV	(R1)+,R0	; GET EFN
	CMP	R0,#64.		; LEGAL EVENT FLAG NUMBER?
	BHI	ISIEF		; IF HI NO
	TST	(R1)+		; LEGAL INITIAL POINT?
	BNE	ISMOD		; IF NE NO
	MOV	(R1),R4		; GET CHANGE-OF-STATE MASK
	BEQ	ISBAD		;       IF EQ BAD PARAMETERS
	BIT	R4,#IPMSK	; DOES POINT EXIST?
	BNE	ISMOD		; IF NE NO
	BIT	R4,ISRES	; RESOURCE AVAILABLE?
	BNE	ISRSU		; IF NE NO
	MOV	R0,-(SP)	; SAVE EVENT FLAG NUMBER
	MOV	#LLGH,R1	; GET ADDRESS OF LINKED TASK ENTRY
	CALL	$ALOCB		; ALLOCATE BLOCK
	MOV	(SP)+,R3	; RESTORE EVENT FLAG NUMBER
	BCS	ISNOD		; IF C/S NO DYNAMIC STORAGE
	MOV	R0,-(SP)	; SAVE ADDRESS OF ENTRY
	MOV	R3,R0		; COPY EVENT FLAG NUMBER
	CALL	$CEFI		; CONVERT TO MASK AND ADDRESS
	MOV	(SP)+,R2	; RESTORE ADDRESS OF LINKED       TASK ENTRY
	CLR	(R2)		; CLEAR LINK TO NEXT
	MOV	R2,@ISLNK+2	; LINK ENTRY TO LAST
	MOV	R2,ISLNK+2	; SET NEW LAST
	TST	(R2)+		; POINT TO TCB ADDRESS
	MOV	R5,(R2)+	; SET ADDRESS OF TCB
	CLR	(R2)+		; CLEAR ACTIVATION COUNT
	MOV	#ILTBL-ILGH,R2	; GET ADDRESS OF INTERRUPT LINK TABLE MINUS OFFSET
	MOV	R4,R3		; COPY RESOURCE MASK
10$:				;
	ADD	#ILGH,R2	; POINT TO NEXT ENTRY
20$:				;
	ROR	R3		; ROTATE MASK
	BCS	30$		; IF C/S LINK THIS MODULE
	BNE	10$		; IF NE GO AGAIN
	BR	40$		; ELSE TESTED ALL ENTR      IES
30$:				;
	MOV	ISLNK+2,(R2)+	; ALLOCATE THIS RESOURCE
	MOV	R0,(R2)+	; SET EVENT FLAG MASK
	MOV	R1,(R2)+	; SET EVENT FLAG ADRESS
	CLR	(R2)+		; CLEAR RUN FLAG
	BIS	#100,@(R2)+	; ENABLE DEVICE INTERRUPTS
	BR	20$		; GO AGAIN
40$:				;
	BIS	R4,ISRES	; ALLOCATE ALL REQUESTED BITS
	JMP	ISSUC		;
;+
;
; **-$ISINT-DRS/DSS11 INTERRUPT SERVICE ROUTINE
;
;-

	.IFTF

$ISINT::			;;;

	.IFF

	RTI			;;; IGNORE SPURIOUS INTERRUPT

	.IFT

	MOVB	PS,TMP		;;; SAVE PROCESSOR STATUS WORD
	CALL	$INTS      V,PR4	;;; SAVE R4-R5, SET PRIORITY
	MOV	TMP,R5		;;; GET PS WORD
	BIC	#^C<17>,R5	;;; CLEAR ALL BUT DEVICE NUMBER
	CMP	R5,#I$$S11	;;; LEGAL DEVICE NUMBER
	BHIS	ISCAN		;;; IF HI NO EXIT ISR
	ASL	R5		;;; CONVERT TO WORD OFFSET
	MOV	$BTMSK(R5),R4	;;; GET CORRESPONDING BIT MASK
	MOV	R5,-(SP)	;;; COPY WORD OFFSET
	ASL	R5		;;; CONVERT TO INTERRUPT LINK TABLE OFFSET
	ASL	R5		;;; ...
	ADD	(SP)+,R5	;;;
	ADD	#ILTBL,R5	;;; COMPUTE ENTRY ADDRESS
	TST	@ILCSR(R5)	;;; RESET INTERRUPT REQUEST
	BIT	R4,ISRES	;;; R      ESOURCE ALLOCATED
	BEQ	ISCAN		;;; IF EQ NO
	INC	ILRUN(R5)	;;; SET RUN FLAG
	MOV	(R5),R5		;;; GET ADDRESS OF LINKED TASK ENTRY
	ADD	#LACT,R5	;;; POINT TO ACTIVITY COUNT
	TST	(R5)		;;; PREVIOUS DATA READ BY TASK
	BNE	10$		;;; IF NE NO
	INC	(R5)+		;;; SET ACTIVATION COUNT
	MOV	R4,(R5)		;;; RECORD MODULE DATA
	BR	30$		;;;
10$:				;;;
	BMI	20$		;;; IF MI TASK ALREADY MISSED ONE COUNT
	CLR	(R5)		;;; SET COUNT TO ZERO
20$:				;;;
	DEC	(R5)+		;;; DECREMENT COUNT
	BIS	R4,(R5)		;;; MERGE MODULE DATA
3      0$:				;;;
	TST	FORK		;;; FORK PENDING?
	BNE	ISCAN		;;; IF NE YES
	INC	FORK		;;; SET FORK PENDING
	MOV	ISUCB,R5	;;; GET ADDRESS OF UCB
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS
	CLR	FORK		; CLEAR FORK-PENDING
	MOV	#I$$S11,R5	; GET NUMBER OF DRS/DSS INSTALLED
	MOV	#ILTBL,R4	; GET ADDRESS OF INTERRUPT LINK TABLE
40$:				;
	TST	(R4)		; ANY TASK LINKED?
	BEQ	70$		; IF EQ NO
	TST	ILRUN(R4)	; RUN FLAG SET
	BEQ	70$		; IF EQ NO
	CLR	ILRUN(R4)	; RESET RUN FLAG
	MOV	(R4),R0		; GET ADDRESS OF LINKED TASK       ENTRY
	MOV	LTCB(R0),R0	; GET TCB ADDRESS
	MOV	T.STAT(R0),R1	; COPY TASK STATUS WORD
	BIT	#TS.EXE,R1	; TASK ACTIVE?
	BNE	60$		; IF NE NO
	BIT	#T2.ABO,T.ST2(R0) ; TASK BEING ABORTED?
	BNE	70$		; IF NE YES
	BIT	#TS.OUT,R1	; TASK OUT OF MEMORY?
	BEQ	50$		; IF EQ NO
	BIT	#TS.CKP,R1	; TASK CHECKPOINTED?
	BEQ	70$		; IF EQ NO
50$:				;
	MOV	ILEVA(R4),R2	; GET ADDRESS OF EVENT FLAG MASK
	BEQ	70$		; IF EQ NONE SPECIFIED
	BIS	ILEVM(R4),(R2)	; SET EVENT FLAG
	CALL	$SETCR		; ISSUE CONDITIONAL SCHEDULE RE      QUEST
	BR	70$		; GO AGAIN
60$:				;
	CLR	R1		; SET DEFAULT UIC
	CALL	$TSKRT		; REQUEST TASK
70$:				;
	ADD	#ILGH,R4	; POINT TO NEXT INTERRUPT LINK ENTRY
	DEC	R5		; DECREMENT MODULE COUNT
	BNE	40$		; IF NE GO AGAIN

	.IFTF

;+
;
; **-ISCAN-CANCEL I/O AND DEVICE TIMEOUT ENTRY POINT
;
;-

ISCAN:				;;;
	RETURN			;;;

;+
;
; **-ISPWF-DEVICE DEPENDANT POWER RECOVERY CODE
;
; THIS CODE IS ENTERED TO RESTORE THE STATE OF ALL INTERRUPT ENABLE BITS AND
; LATCHING OUTPUTS UPON POWER RECOVERY      .
;
;-

ISPWF:				;
	CALL	$SGFIN		; COROUTINE TO SET CARRY IF A TRAP	;TL020
				; THROUGH 4 (NONEXISTANT MEMORY)	;TL020
				; OCCURS				;TL020
	MOV	R5,ISUCB	; SAVE THE UCB ADDRESS

	.IFT

	MOV	#ILTBL,R0	; GET ADDRESS OF INTERRUPT LINK TABLE
	MOV	#I$$S11,R1	; SET NUMBER OF MODULES
10$:				;
	TST	(R0)		; TASK LINKED?
	BEQ	20$		; IF EQ NO
	BIS	#100,@ILCSR(R0)	; ENABLE MODULE INTERRUPTS
	BCS	40$		; BRANCH IF THE REGISTER WASN'T THERE	;TL020
20$:				;
	ADD	#ILGH,R0	; POINT TO NEXT ENTRY
	DEC      	R1		; DECREMENT MODULE COUNT
	BNE	10$		; IF NE GO AGAIN

	.ENDC

	.IF DF	I$$SDR&I$$SPW

	MOV	#ISPRV,R0	; GET ADDRESS OF PREVIOUS STATE TABLE
	MOV	#ISBUS,R1	; GET ADDRESS OF BUS VECTOR TABLE
	MOV	#I$$SDR*3,R2	; GET COUNT OF ADDRESSES TO REFRESH
	CLC			; CLEAR CARRY FOR $SGFIN		;TL020
30$:				;
	MOV	(R0)+,@(R1)+	; REFRESH BISTABLE OUTPUTS
	BCS	40$		; BRANCH IF THE REGISTER WASN'T THERE	;TL020
	DEC	R2		; DECREMENT ADDRESS COUNT
	BNE	30$		; IF NE GO AGAIN

	.ENDC

35$:	RETURN			;					;TL020     
									;TL020
;									;TL020
; THE UNIT IS SET OFFLINE IF ANY OF THE DEVICE REGISTERS DO NOT		;TL020
; EXIST									;TL020
;									;TL020
40$:	BISB	#US.OFL,U.ST2(R5)  ; SET UNIT OFFLINE			;TL020
	BR	35$		; RETURN				;TL020
									;**-1
	.END

          ¼LðskQ	› c,        	.TITLE	LKDRV
	.IDENT	/01.04/
 
;
; COPYRIGHT (C) 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 01.04
;
; B. S. MCCARTHY 22-MAR-78
; B. SCHREIBER	 14-SEP-78
;
;
; MODIFIED BY:
;
;	B. S. MCCARTHY 21-NOV-78
;
;	BM002 -- CORRECT SENSE OF 'LS11' BIT
;
;	B. S. MCCARTHY 26-SEP-79
;
;		BM038 -- RELEASE KMC BEFORE CALLING FORK
;
;	B. S. MCCARTHY 2      9-NOV-79
;
;		BM055 -- CLOSE TIMING WINDOW OPENED BY BM038
;
;	R. T. PERRON	22-MAY-81
;
;		RP058 -- CONDITIONALIZE SUPPORT TO PASS RUBOUTS/NULLS
;
; LP11/LS11 LINE PRINTER CONTROLLER DRIVER
; FOR USE WITH COMM-IOP-LP OPTION
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$, HWDDF$, PKTDF$, UCBDF$
	ABODF$			; DEFINE TASK ABORT CODES
	HWDDF$			; DEFINE HARDWARE REGISTERS
	PKTDF$			; DEFINE I/O PACKET OFFSETS
	UCBDF$			; DEFINE UCB OFFSETS
	.PAGE

;	LOCAL DATA BIT DEFINITIONS

;	SOME OF THESE DE      FINITIONS ARE INCLUDED FOR INFORMATION ONLY
;	AND ARE NOT REFERENCED IN THE DRIVER

;	LINE PRINTER STATUS WORD BIT DEFINITIONS (U.CW2)

LS11   = 100000			; LS11 PRINTER (1=YES)
LOWER  =  40000			; PRINTER KNOWN TO KMC-11 (1=YES)
ABRT   =  20000			; ABORT ISSUED
PWRFLG =  10000			; POWER FAIL RECOVERY IN PROGRESS
RQINPR =   4000			; REQUEST IN PROGRESS WHEN POWER FAILED
KNOWN  =   2000			; PRINTER KNOWN TO KMC-11 (1=YES)

;	LINE PRINTER WIDTH KNOWN TO KMC (LOW BYTE OF U.CW3)

SAVWID = 377			; C      URRENT SET WIDTH IN LOW BYTE

;	KMC-11/COMM-IOP-LP BIT DEFINITIONS

;	KMC CSR WORD 0 (SEL0)

RUN    = 100000			; RUN BIT (1=KMC RUNNING)
MC     =  40000			; MASTER CLEAR (SET TO 1 TO CLEAR KMC)
RQI    =    200			; REQUEST INPUT (SET TO REQUEST KMC INPUT_
IEO    =     20			; OUTPUT INTERRUPT ENABLE (SET TO ENABLE)
IEI    =      1			; INPUT INTERRUPT ENABLE (SET TO ENABLE)

;	KMC CSR WORD 1 (SEL2)

PRTNUM =   3400			; PRINTER NUMBER MASK
RDYO   =    200			; READY OUTPUT (1=READY)
RDYI   =           20			; READY INPUT (1=READY)
FNCBSI =      3			; BASE IN FUNCTION
FNCCTI =      1			; CONTROL IN FUNCTION
FNCBAI =      0			; BASE IN FUNCTION

;	KMC CSR WORD 2 (SEL4)

POLCNT = 177400			; POLLING COUNT FOR BASE IN FUNCTION

;	KMC CSR WORD 3 (SEL6)

KOPKOE =    200			; KILL ON ERROR OPTION (FOR CONTROL IN)
KOPNXT =     40			; DON'T EXPAND TABS OPTION
KOPVTL =     20			; CONVERT VT TO LF OPTION
KOPDRN =     10			; DISCARD RUBOUTS/NULLS OPTION
KOPDNP =      4			; DISCARD NON-PRINTING CHARACTERS       OPTION
KOPLUC =      2			; CONVERT LOWER TO UPPER CASE OPTION
KOPFPR =      1			; FAST PRINTER OPTIMIZATIONS OPTION

KMCABF =     10			; KILL (ABORT) FINISHED ON CONTROL OUT
KMCNXM =      6			; NON-EXISTENT MEMORY (WE CAN'T GET THIS?)
KMCONL =      4			; PRINTER ERROR CONDITION CLEAR
KMCOFL =      2			; PRINTER ERROR OCCURED (PAPER JAM,ETC.)

BEXT   = 140000			; BUS EXTENSION BITS FOR BUFF. ADDR. IN
KILASN =  20000			; KILL ASSIGN BIT
KILL   =  10000			; KILL BIT

;	BUFFER DESCRIPTOR BITS

L      ASTBF = 100000			; LAST DESCRIPTOR IN LIST

;                                                                       ; RP058
; DEFINE THE SYMBOL "L$$PRN" EITHER IN THE RSXMC.MAC CONDITIONAL        ; RP058
; ASSEMBLY FILE FOR YOUR SYSTEM OR REMOVE THE SEMICOLON (;) FROM        ; RP058
; THE LINE CONTAINING THE SYMBOL IN THE KMC LINE PRINTER DRIVER         ; RP058
; (LKDRV).                                                              ; RP058
;                                                                             ; RP058
;L$$PRN=0			;SYMBOL TO PASS RUBOUTS/NULLS           ; RP058
;                                                                       ; RP058
;	LOCAL DATA

LDNAM:	.RAD50	/LPINIT/	; MICROCODE LOADER TASK NAME
PWFCNT:	.WORD	0		; POWERFAIL INITIALIZATION COUNT
KMCSR2:	.WORD	0		; KMC-11 CSR ADDRESS +2

;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;

CNTBL:	.BLKW	L$$P11		;ADDRESS OF UNIT CONTROL BLOCK
	.PAGE
;
; DRIVER DISPATCH TABLE
;

$LPTBL::.WORD	LKINI	      	;DEVICE INITIATOR ENTRY POINT
	.WORD	LKCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	LKOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	LKPWF		;POWERFAIL ENTRY POINT
	.PAGE

;+
; **-LKINI-LP11/LS11 LINE PRINTER CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST      . ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
LKINI:	CALL	$GTPKT		; GET AN I/O PACKET TO PROCESS
	BCS	25$      		; IF CS CONTROLLER BUSY OR NO REQUEST

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; LINE PRINTER I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 0      3 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCATION BIAS OF I/O BUFFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
;	WD. 14 -- NUMBER OF B      YTES TO BE TRANSFERED.
;	WD. 15 -- CARRIAGE CONTROL BYTE.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
	.PAGE

	MOV	R5,CNTBL(R3)	; SAVE ADDRESS OF REQUEST UCB

	BIC	#ABRT,U.CW2(R5) ; CLEAR REQUEST ABORTED

	.IF DF	M$$MGE&M$$EXT

	CALL	$STMAP		; SETUP UNIBUS MAP

	.ENDC			; M$$MGE&M$$EXT

;	TEST TO SEE IF KMC KNOW'S ABOUT THIS PRINTER
;	AND ISSUE BASE IN IF NECESSARY

LKIN1:	BIT	#KNOWN,U.CW2(R5) ; PRINTER KNOWN ?
	BNE	10$		; IF NE YES
	CALL	WTKMC		; WAIT FOR KMC       READY
	MOV	U.KCS6(R5),R0	; POINT TO LAST REGISTER OF KMC
	MOV	S.CSR(R4),(R0)	; FILL IN CSR ADDRESS
	MOV	#L$$KPC*256.,-(R0) ; SET UP POLLING COUNT
	CLR	R4		; SCRATCH FOR UNIT/FUNCTION
	BISB	U.UNIT(R5),R4	; SET UNIT NUMBER
	SWAB	R4		; PUT IT IN HIGH BYTE
	BIS	#FNCBSI,R4	; SET BASE IN FUNCTION
	MOV	R4,-(R0)	; AND ISSUE FUNCTION
	MOV	U.SCB(R5),R4	; RESTORE SCB ADDRESS
	BIS	#KNOWN,U.CW2(R5) ; SET PRINTER KNOWN

;	TEST TO SEE IF PRINTER HAS BEEN INITIALIZED FOR CORRECT WIDTH
;	(CURRENT SET WIDTH IN U      .CW3)

10$:	CMPB	U.CW4(R5),U.CW3(R5) ; BUF SIZE CURRENT WIDTH ?
	BEQ	20$		; IF EQ YES, CONTROL IN WAS ISSUED
	CALL	WTKMC		; WAIT FOR KMC READY
	MOV	U.KCS6(R5),R0	; POINT TO END OF REGISTERS.
                                                                        ; RP058
                                                                        ; RP058
	.IF NDF	L$$PRN                                                  ; RP058
                                                                        ; RP058      
	MOV	#KOPDRN,R4	; SET FUNCTION TO DISCARD RUBOUTS/NULLS ; RP058
                                                                        ; RP058
	.IFF                                                            ; RP058
                                                                        ; RP058
	CLR	R4		; SET FUNCTION TO PASS RUBOUTS/NULLS    ; RP058
                                                                        ; RP058
	.ENDC                                                           ; RP0      58
                                                                        ; RP058
                                                                        ; RP058
	BIT	#LOWER,U.CW2(R5) ; LOWER CASE PRINTER                   ;**-1
	BNE	11$		; IF NE YES, OK
	BIS	#KOPLUC,R4	; SET LOWER TO UPPER CASE SUPPORT
11$:				; REF LABEL
	.IF DF	L$$11R
	BIT	#LS11,U.CW2(R5) ; FAST PRINTER ?
	BNE	12$		; IF NE NO
	BIS	#KOPFPR,R4	; SET FAST PRINTER OPTIMIZATIONS
	.ENDC			; DF L$$11R

12$:	MOV	R4,(R0)		; SET OPTI      ONS WORD
	MOV	U.CW4(R5),-(R0)	; SET PRINTER WIDTH
	CLR	R4		; SCRATCH FOR UNIT NUMBER/FUNCTION
	BISB	U.UNIT(R5),R4	; SET IN UNIT NUMBER
	SWAB	R4		; PUT IT IN HIGH BYTE
	BIS	#FNCCTI,R4	; SET CONTROL IN FUNCTION
	MOV	R4,-(R0)	; ISSUE FUNCTION
	MOV	U.SCB(R5),R4	; RESTORE SCB ADDRESS
	MOVB	U.CW4(R5),U.CW3(R5) ; SET PRINTER SIZE SET
	.PAGE

;	BUILD ADDRESS BUFFER IN I/O PACKET AND ISSUE REQUEST

20$:				; REFERENCE LABEL

	.IF DF	M$$MGE & M$$EXT

	MOV	R1,-(SP)	; SAVE I/O PACKET ADDRESS
	CALL	$MP      UBM		; MAP UNIBUS TO MEMORY
	MOV	(SP)+,R1	; RESTORE I/O PACKET ADDRESS

	.ENDC			; M$$MGE & M$$EXT

	CALL	WTKMC		; WAIT FOR KMC READY
	MOV	U.BUF+2(R5),I.PRM+10(R1) ; SET LOW PART OF BUFFER ADDR.
	MOV	U.CNT(R5),I.PRM+12(R1) ; AND LENGTH OF BUFFER
	MOV	U.BUF(R5),R0	; GET HIGH TWO BITS OF ADDR.
	SWAB	R0		; PUT IN HIGH BYTE
	ASR	R0		; SHIFT INTO BITS 10/11
	ASR	R0		;
	BIS	#LASTBF,R0	; SET FOR LAST FUNCTION
	BISB	I.PRM+6(R1),R0	; SET VFC BITS IN
	MOV	R0,I.PRM+14(R1) ; STORE INTO BUFF ADDR DESC.

      ;	BUFFER DESCRIPTOR BUILT IN WORDS 4,5,6 OF PARAM LIST

	MOV	U.KCS6(R5),R0	; POINT TO LAST ADDRESS OF KMC
	CLR	(R0)		; CLEAR OUT KILL BITS
	MOV	R1,R4		; COPY PACKET ADDRESS
	ADD	#I.PRM+10,R4	; POINT TO BUFFER DESCRIPTOR
	MOV	R4,-(R0)	; FILL IN BUFFER ADDRESS
	CLR	R4		; SCRATCH FOR UNIT NUMBER
	BISB	U.UNIT(R5),R4	; SET IN UNIT NUMBER
	SWAB	R4		; PUT IT IN HIGH BYTE
	MOV	R4,-(R0)	; AND START TRANSFER
25$:	RETURN			; EXIT FROM DRIVER
	.PAGE
;
;	POWERFAIL PROCESSING MARKS A DEVICE AS UNKNOWN AND O      F UNKNOWN
;	WIDTH. THE CONTROLLER IS MARKED AS BUSY EVEN IF IT IS IDLE, TO
;	PREVENT EARLY DEQUEUEING OF REQUESTS. A TIMEOUT IS FORCED IN 5
;	SECONDS, AND THE MICROCODE LOADER (LPINIT) IS REQUESTED. IF
;	LPINIT IS NOT INSTALLED AN ERROR MESSAGE IS ISSUED. WHEN
;	THE TIMEOUT OCCURS WE CHECK TO SEE IF THE KMC IS RUNNING.
;

LKPWF:	BIS	#PWRFLG,U.CW2(R5) ; SET POWERFAIL IN PROGRESS
	TST	CNTBL(R3)	; REQUEST IN PROGRESS
	BEQ	LKPWF0		; IF EQ NO
	BIS	#RQINPR,U.CW2(R5) ; SET REQUEST IN PROGRESS FLAG
LKPW      F0:	BIC	#KNOWN,U.CW2(R5) ; SET PRINTER UNKNOWN
	CLRB	U.CW3(R5)	; AND SET WIDTH TO 0 (FORCING ZERO)
	BISB	#US.KPF!US.BSY,U.STS(R5) ; SET POWERFAIL INTERLOCK
	MOVB	#1,S.STS(R4)	; FAKE CONTROLLER BUSY
	MOVB	#5,S.CTM(R4)	; FORCE 5 SECOND TIMEOUT
	DEC	PWFCNT		; IS THIS FIRST PRINTER ?
	BLT	30$		; IF LT YES, INVOKE REST OF POWERFAIL
	RETURN			; ELSE EXIT FROM DRIVER

30$:	MOV	#L$$P11-1,PWFCNT ; SET UP COUNT OF REST OF PRINTERS

	MOV	U.KCSR(R5),R0	; GET CSR ADDRESS OF PRINTER
	MOV	#MC,(R0)+	; MASTER CL      EAR KMC-11
	MOV	R0,KMCSR2	; SAVE ADDRESS OF SECOND CSR

;	REQUEST MICROCODE LOADER IF INSTALLED

	MOV	#LDNAM,R3	; GET NAME OF MICROCODE LOADER
	CALL	$SRSTD		; LOOK IT UP
	BCS	40$		; IF CS NOT THERE, ISSUE MESSAGE
	CALLR	$EXRQN		; REQUEST LOADER

40$:	MOV	#T.NKLF,R0	; MESSAGE NUM "MICROCODE LOADER NOT ..."
	CALLR	$DVMSG		; PRINT MESSAGE AND EXIT
	.PAGE
;+
; **-$LPINT-LP11/LS11 LINE PRINTER CONTROLLER INTERUPTS
;	(INTERRRUPTS ARE FROM COMM IOP, NOT PRINTER)
;
;	INPUT INTERRUPTS SHOULD NOT OCC      UR, AND ARE THEREFORE
;	DISMISSED IMMEDIATELY.
;
;	OUTPUT INTERRUPTS ARE CAUSED FOUR WAYS:
;
;	1) - BUFFER ADDRESS OUT - INDICATES SUCCESSFUL COMPLETION
;	     OF AN OUTPUT OPERATION
;	2) - CONTROL OUT - KMCABF SET IN KCS3 - ABORT COMPLETED
;	3) - CONTROL OUT - KMCONL SET IN KCS3 - PREVIOUS ERROR CLEARED
;	4) - CONTROL OUT - OTHER - ERROR CONDITION ON PRINTER
;-

$LPINP::			; IGNORE INPUT INTERRUPTS
				; ($LPINP IS NEEDED TO MAKE DRIVER LOAD
				; CORRECTLY)
	.IF NDF	L$$DRV ! M$$MGE ! LD$LP      

	RTI

	.IFF

	RETURN

	.ENDC
	.PAGE
$LPOUT::			;;; REF LABEL

	.IF NDF	L$$DRV ! M$$MGE ! LD$LP

	JSR	R5,$INTSV	;;; SINCE THERE'S ONE KMC VECTOR,
	.WORD	^C<PR5>&PR7	;;; NORMAL UCB CALC. DOESN'T WORK

	.ENDC

	MOV	@KMCSR2,R4	;;; GET PRINTER NUMBER FROM KMC
	BIC	#^C<PRTNUM>,R4	;;; STRIP OFF JUNK
	SWAB	R4		;;; INTO LOW HALF OF REG
	ASL	R4		;;; AND CREATE WORD INDEX
	MOV	CNTBL(R4),R5	;;; GET UCB ADDRESS
	BEQ	90$		;;; IF EQ DISMISS SPURIOUS INTERRUPT
	MOV	KMCSR2,R4	;;; GET ADDRESS OF KMC       CSR              ; BM038
	MOV	4(R4),R4	;;; GET PRINTER ERROR CODE              ; BM038
	SWAB	R4		;;; PUT INTO HIGH BYTE                  ; BM038
	CLRB	R4		;;; CLEAR OUT LOW BYTE                  ; BM038
	BISB	@KMCSR2,R4	;;; AND MERGE IN INTERRUPT CAUSE        ; BM038
	BIC	#IEO,@U.KCSR(R5) ;;; DISABLE KMC INTERRUPTS             ; BM055
	BIC	#RDYO,@KMCSR2	;;; RELEASE KMC                         ; BM038
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS             ; BM038
	BIS	#IEO,@U.KCSR(R5) ; RE-ENABLE KMC       INTERRUPTS             ; BM055
	MOV	R4,R0		; COPY INTERRUPT CAUSE                  ; BM038
	MOV	R4,R1		; COPY POSSIBLE ERROR BYTE              ; BM038
	SWAB	R1		; AND MOVE IT TO LOW BYTE               ; BM038
	MOV	U.SCB(R5),R4	; GET SCB                               ; BM038
	BIT	#1,R0		; WAS IT A CONTROL OUT ?                ;**-7

	BNE	70$		; IF NE YES
	MOV	#IS.SUC,R0	; SET SUCCESS STATUS
60$:	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS
	MOV	I.PRM+4(R1),R1	; GET REQUESTED BYTE COUNT
	CALL	$IODON		      ; FINISH I/O OPERATION
	MOV	U.SCB(R5),R4	; GET SCB ADDRESS
	MOVB	S.CON(R4),R4	; AND CONTROLLER INDEX
	CLR	CNTBL(R4)	; CLEAR UCB TABLE ENTRY
	JMP	LKINI		; AND START DRIVER AGAIN

70$:	CMPB	#KMCABF,R1	; ABORT FINISHED ?
	BNE	80$		; IF EQ NO
75$:	MOV	#IE.ABO,R0	; SET ABORT STATUS
	BR	60$		; AND OUT NORMALLY

80$:	CMPB	#KMCONL,R1	; PRINTER BACK NOW ?
	BNE	LKOUT		; IF EQ NO, MUST BE ERROR
	RETURN			; ELSE YES, THAT'S NICE.

90$:	BIC	#RDYO,@KMCSR2	; RELEASE KMC
	RETURN			; AND EXIT FROM DRIVER
	.      PAGE
;
;	TIMEOUT PROCESSING IS ENTERED FOR ANY OF THE FOLLOWING
;
;	1. 5 SECONDS AFTER POWER FAIL RECOVERY (ALSO LOAD,BOOT)
;	   THE DRIVER IS ENTERED AND TESTS TO SEE IF RECOVERY
;	   IS COMPLETE. IF IT IS, THE DRIVER STARTS OR RESTARTS
;	   AN OPERATION AS NECESSARY. IF NOT, THE TIMEOUT COUNT
;	   IS RESET TO 5 AND THE DRIVER EXITS.
;
;	2. FOLLOWING AN IO.KIL, IF THE REQUEST IS NOT COMPLETED
;	   NORMALLY BEFORE THE NEXT TIMEOUT CHECK, THEN A HARDWARE
;	   ABORT IS ISSUED HERE.
;
;	3. AFTER       A DEVICE ERROR, THE TIMEOUT SECTION TAKES CARE OF
;	   ISSUING NOT READY MESSAGES.
;

LKOUT:	MTPS	#0		;;;ALLOW INTERRUPTS
	BIT	#PWRFLG,U.CW2(R5) ; POWERFAIL RECOVERY IN PROGRESS ?
	BEQ	99$		; IF EQ NO
	BITB	#US.KPF,U.STS(R5) ; KMC RECOVERY COMPLETE ?
	BEQ	93$		; IF EQ YES
	MOVB	#5,S.CTM(R4)	; BETTER LUCK NEXT TIME
	RETURN			; (IN 5 SECONDS OR SO)
93$:	BIC	#PWRFLG,U.CW2(R5) ; CLEAR POWERFAIL FLAG
	BIT	#ABRT,U.CW2(R5)	; ABORT REQUESTED ?
	BNE	75$		; IF EQ YES, BUT REQUEST IS ALREADY
				; ABORTE      D (AND HOW) DUE TO KMC FAILURE
	BIT	#RQINPR,U.CW2(R5) ; REQUEST IN PROGRESS WHEN WE WENT DOWN ?
	BEQ	96$		; IF NE NO
	BIC	#RQINPR,U.CW2(R5) ; CLEAR REQUEST IN PROGRESS
	MOV	S.PKT(R4),R1	; RESTORE I/O PACKET ADDRESS
	JMP	LKIN1		; AND RESTART REQUEST
96$:	CLRB	S.STS(R4)	; CLEAR FAKE CONTROLLER BUSY
	BICB	#US.BSY,U.STS(R5) ; AND DECLARE UNIT IDLE
	JMP	LKINI		; TRY TO ACTIVATE CONTROLLER
99$:	BIT	#ABRT,U.CW2(R5)	; ABORT REQUESTED ?
	BEQ	100$		; IF NE NO

	CALL	WTKMC		; WAIT TILL IT'S READY
	MOV	U.K      CS6(R5),R0	; POINT TO LAST CSR
	MOV	#KILL,(R0)	; SET KILL FUNCTION
	CLR	-(R0)		; NO BUFF ADDR
	CLR	R1		; SCRATCH FOR PRINTER NUMBER
	BISB	U.UNIT(R5),R1	; SET IN UNIT NUMBER
	SWAB	R1		; PUT IT IN HIGH BYTE
	MOV	R1,-(R0)	; FILL IN PRINTER NUMBER AND START KILL
	RETURN			; WAIT TIL IT'S ALL OVER
	.PAGE

;	PROCESS DEVICE NOT READY MESSAGES

100$:				; REF LABEL
	.IF DF	T$$KMG

	MOV	#T.NDNR,R0	; SET FOR DEVICE NOT READY MESSAGE

	.IFTF			; DF T$$KMG

	MOVB	#1,S.CTM(R4)	; SET TIMEOUT FOR 1 SECO      ND

	.IFT			; DF T$$KMG

	DECB	S.STS(R4)	; TIME TO OUTPUT MESSAGE ?
	BNE	120$		; IF NE NO

	.IF NDF	L$$PTO

	MOVB	#15.,S.STS(R4)	; SET TO OUTPUT NEXT MESSAGE IN
				; 15. SECONDS

	.IFF			; NDF L$$PTO

	MOVB	#L$$PTO,S.STS(R4) ; SET TO OUTPUT NEXT MESSAGE IN
				  ; L$$PTO SECONDS
	BNE	110$		; IF NE LP NOT READY MESSAGES ENABLED
	INCB	S.STS(R4)	; LP NOT READY MESSAGE NOT WANTED, SO
	BR	120$		; RE-BUSY CONTROLLER

	.ENDC			; NDF L$$PTO

110$:	CALLR	$DVMSG		; OUTPUT MESSAGE

	.ENDC			;       DF T$$KMG

120$:	RETURN			; OUT !

	.DSABL LSB
	.PAGE
;
; CANCEL I/O OPERATION-FORCE I/O TO COMPLETE IF DEVICE IS NOT READY
;

LKCAN:	CMP	R1,I.TCB(R0)	;;; REQUEST FOR CURRENT TASK?
	BNE	10$		;;; IF NE NO
	BIS	#ABRT,U.CW2(R5)	;;; SET FOR ABORT IF DEVICE NOT READY
	MOVB	#1,S.CTM(R4)	;;; FORCE TIMEOUT IN 1 SECOND (OR LESS)
10$:	RETURN			;;;

;
;	SUBROUTINE TO WAIT FOR THE KMC TO BE READY
;
;	INPUTS:
;
;		R5 = UCB ADDRESS OF THE PRINTER
;
;	R0 IS DESTROYED.

WTKMC:	MOV	U.KCSR(R5),R0	; G   ¼  ET KMC CSR ADDRESS
	BIS	#RQI,(R0)	; REQUEST KMC INPUT
10$:	TST	(R0)		; IS THE KMC-11 RUNNING ?
	BPL	20$		; IF IT CAN'T TAKE A JOKE, POWERFAIL
	BIT	#RDYI,@KMCSR2	; READY BIT SET ?
	BEQ	10$		; IF EQ NO, WAIT SOME MORE
	BIC	#RQI,(R0)	; CLEAR REQUEST INPUT
	RETURN			; YES, BO BACK
20$:	BIS	#PWRFLG!RQINPR,U.CW2(R5) ; SET POWERFAIL IN PROGRESS
	TST	(SP)+		; WE WON'T BE RETURNING TO CALLER
	JMP	LKPWF0		; FINISH IN COMMON CODE

	.END
 ¼         ¬˜ðskQ	› c,        	.TITLE	XQDRV
	.IDENT	/03.3/
 
;
; COPYRIGHT (C) 1974, 1976, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 03.3
;
; EARL D. WALDIN 10-MAR-75
;
; PREVIOUSLY MODIFIED BY:
;
;	L. GILLESPIE
;	E. D. WALDIN
;
; MODIFIED BY:
;
; B. SCHREIBER	30-JUN-78
;
;	BLS056 -- CORRECT UMR ALLOCATION HANDLING
;
; C. SPITZ	9-AUG-78
;
;	CS015 -- CORRECT HANDLI      NG OF I/O KILLS
;
;	R. E. CALDWELL	29-OCT-79
;
;		RC024 -- REMOVE UNNEEDED CONDITIONALIZATION.
;
;
; DQ11 SYNCHRONOUS COMMUNICATIONS DRIVER
;


;
; MACRO LIBRARY CALLS
;

	.MCALL	PKTDF$,CLKDF$,HWDDF$
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	CLKDF$			;DEFINE CLOCK QUEUE PACKET OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	.MCALL	UCBDF$,CUCDF$
	UCBDF$			; DEFINE UCB OFFSETS
	CUCDF$			;COMMUNICATIONS UCB LABELS
;
; EQUATED SYMBOLS
;

;
; RXCSR BIT ASSIGNMENTS
;

RXGO=	1				;RECEIVE       GO, SET TO START RECEIVER
STRSYN=	2				;STRIP SYNC CHARACTERS WHEN SET
RXPS=	4				;RX PRIMARY OF SECONDARY REG ACTIVE(0=PR)
HDPX=	10				;HALF DUPLEX IF SET
RXDNIE=	40				;RECEIVER DONE INTERRUPT ENABLE
RXDNP=	200				;RECEIVE PRIMARY REGISTER DONE
RXDNS=	100				;RECEIVE SECONDARY REGISTER DONE
RXACT=	10000				;RECEIVER ACTIVE FLAG
RXDIS=	RXDNIE!RXDNP!RXDNS		;DISABLE RECIEVER MASK

;
; TXCSR BIT ASSIGN
;

TXGO=	1				;TRANSMIT GO
IDLSYN=	2				;IDLE SYNC MODE BIT
TXPS=	4				;TX PRI OF SEC REG AC      TIVE (0=PRI)
ERRIE=	10				;ERROR INTERRUPT ENABLE
DTSIE=	20				;DATA SET INTR ENABLE
TXDNIE=	40				;TX DONE INTR ENABLE
TXDNP=	200				;TX DONE PRIMARY REG
TXDNS=	100				;TX DONE SECONDARY REG
RTS=	400				;REQUEST TO SEND
DTR=	1000				;DATA TERMINAL READY
DSR=	2000				;DATA SET READY
CTS=	20000				;CLEAR TO SEND WHEN SET
DSFLG=	100000				;DATA SET FLG (RI!CTS!SQDT)
TXDISF=	^C<RTS!IDLSYN!DTR>		;TX DISABLE FOR FULL DUPLEX
TXDISH=	^C<DTR>				;TX DISABLE FOR HALF DUPLEX
TXNDIS=	TXDISF&<^CERRIE>		;TX       NETWORK DISABLE

;
;REG/ERR REGISTER BIT ASSIGNMENTS
;

ERRINT=	100000				;ERROR INTERRUPT
WRTEN=	20				;WRITE ENABLE BIT FOR EXTENSION BITS
TEXIT=	60				;EXIT TRANSPARENCY BITS
TENTR=	120				;ENTER TRANSPARENCY BITS
CCRG=	1!WRTEN				;CCRG!<BUF ADDR PTR>= COUNT REG
TXCLK=	1				;TX CLOCK LOSS ERROR
TXLAT	=4				;TX BUSS LATENCY ERROR
TXNEX=	20				;TX NON EXISTENT MEMORY ERROR
RXCLK=	2				;RX CLOCK LOSS ERROR
RXLAT=	10				;RX BUS LATENCY ERROR
RXNEX=	40				;RX NON EXISTENT MEMORY ERROR
BCCERR      =100				;BCC (RX) ERROR BIT
TXERR=TXCLK!TXLAT!TXNEX			;OR OF TRANSMIT ERROR BITS
RXERR=RXCLK!RXLAT!RXNEX!BCCERR		;OR OF RECEIVE ERROR BITS


;
;MISC SECONDARY REGISTER BIT ASSIGNMENTS
;

TXACT=	40000				;=1 WHEN TX IS ACTIVE
MSCLR=40				;MASTER CLEAR


;
; SECONDARY REGISTER ADDRESS ASSIGNMENTS
;

RXBAP=	0				;RX BUS ADDR PRIMARY REG
RXCCP=	1				;RX CHAR COUNT PRIMARY
TXBAP=	2				;TX BUS ADDR PRIMARY
TXCCP=	3				;TX CHAR COUNT PRIMARY
RXBAS=	4				;RX BUS ADDR SECONDARY
RXCCS=	5				;RX       CHAR COUNT SECONDARY
TXBAS=	6				;TX BUS ADDR SECONDARY
TXCCS=	7				;TX CHAR COUNT SECONDARY
SYNREG=	4400				;SYNC CHAR REGISTER
MISCRG= 5000				;MISC REGISTER
MISCRB= 12				;MISC REGISTER ADDR, HIGH BYTE
POLY= 7400				;POLYNOMIAL REGISTER FOR CRC
SEQREG=	6000				;SEQUENCE REGISTER FOR PROTOCOL OPTION

;
; MISC ASSIGNMENTS
;

TERM=	U2.CTS!U2.HDX!U2.ONL!U2.SNC!U2.RCV	;U.CW2 BITS WHICH
					;ARE CLEARED ON TERMINATE
CLNGTH=4000				;SETS CHAR LENGTH TO 8 BITS
CRC16=120001				;POLYNOMIAL REG BIT      S FOR CRC 16
IE.BCC=-64.				;RX BCC ERROR CODE

	MXSYNC=10.

;
; LOCAL DATA
;

;
; UNIT IMPURE DATA TABLE
;

CNTBL:					;REF LABEL
UNITBL: .REPT  D$$Q11			;UCB ADDRESS TABLE
					;INDEXED BY CONTROLLER NUMBER
	.WORD	0

	.ENDM

	.IF GT	D$$Q11-1

TEMP:					;REF LABEL
UNIT:	.BLKW	1

	.ENDC
;									;**-3
; DEVICE DISPATCH TABLE
;

$XQTBL:: .WORD DQINIT			;DEVICE INITILIZATION
	 .WORD DQCANC			;DEVICE I/O CANCEL ENTRY
	 .WORD DQTMO			;TIMEOUT ENTRY
	 .WORD DQPWRF			;POWER FAIL       ROUTINE
;+
;**- DQINIT - DQ-11 SYNCHRONOUS COMMUNICATION CONTROLLER I/O INITIATOR
;
; DQINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE
; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE
; NORMAL RSX-11M INPUT/OUTPUT LOGIC FLOW.  IF THE DEVICE IS
; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT,
; THE REQUEST IS INITIATED.
; IF NO REQUEST EXISTS FOR THAT UNIT OR IF IT IS BUSY,
; AN EXIT IS TAKEN TO THE CALLER.  NOTE THAT BECAUSE OF THE
; NATURE OF THE DQ-11, EACH UNIT IS A       CONTROLLER ITSELF, HAS
; ITS OWN SCB, AND THEREFORE ITS OWN QUEUE.
; EACH TIME DQINIT IS CALLED, IT IS CALLED TO SERVICE ONLY
; THE UNIT SPECIFIED IN THE CALL.
;
; INPUTS:
;	R4 = STATUS CONTROL BLOCK ADDRESS
;	R5 = ADDRESS OF THE UCB TO BE INITIATED.
;
; OUTPUTS;
;	IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE
;	DEVICE IS INITIATED APPROPRIATELY.
;
;-
	.ENABL	LSB							;**-5

DQINIT:					;REFERENCE LABEL
	CALL	$GTPKT			;GET I/O PACKET TO PROCESS	;**-9
	BCC	10$			;CC MEANS WORK TO DO
DQRET:	R      ETURN

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1= ADDRESS OF I/O REQUEST PACKET
;	R2= PHYSICAL UNIT NUMBER OF REQUEST UCB
;	R3= CONTROLLER INDEX
;	R4= ADDRESS OF STATUS CONTROL BLOCK
;	R5= ADDRESS OF THE UCB SPECIFIED IN THE DQINIT CALL
;
; DQ11 I/O REQUEST PACKET FORMAT
;
;	WORD	     CONTENT
;
;	  0	I/O QUEUE THREAD WORD
;	  1	REQUEST PRIORITY, EVENT FLAG NUMBER
;	  2	ADDRESS OF THE TCB OF THE REQUESTER TASK
;	  3	POINTER TO SECOND LUN WORD IN TASK HEADER
;	  4	CONTENTS       OF FIRST LUN WORD (UCB)
;	  5	I/O FUNCTION CODE
;	  6	VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	  7	RELOCATION BIAS OF I/O STATUS BLOCK
;	 10	I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)
;	 11	VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	 12	RELOCATION BIAS OF I/O BUFFER
;	 13	BUFFER ADDRESS FOR TRANSFER
;	 14	TOTAL BYTE COUNT TO TRANSFER
;	 15	NOT USED
;	 16	NOT USED
;	 17	NOT USED
;	 20	NOT USED
;


10$:	MOV	S.CSR(R4),R2		;GET RX CSR ADDR
	ADD	#I.FCN+1,R1		;POINT TO I/O FUNC CODE
	CM      PB	#IO.INL/256.,(R1)	;CHECK IF TRANSFER FUNC
	BLOS	110$			;BR IF CONTROL FUNCTION
	BIT	#U2.ONL,U.CW2(R5)	;IS DEVICE ONLINE
	BNE	30$			;CONTINUE
20$:	JMP	210$			;DEVICE NOT READY

30$:					;REFERENCE LABEL
	BIT	#DSR,2(R2)		;DATA SET READY?		;**-3
	BEQ	20$			;BRANCH IF NOT READY
	.IF DF	M$$MGE							;**-3

	.IF DF	M$$EXT

	CMP	#4096.,U.CNT(R5)	;BUFFER TOO BIG?
	BHIS	33$			;CONTINUE IF NOT
	MOV	#IE.SPC&377,R0		;SIGNAL BUFFER TOO BIG
	JMP	UNSUCC			;FINISH I/O

33$:	CALL	$STMAP			;GET DEVICE'S       BUS ADDRESS
	MOV	R1,-(SP)		;SAVE R1
	MOV	R2,-(SP)		;AND R2
	CALL	$MPUBM			;MAP 11/70 UNIBUS FOR DEVICE
	MOV	(SP)+,R2		;RESTORE R2 AND R1
	MOV	(SP)+,R1

	.ENDC

	MOV	U.BUF(R5),R0		;GET MEMORY EXTENSION BITS
	ASL	R0			;PUT THEM IN BITS 5 & 6
	BIS	#WRTEN,R0		;OR IN WRITE ENABLE BIT

	.IFF

	MOV	#WRTEN,R0		;ZERO MEMORY EXTENSION BITS

	.ENDC

	CMPB	#IO.RLB/256.,(R1)	;IS FUNC READ LOGICAL?
	BEQ	100$			;YES, GO TO READ REQ

; FALL THROUGH ON TRANSMIT REQUEST
	TST	(R2)+			;POINT TO TXCSR			;      **-13
	BIS	#RTS,(R2)+		;SET REQUEST TO SEND
	INC	R2			;POINT TO ERR/REG HIGH BYTE
	CALL	TNEXT			;GET NEXT BUFFER REGISTER ADDR
	BIS	#WRTEN,R3		;CLEAR MEM EXT BITS
	MOVB	R3,(R2)+		;SET UP SECONDARY REGISTER PTR
	MOV	U.QSYN(R5),(R2)		;LOAD ADDRESS OF SYNC BUFFER
	BIS	#CCRG,R3		;SELECT CHAR COUNT REG
	MOVB	R3,-(R2)		;SET UP SECONDARY REG PTR
	MOVB	U.NSYN(R5),R1		;GET NO.OF SYNCS TO SEND
	CMPB	#MXSYNC,R1		;COUNT EXCEED SPACE?
	BHIS	40$			;BR IF NOT
	MOV	#MXSYNC,R1		;SET COUNT TO MAX OF 8 SYNCS
40$:      	NEG	R1			;COUNT IN 2'S COMPLEMENT
	MOV	R1,1(R2)		;COUNT INTO DQ
	BIS	#U2.SNC,U.CW2(R5)	;SAY SENDING SYNCS
	CALL	TOAN			;SETUP SECOND BUFFER
50$:	BIS	R0,R3			;OR IN MEM  EXT BITS
	MOVB	R3,(R2)+		;SET UP SECONDARY REG PTR
	MOV	U.BUF+2(R5),(R2)	;USER BUFFER ADDR INTO DQ	;**-7
	BIC	R0,R3			;CLR OUT MEM EXT BITS

	.IF DF	Q$$CRC

	BIS	#CCRG!TENTR,R3		;SELECT COUNT REG, START CRC

	.IFF

	BIS	#CCRG,R3		;JUST SELECT COUNT REG

	.ENDC

55$:	MOVB	R3,-1(R2)		;SET UP SECONDARY REG PTR
	NEG	U.CNT(R5      )		;COUNT IN 2'S COMPLEMENT
	MOV	U.CNT(R5),(R2)		;LOAD COUNT INTO DQ
	MOVB	S.ITM(R4),S.CTM(R4)	;SET TIMEOUT
	TST	-(R2)			;POINT TO ERR/REG REG
	BIT	#CTS,-(R2)		;CTS SET YET?
	BEQ	70$			;BR IF NOT SET YET
	BIS	#TXGO!TXDNIE!ERRIE,(R2)  ;START XMIT, ENABLE INTERRUPTS
	BR	80$			;RETURN

70$:	BIS	#U2.CTS,U.CW2(R5)	;SAY CTS EXPECTED IN UCB
	BIS	#DTSIE,(R2)		;ENABLE DATA SET INTERRUPTS
80$:	RETURN				;RETURN, INTR PROPAGATES XMIT

;
; RECEIVE FUNCTION INITIATION
;


100$:					;REFERENCE LABEL
	      ADD	#5,R2			;POINT TO ERR/REG HIGH BYTE	;**-4
	CALL	RNEXT			;SETUP FIRST BUFFER
	BIS	R0,R3			;OR IN MEMORY EXTENSION BITS
	MOVB	R3,(R2)+		;SET UP SECONDARY REG PTR
	MOV	U.BUF+2(R5),(R2)	;USER BUFFER ADDR INTO DQ
	BIC	R0,R3			;CLR OUT MEM EXT BITS
	BIS	#TENTR!CCRG,R3		;SELECT CC REG AND ENTER TRANS
	MOVB	R3,-1(R2)		;SET UP SECONDARY REG PTR
	MOV	U.CNT(R5),(R2)		;DATA COUNT INTO DQ
	NEG	(R2)			;COUNT IN 2'S COMPLEMENT
	DEC	R2			;POINT TO ERR/REG HIGH BYTE


	.IF DF	Q$$CRC

	CALL	ROAN			;SETUP S      ECOND BUFFER
	BIS	#TEXIT!CCRG,R3		;SELECT CC AND EXIT TRANS
	MOVB	R3,(R2)			;SET UP SECONDARY REG PTR
	CLR	1(R2)

	.ENDC


	DEC	R2			;POINT TO ERR/REG REGISTER
	BIS	#ERRIE,-(R2)		;ENABLE ERROR INTERRUPTS
	BIS	#RXGO!RXDNIE,-(R2)	;START RECEIVER
	RETURN				;RETURN, INTERRUPTS PROPAGATE RECEIVE
; FUNCTION WAS CONTROL FUNCTION						;**-8

110$:	BNE	160$			;BR IF CHANGE MODE FUNCTION
	TSTB	-(R1)			;TEST SUBCODE
	BNE	220$			;FUNCTION WAS TERMINATE

; START FUNCTION INITIATION


	CMP	(R2)+,(R2      )+		;POINT TO ER/REG
	MOV	#MISCRG,(R2)		;SELECT MISCELL REG
	MOV	#MSCLR,2(R2)		;AND DO A MASTER CLEAR
	MOVB	#20,R0			;SET UP TO CLEAR SEC REGS
120$:	MOVB	R0,1(R2)		;SELECT SECONDARY REGISTER
	CLR	2(R2)			;CLEAR SECONDARY REGISTER
	INC	R0			;NEXT SEC REG ADDR
	CMPB	#30,R0			;LAST REG TO CLEAR
	BHI	120$			;BR IF MORE TO CLEAR


	.IF DF	Q$$HPT

	BIT	#U2.HPT,U.CW2(R5)	;DOES DEVICE HAVE PROTOCOL OPTION?
	BEQ	125$			;BR IF NO
	MOV	#17,R0			;SET UP TO CLR SEQUENCE SCRATCHPAD
	MOV	#SEQREG,(R2)		;SEL      ECT SEQUENCE REG
122$:	MOVB	R0,-3(R2)		;INDEX INTO SEQUENCE SCRATCHPAD
	CLR	2(R2)			;CLEAR ENTRY
	DEC	R0
	BGE	122$			;BR IF MORE TO GO

	.ENDC


125$:	MOV	#MISCRG,(R2)+		;SELECT MISC REGISTER
	MOV	#CLNGTH,(R2)		;SET CHARACTER LENGTH
	MOV	#SYNREG,-(R2)		;SELECT SYNC REGISTER
	MOVB	U.SYNC(R5),-(SP)	;GET SYNC CHAR FROM UCB
	MOVB	(SP),1(SP)		;COPY LOW BYTE INTO HIGH BYTE
	MOV	(SP)+,2(R2)		;LOAD DQ SYNC REG

	.IF DF	Q$$CRC

	MOV	#POLY,(R2)		;SELECT POLYNOMIAL REG
	MOV	#CRC16,2(R2)		;LOAD POLYN      OMIAL FOR CRC16

	.ENDC


	BIS	#DTR,-(R2)		;SET DATA TERMINAL READY
	TST	U.CW2(R5)		;IN HALF DUPLEX?
	BPL	130$			;BR IF FULL DUPLEX
	BIS	#HDPX,-(R2)		;SET HALF DUPLEX IN RXCSR
130$:	MOV	R5,UNITBL(R3)		;PUT UCB INTO TABLE
	MOV	U.QSYN(R5),R0		;SYNC BUFFER ALREADY ALLOCATED?
	BNE	135$			;DON'T RE-ALLOCATE BUFFER
	MOV	#MXSYNC,R1		;GET SIZE OF SYNC BUFFER
	CALL	$ALOCB			;TRY TO ALLOCATE BUFFER
	BCS	210$			;BR IF COULDN'T
	MOV	R0,U.QSYN(R5)		;SAVE POINTER TO AREA
135$:	BIS	#U2.ONL,U.CW2(R5)	;MARK       DEVICE ONLINE
	MOV	#MXSYNC,R2		;SET UP TO LOAD SYNC BUFFER	;**-12
150$:	MOVB	U.SYNC(R5),(R0)+	;MOV SYNC CHAR INTO BUFFER
	DEC	R2			;MORE TO PUT IN?
	BGT	150$			;BR IF MORE TO GO
	BR	SUCC			;COMPLETE I/O DONE


; SERVICE DEVICE MODE CHANGE REQUEST

160$:	BITB	#IO.HDX,-(R1)		;HALF DUPLEX SUBFUNCTION?
	BEQ	170$			;BR IF NOT
	BIS	#U2.HDX,U.CW2(R5)	;SET HALF DUPLEX
170$:	BITB	#IO.FDX,(R1)		;FULL DUPLEX SUBFUNCTION?
	BEQ	200$			;BR IF NOT
	BIT	#U2.LIN,U.CW2(R5)	;DEVICE CAPABLE OF FULL DUPLEX?
	BEQ      	190$			;BR IF YES
180$:	MOV	#IE.IFC&377,R0		;SIGNAL ILLEGAL FUNCTION CODE
	BR	UNSUCC			;FINISH I/O UNSUCCESSFUL

190$:	BIC	#U2.HDX,U.CW2(R5)	;SET FULL DUPLEX CHARACTERISTIC
200$:	BITB	#IO.SYN,(R1)		;SYNC CHARACTER SPECIFIED?
	BEQ	SUCC			;DO I/O DONE IF NOT
	MOVB	I.PRM-I.FCN(R1),U.SYNC(R5) ;MARK NEW SYNC CHAR
	BR	SUCC			;COMPLETE I/O DONE


; CAN'T ESTABLISH COMMUNICATIONS

210$:	MOV	#IE.DNR&377,R0		;SAY DEVICE NOT READY
	BR	UNSUCC			;DO I/O DONE

;FUNCTION WAS TERMINATE LINE

220$:	CMP	(R      2)+,(R2)+		;POINT TO ER/REG
	MOV	#MISCRG,(R2)+		;SELECT MISC REG
	MOV	#MSCLR,(R2)		;AND DO A MASTER CLEAR
	BIC	#TERM,U.CW2(R5)		;CLR STATUS BITS IN UCB
	CLR	UNITBL(R3)		;REMOVE UCB FROM UNITBL
	MOV	U.QSYN(R5),R0		;GET FORK BLOCK AREA
	BEQ	SUCC			;DON'T RELEASE IF NOT ALLOCATED
	MOV	#MXSYNC,R1		;SET SIZE OF FORK AREA
	CALL	$DEACB			;RELEASE BLOCK AREA
	CLR	U.QSYN(R5)		;SIGNAL NOTHING THERE
SUCC:	MOV	#IS.SUC&377,R0		;SUCC COMP ENTRY
UNSUCC:	CLRB	S.STS(R4)		;IDLE CONTROLLER
	BICB	#US.BSY,U.STS(R5)	      ;MARK UNIT IDLE
	MOV	R0,-(SP)		;SAVE STATUS WORD 1
	MOV	S.PKT(R4),-(SP)		;SAVE OLD PACKET ADDR
	CALL	DQINIT			;TRY TO ACT NEXT REQ
	MOV	(SP)+,R3		;GET OLD I/O PACKET
	MOV	I.PRM+4(R3),R1		;RETURN REQ ITEM CNT
	MOV	(SP)+,R0		;GET STATUS WORD 1
	CALLR	$IOFIN			;TERMINATE OLD PACKET


; I/O CANCELLATION ENTRY
;
;	INPUTS:
;		R5 = ADDRESS OF UNIT CONTROL BLOCK
;		R4 = ADDRESS OF STATUS CONTROL BLOCK
;		R1 = TCB ADDRESS OF TASK FOR CANCELL
;		R0 = ADDRESS OF CURRENT PACKET
;

DQCANC:					;;;REF      ERENCE LABEL
	CMP	R1,I.TCB(R0)		;;;CURRENT PACKET FOR THIS TASK?;**-7
	BNE	225$			;;;RETURN IF NOT
	CMPB	#IO.WLB/256.,I.FCN+1(R0);;;TRANSMIT?
	BEQ	225$			;;;JUST LET FINISH IF YES
	MOV	#IE.ABO&377,R0		;;;ASSUME WE WILL ABORT
	BIT	#RXACT,@S.CSR(R4)	;;;IS RECEIVER ACTIVE?
	BNE	217$			;RECEIVER IS ACTIVE
	BIT	#RXDNP!RXDNS,@S.CSR(R4)	;HAS RECEIVE FINISHED?
	BNE	225$			;IF NE, YES, LET IT BE SUCCESSFUL
217$:	BIC	#RXDIS!RXGO,@S.CSR(R4)	;DISABLE RECEIVER
	BR	UNSUCC			;FINISH UNSUCCESSFUL I/O
225$:	RETU      RN				;;;RETURN TO CALLER

; POWERFAIL ENTRY FOR NON NETWORKS

DQPWRF:	MOV	S.CSR(R4),R2		;;;GET DEVICE CSR ADDRESS
	BIC	#RXDIS!RXGO,(R2)+	;;;DISABLE RECEIVER
	BIC	#TXDISH,(R2)+		;;;DISABLE TRANSMITTER
	CLRB	(R2)			;;;CLEAR ALL ERROR BITS
	MOVB	#2,S.CTM(R4)		;;;FORCE TIMEOUT
230$:	RETURN				;;;RETURN TO CALLER
; TIMEOUT ENTRY								;**-10
; THIS CODE IS ENTERED WHEN THE TRANSMIT TIMEOUT COUNT GOES TO ZERO.

DQTMO:	MOV	S.CSR(R4),R2		;;;GET CSR IN R2
	BIC	#TXDISH,2(R2)		;;;DISABLE TRANSMITTER
	      BIC	#U2.CTS,U.CW2(R5)  	;;;CLR WAITING FOR CTS FLAG
	MTPS	#0			;;;DROP PRIORITY LEVEL
	BR	UNSUCC			;FINISH I/O UNSUCCESSFUL	;**-3
	.DSABL	LSB							;**-7
;+
; TNEXT,TOAN,RNEXT AND ROAN ARE SUBROUTINES WHICH SELECT THE
; APPROPRIATE BUFFER ADDRESS REGISTER TO USE.  TNEXT (TRANSMIT)
; AND RNEXT (RECEIVE) SELECT THE NEXT BUFFER AS INDICATED BY THE
; TXPS AND TXPS STATUS BITS RESPECTIVELY.  TOAN AND ROAN SELECT THE
; BUFFER WHICH IS THE ONE AFTER THE NEXT BUFFER TO BE USED. (IE.
; FOR DOUBLE BUFFERIN      G AHEAD)
;
;	INPUTS:
;		R2 = ADDR OF DQ ERR/REG REGISTER, HIGH BYTE
;
;	OUTPUTS:
;		R3 = APPROPRIATE SECONDARY REGISTER ADDRESS
;-

	.ENABL	LSB

TNEXT:	BIT	#TXGO,-3(R2)		;CURRENT BUFFER ACTIVE?
	BNE	TOAN			;USE OTHER IF YES
	BIT	#TXPS,-3(R2)		;PRIMARY OR SEC REG ACTIVE?
	BNE	20$			;BR IF SECONDARY
	BR	10$			;BR IF PRIMARY

TOAN:	BIT	#TXPS,-3(R2)		;PRIMARY OR SECONDARY ACTIVE?
	BEQ	20$			;BR IF SECONDARY NOT ACTIVE
10$:	MOV	#TXBAP,R3		;SELECT PRIMARY TX REG
	RETURN				;RETURN
20$:	MOV	#T      XBAS,R3		;SELECT SECONDARY TX REG
	RETURN				;RETURN

	.IF DF Q$$CRC							; RC024
									;**-1
ROAN:	BIT	#RXPS,-5(R2)		;PRIMARY OR SECONDARY ACTIVE?
	BEQ	40$			;BR IF SEC NOT ACTIVE
	BR	30$			;BR IF PRI NOT ACTIVE

	.IFTF

RNEXT:					;REFERENCE LABEL

	.IFT

	BIT	#RXACT,-5(R2)		;RECEIVER ACTIVE?
	BNE	ROAN			;USE ROAN IF ACTIVE

	.ENDC

	BIT	#RXPS,-5(R2)		;PRIMARY OR SECONDARY ACTIVE?
	BNE	40$			;BR IF SEC ACTIVE
30$:	CLR	R3			;SELECT PRIMARY RECEIVE REG
	RETURN				;RETURN

40$:	M      OV	#RXBAS,R3		;SELECT SECONDARY RECEIVE REG
	RETURN

	.DSABL	LSB

;
; TRANSMIT INTERRUPT ROUTINE
;

	.ENABL	LSB

$XQOUT::				;;;REFERENCE LABLE
	INTSV$	XQ,PR5,D$$Q11		;;;GENERATE INTERRUPT SAVE CODE
	CALL	DQSET			;;;RXCSR->R4, UCB->R5
	TST	(R4)+			;;;POINT TO TXSCR
	BIT	#U2.CTS,U.CW2(R5)	;;;CTS EXPECTED?
	BEQ	20$			;;;BR IF NOT EXPECTED
	BIT	#CTS,(R4)		;;;IS CTS SET?
	BEQ	10$			;;;BR IF NOT SET YET
	BIC	#DTSIE,(R4)		;;;DISABL DATASET INTERRUPTS
	BIS	#TXGO!TXDNIE!ERRIE,(R4) ;;;START TRAN      SMIT
	BIC	#U2.CTS,U.CW2(R5)	;;;CLR CTS EXPECTED IN UCB
10$:	BIC	#DSFLG,(R4)		;;;RESET DATA SET FLAG
20$:	TST	2(R4)			;;;ANY ERRORS?
	BPL	22$			;;;BR IF NO ERRORS
	JMP	ERROR			;;;GO TO ERROR ROUTINE

22$:					;;;REFERENCE LABEL

	BIT	#TXDNP,(R4)		;;;PRIMARY BUFFER FINISH?
	BNE	70$			;;;BR IF YES
	BIT	#TXDNS,(R4)		;;;SECONDARY BUFFER FINISH?
	BNE	25$			;;;BR IF YES
	JMP	DQEXIT			;;;EXIT FROM INTERRUPT

25$:	BIC	#TXDNS,(R4)		;;;CLR SECONDARY DONE
	BR	80$			;;;CONTINUE
70$:	BIC	#TXDNP,(R4)		;;;      CLR PRIMARY DONE
80$:	BIT	#U2.SNC,U.CW2(R5)	;;;SENDING SYNCS?
	BEQ	180$			;;;BR IF SENDING DATA
	BIC	#U2.SNC,U.CW2(R5)	;;;CLR SENDING SYNCS IN UCB
	MOV	R2,-(SP)		;;;SAVE R2

	.IF DF	Q$$CRC

	MOV	R3,-(SP)		;;;SAVE R3
	MOV	R4,R2			;;;COPY CSR ADDR
	ADD	#3,R2			;;;POINT TO ERR/REG HIGH BYTE
	CALL	TNEXT			;;;GET NEXT REGISTER POINTER
	BISB	#CCRG!TEXIT,R3		;;;FORCE EXIT TRANSPARENCY
	MOVB	(R2),-(SP)		;;;SAVE OLD SECONDARY POINTER
	MOVB	R3,(R2)+		;;;SETUP SECONDARY ADDR
	CLR	(R2)			;;;SET COUNT OF       ZERO
	MOVB	(SP)+,-(R2)		;;;RESTORE OLD SECONDARY POINTER

	.IFTF

	MOV	U.SCB(R5),R2		;;;GET SCB ADDR
	MOVB	S.ITM(R2),S.CTM(R2)	;;;RESET TIMEOUT

	.IFT

	MOV	(SP)+,R3		;;;RESTORE R3

	.ENDC

	MOV	(SP)+,R2		;;;RESTORE R2
	BR	20$			;;;CHECK FOR NEW FLAGS

180$:	BIC	#TXDISF,(R4)		;;;DISABLE TRANSMITTER
	CALL	$FORK			;GO TO FORK LEVEL
TXTRN:	MOV	U.SCB(R5),R4		;GET SCB ADDRESS INTO R4
	MOV	S.CSR(R4),R2		;GET DEVICE RXCSR
	TST	(R2)+			;POINT TO TXCSR
	TST	U.CW2(R5)		;IN HALF DUPLEX?		;**-7
	      BPL	220$			;BR IF FULL DUPLEX		;**-3
	MOVB	#MISCRB,3(R2)		;SELECT MISCELLANEOUS REG
	BIT	#TXACT,4(R2)		;TX STILL ACTIVE?
	BEQ	210$			;BR IF FINISHED
	MOV	R4,R0			;SCB ADDR INTO R0
	ADD	#S.XQCK,R0		;POINT TO CLOCK QUEUE BLOCK
	CLR	R1			;CLR HIGH TIME
	MOV	#1,R2			;SET TIMEOUT OF ONE TICK
	MOV	#C.SYST,R4		;SIGNAL INTERNAL REQUEST
	MOV	#200$,C.SUB(R0)		;SET TIMEOUT ADDRESS
	CALLR	$CLINS			;QUEUE A CLOCK PACKET

200$:	MOV	C.TCB(R4),R5		;RECOVER UCB ADDR
	BR	TXTRN			;CHECK ACTIVE AGAIN

210$:	BIC	      #RTS,(R2)		;CLEAR REQUEST TO SEND

220$:					;REFERENCE LABEL
	JMP	SUCC			;FINISH I/O			;**-3
	.DSABL	LSB							;**-10
ERROR:					;;;REFERENCE LABEL
	TST	-(R4)			;;;POINT TO RXCSR		;**-3
	BIC	#RXDIS,(R4)+		;;;DISABLE RECEIVER
	BIC	#TXDISH,(R4)+		;;;DISABLE TRANSMITTER
	CALL	$FORK			;;;GO TO FORK LEVEL
RBCERR:	MOV	(R4),R0			;;;GET ERROR BITS IN R0
	CLRB	(R4)			;;;CLR ERROR BITS IN DEVICE
	BIT	#TXCLK!TXLAT!RXCLK!RXLAT,R0  ;;;CLOCK OR LATENCY ERROR?
	BEQ	10$			;;;BR IF NOT
	MOV	#IE.DAO&377,R0		;      ;;SIGNAL DATA OVERRUN ERROR
	BR	30$			;;;CONTINUE

10$:	BIT	#RXNEX!TXNEX,R0		;;;NON EXISTENT MEMORY ERROR?
	BEQ	20$			;;;BR IF NOT
	MOV	#IE.SPC&377,R0		;;;SIGNAL SPACE ERROR
	BR	30$			;;;CONTINUE

20$:	MOV	#IE.BCC&377,R0		;;;MUST BE BCC ERROR
30$:	MOV	U.SCB(R5),R4		;;;GET SCB ADDR FOR I/O DONE
	CALLR	UNSUCC			;;;FINISH I/O
;
;DQSET - SET UP REGISTER R4 WITH RXCSR ADDR, R5 WITH
;	UCB ADDR. UNIT NUMBER IN LOW ORDER 4 BITS OF UNIT

DQSET:
	TST	R5			;;;CHECK FOR UCB ADDRESS
	BEQ	10$			;;;NO UN      IT, EXIT INTR
	BIT	#U2.ONL,U.CW2(R5)	;;;UNIT ONLINE?
	BEQ	10$			;;;DISMIS IF NOT
	MOV	U.SCB(R5),R4		;;;GET SCB ADDR
	MOV	S.CSR(R4),R4		;;;NOW GET RXCSR ADDR
	RETURN				;;;RETURN

10$:	TST	(SP)+			;;;CLEAR STACK
DQEXIT:	JMP	$INTXT			;;;DISMISS INTERRUPT
;
; RECEIVE INTERRUPT ROUTINE
;

	.ENABL	LSB

$XQINP::
	INTSV$	XQ,PR5,D$$Q11		;;;GENERATE INTERRUPT SAVE CODE
	CALL	DQSET			;;;R4=RXCSR, R5=UCB ADDR
	BIT	#RXDNP!RXDNS,(R4)	;;;DID BUFFER COMPLETE?
	BEQ	DQEXIT			;;;BR IF NOT
	BIC	#RXDIS,(R4   L  )+		;;;DISABLE RECEIVER		;**-4
	BIC	#ERRIE,(R4)+		;DISABLE ERROR INTERRUPTS
	CALL	$FORK			;;;GO TO FORK LEVEL
	BIC	#RXCLK,(R4)		;CLR RECEIVE CLOCK ERROR
	BIT	#BCCERR,(R4)		;WAS THERE A BCC ERROR?
	BNE	RBCERR			;BR IF YES
	MOV	U.SCB(R5),R4		;GET SCB ADDR FOR I/O DONE
	JMP	SUCC			;FINISH SUCCESSFUL I/O
	.END								;**-155
L         <TðskQ	› c,        	.TITLE	MSDRV
	.IDENT	/05.10/

;
; COPYRIGHT (C) 1979, 1980, 1981
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS  SOFTWARE IS FURNISHED  UNDER A LICENSE  FOR USE ONLY ON  A
; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY 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 EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO
; AGREES TO THESE  LICENSE TERMS.   TITLE TO AND        OWNERSHIP OF THE
; SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC.
;
; THE  INFORMATION IN THIS  DOCUMENT IS SUBJECT TO CHANGE  WITHOUT
; NOTICE AND SHOULD  NOT BE CONSTRUED AS  A COMMITMENT  BY DIGITAL
; EQUIPMENT CORPORATION.
;
; DEC  ASSUMES NO  RESPONSIBILITY  FOR THE  USE OR  RELIABILITY OF
; ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
;
; VERSION 05.10
;
; A. W. PROTIN, JR  13-FEB-78
;
; MODIFIED BY:
;
;	J. CLEARY	4-MAR-78
;
;		JC032 -- CLEANUP TIMEOUT AND INTERRUPT SERVICE
      ;
;	P. J. BEZEREDI 20-AUG-79
;
;		PB116 -- FIX BUGS IN TAPE POSITIONING AND CLEAN
;			THINGS UP.
;
;	R. T. PERRON 07-SEP-79
;
;		RP023 -- ELIMINATE MESSAGE BUFFER RELEASE PROBLEM,
;			CHANGE HOW STATUS IS GOTTEN, MAKE SURE
;			SUB-SYSTEM READY IS UP BEFORE ANY COMMAND,
;			AND TIDY UP SOME MORE.
;
;	R. T. PERRON 03-APR-80
;
;		RP031 -- CORRECT IE.EOT STATUS RETURN DURING ANY
;			READ OPERATION ENDING WITH A TAPE STATUS ALERT
;
;	R. T. PERRON 09-SEP-80
;
;		RP034 -- CHECK FOR CORRECT TASK       AT CANCEL I/O
;
;	R. T. PERRON 19-FEB-81
;
;		RP045 -- CORRECT REGISTER USAGE WHEN CHECKING TAPE CLASS
;			ERROR RETURNS
;
;		RP046 -- CHANGE REF'S FROM "U.CW3(R5)" TO "CSTAT(R3)"
;
;		RP047 -- REVERSE USAGE OF M.AEOV AND M.PEOV STATUS BITS
;
;		RP048 -- CHANGE REGISTER USAGE FROM "U.CW2(R5)" TO "R2"
;
;	R. T. PERRON 06-MAR-81
;
;		RP052 -- VALIDATE COMMAND BUFFER POINTER SETUP BEFORE 
;			SENDING IT TO TS11
;
;	R. T. PERRON 12-JUN-81
;
;		RP063 -- CHECK FOR CORRECT DETECTION OF HRADWAR      E WRITE LOCK 
;			STATUS AND PROPER TERMINATION OF WRITING A TAPE MARK
;			(MODIFIED ON 22-JUL-81)
;
; TS11 MAGNETIC TAPE CONTROLLER DRIVER
;
;
;			N O T I C E
;			= = = = = =
;
; THE FOLLOWING ASSUMPTIONS HAVE BEEN MADE FOR THIS VERSION OF
; THE DRIVER:
;
;	1) THE FIRST FIVE UNIBUS MAP REGISTERS ON 22-BIT CPU'S ARE
;	   MAPPED TO THE EXECUTIVE'S MEMORY SPACE (FIRST 20K WORDS
;	   OF ABSOLUTE MEMORY).
;
;	2) THE DRIVER'S DATA BASE, SPECIFICALLY THE UCB'S, WILL
;	   ALWAYS BE LOCATED IN THE       FRST 20K WORDS OF ABSOLUTE
;	   MEMORY ON CPU'S USING THE UNIBUS MAP.
;
;	3) THE DEVICE SPECIFIC ENTRIES IN THE DEVICE DATA TABLES,
;	   MOST NOTABLY IN THE UNIT CONTROL BLOCK (UCB), ARE NOT
;	   RELOCATABLE.
;
;
;	IF THE DRIVERS DATA BASE (UCB AND SCB) ARE NO LONGER IN THE
;	FIRST 32K WORDS OF MEMORY ( IE. WITH 16 BIT REAL ADDRESSES)
;	THEN THE ROUTINE "GCR" WILL HAVE TO BE REWRITTEN.		; RP023
;
;	IF AND WHEN THE DRIVER SPECIFIC AREA OF THE "UCB" IS
;	MADE RELOCATABLE, THEN THE LOCATION  "UMS      GBn"+16.
;	SHOULD BE RELOCATED AND THE SYMBOL  "RELUCB"  SHOULD
;	BE DEFINED BOTH HERE AND IN THE DATABASE (MSTAB.MAC).
;
;
; MACRO LIBRARY CALLS
;
	.MCALL	HWDDF$,PKTDF$,UCBDF$					; RP023
	HWDDF$			;HARDWARE REGISTERS			; RP023
	PKTDF$			;I/O PACKET OFFSETS			; RP023
	UCBDF$			;UNIT CONTROL BLOCK OFFSETS		; RP023

									; RP023
	.IF DF D$$IAG		;%%% 1 %%%
									; RP023
	.MCALL	UMDIO$
	UMDIO$			;USER MODE DIAGNOSITIC DEFINITIONS
									; RP023
	.ENDC			;%%% 1 %%%
									; RP023
      
;
; EQUATED SYMBOLS
;

RETRY=	24.			;TOTAL RETRY COUNT (3 GROUPS OF 8)
MODUL4=	3			;MODULO 4 BOUNDARY BIT CLEAR MASK

;
; TS11 UNIBUS DEVICE REGISTER OFFSETS
;

TSBA	=	-2		;BUS ADDRESS REGISTER			; RP023
TSDB	=	-2		;DATA BUFFER REGISTER			; RP023
TSSR	=	0		;STATUS REGISTER			; RP023

;
; UCB EXTENSION AREA OFFSETS AND FORMATS
;

U.CBP=	U.VCB+2			;COMMAND BUFFER POINTER.
U.CRP=	U.CBP+2			;CHARACTERISTICS POINTER.
U.MSGB=	U.CRP+2			;MESSAGE BUFFER OFFSET
				;MESSAGE HEADER WORD
				;      DATA FIELD LENGTH WORD
				;RBPCR
				;XSTAT0
				;XSTAT1
				;XSTAT2
				;XSTAT3
				;TSSR COPY.
THRES1=	16.			; FIRST THRESHOLD FOR RETRIES
THRES2=	8.			; SECOND THRESHOLD FOR RETRIES
U.CMDB=	U.MSGB+TSSRC+2		;COMMAND BUFFER
				;MODULO 4 ALIGNMENT PAD WORD
				;COMMAND HEADER WORD
				;BUS ADDRESS BITS 0-15 OR COUNT
				;BUS ADDRESS BITS 16-17
				;COUNT
U.CDAT=	U.CMDB+10.		;WRITE CHARACTERISTICS DATA
				;MESSAGE BUFFER ADDRESS (2 WORDS)
				;MESSAGE BUFFER LENGTH (ALWAYS 14.)
U.CHAR=	U      .CDAT+6		;CHARACTERISTIC WORD
									; PB116
;
; BIT DEFINITIONS FOR UCB CHARACTERISTICS WORD # 2 (U.CW2)
;

M.PEOV=	100000			;TAPE PAST LOGICAL END OF VOLUME
M.AEOV=	40000			;TAPE AT LOGICAL END OF VOLUME
M.BOT=	20000			;TAPE IS AT BOT
M.1600=	4000			;UNIT IS 1600 BPI PHASE ENCODED
M.HWL=	2000			;HARDWARE WRITE LOCK
M.RWD=	1000			;UNIT IS REWINDING
M.SER=	400			;SELECT ERROR HAS OCCURRED
M.IWR=	200			;*INHIBIT WRITE RETRIES
M.SWL=	100			;*SOFTWARE WRITE LOCKED
M.TMK=	40			;LAST COMMAND ENC      OUNTERED A TAPE MARK	; RP023
M.EOT=	20			;LAST CMND ENCOUNTERED END OF TAPE
M.SWAP= 2			;*SWAP BYTES FOR COMPATIBILITY MODE
M.FEF=	1			;TAPE IS PAST ONE TAPE MARK.

USRBTS=	M.IWR!M.SWL!M.SWAP	;STATUS BITS CONTROLLED BY THE USER
NEWBTS=	M.PEOV!M.BOT!M.EOT!M.SER!M.HWL!M.1600	;STATUS BITS TO BE	; RP023
				;DETERMINED				; RP023
MOVBTS=	M.TMK!M.AEOV			; BITS SET BY TAPE MOTION

;
; FLAG BIT DEFINITIONS FOR CONTROLLER STATUS WORD (CSTAT)		; RP046
;									;**-1

CS.ERR	=	100000		;ERROR DETECTED D      OING REQUEST		; RP046
CS.EOF	=	40000		;TAPE POSITIONED PAST TAPE MARK		; RP046
CS.WSS	=	20000		;WAITING FOR SUB-SYSTEM READY FLAG	; RP046
CS.TMO	=	10000		;THIS OPERATION HAS TIMED OUT		; RP046
CS.CVC	=	4000		;VOLUME CHECK BEING CLEARED		; RP046
CS.NER	=	2000		;NO ERROR RECOVERY			; RP046
CS.ABO	=	1000		;ABORT IN PROGRESS			; RP046
CS.STK	=	400		;INITERNAL OPERATION - ORIGINAL STACKED	; RP046
CS.UMD	=	200		;USER MODE DIAGNOSTIC			; RP046
CS.RSP	=	40		;REWIND/SPACE IN PROGRESS		; RP046
CS.LBA	=	20		      ;LOADING MSG BUFFER ADDRESS INTO TS11	; RP046
CS.GST	=	10		;DOING GET STATUS			; RP046
CS.MBR	=	4		;MESSAGE BUFFER RELEASE FLAG		; RP046
;CS.SAK	=	2		;SEND ACK BIT FLAG			; RP046
CS.CIP	=	1		;COMMAND IN PROGRESS FLAG		; RP046
									;**-15
;
; EXTENDED STATUS REGISTER OFFSETS
;

TSRBPC=	4			;RESIDUAL BYTE/POSITION COUNT
TSXSR0=	6			;EXTENDED STATUS REGISTER 0
TSXSR1=	10			;EXTENDED STATUS REGISTER 1
TSXSR2=	12			;EXTENDED STATUS REGISTER 2
TSXSR3=	14			;EXTENDED STATUS REGISTER 3
TSSRC = 16      			;DEVICE STATUS REGISTER COPY.

;
; MSGHDR BIT DEFINITIONS
;

MG.ACK=	100000			;MESSAGES'S ACKNOWLEDGE BIT
;	70000			;RESERVED BITS
;	7400			;CLASS CODE BITS (NOT USED)
MG.FMT=	340			;MESSAGE FORMAT BITS
MG.COD=	37			;MESSAGE CODE BITS

;
; MESSAGE CODES
;

MC.END=	020			;END
MC.FAL=	021			;FAIL
MC.ERR=	022			;ERROR
MC.ATN=	023			;ATTENTION
MC.LOG=	024			;LOG (NOT USED)

;
; TSXSR0 BIT DEFINITIONS
;

X0.TMK=	100000			;TAPE MARK DETECTED
X0.RLS=	40000			;RECORD LENGTH SHORT
X0.L      ET=	20000			;LOGICAL END OF TAPE
X0.RLL=	10000			;RECORD LENGTH LONG
X0.WLE=	4000			;WRITE LOCK ERROR
X0.NEF=	2000			;NON-EXECUTABLE FUNCTION
X0.ILC=	1000			;ILLEGAL COMMAND
X0.ILA=	400			;ILLEGAL ADDRESS
X0.MOT=	200			;TAPE MOTION ON LAST COMMAND.
X0.ONL=	100			;ON LINE
X0.IE=	40			;INTERRUPT ENABLE
X0.VCK=	20			;VOLUME CHECK
X0.PED=	10			;PHASE ENCODED DRIVE
X0.WLK=	4			;WRITE LOCK
X0.BOT=	2			;BEGINNING OF TAPE
X0.EOT=	1			;END OF TAPE DETECTED
									; PB116
;
; TSXSR1 BIT DEFINITIONS      
;

X1.DLT=	100000			;DATA LATE
;	40000			;NOT USED.
X1.COR=	20000			;CORRECTABLE DATA
X1.CRS=	10000			;CREASE DETECTED
X1.TIG= 4000			;TRASH IN GAP
X1.DBF=	2000			;(PE)  DESKEW BUFFER FAIL.
X1.NZO=	2000			;(NRZ) NRZ BOARD FIFO OVERFLOW.
X1.SCK=	1000			;SPEED CHECK
;	400			;NOT USED
X1.IPR=	200			;(PE)  INVALID PREAMBLE
X1.SYN=	100			;(PE)  SYNCH ERROR
X1.DRP=	100			;(NRZ) FRAME DROPOUT.
X1.IPO=	40			;(PE)  INVALID POSTAMBLE
X1.ITM=	40			;(NRZ) ILLEGAL TAPE MARK
X1.IED=	20			;(PE)  INVALID E      ND DATA
X1.LC0=	20			;(NRZ) LRC WAS ZERO (0).
X1.POS=	10			;(PE)  POSTAMBLE SHORT
X1.NZN=	10			;(NRZ) NOISE RECORD.
X1.POL=	4			;(PE)  POSTAMBLE LONG
X1.LRC=	4			;(NRZ) LONGITUDINAL REDUNDANCY CHECK ERR
X1.UNC=	2			;(PE)  UNCORRECTABLE DATA ERROR
X1.CRC=	2			;(NRZ) CYCLIC REDUNDANCY CHECK ERROR
X1.MTE=	1			;(PE)  MULTI-TRACK ERROR
X1.VPE=	1			;(NRZ) VERTICAL PARITY ERROR

;
; TSXSR2 BIT DEFINITIONS
;

X2.OPM=	100000			;OPERATION IN PROGRESS
X2.SIP=	40000			;SILO PARITY ERROR.
X2.BPE=	20000	      		;SERIAL BUS PARITY ERROR AT DRIVE
X2.CAF=	10000			;CAPSTAN ACCELERATION FAIL
;	4000			;NOT USED.
X2.WCF=	2000			;WRITE CLOCK FAIL.
X2.XSK=	1000			;EXCESSIVE SKEW
X2.DTK=	777			;DEAD TRACKS P,7-0.

;
; TSXSR3 BIT DEFINITIONS
;

X3.FEC=	177400			;FATAL ERROR CODE BITS
X3.LMX=	200			;TAPE LIMIT EXCEEDED.
X3.OPI=	100			;OPERATION INCOMPLETE
X3.REV=	40			;TAPE MOVED BACKWARDS.
X3.CRF=	20			;CAPSTAN RESPONSE FAIL
X3.DCK=	10			;DENSITY CHECK
X3.NOI=	4			;NOISE RECORD
X3.SGP=	2			;SHORT GAP
X3.      RIB=	1			;REVERSE INTO BOT
									; PB116
;
; TSSR BIT DEFINITIONS
;

SR.SC=	100000			;SPECIAL CONDITION
SR.UPE=	40000			;UNIBUS PARITY ERROR
SR.SPE=	20000			;SERIAL BUS PARITY ERROR
SR.RMR=	10000			;REGISTER MODIFICATION REFUSED
SR.NXM=	4000			;NON-EXISTENT MEMORY
SR.NBA=	2000			;NEED BUFFER ADDRESS
SR.A17=	1000			;BA 17
SR.A16=	400			;BA 16
SR.SSR=	200			;SUB-SYSTEM READY
SR.OFL=	100			;DEVICE IS OFF LINE
SR.FC1=	40			;FATAL ERROR CLASS BIT 1
SR.FC0=	20			;FATAL ERROR CLASS BIT 0
SR.TC      2=	10			;TERMINATION CLASS BIT 2
SR.TC1=	4			;TERMINATION CLASS BIT 1
SR.TC0=	2			;TERMINATION CLASS BIT 0
SR.TCN=	SR.TC2!SR.TC1!SR.TC0	;TERMINATION CLASS NUMBER.

SR.BAD=	SR.UPE!SR.SPE!SR.NXM!SR.NBA	;FATAL ERROR CODITIONS.

;
; CHARACTERISTICS FLAG DEFINITIONS
;

CH.ESS=	200			;ENABLE SPACE STOP ON EOF,EOF
CH.ENB=	100			;ENABLE STOP ON BOT,EOF			; RP023
CH.EAI=	40			;ENABLE ATTENTION INTERRUPTS.
CH.ERI=	20			;ENABLE (BUFFER) RELEASE INTERRUPTS.
									; PB116
;
; CMDHDR BIT DEFINITIONS
      ;

CM.ACK=	100000			;ACKNOWLEDGE BIT
CM.CVC=	40000			;CLEAR VOLUME CHECK
CM.OPP=	20000			;OPPOSITE BIT
CM.SWB=	10000			;SWAP BYTES
CM.MOD=	7400			;COMMAND MODE BITS
CM.RTY=	1000			;RETRY MODE BIT.
CM.RVS=	400			;REVERSE DIRECTION MODE BIT.
CM.IE=	200			;INTERRUPT ENABLE
CM.COD=	37			;COMMAND CODE BITS
CM.LOW=	3			;LOW HALF OF CODE BITS.
CM.NML= CM.IE!CM.ACK		;NORMAL COMBO. OF FLAGS.

;
; TS04 COMMAND MODES/CODES
;

CC.RDN=	0001!CM.NML		;* READ NEXT (FORWARD)
CC.RDP=	0401!CM.NML		;* READ P      REVIOUS (REVERSE)
CC.RRP=	1001!CM.NML		;* REREAD PREVIOUS (SPACE REV,READ FWD)
CC.RRN=	1401!CM.NML		;* REREAD NEXT (SPACE FWD, READ REV)
CC.WRC=	0004!CM.NML		;+ WRITE CHARACTERISTICS
CC.WRD=	0005!CM.NML		;* WRITE DATA
CC.WDR=	1005!CM.NML		;* WRITE DATA RETRY (SPACE REV, ERASE,
				; WRITE DATA)
CC.WSM=	0006!CM.NML		;* WRITE SUBSYSTEM MEMORY
CC.SRF=	0010!CM.NML		;$ SPACE RECORDS FORWARD
CC.SRR=	0410!CM.NML		;$ SPACE RECORDS REVERSE
CC.STF=	1010!CM.NML		;$ SKIP TAPE MARKS FORWARD
CC.STR=	1410!CM.NM      L		;$ SKIP TAPE MARKS REVERSE
CC.RWD=	2010!CM.NML!CM.CVC	;- REWIND
CC.WTM=	0011!CM.NML		;- WRITE TAPE MARK
CC.ERS=	0411!CM.NML		;- ERASE
CC.WTR=	1011!CM.NML		;- WRITE TAPE MARK RETRY (SPACE REV,
				; ERASE, WRITE TAPE MARK)
CC.BRL=	0012!CM.NML		;- MESSAGE BUFFER RELEASE
CC.UNL=	0412!CM.NML!CM.CVC	;- REWIND AND UNLOAD
CC.CLN=	1012!CM.NML		;- CLEAN
CC.DRI=	0013!CM.NML		;- DRIVE INITIALIZE
CC.GST=	0017!CM.NML		;- GET STATUS IMMEDIATE

CC.MST=CC.GST!CM.CVC		;MOUNT & SET CHARACTERISTICS
									;       PB116
;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;

CNTBL:	.BLKW	T$$S11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	T$$S11		;CURRENT ERROR RETRY COUNT (LOW BYTE)
CSTAT:	.BLKW	T$$S11		;CONTROLLER STATE BITS			; RP046
INTADD:	.BLKW	T$$S11		; INTERRUPT ADDRESS STORAGE
SSRRTY:	.BLKW	T$$S11		; RECOVERY ADDRESS FROM LOSS OF SUB-	; RP023
				;SYSTEM READY				; RP023
TMOCNT:	.BLKW	T$$S11		; TIMEOUT SAVE AREA DURING COMMAND RETRY; RP023
RTYINT:	.BLKW	T$$S11      		; SAVE AREA FOR INTERRUPT ADDRESS
CMDHDR:	.BLKW	T$$S11		; COMMAND HEADER SAVE AREA

	.IF GT	T$$S11-1	;%%% 1 %%%
									; RP023
TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER
									; RP023
	.ENDC			;%%% 1 %%%
									; RP023
									; RP023
;
; DISPATCH TABLES
;
; DRIVER DISPATCH TABLE
;

$MSTBL::.WORD	MSINI		;I/O OPERATION INITIATION ENTRY POINT
	.WORD	MSCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	MSOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	MSPWF		;POWERFAIL ENTRY POINT      


;
; TERMINATION CODE DISPATCH TABLE
;

ERJTBL:	.IRPC	X,<01234567>
	.WORD	TCL'X'ER
	.ENDM

;
;+
; SETRTY - SETUP RETRY COMMAND FOR COMMANDS OTHER THAN FUNCTION IN PROGRESS
;
;-
;
	.MACRO	SETRTY	FCDE,ADR,CNT

	MOV	(R2),CMDHDR(R3)	; SAVE COMMAND HEADER
	MOV	#CC.'FCDE,(R2)	; SET NEW COMMAND
	MOVB	#15.,S.STS(R4)	; SET 1 MINUTE TIMEOUT			; RP023
	MOVB	#4.,S.ITM(R4)	; FOUR SECONDS AT A TIME		; RP023
	MOV	INTADD(R3),RTYINT(R3) ;SAVE INTERRUPT ADDRESS
	MOV	#'ADR,INTADD(R3) ; SET INTERMEDIAT      E INT ADDR
	.IIF NB <CNT>,MOV	#'CNT,2(R2)				; PB116
	.ENDM	SETRTY							; PB116
									; PB116
;
; VALID TS11/TS04 FUNCTION TABLE
;
; FORMAT OF EACH TABLE ENTRY:
;	FCN=I/O FUNCTION CODE
;	HCC=EQUIVALENT HARDWARE COMMAND CODE
;	EXT=COMMAND'S EXTENDED TIMEOUT VALUE				; RP023
;	TMO=COMMAND'S TIMEOUT COUNT IN SECONDS				; RP023
;	ADR=INITIATION PROCESSING ADDRESS OR I/O COMMON ADDRESS
;
	.MACRO	FUNCT	FCN,HCC,EXT,TMO,INT,ADR				; RP023
	.WORD	IO.'FCN
	.WORD	CC.'HCC
	.BYTE	EXT,TMO							; RP0      23
	.WORD	I'INT
	.WORD	P'ADR
	.ENDM	FUNCT							; RP023

VFTBL:	FUNCT	RLB,RDN,1,12.,OCOM,IOCOM   ; READ LOGICAL BLOCK FORWARD	; RP023
	FUNCT	WLB,WRD,1,12.,OCOM,WRITE   ; WRITE LOGICAL BLOCK	; RP023
	FUNCT	RLV,RDP,1,12.,RREV,IOCOM   ; READ LOGICAL BLOCK REVERSE	; RP023
	FUNCT	EOF,WTM,1,4.,WRMK,WRTMK	   ; WRITE TAPE MARK		; RP023
	FUNCT	RWD,RWD,60.,5.,ODON,REWND  ; REWIND			; RP023
	FUNCT	RWU,UNL,1,2.,ODON,UNLOD	   ; REWIND AND UNLOAD		; RP023
	FUNCT	SPB,SRF,132.,5.,SPCB,SPACE ; SPACE BLOCKS		; RP0      23
	FUNCT	SPF,STF,132.,5.,SPCF,SPACE ; SPACE FILES		; RP023
	FUNCT	STC,MST,1,2.,STAT,SET	   ; SET CHARACTERISTICS	; RP023
	FUNCT	SEC,GST,1,2.,STAT,GSTAT	   ; SENSE CHARACTERISTICS	; RP023
	FUNCT	SMO,MST,1,2.,MOUNT,SET	   ; MOUNT/SET CHARACTERISTICS	; RP023
	FUNCT	ERS,ERS,1,12.,ODON,WRTMK   ; ERASE TAPE			; RP023
EVFTBL:

;
; MESSAGE HEADER TABLE
;

MESSAG:	.IRP	X,<END,ATN,END,FAL,ERR,ERR,ERR,ERR>			; RP023
	.WORD	MC.'X							; RP023
	.ENDM								; RP023
;+
; **-MSINI-TS11/TS04 MAGNETIC TAPE       CONTROLLER I/O INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O
; REQUEST IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO
; PROPAGATE THE EXECUTION OF THE DRIVER.  IF THE SPECIFIED CONTROLLER
; IS NOT BUSY, THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O
; REQUEST.  ELSE A RETURN TO THE CALLER IS EXECUTED.  IF THE
; DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPERATION IS
; INITIATED.  A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5 = ADDRE      SS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST
;	IS WAITING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED
;	AND THE I/O OPERATION IS INITIATED.
;-
;+
; THE FOLLOWING REGISTERS CONTENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB
;	R3=CONTROLLER INDEX
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED
;      
; TS11 MAGNETIC TAPE FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT:
;
;I.LNK	WD. 00 = I/O QUEUE THREAD WORD.
;I.PRI	WD. 01 = REQUEST PRIORITY (LOW BYTE).
;I.EFN	WD. 01 = EVENT FLAG NUMBER (HIGH BYTE).
;I.TCB	WD. 02 = ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;I.LN2	WD. 03 = POINTER TO 2ND LUN WORD IN REQUESTOR TASK HEADER.
;I.UCB	WD. 04 = CONTENTS OF 1ST LUN WORD IN REQUESTOR TASK HEADER (UCB)
;I.FCN	WD. 05 = I/O FUNCTION CODE (IO.RLB/IO.RWD/IO.SPB/ETC.).
;I.IOSB	WD. 06 = VIRTUAL ADDRESS OF I/O S      TATUS BLOCK.
;IOSB+2	WD. 07 = RELOCATION BIAS OF I/O STATUS BLOCK.
;IOSB+4	WD. 10 = I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT+140000).
;I.AST	WD. 11 = VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;
;
; READ/WRITE LOGICAL FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;I.PRM	WD. 12 = HIGH 2 BITS (BITS 4 & 5) OF 18 BIT DATA BUFFER ADDRESS.
;PRM+2	WD. 13 = LOW 16 BITS OF 18 BIT DATA BUFFER ADDRESS.
;PRM+4	WD. 14 = NUMBER OF BYTES TO BE TRANSFERRED.
;PRM+6	WD. 15 = NOT USED.
;PRM+10	WD. 16 = NOT USED.
;PR      M+12	WD. 17 = NOT USED.
;PRM+14	WD. 20 = RELOCATION BIAS OF DIAGNOSTIC REGISTER BLOCK ADDRESS.
;PRM+16	WD. 21 = DIAG. REG. BUFFER ADDRESS (REAL/DISPLACEMENT+140000).
;
;
; BLOCK AND FILE SPACING FUNCTIONS DEPENDENT I/O PACKET FORMAT:
;
;I.PRM	WD. 12 = SPACING COUNT (POSITIVE=FORWARD, NEGATIVE=BACKWARD).
;PRM+2	WD. 13 = NOT USED.
;PRM+4	WD. 14 = NOT USED.
;PRM+6	WD. 15 = NOT USED.
;PRM+10	WD. 16 = NOT USED.
;PRM+12	WD. 17 = RELOCATION BIAS OF DIAGNOSTIC REGISTER BLOCK ADDRESS.
;PRM+14	WD. 20 = D      IAG. REG. BUFFER ADDRESS (REAL/DISPLACEMENT+140000).
;PRM+16 WD. 21 = NOT USED.
;
;
; (MOUNT AND) SET CHARACTERISTICS FUNCTION DEPENDENT I/O PACKET FORMAT.
; FOR SENSE CHARACTERISTICS, I.PRM (WD. 12) IS NOT USED:
;
;I.PRM	WD. 12 = NEW CHARACTERISTICS WORD.
;PRM+2	WD. 13 = NOT USED.
;PRM+4	WD. 14 = NOT USED.
;PRM+6	WD. 15 = NOT USED.
;PRM+10	WD. 16 = NOT USED.
;PRM+12	WD. 17 = NOT USED.
;PRM+14	WD. 20 = NOT USED.
;PRM+16	WD. 21 = NOT USED.
;
;
; WREOF, REWIND, AND UNLOAD FUNCTIONS DEPENDENT       I/O PACKET FORMAT:
;
;I.PRM	WD. 12 = NOT USED.
;PRM+2	WD. 13 = NOT USED.
;PRM+4	WD. 14 = NOT USED.
;PRM+6	WD. 15 = NOT USED.
;PRM+10	WD. 16 = NOT USED.
;PRM+12	WD. 17 = RELOCATION BIAS OF DIAGNOSTIC REGISTER BLOCK ADDRESS.
;PRM+14	WD. 20 = DIAG. REG. BUFFER ADDRESS (REAL/DISPLACEMENT+140000).
;PRM+16 WD. 21 = NOT USED.
;-

	.ENABL	LSB
MSINI:	CALL	$GTPKT		;ATTEMPT TO GET AN I/O PACKET
	BCC	10$	; IF CC WE HAVE A PACKET
	RETURN		; ELSE RETURN

10$:	MOV	R5,CNTBL(R3)	; SAVE ADDRESS OF CURRENT UC      B
	CLR	CSTAT(R3)	;CLEAR CONTROLLER STATE FLAGS		; RP046
	BIC	#CH.EAI,U.CHAR(R5)  ;CLEAR ATTENTION ENABLE INT		;**-1
	MOV	U.CHAR(R5),R0	; RETRIEVE CHARACTERISTICS WORD

									; RP023
	.IF DF	A$$NSI

	BIC	#CH.ESS,R0	;CLEAR LET FLAG				; RP023
	BITB	#US.LAB,U.STS(R5) ; MOUNTED ANSII TAPE?
	BNE	20$		; IF NE YES - DON'T STOP ON DOUBLE TMK
	BIS	#CH.ESS,R0	;NOT ANSII - ENABLE LET FLAG		; RP023
20$:	CMP	R0,U.CHAR(R5)	;CHARACTERISTICS WORD SET CORRECTLY?	; RP023
	BNE	GCR		;IF NE NO, GO WRITE CHARACTE      RISTICS WORD; RP023

	.ENDC
									; RP023
									; RP023
	BIT	#SR.NBA,@S.CSR(R4)  ;IS THE TS04 TALKING?		; RP023
	BNE	GCR		;IF NE NO				; RP023
ILDBA:	MOV	S.PKT(R4),R1	;RELOAD PACKET POINTER.
	MOV	#VFTBL,R2	;POINT AT VALID FUNCTIONS TABLE
	MOV	I.FCN(R1),R0	;GET FUNCTION CODE FROM PACKET
	BIT	#IQ.X,R0	;ERROR RECOVERY PROHIBITED ?
	BEQ	50$		;NO=> SKIP AHEAD; ELSE SET
	BIS	#CS.NER,CSTAT(R3)  ; CORRESPONDING FLAG			; RP046
	BIC	#IQ.X,R0	; AND CLEAR BIT FOR COMPARE.		;**-1
50$:				;REFERENCE L      ABEL.

									; RP023
	.IF DF	D$$IAG		;%%% 1 %%%
									; RP023
	BITB	#IQ.UMD,R0	;DIAGNOSTIC FUNCTION CALL?
	BEQ	60$		;IF EQ NO
	BIS	#CS.UMD,CSTAT(R3)  ;COPY DIAGNOSTIC FLAG		; RP046
	BIC	#IQ.UMD,R0	;CLEAR BIT FOR FUNCTION CHECK		;**-1
									; RP023
	.ENDC			;%%% 1 %%%
									; RP023

60$:	CMP	R0,(R2)+	;FUNCTION CODES MATCH?
	BEQ	70$		;IF EQ YES
	ADD	#10,R2		; POINT TO NEXT TABLE ENTRY
	CMP	#EVFTBL,R2	;END OF TABLE?				; RP023
	BNE	60$		;IF NE NO
	MOV	#IE.IFC&377,R0	;SET UP ILLEGA      L FUNCTION CODE
	BR	ALT		;GO TO EXIT



70$:	MOVB	#RETRY,RTTBL(R3) ;SET RETRY COUNT
	MOV	(R2)+,R1	; RETRIEVE HARDWARE COMMAND CODE
	MOVB	(R2)+,S.STS(R4)	;SET EXTENDED TIMEOUT VALUE		; RP023
	MOVB	(R2)+,S.ITM(R4)	;SET INITIAL TIMEOUT VALUE		; RP023
	MOV	(R2)+,INTADD(R3)	; STORE INTERRUPT ADDRESS
	CALLR	@(R2)		;GO TO PRE-PROCESSING FOR THIS FUNCTION	; RP023

;+									; RP023
; **-GCR-GENERATE CHARACTERISTICS ROUTINE				; RP023
;									; RP023
; THIS ROUTINE WILL SEND THE CHARACTERISTICS WOR      D TO THE TS11/TS04	; RP023
; SUB-SYSTEM.								; RP023
;									; RP023
; INPUTS:								; RP023
;									; RP023
;	R4= SCB ADDRESS							; RP023
;	R5 = UCB ADDRESS						; RP023
;									; RP023
; OUTPUTS:								; RP023
;									; RP023
;	THE TS11/TS04 SUB-SYSTEM IS GIVEN THE MESSAGE BUFFER ADDRESS	; RP023
;									; RP023
;-									; RP023
									; RP023
GCR:	MOVB	#2.,S.ITM(R4)	;SET TIMEOUT				; RP023
	BIS	#CS.LBA,CSTAT(R3)  ;SET WRITE CHARACTERISTICS FLAG	; RP046
	TST	U.CBP(R5)	;      HAVE WE SET UP COMMAND BUFFER POINTER?	; RP052
	BNE	72$		;IF NE YES				; RP052
	CALL	MSPWF		;NO, CALCULATE COMMAND BUFFER POINTER	; RP052
72$:	MOV	U.CBP(R5),R2	;RETRIEVE COMMAND BUFFER POINTER	; RP052
	MOV	#CC.WRC,(R2)+	;SET WRITE CHARACTERISTICS FUNCTION	;**-2
	MOV	U.CRP(R5),(R2)+	;LOAD LOW ADDRESS OF MESSAGE BUFFER	; RP023
	CLR	(R2)+		;LOAD HIGH ADDRESS OF MESSAGE BUFFER	; RP023
	MOV	#10,(R2)	;LOAD BYTE COUNT			; RP023
	BR	INITIO		;GO INITIATE I/O			; RP023
									; RP023
;-
;  PRE-PROCESSING       ROUTINES FOR I/O OPERATIONS
;
; INPUTS:
;	R1 = HARDWARE FUNCTION CODE
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;-

;
; WRITE DATA
;

PWRITE:	CMP	U.CNT(R5),#14.	;ENOUGH BYTES FOR WRITE?
	BHIS	75$		;IF HIS YES
	TST	U.CNT(R5)	;IS IT MAX COUNT?
	BEQ	75$		;IF EQ YES
	MOV	#IE.SPC&377,R0	;SET UP PARAMETER ERROR CODE
	BR	ALT		;GO TO EXIT

;
; WRITE TAPE MARK
;

PWRTMK:	CLR	U.CNT(R5)	;INSURE COUNT IS 0
75$:	BIT	#M.SWL,U.CW2(R5) ;SOFTWARE WRITE LOCK IN EFFECT?
	BEQ	PIOC      OM		;IF EQ NO
	MOV	#IE.WLK&377,R0	;SET UP WRITE LOCK ERROR CODE
	BR	ALT		;GO TO EXIT

;
; SPACE BLOCKS AND SPACE FILES
;

PSPACE:	MOV	#IS.SUC&377,R0	;ASSUME 0 SPACING COUNT
	MOV	U.BUF(R5),U.CNT(R5) ;PUT SPACING COUNT IN PLACE
	BEQ	ALT		;IF EQ NO I/O NEEDED (U.BUF=0)
	BMI	90$		;IF MI SPACE REVERSE (U.BUF=NEGATIVE)
	BIT	#M.AEOV,U.CW2(R5)  ;ALREADY AT EOV?			; RP047
	BEQ	100$		;IF EQ NO				;**-1
	MOV	#IE.EOV&377,R0	;SET UP END OF VOLUME CODE
ALT:	CALL	$IOALT		;TERMINATE THIS REQUEST
	BR	MSINI		      ;GO CHECK FOR ANOTHER PACKET		; RP023



90$:	BIS	#CC.SRR-CC.SRF,R1 ;MAKE CMND SPACE/SKIP REVERSE
	NEG	U.CNT(R5)	;MAKE COUNT POSITIVE
100$:	BIS	#CS.RSP,CSTAT(R3)  ;SET "REWIND/SPACE INP PROGRESS" FLAG; RP046
	BR	PIOCOM		;GO TO COMMON PROCESSING		;**-1
									; PB116
;
; (MOUNT AND) SET CHARACTERISTICS					; RP023
;

PSET:	BIC 	#USRBTS,U.CW2(R5) ;CLEAR USER SETTABLE BITS
	BIC	#^C<USRBTS>,U.BUF(R5)	;REMOVE NON-SETABLE BITS.
	BIS	U.BUF(R5),U.CW2(R5)	;UPDATE USER SETABLE BITS.
									; RP023      
;
; GET STATUS (FOR SENSE, (MOUNT AND) SET CHARACTERISTICS)
;
									; RP023
PGSTAT:	BIS	#CS.GST,CSTAT(R3)  ;SET GET STATUS FLAG			; RP046
	BR	PUNLOD		;CONTINUE				;**-1

;
; REWIND TAPE
;

PREWND:	BIS	#M.RWD,U.CW2(R5)	;SET TAPE REWINDING FLAG.
	BIS	#CS.RSP,CSTAT(R3)  ;SET "REWIND/SPACE INP PROGRESS" FLAG; RP046
									;**-1
;
; UNLOAD TAPE
;

PUNLOD:	CLR	U.CNT(R5)	;INSURE COUNT IS 0
									; PB116
;
;  I/O OPERATION COMMON PRE-PROCESSING
;

PIOCOM:	MOV	U.CBP(R5),R2	; GET COM      MAND BUFFER POINTER
	MOV	R1,(R2)+	; LOAD COMMAND HEADER IN BUFFER
	BIC	#^C<CM.COD>,R1	;ISOLATE COMMAND CODE BITS
	CMP	R1,#CC.SRF&CM.COD ;COMMAND NEED AN ADDRESS?
	BHIS	130$		;IF HIS NO
	BIT	#M.SWAP,U.CW2(R5)  ;SWAP BYTES ON DATA?
	BEQ	120$		;IF EQ NO
	BIS	#CM.SWB,-2(R2)	; SET SWAP BITS BYTE IN HEADER WORD
120$:				;REF LABEL

									; RP023
	.IF DF	M$$EXT&M$$MGE	;%%% 1 %%%
									; RP023
	CALL	$STMAP		; SET UP UNIBUS MAPPING
	MOV	R2,-(SP)	; SAVE R2
	CALL	$MPUBM		; MAP UNIBUS TO TRANSFER
      	MOV	(SP)+,R2	; RESTORE R2
									; RP023
	.ENDC			;%%% 1 %%%
									; RP023

	MOV	U.BUF+2(R5),(R2)+	; PUT LOW ORDER 16 BITS IN BUFFER

									; RP023
	.IF DF	M$$MGE		;%%% 1 %%%
									; RP023
	MOV	U.BUF(R5),(R2)	; LOAD HIGH 2 BITS OF ADDRESS
	ASR	(R2)		; AND MOVE FROM
	ASR	(R2)		; BITS 4 AND 5
	ASR	(R2)		;     TO
	ASR	(R2)+		; BITS 0 AND 1

	.IFF

	CLR	(R2)+		; CLEAR HIGH BITS

	.ENDC
									; RP023

130$:	MOV	U.CNT(R5),(R2)	; LOAD BYTE/RECORD/FILE COUNT
									; PB116
      ;+
; INITIATE I/O OPERATION
;
; INPUTS:
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;-

INITIO:	MOVB	S.ITM(R4),S.CTM(R4) ;START THE TIMER

									; RP023
	.IF DF	E$$DVC		;%%% 1 %%%
									; RP023
	CALL	$BMSET		;;;SET BIT IN I/O ACTIVE MAP

	.IFF			;%%% 1 %%%
									; RP023
	MTPS	#PR7		;;;INHIBIT INTERRUPTS

	.IFTF				;%%% 1 %%%
									; RP023
	MOV	S.CSR(R4),R2	;;;RETRIEVE CSR ADDRESS			; RP023
	TSTB	(R2)		;;;SUB-SYSTEM READY?			; RP023
	BPL	140$		;;;IF PL NO				; RP023
	MOV	U.CBP(R      5),TSDB(R2)  ;;;LOAD COMMAND POINTER		; RP023
	BIS	#CS.CIP,CSTAT(R3)  ;;;SET COMMAND IN PROGRESS		; RP046
	BR	150$		;;;EXIT					;**-1
140$:	MOVB	#4.,S.CTM(R4)	;;;SET TIMER				; RP023
	MOV	#INITIO,SSRRTY(R3)  ;;;SETUP SUB-SYSTEM READY RETRY	; RP023
				;;;HANDLER				; RP023
	BIS	#CS.WSS,CSTAT(R3) ;;;SET WAITING FOR SUB-SYSTEM READY	; RP046
				;;;FLAG					;**-1
150$:				;;;REF LABEL				; RP023

	.IFF				;%%% 1 %%%
									; RP023
	MTPS	#0			;;;ALLOW INTERRUPTS
									; RP023
	.ENDC				;%%% 1       %%%
									; RP023

	RETURN			;EXIT WHILE I/O IN PROGRESS
	.DSABL	LSB							; PB116
									; PB116
;+
; **-MSCAN-TS11/TS04 CANCEL I/O ENTRY POINT
;
; THE CANCEL I/O OPERATION IS BASICALLY A NOP FOR TS11
; MAGNETIC TAPES.  HOWEVER, IF A "NOT READY" MESSAGE IS
; BEING ISSUED DUE TO A SELECT ERROR, THE CANCEL I/O WILL
; CAUSE THE MESSAGES TO BE TERMINATED AND THE I/O ABORTED.
;
; INPUTS:
;	R0 = ACTIVE I/O PACKET ADDRESS
;	R1 = CURRENT TCB ADDRESS
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRES      S
;	R5 = UCB ADDRESS
;-

MSCAN:	CMP	I.TCB(R0),R1	;;;IS THIS THE CORRECT TASK?		; RP034
	BNE	10$		;;;IF NE NO				; RP034
	BIS	#CS.ABO,CSTAT(R3)  ;;;YES, INDICATE AN ABORT CONDITION	; RP046
10$:	RETURN			;;;RETURN				; RP034
									;**-2
;+
; **-MSPWF-TS11/TS04 POWERFAIL ENTRY POINT
;
; POWERFAIL IS THE SAME AS INITIALIZE.  OUTSTANDING REQUESTS ARE
; HANDLED VIA THE DEVICE TIMEOUT FACILITY. THIS IS DONE TO AVOID
; A RACE CONDITION THAT COULD EXIST IN RESTARTING THE I/O OPERATION.
; THIS IS A       GOOD TIME TO CALCULATE ALL SEMI-STATIC POINTERS.
;
; INPUTS:
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;-

MSPWF:	BISB	#US.PWF,U.STS(R5)  ;SET POWERFAIL FLAG			; RP046
	MOV	R5,R0		;COPY UCB BASE ADDRESS			; RP046
	ADD	#U.CDAT,R0	;ADD OFFSET TO PRODUCE VIRTUAL ...	; RP046
	MOV	R0,U.CRP(R5)	;... ADDRESS OF CHARACTERISTICS DATA	; RP046
	ADD	#U.MSGB-U.CDAT,R0  ;ADD OFFSET FROM OFFSET ...		; RP046
	MOV	R0,U.CDAT(R5)	;... TO COMPUTE POINTER TO MESSAGE ...	; RP046
	CLR	U.CDAT+2(R5      )	;... AND CLEAR HIGH ORDER BITS		; RP046
	ADD	#U.CMDB+2-U.MSGB,R0  ;ADD OFFSET FROM OFFSET ...	; RP046
	BIC	#MODUL4,R0	;... AND ALIGN ON DOUBLE WORD BOUNDARY .; RP046
	MOV	R0,U.CBP(R5)	;... TO MAKER POINTER TO COMMAND BUFFER	; RP046
	RETURN			;EXIT					; RP046
									;**-10
;+
; **-MSOUT-TS11/TS04 TIMEOUT ENTRY POINT
;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED.
; IF THE OPERATION WAS DIAGNOSTIC, THE QIO REQUEST IS TERMINATED.
; TIMEOUTS ARE USUALLY CAUSED BY POWER FAIL      URE BUT MAY ALSO BE THE
; RESULT OF HARDWARE CONSIDERATIONS.  IN PARTICULAR, A LENGTHY
; SPACING OPERATION OR A REWIND ON THIS MODEL TAPE DRIVE MAY
; RESULT IN A TIMEOUT WHICH WILL BE IGNORED.
;
; INPUTS:
;	R0 = LITERAL CONSTANT IE.DNR
;	R2 = CSR ADDRESS
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;-

	.ENABL	LSB							; RP023
MSOUT:	BIT	#CS.ABO,CSTAT(R3)  ;;;BEEN TOLD TO ABORT?		; RP046
	BNE	10$		;;;IF NE YES - ABORT			;**-1
	BIT	#CS.WSS,CSTAT(R3)  ;;;WAITING FOR SUB-SYSTE      M READY?	; RP046
	BNE	30$		;;;IF NE YES				;**-1
	BIT	#CS.RSP,CSTAT(R3)  ;;;REWIND/SPACE IN PROGRESS		; RP046
	BNE	40$		;;;IF NE YES				;**-1
	BIS	#CS.TMO,CSTAT(R3)  ;;;SET TIMEOUT IN PROGRESS		; RP046
									;**-1
									; RP023
	.IF DF	E$$DVC							; RP023
									; RP023
	CALL	DVER		;;;LOG TIMEOUT ERROR			; RP023
									; RP023
	.ENDC								; RP023
									; RP023
									; RP023
10$:	MTPS	#0		;;;LOWER PRIORITY			; RP023
	BIT	#M.SER,U.CW2(R5)  ;SELECT ERROR IN PROGRESS?		; RP023      
	BNE	NORDY		;IF NE YES				; RP023
MSOUT1:	CLR	R1		;ZERO STATUS RETURN			; RP023
	CALLR	IODON		;EXIT					; RP023
20$:	MOVB	S.ITM(R4),S.CTM(R4)  ;;;RESET TIMER			; RP023
	RETURN			;;;EXIT					; RP023
30$:	TSTB	(R2)		;;;SUB-SYSTEM READY?			; RP023
	BPL	40$		;;;IF PL NO				; RP023
	MTPS	#0		;LOWER PRIORITY				; RP023
	INCB	S.STS(R4)	;SET CONTROLLER BUSY			; RP023
	BIC	#CS.WSS,CSTAT(R3)  ;RESET WAITING FOR SUB-SYSTEM READY	; RP046
				;FLAG					;**-1
	CALLR	@SSRRTY(R3)	;RETRY AT SUB-SYSTEM READY RETR      Y HANDLER; RP023
40$:	DECB	S.STS(R4)	;;;SUB-SYSTEM RECOVERY TIMED OUT?	; RP023
	BEQ	10$		;;;IF EQ YES, RETURN IE.DNR		; RP023
	BR	20$		;;;OTHERWISE GIVE IT MORE TIME		; RP023
	.DSABL	LSB							; RP023

;+									; RP023
; **-NORDY - TAPE UNIT NOT READY ROUTINE				; RP023
;									; RP023
; THIS ROUTINE WILL SEND OPERATOR "SELECT ERROR"			; RP023
; MESSAGE AND DETERMINE WHETHER TO RETURN TO USER OR			; RP023
; RETRY THE REQUESTED OPERATION						; RP023
;									; RP023
; INPUTS:								; RP02      3
;	R3 = CONTROLLER INDEX						; RP023
;	R4 = SCB ADDRESS						; RP023
;	R5 = UCB ADDRESS						; RP023
;									; RP023
;-									; RP023
									; RP023
NORDY:	BIT	#CS.NER!CS.UMD!CS.ABO,CSTAT(R3)  ;RETURN TO REQUESTOR?	; RP046
	BNE	10$		;IF NE YES				;**-1
	TST	U.ACP(R5)	; ACP ALSO WANTS RETURN
	BEQ	20$		;IF EQ NO				; RP023
10$:	MOV	#IE.DNR&377,R0	;INSURE PROPER MESSAGE RETURNED		; RP023
	BR	MSOUT1		;AND EXIT				; RP023
20$:	MOV	U.CBP(R5),R2	;RETRIEVE COMMAND BUFFER POINTER	; RP023
	CMP	#      NORDY1,INTADD(R3)  ;HAVE WE BEEN HERE BEFORE?		; RP023
	BEQ	NORDY0		;IF EQ YES				; RP023
	MOV	(R2),CMDHDR(R3)  ;SAVE COMMAND HEADER			; RP023
	MOV	#CC.GST,(R2)	;SET GET STATUS COMMAND			; RP023
	MOVB	S.ITM(R4),TMOCNT(R3)  ;SAVE TIMEOUT COUNT		; RP023
	MOVB	#2.,S.ITM(R4)	;SET TIMEOUT				; RP023
	MOV	INTADD(R3),RTYINT(R3)  ;SAVE INTERRUPT ADDRESS		; RP023
	MOV	#NORDY1,INTADD(R3)  ;SET INTERMEDIATE INTERRUPT ADDRESS	; RP023
NORDY0:	CALLR	INITIO		;GO GET STATUS				; RP023
NORDY1:	BIT	#M.SER,U.CW2(R5)        ;SELECT ERROR REMAIN SET?		; RP023
	BNE	10$		;IF NE YES				; RP023
	MOV	U.CBP(R5),R2	;RETRIEVE COMMAND BUFFER POINTER	; RP023
	MOV	CMDHDR(R3),(R2)  ;RETRIEVE COMMAND HEADER		; RP023
	MOV	RTYINT(R3),INTADD(R3)  ;RETRIEVE INTERRUPT ADDRESS	; RP023
	MOVB	TMOCNT(R3),S.ITM(R4)  ;RETRIEVE TIMEOUT COUNT		; RP023
	BR	NORDY0		;RETRY PREVIOUS COMMAND			; RP023
10$:	MOVB	#8.,S.STS(R4)	;SET EXTENDED TIMEOUT VALUE		; RP023
	MOVB	#2.,S.CTM(R4)	;SET TIMEOUT VALUE			; RP023
	MOV	#T.NDSE,R0	;INSURE PROPER MESSAGE       RETURNED		; RP023
	CALLR	$DVMSG		;SEND OPERATOR MESSAGE			; RP023
									; PB116
;+
; **-$MSINT-TS11/TS04 MAGNETIC TAPE CONTROLLER INTERRUPTS
;-

	INTSE$	MS,PR5,T$$S11		;;;SAVE REGISTERS & SET PRIORITY
	BIT	#CS.CIP,CSTAT(R4)  ;;;IS A COMMAND IN PROGRESS?		; RP046
	BNE	5$		;;;IF NE YES				;**-1
	RETURN			;;;OTHERWISE EXIT			; RP023
5$:	CALL	$FORK		;;;CREATE A SYSTEM PROCESS		; RP023
	MOV	R4,R3		;COPY CONTROLLER INDEX			; RP023
	MOV	U.SCB(R5),R4	;PICK UP SCB ADDRESS
	MOV	@S.CSR(R4),R1	;SAVE DE      VICE STATUS.
	MOV	R1,U.MSGB+TSSRC(R5)	;SAVE DEVICE STATUS.
	MOV	R5,R2		;COPY UCB ADDRESS			; RP023
	ADD	#U.MSGB+TSXSR0,R2  ;AND POINT TO EXTENDED STATUS	; RP023
				;REGISTER				; RP023
	BIT	#M.TMK!M.BOT,U.CW2(R5)  ;TAPE MARK SEEN LAST TIME?	; RP023
	BEQ	10$		;IF EQ NO				; RP023
	BIS	#M.PEOV,U.CW2(R5)  ;YES, SET FLAG FOR EOV CHECK		; RP047
10$:	BIC	#NEWBTS!M.TMK,U.CW2(R5)  ;CLEAR STATUS BITS TO BE	;**-1
				;DETERMINED				; RP023
	BIT	#X0.PED,(R2)	;PHASE ENCODED DRIVE?			; RP023
	BEQ	20$		;IF EQ       NO				; RP023
	BIS	#M.1600,U.CW2(R5)  ;YES, SET 1600 BPI PHASE ENCODED	; RP023
				;STATUS					; RP023
20$:	BIT	#X0.BOT,(R2)	;TAPE AT BOT?				; RP023
	BEQ	30$		;IF EQ NO				; RP023
	BIS	#M.BOT,U.CW2(R5)  ;YES, SET BOT STATUS			; RP023
30$:	BIT	#X0.EOT,(R2)	;TAPE AT EOT?				; RP023
	BEQ	40$		;IF EQ NO				; RP023
	BIS	#M.EOT,U.CW2(R5)  ;YES, SET EOT STATUS			; RP023
40$:	BIT	#X0.TMK,(R2)	;TAPE MARK DETECTED?			; RP023
	BEQ	50$		;IF EQ NO				; RP023
	BIS	#M.TMK,U.CW2(R5)  ;YES, SET TAPE MARK DETECT      ED STATUS	; RP023
50$:	BIT #X0.WLK,(R2)	;WRITE LOCK STATUS?			; RP063
	BEQ	60$		;IF EQ NO				;**-1
	BIS	#M.HWL,U.CW2(R5)  ;YES, SET HARDWARE WRITE LOCK STATUS	; RP023
60$:	BIT	#SR.OFL,R1	;UNIT GO OFFLINE?			; RP023
	BEQ	70$		;IF EQ NO				; RP023
	BIS	#M.SER,U.CW2(R5)  ;YES, SET SELECT ERROR STATUS		; RP023
70$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESS				; RP023
	MOV	U.CW2(R5),R2	;COPY STATUS BITS			; RP048
	BIC	#^C<SR.TCN>,R1  ;CLEAR ALL BUT TERMINATION CODE		; RP023
	CMPB	U.MSGB(R5),MESSAG(R1) ;DOES M      ESSAGE MATCH TC?
	BEQ	80$		;IF EQ YES				; RP023
	MOV	#SR.TC2!SR.TC1,R1  ;SETUP FATAL ERROR CODE		; RP023
80$:	CALLR	@ERJTBL(R1)	;GO PROCESS INTERRUPT			; RP023
									; PB116
;+
; CODE FOR THE TREATMENT OF THE EIGHT (10) TERMINATION CODES
; RETURNED WITH FAIL, ERROR, AND ATTENTION MESSAGES.
;
; INPUTS:
;	R0 = IS.SUC&377							; RP023
;	R2 = CONTENTS OF U.CW2(R5)					; RP048
;	R3 = CONTROLLER INDEX						;**-1
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;-									; RP023
									; RP023
;
; T      ERMINATION CLASS 0 (AN END MSG)
;

TCL0ER:	BIT	#CS.LBA,CSTAT(R3)  ;WRITTEN CHARACTERISTICS?		; RP046
	BEQ	TCEXIT		;IF EQ NO - FINISH PROCESSING		;**-1

;
; TERMINATION CLASS CODE 1 (ATTENTION CONDITION)
;


TCL1ER:	BIC	#CS.LBA,CSTAT(R3)  ;CLEAR LOADING BUFFER ADDRESS FLAG	; RP046
	CALLR	ILDBA		;RESTART THE USER'S REQUEST		;**-1
									; PB116
;
; TERMINATION CLASS 2 (TAPE STATUS ALERT)
;

TCL2ER:	BIT	#M.EOT,R2	;EOT DETECTED?				; RP048
	BEQ	10$		; IF EQ NO				;**-1
	CMPB	#CC.WRD,@U.CBP      (R5)  ;IS IT A WRITE COMMAND?		; RP045
	BEQ	5$		;IF EQ YES				; RP031
;									; RP031
; WRITE COMMANDS MUST LOOK FOR PHYSICAL END-OF-TAPE (M.EOT)		; RP031
;									; RP031
	CMPB	#CC.WTM,@U.CBP(R5)  ;IS IT A WRITE TAPE MARK COMMAND?	; RP045
	BEQ	5$		;IF EQ YES				; RP031
;									; RP031
; WRITE TAPE MARK COMMANDS MUST LOOK FOR PHYSICAL END-OF-TAPE (M.EOT)	; RP031
;									; RP031
	CMPB	#CC.ERS,@U.CBP(R5)  ;IS IT AN ERASE COMMAND?		; RP045
	BNE	10$		;IF NE NO				; RP031
;									; RP031
;       ERASE COMMANDS MUST LOOK AT PHYSICAL END-OF-TAPE			; RP031
;									; RP031
5$:	MOV	#IE.EOT&377,R0	;SET EOT FOR RETURN			; RP031
10$:	BIT	#M.TMK,R2	;TAPE MARK DETECTED?			; RP048
	BEQ	20$		;IF EQ NO				;**-2
	MOV	#IE.EOF&377,R0	;SET EOF FOR RETURN			; RP023
;									; RP023
; NOTE:  EOF OVERRIDES EOT IF OCCURRING ON THE SAME COMMAND		; RP023
;									; RP023
20$:	BIT	#X0.RLL,U.MSGB+TSXSR0(R5) ; RECORD LENGTH LONG?
	BEQ	TCEXIT		;FINISH PROCESSING			; RP023
	MOV	#IE.DAO&377,R0	; SET RECORD LONG      
	BR	TCEXIT		;FINISH PROCESSING			; RP023
									; PB116
;
; TERMINATION CLASS CODE 3 (FUNCTION REJECT)
;

TCL3ER:	BIT	#CS.GST,CSTAT(R3)  ;IS A GET STATUS IN PROGRESS?	; RP046
	BNE	TCEXIT		;IF NE YES				;**-1
	BIT	#M.SER,R2	;UNIT GO OFFLINE?			; RP048
	BEQ	10$		; IF EQ NO				;**-1
	CALLR	NORDY		;SEND SELECT ERROR MESSAGE		; RP023
10$:	BIT	#X0.VCK!X0.ILC!X0.ILA,U.MSGB+TSXSR0(R5) ;HARD ERROR?
	BNE	TCL6ER		;IF NE YES, FATAL			; RP023
	BIT	#M.HWL,R2	;WRITE LOCK STATUS?			; RP048
	BEQ	TCEXIT		;IF       EQ NO				;**-1
	MOV	#IE.WLK&377,R0	; SET WRITE LOCK
TCEXIT:	CALLR	@INTADD(R3)	;PROCESS TO COMPLETION			; RP023
									; PB116
	.ENABL	LSB							; PB116
;
; TERMINATION CLASS CODE 4 (RECOVERABLE ERROR - 1 BLOCK DOWN)
;

TCL4ER:				;REF LABEL				; RP023
									; RP023
									; RP023
	.IF DF	E$$DVC							; RP023
									; RP023
	CALL	DVER		;LOG ERROR				; RP023
									; RP023
	.ENDC								; RP023
									; RP023
									; RP023
	BIT	#CS.NER!CS.UMD,CSTAT(R3)  ;RETRIES PROHIBITED?      		; RP046
	BNE	50$		; IF NE YES - EXIT			;**-1
	MOV	U.CBP(R5),R2	; RETRIEVE COMMAND BUFFER POINTER
	MOV	(R2),R0		; RETRIEVE COMMAND HEADER WORD
	CMP	#CC.WRD,R0	; WRITE COMMAND?
	BNE	10$		; IF NE NO SKIP CHECK
	BIT	#M.IWR,U.CW2(R5) ;WRITE EXTEND PROHIBITED?
	BNE	50$		; IF NE YES - EXIT
10$:	BIC	#^C<CM.LOW>,R0	; CLEAR ALL BUT LOW 2 BITS
	CMP	#1,R0		; RETRYABLE COMMAND?
	BNE	TCL6ER		;IF NE NO, FATAL HARDWARE ERROR		; RP023
	DECB	RTTBL(R3)	; DECREMENT RETRY COUNT
	BEQ	50$		; IF EQ RETRIES EXHAUSTED      
	CMPB	#THRES1,RTTBL(R3) ; REACHED FIRST THRESHOLD?
	BHIS	20$		; YES TIME FOR OPPOSITE RETRY
	BIS	#CM.RTY,(R2)	; SET RETRY COMMAND BIT
	BR	AGAIN		;AND RE-ISSUE COMMAND			; RP023
;
; AN OPPOSITE RETRY CAN ONLY OCCUR FOR READ OPERATIONS. ALL OTHER
; COMMANDS WILL SKIP THIS RETRY SET AND PROCEED IMMEDIATLY TO THE
; NEXT STEP WHICH CONSISTS OF DOING A CLEAN OPERATION BEFORE ISSUANCE
; OF THE COMMAND. READ OPERATIONS WHICH INDICATE THAT THE ACTUAL RECORD
; SIZE ON TAPE DOES NOT EQUAL THE BUFFER SIZE SPE      CIFIED MUST ALSO SKIP THIS
; STEP.
;
20$:	CMPB	#THRES2,RTTBL(R3) ; TIME FOR CLEAN ?
	BHIS	30$		; YES GO TO ALTERNATE RCOVERY
	BIT	#X0.RLL!X0.RLS,U.MSGB+TSXSR0(R5) ; RECORD LENGTH OFF?
	BNE	30$		; YES CAN'T DO OPPOSITE
	MOV	(R2),R0		; RETRIEVE COMMAND HEADER
	BIC	#^C<CM.COD>,R0	; CLEAR ALL BUT COMMAND CODE
	CMP	#CC.RDN,R0	; IS IT A READ OPERATION?
	BNE	30$		; IF NE NO GO DO CLEAN
	BIS	#CM.OPP,(R2)	; ALLS WELL SET OPPOSITE
	BR	AGAIN		;ISSUE OPPOSITE COMMAND			; RP023

30$:	SETRTY	CLN,RTNCLN	; SE      TUP FOR CLEAN FUNCTION
	BR	AGAIN		;ISSUE CLEAN				; RP023

;
; TERMINATION CLASS CODE 5 (RECOVERABLE ERROR - TAPE NOT MOVED)
;

TCL5ER:				;REF LABEL				; RP023
									; RP023
									; RP023
	.IF DF	E$$DVC							; RP023
									; RP023
	CALL	DVER		;LOG ERROR				; RP023
									; RP023
	.ENDC								; RP023
									; RP023
									; RP023
	DECB	RTTBL(R3)	; DECREMENT RETRY COUNT
	BNE	AGAIN		;RE-ISSUE COMMAND			; RP023
50$:	MOV	#IE.VER&377,R0	;SET UNRECOVERABLE ERROR		; RP023
	BR	TC      EXIT		;FINISH PROCESSING			; RP023

;
; TERMINATION CLASS CODE 7 (FATAL CONTROLLER ERROR)			; RP023
;
									; RP023
TCL7ER:	CLR	@S.CSR(R4)	; INIT CONTROLLER
	MOV	#TCL6ER,SSRRTY(R3)  ;SETUP SUB-SYSTEM READY RETRY	; RP023
				;HANDLER				; RP023
	BIS	#CS.WSS,CSTAT(R3)  ;SET WAITING FOR SUB-SYSTEM READY	; RP046
				;FLAG					;**-1
	MOV	#5.*256.+5.,S.CTM(R4)	;SET 5 SECOND TIMER		; RP023
	MOVB	#60.,S.STS(R4)	;SET EXTENDED TIMEOUT (5 MINUTES)	; RP023
	RETURN			;EXIT					; RP023
									; RP023
      ;
; TERMINATION CLASS CODE 6 (UNRECOVERABLE ERROR)
;

TCL6ER:	MOV	#IE.FHE&377,R0	; SET FATAL ERROR STATUS
									; RP023
									; RP023
	.IF DF	E$$DVC							; RP023
									; RP023
	CALL	DVER		;LOG ERROR				; RP023
									; RP023
	.ENDC								; RP023
									; RP023
									; RP023
	BR	TCEXIT		;FINISH PROCESSING			; RP023
	.DSABL	LSB							; PB116
									; PB116
;+
; **- IRREV - READ REVERSE COMPLETION
;-
									; RP023
IRREV:	BIC	#M.TMK,U.CW2(R5)	; DON'T SET FOR REVERSE O      PERATIO
	BR	IOCOM		; DO COMMON COMPLETION FOR TRANSFER

;+
; **- IWRMK - WRITE TAPE MARK COMPLETION
;-
									; RP023
IWRMK:	BIT	#M.HWL,R2	;UNIT HARDWARE WRITE LOCKED?		; RP063
	BNE	IOCOM		;IF NE YES				; RP063
	MOV	#IS.SUC&377,R0	;NO, SET SUCCESS STATUS			; RP063
	BR	IOCOM		; AND GO TO COMMON EXIT			;**-1

;+									; RP023
; **- IMOUNT - CHECK FOR BOT DURING MOUNT AND SET CHARACTERISTICS	; RP023
;-									; RP023
									; RP023
IMOUNT:	BIT	#M.SER,R2	;UNIT OFFLINE?				; RP048
	BNE	10      $		;IF NE YES				;**-1
	BIT	#M.BOT,R2	;AT BOT?				; RP048
	BNE	ISTAT		;IF NE YES				;**-1
10$:	MOV	#IE.FHE&377,R0	;NO, FATAL HARDWARE ERROR		; RP023
									; RP023
;+
; **- ISTAT - STATUS EXIT FOR SET, SENSE, AND MOUNT AND SET
;-
									; RP023
ISTAT:	MOV	U.CW2(R5),R1	;SET STATUS WORD 1 IN R1		; RP023
	BR	IODON		;AND EXIT				; RP023
									; RP023
;+
; **-RTNCLN - RETRY COMMAND AFTER CLEAN
;-
									; RP023
RTNCLN:	MOV	RTYINT(R3),INTADD(R3)	; RESTORE INTERRUPT ADDRES
	TSTB	R0		; ERR      OR ON CLEAN?
	BMI	TCL6ER		;IF MI YES, TAPE POSITION LOST - EXIT	; RP023
	MOV	U.CBP(R5),R2	; RETRIEVE COMMAND BUFFER POINTER
	MOV	CMDHDR(R3),(R2)	; RESTORE ORIGINAL COMMAND
	MOVB	#8.,S.ITM(R4)	; RESET TIMEOUT COUNT
AGAIN:	CALLR	INITIO		;RE-ISSUE COMMAND			; RP023
									; PB116
;+									; PB116
; **- ISPCB - SPACE BLOCKS COMPLETION
;-									; RP023
									; RP023
ISPCB:	BIT	#CC.SRR-CC.SRF,@U.CBP(R5) ;SPACE REVERSE FUNCTION?
	BEQ	10$		; IF EQ NO - CHECK FOR EOV
	BIC	#M.TMK,U.CW2(R5) ; CLE      AR TAPE MARK ON REVERSE
	BR	IOCOM		; GO TO COMMON EXIT
10$:				; REFERENCE LABEL
									; RP023
									; RP023
	.IF DF	A$$NSI

	BITB	#US.LAB,U.STS(R5) ;ANSII LABELED TAPE?
	BNE	IOCOM		; IF NE YES CAN'T BE EOV

	.ENDC

									; RP023
	BIT	#M.PEOV,U.CW2(R5)  ;TAPE MARK DETECTED LAST TIME	; RP047
	BEQ	IOCOM		; IF EQ NO - CAN'T BE EOV		;**-1
	BIT	#M.TMK,U.CW2(R5)	; TAPE MARK SEEN THIS TIME?
	BEQ	IOCOM		; IF EQ NO - CAN'T BE EOV
	MOV	U.CNT(R5),R1	; RETRIEVE REQUESTED COUNT
	SUB	U.MSGB+TSR      BPC(R5),R1 ; LESS RESIDUAL
	CMP	#1,R1		; ONLY ONE SPACED?
	BNE	IOCOM		; IF NE NO - NOT EOV
;
; AT EOV - DOING SPACE BLOCKS - NEED TO REPOSITION TAPE
;
	MOV	U.CBP(R5),R2	; SET COMMAND BUFFER POINTER
	SETRTY	SRR,SBRPOS,1	;SET OPERATION				; RP023
	BR	AGAIN		;RE-ISSUE COMMAND			; RP023
									; RP023
;+
; **-SBRPOS - RETURN FROM REPOSITIONING DURING SPACE BLOCKS		; RP023
;-
									; RP023
SBRPOS:	MOV	#IE.EOV&377,R0	;SET EOV STATUS				; RP023
	CLR	R1		; SET COUNT
	BIS	#M.AEOV,U.CW2(R5)  ;SET       POSITIONED AT EOV		; RP047
	BR	IODON		;AND EXIT				;**-1
									; RP023

;+
; **- ISPCF - SPACE FILES COMPLETION
;-

ISPCF:	BIT	#CC.STR-CC.STF,@U.CBP(R5)  ;SPACE REVERSE?		; PB116
	BEQ	10$		; IF EQ NO - CHECKK EOV
	BIC	#M.TMK,U.CW2(R5) ;CLR BIT FOR REVERSE
	BR	IOCOM		; AND EXIT
10$:	BIT	#X0.LET,U.MSGB+TSXSR0(R5) ; AT LEOT?
	BEQ	IOCOM		; IF EQ NO - EXIT
;									; RP023
; AT EOV - DOING SPACE FILE - NEED TO REPOSITION TAPE			; RP023
;									; RP023
	MOV	U.CBP(R5),R2	;GET COMMAND BUFFER       POINTER		; RP023
	SETRTY	STR,SFRPOS,1	;SPACE ONE TAPE MARK REVERSE		; RP023
	BR	AGAIN		;DO IT					; RP023
									; RP023
;+									; RP023
; **-SFRPOS - RETURN FROM REPOSITIONING DURING SPACE FILES		; RP023
;-									; RP023
									; RP023
SFRPOS:	MOV	#IE.EOV&377,R0	;SET EOV STATUS				; RP023
	BIS	#M.AEOV,U.CW2(R5)  ;SET POSITIONED AT EOV		; RP047
									;**-1
;+
;
; **- IOCOM - COMMON EXIT ROUTINE FOR ALL ROUTINES REQUIRING STATUS
;-
									; RP023
IOCOM:	MOV	U.CNT(R5),R1	; RETRI      EVE REQUESTED COUNT
	SUB	U.MSGB+TSRBPC(R5),R1 ; LESS RESIDUAL COUNT

;+
; **- IODON - COMMON EXIT FOR ALL FUNCTIONS				; RP023
;-
									; RP023

IODON:				;REF LABEL				; RP023
									; RP023
									; RP023
	.IF DF	D$$IAG

	CALL	MSDINT		; CALL DIAGNOSTIC COMPLETION

	.ENDC

									; RP023
	.IF DF	E$$DVC

	MOVB	RTTBL(R3),R2	;GET REMAINING RETRY COUNT		; RP023
	BIS	#RETRY*256.,R2	;MERGE ORIGINAL RETRY COUNT		; RP023

	.ENDC

									; RP023
	BIC	#CS.CIP,CSTAT(R3)  ;RESET CO      MMAND IN PROGRESS FLAG	; RP046
	BIC	#M.PEOV!M.RWD,U.CW2(R5)  ;RESET EOV STATUS CHECK AND ...; RP047
				;... REWINDING FLAG			; RP047
	CALL	$IODON		; CALL COMPLETION			;**-2
	JMP	MSINI		; GO CHECK FOR ANOTHER REQUEST

									; PB116
									; PB116
	.IF DF	E$$DVC		;%%% 1 %%%
									; RP023
;+
; **-DVER-TO INTERFACE WITH THE ERROR LOGGER.
;
; THE ERROR LOGGER ASSUMES (ERRONEOUSLY) THAT THE REGISTERS OF
; INTEREST ARE THE HARDWARE REGISTERS IN THE I/O PAGE POINTED TO
; BY S.CSR.  MOST OF T      HE STATUS INFORMATION FOR THE TS04 IS FOUND
; IN THE MESSAGE BUFFER ("EXTENDED STATUS REGISTERS") IN THE UCB.
; WE MUST, THEREFORE, CORRUPT OUR SCB TO MAKE S.CSR CONTAIN THE
; ADDRESS OF THE MESSAGE BUFFER AND THEN RESTORE IT ON RETURN.
; "TSSR", THE ONLY REAL HARDWARE REGISTER, IS COPIED INTO A SLOT IN
; THE MESSAGE BUFFER NORMALLY WHEN WE LOOK AT IT.
;
; INPUT:
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;	ERROR MESSAGE BUFFER (EMB) FILLED "CORRECTLY".
;
;-

DVER:	BIT	#CS.UMD,CSTAT(      R3)  ;USER MODE DIAGNOSTIC IN PROGRESS?	; RP046
	BNE	10$			;YES=> SKIP THIS REPORT; ELSE	;**-1
	MOV	S.CSR(R4),-(SP)		;PUSH (SAVE) CSR ADDRESS.
	MOV	#U.CBP,S.CSR(R4)	;USE DRIVER SPECIFIC DDB
	ADD	R5,S.CSR(R4)	; ADDRESS TO FOOL ERR LOG.
	BIT	#CS.TMO,CSTAT(R3)  ;TIMEOUT TO LOG?			; RP046
	beq	3$			;no=>plain log; else		;**-1
	call	$dtoer		;log the error with timeout.
	br	7$		;restore the data base.
3$:	CALL	$DVERR		;LOG THE ERROR
7$:	MOV	(SP)+,S.CSR(R4)	;RESTORE THE CSR ADDRESS.
10$:	RETURN			;RETUR      N TO CALLER.
									; RP023
	.ENDC			;%%% 1 %%%
									; PB116

	.IF DF	D$$IAG		;%%% 1 %%%

;+
; **-MSDINT-TS11 DIAGNOSTIC INTERRUPT AND TIMEOUT HANDLER
;
; IF ENTRY WAS FROM A DIAGNOSTIC CONTROL FUNCTION, THEN MOVE THE
; I/O PACKET WORDS 17 & 20 TO WORDS 20 & 21 FOR THE $CRPAS ROUTINE.
; FOR ANY DIAGNOSTIC FUNCTION, PASS THE UNIBUS DEVICE REGISTERS
; AND THE EXTENDED STATUS REGISTERS VIA THE $CRPAS ROUTINE.
;
; INPUTS:
;
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS						; RP023
;
; OUTPUTS      :
;	CARRY BIT CLEAR = NON-DIAGNOSTIC FUNCTION
;	CARRY BIT SET = DIAGNOSTIC FUNCTION
;
;-

MSDINT:	BIT	#CS.UMD,CSTAT(R3)  ;NON-DIAGNOSTIC FUNCTION?		; RP046
	BEQ	30$		;TRUE=> FINISHED; ELSE DO THINGS ...	;**-1
	MOV	R1,-(SP)	;SAVE R1
	MOV	R2,-(SP)	;SAVE R2
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOV	#U.MSGB,R2	;LOAD MESSAGE BUFFER OFFSET.
	ADD	R5,R2		;ADD IN UCB ADDRESS.
	CMPB	#IO.EOF/256.,I.FCN+1(R1) ;WRITE EOF FUNCTION?
	BEQ	10$		;IF EQ YES
	CMPB	#IO.RWD/256.,I.FCN+1(R1) ;REWIND FUNCTION?      
	BEQ	10$		;IF EQ YES
	CALL	$CRPAS		;PASS DEVICE REGISTERS TO DIAGNOSTIC
	BR	20$		;GO TO EXIT
10$:	MOV	I.PRM+14(R1),I.PRM+16(R1) ;MOVE PACKET WD20 TO WD21
	MOV	I.PRM+12(R1),I.PRM+14(R1) ;MOVE PACKET WD17 TO WD20
	CALL	$CRPAS		;PASS DEVICE REGISTERS TO DIAGNOSTIC
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS			; RP023
	MOV	I.PRM+14(R1),I.PRM+12(R1) ;MOVE WD20 BACK TO WD 17
	MOV	I.PRM+16(R1),I.PRM+14(R1) ;MOVE WD21 BACK TO WD20
20$:	MOV	(SP)+,R2	;RESTORE R2				; RP023
	MOV	(SP)+,R1	;RESTORE R1.
30$:	RE   J   TURN			;EXIT TO CALLER

	.ENDC			;%%% 1 %%%

									; RP023
	.END
J          dTðskQ	› c,        	.TITLE	MTDRV
	.IDENT	/04.15/
 
;
; COPYRIGHT (C) 1974,1978,1979,1980,1981
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;	VERSION  04.15/
;
; SCOTT G. DAVIS 9-JUL-74
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	S. G. DAVIS
;	C. A. D'ELIA
;	B. LYONS
;	T. J. MILLER
;	F. L. STRAIGHT
;
; MODIFIED BY:
;
;	J. CLEARY 26-APR-77
;
;		JC001 -      - POWERFAIL SUPPORT FOR TE10.
;
;	P. J. BEZEREDI 04-MAY-77
;
;		PB027 -- TIGHTEN UP DOUBLE INTERRUPT TIMING WINDOW.
;
;	P. J. BEZEREDI 06-MAY-77
;
;		PB028 -- CLEAN UP SPACE FUNCTION EXECUTION.
;
;	J. CLEARY 20-SEP-77
;
;		JC006 -- INSURE INTERRUPT ENABLE IS CLEARED.
;
;	J. CLEARY 23-MAR-78
;
;		JC011 -- CLEAN UP SPACE FUNCTION PATCH
;
;	J. CLEARY  24-APR-78
;
;		JC014 -- IGNORE EOT ON READS
;
;	J. CLEARY 21-JUN-78
;
;		JC017 -- FIX BUG IN UMR ALLOCATION
;
;	J. CLEARY 4-DEC-78
;
      ;		JC024 -- CLEAR US.ABO TO PREVENT UNINTENDED ABORTS
;
;	J. CLEARY 4-DEC-78
;
;		JC025 --  IMPLEMENT IQ.X SUPPRESS RETRIES
;
;	J. CLEARY 3-APR-79
;
;		JC036 -- BYPASS CALL TO ERRLOG WHEN SMO RETURNS ERROR
;
;
;		JC041 -- FIX PROBLEM IN SENSE CHARACTERISTICS
;
;		TL030 -- CHECK THAT A CANCEL IS ISSUED BY THE TASK
;			 WHICH ISSUED THE CURRENT OPERATION
;
;		TL067 -- RETURN THE CORRECT BLOCK COUNT FOR
;			 IO.SPB AT EOV
;
;		TL068 -- FIX BRANCH OUT OF RANGE
;
;		TL072 -- DO NOT LOG DATA       OVERRUN
;
;		TL073 -- RETURN EOV FOR IO.SPF, NOT EOT
;
;		CS001 -- TAPE DENSITY SUPPORT IDENTIFICATION IN U.CW3
;
;		CS002 -- DEVICE NOT READY IF TAPE UNIT OFF LINE
;
;		CS003 -- BOT STATUS IF TAPE UNIT READY
;
; TM11 MAGNETIC TAPE CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;
	.MCALL	HWDDF$,PKTDF$,ABODF$,CLKDF$,UCBDF$			;CS001
	HWDDF$								;**-1
	PKTDF$
	ABODF$
	CLKDF$
	UCBDF$			; UNIT CONTROL BLOCK OFFSETS		;CS001


	.IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNO      STIC DEFINITIONS

	.ENDC


;
; EQUATED SYMBOLS
;

US.ABO=1			;ABORT IN PROGRESS - U.STS
US.BSP=2			;INTERNAL BACKSPACE IN PROGRESS - U.STS
US.PWF=10			;POWER FAIL STATUS
RETRY=12			;RETRY COUNT

;
; REGISTER BIT SYMBOLS
;

CS.GO=1				;GO
CS.EXM=60			;EXTENDED MEMORY BITS
CS.IE=100			;INTERRUPT ENABLE
CS.RDY=200			;CONTROLLER READY BIT
CS.EVN=4000			;EVEN PARITY
CS.CLR=10000			;POWER CLEAR
CS.DN5=20000			;556 BPI DENSITY BIT
CS.DN8=40000			;800 BPI DENSITY BIT

DS.TUR=1			;TAPE UNI      T READY
DS.RWS=2			;REWINDING
DS.HWL=4			;WRITE LOCK
DS.SDN=10			;SETTLE DOWN
DS.7CH=20			;UNIT IS 7 CHANNEL
DS.BOT=40			;BEGINNING OF TAPE
DS.MOL=100			;MEDIUM ON LINE
DS.BTE=400			;BAD TAPE ERROR
DS.RLE=1000			;RECORD LENGTH ERROR
DS.EOT=2000			;END OF TAPE DETECTED
DS.BGL=4000			;BUS GRANT LATE
DS.PAE=10000			;PARITY ERROR
DS.CRE=20000			;CYCLICAL REDUNDANCY ERROR
DS.TM=40000			;TAPE MARK DETECTED
DS.ILG=100000			;ILLEGAL COMMAND

RD.GAP=10000			;GAP SHUTDOWN IN PROGRESS
RD.LPC=40000			;      READ LPC CHARACTER AND RTTBL FLAG

;
; MAG TAPE STATUS REGISTER BIT DEFINITIONS (SENSE AND SET CHARACTERISTICS)
;

M.PEOV=100000			;TAPE PAST LOGICAL END OF VOLUME
M.AEOV=40000			;TAPE AT LOGICAL END OF VOLUME
M.BOT=20000			;TAPE AT BOT
M.7CH=10000			;UNIT IS 7 CHANNEL
M.HWL=2000			;HARDWARE WRITE LOCK
M.RWD=1000			;UNIT IS REWINDING
M.SER=400			;SELECT ERROR HAS OCCURED
M.IXG=200			;INHIBIT WRITE WITH EXTENDED INTERRECORD
M.SWL=100			;SOFTWARE WRITE LOCK
M.EOF=40			;LAST COMMAND ENCOUNTERED       TAPE MARK
M.EOT=20			;LAST COMMAND ENCOUNTERED EOT
M.EVN=10			;EVEN PARITY
M.CDM=4				;CORE DUMP MODE (7 CHANNEL ONLY)
M.200=2				;200 BPI (7 CHANNEL ONLY)
M.556=1				;556 BPI (7 CHANNEL ONLY)

USRBTS=317			;STATUS BITS CONTROLLED BY THE USER
NEWBTS=M.PEOV!M.BOT!M.EOF!M.EOT	;STATUS BITS TO BE SET BEFORE $IODON

;
; COMMANDS
;

RWU=101				;REWIND AND OFFLINE
RED=103				;READ
WRT=105				;WRITE
WEF=107				;WRITE END-OF-FILE
SPF=111				;SPACE FORWARD
SPR=113				;SPACE REVERSE
WTE=115				;WRI      TE WITH EXTENDED GAP
RWD=117				;REWIND

U.SPC =	U.VCB+2			; SPACING COUNT, RDBLK TEMP.		;CS001
									;CS001
;
; LOCAL MACROS
;
;
; THE FOLLOWING MACRO DEFINES ENTRIES IN THE FUNCTION TABLE
;
.MACRO	DFENT	COM,TIMOUT,PWF,OPCODE,TYPE,INTADD
	.WORD	COM
	.BYTE	PWF,TIMOUT
	.BYTE	TYPE,OPCODE
	.WORD	INTADD
.ENDM	DFENT

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;
; DIAGNOSTIC FUNCTIONS USE BITS 14-15 OF RTTBL AS FLAGS FOR
; INTERRUPT AND FUNCTION HAND      LING.

CNTBL:	.BLKW	T$$M11		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	T$$M11		;ERROR RETRY COUNT
SPTBL:	.BLKW	T$$M11		;FOR SPACE CHECKING
INTADD:	.BLKW	T$$M11		;CURRENT INTERRUPT SERVICE ADDRESS


	.IF GT	T$$M11-1

TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC


;
; LEGAL FUNCTION DISPATCH TABLE
;

LGFCN:	DFENT	IO.RLB,8.,0,RED,0,RDBLK ;READ LOGICAL BLOCK
	DFENT	IO.WLB,6.,0,WRT,0,WRBLK ;WRITE LOGICAL BLOCK
	DFENT	IO.EOF,2.,0,WEF,0,WREOF ;WRITE TAPE MARK
	DFEN      T	IO.RWD,2.,1,RWD,0,REWND ;REWIND
	DFENT	IO.RWU,2.,1,RWU,0,REWND ;REWIND THEN OFF-LINE
	DFENT	IO.SPB,8.,0,SPF,1,SPCBK ;SPACE BLOCK
	DFENT	IO.SPF,8.,0,SPF,2,SPCFL ;SPACE FILE
	DFENT	IO.STC,0,-1,0,-1,-1	;SET CHARACTERISTICS
	DFENT	IO.SEC,0,-1,1,-1,-1	;SENSE CHARACTERISTICS
	DFENT	IO.SMO,0,1,-1,-1,-1	;MOUNT AND SET CHARACTERISTICS

ENDFCN=.			;END OF FUNCTION TABLE

;
; DRIVER DISPATCH TABLE
;

$MTTBL::.WORD	MTINI		;DEVICE INITIATOR ENTRY POINT
	.WORD	MTCAN		;CANCEL I/O OPERATION ENTRY POINT
	.      WORD	MTOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	MTPWF		;POWERFAIL ENTRY POINT

;+
; **-MTINI-TM11 MAGNETIC TAPE CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NE      XT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
MTINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCC	10$		;IF CC PROCESS REQUEST
	RETURN			;NOTHING TO DO OR CONTROLLER BUSY

;
; THE FOLLOWING ARGU      MENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; TM11 MAGNETIC TAPE FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQU      ESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB/IO.RWD/IO.SPB/IO.SPF/IO.EOF).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;

10$:	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB
	MOV	#$MTCLK,S.MTCK+C.SUB(R4)  ;SET ADDR OF CLOCK ROUTINE
	CLR	S.      FRK+2(R4)	;INIT FORK PC WORD
	MOV	#LGFCN,R2	;POINT TO LEGAL FUNCTION TABLE
	MOV	I.FCN(R1),R0	;GET FUNCTION CODE

	.IF DF  D$$IAG

	CLRB	RTTBL+1(R3)	;CLEAR DIAGNOSTIC FLAG
	MOV	I.FCN(R1),R0	;GET FUNCTION CODE
	BITB	#IQ.UMD,R0	;DIAGNOSTIC FUNCTION CALL?
	BEQ	20$		;IF EQ NO
	MOV	#100000,RTTBL(R3) ;STOP RETRIES AND SET DIAG. FLAG
	CMP	#IO.LPC!IQ.UMD,R0  ;READ LPC CHARACTER FUNCTION?
	BNE	15$		;IF NE NO
	BIS	#RD.LPC,RTTBL(R3)  ;SET LPC READ FLAG
	MOV	#IO.RLB!IQ.UMD,R0  ;CONVERT TO READ LOGICAL
	MO      V	R0,I.FCN(R1)	;SAVE FOR LATER USE
15$:	BIC	#IQ.UMD,R0	;CLEAR FOR FUNCTION CHECK

	.IFTF

20$:	BICB	#IQ.X,R0	;CLEAR IQ.X IT WILL BE
				;CHECKED LATER

	.ENDC
	CMP	R0,(R2)+	;FUNCTION CODE MATCH?

	BEQ	35$		;IF EQ YES
	ADD	#6,R2		;POINT TO NEXT TABLE ENTRY
	CMP	R2,#ENDFCN	;AT END OF TABLE?
	BNE	20$		;IF NE NO
	BR	40$		;ILLEGAL FUNCTION

;
; FUNCTION CODE MATCH FOUND
;



	.IF DF	P$$RFL

35$:	BITB	#US.PWF,U.STS(R5) ;POWER FAIL OCCUR?
	BEQ	45$		;IF EQ NO
	TSTB	(R2)		;LEGAL FUNCTION?      
	BMI	45$		;IF MI YES
	BNE	43$		;IF NE THIS IS A BETTER ONE

	.IFTF

40$:	MOV	#IE.IFC&377,R0	;SET ILLEGAL FUNCTION
	JMP	230$		;INFORM THE USER

43$:	BICB	#US.PWF,U.STS(R5)   ;ALLOW ALL FUNCTIONS

	.IFF

35$:				;REF LABEL

	.ENDC


45$:	MOV	(R2)+,S.CTM(R4)	;SET UP FOR PROPER TIMEOUT
	CLRB	S.CTM(R4)	;CLEAR OUT PWF INFO
	CLR	SPTBL(R3)	;RESET SPACING FLAG
	CLR	U.SPC(R5)	;NOT SPACING FILE			;CS001
	TSTB	(R2)+		;DETERMINE TYPE OF OPERATION		;**-1
	BPL	50$		;IF PL NOT STATUS FUNCTION
	JMP	1      90$		;STATUS FUNCTION
50$:	BEQ	90$		;IF EQ NON-SPACING FUNCTION

;
; SPACING FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- SPACING COUNT (POSITIVE=FORWARD, NEGATIVE=BACKWARD).
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- RELOCATON BIAS OF DIAGNOSTIC REG. BLK. ADDRESS
;	WD. 20 -- DIAG. REG. BUFFER ADDRESS (REAL OR DISPL. + 140000)
;

	MOV	U.BUF(R5),I.PRM+4(R1) ;MOVE SPACING COUNT TO COMMON PLACE
	CLR	U.BUF(R5)	;RESET TO TAKE ON OPCO      DE BELOW
	MOV	I.PRM+4(R1),U.CNT(R5) ;MOVE SPACING COUNT TO COMMON PLACE
	BNE	60$		;IF NE SOME SPACING REQUIRED
	CLR	I.PRM+4(R1)	;CLEAR COUNT FOR STATUS RETURN		;TL067
	JMP	220$		;NO SPACING REQUIRED
60$:	BMI	65$		;IF MI SPACE REVERS
	BIT	#M.AEOV,U.CW2(R5) ;AT EOV?
	BEQ	70$		;IF EQ NO - PROCEED
	MOV	#IE.EOV&377,R0	;STILL AT EOV
	CLR	I.PRM+4(R1)	;CLEAR COUNT FOR STATUS RETURN		;TL067
	JMP	230$		;TELL THE USER
65$:				;REFERENCE LABEL
	NEG	U.CNT(R5)	;CONVERT TO POSITIVE COUNT
	NEG	I.PRM+4(R1)	;THI      S ONE, TOO
	BIS	#2,U.BUF(R5)	;CHANGE SPACE FORWARD TO SPACE REVERSE
70$:	CMPB	-1(R2),#1	;SPACE FILE OR SPACE BLOCK?
	BEQ	80$		;IF EQ SPACE BLOCK
	MOV	U.CNT(R5),U.SPC(R5) ;SAVE COUNT OF FILES TO SPACE	;CS001
	NEG	U.SPC(R5)	;SET UP FOR FINAL ACCOUNTING		;CS001
	MOV	#-1,U.CNT(R5)	;SET UP FOR BIG SPACE			;**-2
80$:	MOV	U.CNT(R5),SPTBL(R3) ;SAVE SPACING COUNT
	NEG	SPTBL(R3)	;MAKE IT MATCH REGISTER CONTENTS
	BR	110$		;SKIP SOME CHECKS AND BIC'S

;
; READ/WRITE LOGICAL FUNCTION DEPENDENT I/O PACKET FOR      MAT:
;
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- RELOCATON BIAS OF DIAGNOSTIC REG. BLK. ADDRESS
;	WD. 21 -- DIAG. REG. BUFFER ADDRESS (REAL OR DISPL. + 140000)
;
; NO FUNCTION DEPENDENT PARAMETERS ARE REQUIRED FOR REWIND OR WRITE EOF
;

90$:				;REF LABEL


	.IF DF	M$$EXT&M$$MGE

	CALL	$STMAP		;SET UP UNIBUS MAPPING ADDRESS

	.END      C


	CMPB	-2(R2),#2	;WRITE EOF, REWIND OR REWIND & OFFLINE?
	BEQ	100$		;IF EQ YES - SEE IF WRITELOCK SET
	CMPB	(R2),#WRT	;WRITE?
	BNE	110$		;IF NE NO
	MOV	#IE.SPC&377,R0	;ASSUME PARAMETER PROBLEMS
	CMP	I.PRM+4(R1),#14. ;TOO SHORT?
	BLO	163$		;IF LO YES
	BR	105$		;SKIP EXMEM BIT CLEAR
100$:	CLR	U.BUF(R5)	;NOTHING THERE FOR WEF
	CMPB	(R2),#WEF	;WRITE EOF?
	BNE	110$		;IF NE NO, SKIP CHECK FOR WRITE LOCK
105$:	MOV	#IE.WLK&377,R0	;ASSUME (SOFTWARE) WRITE LOCK
	BIT	#M.SWL,U.CW2(R5) ;LOCKED?
	BNE	1      63$		;IF NE YES
110$:	BISB	(R2)+,U.BUF(R5)	;PICK UP FUNCTION CODE FROM COMMAND TABLE
	MOV	(R2),INTADD(R3)	;SET INITIAL INTERRUPT ADDRESS


	.IF DF  D$$IAG

	TST	RTTBL(R3)	;DIAGNOSTIC FUNCTION CALL?
	BMI	120$		;IF MI YES -STOP RETRIES

	.ENDC


	MOV	#RETRY,RTTBL(R3) ;SET UP RETRY COUNTS
120$:	CALL	SELECT		;SELECT THE REQUIRED DRIVE
	BCS	SELERR		;IF CS SELECT ERROR OCCURRED
	MOV	U.CW2(R5),R1	;PICK UP DRIVE'S CHARACTERISTICS
	BIT	#M.EVN,R1	;EVEN PARITY REQUIRED?
	BEQ	140$		;IF EQ NO
	BIS	#CS      .EVN,U.BUF(R5) ;SET BIT IN STATUS REGISTER
140$:	BIS	#CS.DN5!CS.DN8,U.BUF(R5) ;ASSUME 9-CHANNEL, 800BPI
	BIT	#M.7CH,R1	;7-CHANNEL DRIVE?
	BEQ	151$		; IF EQ NO
	BIT	#M.CDM,R1	;CORE DUMP MODE?
	BNE	151$		; IF NE YES
	BIT	#M.556,R1	;556 BPI?
	BNE	150$		;IF NE YES
	BIC	#CS.DN5,U.BUF(R5) ;RESET BIT FOR COMMAND
	BIT	#M.200,R1	;200 BPI?
	BEQ	151$		; IF EQ NO
150$:	BIC	#CS.DN8,U.BUF(R5) ;RESET COMMAND BIT
151$:	JMP	170$		; RETURN

;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED.      
; IF THE OPERATION WAS DIAGNOSTIC, THE QIO REQUEST IS TERMINATED.
; TIMEOUTS ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE
; RESULT OF HARDWARE CONSIDERATIONS.  IN PARTICULAR, A LENGTHY SPACING
; OPERATION MAY RESULT IN A TIMEOUT WHICH WILL BE IGNORED.
;

MTOUT:	MOV	S.CSR(R4),R2	;;;PICK UP ADDRESS OF CSR
	BITB	#US.ABO,U.STS(R5) ;;;ABORTING?
	BEQ	152$		;;;IF EQ NO
	BICB	#US.ABO,U.STS(R5) ;CLEAR ABORT FLAG
	BIC	#M.RWD,U.CW2(R5) ;;;REWIND NOT IN PROGRESS
	BR	162$		;;;TERMINATE
152$:				;;      ;REFERENCE LABEL
	MOVB	S.CON(R4),R3	;;;FETCH CONTROLLER NO.
	BIT	#M.RWD,U.CW2(R5) ;;;REWINDING?
	BNE	155$		;;;IF NE YES
	MOV	SPTBL(R3),R0	;;;SPACE IN PROGRESS?
	BEQ	154$		;;; IF EQ THEN NO
	CMP	R0,2(R2)	;;;IS THE TAPE BLANK?
	BNE	153$		;;; IF NE THEN NO
	CALL	$DTOER		;;; LOG DEVICE TIMEOUT
	BR	161$		;;; EXIT WITH IE.DNR ERROR CODE
153$:				;;; REF. LABEL
	MOV	2(R2),SPTBL(R3)	;;;SAVE VALUE FOR NEXT COMPARISON
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESUME TIMEOUT
	RETURN			;;;THAT IS ALL FOR NOW
154$:	CAL      L	$DTOER		;;; LOG DEVICE TIMEOUT


	.IF DF	D$$IAG

	BCS	161$		;ABORT DIAGNOSTIC CALL

	.ENDC


155$:	BIC	#CS.IE,(R2)	;;;CLEAR INTERRUPT ENABLE
	MTPS	#0		;;;ALLOW INTERRUPTS
	BIT	#M.SER,U.CW2(R5) ;WAS THERE A SELECT ERROR?
	BEQ	160$		;IF EQ NO
	BIC	#M.SER,U.CW2(R5) ;RESET STATUS BIT
	BIT	#M.RWD,U.CW2(R5) ;REWINDING?
	BEQ	120$		;IF EQ NO - REISSUE ORIGINAL COMMAND
	BIT	#DS.MOL,-2(R2)	;IS THE DRIVE ON-LINE NOW?
	BEQ	SELERR		;IF EQ NO
	MOVB	#RWD-CS.IE,(R2)	;START THE REWIND AGAIN
	BR	172$		;      START UP TIMEOUT
160$:	BIT	#M.RWD,U.CW2(R5) ;REWINDING?
	BNE	164$		;IF NE YES
161$:	MOV	#IE.DNR&377,R0	;INDICATE DEVICE NOT READY
162$:


	.IF DF  D$$IAG

	CALL	MTDINT		;PASS DIAGNOSTIC DEVICE REGISTERS

	.ENDC


	BIS	#CS.CLR,(R2)	 ;RESET CONTROLLER
163$:	JMP	230$		; REPORT FATAL ERROR
164$:	BIT	#DS.MOL,-2(R2)	;EVERYTHING COPASETIC?
	BEQ	SELERR		;IF EQ NO
	BIT	#DS.BOT!DS.RWS,-2(R2) ;TAPE OK?
	BNE	165$		;IF NE OK
SELERR:
	MOV	#IE.DNR&377,R0	;NOT READY - IF TAPE OFF LINE		;CS002


	.IF       DF  D$$IAG

	TST	RTTBL(R3)	;DIAGNOSTIC FUNCTION CALL?
	BMI	230$		;IF MI YES - STOP SELECT MSG.

	.ENDC


	MOV	S.PKT(R4),R1	;RETREIVE I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	;RETRIES SUPPRESSED?
	BNE	230$		;IF NE YES - SKIPP SELERR
	TST	U.ACP(R5)	; ACP WANTS RETURN?
	BNE	230$		; IF NE YES EXIT
	BIS	#M.SER,U.CW2(R5) ;SET SELECT ERROR BIT
	DECB	S.STS(R4)	;TIME FOR A MSG?
	BNE	172$		;IF NE NO
	MOV	#T.NDSE,R0	;SET UP TO DELIVER MESSAGE
	MOVB	#15.,S.STS(R4)	;SET UP TIMEOUT
	CALL	$DVMSG		;SEND       THE MESSAGE
	BR	172$		;SET THE TIMOUT
165$:	BIT	#DS.TUR,-2(R2)	;REWIND COMPLETE?
	BEQ	172$		;IF EQ NO
	BIT	#DS.BOT,-2(R2)	;DID WE GET TO BOT?
	BNE	175$		;IF NE YES - REWIND COMPLETE
170$:	BIT	#M.RWD,U.CW2(R5) ;REWINDING?
	BEQ	177$		;IF EQ NO
172$:	MOVB	#1,S.CTM(R4)	;SET UP A TIMEOUT
	RETURN			;THAT IS ALL FOR NOW
175$:	BIS	#M.BOT,U.CW2(R5) ;SAY AT BOT
177$:				;REF LABEL


	.IF DF	M$$EXT&M$$MGE

	CMPB	#SPF,U.BUF(R5)	;SPACE FORWARD?
	BEQ	178$		;YES UMRS NOT NEEDED
	CMPB	#SPR,U.BUF(R5)	;SPAC      E REVERSE?
	BEQ	178$		;YES UMRS NOT NEEDED
	MOV	R2,-(SP)	;SAVE R2
	CALL	$MPUBM		;MAP UNIBUS TO TRANSFER
	MOV	(SP)+,R2	;RESTORE R2

	.ENDC


178$:	CMP	(R2)+,(R2)+	;POINT TO MEMORY ADDRESS REGISTER
	MOV	U.BUF+2(R5),(R2) ;SET UP BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	;SET UP BYTE COUNT REGISTER
	NEG	(R2)		;NEED 2S COMPLEMENT
180$:	MOVB	S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT
	BIC	#M.AEOV!M.SER!M.RWD,U.CW2(R5) ;RESET VARIOUS FLAGS
	BICB	#US.BSP,U.STS(R5) ;RESET FLAGS


	.IF DF  D$$I      AG

	BIT	#RD.LPC,RTTBL(R3) ;READ LPC CHAR FUNCTION?
	BEQ	185$		;IF EQ NO
	BIS	#RD.LPC,6(R2)	;SET LPC READ IN MTRD REG.
185$:				;REF. LABEL

	.ENDC


	.IF DF	E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE IN BITMAP

	.ENDC


	MOV	U.BUF(R5),-(R2)	;INITIATE THE FUNCTION
	RETURN			;DONE

;
; CANCEL I/O OPERATION IS A NOP FOR TM11 MAGNETIC TAPES
;

MTCAN:	CMP	I.TCB(R0),R1	;CANCEL FOR THIS TASK?			;TL030
	BNE	111$		;BRANCH IF NOT				;TL030
	BISB	#US.ABO,U.STS(R5) ;FLAG THE ABORT CONDITION		;TL03      0
111$:	RETURN								;TL030
;									;**-2
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION.
;

MTPWF:				; POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	BISB	#US.PWF,U.STS(R5)  ;SET POWER FAIL INDICATOR

	.ENDC

	CALL	DRVSTS		;INDICATE TAPE DENSITY SUPPORT		;CS001

	RETURN			;

;
; STATUS FUNCTION PROCESSING
;

190$:				;REFERENCE LA      BEL
	MOV	R2,-(SP)	;SAVE TABLE POINTER
	CALL	SELECT		;SET BOT, HWL, AND 7CH STATUS
	MOV	(SP)+,R2	;RESTORE POINTER
	MOV	U.CW2(R5),I.PRM+4(R1) ;ASSUME SENSE CHARACTERISTICS
	TSTB	(R2)+		;DETERMINE FUNCTION REQUIRED
	BEQ	210$		;IF EQ SET CHARACTERISTICS
	BPL	220$		;IF PL "SENSE CHARACTERISTICS"
200$:				;REF. LABEL				;**-21
	BIT	#M.BOT,U.CW2(R5) ;AT BOT?				;**-8
	BEQ	245$		;IF EQ NO - FATAL ERROR
									;**-1
210$:	BIC	#USRBTS,U.CW2(R5) ;PREPARE TO SET NEW BITS
	BIC	#^C<USRBTS>,U.BUF(R5) ;LEAVE       ONLY USER CONTROLLED BITS
	BIS	U.BUF(R5),U.CW2(R5) ;NEW STATUS WORD

;
; NO SPACING REQUIRED
;

220$:	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS
230$:	MOV	S.CSR(R4),R2	;PICK UP CSR ADDRESS
	BIC	#CS.IE!CS.EXM,(R2) ;CLEAR IE AND EX. MEM. BITS
	CLR	2(R2)		;ASSURE PROPER VALUE FOR RETURN
	JMP	540$		;CLEAN UP AND EXIT


;+
; **-$MTINT-TM11 MAGNETIC TAPE CONTROLLER INTERRUPTS
;-

	INTSE$	MT,PR5,T$$M11	;;;GENERATE INTERRUPT SAVE CODE
	MOV	U.SCB(R5),R4	;;;RETRIEVE ADDRESS OF SCB
	TST	      S.FRK+2(R4)	;;;HAVE WE FORKED ALREADY?
	BNE	300$		;;;IF NE YES, RETURN FROM INTERRUPT
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
240$:	MOV	U.SCB(R5),R4	;GET SCB ADDRESS
	MOV	S.CSR(R4),R2	;PICK UP COMMAND REGISTER ADDRESS
	BICB	#US.ABO,U.STS(R5) ;CLEAR ABORT FLAG
	BIT	#DS.TUR!DS.RWS!DS.ILG!DS.EOT!DS.BOT,-(R2) ;UNIT DONE?
	BNE	250$		;IF NE YES
	CMPB	U.BUF(R5),#RWU	;WAS IT A REWIND AND OFFLINE FUNCTION?
	BEQ	220$		;IF EQ YES, COMPLETE WITH SUCCESS
	MOV	R4,R0		;GET ADDR OF CLOCK QUEUE BLOCK
	ADD	#S.MTCK      ,R0	;
	CLR	R1		;SET UP HIGH TICKS
	MOV	#1,R2		;TIMEOUT UNTIL TUR
	MOV	#C.SYST,R4	;TYPE OF CLOCK ENTRY
	CALLR	$CLINS		;TIMEOUT

$MTCLK::			;REF LABEL FOR TIMEOUT

	MOV	C.TCB(R4),R5	;RESTORE UCB ADDRESS
	BR	240$		;SEE IF UNIT READY
245$:	MOV	#IE.FHE&377,R0	; SET FATAL ERROR STATUS
	JMP	540$		; EXIT
250$:	MOVB	S.CON(R4),R3	;PICK UP CONTROLLER NO.
	BIT	#DS.MOL,(R2)+	;IS THE DRIVE STILL ON-LINE?
	BNE	260$		;IF NE YES
	JMP	161$		;ISSUE "DEVICE-NOT-READY" MSG
260$:	BIC	#CS.IE!CS.EXM,(R2)  ;CLEAR IN      T. ENABLE AND EX.MEM BITS
	MOVB	S.ITM(R4),S.CTM(R4)  ;RESET TIMEOUT COUNT
	CLR	S.FRK+2(R4)	;ALLOW INTERRUPT PROCESSING
	MOV	-2(R2),R1	;GET CONTENTS OF DRIVE STATUS REGISTER
	BITB	#US.BSP,U.STS(R5) ;INTERNAL BACKSPACE IN PROGRESS?
	BNE	280$		;IF NE YES - CALL SERVICE ROUTINE
270$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESS FOR VARIOUS REASONS
	TST	(R2)		;ANY ERRORS?
	BMI	280$		;IF MI YES
	TST	U.SPC(R5)	;SPACING FILE?				;CS001
	BNE	280$		;IF NE, YES. TREAT AS ERROR ANYWAY.	;CS001
	CMPB	(R2),#RWD+CS.RDY-CS      .GO-CS.IE ;WAS THAT A REWIND?	;**-2
	BNE	275$		;IF NE NO
	BIS	#M.RWD,U.CW2(R5) ;SET STATUS BIT
275$:	JMP	500$		;SUCCESS!!
280$:				; REF LABEL


	.IF DF	D$$IAG&E$$DVC

	TST	RTTBL(R3)	; DIAGNOSTIC FUNCTION CALL?
	BMI	290$		; IF MI YES

	.ENDC


	.IF DF	E$$DVC

	BIT	#DS.ILG!DS.CRE!DS.PAE!DS.BGL!DS.BTE,R1			;TL072
				; ANY ERRORS IN STATUS REG (MTS)?	;**-1
	BEQ	290$		; IF EQ THEN NO
	CALL	$DVERR		; LOG DEVICE ERROR

	.ENDC


290$:				; REF LABEL
	CALL	@INTADD(R3)	; CALL THE INTERRUPT       ROUTINE
	MOV	(SP)+,INTADD(R3) ;SAVE INTERRUPT ADDRESS
300$:	RETURN			;WAIT FOR END OF NEXT COMMAND STEP

;
; WRITE LOGICAL FUNCTION
;

WRBLK:	BIT	#DS.TM,R1	;DID WRITE SEE EOF?
	BNE	320$		;IF NE YES

;
; WRITE TAPE MARK FUNCTION
;

WREOF:	BIT	#34404,R1	;ANY OTHER ERRORS?
	BEQ	325$		;IF EQ NO - REALLY SUCCESSFUL		;TL068
	MOV	#IE.WLK&377,R0	;ASSUME WRITE-LOCK			;**-1
	BIT	#DS.HWL,R1	;WRITE LOCK?
	BNE	325$		;IF NE YES				;TL068
	BIT	#34400,R1	;RECOVERABLE ERROR?			;**-1
	BNE	320$		;IF NE Y      ES

;
; REWIND FUNCTIONS
;

REWND:	MOV	#IE.FHE&377,R0	;FATAL ERROR
	BR	490$		;THAT'S ALL, FOLKS!

320$:	MOV	#IE.BBE&377,R0	;ASSUME BAD TAPE OR EQUIVALENT
	TSTB	U.CW2(R5)	;SHOULD WE REWRITE?
	BMI	490$		;IF MI USER SAID "NO"
	BIT	#2,@R2		;IS THIS A WRITE EOF?
	BNE	420$		;IF NE YES
	BIS	#WTE-WRT,U.BUF(R5) ;DO WRITE WITH EXTENDED GAP FROM NOW ON
	BR	420$		;DO THE OPERATION
;									;TL068
325$:	BR	490$		;GO FINISH UP INT SERVICE		;TL068
;
; SPACE FILE FUNCTION
;

SPCFL:	BIT	#DS.TM,R1	;TAP      E MARK ENCOUNTERED?
	BNE	350$		;IF NE YES
	MOV	U.SPC(R5),2(R2)	;SOMETHING ELSE STOPPED US		;CS001
									;**-1
;
; SPACE BLOCK FUNCTION
;

SPCBK:	BIT	#DS.BOT,R1	;AT BOT?
	BNE	490$		;IF NE YES, NOT AN ERROR, BUT NEED STACK CLEAR
	BIT	#DS.TM,R1	;EOF?
	BEQ	340$		;IF EQ NO
	CALL	CHKEOV		;SEE IF AT END OF VOLUME
	BCC	410$		;IF CC NOT FOUND
	BR	360$		;POSITION TAPE AT EOV
340$:	BIT	#DS.BTE!DS.EOT,R1 ;BAD TAPE ERROR OR EOT?
	BNE	RDBLK		;IF NE YES - NOT RECOVERABLE
	BR	REWND		;FATAL

350$:	CALL      	CHKEOV		;DID TAPE REACH LOGICAL END OF VOLUME?
	BCC	370$		;IF CC NO, TRY NEXT FILE
360$:	CALL	BSPACE		;BACKSPACE THE TAPE
	CALL	@(SP)+		;WAIT FOR COMPLETION
	MOV	#IE.EOV&377,R0	;INFORM USER THAT EOV HAS BEEN DETECTED
	BIS	#M.AEOV,U.CW2(R5) ;SET STATUS BIT
	BR	380$		;FIX COUNT AND RETURN
370$:	INC	U.SPC(R5)	;ANOTHER TAPE MARK DETECTED		;CS001
	BNE	390$		;IF NE NOT DONE				;**-1
380$:	MOV	U.SPC(R5),2(R2)	;SET UP FINAL COUNT			;CS001
	MOV	S.PKT(R4),R3	;GET THE I/O PACKET ADDRESS		;TL067
	MOV	I.FCN(      R3),-(SP)	;GET THE FUNCTION CODE			;TL067
	BIC	#IQ.UMD!IQ.X,(SP)  ;CLEAR EXTRA BITS			;TL067
	CMP	#IO.SPB,(SP)+	;SPACE BLOCKS?				;TL067
	BNE	385$		;NO -- LEAVE STATUS ALONE		;TL067
	CLR	I.PRM+4(R3)	;CLEAR FOR STATUS RETURN		;TL067
	CLR	2(R2)		;...					;TL067
385$:	BR	490$		;RETURN TO USER				;**-1
390$:	BIS	#M.EOF,U.CW2(R5) ;I SAW AN EOF
	MOV	#1,2(R2)	;SET RECORD COUNT FOR SPACING
	MOV	2(R2),SPTBL(R3)	;SAVE RECORD COUNT
	ADD	#-CS.RDY+CS.GO+CS.IE,(R2)  ;REISSUE SPACING COMMAND
	CALL	@(SP)+		;WAIT       FOR COMPLETION
	BR	SPCFL		;SEE WHAT HAPPENED

;
; READ LOGICAL FUNCTION
;

RDBLK:	MOV	#IE.BBE&377,R0	;ASSUME BAD TAPE
	BIT	#DS.BTE,R1	;BAD TAPE?
	BNE	490$		;IF NE YES
	MOV	#IE.DAO&377,R0	;ASSUME RECORD LENGTH ERROR
	BIT	#DS.RLE,R1	;RECORD LTH ERROR?
	BNE	490$		;IF NE YES
410$:	MOV	#IE.EOF&377,R0	;TRY EOF
	BIT	#DS.TM,R1	;EOF DETECTED?
	BNE	490$		;IF NE YES
	MOV	#IS.SUC&377,R0	; EOT ON READ IS SUCCESS
	BIT	#DS.EOT,R1	;EOT?
	BNE	490$		;IF NE NO
	MOV	#IE.VER&377,R0	;ASSUME DATA ERROR
420$:	      MOV	R1,-(SP)	;SAVE R1
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	;RETRIES SUPPRESSED?
	BEQ	430$		;IF EQ NO
	MOV	(SP)+,R1	;RESTORE R1
	BR	490$		;AND EXIT
430$:	MOV	(SP)+,R1	;RESTORE R1 AND CONTINUE
	DECB	RTTBL(R3)	;ANY MORE RETRIES?
	BLE	490$		; IF LE NO
	MOV	INTADD(R3),U.SPC(R5) ;SAVE ORIGINAL ADDRESS		;CS001
	CALL	BSPACE		;BACKSPACE THE TAPE			;**-1
	CALL	@(SP)+		;WAIT FOR BACKSPACE
	MOV	U.SPC(R5),INTADD(R3) ;RESTORE INT ADDRESS		;CS001
	CLR	U.SPC(R5)	;RESET TO INDICATE NO      T SPACING FILE	;CS001
	TST	(SP)+		;CLEAN UP THE STACK			;**-2
	JMP	177$		;RETRY

;
; END OF INTERRUPT SERVICE ROUTINE PROCESSING
;

490$:	TST	(SP)+		;CLEAN UP THE STACK
500$:	MOV	R5,R3		;MAKE A COPY OF UCB BASE
	ADD	#U.CW2,R3	;COMPUTE OFFSET TO MAG TAPE STATUS
	MOV	(R3),-(SP)	;SAVE CURRENT STATUS
	BIC	#NEWBTS,(R3)	;CLEAR STATUS BITS TO BE DETERMINED
	BIT	#DS.BOT,R1	;AT BOT?
	BEQ	510$		;IF EQ NO
	BIS	#M.BOT,(R3)	;SET STATUS BIT
510$:	BIT	#DS.TM,R1	;TAPE MARK?
	BEQ	520$		;IF EQ NOT TAPE MARK      
	CMPB	(R2),#SPR+CS.RDY-CS.IE-CS.GO ;WAS THAT A BACKSPACE?
	BEQ	520$		;IF EQ YES - DON'T SET INTERNAL EOF BIT
	BIS	#M.EOF,(R3)	;SET STATUS BIT
520$:


	.IF DF  D$$IAG

	MOV	R1,-(SP)	;SAVE R1
	CALL	MTDINT		;PASS DIAGNOSTIC DEVICE REGISTERS
	MOV	(SP)+,R1	;RESTORE R1 AND CLEAN STACK

	.ENDC


	.IF DF	D$$IAG&E$$DVC

	BCS	530$		;

	.ENDC


	.IF DF	E$$DVC

	BIT	#DS.ILG!DS.CRE!DS.PAE!DS.BGL!DS.BTE,R1			;TL072
				; ANY ERRORS IN STATUS REG (MTS)?	;**-1
	BEQ	530$		; IF EQ THEN NO
	CALL	$D      VERR		; LOG DEVICE ERROR

	.ENDC


530$:				; REF LABEL
	CMPB	(R2),#RED+CS.RDY-CS.IE-CS.GO ;WAS THAT A READ?
	BEQ	539$		;YES IGNORE EOT
	BIT	#DS.EOT,R1	;EOT?
	BEQ	539$		;IF EQ NO
	TSTB	R0		;ALREADY RETURNING AN ERROR?		;**-2
	BMI	538$		;IF MI YES
535$:	MOV	#IE.EOT&377,R0	;SET FOR EOT STATUS
538$:	BIS	#M.EOT,(R3)	;REMEMBER EOT FOR NEXT COMMAND
	MOV	2(R2),-(SP)	;PRESERVE THE COUNT REGISTER
	BIS	#CS.CLR,@R2	;STOP THE DRIVE IF RUNNING AWAY
	MOV	(SP)+,2(R2)	;RESTORE THE COUNT REGISTER
539$:	TST	      (SP)+		;CLEAN STACK
540$:	MOV	S.PKT(R4),R1	;RETRIEVE ADDRESS OF I/O PACKET
	MOV	I.PRM+4(R1),R1	;GET ORIGINAL COUNT VALUE
	ADD	2(R2),R1	;FIX COUNT REMAINING


	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	; RETRIEVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	; GET FINAL RETRY COUNT
	BIS	#RETRY*256.,R2	; MERGE STARTING RETRY COUNT

	.ENDC


	CALL	$IODON		;FINISH I/O OPERATION
	JMP	MTINI		;GO AGAIN
	.DSABL	LSB

;
; THIS SUBROUTINE CHECKS FOR THE LOGICAL END-OF-VOLUME CONDITION
;
; RETURNS WITH CC IF NOT EO      V.
; RETURNS WITH CS IF EOV.
;

CHKEOV:	MOV	2(R2),-(SP)	;SAVE FRAME COUNT
	ADD	U.CNT(R5),(SP)	;GET NUMBER ACTUALLY SPACED
	CMP	(SP)+,#1	;EXACTLY ONE? (COUNT STARTED WITH 1)
	CLC			;ASSUME NOT EOV
	BNE	30$		;IF NE NO, NOT EOV


	.IF DF	A$$NSI

	BITB	#US.LAB,U.STS(R5) ;MOUNTED ANSII TAPE?
	BNE	30$		;IF NE YES - EXIT WITH CC

	.ENDC


	BIT	#2,(R2)		;FORWARD SPACE?
	BNE	30$		;IF NE NO - CANNOT BE EOV
	BIT	#M.EOF!M.BOT,U.CW2(R5) ;AT EOV?
	BEQ	30$		;IF EQ NO - EXIT WITH CC
	SEC			;EOV DETEC      TED
30$:	RETURN			;

;
; THIS SUBROUTINE ISSUES A COMMAND TO BACKSPACE ONE RECORD
;

BSPACE:	BISB	#US.BSP,U.STS(R5)  ;SET INTERNAL BACKSPACE IN PROGRESS
	MOV	#-1,2(R2)	;BACKSPACE ONE RECORD
	MOVB	#SPR,(R2)	;ISSUE BACKSPACE FUNCTION
	RETURN

;
; THIS ROUTINE ATTEMPTS TO SELECT A TAPE DRIVE.
; THE CURRENT STATUS OF THE DRIVE WITH REGARD TO 7CH,
; BOT, AND HWL IS SET AT THIS TIME.
;
; ON RETURN:	CC==>GOOD SELECT
;		CS==>BAD SELECT
;

SELECT:	CALL	DRVSTS		;GET TAPE UNIT STATUS			;CS001
	MO      VB	1(R2),U.BUF+1(R5) ;SET UP FOR COMMAND			;**-5
	MOV	-2(R2),-(SP)	;SAVE THE TAPE UNIT STATUS.		;CS001
	BIC	#<M.BOT!M.7CH!M.HWL!M.RWD!M.SER>,U.CW2(R5) ;CLEAR EXCESS;**-1
	SEC			;ASSUME SELECT ERROR
	BIT	#DS.MOL,(SP)	;DID DRIVE SELECT?
	BEQ	10$		;IF EQ NO - SELECT ERROR
	BIT	#DS.TUR!DS.RWS!DS.SDN,(SP) ;MAKE SURE DRIVE IS OK
	BNE	7$		;IF NE OK
	BIT	#RD.GAP,10(R2)	;LAST CHANCE
	BEQ	10$		;IF EQ VACUUM IS GONE - FATAL
7$:	BIT	#DS.TUR,(SP)	;TRUST BOT ?				;CS003
	BNE	8$		;IF NE, YES.				;CS003
	BIC	#D      S.BOT,(SP)	;MAY BE INTERMITTENT.			;CS003
8$:	SWAB	(SP)		;UNIT SELECTABLE. CARRY CLEARED.	;CS003
	BIC	#^C<M.BOT!M.7CH!M.HWL!M.RWD>,(SP) ;CLEAR EXTRA BITS	;**-1
	BIS	(SP),U.CW2(R5)	;
	BICB	#US.ABO,U.STS(R5) ;NOT ABORTING
10$:	INC	(SP)+		;CLEAN UP STACK WITHOUT AFFECTING CARRY	;**-1
	BCC	20$		;IF CC GOOD SELECT
	BIS	#M.SER,U.CW2(R5) ;SET SELECT ERROR BIT
20$:	RETURN			;


;+									;CS001
; SUBROUTINE SELECTS A TAPE UNIT AND TRIES TO OBTAIN TAPE UNIT STATUS.	;CS001
;									;CS001
; IF TAPE UN      IT READY, DETERMINE 7/9 TRACK STATUS AND UPDATE U.CW3 ACCORD;CS001
;-									;CS001
									;CS001
DRVSTS:	MOV	S.CSR(R4),R2	;R2=CSR.				;CS001
	MOVB	U.UNIT(R5),1(R2) ;SELECT TAPE UNIT			;CS001
	MOV	#50.,-(SP)	;INTERVAL TILL DEV REG RDY.		;CS001
5$:	DEC	(SP)		;INTERVAL OVER ?			;CS001
	BNE	5$		;IF NE, NO.				;CS001
	BIT	#DS.TUR,-2(R2)	;TAPE UNIT READY ?			;CS001
	BEQ	10$		;IF EQ, NO. BITS 0-5 NOT AVAILABLE.	;CS001
	MOVB	#UD.800,U.CW3(R5)  ;INDICATE (ONLY) 			;CS001
	MOVB	#UD.UNS,U.CW3+1(R5)  ;9T      RACK/800BPI. 			;CS001
	BIT	#DS.7CH,-2(R2)	;7 TRACK TAPE UNIT?			;CS001
	BEQ	10$		;IF EQ, NO.				;CS001
	MOVB	#UD.200,U.CW3(R5)  ;INDICATE 7 TRACK,			;CS001
	MOVB	#UD.800,U.CW3+1(R5)  ;200 TO 800BPI SUPPORT.		;CS001
10$:	TST	(SP)+		;RETURN STACK AS FOUND.			;CS001
	RETURN								;CS001
									;CS001
									;CS001
	.IF DF  D$$IAG

;+
; **-MTDINT-TM11 DIAGNOSTIC INTERRUPT AND TIMEOUT HANDLER
;
; IF ENTRY WAS FROM A DIAGNOSTIC CONTROL FUNCTION THEN MOVE I/O
; PACKET WORDS 17-20 TO WORDS 20-2      1 FOR $CRPAS ROUTINE.
; FOR ANY DIAGNOSTIC FUNCTION PASS THE UNIBUS DEVICE REGISTERS VIA
; THE $CRPAS ROUTINE.
;
; INPUTS
;	R2= CSR ADDRESS
;	R4= SCB ADDRESS
;
; OUTPUTS
;	R1= IO PACKET ADDRESS
;-

MTDINT:	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	CLC			;
	BITB	#IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL?
	BEQ	4$			;IF EQ NO
	MOV	R1,-(SP)	;SAVE IO PACKET ADDRESS
	CMPB	#IO.EOF/256.,I.FCN+1(R1) ;WRITE EOF FUNCTION?
	BEQ	1$			;IF EQ YES
	CMPB	#IO.RWD/256.,I.FCN+1(R1) ;CNTRL FUNCT.OTHER THAN       IO.EOF?
	BEQ	1$			;IF EQ YES
	CALL	$CRPAS		;PASS DEVICE REGISTERS TO DIAGNOSTIC
	MOV	(SP)+,R1	;RESTORE IO PACKET ADDRESS
	BR	3$		;RETURN
1$:	MOV	I.PRM+14(R1),I.PRM+16(R1) ;MOVE WD20 TO WD21
	MOV	I.PRM+12(R1),I.PRM+14(R1) ;MOVE WD17 TO WD20
2$:	CALL	$CRPAS		;PASS DEVICE REGISTERS TO DIAGNOSTIC
	MOV	(SP)+,R1	;RESTORE IO PACKET ADDRESS
	MOV	I.PRM+14(R1),I.PRM+12(R1) ;MOVE WD20 BACK TO WD17
	MOV	I.PRM+16(R1),I.PRM+14(R1) ;MOVE WD21 BACK TO WD20
3$:	BIC	#RD.LPC,10(R2)	;CLEAR LPC MODE BIT IN MTRD REG.   N   
	SEC			;SET DIAGNOSTIC FUNCTION CALL RETURN
4$:	RETURN

	.ENDC

	.END
 N          dYðskQ	› c,        	.TITLE	NLDRV
	.IDENT	/03/
 
;
; COPYRIGHT (C) 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 03
;
; E. L. BAATZ 22-JUL-76
;
; NULL DEVICE DRIVER.
;
; MACRO LIBRARY CALLS
;
; EQUATED SYMBOLS
;
; LOCAL DATA
;
; NO CONTROLLER IMPURE DATA TABLES (THERE IS NO DEVICE TO
;	CAUSE INTERRUPTS)
;
; DRIVER DISPATCH TABLE
;
$NLTBL::
	.WORD	NLINI		;IN      ITIATION
	.WORD	$INTXT		;CANCEL ($INTXT IS A "RETURN")
	.WORD	$INTXT		;TIMEOUT
	.WORD	$INTXT		;POWERFAIL
;+
; NLDRV AND DRQIO IMPLEMENT A DEVICE NL:, WHICH ACTS AS
;   1)	A SINK FOR ALL INFORMATION SEND TO IT (IO.WLB)
;   2)	A SOURCE FOR AN INFINITE NUMBER OF END OF FILES (IO.RLB)
;   3)	A SOURCE FOR AN INFINITE NUMBER OF NULL RECORDS (IO.RLB)
;	IF "IE.EOF" IS CHANGED TO "IS.SUC"
;-
;
; DRQIO (BECAUSE THE UC.QUE BIT IS SET IN THE UCB) SETS THE REGISTERS
; TO THE FOLLOWING:
;
;	R1 = ADDRESS OF       I/O PACKET
;	R4 = ADDRESS OF SCB
;	R5 = ADDRESS OF UCB
;
; ONLY TWO FIELDS OF AN I/O PACKET MATTER
;	I.FCN+1 = THE I/O FUNCTION CODE.  ONLY IO.WLB
;		  AND IO.RLB MAKE IT TO NLDRV
;	I.PRM+4 = IF I.FCN+1 IS IO.WLB, THIS IS THE 
;		  NUMBER OF BYTES THE CALLER WANTS TO WRITE
;
NLINI:	MOV	R1,R3		;POINT AT PACKET FOR $IOFIN
	MOV	#IS.SUC&377,R0	;A WRITE ALWAYS SUCCEEDS
	MOV	I.PRM+4(R1),R1	;SAY EVERYTHING WAS WRITTEN
	CMPB	#IO.WLB/400,I.FCN+1(R3) ;WANTS TO WRITE?
	BEQ	10$		;IF EQ YES
	MOV	#IE.EOF&   f   377,R0	;IT IS A READ
	CLR	R1		;READ NO CHARACTERS
10$:	CALLR	$IOFIN		;FINISH OFF PACKET
 
	.END
 f          ¤ZðskQ	› c,        	.TITLE	NTDRV
	.IDENT	/03/
 
;
; COPYRIGHT (C) 1974, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 03
;
; J. M. GILBERT	9-MAY-75
;
; LG005 - MODIFIED 8-SEP-76 FOR LOADABLE DRIVER SUPPORT
;
; RSX-11M NETWORK DEVICE DRIVER
;
; MACRO LIBRARY CALLS
;
	.MCALL	PKTDF$,DEVDF$
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	DEVDF$			;DEFINE DEVICE TABLE OFFSETS      
	.MCALL	PCBDF$
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
;
; DRIVER DISPATCH TABLE
;
 
 
	.IF DF	M$$NET
 
$NTTBL::.WORD	NTINIT		;INITIALIZATION
	.WORD	NTCANC		;I/O CANCELLATION
	.WORD	NTTMO		;TIMEOUT
	.WORD	NTPWRF		;POWER FAIL
	.WORD	NTRCV		;UNSOLICITED RECEIVE ENTRY
	.WORD	NTRXER		;RECEIVER ERROR CLEAR
 
;+
;**- NTINIT - NT DEVICE SERVICE.  PROVIDED SO
; THAT STAND-ALONE TESTING OF NETWORKS CAN TAKE PLACE
; ON A SYSTEM WITHOUT NETWORK COMMUNICATION DEVICES.
; PRIMARY FUNCTION O      F INITIATOR IS TO CALL $GTPKT, FORCING
; DISPATCH OF PACKET TO ACP.  ONLY ACP FUNCTIONS ARE
; LEGAL ON THIS DEVICE.  HOWEVER, THE FUNCTION IO.LOV IS ALSO
; ACCEPTED AND IS MAPPED INTO A FUNCTION CODE 30.  THE PACKET
; IS THEN REQUEUED TO NT:;  HOWEVER, NOW THAT THE FUNCTION IS
; AN ACP FUNCTION, THE PACKET IS QUEUED TO THE ACP.
;
;	INPUTS:
;
;		R1 = PACKET ADDRESS
;		R4 = STATUS CONTROL BLOCK ADDRESS
;		R5 = ADDRESS OF THE UCB OF THE NT DEVICES
;
;	OUTPUTS:
;
;		THE PACKET WILL BE QUEUED TO T      HE ACP.
;-
 
NTINIT:	CALL	$GTPKT		;QUEUE PACKET TO ACP
	BCS	10$		;IF CS, NO PACKETS
;
; R1 NOW CONTAINS PACKET ADDRESS
; R5 CONTAINS UCB ADDRESS
; FUNCTION MUST BE IO.RLB,
; SPECIFICALLY IO.LOV
;
	CLRB	S.STS(R4)	;CLEAR CONTROLLER STATUS
	BICB	#US.BSY,U.STS(R5) ;MARK UNIT IDLE
	MOV	#30*256.,I.FCN(R1) ;SET FUNCTION TO 30
	CALL	$DRQRQ		;QUEUE PACKET TO ACP
 
10$:				;REFERENCE LABEL
 
;+
;**- NTCANC,NTTMO,NTPWRF,NTRCV,NTRXER ARE ALL
; NO-OP'D, SINCE THIS IS A LOGICAL DEVICE.
;-
 
NTCANC:      				;I/O CANCELLATION
NTTMO:	 			;DEVICE TIMEOUT
NTPWRF:				;POWER FAILURE
NTRCV:				;RECEIVE INITIATION
NTRXER:				;RECEIVER RESET
	RETURN
 
	.IF	DF	M$$MGE&L$$DRV
 
;+
; **-$MLDC-MAP LOADABLE DRIVER TO APR5 AND CALL DRIVER
; **-$MLDCS-ENTRY POINT IF ALREADY ON SYSTEM STACK
;
; INPUTS:
;	R0=DISPLACEMENT IN DISPATCH TABLE OF ENTRY POINT
;	R5=UCB ADDRESS
;
; OUTPUTS:
;	DRIVER CALLED WITH ALL REGISTERS EXCEPT R0 UNCHANGED
;	R0=DESTROYED
;-
$MLDC::	SWSTK$	EXIT		;GO TO SYSTEM STATE
$MLDCS::   ¦  MOV	KISAR5,-(SP)	;SAVE APR5
	MOV	R0,-(SP)	;DISPATCH TABLE DISPLACEMENT
	MOV	(R5),R0		;DCB ADDRESS
	ADD	D.DSP(R0),(SP)	;DISPATCH TABLE ADDRESS
	MOV	D.PCB(R0),R0	;DRIVER PCB ADDRESS
	BEQ	10$		;IF EQ, DRIVER IS PART OF EXEC
	MOV	P.REL(R0),KISAR5 ;MAP THE DRIVER
10$:	MOV	@(SP)+,R0	;DRIVER ENTRY POINT
	CALL	(R0)		;CALL THE DRIVER
	MOV	(SP)+,KISAR5	;RESTORE APR5
EXIT:	RETURN
 
	.ENDC
 
	.ENDC
 
 
 
	.END
 ¦         y:à~kQ	› c,        	.TITLE	INITL
	.IDENT	/14.29/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 14.29
;
; D. N. CUTLER 23-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	B. SCHREIBER
;	C. SPITZ
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	18-JUL-79
;		MSH044 -- HANDLE SYSTEM CLOCK WITH NO CSR.
;			        ALSO, CLEAN UP UNNECESSARY CODE.
;
;	M. S. HARVEY	25-OCT-79
;		MSH045 -- DIRECTIVE COMMON VALIDATION CHECKS
;
;	M. S. HARVEY	19-DEC-79
;		MSH043 -- UPDATE RSX VERSION NUMBERS
;
;	P. J. BEZEREDI 19-AUG-80
;		PB175 -- ADD SUPPORT FOR EXTENDED INSTRUCTION SET.
;
;	M. S. HARVEY	20-AUG-80
;		MSH112 -- USE $TRINT TO TRAP ILLEGAL INSTRUCTIONS
;
;	M. S. HARVEY	25-AUG-80
;		MSH097 -- ADD SUPPORT FOR 22-BIT SYSTEMS WITHOUT
;			  AN I/O MAP
;
;	M. S. HARVEY	17-OCT-80
;		MSH123 -- INITIALIZE TICKS P      ER SECOND PARAMETER IN
;			  SET SYSTEM TIME VALIDATION TABLE
;
;	M. S. HARVEY	12-FEB-81
;		MSH149 -- DETERMINE THE EXISTENCE OF THE FLOATING
;			  POINT PROCESSOR
;
;	M. S. HARVEY	5-MAR-81
;		MSH142 -- INITIALIZE THE POOL MONITOR CONTROL WORDS
;
;		MSH156 -- INITIALIZE THE WATCHDOG TIMER CSR POINTER
;
;	M. S. HARVEY	31-MAR-81
;		MSH161 -- FOR RSX-11S ONLY, ALLOW LAST PARTITION TO
;			  ENCOMPASS REMAINDER OF MEMORY IF SYSTEM
;			  CONTROLLED
;
;	M. S. HARVEY	1-MAY-81
;		MSH165 -- ADD SUPP      ORT FOR SECOND DIRECTIVE COMMON
;
;	M. S. HARVEY	29-MAY-81
;		MSH171 -- FOR RSX-11S ONLY, INITIALIZE MEMORY
;			  ABOVE $SYSIZ AND CLEAN UP COMMENTS
;
;	M. S. HARVEY	16-JUL-81
;		MSH179 -- CLEAN UP THE EIS TESTING CODE
;
;	M. S. HARVEY	21-JUL-81
;		MSH181 -- HANDLE POSSIBLE T-BIT TRAP AFTER POWER UP
;			  ON PDP 11/02 PROCESSORS
;
;	M. S. HARVEY	5-NOV-81
;		MSH201 -- ENHANCE PARITY CSR DETECTION FOR ERROR LOGGING
;
;	M. S. HARVEY	28-DEC-81
;		MSH208 -- CORRECTLY SIZE MEMORY ON Q22-BUS SYSTE      MS
;
;		MSH209 -- FORCE RLV12 TO USE BAE REGISTER IF NECESSARY
;
;
; SYSTEM START UP AND INITIALIZATION ROUTINE
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS

;
; LOCAL DATA
;
; SYSTEM IDENTIFICATION MESSAGES
;
;
; MAKE SURE THAT INITL TASK BUILDS AS THE LAST MODULE IN THE EXEC
;
	.PSECT	......


$POOL::				;START OF POOL


	.IF NDF	R$$11S

SYSMG:	.ASCII	<15><12>/RSX11M V4.0 BL/				;MSH043
									;**-1
	.IFF

SYSMG:	.ASCII	<15><12>/RSX11S V      4.0 BL/				;MSH043
									;**-1
	.ENDC


SYSID:	.ASCIZ	/XXXX/<15><12><12> ;
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
NDCOM:	.ASCII	<15><177><177><12>/ MISSING EXECUTIVE COMMON(S)/	;MSH045
	.ASCIZ	<15><12>						;MSH045
									;MSH045
	.ENDC								;MSH045
									;MSH045
	.IF DF	M$$EIS							; PB175
									; PB175
NOEIS:	.ASCII	<15><177><177><12>/ PROCESSOR DOES NOT SUPPORT EIS/	; PB175
	.ASCIZ	<15><12>						; PB175
									; PB175
	.ENDC								; PB175
					      				; PB175
DEVMG:	.ASCIZ	<15><177><177><12>/ DEVICE DDUU: NOT IN CONFIGURATION/<15> ;
PROMT:	.ASCIZ	<15><12>/>/	;
	.EVEN

;+
; **-$INITL-SYSTEM TRANSFER ADDRESS
;
; THIS ROUTINE CONTAINS THE TRANSFER POINT OF THE RESIDENT EXECUTIVE. WHEN
; THE SYSTEM IS BOOTED, CONTROL IS TRANSFERED HERE TO INITIALIZE AND START
; UP THE SYSTEM
;-

$INITL::RESET			;RESET PROCESSOR
									;MSH181
	.IF NDF	X$$DBT							;MSH181
	.IF DF	L$$SI1							;MSH181
									;MSH181
	MOV	#$TRACE,@#14	;SET THE BPT/T-B      IT (TRACE) VECTOR	;MSH181
									;MSH181
	.ENDC								;MSH181
	.ENDC								;MSH181
									;MSH181
	MOV	#$SYSIZ+2,R0	;POINT TO SYSTEM CONFIGURATION VECTOR
	MOVB	R3,(R0)+	;SAVE UNIT NUMBER
	MOVB	R1,(R0)+	;SAVE LBN OF LOAD IMAGE
	MOV	R2,(R0)+	;
	MOV	R4,(R0)+	;SAVE DEVICE NAME
	MOV	R5,(R0)+	;SAVE LENGTH OF LOAD FILE


	.IF DF	M$$MGE

	MOV	#PMODE+PR7,PS	;SET MODE BITS AND LOCK OUT INTERRUPTS
	MOV	#$STACK-20,SP	;SETUP EXEC STACK POINTER
	MOV	#KISAR0,R0	;POINT TO KERNEL PAR 0
	MOV	#KISDR0,R      1	;POINT TO KERNEL PDR 0
	MOV	#UISAR0,R2	;POINT TO USER PAR 0
	MOV	#UISDR0,R3	;POINT TO USER PDR 0
	MOV	#8.,R4		;SET LOOP COUNT
	CLR	R5		;START AT BOTTOM OF MEMORY
10$:	MOV	R5,(R0)+	;SET KERNEL AND USER RELOCATION BIAS
	MOV	R5,(R2)+	;
	MOV	#77406,(R1)	;SET KERNEL AND USER DESCRIPTOR  REGISTERS
	MOV	(R1)+,(R3)+	;
	ADD	#200,R5		;ADVANCE TO NEXT 4K BLOCK
	DEC	R4		;ANY MORE REGISTERS TO LOAD?
	BGT	10$		;IF GT YES
	MOV	#177600,-(R0)	;SET KERNEL PAR 7 TO I/O PAGE
	INC	SR0		;AND AWAY WE GO

	.IFF			      					;MSH097
									;MSH097
	MTPS	#PR7		;LOCK OUT INTERRUPTS			;MSH097
	MOV	#$STACK-10,SP	;SETUP EXEC STACK POINTER		;MSH097
									;MSH097
	.IFTF								;MSH097
									;MSH097
	MOV	#$DIRXT,-(SP)	;SET UP RETURN FOR $SGFIN		;MSH097
	CALL	$SGFIN		;TRAP NON-EXISTENT MEMORY		;MSH097
									;MSH097
	.IFT								;MSH097

	.IF DF	M$$EXT

	MOV	#UBMPR,R0	;POINT TO FIRST UNIBUS MAPPING REG
	TST	(R0)		;DOES I/O MAP EXIST?			;MSH097
	BCS	12$		;IF CS NO, DON'T INITIALIZE MAP		;MSH097
	CLR	R1		;S      ET INITIAL ADDRESS TO ZERO
	MOV	#5.,R2		;SET NUMBER OF REGISTER PAIRS TO LOAD
11$:	MOV	R1,(R0)+	;LOAD LOW 16 BITS OF ADDRESS
	CLR	(R0)+		;CLEAR HIGH 6 BITS OF ADDRESS
	ADD	#20000,R1	;ADVANCE 8K BYTES
	DEC	R2		;ANY MORE TO LOAD?
	BGT	11$		;IF GT YES
	BR	125$		;JOIN COMMON CODE			;MSH097
12$:	CLR	$UMRPT		;INDICATE NO I/O MAP IN THIS SYSTEM	;MSH097
125$:	MOV	#60,SR3		;ENABLE 22 BIT ADDRESSING AND UB MAP	;MSH097
									;**-1
	.ENDC

	.IFTF								;**-6

;									;MSH097
; THIS SECTION SIZES M      EMORY FOR THE SYSTEM. IF THIS IS AN RSX-11S	;MSH097
; SYSTEM, THEN ALL MEMORY ABOVE $SYSIZ MUST BE INITIALIZED.		;MSH097
;									;MSH097
									;MSH097
	MOV	#$SYSID,R0	;POINT TO SYSTEM IDENTIFICATION		;**-2
	MOV	#SYSID,R1	;POINT TO IDENTIFICATION MESSAGE
	MOVB	(R0)+,(R1)+	;MOVE SYSTEM IDENTIFICATION INTO MESSAGE
	MOVB	(R0)+,(R1)+	;
	MOVB	(R0)+,(R1)+	;
	MOVB	(R0),(R1)	;
	JSR	R5,OPMSG	;TELL EVERYBODY WE'RE ON THE AIR
	.WORD	SYSMG		;
									;MSH208
	CLR	R1		;ZERO NUMBER OF 32W BLOCKS IN SYST      EM	;MSH208

	.IFT

	MOV	#140000,R0	;SET INITIAL MEMORY ADDRESS
	MOV	#KISAR6,R4	;LOAD KERNEL APR6 ADDRESS		;MSH171
									;MSH208
	.IF DF	M$$EXT							;MSH208
									;MSH208
	MOV	#10000,(R4)	;POINT TO 128K				;MSH208
	MOV	(R1),-(SP)	;SAVE CONTENTS OF LOCATION ZERO		;MSH208
	MOV	SP,(R1)		;MOVE NONZERO VALUE INTO LOC ZERO	;MSH208
	MOV	#0,(R0)		;ATTEMPT TO ACCESS WORD AT 128K		;MSH208
	TST	(R1)		;ADDRESS WRAPAROUND TO LOCATION ZERO?	;MSH208
	BNE	127$		;IF NE NO, SYSTEM HAS MORE THAN 128KW	;MSH      208
	MOV	#10000,16$	;SET UPPER LIMIT TO 128KW		;MSH208
127$:	MOV	(SP)+,(R1)	;RESTORE CONTENTS OF LOCATION ZERO	;MSH208
									;MSH208
	.ENDC								;MSH208
									;MSH208
	CLR	(R4)		;SET ZERO RELOCATION BIAS		;MSH171
									;MSH171
	.IF DF	R$$11S							;MSH171
									;MSH171
	MOV	$SYSIZ,R5	;GET TOP OF INITIALIZED MEMORY		;MSH171
									;MSH171
	.ENDC								;MSH171
									;**-1
	.IFF

	CLR	R0		;SET INITIAL MEMORY ADDRESS

	.IFTF

13$:	TST	(R0)		;MEMORY EXIST?				;**-1
	BCS	1      7$		;IF CS NO
	ADD	#40,R1		;UPDATE NUMBER OF 32W BLOCKS

	.IFT

	.IF DF	R$$11S							;MSH171
									;MSH171
	CMP	R1,R5		;HIGHER THAN LAST INITIALIZED MEMORY?	;MSH171
	BLOS	15$		;IF LOS NO, NO NEED TO CLEAR MEMORY	;MSH171
	MOV	R1,R3		;GET TOP OF CURRENT 1K SEGMENT		;MSH171
	SUB	R5,R3		;GET SIZE OF MEMORY TO BE CLEARED	;MSH171
	SWAB	R3		;CONVERT TO WORD COUNT			;MSH171
	ASR	R3		;					;MSH171
	ASR	R3		;					;MSH171
	ASR	R3		;					;MSH171
	MOV	R5,(R4)		;POINT TO SEGMENT TO BE CLEARED		;MSH171
      	MOV	R0,R2		;SET SCRATCH POINTER			;MSH171
14$:	MOV	#0,(R2)+	;INIT MEMORY (NOTE-CLR CAN'T BE USED)	;MSH171
	DEC	R3		;DONE WITH THIS SEGMENT YET?		;MSH171
	BNE	14$		;IF NE NO, CLEAR MORE MEMORY		;MSH171
	MOV	R1,R5		;SET TOP OF INITIALIZED MEMORY		;MSH171
									;MSH171
	.ENDC								;MSH171
									;MSH171
15$:	MOV	R1,(R4)		;POINT TO NEXT 1K BLOCK OF MEMORY	;MSH171
									;MSH171
	.IF DF	M$$EXT							;**-3

	CMP	(R4),(PC)+	;END OF MEMORY?				;MSH208
16$:	.WORD	170000		;ASSUME UPPER LIMIT TO       BE 2MW		;MSH208
									;**-1
	.IFF

	CMP	(R4),#7600	;END OF MEMORY?				;MSH171
									;**-1
	.ENDC
									;**-1
	BLO	13$		;IF LO NO

	.IFF

	ADD	#4000,R0	;UPDATE MEMORY ADDRESS BY 1K
	CMP	R0,#160000	;END OF MEMORY?
	BLO	13$		;IF LO NO

	.IFTF

17$:	MOV	R1,$SYSIZ	;SET SIZE OF MEMORY IN 32W BLOCKS
									;MSH161
;									;MSH161
; IF THE LAST PARTITION IN AN RSX-11S SYSTEM IS DYNAMIC, EXTEND ITS	;MSH161
; SIZE TO THE END OF MEMORY.						;MSH161
;									;MSH161
									;MSH      161
	.IFT	;M$$MGE							;MSH161
									;MSH161
	.IF DF	R$$11S&D$$YNM						;MSH161
									;MSH161
	MOV	#$PARHD,R0	;PICK UP PCB LIST HEAD			;MSH161
173$:	MOV	(R0),R2		;GET ADDRESS OF NEXT PCB		;MSH161
	BEQ	177$		;IF EQ END OF LIST			;MSH161
									;MSH161
	.IF DF	M$$EXT							;MSH161
									;MSH161
	CMP	P.REL(R2),#177600 ;IS IT A DEVICE PARTITION PCB?	;MSH161
									;MSH161
	.IFF								;MSH161
									;MSH161
	CMP	P.REL(R2),#7600	;IS IT A DEVICE PARTITION PCB?		;MSH161
									;MS      H161
	.ENDC								;MSH161
									;MSH161
	BHIS	177$		;IF HIS YES, LAST REAL PAR FOUND	;MSH161
	MOV	R2,R0		;GET NEXT PCB IN LIST			;MSH161
	BR	173$		;					;MSH161
									;MSH161
177$:	BIT	#PS.SYS,P.STAT(R0) ;SYSTEM CONTROLLED PARTITION?	;MSH161
	BEQ	179$		;IF EQ NO				;MSH161
	MOV	R1,R2		;COPY SYSTEM SIZE IN 32-WORD BLOCKS	;MSH161
	SUB	P.REL(R0),R2	;COMPUTE SIZE OF LAST PARTITION		;MSH161
	MOV	R2,P.SIZE(R0)	;AND SET IT				;MSH161
179$:									;MSH161
									;MSH161
	.ENDC								;MSH161      

	MOV	#1400,(R4)	;RESET MAPPING RELOCATION BIAS		;MSH171
									;MSH045
;									;MSH045
; VERIFY THE EXISTENCE OF THE EXTERNAL EXECUTIVE COMMONS. IF NOT	;MSH045
; THERE, THEN OBVIOUSLY THE SYSTEM WILL NOT RUN.			;MSH045
;									;MSH045
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
18$:	MOV	$XCOM1,R0	;GET FIRST EXEC COMMON OFFSET		;MSH045
	BNE	19$		;IF NE POINTER IS LOADED		;MSH045
181$:	JSR	R5,OPMSG	;ERROR - MISSING EXECUTIVE COMMON	;MSH045
	.WORD	NDCOM							;MSH045
	      								;MSH045
	.IF DF	X$$DBT							;MSH045
									;MSH045
	BPT			;TRAP TO XDT				;MSH045
									;MSH045
	.IFF								;MSH045
									;MSH045
	HALT			;HALT THE BOOT PROCESS			;MSH045
									;MSH045
	.ENDC								;MSH045
									;MSH045
	BR	181$		;NO MORE EXECUTION ALLOWED!		;MSH045
									;MSH045
19$:	CALL	PARCK		;GO VALIDATE THE COMMON'S OFFSET	;MSH165
	BCS	181$		;IF CS INVALID POINTER			;MSH165
	MOV	$XCOM2,R0	;GET SECOND EXEC COMMON OFFSET		;MSH165
	BEQ	181$		;IF EQ NOT THERE			      ;MSH165
	CALL	PARCK		;GO VALIDATE THE COMMON'S OFFSET	;MSH165
	BCS	181$		;IF CS INVALID POINTER			;MSH165
									;MSH165
	.ENDC								;MSH045
									;**-3
	.ENDC


;									;MSH149
; DETECT WHETHER OR NOT THE FLOATING POINT PROCESSOR IS PRESENT.	;MSH149
; ALSO, DETECT WHETHER OR NOT EIS IS PRESENT. IF NOT AND IT IS		;MSH149
; SUPPORTED, THE SYSTEM CANNOT RUN.					;MSH149
;									;MSH149
									;MSH149
	.IF DF	F$$LPP!M$$EIS						;MSH149
									; PB175
	MOV	@#10,-(SP)	;SAVE ILLEGA      L INSTR. VECTOR		; PB175
	MOV	#$TRINT,@#10	;PLUG VECTOR WITH TRAP ADDRESS		;MSH112
									;MSH149
	.IF DF	F$$LPP							;MSH149
									;MSH149
	CLC			;MAKE SURE CARRY IS CLEAR		;MSH149
	SETI			;ISSUE A FLOATING POINT INSTRUCTON	;MSH149
	BCS	193$		;IF CS, NO FLOATING POINT PROCESSOR	;MSH149
	BIC	#HF.FPP,$HFMSK	;SHOW FPP PRESENT			;MSH149
193$:									;MSH149
	.ENDC								;MSH149
									;MSH149
	.IF DF	M$$EIS							;MSH149
									;MSH149
	CLR	R0		;SET UP NULL SHIFT, CLR'S C ON SUCCESS	;      MSH179
	ASH	R0,R0		;EXECUTE AN EIS INSTRUCTION		;MSH179
	BCC	195$		;IF CC THE ASH WORKED, SO EIS IS HERE	;MSH179
	JSR	R5,OPMSG	;ERROR - NO EIS ON THIS CPU		; PB175
	.WORD	NOEIS		;					; PB175
	HALT			;STOP RIGHT HERE			; PB175
	BR	.-2		;GO NO FURTHER!!			; PB175
									;MSH149
	.ENDC								;MSH149
									;MSH149
195$:	MOV	(SP)+,@#10	;RESTORE ILLEGAL INSTR. VECTOR		; PB175
									; PB175
	.ENDC								; PB175
									; PB175
;									; PB175
; MAKE SURE THAT ALL SELECTED DEVICES ARE O      NLINE.			; PB175
;									; PB175
									; PB175
	MOV	#$DEVHD,R5	;GET ADDRESS OF FIRST DCB ADDRESS
20$:	MOV	(R5),R5		;GET ADDRESS OF NEXT DCB
	BEQ	80$		;IF EQ NO MORE TO SCAN
	MOV	D.UCB(R5),R4	;POINT TO FIRST UCB
	BIT	#DV.PSE,U.CW1(R4) ;PSEUDO DEVICE?
	BNE	20$		;IF NE YES
	MOVB	D.UNIT(R5),-(SP) ;SET STARTING LOGICAL UNIT NUMBER
	MOVB	D.UNIT+1(R5),-(SP) ;CALCULATE NUMBER OF UCB'S TO SCAN
	SUB	D.UNIT(R5),(SP)	;
	INCB	(SP)		;
40$:	CMP	$SYSIZ+6,D.NAM(R5) ;DEVICE NAMES MATCH?			;**-5
	BNE	45$		;      IF NE NO
	CMPB	$SYSIZ+2,2(SP)	;UNIT NUMBERS MATCH?
	BNE	45$		;IF NE NO
	MOV	R4,.SY0+2	;REDIRECT SYSTEM DEVICE
	MOV	R4,.LB0+2	;REDIRECT LB: AS WELL
45$:	MOV	U.SCB(R4),R2	;GET ADDRESS OF SCB
	TSTB	@S.CSR(R2)	;DEVICE IN SYSTEM?			;**-1
	BCC	60$		;IF CC YES
	BISB	#US.OFL,U.ST2(R4) ;SET DEVICE OFFLINE
	MOVB	D.NAM(R5),DEVMG+12. ;INSERT GENERIC DEVICE NAME
	MOVB	D.NAM+1(R5),DEVMG+13. ;
	MOV	R4,R0		;COPY ADDRESS OF UCB
	CLR	R0		;GET LOGICAL UNIT NUMBER		;MSH044
	BISB	2(SP),R0	;					;MSH044
	MOV	#8.,R1      		;SET DIVISOR				;**-5
	CALL	$DIV		;CONVERT UNIT NUMBER TO 2 DIGITS
	ADD	#'0,R0		;ADD CHARACTER BIAS
	ADD	#'0,R1		;ADD CHARACTER BIAS
	MOVB	R0,DEVMG+14.	;INSERT DEVICE UNIT NUMBER
	MOVB	R1,DEVMG+15.	;
	JSR	R5,OPMSG	;OUTPUT DEVICE MESSAGE
	.WORD	DEVMG		;
60$:				;					;MSH209
									;MSH209
	.IF DF	M$$EXT&R$$L11						;MSH209
									;MSH209
	CMP	#"DL,D.NAM(R5)	;'DL' DEVICE?				;MSH209
	BNE	65$		;IF NE NO				;MSH209
	BIC	#DV.EXT,U.CW1(R4) ;ASSUME DRIVER MUST USE UNIBUS MAP	;MSH209
	TST	$UMR      PT		;Q22-BUS MACHINE?			;MSH209
	BNE	65$		;IF NE NO, UNIBUS MAP EXISTS		;MSH209
	BIS	#DV.EXT,U.CW1(R4) ;FORCE DRIVER TO ACCESS BAE REGISTER	;MSH209
									;MSH209
	.ENDC								;MSH209
									;MSH209
65$:	ADD	D.UCBL(R5),R4	;CALCULATE ADDRESS OF NEXT UCB		;MSH209
	INCB	2(SP)		;UPDATE LOGICAL UNIT NUMBER		;MSH044
	DECB	(SP)		;ANY MORE UCB'S TO SCAN?		;MSH044
	BNE	40$		;IF NE YES				;MSH044
	CMP	(SP)+,(SP)+	;CLEAN STACK				;MSH044
	BR	20$		;LOOK AT NEXT DCB			;MSH044
80$:				;REF LABEL				;**-2      

;									;MSH156
; VERIFY THE PRESENCE OF THE WATCHDOG TIMER. IF NOT THERE, DISABLE	;MSH156
; ACCESS TO IT.								;MSH156
;									;MSH156
									;MSH156
	.IF DF	K$$W11							;MSH156
									;MSH156
	MOV	#K$$W11,R0	;GET THE WATCHDOG TIMER CSR ADDRESS	;MSH156
	TST	(R0)		;DOES THE WATCHDOG TIMER EXIST?		;MSH156
	BCS	85$		;IF CS NO				;MSH156
	MOV	R0,$WTCSR	;SET WATCHDOG TIMER CSR POINTER		;MSH156
85$:									;MSH156
	.ENDC								;MSH156
									;MSH156
;									;MSH201
; INITIALIZ      E THE PARITY MEMORY CONTROL STRUCTURE.			;MSH201
;									;MSH201

	.IF DF	P$$RTY

	MOV	#$PARTB,R0	;GET ADDRESS OF PARITY CSR ADDRESS TABLE
	MOV	R0,R1		;COPY ADDRESS OF TABLE
	MOV	#1,(R1)+	;INSERT A ONE IN FIRST TABLE ENTRY
	MOV	(R0),R5		;INIT CSR MASK BIT			;MSH201
	MOV	R0,R4		;COPY ADDRESS OF TABLE			;MSH201
	TST	-(R4)		;POINT TO PARITY CSR MASK WORD		;MSH201
	MOV	#MPAR-2,R2	;GET ADDRESS OF FIRST PARITY REGISTER-2
	MOV	#16.,R3		;SET NUMBER OF PARITY REGISTERS
90$:	ADD	#2,R2		;ADVANCE TO NEXT       PARITY CSR REGISTER
	MOV	R2,(R1)+	;ASSUME PARITY REGISTER PRESENT
	TST	(R2)		;PARITY CSR REGISTER PRESENT?
	BCC	100$		;IF CC YES
	MOV	R0,-2(R1)	;POINT TO FIRST WORD OF TABLE
	BIC	R5,(R4)		;MARK THIS CSR AS MISSING		;MSH201
100$:	ASL	R5		;ADVANCE MASK BIT			;MSH201
	DEC	R3		;ANY MORE TO SCAN?			;MSH201
	BGT	90$		;IF GT YES				;**-1
	MOV	(R1),R1		;11/70 CACHE PARITY CSR SEARCH DONE?
	BEQ	105$		;IF EQ YES
	MOV	(R0),R5		;INIT CACHE CSR MASK BIT		;MSH201
	TST	-(R4)		;POINT TO CACHE CSR MASK WORD		;M      SH201
	MOV	#MPCSR-10,R2	;POINT TO FIRST CSR ADDRESS - 2
	MOV	#6,R3		;SET COUNT OF REGISTERS
	BR	90$		;SEARCH FOR THEM
105$:				;REF LABEL

	.ENDC

;									;MSH171
; MAKE SURE THAT THE FLOATING POINT EXCEPTION VECTOR IS CORRECT.	;MSH171
;									;MSH171

	.IF DF	F$$LPP

	TST	PIRQ		;IS THERE A PIRQ REGISTER?
	BCS	106$		;IF CS NO
	MOV	#$FPPRQ,@#240	;SET UP PIRQ VECTOR
	MOV	#$FPPR8,@#244	;SET UP FLOATING POINT EXCEPTION VECTOR
106$:				;REF LABEL

	.ENDC


	JSR	R5,OPMSG	;OUTPUT INITIAL       PROMPT MESSAGE
	.WORD	PROMT		;

;									;MSH171
; SET UP CORRECT SYSTEM CLOCK. IF THE SET SYSTEM TIME DIRECTIVE IS	;MSH171
; SUPPORTED, INITIALIZE SOME CRITICAL CONTROL DATA FOR IT.		;MSH171
;									;MSH171

	MOV	$CKCSR,R0	;GET ADDRESS OF CLOCK CSR
	TST	(R0)		;IS THE GENERATED CLOCK AVAILABLE?
	BCC	110$		;IF CC YES
	MOV	#172540,R0	;GET ADDRESS OF KW11-P CSR
	MOV	R0,$CKCSR	;SETUP FOR KW11-P
	MOV	#172542,$CKCNT	;
	MOV	#K$$LDC,$CKLDC	;SET COUNT REGISTER LOAD COUNT
	MOV	#K$$TPS,$TKPS	;SET TI      CKS PER SECOND
	TST	(R0)		;KW11-P?
	BCC	110$		;IF CC YES
	MOV	#177546,R0	;GET ADDRESS OF KW11-L CSR
	MOV	R0,$CKCSR	;SETUP FOR KW11-L
	MOV	R0,$CKCNT	;
	CLR	$CKLDC		;
	MOV	#H$$RTZ,$TKPS	;SET TICKS PER SECOND TO LINE FREQUENCY
110$:	MOV	#$NONSI,@#100	;RESET KW11-L INTERRUPT VECTOR
	MOV	#$CKINT,104	;SETUP KW11-P VECTOR
	CMP	#172540,R0	;KW11-P?
	BEQ	120$		;IF EQ YES
	MOV	#$CKINT,100	;SETUP KW11-L VECTOR
	MOV	#$NONSI,104	;RESET KW11-P VECTOR
	TST	(R0)		;KW11-L?				;MSH044
	BCC	120$		;IF CC YES				;      MSH044
	CLR	$CKCSR		;CLEAR CLOCK CSR POINTER		;MSH044
	CLR	$CKCNT		;CLEAR CLOCK COUNTER POINTER		;MSH044
	BR	130$							;MSH044
120$:	MOV	$CKCNT,R1	;GET ADDRESS OF COUNT REGISTER
	MOV	$CKLDC,(R1)	;SETUP CLOCK COUNT REGISTER
	MOV	#K$$IEN,(R0)	;START CLOCK
130$:				;REF LABEL				;MSH044
									;MSH123
	.IF DF	S$$TIM							;MSH123
									;MSH123
	MOV	$TKPS,$TIKLM	;INIT TICKS/SECOND HIGH CHECK		;MSH123
	DEC	$TIKLM		;CONVERT FROM FREQUENCY TO HIGH LIMIT	;MSH123
									;MSH123
	.ENDC								;M      SH123

	.IF DF	M$$MGE

	MOV	#PMODE+PR7,PS	;MAKE SURE PS IS SETUP PROPERLY

	.ENDC

;									;MSH142
; INITIALIZE THE POOL MONITOR CONTROL STRUCTURE.			;MSH142
;									;MSH142
									;MSH142
	.IF DF	P$$CTL							;MSH142
									;MSH142
	MOV	$CRAVL,R0	;GET POINTER TO SECOND FREE POOL BLOCK	;MSH142
	CLR	R1		;INITIALIZE SIZE COUNTER		;MSH142
140$:	ADD	2(R0),R1	;ADD LENGTH OF FREE POOL BLOCK		;MSH142
	MOV	(R0),R0		;POINT TO NEXT FREE POOL BLOCK IN LIST	;MSH142
	BNE	140$		;IF NE THERE IS O      NE			;MSH142
	MOV	R1,$PRISZ	;STORE IT AWAY FOR THE POOL MONITOR	;MSH142
	CLR	$POLST		;INITIALIZE EXEC/POOL TASK FLAGS	;MSH142
									;MSH142
	.ENDC								;MSH142
									;MSH171
;									;MSH171
; NOW THAT INITL IS DONE, DEALLOCATE IT INTO THE DYNAMIC STORAGE	;MSH171
; REGION. CORRECT THE STARTING ADDRESS OF THE NEW POOL BLOCK TO		;MSH171
; BEGIN ON A DOUBLEWORD BOUNDARY.					;MSH171
;									;MSH171

	MOV	#SYSMG,R0	;SET ADDRESS OF BLOCK TO RELEASE
	ADD	$CRAVL-2,R0	;ROUND TO NEXT BOUNDARY      
	BIC	$CRAVL-2,R0	;
	MOV	#$SYBEG-SYSMG,R1 ;SET LENGTH OF BLOCK TO RELEASE
	CALLR	$DEACB		;DEALLOCATE INITIALIZATION CODE
									;MSH165
;									;MSH165
; SUBROUTINE TO VALIDATE EXECUTIVE COMMON POINTERS			;MSH165
;									;MSH165
; INPUTS:	R0=COMMON PARTITION OFFSET IN 32-WORD BLOCKS		;MSH165
;		R1=SYSTEM SIZE IN 32-WORD BLOCKS			;MSH165
;									;MSH165
									;MSH165
PARCK:	MOV	#$PARHD,R5	;LOAD PARTITION LISTHEAD		;MSH165
10$:	MOV	(R5),R5		;GET NEXT PCB IN LIST			;MSH165
	BEQ	20$		;I      F EQ NO MATCH				;MSH165
	CMP	P.REL(R5),R0	;IS THIS THE CORRECT PCB?		;MSH165
	BNE	10$		;IF NE NO, LOOK AT THE NEXT ONE		;MSH165
	ADD	P.SIZE(R5),R0	;FOUND IT, CALCULATE TOP OF COMMON	;MSH165
	BCS	20$		;IF CS, THEN 6 X 9 MUST BE 42		;MSH165
	CMP	R0,R1		;IS COMMON LOADED IN MEMORY?		;MSH165
	BHI	20$		;IF HI NO, CAN'T BOOT THIS SYSTEM	;MSH165
	TST	P.BUSY(R5)	;IS COMMON ACTUALLY INSTALLED?		;MSH165
	BPL	20$		;IF PL NO, CAN'T BOOT			;MSH165
	TSTB	P.STAT(R5)	;IS THIS A COMMON PARTITION?		;MSH165
	BPL	20      $		;IF PL NO, CANNOT BE AN EXEC COMMON	;MSH165
	RETURN			;COMMON POINTER IS VALID		;MSH165
									;MSH165
20$:	SEC			;COMMON POINTER IS INVALID		;MSH165
	RETURN			;					;MSH165

;
; SUBROUTINE TO OUTPUT A MESSAGE TO THE SYSTEM CONSOLE TERMINAL
;

OPMSG:	MOV	(R5)+,R1	;GET ADDRESS OF OUTPUT MESSAGE
10$:	MOVB	(R1)+,R0	;GET NEXT BYTE TO OUTPUT
	BEQ	30$		;IF EQ DONE
	MOVB	R0,TPS+2	;LOAD BYTE IN OUTPUT BUFFER
20$:	TSTB	TPS		;PRINTER BUSY?
	BCS	30$		;IF CS NO CONSOLE TERMINAL
	BPL	20$		;IF PL YES      
	BR	10$		;GO AGAIN
30$:	RTS	R5		;
									;MSH181
;									;MSH181
; SUBROUTINE TO INTERCEPT UNEXPECTED T-BIT TRAPS AFTER LSI POWER UP.	;MSH181
; THIS ROUTINE CLEARS THE T-BIT AND DISMISSES IT. IT IS ASSUMED THAT	;MSH181
; THE BPT/T-BIT VECTOR WILL BE RESET TO THE EXECUTIVE'S SST ROUTINE	;MSH181
; SOON AFTER BOOTING RSX.						;MSH181
;									;MSH181
									;MSH181
	.IF NDF	P$$RFL							;MSH181
	.IF DF	L$$SI1							;MSH181
									;MSH181
$TBIT::	BIC	#20,2(SP)	;CLEAR T-BIT IN SAVED PS		      ;MSH181
	RTI			;DISMISS THE TRAP			;MSH181
									;MSH181
	.ENDC								;MSH181
	.ENDC								;MSH181
									;**-7
;
; MAKE SURE THAT INITL IS OF DOUBLEWORD LENGTH. NOTE THAT THIS CAUSES	;MSH171
; $SYBEG TO BE ON A MATCHING BOUNDARY TYPE AS THAT OF $POOL.		;MSH171
;									;**-1

	.EVEN								;MSH171

	.IF NE	<.-SYSMG>&3

	.BLKB	<.-SYSMG>&3

	.ENDC


;
; BEGINNING OF DYNAMIC STORAGE REGION. NOTE THAT AFTER TASK BUILDING,	;MSH171
; $SYBEG MAY NOT BE ON A DOUBLEWORD BOUNDARY. THIS       IS CORRECTED AS	;MSH171
; SOON AS THE SYSTEM IS VMR'ED. ALSO, A COMPARABLE CORRECTION IS MADE	;MSH171
; TO $POOL WHEN INITL DEALLOCATES ITSELF. WE ARE GUARANTEED THAT SINCE	;MSH171
; $POOL AND $SYBEG HAVE TO BE EQUALLY CORRECTED (BECAUSE INITL IS ALWAYS;MSH171
; OF DOUBLEWORD LENGTH) WE DO NOT HAVE TO ADJUST THE AMOUNT TO		;MSH171
; DEALLOCATE AND THAT INITL WILL BE CORRECTLY AGGLOMERATED INTO POOL.	;MSH171
;									;**-1

$SYBEG::.WORD	0		;LINK TO NEXT BLOCK IN FREE LIST
	.WORD	<<<C$$ORE*2>+3>&17   ’   7774> ;LENGTH OF FREE BLOCK
	.BLKB	<<<C$$ORE*2>+3>&177774>-4 ;ALLOCATE REMAINING STORAGE
$SYTOP::			;LAST ADDRESS IN EXECUTIVE

	.END	$INITL
’          óe�ƒkQ	› c,        	.TITLE	PLSUB
	.IDENT	/01.00/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.00
;
; T. J. MILLER 8-MAR-76
;
; PROGRAM LOGICAL ADDRESS SPACE (PLAS) COMMON SUBROUTINES
;
; MACRO LIBRARY CALLS
;


	.IF DF	P$$LAS

	.MCALL	HDRDF$,HWDDF$,PCBDF$,TCBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HAR      DWARE REGISTERS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$SRNAM-SEARCH FOR NAMED PARTITION
;
; THIS ROUTINE SEARCHES FOR A NAMED PARTITION AND RETURNS A SUCCESS/
; FAILURE INDICATION AND A POINTER TO THE PCB IF FOUND.
;
; INPUTS:
;
;	R3=POINTER TO DOUBLE-WORD RAD50 NAME
;
; OUTPUTS:
;
;	C=1 IF NO MATCH ON NAME
;
;	C=0 IF NAMED PARTITION FOUND
;		R2=PCB ADDRESS
;-

$SRNAM::MOV	$PARHD,R2	;POINT TO FIRST PCB IN THE LIST
10$:	      CMP	P.NAM(R2),(R3)	;MATCH ON FIRST WORD OF NAME?
	BNE	20$		;IF NE NO
	CMP	P.NAM+2(R2),2(R3) ;MATCH ON SECOND WORD OF NAME?
	BEQ	50$		;IF EQ YES
20$:				;REF LABEL


	.IF DF	D$$YNM&M$$MGE

	BIT	#PS.SYS,P.STAT(R2) ;SYSTEM CONTROLLED PARTITION?
	BEQ	40$		;IF EQ NO
	TST	P.SUB(R2)	;IS THERE ANOTHER SUBPARTITION?
	BEQ	30$		;IF EQ NO
	MOV	P.SUB(R2),R2	;POINT TO NEXT SYS SUBPARTITION
	BR	10$		;
30$:	MOV	P.MAIN(R2),R2	;POINT BACK TO MAIN PCB

	.ENDC


40$:	MOV	(R2),R2		;POINT TO NEXT PCB (P.LNK)      
	BNE	10$		;IF NE THERE IS ONE
	SEC			;RETURN C=1
50$:	RETURN			;

;+
; **-$CKACC-CHECK DESIRED ACCESS
;
; THIS ROUTINE CHECKS IF THE DESIRED ACCESS OF A TASK TO A REGION
; IS ALLOWED.  THE BITS IN THE PROTECTION WORD ARE ARRANGED IN THE
; FOLLOWING ORDER:
;
;	[WORLD,GROUP,OWNER,SYSTEM]
;	 15			0
;
; THE BITS WITHIN EACH CATEGORY IN THE PROTECTION WORD ARE ARRANGED
; IN THE FOLLOWING ORDER:
;
;	DELETE  EXTEND  WRITE  READ
;	3       2       1      0
;
; A BIT SET MEANS THE CORRESPONDING A      CCESS IS NOT ALLOWED.
;
; INPUTS:
;
;	R0=DESIRED ACCESS MASK IN LOW FOUR BITS
;	R1=CURRENT UIC OF TASK
;	R2=PCB ADDRESS OF REGION
;
; OUTPUTS:
;
;	R0,R1 ARE MODIFIED
;
;	DIRECTIVE STATUS OF D.RS16 RETURNED IF ACCESS DENIED.
;-

$CKACC::MOV	#30$,-(SP)	;PUSH COROUTINE ADDRESS
	BIC	#^C17,R0	;CLEAR ALL BUT DESIRED ACCESS MASK
10$:	SWAB	R1		;REVERSE GROUP AND OWNER IN UIC WORD
	CALL	@(SP)+		;CHECK IF QUALIFIED IN NEXT CATEGORY
	BNE	20$		;IF NE NO
	BIT	R0,P.PRO(R2)	;ALLOWED ACCESS IN THIS CATE      GORY?
	BNE	20$		;IF NE NO
	TST	(SP)+		;POP COROUTINE ADDRESS
	RETURN			;RETURN TO CALLER
20$:	ASL	R0		;SHIFT MASK TO NEXT CATEGORY
	ASL	R0		;
	ASL	R0		;
	ASL	R0		;
	BR	10$		;CHECK ACCESS IN THIS CATEGORY
30$:	CMPB	R1,#10		;SYSTEM UIC?
	BHI	40$		;IF HI NO
	SEZ			;SET FLAG FOR ACCESS CHECK
40$:	CALL	@(SP)+		;CHECK ACCESS AND SHIFT MASK
	CMP	R1,P.OWN(R2)	;OWNER UIC?
	CALL	@(SP)+		;CHECK ACCESS AND SHIFT MASK
	CMPB	R1,P.OWN+1(R2)	;SAME GROUP?
	CALL	@(SP)+		;CHECK ACCESS AND SHIFT MASK
	SEZ			;I      NSURE CHECK FOR WORLD ACCESS
	CALL	@(SP)+		;CHECK ACCESS
	DRSTS	D.RS16		;ACCESS DENIED IF WE GET HERE

;+
; **-$CRATT-CREATE ATTACHMENT DESCRIPTOR
;
; THIS ROUTINE CREATES AN ATTACHMENT DESCRIPTOR AND INSERTS IT IN THE
; NECESSARY QUEUES.
;
; INPUTS:
;
;	R2=PCB ADDRESS OF REGION BEING ATTACHED TO
;	R4=ACCESS CODE
;	R5=TCB ADDRESS OF ATTACHING TASK
;
; OUTPUTS:
;
;	C=0 IF SUCCESSFUL
;		R1=ADDRESS OF ATTACHMENT DESCRIPTOR
;		R0 IS MODIFIED
;	C=1 IF AN ATTACHMENT DESCRIPTOR COULD NOT BE AL      LOCATED
;		R0,R1 ARE MODIFIED
;-

$CRATT::MOV	R3,-(SP)	;SAVE R3
	MOV	R2,-(SP)	;SAVE PCB ADDRESS
	MOV	#A.LGTH,R1	;PICK UP ATTACHMENT DESCRIPTOR SIZE
	CALL	$ALOCB		;ALLOCATE THE ATTACHMENT DESCRIPTOR
	BCS	10$		;IF CS ALLOCATION FAILURE
	ADD	R0,R1		;POINT PAST END OF ATTACHMENT DESCRIPTOR
	MOV	(SP),-(R1)	;SET PCB ADDRESS (A.PCB)
	MOV	R4,-(R1)	;INIT STATUS AND MAP COUNT (A.STS)
	BIC	#^C17,(R1)	;CLEAR ALL BUT ACCESS BITS (A.STS)
	TST	-(R1)		;POINT TO TCBL THREAD WORD (A.TCBL)
	MOV	R5,R0		;POINT TO       TCB ATTACHMENT LISTHEAD
	ADD	#T.ATT,R0	;
	CALL	$QINSF		;INSERT DESCRIPTOR AT END OF QUEUE
	MOV	R5,-(R1)	;SET TCB ADDRESS (A.TCB)
	CLRB	-(R1)		;ZERO I/O COUNT (A.IOC)
	MOVB	T.PRI(R5),-(R1)	;INIT PRIORITY TO TASK PRIORITY (A.PRI)
	TST	-(R1)		;POINT TO PCBL THREAD (A.PCBL)
	MOV	(SP),R0		;POINT TO PCB ATTACHMENT LISTHEAD
	ADD	#P.ATT,R0	;
	CALL	$QINSP		;INSERT IN QUEUE BY PRIORITY
	CLC			;INDICATE SUCCESS
10$:	MOV	(SP)+,R2	;RESTORE PCB ADDRESS
	MOV	(SP)+,R3	;RESTORE R3
	RETURN			;

;+
; **-$SRATT      -SEARCH FOR ATTACHMENT DESCRIPTOR
;
; THIS ROUTINE VERFIES IF A VALID REGION ID WAS PASSED IN A PLAS DIRECTIVE
; BY SEARCHING FOR THE CORRESPONDING ATTACHMENT DESCRIPTOR IN THE TCB'S
; ATTACHMENT QUEUE.
;
; INPUTS:
;
;	(R3)=REGION ID TO VERIFY (OR 0 TO IMPLY TASK REGION)
;	R5=TCB ADDRESS OF CURRENT TASK
;
; OUTPUTS:
;
;	R5=ADDRESS OF ATTACHMENT DESCRIPTOR
;
;	D.RS86 IS RETURNED IF THE ATTACHMENT DESCRIPTOR CANNOT BE FOUND.
;-

$SRATT::MOV	T.ATT(R5),R5	;POINT TO FIRST ATTACHMENT DESCRIPTOR      
	MOV	(R3),-(SP)	;DEFAULT TO TASK REGION?
	BEQ	20$		;IF EQ YES
	ADD	#A.TCBL,(SP)	;ADD BIAS TO LINK WORD
10$:	CMP	R5,(SP)		;MATCH ON THIS DESCRIPTOR?
	BEQ	20$		;IF EQ YES
	MOV	(R5),R5		;ELSE POINT TO NEXT DESCRIPTOR (A.TCBL)
	BNE	10$		;IF NE THERE IS ONE
	DRSTS	D.RS86		;INVALID REGION ID
20$:	SUB	#A.TCBL,R5	;POINT TO START OF ATTACHMENT DESCRIPTOR
	TST	(SP)+		;CLEAN STACK
	RETURN			;

;+
; **-$SRWND-SEARCH FOR SPECIFIED ADDRESS WINDOW
;
; THIS ROUTINE VERIFIES THAT THE SPECIFIED ADDRESS WINDOW       ID CORRESPONDS
; TO A VALID ESTABLISHED ADDRESS WINDOW.
;
; INPUTS:
;
;	(R3)=ADDRESS WINDOW ID
;	R4=ADDRESS OF CURRENT TASK HEADER
;
; OUTPUTS:
;
;	R4=POINTER TO SPECIFIED WINDOW BLOCK
;	R0 IS MODIFIED.
;
;	D.RS87 IS RETURNED IF THE SPECIFIED ADDRESS WINDOW IS INVALID
;-

$SRWND::MOV	H.WND(R4),R4	;POINT TO NUMBER OF WINDOWS
	MOVB	(R3),R0		;PICK UP ADDRESS WINDOW ID (W.NID)
	BEQ	10$		;IF EQ ILLEGAL
	CMP	R0,(R4)+	;WINDOW ID TOO LARGE?
	BHIS	10$		;IF HIS YES
	ASL	R0		;CONVERT WINDOW ID TO       8 WORD OFFSET
	ASL	R0		;
	ASL	R0		;
	ASL	R0		;
	ADD	R0,R4		;POINT TO ADDRESS WINDOW
	TST	W.BSIZ(R4)	;IS IT AN ESTABLISHED ADDRESS WINDOW?
	BEQ	10$		;IF EQ NO
	RETURN			;
10$:	DRSTS	D.RS87		;INVALID ADDRESS WINDOW

;+
; **-$UNMAP-UNMAP ADDRESS WINDOW
;
; THIS ROUTINE SEARCHES FOR AND CONDITIONALLY UNMAPS THE SPECIFIED
; ADDRESS WINDOW.
;
; INPUTS:
;
;	R4=ADDRESS OF WINDOW TO BE UNMAPPED
;
; OUTPUTS:
;
;	R0 IS MODIFIED
;
;	C=1 IF UNMAPPING WAS PERFORMED
;-

	.ENABL	LSB
$UNMAP::TST      	(R4)		;IS WINDOW MAPPED? (W.BPCB)
	BEQ	20$		;IF EQ IT IS NOT MAPPED
	MOV	R1,-(SP)	;SAVE R1
	CLR	(R4)		;UNMAP ADDRESS WINDOW (W.BPCB)
	MOV	W.BATT(R4),R0	;PICK UP ADDRESS OF ATTACHMENT DESCRIPTOR
	CLR	W.BATT(R4)	;CLEAR ATTACHMENT DESCRIPTOR POINTER
	DECB	A.MPCT(R0)	;DECREMENT MAPPING COUNT
	MOV	A.TCB(R0),R1	;POINT TO TASK TCB ADDRESS
	MOVB	W.BFPD(R4),R0	;POINT TO FIRST USER PDR
10$:	BIT	#T3.PRV,T.ST3(R1) ;IS THE TASK PRIVILEGED?
	BEQ	14$		;IF EQ NO
	MOV	KISAR0-UISDR0(R0),UISAR0-UISDR0(R0) ;RESTORE   ô    PRV MAPPING
	MOV	#77406,(R0)+	;
	BR	15$		;
14$:	CLR	(R0)+		;CLEAR NEXT USER PDR
15$:	DECB	W.BNPD(R4)	;DONE YET?
	BGT	10$		;IF GT NO
	MOV	(SP)+,R1	;RESTORE R1
	SEC			;RETURN CS FOR WINDOW UNMAPPED
20$:	RETURN			;

	.ENDC


	.END
 ô          Ô@ykQ	› c,        	.TITLE	DRDSP
	.IDENT	/15.35/
 
;
;		COPYRIGHT (c) 1981 BY
;	DIGITAL EQUIPMENT CORPORATION, MAYNARD
;	 MASSACHUSETTS.  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 SO      FTWARE 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 THAT IS
; NOT SUPPLIED BY DIGITAL.
;
; VERSION 15.35
;
; D. N. CUTLER 12-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVE      Y	24-JUL-79
;		MSH045 -- ADD DIRECTIVE PARTITION SUPPORT
;
;	M. S. HARVEY	17-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	1-SEP-79
;		MSH052 -- ENABLE CANCEL SELECTIVE MARK TIME DIRECTIVE
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	2-JAN-80
;		MSH078 -- ADD GET/PUT INFORMATION DIRECTIVE
;
;	M. S. HARVEY	19-MAY-80
;		MSH100 -- RETURN CORRECT DIRECTIVE STATUS FROM ERROR
;			  THR      EADED DIRECTIVES
;
;	M. S. HARVEY	3-JUN-80
;		MSH104 -- EMIT STATUS DIRECTIVE SUPPORT
;			  SEND, REQUEST AND CONNECT DIRECTIVE SUPPORT
;
;	M. S. HARVEY	15-SEP-80
;		MSH118 -- EXTEND PARTITION DIRECTIVE MUST BE ILLEGAL
;			  FOR RSX-11S SYSTEMS
;
;	M. S. HARVEY	6-OCT-80
;		MSH121 -- ADD SPECIFY REQUESTED EXIT AST DIRECTIVE
;
;	M. S. HARVEY	17-OCT-80
;		MSH123 -- ADD SUPPORT FOR SET SYSTEM TIME DIRECTIVE
;
;	M. S. FOX	07-JAN-81
;		MF204 -- ADD GCCI$ DIRECTIVE
;
;	M. S. HARVEY	8-JAN-81
;		      MSH139 -- MAP STOPFOR DIRECTIVES INTO WAITFOR DIRECTIVES
;			  IF THE FORMER WERE NOT CHOSEN DURING SYSGEN
;
;	DAN BROWN	7-JAN-81
;		DTB003 -- ADD SUPPORT FOR SEND MESSAGE DIRECTIVE
;
;	M. S. FOX	26-JAN-81
;		MF207 -- ADD RPOI$ AND SDRP$ DIRECTIVES
;
;	M. S. FOX	03-FEB-81
;		MF208 -- ADD CLI CONTROL DIRECTIVES
;
;	M. S. HARVEY	11-FEB-81
;		MSH148 -- ADD THE UNLOCK GROUP GLOBAL DIRECTIVE
;
;	M. S. HARVEY	21-APR-81
;		MSH165 -- ADD SUPPORT FOR SECOND DIRECTIVE COMMON
;
;	M. S. HARVEY	12-JUN-      81
;		MSH176 -- MAP 'EXIT WITH STATUS' INTO 'EXIT TASK'
;			  IF NO PARENT/OFFSPRING TASKING SUPPORT
;
;	M. S. HARVEY	21-JUL-81
;		MSH180 -- ALLOW UNSTOP TO CONSISTENTLY ALLOW DEFAULTED
;			  TASK NAME
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
;	M. S. HARVEY	6-OCT-81
;		MSH194 -- EXTERNALIZE WAITFOR ROUTINE
;
; DIRECTIVE DISPATCHER
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,HWDDF$,TCBDF$,WDBDF$
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HARDWARE REG      ISTERS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	WDBDF$			;DEFINE USER WINDOW DEF BLOCK OFFSETS

; LOCAL MACROS

;
; MACRO TO DEFINE SUCCESSIVE DIRECTIVE MASK BITS
;

	.MACRO	DEFINE SYM
SYM=N
N=N/2
	.ENDM

; THE SIZ MACRO IS USED TO DETERMINE THE HIGHEST DIC CODE USED, AS
; WELL AS THE TOTAL NUMBER OF DIC'S IN USE. IT'S PARAMETERS ARE THE
; SAME AS THE GEN MACRO BELOW, THOUGH IT ONLY NEEDS THE DIC AND COND.

	.MACRO	SIZ,DIC,DPBSIZ,DIRADR,MASK,COND,SECOND

	.IF NB <COND>

	.IF DF C      OND

NUMDIR=NUMDIR+1

	.IF GT DIC-HIDIR
HIDIR=DIC
	.ENDC

	.ENDC	;COND

	.IFF	;NB COND

NUMDIR=NUMDIR+1

	.IF GT DIC-HIDIR
HIDIR=DIC
	.ENDC

	.ENDC	;NB COND
	.ENDM


; THE GEN MACRO IS USED TO FILL IN THE ABOVE TABLES, BASED UPON THE
; CONDITIONAL ASSEMBLY PARAMETERS DEFINED IN RSXMC.MAC.  RSXMC.MAC
; IS CREATED BY SYSGEN PART 1.  THE PARAMETERS FOR THE GEN MACRO ARE:
;	DIC -	 DIRECTIVE IDENTIFICATION CODE (MUST BE ODD).		;MSH165
;	DPBSIZ - SIZE OF THE DIRECTIVE PARAMETER BLOCK IN       BYTES.	;MSH165
;	DIRADR - ADDRESS OF THE DIRECTIVE PROCESSING ROUTINE. IF	;MSH165
;		 THE ODD BIT IS SET, THEN THE ROUTINE RESIDES IN	;MSH165
;		 THE SECOND EXTERNAL EXECUTIVE COMMON.			;MSH165
;	MASK -	 DIRECTIVE PROCESSING CONTROL MASK.			;MSH165
;	COND -	 CONDITIONAL ASSEMBLY PARAMETERS WHICH IF SPECIFIED	;MSH165
;		 MUST BE DEFINED IF THE DIRECTIVE IS SUPPORTED. IF	;MSH165
;		 NONE SPECIFIED, THEN 'R$$11M' IS SPECIFIED BY DEFAULT.	;MSH165
;	SECOND - CONDITIONAL ASSEMBLY PARAMETERS WHICH IF DEFIN      ED	;MSH165
;		 ALLOWS THE DIRECTIVE TO HAVE  A VARIABLE LENGTH	;MSH165
;		 DIRECTIVE PARAMETER BLOCK. THE PROCESSING ROUTINES	;MSH165
;		 FOR SUCH DIRECTIVES MUST VALIDATE THE SIZE OF THE	;MSH165
;		 DPB THEMSELVES.					;MSH165
;									;**-8
	.MACRO	GEN,DIC,DPBSIZ,DIRADR,MASK,COND,SECOND

	.IF B <COND>

	GEN	<DIC>,<DPBSIZ>,<DIRADR>,<MASK>,R$$11M,<SECOND>

	.IFF	;B <COND>

	.IF DF COND

	.IF DF BYTTAB
.=<BTAB+<DIC/2>>
	.BYTE	DSPPTR
.=DSPTBL+DSPPTR
DSPPTR=DSPPTR+4
	.IFF	;BYTTAB
.=<DIC*      2-2+DSPTBL>
	.ENDC	;BYTTAB

	.WORD	DIRADR

	.IF NB <SECOND>

	.IF DF SECOND

	.BYTE	0
VARDPB=0

	.IFF	;SECOND

	.BYTE	DPBSIZ*2

	.ENDC	;SECOND

	.IFF	;NB SECOND

	.BYTE	DPBSIZ*2

	.ENDC	;NB SECOND

DSPMK=0

	.IF NB	<MASK>
	.IRP	X,<MASK>
DSPMK=DSPMK!X
	.ENDM
	.ENDC

	.BYTE	DSPMK

	.ENDC	;COND

	.ENDC	;B <COND>

	.ENDM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MSH165
;									;MSH165
;		R S X - 1 1 M / S   D I R E C T I V E S			;MSH165      
;		---------------------------------------			;MSH165
;									;MSH165
; EACH DIRECTIVE IS REPRESENTED AS A LINE IN THE DIREC MACRO.
; THE ONLY PARAMETER FOR THE DIREC MACRO IS THE NAME OF THE MACRO
; TO BE INVOKED UPON EACH LINE.  THE FIRST CALL OF DIREC SPECIFIES
; THE SIZ MACRO TO DETERMINE WHETHER THE SINGLE OR DOUBLE TABLE
; SCHEME IS TO BE USED.  THE SECOND CALL SPECIFIES THE GEN MACRO
; TO ACTUALLY GENERATE THE PROPER TABLE STRUCTURE.

	.MACRO	DIREC,MAC

; QUEUE I/O REQUEST							;MSH165      
	MAC	1.,12.,$DRQIO						;MSH165
									;MSH165
; QUEUE I/O REQUEST AND WAIT						;MSH165
	MAC	3.,12.,$DRQIO						;MSH165
									;MSH165
; GET LUN INFORMATION							;MSH165
	MAC	5.,3.,$DRGLI						;MSH165
									;MSH165
; ASSIGN LUN								;MSH165
	MAC	7.,4.,$DRASG!PAG					;MSH165
									;MSH165
; ALTER TASK PRIORITY							;MSH165
	MAC	9.,4.,$DRAP1!PAG,<DFCTSK,SRSTCL>,A$$PRI			;MSH165
									;MSH165
; REQUEST TASK OR SPAWN OFFSPRING TASK					;MSH165
	MAC	11.,7.,$DRREQ,<SRSTCL>,,P$$O      FF				;MSH165
									;MSH165
; RUN TASK								;MSH165
	MAC	17.,11.,$DRRUN,<SRSTCL>					;MSH165
									;MSH165
; SPECIFY RECEIVE-BY-REFERENCE AST					;MSH165
	MAC	21.,2.,$DRRRA,,A$$TRP&P$$LAS&P$$SRF			;MSH165
									;MSH165
; MARK TIME								;MSH165
	MAC	23.,5.,$DRMKT,<CEFNCL>					;MSH165
									;MSH165
; CANCEL SCHEDULE REQUESTS						;MSH165
	MAC	25.,3.,$DRCSR,<SRSTCL,MUPCHK>				;MSH165
									;MSH165
; CANCEL (SELECTIVE) MARK TIME						;MSH052
	MAC	27.,1.,$DRCMS,,,C$$SMT					;MSH      052
									;MSH052
; EXIT WITH STATUS							;MSH165
									;MSH176
	.IF DF	P$$OFF							;MSH176
									;MSH176
	MAC	29.,2.,$DREXS						;MSH176
									;MSH176
	.IFF								;MSH176
									;MSH176
	MAC	29.,2.,$DREXT						;MSH176
									;MSH176
	.ENDC	;P$$OFF							;MSH176
									;MSH165
; CLEAR EVENT FLAG							;MSH049
	MAC	31.,2.,$DRCEF,<CEFNCL,GEFUSE,CEFNMT>			;MSH049
									;MSH049
; SET EVENT FLAG							;MSH049
	MAC	33.,2.,$DRSEF,<CEFNCL,GEFUSE,CEFNMT>			;MSH049
									      ;MSH049
; DECLARE SIGNIFICANT EVENT						;MSH165
	MAC	35.,1.,$DRDSE						;MSH165
									;MSH165
; READ ALL/EXTENDED EVENT FLAGS						;MSH165
	MAC	39.,2.,$DRRAF,,,G$$EFN					;MSH165
									;MSH165
; WAIT FOR SINGLE EVENT FLAG						;MSH165
	MAC	41.,2.,$DRWFD,<CEFNCL,CEFNMT>				;MSH194
									;MSH165
; WAIT FOR LOGICAL 'OR' OF EVENT FLAGS					;MSH165
	MAC	43.,3.,$DRWFL						;MSH165
									;MSH165
; SUSPEND TASK EXECUTION						;MSH165
	MAC	45.,1.,$DRSPN						;MSH165
									;MSH165
; RE      SUME TASK EXECUTION							;MSH165
	MAC	47.,3.,$DRRES,<SRSTCL>					;MSH165
									;MSH165
; WAIT FOR SIGNIFICANT EVENT						;MSH165
	MAC	49.,1.,$DRWSE						;MSH165
									;MSH165
; TASK EXIT								;MSH165
	MAC	51.,1.,$DREXT						;MSH165
									;MSH165
; EXIT IF EVENT FLAG IS SET						;MSH049
	MAC	53.,2.,$DREIF,<CEFNCL,GEFUSE,CEFNMT>			;MSH049
									;MSH049
; CREATE DYNAMIC REGION							;MSH165
	MAC	55.,2.,$DRCRR!PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; ATTACH REGION								;M      SH165
	MAC	57.,2.,$DRATR!PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; DETACH REGION								;MSH165
	MAC	59.,2.,$DRDTR!PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; GET TIME PARAMETERS / SET SYSTEM TIME					;MSH123
	MAC	61.,2.,$DRGTP!PAG,,,S$$TIM				;MSH123
									;MSH165
; GET TASK PARAMETERS							;MSH165
	MAC	63.,2.,$DRGTK,,G$$TTK					;MSH165
									;MSH165
; GET PARTITION PARAMETERS						;MSH165
	MAC	65.,4.,$DRGPP,,G$$TPP					;MSH165
									;MSH165
; SEND BY REFERENCE							;M      SH165
	MAC	69.,5.,$DRSRF!PAG,<SRSTCL>,P$$LAS&P$$SRF		;MSH165
									;MSH165
; SEND DATA TO TASK							;MSH165
	MAC	71.,5.,$DRSND,<SRSTCL>,R$$SND				;MSH165
									;MSH165
; RECEIVE DATA FROM TASK						;MSH165
	MAC	75.,4.,$DRREC,,R$$SND					;MSH165
									;MSH165
; RECEIVE DATA FROM TASK OR EXIT					;MSH165
	MAC	77.,4.,$DRREC,,R$$SND					;MSH165
									;MSH165
; RECEIVE BY REFERENCE							;MSH165
	MAC	81.,2.,$DRRRF!PAG,<ACHKDB>,P$$LAS&P$$SRF		;MSH165
									;MSH165
; ABORT TASK						      		;MSH165
	MAC	83.,3.,$DRABO,<SRSTCL,MUPCHK>				;MSH165
									;MSH165
; EXTEND TASK PARTITION							;MSH118
	MAC	89.,3.,$DREXP!PAG,,D$$YNM&E$$XPR&M$$MGE&D$$ISK&C$$CKP	;MSH118
									;MSH118
; DISABLE CHECKPOINTING FOR TASK					;MSH165
	MAC	95.,1.,$DRDCP,,C$$CKP&D$$ISK				;MSH165
									;MSH165
; ENABLE CHECKPOINTING FOR TASK						;MSH165
	MAC	97.,1.,$DRECP,,C$$CKP&D$$ISK				;MSH165
									;MSH165
; DISABLE AST RECOGNITION						;MSH165
	MAC	99.,1.,$DRDAR,,A$$TRP					;MSH165
									;M      SH165
; ENABLE AST RECOGNITION						;MSH165
	MAC	101.,1.,$DREAR,,A$$TRP					;MSH165
									;MSH165
; SPECIFY SST VECTOR FOR DEBUGGING AID					;MSH165
	MAC	103.,3.,$DRSDV						;MSH165
									;MSH165
; SPECIFY SST VECTOR FOR TASK						;MSH165
	MAC	105.,3.,$DRSTV						;MSH165
									;MSH165
; SPECIFY RECEIVE DATA AST						;MSH165
	MAC	107.,2.,$DRRCV,,A$$TRP&R$$SND				;MSH165
									;MSH165
; SPECIFY POWERFAIL RECOVERY AST					;MSH165
	MAC	109.,2.,$DRPUT,,A$$TRP&P$$RFL				;MSH165
								      	;MSH165
; SPECIFY FLOATING POINT EXCEPTION AST					;MSH165
	MAC	111.,2.,$DRFEX,,A$$TRP&F$$LPP				;MSH165
									;MSH165
; GET MAPPING CONTEXT							;MSH165
	MAC	113.,2.,$DRGMX!PAG,,P$$LAS&P$$GMX			;MSH165
									;MSH165
; ASYNCHRONOUS SYSTEM TRAP ROUTINE EXIT					;MSH165
	MAC	115.,1.,$DRATX,,A$$TRP					;MSH165
									;MSH165
; CREATE ADDRESS WINDOW							;MSH165
	MAC	117.,2.,$DRCRW!PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; ELIMINATE ADDRESS WINDOW						;MSH165
	MAC	119.,2.,$DRELW      !PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; MAP ADDRESS WINDOW							;MSH165
	MAC	121.,2.,$DRMAP!PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; UNMAP ADDRESS WINDOW							;MSH165
	MAC	123.,2.,$DRUNM!PAG,<ACHKDB>,P$$LAS			;MSH165
									;MSH165
; GET SENSE SWITCHES							;MSH165
	MAC	125.,1.,$DRGSS,,G$$TSS					;MSH165
									;MSH165
; GET COMMAND LINE							; MF204
	MAC	127.,41.,$DRGCL,,M$$CRX,A$$CLI				; MF204
									; MF204
; CONNECT TO INTERRUPT							;MSH165
	MAC	129.,7.,$DRC      IN!PAG,,C$$INT				;MSH165
									;MSH165
; STOP TASK								;MSH165
	MAC	131.,1.,$DRSTP,,S$$TOP					;MSH165
									;MSH165
; UNSTOP TASK								;MSH165
	MAC	133.,3.,$DRUNS,<DFCTSK,SRSTCL>,S$$TOP			;MSH165
									;MSH165
; STOP FOR SINGLE EVENT FLAG						;MSH139
	MAC	135.,2.,$DRSTS,<CEFNCL,CEFNMT>				;MSH139
									;MSH139
; STOP FOR LOGICAL 'OR' OF EVENT FLAGS					;MSH139
	MAC	137.,3.,$DRSTL						;MSH139
									;MSH139
; RECEIVE DATA FROM TASK OR STOP					;MSH165
	MAC	139.,4.,$DRRCS      ,,S$$TOP&R$$SND				;MSH165
									;MSH165
; SEND, REQUEST AND CONNECT / SEND, REQUEST AND CHAIN			; MF207
	MAC	141.,7.,$DRSRC,<SRSTCL>,P$$OFF&R$$SND,R$$POI		; MF207
									; MF207
; CONNECT TO TASK							;MSH165
	MAC	143.,6.,$DRCNC,<SRSTCL>,P$$OFF				;MSH165
									;MSH165
; EMIT STATUS								;MSH104
	MAC	147.,4.,$DREMS,,P$$OFF					;MSH104
									;MSH104
; CREATE GROUP GLOBAL EVENT FLAGS					;MSH165
	MAC	157.,2.,$DRCRE!PAG,,G$$EFN				;MSH165
									;MSH165
; ELIMINATE / UNLOCK GROUP       GLOBAL EVENT FLAGS				;MSH148
	MAC	159.,2.,$DRELE!PAG,,G$$EFN,G$$EFN			;MSH148
									;MSH148
; SPECIFY REQUESTED EXIT AST						;MSH121
	MAC	167.,2.,$DRREX,,A$$TRP&A$$BRT,A$$BRT			;MSH121
									;MSH121
; GET / PUT INFORMATION							;MSH078
	MAC	169.,0.,$DRGIN,,D$$GIN,D$$GIN				;MSH078
									;MSH078
; SEND MESSAGE								;DTB003
	MAC	171.,0.,$DRSMG!PAG,,E$$LOG,E$$LOG			;DTB003
									;DTB003
; COMMAND LINE INTERPRETER CONTROL DIRECTIVES				; MF208
	MAC	173.,0.,$DRCLI,,A$$CLI,A$$CLI			      	; MF208
									; MF208
;									;MSH165
; DIRECTIVE IDENTIFICATION CODES 191. THRU 199. ARE GUARANTEED		;MSH165
; TO BE AVAILABLE FOR USER-WRITTEN DIRECTIVES.				;MSH165
;									;MSH165
; ALL OTHER UNUSED DICS ARE RESERVED BY DIGITAL FOR FUTURE USE.		;MSH165
;									;MSH165
									;MSH165
									;MSH165
;									;MSH165
;		END OF DIRECTIVE LIST					;MSH165
;									;MSH165
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MSH165
									;**-69
	.ENDM

      
;
; THE DIRECTIVE DISPATCHER IS ASSEMBLED TO USE ONE OF THE FOLLOWING
; DISPATCH TABLE STRUCTURES, DEPENDING UPON WHICH REQUIRES THE LEAST
; AMOUNT OF MEMORY.  THE FIRST SCHEME USES A DISPATCH TABLE, DSPTBL,
; THAT CONTAINS 2 WORDS FOR EACH POSSIBLE DIC. THE FORMAT OF EACH ENTRY
; IS:
;	.WORD	ADDRESS ;ADDRESS OF DIRECTIVE PROCESSING ROUTINE
;			; OR 0 IF DIRECTIVE IS NOT SUPPORTED.
;	.BYTE	DBPSIZ	;SIZE OF DPB FOR THIS DIRECTIVE OR 0 IF
;			; THIS DIRECTIVE HAS A VAIRABLE LENGTH DPB.
;	.BYTE	MASK	      ;CONTROL BITS USED BY THE DISPATCHER.
;
; THE MEMORY USED FOR THIS TABLE IS EQUAL TO THE HIGHEST DIC VALUE
; TIMES 2 MINUS 2 BYTES.
;
; IF THE ABOVE TABLE WOULD BE LESS THAN 3/4 FULL, WE USE THE FOLLOWING
; TWO TABLES FOR DIRECTIVE DISPATCHING.  THE FIRST TABLE, BTAB, CONTAINS A
; BYTE FOR EACH POSSIBLE DIC.  THE BYTE CONTAINS THE OFFSET INTO THE
; DISPATCH TABLE DSPTBL IF THE DIRECTIVE IS SUPPORTED, OR 0 IF IT IS NOT.
; THE SECOND TABLE, DSPTBL, IS THE SAME FORMAT AS ABOVE, HOWEVER, IT IS
; ONLY       REQUIRED TO HAVE ENTRIES FOR THE DIC'S IN USE.  THE FIRST ELEMENT IN
; DSPTBL IS 2(DSPTBL) BECAUSE WE USE 0 TO REPRESENT INVALID DIC'S.
;
; THE CONDITIONAL ASSEMBLY PARAMETER BYTTAB IS DEFINED IF THE TWO TABLE
; SCHEME IS USED.
;

; LOCAL SYMBOLS

NUMDIR=0			;NUMBER OF DIC'S IN USE
HIDIR=0				;HIGHEST DIC IN USE
									;MSH165
	.IF DF	D$$PAR							;MSH165
									;MSH165
PAG=1				;SECOND DIRECTIVE COMMON EXISTS		;MSH165
									;MSH165
	.IFF								;MSH165
									;MSH165
PAG=0				;SE      COND DIRECTIVE COMMON DOES NOT EXIST	;MSH165
									;MSH165
	.ENDC								;MSH165

;									;MSH165
; DIRECTIVE PRE-PROCESSING MASK BITS. ALL UNDEFINED MASK BITS		;MSH165
; ARE RESERVED BY DIGITAL FOR FUTURE EXPANSION.				;MSH165
;									;MSH165
									;**-1
DSPNX=2				;INITIAL DIRECTIVE MAPPING TABLE INDEX
N=200				;INITIAL MASK VALUE
	DEFINE	ACHKDB		;ADDRESS CHECK PLAS DEFINITION BLOCK
	DEFINE	CEFNCL		;BIT SET INDICATES THAT THE NEXT DPB	;MSH165
				; ARGUMENT IS AN EVENT FLAG THAT MUS      T	;MSH165
				; BE CONVERTED INTO A MASK (R0) AND	;MSH165
				; MASK ADDRESS (R1).			;MSH165
	DEFINE	GEFUSE		;USED WITH CEFNCL AND HAS MEANING ONLY	;MSH049
				; IF THE EVENT FLAG BEING CONVERTED IS	;MSH049
				; GROUP GLOBAL. ASYNCHRONOUS GGEF USAGE	;MSH049
				; REQUIRES THAT THE FLAGS BE LOCKED FOR	;MSH049
				; THE DIRECTIVE TO PREVENT PREMATURE	;MSH049
				; FLAG ELIMINATION. THIS REVERSE-POLARIT;MSH049
				; BIT, WHEN CLEAR, CAUSES THE FLAGS TO	;MSH049
				; BE LOCKED ON A SUCCESSFUL DIRECTI      VE	;MSH049
				; COMPLETION.				;MSH049
	DEFINE	CEFNMT		;BIT SET INDICATES THAT THE DIRECTIVE	;MSH165
				; REQUIRES AN EVENT FLAG TO BE SPECIFIED;MSH165
									;MSH165
;  THE REMAINING BITS EACH INDICATE, WHEN SET, THAT THE NEXT DPB	;MSH165
;  ARGUMENT IS A RAD50 TASK NAME SPECIFICATION THAT MUST BE		;MSH165
;  VALIDATED.								;MSH165
									;MSH165
	DEFINE	DFCTSK		;BIT SET INDICATES THAT THE TASK NAME	;MSH165
				; MAY BE DEFAULTED TO THAT OF THE	;MSH165
				; CURRENT TASK.				;MSH165
	D      EFINE	MUPCHK		;BIT SET INDICATES THAT THE DIRECTIVE	;MSH165
				; MUST BE SUBJECTED TO SOME STANDARD	;MSH165
				; MULTIUSER PROTECTION CHECKS.		;MSH165
	DEFINE	SRSTCL		;NO SPECIAL ACTION. BIT SET INDICATES	;MSH165
				; THAT NEXT ARGUMENT IS A TASK NAME THAT;MSH165
				; MUST BE VALIDATED.			;MSH165
									;MSH165
									;MSH165
									;MSH165
									;**-5
	DIREC	SIZ		;DETERMINE HIGHEST DIC AND NUMBER OF DIC'S
				;IN USE

	.IF LE NUMDIR-<HIDIR*3/8.>	;IF WE ARE USING LESS THAN
 					;      3/4 OF THE DIC'S, WE WILL
BYTTAB=0				;USE THE TWO TABLE SCHEME

	.ENDC

;
; LOCAL DATA - ADJACENCY ASSUMED
;
USRPS:	.BLKW	1		;POINTER TO USER PS WORD
BTRMV:	.BLKW	1		;BYTES TO REMOVE ON EXIT


	.IF DF BYTTAB

BTAB:	.BLKB	HIDIR/2+1	;BYTE INDEX TABLE
	.EVEN
.=.-2
DSPTBL:	.BLKW	NUMDIR*2+1	;DISPATCH TABLE
DSPPTR=2			;POINTER INTO DISPATCH TABLE

	.IFF	;BYTTAB

DSPTBL:	.BLKW	HIDIR+1

	.ENDC	;BYTTAB

$$$=.
	DIREC	GEN		;GENERATE DIRECTIVE DISPATCH TABLE
.=$$$


;+
; **-$TRTRP-TRAP       TRAP
; **-$DRTRP-TRAP TRAP (EXECUTIVE COMMON ENTRY POINT)			;MSH165
;
; THIS ROUTINE IS TRAPPED TO WHEN A TRAP INSTRUCTION IS EXECUTED. IF THE
; STACK DEPTH IS ZERO, THEN A DIRECTIVE STATUS IS TO BE RETURNED. ELSE
; CONTROL IS TRANSFERED TO THE EMT/TRAP SST HANDLING ROUTINE.
;
; INPUTS:
;
;	2(SP)=PS WORD PUSHED BY TRAP INSTRUCTION.
;	0(SP)=PC WORD PUSHED BY TRAP INSTRUCTION.
;
; OUTPUTS:
;
;	IF THE STACK DEPTH IS ZERO, THEN A DIRECTIVE STATUS IS RETURNED.
;	ELSE CONTROL IS TRANSFERED TO THE E      MT/TRAP SST HANDLING ROUTINE.
;-

	.ENABL	LSB
									;MSH165
	.IF NDF	D$$PAR							;MSH165
									;MSH165
$TRTRP::TST	$STKDP		;;;STACK DEPTH ZERO?
	BNE	$EMTRP		;;;IF NE NO
	MTPS	#0		;;;ALLOW INTERRUPTS
	MOV	(SP),R0		;GET ADDRESS PLUS 2 OF TRAP INSTRUCTION
	MOVB	-2(R0),R0	;PICK UP DIRECTIVE STATUS		;MSH100
									;MSH165
	.ENDC								;MSH165
									;MSH165
$DRTRP::			;					;MSH165
									;**-1
	.IF DF	M$$MGE

	BIS	#PMODE,PS	;SET PREVIOUS MODE TO USER
	MOV	#$STACK-22,SP	;RELOAD       EXEC STACK POINTER

	.IFF

	MOV	#$STACK-12,SP	;RELOAD EXEC STACK POINTER

	.ENDC


	MOV	R0,-(SP)	;SAVE DIRECTIVE STATUS			;**-1
	BPL	259$		;IF PL OKAY AS IS			;MSH049
	INC	@USRPS		;SET CARRY IN USER PS WORD		;**-1
	JMP	60$		;					;MSH049
259$:	JMP	$DRSOK		;					;MSH049
									;**-1
;+
; **-$EMTRP-EMT TRAP
; **-$DRDSP-DIRECTIVE DISPATCHER - EMT TRAP (EXECUTIVE COMMON ENTRY PT.);MSH165
;
; THIS ROUTINE IS TRAPPED TO WHEN AN EMT INSTRUCTION IS EXECUTED. IF THE
; STACK DEPTH IS NOT +1, THE      N THE SYSTEM IS CRASHED. ELSE A TEST IS
; MADE TO SEE IF THE EMT INSTRUCTION HAD A CODE OF 377. IF NOT, THEN
; CONTROL IS TRANSFERED TO THE EMT/TRAP SST HANDLING ROUTINE. ELSE THE
; APPROPRIATE DIRECTIVE IS EXECUTED.
;
; INPUTS:
;
;	2(SP)=PS WORD PUSHED BY EMT INSTRUCTION.
;	0(SP)=PC WORD PUSHED BY EMT INSTRUCTION.
;
; OUTPUTS:
;
;	IF THE STACK DEPTH IS NOT +1, THEN THE SYSTEM IS CRASHED. ELSE
;	CONTROL IS GIVEN TO THE EMT/TRAP SST ROUTINE OR A DIRECTIVE ROUTINE
;	DEPENDENT ON WHETHER THE EMT       HAD A CODE OF 377.
;-
									;MSH165
	.IF NDF	D$$PAR							;MSH165
									;MSH165

$EMTRP::DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY
	TST	$STKDP		;WERE WE AT STACK DEPTH +1?
	BEQ	$DRDSP		;IF EQ YES				;MSH165
	CRASH			;EMT/TRAP WITH $STKDP NOT +1		;MSH165
									;MSH165
	.ENDC								;MSH165
									;MSH165
$DRDSP::MOV	@$HEADR,R3	;GET SAVED STACK POINTER		;MSH165
	CMP	(R3)+,(R3)+	;POINT TO USER PC WORD			;**-2
	MOV	(R3)+,R5	;GET ADDRESS OF EMT PLUS 2


	.IF DF	M$$MGE

	MFPI	-(R5      )		;GET DIRECTIVE WORD
	CMP	#104377,(SP)	;DIRECTIVE EMT?
	BEQ	7$		;IF EQ YES				;MSH049
	JMP	80$		;CHECK THIS EMT'S VALIDITY		;MSH049
7$:	MOV	#1,(SP)		;SET SUCCESSFUL DIRECTIVE STATUS	;MSH049
									;**-2
	.IFF

	CMP	#104377,-(R5)	;DIRECTIVE EMT?
	BEQ	7$		;IF EQ YES				;MSH049
	JMP	80$		;CHECK THIS EMT'S VALIDITY		;MSH049
7$:	MOV	#1,-(SP)	;SET SUCCESSFUL DIRECTIVE STATUS	;MSH049
									;**-2
	.IFTF

	MOV	#USRPS,R5	;POINT TO LOCAL DATA
	MOV	R3,(R5)+	;SAVE ADDRESS OF USER PS
	BIC	(SP),(R3      )+	;CLEAR CARRY IN USER PS WORD
	CLR	(R5)		;INDICATE NO BYTES

	.IFT

	MFPI	SP		;GET USER STACK POINTER
	MOV	(SP)+,R3	;
$DRLM1::MFPI	(R3)		;GET FIRST WORD ON USER STACK
	BIT	#1,(SP)		;DPB ON STACK?
	BNE	$DRLM2		;IF NE YES
	MOV	#2,(R5)		;INDICATE DPB POINTED TO BY STACK
	MOV	(SP),R3		;SET ADDRESS OF DPB
	MFPI	@(SP)+		;GET FIRST WORD OF DPB
$DRLM2::MOV	(SP)+,R1	;PICK UP FIRST DPB WORD
	CLR	R0		;EXTRACT DIC CODE
	BISB	R1,R0		;
	MOV	R1,$DICSV	;SAVE DIC AND DPB SIZE
	CLRB	R1		;CLEAR DIC BYTE
	S      WAB	R1		;SWAP DPB SIZE TO LOW BYTE

	.IFF

	BIT	(SP),(R3)	;DPB ON STACK?
	BNE	10$		;IF NE YES
	MOV	(R3),R3		;GET ADDRESS OF DPB
	MOV	#2,(R5)		;INDICATE DPB POINTED TO BY STACK


	.IF DF	A$$CHK

	CALL	$ACHK2		;ADDRESS CHECK FIRST DPB WORD

	.ENDC

10$:	CLR	R0		;EXTRACT DIC CODE
	BISB	(R3),R0		;
	MOV	(R3),$DICSV	;SAVE DIC AND DPB SIZE
	MOVB	1(R3),R1	;EXTRACT DPB SIZE

	.ENDC


	ASL	R1		;CONVERT TO BYTES TO REMOVE AT EXIT
	MOV	R1,R4		;COPY SIZE
	CLR	-(SP)		;ASSUME ILLEGAL DIC OR DPB S      IZE
	ASR	R0		;DIVIDE CODE BY 2
	BCC	35$		;IF CC ILLEGAL DIC CODE
	CMP	R0,#HIDIR/2	;LEGAL DIC CODE?			;**-2
	BHI	35$		;IF HI NO


	.IF DF BYTTAB

	CLR	R2		;MAP TO DIRECTIVE DISPATCH TABLE
	BISB	BTAB(R0),R2	;
	BEQ	35$		;IF EQ ILLEGAL DIRECTIVE
	ADD	#DSPTBL,R2	;POINT TO PROPER TABLE ENTRY

	.IFF	;BYTTAB

	MOV	#DSPTBL,R2	;MAP TO DIRECTIVE DISPATCH TABLE
	ASL	R0
	ASL	R0
	ADD	R0,R2
	TST	(R2)		;VALID DIRCTIVE?
	BEQ	35$		;IF EQ, NO

	.ENDC	;BYTTAB

	CMPB	R1,2(R2)	;DPB SIZE MATCH?

	.IF DF       VARDPB

	BEQ	20$		;IF EQ YES
	TSTB	2(R2)		;VARIABLE LENGTH DPB?

	.ENDC	;VARDPB

	BNE	35$		;IF NE NO
20$:	MOV	(R2)+,(SP)	;GET ADDRESS OF DIRECTIVE ROUTINE	;MSH049
	BIS	(R2),R4		;PICK UP DIRECTIVE SIZE AND MASK BYTE	;**-2


	.IF DF	P$$LAS&M$$MGE

	BPL	35$		;IF PL NOT A PLAS DIRECTIVE
$DPLM1::MFPI	2(R3)		;PICK UP POINTER TO DEFINITION BLOCK
$DPLM2::MOV	(SP)+,R3	;
	MOV	#8.*2,R1	;PICK UP SIZE OF DEFINITION BLOCK

	.ENDC


35$:				;REFERENCE LABEL

	.IF DF	G$$EFN							;MSH049
									      ;MSH049
	MOV	#$GEFDM,$GEFPT	;INIT GRP GLOBAL USE COUNT POINTER	;MSH049
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	MOV	#$GEFDM,$GFTCB	;INIT GRP GLOBAL USER POINTER		;MSH076
									;MSH076
	.ENDC	;R$$SND							;MSH076
									;MSH049
	.ENDC								;MSH049

	.IF DF	A$$CHK!M$$MGE

	CALL	$ACHKP		;ADDRESS CHECK AND MAP DEFINITION BLOCK

	.ENDC


	TST	(R3)+		;SKIP OVER FIRST DPB WORD
	TST	(R5)		;DPB ON STACK?
	BNE	36$		;IF NE NO
	MOVB	R4,(R5)		;SET NUMBER OF BYTES       TO REMOVE AT EXIT
36$:	CLRB	R4		;CLEAR OUT SIZE BYTE
	TST	(SP)		;LEGAL DIC AND DPB SIZE?
	BEQ	90$		;IF EQ NO
	MOV	$TKTCB,R5	;PICK UP CURRENT TASK TCB
	ASL	R4		;PLAS DIRECTIVE?			;MSH049
									;**-1

	.IF DF	P$$LAS

	BCC	37$		;IF CC NOT A PLAS DIRECTIVE
	TST	-(R3)		;POINT BACK TO FIRST WORD OF BLOCK
	BIC	#WS.CRW!WS.UNM!WS.ELW!WS.RRF,W.NSTS(R3) ;INIT OUTPUTS
37$:				;REFERENCE LABEL

	.ENDC


	ASL	R4		;CALL $CEFN OR $CEFNG?			;MSH049
	BCC	40$		;IF CC NO				;MSH049
									;MSH049
	.I      F DF	G$$EFN							;MSH049
									;MSH049
	BMI	38$		;IF MI DON'T INCREMENT GRP GBL USE COUNT;MSH049
	CALL	$CEFNG		;CONVERT EFN AND LOCK IF GROUP GLOBAL	;MSH049
	BR	39$		;JOIN COMMON CODE			;MSH049
38$:									;MSH049
	.IFTF								;MSH049
									;MSH049
	CALL	$CEFN		;CONVERT EVENT FLAG NUMBER		;**-1
									;MSH049
	.IFT								;MSH049
									;MSH049
	BIC	#1,R1		;CLR GROUP GLOBAL 2ND MASK INDICATOR	;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
39$:	BCC	50$		;IF CC EV      ENT FLAG SPECIFIED		;MSH049
40$:	ASL	R4		;EVENT FLAG REQUIRED?			;**-1
	BEQ	50$		;IF EQ NO
	BMI	100$		;IF MI EVENT FLAG WAS REQUIRED


	.IF DF	A$$PRI!M$$MUP!S$$TOP					;MSH180
									;**-1
	ASL	R4		;TASK NAME DEFAULT TO CURRENT TASK?
	BPL	45$		;IF PL NO
	MOV	R5,R0		;PICK UP CURRENT TASK TCB
	TST	(R3)		;TASK NAME SPECIFIED?
	BEQ	46$		;IF EQ NO

	.ENDC


45$:	CALL	$SRSTD		;SEARCH STD FOR TASK NAME
	BCS	110$		;IF CS NAME NOT FOUND
46$:	CMP	(R3)+,(R3)+	;ADVANCE PAST TASK NAME


	.IF DF	M      $$MUP

	ASL	R4		;PERFORM MULTI-USER PROTECTION CHECK?
	BPL	47$		;IF PL NO
	BIT	#T3.PRV,T.ST3(R5) ;ISSUING TASK PRIVILEGED?
	BNE	47$		;IF NE YES
	BIT	#T3.SLV,T.ST3(R0) ;TARGET TASK A SLAVE TASK?
	BNE	120$		;IF NE YES, DON'T ALLOW
	CMP	T.UCB(R5),T.UCB(R0) ;CURRENT AND TARGET TASK UCBS MATCH?
	BNE	120$		;IF NE NO

	.ENDC


47$:	MOV	R0,R1		;COPY TCB ADDRESS
	ADD	#T.STAT,R1	;POINT TO TASK STATUS WORD
50$:	MOV	R5,R2		;SET POINTER TO SECOND TASK STATUS WORD
	ADD	#T.ST2,R2	;
	MOV	$HEADR,R4	;POINT       TO CURRENT TASK HEADER
;									;MSH045
; THE DIRECTIVE PROCESSING ROUTINE MAY RESIDE IN ONE OF THREE PLACES,	;MSH045
; THE MAIN BODY OF THE EXECUTIVE, OR ONE OF THE TWO EXTERNAL EXECUTIVE	;MSH045
; COMMONS, IF SUPPORTED. IT IS ASSUMED THAT THE DIRECTIVE IS IN EITHER	;MSH045
; THE RESIDENT EXECUTIVE OR IN THE FIRST EXEC COMMON. IF IT ISN'T, THE	;MSH045
; ODD BIT OF THE ROUTINE ADDRESS IN (SP) IS SET. THE FOLLOWING CODE	;MSH045
; DETECTS THAT AND REMAPS KERNEL APR5 TO THE SECOND COMMON IF		;MSH045
;       NECESSARY.								;MSH045
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
	ASR	(SP)		;DIRECTIVE IN SECOND EXTERNAL COMMON?	;MSH165
	BCC	58$		;IF CC NO				;MSH165
	CALLR	$OTHR1		;CALL DIRECTIVE ROUTINE W/ARGS BELOW	;MSH165
									;MSH165
58$:	ASL	(SP)		;RESTORE TO BYTE ADDRESS		;MSH165
									;MSH045
	.ENDC								;MSH045

;
; CALL DIRECTIVE ROUTINE WITH THE FOLLOWING ARGUMENTS:
;
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.      
;	R3=ADDRESS OF THE NEXT WORD IN THE DIRECTIVE DPB.
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.
;	R1=DEPENDENT ON DIRECTIVE.
;	R0=DEPENDENT ON DIRECTIVE.
;

	CALL	@(SP)+		;CALL DIRECTIVE ROUTINE
									;MSH049
;									;MSH049
; IF THE SPECIFIED DIRECTIVE CAUSES AN ASYNCHRONOUS UTILIZATION OF	;MSH049
; AN EVENT FLAG TO BEGIN AND THAT EVENT FLAG IS A GROUP GLOBAL EVENT	;MSH049
; FLAG, THEN THE USE COUNT FOR THE FLAG IS INCREMENTED HERE BECAUSE	;MSH049
; IT IS KNOWN THAT T      HE DIRECTIVE SUCCEEDED. THIS PREVENTS ELIMINATION	;MSH049
; OF THE EVENT FLAGS BEFORE THAT ASYNCHRONOUS UTILIZATION COMPLETES.	;MSH049
;									;MSH049
									;MSH049
$DRSOK::			;					;MSH049
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
	INC	@$GEFPT		;INCREMENT GROUP GLOBAL USE COUNT	;MSH049
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	INCB	@$GFTCB		;INC GRP GLOBAL USE COUNT FOR TASK	;MSH076
									;MSH076
	.ENDC	;R$$SND							;MSH076
									;      MSH049
	.ENDC								;MSH049
									;MSH049
;									;MSH049
; RETURN THE DIRECTIVE'S COMPLETION STATUS TO THE DIRECTIVE STATUS	;MSH049
; WORD IN THE ISSUING TASK'S HEADER AND CLEAN UP THE TASK'S STACK.	;MSH049
;									;MSH049
									;MSH049
60$:				;REF LABEL


	.IF DF	M$$MGE

	MTPI	@#H.DSW		;SET DIRECTIVE STATUS WORD
	MFPI	SP		;GET USER STACK POINTER
	ADD	BTRMV,(SP)	;REMOVE BYTES FROM USER STACK
	MTPI	SP		;RESTORE USER STACK POINTER

	.IFF

	MOV	(SP)+,@.DSW	;SET DIRECTIVE STATUS       WORD
	MOV	$HEADR,R0	;GET ADDRESS OF TASK HEADER
	BEQ	65$		;IF EQ TASK TERMINATED
	MOV	(R0),R0		;GET TASK STACK POINTER
	ADD	#8.,R0		;POINT TO FIRST STACK WORD
	MOV	R0,R1		;COPY ADDRESS
	ADD	BTRMV,R1	;POINT TO NEW TOP OF USER STACK
	MOV	-(R0),-(R1)	;MOVE RETURN PS WORD
	MOV	-(R0),-(R1)	;MOVE RETURN PC WORD
	MOV	-(R0),-(R1)	;MOVE SAVED R5
	MOV	-(R0),-(R1)	;MOVE SAVED R4
	MOV	R1,@$HEADR	;SET NEW STACK POINTER

	.ENDC
									;**-8
65$:	RETURN			;EXIT FROM TRAP

;									;**-6
; EMT/TRAP SS      T ROUTINE TRANSFER
;

80$:				;REF LABEL


	.IF DF	M$$MGE

	MOV	$HEADR,R5	;POINT TO CURRENT TASK HEADER
	MOV	H.WND(R5),R5	;POINT TO NUMBER OF WINDOW BLOCKS
	TST	W.BLVR+2(R5)	;CURRENT TASK MAPPED TO EXEC?
	BEQ	85$		;IF EQ NO
	CMP	(SP),#104376	;IS THIS A CALL TO $SWSTK?

	.IFF

	CMP	(R5),#104376	;IS THIS A CALL TO $SWSTK?

	.ENDC


	BNE	85$		;IF NE NO
	JMP	$SWSTK		;PROCESS CALL TO $SWSTK
85$:	JMP	$EMSST		;PROCESS SST FAULT

;
; ILLEGAL DIRECTIVE
;

90$:	DRSTS	D.RS99		;SET DIRECTIV   V  E STATUS

;
; REQUIRED EVENT FLAG NUMBER NOT SPECIFIED
;

100$:	DRSTS	D.RS97		;SET DIRECTIVE STATUS

;
; SPECIFIED TASK NAME NOT FOUND IN TASK DIRECTORY
;

110$:	DRSTS	D.RS2		;SET DIRECTIVE STATUS

;
; PRIVILEGE VIOLATION
;


	.IF DF	M$$MUP

120$:	DRSTS	D.RS16		;SET DIRECTIVE STATUS

	.ENDC


	.DSABL	LSB

	.END
V         »zðkQ	› c,        	.TITLE	SYSDF
	.IDENT	/09.10/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 09.10
;
; D. N. CUTLER 23-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	P. WANNHEDEN
;	J. PROVINO
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	11-SEP-79
;		MSH053 -- DEFINE NEW SYMBOLS FOR       EXTK$ DIRECTIVE:
;				D.RS18 - NO SWAP SPACE AVAILABLE
;				D.RS83 - WINDOW HAS I/O IN PROGRESS
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	9-MAY-80
;		MSH099 -- GET FILES-11 BLOCK OFFSETS AND UCB OFFSETS
;
;	DAN BROWN	7-JAN-81
;		DTB002 -- DEFINE NEW MEANING OF D.RS8
;
;	M. S. HARVEY	27-JAN-81
;		MSH145 -- DEFINE SYMBOL INDICATING BASELINE STATUS
;
;	M. S. FOX	13-FEB-81
;		MF207 -- ADD D.RS89 FOR SDRP$
;
;      	M. S. HARVEY	30-APR-81
;		MSH156 -- DEFINE K$$W11 GLOBALLY
;
; SYSTEM GLOBAL AND CONTROL BLOCK OFFSET DEFINITIONS
;
; GLOBALLY DEFINE THE HIGHEST VECTOR ADDRESS
;

	.GLOBL	V$$CTR

;
; DEFINE SYSTEM DEPENDENT CONTROL BLOCK OFFSETS AND LENGTHS GLOBALLY
;

	.MCALL	ITBDF$,PCBDF$,PKTDF$,SCBDF$,TCBDF$,HWDDF$,F11DF$	;MSH099
	.MCALL	UCBDF$							;MSH099
	UCBDF$	<:>,,,SYSDEF		;DEFINE UCB OFFSETS		;MSH099
	F11DF$	<:>,<=>,SYSDEF		;DEFINE FILES-11 OFFSETS	;MSH099
	ITBDF$	<:>,<=>,SYSDEF		;DEFINE ITB O      FFSETS AND LENGTH	;**-1
	PCBDF$	<:>,<=>,SYSDEF		;DEFINE PCB OFFSETS AND LENGTH
	SCBDF$	<:>,,SYSDEF		;DEFINE SCB OFFSETS
	TCBDF$	<:>,<=>,SYSDEF		;DEFINE TCB OFFSETS

	HWDDF$	,<=>			;DEFINE HARDWARE OFFSETS
;
; CAUSE OFFSET DEFINITIONS FROM PREFIX FILES TO BE LISTED
;

S$$YDF=0

;
; SYSTEM GLOBAL SYMBOL DEFINITIONS
;
; DIRECTIVE STATUS CODES
;
; INSUFFICIENT DYNAMIC CORE AVAILABLE TO SATISFY REQUEST
;

D.RS1==-1.			;

;
; SPECIFIED TASK NOT INSTALLED IN THE SYSTEM
;

D.RS2==-2.			;
      
;
; UNASSIGNED LUN
;

D.RS5==-5.			;

;
; DRIVER NOT LOADED
;

D.RS6==-6.			;
;
; TASK NOT ACTIVE
;

D.RS7==-7.			;

;
; TASK NOT SUSPENDED/NO DATA QUEUED/TASK CHECKPOINTING ALREADY ENABLED
; OR DISABLED/AST RECOGNITION ALREADY ENABLED OR DISABLED/AST ENTRY ALREADY
; UNSPECIFIED/ILLEGAL SMSG$ TARGET					;DTB002
;									;**-1

D.RS8==-8.			;

;
; ISSUING TASK NOT CHECKPOINTABLE
;

D.RS10==-10.			;

;
; PRIVILEGE VIOLATION
;

D.RS16==-16.			;

;
; VECTOR ALREADY IN US      E (CINT$) / GROUP GLOBAL EVENT FLAGS IN USE	;MSH076
;									;**-1

D.RS17==-17.
									;MSH053
;									;MSH053
; NO SWAP SPACE AVAILABLE, OR TASK HAS PREALLOCATED CHECKPOINT SPACE	;MSH053
; AND IS ATTEMPTING TO EXTEND TO GREATER THAN INSTALLED SIZE (EXTK$)	;MSH053
;									;MSH053
									;MSH053
D.RS18==-18.								;MSH053

;
; ILLEGAL VECTOR (CINT$)
;

D.RS19==-19.

;
; DIRECTIVE ISSUED/NOT ISSUED FROM AST ROUTINE
;

D.RS80==-80.			;

;
; CANNOT MAP ISR OR DISABLE-INTERRUP      T ROUTINE (CINT$)
;

D.RS81==-81.
									;MSH053
;									;MSH053
; WINDOW HAS I/O IN PROGRESS, OR TASK HAS I/O IN PROGRESS (EXTK$)	;MSH053
;									;MSH053
									;MSH053
D.RS83==-83.								;MSH053

;
; ALIGNMENT ERROR
;

D.RS84==-84.			;

;
; ADDRESS WINDOW OVERFLOW
;

D.RS85==-85.			;

;
; INVALID REGION ID
;

D.RS86==-86.			;

;
; INVALID WINDOW ID
;

D.RS87==-87.			;
									; MF207
;									; MF207
; ILLEGAL SEND BUFFER LENGTH						; MF207
;									; MF20      7
									; MF207
D.RS89==-89.								; MF207

;
; SPECIFIED LUN IS LOCKED IN USE.
;

D.RS90==-90.			;

;
; INVALID UIC
;

D.RS91==-91.			;

;
; INVALID DEVICE AND/OR UNIT SPECIFIED.
;

D.RS92==-92.			;

;
; INVALID TIME PARAMETER
;

D.RS93==-93.			;

;
; PARTITION/REGION NOT IN SYSTEM
;

D.RS94==-94.			;

;
; INVALID PRIORITY
;

D.RS95==-95.			;

;
; INVALID LUN
;

D.RS96==-96.			;

;
; INVALID EFN OR REQUIRED EFN NOT SPECIFIED
;

D.RS97==-97.			;

;
;       PART OF DPB IS OUTSIDE OF ISSUING TASK'S ADDRESS SPACE
;

D.RS98==-98.			;

;
; INVALID DIC OR DPB SIZE
;

D.RS99==-99.			;

;
; EFN WAS SET
;

D.RS22==2.			;

;
; EFN WAS CLEAR
;

D.RS00==0.			;

;
; IF DYNAMIC ALLOCATION IS PRESENT DEFINE D$$YNM GLOBALLY
;

	.IIF DF D$$YNM , D$$YNM==0 ;

;
; IF 11/70 EXTENDED MEMORY IS PRESENT DEFINE M$$EXT GLOBALLY
;

	.IIF DF	M$$EXT , M$$EXT==0 ;

;
; IF MEMORY MANAGEMENT IS PRESENT DEFINE M$$MGE GLOBALLY
;

	.IIF DF M$$MGE , M$$MG      E==0 ;

;									;**-1
; IF SEND / RECEIVE BY REFERENCE SUPPORTED, DEFINE P$$SRF GLOBALLY
;

	.IIF DF	P$$SRF , P$$SRF==P$$SRF

;									;MSH145
; DEFINE THE BASELINE STATUS OF THIS SYSTEM				;MSH145
;									;MSH145
									;MSH145
	.IF DF	B$$LIN							;MSH145
									;MSH145
$BASLN==1			;THE SYSTEM IS A BASELINE SYSTEM	;MSH145
									;MSH145
	.IFF								;MSH145
									;MSH145
$BASLN==0			;THE SYSTEM IS NOT A BASELINE SYSTEM	;MSH145
									;MSH145
	.ENDC								;MSH145
					   œ  				;MSH145
;									;MSH156
; DEFINE K$$W11 GLOBALLY FOR PRIVILEGED TASKS				;MSH156
;									;MSH156
									;MSH156
	.IF DF	K$$W11							;MSH156
									;MSH156
K$$W11==K$$W11			;DEFINE WATCHDOG CSR GLOBALLY		;MSH156
									;MSH156
	.IFF								;MSH156
									;MSH156
K$$W11==-1			;DEFINE SYMBOL FOR REFERENCE ONLY	;MSH156
									;MSH156
	.ENDC								;MSH156
									;MSH156
	.END
œ         Õ09kQ	› c,        	.TITLE	DREIF
	.IDENT	/16.37/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 16.37
;
; D. N. CUTLER 13-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	23-JUL-79
;		MSH008 -- CLEAR TCB ADDRESS FROM ALL RREF PACKETS
;
;	M. S.       HARVEY	25-JUL-79
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	20-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	11-SEP-79
;		MSH045 -- ADD DIRECTIVE PARTITION SUPPORT
;
;	M. S. HARVEY	8-OCT-79
;		MSH021 -- CONDITIONALIZE ACP TEST
;
;	M. S. HARVEY	29-AUG-80
;		MSH091 -- UPDATE KERNEL AST SUPPORT
;
;	M. S. HARVEY	29-AUG-80
;		MSH103 -- ALWAYS QUEUE REMOVE COMMAND TO MCR
;
;	M. S. HARVEY	12-SEP-80
;		MSH115 -- CLEANUP GROUP GLOBAL USE FOR       ABORTED TASKS
;
;	M. S. HARVEY	12-SEP-80
;		MSH116 -- FIX BUG LEAVING TASKS IN I/O RUNDOWN STATE
;
;	M. S. HARVEY	8-OCT-80
;		MSH121 -- CLEAN UP ABORT ASTS FOR EXITING TASKS
;
;	M. S. HARVEY	24-NOV-80
;		MSH129 -- PASS SECONDARY EXIT CODE TO PARENT TASK
;
;	M. S. FOX	07-JAN-81
;		MF203 -- INITIAL ALTERNATE CLI SUPPORT
;
;	M. S. HARVEY	12-FEB-81
;		MSH148 -- UNLOCK GROUP GLOBAL EVENT FLAGS ON EXIT
;
;	M. S. FOX	11-MAR-81
;		MF211 -- IFDF A$$CLI, SEND 6 BYTE PACKET FOR PROMPT
;
;	M. S. HA      RVEY	5-MAY-81
;		MSH165 -- ENSURE CORRECT EXECUTIVE COMMON MAPPING
;
;	M. S. HARVEY	10-JUN-81
;		MSH174 -- FORCIBLY DEACCESS TASK FROM GROUP GLOBALS
;			  IN CASE ABORTED BECAUSE OF CHECKPOINT READ
;			  FAILURE WHERE THE HEADER MAY BE GARBAGE
;
;	M. S. HARVEY	29-JUL-81
;		MSH183 -- ADD SUPPORT FOR GROUP GLOBAL RUNDOWN FROM
;			  RECEIVE-BY-REFERENCE PACKETS
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
;	M. S. HARVEY	13-OCT-81
;		MSH196 -- MOVE FORMER $CLSRF SUBROUTINE       DIRECTLY
;			  INTO EXIT PROCESSING CODE PATH. THIS
;			  SWALLOWS UP MSH008. $CLSRF WAS ORIGINALLY
;			  LOCATED IN MODULE REQSB.
;
;	M. S. HARVEY	20-OCT-81
;		MSH197 -- MAKE SURE THAT ANY ASTS QUEUED DURING
;			  I/O RUNDOWN ARE CLEANED UP
;
; EXIT DIRECTIVES
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$,CLKDF$,HDRDF$,PCBDF$,PKTDF$,TCBDF$
	CLKDF$			;DEFINE CLOCK BLOCK OFFSETS
	ABODF$			;DEFINE TASK ABORT CODES
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK O      FFSETS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;
; LOCAL SYMBOL DEFINITION
;

CLRMSK=T2.AST!T2.DST!T2.CKD!T2.HLT!T2.ABO!T2.CAF!T2.REX			;MSH121
CLRMSK=CLRMSK!<<T2.STP!T2.SPN!T2.WFR>*2>!T2.STP!T2.SPN!T2.WFR		;**-1

;+
; **-$DREIF-EXIT IF
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO TERMINATE THE EXECUTION OF THE
; ISSUING TASK IF, AND ONLY IF, AN INDICATED EVENT FLAG IS CLEAR.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(53.),DPB SIZE(2.).
;	WD. 01 -- EVENT F      LAG NUMBER OF EVENT FLAG THAT MUST BE CLEAR.
;
; INPUTS:
;
;	R0=EVENT FLAG MASK WORD.
;	R1=EVENT FLAG MASK ADDRESS.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF 'D.RS22' IS RETURNED IF THE SPECIFIED
;			EVENT FLAG IS SET      .
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS97' IF NO OR AN INVALID EVENT
;			FLAG NUMBER IS SPECIFIED.
;-

$DREIF::BIT	R0,(R1)		;EVENT FLAG CLEAR?
	BEQ	$DREXT		;IF EQ YES
	DRSTS	D.RS22		;SET DIRECTIVE STATUS

;+
; **-$DREXT-EXIT
;									;**-1
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO TERMINATE THE EXECUTION OF THE
; ISSUING TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(51.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS       OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	NOTE: $DREXT IS ALSO JUMPED TO FROM PRIVILEGED TASKS DIRECTLY.	;MSH129
;		IN THIS CASE, ONLY R5 IS REQUIRED TO BE LOADED AS	;MSH129
;		DESCRIBED ABOVE. ALSO, ON SYSTEMS SUPPORTING THE	;MSH165
;		EXECUTIVE COMMONS, THIS MEANS THAT KERNEL APR5		;MSH165
;		CANNOT BE ASSUMED TO BE MAPPED TO THE DIRECTIVE		;MSH165
;		DISPATCHER IN THE FIRST COMMON AT $DREXT.		;MSH165
;							      		;MSH174
;	SPECIAL NOTE: THIS ROUTINE IS ENTERED DIRECTLY WHEN A TASK	;MSH174
;		IS ABORTED AND ASSUMES THAT THE TASK HEADER IN		;MSH174
;		POOL IS INTACT. IF NOT, GROUP GLOBAL CONTEXT AND	;MSH174
;		FILE RESOURCE CLEANUP CANNOT BE DONE CORRECTLY.		;MSH174
;		THIS CAN ONLY HAPPEN AFTER A CHECKPOINT READ FAILURE,	;MSH174
;		WHICH IS HARDWARE RELATED. UNEXPECTED SYSTEM BEHAVIOR	;MSH174
;		MAY OCCUR IN THIS CASE.					;MSH174
;									;**-2
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	      NO STATUS IS RETURNED TO THE ISSUING TASK SINCE THIS DIRECTIVE
;	TERMINATES ITS EXECUTION.
;-

$DREXT::			;REFERENCE LABEL

	.IF DF	P$$OFF

	.IF DF	A$$CPS							;MSH021
									;MSH021
	BIT	#T3.ACP,T.ST3(R5) ;IS TASK AN ACP?
	BNE	$DREX1		;IF NE YES				;MSH115
									;MSH021
	.ENDC								;MSH021
									;MSH021
	MOV	#EX$SUC,T.EFLG+2(R5) ;SET SUCCESSFUL EXIT STATUS	;**-1
$DREX2::MOV	#S.CEXT,T.EFLG(R5) ;SET 'TASK EXIT' SECONDARY EXIT CODE	;MSH129
									;**-1
	.ENDC	;P$$OFF

$DREX1::      			;REF LABEL				;MSH115
									;MSH115
	.IF DF G$$EFN

	MOV	$HEADR,R4	;GET TASK HEADER ADDRESS		;MSH115
	BIT	#T2.WFR*2,T.ST2(R5) ;WAS TASK IN PRE-AST WAITFOR?	;MSH115
	BEQ	55$		;IF EQ NO				;MSH115
	MOV	H.EFSV(R4),R3	;GET EVENT FLAG MASK ADDRESS		;MSH049
	CALL	$DEAGF		;DEACCESS GROUP GLOBAL EVENT FLAGS	;**-5
	BIC	#T2.WFR*2,T.ST2(R5) ;DEACCESS PRE-AST WFR ONLY ONCE	;MSH115
55$:				;					;MSH115

	.IF DF	D$$PAR							;MSH045
									;MSH045
	MOV	$XCOM2,KISAR5	;MAP SECOND EXECUTIVE COMMON		;M      SH165
									;MSH045
	.ENDC								;MSH045
									;MSH045
	CALL	$UNLCK		;UNLOCK GROUP GLOBAL EVENT FLAGS	;MSH148
	BCS	57$		;IF CS ALREADY UNLOCKED			;MSH148
	CALL	$ELIM		;ELIMINATE THEM IF NECESSARY		;MSH148
57$:	MOV	$TKTCB,R5	;RESTORE TCB POINTER			;MSH148
									;MSH148
	.ENDC								;MSH148
									;MSH165
	.IF DF	D$$PAR							;MSH165
									;MSH165
	CLR	R4		;SET TYPE OF REQUEST TO REMOVE		;MSH165
	CALL	$CLRMV		;CANCEL MARK TIME REQUESTS		;MSH165
									;MSH165
	.IFF								;MS      H165
									;MSH045
	CALL	$DRCMT		;CANCEL MARK TIME REQUESTS		;MSH045
									;MSH165
	.ENDC								;MSH165
									;**-4
	.IF DF	C$$INT

	BIT	#T2.CKD,T.ST2(R5) ;DOES TASK POSSIBLY HAVE ANY ITB'S?
	BEQ	2$		;IF EQ NO
									;MSH165
	.IF DF	D$$PAR							;MSH165
	.IF NDF	G$$EFN							;MSH165
									;MSH165
	MOV	$XCOM2,KISAR5	;MAP 2ND EXEC COMMON			;MSH165
									;MSH165
	.ENDC								;MSH165
	.ENDC								;MSH165
									;MSH165
1$:	MOV	T.CPCB(R5),R1	;PICK UP NEXT ITB POINTER
	BE      Q	2$		;IF EQ NONE LEFT
	CALL	$DISIN		;DISCONNECT INTERRUPT VECTOR
	BR	1$		;
2$:				;REF LABEL

	.ENDC


	.IF DF	M$$CRX

	.IF DF	D$$PAR							;MSH165
									;MSH165
	MOV	$XCOM1,KISAR5	;ESTABLISH 1ST EXEC COMMON MAPPING	;MSH165
									;MSH165
	.ENDC								;MSH165
									;MSH165
	.IF DF	A$$CLI							; MF203
									; MF203
	BIT	#T3.CLI,T.ST3(R5) ;IS TASK A CLI			; MF203
	BEQ	205$		;IF EQ NO				; MF203
	CALL	$RLCIB		;RELEASE CLI COMMAND BUFFERS		; MF203
	BR	207$		;					; MF203
				      					; MF203
	.ENDC								; MF203
									; MF203
									; MF203
205$:	CALL	$RLMCB		;RELEASE MCR COMMAND BUFFER		; MF203
207$:				;REFERENCE LABEL			; MF203
									;**-1
	.ENDC


	CMP	R5,$LSTLK	;TASK OWN MCR DATA BASE LOCK?
	BNE	3$		;IF NE NO
	CLR	$LSTLK		;CLEAR OWNER TCB ADDRESS
3$:	BIS	#T2.HLT,T.ST2(R5) ;SET TO HALT TASK

	CLRB	$CXDBL		;MAKE SURE CONTEXT SWITCHING ENABLED

	.IF DF	F$$LPP!P$$RFL!R$$SND!P$$SRF!A$$BRT&A$$TRP		;MSH121
									;**-1
	MOV	T.SAST(R5),R0	;GET ADDRESS OF       SPEC AST BLOCK
	BEQ	35$		;IF EQ LIST IS EMPTY
	MOV	R0,@T.ASTL+2(R5) ;LINK BLOCK TO NORMAL AST LIST
32$:	MOV	R0,R1		;SAVE ADDRESS OF SPEC AST BLOCK
	MOV	(R0),R0		;GET NEXT BLOCK
	BNE	32$		;IF NE MORE BLOCKS IN LIST
	MOV	R1,T.ASTL+2(R5)	;FIX UP LAST POINTER IN LISTHEAD
	CLR	T.SAST(R5)	;NO MORE SPEC ASTS
35$:				;REF LABEL

	.ENDC								;MSH121
									;**-1
	.IF DF	K$$AST!A$$TRP						;MSH091
									;**-1
	JSR	R5,MTQUE	;EMPTY AST QUEUE
	.WORD	T.ASTL		;OFFSET TO AST QUEUE LISTHEAD
	.WORD	$DE      ACB		;ADDRESS OF DEALLOCATION ROUTINE

	.ENDC


	.IF DF	R$$SND

	BIT	#T3.NSD!T3.ACP,T.ST3(R5) ;FLUSH RECEIVE QUEUE?
	BNE	4$		;IF NE NO
	JSR	R5,MTQUE	;EMPTY RECEIVE QUEUE
	.WORD	T.RCVL		;OFFSET TO RECEIVE QUEUE LISTHEAD
	.WORD	$DEPKT		;ADDRESS OF DEALLOCATION ROUTINE
4$:				;REF LABEL

	.ENDC


	.IF DF	P$$LAS&P$$SRF

	.IF DF	G$$EFN							;MSH049
									;MSH049
	MOV	$HEADR,R4	;GET CURRENT TASK HEADER ADDRESS	;MSH049
									;MSH049
	.ENDC	;G$$EFN							;MSH049
									;MSH196
; CL      EAR CURRENT TCB FROM ALL UNRECEIVED SEND-BY-REFERENCE PACKETS	;MSH196
									;MSH196
	MOV	$TSKHD,R1	;GET FIRST TCB IN ATL			;MSH196
410$:	TSTB	T.SRCT(R5)	;ANY UNRECEIVED SREF PACKETS?		;MSH196
	BEQ	440$		;IF EQ NO				;MSH196
	MOV	T.TCBL(R1),-(SP) ;END OF LIST?				;MSH196
	BEQ	430$		;IF EQ YES				;MSH196
	ADD	#T.RRFL,R1	;POINT TO RECEIVE BY REFERENCE LIST	;MSH196
420$:	MOV	(R1),R1		;GET NEXT REC BY REF PACKET		;MSH196
	BEQ	430$		;IF EQ END OF LIST			;MSH196
	CMP	2(R1),R5	;DOES IT POINT TO EXITING       TASK?		;MSH196
	BNE	420$		;IF NE NO				;MSH196
	DECB	T.SRCT(R5)	;DECREMENT UNRECEIVED SREF COUNT	;MSH196
									;MSH196
	.IF DF	G$$EFN							;MSH196
									;MSH196
	MOV	R1,-(SP)	;SAVE PACKET ADDRESS			;MSH196
	MOV	6(R1),R3	;GET EVENT FLAG MASK ADDRESS		;MSH196
	CALL	$DEAGF		;DEACCESS IF GROUP GLOBAL		;MSH196
	MOV	(SP)+,R1	;RESTORE PACKET ADDRESS			;MSH196
									;MSH196
	.ENDC								;MSH196
									;MSH196
	MOV	R1,R3		;COPY PACKET ADDRESS			;MSH196
	TST	(R3)+		;POINT TO SENDER TCB POI      NTER		;MSH196
	CLR	(R3)+		;CLEAR POINTER TO EXITING TASK		;MSH196
	MOV	T.NAM(R5),(R3)+	;STORE SENDER TASK NAME			;MSH196
	MOV	T.NAM+2(R5),(R3) ;					;MSH196
	BR	420$		;GO AGAIN				;MSH196
430$:	MOV	(SP)+,R1	;GET ADDRESS OF NEXT TCB IN LIST	;MSH196
	BNE	410$		;IF NE, NOT NULL TASK			;MSH196
									;MSH196
440$:	JSR	R5,MTQUE	;EMPTY RECEIVE BY REFERENCE QUEUE	;MSH196
	.WORD	T.RRFL		;OFFSET TO RECEIVE BY REF LISTHEAD	;**-1
	.WORD	$DEPKT		;ADDRESS OF DEALLOCATION ROUTINE

	.ENDC

	.IF DF	D$$PAR		      					;MSH165
									;MSH165
	MOV	$XCOM1,KISAR5	;MAP DISPATCHER RETURN ADDRESS		;MSH165
									;MSH165
	.ENDC								;MSH165

	.IF DF	I$$RAR!I$$RDN!M$$MGE

5$:	MOV	#SCNLN,-(SP)	;SET ADDRESS OF LUT SCANNING CO-ROUTINE
	TSTB	T.IOC(R5)	;ANY I/O OUTSTANDING?


	.IF DF	T$$BUF

	BNE	6$		;IF NE YES
	TSTB	T.TIO(R5)	;TASK HAVE OUTSTANDING BUFFERED I/O?	;MSH046
									;**-1
	.ENDC


	BEQ	30$		;IF EQ NO
6$:	BIT	#T2.ABO,T.ST2(R5) ;TASK ALREADY MARKED FOR ABORT?
	BNE	10$		;IF NE YES
	MOV	#S.I      OMG,R0	;SET REASON FOR ABORT
	CALL	$ABCTK		;ABORT CURRENT TASK
10$:	MOV	(SP),-(SP)	;DUPLICATE ADDRESS OF LUT SCANNING CO-ROUTINE
20$:	CALL	@(SP)+		;GET NEXT ASSIGNED LUN
	BCS	30$		;IF CS END OF LOGICAL UNIT TABLE
	CALL	$IOKIL		;KILL I/O ON UNIT FOR CURRENT TASK
	BR	20$		;GO AGAIN
30$:	CALL	@(SP)+		;GET NEXT ASSIGNED LUN
	BCS	100$		;IF CS END OF LOGICAL UNIT TABLE
	CMP	$TKTCB,U.ATT(R5) ;UNIT ATTACHED TO CURRENT TASK?
	BNE	40$		;IF NE NO
	MOV	#IO.DET,R4	;SET DETACH I/O FUNCTION
	BR	50$		;
40$:	MO      V	(R1),R2		;FILE OPEN ON UNIT?
	BEQ	30$		;IF EQ NO
	ASR	R2		;ACCESS OR DEACCESS PENDING?
	BCS	30$		;IF CS YES
	MOV	#IO.CLN,R4	;SET CLOSE LUN I/O FUNCTION
50$:	CMP	(SP)+,(SP)+	;CLEAN STACK
	MOV	R1,-(SP)	;SAVE ADDRESS OF SECOND LUN WORD
	MOV	#I.LGTH,R1	;SET LENGTH OF BLOCK NEEDED
	CALL	$ALOCB		;ALLOCATE I/O PACKET
	MOV	(SP)+,R3	;RETRIEVE ADDRESS OF SECOND LUN WORD
	BCS	90$		;IF CS NO CORE AVAILABLE
	MOV	R0,R1		;COPY ADDRESS OF I/O PACKET
	TST	(R0)+		;POINT TO SECOND WORD
	MOV	$TKTCB,R2	;GET ADDRE      SS OF TCB OF CURRENT TASK
	MOVB	T.IOC(R2),-(SP)	;SAVE CURRENT I/O COUNT
	INCB	T.IOC(R2)	;INCREMENT OUTSTANDING I/O COUNT
	MOVB	T.PRI(R2),(R0)+	;SET REQUEST PRIORITY
	CLRB	(R0)+		;CLEAR EVENT FLAG NUMBER
	MOV	R2,(R0)+	;INSERT CURRENT TASK TCB ADDRESS
	MOV	R3,(R0)+	;INSERT ADDRESS OF SECOND LUN WORD
	MOV	R5,(R0)+	;INSERT UCB ADDRESS
	MOV	R4,(R0)+	;INSERT I/O FUNCTION CODE
	CMP	#IO.CLN,R4	;CLOSE LUN I/O FUNCTION?
	BNE	60$		;IF NE NO
	INC	@U.VCB(R5)	;INCREMENT VOLUME TRANSACTION COUNT
	INC	(R3)		;IN      TERLOCK LUN USAGE
60$:	MOV	#<I.LGTH-I.IOSB>/2,R2 ;SET LOOP COUNT			;MSH046
70$:	CLR	(R0)+		;CLEAR REMAINDER OF I/O PACKET		;**-1
	DEC	R2		;ANY MORE TO CLEAR?
	BGT	70$		;IF GT YES
	CALL	$DRQRQ		;QUEUE I/O REQUEST
	MOV	$TKTCB,R5	;GET ADDRESS OF TCB OF CURRENT TASK
	CMPB	T.IOC(R5),(SP)+	;REQUEST ALREADY FINISHED?
	BLOS	5$		;IF LOS YES				;MSH116
80$:	BIS	#TS.RDN,T.STAT(R5) ;SET I/O RUNDOWN IN PROGRESS		;**-1
90$:	CALLR	$TKWSE		;WAITFOR SIGNIFICANT EVENT
100$:	TSTB	T.IOC(R5)	;ANY I/O STILL OUTSTANDIN      G?
	BNE	80$		;IF NE YES


	.IF DF	T$$BUF

	TSTB	T.TIO(R5)	;TASK HAVE OUTSTANDING BUFFERED I/O?	;MSH046
	BNE	80$		;IF NE YES				;**-1

	.ENDC

									;MSH197
	.IF DF	A$$TRP!K$$AST						;MSH197
									;MSH197
	TST	T.ASTL(R5)	;ASTS DECLARED DURING I/O RUNDOWN?	;MSH197
	BEQ	91$		;IF EQ NO, CONTINUE EXIT PROCESSING	;MSH197
	RETURN			;RESCHEDULE CURRENT TASK ($SETCR CALLED);MSH197
									;MSH197
	.ENDC								;MSH197

	.ENDC

91$:	MOV	$HEADR,R4	;GET ADDRESS OF CURRENT TASK HEADER	;MSH1      97
									;MSH197
	.IF DF	P$$OFF

	MOV	$TSKHD,R0	;POINT TO FIRST INSTALLED TASK TCB
92$:	TST	T.RDCT(R5)	;ANY RUNDOWN OPERATIONS REMAINING?
	BEQ	98$		;IF EQ NO
	MOV	T.TCBL(R0),-(SP) ;SAVE POINTER TO NEXT INSTALLED TASK
	BEQ	96$		;IF EQ CURRENT TASK IS NULL TASK
	ADD	#T.OCBH,R0	;POINT TO OCB QUEUE OF TASK
94$:	MOV	(R0),R0		;POINT TO NEXT ENTRY IN LIST
	BEQ	96$		;IF EQ THERE IS NONE
	CMP	O.PTCB(R0),R5	;IS EXITING TASK THE PARENT?
	BNE	94$		;IF NE NO
	DEC	T.RDCT(R5)	;DECREMENT RUNDOWN COUNT
	CL      R	O.PTCB(R0)	;INDICATE PARENT TASK HAS EXITTED
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
	CMP	O.EFN(R0),#64.	;GROUP GLOBAL EVENT FLAG?		;MSH049
	BLOS	94$		;IF LOS NO				;MSH049
	MOV	R0,-(SP)	;SAVE OCB POINTER			;MSH049
	MOV	O.EFN(R0),R0	;GET EVENT FLAG NUMBER			;MSH049
	CALL	$CEFI		;CONVERT TO MASK AND MASK ADDRESS	;MSH049
	MOV	R1,R3		;COPY EVENT FLAG MASK ADDRESS		;MSH049
	CALL	$DEAGF		;DEACCESS GROUP GLOBAL EVENT FLAGS	;MSH049
	MOV	(SP)+,R0	;RESTORE OCB POINTER			;MSH049
	      								;MSH049
	.ENDC								;MSH049
									;MSH049
	BR	94$		;TRY TO REMOVE ANY MORE
96$:	MOV	(SP)+,R0	;RESTORE TCB ADDRESS
	BNE	92$		;IF NE NO
98$:				;REF LABEL

	.ENDC	;P$$OFF

	ADD	#T.ST2,R5	;POINT TO SECOND TASK STATUS WORD


	.IF DF	T$$KMG

	BIT	#T2.ABO,(R5)	;TASK MARKED FOR ABORT?
	BEQ	110$		;IF EQ NO
	MOV	$TKNPT,R0	;GET TERMINATION NOTIFICATION TCB ADDRESS
	BEQ	110$		;IF EQ NOT IN SYSTEM
	CMP	$TKTCB,R0	;TERMINATION NOTIFICATION TASK BEING TERMINATED?
	BEQ	103$		;IF EQ YES
	BI      S	#TS.MSG,-(R5)	;SET ABORT MESSAGE IN PROGRESS
	CALL	$EXRQN		;REQUEST TERMINATION NOTIFICATION TASK
									;MSH165
	.IF DF	I$$RAR!I$$RDN!M$$MGE					;MSH165
									;MSH165
	BR	90$		;WAITFOR SIGNIFICANT EVENT		;MSH165
									;MSH165
	.IFF								;MSH165
									;MSH165
	CALLR	$TKWSE		;WAITFOR SIGNIFICANT EVENT
									;MSH165
	.ENDC								;MSH165
									;MSH165
103$:	MOV	$ACTHD,R0	;GET ADDRESS OF FIRST TCB
107$:	BIC	#TS.MSG,T.STAT(R0) ;CLEAR WAITING FOR MESSAGE
	BIC	#T2.ABO,T.ST2(R0)       ;CLEAR MARKED FOR ABORT
	MOV	T.ACTL(R0),R0	;GET ADDRESS OF NEXT TCB
	TST	T.ACTL(R0)	;NULL TASK?
	BNE	107$		;IF NE MORE TO GO
110$:				;REF LABEL

	.ENDC


	.IF DF	I$$RAR

	BIT	#T3.REM,2(R5)	;REMOVE TASK AT EXIT?
	BEQ	120$		;IF EQ NO
	MOV	#M$$CRB,R1	;SET LENGTH OF BLOCK NEEDED
	CALL	$ALOCB		;ALLOCATE CORE BLOCK
	BCS	90$		;IF CS WAITFOR SIGNIFICANT EVENT
	MOV	R0,-(SP)	;SAVE ADDRESS OF CORE BLOCK
	TST	(R0)+		;POINT TO SECOND WORD IN BLOCK
	MOV	T.UCB-T.ST2(R5),(R0)+ ;INSERT TI UCB ADDRESS
	M      OV	(PC)+,(R0)+	;INSERT REMOVE COMMAND
	.ASCII	/RE/		;
	MOV	(PC)+,(R0)+	;
	.ASCII	/M /		;
	MOV	T.NAM-T.ST2(R5),R1 ;GET FIRST HALF OF TASK NAME
	CALL	$C5TA		;CONVERT TO ASCII
	MOV	T.NAM+2-T.ST2(R5),R1 ;GET SECOND HALF OF TASK NAME
	CALL	$C5TA		;CONVERT TO ASCII
	MOVB	#33,(R0)	;INSERT ALTMODE AS TERMINAL BYTE
	MOV	(SP)+,R1	;RETRIEVE ADDRESS OF CORE BLOCK
	CALL	$QMCR		;QUEUE MCR COMMAND LINE TO MCR		;MSH103
									;**-1
	.ENDC


120$:				;REF LABEL				;MSH174
									;MSH174
;									;MSH17      4
; IN CASE OF CHECKPOINT READ FAILURE, IT IS LIKELY THAT THE TASK	;MSH174
; HEADER IS GARBAGE. THUS, IF THE TASK HAD GROUP GLOBAL CONTEXT		;MSH174
; ACTIVE, IT IS LIKELY THAT IT HAS NOT AND WILL NEVER BE RUN DOWN	;MSH174
; CORRECTLY. THE FOLLOWING CODE ENSURES A 'CLEAN SLATE' CONCERNING	;MSH174
; GROUP GLOBAL CONTEXT IN CASE THIS TASK IS INVOKED AGAIN.		;MSH174
;									;MSH174
									;MSH174
	.IF DF	G$$EFN							;MSH174
									;MSH174
	BIC	#T3.GFL,2(R5)	;UNLOCK TASK FROM GROUP GLOBAL EFNS	;      MSH174
									;MSH174
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH174
	CLRB	T.GGF-T.ST2(R5)	;CLEAR USE COUNT FOR TASK		;MSH174
									;MSH174
	.ENDC								;MSH174
									;MSH174
	.ENDC								;MSH174
									;MSH174
	BIS	#TS.EXE,-(R5)	;DEACTIVATE TASK			;MSH174
	BIC	#TS.CKR!TS.MSG,(R5)+ ;CLEAR STATUS BITS			;**-1
	BIC	#CLRMSK,(R5)	;


	.IF DF	A$$PRI

	MOVB	T.DPRI-T.ST2(R5),T.PRI-T.ST2(R5) ;RESTORE TASK PRIORITY

	.ENDC


	.IF DF	D$$ISK

	BIT	#T2.FXD,(R5)+	;TASK FIXED IN M      EMORY?
	BNE	130$		;IF NE YES
	BIS	#TS.OUT,-4(R5)	;SET TASK OUT OF MEMORY


	.IF DF	P$$LAS

	MOV	T.PCB-T.ST3(R5),R0 ;POINT TO TASK PCB
	MOV	R0,-(SP)	;SAVE CURRENT PCB POINTER
	BIT	#PS.SYS,P.STAT(R0) ;IS IT A SYSTEM CONTROLLED PARTITION?
	BEQ	124$		;IF EQ NO
	MOV	P.MAIN(R0),(SP)	;POINT BACK TO MAIN PCB
124$:	MOV	R5,-(SP)	;SAVE ADDRESS OF THIRD STATUS WORD
	TST	T.ATT-T.ST3(R5)	;ATTACH QUEUE EMPTY (IF EQ LOAD FAILURE)
	BNE	125$		;IF NE NO
	MOV	R5,R0		;COPY TCB POINTER
	SUB	#T.ST3,R0	;POINT TO ST      ART OF TCB
	CALL	$RLPAR		;RELEASE TASK PARTITION
	MOV	T.PCB-T.ST3(R5),R0 ;PICK UP TASK PCB ADDRESS
	BIT	#PS.SYS,P.STAT(R0) ;SYSTEM CONTROLLED PARTITION?
	BEQ	125$		;IF EQ NO
	MOV	#P.LGTH,R1	;SET SIZE TO RELEASE
	CALL	$DEACB		;DEALLOCATE TASK PCB
125$:	MOV	(SP),R5		;PICK UP ADDRESS OF THIRD STATUS WORD
	MOV	T.ATT-T.ST3(R5),R5 ;POINT TO NEXT ATTACHMENT DESCRIPTOR
	BEQ	126$		;IF EQ THERE IS NONE
	SUB	#A.TCBL,R5	;POINT TO START OF ATTACHMENT DESCRIPTOR
	CALL	$DETRG		;DETACH THE REGION
	BR	125$		;
1      26$:	MOV	(SP)+,R5	;RESTORE ADDRESS OF THIRD STATUS WORD
	MOV	(SP)+,T.PCB-T.ST3(R5) ;RESET TASK PCB ADDRESS

	.ENDC


	.IF DF	M$$MGE

	MOV	R4,R0		;SET ADDRESS OF TASK HEADER
	MOV	H.HDLN(R0),R1	;GET LENGTH OF HEADER IN BYTES
	CALL	$DEACB		;DEALLOCATE HEADER

	.ENDC


	MOV	$TKTCB,R0	;SET ADDRESS OF TASK TCB


	.IF NDF	P$$LAS


	.IF DF	D$$YNM&M$$MGE

	MOV	T.PCB(R0),R4	;SAVE ADDRESS OF TASK PCB

	.IFTF
									;MSH165
	CALL	$RLPAR		;RELEASE TASK PARTITION

	.IFT

	BIT	#PS.SYS,P.ST      AT(R4) ;SYSTEM CONTROLLED PARTITION?
	BEQ	130$		;IF EQ NO
	MOV	$TKTCB,R0	;RETRIEVE ADDRESS OF TCB
	MOV	P.MAIN(R4),T.PCB(R0) ;RESET TASK PCB POINTER
	MOV	R4,R0		;SET ADDRESS OF BLOCK TO RELEASE
	MOV	#P.LGTH,R1	;SET LENGTH OF BLOCK TO RELEASE
	CALL	$DEACB		;DEALLOCATE PARTITION CONTROL BLOCK

	.ENDC


	.ENDC


130$:				;REFERENCE LABEL

	.ENDC


	.IF DF P$$OFF

132$:	MOV	R5,R0		;COPY POINTER TO THIRD STATUS WORD

	.IF DF D$$ISK

	ADD	#T.OCBH-T.ST3,R0 ;POINT TO OCB QUEUE LISTHEAD

	.      IFF	;D$$ISK

	ADD	#T.OCBH-T.ST2,R0 ;POINT TO OCB QUEUE LISTHEAD

	.IFTF	;D$$ISK

	CALL	$QRMVF		;REMOVE NEXT OCB
	BCS	134$		;IF CS, THERE IS NONE

	.IFT	;D$$ISK

	MOVB	T.EFLG-T.ST3(R5),R2 ;GET SECONDARY EXIT STATUS CODE	;MSH129
	MOV	T.EFLG+2-T.ST3(R5),R0 ;PICK UP SAVED EXIT STATUS

	.IFF	;D$$ISK

	MOVB	T.EFLG-T.ST2(R5),R2 ;GET SECONDARY EXIT STATUS CODE	;MSH129
	MOV	T.EFLG+2-T.ST2(R5),R0 ;PICK UP SAVED EXIT STATUS

	.ENDC	;D$$ISK

	CALL	$QUEXT		;QUEUE EXIT STATUS TO PARENT
	BR	132$		;GO       AGAIN
134$:				;REF LABEL

	.ENDC	;P$$OFF


	CLR	$HEADR		;DO NOT SAVE CONTEXT OF CURRENT TASK
	MOV	$TKTCB,R0	;GET ADDRESS OF CURRENT TCB
	CALL	$ACTRM		;REMOVE TCB FROM THE ATL QUEUE


	.IF DF	M$$CRX

	BIT	#T3.MCR,(R5)	;MCR EXTERNAL FUNCTION TASK?
	BEQ	140$		;IF EQ NO
	BIC	#T3.MCR,(R5)	;CLEAR MCR FUNCTION FLAG
									; MF211
									; MF211
	.IF DF	A$$CLI							; MF211
									; MF211
	MOV	#6,R1		;SET SIZE OF TASK EXIT BLOCK		; MF211
									; MF211
	.IFF	;A$$CLI							; MF211
		      							; MF211
	MOV	#4,R1		;SET SIZE OF BLOCK REQUIRED
									; MF211
	.IFTF	;A$$CLI							; MF211
									; MF211
	CALL	$ALOCB		;ALLOCATE CORE BLOCK
	BCS	140$		;IF CS ALLOCATION FAILURE
	MOV	R0,R1		;COPY ADDRESS OF BLOCK
	TST	(R0)+		;POINT TO SECOND WORD OF BLOCK
									; MF211
	.IFT	;A$$CLI							; MF211
									; MF211
	MOV	#1,(R0)+	;SET SECOND WORD			; MF211
									; MF211
	.ENDC	;A$$CLI							; MF211
									; MF211
									; MF211
	MOV	T.UCB-T.ST3(R5),(R0) ;INSERT TI UCB ADD      RESS
	INC	(R0)		;SET FLAG TO SIGNIFY MCR PROMPT
	CALL	$QMCRL		;QUEUE MCR COMMAND LINE

	.ENDC


140$:	CALLR	$DRDSE		;DECLARE SIGNIFICANT EVENT

;
; SUBROUTINE TO EMPTY QUEUE
;


	.IF DF	K$$AST!A$$TRP!R$$SND!P$$SRF				;MSH091
									;**-1
MTQUE:	MOV	(R5)+,R4	;GET OFFSET TO QUEUE LISTHEAD
	ADD	(SP),R4		;CALCULATE ADDRESS OF QUEUE LISTHEAD
10$:	TST	(R5)+		;ADVANCE TO RETURN ADDRESS
13$:	MOV	R4,R0		;SET ADDRESS OF LISTHEAD
	CALL	$QRMVF		;REMOVE AN ENTRY FROM QUEUE
	BCS	40$		;IF CS NO ENTR      IES LEFT
	MOV	R1,R0		;SET ADDRESS OF BLOCK TO DEALLOCATE

	.IF DF	A$$TRP!K$$AST						;MSH091
									;**-1
	CMP	#T.ASTL,-4(R5)	;PROCESSING AST QUEUE?
	BNE	20$		;IF NE, NO, JUST DEALLOCATE PACKET
	MOVB	A.CBL(R0),R1	;SET LENGTH OF BLOCK (FOR ASTS ONLY)	;MSH091
	BGT	20$		;IF GT LENGTH SPECIFIED (AST'S ONLY)	;**-1
									;MSH091
	.IF DF	K$$AST							;MSH091
									;MSH091
	BMI	30$		;IF MI, ITS A KERNEL AST		;MSH091
									;MSH091
	.ENDC								;MSH091
									;**-1
	.IF DF A$$TRP

	TST      	A.CBL(R0)	;IS IT UNSOL CHAR AST?			;MSH091
	BNE	18$		;IF NE, NO, ITS A SPECIFIED AST		;**-1
	MOV	R4,-(SP)	;SAVE R4
	MOV	R5,-(SP)	;SAVE R5

	.IF DF M$$MGE

	CMP	-(R0),-(R0)	;POINT TO KISAR5 VALUE OF DEALL SUBR
	MOV	(R0)+,KISAR5	;MAP THE SUBROUTINE
	CALL	@(R0)+		;DEALLOCATE THE BLOCK

	.IFF	;M$$MGE

	CALL	@-2(R0)		;CALL THE DEALLOCATION ROUTINE

	.ENDC	;M$$MGE

	MOV	(SP)+,R5	;RESTORE REGS
	MOV	(SP)+,R4	;
	BR	13$		;GO AGAIN
18$:	MOV	#C.LGTH,R1	;SET SIZE OF SPECIFIED AST BLOCK

	.ENDC	;A$      $TRP

	.ENDC	;K$$AST!A$$TRP						;MSH091
									;**-1
20$:				;					;MSH183
									;MSH183
	.IF DF	P$$SRF&G$$EFN						;MSH183
									;MSH183
	CMP	#T.RRFL,-4(R5)	;PROCESSING RREF QUEUE?			;MSH183
	BNE	23$		;IF NE NO				;MSH183
	MOV	2(R0),R1	;GET SENDER'S TCB ADDRESS		;MSH183
	BEQ	23$		;IF EQ NO EVENT FLAG RUNDOWN POSSIBLE	;MSH183
	MOV	#AK.GGF,A.CBL(R0) ;CONVERT TO KERNEL AST CONTROL BLOCK	;MSH183
	ADD	#T.ASTL,R1	;POINT TO SENDER'S AST QUEUE		;MSH183
	MOV	(R1),(R0)	;ESTABLISH PACKET'S POSI      TION IN QUEUE	;MSH183
	BNE	21$		;IF NE QUEUE WAS NOT EMPTY		;MSH183
	MOV	R0,2(R1)	;ESTABLISH END OF QUEUE			;MSH183
21$:	MOV	R0,(R1)		;ESTABLISH BEGINNING OF QUEUE		;MSH183
	BR	13$		;DEALLOCATE NEXT PACKET			;MSH183
23$:				;					;MSH183
									;MSH183
	.ENDC								;MSH183
									;MSH183
	CALL	@-(R5)		;DEALLOCATE CORE BLOCK			;MSH183
	BR	10$		;GO AGAIN				;**-1
									;MSH091
	.IF DF	K$$AST							;MSH091
									;MSH091
30$:	CRASH			;TASK CAN'T EXIT WITH KERNEL ASTS	;MSH091
									;      MSH091
	.ENDC	;K$$AST							;MSH091
									;**-23
40$:	RTS	R5		;

	.ENDC


;
; CO-ROUTINE TO SCAN LOGICAL UNIT TABLE
;


	.IF DF	I$$RAR!I$$RDN!M$$MGE

SCNLN:	MOV	(SP),R3		;SAVE RETURN ADDRESS
	CLR	(SP)		;START AT LUN ZERO
10$:	MOV	$TKTCB,R5	;GET ADDRESS OF CURRENT TASK TCB
	MOV	$HEADR,R4	;GET ADDRESS OF HEADER OF CURRENT TASK
20$:	MOV	(SP),R1		;GET NEXT LUN NUMBER
	INC	(SP)		;INCREMENT LUN NUMBER
	CMP	H.NLUN(R4),(SP)	;END OF LUT?
	BLO	30$		;IF LO YES
	CALL	$MPLNE		;MAP LUN NUMBER TO      UCB ADDRESS
	BCS	20$		;IF CS NO DEVICE ASSIGNED TO LUN
	MOV	R0,R5		;COPY UCB ADDRESS
	CALL	(R3)		;CALL THE CALLER BACK
	MOV	(SP)+,R3	;RETRIEVE RETURN ADDRESS
	BR	10$		;GO AGAIN
30$:	MOV	R3,(SP)		;SET RETURN ADDRESS
	RETURN			;

	.ENDC


	.END
          Ìy�ykQ	› c,        	.TITLE	SSTSR
	.IDENT	/11.08/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 11.08
;
; D. N. CUTLER 27-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;	J. R. COVERT
;
; MODIFIED BY:
;
;	M. S. HARVEY	25-AUG-80
;		MSH045 -- DRQIO FAULTS CAN ONLY OCCUR IF DIRCOM MAPPED
;
;	M      . S. HARVEY	13-NOV-80
;		MSH125 -- SET CRASH ORIGINATION BIT FOR CRASH ANALYSIS
;
;	M. S. HARVEY	5-MAY-81
;		MSH165 -- MODIFY MSH045 TO INCORPORATE SUPPORT FOR
;			  THE SECOND DIRECTIVE COMMON
;
; SYNCHRONOUS SYSTEM TRAP (SST) SERVICE ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	ABODF$,HDRDF$,HWDDF$,PKTDF$
	ABODF$			;DEFINE TASK ABORT CODES
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;
; LOCAL DATA
;
; FLOATING POINT E      XCEPTION VECTOR (FINAL SETUP OF THIS VECTOR AND, IF
; NECESSARY, THE PIRQ VECTOR IS PERFORMED IN INITL AND THE MCR SAVE
; COMMAND.)
;


	.IF DF	F$$LPP!F$$LTP

	.ASECT
.=244
	.WORD	$FLTRP		;
	.WORD	PR7		;

	.PSECT

	.ENDC


;
; FLOATING POINT STATUS AND FORK BLOCK
;


	.IF DF	F$$LPP

FLSTS:	.BLKW	2		;FLOATING POINT STATUS
FLFRK:	.BLKW	2		;FLOATING POINT FORK BLOCK
FLTCB:	.BLKW	1		;ADDRESS OF TCB CAUSING EXCEPTION TRAP

	.ENDC


;
; SEGMENT FAULT VECTOR
;


	.IF DF	M$$MGE      

	.ASECT
.=250
	.WORD	$SGFLT		;
	.WORD	PR7		;
	.CSECT

	.ENDC


;+
;
; **-$EMSST-NON RSX EMT/TRAP INSTRUCTION
;
; THIS ROUTINE IS TRANSFERED TO BY THE DIRECTIVE DISPATCHER WHEN A NON RSX
; EMT OR A TRAP INSTRUCTION IS EXECUTED. THE MACHINE STATE HAS ALREADY BEEN
; SAVED. THE EMT/TRAP CODE (LOW BYTE OF INSTRUCTION) IS SETUP TO BE
; PASSED TO THE USER AND CONTROL IS TRANSFERED TO THE SST EXIT ROUTINE.
;
; INPUTS:
;
;	R5=ADDRESS OF THE EMT/TRAP INSTRUCTION.
;
; OUTPUTS:
;
;	04(SP)=EMT      /TRAP CODE MULTIPLIED BY 2.
;	02(SP)=SST CODE (S.CEMT=EMT, S.CTRP=TRAP)			;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO USER STACK (6).	;**-1
;-

	.ENABL	LSB
$EMSST::			;REF LABEL


	.IF DF	M$$MGE

	MOV	(SP),R5		;GET EMT/TRAP INSTRUCTION
	BIC	#177400,(SP)	;CLEAR INSTRUCTION CODE
	ASL	(SP)		;MULTIPLY CODE BY 2
	MOV	#S.CEMT,-(SP)	;ASSUME NON-RSX EMT INSTRUCTION
	BIT	#400,R5		;EMT INSTRUCTION?

	.IFF

	CLR	-(SP)		;PICKUP SST CODE
	BISB	(R5)+,(SP)	;
	ASL	(SP)		;MULTIPLY CODE BY 2
	M      OV	#S.CEMT,-(SP)	;ASSUME NON-RSX EMT INSTRUCTION
	BITB	#1,(R5)		;EMT INSTRUCTION

	.ENDC


	BEQ	10$		;IF EQ YES-SET NUMBER OF BYTES
	MOV	#S.CTRP,(SP)	;SET FOR TRAP INSTRUCTION
10$:	MOV	#3*2,-(SP)	;SET NUMBER OF BYTES
	BR	SSTXT		;TAKE COMMON SST EXIT ROUTINE

;+
; **-$FLTRP-FLOATING POINT EXCEPTION (11/40)
;
; THIS ROUTINE IS TRAPPED TO WHEN AN 11/40 FLOATING POINT EXCEPTION FAULT
; OCCURS. THE CURRENT MACHINE STATE IS SAVED AND CONTROL IS TRANSFERED TO
; THE SST EXIT ROUTINE.
;
; INPUTS:
      ;
;	NONE.
;
; OUTPUTS:
;
;	02(SP)=SST CODE (S.CFLT).					;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO USER STACK (4).	;**-1
;-

$FLTRP::			;DEFINE UNCONDITIONALLY FOR VECTOR SETUP


	.IF DF	F$$LTP

	DIRSV$			;;;SAVE REGISTERS AND CLEAR PRIORITY
	MOV	#S.CFLT,-(SP)	;SET FOR FLOATING POINT EXCEPTION FAULT
	BR	20$		;SET NUMBER OF BYTES

	.ENDC


;+
; **-$FPPR7-$FPPR8-$FPPRQ-FLOATING POINT PROCESSOR EXCEPTION HANDLING
;
; THESE ROUTINES HANDLE EXCEPTION FAULTS FROM THE FLOATING PO      INT
; PROCESSOR.  THE FLOATING POINT EXCEPTION AND ADDRESS REGISTERS AND
; THE CURRENT TASK TCB ARE SAVED AND THEN AN ATTEMPT IS MADE TO QUEUE AN
; AST TO THE TASK AT FORK LEVEL.  THESE ROUTINES SUPPORT TWO MODES OF
; OPERATION DEPENDING ON WHETHER THE FPP'S EXCEPTION FAULTS CAN OCCUR
; WHILE THE PROCESSOR IS AT PRIORITY 7 OR NOT.  IF THE FPP'S EXCEPTION
; FAULT CAN OCCUR WHILE THE PROCESSOR IS AT PRIORITY 7, THEN THE
; PROCESSOR MUST HAVE A PIRQ REGISTER.  INITL AND THE MCR SAVE
; COMMAND DETERMINE       WHICH MODE OF OPERATION IS TO BE USED OR NOT
; DEPENDING ON WHETHER THE PROCESSOR HAS A PROGRAM INTERRUPT REQUEST
; REGISTER (PIRQ) OR NOT, AND SET UP THE FPP AND PIRQ VECTORS
; ACCORDINGLY.  THE ROUTINES OPERATE AS FOLLOWS.
;
;    1.	IF THE PROCESSOR DOES NOT HAVE A PIRQ REGISTER THEN THE FPP MUST
;	NEVER FAULT WHEN THE PROCESSOR IS AT PRIORITY 7 OR IT MUST BE
;	SYNCHRONOUS.  IN THIS CASE THE FLOATING POINT EXCEPTION VECTOR
;	POINTS TO $FPPR7, AND THE PROCESSOR SIMPLY CALLS INTERRUPT SAVE
;	AND F      ORK TO GET TO SYSTEM STATE.
;
;    2.	IF THE PROCESSOR HAS A PIRQ REGISTER, THE FLOATING POINT EXCEP-
;	TION TRAP VECTOR POINTS TO $FPPR8 AND THE PIRQ VECTOR POINTS TO
;	$FPPRQ.  FLOATING POINT TRAPS ARE CONVERTED TO PIRQ PRIORITY 1
;	INTERRUPTS AFTER SAVING THE FLOATING POINT STATUS.  ON THE PIRQ
;	TRAP AN INT SAVE AND FORK IS USED TO GET TO SYSTEM STATE.  NOTE
;	THAT THIS STRATEGY WOULD ALSO WORK FOR PROCESSORS DESCRIBED IN 1
;	ABOVE.
;
; INPUTS:
;
;	THE FLOATING POINT EXCEPTION REGISTER CONTA      INS THE REASON FOR THE
;	FAULT AND THE FLOATING POINT ADDRESS REGISTER CONTAINS THE ADDRESS
;	OF THE FAULTING INSTRUCTION.
;
; OUTPUTS:
;
;	AN ATTEMPT IS MADE TO QUEUE AN AST TO THE TASK CAUSING THE FAULT
;	WITH THE CONTENTS OF THE FLOATING POINT EXCEPTION REGISTER AND
;	AND ADDRESS REGISTER.
;-


	.IF DF	F$$LPP

$FPPR7::STST	FLSTS		;;;STORE FLOATING POINT EXCEP AND ADDR
	BR	14$		;;;

$FPPR8::STST	FLSTS		;;;STORE FLOATING POINT EXCEP AND ADDR
	BIS	#<2*256.>,PIRQ	;;;POST PROGRAMMED INTERRUP      T REQUEST
	RTI			;;;WAIT FOR PIRQ INTERRUPT

$FPPRQ::CLR	PIRQ		;;;DISABLE PROGRAM INTERRUPT REQUEST
14$:	MOV	$TKTCB,FLTCB	;;;MUST SAVE FAULTING TCB NOW
	CALL	$INTSV,PR1	;;;GO TO PRIORITY 1
	MOV	#FLFRK+4,R4	;;;SET ADDRESS OF FORK BLOCK
	CALL	$FORK0		;;;CREATE A SYSTEM PROCESS
	MOV	#AS.FPA,R4	;SET FLOATING POINT TYPE AST
	MOV	FLTCB,R5	;GET TCB ADDRESS OF FAULTING TASK
	CALL	$DASTT		;DECLARE FLOATING POINT AST
	BCS	15$		;IF CS NO AST DECLARED
	MOV	FLSTS,A.PRM+2(R1) ;INSERT AST PARAMETERS
	MOV	FLST      S+2,A.PRM(R1) ;
15$:	RETURN			;

	.IFF

$FPPR7::			;DEFINE LABELS FOR SAVE
$FPPR8::			;
$FPPRQ::			;

	.ENDC


;+
; **-$ILINS-ILLEGAL OR RESERVED INSTRUCTION
;
; THIS ROUTINE IS TRAPPED TO WHEN AN ILLEGAL OR RESERVED INSTRUCTION
; IS EXECUTED. THE CURRENT MACHINE STATE IS SAVED AND CONTROL IS TRANS-
; FERRED TO THE SST EXIT ROUTINE.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	02(SP)=SST CODE (S.CILI).					;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO THE USER STACK (4).	;**-1
;-      

$ILINS::DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY
	MOV	#S.CILI,-(SP)	;SET FOR ILLEGAL OR RESERVED INSTRUCTION
	BR	20$		;SET NUMBER OF BYTES

;+
; **-$IOTRP-IOT INSTRUCTION
;
; THIS ROUTINE IS TRAPPED TO WHEN AN IOT INSTRUCTION IS EXECUTED. IF THE
; STACK DEPTH IS NOT +1, THEN THE SYSTEM IS CRASHED VIA A JUMP TO
; $CRASH. ELSE THE CURRENT MACHINE STATE IS SAVED AND CONTROL IS TRANS-
; FERED TO THE SST EXIT ROUTINE.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	IF THE CURRENT STACK DEPTH IS N      OT +1, THEN THE SYSTEM IS CRASHED.
;	ELSE THE FOLLOWING ARGUMENTS ARE SETUP ON THE CURRENT STACK:
;
;	02(SP)=SST CODE (S.CIOT).					;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERRED TO THE USER STACK (4).	;**-1
;-

$IOTRP::TST	$STKDP		;;;RUNNING ON SYSTEM STACK?
	BLE	16$		;;;IF LE YES, FATAL SYSTEM ERROR	;MSH125
	DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY	;**-1
	MOV	#S.CIOT,-(SP)	;SET FOR IOT INSTRUCTION
	BR	20$		;SET NUMBER OF BYTES

;+
; **-$SGFLT-SEGMENT FAULT
;
; THIS ROUTINE IS TRAPPE      D TO WHEN A SEGMENT FAULT OCCURS. THE CURRENT
; MACHINE STATE IS SAVED, SR0 THRU SR2 ARE SETUP TO BE PASSED TO THE USER,
; AND CONTROL IS TRANSFERED TO THE SST EXIT ROUTINE.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	10(SP)=CONTENTS OF SR0.
;	06(SP)=CONTENTS OF SR2.
;	04(SP)=CONTENTS OF SR1.
;	02(SP)=SST CODE (S.CSGF).					;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO THE USER STACK (10.).;MSH125
;-									;**-2


	.IF DF	M$$MGE

$SGFLT::DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY
	      MOV	#SR0+4,R5	;POINT SR2
	MOV	(R5),-(SP)	;SAVE SR2
	MOV	(SP),-(SP)	;COPY SAVED SR2
	MOV	-(R5),-(SP)	;SAVE SR1
	MOV	-(R5),4(SP)	;SAVE SR0
	BIC	#160000,(R5)	;UNFREEZE MEMORY MANAGEMENT UNIT
	MOV	#S.CSGF,-(SP)	;SET FOR SEGMENT FAULT
	MOV	#5*2,-(SP)	;SET NUMBER OF BYTES
	BR	SSTXT		;TAKE COMMON SST EXIT ROUTINE

	.ENDC


;+
; **-$TRACE-TRACE (T-BIT) OR BREAK POINT INSTRUCTION (BPT) TRAP
;
; THIS ROUTINE IS TRAPPED TO WHEN A TRACE TRAP (T-BIT) OCCURS OR A BREAK-
; POINT TRAP INSTRUCTION IS EXECUT      ED. THE CURRENT MACHINE STATE IS SAVED
; AND CONTROL IS TRANSFERED TO THE SST EXIT ROUTINE.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	02(SP)=SST CODE (S.CBPT).					;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO THE USER STACK (4).	;**-1
;-

$TRACE::DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY
	MOV	#S.CBPT,-(SP)	;SET FOR TRACE OR BREAKPOINT TRAP
	BR	20$		;SET NUMBER OF BYTES

;+
; **-$TRP04-TRAPS AT 4 (ODD ADDRESS, NONEX MEM, ETC.)
;
; THIS ROUTINE IS TRAPPED TO WHEN A TRAP AT 4 OCCURS.       IF A STACK VIOLATION
; HAS CAUSED THE TRAP (I.E. A STACKPOINTER OF LESS THAN 400), THEN THE
; THE SYSTEM IS CRASHED. ELSE THE CURRENT MACHINE STATE IS SAVED AND
; CONTROL IS TRANSFERED TO THE SST EXIT ROUTINE.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	02(SP)=SST CODE (S.COAD).					;MSH125
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO THE USER STACK (4).	;**-1
;-

$TRP04::CMP	SP,#400		;;;STACK VIOLATION?
	BHIS	17$		;;;IF HIS NO				;MSH125
16$:				;;;					;MSH125
	.IF DF	C$$RSH							;MSH125
	      								;MSH125
	INC	$FMASK+4	;;;SET SYSTEM CRASH BIT (F3.CRA)	;MSH125
									;MSH125
	.ENDC	;C$$RSH							;MSH125
									;MSH125
	JMP	$CRASH		;;;CRASH THE SYSTEM			;MSH125
17$:	DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY	;MSH125
	CLR	-(SP)		;SET FOR ODD ADDRESS TRAP		;**-2
20$:	MOV	#2*2,-(SP)	;SET NUMBER OF BYTES
									;MSH125
	.DSABL	LSB							;**-2

;+
; **-SSTXT-COMMON SST EXIT ROUTINE
;
; CONTROL IS TRANSFERED TO THIS ROUTINE TO EFFECT AN SST. IF THE CURRENT
; STACK DEPTH IS NOT       ZERO, THEN THE SYSTEM IS CRASHED. ELSE AN ATTEMPT IS
; MADE TO EFFECT AN SST FOR THE CURRENT TASK. IF THE TASK DOES NOT HAVE
; AN APPROPRIATE SST VECTOR ENTRY OR A PUSH OF THE SST PARAMETERS ONTO THE
; TASK STACK CANNOT BE EFFECTED, THEN THE TASK IS ABORTED. ELSE THE SST
; IS SETUP AND A DIRECTIVE EXIT IS EXECUTED.
;
; INPUTS:  (MAPPED SYSTEM)
;
;	24(SP)=PS WORD SAVED BY SST TRAP.
;	22(SP)=PC WORD SAVED BY SST TRAP.
;	20(SP)=SAVED R5.
;	16(SP)=SAVED R4.
;	14(SP)=SAVED R3.
;	12(SP)=SAVED R2.
;	      10(SP)=SAVED R1.
;	06(SP)=SAVED R0.
;	04(SP)=SST PARAMETER (ZERO OR MORE PARAMETERS MAY BE SPECIFIED).
;	02(SP)=SST CODE.
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO USER STACK.
;
; INPUTS: (REAL MEMORY SYSTEM)
;
;	14(SP)=SAVED R3.
;	12(SP)=SAVED R2.
;	10(SP)=SAVED R1.
;	06(SP)=SAVED R0.
;	04(SP)=SST PARAMETER (ZERO OR MORE PARAMETERS MAY BE SPECIFIED).
;	02(SP)=SST CODE.
;	00(SP)=NUMBER OF BYTES TO BE TRANSFERED TO USER STACK.
;
; OUTPUTS:
;
;	AN ATTEMPT IS MADE TO EFFECT THE SPECIFIED S      ST FOR THE CURRENT TASK.
;-

SSTXT:	MOV	$HEADR,R5	;GET ADDRESS OF TASK HEADER


	.IF DF	M$$MGE

	CMP	#-1,$STKDP	;FAULT OCCUR AT STACK DEPTH ZERO?
	BNE	7$		;IF NE NO
	MOV	SP,R0		;COPY CURRENT STACK POINTER
	ADD	(SP),R0		;ADD NUMBER OF BYTES TO BE TRANSFERED
	MOV	16(R0),R0	;GET FAULT PC ADDRESS
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH045
	CMP	KISAR5,$XCOM1	;FIRST EXEC COMMON MAPPED?		;MSH165
	BNE	7$		;IF NE NO, SKIP EXEC BOUNDS CHECKS	;MSH165
									;MSH045
	.ENDC	;D$$P      AR							;MSH045
									;MSH045
	CMP	R0,#$DRLM1	;FAULT OCCUR IN DIRECTIVE DISPATCHER?
	BLO	3$		;IF LO NO
	CMP	R0,#$DRLM2	;FAULT OCCUR IN DIRECTIVE DISPATCHER?
	BLOS	90$		;IF LOS YES
3$:	CMP	R0,#$DQLM1	;FAULT OCCUR IN QIO DIRECTIVE?
	BLO	4$		;IF LO NO
	CMP	R0,#$DQLM2	;FAULT OCCUR IN QIO DIRECTIVE?
	BLOS	90$		;IF LOS YES
4$:				;REFERENCE LABEL


	.IF DF	P$$LAS

	CMP	R0,#$DPLM1	;FAULT OCCUR RETRIEVING DEF BLOCK ADDR?
	BLO	7$		;IF LO NO
	CMP	R0,#$DPLM2	;FAULT OCCUR RETRIEVING DEF BLOCK ADDR?      
	BLOS	90$		;IF LOS YES

	.ENDC


	.IFTF

7$:	TST	$STKDP		;STACK DEPTH ZERO?
	BNE	60$		;IF NE NO - FATAL SYSTEM ERROR
	MOV	R5,R4		;COPY ADDRESS OF HEADER
	ADD	#H.ODVA,R4	;POINT TO ODT SST VECTOR DESCRIPTOR
	CALL	10$		;SST ADDRESS IN ODT VECTOR?
	MOV	#80$,-(SP)	;SST ADDRESS IN TASK VECTOR?
10$:	MOV	(R4)+,R3	;GET ADDRESS OF SST VECTOR
	BEQ	20$		;IF EQ NO VECTOR THIS DESCRIPTOR
	CMP	4(SP),(R4)	;VECTOR LONG ENOUGH TO COVER SST?
	BHIS	20$		;IF HIS NO
	ADD	4(SP),R3	;POINT TO APPROPRIATE VECTOR E      NTRY

	.IF DF	A$$CHK!M$$MGE

	MOV	R3,R0		;SUPPLY VECTOR ELEMENT ADDRESS AND
	MOV	#2,R1		;TWO BYTE SIZE FOR CALL
	CALL	$ACHCK		;ADDRESS CHECK VECTOR ELEMENT
	BCS	20$		;IF CS THEN VECTOR ELEMENT NOT VALID

	.ENDC	;DF A$$CHK!M$$MGE

	.IFT

	MFPI	(R3)		;GET ADDRESS OF SST ROUTINE
	MOV	(SP)+,R3	;

	.IFF

	MOV	(R3),R3		;GET ADDRESS OF SST ROUTINE

	.IFTF

	BNE	30$		;IF NE SST ROUTINE FOUND
20$:	TST	(R4)+		;POINT TO NEXT VECTOR DESCRIPTOR
	RETURN			;
30$:	TST	(SP)+		;REMOVE RETURN ADDRESS      
	MOV	(SP),R1		;GET NUMBER OF BYTES TO BE TRANSFERED

	.IFT

	MFPI	SP		;GET CURRENT TASK STACK POINTER
	SUB	R1,(SP)		;CALCULATE NEW TOP OF STACK
	MOV	(SP),R0		;COPY NEW TOP OF STACK ADDRESS
	MTPI	SP		;RESTORE NEW TASK STACK POINTER

	.IFF

	MOV	(R5),R0		;GET CURRENT TASK STACK POINTER
	SUB	R1,R0		;CALCULATE NEW TOP OF STACK
	MOV	(R5),R4		;SAVE CURRENT TASK STACK POINTER
	MOV	R0,(R5)		;RESTORE NEW TASK STACK POINTER

	.IFTF


	.IF DF	A$$CHK!M$$MGE

	CALL	$ACHCK		;ADDRESS CHECK PUSH ONTO       TASK STACK
	BCS	70$		;IF CS ADDRESS CHECK FAILURE

	.ENDC


	.IFT

	CALL	$RELOM		;RELOCATE AND MAP STACK ADDRESS

	.IFF

	MOV	(R4)+,(R0)+	;MOVE SAVED R4
	MOV	(R4),(R0)+	;MOVE SAVED R5
	MOV	R3,(R0)+	;SET SST PC WORD
	CLR	(R0)+		;SET SST PS WORD

	.IFTF

	MOV	(SP)+,R1	;GET NUMBER OF BYTES TO TRANSFER
	CMP	-(R1),-(R1)	;ADJUST BY 4 BYTES (PS AND PC WORDS)
	ASR	R1		;CONVERT TO WORD COUNT
	TST	(SP)+		;REMOVE SST CODE FROM STACK
40$:	DEC	R1		;ANY MORE PARAMETERS TO TRANSFER?
	BLT	50$		;IF L      T NO
	MOV	(SP)+,(R0)+	;TRANSFER PARAMETER TO TASK STACK
	BR	40$		;
50$:				;REF LABEL

	.IFT

	MOV	#$STACK-4,R4	;POINT TO SAVED PC WORD
	MOV	(R4),(R0)+	;SAVE PC AT TRAP ON USER STACK
	MOV	R3,(R4)+	;SET SST PC WORD
	MOV	(R4),(R0)	;SAVE PS AT TRAP ON USER STACK
	MOV	#CMODE!PMODE,(R4) ;SET SST PS WORD

	.IFTF

	RETURN			;EXIT FROM TRAP

;
; SST FAULT AT NON ZERO STACK DEPTH-FATAL SYSTEM ERROR
;

60$:	CRASH			;CRASH SYSTEM

;
; SST CANNOT BE EFFECTED BECAUSE OF BAD TASK STACK
;


	.I      F DF	A$$CHK!M$$MGE

70$:	MOV	#S.CSST,2(SP)	;SET BAD STACK SST ABORT CODE

	.ENDC


;
; SST CANNOT BE EFFECTED BECAUSE OF NO SST VECTOR ENTRY
;

80$:	MOV	2(SP),R0	;SET SST ABORT CODE

	.IFT

	MOV	#$STACK-22,SP	;RELOAD EXEC STACK POINTER

	.IFF

	MOV	#$STACK-12,SP	;RELOAD EXEC STACK POINTER

	.IFTF

	CALLR	$ABCTK		;ABORT CURRENT TASK

;
; FAULT FROM PROTECTED LIMITS IN DRDSP OR DRQIO
;

	.IFT

90$:	INC	$STKDP		;CORRECT STACK DEPTH INDICATOR
	DRSTS	D.RS98		;SET DIRECTIVE STATUS      

	.ENDC


	.END
          of"kQ	› c,        	.TITLE	POWER
	.IDENT	/09.12/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 09.12
;
; D. N. CUTLER 1-OCT-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	CHUCK SPITZ
;	M. S. HARVEY
;	R. R. ADAMS
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-SEP-80
;		MSH119 -- DEFINE GLOBAL ENTRY PO      INT FOR AUTOCONFIGURE
;
;	M. S. HARVEY	19-SEP-80
;		MSH097 -- DON'T ACCESS UNIBUS MAP IF NOT THERE
;
;	M. S. HARVEY	13-NOV-80
;		MSH127 -- CLEAN UP CACHE MEMORY CONDITIONALIZATION
;
;		MSH128 -- IMPLEMENT NETWORK POWERFAIL RECOVERY
;
;	M. S. HARVEY	23-DEC-80
;		MSH134 -- PREVENT UNDEFINED VARIABLE INTERRUPTS WHEN
;			  RESTORING FLOATING POINT CONTEXT
;
;	DAN BROWN	7-JAN-81
;		DTB009 -- MODIFY HANDLING OF ERROR LOG ENTRIES FOR NEW
;			  ERROR LOGGER.
;
;	M. S. HARVEY	3-MAR-81
;		MSH154 --       CONSOLIDATE POWERFAIL AND CRASH STACKS
;
;	M. S. HARVEY	5-MAR-81
;		MSH156 -- ADD TRANSPORTABILITY SUPPORT FOR THE
;			  WATCHDOG TIMER
;
;	M. S. HARVEY	27-JUL-81
;		MSH181 -- HANDLE POSSIBLE T-BIT TRAPS FOLLOWING
;			  POWER UP ON LSI11/02 PROCESSORS
;
;	M. S. HARVEY	30-NOV-81
;		MSH149 -- ADD FLOATING POINT TRANSPORTABILITY
;
; POWERFAIL RECOVERY
;
; MACRO LIBRARY CALLS
;

	.MCALL	EPKDF$,HDRDF$,HWDDF$,PCBDF$,TCBDF$			;DTB009
	EPKDF$			;DEFINE ERROR LOG PACKET OFFSETS	;DTB009
	HDRDF$		      	;DEFINE TASK HEADER OFFSETS		;**-2
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;
; LOCAL DATA
;
; VOLATILE REGISTER STORAGE
;


	.IF DF	P$$RFL

;									;MSH154
; NOTE THAT THE POWERFAIL STACK IS ACTUALLY ALLOCATED IN THE		;MSH154
; CRASH MODULE WHERE IT DOES DOUBLE DUTY AS THE CRASH STACK,		;MSH154
; ON SYSTEMS WITH CRASH NOTIFICATION SUPPORT. OTHERWISE, THE		;MSH154
; POWERFAIL STACK IS ALLOCATED H      ERE. NOTE THAT ANY CHANGES TO		;MSH154
; THE DEFINITION OF THE STACK HERE MUST BE REFLECTED IN THE		;MSH154
; DEFINITION OF THE CRASH STACK AS WELL.				;MSH154
;									;MSH154
									;MSH154
	.IF DF	C$$RSH							;MSH154
									;MSH154
	.ASECT								;MSH154
									;MSH154
.=0									;MSH154
									;MSH154
	.IFF								;MSH154
									;MSH154
$CRPBF::			;BEGINNING OF POWERFAIL STACK		;MSH154
									;MSH154
	.IFTF								;MSH154
									;MSH154
	.BLKW	7		;R0 THRU R5 AND SP			;M      SH154
									;**-1
	.IF DF	L$$SI1							;MSH181
									;MSH181
	.BLKW	1		;SAVE BPT/T-BIT TRAP VECTOR CONTENTS	;MSH181
									;MSH181
	.ENDC								;MSH181

	.IF DF	M$$MGE


	.IF DF	M$$EXT

	.BLKW	<31.-5.>*2	;UNIBUS MAPPING REGISTERS

	.ENDC


	.BLKW	25.		;MEMORY MANAGEMENT REGISTERS

	.IFF


	.IF DF	E$$EAE

	.BLKW	3		;EAE REGISTERS

	.ENDC


	.ENDC


	.IF DF	F$$LPP

	.BLKW	27.		;FLOATING POINT REGISTERS

	.ENDC


PWSTK=.-2								;MSH154
									;MSH154
	.IFT      								;MSH154
									;MSH154
	.PSECT								;MSH154
									;MSH154
	.ENDC	;C$$RSH							;MSH154
									;**-1
;
; POWERFAIL VECTOR
;

	.IFTF

	.ASECT
.=24
PWVCT:	.WORD	PDOWN		;
	.WORD	PR7		;
	.PSECT

;+
; **-PDOWN-POWERFAIL INTERRUPT (DOWN)
;
; THIS ROUTINE IS ENTERED AS A RESULT OF A POWER DOWN INTERRUPT. ALL
; VOLATILE MACHINE REGISTERS ARE SAVED, THE POWERFAIL VECTOR IS SWITCHED
; TO THE POWER UP ROUTINE, AND THE PROCESSOR IS HALTED TO AWAIT THE
; POWER UP INTERRUPT.
;-
      
PDOWN:				;REF LABEL

	.IFT

	MOV	SP,$CRPBF+PWSTK	;;;SAVE CURRENT STACK POINTER		;MSH154
	MOV	#$CRPBF+PWSTK,SP ;;;SET ADDRESS OF REGISTER SAVE AREA	;MSH154
	MOV	R5,-(SP)	;;;SAVE REGISTERS R5 THRU R0		;**-2
	MOV	R4,-(SP)	;;;
	MOV	R3,-(SP)	;;;
	MOV	R2,-(SP)	;;;
	MOV	R1,-(SP)	;;;
	MOV	R0,-(SP)	;;;

	.IF DF	L$$SI1							;MSH181
									;MSH181
	MOV	@#14,-(SP)	;;;SAVE BPT/T-BIT SERVICE ROUTINE ADDR.	;MSH181
	MOV	#$TBIT,@#14	;;;RESET TO DISMISS T-BIT TRAPS		;MSH181
									;MSH181
	.ENDC					      			;MSH181

	.IF DF	M$$MGE


	.IF DF	M$$EXT

	TST	$UMRPT		;;;UNIBUS MAP EXISTS?			;MSH097
	BEQ	7$		;;;IF EQ NO, SKIP SAVING IT		;MSH097
	MOV	#UBMPR+<31.*4>,R0 ;;;POINT PAST LAST MAP REGISTER
	MOV	#31.-5.,R1	;;;SET COUNT OF REGISTERS TO SAVE
5$:	MOV	-(R0),-(SP)	;;;SAVE HIGH 6 BITS OF ADDRESS		;MSH097
	MOV	-(R0),-(SP)	;;;SAVE LOW 16 BITS OF ADDRESS		;**-1
	DEC	R1		;;;ANY MORE TO SAVE?
	BGT	5$		;;;IF GT YES				;MSH097
7$:				;;;REFERENCE LABEL			;MSH097
									;**-1
	.ENDC



	BIS	#PMODE      ,PS	;;;MAKE SURE PREVIOUS MODE IS USER
	MFPI	SP		;;;SAVE USER STACK POINTER
	MOV	#KISAR0+16.,R0	;;;POINT TO KERNEL ADDRESS REGISTER 7+2
	MOV	#UISAR0+16.,R1	;;;POINT TO USER ADDRESS REGISTER 7+2
	MOV	#UISDR0+16.,R2	;;;POINT TO USER DESCRIPTOR REGISTER 7+2
	MOV	#8.,R3		;;;SET LOOP COUNT
10$:	MOV	-(R0),-(SP)	;;;SAVE KERNEL ADDRESS REGISTER
	MOV	-(R1),-(SP)	;;;SAVE USER ADDRESS REGISTER
	MOV	-(R2),-(SP)	;;;SAVE USER DESCRIPTOR REGISTER
	DEC	R3		;;;ANYMORE TO SAVE?
	BGT	10$		;;;IF GT YES

	.IFF


      	.IF DF	E$$EAE

	MOV	SC,-(SP)	;;;SAVE EAE SHIFT COUNT
	MOV	AC,-(SP)	;;;SAVE EAE ACCUMULATOR
	MOV	MQ,-(SP)	;;;SAVE EAE MULTIPLIER-QUOTIENT

	.ENDC


	.ENDC


	.IF DF	F$$LPP

	TST	$HFMSK		;;;FPU PRESENT?				;MSH149
	BMI	35$		;;;IF MI NO, DON'T TRY TO ACCESS IT	;MSH149
	STFPS	-(SP)		;;;STORE FLOATING POINT STATUS
	SETD			;;;SET FLOATING DOUBLE MODE
	STD	R0,-(SP)	;;;SAVE FIRST FL. PT. ACCUMULATOR (FACC);MSH134
	STD	R1,-(SP)	;;;SAVE SECOND FACC			;MSH134
	STD	R2,-(SP)	;;;SAVE THIRD FACC			;MS      H134
	STD	R3,-(SP)	;;;SAVE FOURTH FACC			;MSH134
	LDD	R4,R0		;;;MOVE FIFTH FACC TO FIRST FACC	;MSH134
	STD	R0,-(SP)	;;;SAVE FIFTH FACC			;MSH134
	LDD	R5,R0		;;;MOVE SIXTH FACC TO FIRST FACC	;MSH134
	STD	R0,-(SP)	;;;SAVE SIXTH FACC			;MSH134
	CLR	-(SP)		;;;PUSH AN ADDRESS OF ZERO		;**-8
	CMP	@#244,#$FPPR7	;;;IS THERE A PIRQ REGISTER TO SAVE?
	BEQ	30$		;;;IF EQ NO, DO DUMMY SAVE OF LOCATION 0
	MOV	#PIRQ,(SP)	;;;SET FOR SAVE OF PIRQ
30$:	MOV	@(SP),-(SP)	;;;SAVE PIRQ REGISTER OR CONTENTS OF 0

	.END      C


35$:	MOV	#PUP,PWVCT	;;;SWITCH TO POWER UP ROUTINE		;MSH149
									;**-1
	.IFTF


	.IF DF	I$$PPF

	.IF DF LD$IP

	MOV	#.IP0,R0	;;;GET IP UCB
	MOV	(R0),R0		;;;GET IP DCB
	MOV	D.DSP(R0),R1	;;;GET IP DRIVER DISPATCH TABLE
	BEQ	40$		;;;DRIVER NOT LOADED OR RESIDENT
	MOV	D.PCB(R0),R0	;;;GET IPDRV PCB
	BEQ	40$		;;;IF EQ, DRIVER RESIDENT (LD$IP ?)
	MOV	P.REL(R0),KISAR5 ;;;MAP IPDRV
	MOV	D.VINI-2(R1),SP	;;;GET POWER-DOWN ENTRY POINT
	CALL	(SP)		;;;CALL DRIVER
40$:
	.IFF

	MOV	#$PCSPF,SP      	;;;SET STACK POINTER
	CALL	(SP)		;;;CALL USER POWER FAIL ROUTINE

	.ENDC

	.ENDC


	HALT			;;;WAIT FOR SOME JUICE!

	.IFT

;+
; **-PUP-POWERFAIL INTERRUPT (UP)
;
; THIS ROUTINE IS ENTERED AS A RESULT OF A POWER UP INTERRUPT. ALL VOLATILE
; MACHINE REGISTERS ARE RESTORED, A SCHEDULE REQUEST IS FORCED FOR THE
; NULL TASK, THE POWERFAIL INDICATOR IS INCREMENTED, AND AN RTI IS
; EXECUTED. AT THE APPROPRIATE TIME THE DISPATCHER WILL CALL THE POWER
; RECOVERY ROUTINE TO ACTUALLY PROCESS THE PO      WER FAILURE.
;-

PUP:	MOV	#$CRPBF,SP	;;;POINT TO LAST REGISTER SAVED		;MSH154
									;**-1

	.IF DF	F$$LPP

	TST	$HFMSK		;;;FPU PRESENT?				;MSH149
	BMI	5$		;;;IF MI NO, DON'T TRY TO ACCESS IT	;MSH149
	MOV	(SP)+,@(SP)+	;;;CONDITIONALLY RESTORE PIRQ OR LOC. 0
	LDFPS	#200		;;;SET DOUBLE MODE - CLR INTERRUPT BITS	;MSH134
	LDD	(SP)+,R0	;;;LOAD SIXTH FACC INTO FIRST FACC	;MSH134
	STD	R0,R5		;;;MOVE SIXTH FACC INTO POSITION	;MSH134
	LDD	(SP)+,R0	;;;LOAD FIFTH FACC INTO FIRST FACC	;MSH134
	STD	R0,      R4		;;;MOVE FIFTH FACC INTO POSITION	;MSH134
	LDD	(SP)+,R3	;;;LOAD FOURTH FACC			;MSH134
	LDD	(SP)+,R2	;;;LOAD THIRD FACC			;MSH134
	LDD	(SP)+,R1	;;;LOAD SECOND FACC			;MSH134
	LDD	(SP)+,R0	;;;LOAD FIRST FACC			;MSH134
	LDFPS	(SP)+		;;;RESTORE FLOATING POINT STATUS	;**-9

	.ENDC

5$:				;;;					;MSH149

	.IF DF	M$$MGE

	BIS	#PMODE,PS	;;;SET PREVIOUS MODE TO USER
	MOV	#KISAR0,R0	;;;POINT TO KERNEL ADDRESS REGISTER 0
	MOV	#KISDR0,R1	;;;POINT TO KERNEL DESCRIPTOR REGISTER 0
	MOV	#UISAR0,R2	;;;P      OINT TO USER ADDRESS REGISTER 0
	MOV	#UISDR0,R3	;;;POINT TO USER DESCRIPTOR REGISTER 0
	MOV	#8.,R4		;;;SET LOOP COUNT
10$:	MOV	(SP)+,(R3)+	;;;RESTORE USER DESCRIPTOR REGISTER
	MOV	(SP)+,(R2)+	;;;RESTORE USER ADDRESS REGISTER
	MOV	#77406,(R1)+	;;;RESTORE KERNEL DESCRIPTOR REGISTER
	MOV	(SP)+,(R0)+	;;;RESTORE KERNEL ADDRESS REGISTER
	DEC	R4		;;;ANY MORE TO RESTORE?
	BGT	10$		;;;IF GT YES
	INC	SR0		;;;TURN ON MEMORY MANAGEMENT
	MTPI	SP		;;;RESTORE USER STACK POINTER


	.IF DF	M$$EXT

	TST	$UMRPT      		;;;UNIBUS MAP EXISTS?			;MSH097
	BEQ	35$		;;;IF EQ NO, SKIP INITIALIZING IT	;MSH097
	MOV	#UBMPR,R0	;;;POINT TO FIRST MAP REGISTER
	MOV	#5.,R1		;;;SET COUNT OF EXEC REGISTERS
	CLR	R2		;;;CLEAR STARTING ADDRESS
20$:	MOV	R2,(R0)+	;;;LOAD LOW 16 BITS OF ADDRESS
	CLR	(R0)+		;;;CLEAR HIGH 6 BITS OF ADDRESS
	ADD	#20000,R2	;;;ADVANCE 8K BYTES
	DEC	R1		;;;ANY MORE TO LOAD?
	BGT	20$		;;;IF GT YES
	MOV	#31.-5.,R1	;;;SET COUNT OF REGISTERS
30$:	MOV	(SP)+,(R0)+	;;;RESTORE LOW 16 BITS OF ADDRESS
	MOV	(SP)+,      (R0)+	;;;RESTORE HIGH 6 BITS OF ADDRESS
	DEC	R1		;;;ANY MORE REGISTERS
	BGT	30$		;;;IF GT YES
35$:	MOV	#60,SR3		;;;ENABLE 22 BIT AND UNIBUS MAP		;MSH097
									;**-1
	.ENDC


	.IFF


	.IF DF	E$$EAE

	MOV	(SP)+,MQ	;;;RESTORE EAE MULTIPLIER-QUOTIENT
	MOV	(SP)+,AC	;;;RESTORE EAE ACCUMULATOR
	MOV	(SP)+,SC	;;;RESTORE EAE SHIFT COUNT

	.ENDC


	.ENDC

	.IF DF	L$$SI1							;MSH181
									;MSH181
	MOV	(SP)+,@#14	;;;RESTORE BPT/T-BIT VECTOR CONTENTS	;MSH181
									;MSH181
	.ENDC						      		;MSH181

	MOV	(SP)+,R0	;;;RESTORE R0 THRU R5
	MOV	(SP)+,R1	;;;
	MOV	(SP)+,R2	;;;
	MOV	(SP)+,R3	;;;
	MOV	(SP)+,R4	;;;
	MOV	(SP)+,R5	;;;
	MOV	(SP),SP		;;;RESTORE STACK POINTER
	INC	$PWRFL		;;;INDICATE A POWER FAILURE HAS OCCURED
	MOV	#$HEADR,$RQSCH	;;;FORCE REDISPATCHING
	MOV	#PDOWN,PWVCT	;;;SWITCH TO POWER DOWN ROUTINE
	MOV	#40$,-(SP)	;;;GIVE A RETURN ADDRESS FOR $SGFIN
	CALL	$SGFIN		;;;PLUG VECTORS (IF NO CLOCK)
	MOV	$CKLDC,@$CKCNT	;;;RELOAD CLOCK COUNT REGISTER
	MOV	#K$$IEN,@$CKCSR	;;;TURN       CLOCK BACK ON
	RETURN			;;;RETURN TO $SGFIN, WHICH WILL RETURN TO 40$
40$:	RTI			;;;

;+
; **-$POWER-POWER FAIL RECOVERY
;
;-

	.IFTF

	.ENABL	LSB

$POWER::CLR	$PWRFL		;CLEAR FAILURE INDICATOR
	CALL	$DRDSE		;DECLARE A SIGNIFICANT EVENT


	.IF DF	K$$W11

	MOV	$WTCSR,R0	;GET WATCHDOG TIMER CSR POINTER		;MSH156
	CLR	2(R0)		;CLEAR CLOCK ERROR FLAGS		;MSH156
	MOV	#1,6(R0)	;ENERGIZE OUTPUT RELAY			;MSH156
									;**-2
	.ENDC


	.IF DF	P$$RTY

	CALL	$CLPAR		;CLEAR MEMORY PARITY CSR'S      
	MOV	$MPCSR+6,R0	;PICK UP CACHE CSR REGISTER		;MSH127
									;**-1

	.IF DF	C$$CHE							;MSH127
									;**-1
	BIC	#^C<14>,(R0)	;PRESERVE FORCE MISS BITS
	MOV	(R0),$MPCTL	;SAVE PARITY CONTROL REGISTER		;MSH127
									;**-1
	.IFF

	MOV	#3,(R0)	;DISABLE TRAPS

	.ENDC


	MOV	#177777,-(R0)	;CLEAR MEMORY ERROR REGISTER

	.ENDC


	.IF DF	E$$LOG							;DTB009
 									;DTB009
	BIT	#ES.DAT,$ERFLA	;ARE WE LOGGING?			;DTB009
	BEQ	6$		;IF EQ NO				;DTB009
	MOV	#E$CSYS+<E$SPWR*400>,R0 ;      GET ERROR CODE			;DTB009
	CLR	R1		;NO DATA SUBPACKET			;DTB009
	MOV	#SM.HDR,R2	;ONLY A HEADER SUBPACKET		;DTB009
	CALL	$CRPKT		;CREATE THE PACKET			;DTB009
	BCS	6$		;IF CS ALLOCATION FAILURE		;DTB009
	CALL	$QUPKT		;QUEUE THE PACKET			;DTB009
6$:									;DTB009
									;**-8
	.ENDC


;
; EFFECT POWERFAIL AST'S FOR TASKS THAT ARE ACTIVE AND IN CORE
;

	.IFT


	.IF DF	A$$TRP

	MOV	$ACTHD,R5	;GET ADDRESS OF FIRST TCB
10$:	MOV	#AS.PFA,R4	;SET  POWERFAIL TYPE AST
	MOV	T.ACTL(R5),-(SP) ;SAV      E POINTER TO NEXT ACTIVE TASK
	BEQ	15$		;IF EQ THERE IS NONE
	CALL	$DASTT		;DECLARE POWERFAIL AST
15$:	MOV	(SP)+,R5	;GET ADDRESS OF NEXT ACTIVE TASK
	BNE	10$		;IF NE NO

	.ENDC

	.IFTF								;MSH128
									;MSH128
;									;MSH128
; DO POWERFAIL RECOVERY FOR THE NETWORK					;MSH128
;									;MSH128
									;MSH128
	.IF DF	M$$NET							;MSH128
									;MSH128
	MOV	$NETPF,R5	;GET NETWORK POWERFAIL ROUTINE ADDRESS	;MSH128
	BEQ	$DRVPF		;IF EQ THERE IS NONE			;MSH128
	CALL	(R5)		;RECOVER       FROM POWERFAIL			;MSH128
									;MSH128
	.ENDC								;MSH128
									;MSH128
;									;**-1
; DO POWERFAIL RECOVERY FOR ALL ACTIVE DEVICES
;

$DRVPF::MOV	#$SCDVT,-(SP)	;SCAN THE DEVICE TABLES (CO-ROUTINE)	;MSH119
30$:	CALL	@(SP)+		;GET NEXT UCB ADDRESS			;**-3
	BCC	40$		;IF CC GOT ONE
	RETURN			;
40$:	BITB	#US.OFL,U.ST2(R5) ;DEVICE IN CONFIGURATION?
	BNE	30$		;IF NE NO
	BITB	#UC.PWF,U.CTL(R5) ;CALL DRIVER REGARDLESS OF ACTIVITY?
	BNE	50$		;IF NE YES
	TSTB	U.STS(R5)	;IS UNIT ACTIVE?
	B      PL	30$		;IF PL NO
50$:	MOV	D.DSP(R3),R2	;GET ADDRESS OF DRIVER DISPATCH TABLE
	BEQ	30$		;IF EQ DRIVER NOT LOADED


	.IF DF	L$$DRV&M$$MGE

$LDPWF::MOV	KISAR5,-(SP)	;SAVE APR5 (REF LABEL FOR 'LOAD')
	MOV	D.PCB(R3),R3	;GET DRIVER PCB ADDRESS
	BEQ	55$		;IF EQ DRIVER IS PART OF EXEC
	MOV	P.REL(R3),KISAR5  ;MAP THE DRIVER
55$:				;

	.IFTF

	MOVB	S.CON(R4),R3	;GET CONTROLLER INDEX

;
; CALL DRIVER AT POWERFAIL ENTRY POINT WITH THE ARGUMENTS:
;
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS       CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;

	CALL	@D.VPWF(R2)	;ENTER DRIVER

	.IFT

	MOV	(SP)+,KISAR5	;RESTORE APR5

	.ENDC


	BR	30$		;GO AGAIN
									;MSH181
	.IFT	;P$$RFL							;MSH181
									;MSH181
	.IF DF	L$$SI1							;MSH181
									;MSH181
;									;MSH181
; SUBROUTINE TO INTERCEPT UNEXPECTED T-BIT TRAPS AFTER LSI POWER UP.	;MSH181
; THIS ROUTINE CLEARS THE T-BIT IN THE SAVED PS ON THE STACK AND	;MSH181
; DISMISSES THE TRAP.							;MSH181
;									;MSH181   Ä   
									;MSH181
$TBIT::	BIC	#20,2(SP)	;;;CLEAR T-BIT IN SAVED PS		;MSH181
	RTI			;;;DISMISS THE TRAP			;MSH181
									;MSH181
	.ENDC								;MSH181

	.ENDC


	.DSABL	LSB


	.END
Ä          :dè€kQ	› c,        	.TITLE	PARTY
	.IDENT	/10.07/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 10.07
;
; D. N. CUTLER 	14-FEB-74
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	9-APR-80
;		MSH094 -- CLEAN UP AND ENHANCE PARITY CODE
;
;	M. S. HARVEY	      13-NOV-80
;		MSH127 -- CLEAN UP CACHE MEMORY CONDITIONALIZATION
;
;	DAN BROWN	7-JAN-80
;		DTB007 -- MODIFY FOR NEW ERROR LOGGER
;
;	M. S. HARVEY	4-NOV-81
;		MSH200 -- PASS TCB ADDRESS TO ERROR LOGGING SUBSYSTEM
;
;	M. S. HARVEY	5-NOV-81
;		MSH201 -- PASS CSR EXISTENCE BITMASK TO ERROR LOGGER
;
;		MSH202 -- MAKE SURE REGISTERS ARE AVAILABLE FOR
;			  USER-WRITTEN CODE ON KERNEL MODE CACHE
;			  PARITY ERROR
;
;
;
; MEMORY PARITY INTERRUPT HANDLING
;
; MACRO LIBRARY CALLS
;


	.IF DF	P      $$RTY

	.MCALL	ABODF$,HWDDF$,PCBDF$,TCBDF$,EPKDF$			;MSH094
	ABODF$			;DEFINE TASK ABORT CODES		;**-1
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	EPKDF$			;DEFINE ERROR LOG PACKET OFFSETS	;DTB007

;
; LOCAL DATA
;
; EXEC PARITY ERROR MESSAGE
;

EXMSG:	.ASCIZ	<15><12>/***EXEC PARITY ERROR STOP***/<15><12><12> ;

;
; INTERRUPT RECURSION LEVEL COUNTER
;

PARLV:	.WORD	-1		;

;
; PARITY CONTROL STATUS       REGISTER ADDRESS TABLE
;

	.WORD	77		;CACHE CSR BIT MASK (PRESENCE ASSUMED)	;MSH201
	.WORD	177777		;MEMORY CSR BIT MASK (PRESENCE ASSUMED)	;MSH201
$PARTB::.WORD	1		;DUMMY CSR FOR NONEXISTANT REGISTERS	;**-1
	.BLKW	16.		;MEMORY PARITY CSR TABLE
	.WORD	$MPCSR		;POINT TO 11/70 CSR TABLE

;
; CACHE MEMORY PARITY STATUS TABLE					;MSH127
;									;**-1


	.IF DF	C$$CHE							;MSH127
									;**-1

	.IF DF	E$$LOG							;DTB007
									;**-1
MSTAT:	.BLKW	2		;FIRST TWO PARITY CSR'S
STAT:	.BL      KW	1		;MEMORY STATUS REGISTER
	.BLKW	3		;LAST THREE PARITY CSR'S

	.IFF

STAT:	.BLKW	1		;MEMORY STATUS REGISTER

	.ENDC


ERTRK:	.BYTE	44,120		;ADDRESS/DATA GROUP 0
	.WORD	0		;TIME OF LAST ERROR
	.BYTE	30,240		;ADDRESS/DATA GROUP 1
	.WORD	0		;TIME OF LAST ERROR
	.WORD	0		;END OF TABLE

;
; NEW CACHE PARITY CSR CONTENTS
;

$MPCTL::.BLKW	1		;

	.ENDC


;
; VECTOR OF CACHE CSR ADDRESSES
;

$MPCSR::.BLKW	6		;ALL SIX REGISTERS
	.WORD	0		;TERMINATOR LINK FOR INITL AND SAVE


;
;       PARITY VECTOR
;

	.ASECT
.=114
	.WORD	$PARER
	.WORD	PR7		;
	.PSECT

;+
; **-$PARER-MEMORY PARITY ERROR INTERRUPT
;
; THIS ROUTINE IS ENTERED AS THE RESULT OF A MEMORY PARITY ERROR INTERRUPT. IF
; THE ERROR OCCURED IN THE EXECUTIVE OR WHILE ON THE SYSTEM STACK, THEN A
; MESSAGE IS PRINTED ON THE CONSOLE TERMINAL AND THE SYSTEM IS HALTED.
; ELSE A SWITCH TO THE SYSTEM STACK IS EXECUTED AND THE TASK IN WHICH
; THE PARITY ERROR OCCURED IS LOCKED IN MEMORY.
;-

	.ENABL	LSB
RECURS:	JMP	60$		;;      ;JUMP TO HALT PROCESSOR
$PARER::			;;;REF LABEL

	.IF DF	C$$CHE							;MSH127
									;**-1
	.IF DF	E$$LOG							;MSH094
									;MSH094
	MOV	@$MPCSR+6,MSTAT+6 ;;;SAVE MEMORY CONTROL REGISTER	;MSH094
									;MSH094
	.ENDC								;MSH094
									;MSH094
	BIS	#3,@$MPCSR+6	;;;TURN CACHE TRAPS OFF

	.IFTF	;C$$CHE							;MSH127
									;**-1
	INC	PARLV		;;;INTERRUPT RECURSION?
	BNE	RECURS		;;;IF NE YES


	.IFT	;C$$CHE							;MSH127
									;**-1
	MOV	R0,-(SP)	;;;SAVE R0
	MOV	R1,-(SP)      	;;;SAVE R1


	.IF DF	E$$LOG							;DTB007
									;**-1
	MOV	#$MPCSR,R0	;POINT TO PARITY CSR TABLE
	MOV	#MSTAT,R1	;POINT TO PARITY CSR SAVE AREA
	MOV	@(R0)+,(R1)+	;SAVE LOW ADDRESS REGISTER
	MOV	@(R0)+,(R1)+	;SAVE HIGH ADDRESS REGISTER

	.IFF

	MOV	#$MPCSR+4,R0	;POINT INTO PARITY CSR TABLE
	MOV	#STAT,R1	;POINT TO STATUS WORD SAVE AREA

	.IFTF

	MOV	#-1,(R1)	;ASSUME MEM PARITY ON NONCACHE MACHINE
	CMP	(R0)+,#MPCSR-2	;RUNNING ON CACHE MACHINE?
	BNE	2$		;IF NE NO
	MOV	@-2(R0),(R1)+	;SAVE       MEMORY ERROR REGISTER		;MSH094
									;**-2
	.IFT

	CMP	(R0)+,(R1)+	;SKIP MEMORY CONTROL REGISTER		;MSH094
	MOV	@(R0)+,(R1)+	;SAVE MAINTENANCE REGISTER		;**-1
	MOV	@(R0)+,(R1)+	;SAVE CACHE HIT REGISTER

	.ENDC


2$:	MOV	(SP)+,R1	;;;RESTORE R1
	MOV	(SP)+,R0	;;;RESTORE R0

	.IFTF


	.IF DF	M$$MGE

	BIT	#CMODE,2(SP)	;;;PREVIOUS MODE USER?
	BNE	4$		;;;IF NE YES

	.IFF

	CMP	(SP),$EXSIZ	;;;PARITY ERROR PC IN EXEC?
	BLO	3$		;;;IF LO YES
	TST	$STKDP		;;;PARITY ERROR ON SYSTEM STACK?
	B      GT	4$		;;;IF LE YES

	.ENDC


	.IFT

3$:	TST	STAT		;;;FATAL MEMORY ERROR?
	BLE	20$		;;;IF LE YES
	DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY	;MSH202
	MOV	#ERTRK,R1	;POINT TO ERROR TRACKING TABLE		;MSH202
	CALL	14$		;EXECUTE CACHE ALGORITHM		;MSH202
	CALL	MECLR		;RESET PARITY CSR'S			;MSH094
	BR	9$		;RETURN FROM PARITY TRAP		;MSH202
									;**-7
	.IFF

3$:	BR	20$		;;;FATAL MEMORY PARITY ERROR

	.IFTF


4$:	DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY

;
; LOG PARITY ERROR IN TASK
      ;
;	THE DATA SUBPACKET CONTAINS THE FOLLOWING INFORMATION:		;DTB007
;									;DTB007
;	WD.00 -	(15:6) RESERVED, (5:0) BITMAP INDICATING WHICH		;MSH201
;		CACHE CSRS ARE PRESENT ON THE SYSTEM			;MSH201
;	WD.01 - MEMORY PARITY CSR BITMAP INDICATING WHICH CSRS		;MSH201
;		EXIST ON THE SYSTEM					;MSH201
;	WD.02 THRU WD.17- CONTENTS OF THE MEMORY PARITY CSRS		;MSH201
;	WD.18 THRU WD.23- CONTENTS OF CACHE CSRS			;MSH201
;									;DTB007
 									;DTB007
 									;DTB007
	.IF DF	E$$LOG							;DTB0      07
 									;DTB007
	BIT	#ES.LOG,$ERFLA	;ARE WE LOGGING ERRORS?			;DTB007
	BEQ	8$		;NO, SO IGNORE THIS			;DTB007
	INC	$ERRSQ		;COUNT ONE MORE ERROR IN SYSTEM		;DTB007
	MOV	#E$CCPU+<E$SMEM*400>,R0 ;GET THE ERROR CODE		;DTB007
	MOV	#24.*2,R1	;GET THE SIZE OF THE DATA SUBPACKET	;MSH201
	MOV	#SM.HDR!SM.TSK!SM.DAT,R2 ;GET THE CONTROL MASK		;DTB007
	CLR	R3		;NO BEGINNING ADDRESS FOR DATA		;DTB007
	MOV	$TKTCB,R4	;LOAD CURRENT TASK TCB ADDRESS		;MSH200
	CLR	R5		;NO UCB					;DTB007
	CALL	$CRPKT		;CREATE       THE PACKET			;DTB007
	BCS	8$		;IF CS POOL ALLOCATION FAILURE		;DTB007
 									;DTB007
	MOV	#$PARTB-4,R2	;POINT TO CSR BITMAPS			;MSH201
	MOV	(R2)+,(R1)+	;STORE CACHE CSR BIT MAP		;MSH201
	MOV	(R2)+,(R1)+	;STORE PARITY CSR BIT MAP		;MSH201
	TST	(R2)+		;SKIP DUMMY CSR WORD			;MSH201
6$:	MOV	@(R2)+,(R1)+	;STORE MEMORY PARITY CSR CONTENTS	;DTB007
	CMP	R2,#$PARTB+2+<16.*2> ;DONE YET?				;DTB007
	BLO	6$		;IF LO NO				;DTB007
 									;DTB007
	.IF DF	C$$CHE							;DTB007
 									;DTB007
	TST	(R2)      +		;POINT TO CACHE PARITY CSR'S		;DTB007
7$:	MOV	(R2)+,(R1)+	;STORE SAVED CACHE CSR CONTENTS		;DTB007
	CMP	R2,#MSTAT+14	;DONE YET?				;**-62
	BLO	7$		;IF LO NO

	.ENDC
  									;DTB007
	CALL	$QUPKT		;QUEUE ERROR MESSAGE BLOCK		;DTB007
8$:				;REF LABEL				;**-3

	.ENDC

	.IFTF								;MSH094
									;MSH094
;									;MSH094
; CLEAR ALL PARITY REGISTERS AND REENABLE FOR PARITY ERRORS		;MSH094
;									;MSH094
									;MSH094
	CALL	$CLPAR		;RESET ALL PARITY CSR'S			;MSH094

	.IFT

      	MOV	#ERTRK,R1	;POINT TO ERROR TRACKING TABLE
	TST	STAT		;WAS IT ONLY A CACHE ERROR?
	BLE	10$		;IF LE NO				;MSH202
	CALL	14$		;EXECUTE CACHE ALGORITHM		;MSH202
9$:	DEC	PARLV		;RESET RECURSION LEVEL			;MSH202
	RETURN			;EXIT FROM PARITY ERROR PROCESSING	;MSH202
									;**-2
	.IFTF

;									;**-6
; FREEZE CURRENT TASK IN MEMORY AND THEN ABORT TASK
;

10$:	MOV	$TKTCB,R1	;GET TCB ADDRESS OF CURRENT TASK	;MSH202
	BIS	#T2.FXD,T.ST2(R1) ;FIX TASK IN MEMORY			;**-1
	BIC	#T3.REM,T.ST3(R1) ;CLEAR       REMOVE ON EXIT BIT


	.IF DF	D$$SHF

	MOV	T.PCB(R1),R0	;GET ADDRESS OF TASK PCB
	BIT	#PS.SYS,P.STAT(R0) ;SYSTEM CONTROLLED PARTITION?
	BEQ	11$		;IF EQ NO
	BIS	#PS.NSF,P.STAT(R0) ;FREEZE PARTITION FOR SHUFFLER

	.ENDC


11$:	MOV	#S.PRTY,R0	;SET REASON FOR ABORT
	CALL	$ABTSK		;ABORT TASK
									;MSH202
	.IFF								;MSH202
									;MSH202
	DEC	PARLV		;RESET RECURSION LEVEL			;MSH202

	.IFT

	CALL	16$		;DO FINAL PARITY ERROR PROCESSING	;MSH202
	BR	9$		;ALL DONE				;MSH202
									;*      *-1
;
; PDP-11/70 CACHE TRAP
;

12$:	MOV	$TTNS-4,-(R1)	;;;SAVE TIME OF LAST ERROR
13$:	TST	(R1)+		;;;POINT TO NEXT GROUP
14$:	MOVB	(R1)+,R0	;;;GET CACHE DISABLE BITS
	BEQ	16$		;;;IF EQ END OF TABLE
	BITB	(R1)+,STAT	;;;ERROR IN THIS GROUP?
	BEQ	13$		;;;IF EQ NO
	CMP	(R1)+,$TTNS-4	;;;OCCUR IN SAME MINUTE?
	BNE	12$		;;;IF NE NO
	BIS	R0,$MPCTL	;;;DISABLE THAT PART OF CACHE
	BR	14$		;;;PROCESS NEXT GROUP
16$:	MOV	$MPCTL,@$MPCSR+6 ;RELOAD 11/70 PARTIY CSR
									;**-1
	.ENDC


;
; AT THIS P      OINT EVERYTHING HAS BEEN CLEANED UP AND THE USER MAY
; INSERT CODE SPECIFIC TO HIS APPLICATION.
;
;***************
; INSERT CODE HERE-ALL REGISTERS ARE AVAILABLE
;***************
									;MSH202
	RETURN			;EXIT FROM TRAP				;**-5

;
; PARITY ERROR OCCURED WHILE IN EXEC CODE. THIS IS A FATAL SITUATION
; AND THE SYSTEM IS SHUT DOWN. THE USER MAY INSERT CODE SPECIFIC
; TO HIS APPLICATION AT THIS POINT.
;

20$:				;;;REF LABEL

;;;***************
;;; INSERT CODE HERE-ALL REGISTERS HAVE NOT BE      EN SAVED
;;;***************

	MOV	#60$,@#4	;;;PLUG NONEX MEMORY VECTOR
	MOV	R0,-(SP)	;;;SAVE R0
	MOV	#EXMSG,R0	;;;GET ADDRESS OF PARITY STOP MESSAGE
30$:	MOVB	(R0)+,TPS+2	;;;OUTPUT NEXT BYTE
	BEQ	50$		;;;IF EQ DONE
40$:	TSTB	TPS		;;;OUTPUT DONE?
	BPL	40$		;;;IF PL NO
	BR	30$		;;;GO AGAIN
50$:	MOV	(SP)+,R0	;;;RESTORE R0
60$:	HALT			;;;HALT SYSTEM
	BR	60$		;;;IF CONTINUED HALT AGAIN
	.DSABL	LSB

;+
; **-$CLPAR-CLEAR PARITY REGISTERS
;
; THIS ROUTINE CLEARS OUT ALL PARITY ERRORS IN THE MEMOR      Y PARITY ERROR
; REGISTERS AND ENABLES PARITY ERROR NOTIFICATION.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	NONE.
;
;	NOTE:	IF THE SYMBOL M$$K11 IS DEFINED (11/70 TYPE ECC MEMORY),
;		THIS ROUTINE WILL NOT PROPERLY HANDLE UNIBUS ECC MEMORY
;		(SUCH AS MF11S-K) SINCE THE ROUTINE ASSUMES THAT ANY
;		OTHER MEMORY ON THE SYSTEM MUST BE PARITY MEMORY AND
;		THAT AN ATTEMPT TO SET THE SINGLE-BIT ECC ERROR BIT ON
;		SUCH A MEMORY WILL FAIL.  THIS ASSUMPTION IS USED TO
;		DISTINGUISH MK11 ECC MEMORY F      ROM PARITY MEMORY.
;-

$CLPAR::MOV	#$PARTB+2,R0	;POINT TO PARITY CSR VECTOR
10$:				;REF LABEL


	.IF DF	M$$K11

	TST	(R0)		;EVEN WORD CSR PRESENT?
	BPL	20$		;IF PL NO
	MOV	#21,@(R0)+	;SET ENABLE AND SINGLE-BIT ECC ERROR
	BIT	#20,@-(R0)	;SINGLE-BIT ECC ERROR BIT SET (MK11)?
	BEQ	20$		;IF EQ NO
	MOV	#1,@(R0)+	;SET ENABLE BIT AND CLR REST IN 1ST WORD
	BIC	#100000,@(R0)+	;CLEAR ERROR BIT IN SECOND WORD
	BR	30$		;
20$:	MOV	#1,@(R0)+	;ENABLE PARITY ERROR NOTIFICATION

	.ENDC


	MOV	#1,@(R0)     +	;ENABLE PARITY (OR UNIBUS MEM ECC) NOTIF
30$:	CMP	R0,#$PARTB+2+<16.*2> ;DONE YET?
	BLO	10$		;IF LO NO

	.IF DF	C$$CHE							;MSH127
									;**-1
MECLR:	MOV	@$MPCSR+4,-(SP) ;CLEAR MEMORY SYSTEM ERROR REGISTER
	MOV	(SP)+,@$MPCSR+4

	.ENDC

	RETURN			;
	.ENDC


	.END
          ³} kQ	› c,        	.TITLE	TDSCH
	.IDENT	/09.11/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 09.11
;
; D. N. CUTLER 11-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;
; MODIFIED BY:
;
;	M. S. HARVEY	16-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	3-FEB-8      1
;		MSH132 -- DEFINE C.SYST CLOCK BLOCK CODE FOR USE BY
;			  CINT$ INTERRUPT ROUTINES
;
;	M. S. HARVEY	5-MAR-81
;		MSH156 -- ADD TRANSPORTABILITY SUPPORT FOR THE
;			  WATCHDOG TIMER
;
;	M. S. HARVEY	3-APR-81
;		MSH098 -- ADD SUPPORT FOR DYNAMIC SYSTEM TUNING
;
;	M. S. HARVEY	6-AUG-81
;		MSH184 -- IMPLEMENT SHUFFLER RUN LIMITING
;
;	M. S. HARVEY	10-NOV-81
;		MSH204 -- REDUCE CHANCES OF T1 TIMEOUT
;
; TIME DEPENDENT SCHEDULING AND DEVICE TIME OUT
;
; MACRO LIBRARY CALLS
;

	.MCALL	CLK      DF$,HDRDF$,HWDDF$,TCBDF$,PCBDF$
	CLKDF$			;DEFINE CLOCK QUEUE CONTROL BLOCK OFFSET
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS

;
; LOCAL DATA
;


	.IF DF	R$$NDC

RNDCT:	.WORD	R$$NDC		;CLOCK TICKS TO NEXT SCHEDULE INTERVAL

	.ENDC


	.IF DF	S$$WPC&D$$ISK

SWPCT:	.WORD	S$$WPC		;CLOCK TICKS TO NEXT SWAPPING INTERVAL

	.ENDC


;+
; **-$CKINT-CLOCK INTERRUPT
;      
; THIS ROUTINE IS ENTERED AS THE RESULT OF A CLOCK INTERRUPT. $INTSV
; IS CALLED TO SAVE REGISTERS R4 AND R5 AND $INTCT IS INCREMENT. IF
; THE RESULT IS NONZERO, THEN A JUMP TO $INTXT IS EXECUTED. ELSE
; A FORK IS EXECUTED SO THAT PENDING CLOCK INTERRUPTS CAN BE PRO-
; CESSED.
;									;MSH204
; NOTE THAT IF A WATCHDOG TIMER EXISTS, PUNCH ITS CSR AT PR7 LEVEL.	;MSH204
; THIS ENSURES THAT THE WATCHDOG TIMER IS NOT ACCESSED TOO OFTEN	;MSH204
; BY NOT ALLOWING THE NESTING OF CLOCK INTERRUPTS TO DELA      Y TIMER	;MSH204
; ACCESS. SUCH A DELAY COULD RESULT IN MULTIPLE ACCESSES BEFORE		;MSH204
; THE T1 TIMEOUT.							;MSH204
;-

$CKINT::			;;;CLOCK INTERRUPT SERVICE ROUTINE	;MSH204
									;MSH204
	.IF DF	K$$W11							;MSH204
									;MSH204
	MOV	#3,@$WTCSR	;;;ENABLE AND START TIMER		;MSH156
									;MSH204
	.ENDC								;MSH204
									;MSH204
	CALL	$INTSV,PR6	;;;SAVE REGISTERS AND SET PRIORITY	;MSH204
	MOV	#$INTCT,R4	;;;POINT TO INTERRUPT COUNT		;**-10
	INC	(R4)		;;;INCREMENT INTERRUPT CO      UNT
	BEQ	10$		;;;IF EQ FORK
	RETURN			;;;EXIT FROM INTERRUPT
10$:	CALL	$FORK0		;;;EXECUTE FORK

;
; UPDATE ABSOLUTE AND REAL TIME OF DAY AND DATE
;

UPTIM:	MOV	#$TKPS+2,R4	;POINT PAST CONVERSION VECTOR
	MOV	#$TTNS+2,R5	;POINT PAST CURRENT TIME VECTOR
10$:	MOV	#$TTNS-10,R2	;POINT TO DAY
	INC	-(R5)		;UPDATE A COUNTER
	CMP	-(R4),(R5)	;EXCEEDED LIMIT?
	BHI	20$		;IF HI NO
	CLR	(R5)		;RESET COUNTER
	CMP	R5,R2		;CHECK FOR LAST DAY OR MONTH
	BHI	10$		;IF HI NO
	INC	(R5)		;DAY AND MONTH ARE 1 ORIGI      N
	BCS	10$		;IF CS NOT DAY
	MOV	-(R2),R1	;GET CURRENT MONTH
	MOVB	$DYPMN-1(R1),R0	;GET DAYS FOR NEXT MONTH PLUS 1
	MOV	R0,(R4)		;MOVE TO DAYS PER MONTH LIMIT
	DEC	R1		;IS CURRENT MONTH ENDING JANUARY?
	BNE	10$		;IF NE NO
	BIT	#3,-(R2)	;IS THIS A LEAP YEAR?
	BNE	10$		;IF NE NO
	INC	(R4)		;INCREMENT DAYS FOR FEBRUARY
	BR	10$		;
20$:				;					;MSH184
									;MSH184
	.IF DF	D$$YNM&D$$SHF						;MSH184
									;MSH184
	TST	$SHFTM		;SHUFFLER RUN LIMITER EXPIRED?		;MSH184
	BEQ	30$		;IF EQ YES				      ;MSH184
	DEC	$SHFTM		;RUN DOWN THE LIMITER TIMER		;MSH184
									;MSH184
	.ENDC								;MSH184
									;MSH184
30$:	INC	$ABTIM		;UPDATE ABSOLUTE TIME COUNTER		;MSH184
	BNE	TDS		;IF NE NO OVERFLOW			;**-1
	MOV	#$CLKHD,R0	;POINT TO CLOCK QUEUE LISTHEAD
40$:	MOV	(R0),R0		;GET ADDRESS OF NEXT ENTRY
	BEQ	TDS		;IF EQ NO MORE IN LIST
	DEC	C.TIM+2(R0)	;ADJUST HIGH ORDER TIME
	BR	40$		;

;
; TIME DEPENDENT SCHEDULING
;

TDS:	MOV	$CLKHD,R4	;GET ADDRESS OF NEXT IN QUEUE
	BEQ	DVOUT		;IF EQ NONE IN       LIST
	TST	C.TIM+2(R4)	;HIGH ORDER PART NONZERO?
	BNE	DVOUT		;IF NE YES
	CMP	$ABTIM,C.TIM(R4) ;TIME TO GO?
	BLO	DVOUT		;IF LO NO
	MOV	(R4),$CLKHD	;REMOVE ENTRY FROM CLOCK QUEUE
	MOVB	C.RQT(R4),R5	;GET ENTRY REQUEST TYPE
	ADD	R5,PC		;DISPATCH TO PROCESSING ROUTINE
10$:	BR	20$		;MARK TIME REQUEST
	BR	30$		;TASK REQUEST WITH PERIODIC RESCHEDULE
	BR	30$		;SINGLE SHOT TASK REQUEST
	BR	15$		;SINGLE SHOT INTERNAL SUBROUTINE


	.IF DF	D$$SHF&D$$YNM

	BR	15$		;SINGLE SHOT INTERNAL SUBROUTINE

;
; C      LEAR STOP BIT AND REALLOCATE PARTITION
;

	MOV	C.TCB(R4),R0	;PICK UP TCB ADDRESS
	CALL	$EXRQN		;CLEAR STOP BIT AND REALLOCATE PARTITION
	BR	TDS		;

	.ENDC


;
; SINGLE SHOT INTERNAL SYSTEM SUBROUTINE (TYPE 6 OR 8)
;

15$:				;


	.IF DF	L$$DRV&M$$MGE!C$$INT&M$$MGE				;MSH132
									;**-1
	MOV	KISAR5,-(SP)	;SAVE APR5
	MOV	C.AR5(R4),KISAR5  ;MAP TO SYSTEM ROUTINE (DRIVER)

	.IFTF

	CALL	@C.SUB(R4)	;CALL SYSTEM SUBROUTINE

	.IFT

	MOV	(SP)+,KISAR5	;RESTORE APR5

	.ENDC


	BR	      TDS		;

;
; MARK TIME REQUEST
;

20$:	MOV	C.SRC(R4),R0	;PICK UP EVENT FLAG MASK WORD
	MOV	C.DST(R4),R1	;PICK UP EVENT FLAG MASK ADDRESS
	MOV	C.TCB(R4),R5	;PICK UP TCB ADDRESS
	CALL	$SETMG		;SET EFN AND UNLOCK IF GROUP GLOBAL	;MSH049
	CLR	R5		;RESET CLOCK BLOCK TYPE			;**-1


	.IF DF	A$$TRP

	MOV	C.AST(R4),R3	;GET AST TRAP ADDRESS
	BEQ	40$		;IF EQ NO AST SPECIFIED
	MOVB	C.EFN(R4),R2	;GET EFN NUMBER
	MOV	R4,R1		;COPY ADDRESS OF CLOCK QUEUE ENTRY
	TST	(R4)+		;POINT TO CONTROL BLOCK LENGTH
	      MOV	#C.LGTH,(R4)+	;SET LENGTH OF AST CONTROL BLOCK
	MOV	#8.*2,(R4)+	;SET BYTES TO ALLOCATE ON TASK STACK
	MOV	R3,(R4)+	;INSERT AST TRAP ADDRESS
	MOV	#1,(R4)+	;SET NUMBER OF AST PARAMETERS
	MOV	R2,(R4)		;INSERT EFN AS AST PARAMETER
	CALL	$QASTT		;QUEUE AST TO TASK
	BR	TDS		;

	.IFF

	BR	40$		;RELEASE CLOCK CONTROL BLOCK

	.ENDC


;
; SCHEDULE REQUEST
;

30$:	MOV	C.TCB(R4),R0	;GET TASK TCB ADDRESS
	MOV	C.UIC(R4),R1	;GET REQUEST UIC
	CALL	$TSKRT		;REQUEST TASK EXECUTION
40$:	MOV	R4,R0		;S      ET ADDRESS OF BLOCK TO RELEASE
	CMPB	#C.SCHD,R5	;PERIODIC REQUEST?
	BEQ	50$		;IF EQ YES
	CALL	$DECLK		;DEALLOCATE CONTROL BLOCK
	BR	TDS		;
50$:	MOV	C.RSI+2(R0),R1	;SET HIGH ORDER PART OF TIME
	MOV	C.RSI(R0),R2	;SET LOW ORDER PART OF TIME
	MOV	R5,R4		;SET REQUEST TYPE
	MOV	C.TCB(R0),R5	;SET ADDRESS OF REQUEST TASK TCB
	CALL	$CLINS		;REINSERT ENTRY IN CLOCK QUEUE
	BR	TDS		;

;
; DEVICE TIME OUT
;

DVOUT:	TST	$TTNS		;ONE SECOND ELAPSED?
	BNE	ROBIN		;IF NE NO
	MOV	#$SCDVT,-(SP)	;SET ADDRESS OF       DEVICE TABLE SCANNING CO-ROUTINE
10$:	CALL	@(SP)+		;GET NEXT UCB ADDRESS
	BCS	ROBIN		;IF CS END OF TABLE
	MTPS	S.PRI(R4)	;;;RAISE PRIORITY TO DEVICE LEVEL
	TSTB	U.STS(R5)	;;;UNIT BUSY?
	BPL	20$		;;;IF PL NO
	TSTB	S.CTM(R4)	;;;TIMEOUT ACTIVE?
	BEQ	20$		;;;IF EQ NO
	DECB	S.CTM(R4)	;;;DECREMENT TIMEOUT COUNT
	BNE	20$		;;;IF NE MORE TIME TO GO
	MOV	#IE.DNR&377,R0	;;;SET DEVICE TIMEOUT STATUS
	MOV	D.DSP(R3),R1	;;;GET ADDRESS OF DRIVER DISPATCH TABLE
	MOV	S.CSR(R4),R2	;;;GET ADDRESS OF DEVICE CSR

      
	.IF DF	L$$DRV&M$$MGE

	MOV	KISAR5,-(SP)	;;;SAVE APR5
	MOV	D.PCB(R3),R3	;;;GET DRIVER PCB ADDRESS
	BEQ	15$		;;;IF EQ DRIVER IS PART OF EXEC
	MOV	P.REL(R3),KISAR5  ;;;MAP THE DRIVER
15$:				;;;

	.IFTF

	MOVB	S.CON(R4),R3	;;;GET CONTROLLER INDEX

;
; CALL DRIVER AT TIMEOUT ENTRY POINT WITH THE ARGUMENTS:
;
;	R0=DEVICE TIMEOUT STATUS 'IE.DNR'.
;	R2=ADDRESS OF DEVICE CSR.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;

	CALL	@D      .VOUT(R1)	;;;ENTER DRIVER

	.IFT

	MOV	(SP)+,KISAR5	;;;RESTORE APR5

	.ENDC


20$:	MTPS	#0		;;;ALLOW INTERRUPTS
	BR	10$		;GO AGAIN

;
; EXECUTIVE LEVEL ROUND ROBIN SCHEDULING
;

ROBIN:				;REF LABEL


	.IF DF	R$$NDC

	DEC	RNDCT		;TIME TO SCHEDULE?
	BNE	SWAP		;IF NE NO
	MOV	$RNDCT,RNDCT	;RESET CLOCK TICKS TO NEXT INTERVAL	;MSH098
	CALL	$DRDSE		;CAUSE A REDISPATCH OF PROCESSOR	;**-1
	MOV	#$ACTHD-T.ACTL,R1 ;SET ADDRESS OF PREVIOUS ENTRY
10$:	MOV	R1,R0		;SAVE ADDRESS OF PREVIOUS ENTRY      
	MOV	T.ACTL(R0),R1	;GET ADDRESS OF NEXT ENTRY
	BEQ	SWAP		;IF EQ END OF LIST
	CMPB	#R$$NDH,T.PRI(R1) ;PRIORITY IN RANGE?
	BLO	10$		;IF LO NO
20$:	CMPB	#R$$NDL,T.PRI(R1) ;PRIORITY IN RANGE?
	BHI	SWAP		;IF HI NO
	TST	T.STAT(R1)	;TASK BLOCKED?
	BNE	30$		;IF NE YES
	BIT	#T2.SPN!T2.WFR,T.ST2(R1) ;TASK IN WAITFOR OR SUSPEND?
	BEQ	40$		;IF EQ NO
30$:	MOV	R1,R0		;SAVE ADDRESS OF LAST ENTRY
	MOV	T.ACTL(R0),R1	;GET ADDRESS OF NEXT ENTRY
	BR	20$		;
40$:	TST	T.ACTL(R1)	;NULL TASK?
	BEQ	SWAP		;IF EQ YES
	      MOV	T.ACTL(R1),T.ACTL(R0) ;REMOVE TCB FROM TASK LIST
	MOV	R1,R2		;SAVE ADDRESS OF TCB
	MOV	R0,R1		;SET ADDRESS OF LAST ENTRY
50$:	MOV	R1,R0		;SAVE ADDRESS OF LAST ENTRY
	MOV	T.ACTL(R0),R1	;GET ADDRESS OF NEXT ENTRY
	CMPB	T.PRI(R1),T.PRI(R2) ;IN SAME PRIORITY CLASS?
	BEQ	50$		;IF EQ YES
	MOV	R2,T.ACTL(R0)	;SET ADDRESS OF NEXT IN LAST
	MOV	R1,T.ACTL(R2)	;SET ADDRESS OF NEXT IN REMOVED ENTRY
	MOV	R2,R0		;SET ADDRESS OF LAST ENTRY
	BR	20$		;

	.ENDC


;
; DISK SWAPPING ALGORITHM - REDUCE SWAPPIN      G PRIORITY OF RESIDENT TASKS
;

SWAP:				;REF LABEL


	.IF DF	C$$CKP&S$$WPC&D$$ISK

	DEC	SWPCT		;TIME TO MODIFY PRIORITY DIFFERENCES?
	BNE	70$		;IF NE NO
	MOV	$SWPCT,SWPCT	;RESET CLOCK TICKS TO NEXT INTERVAL	;MSH098
	MOV	$PARHD,R5	;POINT TO FIRST PCB IN LIST		;**-1
10$:				;REF LABEL


	.IF DF	D$$YNM&M$$MGE

	BIT	#PS.SYS,P.STAT(R5) ;SYSTEM CONTROLLED PARTITION?
	BNE	30$		;IF NE YES

	.IFTF

	BITB	P.BUSY(R5),P.BUSY+1(R5) ;PARTITION OCCUPIED?
	BEQ	20$		;IF EQ NO
15$:	BIT	#PS.COM!PS.DRV      ,P.STAT(R5) ;COMMON OR DRIVER PARTITION?
	BNE	40$		;IF NE YES
	MOV	P.TCB(R5),R4	;PICK UP OWNER TCB ADDRESS
	BIT	#TS.CKP!TS.CKR!TS.OUT,T.STAT(R4) ;TASK IN MEMORY?
	BNE	40$		;IF NE NO
	MOV	P.HDR(R5),R4	;POINT TO TASK HEADER
	CMPB	H.SPRI(R4),#-S$$WPR ;SWAPPING PRIORITY AT MINIMUM?
	BLE	40$		;IF LE YES
	DECB	H.SPRI(R4)	;REDUCE SWAPPING PRIORITY
20$:	CMP	R5,P.MAIN(R5)	;IS THIS THE MAIN PARTITION?
	BNE	40$		;IF NE NO
30$:	MOV	R5,R0		;COPY PCB ADDRESS
	CALL	$NXTSK		;REALLOCATE PARTITION
40$:				;REF L      ABEL

	.IFT

	BIT	#PS.SYS,P.STAT(R5) ;SYSTEM CONTROLLED PARTITION?
	BEQ	60$		;IF EQ NO
	TST	P.SUB(R5)	;IS THERE ANOTHER SUBPARTITION?
	BEQ	50$		;IF EQ NO
	MOV	P.SUB(R5),R5	;POINT TO NEXT SUBPARTITION PCB
	BR	15$		;
50$:	MOV	P.MAIN(R5),R5	;POINT TO MAIN SYS PARTITION PCB

	.ENDC


60$:	MOV	(R5),R5		;POINT TO NEXT PCB IN LIST
	BNE	10$		;IF NE THERE IS ONE
70$:				;REF LABEL

	.ENDC


;
; EXIT TIME DEPENDENT SCHEDULE IF THERE ARE NOT REMAINING UNPROCESSED CLOCK TICK
;

TIMXT:	DEC	$INT   `   CT		;ANY MORE TICKS TO PROCESS?
	BGE	10$		;IF GE YES
	RETURN			;
10$:	JMP	UPTIM		;

	.END
`          * kQ	› c,        	.TITLE	CORAL
	.IDENT	/08.13/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 08.13
;
; D. N. CUTLER 3-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	H. D. COFFMAN
;	D. N. CUTLER
;	T. J. MILLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	B. S. MCCARTHY	03-FEB-81
;		BM113 -- ADDITION OF EXECUTIVE POOL USAGE
;			CONTROL HOOKS      
;
;	M. S. HARVEY	13-FEB-81
;		MSH142 -- ENHANCE POOL USAGE HOOKS (REPLACES MOST
;			  OF BM113 ABOVE)
;
; CORE BUFFER ALLOCATION ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	CLKDF$,PKTDF$
	CLKDF$			;DEFINE CLOCK QUEUE CONTROL BLOCK OFFSETS
	PKTDF$			;DEFINE I/O PACKET OFFSETS

;+
; **-$ALOCB-ALLOCATE CORE BUFFER
; **-$ALOC1-ALLOCATE CORE BUFFER (ALTERNATE ENTRY)
;
; THIS ROUTINE IS CALLED TO ALLOCATE AN EXEC CORE BUFFER. THE ALLOCATION
; ALGORITHM IS FIRST FIT AND BLOCKS ARE ALLOCATED IN       MULTIPLES OF FOUR
; BYTES.
;
; INPUTS:
;
;	R0=ADDRESS OF CORE ALLOCATION LISTHEAD-2 IF ENTRY AT $ALOC1.
;	R1=SIZE OF THE CORE BUFFER TO ALLOCATE IN BYTES.
;
; OUTPUTS:
;
;	C=1 IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK.
;	C=0 IF THE BLOCK IS ALLOCATED.
;		R0=ADDRESS OF THE ALLOCATED BLOCK.
;		R1=LENGTH OF BLOCK ALLOCATED
;									;MSH142
;	R3 IS PRESERVED.						;MSH142
;-

	.ENABL	LSB
$ALOCB::MOV	#$CRAVL-2,R0	;POINT TO ALLOCATION MASK WORD


	.IF DF	Q$$OPT

	ADD	(R0),R      1		;ROUND TO NEXT BOUNDARY
	BIC	(R0)+,R1	;
	BEQ	5$		;IF EQ ZERO LENGTH REQUEST
	CMP	R1,#I.LGTH	;REQUEST SIZE OF PACKET?
	BNE	5$		;IF NE NO
	MOV	#$PKAVL,R2	;POINT TO PACKET AVAILABLE POINTER
	MOV	(R2),R0		;PICK UP PACKET POINTER
	BEQ	4$		;IF EQ THERE IS NONE
	MOV	(R0),(R2)+	;UNLINK PACKET FROM LIFO LIST
	DEC	(R2)		;INDICATE ONE PACKET LESS IN LIST
	RETURN			;
4$:	MOV	#$CRAVL-2,R0	;POINT BACK TO ALLOCATION MASK WORD

	.ENDC


$ALOC1::ADD	(R0),R1		;ROUND TO NEXT BOUNDARY
	BIC	(R0)+,R1	;CLEAR E      XCESS
5$:	SEC			;ASSUME ZERO LENGTH REQUEST
	BEQ	35$		;IF EQ, ZERO LENGTH REQUEST

	.IF DF	R$$DER!P$$CTL						; BM113
									;**-1
	MOV	R0,-(SP)	;SAVE ADDRESS OF LISTHEAD

	.ENDC								;MSH142
									;**-1
10$:	MOV	R0,R2		;SAVE ADDRESS OF CURRENT BLOCK
	MOV	(R2),R0		;GET ADDRESS OF NEXT BLOCK
	BEQ	30$		;IF EQ END OF CHAIN


	.IF  DF,R$$DER

	CMP	R0,R2		;BACKWARD REFERENCE?
	BLO	40$		;IF LE YES
	CMP	#$CRAVL,(SP)	;ALLOCATION IN EXEC'S POOL?
	BNE	15$		;IF NE, NO
	CMP	R0,#$POOL	;ALLOCA      TION BEFORE EXEC POOL?
	BLO	40$		;IF LO YES
	CMP	R0,$EXSIZ	;ALLOCATION PAST END OF POOL?
	BHI	40$		;IF HI YES
15$:				;REF LABEL

	.ENDC	;R$$DER


	CMP	2(R0),R1	;BLOCK BIG ENOUGH?
	BLO	10$		;IF LO NO
	BEQ	20$		;IF EQ BLOCK IS EXACT SIZE
	TST	(R0)+		;POINT TO SIZE OF FREE BLOCK
	SUB	R1,(R0)		;CALCULATE SIZE REMAINING
	ADD	R0,R1		;POINT TO NEW FREE BLOCK
	MOV	(R0),(R1)	;COPY SIZE
	MOV	-(R0),-(R1)	;COPY LINK
	MOV	R1,(R0)		;STORE LINK TO NEW FREE BLOCK
	SUB	R0,R1		;RESTORE SIZE OF BLOCK
20$:	      MOV	(R0),(R2)	;UPDATE LINK TO NEW FREE BLOCK
30$:				;REF LABEL

	.IF DF	P$$CTL							;MSH142
									;MSH142
	BIT	#^C<$CRAVL>,(SP)+ ;ALLOCATION FROM EXEC'S POOL?		;MSH142
	BNE	35$		;IF NE NO, SKIP POOL SIZE TRACKING	;MSH142
	ROR	(R0)		;ALLOCATION FAILURE? (SAVE C-BIT)	;MSH142
	BPL	32$		;IF PL NO				;MSH142
	MOV	#PC.ALF!<PC.LOW*400>,R2 ;SET LOW POOL MASK		;MSH142
	BR	33$		;REPORT THE ALLOCATION FAILURE		;MSH142
32$:	SUB	R1,$PRISZ	;SUBTRACT FROM TOTAL FREE POOL SIZE	;MSH142
	CMP	$PRISZ,$PRILL	;D      ID WE CROSS LOWER POOL LIMIT?		;MSH142
	BHIS	34$		;IF HIS NO, ALLOCATION OK		;MSH142
	MOV	#PC.LOW!<PC.LOW*400>,R2 ;SET UP LOW POOL CONDITION	;MSH142
33$:	CALL	$PLTRQ		;REQUEST POOL MONITOR TASK		;MSH142
34$:	ASL	(R0)		;RECOVER THE CARRY BIT			;MSH142
									;MSH142
	.IFF	;P$$CTL							;MSH142
									;MSH142
	.IF DF R$$DER

	INC	(SP)+		;CLEAN STACK W/O AFFECTING C-BIT

	.ENDC	;R$$DER
									;MSH142
	.ENDC	;P$$CTL							;MSH142

35$:	RETURN			;


	.IF  DF,R$$DER

40$:	CRASH			;POOL       CLOBBERED

	.ENDC	;R$$DER

	.DSABL	LSB

;+
; **-$ALCLK-ALLOCATE CLOCK QUEUE CORE BLOCK
;
; THIS ROUTINE IS CALLED TO ALLOCATE A CORE BLOCK FOR A CLOCK QUEUE ENTRY.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK, THEN A
;	DIRECTIVE STATUS OF 'D.RS1' IS RETURNED. ELSE THE ADDRESS OF
;	THE ALLOCATED BLOCK IS RETURNED TO THE CALLER IN R0.
;-

	.ENABL	LSB
$ALCLK::MOV	#C.LGTH,R1	;PICK UP LENGTH OF CLOCK BLOCK
	BR	10$		;

;+
; **-$DECLK-DEA      LLOCATE CLOCK QUEUE CORE BLOCK
;
; THIS ROUTINE IS CALLED TO DEALLOCATE A CORE BLOCK THAT WAS BEING USED
; FOR A CLOCK QUEUE ENTRY.
;
; INPUTS:
;
;	R0=ADDRESS OF THE CORE BLOCK TO BE DEALLOCATED.
;
; OUTPUTS:
;
;	THE CLOCK QUEUE ENTRY CORE BLOCK IS DEALLOCATED.
;-

$DECLK::MOV	#C.LGTH,R1	;PICK UP LENGTH OF CLOCK BLOCK
	BR	$DEACB		;

;+
; **-$ALPKT-ALLOCATE SEND OR I/O REQUEST CORE BLOCK
;
; THIS ROUTINE IS CALLED TO ALLOCATE A CORE BLOCK FOR A SEND OR I/O
; REQUEST QUEUE ENTRY.
;
; IN      PUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK, THEN A
;	DIRECTIVE STATUS OF 'D.RS1' IS RETURNED. ELSE THE ADDRESS OF
;	THE ALLOCATED BLOCK IS RETURNED TO THE CALLER IN R0.
;-

$ALPKT::MOV	#I.LGTH,R1	;SET LENGTH OF I/O PACKET
10$:	CALL	$ALOCB		;ATTEMPT TO ALLOCATE BLOCK
	BCC	80$		;IF CC SUCCESSFUL
	DRSTS	D.RS1		;ALLOCATION FAILURE

;+
; **-$DEPKT-DEALLOCATE SEND OR I/O REQUEST CORE BLOCK
;
; THIS ROUTINE IS CALLED TO DEALLOCATE A CORE BLOCK THAT W      AS BEING USED
; FOR A SEND OR I/O REQUEST QUEUE ENTRY.
;
; INPUTS:
;
;	R0=ADDRESS OF THE CORE BLOCK TO BE DEALLOCATED.
;
; OUTPUTS:
;
;	THE SEND OR I/O REQUEST QUEUE ENTRY CORE BLOCK IS DEALLOCATED.
;-

$DEPKT::MOV	#I.LGTH,R1	;SET LENGTH OF I/O PACKET

;+
; **-$DEACB-DEALLOCATE CORE BUFFER
; **-$DEAC1-DEALLOCATE CORE BUFFER (ALTERNATE ENTRY)
;
; THIS ROUTINE IS CALLED TO DEALLOCATE AN EXEC CORE BUFFER. THE BLOCK IS
; INSERTED INTO THE FREE BLOCK CHAIN BY CORE ADDRESS. IF AN ADJACENT
; BL      OCK IS CURRENTLY FREE, THEN THE TWO BLOCKS ARE MERGED AND INSERTED
; IN THE FREE BLOCK CHAIN.
;
; INPUTS:
;
;	R0=ADDRESS OF THE CORE BUFFER TO BE DEALLOCATED.
;	R1=SIZE OF THE CORE BUFFER TO DEALLOCATE IN BYTES.
;	R3=ADDRESS OF CORE ALLOCATION LISTHEAD-2 IF ENTRY AT $DEAC1.
;
; OUTPUTS:
;
;	THE CORE BLOCK IS MERGED INTO THE FREE CORE CHAIN BY CORE
;	ADDRESS AND IS AGCOMERATED IF NECESSARY WITH ADJACENT BLOCKS.
;-

$DEACB::MOV	#$CRAVL-2,R3	;POINT TO ALLOCATION MASK WORD


	.IF DF	Q$$OPT

      	ADD	(R3),R1		;ROUND TO NEXT BOUNDARY
	BIC	(R3)+,R1	;
	BEQ	80$		;IF EQ NO BLOCK TO RELEASE
	CMP	R1,#I.LGTH	;LENGTH EQUAL TO I/O PACKET?
	BNE	30$		;IF NE NO
	MOV	#$PKMAX,R2	;PNT TO MAX # OF PACKETS TO PREALLOCATE
	CMPB	(R2),-(R2)	;MAX NUMBER PREALLOCATED?
	BLOS	30$		;IF LOS YES
	INC	(R2)		;INDICATE ONE MORE AVAILABLE
	MOV	-(R2),(R0)	;LINK PACKET INTO LIFO LIST
	MOV	R0,(R2)		;
	RETURN			;

	.ENDC


$DEAC1::ADD	(R3),R1		;ROUND TO NEXT BOUNDARY
	BIC	(R3)+,R1	;CLEAR EXCESS
	BEQ	80$		;IF EQ NO B      LOCK TO RELEASE
30$:				;REF LABEL


	.IF DF	R$$DER!P$$CTL						;MSH142
									;**-1
	MOV	R3,-(SP)	;SAVE ADDRESS OF LISTHEAD

	.ENDC								;MSH142
									;**-1
40$:	MOV	R3,R2		;SAVE ADDRESS OF CURRENT BLOCK
	MOV	(R2),R3		;GET ADDRESS OF NEXT BLOCK
	BEQ	50$		;IF EQ END OF CHAIN
	CMP	R0,R3		;BLOCK GO HERE?
	BHIS	40$		;IF HIS NO
50$:	MOV	R3,(R0)		;ASSUME NO AGLOMERATION
									; BM113
	.IF DF	P$$CTL							; BM113
									; BM113
	CMP	#$CRAVL,(SP)	;DEALLOCATION OF EXEC'S POOL?		;MSH14      2
	BNE	53$		;IF NE NO, SKIP POOL TRACKING		;MSH142
	ADD	R1,$PRISZ	;COUNT SIZE IN POOL TOTAL		; BM113
53$:				;					;MSH142
									; BM113
	.ENDC	; DF P$$CTL						; BM113
									; BM113
	MOV	R0,-(SP)	;CALCULATE ADDRESS OF NEW BLOCK
	ADD	R1,(SP)		;

	.IF DF	R$$DER							;MSH142
									;**-1
	BCS	100$		;IF CS ILLEGAL DEALLOCATION
	CMP	2(SP),#$CRAVL	;DEALLOCATION IN EXECUTIVE POOL?
	BNE	55$		;IF NE NO
	CMP	R0,#$POOL	;DEALLOCATION BEFORE FRONT OF LIST?
	BLO	100$		;IF LO YES
	CMP	(SP),$EXSI      Z	;DEALLOCATION PAST END OF POOL?
	BHI	100$		;IF HI YES
55$:				;REFERENCE LABEL

	.IFTF

	CMP	R3,(SP)+	;EQUAL TO NEXT IN CHAIN?

	.IFT

	BLO	90$		;IF LO, DEALLOCATION OVERLAPS

	.IFTF

	BNE	60$		;IF NE NO
	MOV	(R3)+,(R0)	;MOVE LINK WORD TO BLOCK RELEASED
	ADD	(R3),R1		;MERGE TWO BLOCKS
60$:	MOV	R2,-(SP)	;SAVE ADDRESS OF PREVIOUS BLOCK
	MOV	R0,(R2)+	;ASSUME NO AGLOMERATION
	ADD	(R2),(SP)	;CALCULATE ADDRESS OF NEXT BLOCK
	CMP	R0,(SP)+	;EQUAL TO BLOCK BEING RELEASED?

	.IFT

	BHIS	65$	      	;IF HIS, NO OVERLAP
	CMP	(SP),#$CRAVL	;DEALLOCATION IN EXECUTIVE CORE POOL?
	BEQ	100$		;IF EQ YES (ELSE NOT SURE OF OVERLAP)
65$:				;REF LABEL

	.ENDC								;MSH142
									;**-1
	BNE	70$		;IF NE NO
	ADD	(R2),R1		;MERGE TWO BLOCKS
	MOV	(R0),-(R2)	;MOVE LINK WORD TO PREVIOUS BLOCK
	MOV	R2,R0		;SET NEW ADDRESS OF BLOCK
70$:	MOV	R1,2(R0)	;SET SIZE OF BLOCK RELEASED

									;MSH142
	.IF DF	P$$CTL							;MSH142
									;MSH142
	CMP	#$CRAVL,(SP)+	;ALLOCATION IN EXEC CORE POOL ?		;MSH142
	B      NE	80$		;IF EQ NO, SKIP DEALLOCATION CHECKS	;MSH142
	CMP	$PRISZ,$PRIHL	;DID WE CROSS UPPER POOL LIMIT?		;MSH142
	BLOS	80$		;IF LOS NO				;MSH142
	MOV	#PC.HIH!<PC.HIH*400>,R2 ;SET UP HIGH POOL CONDITION	;MSH142
	BR	$PLTRQ		;REQUEST POOL MONITOR TASK		;MSH142
									;MSH142
	.IFF								;MSH142
									;MSH142
	.IF DF	R$$DER							;MSH142
									;**-1
	TST	(SP)+		;POP ADDRESS OF LISTHEAD

	.ENDC								;MSH142
									; BM113
$PLTRQ::			;MAKE SURE $PLTRQ IS ALWAYS DEFINED	; BM113
								      	; BM113
	.ENDC	; NDF	P$$CTL						; BM113
									;**-1
80$:	RETURN			;

	.IF DF	R$$DER							;MSH142
									;**-1
90$:	TST	R3		;INSERT AT END OF LIST?
	BEQ	60$		;IF EQ YES, OK
100$:	CRASH			;CRASH SYSTEM, BAD CORE DEALLOCATION

	.ENDC


;+									; BM113
; **-$PLTRQ-REQUEST POOL MONITOR TASK					; BM113
;									; BM113
; THIS ROUTINE IS USED TO REQUEST THE EXECUTION OF THE POOL		;MSH142
; MONITOR TASK, IF INSTALLED. THE FORMAT OF THE POOL TASK/EXECUTIVE	;MSH142
; COMMUNICATIONS WOR      D IS AS FOLLOWS:					;MSH142
;									;MSH142
;	$POLST	CONTAINS CONDITION BITS INDICATING THE CUMULATIVE	;MSH142
;		HISTORY OF THE POOL'S CONDITION SINCE THE LAST TIME	;MSH142
;		THAT THE POOL MONITOR TASK CLEARED THEM. THESE BITS	;MSH142
;		ARE SET BY THIS ROUTINE AND MAY BE CLEARED BY THE	;MSH142
;		POOL MONITOR TASK. NOTE THAT MORE THAN ONE BIT MAY	;MSH142
;		BE SET IN THIS BYTE AT ANY ONE TIME.			;MSH142
;	$POLST+1 CONTAINS INHIBIT BITS INDICATING WHAT POOL CONDITIONS	;MSH142
;		THE POOL MONIT      OR TASK IS CURRENTLY AWARE OF. A BIT SET	;MSH142
;		IN THIS BYTE INDICATES TO THIS ROUTINE A POOL CONDITION	;MSH142
;		THAT DOES NOT REQUIRE EXECUTION OF THE POOL MONITOR	;MSH142
;		TASK. THESE BITS ARE ONLY MODIFIED BY THE POOL TASK.	;MSH142
;		GENERALLY, THERE IS NEVER MORE THAN ONE BIT SET IN	;MSH142
;		THIS BYTE AT ANY GIVEN TIME.				;MSH142
;									;MSH142
; THE CALLER OF THIS ROUTINE PROVIDES A BIT MASK INDICATING A		;MSH142
; POOL CONDITION THAT IT WISHES TO MAKE KNOWN TO THE POOL MONITOR	;      MSH142
; TASK. THE GENERAL FORM OF THIS BIT MASK IS #<PC.XXX!<PC.XXX*400>>,	;MSH142
; WHERE 'XXX DENOTES WHICH OF THE EIGHT POTENTIAL CONDITIONS THE	;MSH142
; USER WISHES TO MAKE KNOWN TO THE POOL MONITOR TASK (BY STORING	;MSH142
; THE PC.XXX BIT IN THE LOW BYTE OF $POLST). THE FOLLOWING ACTIONS	;MSH142
; CAN OCCUR:								;MSH142
;									;MSH142
;	1) IF THE SPECIFIED LOW BYTE MASK BIT IS ALREADY SET IN THE	;MSH142
;	LOW BYTE OF $POLST, THEN THIS INDICATES THAT THIS ROUTINE HAS	;MSH142
;	BEEN CAL      LED MULTIPLE TIMES FOR THE SAME POOL CONDITION BEFORE	;MSH142
;	THE POOL TASK COULD EXECUTE AND CLEAR THE BIT. IN THIS CASE,	;MSH142
;	THE ROUTINE RETURNS.						;MSH142
;									;MSH142
;	2) IF THE BIT IS NOT ALREADY SET IN THE LOW BYTE OF $POLST,	;MSH142
;	THEN THIS INDICATES THAT THE POOL PROGRAM MIGHT NOT BE AWARE	;MSH142
;	OF THIS POOL CONDITION AND A SECOND CHECK MUST BE MADE USING	;MSH142
;	THE HIGH BYTE OF $POLST. IF THE SPECIFIED HIGH BYTE MASK BIT	;MSH142
;	IS ALREADY SET IN THE HIGH BYTE,       THEN THE POOL TASK IS		;MSH142
;	CURRENTLY AWARE OF THE CONDITION AND DOES NOT WISH TO EXECUTE.	;MSH142
;	IF THE BIT IS NOT SET IN THE HIGH BYTE, THEN THE POOL CONDITION	;MSH142
;	IS A NEW ONE AND THE POOL MONITOR TASK IS REQUESTED TO RUN.	;MSH142
;									;MSH142
; THIS INTERFACE IS FLEXIBLE ENOUGH TO ALLOW OTHER INTERFACE PROTOCOLS:	;MSH142
;									;MSH142
;	- ONE INHIBIT BIT ($POLST+1) COULD BE DEFINED TO 'COVER' MORE	;MSH142
;	THAN ONE CONDITION BIT ($POLST+0). FOR INSTANCE, $PLTRQ CAN	;MSH1      42
;	BE CALLED WITH R2=403, WHERE THERE ARE TWO CONDITION BITS	;MSH142
;	SET, BUT ONLY ONE INHIBIT BIT SPECIFIED FOR BOTH.		;MSH142
;									;MSH142
;	- THERE NEED NOT BE A MIRROR-IMAGE RELATIONSHIP BETWEEN THE	;MSH142
;	INHIBIT BITS AND THE CONDITION BITS. FOR VARYING CONDITIONS	;MSH142
;	AND STATES, VARIOUS COMBINATIONS OF THESE BITS CAN BE ENCODED.	;MSH142
;									;MSH142
;	- NO INHIBIT BIT NEED BE SPECIFIED AT ALL. IN THIS CASE, EVEN	;MSH142
;	IF THE POOL MONITOR TASK HAD SET THE CORRESPONDI      NG INHIBIT BIT	;MSH142
;	IN $POLST+1 FOR THE CONDITION ABOUT TO BE REPORTED, LEAVING	;MSH142
;	THE HIGH BYTE OF R2 CLEAR WILL FORCE THE POOL MONITOR TASK TO	;MSH142
;	EXECUTE FOR THAT CONDITION REPORTED IN THE LOW BYTE OF		;MSH142
;	R2 (UNLESS, OF COURSE, THAT BIT IS ALREADY SET IN $POLST+0,	;MSH142
;	INDICATING A MULTIPLE REQUEST). FOR INSTANCE, IF $PLTRQ IS	;MSH142
;	CALLED WITH R2=1, THE POOL TASK MAY EXECUTE AND SET $POLST	;MSH142
;	TO 400, THE INHIBIT BIT FOR POOL CONDITION '1'. IF  $PLTRQ	;MSH1      42
;	WERE THEN CALLED AGAIN WITH R2=1, THE POOL TASK WOULD AGAIN	;MSH142
;	BE CALLED BECAUSE R2 DID NOT HAVE THE INHIBIT BIT SPECIFIED.	;MSH142
;	THIS OPERATION FORCES THE POOL TASK TO RESPOND ANYWAY.		;MSH142
;									;MSH142
; THE REASON FOR SUCH FLEXIBILITY IS TO GENERALIZE THE INTERFACE TO	;MSH142
; BE USEFUL FOR A VARIETY OF CHORES. THE INTERFACE NEED NOT BE LIMITED	;MSH142
; TO POOL STATUS REPORTING.						;MSH142
;									;MSH142
; INPUTS:								;MSH142
;									;MSH142
;	R2=POOL CONDIT      ION BIT MASK (PC.XXX OR'ED WITH PC.XXX*400).	;MSH142
;									;MSH142
; OUTPUTS:								;MSH142
;									;MSH142
;	IF NO BITS IN THE LOW BYTE OF R2 ARE SET IN $POLST AND NO	;MSH142
;	BITS IN THE HIGH BYTE OF R2 ARE SET IN $POLST+1, THEN THE	;MSH142
;	POOL TASK IS REQUESTED WITH THE REASON FOR THE REQUEST		;MSH142
;	(PC.XXX) STORED IN THE LOW BYTE OF $POLST. OTHERWISE, RETURN.	;MSH142
;									;MSH142
;	R0, R1 AND R3 ARE PRESERVED.					;MSH142
;-									; BM113
									; BM113
	.IF DF	P$$CTL      							; BM113
									;MSH142
	.ENABL	LSB							;MSH142
$PLTRQ::BITB	R2,$POLST	;ALREADY REQUESTED FOR THIS CONDITION?	;MSH142
	BNE	20$		;IF NE YES, AVOID MULTIPLE REQUESTS	;MSH142
	BISB	R2,$POLST	;INDICATE CURRENT POOL CONDITION	;MSH142
	CLRB	R2		;CHECK POOL TASK INHIBIT BITS		;MSH142
	BIT	R2,$POLST	;REQUEST POOL TASK FOR THIS CONDITION?	;MSH142
	BNE	20$		;IF NE NO, TASK AWARE OF POOL CONDITION	;MSH142
	MOV	R0,-(SP)	;SAVE R0				;MSH142
	MOV	$PTTCB,R0	;POOL MONITOR TASK INSTALLED?		;MSH142
	BEQ	   ²  10$		;IF EQ NO, CAN'T REQUEST IT		;MSH142
	MOV	R1,-(SP)	;SAVE R1				;MSH142
	MOV	R3,-(SP)	;SAVE R3				;MSH142
	CALL	$EXRQN		;REQUEST THE POOL MONITOR TASK		;MSH142
	MOV	(SP)+,R3	;RESTORE R3				;MSH142
	MOV	(SP)+,R1	;RESTORE R1				;MSH142
10$:	MOV	(SP)+,R0	;RESTORE R0				;MSH142
20$:	RETURN			;					;MSH142
	.DSABL	LSB							;MSH142
									;MSH142
	.ENDC	; DF P$$CTL						; BM113
									; BM113
	.DSABL	LSB

	.END
 ²         á˜:kQ	› c,        	.TITLE	DRQIO
	.IDENT	/11.22/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 11.22
;
; D. N. CUTLER 8-OCT-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	B. A. O'CONNELL
;
; MODIFIED BY:
;
;	M. S. HARVEY	17-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M.       S. HARVEY	13-OCT-79
;		MSH045 -- DO NOT ALLOW $DRQRQ TO BE IN DIRECTIVE COMMON
;			  AND CLEAN UP SOME COMMENTS
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	1-AUG-80
;		MSH109 -- PREVENT TRANSLATION OF IO.RVB TO IO.WLB
;
;	M. S. HARVEY	25-FEB-81
;		MSH152 -- REJECT IO.ATT OR IO.DET IF IQ.X SUBFUNCTION
;			  BIT IS SET
; 
; 	C. H. FRANKS	11-MAR-81
; 		CHF023 -- ADD SOFTWARE WRITE LOCK
;
;	M. S. HARVEY	14-MAR-81      
;		MSH151 -- DO NOT ALLOW GROUP GLOBAL USE COUNT TO
;			  BE DECREMENTED BEFORE BEING INCREMENTED
;
;	M. S. HARVEY	14-APR-81
;		MSH163 -- CLEAN UP SOME OF THE CODE
;
;	M. S. HARVEY	1-SEP-81
;		MSH187 -- ADD EXPLICIT CHECK FOR ODD IOSB ADDRESSES
;			  FOR PROCESSORS WITHOUT THE ODD ADDRESS
;			  TRAP MECHANISM
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
;	M. S. HARVEY	6-OCT-81
;		MSH194 -- EXTERNALIZE WAITFOR ROUTINE
;
;
; MACRO LIBRARY CALLS
;

	.MCALL	F11DF$,H      WDDF$,PKTDF$,TCBDF$,PCBDF$
	F11DF$			;DEFINE FILES-11 CONTROL BLOCK OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS

;
; LOCAL DATA
;
; TEMPORARY LOCATION TO MARK STACK ADDRESS
;

MSTK:	.BLKW	1		;

; POLISH INTERPRETER DATA BASE
;
; FUNCTION CODE DISPATCH VECTOR
;


	.IF DF	A$$CPS

FCDSP:	.WORD	FCIFC		;10-ILLEGAL FUNCTION
	.WORD	FCPKT		;11-FIND FILE NAME IN       DIRECTORY


	.IF DF	R$$LKL

	.WORD	UNLCK		;12-UNLOCK BLOCK

	.IFF

	.WORD	FCIFC		;12-ILLEGAL FUNCTION

	.ENDC


	.WORD	FCPKT		;13-REMOVE FILE NAME FROM DIRECTIRY
	.WORD	FCPKT		;14-ENTER FILE NAME IN DIRECTORY
	.WORD	FCACC		;15-ACCESS FILE FOR READ
	.WORD	FCACC		;16-ACCESS FILE FOR READ AND WRITE
	.WORD	FCACC		;17-ACCESS FILE FOR READ, WRITE, AND EXTEND
	.WORD	FCDAC		;20-DEACCESS FILE
	.WORD	FCRVB		;21-READ VIRTUAL BLOCK
	.WORD	FCWVB		;22-WRITE VIRTUAL BLOCK
	.WORD	FCEXT		;23-EXTEND FI      LE
	.WORD	FCCRE		;24-CREATE FILE
	.WORD	FCDEL		;25-MARK FILE FOR DELETE/TRUNCATE FILE
	.WORD	FCPKT		;26-READ FILE ATTRIBUTES
	.WORD	FCPKT		;27-WRITE FILE ATTRIBUTES
	.WORD	FCPKT		;30-USER MAGTAPE CONTROLL FUNCTION
	.WORD	FCWVB		;31-TRANSMIT PROCESS MESSAGE
	.WORD	FCRVB		;32-RECEIVE PROCESS MESSAGE
	.WORD	FCCON		;33-CONNECT TO PROCESS
	.WORD	FCDIS		;34-DISCONNECT FROM PROCESS
	.WORD	FCNCT		;35-NETWORK CONTROL FUNCTION
	.WORD	FCIFC		;36-ILLEGAL FUNCTION
	.WORD	FCIFC		;37-ILLEGAL FUNCTION


	.IF       NDF	M$$NET

FCCON:				;REF LABEL IF NO NETWORK SUPPORT
FCDIS:				;REF LABEL IF NO NETWORK SUPPORT
FCNCT:				;REF LABEL IF NO NETWORK SUPPORT

	.IFTF

;
; ILLEGAL FUNCTION
;

FCIFC:	.WORD	IEIFC		;SET ILLEGAL FUNCTION STATUS

;
; ACCESS FILE FOR READ, READ/WRITE, OR READ/WRITE/EXTEND
;

FCACC:	.WORD	CKDMO		;CHECK IF VOLUME MARKED FOR DISMOUNT
	.WORD	CKALN		;CHECK IF FILE ALREADY ACCESSED ON LUN
	.WORD	CKMOU		;CHECK VOLUME MOUNTED THIS USER
	.WORD	CKACP		;SET FLAG TO QUEUE TO ACP
	.WORD	      BDPKT		;BUILD AN I/O PACKET
	.WORD	CKRLK		;SYNCHRONIZE ACCESS AND EXIT

;
; DEACCESS FILE
;

FCDAC:	.WORD	CKNLN		;CHECK IF FILE ACCESSED ON LUN

	.IF	DF,A$$NSI

	.WORD	CKQMT		;QUEUE TO MTAACP IF ANSI

	.ENDC

	.WORD	BDPKT		;BUILD AN I/O PACKET
	.WORD	CKRLK		;EXIT

;
; READ VIRTUAL BLOCK
;

FCRVB:	.WORD	CKNLN		;CHECK IF FILE ACCESSED ON LUN
	.WORD	CKRAC		;CHECK READ ACCESS AND EXIT

;
; WRITE VIRTUAL BLOCK
;

FCWVB:	.WORD	CKNLN		;CHECK IF FILE ACCESSED ON LUN
	.WORD	CKWAC		;CHEC      K WRITE ACCESS AND EXIT

;
; CREATE FILE
;	CREATE & ACCESS NOT LEGAL COMBINATION
;

FCCRE:	.WORD	CKDMO		;CHECK IF VOLUME MARKED FOR DISMOUNT
	.WORD	CKALN		;CHECK IF FILE ACCESSED ON LUN
	.WORD	CKPKT		;JOIN COMMON ACP & CHECK MOUNT

;
; DELETE FILE -- CHECK IF REALLY TRUNCATE
; DON'T MOVE THIS - FALLS THRU TO FCPKT
;

FCDEL:	.WORD	CKTRN		;CHECK IF REALLY TRUNCATE

;
; BUILD AN I/O PACKET FOR FIND, ENTER, REMOVE, READ ATTRIBUTES
; AND WRITE ATTRIBUTES
;

FCPKT:	.WORD	CKACP		;SET FLAG TO       QUEUE TO ACP
	.WORD	CKMOU		;CHECK VOLUME MOUNTED THIS USER
	.WORD	BDPKT		;BUILD AN I/O PACKET
	.WORD	CKXIT		;EXIT

;
; EXTEND FILE -- INCR WINDOW TURN PENDING COUNT
;

FCEXT:	.WORD	CKPND		;INCR WINDOW TURN PENDING CNT FOR EXTEND

;
; EXPLICIT UNLOCK BLOCK FUNCTION
;


	.IF DF	R$$LKL

UNLCK:	.WORD	CKNLN		;CHECK IF FILE ACCESSED ON LUN
	.WORD	UNLXT		;SET REGISTERS AND EXIT

	.ENDC


	.IFF

;
; CONNECT TO PROCESS
;

FCCON:	.WORD	CKDMO		;CHECK IF VOLUME MARKED FOR DISMOUNT
	.WORD      	CKALN		;CHECK IF PROCESS ALREADY CONNECTED ON LUN
	.WORD	CKCON		;ADDRESS CHECK CONNECT BUFFER AND EXIT
	.WORD	CKRLK		;INTERLOCK LUN USAGE AND EXIT

;
; DISCONNECT FROM PROCESS
;

FCDIS:	.WORD	CKNLN		;CHECK IF PROCESS CONNECTED ON LUN
	.WORD	CKDIS		;CHECK BUFFER AND COPY PARAMETERS
	.WORD	CKRLK		;INTERLOCK LUN USAGE AND EXIT

;
; NETWORK CONTROL FUNCTION
;

FCNCT:	.WORD	CKDMO		;CHECK IF VOLUME MARKED FOR DISMOUNT
	.WORD	CKCON		;ADDRESS CHECK BUFFER
	.WORD	CKXIT		;EXIT


	.ENDC


	.EN      DC


									;CHF023
; 									;CHF023
; TABLE OF SPECIAL FUNCTION CODES TO BE CHECKED BY SOFTWARE WRITE LOCK	;CHF023
; 									;CHF023
									;CHF023
	.IF DF	S$$WLK							;CHF023
									;CHF023
WLKTB:									;CHF023
				;DEVICE DEPENDENT CODES			;CHF023
	.WORD	IO.SMD		;SET MEDIA DENSITY			;CHF023
	.WORD	IO.EOF		;WRITE END OF FILE			;CHF023
	.WORD	IO.ERS		;ERASE TAPE				;CHF023
	.WORD	IO.DSE		;DATA SECURITY ERASE			;CHF023
									;CHF023
	.IF DF	D$$IAG							;CHF023
				;DIAGNOST      IC CODES			;CHF023
	.WORD	IO.WDH		;WRITE DATA AND HEADER			;CHF023
	.WORD	IO.WTD		;WRITE TRACK DESCRIPTOR			;CHF023
	.WORD	IO.TDD		;WRITE TRACK DESCRIPTOR DISPLACED	;CHF023
	.WORD	IO.CEW		;WRITE BLOCK ON CE TRACK		;CHF023
									;CHF023
	.ENDC	;D$$IAG							;CHF023
									;CHF023
	.WORD	0		;TERMINATOR FOR WRITE LOCK TABLE	;CHF023
									;CHF023
	.ENDC	;S$$WLK							;CHF023
									;CHF023
									;CHF023
;+
; **-$DRQIO-QUEUE I/O REQUEST
; **-$DRQIW-QUEUE I/O REQUEST AND WAIT.
;
; TH      ESE DIRECTIVES INSTRUCT THE SYSTEM TO PLACE AN I/O REQUEST IN A
; QUEUE OF PRIORITY ORDERED REQUESTS FOR A DEVICE-UNIT SPECIFIED BY
; A LOGICAL UNIT NUMBER.  IN ADDITION, IF THE DIRECTIVE IS QIO AND
; WAIT AND AN EVENT FLAG IS SPECIFIED, THE TASK IS PUT INTO A WAIT STATE
; FOR THE SPECIFIED EVENT FLAG.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(1./3.),DPB SIZE(12.).
;	WD. 01 -- I/O FUNCTION CODE.
;	WD. 02 -- LUN AND UNUSED BYTE.
;	WD. 03 -- EVENT FLAG NUMBER AND PRIORITY (PRIORITY IS IGNORED).
;	WD. 04 -      - ADDRESS OF I/O STATUS BLOCK.
;	WD. 05 -- ADDRESS OF AST SERVICE ROUTINE.
;	WD. 06 -- PARAMETER 1.
;	WD. 07 -- PARAMETER 2.
;	WD. 10 -- PARAMETER 3.
;	WD. 11 -- PARAMETER 4.
;	WD. 12 -- PARAMETER 5.
;	WD. 13 -- PARAMETER 6.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE I/O FUNCTION CODE IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)      
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS5' IS RETURNED IF SPECIFIED
;			LUN IS NOT ASSIGNED.
;		DIRECTIVE STATUS OF 'D.RS6' IS RETURNED IF DEVICE	;MSH045
;			DRIVER NOT LOADED.				;MSH045
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF THE		;MSH187
;			SPECIFIED I/O STATUS BLOCK IS ODD OR NOT	;MSH187
;			WITHIN THE CURRENT VIRTUAL ADDRESS SPACE	;MSH187
;-

	.ENABL	LSB
$DRQIO::MOV	(R3)+,-(      SP)	;SAVE I/O FUNCTION CODE
	CALL	$MPLUN		;MAP LUN TO UCB ADDRESS
	BCC	10$		;IF CC LUN ASSIGNED
	DRSTS	D.RS5		;SET DIRECTIVE STATUS
10$:	BIT	#1,(R1)		;OPERATION PENDING?
	BEQ	15$		;IF EQ NO
	ADD	#6,SP		;REMOV FUNC, RETURN AND +1 FROM STACK
	MOV	(R4),R0		;GET SAVED TASK STACK POINTER
	SUB	#2,4(R0)	;BACKUP TASK PC SO EMT WILL BE RE-EXECUTED
	CALLR	$TKWSE		;WAITFOR SIGNIFICANT EVENT
15$:				;


	.IF DF	L$$DRV

	MOV	(R0),R2		;GET DCB ADDRESS
	TST	D.DSP(R2)	;IS THE DRIVER RESIDENT?
	BNE	16$		;IF       NE YES
	DRSTS	D.RS6		;SET DIRECTIVE STATUS
16$:				;

	.ENDC


	MOV	R0,-(SP)	;SAVE POINTER TO UCB
	MOV	R1,-(SP)	;SAVE POINTER TO SECOND LUN WORD
	MOVB	(R3),-(SP)	;SAVE EVENT FLAG NUMBER
	CALL	$CEFNG		;CONVERT EVENT FLAG NUMBER		;MSH049
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
	BIC	#1,R1		;CLR GRP GLOBAL 2ND WORD INDICATOR	;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
	BIC	R0,(R1)		;CLEAR SPECIFIED EVENT FLAG		;**-1
	MOV	R3,-(SP)	;SAVE ADDRESS OF I/      O STATUS BLOCK ADDRESS
	MOV	(R3),R0		;GET ADDRESS OF I/O STATUS BLOCK ADDRESS
	BEQ	20$		;IF EQ NO I/O STATUS BLOCK SPECIFIED


	.IF DF	M$$MGE

	BIT	#1,R0		;SPECIFIED I/O STATUS BLOCK ODD?	;MSH187
	BEQ	$DQLM1		;IF EQ NO				;MSH187
	DRSTS	D.RS98		;I/O STATUS BLOCK MUST WORD ALIGNED	;MSH187
$DQLM1::CLR	-(SP)		;ZERO I/O STATUS BLOCK
	MTPI	(R0)+		;
	CLR	-(SP)		;
	MTPI	(R0)		;
$DQLM2::			;REF LABEL

	.IFF


	.IF DF	A$$CHK

	MOV	#4,R1		;SET LENGTH OF I/O STATUS BLOCK
	CALL	$ACHKW		;ADDRESS CH      ECK I/O STATUS BLOCK

	.ENDC


	CLR	(R0)+		;CLEAR I/O STATUS BLOCK
	CLR	(R0)		;

	.ENDC


20$:	CALL	$ALPKT		;ALLOCATE AN I/O PACKET

;									;MSH151
; AT THIS POINT, THE QIO DIRECTIVE ITSELF IS SUCCESSFUL. ANY ERRORS	;MSH151
; ENCOUNTERED AFTER THIS POINT WILL BE REPORTED AS I/O STATUS IN	;MSH151
; THE SPECIFIED IOSB. THE DSW WILL SHOW SUCCESS.			;MSH151
;									;MSH151
; IF THE SPECIFIED EVENT FLAG WAS GROUP GLOBAL, THE USE COUNT MUST	;MSH151
; BE INCREMENTED NOW RATHER THAN IN THE D      ISPATCHER. THIS PREVENTS	;MSH151
; DECREMENTING BEFORE INCREMENTING IN CASE THE I/O PACKET IS FLUSHED	;MSH151
; BEFORE RETURNING TO THE DISPATCHER.					;MSH151
;									;MSH151
									;MSH151
	.IF DF	G$$EFN							;MSH151
									;MSH151
	INC	@$GEFPT		;LOCK GROUP GLOBALS PENDING I/O COMPLETI;MSH151
									;MSH151
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH151
	INCB	@$GFTCB		;DON'T ALLOW SLAVE TASKS TO CHANGE UIC	;MSH151
									;MSH151
	.ENDC								;MSH151
									;MSH151
	.ENDC	      							;MSH151

	.IF DF	R$$LKL

	CLR	I.PRM+16(R0)	;INITIALLY CLEAR LOCK ENTRY POINTER

	.ENDC


	INCB	T.IOC(R5)	;INCREMENT I/O REQUEST COUNT
	MOV	(SP)+,R3	;RETRIEVE ADDRESS OF I/O STATUS BLOCK ADDRESS
	CMPB	-10(R3),#3	;IS FUNCTION QIO AND WAIT?
	BNE	25$		;IF NE NO
	MOV	R0,-(SP)	;SAVE PACKET ADDRESS
	MOVB	2(SP),R0	;PICK UP EVENT FLAG NUMBER
	BEQ	24$		;IF EQ NONE SPECIFIED
	CALL	$CEFI		;CONVERT FLAG TO MASK AND ADDRESS
	CALL	$DRWFD		;PUT TASK IN WAITFOR STATE		;MSH194
									;MSH049
	.IF       DF	G$$EFN							;MSH049
									;MSH049
	INC	@$GEFPT		;KEEP GROUP GLOBALS AROUND FOR WAITFOR T;MSH049
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	INCB	@$GFTCB		;INC GRP GLOBAL USE COUNT FOR TASK	;MSH076
									;MSH076
	.ENDC	;R$$SND							;MSH076
									;MSH049
	.ENDC								;MSH049
									;MSH049
24$:	MOV	(SP)+,R0	;RESTORE PACKET ADDRESS			;MSH151
25$:				;					;MSH151
									;MSH151
	.IF DF	G$$EFN							;MSH151
									;MSH151
	MOV	#$GEFDM,$GEFPT	;PREVE      NT USE COUNT INCREMENT IN DISPATCH;MSH151
									;MSH151
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH151
	MOV	#$GEFDM,$GFTCB	;DON'T LOCK SLAVE TASKS AGAIN		;MSH151
									;MSH151
	.ENDC								;MSH151
									;MSH151
	.ENDC								;MSH151
									;MSH151
	MOV	R0,R4		;COPY PACKET ADDRESS			;MSH151
	TST	(R4)+		;POINT TO SECOND WORD IN PACKET		;**-3
	MOVB	T.PRI(R5),(R4)+	;PRIORITY IS THAT OF ISSUING TASK
	MOVB	(SP)+,(R4)+	;INSERT EVENT FLAG NUMBER
	MOV	R5,(R4)+	;INSERT TCB ADDRESS
	MOV      	(SP)+,(R4)+	;INSERT POINTER TO SECOND LUN WORD
	MOV	(SP)+,R5	;RETRIEVE UCB ADDRESS
	MOV	R5,(R4)+	;INSERT UCB ADDRESS
	MOV	(SP)+,(R4)	;INSERT I/O FUNCTION CODE

	.IF	DF,A$$CPS

	CLR	-(SP)		;SET FLAG TO QUEUE TO DRIVER (NE 0=ACP)

	.ENDC

	MOV	R0,-(SP)	;SAVE ADDRESS OF I/O PACKET
	CLR	-(SP)		;CLEAR ADDRESS OF SECONDARY CONTROL BLOCK
	MOV	SP,MSTK		;MARK STACK ADDRESS
	MOV	(R4)+,-(SP)	;SAVE I/O FUNCTION CODE
	CLR	R2		;ASSUME NO I/O STATUS BLOCK SPECIFIED
	MOV	(R3)+,R0	;GET ADDRESS OF I/O STATUS       BLOCK
	BEQ	30$		;IF EQ NONE SPECIFIED
	CALL	$RELOC		;RELOCATE I/O STATUS BLOCK ADDRESS
30$:	MOV	R0,(R4)+	;INSERT VIRTUAL ADDRESS OF I/O STATUS BLOCK
	MOV	R1,(R4)+	;INSERT RELOCATION BIAS
	MOV	R2,(R4)+	;INSERT DISPLACEMENT ADDRESS
	MOV	(R3)+,(R4)+	;INSERT AST SERVICE ROUTINE ADDRESS
	MOV	(SP),R2		;RETRIEVE I/O FUNCTION CODE
	CLRB	R2		;CLEAR MODIFIER FLAGS
	SWAB	R2		;SWAP FUNCTION CODE INTO RIGHT BYTE
	BEQ	FCKIL		;IF EQ KILL I/O FUNCTION


	.IF DF	M$$MUP

	MOV	U.OWN(R5),R0	;IS THE DEVICE OWNED      ?
	BEQ	35$		;IF EQ NO
	BITB	#US.PUB,U.ST2(R5) ;PUBLIC ACCESS ALLOWED?
	BNE	35$		;IF NE YES
	MOV	$TKTCB,R1	;POINT TO CURRENT TASK'S TCB
	CMP	T.UCB(R1),R0	;DEVICE OWNED BY CURRENT TASK?
	BEQ	35$		;IF EQ YES
	BIT	#T3.PRV,T.ST3(R1) ;CURRENT TASK PRIVILEGED?
	BNE	35$		;IF NE YES
	JMP	IEPRI		;ELSE PRIVILEGE VIOLATION
35$:				;ACCESS ALLOWED

	.ENDC


	CMP	R2,#31.		;FUNCTION CODE IN RANGE?
	BHI	IEIFC		;IF HI NO
	MOV	(R5),R1		;GET ADDRESS OF DEVICE DCB
	ADD	#D.MSK,R1	;ASSUME FUNCTION CODE IN 0-15.       RANGE
	CMP	R2,#15.		;0-15. FUNCTION CODE?
	BLOS	40$		;IF LOS YES
	ADD	#10,R1		;POINT TO SECOND MASK SET
	SUB	#16.,R2		;REDUCE FUNCTION CODE
40$:	ASL	R2		;CONVERT TO WORD INDEX
	MOV	$BTMSK(R2),R2	;GET FUNCTION MASK WORD
	BIT	R2,(R1)+	;IS THIS A LEGAL FUNCTION?
	BEQ	IEIFC		;IF EQ NO
	BITB	#US.OFL,U.ST2(R5) ;DEVICE OFFLINE?
	BNE	IEOFL		;IF NE YES
	BIT	R2,(R1)+	;IS THIS A CONTROL FUNCTION?
	BNE	FCCTL		;IF NE YES
	BIT	R2,(R1)+	;IS FUNCTION NOP'ED?
	BNE	ISSUC		;IF NE YES


	.IF DF	A$$CPS

	TST      	U.CW1(R5)	;MOUNTABLE DEVICE?
	BPL	80$		;IF PL NO
	MOVB	U.STS(R5),R0	;GET STATUS BYTE FOR TESTS BELOW
	BITB	#US.MNT!US.FOR,R0	;DEVICE MOUNTED AND NOT FOREIGN?
	BNE	60$		;IF NE NO
	BIT	R2,(R1)		;ACP FUNCTION?
	BEQ	70$		;IF EQ NO
	MOVB	1(SP),R2	;RETRIEVE I/O FUNCTION CODE
	SUB	#10,R2		;NORMALIZE FOR POLISH DISPATCH
	BLT	50$		;IF LT TABLE INCONSISTANCY
	ASL	R2		;CONVERT TO WORD INDEX
	MOV	R5,-(SP)	;SAVE UCB ADDRESS FOR POLISH ROUTINES
	MOV	R5,R0		;
	MOV	I.LN2-I.PRM(R4),R1 ;SAVE ADDRESS OF SECOND L      UN WORD
	MOV	R1,-(SP)	;FOR POLISH ROUTINES
	MOV	FCDSP(R2),R5	;GET ADDRESS OF POLISH VECTOR
	JMP	@(R5)+		;EXECUTE POLISH ROUTINE

;
;	REGISTERS AT POLISH DISPATCH:
;
;	R0 -	UCB
;	R1 -	ADDRESS 2ND LUN WORD
;	R2 -	NORMALIZED FCTN CODE
;	R3 -	POINTER TO PARAMETERS, INITIALLY -> PARAMETER 1
;	R4 -	POINTER INTO I/O PACKET, INITIALLY -> I.PRM
;
;	SP->	2ND LUN WORD ADDRESS
;		UCB ADDRESS
;		FUNCTION CODE
;	MSTK -> SECONDARY CONTROL BLOCK ADDRESS (OR 0)
;		I/O PACKET ADDRESS
;		QUEUE FLAG (0=DRIVE      R; NE=ACP)
;
; SEE COMMENT LOCATED BETWEEN FCXIT AND $DRQRQ FOR DETAILS ON QUEUING
; AND INTERLOCKING INTERFACES FOR MOUNTABLE DEVICES.
;
;
; DEVICE TABLE MASK WORD INCONSISTANCY
;

50$:	CRASH			;

;
; DEVICE NOT MOUNTED OR MOUNTED AS FOREIGN
;

60$:	BITB	#US.MNT,R0	;DEVICE NOT MOUNTED OR FOR?
	BEQ	65$		;BRANCH IF MOUNTED FOREIGN
;
; DEVICE NOT MOUNTED
;	ALLOW TRANSFER FUNTCTION
;	ACP FUNCTIONS ARE ILLEGAL
;
	BIT	R2,(R1)		;ACP FUNCTION
	BNE	75$		;IF NE YES
	BR	FCTRN		;

;
; MOUNTE      D FOREIGN
;	CHECK IF VOLUME MOUNTED THIS USER
;	IF ACP FUNCTION:
;		ERROR IF NO ACP
;		COPY PARAMETERS 1-6  (NO POLISH IF FOREIGN)
;		QUEUE TO ACP UNLESS UC.QUE SET (U.CTL)
;	IF TRANSFER FUNCTION:
;		ADDRESS CHECK AND RELOCATE BUFFER ADDRESS-PARM 1
;		MAP ADDRESS TO 18/22 BIT PHYSICAL ADDRESS
;		INCREMENT VOLUME TRANSACTION COUNT
;		COPY PARAMETERS 2-6
;		QUEUE TO DRIVER
;
65$:				;

	.IF	DF,M$$MUP

	CALL	CXMOU		;CHECK VOLUME MOUNTED THIS USER
	BCS	75$		;ERROR

	.ENDC

	BIT	R2,(R1)		;A      CP FUNCTION?
	BEQ	FCTRN		;NOT ACP--TRANSFER
	TST	U.ACP(R5)	;MOUNTED WITH AN ACP?
	BEQ	75$		;ERROR IF NO ACP
	INC	6(SP)		;SET FLAG TO QUEUE TO ACP
	MOV	U.VCB(R5),R1	;HAVE A VCB?
	BEQ	FCXOP		;NO VCB THEN DON'T DO ANYTHING
	INC	(R1)		;INCREMENT VOL TRANS CNT IN VCB
	BR	FCXOP		;INSERT PARAMETERS 1-6
;
; DEVICE MOUNTED AND NOT FOREIGN BUT NOT ACP FUNCTION
;

70$:	CMP	#IO.LOV,(SP)	;LOAD OVERLAY FUNCTION?
	BEQ	FCTRN		;IF EQ YES
	MOV	$TKTCB,R0	;GET ADDRESS OF TCB OF CURRENT TASK
	BIT	#T3.PRV,T.ST3(R      0) ;TASK PRIVILEGED?
	BNE	FCTRN		;IF NE YES
75$:	JMP	IEPRI		;PRIVILEGE VIOLATION

	.ENDC


;
; DEVICE IS NOT MOUNTABLE
;

80$:	BIT	R2,(R1)		;ACP FUNCTION?
	BEQ	FCTRN		;IF EQ NO

;
; FUNCTION IS A FILE STRUCTURE FUNCTION FOR A NONFILE STRUCTURED DEVICE. BY DEF-
; INITION THIS MUST BE A READ OR WRITE VIRUTAL SINCE ALL OTHER FUNCTIONS WOULD
; HAVE BEEN EITHER ILLEGAL OR NOP'ED. MAP FUNCTION TO IT LOGICAL COUNTERPART.
;
; NOTE THAT THE SUBFUNCTION BITS ARE IGNORED SINCE READ VIRTUAL		;MSH109      
; AND WRITE VIRTUAL FUNCTIONS ARE INTENDED TO BE DEVICE INDEPENDENT.	;MSH109
;									;MSH109

	MOV	#IO.RLB,I.FCN-I.PRM(R4)	;ASSUME FUNCTION IS READ VIRTUAL
	CMPB	#IO.RVB/256.,1(SP) ;READ VIRTUAL FUNCTION?		;MSH109
	BEQ	FCTRN		;IF EQ YES				;**-1
	MOV	#IO.WLB,I.FCN-I.PRM(R4) ;SET FUNCTION TO WRITE LOGICAL BLOCK
	.DSABL	LSB

;
; FUNCTION IS A TRANSFER FUNCTION-ADDRESS CHECK AND MAP TRANSFER
;

FCTRN:	CALL	FACHK		;PERFORM ADDRES CHECK

	.IF	DF,M$$MGE

	CALL	$MPPHY		;MAP TO 18/22 BIT PHYS AD      DR

	.ENDC

	CALL	FCXR1		;INSERT RELOC DISP & BIAS; & PARM 2-6
	BR	FCXTR		;

;
; FUNCTION IS A KILL I/O FUNCTION-FLUSH I/O QUEUE OF TASK REQUESTS
;

FCKIL:	CALL	$IOKIL		;FLUSH I/O QUEUE

;
; FUNCTION IS A NOP'ED FUNCTION-DECLARE SUCCESSFUL COMPLETION STATUS
;

ISSUC:	MOV	#IS.SUC&377,R4	;SET SUCCESSFUL COMPLETION CODE
	BR	IECM1		;					;CHF023
									;**-1
;
; FUNCTION IS AN ILLEGAL FUNCTION-DECLARE ILLEGAL FUNCTION CODE STATUS
;

IEIFC:	MOV	#IE.IFC&377,R4	;SET ILLEGAL FUNCTION CODE      
	BR	IECM1		;					;CHF023
									;**-1
;
; SPECIFIED DEVICE IS OFFLINE
;

IEOFL:	MOV	#IE.OFL&377,R4	;SET DEVICE OFFLINE STATUS
IECM1:	JMP	IECMN		;					;CHF023
									;**-1
;
; FUNCTION IS A CONTROL FUNCTION-COPY REMAINDER OF DPB
;

FCCTL:				;REF LABEL


	.IF DF	A$$NSI

	TST	U.CW1(R5)	;MOUNTABLE DEVICE?
	BPL	10$		;IF PL NO
	BITB	#US.MNT!US.FOR,U.STS(R5) ;MOUNTED AND NOT FOREIGN?
	BNE	10$		;IF NE NO
	BITB	#US.LAB,U.STS(R5) ;IS IT AN ANSI TAPE?
	BEQ	10$		;IF EQ NO
	MOV	$TKTCB,R0	;P      OINT TO CURRENT TASK TCB
	BIT	#T3.PRV,T.ST3(R0) ;TASK PRIVILEGED?
	BNE	10$		;IF NE YES				;CHF023
	JMP	IEPRI		;					;CHF023
									;**-1
	.ENDC


10$:				;
FCXOP:	CALL	FCXP1		;INSERT PARAMETERS 1 TO 6
FCXTR:				;REFERENCE LABEL

	CMPB	1(SP),#IO.ATT/256. ;ATTACH FUNCTION?			;MSH152
	BEQ	5$		;IF EQ YES, CHECK IQ.X BIT		;MSH152
	CMPB	1(SP),#IO.DET/256. ;DETACH FUNCTION?			;MSH152
	BNE	7$		;IF NE NO				;MSH152
5$:	TST	U.ATT(R5)	;DEVICE ALREADY ATTACHED?		;MSH152
	BEQ	6$		;IF EQ NO				;MSH152      
	BITB	#IQ.X,(SP)	;REJECT IF ATTACHED BY ANOTHER TASK?	;MSH152
	BEQ	10$		;IF EQ NO				;MSH152
	CMP	$TKTCB,U.ATT(R5) ;ATTACHED BY ISSUING TASK?		;MSH152
	BNE	IERSU		;IF NE NO, REJECT THE REQUEST		;MSH152
6$:	MOV	4(SP),R0	;GET I/O PACKET ADDRESS			;MSH152
	BIC	#IQ.X,I.FCN(R0)	;CLEAR IQ.X BIT				;MSH152
									;MSH152
	.IF DF	D$$IAG							;MSH152
									;MSH152
	BR	10$		;JOIN COMMON CODE			;MSH152
									;MSH152
	.IFTF								;MSH152
									;MSH152
7$:				;					;MSH152

	.IFT	;D$$IAG				      			;MSH152
									;**-1
	BITB	#IQ.UMD,(SP)	;IS THIS A DIAGNOSTIC FUNCTION?
	BEQ	10$		;IF EQ NO
	BIT	#DV.UMD,U.CW1(R5) ;DOES DEVICE SUPPORT DIAGNOSTICS?
	BEQ	10$		;IF EQ NO
	BITB	#US.UMD,U.ST2(R5) ;IS DEVICE ATTACHED FOR DIAGNOSTICS?	;**-4
	BEQ	IEPRI		;IF EQ NO, PRIVILEGE VIOLATION
	MOV	(R4),R0		;PICK UP REGISTER BUFFER ADDRESS


	.IF DF	A$$CHK!M$$MGE

	MOV	#40.*2,R1	;PICK UP MAX LENGTH
	CALL	$ACHCK		;ADDRESS CHECK REGISTER BUFFER
	BCS	IESPC		;IF CS ADDRESS CHECK FAILED

	.ENDC


	CALL	      $RELOC		;RELOCATE REGISTER BUFFER
	MOV	R1,(R4)+	;STORE KISAR6 BIAS
	MOV	R2,(R4)		;STORE DISPLACEMENT
									;**-1
	.ENDC


10$:	CMP	#IO.LOV,(SP)+	;IS THIS A LOAD OVERLAY FUNCTION?	;MSH152
	BNE	FCXIT		;IN NE NO				;**-1
	TST	U.CW1(R5) 	;MOUNTABLE DEVICE?
	BPL	FCXIT		;IF PL NO
	MOV	$TKTCB,R3	;GET ADDRESS OF TCB OF CURRENT TASK
	MOV	T.LDV(R3),R0	;GET UCB ADDRESS OF LOAD DEVICE
	CALL	$MPLND		;MAP TO ACTUAL UCB ADDRESS
	CMP	R0,R5		;LOAD DEVICE UCB MATCH SPECIFIED UCB?
	BNE	IEOVR		;IF NE NO
	ADD      	T.LBN+1(R3),-(R4) ;ADD IN LOW PART OF TASK LOGICAL
	ADC	-(R4)		;BLOCK NUMBER
	MOVB	T.LBN(R3),R0	;GET HIGH BYTE OF TASK LOGICAL BLOCK NUMBER
	ADD	R0,(R4)		;ADD IN HIGH PART
FCXIT:	TST	(SP)+		;CLEAN STACK
	MOV	(SP)+,R1	;RETRIEVE ADDRESS OF I/O PACKET

	.IF	DF,A$$CPS

	TST	(SP)+		;QUEUE TO DRIVER??
	BEQ	DRQRQ		;IF EQ YES; IF NE Q ACP			;MSH045
	BITB	#UC.QUE,U.CTL(R5)	;IF SET QUEUE TO DRIVER		;**-1
	BNE	DRQRQ		;EVEN IF ACP FUNCTION			;MSH045
	MOV	U.ACP(R5),R0	;					;**-1
	CALLR	$EXRQP		;INSURE FI      LE SYSTEM ACTIVE

	.ENDC

;
; DESCIPTION OF QUEUING AND INTERLOCKING INTERFACES
;	FOR MOUNTABLE DEVICES.
;
;	I.  NOT MOUNTED - ALLOW TRANSFER FUNCTIONS.
;		ACP FCTNS ARE ILLEGAL.
;		ADDRESS CHECK & AND MAP BUFFER ADDRESS IN
;			PARAMETER 1
;		QUEUE TO DRIVER.
;
;	II. MOUNTED
;		A. ALL CASES - IF 'UC.QUE' SET IN 'U.CTL' THEN QUEUE
;			TO DRIVER. (NECESSARY TO SUPPORT EXISTING
;			DRIVERS THAT ARE REALLY ALSO LIKE ACP'S)
;
;		B. MOUNTED FOREIGN
;			1. XFER FCTN - ADDRESS CHECK AND MAP
;		      		BUFFER ADDRESS IN PARAMETER 1. COPY
;				PARAMETERS 2-6. QUEUE TO DRIVER.
;			2. ACP FCTN - ERROR IF NO ACP. COPY PARAMETERS
;				1-6. NO POLISH ROUTINE PROCESSING.
;				INCREMENT VOLUME TRANSACTION COUNT.
;				QUEUE TO ACP.
;
;		C. MOUNTED NOT FOREIGN
;			1. XFER FCTN - EITHER OVERLAY OR PRIVILEGED
;				TASK I/O.  ADDRESS CHECK AND MAP
;				BUFFER ADDRESS IN PARAMETER 1. COPY
;				PARAMETERS 2-6. QUEUE TO DRIVER.
;			2. DECNET ACP - I/O FUNCTION CODES ARE DISJOINT
;				FROM FILES ACPS' FUNCT      ION CODES. POLISH
;				ROUTINE PROCESSING.  QUEUED TO DRIVER
;				BECAUSE 'UC.QUE' SET.
;			3. ANSI MAGTAPE ACP (MTAACP) - SAME FUNCTION
;				CODES AS DISK FILE ACP (F11ACP) BUT
;				NOT ALL ARE ALLOWED. POLISH ROUTINE
;				PROCESSING. ALL OPERATIONS QUEUED TO
;				MTAACP. NO BLOCK LOCKING. ACCESS/DEACCESS
;				INTERLOCK BUT NO WINDOW-TURN PENDING
;				COUNT BECAUSE EVERYTHING QUEUED TO ACP.
;				INCREMENT VOLUME TRANSACTION COUNT.
;			4. FILES-11 DISK ACP (F11ACP) - POLISH ROUTINE
;				PROCESSI      NG. TABLE BELOW DESCIBES QUEUING
;				AND INTERLOCKING. LEGEND: A=QUEUE TO ACP;
;				D=QUEUE TO DRIVER; I=INTERLOCK LUN;
;				P=INCREMENT WINDOW TURN PENDING COUNT.
;				VOLUME TRANSACTION COUNT INCREMENTED.
;				SEE COMMENT LOCATED NEAR CKRAC AND CKWAC
;				FOR DESCRIPTION OF WINDOW TURN PENDING
;				COUNT ALGORITHM.
;
;
;			OPERATION			QUEUE  INTERLOCK
;
;		FIND NAME IN DIRECTORY			A	0
;		ENTER NAME IN DIRECTORY			A	0
;		REMOVE NAME FROM DIRECTORY		A	0
;		ACCESS FILE				A	I
;		DEACCESS FIL      E				D	I
;		READ/WRITE VIRTUAL BLOCK-MAP OK		D	0
;		READ/WRITE VIRTUAL BLOCK-MAP FAIL	A	P
;		READ/WRITE VIRTUAL BLOCK-PARTIAL MAP	D	I
;		EXTEND FILE				A	P
;		CREATE FILE				A	0
;		MARK FILE FOR DELETE			A	0
;		TRUNCATE FILE				D	I
;		READ ATTRIBUTES				A	0
;		WRITE ATTRIBUTES			A	0
;
;

DRQRQ:									;MSH045
									;CHF023
; 									;CHF023
; CHECK SOFTWARE WRITE LOCK						;CHF023
; 									;CHF023
									;CHF023
	.IF DF	S$$WLK							;CHF023
									;CHF023
	BIT	#DV.MSD,U.CW1(R      5)  ;MASS STORAGE DEVICE?		;CHF023
	BEQ	20$		;IF EQ NO				;CHF023
	BIT	#DV.SWL,U.CW1(R5)  ;SOFTWARE WRITE LOCKED?		;CHF023
	BEQ	20$		;IF EQ NO				;CHF023
	CMPB	#IO.RLB/256.,I.FCN+1(R1)  ;READ LOGICAL FUNCTION?	;CHF023
	BEQ	20$		;IF EQ YES				;CHF023
	CMPB	#IO.WLB/256.,I.FCN+1(R1)  ;WRITE LOGICAL FUNCTION?	;CHF023
	BEQ	IEWLK		;IF EQ YES				;CHF023
	MOV	#WLKTB,R4	;POINT TO TABLE				;CHF023
	MOV	I.FCN(R1),R0	;GET FUNCTION CODE			;CHF023
	BIC	#7,R0		;GET RID OF MODIFIERS			;CHF023
10$:	CMP	(R4)+,R0	;      IS THIS THE FUNCTION CODE?		;CHF023
	BEQ	IEWLK		;IF EQ YES				;CHF023
	TST	(R4)		;END OF TABLE?				;CHF023
	BNE	10$		;IF NE NO				;CHF023
20$:									;CHF023
									;CHF023
	.ENDC	;S$$WLK							;CHF023
									;CHF023
	CALLR	$DRQRQ		;QUEUE I/O REQUEST			;MSH045
									;MSH045
									;**-50


; 									;CHF023
; WRITE ATTEMPTED TO WRITE LOCKED UNIT (WRITE LOCK ERROR)		;CHF023
; 									;CHF023
									;CHF023
IEWLK:	MOV	#IE.WLK&377,R4	;SET WRITE LOCK ERROR			;CHF023
	BR	IECMN		;	      				;CHF023
									;CHF023
;									;MSH152
; DEVICE ALREADY ATTACHED BY ANOTHER TASK (RESOURCE IN USE)		;MSH152
;									;MSH152
									;MSH152
IERSU:	MOV	#IE.RSU&377,R4	;SET RESOURCE IN USE			;MSH152
	BR	IECMN		;					;MSH152
									;MSH152
;
; ILLEGAL BUFFER ADDRESS SPECIFIED-DECLARE ILLEGAL BUFFER STATUS
;

IESPC:	MOV	#IE.SPC&377,R4	;SET ILLEGAL BUFFER CODE
IECOM:	BR	IECMN		;

;
; ILLEGAL LOAD OVERLAY UCB-DECLARE ILLEGAL LOAD OVERLAY FUNCTION STATUS
;

IEOVR:	MOV	#IE.OVR&377,R      4	;SET ILLEGAL LOAD OVERLAY CODE
	BR	IECMN		;

;
; ILLEGAL BYTE COUNT OR ALIGNMENT-DECLARE ODD BYTE STATUS
;

IEBYT:	MOV	#IE.BYT&377,R4	;SET ODD BYTE STATUS


	.IF DF	A$$CPS

	BR	IECMN		;

;
; NO BUFFER SPACE AVAILABLE-SET NO BUFFER AVAILABLE STATUS
;

IENOD:	MOV	#IE.NOD&377,R4	;SET NO BUFFER AVAILABLE CODE
	BR	IECMN		;

;
; BAD PARAMETER-SET BAD PARAMETER STATUS
;

IEBAD:	MOV	#IE.BAD&377,R4	;SET BAD PARAMETER CODE
	BR	IECMN		;

;
; PRIVILEGE VIOLATION-SET PRIVILEGE VIOLATION ST      ATUS
;

	.IFTF


	.IF DF	A$$CPS!D$$IAG

IEPRI:	MOV	#IE.PRI&377,R4	;SET PRIVILEGE VIOLATION CODE
	BR	IECMN		;

	.ENDC


	.IFT

;
; FILE ALREADY ACCESSED ON LUN-SET FILE ALREADY ACCESSED STATSU
;

IEALN:	MOV	#IE.ALN&377,R4	;SET FILE ALREADY ACCESSED CODE
	BR	IECMN		;

;
; NO FILE ACCESSED ON LUN-SET NO FILE ACCESSED STATUS
;

IENLN:	MOV	#IE.NLN&377,R4	;SET NO FILE ACCESSED STATUS

	.IF	DF,R$$LKL

	BR	IECMN		;
;
;	BLOCK LOCKING ERROR OR UNLOCK PERFORMED
;

IELCK:	MOV	R0,R4		      ;STATUS IN R0

	.ENDC

;
; COMMON ERROR EXIT
;


	.IFTF

IECMN:	MOV	MSTK,SP		;RESET STACK POINTER
	MOV	(SP)+,R0	;RETRIEVE ADDRESS OF SECONDARY CONTROL BLOCK
	BEQ	10$		;IF EQ NONE
	CALL	$DEPKT		;DEALLOCATE SECONDARY CONTROL BLOCK
10$:	MOV	R4,R0		;SET FINAL I/O STATUS
	CLR	R1		;CLEAR SECOND I/O STATUS WORD
	MOV	(SP)+,R3	;RETRIEVE ADDRESS OF I/O PACKET

	.IF	DF,A$$CPS

	TST	(SP)+		;CLEAN STACK

	.ENDC

	MOV	I.UCB(R3),R5	;RETRIEVE UCB ADDRESS
	CALLR	$IOFIN		;FINISH OFF I/O OPERATION
      
;
; BUILD AN I/O PACKET
;

	.IFT

BDPKT:	MOV	#2*2,R1		;SET LENGTH OF FILE ID BLOCK
	CALL	OPPRM		;INSERT OPTIONAL FILE ID BLOCK

;
; BUILD ATTRIBUTE POINTER BLOCK
;

ATRBK:	MOV	(R3)+,(R4)+	;ATTRIBUTE DESCRIPTOR BLOCK SPECIFIED?
	BEQ	MOVE3		;IF EQ NO
	MOV	R3,-(SP)	;SAVE ADDRESS OF NEXT DPB WORD
	MOV	#I.LGTH,R1	;SET LENGTH OF SECONDARY CONTROL BLOCK
	CALL	$ALOCB		;ALLOCATE SECONDARY CONTROL BLOCK
	BCS	IENOD		;IF CS NO STORAGE AVAILABLE
	MOV	R0,@MSTK	;SAVE ADDRESS OF SECONDARY CONTROL BLOCK      


	.IF DF	M$$MGE

	MOV	KISAR6,-(SP)	;SAVE CURRENT MAPPING

	.ENDC


	MOV	-(R4),R3	;RETRIEVE ADDRESS OF ATTRIBUTE DESCRIPTOR BLOCK
	MOV	R0,(R4)+	;SET POINTER TO SECONDARY CONTROL BLOCK
	MOV	R4,-(SP)	;SAVE ADDRESS OF NEXT WORD IN I/O PACKET
	MOV	R0,R4		;SET ADDRESS OF FIRST ATTRIBUTE POINTER
	MOV	#6,-(SP)	;SET MAXIMUM NUMBER OF ATTRIBUTE POINTERS
10$:	MOV	R3,R0		;SET ADDRESS OF NEXT ATTRIBUTE DESCRIPTOR


	.IF DF	A$$CHK!M$$MGE

	MOV	#4,R1		;SET SIZE OF ATTRIBUTE DESCRIPTOR
	CALL	$ACHCK		;      ADDRESS CHECK ATTRIBUTE DESCRIPTOR
	BCS	IESPC		;IF CS ADDRESS CHECK FAILURE

	.ENDC


	.IF DF	M$$MGE

	CALL	$RELOM		;RELOCATE AND MAP ATTRIBUTE DESCRIPTOR
	ADD	#4,R3		;POINT TO NEXT ATTRIBUTE DESCRIPTOR

	.IFF

	CMP	(R3)+,(R3)+	;POINT TO NEXT ATTRIBUTE DESCRIPTOR

	.ENDC


	MOVB	(R0)+,(R4)+	;INSERT ATTRIBUTE NUMBER
	BEQ	20$		;IF EQ END OF ATTRIBUTE DESCRIPTOR BLOCK
	CLR	R1		;PICKUP SIZE OF ATTRIBUTE BLOCK
	BISB	(R0)+,R1	;
	MOVB	R1,(R4)+	;INSERT LENGTH OF ATTRIBUTE BLOCK
	BNE	15$		;IF       NE LENGTH OKAY
	MOV	#256.*2,R1	;SET LENGTH FOR ZERO CASE
15$:	MOV	(R0),R0		;GET ADDRESS OF ATTRIBUTE BLOCK


	.IF DF	A$$CHK!M$$MGE

	CALL	$ACHCK		;ADDRESS CHECK ATTRIBUTE BLOCK
	BCS	IESPC		;IF CS ADDRESS FAILURE

	.ENDC


	CALL	$RELOC		;RELOCATE ATTRIBUTE BLOCK ADDRESS
	MOV	R1,(R4)+	;INSERT RELOCATION BIAS
	MOV	R2,(R4)+	;INSERT ATTRIBUTE BLOCK ADDRESS
	DEC	(SP)		;ANY MORE SPACE IN POINTER BLOCK?
	BGT	10$		;IF GT YES
20$:	TST	(SP)+		;CLEAN STACK
	MOV	(SP)+,R4	;RETRIEVE ADDRESS OF NEXT WORD       IN I/O PACKET


	.IF DF	M$$MGE

	MOV	(SP)+,KISAR6	;RESTORE CURRENT MAPPING

	.ENDC


	MOV	(SP)+,R3	;RETRIEVE ADDRESS OF NEXT WORD IN DPB

;
; MOVE EXTEND AND ACCESS CONTROL WORDS INTO I/O PACKET
;

MOVE3:	MOV	(R3)+,(R4)+	;INSERT EXTEND CONTROL WORDS
	MOV	(R3)+,(R4)+	;
	MOV	(R3)+,(R4)+	;INSERT ACCESS CONTROL WORD

;
; INSERT OPTIONAL FILENAME BLOCK
;

FILNM:	MOV	#13.*2,R1	;SET LENGTH OF FILENAME BLOCK
	CALL	OPPRM		;INSERT OPTIONAL FILENAME BLOCK
	BR	POLJMP		;					;MSH163
									      ;**-1
;
; INTERPRET REQUIRED BLOCK ADDRESS
;

	.ENABL	LSB
RQPRM:	MOV	SP,R2		;SET REQUIRED PARAMETER FLAG
	BR	10$		;

;
; INTERPRET OPTIONAL BLOCK ADDRESS
;

OPPRM:	CLR	R2		;CLEAR REQUIRED PARAMETER FLAG
10$:	MOV	(R3)+,R0	;GET ADDRESS OF CONTROL BLOCK
	BEQ	20$		;IF EQ NONE SPECIFIED


	.IF DF	A$$CHK!M$$MGE

	CALL	$ACHCK		;ADDRESS CHECK BLOCK
	BCS	IESPC		;IF CS ADDRESS CHECK FAILURE

	.ENDC


	CALL	$RELOC		;RELOCATE BUFFER ADDRESS
	MOV	R1,(R4)+	;INSERT RELOCATION BIAS
	MOV	R2,(R4)+      	;INSERT BLOCK ADDRESS
	BR	30$		;
20$:	MOV	R2,(R4)+	;PARAMETER REQUIRED?
	BNE	IEBAD		;IF NE YES
	CLR	(R4)+		;CLEAR SECOND WORD
30$:	RETURN			;
	.DSABL	LSB

;
; FILL DISCONNECT PARAMETER BUFFER AND INTERLOCK LUN USAGE
;


	.IF DF	M$$NET

	.ENABL	LSB
CKDIS:	MOV	(R3)+,(R4)+	;COPY FIRST PARAMETER TO I/O PACKET
	BR	10$		;FINISH IN COMMON CODE

;
; CHECK CONNECT PARAMETER BUFFER
;

CKCON:	MOV	2(R3),R1	;GET LENGTH OF BUFFER IN BYTES
	BEQ	IESPC		;IF EQ ZERO LENGTH
	CALL	RQPRM		;INSERT REQUI      RED PARAMETER
10$:	CALL	FCXP2		;INSERT PARAMETERS
	BR	POLJMP		;					;MSH163
	.DSABL	LSB							;**-1

	.ENDC


;
; CHECK FOR VOLUME MARKED FOR DISMOUNT
;

CKDMO:	BITB	#US.MDM,U.STS(R0) ;VOLUME MARKED FOR DISMOUNT?
	BNE	IEPRI		;IF NE YES
	BR	POLJMP		;					;MSH163
									;**-1
;
; CHECK VOLUME MOUNTED BY THIS USER
;
	.ENABL	LSB
CKMOU:				;

	.IF	DF,M$$MUP

	MOV	R5,-(SP)	;SAVE REGISTER
	MOV	4(SP),R5	;GET UCB ADDRESS
	CALL	CXMOU		;CHECK MOUNT LIST
	BCS	15$		;ERROR
	MOV	(SP)+,R5	;RES      TORE REGISTER

	.IFTF

POLJMP:	JMP	@(R5)+		;					;MSH163
									;**-1
	.IFT

;
; SUBROUTINE TO SEARCH MOUNT LIST TO SEE IF VOLUME
;	REALLY MOUNTED BY THIS USER
;
CXMOU:	MOV	R1,-(SP)	;SAVE REGISTERS
	MOV	R2,-(SP)	;
	BITB	#US.PUB,U.ST2(R5)	;PUBLIC DEVICE?
	BNE	8$		;PUBLIC DEVICE OK
	MOV	$TKTCB,R1	;IS TASK PRIVILEGED?
	BIT	#T3.PRV,T.ST3(R1)
	BNE	8$		;PRIVILEGED TASK OK
	MOV	T.UCB(R1),R1	;GET USER TI: UCB ADDR AS ID
	MOV	#$MOULS,R2	;GET MOUNT LIST

5$:	SEC			;ASSUME FAIL
	MOV	(R2),R2		;      GET MOUNT LIST ENTRY
	BEQ	9$		;NONE=DONE=FAIL
	CMPB	#MT.MLS,M.TYPE(R2) ;RIGHT TYPE OF ENTRY?		;MSH163
	BNE	5$		;BRANCH NOT MOUNT ENTRY			;**-1
	CMP	M.DEV(R2),R5	;SAME DEVICE UCB?			;MSH163
	BNE	5$		;BRANCH DIFFERENT DEVICE		;**-1
	CMP	M.TI(R2),R1	;SAME USER TI:?				;MSH163
	BNE	5$		;BRANCH DIFFERENT USER			;**-1

8$:	CLC			;SUCCESS
9$:	MOV	(SP)+,R2	;RESTORE REGISTERS
	MOV	(SP)+,R1	;
	RETURN			;

	.ENDC


;
; CHECK FOR READ ACCESS PRIVILEGES
;

CKRAC:	MOV	#WI.RDV,R2	;SET READ ACCESS MASK       WORD
	BR	10$		;

;
; CHECK FOR WRITE ACCESS PRIVILEGES
;

CKWAC:	MOV	#WI.WRV,R2	;SET WRITE ACCESS MASK WORD
10$:	BIT	R2,@(R1)+	;DESIRED ACCESS PERMITTED?
	BNE	20$		;IF NE YES
15$:	JMP	IEPRI		;PRIVILEGE VIOLATION
;
;	ADDRESS CHECK & INSERT RELOC BIAS, DISP  & PARM 2-6
;
20$:	MOV	R0,R5		;GET UCB ADDRESS
	CALL	FACHK		;PERFORM ADDRESS CHECK
	CALL	FCXR1		;COPY PARAMETERS

	.IF	DF,M$$NET

	CMP	#IO.WVB,4(SP)	;DECNET FUNCTION??
	BLT	50$		;EXIT HERE IF DECNET

	.ENDC

;
;	ONLY READ/WRITE V      IRTUAL FUNCTIONS COME HERE
;
;	IF ANSI - QUEUE TO MTAACP
;	IF F11ACP - PERFORM BLOCK LOCKING AND MAP VIRTUAL TO LOGICAL
;		MAP OK - QUEUE TO DRIVER
;		MAP FAIL - INCREMENT PENDING & QUEUE TO ACP
;		PARTIAL MAP - INTERLOCK & QUEUE TO DRIVER
;
;
;	THE ROUTING OF WINDOW TURN REQUESTS DEPENDS ON THE ABILITY
;	TO DISTINGUISH BETWEEN REQUESTS THAT MAP TO DISJOINT LBN'S.
;	ANY NUMBER OF (SUCCESSFULLY MAPPED) REQUESTS FOR THIS LUN
;	MAY BE IN THE DRIVER QUEUE ALREADY.  IF THE ACP QUEUE IS EMPTY
;	THEN       ANY NEXT REQUEST IS OK.  IF THE ACP QUEUE CONTAINS ONE
;	REQUEST (FROM THE TRANSITION ZERO TO ONE) THEN ANY REQUEST
;	THAT MAPS SUCCESSFULLY IS DISJOINT AND OK. IF THE ACP QUEUE
;	HAS TWO REQUESTS (OR ONE FROM THE TRANSITION TWO TO ONE) THEN
;	WE MUST WAIT FOR ZERO IN ORDER FOR THE SUCCESSFUL MAPPING OF
;	VIRTUAL TO LOGICAL TO INDICATE DISJOINT LBNS.  AT THIS POINT
;	THE LUN IS INTERLOCKED. (EXAMPLE: THREE REQUESTS TO SAME BLOCK;
;	FIRST CAUSES WINDOW TURN AND IS COMPLETED; SECOND STILL REMAINS
;	IN       ACP QUEUE; THE THIRD WILL MAP OK BUT IT CAN NOT BE PERFORMED
;	SAFELY UNTIL THE SECOND IS COMPLETE.)
;	AN ALTERNATIVE ALGORITHM WOULD BE TO ROUTE ALL VIRTUAL I/O
;	REQUESTS TO THE ACP IF THE 'ACP VIRTUAL PENDING COUNT' WERE
;	GREATER THAN ZERO. INTERLOCK WOULD OCCUR WHEN COUNT=MAX
;	(I.E. NO BITS TO COUNT HIGHER).  THE IMPLEMENTED ALGORITHM
;	YIELDS BETTER PERFORMANCE WHEN LIMITED TO TWO BITS FOR PENDING
;	COUNT AND INTERLOCK: THERE IS LESS LATENCY FOR ANY SECOND
;	REQUEST-IT IS QUEUED TO THE DRIVE      R IF IT CAN BE MAPPED
;	SUCCESSFULLY; BOTH ALGORITHMS CAN HANDLE ABOUT THE SAME
;	NUMBER OF REQUESTS BEFORE FORCED INTERLOCK OCCURS.  IRRESPECTIVE
;	OF THE NUMBER OF BITS AVAILABLE, THE ALTERNATIVE ALGORITHM
;	ALWAYS HAS THE PROBLEM OF POSSIBLY ROUTING VIRTUAL REQUESTS
;	INDEFINITELY TO THE ACP INSTEAD OF THE DRIVER.
;
;	PARTIALLY MAPPED REQUESTS OBVIOUSLY SCREW UP EVERYTHING
;	BECAUSE OF THE POSSIBILITY OF ACCESSING THE SAME DISK
;	BLOCKS SEPARATELY, ONE BLOCK AT A TIME.
;	PARTIALLY MAPPED REQUES      TS ARE QUEUED TO DRIVER FOR CORRECT
;	SEQUENCING: THEY WILL BE PROCESSED AFTER THE OUTSTANDING
;	MAPPED REQUESTS IN THE DISK QUEUE; $GTPKT WILL ROUTE
;	THESE REQUESTS TO THE ACP SO THEY WILL ALSO FOLLOW ANY
;	OUTSTANDING REQUESTS IN THE ACP QUEUE. INTERLOCK IS SET
;	SO THAT ANY NEW REQUESTS WILL BE PROCESSED AFTER THE
;	PARTIALLY MAPPED ONE IS COMPLETE AND THE WINDOW TURNED.
;
;
;		WINDOW TURN PENDING COUNT ALGORITHM
;
;	CURRENT		ARRIVE		ARRIVE		DEPART
;	STATE		'P' CASES	'I' CASES	ALL
;			(RWVB       MAP	(ACCESS,	CASES
;			FAIL, EXTEND)	DEACCESS,
;					RWVB PARTIAL
;					MAP, TRUNCATE)
;
;	0  0		0  P		I  0		XXXX
;	0  P		I  P		I  P		0  0
;	I  0		XXXX		XXXX		0  0
;	I  P		XXXX		XXXX		I  0
;
;
;	NOTE: F11ACP RAISES WINDOW TURN PENDING TO INTERLOCK WHILE
;	A WINDOW TURN OPERATION IS IN PROGRESS.  THIS MAY INVOLVE
;	THE FOLLOWING STATE TRANSITION:
;		0  P  ->  I  0
;

CKLCK:

	.IF	DF,A$$NSI

	BITB	#US.LAB,U.STS(R5)	;ANSI MAGTAPE??
	BNE	40$		;IF ANSI-NO LOCKING, Q TO ACP

	.ENDC

	MO      V	10(SP),R1	;GET ADDRESS I/O PACKET

	.IF	DF,R$$LKL

	CALL	$LCKPR		;PERFORM LOCK PROCESSING
	BCC	22$		;CS IF ERROR OR UNLOCK DONE
	JMP	IELCK		;
22$:				;REFERENCE LABEL

	.ENDC

	CALL	$MPPKT		;MAP VBN TO LBN
	MOV	(SP),R1		;GET ADDRESS 2ND LUN WORD
	BCS	30$		;MAP FAILURE
	TST	R0		;ALL BLOCKS MAPPED??
	BEQ	50$		; IF .EQ. YES
	INC	(R1)		;PARTIAL MAP-SET INTERLOCK
	BR	50$		;AND EXIT HERE
30$:	CALL	FCPND		;MAP FAILURE - INCR WINDOW PENDING
40$:	INC	12(SP)		;MAG TAPE OR MAP FAIL - Q TO ACP
50$      :	TST	(SP)+		;CLEAN STACK
	MOV	(SP)+,R5	;RESTORE TO UCB ADDRESS
	TST	(SP)+		;CLEAN STACK
CKJXT:	JMP	FCXIT
	.DSABL	LSB

;
; CHECK FOR FILE ALREADY ACCESSED ON LUN
;

	.ENABL	LSB
CKALN:	TST	(R1)		;FILE ACCESSED ON LUN?
	BEQ	CKJR5			;IF EQ NO
	JMP	IEALN		;ERROR

;
; CHECK FOR FILE ACCESSED ON LUN
;

CKNLN:	TST	(R1)		;FILE ACCESSED ON LUN?
	BNE	CKJR5			;IF NE YES
	JMP	IENLN		;ERROR

;
; SET UP REGISTERS FOR UNLOCK AND EXIT TO CONTROL FUNCTION
;


	.IF DF	R$$LKL

UNLXT:	TST	(R4)+		;      ADVANCE POINTER
	MOV	R0,R5		;UCB ADDRESS
	CALL	FCXP1		;COPY PARAMETERS
	BR	CKLCK		;

	.ENDC


;
; SET ACCESS/DEACCESS INTERLOCK
;

CKRLK:	INC	@(SP)		;SET ACCESS/DEACCESS PENDING INTERLOCK

;
; EXIT POLISH TO FUNCTION EXIT
;

CKXIT:	TST	(SP)+		;REMOVE ADDRESS OF SECOND LUN WORD
	MOV	(SP)+,R5	;RETRIEVE UCB ADDRESS
	TST	(SP)+		;ADJUST STACK PTR
	MOV	U.VCB(R5),R1	;INCREMENT VOLUME TRANSACTION COUNT
	BEQ	CKJXT		;IN ANY VCB
	INC	(R1)		;
	BR	CKJXT		;EXIT POLISH

	.ENABL	LSB
;
; SET FLAG       TO QUEUE TO ACP IF ANSI MAGTAPE
;

	.IF	DF,A$$NSI

CKQMT::	BITB	#US.LAB,U.STS(R0)	; ANSI MAGTAPE?
	BEQ	10$			; IF .EQ. NOT ANSI

	.ENDC

;
; SET FLAG TO QUEUE TO ACP
;

CKACP::	INC	12(SP)		;SET FLAG TO QUEUE TO ACP
10$:	JMP	@(R5)+		;
	.DSABL	LSB

;
; INCREMENT WINDOW TURN PENDING COUNT FOR EXTEND
; PENDING COUNT NOT MAINTAINED ANSI MAGTAPE
;

CKPND::

	.IF	DF,A$$NSI

	BITB	#US.LAB,U.STS(R0)	; ANSI MAGTAPE?
	BNE	CKPKT			; IF .NE. YES - SKIP INCR PEND

	.ENDC

	TST	(R1)		;HAVE       A WINDOW?
	BEQ	CKPKT		;NO - DON'T INCR WINDOW PEND NO WINDOW
	CALL	FCPND		;INCREMENT WINDOW TURN PENDING COUNT
CKPKT:	MOV	#FCPKT,R5	;JOIN COMMON ACP REQUESTS
CKJR5:	JMP	@(R5)+		;

;
; CHECK IF DELETE OR TRUNCATE OPERATION
;	ONLY F11ACP ALLOWS DELETE, ILLEGAL DECNET & MTAACP
;		DELETE - FALL THRU SO QUEUE TO ACP
;		TRUNCATE BUT NO WINDOW - TREAT LIKE DELETE
;			CANT SET INTERLOCK SO MUST Q TO ACP
;		TRUNCATE - ADVANCE R5 SO NO QUEUE TO ACP
;			& SET INTERLOCK
;

CKTRN::	TST	(R1)		;HAVE A WIN      DOW
	BEQ	10$		;NO WINDOW - DON'T DO ANYTHING
	TST	4(R3)		;NEG PARAMETER = TRUNCATE
	BPL	10$		;FALL THRU IF NORMAL DELETE
	TST	(R5)+		;SKIP OVER Q TO ACP
	INC	(R1)		;SET INTERLOCK
10$:	JMP	@(R5)+		;

;
; SUBROUTINE TO INCREMENT WINDOW TURN PENDING COUNT
;
;	INPUTS:	R1 - ADDRESS OF 2ND LUN WORD
;
;	OUTPUTS: ALL REGISTERS PRESERVED
;		WI.PND SET IN WINDOW
;		INTERLOCK SET IF WI.PND WAS ALREADY SET
;

FCPND:	BIT	#WI.PND,@(R1)+	;PENDING BIT ALREADY SET??		;**-4
	BNE	10$		;BR IF SET - DO INTERL      OCK
	BIS	#WI.PND,@-(R1)	;SET PENDING BIT
	RETURN
10$:	INC	-(R1)		;SET INTERLOCK
	RETURN

	.ENDC			; END A$$CPS

;
; SUBROUTINES TO COPY PARAMETERS INTO I/O PACKET
;
;	INPUTS:
;		FCXR1 - R1 RELOCATION BIAS
;			R2 DISPLACEMENT BIAS
;			R3 PARAMETER PTR
;			R4 I/O PACKET PTR
;			COPIES R1, R2, AND PARAMETERS 2-6
;
;		FCXP2 -	R3, R4
;			COPIES PARAMETERS 2-6
;
;		FCXP1 -	R3,R4
;			COPIES PARAMETERS 1-6
;
;	OUTPUTS: R3, R4 UPDATED PTR'S
;

FCXR1:	MOV	R1,(R4)+	;INSERT RELOCATION BIAS
	      MOV	R2,(R4)+	;INSERT DISPLACEMENT BIAS
	BR	FCXP2		;COPY PARAMETERS 2-6
FCXP1:	MOV	(R3)+,(R4)+	;INSERT PARAMETER 1
FCXP2:	MOV	(R3)+,(R4)+	;INSERT PARAMETER 2
	MOV	(R3)+,(R4)+	;INSERT PARAMETER 3
	MOV	(R3)+,(R4)+	;INSERT PARAMETER 4
	MOV	(R3)+,(R4)+	;INSERT PARAMETER 5
	MOV	(R3),(R4)	;INSERT PARAMETER 6
	RETURN			;

;
; SUBROUTINE TO PERFORM ADDRESS CHECK AND MAP TRANSFER
;

FACHK:	MOV	(R3)+,R0	;GET ADDRESS OF USER BUFFER

	.IF	DF,A$$CHK ! M$$MGE

	MOVB	U.CTL(R5),R1	;GET CONTROL BYTE
	BPL	1      0$		;IF PL BYTE ALLOWED
	BIT	#1,R0		;IS BUFFER BYE ALIGNED
	BNE	30$		;IF NE YES-ALIGNMENT ERROR
10$:	BIC	#^C<UC.LGH>,R1	;CLEAR ALL BUT LENGTH MODULO BITS
	BIT	R1,(R3)		;DOES LENGTH HAVE CORRECT MODULUS
	BNE	30$		;IF NE NO ALIGNMENT ERROR
	MOV	(R3),R1		;GET LENGTH OF BUFFER IN BYTES
	BEQ	40$		;IF EQ ILLEGAL BUFFER
	CALL	$ACHKB		;ADDRESS CHECK BUFFER
	BCS	40$		;IF CS ADDRESS CHECK ERROR

	.IFTF

	CALLR	$RELOC		;RELOCATE USER BUFFERR ADDRESS

	.IFT

30$:	JMP	IEBYT		;
40$:	JMP	IESPC		;ILLEGAL    *   BUFFER ADDRESS



	.ENDC


	.END
 *          üðskQ	› c,        	.TITLE	DSDRV
	.IDENT	/08.03/
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 08.03
;
; D. N. CUTLER 14-FEB-74
;
; PREVIOUSLY MODIFIED BY:
;
;	P. J. BEZEREDI
;	D. N. CUTLER
;	C. A. D'ELIA
;
; MODIFIED BY:
;
;	P. J. CARR	30-JAN-81
;
;		PJC019 -- REMOVE M$$IXD STUFF
;
;	P. J. CARR	30-JAN-81
;
;		PJC020 -- ADD PHYSIC      AL BLOCK ACCESSING SUPPORT 
;			  FOR RTEM-11
;
;	P. J. CARR	12-JUN-81
;
;		PJC029 -- CORRECT POWERFAIL RECOVERY
;
; RH11-RS03/RS04 FIXED HEAD DISK DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS


	.IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER-MODE DIAGNOSTIC DEFINITIONS

	.ENDC


;
; EQUATED SYMBOLS
;

RETRY=8.			;ERROR RETRY COUNT
RSWC=2				;WORD COUNT REGISTER
RSCS2=10			;SECOND STATUS       REGISTER
RSDS=12				;DRIVE STATUS REGISTER
RSER=14				;ERROR REGISTER
RSBAE=30			;BUS ADDRESS EXTENSION REGISTER


;									;**-7
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER)
;

CNTBL:	.BLKW	R$$JS1		;ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	R$$JS1		;RETRY COUNT FOR CURRENT OPERATION


	.IF GT	R$$JS1-1

TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC

;
; DRIVER DISPATCH TABLE
;

$DSTBL::.WORD	DSINI		;DEVICE INITIATOR ENTRY       POINT
	.WORD	DSCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	DSOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	DSPWF		;POWERFAIL ENTRY POINT

;+
; **-DSINI-RH11-RS03/RS04 FIXED HEAD DISK CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE C      ALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
;	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-

	.ENABL	LSB
DSINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	DSCAN		;IF CS CONTROLLER BUS      Y OR NO REQUEST

;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; RH11-RS03/RS04 FIXED HEAD DISK I/O REQUEST PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
;	WD. 03 -- P      OINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
;	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFE      R.
;	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED.
;	WD. 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST.
;	WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. ADRS ELSE NOT USED
;	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000)
;

	MOV	R5,CNTBL(R3)	;SAVE ADDRESS OF REQUEST UCB


	.IF DF	M$$EXT

	BIT	#DV.MBC,U.CW1(R5)  ;IS IT A MASS BUSS DEVICE?
	BNE	1$		;IF NE YES -- DOES NOT USE UMR'S
	CALL	$STMAP		;SET UP UNIBUS M      AP

	.ENDC


	ASL	U.BUF(R5)	;SHIFT ADDRESS EXTENSION BITS INTO PLACE
	ASL	U.BUF(R5)	;
	ASL	U.BUF(R5)	;
	ASL	U.BUF(R5)	;
1$:				;REF LABEL


	.IF DF	D$$IAG

	CMP	#IO.WCK!IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC WRITE CHECK?
	BNE	5$		;IF NE NO
	BIS	#151,U.BUF(R5)	;YES, SET FUNCTION CODE
	BR	10$		;

	.ENDC


5$:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION
	BIS	#171,U.BUF(R5)	;ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION?
	BHIS	6$		;IF HIS FUNCTION IS LEGAL
	      JMP	70$		;FUNCTION IS ILLEGAL
6$:	BEQ	10$		;IF EQ FUNCTION IS READ
	SUB	#10,U.BUF(R5)	;CONVERT TO WRITE LOGICAL FUNCTION
10$:	MOV	#RETRY,RTTBL(R3) ;SET RETRY COUNT
									; PJC020
									; PJC020
	.IF DF	A$$HDR							; PJC020
									; PJC020
	BITB	#IO.WPB&377,I.FCN(R1) ;PHYSICAL BLOCK FUNCTION?		; PJC020
	BNE	30$		;IF NE YES				; PJC020
									; PJC020
	.ENDC								; PJC020
									; PJC020
									; PJC020
	CALL	$BLKCK		;CHECK LOGICAL BLOCK NUMBER
	TST	U.CW2(R5)	;RS04 DRIVE?
	BMI      	20$		;IF MI YES
	ASL	R0		;MULTIPLY RS03 BLOCK
20$:	ASL	R0		;CONVERT TO SECTOR AND TRACK ADDRESS
	MOV	R0,I.PRM+12(R3)	;SAVE DISK ADDRESS


;									;**-7
; INITIATE I/O OPERATION
;

30$:				;REF LABEL


	.IF DF	M$$EXT

	BIT	#DV.MBC,U.CW1(R5)  ;IS IT A MASS BUS DEVICE?
	BNE	300$		;IF NE YES -- DOES NOT USE UMR'S
	CALL	$MPUBM		;MAP UNIBUS TO MEMORY
300$:				;REF LABEL

	.ENDC


	MOV	S.CSR(R4),R2	;GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	MOVB	S.ITM(R4),S.CTM(R4)        ;SET CURRENT DEVICE TIMEOUT COUNT
	ADD	#RSCS2,R2	;POINT TO SECOND CSR
	MOV	#40,(R2)	;CLEAR RH11 CONTROLLER AND ALL DRIVES
	MOVB	U.UNIT(R5),(R2)	;SELECT PROPER DRIVE
	MOV	I.PRM+12(R1),-(R2)  ;INSERT DISK ADDRESS
	MOV	U.BUF+2(R5),-(R2)  ;INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	;INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		;CONVERT TO WORD COUNT
	NEG	(R2)		;MAKE NEGATIVE WORD COUNT
	TST	-(R2)		;POINT TO CSR REGISTER
	MOV	#IE.DNR&377,R0	;ASSUME DRIVE NOT READY
	MOV	RSDS(R2),R3	;GET CONTENTS OF DR      IVE STATUS REGISTER
	COM	R3		;COMPLEMENT STATUS
	BIT	#10200,R3	;DRIVE READY AND ON-LINE?
	BEQ	32$		;IF EQ YES


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;IS DRIVE SPINNING UP?
	BNE	35$		;IF NE YES

	.IFTF


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC OPERATION?
	BEQ	31$		;IF EQ NO
	JMP	45$		;LOG DIAGNOSTIC DRIVE NOT READY
31$:				;REF LABEL

	.ENDC


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DRIVE NOT READY ERROR

	.ENDC


	JMP	60$		;FINISH I/O
32$:				;REF LABEL

	.IFT
      
	BICB	#US.SPU,U.STS(R5)  ;RESET DRIVE SPINNING UP

	.ENDC




	.IF DF	E$$DVC

	CALL	$BMSET		;SET I/O ACTIVE BIT IN MAP

	.ENDC


	.IF DF	M$$EXT&M$$MGE

	BIT	#DV.MBC,U.CW1(R5)  ;;;IS IT A MASS BUS DEVICE?
	BEQ	34$		;;;IF EQ NO -- DOES USE UMR'S
	MOVB	U.BUF+1(R5),RSBAE(R2)  ;;;SET ADDRESS EXTENSION BITS
	MOVB	U.BUF(R5),(R2)	;;;START FUNCTION
	RETURN			;;;

	.ENDC


34$:	MOV	U.BUF(R5),(R2)	;;;START FUNCTION


;
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
;

DS      CAN:	RETURN			;;;NOP FOR RS03/RS04

;+
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON THE UNIT.  THE CURRENT TIMEOUT
; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE
; SUFFICIENT TIME TO SPN BACK UP.  THE NEXT I/O REQUEST TO ANY
; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS
; THE UNIT IS ALREADY READY.
;-

DSPWF:				;POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	TSTB	S.STS(R4)	;IS THE DRIVE CURRENTLY BUSY?
	BEQ	36$		;IF       EQ NO
35$:	MOVB	#4,S.CTM(R4)	;TIMEOUT IN 4-SECOND INCREMENTS		; PJC029
36$:	BISB	#US.SPU,U.STS(R5)  ;SET UNIT SPINNING UP		;**-2

	.ENDC


	RETURN			;WAIT FOR UNIT TO RESPOND


;+
; **-$DSINT-RH11-RS03/RS04 FIXED HEAD DISK CONTROLLER INTERRUPTS
;-

	INTSE$	DS,PR5,R$$JS1	;;;SAVE REGISTERS AND SET PRIORITY
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,R3		;COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER
	MOV	S.CSR(R4),R2	;GET AD      DRESS OF CSR
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC FUNCTION EXECUTED?
	BNE	45$		;IF NE YES

	.ENDC


	BIT	#60000,(R2)	;ANY ERRORS?
	BEQ	55$		;IF EQ NO


	.IF DF	E$$DVC

	CALL	$DVERR		;LOG DEVICE ERROR

	.ENDC


	MOV	#IE.VER&377,R0	;ASSUME UNRECOVERABLE ERROR
	MOV	RSER(R2),R1	;GET CONTENTS OF ERROR REGISTER
	BIT	#47007,R1	;HARD ERROR?
	BNE	40$		;IF NE YES
	BIT	#14000,RSCS2(R2)  ;NEM OR NED?
	BEQ	50$		;IF EQ NO
40$:	BIT	#4      000,R1	;WRITE LOCK ERROR?
	BEQ	57$		;IF EQ NO
	MOV	#IE.WLK&377,R0	;SET WRITE LOCK ERROR
	BR	60$		;

;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED
; UNLESS THE REQUEST WAS DIAGNOSTIC.  TIMEOUTS ARE USUALLY CAUSED
; BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE.
;

DSOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;;IS DRIVE SPINNING UP?
	BEQ	44$		;;;IF EQ NO
	INCB	S.STS(R4)	;;;COUNT TIMEOUTS			; PJC029
	CMPB	#9.,S.STS(R4)	;      ;;HAVE WE WAITED 32 SECONDS YET?	; PJC029
	BEQ	44$		;;;IF EQ YES				;**-1
	MTPS	#0		;;;ALLOW INTERRUPTS
	JMP	30$		;RETRY ENTIRE OPERATION
44$:	MOVB	#1,S.STS(R4)	;;;LEAVE CONTROLLER BUSY		; PJC029
	BICB	#US.SPU,U.STS(R5)  ;;;RESET DRIVE SPINNING UP		;**-1

	.ENDC


	CALL	$DTOER		;;;LOG DEVICE TIMEOUT


	.IF DF	D$$IAG

	BCC	50$		;IF CC TIMEOUT DURING NORMAL FUNCTION
45$:	CALL	$CRPAS		;PASS CONTROLLER REGISTERS TO TASK
	BR	60$		;DIAGNOSTIC PROCESSING COMPLETE

	.ENDC


50$:	MOV	S.PKT(R4),      R1	;GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	;INHIBIT RETRIES?
	BNE	57$		;IF NE YES
	DEC	RTTBL(R3)	;RETRY FUNCTION?
	BLE	57$		;IF LE NO
51$:	JMP	30$		;RETRY OPERATION

55$:				;REF LABEL


	.IF DF	D$$WCK

	BITB	#IO.WLC&377,I.FCN(R1)  ;WRITE FOLLOWED BY WRITE CHECK?
	BNE	56$		;IF NE YES
	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK ENABLED BY MCR?
	BEQ	60$		;IF EQ NO
56$:	MOVB	U.BUF(R5),R1	;GET LAST FUNCTION
	CMPB	#171,R1		;WAS IT A READ?
	BEQ	60$		;IF EQ YES
	MOVB	#151,U.BUF(R5)	;ASSUME A WRI      TE CHECK OPERATION
	CMPB	#161,R1		;WAS LAST FUNCTION A WRITE?
	BNE	60$		;IF NE NO
	MOV	#RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT
	BR	51$		;START WRTIE CHECK OPERATION

	.IFTF

57$:				;REF LABEL

	.IFT

	BIT	#40000,RSCS2(R2)  ;WRITE CHECK ERROR?
	BEQ	60$		;IF EQ NO
	MOV	#IE.WCK&377,R0	;SET WRITE CHECK ERROR

	.ENDC


60$:	MOV	RSWC(R2),R1	;GET WORDS REMAINING TO TRANSFER
	ASL	R1		;CONVERT TO BYTES LEFT TO TRANSFER
	ADD	U.CNT(R5),R1	;CALCULATE BYTES ACTUALLY TRANSFERED
	MOV	#40011,(R2)	;   L  CLEAR CONTROLLER AND DRIVE
70$:				;REF LABEL


	.IF DF	E$$DVC

	MOVB	S.CON(R4),R3	;RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	;GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	;MERGE STARTING RETRY COUNT

	.ENDC


	CALL	$IODON		;FINISH I/O OPERATION			;**-7
	JMP	DSINI		;PROCESS NEXT REQUEST
	.DSABL	LSB

	.END
 L         ÑØwkQ	› c,        	.TITLE	DRASG
	.IDENT	/06.05/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 06.05
;
; D. N. CUTLER 18-SEP-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	M. S. HARVEY
;
; MODIFIED BY:
; 
;	M. S. HARVEY	19-DEC-79
;		MSH074 -- CLEANUP CODE AND COMMENTS
;
;	M. S. HARVEY	9-JAN-80
;		MSH084 -      - HANDLE UNASSIGNED LUN DURING SEARCH
;
; MACRO LIBRARY CALLS
;

	.MCALL	TCBDF$
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$DRASG-ASSIGN LUN
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO ASSIGN A DEVICE UNIT TO A
; LOGICAL UNIT NUMBER (LUN).
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(7.),DPB SIZE(4.).
;	WD. 01 -- LUN TO BE ASSIGNED.
;	WD. 02 -- NAME OF DEVICE TO BE ASSIGNED.
;	WD. 03 -- UNIT NUMBER OF DEVICE TO BE ASSIGNED.
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURR      ENT TASK.
;	R3=ADDRESS OF THE LUN IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS90' IS RETURNED IF A FILE
;			IS OPEN OR UNIT ATTACHED ON THE SPECIFIED LUN	;MSH074
;			AND NO OTHER LUN IS ASSIGNED TO THAT UNIT.	;MSH074
;		DIRECTIVE STATU      S OF 'D.RS92' IS RETURNED IF DEVICE	;**-1
;			AND/OR UNIT IS INVALID.
;-

$DRASG::CALL	$MPLUN		;MAP LUN TO DEVICE UCB
	TST	(R1)		;FILE ACCESSED ON LUN?
	BNE	40$		;IF NE YES
	MOV	R0,-(SP)	;SAVE ADDRESS OF UCB
	MOV	R1,R4		;SAVE ADDRESS OF SECOND LUN WORD
	MOV	(R3)+,R2	;GET NAME OF DEVICE
	MOVB	(R3),R0		;GET UNIT NUMBER


	.IF DF	L$$ASG


	.IF DF	M$$MUP

	BIT	#T3.SLV,T.ST3(R5) ;SLAVE TASK?
	BNE	17$		;IF NE YES, BYPASS LOGICAL DEVICE TABLE

	.ENDC


	MOV	#$LOGHD,R3	;POINT TO LOGICAL ASSI      GNMENT LIST
13$:	MOV	(R3),R3		;GET ADDRESS OF NEXT ENTRY
	BEQ	17$		;IF EQ END OF LIST
	TSTB	L.TYPE(R3)	;SYSTEM WIDE ASSIGNMENT?
	BEQ	15$		;IF EQ YES
	CMP	L.UCB(R3),T.UCB(R5) ;TI UCB ADDRESS MATCH?
	BNE	13$		;IF NE NO
15$:	CMP	R2,L.NAM(R3)	;DEVICE NAME MATCH?
	BNE	13$		;IF NE NO
	CMPB	R0,L.UNIT(R3)	;UNIT NUMBER MATCH?
	BNE	13$		;IF NE NO
	MOV	L.ASG(R3),R1	;GET ASSIGNMENT UCB ADDRESS
	BR	25$		;FINISH IN COMMON CODE

	.ENDC


17$:	MOV	#$DEVHD,R3	;POINT TO PHYSICAL DEVICE TABLES
20$:	MOV	(R3),      R3		;GET ADDRESS OF NEXT DCB
	BEQ	50$		;IF EQ END OF TABLES
	CMP	R2,D.NAM(R3)	;DEVICE NAME MATCH?
	BNE	20$		;IF NE NO
	CMPB	R0,D.UNIT(R3)	;UNIT GREATER THAN OR EQUAL TO LOW BOUNDRY?
	BLO	20$		;IF LO NO
	CMPB	R0,D.UNIT+1(R3)	;UNIT LESS THAN OR EQUAL TO HIGH BOUNDRY?
	BHI	20$		;IF HI NO
	SUB	D.UNIT(R3),R0	;CALCULATE RELATIVE UNIT NUMBER
	BIC	#177400,R0	;CLEAR EXCESS BITS
	MOV	D.UCBL(R3),R1	;GET LENGTH OF UCB IN BYTES
	CALL	$MUL		;CALCULATE NUMBER OF BYTES
	ADD	D.UCB(R3),R1	;CALCULATE ADDRESS OF UC      B
25$:	MOV	(SP)+,R3	;WAS LUN PREVIOUSLY ASSIGNED?
	BEQ	30$		;IF EQ NO
	CMP	R5,U.ATT(R3)	;UNIT ATTACHED TO CURRENT TASK?
	BNE	27$		;IF NE NO
	MOV	R1,-(SP)	;SAVE NEW ASSIGNMENT UCB ADDRESS
	MOV	R1,R0		;COPY UCB ADDRESS
	CALL	$MPLND		;MAP TO REAL UCB ADDRESS
	CMP	R0,R3		;NEW ASSIGNMENT TO SAME FINAL UCB?	;**-1
	BNE	35$		;IF EQ NO
	MOV	(SP)+,R1	;RETRIEVE NEW ASSIGNMENT UCB ADDRESS	;MSH074
27$:	MOV	R3,R5		;COPY OLD ASSIGNMENT UCB ADDRESS
									;MSH074
;									;MSH074
; BEFORE REASSIGNING THIS       LUN, MAKE SURE THAT ALL I/O REQUESTS		;MSH074
; ASSOCIATED WITH THE OLD ASSIGNMENT ARE ELIMINATED SO THAT THEY	;MSH074
; CANNOT POSSIBLY BE ASSOCIATED WITH THE NEW LUN CONTEXT. (THE		;MSH074
; I/O PACKET HAS A POINTER TO THE SECOND WORD OF ITS LUN.) ALSO,	;MSH074
; SINCE I/O KILL INCLUDES NO MECHANISM FOR HANDLING LUN SPECIFIC	;MSH074
; KILLING, ESPECIALLY AT THE DRIVER/CURRENT-PACKET LEVEL, ALL I/O	;MSH074
; ASSOCIATED WITH THE DEVICE ACCESSED THRU THE OLD ASSIGNMENT MUST	;MSH074
; BE ELIMINATED, RE      GARDLESS OF WHICH LUN THE I/O WAS ORIGINALLY		;MSH074
; ISSUED FROM.								;MSH074
;									;MSH074
									;MSH074
	MOV	#$IOKIL,-(SP)	;SET TO KILL I/O ON PREVIOUS ASSIGNMENT
30$:	MOV	R1,-(R4)	;ASSIGN LUN TO NEW UNIT
	RETURN			;
									;MSH074
35$:	MOV	$HEADR,R1	;GET TASK HEADER			;MSH074
	ADD	#H.NLUN,R1	;POINT TO THE NUMBER OF LUNS		;**-2
	MOV	(R1),-(SP)	;PICK UP COUNT
37$:	CMP	(R1)+,(R1)+	;ADVANCE TO NEXT UCB POINTER + 2
	CMP	R1,R4		;SAME LUN AS BEING REASSIGNED?
	BEQ	39$		;IF EQ YES
	M   Ú  OV	-2(R1),R0	;GET THIS LUN ASSIGNMENT
	BEQ	39$		;IF EQ LUN IS UNASSIGNED, SKIP IT	;MSH084
	CALL	$MPLND		;FOLLOW ANY REDIRECT; HANDLE TI:
	CMP	R0,R3		;LUN ASSIGNED TO SAME DEV AS REASS LUN?
	BNE	39$		;NO, BRANCH
	TST	(SP)+		;REMOVE COUNT
	MOV	(SP)+,R1	;GET NEW LUN ASSIGNMENT
	BR	27$		;ATTACH CAN BE IGNORED
39$:	DEC	(SP)		;POINT TO NEXT LUN
	BGT	37$		;TRY AGAIN
40$:	DRSTS	D.RS90		;SET DIRECTIVE STATUS			;**-1
50$:	DRSTS	D.RS92		;SET DIRECTIVE STATUS

	.END
 Ú         �m„kQ	› c,        	.TITLE	QUEUE
	.IDENT	/06.07/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 06.07
;
; D. N. CUTLER 3-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	C. A. D'ELIA
;	T. J. MILLER
;	J. A. SCHRIESHEIM
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	20-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG       SUPPORT
;
;	M. S. HARVEY	2-JUN-80
;		MSH103 -- CLEAN UP COMMAND LINE INTERPRETER REQUESTING
;
;	M. S. FOX	07-JAN-81
;		MF203 -- INITIAL ALTERNATE CLI SUPPORT
;
;	M. S. HARVEY	3-FEB-81
;		MSH132 -- DEFINE C.SYST CLOCK BLOCK CODE FOR USE BY
;			  CINT$ INTERRUPT ROUTINES
;
;	M. S. FOX	03-FEB-81
;		MF208 -- ADD COMMAND ARRIVAL ASTS FOR CLIS
;
; GENERAL QUEUE MANIPULATION ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	CLKDF$,TCBDF$
	CLKDF$			;DEFINE CLOCK QUEUE CONTROL BLOCK OFFSETS
	TCBDF$	      		;DEFINE TASK CONTROL BLOCK OFFSETS

;+
; **-$CLINS-CLOCK QUEUE INSERTION
;
; THIS ROUTINE IS CALLED TO MAKE AN ENTRY IN THE CLOCK QUEUE. THE ENTRY
; IS INSERTED SUCH THAT THE CLOCK QUEUE IS ORDERED IN ASCENDING TIME.
; THUS THE FRONT ENTRIES ARE MOST IMMINENT AND THE BACK LEAST.
;
; INPUTS:
;
;	R0=ADDRESS OF THE CLOCK QUEUE ENTRY CORE BLOCK.
;	R1=HIGH ORDER HALF OF DELTA TIME.
;	R2=LOW ORDER HALF OF DELTA TIME.
;	R4=REQUEST TYPE.
;	R5=ADDRESS OF REQUESTING TCB OR REQUEST IDENTIFIER.
;
; O      UTPUTS:
;
;	THE CLOCK QUEUE ENTRY IS INSERTED IN THE CLOCK QUEUE ACCORDING
;	TO THE TIME THAT IT WILL COME DUE.
;-

	.ENABL	LSB
$CLINS::CLR	(R0)+		;POINT TO TYPE FIELD AND CLEAR LINK
	MOVB	R4,(R0)+	;SET REQUEST TYPE
	INC	R0		;ADVANCE TO TCB ADDRESS
	MOV	R5,(R0)+	;SET TCB OR REQUEST IDENTIFIER
	ADD	$ABTIM,R2	;CALCULATE ABSOLUTE TIME WHEN
	ADC	R1		;REQUEST WILL COME DUE
	MOV	R2,(R0)+	;SET LOW ORDER PART OF TIME
	MOV	R1,(R0)		;SET HIGH ORDER PART OF TIME
	MOV	#$CLKHD,R2	;POINT TO CLOCK QUEUE LIS      T HEAD
10$:	MOV	R2,R1		;SAVE ADDRESS OF PREVIOUS ENTRY
	MOV	(R1),R2		;GET ADDRESS OF NEXT ENTRY
	BEQ	20$		;IF EQ END OF LIST
	CMP	(R0),C.TIM+2(R2) ;COMPARE HIGH ORDER TIMES
	BHI	10$		;IF HI NOT THIS ENTRY
	BLO	20$		;IF LO ENTRY GOES HERE
	CMP	-2(R0),C.TIM(R2) ;COMPARE LOW ORDER TIMES
	BHIS	10$		;IF HIS NOT THIS ENTRY
20$:	SUB	#8.,R0		;BACK UP TO FRONT OF BLOCK
	MOV	R0,(R1)		;SET NEW NEXT IN PREVIOUS ENTRY
	MOV	R2,(R0)		;SET NEXT IN NEW ENTRY


	.IF DF	L$$DRV&M$$MGE!C$$INT&M$$MGE				;MSH132
		      							;**-1
	CMPB	#C.SYST,R4	;A SYSTEM ROUTINE REQUEST (DRIVER)?
	BNE	30$		;IF NE NO
	MOV	KISAR5,C.AR5(R0)  ;SAVE APR5 MAPPING

	.ENDC


30$:	RETURN			;

;+
; **-$CLRMV-CLOCK QUEUE REMOVAL
; **-$CLRSM-CLOCK QUEUE REMOVAL - SELECTIVE MARK TIME
;
; THIS ROUTINE IS CALLED TO REMOVE ALL ENTRIES FOR A SPECIFIED TCB ADDRESS
; AND REQUEST TYPE FROM THE CLOCK QUEUE, OR SELECTIVELY BY EFN OR AST
; ADDRESS IF ENTRY AT $CLRSM.
;
; INPUTS:
;
;	R1=EFN NUMBER OR 0 (IF ENTRY AT $CLRSM).
;	R2=AST ADDR      ESS OR 0 (IF ENTRY AT $CLRSM).
;	R4=REQUEST TYPE.
;	R5=ADDRESS OF REQUESTING TCB OR SYSTEM SUBROUTINE.
;
; OUTPUTS:
;
;	ALL OF THE MATCHING ENTRIES FOR THE SPECIFIED TCB ADDRESS ARE
;	REMOVED FROM THE CLOCK QUEUE. IF THE REQUEST TYPE IS NOT 'C.SYST',
;	THEN THE CLOCK QUEUE ENTRY CORE BLOCK IS RELEASED.
;-

$CLRMV::			;REF LABEL

	.IF DF C$$SMT

	CLR	R1		;MATCH ON ANY EVENT FLAG (MKTM ONLY)
	CLR	R2		;MATCH ON ANY AST ADDRESS (MKTM ONLY)
$CLRSM::			;REF LABEL

	.IFTF	;C$$SMT

	MOV	#$CLKHD      ,R0	;POINT TO CLOCK QUEUE LISTHEAD
40$:	MOV	R0,R3		;SAVE ADDRESS OF PREVIOUS ENTRY
	MOV	(R3),R0		;GET ADDRESS OF NEXT ENTRY
	BEQ	30$		;IF EQ END OF LIST
	CMPB	R4,C.RQT(R0)	;REQUEST TYPE MATCH?
	BNE	40$		;IF NE NO
	CMP	R5,C.TCB(R0)	;TCB OR SYSTEM SUBROUTINE ADDRESS MATCH?
	BNE	40$		;IF NE NO

	.IF DF	C$$SMT!G$$EFN						;MSH049
									;**-1
	TST	R4		;MARK TIME ENTRY?
	BNE	60$		;IF NE NO
									;MSH049
	.ENDC								;MSH049
									;MSH049
	.IFT	;C$$SMT							;MSH049
									;MSH049
	TS      TB	R1		;EFN SPECIFIED?
	BEQ	50$		;IF EQ NO
	CMPB	R1,C.EFN(R0)	;MATCH ON EFN?
	BEQ	55$		;IF EQ YES, REMOVE ENTRY		;MSH049
	TST	R2		;AST ADDRESS SPECIFIED?			;**-1
	BEQ	40$		;IGNORE PACKET
50$:	TST	R2		;AST SPECIFIED?
	BEQ	55$		;IF EQ NO				;MSH049
	CMP	R2,C.AST(R0)	;MATCH ON AST?				;**-1
	BNE	40$		;IF NE NO
55$:				;REF LABEL				;MSH049
									;**-1
	.IFTF	;C$$SMT

	.IF DF	G$$EFN							;MSH049
									;MSH049
	MOV	R2,-(SP)	;SAVE AST ADDRESS			;MSH049
	MOV	R1,-(SP)	;SAVE EVENT FLAG			;MSH      049
	MOV	R3,-(SP)	;SAVE ADDRESS OF PREVIOUS ENTRY		;MSH049
	MOV	C.DST(R0),R3	;GET EVENT FLAG MASK ADDRESS		;MSH049
	MOV	T.PCB(R5),R4	;GET TASK PCB				;MSH049
	MOV	P.HDR(R4),R4	;GET HEADER				;MSH049
	CALL	$DEAGF		;DEACCESS IF GROUP GLOBAL		;MSH049
	MOV	(SP)+,R3	;RESTORE ADDRESS OF PREVIOUS ENTRY	;MSH049
	MOV	(SP)+,R1	;RESTORE EVENT FLAG			;MSH049
	MOV	(SP)+,R2	;RESTORE AST ADDRESS			;MSH049
	MOV	(R3),R0		;RESTORE ADDRESS OF CURRENT CLOCK BLK	;MSH049
	CLR	R4		;RESTORE MARK TIME REQUEST TYPE		;MSH04      9
									;MSH049
	.ENDC								;MSH049
									;MSH049
60$:	MOV	(R0),(R3)	;REMOVE ENTRY FROM LIST			;MSH049
	CMPB	#C.SYST,C.RQT(R0) ;SYSTEM SUBROUTINE REQUEST?		;**-1
	BEQ	40$		;IF EQ YES CONTINUE

	.IFT	;C$$SMT

	MOV	R2,-(SP)	;SAVE NECESSARY REGISTERS
	MOV	R1,-(SP)	;

	.IFTF	;C$$SMT

	CALL	$DECLK		;DEALLOCATE ENTRY CORE BLOCK

	.IFT	;C$$SMT

	MOV	(SP)+,R1	;RESTORE SAVED REGISTERS
	MOV	(SP)+,R2	;
	BR	$CLRSM		;GO AGAIN

	.IFF	;C$$SMT

	BR	$CLRMV		;GO AGAIN

	.ENDC	;C$$SMT

	.D      SABL	LSB

;+
; **-$QINSF-QUEUE INSERTION AT END OF LIST (FIFO)
;
; THIS ROUTINE IS CALLED TO MAKE AN ENTRY IN A FIRST IN FIRST OUT
; LIST. THE ENTRY IS LINKED TO THE END OF THE LIST.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TWO WORD LISTHEAD.
;	R1=ADDRESS OF THE ENTRY TO BE INSERTED.
;
; OUTPUTS:
;
;	THE ENTRY IS LINKED TO THE END OF THE QUEUE.
;
;	R0 AND R1 ARE PRESERVED ACROSS CALL.
;-

	.ENABL	LSB
$QINSF::MOV	2(R0),R2	;GET ADDRESS OF LAST ENTRY IN LIST
	BR	20$		;FINISH IN COMMON CODE

;+      
; **-$QINSP-QUEUE INSERTION BY PRIORITY
;
; THIS ROUTINE IS CALLED TO INSERT AN ENTRY IN A PRIORITY ORDERED
; LIST. THE LIST IS SEARCHED UNTIL AN ENTRY IS FOUND THAT HAS A
; LOWER PRIORITY OR THE END OF THE LIST IS REACHED. THE NEW
; ENTRY IS THEN LINKED INTO THE LIST AT THE APPROPRIATE POINT.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TWO WORD LISTHEAD.
;	R1=ADDRESS OF THE ENTRY TO BE INSERTED.
;
;
; OUTPUTS:
;
;	THE ENTRY IS LINKED INTO THE LIST BY PRIORITY.
;
;	R0 AND R1 ARE PRESERVED ACROSS CA      LL.
;-

$QINSP::MOV	R0,R3		;COPY ADDRESS OF LISTHEAD
10$:	MOV	R3,R2		;SAVE ADDRESS OF CURRENT ENTRY
	MOV	(R2),R3		;GET ADDRESS OF NEXT ENTRY
	BEQ	20$		;IF EQ END OF LIST
	CMPB	T.PRI(R1),T.PRI(R3) ;NEW ENTRY LOWER OR SAME PRIORITY?
	BLOS	10$		;IF LOS YES
	MOV	R3,(R1)		;LINK CURRENT TO NEW ENTRY
	BR	30$		;
20$:	MOV	R1,2(R0)	;SET ADDRESS OF NEW LAST
	CLR	(R1)		;CLEAR LINK TO NEXT ENTRY
30$:	MOV	R1,(R2)		;LINK NEW TO PREVIOUS ENTRY
	RETURN			;
	.DSABL	LSB

;+									; MF203
; **-$QMCRL-QUEUE       A COMMAND LINE TO THE CLI OF A TERMINAL		; MF203
; **-$QCLIL-QUEUE A COMMAND LINE TO A SPECIFIED CLI			; MF203
; **-$QMCR -QUEUE A COMMAND LINE TO MCR					; MF203
; **-$QCLNR-QUEUE A COMMAND BUT NO CLI REQUEST (A$$CLI SYSTEMS ONLY)	; MF203
;									; MF203
; THESE ROUTINES ARE CALLED TO QUEUE A COMMAND LINE TO A COMMAND	; MF203
; LINE INTERPRETER AND REQUEST EXECUTION OF THE CLI.			; MF203
;									; MF203
; INPUTS:								; MF203
;									; MF203
;	R0=TCB ADDRESS OF CLI ($QCLIL ONLY)				; MF20      3
;	R1=ADDRESS OF THE COMMAND LINE CONTROL BLOCK			; MF203
;									; MF203
; OUTPUTS:								; MF203
;									; MF203
;	THE CLI THE COMMAND IS INTENDED FOR IS DETERMINED AND REQUESTED	; MF203
;	WITH THE SPECIFIED COMMAND LINE.				; MF203
;-									; MF203
									; MF203
	.IF NDF A$$CLI							; MF203
									; MF203
$QMCRL::			;REF LABEL				; MF203
	.IF DF	M$$CLI							; MF203
									; MF203
	MOV	2(R1),R0	;GET TERMINAL UCB ADDRESS		; MF203
	BIC	#1,R0		;CLEAR PROMPT FLAG			; MF203
	CA      LL	$MPLND		;FOLLOW REDIRECTION			; MF203
	MOV	@U.CLI(R0),R0	;EXTRACT TERMINAL'S CLI TCB ADDRESS	; MF203
	BR	$QCLIL		;QUEUE COMMAND LINE AND REQUEST CLI	; MF203
									; MF203
	.ENDC	;M$$CLI							; MF203
									; MF203
									; MF203
$QMCR::	MOV	$MCRPT,R0	;EXTRACT MCR'S TCB ADDRESS		; MF203
$QCLIL::CALLR	$EXRQF		;PASS LINE TO CLI AND REQUEST CLI	; MF203
$QCLNR::			;ROUTINE DOES NOT EXIST WITHOUT A$$CLI	; MF203
									; MF203
	.IFF	; NDF A$$CLI						; MF203
									; MF203
	.ENABL LSB		      					; MF203
$QCLIL::CMP	$MCRPT,R0	;IS TARGET CLI THE DISPATCHER		; MF203
	BEQ	$QMCR		;IF EQ YES, SEND CMD TO MCR		; MF203
	MOV	R0,-(SP)	;SAVE CLI TCB ADDRESS			; MF203
	BR	10$		;					; MF203
$QCLNR::CLR	-(SP)		;DO NOT REQUEST CLI			; MF203
10$:									; MF203
									; MF208
	.IF DF	A$$TRP							; MF208
									; MF208
	MOV	R0,-(SP)	;SAVE TCB ADDRESS AGAIN			; MF208
									; MF208
	.IFTF								; MF208
									; MF208
	MOV	#$CLICQ,R0	;POINT TO CMD QUEUE LISTHEAD		; MF208
	CALL	$QINSF		      ;INSERT COMMAND IN QUEUE		; MF208
									; MF208
	.IFT	;A$$TRP							; MF208
									; MF208
	MOV	(SP)+,R0	;RETREIVE TCB ADDRESS OF CLI		; MF208
	MOV	R1,-(SP)	;SAVE ADDRESS OF COMMAND		; MF208
	CALL	$DCAST		;DECLARE COMMAND ARRIVAL AST		; MF208
	MOV	(SP)+,R1	;RESTORE CMD ADDRESS			; MF208
	BCS	20$		;IF CS, NO AST SO REQUEST		; MF208
	TST	(SP)+		;CLEAN STACK				; MF208
	RETURN								; MF208
									; MF208
	.ENDC	;A$$TRP							; MF208
									; MF203
									; MF203
20$:	MOV	(SP)+,R0	;R      ESTORE TCB ADDR OR ZERO		; MF203
	BNE	25$		;IF NE, REQUEST CLI			; MF203
	RETURN								; MF203
25$:	CALLR	$EXRQN		;REQUEST CLI AND RETURN			; MF203
$QMCR::	MOV	#40,R2		;SET FLAG TO SPECIFY MCR		; MF203
	BR	30$		;					; MF203
$QMCRL::CLR	R2		;GO WITH DEFAULT CLI			; MF203
30$:	BIT	#1,2(R1)	;IS BUFFER A PROMPT REQUEST		; MF203
	BNE	50$		;IF NE YES				; MF203
	CMPB	M$$CRB-1(R1),#33 ;IS LAST CHAR AN ESCAPE		; MF203
	BEQ	40$		;IF EQ YES				; MF203
	MOVB	#15,M$$CRB-1(R1) ;FORCE A CARRIAGE RETURN		; MF      203
40$:	BISB	R2,M$$CRB-1(R1)	;SET FORCE TO MCR INDICATOR		; MF203
50$:	MOV	$MCRPT,R0	;POINT TO MCR'S TCB			; MF203
	CALLR	$EXRQF		;INSERT COMMAND IN QUEUE AND REQUEST	; MF203
	.DSABL	LSB							; MF203
									; MF203
	.ENDC	;A$$CLI							; MF203
									; MF203
									;**-34

;+
; **-$QRMVF-QUEUE REMOVAL FROM FRONT OF LIST
;
; THIS ROUTINE IS CALLED TO REMOVE THE NEXT (FRONT) ENTRY FROM A
; LIST.	THE LIST ORGANIZATION MAY BE EITHER FIFO OR BY PRIORITY.
;
; INPUTS:
;
;	R0=ADDRESS OF TH      E TWO WORD LISTHEAD.
;
; OUTPUTS:
;
;	C=1 IF THERE ARE NO ENTRIES IN THE LIST.
;	C=0 IF THE NEXT ENTRY IS REMOVED FROM THE LIST.
;		R1=ADDRESS OF THE ENTRY REMOVED.
;
;	R0 IS PRESERVED ACROSS CALL.
;-

	.ENABL	LSB
$QRMVF::MOV	R0,R2		;COPY ADDRESS OF LISTHEAD
	MOV	(R2),R3		;GET ADDRESS OF NEXT ENTRY
	BNE	30$		;IF NE LIST HAS AN ENTRY
10$:	SEC			;NO ENTRIES IN LIST
	RETURN			;

;+
; **-$QRMVT-QUEUE REMOVAL BY TCB ADDRESS
;
; THIS ROUTINE IS CALLED TO REMOVE THE NEXT ENTRY FROM A LIST THAT      
; MATCHES A SPECIFIED TCB ADDRESS. THE LIST ORGANIZATION MAY BE
; EITHER FIFO OR BY PRIORITY.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TWO WORD LISTEAD.
;	R1=ADDRESS OF THE TCB TO SEARCH FOR.
;
; OUTPUTS:
;
;	C=1 IF THERE IS NO ENTRY IN THE LIST THAT MATCHES THE TCB ADDRESS.
;	C=0 IF A MATCHING ENTRY IS REMOVED FROM THE LIST.
;		R1=ADDRESS OF THE ENTRY REMOVED.
;
;	R0 IS PRESERVED ACROSS CALL.
;-

$QRMVT::MOV	R0,R3		;COPY ADDRESS OF LISTHEAD
20$:	MOV	R3,R2		;SAVE ADDRESS OF CURRENT ENTRY
	MOV	   ˆ  (R2),R3		;GET ADDRESS OF NEXT ENTRY
	BEQ	10$		;IF EQ END OF LIST
	CMP	R1,R3		;MATCH ON TCB ADDRESS?
	BEQ	30$		;IF EQ YES
	CMP	R1,C.TCB(R3)	;MATCHING TCB ADDRESS?
	BNE	20$		;IF NE NO
30$:	MOV	(R3),(R2)	;CLOSE UP LIST
	BNE	40$		;IF NE NO NEW LAST
	MOV	R2,2(R0)	;SET ADDRESS OF NEW LAST
40$:	MOV	R3,R1		;SET ADDRESS OF ENTRY REMOVED
	CLC			;SUCCESS
	RETURN			;
	.DSABL	LSB

	.END
ˆ         Ó`TkQ	› c,        	.TITLE	DRCMT
	.IDENT	/06.03/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 06.03
;
; D. N. CUTLER 31-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	1-SEP-79
;		MSH052 -- ALWAYS DEFINE CANCEL SELECTIVE MARK TIME
;			  ENTRY POINT FOR DIRECTIVE DISPATCHER      
;
;	M. S. HARVEY	19-DEC-79
;		MSH075 -- DEFINE SPECIAL ENTRY POINT FOR ERROR LOGGING
;			  ON NON-DIRECTIVE COMMON SYSTEMS
;		** RETRACTED FOR NEW ERROR LOGGER - 20-JAN-81 **
;
; CANCEL MARK TIME AND SCHEDULE REQUESTS DIRECTIVES
;
; MACRO LIBRARY CALLS
;

	.MCALL	CLKDF$
	CLKDF$			;DEFINE CLOCK QUEUE CONTROL BLOCK OFFSETS

;+
; **-$DRCMT-CANCEL MARK TIME REQUESTS
; **-$DRCMS-CANCEL SELECTIVE MARK TIME REQUESTS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CANCEL ALL MARK TIME REQUESTS
; (DPB       SIZE=1) OR ALL REQUESTS WITH MATCHING EVENT FLAG OR AST ADDRESS
; (DPB SIZE=3).
;
; DPB FORMAT.
;
;	WD. 00 -- DIC(27.), DPB SIZE(1. OR 3.)
;	WD. 01 -- EFN NUMBER
;	WD. 02 -- AST ADDRESS
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF WD. 00 + 2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	NOTE: $DRCMT IS ALSO CALLED FROM THE EXIT DIRECTIVE AND
;		ONLY REQUIRES R5 TO BE LOADED ON ENTRANCE.
;
; OUT      PUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF +1.
;-

	.ENABL	LSB
$DRCMS::			;REF LABEL				;MSH052
	.IF DF C$$SMT							;**-1

	CMPB	-(R3),#1	;DPB SIZE = 1?				;MSH052
	BEQ	$DRCMT		;IF EQ YES, CANCEL ALL MARK TIMES	;**-1
	CMPB	(R3)+,#3	;DPB SIZE = 3?
	BNE	5$		;IF NE NO, INVALID DPB SIZE
	MOV	(R3)+,R1	;PICK UP SPECIFIED EFN
	MOV	(R3),R2		;PICK UP SPECIFIED AST ADDRESS
	CLR	R4		;SET MARK TIME CODE
	CALLR	$CLRSM		;CANCEL SELECTED MARK TIME ENTRIES

	.IFTF      	;C$$SMT

$DRCMT::CLR	R4		;SET TYPE OF REQUEST TO REMOVE
	BR	10$		;REMOVE ALL MARK TIME ENTRIES.


	.IFT	;C$$SMT

5$:	DRSTS	D.RS99		;INVALID DPB SIZE

	.ENDC	;C$$SMT

;+
; **-$DRCSR-CANCEL SCHEDULE REQUESTS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CANCEL ALL SCHEDULE REQUESTS FOR A
; SPECIFIED TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(25.),DPB SIZE(3.).
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB TO CANCEL SCHEDUL      E REQUESTS FOR.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO CANCEL SCHEDULE REQUES
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF +1.
;-

$DRCSR::MOV	R0,R5		;SET TCB ADDRESS
	CLR	R4		;SET INITIAL ENTRY TYPE MINUS 2
	CALL	(PC)		;REMOVE PERIODIC/SINGLE    €   SHOT REQUESTS
	TST	(R4)+		;ADVANCE TO NEXT ENTRY TYPE
10$:	CALLR	$CLRMV		;REMOVE ALL REMAINING ENTRIES
	.DSABL	LSB

	.END
€          âX kQ	› c,        	.TITLE	DRREG
	.IDENT	/03.13/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 03.13
;
; T. J. MILLER 12-MAR-76
;
; PREVIOUSLY MODIFIED BY:
;
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	25-JUL-79
;		MSH046 -- ADD ASYNCHRONOUS BUFFERED I/O SUPPORT
;
;	M. S. HARVEY	3-OCT-79
;		MSH045 -- ADD DIRECTIVE PARTIT      ION SUPPORT
;
;	M. S. HARVEY	19-DEC-79
;		MSH072 -- DON'T ALLOW REGIONS TO BE CREATED OUTSIDE
;			  THE TARGET SYSTEM-CONTROLLED PARTITION
;
;	M. S. HARVEY	2-JUL-80
;		MSH096 -- SUPPORT ALTERNATE HEADER REFRESH AREAS
;
;	M. S. HARVEY	7-AUG-80
;		MSH110 -- DON'T DESTROY STATIC COMMON ON DETACH
;
;	M. S. HARVEY	15-DEC-80
;		MSH130 -- ALLOW RETURN OF SUCCESS STATUS FOR CREATE
;			  REGION WITHOUT SYS-CONTROLLED PARTITIONS
;
;	M. S. HARVEY	14-SEP-81
;		MSH191 -- DON'T DUPLICATE EXISTING ATTACHM      ENT
;
;	J. M. LAWLER	 7-DEC-81
;		JML095 -- RETRACT MSH191
;
	.PAGE
;
; THE FOLLOWING DIRECTIVES RECEIVE AS INPUT A POINTER TO A REGION DEFINITION
; BLOCK WHICH SERVES AS A COMMUNICATION AREA BETWEEN THE ISSUING TASK AND
; THE EXECUTIVE.  THE REGION DEFINITION BLOCK HAS THE FOLLOWING FORMAT:
;
;		-------------------------------------------------
;		!						!
;	R.GID	!	REGION ID				!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	R.GSIZ	!	SIZE OF REGION (32W BL      OCKS)		!
;		!						!
;		!-----------------------------------------------!
;		!						!
;		!						!
;		!						!
;	R.GNAM	!	NAME OF REGION (RAD50)			!
;		!						!
;		!						!
;		!						!
;		!-----------------------------------------------!
;		!						!
;		!						!
;		!						!
;	R.GPAR	!	REGION'S MAIN PARTITION NAME (RAD50)	!
;		!						!
;		!						!
;		!						!
;		!-----------------------------------------------!
;		!						!
;	R.GSTS	!	REGION STATUS WORD			!
;		!						!
;		!----------------      -------------------------------!
;		!						!
;	R.GPRO	!	PROTECTION CODE OF REGION 		!
;		!						!
;		-------------------------------------------------
;

;
; GLOBAL SYMBOL DEFINITION
;
	.IF DF	P$$LAS							;MSH045
									;**-9
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,PCBDF$,RDBDF$,TCBDF$
	HDRDF$			;DEFINE HEADER AND WINDOW BLOCK OFFSETS
	PCBDF$			;DEFINE PCB AND ATTACHMENT DESCRIPTOR OFFSETS
	RDBDF$			;DEFINE REGION DEFINITION BLOCK OFFSETS
	TCBDF$			;DEFINE TCB OFFSETS

;+
; **-$D      RCRR-CREATE REGION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CREATE A REGION AND OPTIONALLY
; ATTACH TO IT.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(55.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF REGION DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE REGION DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE REGION DEFINITION BLOCK ARE:
;		R.GSIZ=SIZE OF REGIO      N TO CREATE.
;		R.GNAM=NAME OF REGION TO CREATE OR 0 FOR NO NAME.
;		R.GPAR=NAME OF SYSTEM PARTITION IN WHICH TO ALLOCATE REGION
;			OR 0 FOR MAIN SYSTEM PARTITION OF TASK.
;		R.GSTS=CONTROL INFORMATION.
;			RS.NDL=1 IF REGION SHOULD NOT BE DELETED ON LAST
;				DETACH.
;			RS.ATT=1 IF CREATED REGION SHOULD BE ATTACHED.
;			RS.RED=1 IF READ ACCESS IS DESIRED ON ATTACH.
;			RS.WRT=1 IF WRITE ACCESS IS DESIRED ON ATTACH.
;			RS.EXT=1 IF EXTEND ACCESS IS DESIRED ON ATTACH.
;			RS.DEL=1 IF DELETE ACCE      SS IS DESIRED ON ATTACH.
;		R.GPRO=PROTECTION CODE FOR REGION [DEWR,DEWR,DEWR,DEWR].
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF A PCB OR ATTACH-
;			MENT DESCRIPTOR COULD NOT BE ALLOCATED.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF THE DESIRED
;			ACCESS IS DENIED IN THE ATTACHMENT STAGE.
;		DIRECTIVE STATUS OF 'D.RS      94' IS RETURNED IF THE SPECIFIE;MSH072
;			PARTITION IN WHICH THE REGION IS TO BE ALLOCATED;**-1
;			DOES NOT EXIST, OR IF NO PARTITION NAME HAS BEEN
;			SPECIFIED AND RS.ATT=0.
;
;	OUTPUT FIELDS IN THE REGION DEFINITION BLOCK ARE:
;		R.GID=ASSIGNED REGION ID (RS.ATT=1).
;		R.GSTS=DIRECTIVE COMPLETION INFORMATION.
;			RS.CRR=1 IF REGION WAS CREATED.
;-

	.ENABL	LSB
$DRCRR::			;


	.IF DF	D$$YNM&M$$MGE

	ADD	#R.GPAR,R3	;PNT TO NAME OF PAR IN WHICH TO ALLOCATE
	MOV	T.PCB(R5),R2	;ASSUME ALLOC      ATING IN TASK'S PARTITION
	MOV	P.MAIN(R2),R2	;POINT TO MAIN PARTITION PCB
	TST	(R3)		;PARTITION NAME SPECIFIED?
	BEQ	5$		;IF EQ NO
	CALL	$SRNAM		;SEARCH FOR NAMED PARTITION'S PCB
	BCS	90$		;IF CS, PARTITION NOT IN SYSTEM
	CMP	R2,P.MAIN(R2)	;IS IT A MAIN PARTITION?
	BNE	90$		;IF NE NO
5$:	BIT	#PS.SYS,P.STAT(R2) ;IS IT A SYSTEM CONTROLLED PARTITION?
	BEQ	90$		;IF EQ NO
	MOV	R2,R0		;COPY POINTER TO PCB
	TST	-(R3)		;POINT TO REGION NAME (R.GNAM+2)
	TST	-(R3)		;REGION NAME SPECIFIED? (R.GNAM)
	BEQ	1      0$		;IF EQ NO

	.IFF

	CMP	(R3)+,(R3)+	;POINT TO REGION NAME (R.GID)(R.GSIZ)

	.IFTF

	CALL	$SRNAM		;DETERMINE IF NAME IS UNIQUE

	.IFF

	BCS	90$		;IF CS REGION DOES NOT EXIST

	.IFT

	BCC	35$		;IF CC, NAME IS NOT UNIQUE
10$:	MOV	R3,-(SP)	;PUSH NONZERO WORD (P.ATT+2)
	CLR	-(SP)		;(P.ATT)
	MOV	R.GPRO-R.GNAM(R3),-(SP) ;SET PROTECTION MASK (P.PRO)
	BIC	#210,(SP)	;INSURE OWNER AND SYSTEM DELETE ACCESS (P.PRO)
	CLR	-(SP)		;CLEAR HEADER POINTER (P.HDR)
	MOV	#PS.COM!PS.DEL!PS.PIC!PS.SYS,-(SP)       ;SET STATUS WORD (P.STAT)
	MOV	H.CUIC(R4),-(SP) ;SET OWNER UIC (P.OWN)
	CLR	-(SP)		;CLEAR BUSY FLAGS (P.BUSY)
	CLR	-(SP)		;CLEAR SWAP SIZE (P.SWSZ)
	CLR	-(SP)		;CLEAR WAIT QUEUE POINTER (P.WAIT)
	MOV	R.GSIZ-R.GNAM(R3),-(SP) ;STORE SIZE OF REGION (P.SIZE)
	CLR	-(SP)		;CLEAR RELOCATION BIAS (P.REL)
	MOV	R0,-(SP)	;SET MAIN PCB POINTER (P.MAIN)
	CLR	-(SP)		;CLEAR SUBPARTITION LINK (P.SUB)	;MSH072
	MOV	2(R3),-(SP)	;SET SECOND WORD OF PAR NAME (R.GNAM+2)(;**-1
	MOV	(R3),-(SP)	;SET FIRST WORD OF PAR NAM      E (R.GNAM)(P.NAM)
	BNE	30$		;IF NE NAME WAS SPECIFIED
	BIT	#RS.ATT,R.GSTS-R.GNAM(R3) ;IS REGION TO BE ATTACHED
	BEQ	90$		;IF EQ NO, PARTITION NAME ERROR
	CLR	2(SP)		;ELSE CLEAR SECOND WORD OF NAME (P.NAM+2)
30$:	CLR	-(SP)		;ZERO I/O COUNT AND PRIORITY (P.IOC)
	CLR	-(SP)		;CLEAR LINK WORD (P.LNK)
	MOV	SP,R2		;COPY POINTER TO PCB ON STACK

	.IFTF

35$:	BIT	#RS.ATT,R.GSTS-R.GNAM(R3) ;ATTACH DESIRED?
									;MSH130
	.IFF								;MSH130
									;MSH130
	BNE	ATT		;IF NE YES				;MSH130
	RETURN		      	;					;MSH130
									;MSH130
	.IFT								;MSH130
									;MSH130
	BEQ	36$		;IF EQ NO
	CALL	ATT		;ATTACH REGION
36$:				;REF LABEL

	.IFT

	TST	(SP)		;WAS THE REGION CREATED?
	BNE	80$		;IF NE NO, DONE
	MOV	R1,R5		;COPY POINTER TO ATTACHMENT DESCRIPTOR
	MOV	#P.LGTH,R1	;PICK UP PCB SIZE
	CALL	$ALOCB		;ALLOCATE A PCB
	BCS	110$		;IF CS ALLOCATION FAILURE
	MOV	#P.LGTH/2,R1	;PICK UP PCB SIZE IN WORDS
	MOV	R0,R4		;COPY POINTER TO PCB
40$:	MOV	(SP)+,(R0)+	;FILL IN PCB
	DEC	R1		;DONE YET?
	BG      T	40$		;IF GT NO
	CMP	-(R0),-(R0)	;WAS THE PCB ATTACHED?
	BEQ	50$		;IF EQ YES
	MOV	R0,2(R0)	;SET UP LISTHEAD
	CMP	-(R3),-(R3)	;POINT TO REGION ID (R.GSIZ)(R.GID)
	BR	60$		;

	.IFTF

90$:	DRSTS	D.RS94		;PARTITITON NAME ERROR

	.IFT

50$:	MOV	(R0),R5		;PICK UP ADDRESS OF ATTACHMENT DESCRIPTOR
	MOV	R4,A.PCB(R5)	;POINT IT TO THE REAL PCB
60$:	MOV	P.MAIN(R4),R5	;POINT TO MAIN PCB
	CLR	-(SP)		;INDICATE NO PCB FOUND YET
	CLR	-(SP)		;NOT A SUBPARTITION; SIZE MUST BE ZERO	;MSH072
	MOV	R5,R0		;COPY       MAIN PCB ADDRESS
62$:	MOV	P.SUB(R0),R1	;POINT TO NEXT SUBPARTITION
	BEQ	66$		;IF EQ, THIS IS THE LAST ONE
	MOV	P.REL(R1),R2	;GET BASE OF NEXT SUBPARTITION
	SUB	P.REL(R0),R2	;SUBTRACT BASE OF THIS SUBPARTITION
	BEQ	64$		;IF EQ, FIRST SUB STARTS AT BEGINNING
				;OF MAIN, GO ON TO NEXT SUB
	SUB	(SP),R2		;SUBTRACT SIZE OF THIS SUBPARTITION,	;MSH072
				;GIVING THE SPACE ABOVE IT		;**-1
	CMP	P.SIZE(R4),R2	;IS THERE ENOUGH ROOM FOR THE NEW PAR?
	BHI	64$		;IF HI, NO, GO ON TO NEXT SUBPARTITION
	MOV	R0,      2(SP)	;INDICATE A HOLE BIG ENOUGH		;MSH072
64$:	MOV	R1,R0							;**-1
	MOV	P.SIZE(R0),(SP)	;GET SIZE OF NEXT SUBPARTITION		;MSH072
	BR	62$		;GO ON TO NEXT SUBPARTITION
66$:	MOV	P.REL(R5),R2	;PICK UP BASE OF MAIN PARTITION
	ADD	P.SIZE(R5),R2	;ADD SIZE, GIVING TOP OF PARTITION
	SUB	P.REL(R0),R2	;SUBTRACT BASE OF LAST SUB
	SUB	(SP)+,R2	;R2 GETS SIZE OF HOLE AT END OF MAIN	;MSH072
	CMP	P.SIZE(R4),R2	;IS THERE ENOUGH ROOM FOR NEW PAR?	;MSH072
	BHI	70$		;IF HI, NO				;**-4
	MOV	R0,(SP)		;INDICATE SPACE       FOUND
70$:	MOV	(SP)+,R2	;WAS THERE SPACE?
	BEQ	120$		;IF EQ, NO
	MOV	P.SUB(R2),R0	;COPY POINTER TO NEXT SUB
	MOV	R0,P.SUB(R4)	;POINT NEW SUB TO IT
	BNE	72$		;IF NE, THERES A SUB ABOVE NEW
	MOV	R5,R0		;NEW IS GOING IN AT END OF MAIN
72$:	MOV	R4,P.SUB(R2)	;POINT LAST SUB TO NEW ONE
	CMP	R0,R5		;PUTTING NEW AT END OF MAIN?
	BNE	74$		;IF NE NO				;MSH072
	MOV	P.SIZE(R0),R1	;PICK UP SIZE OF MAIN			;**-1
74$:	ADD	P.REL(R0),R1	;POINT TO TOP OF NEW SUB
	SUB	P.SIZE(R4),R1	;SUBTRACT SIZE, GIVING BASE
	MO      V	R1,P.REL(R4)	;PLUG IN BASE
	BIS	#RS.CRR,R.GSTS(R3) ;INDICATE REGION WAS CREATED
	BIT	#RS.NDL,R.GSTS(R3) ;IS NO DELETION DESIRED?
	BEQ	80$		;IF EQ NO
	BIC	#PS.DEL,P.STAT(R4) ;CLEAR DELETE ON LAST DETACH FLAG
80$:	RETURN			;					;**-3
									;MSH130
110$:	BIC	#PS.SYS,P.STAT(SP) ;INSURE DETACH DOES NOT ATTEMPT TO DE;**-3
	MOV	SP,R4		;POINT TO PCB ON STACK
	MOV	#80$,(SP)	;POINT TO NULL ROUTINE
	BR	125$		;JOIN COMMON CODE
120$:	MOV	#$DEACB,(SP)	;ASSUME PCB MUST BE DEALLOCATED
125$:	MOV	(R3),R5		;      PICK UP ATT DESCRIPTOR ADDRESS (R.GID)
	MOV	R4,R0		;POINT TO PCB TO DEALLOCATE
	MOV	#P.LGTH,R1	;PICK UP PCB SIZE
	TST	P.ATT(R4)	;WAS THE PCB ATTACHED?
	BEQ	126$		;IF EQ NO
	MOV	#$DTRG1,(SP)	;SET TO DETACH REGION			;MSH045
126$:	CALL	@(SP)+		;CALL APPRORIATE ROUTINE		;**-1
	DRSTS	D.RS1		;ALLOCATION FAILURE

	.IFTF

;+
; **-$DRATR-ATTACH REGION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO ATTACH THE SPECIFIED REGION
; TO THE CURRENT TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(57.),DPB SIZE(2.)
;      	WD. 01 -- ADDRESS OF REGION DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE REGION DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE REGION DEFINITION BLOCK ARE:
;		R.GNAM=NAME OF REGION TO ATTACH TO OR 0 FOR TASK REGION.
;		R.GSTS=DESIRED ACCESS TO REGION.
;			RS.RED=1 IF READ ACCESS IS DESIRED.
;			RS.WRT=1 IF WRITE ACCESS IS DESIRED.
;			RS.EXT=1       IF EXTEND ACCESS IS DESIRED.
;			RS.DEL=1 IF DELETE ACCESS IS DESIRED.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF AN ATTACHMENT
;			DESCRIPTOR CANNOT BE ALLOCATED.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF THE DESIRED
;			ACCESS IS DENIED.
;		DIRECTIVE STATUS OF 'D.RS84' IS RETURNED IF THE SPECIFIED
;			REGION NAME DOES       NOT EXIST.
;
;	OUTPUT FIELDS IN THE REGION DEFINITION BLOCK ARE:
;		R.GID=ASSIGNED REGION ID.
;		R.GSIZ=SIZE OF ATTACHED REGION.
;-

$DRATR::ADD	#R.GNAM,R3	;POINT TO SPECIFIED REGION NAME
	TST	(R3)		;REGION NAME SPECIFIED?
	BEQ	90$		;IF EQ NO, ILLEGAL
	CALL	$SRNAM		;SEARCH FOR NAMED REGION
	BCS	90$		;IF CS NAMED REGION DOES NOT EXIST
ATT:	BIT	#PS.COM,P.STAT(R2) ;IS THE PARTITION COMMON?
	BEQ	90$		;IF EQ NO

	.IFT

	BIT	#PS.SYS,P.STAT(R2) ;IS IT A SYSTEM CONTROLLED PARTITION?
	BEQ	130$		;IF       EQ NO
	CMP	R2,P.MAIN(R2)	;IS IT THE MAIN SYSTEM CONTROLLED PARTITION?
	BR	140$		;

	.IFTF

130$:	BITB	P.BUSY(R2),P.BUSY+1(R2) ;IS COMMON BLOCK NOT LOADED?
140$:	BEQ	90$		;IF EQ YES
	MOV	R.GSTS-R.GNAM(R3),R0 ;PICK UP STATUS WORD
	BIT	#17,R0		;ATTACH DESIRED?
	BNE	147$		;IF NE YES
	MOV	T.ATT(R5),R1	;POINT TO FIRST ATTACHMENT DESCRIPTOR
146$:	SUB	#A.TCBL,R1	;POINT TO START OF DESCRIPTOR
	CMP	A.PCB(R1),R2	;ATTACHED TO THIS PCB?
	BEQ	155$		;IF EQ YES
	MOV	A.TCBL(R1),R1	;POINT TO NEXT ATTACHMENT D      ESCRIPTOR
	BNE	146$		;IF NE THERE IS ONE
	DRSTS	D.RS86		;NO SUCH REGION ID
147$:	MOV	H.CUIC(R4),R1	;PICK UP CURRENT TASK UIC
	MOV	R0,R4		;COPY STATUS WORD

	.IFT

	.IF DF	D$$PAR							;MSH045
									;MSH045
	CMP	R2,#$STACK	;IS REGION BEING CREATED?		;MSH045
									;MSH045
	.IFF								;MSH045
									;MSH045
	CMP	R2,PC		;IS REGION BEING CREATED?
									;MSH045
	.ENDC								;MSH045
									;MSH045
	BLO	150$		;IF LO YES, SKIP PROTECTION CHECK

	.IFTF

	BIT	#T3.PRV,T.ST3(R5) ;ISS      UING TASK PRIVILEGED?
	BNE	150$		;IF NE YES, SKIP ACCESS CHECK
	CALL	$CKACC		;DETERMINE IF DESIRED ACCESS IS ALLOWED
150$:	CALL	$CRATT		;CREATE ATT DESCRIPTOR AND LINK IT IN
	BCS	160$		;IF CS ALLOCATION FAILURE
155$:	MOV	P.SIZE(R2),-(R3) ;RETURN SIZE OF REGION (R.GSIZ)
									;MSH096
	.IF DF	A$$HDR							;MSH096
									;MSH096
	CMP	R2,T.PCB(R5)	;IS THIS THE TASK REGION?		;MSH096
	BNE	157$		;IF NE NO				;MSH096
	BIT	#T2.CHK,T.ST2(R5) ;TASK HAVE ALTERNATE HEADER AREA?	;MSH096
	BNE	157$		;IF NE       NO, NONCHECKPOINTABLE TASK	;MSH096
	MOVB	T.HDLN(R5),R2	;GET LGTH OF ALT. HDR REFRESH AREA	;MSH096
	SUB	R2,(R3)		;CORRECT REPORTED SIZE OF TASK REGION	;MSH096
157$:				;					;MSH096
	.ENDC								;MSH096
									;MSH096
	MOV	R1,-(R3)	;STORE DESCRIPTOR ADDR AS REG ID (R.GID)
	RETURN			;
160$:	DRSTS	D.RS1		;ALLOCATION FAILURE
	.DSABL	LSB

;+
; **-$DRDTR-DETACH REGION
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO DETACH THE SPECIFIED REGION,
; UNMAPPING IF NECESSARY.
;
; DPB FORMAT:
;
;	WD. 00       -- DIC(59.),DPB SIZE(2.)
;	WD. 01 -- ADDRESS OF REGION DEFINITION BLOCK
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE REGION DEFINITION BLOCK.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
;	INPUT FIELDS IN THE REGION DEFINITION BLOCK ARE:
;		R.GID=REGION ID OF REGION TO DETACH.
;		R.GSTS=CONTROL INFORMATION.
;			RS.MDL=1 IF REGION SHOULD BE MARKED FOR DELETE ON
;				THE LAST DETACH.
;
; OUTPUTS:       (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF AN ATTEMPT IS MADE
;			TO MARK THE REGION FOR DELETE WITHOUT DELETE ACCESS.
;		DIRECTIVE STATUS OF 'D.RS86' IS RETURNED IF AN INVALID REGION
;			ID IS SPECIFIED OR IF AN ATTEMPT IS MADE TO DETACH
;			REGION 0.
;
;	OUTPUT FIELDS IN THE REGION DEFINITION BLOCK ARE:
;		R.GSTS=INDICATION OF ANY       CHANGES IN MAPPING CONTEXT.
;			RS.UNM=1 IF ANY WINDOWS WERE UNMAPPED.
;-

	.ENABL	LSB
$DRDTR::TSTB	T.IOC(R5)	;ANY OUTSTANDING I/O?
	BNE	70$		;IF NE YES, REJECT FOR NOW


	.IF DF	A$$TRP&C$$CKP&T$$BUF

	TSTB	T.TIO(R5)	;TASK HAVE OUTSTANDING BUFFERED I/O?	;MSH046
	BNE	70$		;IF NE YES				;**-1

	.ENDC


	CALL	$SRATT		;SEARCH FOR AND VERIFY REGION ID
	MOV	A.PCB(R5),R0	;POINT TO PCB
	BIT	#PS.COM,P.STAT(R0) ;DETACHING FROM COMMON REGION?
	BEQ	60$		;IF EQ NO, DETACHING FROM TASK REGION
	MOV	H      .WND(R4),R4	;POINT TO NUMBER OF WINDOW BLOCKS
	TST	(R4)+		;POINT TO FIRST WINDOW BLOCK

	.IFT

	BIT	#PS.SYS,P.STAT(R0) ;SYSTEM CONTROLLED PARTITION?
	BEQ	10$		;IF EQ NO
	BIT	#RS.MDL,R.GSTS(R3) ;MARK FOR DELETE DESIRED?
	BEQ	10$		;IF EQ NO
	BITB	#AS.DEL,A.STAT(R5) ;DOES TASK HAVE DELETE ACCESS?
	BEQ	70$		;IF EQ NO
	BIS	#PS.DEL,P.STAT(R0) ;MARK REGION FOR DELETE

	.IFTF

10$:	CMP	W.BATT(R4),R5	;THIS WINDOW MAPPED TO REGION TO DETACH
	BNE	20$		;IF NE NO
	CALL	$UNMAP		;UNMAP WINDOW
	BIS	#RS.UN      M,R.GSTS(R3) ;INDICATE WINDOW WAS UNMAPPED
20$:	ADD	#W.BLGH,R4	;POINT TO NEXT WINDOW BLOCK
	TSTB	A.MPCT(R5)	;ANY MORE WINDOWS MAPPED TO THIS REGION?
	BNE	10$		;IF NE YES

;+
; **-$DETRG-DETACH REGION BY ATTACHMENT DESCRIPTOR ADDRESS
; **-$DTRG1-DETACH REGION BY ATTACHMENT DESCRIPTOR ADDRESS		;MSH045
;
; THIS ROUTINE DETACHES A TASK FROM A REGION AND DEALLOCATES THE ATTACHMENT
; DESCRIPTOR.  ON THE LAST DETACH OF A REGION IT IS CHECKED FOR DELETION.
; WHEN APPRORIATE, $NXTSK IS CALLED.
;
; INPUT      S:
;
;	R5=ADDRESS OF ATTACHMENT DESCRIPTOR
;
; OUTPUTS:
;
;	R0,R1,R2,R3 ARE MODIFIED.
;-

	.IF NDF	D$$PAR							;MSH045
									;MSH045
$DETRG::			;REF LABEL				;MSH045
									;MSH045
	.ENDC								;MSH045
									;MSH045
$DTRG1::MOV	A.PCB(R5),R0	;POINT TO PCB OF REGION			;MSH045
	ADD	#P.ATT,R0	;POINT TO ATTACHMENT DESCR LISTHEAD	;**-1
	CLR	R1		;CLEAR SEARCH KEY
	MOV	A.TCB(R5),-(SP)	;SAVE TCB ADDRESS
	CLR	A.TCB(R5)	;MARK ATTACHMENT DESCRIPTOR FOR REMOVAL
	CALL	$QRMVT		;REMOVE DESCRIP      TOR FROM PCB'S QUEUE

	.IFT

	TST	(R0)		;IS ANYONE ELSE ATTACHED? (P.ATT)
	BNE	50$		;IF NE YES
	BIT	#PS.SYS,P.STAT-P.ATT(R0) ;IS PARTITION SYSTEM CONTROLLED?
	BEQ	50$		;IF EQ NO
	TST	P.NAM-P.ATT(R0)	;IS THIS A NAMED REGION?
	BEQ	25$		;IF EQ NO, FORCE DELETION
	BIT	#PS.DEL,P.STAT-P.ATT(R0) ;IS REGION MARKED FOR DELETE?
	BEQ	55$		;IF EQ NO
25$:	SUB	#P.ATT,R0	;POINT TO START OF PCB
	MOV	P.MAIN(R0),R1	;POINT TO MAIN PARTITION PCB
30$:	CMP	P.SUB(R1),R0	;DOES THIS PARTITION LINK TO ONE TO DELETE?
	      BEQ	40$		;IF EQ YES
	MOV	P.SUB(R1),R1	;POINT TO NEXT SUBPARTITION
	BNE	30$		;IF NE THERE IS ONE
	BR	45$		;SKIP UNLINK OF PCB (THIS INDICATES $DRCRR CALL)
40$:	MOV	P.SUB(R0),P.SUB(R1) ;UNLINK DETACHED PARTITION
45$:	MOV	#P.LGTH,R1	;PICK UP SIZE FOR DELETE
	CALL	$DEACB		;DEALLOCATE PCB

	.ENDC


	.IF DF	D$$ISK

	.IF NDF	D$$YNM!M$$MGE						;MSH110
									;MSH110
	BIT	#PS.COM,P.STAT-P.ATT(R0) ;STATIC COMMON PARTITION?	;MSH110
	BNE	55$		;IF NE YES, DON'T REALLOCATE PARTITION	;MSH110
									;      MSH110
	.IFTF								;MSH110
									;MSH110
49$:	MOV	A.PCB(R5),R0	;POINT TO DETACHED PCB
	MOV	R0,R1		;COPY PCB POINTER
	MOV	P.MAIN(R1),R3	;POINT TO MAIN PARTITION PCB
	CALL	$RLPR1		;RELEASE THE PARTITION
									;MSH110
	.IFF								;MSH110
									;MSH110
	BR	55$		;
50$:	BIT	#PS.COM!PS.SYS,P.STAT-P.ATT(R0) ;FIXED TASK PARTITION?
	BEQ	49$		;IF EQ NO, RELEASE FIXED TASK PARTITION

	.ENDC								;MSH110
									;MSH110
	.IFF

50$:				;REF LABEL

	.ENDC


55$:	MOV	(SP)+,R0	;RESTORE    Ö  TCB ADDRESS
	ADD	#T.ATT,R0	;POINT TO ATTACHMENT DESCRIPTOR LISTHEAD
	CLR	R1		;CLEAR SEARCH KEY
	CLR	A.PCB(R5)	;MARK ATTACHMENT DESCRIPTOR FOR REMOVAL
	CALL	$QRMVT		;REMOVE DESCRIPTOR FROM TCB'S LIST
	MOV	R5,R0		;COPY DESCRIPTOR ADDRESS
	MOV	#A.LGTH,R1	;SET SIZE TO DEALLOCATE
	CALLR	$DEACB		;DEALLOCATE ATTACHMENT DESCRIPTOR
60$:	DRSTS	D.RS86		;INVALID REGION ID
70$:	DRSTS	D.RS16		;ATTEMPT TO MARK FOR DELETE WITHOUT ACCESS
	.DSABL	LSB

	.ENDC


	.END
 Ö         oM�kQ	› c,        	.TITLE	LOWCR
	.IDENT	/10.05/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 10.05
;
; D. N. CUTLER 11-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	P. J. BEZEREDI
;	CHUCK SPITZ
;
; MODIFIED BY:
;
;	M. S. HARVEY	3-APR-80
;		MSH089 -- PRESERVE ENTIRE STACK ON FORCED CRASH
;
;	M. S. H      ARVEY	2-FEB-81
;		MSH146 -- DEFINE ENOUGH EXTRA ROOM ON THE STACK TO
;			  HANDLE FOR THE LOAD IMPOSED BY ERROR THREADING
;
;	M. S. HARVEY	3-FEB-81
;		MSH147 -- INITIALIZE NONSENSE INTERRUPT VECTORS FOR
;			  ERROR LOGGING SYSTEMS
;
;	M. S. HARVEY	21-JUL-81
;		MSH181 -- HANDLE POSSIBLE T-BIT TRAP AFTER POWER UP
;			  ON PDP 11/02 PROCESSORS
;
;
; LOW CORE POINTERS, TRAP VECTORS, AND INTERRUPT VECTORS
;
; THIS FILE MUST BE FIRST IN THE TASK BUILDER COMMAND FILE SINCE
; IT OCCUPIES LOCATIONS S      TARTING AT REAL ZERO.
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PCBDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PCBDF$	,,SYSDEF	;DEFINE PCB OFFSETS AND SIZE

	.PSECT

;
; LOCAL MACROS
;
;	GENVT-GENERATE VECTOR ENTRY
;

	.MACRO	GENVT ARG
	.IF DF	E$$LOG							;MSH147
	.WORD	$NS'ARG							;**-1
	.IFF
	.WORD	$NONSI
	.ENDC
	.WORD	PR7!<<<$$$-START>/4>&17>
	.ENDM

START:

	.REPT	V$$CTR/4
$$$=.
	GENVT	\<<$$$-START>/<4*20>>
	.ENDR

.=START+4
	.WORD	$TRP04		;TRAPS TO 4 (ODD,STACK,NONEX       MEM)
	.WORD	PR7		;
	.WORD	$ILINS		;ILLEGAL (RESERVED) INSTRUCTION TRAPS
	.WORD	PR7		;
									;MSH181
	.IF DF	L$$SI1							;MSH181
									;MSH181
	.WORD	$TBIT		;TEMPORARY T-BIT TRAP HANDLER		;MSH181
									;MSH181
	.IFF								;MSH181
									;MSH181
	.WORD	$TRACE		;BREAK POINT (TRACE) TRAPS
									;MSH181
	.ENDC								;MSH181
									;MSH181
	.WORD	PR7		;
	.WORD	$IOTRP		;
	.WORD	PR7		;
	.WORD	$NONSI		;NONSENSE INTERRUPT
	.WORD	PR7		;
	.WORD	$EMTRP		;EMT INSTRUCTION TRAPS
	.WO      RD	PR7		;
	.WORD	$TRTRP		;TRAP INSTRUCTION TRAPS
	.WORD	PR7		;
	JMP	$CRALT		;JUMP TO CRASH DUMP ROUTINE		;MSH089
.DSW::	.WORD	.+2		;ADDRESS OF DIRECTIVE STATUS		;**-1
	.BLKW	1		;DIRECTIVE STATUS WORD
	.BLKW	1		;FCS IMPURE AREA POINTER
	.BLKW	1		;FORTRAN IMPURE AREA POINTER
	.BLKW	1		;OVERLAY RUN TIME SYSTEM IMPURE AREA POINTER
	.BLKW	1		;RESERVED FOR EXPANSION
	.BLKB	V$$CTR-60	;

;
; EXECUTIVE STACK AREA
;

	.BLKW	40.		;SYSTEM STACK FOR MAPPED AND REAL SYSTEMS.


	.IF DF	D$$H11!M$$MGE!M$$   Æ  NET

	.BLKW	20.		;

	.ENDC


	.IF DF	I$$C11

	.BLKW	30.		;

	.ENDC


	.IF DF	P$$LAS

	.BLKW	P.LGTH/2	;DEFINE EXTRA STACK FOR PLAS SYSTEMS

	.ENDC

	.IF DF M$$NET

	.BLKW	20.		;DEFINE EXTRA STACK FOR DECNET

	.ENDC	;M$$NET
									;MSH146
	.IF DF	P$$OFF							;MSH146
									;MSH146
	.BLKW	20.		;ROOM ON STACK FOR ERROR THREADING	;MSH146
									;MSH146
	.ENDC	;P$$OFF							;MSH146


$STACK::			;REF LABEL

	.END
 Æ         ã˜gkQ	› c,        	.TITLE	DRSPW
	.IDENT	/02.33/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 02.33
;
; T. J. MILLER 26-MAY-77
;
; PREVIOUSLY MODIFIED BY:
;
;	CHUCK SPITZ
;	B. S. MCCARTHY
;	M. S. HARVEY
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-AUG-79
;		MSH049 -- ADD MORE GROUP GLOBAL EVENT FLAG SUPPORT
;
;	M. S. HARVEY	27-AUG      -79
;		MSH051 -- CALCULATE DEFAULT UIC FOR NON-MULTI-USER SYSTEMS
;
;	M. S. HARVEY	8-OCT-79
;		MSH021 -- CONDITIONALIZE ACP TEST
;
;	M. S. HARVEY	2-JUN-80
;		MSH103 -- QUEUE COMMAND TO CORRECT CLI
;
;	M. S. HARVEY	3-JUN-80
;		MSH104 -- ADD EMIT STATUS DIRECTIVE
;			  ADD SEND, REQUEST AND CONNECT DIRECTIVE
;
;	M. S. HARVEY	12-SEP-80
;		MSH115 -- CLEAN UP GROUP GLOBALS FOR TASK EXITTING FROM
;			  EXIT WITH STATUS DIRECTIVE
;
;	M. S. HARVEY	15-SEP-80
;		MSH117 -- SPAWN TASKS THROUGH CLI WIT      H CORRECT UIC
;
;	M. S. HARVEY	25-NOV-80
;		MSH129 -- ALLOW FULL USE OF THE EXIT STATUS BLOCK
;
;	M. S. HARVEY	18-DEC-80
;		MSH131 -- ALWAYS ALLOW SPECIFICATION OF OWN TI:
;
;	M. S. FOX	07-JAN-81
;		MF203 -- INITIAL ALTERNATE CLI SUPPORT
;
;	M. S. FOX	26-JAN-81
;		MF207 -- IMPLEMENT RPOI$ AND SDRP$
;
;	M. S. FOX	01-FEB-81
;		MF209 -- CALL $GTUCB ROUTINE CREATED FOR OTHER DIRECTIVES
;
;	M. S. HARVEY	28-FEB-81
;		MSH153 -- CORRECT MINOR BUGS IN ALTERNATE CLI CODE
;
;	M. S. HARVEY	7-AUG-81      
;		MSH185 -- ALLOW SPECIFICATION OF OLDEST OCB WITHOUT
;			  KNOWING THE PARENT NAME OR OCB ID
;
;	M. S. HARVEY	14-SEP-81
;		MSH190 -- ADD ALTERNATE CLI CONDITIONALIZATION TO
;			  ACTIVE GROUP GLOBAL CONTEXT BYTE
;
;	M. S. HARVEY	6-OCT-81
;		MSH193 -- CONVERT BUFFER LENGTH TO WORD VALUE
;
;
; THIS MODULE CONTAINS THE DIRECTIVE ROUTINES AND PRIMARY SUBROUTINES
; WHICH PROVIDE PARENT-OFFSPRING TASKING SUPPORT.
;
; MACRO LIBRARY CALLS
;


	.IF DF	P$$OFF

	.MCALL	DCBDF$,PKTDF$,TCBDF$,UCBDF      $
	DCBDF$			;DEFINE DEVICE CONTROL BLOCK SYMBOLS
	PKTDF$			;DEFINE I/O PACKET AND OCB OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK SYMBOLS
	UCBDF$			;DEFINE UNIT CONTROL BLOCK SYMBOLS

;+									;MSH104
; **-$DRSRC-SEND REQUEST AND CONNECT / SEND REQUEST AND PASS OCB	;MSH104
;									;MSH104
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO QUEUE A SEND DATA PACKET FOR	;MSH104
; THE SPECIFIED TASK, CONNECT TO THE TASK AND REQUEST IT IF IT IS NOT	;MSH104
; ALREADY ACTIVE.							;MSH104
;									;MSH104      
; DPB FORMAT: (FOR SDRC$)						;MSH104
;									;MSH104
;	WD. 00 -- DIC(141.),DPB SIZE(7.).				;MSH104
;	WD. 01 -- FIRST HALF OF TASK NAME IN RAD50.			;MSH104
;	WD. 02 -- SECOND HALF OF TASK NAME IN RAD50.			;MSH104
;	WD. 03 -- ADDRESS OF SEND BUFFER.				;MSH104
;	WD. 04 -- EFN, LENGTH OF ESB (0 = 1 WORD, >0 = 8. WORDS).	;MSH104
;	WD. 05 -- ADDRESS OF AST ROUTINE TO ENTER UPON STATUS RETURN.	;MSH104
;	WD. 06 -- ADDRESS OF EXIT STATUS BLOCK.				;MSH104
;									; MF207
; THIS DIRECTIVE INSTRUCT      S THE SYSTEM TO QUEUE A SEND DATA PECKET FOR	; MF207
; THE SPECIFIED TASK, UNLINK ALL OR A SELECTED OCB FROM THE CURRENT	; MF207
; TASK, LINK THE OCB(S) OFF THE SPECIFIED TASK, AND REQUEST IT IF IT	; MF207
; IS NOT ALREADY ACTIVE.						; MF207
;									; MF207
; DPB FORMAT: (FOR SDRP$)						; MF207
;									; MF207
;	WD. 00 -- DIC(141.),DPB SIZE(9.)				; MF207
;	WD. 01 -- FIRST HALF OF TASK NAME IN RAD50			; MF207
;	WD. 02 -- SECOND HALF OF TASK NAME IN RAD50			; MF207
;	WD. 03 -- ADDRESS OF SEN      D BUFFER				; MF207
;	WD. 04 -- EFN, FLAGS BYTE					; MF207
;	WD. 05 -- RESERVED FOR LENGTH OF SEND BUFFER ON M-PLUS		; MF207
;	WD. 06 -- FIRST HALF OF NAME OF PARENT WHOSE OCB SHOULD BE PASSE; MF207
;	WD. 07 -- SECOND HALF OF PARENT'S TASK NAME			; MF207
;	WD. 08 -- ADDRESS OF OCB TO PASS (CLI TASKS ONLY);		; MF207
;									;MSH104
; INPUTS:								;MSH104
;									;MSH104
;	R0=ADDRESS OF THE TCB OF THE TARGET TASK.			;MSH104
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TARGET TASK.		;MSH104
;	      R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.	;MSH104
;	R3=ADDRESS OF THE SEND BUFFER ADDRESS IN THE DPB.		;MSH104
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.			;MSH104
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.			;MSH104
;									;MSH104
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)			;MSH104
;									;MSH104
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.			;MSH104
;		DIRECTIVE STATUS OF +1 IS RETURNED.			;MSH104
;	C=1 IF DIRECTIVE IS REJECTED.					;MSH104
;		DIREC      TIVE STATUS OF 'D.RS1' IS RETURNED IF A SEND	;MSH104
;			PACKET, OFFSPRING CONTROL BLOCK OR PARTITION	;MSH104
;			CONTROL BLOCK COULD NOT BE ALLOCATED.		;MSH104
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF IT IS ILLEGAL;MSH104
;			TO SEND TO THE TARGET TASK.			;MSH104
;		DIRECTIVE STATUS OF 'D.RS97' IS RETURNED IF AN INVALID	;MSH104
;			EVENT FLAG NUMBER IS SPECIFIED.			;MSH104
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF THE EXIT	;MSH104
;			STATUS BLOCK IS NOT ENTIRELY WITHIN THE USER'S	;MSH104      
;			SPACE.						;MSH104
;									; MF207
; THE SDRP$ DIRECTIVE CAN RETURN ALL OF THE ABOVE ERRORS, PLUS THE FOLLO; MF207
; THREE:								; MF207
;									; MF207
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF A PARAMETER	; MF207
;			RESERVED FOR A CLI ONLY IS USED BY A NON-CLI TAS; MF207
;			OR AN ATTEMPT IS MADE TO PASS ALL OCBS TO A CLI.; MF207
;		DIRECTIVE STATUS OF 'D.RS86' IS RETURNED IF THERE IS	; MF207
;			NO OCB FROM THE SPECIFIED PARENT		; MF207
;		DIRECTIVE STATUS OF 'D.RS84' IS RETUR      NED IF A CLI TASK	; MF207
;			SPECIFIED BOTH A PARENT NAME AND OCB ADDRESS, AN; MF207
;			THE TWO DO NOT IDENTIFY THE SAME OCB, OR EITHER	; MF207
;			FIELD IS SUPPLIED WITH THE FLAG TO PASS ALL OCBS; MF207
;		DIRECTIVE STATUS OF 'D.RS89' IS RETURNED IF A VALUE	; MF207
;			OTHER THAN 13. IS SUPPLIED AS THE LENGTH OF THE	; MF207
;			SEND PACKET.					; MF207
;-									;MSH104
									;MSH104
	.IF DF	R$$SND							;MSH104
									;MSH104
$DRSRC::MOV	R3,R1		;COPY DPB ADDRESS TO SAVE		;MSH104
						      			; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	MOV	SP,$TEMP4	;SAVE CURRENT STACK, TO EASE UNWIND	; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207
									; MF207
	CALL	ERRSV		;PUSH CONTEXT TO REVERSE SEND OPERATION	;MSH104
	.WORD	NULL		;NO ROUTINE TO CALL NOW			;MSH104
	.WORD	10$		;ADDRESS OF RECOVERY ROUTINE		;MSH104
									;MSH104
	.IF DF	M$$MGE							;MSH104
									;MSH104
	MOV	KISAR6,-(SP)	;SAVE DPB MAPPING			;MSH104
									;MSH104      
	.IFTF								;MSH104
									;MSH104
	MOV	$HEADR,R4	;GET HEADER (DESTROYED BY ERROR THREADIN;MSH104
	CALL	$DRSND		;PERFORM SEND OPERATION			;MSH104
									;MSH104
	.IFT								;MSH104
									;MSH104
	MOV	(SP)+,KISAR6	;RESTORE DPB MAPPING			;MSH104
									;MSH104
	.ENDC	;M$$MGE							;MSH104
									;MSH104
	MOV	4(SP),R3	;RESTORE DPB ADDRESS+6			;MSH104
	TST	(R3)+		;POINT TO EVENT FLAG WORD		;MSH104
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	C      MPB	$DICSV+1,#7.	;IS IT AN SDRC$				; MF207
	BEQ	CNRQT		;IF EQ YES				; MF207
	CMPB	$DICSV+1,#9.	;IS IT AN SDRP$				; MF207
	BEQ	20$		;IF EQ YES				; MF207
	BR	DPBER		;SET ILLEGAL DPB SIZE			; MF207
									; MF207
	.IFF	;R$$POI							; MF207
									; MF207
	BR	CNRQT		;COMMON CONNECT PROCESSING		; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207
									; MF207
									;MSH104
10$:	ADD	#T.RCVL,R0	;POINT TO TARGET TASK RECEIVE QUEUE	;MSH104
	MOV	2(R0),R1	;GET ADDRESS O      F PACKET JUST QUEUED	;MSH104
	CALL	$QRMVT		;REMOVE IT FROM THE QUEUE		;MSH104
	MOV	R1,R0		;COPY POINTER TO PACKET			;MSH104
	CALLR	$DEPKT		;DEALLOCATE THE PACKET			;MSH104
									;MSH104
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
20$:	MOVB	1(R3),R2	;GET FLAGS BYTE, FORCE TASK EXIT??	; MF207
	BMI	30$		;IF MI YES				; MF207
	MOV	#1,$TEMP4	;NO EXIT, BUT IT IS AN SDRP$		; MF207
30$:	TST	(R3)+		;POINT TO LENGTH OF SEND PACKET		; MF207
	CMP	#13.,(R3)+	;IS LENGTH       = 13. WORDS			; MF207
	BNE	40$		;IF NE NO				; MF207
	CALL	LOCOCB		;LOCATE THE OCB(S) TO PASS		; MF207
	MOV	$TKTCB,R5	;GET CURRENT TASK'S TCB ADDRESS		; MF207
	JMP	RQST2		;REQUEST THE TASK TO RUN		; MF207
									; MF207
40$:	MOV	(PC)+,R5	;SET ILLEGAL SEND PACKET SIZE		; MF207
	DRSTS	D.RS89							; MF207
	JMP	ERROR		;GO TO COMMON ERROR CODE		; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207
	.ENDC	;R$$SND							; MF207
									; MF207
									; MF207
;+									;**-1      
; **-$DRCNC-CONNECT TO TASK
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CONNECT THE ISSUING TASK TO
; THE SPECIFIED (ACTIVE) TARGET TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(143.),DPB SIZE(6.).
;	WD. 01 -- FIRST WORD OF TASK NAME IN RAD50.
;	WD. 02 -- SECOND WORD OF TASK NAME IN RAD50.
;	WD. 03 -- EFN, LENGTH OF ESB (0 = 1 WORD, >0 = 8. WORDS)	;MSH129
;	WD. 04 -- ADDRESS OF AST ROUTINE TO ENTER UPON STATUS.		;**-1
;	WD. 05 -- ADDRESS OF THE EXIT STATUS BLOCK.
;
; INPUTS:
;
;	R0=ADDRESS OF THE       TCB OF THE TARGET TASK.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TARGET TASK.
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE EVENT FLAG NUMBER IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RE      TURNED IF AN OFFSPRING
;			CONTROL BLOCK COULD NOT BE ALLOCATED.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF AN ATTEMPT IS
;			BEING MADE TO CONNECT TO A CLI TASK.
;		DIRECTIVE STATUS OF 'D.RS7' IS RETURNED IF THE TARGET
;			TASK IS NOT ACTIVE.
;		DIRECTIVE STATUS OF 'D.RS97' IS RETURNED IF AN INVALID
;			EVENT FLAG NUMBER IS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF THE EXIT
;			STATUS BLOCK IS NOT ENTIRELY IN THE USER'S
;			SPACE.
;-

$DRCNC::MOV	#ERRSV,-(SP)	;PUSH ADDRESS O      F ERROR SAVE ROUTINE
	TST	(R1)		;IS TARGET TASK ACTIVE?
	BMI	10$		;IF MI NO
	BIT	#T3.CLI,T.ST3(R0) ;TARGET TASK A CLI?
	BEQ	CNRQT		;IF EQ NO
	DRSTS	D.RS2		;CONNECTING TO CLI TASK
10$:	DRSTS	D.RS7		;SPECIFIED TASK NOT ACTIVE

;+
; **-$DRREQ-REQUEST, SPAWN, OR CHAIN TO A TASK				; MF207
;									;**-1
; THIS ROUTINE INSTRUCTS THE SYSTEM TO REQUEST OR SPAWN THE SPECIFIED
; TASK, DEPENDING ON THE DPB SIZE.
; IF THE DIRECTIVE IS RPOI$, THE TASK IS CHAINED TO BY UNLINKING	; MF207
; ALL OR A SELECTE      D OCB FROM THE CURRENT TASK, AND LINK IT TO THE	; MF207
; TARGET TASK. THIS DIFFERS FROM SPWN$ IN THAT NO NEW OCB IS CREATED	; MF207
;
; DPB FORMAT (FOR REQUEST OR SPAWN):					; MF207
;									;**-1
;	WD. 00 -- DIC(11.),DPB SIZE(7., 13., OR 14.).
;	WD. 01 -- FIRST HALF OF TASK NAME IN RAD50.
;	WD. 02 -- SECOND HALF OF TASK NAME IN RAD50.
;	WD. 03 -- FIRST WORD OF PARTITION NAME - NOT SUPPORTED.
;	WD. 04 -- SECOND WORD OF PARTITION NAME - NOT SUPPORTED.
;	WD. 05 -- REQUEST PRIORITY - NOT SUPPORTED      .
;	WD. 06 -- REQUEST UIC.
;	WD. 07 -- EFN, LENGTH OF ESB (0 = 1 WORD, >0 = 8. WORDS)	;MSH129
;	WD. 08 -- ADDRESS OF AST ROUTINE TO ENTER UPON STATUS.		;**-1
;	WD. 09 -- EXIT STATUS BLOCK ADDRESS.
;	WD. 10 -- ADDRESS OF COMMAND LINE TO QUEUE FOR TARGET TASK.
;	WD. 11 -- LENGTH OF COMMAND LINE.
;	WD. 12 -- TERMINAL UNIT NUMBER FOR TI:.
;	WD. 13 -- ASCII DEVICE NAME FOR TI:.
;									; MF207
; DPB FORMAT FOR RPOI$ DIRECTIVE					; MF207
;									; MF207
;	WD. 00 -- DIC (11.),DPB SIZE(16.)				; MF      207
;	WD. 01 -- FIRST HALF OF TARGET TASK NAME IN RAD50		; MF207
;	WD. 02 -- SECOND HALF OF TARGET TASK NAME IN RAD50		; MF207
;	WD. 03 -- FIRST WORD OF PARTITION NAME - NOT SUPPORTED		; MF207
;	WD. 04 -- SECOND WORD OF PARTITION NAME - NOT SUPPORTED		; MF207
;	WD. 05 -- REQUEST PRIORITY - NOT SUPPORTED			; MF207
;	WD. 06 -- REQUEST UIC						; MF207
;	WD. 07 -- FIRST HALF OF NAME OF PARENT, WHOSE OCB SHOULD BE PASS; MF207
;	WD. 08 -- SECOND HALF OF NAME OF PARENT, WHOSE OCB SHOULD BE PAS; MF207
;	W      D. 09 -- ADDRESS OF OCB TO PASS (CLI TASKS ONLY)		; MF207
;	WD. 10 -- ADDRESS OF COMMAND BUFFER				; MF207
;	WD. 11 -- LENGTH OF COMMAND					; MF207
;	WD. 12 -- UNIT NUMBER OF TASK TI:, FLAGS BYTE			; MF207
;	WD. 13 -- ASCII DEVICE NAME FOR TI:				; MF207
;	WD. 14 -- FIRST HALF OF RAD50 NAME OF TASK TO BE STARTED (CLIS O; MF207
;	WD. 15 -- SECOND HALF OF NAME OF TASK TO BE STARTED (CLI TASKS O; MF207
;									; MF207
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TARGET TASK.
;	R1=ADDRESS OF THE       TASK STATUS WORD OF THE TARGET TASK.
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE PARTITION NAME WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF AN ALLOCATION
;			FAILURE OCCURS       ON A PARTITION CONTROL BLOCK,
;			OFFSPRING CONTROL BLOCK, OR A COMMAND LINE BUFFER.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF AN ATTEMPT IS
;			MADE TO ISSUE A SPAWN TO A COMMAND LINE INTER-
;			PRETER WITHOUT SPECIFYING A COMMAND LINE.
;		DIRECTIVE STATUS OF 'D.RS7' IS RETURNED IF THE SPECIFIED
;			TASK IS ALREADY ACTIVE (WITH EXCEPTION OF A
;			SPAWN TO A COMMAND LINE INTERPRETER).
;		DIRECTIVE STATUS OF 'D.RS92' IS RETURNED IF AN INVALID
;			TERMINAL UNIT IS SPECIFIED FOR TI:.
;		DIRECTIV      E STATUS OF 'D.RS97' IS RETURNED IF AN INVALID
;			EVENT FLAG NUMBER IS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS98' IS RETURNED IF THE EXIT
;			STATUS BLOCK OR THE COMMAND LINE IS NOT ENTIRELY
;			IN THE TASK'S ADDRESSING SPACE.
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF AN ILLEGAL
;			DPB SIZE IS SPECIFIED (NOT 7., 13., 14., OR 16.); MF207
;									; MF207
; THE ABOVE ERRORS ALSO APPLY TO THE RPOI$ DIRECTIVE, EXCEPT FOR 'D.RS97; MF207
; WHICH IT CANNOT RETURN. THE RPOI$ DIRECTIVE CAN ALSO RETU      RN THE FOLLOW; MF207
; ERRORS:								; MF207
;									; MF207
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF A PARAMETER	; MF207
;			RESERVED FOR A CLI ONLY IS USED BY A NON-CLI TAS; MF207
;			OR AN ATTEMPT IS MADE TO PASS ALL OCBS TO A CLI.; MF207
;		DIRECTIVE STATUS OF 'D.RS86' IS RETURNED IF THERE IS	; MF207
;			NO OCB FROM THE SPECIFIED PARENT		; MF207
;		DIRECTIVE STATUS OF 'D.RS84' IS RETURNED IF A CLI TASK	; MF207
;			SPECIFIED BOTH A PARENT NAME AND OCB ADDRESS, AN; MF207
;			THE TWO DO N      OT IDENTIFY THE SAME OCB, OR EITHER	; MF207
;			FIELD IS SUPPLIED WITH THE FLAG TO PASS ALL OCBS; MF207
;		DIRECTIVE STATUS OF 'D.RS94' IS RETURNED IF AN ATTEMPT I; MF207
;			MADE TO CREATE A NEW TCB, BUT IT CANNOT GO THE	; MF207
;			PARTITION THE PROTOTYPE TCB IS INSTALLED IN	; MF207
;-									;**-1

	.ENABL	LSB
$DRREQ::								; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	MOV	SP,$TEMP4	;SAVE CURRENT STACK TO EASE UNWIND	; MF207
									; MF207
	.ENDC								; MF20      7
									; MF207
									; MF207
	CALL	ERRSV		;INITIALIZE ERROR RECOVERY		; MF207
	.WORD	NULL		;NO IMMEDIATE ACTION			;**-1
	.WORD	NULL		;NO RECOVERY ACTION
	ADD	#6,R3		;POINT TO UIC WORD IN DPB
	MOV	(R3)+,R4	;PICK UP SPECIFIED UIC FOR REQUEST
	CMPB	$DICSV+1,#7.	;IS THIS A SIMPLE REQUEST?		;**-1
	BNE	5$		;IF NE NO
	MOV	T.UCB(R5),R5	;GET UCB ADDRESS OF TASK'S TI:		; MF207
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	CLR	$TEMP4		;NOT AN RPOI$ OR SDRP$			;       MF207
									; MF207
	.ENDC								; MF207
									; MF207
									; MF207
	JMP	RQST		;DO REQUEST PROCESSING
5$:				;REFERENCE LABEL			; MF207
	CMPB	$DICSV+1,#13.	;IS IT A VALID SPAWN REQUEST?		;**-2
	BEQ	CNRQT		;IF EQ YES
	CMPB	$DICSV+1,#14.	;IS IT A SPAWN REQUEST WITH TI SPECIFIED
	BEQ	CNRQT		;IF EQ YES
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	CMPB	$DICSV+1,#16.	;IS IT A RPOI$ DIRECTIVE		; MF207
	BNE	10$		;IF NE NO				; MF207
	MOVB	13(R3),R2	;GE      T FLAGS BYTE, FORCE TASK EXIT??	; MF207
	BMI	7$		;IF MI YES				; MF207
	MOV	#1,$TEMP4	;NO EXIT, BUT REMEMBER IT IS AN RPOI$	; MF207
7$:	CALL	LOCOCB		;LOCATE THE OCB(S) TO BE PASSED		; MF207
	ADD	#6,R3		;POINT TO CMD BUFFER IN DPB		; MF207
	BR	35$		;JOIN COMMON CODE			; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207
									; MF207
DPBER:				;REF LABEL				; MF207
10$:	MOV	(PC)+,R5	;SET ILLEGAL DPB SIZE			; MF207
	DRSTS	D.RS99		;					; MF207
	JMP	ERROR		;ILLEGAL DPB SIZE ER      ROR			; MF207
									;**-1
;
; CONNECT PROCESSING (CNCT,SDRC,SPWN).					;MSH104
;									;**-1
; COMMON CONNECT AND REQUEST PROCESSING BEGINS HERE FOR REQUEST/SPAWN,	;MSH104
; CONNECT, AND SEND REQUEST AND CONNECT DIRECTIVES. THE FOLLOWING	;MSH104
; SECTION PERFORMS THE CONNECT PROCESSING.  AN OFFSPRING CONTROL BLOCK	;**-2
; IS ALLOCATED AND QUEUED TO THE OFFSPRING TASK'S OCB QUEUE.  THEN THE
; EVENT FLAG AND EXIT STATUS BLOCK PARAMETERS ARE CHECKED AS THE OFF-
; SPRING CONTROL BLOCK IS INITIAL      IZED.  IF AN OCB IS SUCCESSFULLY
; ALLOCATED, ITS ADDRESS IS STORED IN $TEMP1 AS A FLAG THAT IT MUST BE
; QUEUED TO THE TARGET TASK ON SUCCESSFUL EXIT.
;
; REGISTER CONTENTS AT THIS POINT:
;
;	R0=ADDRESS OF THE TCB OF THE OFFSPRING TASK
;	R3=PTR TO THE EVENT FLAG NUMBER IN THE DPB.
;

CNRQT:	MOV	#O.LGTH,R1	;PICK UP OCB SIZE
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	CLR	$TEMP4		;NOT AN RPOI$ OR SDRP$			; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF2      07
	CALL	@(SP)+		;ALLOCATE OCB WITH TRAIL TO DEALLOCATE
	.WORD	$ALOCB		;ALLOCATION ROUTINE ADDRESS
	.WORD	$DEACB		;DEALLOCATION ROUTINE ADDRESS
	BCC	20$		;IF CC ALLOCATION SUCCESSFUL
	JMP	ALLER		;ELSE REPORT ALLOCATION FAILURE
20$:	MOV	R0,$TEMP1	;STORE OCB ADDRESS FOR CONNECT
	MOV	(PC)+,R5	;ASSUME INVALID EVENT FLAG NUMBER
	DRSTS	D.RS97		;
	MOV	R0,R4		;COPY OCB POINTER
	MOVB	(R3)+,R0	;PICK UP SPECIFIED EVENT FLAG		;MSH129
									;**-1
	.IF DF G$$EFN

	CMP	R0,#96.		;VALID EVENT FLAG NUMBER?
      
	.IFF	;G$$EFN

	CMP	R0,#64.		;VALID EVENT FLAG NUMBER?

	.IFTF	;G$$EFN

	BHI	10$		;IF HI NO

	.IFT	;G$$EFN

	CMP	R0,#64.		;IS IT A GROUP GLOBAL EVENT FLAG?
	BLOS	25$		;IF LOS NO
	MOV	R4,-(SP)	;SAVE OCB POINTER			;MSH049
	MOV	$HEADR,R4	;GET ADDRESS OF CURRENT TASK'S HEADER	;**-1
	MOVB	H.CUIC+1(R4),R4	;GET CUURRENT TASK'S GROUP NUMBER
	MOV	R0,-(SP)	;SAVE EVENT FLAG NUMBER			;MSH049
	CALL	$SRGEF		;SEARCH FOR GROUP GLOBAL EVENT FLAGS
	MOV	(SP)+,R0	;RESTORE EVENT FLAG NUMBER		;MSH049
	MOV	(SP      )+,R4	;RESTORE OCB POINTER			;MSH049
	BCS	10$		;IF CS, INVALID EVENT FLAG SPECIFIED
25$:				;REFERENCE LABEL			;**-1

	.ENDC	;G$$EFN

	MOV	$TKTCB,R5	;PICK UP CURRENT TASK TCB ADDRESS
	MOV	R0,-(SP)	;SAVE EVENT FLAG NUMBER
	CALL	$CEFIG		;CONVERT EVENT FLAG TO MASK AND ADDRESS	;MSH049
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
	BIC	#1,R1		;CLR GRP GLOBAL 2ND WORD INDICATOR	;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
	BIC	R0,(R1)		;CLEAR EVENT FLAG			;**-1      
	TST	(R4)+		;SKIP OVER OCB LINK WORD (O.LNK)
	CLR	(R4)+		;INITIALLY CLR MCR LINE PTR (O.MCRL)
	MOV	R5,(R4)+	;SET PARENT TCB ADDRESS (O.PTCB)
									;MSH129
;									;MSH129
; THE EXIT STATUS BLOCK COMES IN TWO LENGTHS. THE DEFAULT LENGTH	;MSH129
; AS SET UP BY THE PARENT/OFFSPRING DIRECTIVE MACROS IS 1. WORD.	;MSH129
; THIS IS INDICATED BY HAVING A ZERO VALUE IN THE EXIT STATUS		;MSH129
; BLOCK LENGTH FIELD IN THE DPB. THE OTHER POSSIBLE LENGTH OF THE	;MSH129
; EXIT STATUS BLOCK IS 8. WORDS. T      HIS IS INDICATED BY A NON-ZERO	;MSH129
; IN THE EXIT STATUS BLOCK LENGTH FIELD.				;MSH129
;									;MSH129
									;MSH129
	CLR	R2		;ASSUME 1-WORD EXIT STATUS BLOCK	;MSH129
									;MSH129
	.IF DF	A$$CHK!M$$MGE						;MSH129
									;MSH129
	MOV	#2,R1		;SET APPROPRIATE LENGTH TO ADDRESS CHECK;MSH129
									;MSH129
	.IFTF								;MSH129
									;MSH129
	TSTB	(R3)+		;FULL LENGTH EXIT STATUS BLOCK?		;MSH129
	BEQ	27$		;IF EQ NO				;MSH129
	INC	R2		;MARK AS FULL LENGTH EXIT STATUS BLOCK	;MSH      129
									;MSH129
	.IFT								;MSH129
									;MSH129
	MOV	#16.,R1		;CORRECT ADDRESS CHECK LENGTH		;MSH129
									;MSH129
	.ENDC	;A$$CHK!M$$MGE						;MSH129
									;MSH129
27$:	MOV	(R3)+,(R4)+	;SET AST ADDRESS (O.AST)		;MSH129
	MOV	(SP)+,(R4)+	;SET EVENT FLAG NUMBER (O.EFN)		;**-1
	MOV	(R3)+,R0	;PICK UP EXIT STATUS BLOCK ADDRESS
	MOV	R0,(R4)		;STORE IT IN OCB (O.ESB)		;MSH129
	BIS	R2,(R4)+	;SET LENGTH OF EXIT STATUS BLOCK	;MSH129
	MOV	T.NAM(R5),(R4)+	;STORE PARENT TASK NAME (O.STAT)	;*      *-1
	MOV	T.NAM+2(R5),(R4)+ ;(O.STAT+2)				;MSH117
									;MSH117
	.IF DF	M$$CRX							;MSH117
									;MSH117
	CLR	(R4)+		;INITIALIZE PROTECTION UIC (O.STAT+4)	;MSH117
									;MSH117
	.IF DF	M$$MUP							;MSH117
									;MSH117
	CLR	(R4)		;INITIALIZE DEFAULT UIC (O.STAT+6)	;MSH117
									;MSH117
	.ENDC	;M$$MUP							;MSH117
									;MSH117
	.ENDC	;M$$CRX							;MSH117
									;**-1
	.IF DF A$$CHK!M$$MGE

	TST	R0		;EXIT STATUS BLOCK SPECIFIED?
	BEQ	30$		;IF EQ NO, BYPASS ADDRESS C      HECK
	CALL	$ACHCK		;ADDRESS CHECK EXIT STATUS BLOCK	;**-1
	BCC	30$		;IF CS ADDRESS CHECK OK
	JMP	ADCER		;ADDRESS CHECK FAILURE

	.ENDC	;A$$CHK!M$$MGE

30$:	CMPB	$DICSV,#141.	;IS DIRECTIVE A SEND, REQUEST & CONNECT?;MSH104
	BEQ	80$		;IF EQ YES, BRANCH TO REQUEST TASK	;MSH104
	BLO	35$		;IF LO IT IS SPAWN			;**-1
	JMP	SUCCESS		;IF HI IT IS CONNECT, RETURN SUCCESS	;MSH104
35$:									;**-1

;
; TI: DETERMINATION AND COMMAND LINE PROCESSING (SPWN).
;
; HERE THE TARGET TASK'S TI: IS DETERMINED FO      R THE SUBSEQUENT REQUEST
; AND COMMAND LINE PROCESSING IS INITIATED.  IF A TERMINAL UNIT
; HAS BEEN SPECIFIED, THEN IT IS VERIFIED AND ITS UCB IS FOUND.
; OTHERWISE THE ISSUING TASK'S UCB IS PROPAGATED.
;
; REGISTER CONTENTS AT THIS POINT:
;
;	R3=PTR TO COMMAND LINE BUFFER ADDRESS IN THE DPB.
;


	MOV	R5,R2		;COPY ISSUING TASK'S TCB ADDRESS	;MSH131
	MOV	T.UCB(R5),R5	;GET ISSUING TASK'S TI: UCB		;MSH131
	CMPB	$DICSV+1,#14.	;WAS TI: SPECIFIED?
	BLT	75$		;IF LT NO				; MF207
	TST	6(R3)		;DEVICE       NAME SPECIFIED?			;**-1
	BEQ	75$		;IF EQ NO				;MSH131
	MOV	R3,R1		;SAVE POINTER TO CMD LINE BUF ADD IN DPB;**-16
	CMP	(R1)+,(R1)+	;POINT TO DEV AND UNIT IN DPB		; MF209
	CALL	$GTUCB		;GET UCB ADDRESS OF DEVICE		; MF209
	BCS	ILUER		;IF CS, DEVICE DOES NOT EXIST		; MF209
	BIT	#DV.TTY,U.CW1(R5) ;IS DEVICE A TERMINAL			; MF209
	BEQ	ILUER		;IF EQ NO				; MF209
	MOV	R1,R3		;COPY POINTER				; MF209
	CMP	-(R3),-(R3)	;POINT TO COMMAND BUFFER IN DPB AGAIN	; MF209
	BIT	#T3.PRV!T3.CLI,T.ST3(R2) ;TASK ALLOWED       TO SPECIFY OTHER ; MF203
	BNE	75$		;IF NE YES				;MSH131
	CMP	T.UCB(R2),R5	;SAME TI: SPECIFIED?			;MSH131
	BNE	PRVER		;IF NE NO, NOT ALLOWED BY NONPRIV TASK	;MSH131
75$:				;					;MSH131
									;MSH131
	.IF DF	M$$CRX							;MSH131
									;MSH131
	JMP	CMLPR		;PERFORM COMMAND LINE PROCESSING	;MSH131
									;MSH131
	.IFF								;MSH131
									;MSH131
	MOV	-10(R3),R4	;PICK UP SPECIFIED UIC FOR REQUEST	;MSH131
	BR	RQST		;REQUEST OFFSPRING TASK			;MSH131
									;MSH131
	.ENDC	;M$$CRX				      			;MSH131
									;**-19
;
; COMMON REQUEST PROCESSING (RQST, SPWN).
;
; HERE THE COMMON REQUEST PROCESSING IS PERFORMED FOR REQUEST AND
; SPAWN.  DEFAULT AND PROTECTION UIC DETERMINATION IS
; PERFORMED AND THE TASK IS REQUESTED VIA $TSKRP.  A TASK REQUEST
; FAILURE IS JUDGED IN LIGHT OF THE DIRECTIVE BEING PERFORMED.
;
; REGISTER CONTENTS AT RQST:
;
;	R4=REQUEST UIC
;	R5=TARGET TASK UCB ADDRESS
;

RQST2:				;REFERENCE LABEL FOR SDRP$		; MF207
80$:	CLR	R4		;SET TO PROPAGATE ISSUING TASK'S       UIC
	MOV	T.UCB(R5),R5	;SET TI: UCB ADDRESS

RQST:	MOV	$TEMP0,R0	;RESTORE POINTER TO TARGET TCB
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	BIC	#1,R0		;CLEAR TCB COPIED INDICATOR		; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207

110$:	MOV	$MCRCB,R2	;PICK UP FIRST ENTRY IN GMCR QUEUE
	BEQ	120$		;IF EQ THERE IS NONE
	TST	(R2)+		;POINT TO TCB ADDRESS
	TST	(R2)		;QUEUED IN THIS DIRECTIVE?
	BNE	120$		;IF NE NO
	MOV	R0,(R2)		;SET TCB AD      DRESS IN COMMAND LINE
120$:	MOV	R4,R1		;COPY SPECIFIED UIC ADDRESS
	CALL	UISET		;CALCULATE DEFAULT AND PROTECTION UICS	;MSH117
	MOV	R5,R2		;PICK UP TARGET UCB ADDRESS		;**-12
	MOV	R0,R5		;SAVE ADDRESS OF TARGET TASK TCB
	CALL	$TSKRP		;REQUEST THE TASK
	BCC	RQSUC		;IF CC SUCCESS
	BNE	ALER1		;IF NE ALLOCATION FAILURE
	CMPB	$DICSV,#141.	;IS IT LEGAL FOR TASK TO BE ACTIVE?	;MSH104
	BEQ	SUCCES		;IF EQ YES				;MSH104
	MOV	(PC)+,R5	;PICK UP TASK ALREADY ACTIVE STATUS
	DRSTS	D.RS7		;
	BR	ERROR		;RETURN       ERROR STATUS
	.DSABL	LSB

;
; LOCAL ERROR RETURN ROUTINES.
;
; THE FOLLOWING ROUTINES INTERFACE TO $DRTHR AND $ERREC FOR DIRECTIVE
; ERROR STATUS RETURNS AND ERROR RECOVERY.  R5 IS USED TO STORE THE
; ERROR STATUS TRAP INSTRUCTION.
;

ALLER:	ADD	#6,SP		;POP THREAD TO DEALLOCATE ROUTINE	;**-4
ALER1:	MOV	(PC)+,R5	;PICK UP ALLOCATION FAILURE STATUS
	DRSTS	D.RS1		;
ERROR:	JMP	$ERREC		;THREAD THROUGH ERROR RECOVERY
CMLER:	MOV	(PC)+,R5	;PICK UP COMMAND LINE ERROR STATUS
	DRSTS	D.RS2		;
	BR	ERROR	      	;RETURN ERROR STATUS
ILUER:	MOV	(PC)+,R5	;PICK UP ILLEGAL DEVICE UNIT ERROR
	DRSTS	D.RS92		;
	BR	ERROR		;RETURN ERROR STATUS
PRVER:	MOV	(PC)+,R5	;PICK PRIVILEGE VIOLATION ERROR
	DRSTS	D.RS16		;
	BR	ERROR		;RETURN ERROR STATUS
RQSUC:
SUCCES:	MOV	$TEMP1,R1	;IS THERE AN OCB TO QUEUE?
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	.IFF	;R$$POI							; MF207
									; MF207
	BEQ	30$		;IF EQ NO				; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									;       MF207
	MOV	$TEMP0,R4	;GET ADDRESS OF TARGET TASK		; MF207
	BIT	#1,R4		;WAS TARGET TCB CREATED IN THIS DIRECTIV; MF207
	BEQ	5$		;IF EQ NO				; MF207
	DEC	R4		;GET RID OF INDICATOR BIT		; MF207
	BIS	#T3.REM,T.ST3(R4) ;SET TO REMOVE ON EXIT		; MF207
5$:	MOV	R4,R2		;COPY ADDRESS				; MF207
	ADD	#T.OCBH,R4	;POINT TO ITS OCB LISTHEAD		; MF207
	TST	$TEMP4		;IS IT AN RPOI$ OR SDRP$		; MF207
	BEQ	10$		;IF EQ NO				; MF207
	MOV	$TKTCB,R0	;POINT TO CURRENT TASKS TCB		; MF207
	ADD	#T.OCBH,R0	;ACTUALLY TO IT      S OCB LISTHEAD		; MF207
	CMP	#1,R1		;PASS ALL OCBS				; MF207
	BEQ	40$		;IF EQ YES				; MF207
									; MF207
									; MF207
	.IF DF	A$$CLI							; MF207
									; MF207
	BIT	#T3.CLI,T.ST3-T.OCBH(R4) ;IS OBJECT TASK A CLI		; MF207
	BNE	505$		;IF NE YES				; MF207
	BIT	#T3.CLI,T.ST3-T.OCBH(R0) ;IS CURRENT TASK A CLI		; MF207
	BEQ	6$		;IF EQ NO				; MF207
505$:	CALL	PSPRMT		;PASS PROMPT CONTROL			; MF207
6$:	TST	R1		;IS THERE AN OCB TO PASS		; MF207
	BEQ	60$		;IF EQ NO				; MF207
									;       MF207
	.IFF	;A$$CLI							; MF207
									; MF207
	BHI	60$		;IF HI, NO OCB TO PASS			; MF207
									; MF207
	.ENDC								; MF207
									; MF207
									; MF207
	CALL	$QRMVT		;REMOVE THE OCB, THERE MUST BE ONE	; MF207
	BR	20$		;DO NOT TOUCH PARENT'S RUNDOWN COUNT	; MF207
10$:	TST	R1		;IS THERE AN OCB TO PASS		; MF207
	BEQ	70$		;IF EQ NO				; MF207
									; MF207
	.IFTF	;R$$POI							; MF207
									; MF207
	MOV	O.PTCB(R1),R2	;PICK UP PARENT TCB ADDRESS		; MF207
	INC	T.RDCT(R2)	;INCR      EMENT PARENT'S RUNDOWN COUNT	; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									; MF207
20$:	MOV	R4,R0		;GET OFFSPRING ADDRESS			; MF207
									; MF207
	.IFF	;R$$POI							; MF207
									; MF207
	MOV	$TEMP0,R0	;PICK UP TARGET TCB ADDRESS		; MF207
	ADD	#T.OCBH,R0	;POINT TO OCB LISTHEAD			; MF207
									; MF207
	.IFTF	;R$$POI							; MF207
									; MF207
	CALL	$QINSF		;INSERT OCB IN ITS QUEUE		; MF207
									; MF207
	.IFF	;R$$POI							; MF207
									; MF207
30$:	DRSTS	      +1		;ALL DONE				; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									; MF207
	BR	60$		;					; MF207
40$:	CALL	PSPRMT		;PASS PROMPT CONTROL			; MF207
	MOV	(R0),R1		;GET ADDRESS OF FIRST OCB		; MF207
	BEQ	60$		;THERE MAY NOT BE ANY			; MF207
	CLR	(R0)		;FORCE THE LIST TO EMPTY		; MF207
	MOV	R0,2(R0)	;SET SECOND HALF OF LISTHEAD		; MF207
	MOV	R1,@2(R4)	;LINK IT AFTER PREVIOUS LAST OCB	; MF207
50$:	MOV	R1,2(R4)	;SET NEW POINTER TO LAST ENTRY		; MF207
	MOV	(R1),R1		;POINT TO NEXT OCB IN QUE      UE		; MF207
	BNE	50$		;IF NE, THERE IS ANOTHER ONE		; MF207
60$:	CMP	#1,$TEMP4	;FORCE CURRENT TASK TO EXIT		; MF207
	BHIS	70$		;IF HIS NO				; MF207
	MOV	$TEMP4,SP	;RELOAD STACK TO RETURN TO DRDSP	; MF207
	MOV	$TKTCB,R5	;POINT TO CURRENT TASK TCB		; MF207
	CALLR	$DREXT		;FORCE CURRENT TASK TO EXIT		; MF207
70$:	DRSTS	+1		;ALL DONE				; MF207
;									; MF207
									; MF207
	.IF DF	A$$CLI&I$$RAR&D$$YNM&C$$CKP&D$$YNC			; MF207
									; MF207
PARERR:	MOV	(PC)+,R5	;COPIED TCB CANNOT GO IN THIS       PARTITION	; MF207
	DRSTS	D.RS94		;					; MF207
	BR	ERROR		;RETURN ERROR STATUS			; MF207
									; MF207
									; MF207
	.ENDC	;A$$CLI&I$$RAR&D$$YNM&C$$CKP&D$$YNC			; MF207
									; MF207
	.IFTF	;R$$POI							; MF207
									; MF207
ADCPOP:	TST	(SP)+		;CLEAN STACK BEFORE RETURNING ERROR	; MF207
ADCER:	MOV	(PC)+,R5	;PICK UP ADDRESS CHECK ERROR STATUS	; MF207
	DRSTS	D.RS98		;					; MF207
	BR	ERROR		;RETURN ERROR STATUS			; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									; MF20      7
ILPARM:	MOV	(PC)+,R5	;PICK UP PARAMETER ILLEGAL FOR THIS TASK; MF207
	DRSTS	D.RS8		;					; MF207
	BR	ERROR		;RETURN ERROR STATUS			; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207
									; MF207
									;**-7
;
; COMMAND LINE PROCESSING (SPWN).
;
; THIS SECTION PERFORMS THE COMMAND LINE PROCESSING FOR THE SPWN$ AND RP; MF207
; DIRECTIVE.  FIRST A STANDARD SIZE COMMAND LINE BUFFER IS ALLOCATED	;**-1
; AND THEN ADDRESS CHECKING OF THE USER SPECIFIED COMMAND LINE IS
;       PERFORMED.  THE COMMAND LINE IS THEN TRANSFERRED TO THE ALLOCATED
; BUFFER AND TERMINATED WITH AN ESCAPE CHARACTER.  IF THE TARGET TASK
; IS NOT A COMMAND LINE INTERPRETER, THEN THE COMMAND LINE IS QUEUED	;MSH103
; FOR THE TASK TO $MCRCB, MAKING IT AVAILABLE VIA THE GET MCR COMMAND	;**-1
; LINE DIRECTIVE.  IF THE TARGET TASK IS A COMMAND LINE INTERPRETER,	;MSH103
; ON A SYSTEM WITHOUT A$$CLI, OR THE DISPATCHER ON A SYSTEM WITH A$$CLI	; MF203
; THEN THE COMMAND LINE IS QUEUED TO THE CLI'S RECEIVE QUEUE       AND $EXRQN	;MSH103
; IS CALLED TO INSURE THE CLI IS ACTIVE AND NOT STOPPED (VIA THE ROUTINE;MSH103
; $QCLIL).  SPAWN PROCESSING FOR A CLI IS COMPLETE AT THIS POINT.	;MSH103
; IF THE SYSTEM SUPPORTS A$$CLI AND THE CLI IS NOT THE DISPATCHER (MCR..; MF203
; THE SIZE OF THE COMMAND BUFFER IS NOT STANDARD. IT IS LONG ENOUGH TO	; MF203
; CONTAIN THE COMMAND AND 5 HEADER WORDS. THESE WORDS ARE A LINK WORD,	; MF203
; CLI'S TCB ADDRESS, ISSUING TERMINAL'S UCB ADDRESS, THE SIZE OF	; MF203
; THE BUFFER, THE TE      RMINATOR CHARACTER, AND A STATUS BYTE.		; MF203
; THE BUFFER IS LINKED INTO THE $CLICQ LIST AND THE CLI			; MF203
; STARTED BY THE $QCLIL ROUTINE.					; MF203
;									;**-4
; THIS SECTION LOGICALLY FALLS IN LINE AFTER THE TI: DETERMINATION ABOVE
; BUT HAS BEEN PLACED HERE FOR CONVENIENCE TO MAKE ALL BRANCHES REACH.
;
; REGISTER CONTENTS AT THIS POINT:
;
;	R3=PTR TO COMMAND LINE ADDRESS IN THE DPB.
;	R5=TARGET TASK UCB ADDRESS.
;

	.IF DF M$$CRX

	.IF DF	A$$CLI							; MF203
									; MF20      3
BRALER:	BR	ALLER		;BR TO ALLOCATION FAILURE		; MF203
									; MF203
	.IFTF	;A$$CLI							; MF203
									; MF203
CMLPR:	MOV	(R3),R1		;COMMAND LINE SPECIFIED?
	BEQ	10$		;IF EQ NO
	CMP	2(R3),#79.	;COMMAND LINE TOO LONG			; MF203
	BHI	ADCER		;IF HI YES				; MF203
	MOV	#M$$CRB,R1	;ASSUME STANDARD LENGTH			; MF203
									; MF203
	.IFT	;A$$CLI							; MF203
									; MF203
	MOV	$TEMP0,R0	;POINT TO OBJECT TASK			; MF203
	CLR	$TEMP2		;ASSUME COMMAND GOING TO NON-CLI	; MF203
	CMP	$MCRPT,R0	;IS       IT THE DISPATCHER			; MF203
	BEQ	2$		;IF EQ YES				; MF203
	BIT	#T3.CLI,T.ST3(R0) ;IS TARGET TASK A CLI			; MF203
	BEQ	2$		;IF EQ NO				; MF203
	MOV	2(R3),R1	;GET NUMBER OF CHARACTERS IN COMMAND	; MF203
	ADD	#12+1,R1	;ALLOW FOR LONGER HEADER + TERMINATOR	; MF203
	MOVB	#6,$TEMP2	;SKIP OVER LINK, TCB AND UCB ADDRESSES	; MF203
	MOVB	R1,$TEMP2+1	;SAVE SIZE OF COMMAND BUFFER		; MF203
2$:				;REFERENCE LABEL			; MF203
									; MF203
	.IFTF	;A$$CLI							; MF203
									; MF203
	CALL	@(SP)+		;ALLOC      ATE BUF WITH TRAIL TO DEALLOCATE	;**-1
	.WORD	$ALOCB		;ALLOCATION ROUTINE ADDRESS
	.WORD	$DEACB		;DEALLOCATION ROUTINE ADDRESS
3$:									; MF207
	.IFF	;A$$CLI							; MF207
									; MF207
	BCS	ALLER		;IF CS, ALLOCATION FAILURE		; MF207
									; MF207
	.IFT	;A$$CLI							; MF207
									; MF207
	BCS	BRALER		;IF CS, BR TO ALLOCATION FAILURE	; MF207
	MOVB	$TEMP2,R4	;GET OFFSET TO PACKET SIZE IN BUFFER	; MF203
	ADD	R0,R4		;POINT TO UCB ADDR IN BUFFER		; MF203
									; MF203
	.IFF								;       MF203
									; MF203
	MOV	R0,R4		;SAVE ADDRESS OF ALLOCATED BUFFER	; MF203
									; MF203
	.ENDC	;A$$CLI							; MF203
									; MF203
									; MF203
	TST	(R4)+		;SKIP OVER LINK WORD			;**-2
	CLR	(R4)+		;CLEAR TCB ADDRESS
	MOV	2(R3),R1	;PICK UP SIZE OF COMMAND LINE
	BEQ	6$		;IF EQ, DON'T BOTHER MOVING IT
	MOV	(R3),R0		;PICK UP ADDRESS			;**-2

	.IF DF A$$CHK!M$$MGE

	MOV	R1,-(SP)	;SAVE BUFFER LENGTH
	CALL	$ACHKB		;ADDRESS CHECK COMMAND LINE BUFFER
	BCS	ADCPOP		;IF CS ADDRESS CHECK F      AILURE

	.ENDC	;A$$CHK!M$$MGE

	.IF DF M$$MGE

	CALL	$RELOC		;RELOCATE USER ADDRESS
	SUB	#20000,R2	;CONVERT SOURCE TO KISAR5 DISPLACEMENT
	MOV	(SP)+,R0	;RESTORE COUNT FOR $BLXIO
	CALL	$BLXIO		;COPY USER'S COMMAND LINE

	.IFF	;M$$MGE

	.IF DF A$$CHK

	MOV	(SP)+,R1	;PICK UP SIZE OF COMMAND LINE

	.ENDC	;A$$CHK

4$:	MOVB	(R0)+,(R4)+	;MOVE IT
	DEC	R1		;MORE TO MOVE?
	BGT	4$		;IF GT, YES

	.ENDC	;M$$MGE

6$:	MOVB	#33,(R4)	;TERMINATE LINE WITH ESCAPE
	MOV	2(SP),R1	;RETRIEVE SAVED BUFFER       ADDRESS
10$:	MOV	$TEMP0,R0	;PICK UP TARGET TASK TCB ADDRESS
	BIT	#T3.CLI,T.ST3(R0) ;TARGET TASK A CLI?
	BNE	20$		;IF NE, YES
									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
	CLR	$TEMP2		;ASSUME NO COMMAND LINE			; MF207
									; MF207
	.IFTF	;R$$POI							; MF207
									; MF207
	TST	R1		;COMMAND LINE SPECIFIED?
	BEQ	11$		;IF EQ NO				; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									; MF207
	MOV	R4,$TEMP2	;SAVE ADDRESS OF TERMINATOR IN BUFFER	      ; MF207
									; MF207
	.IFTF	;R$$POI							; MF207
									; MF207
	MOV	#$MCRCB,R0	;POINT TO GET MCR LINE LISTHEAD		;**-1
	CALL	@(SP)+		;QUEUE THE COMMAND WITH TRAIL TO DEQUEUE
	.WORD	QMCRB		;ROUTINE TO QUEUE THE COMMAND LINE
	.WORD	DMCRB		;ROUTINE TO DEQUEUE THE LINE
11$:									; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									; MF207
	MOV	$TEMP4,R4	;IS THIS AN RPOI$ DIRECTIVE		; MF207
	BEQ	15$		;IF EQ NO				; MF207
									; MF207
	.IF DF	I$$RAR&D$$YNM&C$$CKP&D$$YNC&A$$CL      I			; MF207
									; MF207
	ADD	#10,R3		;POINT TO NAME FOR NEW TASK		; MF207
	MOV	$TKTCB,R2	;GET CURRENT TASK'S TCB ADDR		; MF207
	BIT	#T3.CLI,T.ST3(R2) ;IS CURRENT TASK A CLI		; MF207
	BEQ	13$		;IF EQ NO				; MF207
	MOV	$TEMP0,R0	;GET OFFSPRING TCB ADDR			; MF207
	CMP	#^R...,T.NAM(R0) ;IS IT THE MU TYPE			; MF207
	BNE	13$		;IF NE NO				; MF207
	TST	(R3)		;IS A NEW NAME PRESENT			; MF207
	BEQ	14$		;IF NE NO, GO WITH EXISTING TCB		; MF207
	CALL	$SRSTD		;DOES TASK ALREADY EXIST		; MF207
	BCS	12$      		;IF CS, TASK DOES NOT EXIST		; MF207
	CMP	R0,R2		;DID WE FIND OURSELF			; MF207
	BNE	115$		;IF NE NO				; MF207
	CMP	#1,R4		;WILL CURRENT TASK EXIT			; MF207
	BNE	12$		;IF NE YES				; MF207
115$:	MOV	R0,$TEMP0	;USE IT					; MF207
	BR	14$		;					; MF207
12$:	MOV	#T.LGTH,R1	;GET LENGTH OF A TCB			; MF207
	CALL	@(SP)+		;ALLOCATE A TCB				; MF207
	.WORD	$ALOCB		;ALLOCATION ROUTINE			; MF207
	.WORD	$DEACB		;DEALLOCATION ROUTINE			; MF207
	BCS	3$		;ALLOCATION FAILURE			; MF207
	MOV	$TEMP0,R1	;POINT       TO TCB TO BE COPIED		; MF207
	CALL	@(SP)+		;PUSH UNLINK ROUTINE FOR FUTURE ERRORS	; MF207
	.WORD	NULL		;NOTHING TO DO NOW			; MF207
	.WORD	UNLTCB		;UNLINK TCB				; MF207
	CALL	CPYTCB		;COPY TCB AND LINK IT INTO THE STD	; MF207
	BCC	125$		;IF CC OK				; MF207
	JMP	PARERR		;IF CS NEW TASK CANNOT GO IN PARTITION	; MF207
125$:	INC	R0		;INDICATE TCB CREATED BY THIS DIRECTIVE	; MF207
	MOV	R0,$TEMP0	;USE NEW TCB				; MF207
	BR	14$		;					; MF207
13$:	TST	(R3)		;WAS A NEW NAME SUPPLIED		; MF207
	BEQ	14$	      	;IF EQ NO				; MF207
	JMP	ILPARM		;ILLEGAL PARAMETER SPECIFIED		; MF207
14$:	SUB	#10,R3		;POINT TO COMMAND BUFFER ADDR IN DPB	; MF207
									; MF207
	.IFF	;I$$RAR&D$$YNM&C$$CKP&D$$YNC&A$$CLI			; MF207
									; MF207
	TST	10(R3)		;WAS A NEW TASK NAME SPECIFIED		; MF207
	BNE	ILPARM		;ILLEGAL PARAMETER SPECIFIED		; MF207
									; MF207
	.ENDC	;I$$RAR&D$$YNM&C$$CKP&D$$YNC&A$$CLI			; MF207
									; MF207
	.IFTF	;R$$POI							; MF207
									; MF207
									; MF207
15$:	MOV	-10(R3),R4	;PI      CK UP SPECIFIED UIC FOR REQUEST
	JMP	RQST		;JUMP TO REQUEST TASK
20$:	TST	R1		;IS THERE A COMMAND LINE?		; MF207
	BNE	21$		;IF NE YES (MUST BE FOR A CLI)		; MF207
	MOV	(PC)+,R5	;PICK UP COMMAND LINE ERROR STATUS	; MF207
	DRSTS	D.RS2		;					; MF207
	JMP	ERROR		;RETURN ERROR STATUS			; MF207
21$:	MOV	$TEMP1,R2	;PICK UP OCB ADDRESS			; MF207
	BEQ	22$		;IF EQ, NO OCB TO PASS			; MF207
	MOV	R1,O.MCRL(R2)	;STORE POINTER TO MCR COMMAND LINE	; MF207
22$:	MOV	R5,2(R1)	;STORE UCB ADDRESS IN COMMAND LINE BUF      	; MF207
									; MF207
	.IFT	;R$$POI							; MF207
									; MF207
	MOV	R4,(R1)		;STORE TERMINATOR ADDRESS IN BUFFER	; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207
									; MF207
	CALL	@(SP)+		;PUSH ROUTINE TO REMOVE LINE		;**-4
	.WORD	NULL		;NO IMMEDIATE ACTION
	.WORD	40$		;ROUTINE TO REMOVE LINE
	MOV	R1,-(SP)	;SAVE COMMAND LINE POINTER		;MSH117
	MOV	-10(R3),R1	;PICK UP SPECIFIED UIC FOR REQUEST	;MSH117
	BEQ	25$		;IF EQ NONE SPECIFIED			;MSH117
	MOV	R2,R5		;COPY       OCB POINTER			;MSH117
	BEQ	25$		;IF EQ, NO OCB TO PASS			; MF207
									;MSH153
	.IF DF	A$$CLI&M$$MUP						;MSH153
									;MSH153
	MOV	R3,-(SP)	;SAVE DPB POINTER			;MSH153
									;MSH153
	.ENDC								;MSH153
									;MSH153
	CALL	UISET		;CALCULATE DEFAULT AND PROTECTION UICS	;MSH117
	MOV	R1,O.STAT+4(R5)	;SAVE PROTECTION UIC FOR CLI TO PICK UP	;MSH117
									;MSH117
	.IF DF	M$$MUP							;MSH117
									;MSH117
	MOV	R3,O.STAT+6(R5)	;SAVE DEFAULT UIC FOR CLI TO PICK UP	;MSH117
						      			;MSH153
	.IF DF	A$$CLI							;MSH153
									;MSH153
	MOV	(SP)+,R3	;RESTORE DPB POINTER			;MSH153
									;MSH153
	.ENDC								;MSH153
									;MSH117
	.ENDC	;M$$MUP							;MSH117
									;MSH117
25$:	MOV	(SP)+,R1	;RETRIEVE COMMAND LINE POINTER		;MSH117
									; MF203
									; MF203
	.IF DF	A$$CLI							; MF203
									; MF203
	MOV	#$QCLIL,-(SP)	;ASSUME OBJECT TASK IS NOT DISPATCHER	; MF203
	CMP	$MCRPT,R0	;IS IT THE DISPATCHER?			; MF203
	BEQ	26$		;IF EQ YES				; MF203
	MOV	2(R      1),4(R1)	;PUT UCB ADDRESS IN PROPER PLACE	; MF203
	MOV	R0,2(R1)	;INSERT TCB ADDRESS IN BUFFER		; MF203
	MOVB	$TEMP2+1,6(R1)	;PUT NUMBER OF CHARS IN CMD IN BUFFER	; MF203
	CLRB	7(R1)		;CLEAR OUT GARBAGE IN HIGH BYTE		;MSH193
	MOV	#33,10(R1)	;ASSUME TERMINATOR IS ESC		; MF203
									; MF203
	.IF DF	R$$POI							; MF203
									; MF203
	MOV	R1,$TEMP2	;POINT TO LOCATION IN BUFFER FOR TERMINA; MF203
	ADD	#10,$TEMP2	;					; MF203
	MOVB	#15,@(R1)	;PUT A CR IN BUFFER FOR CONSISTANCY	; MF203
									;       MF203
	.IFTF	;R$$POI							; MF203
									; MF203
	BR	27$		;					; MF203
26$:									; MF203
									; MF203
	.IFT	;R$$POI							; MF203
									; MF203
	MOV	(R1),$TEMP2	;POINT TO LOCATION FOR TERMINATOR	; MF203
									; MF203
	.ENDC	;R$$POI							; MF203
									; MF203
									; MF203
	CMP	#^RCLI,-22(R3)	;DOES USER WANT TTY'S CURRENT CLI	; MF203
	BNE	27$		;IF NE NO, MCR IS DESIRED CLI		; MF203
	MOV	#$QMCRL,(SP)	;QUEUE CMD TO TERMINAL'S CLI		; MF203
27$:	CALL	@(SP)+		;QUEUE COMMAN      D AND REQUEST CLI		; MF203
	BCC	28$		;IF CC, SUCCESSFUL REQUEST		; MF203
	BEQ	28$		;IF EQ, SUCCESSFUL REQUEST		; MF203
	JMP	ALER1		;PCB ALLOCATION FAILURE			; MF203
28$:	JMP	SUCCES		;SUCCESS				; MF203
									; MF203
	.IFF	;A$$CLI							; MF203
									; MF203
	CALL	$EXRQF		;QUEUE COMMAND TO CLI AND REQUEST	; MF203
									;MSH153
	.IF DF	R$$POI							;MSH153
									;MSH153
	BCC	31$		;IF CC SUCCESSFUL REQUEST		;MSH153
	BEQ	31$		;IF EQ CLI ALREADY ACTIVE - SUCCESS	;MSH153
	JMP	ALER1		;ELS      E REQUEST FAILED FOR PCB ALLOCATION	;MSH153
31$:	JMP	SUCCES		;					;MSH153
									;MSH153
	.IFF								;MSH153
									;MSH153
	BCC	SUCCES		;IF CC SUCCESSFUL REQUEST		;**-1
	BEQ	SUCCES		;IF EQ CLI WAS ALREADY ACTIVE - SUCCESS
	BR	ALER1		;ELSE REQUEST FAILED FOR PCB ALLOCATION
									;MSH153
	.ENDC	;R$$POI							;MSH153
									;MSH153
40$:				;REFERENCE LABEL			; MF203
	.IFT	;A$$CLI							; MF203
									; MF203
40$:	CMP	$MCRPT,R0	;IS COMMAND QUEUED TO MCR...		; MF203
	BEQ	45$		;IF EQ       YS				; MF203
	MOV	#$CLICQ-T.RCVL,R0 ;SET POINTER TO CMD QUEUE LISTHEAD	; MF203
45$:				;REFERENCE LABEL			; MF203
									; MF203
	.ENDC	;A$$CLI							; MF203
									; MF203
									; MF203
	ADD	#T.RCVL,R0	;POINT TO CLI'S RECEIVE QUEUE		; MF203
	CALLR	$QRMVT		;REMOVE THE COMMAND LINE		;**-1

	.ENDC	;M$$CRX

;+
; **-$DREXS-EXIT WITH STATUS
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO PASS A STATUS WORD TO ALL
; PARENT TASKS AND EXIT.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(29.),DPB SIZE(2.)      
;	WD. 01 -- STATUS WORD.
;
; INPUTS:
;
;	R2=ADDRESS OF THE SECOND STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE STATUS WORD IN THE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	NO STATUS IS RETURNED TO THE ISSUING TASK SINCE THIS DIRECTIVE
;	TERMINATES ITS EXECUTION.
;-

$DREXS::			;REF LABEL				;MSH021
									;MSH021
	.IF DF	A$$CPS							;MSH021
									;MSH021
	BIT	      #T3.ACP,T.ST3(R5) ;IS THIS AN ACP?			;MSH021
	BNE	5$		;IF NE YES				;**-1
									;MSH021
	.ENDC								;MSH021
									;MSH021
	MOV	(R3),T.EFLG+2(R5) ;SET EXIT STATUS IN TCB
5$:	CALLR	$DREX2		;INITIATE TASK EXIT PROCESS		;MSH115
									;**-1
;+									;MSH104
; **-$DREMS-EMIT STATUS							;MSH104
;									;MSH104
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO EMIT A STATUS WORD TO ALL	;MSH104
; OR A SPECIFIED PARENT TASK WITHOUT EXITTING.				;MSH104
;									;MSH104
; DPB FORMAT:								;MSH      104
;									;MSH104
;	WD. 00 -- DIC(147.),DPB SIZE(4.).				;MSH104
;	WD. 01 -- FIRST WORD OF PARENT TASK NAME OR 0 FOR ALL.		;MSH104
;	WD. 02 -- SECOND WORD OF PARENT TASK NAME.			;MSH104
;	WD. 03 -- STATUS WORD.						;MSH104
;									;MSH104
; INPUTS:								;MSH104
;									;MSH104
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.	;MSH104
;	R3=ADDRESS OF THE PARENT TASK NAME IN THE DPB.			;MSH104
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.			;MSH104
;	R5=ADDRESS OF THE T      CB OF THE CURRENT TASK.			;MSH104
;									;MSH104
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)			;MSH104
;									;MSH104
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.			;MSH104
;		DIRECTIVE STATUS OF +1 IS RETURNED.			;MSH104
;	C=1 IF DIRECTIVE IS REJECTED.					;MSH104
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF THE SPECIFIED;MSH104
;			TASK IS NOT A PARENT OF THE ISSUING TASK.	;MSH104
;-									;MSH104
									;MSH104
$DREMS::MOV	4(R3),-(SP)	;SAVE SPECIFIED STATUS WORD		;MSH104      
	MOV	R3,R4		;COPY TASK NAME POINTER			;MSH104
20$:	MOV	R5,R0		;COPY ISSUING TASK TCB POINTER		;MSH104
	ADD	#T.OCBH,R0	;POINT TO OCB QUEUE			;MSH104
	MOV	R0,R1		;COPY LISTHEAD POINTER			;MSH104
30$:	MOV	(R1),R1		;POINT TO NEXT IN QUEUE			;MSH104
	BEQ	60$		;IF EQ THERE IS NONE			;MSH104
	TST	(R4)		;TASK NAME SPECIFIED?			;MSH104
	BEQ	40$		;IF EQ NO (PASSING STATUS TO ALL)	;MSH104
	CMP	(R4),O.STAT(R1)	;MATCH ON FIRST WORD OF TASK NAME?	;MSH104
	BNE	30$		;IF NE NO				;MSH104
	CMP	2(R4),O.STAT+2(R1) ;      MATCH ON SECOND WORD OF TASK NAME?	;MSH104
	BNE	30$		;IF NE NO				;MSH104
40$:	CALL	$QRMVT		;REMOVE THE ENTRY			;MSH104
	MOV	(SP),R0		;PICK UP SPECIFIED STATUS WORD		;MSH104
	MOV	#S.CACT,R2	;TASK STILL ACTIVE			;MSH104
	CALL	$QUEXT		;QUEUE THE OCB TO PARENT TASK		;MSH104
	TST	(R4)		;PASSING STATUS TO ALL PARENTS?		;MSH104
	BEQ	20$		;IF EQ YES				;MSH104
50$:	TST	(SP)+		;CLEAN STACK				;MSH104
	RETURN			;					;MSH104
									;MSH104
60$:	TST	(R4)		;WAS A TASK NAME SPECIFIED?		;MSH104
	BEQ	50$		;      IF EQ NO				;MSH104
	DRSTS	D.RS8		;INCONSISTENT WITH CURRENT TASK STATE	;MSH104
									;MSH104
									;MSH104
									;MSH104
;
; LOCAL ROUTINES.
;
; THE FOLLOWING ROUTINES ARE USED TO INSERT AND REMOVE AN ELEMENT FROM
; THE FRONT OF A LIST.  SPECIFICALLY THESE ROUTINES ARE CALLED TO
; OPERATE ON THE MCR COMMAND LINE LIST AT $MCRCB.
;

QMCRB:	MOV	(R0),(R1)	;LINK NEW LINE TO FIRST IN LIST
	MOV	R1,(R0)		;LINK LISTHEAD TO NEW LINE
	RETURN			;
DMCRB:	MOV	(R1),(R0)	;UNLINK NEW COMMAND LINE
      NULL:	RETURN			;(NULL ROUTINE)

;
; ROUTINE TO INITIALIZE ERROR RECOVERY FOR CONNECT, REQUEST, SEND
; REQUEST AND CONNECT, AND SPAWN.
;

ERRSV:	MOV	R0,$TEMP0	;SAVE TARGET TCB ADDRESS
	CLR	$TEMP1		;INITIALIZE OCB POINTER
	JMP	$DRTHR		;INITIALIZE ERROR RECOVERY THREADING
									;MSH117
;									;MSH117
; THIS ROUTINE CALCULATES THE DEFAULT AND PROTECTION UICS FOR		;MSH117
; THE CURRENT TASK.							;MSH117
;									;MSH117
; INPUTS:								;MSH117
;									;MSH117
;	R1=REQUEST UIC							;      MSH117
;									;MSH117
; OUTPUTS:								;MSH117
;									;MSH117
;	R1=PROTECTION UIC						;MSH117
;	R3=DEFAULT UIC (FOR MULTIUSER SYSTEMS ONLY)			;MSH117
;	R4=ADDRESS OF THE CURRENT TASK'S HEADER				;MSH117
;									;MSH117
; R0 AND R5 ARE PRESERVED ACROSS THIS CALL				;MSH117
;									;MSH117
									;MSH117
UISET:	MOV	$TKTCB,R2	;GET CURRENT TASK'S TCB			;MSH117
	ADD	#T.ST2,R2	;POINT TO THE TASK STATUS WORD		;MSH117
	MOV	$HEADR,R4	;GET CURRENT TASK'S HEADER ADDRESS	;MSH117
									;MS      H117
	.IF DF	M$$MUP							;MSH117
									;MSH117
	CALL	$UISET		;CALCULATE DEFAULT AND PROTECTION UICS	;MSH117
									;MSH117
	.IFF								;MSH051
									;MSH051
	TST	R1		;UIC DEFAULTED?				;MSH051
	BNE	70$		;IF NE NO				;MSH051
	MOV	H.CUIC(R4),R1	;DEFAULT THE CURRENT UIC VALUE		;MSH051
70$:				;					;MSH051
	.ENDC	;M$$MUP							;MSH117
									;MSH117
	RETURN			;DONE					;MSH117
									;MSH117
;									; MF207
; THIS ROUTINE PASSES THE PROMPTING CONTROL BIT (T3.MCR) FROM THE CURREN      ; MF207
; TASK TO THE TARGET. IT IS CALLED ONLY IF THE CURRENT TASK HAS PASSED	; MF207
; ALL ITS OCB(S) TO THE TARGET, OR IF THE CURRENT TASK IS A CLI		; MF207
; ON SYSTEMS THAT SUPPORT ALTERNATE CLIS				; MF207
;									; MF207
; INPUTS:								; MF207
;									; MF207
;	R0=POINTER TO OCB LISTHEAD (T.OCBH) OF CURRENT TASK		; MF207
;	R2=TCB ADDRESS OF THE TARGET TASK				; MF207
;	$TEMP2=ADDRESS OF LOCATION TO PUT TERMINATOR			; MF207
;									; MF207
; OUTPUTS:								; MF207
;									; MF20      7
;	NONE								; MF207
;									; MF207
; ALL REGISTERS PRESERVED						; MF207
;									; MF207
									; MF207
	.IF DF	R$$POI							; MF207
									; MF207
PSPRMT:	MOV	#T3.MCR,-(SP)	;GET PROMPT BIT PATTERN			; MF207
	BIC	(SP),T.ST3(R2)	;ASSUME TARGET SHOULD NOT PROMPT	; MF207
	BIT	(SP),T.ST3-T.OCBH(R0) ;WILL CURRENT TASK PROMPT		; MF207
	BEQ	10$		;IF EQ NO				; MF207
	BIS	(SP),T.ST3(R2)	;TARGET SHOULD PROMPT			; MF207
	TST	$TEMP2		;IS THERE A CMD LINE			; MF207
	BEQ	10$		;IF EQ NO				; M      F207
	MOVB	#15,@$TEMP2	;SET CR AS TERMINATOR			; MF207
10$:	BIC	(SP)+,T.ST3-T.OCBH(R0) ;CURRENT TASK SHOULD NOT PROMPT	; MF207
	RETURN								; MF207
									; MF207
;									; MF207
; THIS ROUTINE LOCATES THE OCB(S) TO BE PASSED BY THE RPOI$ AND SDRP$	; MF207
; DIRECTIVES.								; MF207
;									; MF207
; INPUTS:								; MF207
;									; MF207
;	R2=FLAGS BYTE							; MF207
;	R3=ADDRESS OF THE PARENT'S TASK NAME IN THE DPB			; MF207
;									; MF207
;									; MF207
; OUTPUTS:								      ; MF207
;									; MF207
;	$TEMP1 IS SET WITH THE ADDRESS OF THE OCB TO PASS, CLEAR IF	; MF207
;		NO OCB IS TO BE PASSED, OR ONE TO PASS ALL OCBS		; MF207
;									; MF207
									; MF207
LOCOCB:	MOV	(SP)+,R4	;RETURN ADDR OFF STACK (ERROR THREADING); MF207
	CLR	$TEMP1		;ASSUME NO OCB TO PASS			; MF207
	ASR	R2		;PASS ALL OCBS?				; MF207
	BCS	5$		;IF CS YES				;MSH185
	ASR	R2		;PASS OLDEST OCB?			;MSH185
	BCC	10$		;IF CC NO, PASS SPECIFIC OCB		;MSH185
	MOV	(R3),-(SP)	;PARENT NAME SPECIFIED, OR      		;MSH185
	BIS	4(R3),(SP)+	;AN OCB ID (ADDRESS)?			;MSH185
	BNE	120$		;IF NE YES, ILLEGAL COMBINATION		;MSH185
	MOV	$TKTCB,R2	;GET CURRENT TASK'S TCB ADDRESS		;MSH185
	MOV	T.OCBH(R2),$TEMP1 ;INDICATE WHICH OCB TO PASS		;MSH185
	JMP	(R4)		;RETURN					;MSH185
									;MSH185
5$:				;					;MSH185
									; MF207
	.IF DF	A$$CLI							; MF207
									; MF207
	MOV	$TEMP0,R2	;POINT TO OBJECT TASK			; MF207
	BIT	#T3.CLI,T.ST3(R2) ;IS OBJECT TASK A CLI			; MF207
	BNE	100$		;IF NE YES, ILLEGAL			; MF2      07
									; MF207
	.IFTF								; MF207
									; MF207
	MOV	(R3),-(SP)	;WAS A PARENT NAME SUPPLIED		; MF207
	BIS	4(R3),(SP)+	;OR AN OCB ADDRESS			; MF207
	BNE	120$		;IF NE YES				; MF207
	INC	$TEMP1		;INDICATE PASS ALL			; MF207
	BR	70$		;ALL DONE				; MF207
10$:	MOV	$TKTCB,R2	;POINT TO CURRENT TASK'S TCB		; MF207
	ADD	#T.OCBH,R2	;ITS OCB LISTHEAD			; MF207
									; MF207
	.IFT	;A$$CLI							; MF207
									; MF207
	BIT	#T3.CLI,T.ST3-T.OCBH(R2) ;IS ISSUING TASK A CLI		; MF207
	BEQ	30$	      	;IF EQ NO				; MF207
	TST	(R3)		;WAS A SPECIFIC PARENT REQUESTED	; MF207
	BNE	40$		;IF NE YES				; MF207
	TST	4(R3)		;WAS AN OCB ADDRESS SUPPLIED		; MF207
	BEQ	70$		;IF EQ NO				; MF207
20$:	MOV	(R2),R2		;POINT TO THE NEXT OCB			; MF207
	BEQ	110$		;IF EQ, THERE ARE NO MORE		; MF207
	CMP	4(R3),R2	;IS THIS THE SPECIFIED OCB		; MF207
	BNE	20$		;IF NE NO				; MF207
	BR	60$		;					; MF207
									; MF207
	.IFTF								; MF207
									; MF207
30$:	TST	4(R3)		;WAS AN OCB ADDRESS SPECIFIED		; MF207      
	BNE	100$		;IF NE YES				; MF207
	TST	(R3)		;WAS A SPECIFIC PARENT REQUESTED	; MF207
	BEQ	70$		;IF EQ NO				; MF207
40$:	MOV	(R2),R2		;POINT TO NEXT OCB IN LIST		; MF207
	BEQ	110$		;IF EQ, THERE ARE NO MORE		; MF207
	CMP	O.STAT(R2),(R3)	;IS THIS THE OCB FOR THE CORRECT PARENT	; MF207
	BNE	40$		;IF NE NO				; MF207
	CMP	O.STAT+2(R2),2(R3) ;MAYBE??				; MF207
	BNE	40$		;IF NE NO				; MF207
									; MF207
	.IFT	;A$$CLI							; MF207
									; MF207
	TST	4(R3)		;HAS OCB ADDR BEEN SPECIFIED		; MF      207
	BEQ	60$		;IF EQ NO				; MF207
	CMP	4(R3),R2	;ARE THEY THE SAME ENTRIES		; MF207
	BNE	120$		;IF NE NO				; MF207
									; MF207
	.ENDC	;A$$CLI							; MF207
									; MF207
									; MF207
60$:	MOV	R2,$TEMP1	;SAVE ADDRESS OF OCB TO PASS		; MF207
70$:	JMP	(R4)		;RETURN					; MF207
									; MF207
;									; MF207
; ERROR HANDLING							; MF207
;									; MF207
100$:	JMP	ILPARM		;THIS TASK CANNOT USE THIS PARAMETER	; MF207
110$:	MOV	(PC)+,R5	;PICK UP SPECIFIED OCB DOESN'T EXIST STA;       MF207
	DRSTS	D.RS86		;					; MF207
	BR	150$		;RETURN ERROR STATUS			; MF207
120$:	MOV	(PC)+,R5	;PICK UP NAME AND OCB ADDR DON'T MATCH S; MF207
	DRSTS	D.RS84		;					; MF207
150$:	JMP	ERROR		;ISSUE ERROR				; MF207
									; MF207
									; MF207
;									; MF207
; THIS ROUTINE COPIES THE TCB OF A TASK INSTALLED WITH A NAME OF THE	; MF207
; FORM ...XXX, LINKS IT INTO THE STD, AND SETS ITS REMOVE ON EXIT BIT.	; MF207
; IT WILL ONLY BE CALLED IF THE SPWN$ OR RPOI$ DIRECTIVE IS ISSUED BY	; MF207
;       A CLI TASK ON A SYSTEM WITH ALTERNATE CLI SUPPORT.			; MF207
;									; MF207
;  ****  I M P O R T A N T   ******					; MF207
;									; MF207
; THIS ROUTINE MUST BE KEPT CURRENT WITH ALL TCB FORMAT CHANGES		; MF207
;									; MF207
;									; MF207
; INPUTS:								; MF207
;									; MF207
;	R0=ADDRESS OF NEW TCB BEING CREATED				; MF207
;	R1=ADDRESS OF TCB BEING COPIED					; MF207
;	R3=ADDRESS OF NEW TASK NAME IN DPB				; MF207
;	R5=UCB ADDRESS OF CURRENT TASK'S TI:				; MF207
;								      	; MF207
; OUTPUTS:								; MF207
;									; MF207
;	THE NEW TCB IS CREATED AND LINKED INTO THE STD			; MF207
;									; MF207
; R1, R2  AND R4 ARE MODIFIED						; MF207
;									; MF207
									; MF207
	.IF DF	A$$CLI&I$$RAR&D$$YNM&C$$CKP&D$$YNC			; MF207
									; MF207
CPYTCB:	MOV	T.PCB(R1),R4	;GET ADDRESS OF TASK'S PARTITION PCB	; MF207
	MOV	P.MAIN(R4),R4	;LOCATE MAIN PARTITION			; MF207
	MOV	R0,R2		;COPY ADDRESS OF NEW TCB		; MF207
	CLR	(R2)+		;T.LNK					; MF207
	MOVB	T.DPRI(R1),(R2)      + ;SET TASKS PRIORITY			; MF207
	CLRB	(R2)+		;T.IOC					; MF207
	CLR	(R2)+		;T.CPCB					; MF207
	MOV	(R3),(R2)+	;SET FIRST HALF OF T.NAM		; MF207
	MOV	2(R3),(R2)+	;SET SECOND HALF OF T.NAM		; MF207
	CALL	INILST		;INITIALIZE T.RCVL LISTHEAD		; MF207
	CALL	@(SP)+		;T.ASTL					; MF207
	CLR	(R2)+		;T.EFLG					; MF207
	CLR	(R2)+		;					; MF207
	MOV	R5,(R2)+	;T.UCB					; MF207
	ADD	#T.TCBL-10,R1	;POINT TO T.TCBL IN SOURCE TCB		; MF207
	MOV	(R1),(R2)+	;POINT TO NEXT TASK IN STD		; MF207
	MOV	R0,(R1)+	;      LINK NEW TCB AFTER ONE BEING COPIED	; MF207
;									; MF207
; THE SYSTEM CONTROLLED PARTITION CHECK MUST NOT BE DONE UNTIL		; MF207
; THE TCB HAS BEEN LINKED INTO THE STD, SINCE THE ERROR CODE TO		; MF207
; UNLINK IT HAS ALREADY BEEN PUSHED ONTO THE STACK			; MF207
;									; MF207
	BIT	#PS.SYS,P.STAT(R4) ;IS PARTITION SYSTEM CONTROLLED	; MF207
	BNE	10$		;IF NE YES				; MF207
	COM	(SP)+		;POP STACK AND SET CARRY		; MF207
	RETURN								; MF207
10$:	MOV	#TS.EXE!TS.OUT,(R2)+ ;SET T.STAT TO NOT AC      TIVE AND OUT	; MF207
	TST	(R1)+		;POINT TO T.ST2				; MF207
	MOV	(R1)+,(R2)	;COPY T.ST2				; MF207
	BIC	#^C<T2.CHK>,(R2)+ ;CLEAR ALL BITS EXCEPT T2.CHK		; MF207
	MOV	(R1)+,(R2)	;COPY T.ST3				; MF207
	BIC	#^C<T3.ACP!T3.PMD!T3.PRV!T3.RST!T3.ROV>,(R2)+ ;CLEAR BIT; MF207
	MOV	(R1)+,(R2)+	;T.DPRI AND T.LBN			; MF207
	MOV	(R1)+,(R2)+	;T.LBN (3 BYTE FIELD)			; MF207
	MOV	(R1)+,(R2)+	;T.LDV					; MF207
	MOV	R4,(R2)+	;T.PCB					; MF207
	TST	(R1)+		;					; MF207
	MOV	(R1)+,(R2)+	;T.MXSZ					; MF207
	CLR	      (R2)+		;T.ACTL					; MF207
	CLR	(R2)+		;T.SAST					; MF207
	CLR	(R2)+		;T.TIO					; MF207
	ADD	#T.TKSZ-T.ACTL,R1 ;POINT TO T.TKSZ			; MF207
	MOV	(R1)+,(R2)+	;T.TKSZ					; MF207
									; MF207
									; MF207
	.IF DF	P$$LAS							; MF207
									; MF207
	CALL	@(SP)+		;T.ATT					; MF207
	MOV	(R1)+,(R2)+	;T.OFF					; MF207
	CLR	(R2)+		;T.SRCT					; MF207
	TST	(R1)+		;					; MF207
	CALL	@(SP)+		;T.RRFL					; MF207
									; MF207
	.ENDC								; MF207
									; MF207
									; MF207
	CA      LL	@(SP)+		;T.OCBH					; MF207
	TST	(R1)+		;					; MF207
	CLR	(R2)+		;T.RDCT					; MF207
									; MF207
									; MF207
	.IF DF	S$$TOP!T$$BUF						; MF207
									; MF207
	CMP	(R2)+,(R2)+	;T.EFLM					; MF207
	CMP	(R1)+,(R1)+	;					; MF207
									; MF207
	.ENDC								; MF207
									; MF207
									; MF207
	.IF DF	A$$HDR							; MF207
									; MF207
	MOVB	(R1)+,(R2)+	;T.HDLN					; MF207
									; MF207
	.ENDC								; MF207
									; MF207
									; MF207
	.IF DF	R$$SND&G$$E      FN!A$$CLI&G$$EFN				;MSH190
									; MF207
	CLRB	(R2)+		;T.GGF					; MF207
									; MF207
	.ENDC								; MF207
									; MF207
									; MF207
	CLR	(SP)+		;POP COROUTINE ADDRESS AND CLEAR CARRY	; MF207
	RETURN								; MF207
									; MF207
;									; MF207
; COROUTINE TO INIT STANDARD DOUBLE WORD LISTHEAD TO EMPTY		; MF207
;									; MF207
INILST:	MOV	R2,2(R2)	;SET SECOND WORD TO POINT TO FIRST	; MF207
	CLR	(R2)+		;CLEAR FIRST WORD			; MF207
	TST	(R2)+		;POINT TO NEXT WORD AFTER LI      STHEAD	; MF207
	CMP	(R1)+,(R1)+	;SKIP OVER LISTHEAD IN PROTO TCB	; MF207
	CALL	@(SP)+		;CALL CALLER BACK			; MF207
	BR	INILST		;					; MF207
									; MF207
;									; MF207
; ROUTINE TO UNLINK THE TCB JUST CREATED FROM THE STD IN THE EVENT	; MF207
; OF AN ERROR LATER IN THE DIRECTIVE PROCESSING. THIS ROUTINE IS	; MF207
; CALLED OUT OF THE ERROR THREADING MECHINISM				; MF207
;									; MF207
									; MF207
UNLTCB:	MOV	T.TCBL(R0),T.TCBL(R1) ;UNLINK THE NEW TCB		; MF207
	RETURN								; MF20   ª   7
									; MF207
	.ENDC	;A$$CLI&I$$RAR&D$$YNM&C$$CKP&D$$YNC			; MF207
									; MF207
	.ENDC	;R$$POI							; MF207
									; MF207

	.ENDC	;P$$OFF


	.END
ª          ãƒÈ_kQ	› c,        	.IIF  DF M$$MGE!U$$DCM .TITLE UDCOM
	.IIF NDF M$$MGE&U$$DCM .TITLE UDCDF
	.IDENT	/01/
 
;
; COPYRIGHT (C) 1974, 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A
; SINGLE COMPUTER SYSTEM AND MAY  BE  COPIED   ONLY  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   EXCEPT FOR  USE ON SUCH
; SYSTEM AND TO       ONE WHO AGREES TO THESE LICENSE  TERMS.  TITLE
; TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL  TIMES  REMAIN
; IN DEC.
;
; THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT
; NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
; EQUIPMENT CORPORATION.
;
; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF
; ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
;
; VERSION 01
;
; C. MONIA 17-JUL-74
;
; ALLOCATE UDC COMMON BLOCK AND DEFINE OFFSETS FOR MODULE TY      PES
;
; LOCAL MACROS
;
; DEFINE STORAGE AND OFFSETS FOR UDC-11 MODULES
;
; DFUDC	TYP
;
; WHERE:
;
;	TYP = GENERIC MODULE TYPE. ONE OF THE FOLLOWING
;	      RECOGNIZED:
;
;	'ADM' - ADU01 A/D CONVERTER
;	'AOM' - ANALOG OUTPUT MODULE
;	'CIM' - CONTACT INTERRUPT MODULE
;	'CSM' - CONTACT SENSE MODULE
;	'LTM' - LATCHING MODULE
;	'SSM' - SINGLE SHOT DIGITAL OUTPUT
;	'TIM' - TIMER MODULE
;
; THE SYMBOL "U$$'TYP", IF DEFINED, ENCODES THE FOLLOWING
; INFORMATION:
;
;	BITS 15 - 8 = NUMBER OF MO      DULES
;	BITS 7 - 0  = RELATIVE MODULE NUMBER
;
; THIS MACRO GENERATES GLOBAL CONSTANTS OF THE FOLLWING FORMS
; FOR EACH GENERIC MODULE TYPE:
;
;	$.'TYP = STARTING ADDRESS OF MODULE TYPE
;	M$.'TYP = HIGHEST RELATIVE MODULE NUMBER
;	P$.'TYP = HIGHEST ALLOWABLE POINT NUMBER
;
 
	.MACRO	DFUDC	TYP
	.IF	DF	U$$'TYP
...PC=<U$$'TYP&377>*2
.=UDCBA
	.BLKB	...PC
...SIZ=<U$$'TYP/256.>&377
$.'TYP::	.BLKW	...SIZ
M$.'TYP==<...SIZ>-1
P$.'TYP==<...SIZ*16.>-1
	.ENDC
	.ENDM
 
;+
; **-UDCOM-MODULE TO ALL      OCATE UDC-11 COMMON BLOCK STORAGE, DEFINE UDC
;          MODULE OFFSETS.
;
; THIS MODULE, WHEN ASSEMBLED WITH PREFIX FILE RSXMC.MAC, WILL:
;
;	(1) GENERATE SYMBOLIC ADDRESSES AND LENGTHS FOR GENERIC
;	    UDC MODULE TYPES
;
;	(2) IF 'M$$MGE' OR 'U$$DCM' IS DEFINED ALLOCATE STORAGE FOR
;	     THE UDC GLOBAL COMMON BLOCK
;
; THE GLOBAL COMMON AREA RESIDES IN  A RELOCATABLE PROGRAM SECTION
; NAMED 'UDCOM' HAVING  '.CSECT' ATTRIBUTES (IE. 'GBL', 'OVR', 'I'). IN
; THIS CASE THE SYMBOLIC OFFSETS ARE       RELOCATABLE. THE NAMED
; SECTION MAY BE REFERENCED DIRECTLY BY THE FORTRAN PROGRAM.
;
; IF THE COMMON AREA IS NOT TO BE GENERATED . THEN
; THE OFFSETS ARE ABSOLUTE LOCATIONS ON THE EXTERNAL PAGE.  IN THIS CASE
; DIRECT FORTRAN ACCESS IS NOT POSSIBLE.
;
; THE VARIABLE 'M$$MGE' IS DEFINED IN 'RSXMC.MAC' IF MEMORY MANAGE-
; MENT IS PRESENT.
;
;
;-
 
	.IF	DF	M$$MGE!U$$DCM
 
	.PSECT	UDCOM,GBL,D,OVR
 
	.IFF
 
	.PSECT	$$UDAB,ABS
 
	.BLKB	171000
 
	.ENDC
 
UDCBA=.				; REF LABEL
 
	DFUDC	   d  ADM		; DEFINE ANALOG INPUT CONFIGURATION
	DFUDC	AOM		; DEFINE ANALOG  OUTPUT CONFIGURATION
	DFUDC	CIM		; DEFINE CONTACT INTERRUPT CONFIGURATION
	DFUDC	CSM		; DEFINE CONTACT SENSE CONFIGURATION
	DFUDC	LTM		; DEFINE LATCHING MODULE CONFIGURATION
	DFUDC	SSM		; DEFINE SINGLE SHOT CONFIGURATION
	DFUDC	TIM		; DEFINE TIMER MODULE CONFIGURATION
 
	.END
d         äƒðskQ	› c,        	.TITLE	UDDRV
	.IDENT	/07/
 
;
; COPYRIGHT (C) 1974, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 07
;
; D. N. CUTLER 20-FEB-74
;
; PREVIOUSLY MODIFIED BY:
;
;	D. N. CUTLER
;	T. J. MILLER
;	C. A. MONIA
;
; MODIFIED BY:
;
;	C. A. MONIA 03-MAR-77
;
;		CM085 -- CLEAR OUT SCAN ERROR INDICATIONS CORRECTLY
;
; UDC11 UNIVERSAL DIGITAL INPUT/OUTP      UT CONTROLLER
;
; NOTE:	THIS IS A SINGLE CONTROLLER DRIVER
;
; MACRO LIBRARY CALLS
;
 
	.MCALL	HWDDF$,PKTDF$,TCBDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
 
;
; EQUATED SYMBOLS
;
; UDC11 HARDWARE REGISTER DEFINITIONS
;
 
UDCR=171776			;ADDRESS OF UDC11 CSR
UDSR=171774			;ADDRESS OF UDC11 SCAN REGISTER
UDMD=171000			;ADDRESS OF FIRST FUNCTIONAL MODULE
 
;
; MODULE TABLE AND INTERUPT CONTROL BLOCK OFFSET DEF      INITIONS
;
 
MDCNT=0				;NUMBER OF POINTS OR MODULES
MDBAS=2				;ADDRESS IN I/O PAGE OF FIRST MODULE
NMBYT=4				;NUMBER OF BYTES OF INTERRUPT DATA
STATS=5				;FORK STATUS BYTE (0=FORK IN PROGRESS)
STRBF=6				;STARTING BUFFER RELOCATION BIAS
CURBF=10			;CURRENT BUFFER RELOCATION BIAS
BUFAD=12			;ADDRESS OF START OF BUFFER
CURNX=20			;CURRENT FORTRAN BUFFER FILL INDEX
BFLGH=22			;LENGTH OF BUFFER IN WORDS
EFNMK=24			;EVENT FLAG MASK WORD
EFNAD=26			;EVENT FLAG MASK ADDRESS
LSCNT=30			;LOST DATA       COUNT
CONTK=32			;TCB ADDRESS OF CONNECTED TASK
FRBLK=34			;INTERRUPT FORK BLOCK (3 WORDS)
 
;
; LOCAL DATA
;
; UDC11 UCB ADDRESS
;
 
UDUCB:	.BLKW	1		;SAVED UCB ADDRESS
 
;
; A/D MODULE TABLE
;
 
 
	.IF DF	U$$ADM
 
ADTBL:	.WORD	<<U$$ADM/256.>&377>*U$$ACH ;NUMBER OF A/D CHANNELS
	.WORD	UDMD+<<U$$ADM&377>*2> ;ADDRESS OF BASE MODULE
ADMOD:	.BLKW	1		;INTERRUPT MODULE ADDRESS
 
	.ENDC
 
 
;
; CONTACT INTERRUPT MODULE TABLE, INTERRUPT CONTROL BLOCK, AND PREVIOUS STATE TA
;
;
 
 
	.      IF DF	U$$CIM
 
CITBL:	.WORD	<<U$$CIM/256.>&377>*16. ;NUMBER OF CONTACT INTERRUPT POINTS
	.WORD	UDMD+<<U$$CIM&377>*2> ;ADDRESS OF BASE MODULE
	.WORD	5*2		;NUMBER OF BYTES OF INTERRUPT DATA
	.BLKB	FRBLK+4-NMBYT	;INTERRUPT CONTROL BLOCK
CIPRV:	.BLKW	<U$$CIM/256.>&377 ;CONTACT POINT PREVIOUS STATE TABLE
 
	.ENDC
 
 
;
; LATCHING OUTPUT MODULE TABLE
;
 
 
	.IF DF	U$$LTM
 
LTTBL:	.WORD	<<U$$LTM/256.>&377>*16. ;NUMBER OF LATCHING OUTPUT POINTS
	.WORD	UDMD+<<U$$LTM&377>*2> ;ADDRESS OF BASE MODULE      
LTPRV:	.BLKW	<U$$LTM/256.>&377 ;LATCHING OUTPUT PREVIOUS STATE TABLE
 
	.ENDC
 
 
;
; TIMER INTERRUPT MODULE TABLE, INTERRUPT CONTROL BLOCK, AND INITIAL VALUE TABLE
;
 
 
	.IF DF	U$$TIM
 
TMTBL:	.WORD	<<U$$TIM/256.>&377> ;NUMBER OF TIMER INTERRUPT MODULES
	.WORD	UDMD+<<U$$TIM&377>*2> ;ADDRESS OF BASE MODULE
	.WORD	4*2		;NUMBER OF BYTES OF INTERRUPT DATA
	.BLKB	FRBLK+4-NMBYT	;INTERRUPT CONTROL BLOCK
TMINI:	.BLKW	<<U$$TIM/256.>&377> ;INITIAL TIMER VALUE TABLE
 
	.ENDC
 
;
; DRIVER DISPA      TCH TABLE
;
 
$UDTBL::.WORD	UDCHK		;DEVICE INITIATOR ENTRY POINT
	.WORD	UDCAN		;CANCEL I/O OPERATION ENTRY POINT
	.WORD	UDOUT		;DEVICE TIMEOUT ENTRY POINT
	.WORD	UDPWF		;POWERFAIL ENTRY POINT
 
;+
; **-UDCHK-UDC11 UNIVERSAL DIGITAL INPUT/OUTPUT CONTROLLER PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O
; REQUEST IS RECEIVED FOR THE UDC11 UNIVERSAL DIGIT INPUT/OUTPUT
; CONTROLLER. UDC11 I/O REQUESTS CONTAIN DEVICE DEPENDENT INFORMA-
; ATION THAT MUST BE C      HECKED IN THE CONTEXT OF THE ISSUING TASK.
; THEREFORE THE I/O REQUEST IS NOT QUEUED BEFORE CALLING THE DRIVER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	DEPENDENT UPON FUNCTION TO BE PERFORMED.
;
; UDC11 FUNCTION INDEPENDENT I/O PACKET FORMAT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.      
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE .
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;-
 
UDCHK:	MOV	R1,-(SP)	;SAVE I/O PACKET ADDRESS
	MOV	I.TCB(R1),R0	;GET TCB ADDRESS OF REQUESTER TASK
	MOV      B	I.FCN+1(R1),R2	;GET I/O FUNCTION CODE
	ADD	#I.PRM,R1	;POINT TO FIRST I/O PARAMETER
 
 
	.IF DF	U$$CIM
 
	MOV	#CITBL,R3	;ASSUME CONTACT INTERRUPT FUNCTION
	CMPB	#IO.CCI/256.,R2	;CONNECT CONTACT INTERRUPTS?
	BEQ	UDCNT		;IF EQ YES
	CMPB	#IO.DCI/256.,R2	;DISCONNECT CONTACT INTERRUPTS?
	BEQ	UDDIS		;IF EQ YES
 
	.ENDC
 
 
	.IF DF	U$$TIM
 
	MOV	#TMTBL,R3	;ASSUME TIMER FUNCTION
	CMPB	#IO.CTI/256.,R2	;CONNECT TIMER INTERRUPTS?
	BEQ	UDCNT		;IF EQ YES
	CMPB	#IO.DTI/256.,R2	;DISCONNECT TIMER INTER      RUPTS?
	BEQ	UDDIS		;IF EQ YES
	CMPB	#IO.ITI/256.,R2	;INITIALIZE TIMER MODULE?
	BEQ	UDITM		;IF EQ YES
 
	.ENDC
 
 
	.IF DF	U$$LTM
 
	CMPB	#IO.MLO/256.,R2	;MULTILATCHING DIGITAL OUTPUT?
	BEQ	UDLTM		;IF EQ YES
 
	.ENDC
 
 
	.IF DF	U$$ADM
 
	CMPB	#IO.RBC/256.,R2	;READ BUFFERED A/D MODULES?
 
	.IFTF
 
	BNE	UDIFC		;IF NE NO ILLEGAL FUNCTION
 
	.IFT
 
	JMP	UDRAD		;
 
	.ENDC
 
 
;+
; **-UDCNT-CONNECT TASK TO INTERRUPTS
;
; FUNCTION DEPENDENT I/O REQUEST PACKET FORMAT:
;
;	WD. 12       -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER.
;	WD. 15 -- TRIGGER EVENT FLAG NUMBER.
;	WD. 16 -- INITIAL TIMER BUFFER (IO.CTI ONLY).
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
 
	.IF DF	U$$CIM!U$$TIM
 
UDCNT:	BIT	#T2.CHK!T2.FXD,T.ST2(R0) ;TASK FXD OR NOT CHKPOINTABLE?
	BEQ	UDPRI		;IF EQ NO
	TST	CONTK(R3)	;ANOTHER TASK ALREADY CONNECTED?
	BNE	UDCON		;IF NE YES
	CMP	(R1)+,(R1)+	;POINT TO DATA BUFFER SIZE
	MOVB	NMBYT(R3),R      0	;GET NUMBER OF BYTES OF INTERRUPT DATA
	CMP	(R0)+,(R0)+	;ADJUST FOR BUFFER HEADER
	CMP	(R1)+,R0	;BUFFER BIG ENOUGH?
	BLO	UDSPC		;IF LO NO
	MOV	(R1)+,R0	;GET EVENT FLAG NUMBER
	BEQ	UDIEF		;IF EQ NO EVENT FLAG SPECIFIED
	CMP	R0,#64.		;LEGAL EVENT FLAG NUMBER?
	BHI	UDIEF		;IF HI NO
 
 
	.IF DF	U$$TIM
 
	CMP	#TMTBL,R3	;TIMER CONNECT?
	BNE	20$		;IF NE NO
	MOV	(R1),R0		;GET ADDRESS OF INITIAL VALUE BUFFER
	MOV	(R3)+,R4	;GET NUMBER OF TIMER MODULES
 
 
	.IF DF	A$$CHK!M$$MGE
 
	MOV	R4,R1		;SET       NUMBER OF TIMER MODULES
	ASL	R1		;CONVERT TO BYTE COUNT
	CALL	$ACHCK		;ADDRESS CHECK INITIAL VALUE BUFFER
	BCS	UDSPC		;IF CS ILLEGAL BUFFER
 
	.ENDC
 
 
	.IF DF	M$$MGE
 
	CALL	$RELOM		;RELOCATE AND MAP TO INITIAL VALUE BUFFER
 
	.ENDC
 
 
	BIC	#36,UDCR	;DISABLE UDC INTERRUPTS
	MOV	(R3),R1		;GET ADDRESS OF FIRST TIMER MODULE
	MOV	#TMINI,R2	;GET ADDRESS OF INITIAL VALUE TABLE
10$:	MOV	(R0)+,(R2)	;SET VALUE IN INITIAL VALUE TABLE
	BIS	#1,UDCR		;SET RIF BIT
	MOV	(R2)+,(R1)+	;SET COUNTER VAL      UE AND RESET MODULE
	BIC	#1,UDCR		;CLEAR RIF BIT
	DEC	R4		;ANY MORE INITIALIZE?
	BGT	10$		;IF GT YES
	TST	-(R3)		;POINT TO MODULE COUNT
 
	.IFTF
 
20$:	MOV	(SP),R4		;RETRIEVE ADDRESS OF I/O PACKET
	MOV	R5,-(SP)	;SAVE ADDRESS OF UCB
	MOV	I.TCB(R4),R5	;GET REQUESTER TASK TCB ADDRESS
	ADD	#I.PRM,R4	;POINT TO FIRST I/O PARAMETER
	ADD	#NMBYT,R3	;POINT TO NUMBER OF BYTES OF INT DATA
	MOVB	(R3)+,(R3)+	;SET FORK NOT IN PROGRESS
	MOV	(R4)+,(R3)	;INSERT STARTING BUFFER RELOCATION BIAS
	MOV	(R3)+,(R3)+	      ;COPY STARTING BUFFER RELOCATION BIAS
	MOV	(R4)+,(R3)	;INSERT STARTING BUFFER ADDRESS
	MOV	(R3)+,(R3)	;COPY STARTING BUFFER ADDRESS
	ADD	#4,(R3)		;CALCULATE ADDRESS OF FIRST DATA WORD
	MOV	(R3)+,(R3)+	;COPY ADDRESS OF FIRST DATA WORD
	MOV	#3,(R3)+	;SET CURRENT FORTRAN INDEX
	MOV	(R4)+,(R3)	;GET SIZE OF BUFFER IN BYTES
	ROR	(R3)+		;CONVERT TO SIZE IN WORDS
	MOV	(R4),R0		;GET EVENT FLAG NUMBER
	CALL	$CEFI		;CONVERT TO MASK AND MASK ADDRESS
	MOV	R0,(R3)+	;INSERT EVENT FLAG MASK
	MOV	R1,(R3)+	;INSERT       EVENT FLAG MASK ADDRESS
	BIC	R0,(R1)		;CLEAR EVENT FLAG
	CLR	(R3)+		;CLEAR LOST DATA COUNT
	MOV	R5,(R3)+	;CONNECT TASK TO INTERRUPTS
	INCB	T.IOC(R5)	;BIAS TASK'S OUTSTANDING I/O COUNT
 
	.IF DF	D$$SHF
 
	MOV	T.PCB(R5),R1	;GET ADDRESS OF TASK PCB
	BIS	#PS.NSF,P.STAT(R1) ;DISABLE TASK SHUFFLING
 
	.ENDC
 
	MOV	(SP)+,R5	;RETRIEVE ADDRESS OF UCB
	MOVB	NMBYT-FRBLK(R3),R1 ;GET NUMBER OF BYTES OF INTERRUPT DATA
	ASR	R1		;CONVERT TO WORD COUNT
	DEC	R1		;ADJUST FOR EXISTANCE INDICATOR
	BIS	#3*256.,      R1	;INSERT INITIAL FORTRAN INDEX
	
	.IFT
	
	BIS	#36,UDCR	;ENABLE UDC INTERRUPTS
	
	.ENDC
	
	
	BR	UDSUC1		;
 
	.ENDC
 
 
	.IF DF	U$$LTM
 
UDLTM:	BR	UDLAT		;MULTILATCHING OUTPUT
 
	.ENDC
 
 
;+
; **-UDDIS-DISCONNECT TASK FROM INTERRUPTS
;
; FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- NOT USED.
;	WD. 13 -- NOT USED.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
 
	.IF DF	U$$CIM!U$$TIM
 
UDDIS:	CAL      L	UDCAN1		;DISCONNECT TASK FROM INTERRUPTS
	BCC	UDSUC		;IF CC OKAY
 
;
; ILLEGAL CONNECT/DISCONNECT TO/FROM INTERRUPTS
;
 
UDCON:	MOV	#IE.CON&377,R0	;SET ILLEGAL CONNECT/DISCONNECT STATUS
	BR	UDCMN		;
 
;
; ILLEGAL EVENT FLAG NUMBER
;
 
UDIEF:	MOV	#IE.IEF&377,R0	;SET ILLEGAL EVENT FLAG STATUS
	BR	UDCMN		;
 
;
; PRIVILEGE VIOLATION
;
 
UDPRI:	MOV	#IE.PRI&377,R0	;SET PRIVILEGE VIOLATION STATUS
	BR	UDCMN		;
 
	.ENDC
 
 
;
; ILLEGAL FUNCTION
;
 
UDIFC:	MOV	#IE.IFC&377,R0	;SET ILLE      GAL FUNCTION STATUS
	BR	UDCMN		;
 
;
; ILLEGAL BUFFER SPECIFICATION
;
 
 
	.IF DF	U$$ADM!U$$CIM!U$$TIM
 
UDSPC:	MOV	#IE.SPC&377,R0	;SET ILLEGAL BUFFER STATUS
	BR	UDCMN		;
 
	.ENDC
 
 
;+
; **-UDITM-INITIALIZE TIMER VALUE
;
; FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- RELATIVE MODULE NUMBER.
;	WD. 13 -- NEW TIMER VALUE.
;	WD. 14 -- NOT USED.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
 
	.IF DF	U$$TIM
 
UDITM:	CMP	R0,C      ONTK(R3)	;CURRENT TASK CONNECTED TO TIMER INTERRUPTS?
	BNE	UDIFC		;IF NE NO
	MOV	(R1)+,R2	;GET RELATIVE MODULE NUMBER
	CMP	R2,(R3)+	;LEGAL TIMER MODULE?
	BHIS	UDMOD		;IF HIS NO
	ASL	R2		;CONVERT TO WORD INDEX
	MOV	(R1),TMINI(R2)	;SET NEW TIMER PRESET VALUE
	ADD	(R3),R2		;CALCULATE ADDRESS OF TIMER MODULE
	MOVB	#PR6,PS		;;;LOCKOUT DEVICE INTERRUPTS
	BIS	#1,UDCR		;;;SET RIF BIT
	MOV	(R1),(R2)	;;;SET TIMER VALUE AND RESET MODULE
	BIC	#1,UDCR		;;;RESET RIF BIT
	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
	      BR	UDSUC		;
 
	.ENDC
 
 
;+
; **-UDLAT-MULTIPLE LATCHING OUTPUT
;
; FUNCTION DEPENDENT I/O PACKET FORMAT:
;
;	WD. 12 -- STARTING RELATIVE RELAY POINT NUMBER.
;	WD. 13 -- DATA MASK WORD.
;	WD. 14 -- DATA VALUE.
;	WD. 15 -- NOT USED.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
	.IF DF	U$$LTM
 
UDLAT:	MOV	(R1)+,R0	;GET STARTING RELATIVE RELAY POINT NUMBER
	CMP	R0,LTTBL+MDCNT	;LEGAL STARTING POINT NUMBER?
	BHIS	UDMOD		;IF HIS NO
	BIT	#17,R0		;ALL POINTS WITHIN       ONE MODULE?
	BNE	UDMOD		;IF NE NO
	ASR	R0		;CONVERT STARTING POINT NUMBER TO
	ASR	R0		;RELATIVE INDEX
	ASR	R0		;
	MOV	LTPRV(R0),R4	;GET LAST DATA WRITTEN
	BIC	(R1),R4		;CLEAR BITS TO BE WRITTEN
	COM	(R1)		;COMPLEMENT MASK WORD
	BIC	(R1)+,(R1)	;CLEAR EXTRANEOUS BITS IN DATA WORD
	BIS	(R1),R4		;MERGE NEW DATA WITH LAST WRITTEN
	MOV	R4,LTPRV(R0)	;SAVE RESULT AS LAST DATA WRITTEN
	ADD	LTTBL+MDBAS,R0	;CALCULATE ADDRESS OF OUTPUT MODULE
	MOV	R4,(R0)		;OUTPUT NEW VALUE
 
	.ENDC
 
 
;
; SUCCESSFUL       COMPLETION
;
 
UDSUC:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
UDSUC1:	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS
	BR	UDCMN1		;
 
;
; BAD MODULE NUMBER
;
 
 
	.IF DF	U$$LTM!U$$TIM
 
UDMOD:	MOV	#IE.MOD&377,R0	;SET BAD MODULE NUMBER STATUS
 
	.ENDC
 
 
;
; COMMON FUNCTION EXIT
;
 
UDCMN:	CLR	R1		;CLEAR SECOND I/O STATUS WORD
UDCMN1:	MOV	(SP)+,R3	;RETRIEVE I/O PACKET ADDRESS
	CALLR	$IOFIN		;FINISH I/O OPERATION
 
;+
; **-UDRAD-READ A/D CHANNELS
;
; FUNCTION DEPENDENT I/O P      ACKET FORMAT:
;
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER.
;	WD. 15 -- CONTROL BUFFER ADDRESS.
;	WD. 16 -- NOT USED.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;-
 
 
	.IF DF	U$$ADM
 
UDRAD:	MOV	6(R1),R0	;GET VIRTUAL ADDRESS OF CONTROL BUFFER
 
 
	.IF DF	A$$CHK!M$$MGE
 
	MOV	4(R1),R1	;SET LENGTH OF BUFFER TO CHECK
	CALL	$ACHCK		;ADDRESS CHECK CONTROL BUFFER
	BCS	UDSPC		;IF CS ADDRESS CHECK FAILURE
 
	.ENDC      
 
 
	MOV	(SP)+,R3	;RETRIEVE ADDRESS OF I/O PACKET
	CALL	$RELOC		;RELOCATE CONTROL BUFFER ADDRESS
	MOV	R1,I.PRM+6(R3)	;SET RELOCATION BIAS OF CONTROL BUFFER
	MOV	R2,I.PRM+10(R3)	;SET ADDRESS OF CONTROL BUFFER
	MOV	R3,R1		;SET ADDRESS OF I/O PACKET
	MOV	R4,R0		;SET ADDRESS OF I/O LISTHEAD
	CALL	$QINSP		;INSERT I/O PACKET IN REQUEST QUEUE
 
;+
; **-UNINI-UDC11 ANALOG TO DIGITAL CONVERSION INITIATOR
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT TH      E END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS EXE-
; CUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPERATION
; IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
;
; INPUTS:
;
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUET IS WAIT-
;	ING TO BE PRO      CESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
;	ATION IS INITIATED.
;-
 
	.ENABL	LSB
UDINI:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	20$		;IF CS CONTROLLER BUSY OR NO REQUEST
 
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1=ADDRESS OF THE I/O REQUEST PACKET.
;	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3=CONTROLLER INDEX.
;	R4=ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5=ADDRESS OF THE UCB OF THE UDC11 CONTROLLER.
;
; UDC11 A/D CONVERSION I/O REQUEST PACKET FORM      AT:
;
;	WD. 00 -- I/O QUEUE THREAD WORD.
;	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK.
;	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER.
;	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB).
;	WD. 05 -- I/O FUNCTION CODE (IO.RBC).
;	WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
;	WD. 11       -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD. 12 -- RELOCATION BIAS OF DATA BUFFER.
;	WD. 13 -- DATA BUFFER ADDRESS.
;	WD. 14 -- NUMBER OF BYTES IN DATA BUFFER.
;	WD. 15 -- RELOCATION BIAS OF CONTROL BUFFER.
;	WD. 16 -- CONTROL BUFFER ADDRESS.
;	WD. 17 -- NOT USED.
;	WD. 20 -- NOT USED.
;
; THE DATA BUFFER RECEIVES CONVERTED VALUES AND THE CONTROL BUFFER CONTAINS
; CONTROL WORDS THAT CONTROL THE CONVERSION PROCESS. EACH WORD IN THE CONTROL
; BUFFER HAS THE FORMAT:
;
;	BITS 15-12 -- GAIN CODE      .
;
;		LEGAL GAIN CODES ARE:
;
;		0000=GAIN OF 1.
;		0001=GAIN OF 2.
;		0100=GAIN OF 10.
;		0101=GAIN OF 20.
;		1000=GAIN OF 50.
;		1001=GAIN OF 100.
;		1100=GAIN OF 200.
;		1101=GAIN OF 1000.
;
;	BITS 11-0 -- CHANNEL NUMBER.
;
;		EACH UDC11 MAY HAVE 2016. CHANNELS. THE LEGALITY OF
;		A PARTICULAR CHANNEL NUMBER IS DETERMINED BY THE A/D
;		MODULE TABLE DISCRIPTOR.
;
; EACH CHANNEL IS CONVERTED ACCORDING TO THE CORRESPONDING WORD IN THE CONTROL
; BUFFER AND THE RESULTANT VALUE IS PLACED I      N THE DATA BUFFER. IF AN ILLEGAL
; CONTROL WORD IS DETECTED THEN THE CONVERSION PROCESS IS TERMINATED. THE SECOND
; I/O STATUS WORD SPECIFIES THE NUMBER OF CHANNELS THAT WERE CONVERTED.
;-
 
	MOV	I.PRM+6(R1),U.CBF(R5) ;SET RELOCATION BIAS OF CONTROL BUFFER
	MOV	I.PRM+10(R1),U.CBF+2(R5) ;SET ADDRESS OF CONTROL BUFFER
 
;
; INITIATE I/O OPERATION
;
 
10$:	CALL	$GTCWD		;GET NEXT WORD FROM CONTROL BUFFER
	MOV	#IE.BAD&377,R0	;ASSUME ILLEGAL GAIN OR CHANNEL
	MOV	(SP)+,R1	;RETRIEVE CONTROL WORD
	MOV      	R1,R2		;COPY CONTROL WORD
	BIC	#170000,R1	;CLEAR GAIN CODE BITS
	CMP	R1,ADTBL+MDCNT	;LEGAL CHANNEL NUMBER?
	BHIS	30$		;IF HIS NO
	BIC	R1,R2		;CLEAR CHANNEL NUMBER BITS
	ASL	R2		;ISOLATE GAIN CODE BY DROPPING BIT 13
	ROL	R2		;
	ROL	R2		;
	BCS	30$		;IF CS ILLEGAL GAIN CODE
	ASRB	R2		;DROP BIT 13
	ROR	R2		;SHIFT BITS 15 AND 14 BACK INTO PLACE
	ROR	R2		;
	SEC			;SET CARRY
	ROR	R2		;SHIFT CARRY INTO START CONVERSION
	MOV	R1,R0		;COPY CHANNEL NUMBER
	
	
	.IF EQ	U$$ACH-8.
	
	ASR	R0		;ISOLATE AN      D MERGE CHANNEL NUMBER
	RORB	R2		;WITH GAIN CODE
	ASR	R0		;
	RORB	R2		;
	ASR	R0		;
	RORB	R2		;
	RORB	R2		;SHIFT CHANNEL NUMBER INTO POSITION
	
	.IFF
	
	MOV	#U$$ACH,R1	;GET NUMBER OF CHANNELS PER MODULE
	CALL	$DIV		;CALCULATE MODULE AND CHANNEL NUMBER
	ADD	#8.,R1		;BIAS CHANNEL NUMBER BY 8.
	ASL	R1		;SHIFT CHANNEL NUMBER INTO POSITION
	ASL	R1		;
	ASL	R1		;
	ASL	R1		;
	BIS	R1,R2		;MERGE CHANNEL NUMBER WITH GAIN CODE
	ASL	R0		;CONVERT TO IAD-IA MODULE INDEX
	ASL	R0		;
	ASL	R0		;
	
	.ENDC      
	
	
	ASL	R0		;CONVERT MODULE NUMBER TO WORD INDEX
	ADD	ADTBL+MDBAS,R0	;CALCULATE ADDRESS OF A/D  MODULE
	MOVB	S.ITM(R4),S.CTM(R4) ;SET TIMEOUT COUNT
	MOV	R0,ADMOD	;SAVE ADDRESS OF A/D MODULE
	MOV	R2,(R0)		;START CONVERSION
20$:	RETURN			;
 
;+
; **-UDADI-UDC11 ANALOG TO DIGITAL CONVERSION INTERRUPT
;-
 
UDADI:	TST	(SP)+		;;;REMOVE GENERIC CODE FROM STACK
	MOV	(SP)+,R2	;;;RESTORE R2 AND R3
	MOV	(SP)+,R3	;;;
	CMP	R5,ADMOD	;;;CORRECT MODULE INTERRUPT?
	BNE	40$		;;;IF NE NO
	CLR	ADMOD		;;;CLE      AR A/D MODULE ADDRESS
	MOV	UDUCB,R5	;;;RETRIEVE ADDRESS OF UCB
	CALL	$FORK		;;;CREATE A SYSTEM PROCESS
	MOV	R4,-(SP)	;SET CONVERTED DIGITAL VALUE
	MOV	U.SCB(R5),R4	;GET ADDRESS OF SCB
	CALL	$PTWRD		;PUT CONVERTED VALUE IN DATA BUFFER
	SUB	#2,U.CNT(R5)	;ANY MORE TO CONVERT?
	BGT	10$		;IF GT YES
	MOV	#IS.SUC&377,R0	;
 
;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED WITH A FINAL
; I/O STATUS OF DEVICE NOT READY, THE SECOND I/O STATUS WORD CONTAINS THE NUM-
; BER OF CHANNELS T      HAT WERE SAMPLED BEFORE THE TIMEOUT OCCURRED. TIMEOUTS ARE
; USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE
; FAILURE.
;
 
	.IFTF
 
UDOUT:				;;;REF LABEL
 
	.IFT
 
	CLR	ADMOD		;;;CLEAR A/D MODULE ADDRESS
	CLRB	PS		;;;ALLOW DEVICE INTERRUPTS
30$:	MOV	S.PKT(R4),R3	;GET ADDRESS OF I/O PACKET
	MOV	I.PRM+4(R3),R1	;GET SIZE OF ORIGINAL BUFFER
	SUB	U.CNT(R5),R1	;CALCULATE NUMBER OF BYTES PROCESSED
	ROR	R1		;CONVERT TO NUMBER OF SAMPLES PROCESSED
	CALL	$IODON		;FINISH I/O       OPERATION
	BR	UDINI		;
40$:	JMP	$INTXT		;;;EXIT FROM INTERRUPT
	.DSABL	LSB
 
	.ENDC
 
 
;
; CANCEL I/O OPERATION
;
; THIS ROUTINE IS CALLED TO CANCEL ALL I/O IN PROGRESS FOR THE CURRENT
; TASK. IF THE TASK IS CONNECTED TO EITHER CONTACT OR TIMER INTERRUPTS, THEN
; IT IS DISCONNECTED. ALL A/D INPUT IS ALLOWED TO COMPLETE SINCE IT WILL
; DO SO WITHIN A REASONABLE AMOUNT OF TIME.
;
 
UDCAN:				;;;REF LABEL
 
 
	.IF DF	U$$CIM!U$$TIM
 
	MOV	R1,R0		;;;SET TCB ADDRESS OF CURRENT TASK
 
 
	      .IF DF	U$$CIM
 
	MOV	#CITBL,R3	;;;POINT TO CONTACT INTERRUPT TABLE
 
	.ENDC
 
 
	.IF DF	U$$CIM&U$$TIM
 
	CALL	UDCAN1		;;;DISCONNECT CONTACT INTERRUPTS
 
	.ENDC
 
 
	.IF DF	U$$TIM
 
	MOV	#TMTBL,R3	;;;POINT TO TIMER INTERRUPT TABLE
 
	.ENDC
 
 
UDCAN1:	CMP	R0,CONTK(R3)	;;;CURRENT TASK CONNECTED?
	SEC			;;;ASSUME NO
	BNE	10$		;;;IF NE NO
	CLR	CONTK(R3)	;;;DISCONNECT TASK
	CLR	EFNMK(R3)	;;;CLEAR EVENT FLAG WORD IN CASE A
	CLR	EFNAD(R3)	;;;FORK IS ALREADY QUEUED
	DECB	T.IOC(R0)	;;;DECR      EMENT OUTSTANDING I/O COUNT
 
	.IF DF	D$$SHF
 
	MOV	T.PCB(R0),R1	;;;GET ADDRESS OF TASK PCB
	BIC	#PS.NSF,P.STAT(R1) ;;;ENABLE TASK SHUFFLING
 
	.ENDC
 
 
	.ENDC
 
 
10$:	RETURN			;;;
 
;
; POWERFAILURE IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE
; CAUSES NO IMMEDIATE ACTION ON THE DEVICE. THE UDC11 UNIT CONTROL BLOCK
; ADDRESS IS STORED AND UDC11 INTERRUPTS ARE ENABLED.
;
 
UDPWF:	MOV	R5,UDUCB	;SAVE ADDRESS OF UDC11 UCB
 
 
	.IF DF	U$$ADM!U$$CIM!U$$TIM
 
	MOV	#36,@S.CS      R(R4)	;INITIALIZE UDC11 INTERRUPTS
 
 
	.IF DF	U$$TIM
 
	MOV	#<U$$TIM/256.>&377,R0 ;GET NUMBER OF TIMER MODULES
	MOV	TMTBL+2,R1	;GET ADDRESS OF FIRST TIMER MODULE
	MOV	#TMINI,R2	;GET ADDRESS OF INITIAL VALUE TABLE
10$:	MOV	(R2)+,(R1)+	;SET INITIAL TIMER VALUE
	DEC	R0		;ANY MORE TIMERS TO SET?
	BGT	10$		;IF GT YES
 
	.ENDC
 
 
	.ENDC
 
 
	.IF DF	U$$LTM
 
	MOV	#<U$$LTM/256.>&377,R0 ;GET NUMBER OF LATCHING MODULES
	MOV	LTTBL+2,R1	;GET ADDRESS OF FIRST LATCHING MODULE
	MOV	#LTPRV,R2	;GET A      DDRESS OF PREVIOUS STATE TABLE
20$:	MOV	(R2)+,(R1)+	;RELOAD LATCHING OUTPUT MODULES
	DEC	R0		;ANY MORE TO LOAD?
	BGT	20$		;IF GT YES
 
	.ENDC
 
 
30$:	RETURN			;
 
;+
; **-$UDINT-UDC11 UNIVERSAL DIGITAL INPUT/OUTPUT CONTROLLER INTERRUPTS
;-
 
$UDINT::CALL	$INTSV,PR6	;;;SAVE REGISTERS AND SET PRIORITY
 
 
	.IF DF	U$$ADM!U$$CIM!U$$TIM
 
	MOV	R3,-(SP)	;;;SAVE R3 AND R2
	MOV	R2,-(SP)	;;;
	MOV	#UDCR,R3	;;;GET ADDRESS OF CSR
	BIT	#140000,(R3)	;;;ANY ERRORS?
	BNE	60$		;;;IF NE YES
	TSTB	(R3      )		;;;IMMEDIATE SCAN DONE?
	BMI	10$		;;;IF MI YES
	MOV	-(R3),R2	;;;READ SCAN REGISTER
	BMI	50$		;;;IF MI SCAN DISPLACED
	BR	20$		;;;
10$:	MOV	-(R3),R2	;;;READ SCAN REGISTER
20$:	TST	(R3)+		;;;POINT BACK TO CSR
	CLR	R5		;;;PICKUP INTERRUPTING MODULE NUMBER
	BISB	R2,R5		;;;
	ASL	R5		;;;CALCULATE ADDRESS OF INTERRUPTING
	ADD	#UDMD,R5	;;;MODULE
	BIS	#1,(R3)		;;;SET RIF BIT
	MOV	(R5),R4		;;;READ MODULE DATA RESETTING INTERRUPT
	BIC	#1,(R3)		;;;RESET RIF BIT
	MOV	R2,-(SP)	;;;COPY CONTENTS OF SCAN RE      GISTER
	SWAB	(SP)		;;;SWAP GENERIC CODE TO RIGHT BYTE
	BIC	#^C<7>,(SP)	;;;CLEAR ALL BUT GENERIC CODE
 
 
	.IF DF	U$$ADM
 
	CMP	#7,(SP)		;;;A/D MODULE?
	BEQ	UDADI		;;;IF EQ YES
 
 
	.IF NDF	U$$CIM&U$$TIM
 
	TST	(SP)+		;;;REMOVE GENERIC CODE FROM STACK
 
	.ENDC
 
 
	.ENDC
 
 
	.IF DF	U$$CIM
 
	MOV	#CITBL+2,R3	;;;GET ADDRESS OF CONTACT TABLE
 
	.ENDC
 
 
	.IF DF	U$$CIM&U$$TIM
 
	BIT	#4,(SP)		;;;CONTACT INTERRUPT MODULE?
	BEQ	30$		;;;IF EQ YES
 
	.ENDC
 
 
	.IF DF	U$$TIM
 
      	MOV	#TMTBL+2,R3	;;;GET ADDRESS OF TIMER TABLE
 
	.ENDC
 
 
30$:				;;;REF LABEL
 
 
	.IF DF	U$$CIM!U$$TIM
 
	SUB	(R3),R5		;;;CALCULATE RELATIVE MODULE INDEX
	MOV	R5,-(SP)	;;;CONVERT TO RELATIVE MODULE NUMBER
	ASR	(SP)		;;;
	MOV	R4,-(SP)	;;;SET CURRENT MODULE DATA
 
 
	.IF DF	U$$CIM&U$$TIM
 
	CMP	#TMTBL+2,R3	;;;TIMER MODULE?
	BEQ	70$		;;;IF EQ YES
 
	.ENDC
 
 
;
; CONTACT INTERRUPT MODULE
;
 
 
	.IF DF	U$$CIM
 
	ADD	#CIPRV,R5	;;;POINT TO PREVIOUS MODULE STATE
	BIC	(R5),R4		;;      ;.NOT.PREVIOUS.AND.CURRENT
	BIC	(SP),(R5)	;;;.NOT.CURRENT.AND.PREVIOUS
	BIS	(R5),R4		;;;PREVIOUS.OR.CURRENT
	MOV	(SP),(R5)	;;;SET PREVIOUS VALUE TO CURRENT
	MOV	R4,-(SP)	;;;SET CHANGE OF STATE BITS
	MOV	(R5),R4		;;;RETRIEVE CURRENT VALUE
	COM	R2		;;;COMPLEMENT SCAN REGISTER
	BIT	#60000,R2	;;;BOTH PCL AND POP?
	BEQ	80$		;;;IF EQ YES
	BIT	#40000,R2	;;;PCL?
	BNE	40$		;;;IF NE NO
	COM	R4		;;;COMPLEMENT CURRENT STATE
40$:	BIC	R4,(SP)		;;;CLEAR UNWANTED COS BITS
	BNE	80$		;;;IF NE SOME CHANGED BITS
      	ADD	#10,SP		;;;REMOVE DATA FROM STACK
 
	.ENDC
 
 
	.ENDC
	
	
50$:	BR	140$		;;;TAKE COMMON EXIT
60$:	MOV	#37,(R3)	;;;RESET UDC CONTROLLER
	BIC	#1,(R3)		;;;CLEAR RIF BIT
	BR	140$		;;;TAKE COMMON EXIT
 
;
; TIMER MODULE
;
	
	
	.IF DF	U$$CIM!U$$TIM
 
 
	.IF DF	U$$TIM
 
70$:	MOV	R4,R2		;;;COPY MODULE DATA
	ROL	R2		;;;TEST FOR OVERFLOW TO ZERO
	BVS	80$		;;;IF VS NO OVERFLOW
	TST	CONTK-2(R3)	;;;TASK CONNECTED?
	BEQ	80$		;;;IF EQ NO
	MOV	R5,R2		;;;COPY RELATIVE INDEX
	ADD	(R3),R5		;;;      CALCULATE ADDRESS OF TIMER MODULE
	MOV	TMINI(R2),(R5)	;;;RELOAD TIMER MODULE
 
	.ENDC
 
 
;
; COMMON EXIT FOR CONTACT AND TIMER MODULES
;
 
80$:	MOVB	NMBYT-2(R3),R2	;;;GET NUMBER OF BYTES OF DATA
	MOV	#1,-(SP)	;;;SET EXISTANCE INDICATOR
	TST	CONTK-2(R3)	;;;TASK CONNECTED?
	BEQ	130$		;;;IF EQ NO
 
 
	.IF DF	M$$MGE
 
	MOV	KISAR6,R5	;;;SAVE CURRENT MAPPING
	MOV	CURBF-2(R3),KISAR6 ;;;MAP TO USER BUFFER
 
	.IFTF
 
	MOV	CURBF+6-2(R3),R4 ;;;GET CURRENT BUFFER ADDRESS
	TST	(R4)		;;;BUFFER EN      TRY FREE?
	BNE	120$		;;;IF NE NO
	CLR	LSCNT-2(R3)	;;;CLEAR LOST DATA COUNT
	ASR	R2		;;;CONVERT BYTE COUNT TO WORD COUNT
90$:	MOV	(SP)+,(R4)+	;;;PUT DATA IN USER BUFFER
 
	.IFT
 
	BIT	#20000,R4	;;;OVERFLOW 4K BOUNDRY?
	BEQ	100$		;;;IF EQ NO
	BIC	#20000,R4	;;;RESET TO APR6 ADDRESS
	ADD	#200,CURBF-2(R3) ;;;ADVANCE TO NEXT 4K BLOCK
	ADD	#200,KISAR6	;;;ADVANCE TO NEXT 4K BLOCK
 
	.IFTF
 
100$:	INC	CURNX-2(R3)	;;;INCREMENT FORTRAN INDEX
	CMP	BFLGH-2(R3),CURNX-2(R3) ;;;END OF BUFFER?
	BHIS	110$		      ;;;IF HIS NO
	MOV	#3,CURNX-2(R3)	;;;RESET CURRENT FORTRAN INDEX
 
	.IFT
 
	MOV	STRBF-2(R3),CURBF-2(R3) ;;;RESET CURRENT RELOCATION BIAS
	MOV	CURBF-2(R3),KISAR6 ;;;RESET CURRENT APR6 BIAS
 
	.IFTF
 
	MOV	STRBF+6-2(R3),R4 ;;;RESET CURRENT BUFFER ADDRESS
110$:	DEC	R2		;;;ANY MORE DATA?
	BGT	90$		;;;IF GT YES
	MOV	R4,CURBF+6-2(R3) ;;;SAVE CURRENT BUFFER ADDRESS
 
	.IFT
 
	MOV	STRBF-2(R3),KISAR6 ;;;MAP TO START OF BUFFER
 
	.IFTF
 
	MOV	CURNX-2(R3),@BUFAD-2(R3) ;;;SET FORTRAN INDEX
 
	.IFT      
 
	MOV	R5,KISAR6	;;;RESTORE CURRENT MAPPING
 
	.IFTF
 
	TSTB	STATS-2(R3)	;;;FORK ALREADY IN PROGRESS?
	BNE	150$		;;;IF NE NO
	BR	140$		;;;
120$:	ADD	#LSCNT-2,R3	;;;POINT TO LOST DATA COUNT
	CMP	#100001,(R3)	;;;MAXIMUM VALUE?
	BEQ	125$		;;;IF EQ YES
	DEC	(R3)		;;;DECREMENT LOST DATA COUNT
125$:	MOV	(R3),(R4)	;;;SET LOST DATA COUNT
 
	.IFT
 
	MOV	R5,KISAR6	;;;RESTORE CURRENT MAPPING
 
	.ENDC
 
 
130$:	ADD	R2,SP		;;;REMOVE ENTRIES FROM STACK
 
	.ENDC
 
 
140$:	MOV	(SP)+,R2	;;;RESTOR      E R2 AND R3
	MOV	(SP)+,R3	;;;
 
	.ENDC
 
 
	JMP	$INTXT		;;;EXIT FROM INTERRUPT
 
;
; CREATE FORK PROCESS AND WAKE UP TASK
;
 
 
	.IF DF	U$$CIM!U$$TIM
 
150$:	CLRB	STATS-2(R3)	;;;SET FORK IN PROGRESS
	MOV	R3,R4		;;;COPY DATA CONTROL BLOCK ADDRESS
	MOV	R3,R5		;;;
	ADD	#FRBLK+6-2,R4	;;;POINT TO FORK BLOCK
	MOV	(SP)+,R2	;;;RESTORE R2 AND R3
	MOV	(SP)+,R3	;;;
	CALL	$FORK1		;;;CREATE A SYSTEM PROCESS
	INCB	STATS-2(R5)	;CLEAR FORK IN PROGRESS FLAG
	MOV	CONTK-2(R5),R0	;GET CONNECTED TASK TCB    Ø   ADDRESS
	BIT	#T2.ABO,T.ST2(R0) ;TASK BEING ABORTED?
	BNE	160$		;IF NE YES
	BIS	EFNMK-2(R5),@EFNAD-2(R5) ;SET SPECIFIED EVENT FLAG
160$:	CALLR	$SETCR		;SET A CONDITIONAL SCHEDULE REQUEST
 
	.ENDC
 
 
	.END
 Ø          ä—ðskQ	› c,        	.TITLE XLDRV
	.IDENT	/12.1/
;
;
; COPYRIGHT (C) 1974, 1976, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 12.1
;
; J. M. GILBERT, 31-MAR-74
;
; PREVIOUSLY MODIFIED BY:
;
;	S. G. DAVIS
;	J. M. GILBERT
;	L. GILLESPIE
;	E. D. WALDIN
;
; MODIFIED BY:
;
;	R. E. CALDWELL	30-OCT-79
;
;		RC024 -- REMOVE UNNEEDED CONDITIONALIZATION.
;
; DL11 ASYN      CHRONOUS COMMUNICATIONS DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$,PKTDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	.MCALL	UCBDF$,CUCDF$
	UCBDF$			; DEFINE UCB OFFSETS
	CUCDF$			;COMMUNICATIONS UCB LABELS

;
; CONFIGURATION DEPENDENT PARAMETERS
;

MDMCTL=	0			;SET IF DL-11E (MODEM CONTROL)		;**-1

;
; EQUATED SYMBOLS
;

;
; RXCSR BIT ASSIGNMENTS
;

DTSTCH=	100000			;DATA SET CHANGE
RING=	 40000			;RING LINE ASSERTED
CTS=	 20000			;CLEAR TO       SEND
CRRIER=	 10000			;CARRIER STATE
RECACT=	  4000			;RECEIVER ACTIVE
RXDONE=	   200			;RECEIVER DONE
RCVENB=	   100			;RECEIVER INTERRUPT ENABLE
DSINTE=	    40			;DATA SET CHANGE INTERRUPT ENABLE
RTS=	     4			;REQUEST TO SEND
TRMRDY=	     2			;DATA TERMINAL READY

;
; RXDBUF BIT ASSIGNMENTS
;

RXERR=	100000			;RECEIVER ERROR "OR" BIT
OVRNER=	 40000			;RECEIVER OVERRUN ERROR IF SET
FRMERR=	 20000			;RECEIVER FRAMING ERROR

;
; TXCSR BIT ASSIGNMENTS
;

TXRDY=	   200			;TRANSMITTER DONE       BIT
TXINTE=	   100			;TRANSMITTER INTERRUPT ENABLE BIT
BREAK=	     1			;CLAMP OUTPUT TO SPACE

;
; LOCAL DATA
;
;
; UNIT IMPURE DATA TABLE (INDEXED BY UNIT, POINTS TO UCB)
;

CNTBL:				;REF LABEL
UNITBL:				;UCB ADDRESSES
	.REPT	D$$E11
	.WORD	0		;ENSURE SET TO ZERO
	.ENDM

	.IF GT	D$$E11-1

TEMP:				;REF LABEL
UNIT:	.BLKW	1		;TEMPORARY STORAGE FOR UNIT NUMBER

	.ENDC


	.ENABL	LSB

;
; DRIVER DISPATCH TABLE
;

$XLTBL::.WORD	DLINIT		;DEVICE INITIALIZATION
	.WORD	DLCANC		;DEVI      CE I/O CANCELLATION
	.WORD	DLTMO		;TIMEOUT ENTRY POINT
	.WORD	DLPWRF		;POWER FAIL ROUTINE
;+
;**-  DLINIT - DL-11 SYNCHRONOUS COMMUNICATION CONTROLLER I/O INITIATOR
;
; DLINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE,
; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE
; NORMAL RSX-11M INPUT/OUTPUT LOGIC FLOW.  IF THE DEVICE IS
; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT,
; THE REQUEST IS INITIATED.
; IF NO REQUEST EXISTS FOR THAT UNIT OR IF IT IS
; BUSY, AN EXIT IS T      AKEN TO THE CALLER.  NOTE  THAT BECAUSE OF
; THE NATURE OF THE DL-11, EACH UNIT IS A CONTROLLER ITSELF,
; HAS ITS OWN SCB, AND THEREFORE ITS OWN QUEUE.
; EACH TIME DLINIT IS CALLED, IT IS CALLED TO SERVICE ONLY
; THE UNIT SPECIFIED IN THE CALL. NOTE ALSO THAT ONLY
; 8-BIT, NO PARITY DATA IS SUPPORTED.
; MESSAGE SYNCHRONIZATION IS PROVIDED BY PRECEDING KEY
; MESSAGES WITH A SYNC TRAIN, MUCH AS WITH A SYNCHRONOUS
; DEVICE.  THE DIFFERENCE, OF COURSE, IS THAT THIS SYNC
; TRAIN IS SOLELY FOR MESSAGE SY      NCHRONIZATION.  THE LEADING
; SYNC TRAIN IS UNDER PROGRAM CONTROL, AS IT IS WITH THE
; RSX-11M SYNCHRONOUS LINE CONTROLLERS.
;
; INPUTS:
;
;	R4 = STATUS CONTROL BLOCK ADDRESS
;	R5 = ADDRESS OF THE UCB TO BE INITIATED.
;
; OUTPUTS:
;
;	IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE
;	DEVICE IS INITIATED APPROPRIATELY.
;-

DLINIT:	TSTB	U.CW2(R5)	;UNSOLICITED (HDPX) RECEIVE ACTIVE?
	BMI	15$		;IF SET, NOTHING TO DO - EXIT
	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCS	15$		;NO REQUEST OR UNIT BU      SY
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1 = ADDRESS OF THE I/O REQUEST PACKET.
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3 = CONTROLLER INDEX
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5 = ADDRESS OF THE UCB SPECIFIED IN THE
;	     DLINIT CALL.
;
; DL11 I/O REQUEST PACKET FORMAT
;
;	WORD	     CONTENT
;
;	  0	I/O QUEUE THREAD WORD
;	  1	REQUEST PRIORITY, EVENT FLAG NUMBER
;	  2	ADDRESS OF THE TCB OF THE REQUESTER TASK
;	  3	POINTER TO SECOND LUN WORD IN TAS      K HEADER
;	  4	CONTENTS OF FIRST LUN WORD (UCB)
;	  5	I/O FUNCTION CODE
;	  6	VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	  7	RELOCATION BIAS OF I/O STATUS BLOCK
;	 10	I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)
;	 11	VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	 12	RELOCATION BIAS OF I/O BUFFER
;	 13	BUFFER ADDRESS FOR TRANSFER
;	 14	TOTAL BYTE COUNT TO TRANSFER
;	 15	BYTE COUNT FOR SECOND PART OF TRANSMISSION OR 0
;	 16	NOT USED
;	 17	NOT USED
;	 20	NOT USED
;

	MOV	S.CSR(R4),R2	;GET REC      EIVER CSR ADDRESS
	ADD	#I.FCN+1,R1	;POINT TO I/O FUNCTION CODE
	CMPB	#IO.INL/256.,(R1) ;CHECK IF TRANSFER FUNCTION
	BLOS	40$		;BRANCH ON CONTROL FUNCTION
	BIT	#U2.ONL,U.CW2(R5) ;IS DEVICE ON LINE (INITIALIZED?)
	BEQ	50$		;CAN'T TRANSFER IF NOT
	CMPB	#IO.RLB/256.,(R1) ;READ LOGICAL?
	BEQ	20$		;YES, SERVICE READ REQUEST
;
; FALL THROUGH ON TRANSMIT (WRITE LOGICAL)
;
	MOVB	S.ITM(R4),S.CTM(R4) ;INITIALIZE TIMEOUT COUNT		;**-8
	MOVB	U.NSYN(R5),R3	;NO. OF SYNCS IN LEADER
	BITB	#IO.WNS,-(R1)	;TRANSPAR      ENT WRITE?
	BEQ	5$		;IF EQ NO
	CLR	R3		;SHOW NO SYNCS
5$:	MOVB	R3,U.NSYC(R5)	;SET NO. OF SYNCS NEEDED


	.IF DF	MDMCTL

	BIT	#CTS,(R2)	;CLEAR TO SEND SET YET?
	BNE	10$		;IF SO, START TRANSMITTING
	BIS	#U2.CTS,U.CW2(R5) ;SAY CLEAR TO SEND EXPECTED
	BIS	#RTS!DSINTE,(R2) ;ASSERT REQUEST TO SEND
	BR	140$		;RETURN - INTERRUPT PROPAGATES TRANSFER

	.ENDC


10$:	BIS	#TXINTE,4(R2)	;ENABLE TRANSMITTER
15$:	BR	140$		;RETURN, INTERRUPT PROPAGATES TX

;
; RECEIVE FUNCTION INITIATION
;

20$:				;      REFERENCE LABEL
	BIC	#U2.FTM!U2.SYC,U.CW2(R5) ; ASSUME TRANSPARENT OP	;**-4
	BITB	#IO.RNS,-(R1)	;TRANSPARENT READ?
	BNE	30$		;IF NE YES
	BIS	#U2.FTM!U2.SYC,U.CW2(R5) ;NON-TRANSPARENT READ
30$:				;REF LABEL
	MOV	R5,R0		;SET UP TRANSFER VECTOR
	ADD	#U.RBUF,R0	;RECEIVE TRANSFER INFORMATION HERE
	MOV	U.BUF(R5),(R0)+	;TRANSFER BIAS
	MOV	U.BUF+2(R5),(R0)+ ;AND VIRTUAL ADDRESS
	MOV	U.CNT(R5),(R0)	;AND COUNT
	TSTB	2(R2)		; CLEAR RECEIVE BUFFER STATUS
	BIS	#RCVENB,(R2)	; ENABLE RECEIVER
	BR	140$		;RETU      RN - INTERRUPT CODE PROPAGATES RECEIVE
;									;**-8
; CONTROL FUNCTION INITIATION (INITIATE OR TERMINATE CONTROLLER,
; OR CHANGE OPERATING MODE)
;

40$:	BNE	70$		;IF NOT EQUAL, MODE CHANGE REQUEST
	CLR	(R2)		;CLEAR RXCSR
	TSTB	-(R1)		;START FUNCTION?
	BNE	60$		;IF NON-ZERO, TERMINATE
;
; DO START FUNCTION INITIATION
;


	.IF DF	MDMCTL

	BIS	#TRMRDY,(R2)	;INITIALIZE CONTROLLER

	.ENDC


	MOV	R5,UNITBL(R3)	;INITIALIZE UCB ADDRESS IN UNIT TABLE
	BIS	#U2.ONL,U.CW2(R5) ;MARK UNIT ON LIN      E
	BIC	#U2.SYC,U.CW2(R5) ;CLEAR RECEIVER SYNC COUNT
	BR	120$		;RETURN SUCCESSFUL

;
; CAN'T ESTABLISH COMMUNICATIONS
;

50$:	MOV	#IE.DNR&377,R0	;SAY CAN'T INITIALIZE DEVICE (NOT READY)
	BR	130$		;DO I/O DONE

;
; FUNCTION WAS TERMINATE LINE
;

60$:	BIC	#^C<U2.LIN!U2.SWC!U2.ACU>,U.CW2(R5) ;CLEAR OPERATING STATUS
	CLR	UNITBL(R3)	;UNIT TABLE CLEARED OF UCB
	BR	120$		;RETURN SUCCESSFUL STATUS

;
; SERVICE DEVICE MODE CHANGE REQUEST
;

70$:	BITB	#IO.HDX,-(R1)	; SUBFUNCTION SAY HALF DUPLEX?      
	BEQ	80$		;IF ZERO, NO
	BIS	#U2.HDX,U.CW2(R5) ;SAY HALF DUPLEX CHARACTERISTIC
80$:	BITB	#IO.FDX,(R1)	;SET MODE TO FULL DUPLEX?
	BEQ	110$		;DON'T SET FULL DUPLEX
	BIT	#U2.LIN,U.CW2(R5) ;IS LINK FULL DUPLEX?
	BEQ	100$		;IF SO, RUN FULL DUPLEX
90$:	MOV	#IE.IFC&377,R0 ;MARK AS ILLEGAL FUNCTION
	BR	130$		;AND TERMINATE

100$:	BIC	#U2.HDX,U.CW2(R5) ;PUT IN FULL DUPLEX IN UCB

110$:	BITB	#IO.SYN,(R1)	;SYNC CHARACTER SPECIFIED?
	BEQ	120$		;NO, IF NOT SET
	MOVB	I.PRM-I.FCN(R1),U.SYNC(R5) ;RESET SYNC C      HARACTER
DLSUCC:				;REFERENCE LABEL
120$:	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS
DLFIN:				;REFERENCE LABEL
130$:	CLRB	S.STS(R4)	;CLEAR CONTROLLER STATUS
	BICB	#US.BSY,U.STS(R5) ;CLEAR UNIT STATUS
	MOV	R0,-(SP)	;SAVE STATUS WORD 1
	MOV	S.PKT(R4),-(SP)	;SAVE PACKET ADDRESS
	CALL	DLINIT		;ATTEMPT TO INITIATE SOMETHING
	MOV	(SP)+,R3	;RESTORE PACKET ADDRESS
	MOV	I.PRM+4(R3),R1	;RETURN REQUESTED COUNT
	MOV	(SP)+,R0	;RESTORE STATUS WORD 1
	CALLR	$IOFIN		;TERMINATE LAST PACKET

140$:	RETURN
      
;
; POWER FAIL SERVICE
;

DLPWRF:				;REFERENCE LABEL
	CLRB	S.CTM(R4)	;DISABLE TIMEOUTS			;**-8
	BR	50$		;FINISH I/O
;									;**-3
; I/O CANCELLATION
;

DLCANC:				;;;REFERENCE LABEL
	CMP	R1,I.TCB(R0)	;;;CANCEL FOR THIS TASK?		;**-7
	BNE	140$		;;;JUST RETURN IF NOT
	CMPB	#IO.WLB/256.,I.FCN+1(R0) ;;;WAS FUNCTION TRANSMIT?
	BEQ	140$		;;;JUST LET FINISH IF YES
	TST	U.RCNT(R5)	;;;RECEIVE FINISHED?
	BLE	140$		;;;BR IF YES
	BIC	#RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER
	MOV	#IE.ABO&377,R0	;;;PU      T ERROR CODE IN R0
	CLR	U.RCNT(R5)	;;;MARK COUNT SATISFIED
	BR	150$		;;;FINISH OFF I/O
;									;**-4
; TIMEOUT SERVICE ROUTINE
;
;	INPUTS:
;
;		R0 = DEVICE TIMEOUT STATUS 'IE.DNR'
;		R3 = CONTROLLER INDEX
;		R4 = ADDRESS OF SCB
;		R5 = ADDRESS OF UCB
;

DLTMO:				;;;TIMEOUT ENTRY POINT
	MOV	S.CSR(R4),R3	;;;GET RECEIVER CSR
	BIC	#TXINTE,4(R3)	;;;DISABLE TRANSMITTER

	.IF DF	MDMCTL

	BIC	#RTS!DSINTE,(R3);;;CLEAR RTS AND DATA SET ENABLE
	BIC	#U2.CTS,U.CW2(R5);;;CLEAR WAITING FOR CTS

	      .ENDC

150$:				;;;REFERENCE LABEL
	MTPS	#0		;;;ALLOW INTERRUPTS
	JMP	DLTXND		;;;WAIT FOR SOFTWARE TIMEOUT TO FINISH
	.DSABL	LSB

;
; **- $XLINP - DL-11 INPUT INTERRUPT SERVICE
;

$XLINP::			;;;REFERENCE LABEL
	INTSV$	XL,PR5,D$$E11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DLSET		;;;SET CSR IN R4, UCB IN R5
	MOV	(R4),-(SP)	;;;SAVE CSR, TEST DATA SET CHANGE	;**-11


	.IF DF	MDMCTL

	BPL	10$		;;;NO DATA SET CHANGE, IF NOT SET
	BIT	#U2.CTS,U.CW2(R5) ;;;CTS EXPECTED?
	BEQ	5$		;;;NO, IF NOT SET      
	BIT	#CTS,(R4)	;;;CLEAR TO SEND?
	BEQ	10$		;;;NO, CHECK ON ERROR
	BIS	#TXINTE,4(R4)	;;;ENABLE TRANSMITTER INTERRUPT
	BIC	#U2.CTS,U.CW2(R5) ;;;HAVE CTS
5$:	BIC	#DSINTE,(R4)	;;;DISABLE DATA SET INTERRUPTS

	.IFTF

10$:	MOV	2(R4),R4	;;;CAPTURE BUFFER REGISTER IN R4
	.ENDC								;**-10


20$:	TSTB	(SP)+		;;;RECEIVER DONE?
	BPL	70$		;;;IF NOT, DISMISS INTERRUPT
	TST	U.RCNT(R5)	;;;COUNT ALREADY SATISFIED?
	BLE	70$		;;;IF SO, DISMISS INTERRUPT
	BIT	#U2.FTM,U.CW2(R5) ;;;IN MESSAGE SYNCH?
	BEQ	60      $		;;;IF NOT SET, YES
	CMPB	U.SYNC(R5),R4	;;;IS CHARACTER A SYNC?			;**-17
	BNE	30$		;;;IF NOT, MAY BE DATA
	BIT	#U2.SYC,U.CW2(R5) ;;;WERE WE SYNCHING?
	BEQ	70$		;;;ALREADY SYNCHED - JUST DISCARD
	DECB	U.CW2(R5)	;;;DECREMENT RECEIVER SYNC COUNT
	RETURN			;;;DISMISS INTERRUPT

30$:	BIT	#U2.SYC,U.CW2(R5) ;;;COUNT SATISFIED?
	BEQ	50$		;;;YES, IF EQUAL
	BISB	#2,U.CW2(R5)	;;;TRY TO SYNC AGAIN
	RETURN			;;;DISMISS INTERRUPT
50$:	BIC	#U2.FTM,U.CW2(R5) ;;;NOW PAST LEADING SYNCS		;**-3
60$:				;;;REFERE      NCE LABEL



	.IF DF M$$MGE							; RC024
									;**-1
	MOV	KISAR6,-(SP)	;;;SAVE CURRENT MAPPING
	MOV	U.RBUF(R5),KISAR6 ;;;MAP TO USER BUFFER
	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER
	MOV	(SP)+,KISAR6	;;;RESTORE CURRENT MAPPING


	.IFF

	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER

	.IFTF

	DEC	U.RCNT(R5)	;;;SEE IF COUNT SATISFIED
	BEQ	80$		;;;YES, IF EQUAL
	INC	U.RBUF+2(R5)	;;;BUMP BYTE ADDRESS

	.IFT

	BIT	#20000,U.RBUF+2(R5) ;;;OVERFLOWED 4K BOUNDARY?
	BEQ	70$      		;;;NO, IF ZERO
	BIC	#20000,U.RBUF+2(R5) ;;;CLEAR OVERFLOW BIT
	ADD	#200,U.RBUF(R5)	;;;BUMP BIAS

	.ENDC


70$:				;;;REFERENCE LABEL
	RETURN			;;;EXIT INTERRUPT			;**-9

;
; REQUEST SATISFIED
;

80$:				;;;REFERENCE LABEL
	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS			;**-3
	BIC	#RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER
	CALL	$FORK		;;;GO TO FORK LEVEL
	JMP	DLSUCC		;FINISH I/O SUCESSFUL
;
; **- $XLOUT - TRANSMITTER INTERRUPT SERVICE
;

$XLOUT::			;;;REFERENCE LABEL
	INTSV$	XL,PR5,D$$E11	;;;G      ENERATE INTERRUPT SAVE CODE
	CALL	DLSET		;;;SET RECEIVE CSR IN R4, UCB IN R5
	ADD	#6,R4		;;; POINT TO TRANSMITTER BUFFER
;
; SET UP AND TRANSMIT A BYTE
;
	DECB	U.NSYC(R5)	;;;DECREMENT LEADING SYNC COUNT
	BLT	10$		;;;IF LT GO TO DATA
	MOVB	U.SYNC(R5),(R4)	;;;SEND ANOTHER SYNC CHARACTER
	BR	30$		;;;RESET TIMEOUT, EXIT

10$:	INCB	U.NSYC(R5)	;;; OFFSET DECREMENT ABOVE
	DEC	U.CNT(R5)	;;; CHECK COUNT
	BGE	20$		;;;IF GE,  CONTINUE
	TST	U.CW2(R5)	;;;IN HALF DUPLEX?			;**-3
	BPL	50$		;;;IF NOT, NO LIN      E TURNAROUND
	CMP	#-3,U.CNT(R5)	;;;SENT 2 MARKS?			;**-10
	BGE	40$		;;;IF SO, TURN LINE AROUND
	MOVB	#-1,(R4)	;;;SEND A MARK
	BR	30$		;;;DISMISS INTERRUPT

20$:	CALL	$GTBYT		;;;GET NEXT BYTE FROM BUFFER
	MOVB	(SP)+,(R4)	;;;OUTPUT CHARACTER
30$:	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS BACK
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
	RETURN			;;;EXIT INTERRUPT

40$:				;;;REFERENCE LABEL


	.IF DF	MDMCTL

	BIC	#RTS,-6(R4)	;;;CLR REQUEST TO SEND

	.ENDC

50$:	BIC	#TXINTE,-(R4)	;;;DISABLE       TRANSMITTER			;**-9
	CALL	$FORK		;;;CREATE SYSTEM PROCESS
	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS		;**-3
DLTXND:				;REFERENCE LABEL			;**-3
	MOV	U.SCB(R5),R4	;RESTORE SCB TO R4			;**-10
	JMP	DLFIN		;MARK COMPLETION
;									;**-49
; DLSET - SET UP REGISTER R4 WITH CSR ADDRESS, R5 WITH
;	UCB ADDRESS.  UNIT NUMBER IN LOW ORDER 4 BITS OF UNIT.
;

DLSET:				;;;REFERENCE LABEL
	TST	R5		;;;CHECK FOR UCB ADDRESS
	BEQ	10$		;;;IF NO UCB, TROUBLE
	BIT	#U2.ONL,U.CW2(R5) ;;;UNIT ON LINE?
	BEQ	1   þ   0$		;;;IF NOT ON LINE, NONSENSE
	MOV	U.SCB(R5),R4	;;;FIRST GET SCB ADDRESS
	MOV	S.CSR(R4),R4	;;;NOW DEVICE CSR ADDRESS
	RETURN			;;;AND NOW RETURN

10$:	TST	(SP)+		;;;CLEAR STACK OF RETURN ADDRESS
DLSXT:	JMP	$INTXT		;;;DISMISS INTERRUPT

	.END
 þ          „˜ðskQ	› c,        	.TITLE XPDRV
	.IDENT	/13.1/
 
;
; COPYRIGHT (C) 1974, 1976, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 13.1
;
; J. M. GILBERT, 31-JAN-74
;
; PREVIOUSLY MODIFIED BY:
;
;	J. M. GILBERT
;	L. GILLESPIE
;	E. D. WALDIN
;
; MODIFIED BY:
;
;	R. E. CALDWELL	30-OCT-79
;
;		RC024 -- REMOVE UNNEEDED CONDITIONALIZATION.
;
; DP11 SYNCHRONOUS COMMUNI      CATIONS DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	PKTDF$,HWDDF$
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	.MCALL	UCBDF$,CUCDF$
	UCBDF$			; DEFINE UCB OFFSETS
	CUCDF$			;COMMUNICATIONS UCB LABELS

;
; CONFIGURATION DEPENDENT PARAMETERS
;

									;**-1
;
; EQUATED SYMBOLS
;

;
; RXCSR BIT ASSIGNMENTS
;

RECACT=   4000			;RECEIVER ACTIVE (IN SYNCH)
RCVENB=	   100			;RECEIVER INTERRUPT ENABLE
HDPX=	     2			;HALF DUPLEX IF SET
STRSYN=	     1			;STR      IP SYNC CHARACTERS

;
; TXCSR BIT ASSIGNMENTS
;

CRRTRN=	100000			;CARRIER TRANSITION FLAG
OVRNER=	 40000			;RECEIVER OVERRUN IF SET
RING=	 20000			;RING ASSERTED
DSRDY=	 10000			;DATA SET (MODEM) READY
CRRIER=	  4000			;CARRIER STATE FLAG
CTS=	  2000			;CLEAR TO SEND
RTS=	  1000			;REQUEST TO SEND
TXDONE=	   200			;TRANSMITTER DONE BIT
TXINTE=	   100			;TRANSMITTER INTERRUPT ENABLE
STINTE=	    40			;STATUS INTERRUPT ENABLE
IDLSYN=	     2			;IDLE SYNC CHARACTERS
TRMRDY=	     1			;DATA TERMI      NAL READY

;
; LOCAL DATA
;
;
; UNIT IMPURE DATA TABLE (INDEXED BY UNIT, POINTS TO UCB)
;

CNTBL:				;REF LABEL
UNITBL:				;UCB ADDRESSES
	.REPT	D$$P11		;NUMBER OF UNITS ASSIGNED
	.WORD	0		;INITIALIZE TO 0
	.ENDM

	.IF GT	D$$P11-1

TEMP:				;REF LABEL
UNIT:	.BLKW	1		;TEMPORARY STORAGE FOR UNIT NUMBER

	.ENDC


	.ENABL	LSB

;
; DRIVER DISPATCH TABLE
;

$XPTBL::.WORD	DPINIT		;DEVICE INITIALIZATION
	.WORD	DPCANC		;DEVICE I/O CANCELLATION
	.WORD	DPTMO		;TIMEOUT ENTRY POINT
	.WORD      	DPPWRF		;POWER FAIL ROUTINE
;+
;**-  DPINIT - DP-11 SYNCHRONOUS COMMUNICATION CONTROLLER I/O INITIATOR
;
; DPINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE,
; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE
; NORMAL RSX-11M INPUT/OUTPUT LOGIC FLOW.  IF THE DEVICE IS
; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT,
; THE REQUEST IS INITIATED.
; IF NO REQUEST EXISTS FOR THAT UNIT OR IF IT IS
; BUSY, AN EXIT IS TAKEN TO THE CALLER.  NOTE  THAT BECAUSE OF
; THE NATURE OF THE       DP-11, EACH UNIT IS A CONTROLLER ITSELF,
; HAS ITS OWN SCB, AND THEREFORE ITS OWN QUEUE.
; EACH TIME DPINIT IS CALLED, IT IS CALLED TO SERVICE ONLY
; THE UNIT SPECIFIED IN THE CALL.
;
; INPUTS:
;
;	R4 = STATUS CONTROL BLOCK ADDRESS
;	R5 = ADDRESS OF THE UCB TO BE INITIATED.
;
; OUTPUTS:
;
;	IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE
;	DEVICE IS INITIATED APPROPRIATELY.
;-

DPINIT:	TSTB	U.CW2(R5)	 ;UNSOLICITED (HDPX) RECEIVE ACTIVE?
	BPL	10$		;IF NOT, PROCEED
	JMP	180$		;ACTIVATE NO NEW OP      ERATION

10$:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCC	20$		;CC MEANS HAVE REQUEST
	JMP	180$		;NONE TO DO - EXIT
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1 = ADDRESS OF THE I/O REQUEST PACKET.
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3 = CONTROLLER INDEX
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5 = ADDRESS OF THE UCB SPECIFIED IN THE
;	     DPINIT CALL.
;
; DP11 I/O REQUEST PACKET FORMAT
;
;	WORD	     CONTENT
;
;	  0	I/O QUEUE THREAD WORD
;	  1	REQ      UEST PRIORITY, EVENT FLAG NUMBER
;	  2	ADDRESS OF THE TCB OF THE REQUESTER TASK
;	  3	POINTER TO SECOND LUN WORD IN TASK HEADER
;	  4	CONTENTS OF FIRST LUN WORD (UCB)
;	  5	I/O FUNCTION CODE
;	  6	VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	  7	RELOCATION BIAS OF I/O STATUS BLOCK
;	 10	I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)
;	 11	VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	 12	RELOCATION BIAS OF I/O BUFFER
;	 13	BUFFER ADDRESS FOR TRANSFER
;	 14	TOTAL BYTE COUNT TO TRANSFER
;	 15	BYTE CO      UNT FOR SECOND PART OF TRANSMISSION OR 0
;	 16	NOT USED
;	 17	NOT USED
;	 20	NOT USED
;

20$:	MOV	S.CSR(R4),R2	;GET RECEIVER CSR ADDRESS
	ADD	#I.FCN+1,R1	;POINT TO I/O FUNCTION CODE
	CMPB	#IO.INL/256.,(R1) ;CHECK IF TRANSFER FUNCTION
	BLOS	70$		;BRANCH ON CONTROL FUNCTION
	BIT	#U2.ONL,U.CW2(R5) ;IS DEVICE ON LINE (INITIALIZED?)
	BEQ	90$		;CAN'T TRANSFER IF NOT
	BIT	#DSRDY,4(R2)	;DATA SET READY?			;**-3
	BEQ	90$		;NO, IF BIT NOT SET
	CMPB	#IO.RLB/256.,(R1) ;READ LOGICAL?			;**-3
	BEQ	40$		;YES      , SERVICE READ REQUEST
;
; FALL THROUGH HERE ON TRANSMIT (WRITE LOGICAL)
;
	ADD	#6,R2		;POINT TO TX BUFFER			;**-9
	MOVB	U.SYNC(R5),R0	;LOAD FIRST SYNC
	MOVB	S.ITM(R4),S.CTM(R4) ;INITIALIZE TIMEOUT COUNT
	MOVB	U.NSYN(R5),R3	;SYNC COUNT
30$:	MOVB	R3,U.NSYC(R5)	;SET COUNT OF SYNCS TO ISSUE		;**-13
	MOVB	R0,(R2)		;ISSUE A CHARACTER
	BIS	#IDLSYN!TXINTE,-(R2)	;ENABLE INTERRUPTS ON DEVICE
	BR	180$		;RETURN - INTERRUPT CODE PROPAGATES TRANSMISSION

;
; RECEIVE FUNCTION INITIATION
;

40$:				;REFER      ENCE LABEL
	MOV	R5,R0		;SET UP TRANSFER VECTOR			;**-4
	ADD	#U.RBUF,R0	;RECEIVE TRANSFER INFORMATION HERE
	MOV	U.BUF(R5),(R0)+	;TRANSFER BIAS
	MOV	U.BUF+2(R5),(R0)+ ;AND OFFSET
	MOV	U.CNT(R5),(R0)	;AND COUNT
	BIC	#RECACT,(R2)	;FORCE RESYNCHING
	BIS	#STRSYN!RCVENB,(R2) ; ENABLE RECEIVER
	BR	180$		;RETURN - INTERRUPT CODE PROPAGATES RECEIVE
;									;**-8
; CONTROL FUNCTION INITIATION (INITIATE OR TERMINATE CONTROLLER,
; OR CHANGE OPERATING MODE)
;

70$:	BNE	110$		;IF NOT EQUAL, MODE CHANGE REQ      UEST
	TSTB	-(R1)		;START FUNCTION?
	BNE	100$		;IF NON-ZERO, TERMINATE
;
; DO START FUNCTION INITIATION
;
	MOV	#STRSYN,(R2)	;NOW INITIALIZE CONTROLLER
	TST	U.CW2(R5)	;HALF DUPLEX MODE SELECTED?
	BPL	80$		;NO, IF PLUS
	BIS	#HDPX,(R2)	;PUT DEVICE IN HALF DUPLEX
80$:	MOV	#TRMRDY,4(R2)	;PUT TRANSMITTER ON LINE
	MOVB	U.SYNC(R5),3(R2) ;INITIALIZE SYNC CHARACTER
	MOV	R5,UNITBL(R3)	;INITIALIZE UCB ADDRESS IN UNIT TABLE
	BIS	#U2.ONL,U.CW2(R5) ;MARK UNIT ON LINE
	BR	160$		;RETURN SUCCESSFUL

;
; CAN'T       ESTABLISH COMMUNICATIONS
;

90$:	MOV	#IE.DNR&377,R0	;SAY CAN'T INITIALIZE DEVICE (NOT READY)
	BR	170$		;DO I/O DONE

;
; FUNCTION WAS TERMINATE LINE
;

100$:	CLR	(R2)		;CLEAR UNIT READY
	CLR	4(R2)		;CLEAR TRANSMIT CSR
	BIC	#^C<U2.LIN!U2.SWC!U2.ACU>,U.CW2(R5) ;CLEAR OPERATING STATUS
	CLR	UNITBL(R3)	;UNIT TABLE CLEARED OF UCB
	BR	160$		;RETURN SUCCESSFUL STATUS

;
; SERVICE DEVICE MODE CHANGE REQUEST
;

110$:	BITB	#IO.HDX,-(R1)	;SUBFUNCTION SAY HALF DUPLEX?
	BEQ	120$		;IF ZERO, NO
	BIS	      #U2.HDX,U.CW2(R5) ;SAY HALF DUPLEX CHARACTERISTIC
120$:	BITB	#IO.FDX,(R1)	;SET MODE TO FULL DUPLEX?
	BEQ	150$		;DON'T SET FULL DUPLEX
	BIT	#U2.LIN,U.CW2(R5) ;IS LINE CAPABLE OF FULL DUPLEX?
	BEQ	140$		;YES, IF BIT NOT SET
130$:	MOV	#IE.IFC&377,R0	;SET ILLEGAL FUNCTION CODE
	BR	170$		;AND RETURN ERROR STATUS

140$:	BIC	#U2.HDX,U.CW2(R5) ;PUT IN FULL DUPLEX IN UCB
150$:	BITB	#IO.SYN,(R1)	;SYNC CHARACTER SPECIFIED?
	BEQ	160$		;NO, IF NOT SET
	MOVB	I.PRM-I.FCN(R1),U.SYNC(R5) ;MARK NEW SYNC CHARACTER      
DPSUCC:				;REFERENCE LABEL
160$:	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS
DPFIN:				;REFERENCE LABEL
170$:	CLRB	S.STS(R4)	;IDLE CONTROLLER
	BICB	#US.BSY,U.STS(R5) ;AND MARK UNIT IDLE
	MOV	R0,-(SP)	;SAVE STATUS WORD 1
	MOV	S.PKT(R4),-(SP)	;SAVE OLD PACKET ADDRESS
	CALL	DPINIT		;TRY TO ACTIVATE ANOTHER REQUEST
	MOV	(SP)+,R3	;GET OLD I/O PACKET
	MOV	I.PRM+4(R3),R1	;RETURN REQUESTED ITEM COUNT
	MOV	(SP)+,R0	;GET STATUS WORD 1
	CALLR	$IOFIN		;TERMINATE OLD PACKET

180$:	RETURN


;
; POWER       FAIL SERVICE
;

DPPWRF:				;REFERENCE LABEL
	CLRB	S.CTM(R4)	;CLEAR DEVICE TIMEOUT COUNT		;**-8
	MOV	#IE.DNR&377,R0	;PUT ERROR CODE IN R0 FOR DPTMO
	BR	DPTMO		;FINISH I/O ABORT
;									;**-4
; I/O CANCELLATION ENTRY
;

;	INPUTS:
;		R0=I/O PACKET ADDRESS
;		R1=TCB ADDRESS OF TASK TO CANCEL
;		R4=SCB ADDRESS
;		R5=UCB ADDRESS

DPCANC:				;;;REFERENCE LABEL
	CMP	R1,I.TCB(R0)	;;;CANCEL FOR THIS TASK?		;**-7
	BNE	180$		;;;DON'T CANCEL IF NOT
	CMPB	#IO.WLB/256.,I.FCN+1(R0) ;;;IS FUNCTION TRA      NSMIT?
	BEQ	180$		;;;JUST LET TRANSMIT FINISH
	TST	U.RCNT(R5)	;;;RECEIVE FINISHEED?
	BLE	180$		;;;DON'T CANCEL IF YES
	BIC	#RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER
	MOV	#IE.ABO&377,R0	;;;PUT ERROR CODE IN R0 FOR DPTMO
	BR	DPTMO		;;;FINISH OFF RECEIVE PACKET
;									;**-4
; TIMEOUT SERVICE ROUTINE
;
;	INPUTS:
;
;		R0 = DEVICE TIMEOUT STATUS 'IE.DNR'
;		R3 = CONTROLLER INDEX
;		R4 = ADDRESS OF SCB
;		R5 = ADDRESS OF UCB
;

DPTMO:	MOV	S.CSR(R4),R4	;;;GET DEVICE CSR
	BIC	#TXINTE!IDLSYN,4(R4)       ;;;DISABLE TRANSMITTER
	MTPS	#0		;;;ALLOW INTERRUPTS
210$:	JMP	DPTXND		;WAIT FOR SOFTWARE TIMEOUT

	.DSABL LSB

;
; **- $XPINP - DP-11 INPUT INTERRUPT SERVICE
;

	.ENABL	LSB

$XPINP::			;;;REFERENCE LABEL
	INTSV$	XP,PR5,D$$P11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DPSET		;;;SET CSR IN R4, UCB IN R5
	BIC	#STRSYN,(R4)+	;;;CLEAR STRIP SYNC MODE		;**-11
	MOV	(R4),R4		;;;GET RECEIVED CHARACTER
									;**-3
	.IF DF M$$MGE							; RC024
									;**-1
	MOV	KISAR6,-(SP)	;;;SAVE CURRENT MAPPIN      G
	MOV	U.RBUF(R5),KISAR6 ;;;MAP TO USER BUFFER
	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER
	MOV	(SP)+,KISAR6	;;;RESTORE CURRENT MAPPING


	.IFF

	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER

	.IFTF

	DEC	U.RCNT(R5)	;;;SEE IF COUNT SATISFIED
	BEQ	20$		;;;YES, IF EQ
	INC	U.RBUF+2(R5)	;;;BUMP BYTE ADDRESS

	.IFT

	BIT	#20000,U.RBUF+2(R5) ;;;OVERFLOWED 4K BOUNDARY?
	BEQ	10$		;;;NO, IF ZERO
	BIC	#20000,U.RBUF+2(R5) ;;;CLEAR OVERFLOW BIT
	ADD	#200,U.RBUF(R5)	;;;BUMP BIAS

	.E      NDC
									;**-9
10$:	RETURN			;;;EXIT FROM INTERRUPTS

;
; REQUEST SATISFIED
;

20$:				;;;REFERENCE LABEL
	MOV	U.SCB(R5),R4 ;;;GET DEVICE SCB ADDRESS			;**-33
	BIC	#RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVE INTERRUPTS
	CALL	$FORK		;;;CREATE A FORK PROCESS
	JMP	DPSUCC		;END I/O SUCCESSFUL
									;**-3
	.DSABL	LSB


;
; **- $XPOUT - TRANSMITTER INTERRUPT SERVICE
;

$XPOUT::			;;;REFERENCE LABEL
	INTSV$	XP,PR5,D$$P11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DPSET		;;;SET RECEIVE CSR IN R4      , UCB IN R5
	ADD	#4,R4		;;;POINT TO TX CSR
	BIT	#CRRTRN!OVRNER!RING,(R4)+ ;;;ANY TRANSITIONS MADE?
	BEQ	20$		;;;IF NOT, CHECK TRANSMIT INTERRUPT
10$:	BIC	#OVRNER!CRRTRN!RING,-(R4) ;;;CLEAR STATUS TRANSITION BIT;**-14
	TSTB	(R4)+		;;;TRANSMITTER FLAG SET?
	BPL	60$		;;;IF NOT, DISMISS INTERRUPT
	INC	R4		;;;POINT TO TRANSMITTER BUFFER
20$:	TSTB	U.NSYC(R5)	;;;SYNC COUNT 0?
	BEQ	30$		;;;IF SO, TRANSMIT
	DECB	U.NSYC(R5)	;;;DECREMENT LEADING SYNC COUNT
	BLE	40$		;;;IF LE, BEGIN TRANSMITTING
	MOVB	U.SYN      C(R5),(R4)	;;;SEND ANOTHER SYNC
	BR	50$		;;;AND EXIT

;
; SET UP AND TRANSMIT A BYTE
;

30$:	DEC	U.CNT(R5)	;;;CHECK COUNT (0 NOT VALID)
	BLE	70$		;;;IF LE, COUNT SATISFIED
40$:	CALL	$GTBYT		;;;GET NEXT BYTE FROM BUFFER
	MOVB	(SP)+,(R4)	;;;OUTPUT CHARACTER
50$:	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS BACK
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
60$:	BR	DPSXT		;;;EXIT FROM INTERRUPT

;
; COUNT SATISFIED - TERMINATE TRANSMISSION
;

70$:	BIC	#TXDONE!TXINTE,-(R4) ;;;DISABLE TRANSMITTER
      
	TST	U.CW2(R5)	 ;;;IN HALF DUPLEX?			;**-3
	BPL	80$		;;;IF PLUS NO
	BIC	#IDLSYN,(R4)	;;;DON'T GO TO IDLE SYNC
	CMP	-(R4),-(R4)	;;;POINT TO RECEIVER CSR
	BIC	#RECACT,(R4)	;;;FORCE RE-SYNCHING
80$:	CALL	$FORK		;;;CREATE SYSTEM PROCESS		;**-11
	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS		;**-3
DPTXND:				;REFERENCE LABEL			;**-3
	MOV	U.SCB(R5),R4	;RESTORE SCB TO R4			;**-10
	JMP	DPFIN		;MARK COMPLETION
;
; DPSET - SET UP REGISTER R4 WITH CSR ADDRESS, R5 WITH
; UCB ADDRESS.  UNIT NUMBER IN LOW O   ®  RDER 4 BITS OF UNIT.
;



DPSET:				;;;REFERENCE LABEL
	TST	R5		;;;CHECK FOR UCB ADDRESS
	BEQ	10$		;;;IF NO UCB, TROUBLE
	BIT	#U2.ONL,U.CW2(R5) ;;;UNIT ON LINE?
	BEQ	10$		;;;IF NOT ON LINE, NONSENSE
	MOV	U.SCB(R5),R4	;;;FIRST GET SCB ADDRESS
	MOV	S.CSR(R4),R4	;;;NOW DEVICE CSR ADDRESS
	RETURN			;;;AND NOW RETURN

10$:	TST	(SP)+		;;;CLEAR STACK OF RETURN ADDRESS
DPSXT:	JMP	$INTXT		;;;DISMISS INTERRUPT

	.END
 ®         L™ðskQ	› c,        	.TITLE XUDRV
	.IDENT	/14.1/
 
;
; COPYRIGHT (C) 1974, 1978, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 14.1
;
; J. M. GILBERT, 31-JAN-74
;
; PREVIOUSLY MODIFIED BY:
;
;	J. M. GILBERT
;	L. GILLESPIE
;	E. D. WALDIN
;
; MODIFIED BY:
;
;	J. H. MATTHEWS 19-OCT-77
;
;		JM001 -- MODIFIED TRANSMIT LINE TO IDLE WITH MARK
;			 INSTEAD OF SYNC.
;      
;	R. E. CALDWELL	30-OCT-79
;
;		RC024 -- REMOVE UNNEEDED CONDITIONALIZATION.
;
; DU11 SYNCHRONOUS COMMUNICATIONS DRIVER
;
; MACRO LIBRARY CALLS
;

	.MCALL	PKTDF$,HWDDF$
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	.MCALL	UCBDF$,CUCDF$
	UCBDF$			; DEFINE UCB OFFSETS
	CUCDF$			;COMMUNICATIONS UCB LABELS

;
; CONFIGURATION DEPENDENT PARAMETERS
;

									;**-1

;
; EQUATED SYMBOLS
;

;
; RXCSR BIT ASSIGNMENTS
;

DTSTCH=	100000			;DATA SET CHANGE
      RING=	 40000			;RING LINE ASSERTED
CTS=	 20000			;CLEAR TO SEND
CRRIER=	 10000			;CARRIER STATE
RECACT=	  4000			;RECEIVER ACTIVE
DSRDY=	  1000			;DATA SET READY
STRSYN=	   400			;STRIP SYNC
RXDONE=	   200			;RECEIVER DONE
RCVENB=	   100			;RECEIVER INTERRUPT ENABLE
DSINTE=	    40			;DATA SET CHANGE INTERRUPT ENABLE
SCHSYN=	    20			;SEARCH SYNC MODE BIT
RTS=	     4			;REQUEST TO SEND
TRMRDY=	     2			;DATA TERMINAL READY

;
; RXDBUF BIT ASSIGNMENTS
;

RXERR=	100000			;RECEIVER ERROR "OR" B      IT
OVRNER=	 40000			;RECEIVER OVERRUN ERROR IF SET

;
; PARCSR INITIALIZATION VALUES
;

INTSYN=	 30000			;INTERNAL SYNC MODE PATTERN
WRDLEN=	  6000			;WORD LENGTH (8 BITS STANDARD)
PARENB=	     0			;NO PARITY CHECKING
PARSEN=      0	 		;PARITY SENSE (DEPENDS ON PARENB)
INITMD=	INTSYN!WRDLEN!PARENB!PARSEN ;ALL INITIALIZATION PARAMETERS

;
; TXCSR BIT ASSIGNMENTS
;

DNAINT=	100000			;SET ON DATA NOT AVAILABLE INTERRUPT
MSTRST=	   400			;MASTER DEVICE RESET
TXDONE=	   200			;TRANSMITTER DONE       BIT
TXINTE=	   100			;TRANSMITTER INTERRUPT ENABLE BIT
DNAEN=	    40			;ENABLE DATA NOT AVAILABLE INTERRUPT
SEND=	    20			;TRANSMITTER ENABLE (GO) BIT
HDPX=	    10			;HALF DUPLEX IF SET

;
; LOCAL DATA
;
;
; UNIT IMPURE DATA TABLE (INDEXED BY UNIT, POINTS TO UCB)
;

CNTBL:				;REF LABEL
UNITBL:				;UCB ADDRESS TABLE
	.REPT	D$$U11		;ONE ENTRY PER UNIT
	.WORD	0
	.ENDM

	.IF GT	D$$U11-1

TEMP:				;REF LABEL
UNIT:	.BLKW	1		;TEMPORARY STORAGE FOR UNIT NUMBER

	.ENDC


	.ENABL	LSB

      ;
; DRIVER DISPATCH TABLE
;

$XUTBL::.WORD	DUINIT		;DEVICE INITIALIZATION
	.WORD	DUCANC		;DEVICE I/O CANCELLATION
	.WORD	DUTMO		;TIMEOUT ENTRY POINT
	.WORD	DUPWRF		;POWER FAIL ROUTINE
;+
;**-  DUINIT - DU-11 SYNCHRONOUS COMMUNICATION CONTROLLER I/O INITIATOR
;
; DUINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE,
; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE
; NORMAL RSX-11M INPUT/OUTPUT LOGIC FLOW.  IF THE DEVICE IS
; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT,
      ; THE REQUEST IS INITIATED.
; IF NO REQUEST EXISTS FOR THAT UNIT OR IF IT IS
; BUSY, AN EXIT IS TAKEN TO THE CALLER.  NOTE  THAT BECAUSE OF
; THE NATURE OF THE DU-11, EACH UNIT IS A CONTROLLER ITSELF,
; HAS ITS OWN SCB, AND THEREFORE ITS OWN QUEUE.
; EACH TIME DUINIT IS CALLED, IT IS CALLED TO SERVICE ONLY
; THE UNIT SPECIFIED IN THE CALL.
;
; INPUTS:
;
;	R4 = STATUS CONTROL BLOCK ADDRESS
;	R5 = ADDRESS OF THE UCB TO BE INITIATED.
;
; OUTPUTS:
;
;	IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE
;      	DEVICE IS INITIATED APPROPRIATELY.
;-

DUINIT:	TSTB	U.CW2(R5)	;UNSOLICITED (HDPX) RECEIVE ACTIVE?
	BPL	10$		;IF NOT, PROCEED
	JMP	180$		;ACTIVATE NO NEW OPERATION

10$:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCC	20$		;IF CC, SOMETHING TO DO
	JMP	180$		;NO REQUEST OR UNIT BUSY
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1 = ADDRESS OF THE I/O REQUEST PACKET.
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3 = CONTROLLER INDEX
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK.
      ;	R5 = ADDRESS OF THE UCB SPECIFIED IN THE
;	     DUINIT CALL.
;
; DU11 I/O REQUEST PACKET FORMAT
;
;	WORD	     CONTENT
;
;	  0	I/O QUEUE THREAD WORD
;	  1	REQUEST PRIORITY, EVENT FLAG NUMBER
;	  2	ADDRESS OF THE TCB OF THE REQUESTER TASK
;	  3	POINTER TO SECOND LUN WORD IN TASK HEADER
;	  4	CONTENTS OF FIRST LUN WORD (UCB)
;	  5	I/O FUNCTION CODE
;	  6	VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	  7	RELOCATION BIAS OF I/O STATUS BLOCK
;	 10	I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)      
;	 11	VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	 12	RELOCATION BIAS OF I/O BUFFER
;	 13	BUFFER ADDRESS FOR TRANSFER
;	 14	TOTAL BYTE COUNT TO TRANSFER
;	 15	BYTE COUNT FOR SECOND PART OF TRANSMISSION OR 0
;	 16	NOT USED
;	 17	NOT USED
;	 20	NOT USED
;

20$:	MOV	S.CSR(R4),R2	;GET RECEIVER CSR ADDRESS
	ADD	#I.FCN+1,R1	;POINT TO I/O FUNCTION CODE
	CMPB	#IO.INL/256.,(R1) ;CHECK IF TRANSFER FUNCTION
	BLOS	70$		;BRANCH ON CONTROL FUNCTION
	BIT	#U2.ONL,U.CW2(R5) ;IS DEVICE ON LINE (INITIALIZED?)
	BE      Q	90$		;CAN'T TRANSFER IF NOT
	BIT	#DSRDY,(R2)	;IS DATA SET READY?			;**-3
	BEQ	90$		;IF NOT, CAN'T TRANSFER
	CMPB	#IO.RLB/256.,(R1) ;READ LOGICAL?			;**-3
	BEQ	40$		;YES, SERVICE READ REQUEST
;
; FALL THROUGH HERE ON TRANSMIT (WRITE LOGICAL)
;
	BIS	#RTS,(R2)	;ASSERT REQUEST TO SEND			;**-8
	MOVB	U.SYNC(R5),R0	;LOAD SYNC CHARACTER
	MOVB	S.ITM(R4),S.CTM(R4) ;INITIALIZE TIMEOUT COUNT
	MOVB	U.NSYN(R5),R3	;NUMBER OF SYNCS IN LEADER
30$:	MOVB	R3,U.NSYC(R5)	;LOAD SYNC LEADER COUNT			;**-15
	ADD	#4,R2      		;POINT TO TRANSMIT CSR
	BIS	#SEND,(R2)+	;ENABLE TRANSMISSION
	MOVB	R0,(R2)		;SEND FIRST CHARACTER
	TST	-(R2)		;CLEAR DATA LATE ERRORS
	BIS	#DNAEN!TXINTE,(R2) ;ENABLE INTERRUPTS
	BR	180$		;RETURN - INTERRUPT CODE PROPAGATES TRAN

;
; RECEIVE FUNCTION INITIATION
;

40$:				;REFERENCE LABEL
	MOV	R5,R0		;SET UP TRANSFER VECTOR			;**-4
	ADD	#U.RBUF,R0	;RECEIVE TRANSFER INFORMATION HERE
	MOV	U.BUF(R5),(R0)+	;TRANSFER BIAS
	MOV	U.BUF+2(R5),(R0)+ ;AND OFFSET
	MOV	U.CNT(R5),(R0)	;AND COUNT
	BIC	#S      CHSYN,(R2)	;FORCE RE-SYNCHING
	TSTB	2(R2)		; ENSURE RECEIVE BUFFER CLEAR
	BIS	#STRSYN!RCVENB!SCHSYN,(R2) ; ENABLE RECEIVER
	BR	180$		;RETURN - INTERRUPT CODE PROPAGATES RECEIVE
;									;**-8
; CONTROL FUNCTION INITIATION (INITIATE OR TERMINATE CONTROLLER,
; OR CHANGE OPERATING MODE)
;

70$:	BNE	110$		;IF NOT EQUAL, MODE CHANGE REQUEST
	CMP	(R2)+,(R2)+	;POINT TO TXCSR
	BIS	#MSTRST,(R2)	;RESET DEVICE
	TSTB	-(R1)		;START FUNCTION?
	BNE	100$		;IF NON-ZERO, TERMINATE
;
; DO START FUNCTION INITIA      TION
;
	TST	U.CW2(R5)	;DEVICE TO BE IN HALF DUPLEX?
	BPL	80$		;NO, IF PLUS
	BIS	#HDPX,(R2)	;PUT IN HALF DUPLEX MODE
80$:	MOV	#INITMD,R0	;GET WORD SIZE, SYNC MODE
	BISB	U.SYNC(R5),R0	;OR IN SYNC CHARACTER
	MOV	R0,-(R2)	;INITIALIZE DEVICE PARAMETERS
	BIS	#STRSYN!TRMRDY!SCHSYN,-(R2) ;NOW INITIALIZE CONTROLLER
	MOV	R5,UNITBL(R3)	;INITIALIZE UCB ADDRESS IN UNIT TABLE
	BIS	#U2.ONL,U.CW2(R5) ;MARK UNIT ON LINE
	BR	160$		;RETURN SUCCESSFUL

;
; CAN'T ESTABLISH COMMUNICATIONS
;

90$:	MOV	#IE.DNR&377      ,R0	;SAY CAN'T INITIALIZE DEVICE (NOT READY)
	BR	170$		;DO I/O DONE

;
; FUNCTION WAS TERMINATE LINE
;

100$:	BIC	#^C<U2.LIN!U2.SWC!U2.ACU>,U.CW2(R5) ;CLEAR OPERATING STATUS
	CLR	UNITBL(R3)	;UNIT TABLE CLEARED OF UCB
	BR	160$		;RETURN SUCCESSFUL STATUS

;
; SERVICE DEVICE MODE CHANGE REQUEST
;

110$:	BITB	#IO.HDX,-(R1)	;SUBFUNCTION SAY HALF DUPLEX?
	BEQ	120$		;IF ZERO, NO
	BIS	#U2.HDX,U.CW2(R5) ;SAY HALF DUPLEX CHARACTERISTIC
120$:	BITB	#IO.FDX,(R1)	;SET MODE TO FULL DUPLEX?
	BEQ	150$		;D      ON'T SET FULL DUPLEX
	BIT	#U2.LIN,U.CW2(R5) ;IS LINK FULL DUPLEX?
	BEQ	140$		;IF SO, RUN FULL DUPLEX
130$:	MOV	#IE.IFC&377,R0	;MARK AS ILLEGAL FUNCTION
	BR	170$		;AND TERMINATE

140$:	BIC	#U2.HDX,U.CW2(R5) ;PUT IN FULL DUPLEX IN UCB
150$:	BITB	#IO.SYN,(R1)	;SYNC CHARACTER SPECIFIED?
	BEQ	160$		;NO, IF NOT SET
	MOVB	I.PRM-I.FCN(R1),U.SYNC(R5) ;MARK NEW SYNC CHARACTER
DUSUCC:				;REFERENCE LABEL
160$:	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS
DUFIN:				;REFERENCE LABEL
170$:	CLRB	S.STS(R4)	;CL      EAR CONTROLLER STATUS
	BICB	#US.BSY,U.STS(R5) ;MARK UNIT IDLE, ALSO
	MOV	R0,-(SP)	;SAVE STATUS WORD 1
	MOV	S.PKT(R4),-(SP)	;SAVE OLD PACKET ADDRESS
	CALL	DUINIT		;INITIATE NEXT PACKET
	MOV	(SP)+,R3	;GET OLD PACKET ADDRESS
	MOV	I.PRM+4(R3),R1	;RETURN REQUESTED ITEM COUNT
	MOV	(SP)+,R0	;RESTORE STATUS WORD 1
	CALLR	$IOFIN		;TERMINATE OLD PACKET

180$:	RETURN			;

;
; POWER FAIL SERVICE
;

DUPWRF:				;REFERENCE LABEL
	CLRB	S.CTM(R4)	;DISABLE DEVICE TIMEOUTS		;**-8
	MOV	#IE.DNR&377,R0	;PUT ERR      OR CODE IN R0 FOR DUTMO
	BR	DUTMO		;FINISH I/O ABORT
;									;**-3
; I/O CANCELLATION SERVICE
;

;	INPUTS:
;		R0=I/O PACKET ADDRESS
;		R1=TCB ADDRESS OF TASK TO CANCEL
;		R4=SCB ADDRESS
;		R5=UCB ADDRESS

DUCANC:				;;;REFERENCE LABEL
	CMP	R1,I.TCB(R0)	;;;CANCEL FOR THIS TASK?		;**-7
	BNE	180$		;;;JUST RETURN IF NOT
	CMPB	#IO.WLB/256.,I.FCN+1(R0) ;;;TRANSMIT FUNCTION?
	BEQ	180$		;;;LET TRANSMIT FINISH
	TST	U.RCNT(R5)	;;;RECEIVER FINISHED?
	BLE	180$		;;;RETURN IF YES
	BIC	#RCVENB!SCHSYN,      @S.CSR(R4) ;DISABLE RECEIVER
	MOV	#IE.ABO&377,R0	;;;PUT ERROR CODE IN R0 FOR DUTMO
	BR	DUTMO		;;;FINISH OFF RECEIVE PACKET
;									;**-4
; TIMEOUT SERVICE ROUTINE
;
;	INPUTS:
;
;		R0 = DEVICE TIMEOUT STATUS 'IE.DNR'
;		R3 = CONTROLLER INDEX
;		R4 = ADDRESS OF SCB
;		R5 = ADDRESS OF UCB
;

DUTMO:				;;;REFERENCE LABEL
	MOV	S.CSR(R4),R4	;GET RECEIVER CSR
	BIC	#TXINTE!SEND!DNAEN,4(R4) ;;;DISABLE TRANSMITTER
	BIC	#RTS,(R4)	;;;TURN OFF CARRIER
	MTPS	#0		;;;ALLOW INTERRUPTS
210$:	JMP	DUTXND		      ;WAIT FOR SOFTWARE TIMEOUT

	.DSABL LSB

;
; **- $XUINP - DU-11 INPUT INTERRUPT SERVICE
;

$XUINP::			;;;REFERENCE LABEL
	INTSV$	XU,PR5,D$$U11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DUSET		;;;SET CSR IN R4, UCB IN R5
	BIC	#STRSYN,(R4)+	;;; EXIT STRIP SYNC MODE		;**-11
	MOV	(R4),R4		;;;CONTENTS OF RCV BUFFER IN R4

	.IF DF M$$MGE							; RC024
									;**-12
	MOV	KISAR6,-(SP)	;;;SAVE CURRENT MAPPING
	MOV	U.RBUF(R5),KISAR6 ;;;MAP TO USER BUFFER
	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER B      UFFER
	MOV	(SP)+,KISAR6	;;;RESTORE CURRENT MAPPING


	.IFF

	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER

	.IFTF

	DEC	U.RCNT(R5)	;;;SEE IF COUNT SATISFIED
	BEQ	30$		;;;YES, IF EQUAL
	INC	U.RBUF+2(R5)	;;;BUMP BYTE ADDRESS

	.IFT

	BIT	#20000,U.RBUF+2(R5) ;;;OVERFLOWED 4K BOUNDARY?
	BEQ	20$		;;;NO, IF ZERO
	BIC	#20000,U.RBUF+2(R5) ;;;CLEAR OVERFLOW BIT
	ADD	#200,U.RBUF(R5)	;;;BUMP BIAS

	.ENDC
									;**-10
20$:	RETURN			;;;EXIT FROM INTERRUPT

;
; REQUEST SATISFIED
;

3      0$:				;REFERENCE LABEL
	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS			;**-31
	BIC	#RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER
	CALL	$FORK		;;;GO TO FORK LEVEL
	JMP	DUSUCC		;COMPLETE SUCCESSFUL I/O

;
; **- $XUOUT - TRANSMITTER INTERRUPT SERVICE
;

$XUOUT::			;;;REFERENCE LABEL
	INTSV$	XU,PR5,D$$U11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DUSET		;;;SET RECEIVE CSR IN R4, UCB IN R5
	ADD	#4,R4		;;;POINT TO TX CSR
	TST	(R4)+		;;;DATA NOT AVAILABLE?
	BPL	10$		;;;NO, IF NOT SET

;
; CHECK DATA LATE
;
	TSTB      	-2(R4)		;;;TRANSMITTER DONE SET?		;**-21
	BPL	60$		;;;IF NOT, DISMISS INTERRUPT
10$:	BIT	#CTS,-6(R4)	;;;CLEAR TO SEND SET?
	BEQ	20$		;;;IF NOT, SEND A SYNC
	TSTB	U.NSYC(R5)	;;;SYNC COUNT ZERO?
	BEQ	30$		;;;IF YES, TRANSMIT DATA
	DECB	U.NSYC(R5)	;;;DECREMENT SYNC LEADER COUNT
	BLE	30$		;;;IF LE, TRANSMIT DATA
20$:	MOVB	U.SYNC(R5),(R4)	;;;SEND A SYNC CHARACTER
	BR	50$		;;;EXIT


;
; SET UP AND TRANSMIT A BYTE
;
30$:	DEC	U.CNT(R5)	;;;CHECK COUNT (0 NOT VALID)
	BGE	40$		;;;IF NOT, CONTINUE
	TS      T	U.CW2(R5)	;;;IN HALF DUPLEX?
	BPL	80$		;;;IF NOT, NO TURNAROUND
	CMP	#-3,U.CNT(R5)	;;;SENT TWO MARKS?			;**-8
	BGE	70$		;;;IF SO, TURN LINE AROUND
	MOVB	#-1,(R4)	;;;OUTPUT A MARK
	BR	50$		;;;DISMISS INTERRUPT

40$:	CALL	$GTBYT		;;;GET NEXT BYTE FROM BUFFER
	MOVB	(SP)+,(R4)	;;;OUTPUT CHARACTER
50$:	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS BACK
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
60$:	BR	DUSXT		;;;EXIT FROM INTERRUPT

70$:	BIC	#SEND,-(R4)	;;;DON'T IDLE SYNC
	TST	-(R4)		;;;CLEAR RECEIVE       DONE AND ERROR
	BIC	#SCHSYN!RTS,-(R4) ;;;TURN OFF CARRIER
	BIS	#SCHSYN,(R4)	;;;FORCE RESYNCHIBNG			;**-7
	ADD	#6,R4		;;;POINT TO TRANSMIT BUFFER		;**-3
80$:	BIC	#TXINTE!DNAEN!SEND,-(R4) ;;;DISABLE TRANSMITTER
	CALL	$FORK		;;;CREATE SYSTEM PROCESS
	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS		;**-3
DUTXND:				;REFERENCE LABEL			;**-3
	MOV	U.SCB(R5),R4	;RESTORE SCB TO R4			;**-10
	JMP	DUFIN		;MARK COMPLETION
;
; DUSET - SET UP REGISTER R4 WITH CSR ADDRESS, R5 WITH
;	UCB ADDRESS.  UNIT NUMBER IN   ¾   LOW ORDER 4 BITS OF UNIT.
;



DUSET:				;;;REFERENCE LABEL
	TST	R5		;;;TEST FOR VALID UCB ADDRESS
	BEQ	10$		;;;IF NO UCB, TROUBLE
	BIT	#U2.ONL,U.CW2(R5) ;;;UNIT ON LINE?
	BEQ	10$		;;;IF NOT ON LINE, CAN'T TRANSFER
	MOV	U.SCB(R5),R4	;;;FIRST GET SCB ADDRESS
	MOV	S.CSR(R4),R4	;;;NOW DEVICE CSR ADDRESS
	RETURN			;;;AND NOW RETURN

10$:	TST	(SP)+		;;;CLEAR STACK OF RETURN ADDRESS
DUSXT:	JMP	$INTXT		;;;DISMISS INTERRUPT

	.END
¾         œ™ðskQ	› c,        	.TITLE XWDRV
	.IDENT	/1.1/
 
;
; COPYRIGHT (C) 1976, 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 1.1
;
; SCOTT G. DAVIS	21-JUL-76
;
; DUE ALMOST ENTIRELY TO XUDRV
;
;
; DUP11 SYNCHRONOUS COMMUNICATIONS DRIVER
;
; MODIFIED BY
;
;	R. E. CALDWELL	30-OCT-79
;
;		RC024 -- REMOVE UNNEEDED CONDITIONALIZATION.
;
; MACRO LIBRARY CALLS
;

	.MCA      LL	PKTDF$,HWDDF$
	PKTDF$			;DEFINE I/O PACKET OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	.MCALL	UCBDF$,CUCDF$
	UCBDF$			; DEFINE UCB OFFSETS
	CUCDF$			;COMMUNICATIONS UCB LABELS

;
; CONFIGURATION DEPENDENT PARAMETERS
;

									;**-1

;
; EQUATED SYMBOLS
;

;
; RXCSR BIT ASSIGNMENTS
;

DTSTCH=	100000			;DATA SET CHANGE
RING=	 40000			;RING LINE ASSERTED
CTS=	 20000			;CLEAR TO SEND
CRRIER=	 10000			;CARRIER STATE
RECACT=	  4000			;RECEIVER ACTIVE
DSRDY=	  1000			;DATA SET REA      DY
STRSYN=	   400			;STRIP SYNC
RXDONE=	   200			;RECEIVER DONE
RCVENB=	   100			;RECEIVER INTERRUPT ENABLE
DSINTE=	    40			;DATA SET CHANGE INTERRUPT ENABLE
SCHSYN=	    20			;SEARCH SYNC MODE BIT
RTS=	     4			;REQUEST TO SEND
TRMRDY=	     2			;DATA TERMINAL READY

;
; RXDBUF BIT ASSIGNMENTS
;

RXERR=	100000			;RECEIVER ERROR "OR" BIT
OVRNER=	 40000			;RECEIVER OVERRUN ERROR IF SET

;
; PARCSR INITIALIZATION VALUES
;

DECMOD=	100000			;SET DDCMP/BISYNCH MODE
CRCINH=1000			;INHIBIT CRC       CALCULATION
INITMD=DECMOD!CRCINH		;PARAMETER INITIALIZATION BITS

;

TSOM=400			;TRANSFER - START OF MESSAGE

;
;
; TXCSR BIT ASSIGNMENTS
;

DNAINT=	100000			;SET ON DATA NOT AVAILABLE INTERRUPT
MSTRST=	   400			;MASTER DEVICE RESET
TXDONE=	   200			;TRANSMITTER DONE BIT
TXINTE=	   100			;TRANSMITTER INTERRUPT ENABLE BIT
DNAEN=	    40			;ENABLE DATA NOT AVAILABLE INTERRUPT
SEND=	    20			;TRANSMITTER ENABLE (GO) BIT
HDPX=	    10			;HALF DUPLEX IF SET

;
; LOCAL DATA
;
;
; UNIT IMPUR      E DATA TABLE (INDEXED BY UNIT, POINTS TO UCB)
;

CNTBL:				;REF LABEL
UNITBL:				;UCB ADDRESS TABLE
	.REPT	D$$W11		;ONE ENTRY PER UNIT
	.WORD	0
	.ENDM

	.IF GT	D$$W11-1

TEMP:				;REF LABEL
UNIT:	.BLKW	1		;TEMPORARY STORAGE FOR UNIT NUMBER

	.ENDC

	.ENABL	LSB

;
; DRIVER DISPATCH TABLE
;

$XWTBL::.WORD	DWINIT		;DEVICE INITIALIZATION
	.WORD	DWCANC		;DEVICE I/O CANCELLATION
	.WORD	DWTMO		;TIMEOUT ENTRY POINT
	.WORD	DUPWRF		;POWER FAIL ROUTINE
;+
;**-  DWINIT - DUP-11 SYNCHRONOUS C      OMMUNICATION CONTROLLER I/O INITIATOR
;
; DWINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE,
; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE
; NORMAL RSX-11M INPUT/OUTPUT LOGIC FLOW.  IF THE DEVICE IS
; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT,
; THE REQUEST IS INITIATED.
; IF NO REQUEST EXISTS FOR THAT UNIT OR IF IT IS
; BUSY, AN EXIT IS TAKEN TO THE CALLER.  NOTE  THAT BECAUSE OF
; THE NATURE OF THE DUP-11, EACH UNIT IS A CONTROLLER ITSELF,
; HAS ITS OWN SCB, AND TH      EREFORE ITS OWN QUEUE.
; EACH TIME DWINIT IS CALLED, IT IS CALLED TO SERVICE ONLY
; THE UNIT SPECIFIED IN THE CALL.
;
; INPUTS:
;
;	R4 = STATUS CONTROL BLOCK ADDRESS
;	R5 = ADDRESS OF THE UCB TO BE INITIATED.
;
; OUTPUTS:
;
;	IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE
;	DEVICE IS INITIATED APPROPRIATELY.
;-

DWINIT:	TSTB	U.CW2(R5)	;UNSOLICITED (HDPX) RECEIVE ACTIVE?
	BPL	10$		;IF NOT, PROCEED
	JMP	180$		;ACTIVATE NO NEW OPERATION

10$:	CALL	$GTPKT		;GET AN I/O PACKET TO PROCESS
	BCC	20$	      	;IF CC, SOMETHING TO DO
	JMP	180$		;NO REQUEST OR UNIT BUSY
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
;
;	R1 = ADDRESS OF THE I/O REQUEST PACKET.
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3 = CONTROLLER INDEX
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5 = ADDRESS OF THE UCB SPECIFIED IN THE
;	     DWINIT CALL.
;
; DUP11 I/O REQUEST PACKET FORMAT
;
;	WORD	     CONTENT
;
;	  0	I/O QUEUE THREAD WORD
;	  1	REQUEST PRIORITY, EVENT FLAG NUMBER
;	  2	ADDRESS OF THE TCB OF       THE REQUESTER TASK
;	  3	POINTER TO SECOND LUN WORD IN TASK HEADER
;	  4	CONTENTS OF FIRST LUN WORD (UCB)
;	  5	I/O FUNCTION CODE
;	  6	VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	  7	RELOCATION BIAS OF I/O STATUS BLOCK
;	 10	I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000)
;	 11	VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	 12	RELOCATION BIAS OF I/O BUFFER
;	 13	BUFFER ADDRESS FOR TRANSFER
;	 14	TOTAL BYTE COUNT TO TRANSFER
;	 15	BYTE COUNT FOR SECOND PART OF TRANSMISSION OR 0
;	 16	NOT USED
;	       17	NOT USED
;	 20	NOT USED
;

20$:	MOV	S.CSR(R4),R2	;GET RECEIVER CSR ADDRESS
	ADD	#I.FCN+1,R1	;POINT TO I/O FUNCTION CODE
	CMPB	#IO.INL/256.,(R1) ;CHECK IF TRANSFER FUNCTION
	BLOS	70$		;BRANCH ON CONTROL FUNCTION
	BIT	#U2.ONL,U.CW2(R5) ;IS DEVICE ON LINE (INITIALIZED?)
	BEQ	90$		;CAN'T TRANSFER IF NOT
	BIT	#DSRDY,(R2)	;IS DATA SET READY?			;**-3
	BEQ	90$		;IF NOT, CAN'T TRANSFER
	CMPB	#IO.RLB/256.,(R1) ;READ LOGICAL?			;**-3
	BEQ	40$		;YES, SERVICE READ REQUEST
;
; FALL THROUGH HERE ON TRANS      MIT (WRITE LOGICAL)
;
	BIS	#RTS,(R2)	;ASSERT REQUEST TO SEND			;**-8
	MOVB	U.SYNC(R5),R0	;LOAD SYNC CHARACTER
	MOVB	S.ITM(R4),S.CTM(R4) ;INITIALIZE TIMEOUT COUNT
	MOVB	U.NSYN(R5),R3	;NUMBER OF SYNCS IN LEADER
30$:	MOVB	R3,U.NSYC(R5)	;LOAD SYNC LEADER COUNT			;**-15
	ADD	#4,R2		;POINT TO TRANSMIT CSR
	BIS	#SEND,(R2)+	;ENABLE TRANSMISSION
;
;	*****	NOTE	*****
;
; SINCE TSOM IS SET THROUGHOUT THE TRANSMISSION, DATA LATE
; ERRORS WILL NEVER BE DETECTED.
;
;	*****		*****
;
	BIC	#177400,R0	;CLEAR       HIGH BYTE
	BIS	#TSOM,R0	;SET TSOM
	MOV	R0,(R2)		;SEND CHAR+TSOM
	TST	-(R2)		;CLEAR DATA LATE ERRORS
	BIS	#DNAEN!TXINTE,(R2) ;ENABLE INTERRUPTS
	BR	180$		;RETURN - INTERRUPT CODE PROPAGATES TRANSMISSION

;
; RECEIVE FUNCTION INITIATION
;

40$:				;REFERENCE LABEL
	MOV	R5,R0		;SET UP TRANSFER VECTOR			;**-4
	ADD	#U.RBUF,R0	;RECEIVE TRANSFER INFORMATION HERE
	MOV	U.BUF(R5),(R0)+	;TRANSFER BIAS
	MOV	U.BUF+2(R5),(R0)+ ;AND OFFSET
	MOV	U.CNT(R5),(R0)	;AND COUNT
	BIC	#SCHSYN,(R2)	;FORCE RE-SYNCHI      NG
	TSTB	2(R2)		; ENSURE RECEIVE BUFFER CLEAR
	BIS	#STRSYN!RCVENB!SCHSYN,(R2) ; ENABLE RECEIVER
	BR	180$		;RETURN - INTERRUPT CODE PROPAGATES RECEIVE
;									;**-8
; CONTROL FUNCTION INITIATION (INITIATE OR TERMINATE CONTROLLER,
; OR CHANGE OPERATING MODE)
;

70$:	BNE	110$		;IF NOT EQUAL, MODE CHANGE REQUEST
	CMP	(R2)+,(R2)+	;POINT TO TXCSR
	BIS	#MSTRST,(R2)	;RESET DEVICE
	TSTB	-(R1)		;START FUNCTION?
	BNE	100$		;IF NON-ZERO, TERMINATE
;
; DO START FUNCTION INITIATION
;
	TST	U.CW2(R5)	;DE      VICE TO BE IN HALF DUPLEX?
	BPL	80$		;NO, IF PLUS
	BIS	#HDPX,(R2)	;PUT IN HALF DUPLEX MODE
80$:	MOV	#INITMD,R0	;GET WORD SIZE, SYNC MODE
	BISB	U.SYNC(R5),R0	;OR IN SYNC CHARACTER
	MOV	R0,-(R2)	;INITIALIZE DEVICE PARAMETERS
	BIS	#STRSYN!TRMRDY!SCHSYN,-(R2) ;NOW INITIALIZE CONTROLLER
	MOV	R5,UNITBL(R3)	;INITIALIZE UCB ADDRESS IN UNIT TABLE
	BIS	#U2.ONL,U.CW2(R5) ;MARK UNIT ON LINE
	BR	160$		;RETURN SUCCESSFUL

;
; CAN'T ESTABLISH COMMUNICATIONS
;

90$:	MOV	#IE.DNR&377,R0	;SAY CAN'T INITIALIZE D      EVICE (NOT READY)
	BR	170$		;DO I/O DONE

;
; FUNCTION WAS TERMINATE LINE
;

100$:	BIC	#^C<U2.LIN!U2.SWC!U2.ACU>,U.CW2(R5) ;CLEAR OPERATING STATUS
	CLR	UNITBL(R3)	;UNIT TABLE CLEARED OF UCB
	BR	160$		;RETURN SUCCESSFUL STATUS

;
; SERVICE DEVICE MODE CHANGE REQUEST
;

110$:	BITB	#IO.HDX,-(R1)	;SUBFUNCTION SAY HALF DUPLEX?
	BEQ	120$		;IF ZERO, NO
	BIS	#U2.HDX,U.CW2(R5) ;SAY HALF DUPLEX CHARACTERISTIC
120$:	BITB	#IO.FDX,(R1)	;SET MODE TO FULL DUPLEX?
	BEQ	150$		;DON'T SET FULL DUPLEX
	BIT	      #U2.LIN,U.CW2(R5) ;IS LINK FULL DUPLEX?
	BEQ	140$		;IF SO, RUN FULL DUPLEX
130$:	MOV	#IE.IFC&377,R0	;MARK AS ILLEGAL FUNCTION
	BR	170$		;AND TERMINATE

140$:	BIC	#U2.HDX,U.CW2(R5) ;PUT IN FULL DUPLEX IN UCB
150$:	BITB	#IO.SYN,(R1)	;SYNC CHARACTER SPECIFIED?
	BEQ	160$		;NO, IF NOT SET
	MOVB	I.PRM-I.FCN(R1),U.SYNC(R5) ;MARK NEW SYNC CHARACTER
DWSUCC:				;REFERENCE LABEL
160$:	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS
DWFIN:				;REFERENCE LABEL
170$:	CLRB	S.STS(R4)	;CLEAR CONTROLLER STATUS
	BIC      B	#US.BSY,U.STS(R5) ;MARK UNIT IDLE, ALSO
	MOV	R0,-(SP)	;SAVE STATUS WORD 1
	MOV	S.PKT(R4),-(SP)	;SAVE OLD PACKET ADDRESS
	CALL	DWINIT		;INITIATE NEXT PACKET
	MOV	(SP)+,R3	;GET OLD PACKET ADDRESS
	MOV	I.PRM+4(R3),R1	;RETURN REQUESTED ITEM COUNT
	MOV	(SP)+,R0	;RESTORE STATUS WORD 1
	CALLR	$IOFIN		;TERMINATE OLD PACKET

180$:	RETURN			;

;
; POWER FAIL SERVICE
;

DUPWRF:				;REFERENCE LABEL
	CLRB	S.CTM(R4)	;DISABLE DEVICE TIMEOUTS		;**-8
	MOV	#IE.DNR&377,R0	;PUT ERROR CODE IN R0 FOR DWTMO
	B      R	DWTMO		;FINISH I/O ABORT
;									;**-3
; I/O CANCELLATION SERVICE
;

;	INPUTS:
;		R0=I/O PACKET ADDRESS
;		R1=TCB ADDRESS OF TASK TO CANCEL
;		R4=SCB ADDRESS
;		R5=UCB ADDRESS

DWCANC:				;;;REFERENCE LABEL
	CMP	R1,I.TCB(R0)	;;;CANCEL FOR THIS TASK?		;**-7
	BNE	180$		;;;JUST RETURN IF NOT
	CMPB	#IO.WLB/256.,I.FCN+1(R0) ;;;TRANSMIT FUNCTION?
	BEQ	180$		;;;LET TRANSMIT FINISH
	TST	U.RCNT(R5)	;;;RECEIVER FINISHED?
	BLE	180$		;;;RETURN IF YES
	BIC	#RCVENB!SCHSYN,@S.CSR(R4) ;DISABLE RECEIVE      R
	MOV	#IE.ABO&377,R0	;;;PUT ERROR CODE IN R0 FOR DWTMO
	BR	DWTMO		;;;FINISH OFF RECEIVE PACKET
;									;**-4
; TIMEOUT SERVICE ROUTINE
;
;	INPUTS:
;
;		R0 = DEVICE TIMEOUT STATUS 'IE.DNR'
;		R3 = CONTROLLER INDEX
;		R4 = ADDRESS OF SCB
;		R5 = ADDRESS OF UCB
;

DWTMO:				;;;REFERENCE LABEL
	MOV	S.CSR(R4),R4	;GET RECEIVER CSR
	BIC	#TXINTE!SEND!DNAEN,4(R4) ;;;DISABLE TRANSMITTER
	BIC	#RTS,(R4)	;;;TURN OFF CARRIER
	MTPS	#0		;;;ALLOW INTERRUPTS
210$:	JMP	DWTXND		;WAIT FOR SOFTWARE TIMEOUT      

	.DSABL LSB

;
; **- $XWINP - DUP-11 INPUT INTERRUPT SERVICE
;

$XWINP::			;;;REFERENCE LABEL
	INTSV$	XW,PR5,D$$W11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DWSET		;;;SET CSR IN R4, UCB IN R5
	BIC	#STRSYN,(R4)+	;;; EXIT STRIP SYNC MODE		;**-11
	MOV	(R4),R4		;;;CONTENTS OF RCV BUFFER IN R4

	.IF DF M$$MGE							; RC024
									;**-12
	MOV	KISAR6,-(SP)	;;;SAVE CURRENT MAPPING
	MOV	U.RBUF(R5),KISAR6 ;;;MAP TO USER BUFFER
	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER
	MOV	(SP)+,KISAR6	;      ;;RESTORE CURRENT MAPPING


	.IFF

	MOVB	R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER

	.IFTF

	DEC	U.RCNT(R5)	;;;SEE IF COUNT SATISFIED
	BEQ	30$		;;;YES, IF EQUAL
	INC	U.RBUF+2(R5)	;;;BUMP BYTE ADDRESS

	.IFT

	BIT	#20000,U.RBUF+2(R5) ;;;OVERFLOWED 4K BOUNDARY?
	BEQ	20$		;;;NO, IF ZERO
	BIC	#20000,U.RBUF+2(R5) ;;;CLEAR OVERFLOW BIT
	ADD	#200,U.RBUF(R5)	;;;BUMP BIAS

	.ENDC
									;**-10
20$:	RETURN			;;;EXIT FROM INTERRUPT
;
; REQUEST SATISFIED
;

30$:				;REFERENCE LABEL
	MO      V	U.SCB(R5),R4	;;;GET SCB ADDRESS			;**-31
	BIC	#RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER
	CALL	$FORK		;;;GO TO FORK LEVEL
	JMP	DWSUCC		;COMPLETE SUCCESSFUL I/O

;
; **- $XWOUT - TRANSMITTER INTERRUPT SERVICE
;

$XWOUT::			;;;REFERENCE LABEL
	INTSV$	XW,PR5,D$$W11	;;;GENERATE INTERRUPT SAVE CODE
	CALL	DWSET		;;;SET RECEIVE CSR IN R4, UCB IN R5
	ADD	#4,R4		;;;POINT TO TX CSR
	TST	(R4)+		;;;DATA NOT AVAILABLE?
	BPL	10$		;;;NO, IF NOT SET

;
; CHECK DATA LATE
;
	TSTB	-2(R4)		;;;TRANSMITTER DONE       SET?		;**-21
	BPL	60$		;;;IF NOT, DISMISS INTERRUPT
10$:	BIT	#CTS,-6(R4)	;;;CLEAR TO SEND SET?
	BEQ	20$		;;;IF NOT, SEND A SYNC
	TSTB	U.NSYC(R5)	;;;SYNC COUNT ZERO?
	BEQ	30$		;;;IF YES, TRANSMIT DATA
	DECB	U.NSYC(R5)	;;;DECREMENT SYNC LEADER COUNT
	BLE	30$		;;;IF LE, TRANSMIT DATA
20$:	MOVB	U.SYNC(R5),(R4)	;;;SEND A SYNC CHARACTER
	BR	50$		;;;EXIT


;
; SET UP AND TRANSMIT A BYTE
;
30$:	DEC	U.CNT(R5)	;;;CHECK COUNT (0 NOT VALID)
	BGE	40$		;;;IF NOT, CONTINUE
	TST	U.CW2(R5)	;;;IN HALF DUPLE      X?
	BPL	80$		;;;IF NOT, NO TURNAROUND
	CMP	#-3,U.CNT(R5)	;;;SENT TWO MARKS?			;**-8
	BGE	70$		;;;IF SO, TURN LINE AROUND
	MOVB	#-1,(R4)	;;;OUTPUT A MARK
	BR	50$		;;;DISMISS INTERRUPT

40$:	CALL	$GTBYT		;;;GET NEXT BYTE FROM BUFFER
	MOVB	(SP)+,(R4)	;;;OUTPUT CHARACTER
50$:	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS BACK
	MOVB	S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT COUNT
60$:	BR	DWSXT		;;;EXIT FROM INTERRUPT

70$:	BIC	#SEND,-(R4)	;;;DON'T IDLE SYNC
	TST	-(R4)		;;;CLEAR RECEIVE DONE AND ERROR
	BIC	#SCHSY      N!RTS,-(R4) ;;;TURN OFF CARRIER
	BIS	#SCHSYN,(R4)	;;;FORCE RESYNCHING			;**-7
	ADD	#6,R4		;;;POINT TO TRANSMIT BUFFER		;**-3
80$:	BIC	#TXINTE!DNAEN!SEND,-(R4) ;;;DISABLE TRANSMITTER
	CALL	$FORK		;;;CREATE SYSTEM PROCESS
	MOV	#IS.SUC&377,R0	;RETURN SUCCESSFUL STATUS		;**-3
DWTXND:				;REFERENCE LABEL			;**-3
	MOV	U.SCB(R5),R4	;RESTORE SCB TO R4			;**-10
	JMP	DWFIN		;MARK COMPLETION
;
; DWSET - SET UP REGISTER R4 WITH CSR ADDRESS, R5 WITH
;	UCB ADDRESS.  UNIT NUMBER IN LOW ORDER 4 BITS OF UNIT.
;   ¢  



DWSET:				;;;REFERENCE LABEL
	TST	R5		;;;TEST FOR VALID UCB ADDRESS
	BEQ	10$		;;;IF NO UCB, TROUBLE
	BIT	#U2.ONL,U.CW2(R5) ;;;UNIT ON LINE?
	BEQ	10$		;;;IF NOT ON LINE, CAN'T TRANSFER
	MOV	U.SCB(R5),R4	;;;FIRST GET SCB ADDRESS
	MOV	S.CSR(R4),R4	;;;NOW DEVICE CSR ADDRESS
	RETURN			;;;AND NOW RETURN

10$:	TST	(SP)+		;;;CLEAR STACK OF RETURN ADDRESS
DWSXT:	JMP	$INTXT		;;;DISMISS INTERRUPT

	.END
 ¢         Í:ÀkQ	› c,        	.TITLE IPMAP
;
; AREA TO READ PCS MAP INTO BY ISA FORTRAN SUBROUTINES
;
NMOD=13

IPMAP::	.BLKW	NMOD*N$$PCS*4
	.WORD	0

$I=0

IPMAPF::	.REPT	N$$PCS
	.WORD 	$I*4*NMOD	; OFFSET IN IPMAP FOR THIS CONTROLLER
$I=$I+1
		.ENDR

.IF DF I$$PUN

	LGIPMP==NMOD * N$$PCS * 4 * 2 ;BYTE LENGTH OF MAP ENTRY

.IFF

	LGIPMP==NMOD * 4 * 2

.ENDC

	.PCSBS==I$$PB0			; GLOBALLY DEFINE BASE ADDRESS
	.PCSNC==N$$PCS		;GLOBALLY DEFINE NUMBER OF CONTROLLERS
	.IIF DF I$$PUN,.PCSNC==1;(WE WANT NUMBER OF PERC      EIVED CONTROLLERS)
.END
          ÓhLkQ	› c,        	.TITLE	DRCLI
	.IDENT	/01.09/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.09
;
; M. S. FOX	27-JAN-81
;
; PREVIOUSLY MODIFIED BY:
;
; MODIFIED BY:
;
;	M. S. HARVEY	21-APR-81
;		MSH165 -- MOVE $STCLI FROM MODULE DRSUB INTO THIS
;			  MODULE SO THAT IT CAN BE EXTERNAL TO THE
;			  EXECUTIVE IF DIRECTIVE PAR      TITIONS SUPPORTED.
;			  $STCLI ORIGINALLY WRITTEN BY M. S. FOX.
;
;	M. S. HARVEY	10-SEP-81
;		MSH188 -- CORRECT MANIPULATION OF PROTECTION UIC BY
;			  ESTABLISHING CORRECT MULTIUSER PROTECTION
;			  CONDITIONALIZATION
;
;	M. S. FOX	15-SEP-81
;
;		MF225 -- FIX $STCLI HANDLING OF CP.RST, AND DO NOT
;			 ALLOW A CLI TO BE SET IF THE TTY IS LOGGED OFF
;			 AND CP.LGO IS NOT SET.
;
;	M. S. HARVEY	28-OCT-81
;		MSH198 -- CLEAN UP SOME CODE

;+
; **-$DRCLI-SET CLI / GET CLI INFO / DECLARE CMD AR      RIVAL AST DIRECTIVES
;
; THIS MODULE CONTAINS THE GET CLI INFORMATION AND SET CLI
; DIRECTIVES. IT ALSO GETS CALLED BY DRDSP FOR THE DECLARE
; COMMAND ARRIVAL AST DIRECTIVE, BUT IMMEDIATEDLY JUMPS TO
; THE $CAAST ENTRY POINT OF THE DRPUT MODULE FOR PROCESSING.
;
; INPUTS:
;
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK
;	R3=ADDRESS OF THE SECOND WORD IN THE DPB
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK
;
;-

	.IF DF	A$$CLI
      

	.IF DF	M$$CLI

	.ERROR			;CANNOT DEFINE BOTH M$$CLI AND A$$CLI

	.ENDC	;M$$CLI

	.MCALL	PKTDF$,UCBDF$
	PKTDF$			;DEFINE CPB OFFSETS
	UCBDF$			;DEFINE UCB OFFSETS

	ASSUME	UM.CLI,36	;BITS TO INDICATE TERMINALS CLI
	ASSUME	C.PTCB,0	;TCB ADDRESS MUST BE AT OFFSET ZERO OF CPB

$DRCLI::MOVB	-(R3),R0	;GET DPB SIZE
	CMPB	#5,(R3)+	;IS IT SET CLI (SCLI$)
	BEQ	SCLI		;IF EQ YES, PROCESS SCLI$ DIRECTIVE


	.IF DF	A$$TRP

	CMPB	#2,R0		;IS IT DECLARE CMD ARRIVAL AST (SCAA$)
	BNE	10$		;IF NE NO
	      JMP	$CAAST		;PROCESS DIRECTIVE IN DRPUT

	.ENDC	;A$$TRP


10$:	CMPB	#7,R0		;IS IT GET CLI INFORMATION (GCII$)
	BEQ	GCII		;IF EQ YES, PROCESS GCII$
	DRSTS	D.RS99		;ILLEGAL DPB SIZE

;+
; **-SCLI- SET A TERMINAL'S CLI
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SET THE CLI OF THE
; CURRENT TASK'S TI: TERMINAL (OR SPECIFIED TERMINAL) TO BE THE
; SPECIFIED CLI. SYSTEM MESSAGES INFORMING BOTH THE PREVIOUS AND
; NEW CLIS OF THE CHANGE ARE SENT TO THE CLIS IF THEY DESIRE THEM.
;
; DPB FORMAT:
;
;      	WD. 00 -- DIC(173.),DPB SIZE(5.)
;	WD. 01 -- ASCII NAME OF THE TERMINAL WHOSE CLI SHOULD BE SET
;	WD. 02 -- OCTAL UNIT NUMBER OF TERMINAL
;	WD. 03 -- FIRST HALF OF RAD50 NAME OF THE DESIRED CLI
;	WD. 04 -- SECOND HALF OF THE RAD50 NAME OF THE DESIRED CLI
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF THE
;			LENGTH IS ILLE      GAL
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IS THE
;			ISSUING TASK IS NOT PRIVILEGED.
;		DIRECTIVE STATUS OF 'D.RS92' IS RETURNED IF AN
;			NON-EXISTANT OR NON-TERMINAL DEVICE IS SPECIFIED.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF THE SPECIFIED
;			CLI DOES NOT EXIST.
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF THERE IS
;			INSUFFICIENT POOL SPACE.
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF THE		; MF225
;			TERMINAL IS LOGGED OFF, AND CP.LGO IS CLEAR	; MF225
;
;-

	.ENABL	LSB			      				;MSH198
SCLI:	BIT	#T3.PRV!T3.CLI,T.ST3(R5) ;CAN TASK USE THIS DIRECTIVE?
	BEQ	99$		;IF EQ NO				;MSH198
	TST	(R3)		;IS A TERMINAL SUPPLIED			;**-1
	BNE	15$		;IF NE YES				;MSH198
	MOV	T.UCB(R5),R0	;GET CURRENT TASK'S TI:			;**-1
	CMP	(R3)+,(R3)+	;SKIP DEV NAME AND UNIT NUMBER FIELDS
	BR	25$		;					;MSH198
15$:	MOV	(R3)+,-(SP)	;GET ASCII TERMINAL NAME		;MSH198
	MOV	(R3)+,-(SP)	;GET UNIT NUMBER			;**-2
	MOV	SP,R1		;POINT TO THEM ON STACK
	MOV	R3,-(SP)	;SAVE DPB POINTER
	CALL	$GTUCB		;GET TERMI      NALS UCB ADDRESS
	BCS	120$		;IF CS, DEVICE DOES NOT EXIST		;MSH198
	MOV	R5,R0		;COPY UCB ADDRESS			;**-1
	CALL	$MPLND		;FOLLOW REDIRECT CHAIN
	BIT	#DV.TTY,U.CW1(R0) ;IS DEVICE A TERMINAL
	BEQ	120$		;IF EQ NO				;MSH198
	MOV	(SP)+,R3	;POINT TO CLI NAME IN CPB		;**-1
	CMP	(SP)+,(SP)+	;CLEAN STACK
25$:	CALL	$STCLI		;SET THE TERMINAL'S CLI			;MSH198
	BCC	60$		;IF CC, SUCCESS				;**-1
	TST	R0		;IDENTIFY ERROR
	BEQ	99$		;IF EQ PRIVILEGE VIOLATION		;MSH198
	BMI	110$		;IF MI, CLI NOT IN SYSTEM		;MSH198      
	DEC	R0		;ALLOCATION FAILURE??			;MSH198
	BNE	35$		;IF NE YES				; MF225
	DRSTS	D.RS8		;TERMINAL NOT LOGGED ON, CP.LGO CLEAR	; MF225
35$:	DRSTS	D.RS1		;ALLOCATION FAILURE			; MF225
60$:	RETURN			;SUCCESS				;**-6

;+
; **-GCII-GET CLI INFORMATION DIRECTIVE
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO FILL A BUFFER IN THE CURRENT
; TASK SPACE WITH INFORMATION ABOUT HIS OWN OR A SPECIFIED CLI. THE
; ISSUING TASK MUST BE PRIVILEGED TO GET INFORMATION ABOUT A CLI
; WHICH IS NOT THE CLI OF ITS TI: TER      MINAL. IF THE BUFFER IS NOT
; LONG ENOUGH TO CONTAIN ALL THE DATA, IT IS FILLED FROM LEFT
; TO RIGHT WITH AS MUCH DATA AS WILL FIT. NO INDICATION WILL
; BE GIVEN TO THE TASK THAT ITS BUFFER IS TOO SHORT. THIS ALLOWS
; NEW DATA ITEMS TO BE RETURNED BY FUTURE VERSIONS OF THIS DIRECTIVE,
; SINCE OLD TASKS WILL CONTINUE TO WORK. THEY JUST WILL NOT SEE
; THE NEW DATA.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(173.),DPB SIZE(7).
;	WD. 01 -- ADDRESS OF BUFFER IN CURRENT TASK'S SPACE
;	WD. 02 -- LENGTH OF THE T      ASK'S BUFFER
;	WD. 03 -- FIRST HALF OF NAME OF CLI TO RETURN DATA ON
;	WD. 04 -- SECOND HALF OF NAME OF CLI TO RETURN DATA ON
;	WD. 05 -- ASCII NAME OF TERMINAL WHOSE CLI SHOULD BE USED
;	WD. 06 -- OCTAL UNIT NUMBER OF TERMINAL
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS99' IS RETURNED IF THE
;			DPB LENGTH IS INVALID.
;		DIRECTIVE STATU      S OF 'D.RS98' IS RETURNED IF THE BUFFER
;			IS NOT ENTIRELY WITHIN THE USER'S TASK SPACE.
;		DIRECTIVE STATUS OF 'D.RS81' IS RETURNED IF BOTH THE
;			NAMES OF THE CLI AND TERMINAL ARE SUPPLIED.
;		DIRECTIVE STATUS OF 'D.RS2' IS RETURNED IF THE
;			SPECIFIED CLI DOES NOT EXIST.
;		DIRECTIVE STATUS OF 'D.RS92' IS RETURNED IF THE
;			SPECIFIED DEVICE IS NOT A TERMINAL.
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF A NON-PRIV
;			TASK ATTEMPTS TO GET INFO ON A CLI WHICH IS
;			NOT ASSOCIATED WITH ITS       TI:
;
;-

;
; THE FORMAT OF THE INFORMATION BUFFER IN THE TASK'S ADDRESS SPACE IS:
;
;	+---------------------------------------+
;	!	NAME OF CLI			!
;	!	(2 WORDS)			!
;	!---------------------------------------!
;	!	CLI STATUS WORD FROM CPB	!
;	!---------------------------------------!
;	!	NAME OF TASK SERVING AS CLI	!
;	!	(2 WORDS)			!
;	!---------------------------------------!
;	!	TERMINAL'S U.CW2		!
;	!---------------------------------------!
;	!	TERMINAL'S PROTECTION UIC	!
;	!-------      --------------------------------!
;	!	TERMINAL'S CURRENT UIC		!
;	!---------------------------------------!
;	!					!
;	!	DEFAULT PROMPT STRING		!
;	!	(1 BYTE LENGTH, FOLLOWED BY	!
;	!		31. BYTES STRING)	!
;	+---------------------------------------+
;
;

GCII:	MOV	(R3)+,R0	;GET ADDRESS OF BUFFER
	MOV	(R3)+,R1	;GET LENGTH OF BUFFER
	MOV	R1,-(SP)	;SAVE LENGTH
	CALL	$ACHKW		;ADDRESS CHECK BUFFER
	MOV	R5,R2		;COPY CURRENT TASK'S TCB ADDRESS
	MOV	T.UCB(R2),R5	;POINT TO TASK'S TI:
	TST	(R3)		;WAS       A CLI NAME SPECIFIED
	BEQ	10$		;IF EQ NO
	TST	4(R3)		;WAS A TERMINAL SPECIFIED
	BNE	100$		;IF NE YES
	CALL	$FNCLI		;FIND THE SPECIFIED CLI
	BCS	110$		;IF CS, CLI DOES NOT EXIST
	MOV	U.MUP(R5),R3	;GET WORD CONTAINING TI:S CLI INDICATOR
	BIC	#^CUM.CLI,R3	;ISOLATE CLI INDICATOR BITS
	CMP	R3,R1		;LOOKING AT TI:S CLI??
	BEQ	200$		;IF EQ YES
	BR	30$		;REQUIRE PRIVILEGE
10$:	CMP	(R3)+,(R3)+	;SKIP OVER CLI NAME IN DPB
	TST	(R3)		;TERMINAL SPECIFIED
	BEQ	20$		;IF EQ NO
	MOV	(R3)+,-(SP)	;PUT NAME ON ST      ACK
	MOV	(R3)+,-(SP)	;PUT UNIT NUMBER ON STACK
	MOV	SP,R1		;POINT TO UNIT NUMBER AND NAME
	MOV	R0,-(SP)	;SAVE USERS BUFFER ADDRESS
	CALL	$GTUCB		;GET UCB ADDRESS
	BCS	120$		;IF CS, DEVICE DOES NOT EXIST
	MOV	R5,R0		;COPY UCB ADDRESS
	MOV	R2,-(SP)	;SAVE R2
	CALL	$MPLND		;FOLLOW REDIRECT CHAIN
	MOV	(SP)+,R2	;RESTORE R2
	MOV	R0,R5		;PUT UCB ADDRESS BACK IN R5
	MOV	(SP)+,R0	;RESTORE BUFFER ADDRESS
	BIT	#DV.TTY,U.CW1(R5) ;IS DEVICE A TERMINAL
	BEQ	120$		;IF EQ NO
	CMP	(SP)+,(SP)+	;CLEAN STACK
20$:      	MOV	U.MUP(R5),R4	;GET CLI INDICATOR FROM UCB
	BIC	#^CUM.CLI,R4	;ISOLATE IT
	MOV	$CPTBL(R4),R4	;POINT TO THE CPB
	CMP	T.UCB(R2),R5	;LOOKING AT CURRENT TASK'S TI:
	BEQ	200$		;IF EQ YES, DO NOT NEED PRIVILEGE
30$:	BIT	#T3.PRV!T3.CLI,T.ST3(R2) ;IS CURRENT TASK PRIVILEGED OR CLI
	BNE	200$		;IF NE YES
									;MSH198
99$:	DRSTS	D.RS16		;PRIVILEGE VIOLATION			;MSH198
100$:	DRSTS	D.RS81		;CANNOT SPECIFY BOTH TERMINAL AND CLI	;**-2
110$:	DRSTS	D.RS2		;CLI DOES NOT EXIST
120$:	DRSTS	D.RS92		;ILLEGAL DEVI      CE SPECIFIED
;
200$:	CALL	$RELOC		;RELOCATE USERS INFO BUFFER
	MOV	(SP)+,R3	;GET LENGTH OF BUFFER
	MOV	R1,KISAR6	;MAP BUFFER IN TASK SPACE
	MOV	R4,-(SP)	;SAVE CPB ADDRESS
	ASR	R3		;CONVERT TO WORD OFFSET
	SUB	#2,R3		;SPACE LEFT IN BUFFER FOR CLI NAME
	BLT	210$		;IF LT NO
	MOV	C.PNAM(R4),(R2)+ ;PUT NAME IN BUFFER
	MOV	C.PNAM+2(R4),(R2)+ ;SECOND HALF
	DEC	R3		;SPACE IN BUFFER FOR CPB STATUS WORD
	BLT	210$		;IF LT NO
	MOV	C.PSTS(R4),(R2)+ ;COPY STATUS WORD INTO BUFFER
	SUB	#2,R3		;SPACE LEFT IN B      UFFER FOR TASK NAME
	BLT	210$		;IF LT NO
	MOV	(R4),R4		;POINT TO CLI'S TCB
	MOV	T.NAM(R4),(R2)+	;COPY FIRST HALF OF TASK NAME
	MOV	T.NAM+2(R4),(R2)+ ;AND SECOND HALF
	DEC	R3		;SPACE LEFT IN BUFFER FOR TERMINAL'S U.CW2
	BLT	210$		;IF LT NO
	MOV	U.CW2(R5),(R2)+	;COPY U.CW2 INTO BUFFER
	DEC	R3		;SPACE FOR PROTECTION UIC??
	BLT	210$		;IF LT NO
									;MSH188
	.IF DF	M$$MUP							;MSH188
									;MSH188
	MOV	U.LUIC(R5),(R2)+ ;COPY PROTECTION UIC
									;MSH188
	.IFF								;MSH188
									;      MSH188
	MOV	U.UIC(R5),(R2)+	;ESTABLISH PROTECTION UIC		;MSH188
									;MSH188
	.ENDC								;MSH188
									;MSH188
	DEC	R3		;SPACE FOR CURRENT UIC
	BLT	210$		;IF LT NO
	MOV	U.UIC(R5),(R2)+	;COPY CURRENT UIC
	SUB	#16.,R3		;ENOUGH ROOM LEFT FOR PROMPT STRING
	BLT	210$		;IF LT NO
	MOV	(SP),R4		;GET CPB ADDRESS BACK
	MOVB	C.PDPL(R4),R5	;GET LENGTH OF DEFAULT PROMPT
	DEC	R5		;DO NOT RETURN ZERO AT END OF PROMPT
	MOVB	R5,(R2)+	;PUT LENGTH IN BUFFER
	BEQ	210$		;IF EQ, NO PROMPT STRING
	ADD	#C.PR      MT,R4	;POINT TO START OF STRING
205$:	MOVB	(R4)+,(R2)+	;COPY CHARACTER
	DEC	R5		;MORE CHARS TO COPY?
	BGT	205$		;IF GT YES
210$:	DRSTS	+1		;SUCCESS

	.DSABL	LSB							;MSH198
									; MF209
;+									; MF209
; **-$STCLI-ROUTINE TO SET A TERMINAL'S CLI				; MF209
; **-$STCL1-ROUTINE TO SET A TERMINAL'S CLI (ALTERNATE ENTRY)		;MSH165
;									; MF209
; THIS ROUTINE SETS THE CLI OF THE SPECIFIED TERMINAL FOR BOTH THE	; MF209
; SCLI$ DIRECTIVE AND MCR. IF EITHER THE PREVIOUS OR NEW CLI HAVE	; M      F209
; THE CP.MSG BIT SET IN THEIR CPB'S, A MESSAGE PACKET IS CREATED AND	; MF209
; PASSED TO THEM TO INFORM THEM OF THE CHANGE. NOTE THAT IF AN ALLOCATIO; MF209
; FAILURE OCCURS WHEN ACTIVATING THE NEW CLI AFTER QUEUEING A MESSAGE	; MF209
; TO IT, THE ERROR IS IGNORED SINCE IT WOULD BE IMPOSSIBLE TO UNWIND	; MF209
; ACTIONS WHICH MAY HAVE ALREADY BEEN COMPLETED, SUCH AS DEACTIVATING	; MF209
; THE PREVIOUS CLI AFTER A CALL TO $EXRQN. THE ONLY DRAWBACK TO THIS IS	; MF209
; THAT THE NEW CLI WILL NOT GE      T THE MESSAGE IMMEDIATELY. THE BUFFER	; MF209
; WILL BE LINKED IN ITS QUEUE, BUT THE CLI WILL NOT RECEIVE IT UNTIL IT	; MF209
; GETS ACTIVATED AT A FUTURE POINT BY A COMMAND ARRIVAL OR ANOTHER	; MF209
; SYSTEM MESSAGE.							; MF209
;									; MF209
; INPUTS:								; MF209
;									; MF209
;	R0=UCB ADDRESS OF TERMINAL TO SET				; MF209
;	R3=POINTER TO THE NAME OF THE NEW CLI ($STCLI ONLY)		;MSH165
;									; MF209
; OUTPUTS:								; MF209
;									; MF209
;	C=1 CLI COULD NOT BE SET					; M      F209
;		R0=2  IF AN ALLOCATION FAILURE OCCURED			; MF225
;		R0=1  IF THE TERMINAL IS LOGGED OFF, AND CP.LGO IS CLEAR; MF225
;		      SO THE CLI DOESN'T ACCEPT CMDS FROM LOGGED OFF TTY; MF225
;		R0=0  IF THE CP.RST BIT IS SET, AND A TASK OTHER THAN	; MF209
;			THE CLI IS ATTEMPTING TO SET A TERMINAL TO IT	; MF209
;		R0=-1 IF THE CLI DOES NOT EXIST				; MF209
;	C=0 THE CLI WAS SUCCESSFULLY SET UP FOR THE SPECIFIED TERMINAL	; MF209
;									; MF209
; ALL REGISTERS ARE MODIFIED						; MF209
;								      	; MF209
;-									; MF209
									; MF209
;									; MF209
MSGLEN=16			;LENGTH OF MESSAGE PACKETS		; MF209
;									; MF209
									;MSH165
	.IF NDF	D$$PAR							;MSH165
									;MSH165
$STCLI::CALL	$FNCLI		;FIND THE SPECIFIED CLI			;MSH165
									;MSH165
	.ENDC								;MSH165
									;MSH165
$STCL1::MOV	#-1,-(SP)	;SET EXIT STATUS WORD FOR THIS ROUTINE	; MF209
	BCS	40$		;IF CS, CLI DOES NOT EXIST		;MSH165
	INC	(SP)		;SET EXIT STATUS TO RETURN R0=0		;MSH165
	MOV	U.MUP(R0),R3	;GET WO      RD CONTAINING CURRENT CLI	;MSH165
	BIC	#^CUM.CLI,R3	;ISOLATE CLI BITS			;MSH165
	MOV	$CPTBL(R3),R3	;GET CPB ADDRESS			;MSH165
	MOV	C.PSTS(R3),$TEMP2 ;SAVE CURRENT CLI'S STATUS WORD	;MSH165
	BIT	#CP.RST,$TEMP2	;DOES CURRENT CLI HAVE RESTRICTED ACCESS; MF209
	BEQ	3$		;IF EQ NO				; MF225
	CMP	$TKTCB,(R3)	;IS THE CLI SWITCHING TTY AWAY FROM ITSE; MF225
	BNE	80$		;IF NE NO				; MF225
3$:	BIT	#CP.RST,C.PSTS(R4) ;IS ACCESS RESTRICTED TO NEW CLI	; MF225
	BEQ	5$		;IF EQ NO				; MF209
	CMP	$TKTCB,(R4)	;IS       SETTING TASK THE CLI ITSELF		; MF209
	BNE	80$		;IF NE NO				; MF209
5$:	INC	(SP)		;SET EXIT STATUS TO RETURN R0=1		; MF209
									;MSH198
	.IF DF	M$$MUP							;MSH198
									;MSH198
	BIT	#U2.LOG,U.CW2(R0) ;IS TERMINAL LOGGED IN		; MF225
	BEQ	7$		;IF EQ YES				; MF225
	BIT	#CP.LGO,C.PSTS(R4) ;DOES CLI ACCEPT CMDS FROM LOGGED OFF; MF225
	BEQ	80$		;IF EQ NO				; MF225
									;MSH198
	.ENDC								;MSH198
									;MSH198
7$:	INC	(SP)		;SET EXIT STATUS TO RETURN R0=2		; MF225
	MOV	R1,-(SP)	;      SAVE OFFSET TO NEW CLI IN $CPTBL	; MF209
	MOV	R0,-(SP)	;SAVE UCB ADDRESS			; MF209
	CLR	R5		;ASSUME NO MESSAGE FOR NEW CLI		; MF209
	BIT	#CP.MSG,C.PSTS(R4) ;DOES NEW CLI WANT A MESSAGE		; MF209
	BEQ	10$		;IF EQ NO				; MF209
	MOV	#MSGLEN,R1	;GET LENGTH OF MESSAGE			; MF209
	CALL	$ALOCB		;ALLOCATE A MESSAGE			; MF209
	BCS	70$		;IF CS, NO POOL				; MF209
	MOV	R0,R5		;SAVE BUFFER ADDRESS			; MF209
	MOV	R4,(R0)		;SAVE CPB ADDRESS IN BUFFER		; MF209
10$:	BIT	#CP.MSG,$TEMP2	;DOES CURRENT CLI WANT A MESS      AGE	; MF209
	BEQ	25$		;IF EQ NO				; MF209
	MOV	#MSGLEN,R1	;GET MESSAGE LENGTH			; MF209
	CALL	$ALOCB		;ALLOCATE A MESSAGE BUFFER		; MF209
	BCS	60$		;IF CS, NO POOL				; MF209
	MOV	R0,R1		;COPY BUFFER ADDRESS			; MF209
	MOV	(SP),R2		;GET UCB ADDRESS			; MF209
	MOV	R3,R4		;GET ADDRESS OF CURRENT CPB		; MF209
	CALL	STMSG		;SET UP MESSAGE BUFFER			; MF209
	MOVB	#CM.RMT,7(R1)	;INSERT MESSAGE CODE			; MF209
	MOV	R1,-(SP)	;SAVE BUFFER ADDRESS			; MF209
	MOV	(R4),R0		;GET CLI'S TCB ADDRESS			; MF209
	C      ALL	$QCLIL		;QUEUE BUFFER AND REQUEST CLI		; MF209
	BCC	20$		;IF CC, OK				; MF209
	BNE	50$		;IF NE, ALLOCATION FAILURE		; MF209
;									; MF209
; AFTER THIS POINT, COMLETE ERROR RECOVERY IS IMPOSSIBLE, BECAUSE THE	; MF209
; TASK MAY JUST HAVE BEEN ACTIVATED INSTEAD OF BEING MERELY UNSTOPPED.	; MF209
;									; MF209
20$:	TST	(SP)+		;DON'T NEED BUFFER ADDRESS ANYMORE	; MF209
25$:	MOV	R5,R1		;POINT TO MESSAGE FOR NEW CLI		; MF209
	BEQ	30$		;IF EQ, NO MESSAGE FOR NEW CLI		; MF209
	MOV	(R1),R4		;P      OINT TO NEW CPB			; MF209
	MOV	(SP),R2		;GET UCB ADDRESS			; MF209
	CALL	STMSG		;SET UP MESSAGE				; MF209
	MOVB	#CM.LKT,7(R1)	;INSERT MESSAGE CODE			; MF209
	MOV	(R4),R0		;GET CLI'S TCB ADDRESS			; MF209
	CALL	$QCLIL		;QUEUE MESSAGE AND REQUEST IT		; MF209
				;DO NOT CHECK ERROR RETURNS		; MF209
30$:	MOV	(SP)+,R0	;GET UCB ADDRESS OF TERMINAL		; MF209
	MOV	(SP)+,R1	;GET OFFSET TO NEW CLI IN $CPTBL	; MF209
	MTPS	#PR7		;;;PREVENT TTDRV FROM ANSWERING PHONE WH; MF209
				;;;CLI SETTING IS INVALID		;       MF209
	BIC	#UM.CLI!UM.DSB,U.MUP(R0) ;;;CLEAR OUT PREVIOUS CLI INDIC; MF209
	BIS	R1,U.MUP(R0)	;;;SET NEW CLI				; MF209
	MTPS	#0		;ALLOW INTERRUPTS			; MF209
	CLC			;SUCCESS				; MF209
40$:	MOV	(SP)+,R0	;SET EXIT STATUS			; MF209
	RETURN			;ALL DONE				; MF209
;									; MF209
; ERROR CLEANUP CODE							; MF209
;									; MF209
									; MF209
; ERROR WHILE ACTIVATING CURRENT CLI, SO UNLINK AND DEALLOCATE MESSAGE	; MF209
;									; MF209
50$:	MOV	#$CLICQ,R0	;POINT TO CLI COMMAND QUEUE		; MF      209
	MOV	(SP)+,R1	;POINT TO BUFFER JUST QUEUED		; MF209
	CALL	$QRMVT		;REMOVE MESSAGE JUST INSERTED IN QUEUE	; MF209
	MOV	R1,R0		;COPY POINTER TO MESSAGE		; MF209
	MOV	#MSGLEN,R1	;GET ITS LENGTH				; MF209
	CALL	$DEACB		;DEALLOCATE IT				; MF209
;									; MF209
; DEALLOCATE MESSAGE FOR NEW CLI IF IT EXISTS				; MF209
;									; MF209
60$:	MOV	R5,R0		;POINT TO BUFFER FOR NEW CLI		; MF209
	BEQ	70$		;IF EQ, IT DIDN'T WANT ONE		; MF209
	MOV	#MSGLEN,R1	;SET LENGTH				; MF209
	CALL	$DEACB		;DEALLOC      ATE BUFFER FOR NEW CLI		; MF209
70$:	CMP	(SP)+,(SP)+	;CLEAN STACK				; MF209
80$:	SEC			;SET ERROR STATUS			; MF209
	BR	40$		;GO TO COMMON EXIT CODE			; MF209
									; MF209
;									; MF209
; LOCAL ROUTINE TO SET UP MESSAGE BUFFERS				; MF209
;									; MF209
; INPUTS:								; MF209
;	R1=ADDRESS OF MESSAGE BUFFER					; MF209
;	R2=ADDRESS OF TERMINAL UCB					; MF209
;	R4=ADDRESS OF CPB OF CLI TO RECEIVE MESSAGE			; MF209
;									; MF209
; OUTPUTS:								; MF209
;									; MF209
;	NON      E								; MF209
;									; MF209
; REGISTERS R0, R3  MODIFIED						; MF209
;									; MF209
									; MF209
STMSG:	MOV	R1,-(SP)	;SAVE BUFFER ADDRESS			; MF209
	MOV	R1,R3		;COPY BUFFER ADDRESS			; MF209
	TST	(R3)+		;SKIP LINK WORD				; MF209
	MOV	(R4),(R3)+	;SET TCB ADDRESS OF CLI			; MF209
	CLR	(R3)+		;ZERO TO INDICATE IT IS A MESSAGE, NOT C; MF209
	MOV	#MSGLEN,(R3)+	;PUT LENGTH OF MESSAGE IN BUFFER	; MF209
	CLR	(R3)+		;CLEAR TERMINATOR WORD			; MF209
	MOV	R2,R0		;COPY UCB ADDRESS			; MF209      
	MOV	(R0),R1		;POINT TO DCB				; MF209
	TST	(R1)+		;POINT TO ADDRESS OF FIRST UCB		; MF209
	SUB	(R1)+,R0	;CALC RELATIVE ADDRESS OF UCB		; MF209
	MOV	(R1)+,(R3)+	;COPY DEVICE NAME			; MF209
	MOV	(R1)+,(R3)	;GET LOW UNIT NUMBER FOR DCB		; MF209
	MOV	(R1),R1		;GET LENGTH OF UCB			; MF209
	CALL	$DIV		;CALC RELATIVE UNIT NUMBER		; MF209
	ADD	R0,(R3)+	;CALC LOGICAL UNIT NUMBER		; MF209
	CLRB	-(R3)		;CLEAR STUFF LEFT IN HIGH BYTE		; MF209
	MOV	(SP)+,R1	;RESTORE BUFFER ADDRESS			; MF209
	RETURN			;					;   4    MF209
									; MF209
	.ENDC	;A$$CLI

	.END
 4          ã�ƒkQ	› c,        	.TITLE	DRSUB
	.IDENT	/01.20/

;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.20
;
; M. S. HARVEY	30-SEP-79
;
; MODIFIED BY:
;
;	M. S. HARVEY	15-AUG-79, 30-SEP-79
;		MSH049 -- ALLOW $DEAGF TO BE MORE GENERAL
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL FLAG USE CONTROL
;			  FOR SLAVE TASKS      
;
;	M. S. FOX	01-FEB-81
;		MF209 -- ADD ROUTINES ALTERNATE CLI SUPPORT
;
;	M. S. HARVEY	11-FEB-81
;		MSH148 -- USE SYMBOL FOR LENGTH OF CONTROL BLOCK
;
;	M. S. HARVEY	21-APR-81
;		MSH165 -- MOVE $STCLI TO MODULE DRCLI AND REPLACE WITH
;			  A TRANSFER ROUTINE FOR MCR'S USE IF THE
;			  DIRECTIVE COMMONS ARE SUPPORTED. ALSO, ADD
;			  TRANSFER CONTROL FOR THE DISPATCHER.
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
;	M. S. HARVEY	6-OCT-81
;		MSH194 -- EXTERNALIZE WAIT      FOR ROUTINE
;
; THIS EXECUTIVE MODULE CONTAINS ROUTINES THAT ORIGINALLY RESIDED
; IN THE DIRECTIVE MODULES INCLUDED IN THE DIRECTIVE COMMON, BUT WERE
; COMMONLY REFERENCED BY OTHER PARTS OF THE EXECUTIVE OR EXTERNAL
; PROGRAMS. ROUTINES ARE MOVED HERE TO ELIMINATE EXCESSIVE MAPPING
; CODE IN THE EXECUTIVE THAT WOULD OTHERWISE BE REQUIRED IN A SYSTEM
; THAT SUPPORTS THE DIRECTIVE COMMON.
;
; MACRO LIBRARY CALLS
;
	.MCALL	PKTDF$,TCBDF$,HDRDF$,PCBDF$,HWDDF$,ITBDF$
	.MCALL	UCBDF$							; MF209
	UCB      DF$			;DEFINE UCB OFFSETS			; MF209
	PKTDF$			;DEFINE GROUP GLOBAL OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS
	ITBDF$			;DEFINE INTERRUPT TRANSFER BLOCK OFFSETS



	.IF DF	G$$EFN

;+
; **-$ELGEF-SUBROUTINE TO ELIMINATE A GROUP GLOBAL EVENT FLAG BLOCK
;
; THIS SUBROUTINE UNCONDITIONALLY UNLINKS A GROUP GLOBAL EVENT FLAG BLOCK
; AND DEALLOCATES IT.
;
; INPUTS      :
;
;	R0=ADDRESS OF BLOCK POINTING TO BLOCK TO BE DEALLOCATED
;	R1=ADDRESS OF BLOCK TO BE ELIMINATED
;
; OUTPUTS:
;
;	NONE.
;-

$ELGEF::MOV	(R1),(R0)	;UNLINK THE BLOCK
	MOV	R1,R0		;SET UP TO DEALLOCATE THE BLOCK
	MOV	#G.LGTH,R1	;					;MSH148
	CALLR	$DEACB		;DEALLOCATE THE BLOCK			;**-1

;+
; **-$DEAGF-DEACCESS GROUP GLOBAL EVENT FLAGS
;
; THIS ROUTINE DETERMINES IF THE SPECIFIED TASK IS WAITING FOR A
; GROUP GLOBAL EVENT FLAG. IF IT IS, THE ACCESS COUNT IN THE GROUP
; GLOBAL EVENT FLAG B      LOCK IS DECREMENTED AND THE BLOCK IS DEALLOCATED
; IF IT IS MARKED FOR DELETE.
;
; INPUTS:
;
;	R3=EVENT FLAG MASK ADDRESS					;MSH049
;	R4=TASK HEADER ADDRESS						;MSH049
;	R5=TASK TCB ADDRESS.						;**-1
;
; OUTPUTS:
;
;	NONE.
;
;-									;**-1

$DEAGF::SAVNR								;MSH049
	MOVB	H.CUIC+1(R4),R4	;GET GROUP NUMBER			;MSH049
	CALL	$SRGEF		;SEARCH FOR GROUP GLOBAL EVENT FLAGS	;**-1
	BCS	10$		;IF CS NOT FOUND
	BIC	#1,R3		;CLR GRP GLOBAL 2ND WORD INDICATOR	;MSH049
	CMP	R3,R1		;GROUP GLOBAL       EVENT FLAG?		;**-1
	BLO	10$		;IF LO NO
	SUB	#10.,R3		;POINT TO LINK WORD
	CMP	R3,R1		;GROUP GLOBAL EVENT FLAG?
	BHIS	10$		;IF HIS NO
									;MSH076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	DECB	T.GGF(R5)	;DECR GRP GLOBAL USE COUNT FOR TASK	;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH076
	DEC	G.CNT(R1)	;DECREMENT ACCESS COUNT
	BNE	10$		;IF NE, CAN'T ELIMINATE FLAGS YET
	BITB	#GS.DEL,G.STAT(R1) ;MARKED FOR DELETE?
	BNE	$ELGEF		;ELIMINATE GROUP GLOBAL EVENT FLAG GR      OUP
10$:	RETURN			;

;+
; **-$SRGEF-SEARCH FOR GROUP GLOBAL EVENT FLAGS
;
; THIS ROUTINE IS CALLED TO SEARCH FOR GROUP GLOBAL EVENT FLAGS
;
; INPUTS:
;
;	R4=GROUP NUMBER
;
; OUTPUTS:
;
;	C=1 IF SPECIFIED GROUP GLOBAL EVENT FLAGS NOT FOUND
;	C=0 IF SPECIFIED GROUP GLOBAL EVENT FLAGS ARE FOUND
;		R0=ADDRESS OF WORD POINTING TO BLOCK
;		R1=ADDRESS OF THE BLOCK
;
;-

	.IFTF
$SRGEF::			;REF LABEL
	.IFT

	MOV	#$GGEF,R1	;GET ADDRESS OF GROUP GLOBAL EF HEAD
10$:	MOV	R1,R0		;SAVE POINTER TO       CURRENT BLOCK
	MOV	(R1),R1		;GET ADDRESS OF NEXT BLOCK
	BEQ	20$		;IF EQ END OF LIST
	CMPB	G.GRP(R1),R4	;IS THIS THE CORRECT BLOCK?
	BEQ	30$		;IF EQ YES
	BLO	10$		;IF LO KEEP SEARCHING
20$:	SEC			;SET CARRY TO INDICATE NOT FOUND
30$:	RETURN			;

	.ENDC	;G$$EFN


;+
; **-$DRDSE-DECLARE SIGNIFICANT EVENT
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO DECLARE A SIGNIFICANT EVENT.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(35.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CU      RRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF +1.
;
;	NOTE: THIS DIRECTIVE IS ALSO CALLED AS A SUBROUTINE.
;-

$DRDSE::MOV	$ACTHD,$RQSCH	;SET DISPATCH TO FRONT OF LIST
	CLR	$SIGFL		;CLEAR TASK WAITING FOR SIGNIFICANT EVENT
									;MSH165
	.IF NDF	A$$PRI							;MSH165
									;MSH165
$DRATP::			;DE      FINE FOR MCR'S SAKE			;MSH165
									;MSH165
	.ENDC								;MSH165
									;MSH165
	RETURN			;RETURN DIRECTIVE STATUS OF +1

;+
; **-$TKWSE-TASK WAITFOR SIGNIFICANT EVENT
;
; THIS ROUTINE IS CALLED TO EXECUTE A WAITFOR SIGNIFICANT EVENT DIRECTIVE
; FOR THE CURRENT TASK FROM WITHIN THE EXECUTIVE.
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	A WAITFOR SIGNIFICANT EVENT DIRECTIVE IS EXECUTED FOR THE
;	CURRENT TASK AND A RETURN TO THE CALLER IS EXECUTED.
;-

$TKWSE::MOV	$TKTCB,R5	;GET ADDRESS       OF CURRENT TASK TCB

;+
; **-$DRWSE-WAITFOR SIGNIFICANT EVENT
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO SUSPEND THE EXECUTION OF THE
; ISSUING TASK UNTIL THE NEXT SIGNIFICANT EVENT.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(49.),DPB SIZE(1.).
;
; INPUTS:
;
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE LAST WORD IN THE DPB+2.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED       TO TASK)
;
;	C=0 WITH A DIRECTIVE STATUS OF +1.
;-

$DRWSE::MOV	T.ACTL(R5),R0	;GET TCB ADDRESS OF NEXT TASK
	MOV	R5,$SIGFL	;SET TASK WAITING FOR SIGNIFICANT EVENT
	CALLR	$SETRQ		;FORCE REDISPATCHING OF THE PROCESSOR

;+
; **-$MPXC1-MAP THE FIRST EXECUTIVE COMMON				;MSH165
; **-$MPXC2-MAP THE SECOND EXECUTIVE COMMON				;MSH165
;									;**-1
; THIS COROUTINE IS CALLED TO PRESERVE KERNEL APR 5 FOR REMAPPING
; ONE OF THE EXECUTIVE COMMONS. THE CALLER IS CALLED AS A COROUTINE	;MSH165
; WITH ONE       OF THE EXECUTIVE COMMONS MAPPED. WHEN THE CALLER EXECUTES	;MSH165
; A RETURN, CONTROL IS PASSED TO THIS COROUTINE WHERE KERNEL APR 5'S	;MSH165
; ORIGINAL CONTENTS ARE RESTORED.					;**-3
;
; INPUTS:
;
;	(SP) HAS THE RETURN ADDRESS TO THE CALLER
;
; OUTPUTS:
;
;	THE CALLER IS CALLED WITH THE DESIRED EXECUTIVE COMMON MAPPED.	;MSH165
;									;**-1
;-
									;MSH165
	.ENABL	LSB							;MSH165

	.IF DF	D$$PAR&M$$MGE

$MPXC1::MOV	(SP),-(SP)	;COPY RETURN PC				;MSH165
	MOV	$XCOM1,-(SP)	;GET       FIRST EXEC COMMON BIAS		;MSH165
	BR	10$		;JOIN COMMON CODE			;MSH165
$MPXC2::MOV	(SP),-(SP)	;COPY RETURN PC				;MSH165
	MOV	$XCOM2,-(SP)	;GET SECOND EXEC COMMON BIAS		;MSH165
10$:	MOV	KISAR5,4(SP)	;SAVE OLD KERNEL APR 5 MAPPING		;MSH165
	MOV	(SP)+,KISAR5	;MAP THE EXECUTIVE COMMON		;MSH165
	CALL	@(SP)+		;CALL THE CALLER AS A COROUTINE		;MSH165
	MOV	(SP)+,KISAR5	;RESTORE OLD KERNEL APR 5 MAPPING	;**-4
	RETURN			;

	.ENDC
									;MSH165
	.DSABL	LSB							;MSH165

;+
; **-$DETRG-DETACH REGION B      Y ATTACHMENT DESCRIPTOR (TRANSFER ROUTINE)	;MSH165
;									;**-1
; THIS ROUTINE PROVIDES ACCESS TO THE ROUTINE THAT DETACHES A TASK
; FROM A REGION AND DEALLOCATES THE ATTACHMENT DESCRIPTOR. THIS
; ROUTINE PROVIDES TRANSPARENCY TO THE EXISTENCE OF THE EXECUTIVE	;MSH165
; COMMON.								;**-1
;
; INPUTS:
;
;	NONE.
;
; OUTPUTS:
;
;	$DTRG1 IS CALLED TO DETACH THE TASK FROM A REGION. $DTRG1 IS
;	LOCATED IN THE SECOND EXECUTIVE COMMON.				;MSH165
;									;**-1
;-

	.IF NDF	P$$LAS

$DETRG=      =-1			;THIS LABEL MUST ALWAYS BE DEFINED FOR MCR

	.IFF

	.IF DF	D$$PAR

$DETRG::CALL	$MPXC2		;MAP THE SECOND EXECUTIVE COMMON	;MSH165
	CALLR	$DTRG1		;CALL DETACH ROUTINE			;**-1

	.ENDC

	.ENDC

;+									;MSH194
; **-$DRWFS-WAITFOR SINGLE EVENT FLAG (EXEC COMMON SYSTEMS ONLY)	;MSH194
;									;MSH194
; THIS ROUTINE INSTRUCTS THE SYSTEM TO SUSPEND THE EXECUTION OF		;MSH194
; THE ISSUING TASK UNTIL A SPECIFIED EVENT FLAG IS SET.			;MSH194
;									;MSH194
; INPUTS:								;MSH194
;			      						;MSH194
;	R0=EVENT FLAG MASK WORD.					;MSH194
;	R1=EVENT FLAG MASK ADDRESS.					;MSH194
;	R4=ADDRESS OF THE HEADER OF THE TASK BEING BLOCKED.		;MSH194
;	R5=ADDRESS OF THE TCB OF THE TASK BEING BLOCKED.		;MSH194
;									;MSH194
; OUTPUTS:								;MSH194
;									;MSH194
;	C=0 INDICATING SUCCESS						;MSH194
;-									;MSH194
									;MSH194
	.IF DF	M$$NET							;MSH194
	.IF DF	D$$PAR							;MSH194
									;MSH194
$DRWFS::CALL	$MPXC1		;MAP THE FIRST EXECUTIVE COMMON		;MSH194
	CALLR      	$DRWFD		;PLACE THE TASK IN A WAITFOR STATE	;MSH194
									;MSH194
	.ENDC								;MSH194
	.ENDC								;MSH194
									;MSH194
;+
; **-$CITFR-CONNECT TO INTERRUPT TRANSFER ROUTINE
;
; THIS ROUTINE WILL CALL A USER'S ENABLE/DISABLE INTERRUPT ROUTINE
; ASSOCIATED WITH THE CONNECT TO INTERRUPT DIRECTIVE. THE USER'S
; ROUTINE WILL BE MAPPED THROUGH KERNEL APR 5.
;
; INPUTS:
;
;	R1=POINTER TO ITB
;	R2=ADDRESS OF USER'S ENABLE/DISABLE INTERRUPT ROUTINE
;	C=0 TO ENABLE INTERRUPTS
;	C=1 TO DISAB      LE INTERRUPTS
;
; OUTPUTS:
;
;	NONE.
;-

	.IF DF	C$$INT

$CITFR::			;REF LABEL

	.IF DF	D$$PAR

	MOV	KISAR5,-(SP)	;SAVE DIRECTIVE COMMON MAPPING

	.IFTF

	.IF DF	M$$MGE

	MOV	X.REL(R1),KISAR5 ;MAP ROUTINE IN KERNEL APR 5

	.ENDC

	.IFF

	CALLR  @R2		;CALL ROUTINE

	.IFT

	CALL	@R2		;CALL ROUTINE
	MOV	(SP)+,KISAR5	;RESTORE DIRECTIVE COMMON MAPPING
	RETURN			;

	.ENDC	;D$$PAR

	.ENDC	;C$$INT


;+
; **-$DRQRQ-QUEUE I/O REQUEST
;
; THIS ROUTINE IS CALLED TO INSERT AN I/O       PACKET IN A CONTROLLER QUEUE AND
; CALL THE DRIVER TO INITIATE ACTIVITY ON THE DEVICE.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O PACKET.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	THE I/O PACKET IS PLACED IN THE CONTROLLER QUEUE AND ACTIVITY
;	IS INITIATED ON THE DEVICE.
;
;	NOTE: R4 IS DESTROYED BY THIS ROUTINE.
;-

$DRQRQ::MOV	U.SCB(R5),R4	;GET ADDRESS OF STATUS CONTROL BLOCK
	BITB	#UC.QUE,U.CTL(R5) ;QUEUE PACKET BEFORE CALL?
	BNE	10$		;IF NE NO
	MOV	R4,R0		;SET ADDRESS OF I/      O QUEUE LISTHEAD
	CALL	$QINSP		;QUEUE I/O PACKET IN DEVICE QUEUE
10$:	MOV	(R5),R2		;RETRIEVE ADDRESS OF DEVICE CONTROL BLOCK


	.IF DF	L$$DRV&M$$MGE

	MOV	KISAR5,-(SP)	;SAVE APR5
	MOV	D.PCB(R2),R3	;GET DRIVER PCB ADDRESS
	BEQ	20$		;IF EQ DRIVER IS PART OF EXEC
	MOV	P.REL(R3),KISAR5  ;MAP THE DRIVER
20$:				;

	.IFTF

	MOV	D.DSP(R2),R2	;GET ADDRESS OF DRIVER DISPATCH TABLE

	.IFF

	CALLR	@D.VINI(R2)	;CALL DEVICE INITIATOR

	.IFT

	CALL	@D.VINI(R2)	;CALL DRIVER INITIATOR
	MOV	(SP)+,KIS      AR5	;RESTORE APR5
	RETURN			;

	.ENDC


									; MF209
;+									; MF209
; **-$$SRCCQ-SEARCH COMMAND QUEUE					; MF209
;									; MF209
; THIS SUBROUTINE SEARCHES A COMMAND QUEUE FOR COMMANDS TO THE SPECIFIED; MF209
; TASK.									; MF209
;									; MF209
; INPUTS:								; MF209
;									; MF209
;	R0=ADDRESS OF COMMAND QUEUE LISTHEAD				; MF209
;	R5=TCB ADDRESS OF TASK WHOSE COMMANDS SHOULD BE LOCATED		; MF209
;									; MF209
; OUTPUTS:								; MF209
;									; MF209
;	C=1 IF       NO COMMANDS PRESENT FOR TASK				; MF209
;	C=0 IF COMMAND IS PRESENT					; MF209
;		R0=ADDRESS OF COMMAND BUFFER				; MF209
;									; MF209
;-									; MF209
									; MF209
$SRCCQ::								; MF209
									; MF209
	.IF DF	M$$CRX							; MF209
									; MF209
	MOV	R0,R1		;SAVE ADDRESS OF PREVIOUS BUFFER	; MF209
	MOV	(R1),R0		;GET ADDRESS OF NEXT BUFFER		; MF209
	SEC			;ASSUME END OF LIST			; MF209
	BEQ	10$		;IF EQ YES				; MF209
	CMP	R5,2(R0)	;TCB ADDRESS MATCH			; MF209
	BNE	$SRCCQ		;IF       NE NO				; MF209
10$:	RETURN								; MF209
									; MF209
	.ENDC	;M$$CRX							; MF209
									; MF209
									; MF209
;+									; MF209
; **-$GTUCB-GET UCB ADDRESS FROM DEV AND UNIT NUMBER			; MF209
;									; MF209
; THIS ROUTINE ACCEPTS AND ASCII DEVICE NAME AND OCTAL UNIT NUMBER	; MF209
; AND FINDS THE UCB ADDRESS FOR THAT DEVICE.				; MF209
;									; MF209
; INTPUTS:								; MF209
;									; MF209
;	R1=ADDRESS OF OCTAL UNIT NUMBER (WORD FIELD), FOLLOWED		; MF209
;		BY ASCII D      EVICE NAME					; MF209
;									; MF209
; OUTPUTS:								; MF209
;									; MF209
;	C=1 DEVICE NOT IN SYSTEM					; MF209
;	C=0 IF DEVICE EXISTS						; MF209
;		R5=UCB ADDRESS OF DEVICE				; MF209
;									; MF209
; REGISTERS R0,R3,R4 MODIFIED						; MF209
;									; MF209
;-									; MF209
									; MF209
	.IF DF	P$$OFF!A$$CLI						; MF209
									; MF209
$GTUCB::MOV	#$SCDVT,-(SP)	;SET UP TO SCAN DEVICE TABLES		; MF209
10$:	CALL	@(SP)+		;GET ADDRESS OF NEXT DCB		; MF209
	BCS	30$		;IF       CS DEVICE NOT FOUND			; MF209
	MOV	#1,S$$SPC(SP)	;SET UP TO SKIP THIS DCB IF NO MATCH	; MF209
	CMP	D.NAM(R3),2(R1) ;DEVICE NAMES MATCH?			; MF209
	BNE	10$		;IF NE NO				; MF209
	CMPB	D.UNIT+1(R3),(R1) ;UNIT ASSOCIATED WITH THIS DCB?	; MF209
	BLO	10$		;IF LO NO				; MF209
	ADD	#S$$SPA,SP	;ABORT DEVICE SCAN			; MF209
	MOVB	(R1),R0		;GET UNIT NUMBER SPECIFIED		; MF209
	SUB	D.UNIT(R3),R0	;CALCULATE NUMBER OF UCBS TO SKIP	; MF209
	CLC			;SET SUCCESS				; MF209
20$:	DECB	R0		;IS THIS THE CORRECT UCB?		      ; MF209
	BLT	30$		;IF LT R5 HAS THE ADDRESS OF THE UCB	; MF209
	ADD	D.UCBL(R3),R5	;POINT TO NEXT UCB (NOTE THIS CLEARS CAR; MF209
	BR	20$		;CONTINUE SCAN				; MF209
30$:	RETURN			;					; MF209
									; MF209
	.ENDC	;P$$OFF!A$$CLI						; MF209
									; MF209
;+									;MSH165
; **-$STCLI-SET A TERMINAL'S CLI					;MSH165
;									;MSH165
; THIS ROUTINE PROVIDES ACCESS TO THE ROUTINE THAT SETS THE CLI OF	;MSH165
; THE SPECIFIED TERMINAL. THIS ROUTINE PROVIDES TRANSPARENCY TO THE	;MSH165
; EX      ISTENCE OF THE EXECUTIVE COMMONS.					;MSH165
;									;MSH165
; INPUTS:								;MSH165
;									;MSH165
;	R0=UCB ADDRESS OF TERMINAL TO SET				;MSH165
;	R3=POINTER TO THE NAME OF THE NEW CLI				;MSH165
;									;MSH165
; OUTPUTS:								;MSH165
;									;MSH165
;	THE FIRST EXECUTIVE COMMON IS MAPPED AND THE TARGET ROUTINE	;MSH165
;	IS CALLED TO ACTUALLY DO THE WORK. SEE THE DESCRIPTION		;MSH165
;	OF THE TARGET ROUTINE, $STCL1, FOR OUTPUTS.			;MSH165
;-									;MSH165
									;MSH165
	.I      F DF	A$$CLI							;MSH165
									;MSH165
	.IF DF	D$$PAR							;MSH165
									;MSH165
;									;MSH165
; NOTE THAT $FNCLI WILL RETURN THE C-BIT AS OUTPUT. THE POLARITY OF	;MSH165
; THE C-BIT MUST BE PRESERVED SO THAT ACTION ON THE C-BIT CAN BE	;MSH165
; TAKEN IN $STCL1. $MPXC1 PRESERVES THE POLARITY OF THE C-BIT.		;MSH165
;									;MSH165
									;MSH165
$STCLI::CALL	$FNCLI		;FIND THE SPECIFIED CLI			;MSH165
	CALL	$MPXC1		;MAP THE FIRST EXECUTIVE COMMON		;MSH165
	CALLR	$STCL1		;CALL SET CL      I ROUTINE			;MSH165
									;MSH165
	.ENDC	;D$$PAR							;MSH165
									;MSH165
	.IFF	;A$$CLI							;MSH165
									;MSH165
$STCLI==-1			;ALWAYS DEFINED FOR MCR			;MSH165
									;MSH165
	.IFT	;A$$CLI							;MSH165
									; MF209
;+									; MF209
; **-$FNCLI-FIND CPB FOR SPECIFIED CLI					; MF209
;									; MF209
; THIS ROUTINE LOCATES THE CPB FOR THE SPECIFIED CLI			; MF209
;									; MF209
; INPUTS:								; MF209
;									; MF209
;	R3=ADDRESS OF CLI NAME STORED IN RAD50				;       MF209
;									; MF209
; OUTPUTS:								; MF209
;									; MF209
;	C=1 CLI DOES NOT EXIST						; MF209
;	C=0 CLI SUCCESSFULLY FOUND					; MF209
;		R1=OFFSET TO ENTRY FOR CLI IN $CPTBL			; MF209
;		R4=CPB ADDRESS						; MF209
;									; MF209
; REGISTERS R0, R2 AND R3 ARE PRESERVED ACROSS CALL			; MF209
;									; MF209
;-									; MF209
									; MF209
$FNCLI::MOV	#$NMCLI!40000,-(SP) ;GET NUMBER OF CLIS SYSTEM CAN SUPPO; MF209
	CLR	R1		;START AT BEGINNING OF TABLE		; MF209
10$:	MOV	$CP      TBL(R1),R4	;POINT TO NEXT CPB			; MF209
	BEQ	20$		;IF EQ, EMPTY SLOT			; MF209
	CMP	C.PNAM(R4),(R3)	;IS THIS THE CLI			; MF209
	BNE	20$		;IF NE NO				; MF209
	CMP	C.PNAM+2(R4),2(R3) ;MAYBE				; MF209
	BEQ	30$		;IF EQ YES				; MF209
20$:	TST	(R1)+		;SET OFFSET FOR NEXT SLOT IN TABLE	; MF209
	DECB	(SP)		;IS THERE A SLOT LEFT			; MF209
	BGT	10$		;IF GT YES				; MF209
	ASL	(SP)		;PUT BIT IN POSITION TO SET CARRY	; MF209
30$:	ASL	(SP)+		;POP STACK AND SET APPROPRIATE CARRY	; MF209
	RETURN								; MF2      09
									; MF209
	.IFF	;A$$CLI							; MF209
									; MF209
$FNCLI==-1			;CANNOT USE THIS LABEL			;MSH165
									; MF209
	.ENDC	;A$$CLI							; MF209
									;MSH165
;+									;MSH165
; **-$TRTRP-TRAP TRAP (EXECUTIVE COMMON ENTRY)				;MSH165
;									;MSH165
; THIS ROUTINE IS TRAPPED TO WHEN A TRAP INSTRUCTION IS EXECUTED. IF	;MSH165
; THE STACK DEPTH IS ZERO, THEN A DIRECTIVE STATUS IS TO BE RETURNED.	;MSH165
; ELSE, CONTROL IS TRANSFERED TO THE EMT/TRAP SST HANDLING ROUTINE.	;MSH165      
;									;MSH165
; IF DIRECTIVE STATUS IS TO BE RETURNED, THIS ROUTINE TRANSFERS CONTROL	;MSH165
; BACK TO THE DIRECTIVE DISPATCHER FOR PROCESSING. ON SYSTEMS WITHOUT	;MSH165
; EXECUTIVE COMMON SUPPORT, THIS ROUTINE EXISTS WHOLLY WITHIN THE	;MSH165
; DISPATCHER ITSELF.							;MSH165
;									;MSH165
; INPUTS:								;MSH165
;									;MSH165
;	2(SP)=PS WORD PUSHED BY TRAP INSTRUCTION.			;MSH165
;	0(SP)=PC WORD PUSHED BY TRAP INSTRUCTION.			;MSH165
;									;MSH165
; OUTPUTS:								;MSH165
      ;									;MSH165
;	IF THE STACK DEPTH IS ZERO, THEN THE FIRST EXECUTIVE COMMON	;MSH165
;	IS MAPPED THROUGH KERNEL APR5 AND THE DIRECTIVE DISPATCHER	;MSH165
;	GIVEN CONTROL IN ORDER TO RETURN DIRECTIVE STATUS. NOTE		;MSH165
;	THAT IT IS UNNECESSARY TO SAVE THE CONTENTS OF KERNEL		;MSH165
;	APR5 SINCE WE ARE AT SYSTEM STATE.				;MSH165
;									;MSH165
;	ELSE, CONTROL IS TRANSFERED TO THE EMT/TRAP SST HANDLING	;MSH165
;	ROUTINE.							;MSH165
;-									;MSH165
									;MSH165
	.IF DF	D$$PAR				      			;MSH165
									;MSH165
$TRTRP::TST	$STKDP		;;;STACK DEPTH ZERO?			;MSH165
	BNE	$EMTRP		;;;IF NE NO				;MSH165
	MTPS	#0		;;;ALLOW INTERRUPTS			;MSH165
	MOV	(SP),R0		;GET ADDRESS PLUS 2 OF TRAP INSTRUCTION	;MSH165
	MOVB	-2(R0),R0	;PICK UP DIRECTIVE STATUS		;MSH165
	MOV	$XCOM1,KISAR5	;MAP THE DIRECTIVE DISPATCHER		;MSH165
	JMP	$DRTRP		;PROCESS THE DIRECTIVE STATUS		;MSH165
									;MSH165
;+									;MSH165
; **-$EMTRP-EMT TRAP (EXECUTIVE COMMON ENTRY)				;MSH165
;									;MSH165
; THIS ROU      TINE IS TRAPPED TO WHEN AN EMT INSTRUCTION IS EXECUTED.	;MSH165
; IF THE STACK DEPTH IS NOT +1, THEN THE SYSTEM IS CRASHED. ELSE,	;MSH165
; CONTROL IS IMMEDIATELY TRANSFERED TO THE DIRECTIVE DISPATCHER		;MSH165
; FOR EMT VALIDATION.							;MSH165
;									;MSH165
; ON SYSTEMS WITHOUT EXECUTIVE COMMON SUPPORT, THIS ROUTINE EXISTS	;MSH165
; WHOLLY WITHIN THE DISPATCHER ITSELF.					;MSH165
;									;MSH165
; INPUTS:								;MSH165
;									;MSH165
;	2(SP)=PS WORD PUSHED BY EMT INSTRUCTION.			;MSH1      65
;	0(SP)=PC WORD PUSHED BY EMT INSTRUCTION.			;MSH165
;									;MSH165
; OUTPUTS:								;MSH165
;									;MSH165
;	IF THE STACK DEPTH IS NOT +1, THEN THE SYSTEM IS CRASHED. ELSE	;MSH165
;	THE DIRECTIVE DISPATCHER IS MAPPED THROUGH KERNEL APR5 AND	;MSH165
;	CONTROL TRANSFERED THERE FOR EMT VALIDATION. NOTE THAT IT	;MSH165
;	IS UNNECESSARY TO SAVE THE CONTENTS OF KERNEL APR5 SINCE	;MSH165
;	EMTS ARE CONSIDERED INVALID IF ISSUED FROM SYSTEM STATE.	;MSH165
;-									;MSH165
									;MSH165
$E      MTRP::DIRSV$			;;;SAVE REGISTERS AND SET PRIORITY	;MSH165
	TST	$STKDP		;WERE WE AT STACK DEPTH +1?		;MSH165
	BEQ	5$		;IF EQ YES				;MSH165
	CRASH			;EMT/TRAP WITH $STKDP NOT +1		;MSH165
5$:	MOV	$XCOM1,KISAR5	;MAP THE DIRECTIVE DISPATCHER		;MSH165
	JMP	$DRDSP		;TRANSFER CONTROL TO VALIDATE THE EMT	;MSH165
									;MSH165
;+									;MSH165
; **-$OTHR1-CALL DIRECTIVE ROUTINE RESIDING IN SECOND EXEC COMMON	;MSH165
;									;MSH165
; THIS ROUTINE MAPS THE SECOND EXTERNAL EXECUTIVE COMMON THROUGH	;MS      H165
; KERNEL APR5 AND CALLS THE SPECIFIED DIRECTIVE SERVICE ROUTINE.	;MSH165
;									;MSH165
; INPUTS:								;MSH165
;									;MSH165
;	0(SP)=DIRECTIVE SERVICE ROUTINE / 2				;MSH165
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.			;MSH165
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.			;MSH165
;	R3=ADDRESS OF THE NEXT WORD IN THE DIRECTIVE DPB.		;MSH165
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.	;MSH165
;	R1=DEPENDENT ON DIRECTIVE.					;MSH165
;	R0=DEPENDENT ON DIRECTI      VE.					;MSH165
;									;MSH165
; OUTPUTS:								;MSH165
;									;MSH165
;	THE SECOND EXECUTIVE COMMON IS MAPPED AND THE SPECIFIED		;MSH165
;	DIRECTIVE SERVICE ROUTINE IS CALLED. UPON SUCCESSFUL		;MSH165
;	DIRECTIVE COMPLETION, CONTROL IS RETURNED TO THE DIRECTIVE	;MSH165
;	DISPATCHER FOR PROCESS COMPLETION.				;MSH165
;-									;MSH165
									;MSH165
$OTHR1::ASL	(SP)		;RESTORE TO BYTE ADDRESS		;MSH165
	MOV	$XCOM2,KISAR5	;MAP THE SECOND EXECUTIVE COMMON	;MSH165
	CALL	@(SP)+		;CALL THE DI      RECTIVE ROUTINE		;MSH165
	MOV	$XCOM1,KISAR5	;MAP THE DIRECTIVE DISPATCHER		;MSH165
	JMP	$DRSOK		;SUCCESSFUL DIRECTIVE COMPLETION	;MSH165
									;MSH165
;+									;MSH165
; **-$DRATP-ALTER TASK PRIORITY (EXECUTIVE COMMON TRANSFER ROUTINE)	;MSH165
;									;MSH165
; THIS ROUTINE MAPS THE SECOND EXECUTIVE COMMON AND TRANSFERS		;MSH165
; CONTROL TO THE ALTER PRIORITY DIRECTIVE PROCESSING ROUTINE THERE.	;MSH165
; THIS ROUTINE IS DESIGNED TO PROVIDE TRANSPARENCY TO THE EXISTENCE	;MSH165
; OF THE EXE      CUTIVE COMMONS FOR THE CALLING PROGRAM.			;MSH165
;									;MSH165
; INPUTS:								;MSH165
;									;MSH165
;	(R3)=NEW TASK PRIORITY						;MSH165
;	SEE DESCRIPTION OF $DRAP1 FOR MORE INPUTS			;MSH165
;									;MSH165
; OUTPUTS:								;MSH165
;									;MSH165
;	THE SECOND EXECUTIVE COMMON IS MAPPED THROUGH KERNEL APR5	;MSH165
;	AND THE ALTER PRIORITY DIRECTIVE CODE IS CALLED.		;MSH165
;-									;MSH165
									;MSH165
	.IF DF	A$$PRI							;MSH165
									;MSH165
$DRATP::MOV	(R3),R3		;     GET NEW TASK PRIORITY			;MSH165
	CALL	$MPXC2		;MAP THE SECOND EXECUTIVE COMMON	;MSH165
	CALLR	$DRAP2		;CALL THE ALTER PRIORITY CODE		;MSH165
									;MSH165
	.ENDC								;MSH165
									;MSH165
	.ENDC	;D$$PAR							;MSH165
									;MSH165

	.END
         LðskQ	› c,           	.TITLE	DUDRV
	.IDENT	/01/
;
;		COPYRIGHT (c) 1981 BY
;	DIGITAL EQUIPMENT CORPORATION, MAYNARD
;	 MASSACHUSETTS.  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 TRANSFERED.
;
; THE INFORMATION  IN THIS DOCUMENT 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 THAT IS NOT SUPPLIED BY DIGITAL.
;
;
; VERSION 01
;
; R. T. PERRON 11-NOV-81
;
; UDA50 CLASS DISK DRIVER
;
; MACRO LIBRARY CALLS
;
	.MCALL	HWDDF$,PKTDF$,UCBDF$,UDADF$
	HWDDF$			;HARDWARE REGISTERS
	PKTDF$			;I/O PACKE      T OFFSETS
	UCBDF$			;UNIT CONTROL BLOCK OFFSETS
	UDADF$			;DISK CLASS MSCP SYMBOLS AND OFFSETS
	.PAGE

;
; EQUATED SYMBOLS
;
; UDA50 UNIBUS DEVICE REGISTER AND BIT DEFINITIONS
;

UDAIP	=	0		;INITIALIZATION AND POLLING REGISTER
UDASA	=	2		;STATUS AND ADDRESS REGISTER

;+
; STATUS AND ADDRESS REGISTERS BITS (ERROR READ FORMAT)
;
; BIT 15 IS DEFINED AS THE FATAL ERROR FORMAT:
;
;	BIT 15 = 1
;
; BIT 14 - 11 ARE DEFINED AS THE LAST SUCCESSFULLY COMPLETED STEP FUNCTION:
;
;	BIT 14 = 1 IS ST      EP 4
;	BIT 13 = 1 IS STEP 3
;	BIT 12 = 1 IS STEP 2
;	BIT 11 = 1 IS STEP 1
;-

ERROR	=	100000		;ERROR
S4	=	40000		;STEP 4 BIT
S3	=	20000		;STEP 3 BIT
S2	=	10000		;STEP 2 BIT
S1	=	4000		;STEP 1 BIT
ERRCOD	=	3777		;ERROR CODE MASK

;
; ERROR CODE DEFINITIONS
;

ER001	=	1		;ENVELOPE READ (PARITY OR TIMEOUT)
ER002	=	2		;ENVELOPE WRITE (PARITY OR TIMEOUT)
ER003	=	3		;CONTROLLER ROM AND RAM PARITY
ER004	=	4		;CONTROLLER RAM PARITY
ER005	=	5		;CONTROLLER ROM PARITY
ER006	=	6		;RING READ (PARIT      Y OR TIMEOUT)
ER007	=	7		;RING WRITE (PARITY OR TIMEOUT)
ER008	=	8.		;INTERRUPT MASTER
ER009	=	9.		;HOST ACCESS TIMEOUT (HIGHER-LEVEL PROTOCOL DEPENDENT)
ER010	=	10.		;COMMAND LIMIT EXCEEDED
ER011	=	11.		;DEVICE FATAL HARDWARE ERROR
ER012	=	12.		;DIAGNOSTIC CONTROLLER FATAL ERROR
ER013	=	13.		;INSTRUCTION LOOP TIMEOUT
ER014	=	14.		;INVALID VIRTUAL CIRCUIT IDENTIFIER
ER015	=	15.		;INTERRUPT WRITE
ER016	=	16.		;MAINTENANCE READ/WRITE INVALID REGION IDENTIFIER
ER017	=	17.		;MAINTENANCE WRITE LOAD TO       NON-LOADABLE CONTROLLER

;
; ER018 - ER199 CODES UNASSIGNED
;

;+
; STATUS AND ADDRESS REGISTERS BITS (STEP ONE READ FORMAT)
;
; BITS 15 - 11 ARE DEFINED THE SAME AS THE ERROR FORMAT EXCEPT:
;
;	BIT 15 = 0
;	BIT 14 = 0
;	BIT 13 = 0
;	BIT 12 = 0
;	BIT 11 = 1
;
; BITS 10 - 8 ARE THE CONTROLLER TYPE FIELD
; BITS 7 - 0 ARE RESERVED
;-

STEP1	=	S1		;STEP ONE MASK
NOVEC	=	2000		;INABILITY TO ACCEPT INTERRUPT VECTOR
				;(I.E. CONTROLLER IS USING A HARD-WIRED ...
				;... INTERRUPT VECTOR       PLUG)
EXTMEM	=	1000		;EXTENDED MEMORY SUPPORT
DIAGI	=	400		;ENHANCED DIAGNOSTIC SUPPORT

;+
; STATUS AND ADDRESS REGISTER BITS (STEP ONE WRITE FORMAT)
;
; BIT 15 MUST SET TO ONE
; BIT 14 IS RESERVED FOR DIAGNOSTIC PURPOSES
; BITS 13 - 11 ARE DEFINED AS COMMAND RING LENGTH BITS
; BITS 10 -  8 ARE DEFINED AS RESPONSE RING LENGTH BITS
; BIT 7 IS DEFINED AS INTERRUPT ENABLE FLAG
; BITS 6 - 0 ARE DEFINED AS INTERRUPT VECTOR / 4
;-

;
; HIGH BYTE FORMAT AS FOLLOWS:
;

CRL2	=	40		;COMMAND RING L      ENGTH BIT 2
CRL1	=	20		;COMMAND RING LENGTH BIT 1
CRL0	=	10		;COMMAND RING LENGTH BIT 0
CRLNG	=	CRL2+CRL1+CRL0	;LENGTH BIT MASK
				;LENGTH IS GIVEN AS A POWER OF TWO - 
				;I.E. 0 ALLOCATES ONE DESCRIPTOR FOR COMMAND RING
MRL2	=	4		;MESSAGE RING LENGTH BIT 2
MRL1	=	2		;MESSAGE RING LENGTH BIT 1
MRL0	=	1		;MESSAGE RING LENGTH BIT 0
MRLNG	=	MRL2+MRL1+MRL0	;LENGTH BIT MASK
				;LENGTH IS GIVEN AS A POWER OF TWO -
				;I.E. 0 ALLOCATES ONE DESCRIPTOR FOR MESSAGE RING

;
; LOW BYTE FORMAT AS FOLL      OWS:
;

INTE	=	200		;INTERRUPT ENABLE
INTVEC	=	177		;INTERRUPT VECTOR BYTE MASK
				;INTERRUPT VECTOR / 4


;+
; STATUS AND ADDRESS REGISTER BITS (STEP TWO READ FORMAT)
;
; BITS 15 - 11 ARE DEFINED THE SAME AS THE ERROR FORMAT EXCEPT:
;
;	BIT 15 = 0
;	BIT 14 = 0
;	BIT 13 = 0
;	BIT 12 = 1
;	BIT 11 = 0
;
; BITS 10 - 8 ARE THE PORT TYPE NUMBER
; BITS 7 - 0 WILL BE THE SAME AS IN LOW BYTE OF STEP ONE WRITE FORMAT
;-

STEP2	=	S2		;STEP TWO MASK
PRTYP	=	7000		;PORT TYPE MASK

;+
; STATU      S AND ADDRESS REGISTER BITS (STEP TWO WRITE FORMAT)
;
; BITS 15 - 1 ARE THE LOW ORDER ADDRESS OF COMMUNICATIONS AREA
; (MUST BE ON A WORD BOUNDARY)
;-

;
; LOW ORDER 16-BITS OF THE BEGINNING ADDRESS IN COMMUNICATIONS AREA.
; (I.E. BASE ADDRESS OF THE RING BUFFERS FOR THIS CONTROLLER)
;


;+
; STATUS AND ADDRESS REGISTER BITS (STEP THREE READ FORMAT)
;
; BITS 15 - 11 ARE DEFINED THE SAME AS THE ERROR FORMAT EXCEPT:
;
;	BIT 15 = 0
;	BIT 14 = 0
;	BIT 13 = 1
;	BIT 12 = 0
;	BIT 11 = 0
;
;       BITS 10 - 8 ARE RESERVED
; BITS 7 - 0 ARE IN THE SAME FORMAT AS LOW BYTE OF STEP ONE WRITE FORMAT
;-

STEP3	=	S3		;STEP THREE MASK

;+
; STATUS AND ADDRESS REGISTER BITS (STEP THREE WRITE FORMAT)
;
; BIT 15 IS RESERVED
; BITS 14 - 0 ARE THE HIGH ORDER ADDRESS OF THE COMMUNICATIONS AREA
;-

;
; HIGH ORDER 14-BITS OF THE BEGINNING ADDRESS IN COMMUNICATIONS AREA.
; (I.E. BASE ADDRESS OF THE RING BUFFERS FOR THIS CONTROLLER)
; (MUST BE RIGHT JUSTIFIED)
;

;+
; STATUS AND ADDRESS REGISTER BIT      S (STEP FOUR READ FORMAT)
;
; BITS 15 - 11 ARE DEFINED THE SAME AS THE ERROR FORMAT EXCEPT:
;
;	BIT 15 = 0
;	BIT 14 = 1
;	BIT 13 = 0
;	BIT 12 = 0
;	BIT 11 = 0
; BITS 10 - 8 ARE RESERVED
; BITS  7 - 0 CONTROLLER MICRO-CODE VERSION NUMBER
;-

STEP4	=	S4		;STEP FOUR MASK

UCODE	=	377		;MICRO-CODE VERSION NUMBER MASK

;+
; STATUS AND ADDRESS REGISTER BITS (STEP FOUR WRITE FORMAT)
;
; BITS 15 - 8 ARE RESERVED
; BITS  7 - 3 BURST TRANSFER CONTROL
; BIT 1 IS LAST FAILURE FLAG
; BIT 0 IS THE       GO BIT
;-

BURST	=	374		;BURST TRANSFER MASK
LFAIL	=	2		;LAST FAILURE FLAG
GO	=	1		;GO BIT

;
; COMMAND/MESSAGE DESCRIPTOR OFFSETS
;

CMDINT	=	-4		;COMMAND INTERRUPT OFFSET (FROM BASE OF RING)
RSPINT	=	-2		;RESPONSE INTERRUPT OFFSET (FROM BASE OF RING)
LADDR	=	-2		;LOW ORDER 16-BIT BYTE ADDRESS LOCATION
HADDR	=	0		;HIGH ORDER 14-BIT BYTE ADDRESS LOCATION AND FLAGS

;
; COMMAND/MESSAGE DESCRIPTOR WORD 0 FORMAT
;

;
; 16-BIT LOW ORDER BYTE ADDRESS OF MSCP PACKET (MUST BE WORD ALIGNED)
;      

;
; COMMAND/MESSAGE DESCRIPTOR WORD 1 FORMAT
;

OWN	=	100000		;OWN
FLAG	=	40000		;FLAG

;
; 14-BITS HIGH ORDER BYTE ADDRESS OF MSCP PACKET ADDRESS
;

;
; MESSAGE ENVELOPE
;

MSGLNG	=	-4		;OFFSET TO MESSAGE LENGTH (IN BYTES)
VCID	=	-1		;OFFSET TO VIRTUAL CIRCUIT ID (IN BYTES)
CREDIT	=	-2		;OFFSET TO MESSAGE/CREDIT FIELD (IN BYTES)
MSGTYP	=	360		;MESSAGE TYPE MASK
CRDDBT =	17		;CREDIT/DEBIT MASK

;
; VIRTUAL CIRCUIT IDENTIFIERS
;

VCDSK	=	0		;DISK VIRTUAL CIRCUIT ID
VCDIA	=	255.		      ;DIAGNOSTIC VIRTUAL CIRCUIT ID

;
; MESSAGE TYPE IDENTIFIERS
;

MSGMUL	=	20		;MESSAGE FIELD MULTIPLIER
MSGSEQ	=	0		;SEQUENTIAL MESSAGE
MSGDAT	=	1		;DATAGRAM MESSAGE
MSGCRD	=	2		;CREDIT MESSAGE
MSGMNT	=	15.		;MAINTENANCE MESSAGE

;
; ERROR RETRY COUNT
;

RETRY	=	3.		;CONTROLLER ERROR RETRY COUNT

;
; INTERNAL BIT FLAG FUNCTION INDICATORS FOR CONTROLLER STATE
;

;
; FLAGS IN C.STAT+1
;
C2.INI	=	200		;INITIALIZATION IS IN PROGRESS
C2.PWF	=	100		;POWERFAIL OCCURRED
C2.ONL	=	1		;CONTRO      LLER ON-LINE IS IN PROGRESS
;
; FLAGS IN C.STAT
;
C1.OFF	=	200		;CONTROLLER OFF-LINE
C1.INI	=	100		;RE-INITIALIZATION REQUIRED
C1.CQR	=	10		;CLOCK QUEUE REQUEST
C1.CMD	=	4		;COMMAND RING BUFFER IS FULL
C1.CLK	=	2		;CLOCK ACTIVE FLAG
C1.ON	=	1		;CONTROLLER ON-LINE 

;
; DRIVER SYMBOLS
;

ENVLP	=	-<MSGLNG>	;ADDITIONAL SIZE OF PACKET (IN BYTES) ...
				;... TO ACCOMMADATE THE ENVELOPE
RNGSIZ	=	4		;LENGTH OF RING BUFFER ENTRY (IN BYTES)
RSPLNG	=	L.LENG + ENVLP	;TOTAL LENGTH OF RESPONSE PACKET       (IN BYTES)
CMDLNG	=	P.LENG + ENVLP	;TOTAL LENGTH OF COMMAND PACKET (IN BYTES)

;
; FOR DEBUGGING PURPOSES (USING XDT) UNCOMMENT THE FOLLOWING LINE OF CODE
;.IIF DF X$$DBT, DEBUG = 0
;

;
; LOCAL MACROS
;

	.MACRO	LABEL	NUM,NAM,SUFFIX
	.IF NB	<SUFFIX>
NAM'NUM'SUFFIX:
	.IFF	;NB <SUFFIX>
NAM'NUM:
	.ENDC	;NB <SUFFIX>
	.ENDM	LABEL

	.MACRO	POINT	NUM,NAM,SUFFIX
	.IF NB	<SUFFIX>
	.WORD	NAM'NUM'SUFFIX
	.IFF	;NB <SUFFIX>
	.WORD	NAM'NUM
	.ENDC	;NB <SUFFIX>
	.ENDM	POINT

	.MACRO	SPACE	NUM,N      AM,LENG
	.BLKB	NAM'NUM'*'LENG
	.ENDM	SPACE

	.MACRO	DURNG$	DEV,NCTRLR,NSIZE
N=0
	.REPT	NCTRLR
	.BLKW	2
	LABEL	\N,DEV,RG
	SPACE	\N,DEV'$R,NSIZE
	SPACE	\N,DEV'$C,NSIZE
N=N+1
	.ENDR	;NCTRLR
	.MACRO	DURNG$	X,Y,Z
	.ENDM	DURNG$
	.ENDM	DURNG$

	.MACRO	DUPKT$	DEV,NCTRLR,RLENG,CLENG
N=0
	.REPT	NCTRLR
	LABEL	\N,DEV,PK
	SPACE	\N,DEV'$R,RLENG
	SPACE	\N,DEV'$C,CLENG
N=N+1
	.ENDR	;NCTRLR
	.MACRO	DUPKT$	A,B,C,D
	.ENDM	DUPKT$
	.ENDM	DUPKT$

	.MACRO	DULNG$	NUM,NAM
	.IF DF	NAM'$R'NUM & NAM'$C'NU      M
	.IIF EQ NAM'$R'NUM'-1,'NAM'LR'NUM'=0
	.IIF EQ NAM'$C'NUM'-1,'NAM'LC'NUM'=0
	.IIF EQ NAM'$R'NUM'-2,'NAM'LR'NUM'=1
	.IIF EQ NAM'$C'NUM'-2,'NAM'LC'NUM'=1
	.IIF EQ NAM'$R'NUM'-4,'NAM'LR'NUM'=2
	.IIF EQ NAM'$C'NUM'-4,'NAM'LC'NUM'=2
	.IIF EQ NAM'$R'NUM'-8.,'NAM'LR'NUM'=3
	.IIF EQ NAM'$C'NUM'-8.,'NAM'LC'NUM'=3
	.IIF EQ NAM'$R'NUM'-16.,'NAM'LR'NUM'=4
	.IIF EQ NAM'$C'NUM'-16.,'NAM'LC'NUM'=4
	.IIF EQ NAM'$R'NUM'-32.,'NAM'LR'NUM'=5
	.IIF EQ NAM'$C'NUM'-32.,'NAM'LC'NUM'=5
	.IIF EQ NAM'$R'NUM'-64.,'NAM'L      R'NUM'=6
	.IIF EQ NAM'$C'NUM'-64.,'NAM'LC'NUM'=6
	.IIF EQ NAM'$R'NUM'-128.,'NAM'LR'NUM'=7
	.IIF EQ NAM'$C'NUM'-128.,'NAM'LC'NUM'=7
	.BYTE	NAM'$R'NUM','NAM'LR'NUM
	.BYTE	NAM'$C'NUM','NAM'LC'NUM
	.WORD	10*NAM'LC'NUM'+'NAM'LR'NUM
	.BYTE	NAM'$C'NUM'+'NAM'$R'NUM
	.BYTE	NAM'$C'NUM'+'NAM'$R'NUM
	.ENDC	;DF NAM'$C'NUM & NAM'$R'NUM
	.ENDM	DULNG$

	.MACRO	DUCST$	DEV,NCTRLR
N=0
	.REPT	NCTRLR
	POINT	\N,'DEV',TB
N=N+1
	.ENDR	;NCTRLR
	.MACRO	DUCST$	X,Y
	.ENDM	DUCST$
	.ENDM	DUCST$

	.MACRO	DUTBL$	DEV,      NCTRLR
N=0
	.REPT	NCTRLR
	LABEL	\N,DEV,TB
	.IF DF	M$$MGE
	.BLKW	8.
	.IFF	;M$$MGE
	.BLKW	5.
	.ENDC	;M$$MGE
	POINT	\N,'DEV',RG
	DULNG$	\N,DEV
	POINT	\N,'DEV',PK
	POINT	\N,'DEV',PK
	.BLKB	C.LONG-C.PKT+4
N=N+1
	.ENDR	;NCTRLR
	.MACRO	DUTBL$	X,Y
	.ENDM	DUTBL$
	.ENDM	DUTBL$

;
; DUDRV CONTROLLER STATE TABLE FORMAT
;

	.ASECT

.=0
C.STAT:	.BLKW	1		;CONTROLLER STATE FLAGS
C.RTRY:	.BLKW	1		;RETRY COUNT
C.CMDS:	.BLKW	1		;COUNT FOR COMMANDS ISSUED

	.IF DF	M$$MGE

C.PAR5:	.BLKW	1		;MAPP      ING SAVE AREA, APR5
C.PAR6:	.BLKW	1		;MAPPING SAVE AREA, APR6
C.SAPR:	.BLKW	1		;MAPPING SAVE AREA, PREVIOUS APR6

	.ENDC	;M$$MGE


C.RELC:	.BLKW	2		;RELOCATION CONSTANT (DOUBLE WORD)
C.RING:	.BLKW	1		;BASE ADDRESS OF RINGS
C.RSP:	.BLKW	1		;NUMBER OF RESPONSE RINGS/LOG BASE 2 OF NUMBER 
				;OF RESPONSE RINGS
C.CMD:	.BLKW	1		;NUMBER OF COMMAND RINGS/LOG BASE 2 OF NUMBER 
				;OF COMMAND RINGS
C.STP1:	.BLKW	1		;SIZE OF COMMAND/RESPONSE RINGS ROR STEP 1 (LOW BYTE)
C.PKTS:	.BLKB	1		;NUMBER OF PACK      ETS
C.NMBR:	.BLKB	1		;NUMBER OF AVAILABLE PACKETS
C.PKT:	.BLKW	2		;BASE ADDRESS OF PACKETS
				;SECOND WORD IS POINTER TO CURRENT PACKET
;
; CHARACTERISTICS OBTAINED FROM "SET CONTROLLER CHARACTERISTICS" END PACKET
;
C.VRSN:	.BLKW	1		;MSCP VERSION
C.CNTF:	.BLKW	1		;CONTROLLER FLAGS
C.CTMO:	.BLKW	1		;CONTROLLER TIME OUT
	.BLKW	1		;RESERVED
C.CNTI:	.BLKW	4		;CONTROLLER ID


	.IF DF	E$$DVC

;
; CONTROLLER ERROR LOG PACKET
;
C.MLNG:	.BLKW	1		;LENGTH OF CONTROLLER TIMEOUT PACKET
C.VCID:	.BLKB      	1		;VIRTUAL CIRCUIT ID
C.CRED:	.BLKB	1		;CREDIT/DEBIT FIELD
C.IP:	.BLKW	1		;SAVED VALUE OF UDAIP REGISTER
C.SA:	.BLKW	1		;SAVED VALUE OF UDASA REGISTER

	.ENDC	;E$$DVC


;
; DRIVER / CONTROLLER STATE
;
C.IOPK:.BLKW	1		;OUTSTANDING I/O PACKET STORAGE AREA
C.CLCC:	.BLKB	1		;CURRENT LOOP COUNT CONTROL
C.ILCC:	.BLKB	1		;INITIAL LOOP COUNT CONTROL
C.INIT:	.BLKW	2		;CONTROLLER INITIALIZATION STATE
C.ITBL:	.BLKW	4		;INITIALIZATION TABLE
C.IOSB:	.BLKW	2		;TWO WORD STATUS BLOCK
				;FIRST WORD IS S      TATUS CODE
				;SECOND WORD IS BYTE COUNT TRANSFERED
;
; NOTE: FOR THE SAKE OF SPEED AND SIZE, THE RING BUFFER POINTERS POINT
; TO THE SECOND WORD OF A TWO-WORD RING ENTRY
;
C.CRSP:	.BLKW	2		;CURRENT RESPONSE RING BUFFER POINTER
				;AND VIRTUAL ADDRESS OF ITS PACKET
C.FRSP:	.BLKW	2		;FIRST RESPONSE RING BUFFER POINTER
				;AND VIRTUAL ADDRESS OF ITS PACKET
C.LRSP:	.BLKW	2		;LAST RESPONSE RING BUFFER POINTER
				;AND VIRTUAL ADDRESS OF ITS PACKET
C.CCMD:	.BLKW	2		;CURRENT COMMAND RING BUFFER POI      NTER
				;AND VIRTUAL ADDRESS OF ITS PACKET
C.FCMD:	.BLKW	2		;FIRST COMMAND RING BUFFER POINTER
				;AND VIRTUAL ADDRESS OF ITS PACKET
C.LCMD:	.BLKW	2		;LAST COMMAND RING BUFFER POINTER
				;AND VIRTUAL ADDRESS OF ITS PACKET
C.LONG	=	. - C.STAT	;LENGTH OF CONTROLLER STATE TABLE (IN BYTES)

	.PSECT

;
; LOCAL DATA
;
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
;

DUSTRT:				;START OF DRIVER
;
; DRIVER DISPATCH TABLE
;

$DUTBL::.WORD	DUINI		;INITIATOR ENTRY POINT
	.WORD      	DUCAN		;CANCEL ENTRY POINT
	.WORD	DUOUT		;TIMEOUT ENTRY POINT
	.WORD	DUPWF		;POWERFAIL ENTRY POINT
CNTBL:	.BLKW	R$$UDA		;UCB POINTER


	.IF GT	R$$UDA-1

TEMP:	.BLKW	1		;TEMPORARY STORAGE FOR CONTROLLER NUMBER

	.ENDC	;R$$UDA-1


CTTBL:	DUCST$	DU,R$$UDA	;CONTROLLER STATE TABLE POINTERS
	
;
; MISCELLANEOUS WORDS
;


RCTNAM:.RAD50	/RCT.../	;REPLACEMENT CONTROL TASK'S TASKNAME
RCTTCB:.BLKW	1		;REPLACEMENT CONTROL TASK'S TCB ADDRESS

DUDCB:	.BLKW	1		;POINTER TO DU:'S FIRST DCB
DUDCB2:	.B      LKW	1		;POINTER TO DU:'S CURRENT DCB

;
; USER MODE DIAGNOSTIC SUPPORT DEFINITIONS
;


	.IF DF	D$$IAG

	.MCALL	UMDIO$
	UMDIO$			;DEFINE USER MODE DIAGNOSTIC FUNCTIONS

DUDIAG:				;TABLE OF DEFINED USER MODE DIAGNOSTIC FUNCTIONS
	.WORD	0		;TERMINATOR

	.ENDC	;D$$IAG
	.PAGE
;+
; **- DUINI - UDA50 CONTROLLER INITIATOR
;
; THIS ROUTINE IS ENTERED AT THE END OF A PREVIOUS I/O OPERATION TO
; PROPAGATE THE EXECUTION OF THE DRIVER.  IF THE SPECIFIED CONTROLLER/UNIT
; COMMAND LIMIT HAS NOT BEEN       EXCEEDED THEN AN ATTEMPT IS MADE TO DEQUEUE
; THE NEXT I/O REQUEST.  ELSE THE RESULTS FROM ANY PREVIOUS I/O REQUEST 
; ARE CHECKED FOR COMPLETION.  IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN 
; THAT I/O OPERATION IS INIITIATED.  IF THERE ARE NO I/O REQUEST WHICH 
; MAY BE DEQUEUED NOR ANY RESULTS FROM PREVIOUS I/O REQUESTS, THEN THE 
; DRIVER WILL EXIT BACK TO THE SYSTEM.
;
; INPUTS:
;
;	R5 = ADDRESS  OF THE UCB OF THE UNIT TO BE INITIATED
;
; OUTPUTS:
;
;	IF THE SPECIFIED CONTROLLER/UNIT COMM      AND LIMIT HAS NOT BEEN
;	EXCEEDED AND AN I/O REQUEST IS WAITING TO BE PROCESSED, THEN THE
;	REQUEST IS DEQUEUED AND THE I/O OPERATION IS INITIATED.
;
;-

	.ENABL	LSB

DUINI:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	U.SCB(R5),R4	;RETRIEVE SCB ADDRESS
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOV	#DURSP,-(SP)	;SET UP A RETURN ADDRESS IF WE FAIL
	MOV	#PRTST,R2	;POINT TO PORT TEST/ACCEPTANCE ROUTINE
	CALL	$GSPKT		;GET A      N I/O PACKET TO PROCESS
	BCC	10$		;IF CC, GOT A PACKET
	RETURN			;NO, FAILED TO GET A PACKET EXIT
				;TO CHECK RESPONE RINGS

;
; WE GOT A PACKET - ADDRESS IN R1
;

;+
;
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GSPKT
;
;	R1 = ADDRESS OF THE I/O REQUEST PACKET.
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3 = CONTROLLER INDEX.
;	R4 = ADDRESS OF THE STATUS CONTROLLER BLOCK.
;	R5 = ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; UDA50 CLASS DISK I/O REQUEST PACKET FORMAT.      
;
;	WD 00 -- I/O QUEUE THREAD WORD (I.LINK).
;	WD 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER (I.EFN & I.PRI).
;	WD 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK (I.TCB).
;	WD 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER (I.LN2).
;	WD 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (I.UCB).
;	WD 05 -- I/O FUNCTION CODE (IO.RLB/IO.WLB) (I.FCN).
;	WD 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK (I.IOSB).
;	WD 07 -- RELOCATION BIAS OF I/O STATUS BLOCK (I.IOSB+2).
;	WD 10 -- I/O       STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000) (I.IOSB+4).
;	WD 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE (I.AST).
;
; FOLLOWING FORMAT APPLIES TO ALL DATA TRANSFER FUNCTIONS:
;
;	WD 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER (I.PRM).
;	WD 13 -- BUFFER ADDRESS OF I/O TRANSFER (I.PRM+2).
;	WD 14 -- NUMBER OF BYTES TO BE TRANSFERED (I.PRM+4).
;	WD 15 -- DIAGNOSTIC SUPPLIMENTAL PARAMETER ELSE NOT USED (I.PRM+6).
;	WD 16 -- HIGH PART OF LOGICAL BLOCK NUMBER AND HIGH BYTE NOT U      SED (I.PRM+10).
;	WD 17 -- LOW PART OF LOGICAL BLOCK NUMBER OF I/O REQUEST (I.PRM+12).
;	WD 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLOCK ADRS ELSE NOT USED (I.PRM+14).
;	WD 21 -- DIAGNOSTIC REG. BLOCK ADRS (REAL OR DISPLACEMENT + 140000) (I.PRM+16).
;
;
; FOLLOWING FORMAT APPLIES TO ALL CONTROL FUNCTIONS:
;
;	INITIALIZE FUNCTION CODE
;
;	NO PARAMETERS REQUIRED
;
;	REPLACEMENT FUNCTION CODE
;
;	WD 12 -- HI PART OF REPLACEMENT BLOCK NUMBER AND HIGH BYTE NOT USED (I.PRM)
;	WD 13 -- LO PART OF       REPLACEMENT BLOCK NUMBER (I.PRMT+2)
;	WD 14 -- HI PART OF LOGICAL BLOCK NUMBER AND HIGH BYTE NOT USED (I.PRM+6).
;	WD 15 -- LO PART OF LOGICAL BLOCK NUMBER OF I/O REQUEST (I.PRM+10).
;	WD 16 -- PRIMARY REPLACEMENT BLOCK MODIFIER (I.PRM+12).
;	WD 17 -- 
;	WD 20 --
;
;	TERMINATE REPLACEMENT FUNCTION CODE
;
;	WD 12 -- I/O PACKET ADDRESS TO COMPLETE I/O OPERATION IN PROGRESS
;	WD 13 -- SUCCESS/FAILURE CODE OF REPLACEMENT
;		 IS.SUC = SUCCESS
;		 IE.VER = FAILURE
;
;-

10$:	TST	(SP)+		;CLN THE ST      ACK


	.IF DF	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	R5,CNTBL(R3)	;SAVE UCB ADDRESS FOR LATER
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINTER
	MOVB	C.ILCC(R3),C.CLCC(R3)	;SET LOOP COUNT CONTROL


;
; CHECK AND VALIDATE THE I/O FUNCTION CODE
;

	MOV	R1,S.PKT(R4)	;SAVE I/O PACKET


	.IF DF	D$$IAG

	CMPB	#IO.HMS/256.,I.FCN+1(R1)  ;USER MODE DIAGNOSTIC FUNCTION?
	BNE	30$		;IF NE NO
	MOV	#DUDIAG,R0	;YES, GET USER MODE DIAGNOSTIC TA      BLE
20$:	TST	(R0)		;DIAGNOSTIC FUNCTIONS DEFINED?
	BEQ	ERRIFC		;IF EQ NO
	CMPB	(R0)+,I.FCN(R1)	;LOCATE DESIRED DIAGNOSTIC FUNCTION?
	BNE	20$		;IF NE NO
	BR	70$		;YES, GO ON

	.ENDC	;D$$IAG


30$:	MOV	I.TCB(R1),R2	;GET REQUESTING TASK'S TCB ADDRESS
	MOV	I.FCN(R1),R0	;GET FUNCTION CODE
	CMP	#IO.LOV,R0	;IS IT LOAD OVERLAY FUNCTION?
	BEQ	60$		;IF EQ YES
	BIC	#7,R0		;NO, REMOVE QUALIFIER BITS
 	CMPB	#IO.RLB/256.,I.FCN+1(R1)  ;DATA TRANSFER FUNCTION?
	BLO	80$		;IF LO NO
	TSTB	I.FCN(R1)	;ANY SUB-F      UNCTION CODES SET?
	BEQ	60$		;IF EQ NO
	CMPB	#IO.WLC&IO.RLC,R0  ;COMPARE SUB-FUNCTION CODE SET?
	BEQ	60$		;IF EQ YES
	CMP	#IO.RSN,R0	;READ VOLUME SERIAL NUMBER SUB-FUNCTION CODE SET?
	BEQ	40$		;IF EQ YES
	BIT	#T3.PRV,T.ST3(R2)  ;IS TASK PRIVILEGED?
	BEQ	50$		;IF EQ NO
	CMP	RCTTCB,R2	;YES, THEN IS THIS RCT?
	BNE	50$		;IF NE NO
	CMPB	#IO.RPB&IO.WPB,R0  ;PHYSICAL BLOCK SUB-FUNCTION CODE SET?
	BEQ	70$		;IF EQ YES
	CMP	#IO.WDD,R0	;WRITE DELETED DATA FUNCTION?
	BEQ	70$		;IF EQ YES
ERRPRI:	MOV	#IE.PR      I&377,R0	;SET PRIVILEGE VIOLATION
	BR	DUFIN		;AND FINISH UP
ERRIFC:	MOV	#IE.IFC&377,R0	;ASSUME ILLEGAL FUNCTION
DUFIN:	MOV	R1,R3		;COPY I/O PACKET ADDRESS INTO R3
	CLR	R1		;ZERO BYTE COUNT TRANSFERRED
DUFIN1:	CALL	$IOFIN		;FINISH UP THIS I/O
	BR	DUINI		;PROCESS NEXT REQUEST
40$:	MOV	#IE.BYT&377,R0	;ASSUME ILLEGAL BYTE COUNT
	CMP	#4,I.PRM+4(R1)	;IS BYTE COUNT .GE. 4
	BHI	DUFIN		;IF HI NO
	CALL	DURSN		;COPY VOLUME SERIAL NUMBER INTO USER'S BUFFER
	BR	DUFIN1		;FINISH UP I/O
50$:	BITB	#IQ.X!IQ.Q!IQ.      UMD,I.FCN(R1)  ;ANY GENERAL SUB-FUNCTION BITS SET?
	BEQ	ERRIFC		;IF EQ NO
60$:	CALL	$BLKCK		;VALIDATE THE LBN
70$:	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?
	BNE	100$		;IF NE YES
	CALL	DUMAP		;MAP THE BUFFER ADDRESS THRU UMR'S
	CALL	$STMP1		;SET-UP THE UNIBUS MAP
	CLR	U.CNT(R5)	;CLR UMR MAPPING INTERLOCK
	MOV	R1,R0		;RESTORE POINTER TO UMR WAITING BLOCK
	ADD	#10,R0		;OFFSET TO UMR ASSIGNMENT BLOCK
	MOV	R2,S.PKT(R4)	;SAVE       I/O PACKET ADDRESS
	CALL	$MPUB1		;MAP UNIBUS TO TRANSFER

	.ENDC	;M$$EXT


	BR	100$		;SKIP OVER NEXT
80$:	CMP	#IO.SEC,R0	;SENSE CHARACTERISTICS FUNCTION?
	BEQ	90$		;IF EQ YES
	BIT	#T3.PRV,T.ST3(R2)  ;TASK PRIVILEGED?
	BEQ	ERRPRI		;IF EQ NO
	CMP	RCTTCB,R2	;YES, THEN IS THIS RCT?
	BNE	ERRPRI		;IF NE NO
	CMP	#IO.INL,R0	;INITIALIZE FUNCTION?
	BEQ	90$		;IF EQ YES


	.IF DF	DEBUG

81$:	BPT			;GET TO XDT
	MOV	#NOP,81$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CMP	#IO.RPL,R0	;REPLACE FUNCTION?
	B      EQ	90$		;IF EQ YES
	CMP	#IO.TRM,R0	;TERMINATE FUNCTION?
	BNE	ERRIFC		;IF NE NO


	.IF DF	DEBUG

83$:	BPT			;GET TO XDT
	MOV	#NOP,83$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINTER
	MOV	I.PRM(R1),S.PKT(R4)  ;SAVE I/O PACKET ADDRESS IN SCB
	MOVB	I.PRM+2(R1),C.IOSB(R3)  ;SAVE POTENTIAL STATUS CODE
DUSUC:	MOV	#IS.SUC&377,R0	;SET SUCCESS STATUS CODE
	MOV	R1,R3		;COPY I/O PACKET ADDRESS INTO R3
	CLR	R1		;CLR R1
	CALL	$IOFIN		;FINISH THIS I/O
	MOV	U      .SCB(R5),R4	;RESTORE SCB ADDRESS
	MOV	R5,R0		;COPY UCB ADDRESS TO R0
	ADD	#U.BPKT,R0	;ADD OFFSET TO BAD BLOCK REPLACEMENT QUEUE
	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS TO TERMINATE
	CALL	$QRMVT		;GET I/O PACKET FROM BAD BLOCK REPLACEMENT QUEUE


	.IF DF	DEBUG

	BCC	85$		;IF CC OK
	CRASH			;SOMETHING'S WRONG
85$:				;REF LABEL

	.ENDC	;DEBUG


	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINTER
	TSTB	C.IOSB(R3)	;RESTART THE I/O FOR THIS       PACKET?
	BPL	90$		;IF PL YES
	JMP	DUDON		;NO, FINISH IT UP
90$:	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX
100$:	MOV	S.PKT(R4),R2	;COPY I/O PACKET ADDRESS INTO R2
	MOV	#DUINI,-(SP)	;SET RETURN ADDRESS ON STACK

	.DSABL	LSB

;+
; **- DUCMD - MSCP COMMAND PROCESSOR
;
; THE MSCP COMMAND PROCESSOR WILL INITIATE GETTING A COMMAND RING PACKET
; FILLED IN WITH THE APPROPRIATE VALUES, QUEUE THE I/O PACKET TO THE UNIT'S
; I/O ACTIVE QUEUE, AND CAUSE THE MSCP PACKET TO BE QUEUED TO THE CONTROLLER.
;
      ; INPUTS:
;
;	R2 = I/O PACKET
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE SPECIFIED I/O PACKET IS TRANSFORMED INTO AN MSCP PACKET
;	AND THAT PACKET IS GIVEN TO THE CONTROLLER.
;
;-

DUCMD:	MOV	R5,CNTBL(R3)	;SAVE UCB ADDRESS AWAY
	MOV	CTTBL(R3),R3	;GET POINTER TO CONTROLLER STATE TABLE
DUCMD1:	CALL	MKPKT		;GO SET UP MSCP PACKET
DUCMD2:	MOV	R1,-(SP)	;SAVE POINTER TO CURRENT COMMAND PACKET
	MOV	R5,R0		;SET-UP TO POINT TO UNIT'S I/O QUEUE LISTHEAD
	ADD	#      U.LHD,R0	;BY ADDING THE OFFSET
	MOV	S.PKT(R4),R1	;GET THE I/O PACKET ADDRESS
	TST	(R0)		;ANY I/O OUTSTANDING?
	BNE	10$		;IF NE YES
	MOV	C.CTMO(R3),U.UTMO(R5)  ;NO, SET UP UNIT TIME OUT COUNT
10$:	CALL	$QINSF		;INSERT I/O PACKET INTO UNIT'S I/O QUEUE
	MOV	(SP)+,R1	;RESTORE POINTER TO CURRENT COMMAND PACKET ...
DUCMD3:	MOV	#1,R0		;SET-UP VIRTUAL CIRCUIT AND CREDIT
	CALL	DUINIO		;INITIATE I/O
	BCS	DUCMD4		;IF CS ERROR INITIATING I/O
	RETURN			;ALL'S OK -- RETURN TO CALLER
DUCMD4:	TST	(SP)+		;FLUSH S      TACK
	CALLR	REINIT		;ATTEMPT TO RE-INIT THE CONTROLLER

;+
; **- DURSP - MSCP RESPONSE PROCESSOR
;
; THE MSCP RESPONSE PROCESSOR WILL CAUSE A SCAN OF THE RESPONSE RING
; FOR ANY RESPONSES. RESPONSES MAY COME FROM:
;
;	1.  MSCP SET CONTROLLER CHARACTERISTICS COMMAND
;	2.  MSCP SET UNIT ON-LINE COMMAND
;	3.  MSCP ATTENTION RESPONSES
;	4.  MSCP ERROR LOG RESPONSES
;	5.  AN I/O PACKET QUEUED TO THE CONTROLLER 
;
; EACH OF THESE MUST BE DISPATCHED PROPERLY
;
; INPUTS:
;
;	R5 = UCB ADDRESS
;
      ; OUTPUTS:
;
;	IF UNIT INITIALIZATION IS IN PROGRESS THEN UNITS ARE BROUGHT ON-LINE 
;	ELSE
;
;	IF RE-INITIALIZATION IS IN PROGRESS THEN OUTSTANDING I/O IS RE-ISSUED 
;	ELSE
;
;	THE RESPONSE RING IS SEARCHED FOR A RESPONSE AND 
;	IF THE RESPONSE IS NOT TO AN INTERNALLY GENERATED COMMAND
;	THEN THE RESULTS ARE RETURNED TO THE ISSUING TASK.
;
;-

DURSP:				;REF LABEL


	.IF DF 	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	U.SCB(R5),R4	;RETRIEVE SCB       ADDRESS
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
  	MOV	CTTBL(R3),R3	;GET POINTER TO CONTROLLER STATE TABLE
	TSTB	C.STAT+1(R3)	;CONTROLLER ON-LINE IN PROGRESS?
	BGT	DURSP1		;IF GT YES, SCAN RESPONSE RINGS
	BNE	60$		;IF NE YES, EXIT


	.IF DF	DEBUG

	BITB	#C1.ON,C.STAT(R3)  ;CONTROLLER ON-LINE?
	BNE	10$		;IF NE YES
5$:	CRASH			;NO, CRASH

	.ENDC	;DEBUG


10$:	BITB	#C1.INI,C.STAT(R3)  ;RE-INITIALIZATION IN PROGRESS?
	BEQ	DURSP1		;IF EQ NO
	MOV	#SCUCB,-(SP)	;YES, PUSH "SCAN UCB'S" ROUT      INE ON THE STACK
20$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	DURSP1		;IF CS ALL DONE
	CLR	C.IOPK(R3)	;INITIALIZE OUTSTANDING I/O PACKET STORAGE AREA
	TST	U.LHD(R5)	;ANY I/O OUTSTANDING ON THIS UNIT?
	BEQ	20$		;IF EQ NO
30$:	CMP	C.IOPK(R3),U.LHD(R5)  ;IS THIS THE FIRST ONE AGAIN?
	BEQ	20$		;IF EQ YES
	MOV	R3,-(SP)	;SAVE POINTER TO CONTROLLER STATE TABLE 
	MOV	R5,R0		;SET-UP TO POINT TO UNIT'S I/O QUEUE LISTHEAD
	ADD	#U.LHD,R0	;BY ADDING THE OFFSET
	CALL	$QRMVF		;REMOVE THE FRONT ENTRY FROM THE QUE      UE


	.IF DF	DEBUG

	BCC	40$		;IF CC, ALL'S OK
	CRASH			;CRASH, UNABLE TO REMOVE ANY ENTRY

	.ENDC	;DEBUG


40$:	MOV	(SP)+,R3	;RESTORE POINTER TO CONTROLLER STATE TABLE
	TST	C.IOPK(R3)	;IS THIS THE FIRST ENTRY?
	BNE	50$		;IF NE NO
	MOV	R1,C.IOPK(R3)	;YES, SET ADDRESS INTO C.IOPK
50$:	MOV	R1,R2		;COPY ADDRESS OF I/O PACKET TO R2
	CALL	DUCMD1		;GO ISSUE I/O
	BR	30$		;GO AGAIN	
60$:	RETURN			;EXIT, CONTROLLER INITIALIZATION IN PROGRESS

;+
; **- DURSP1 - MSCP RESPONSE PROCESSING ROUTINE
;      
; THE MSCP RESPONSE PROCESSING ROUTINE IS CALLED TO PROCESS THE NEXT SEQUENTIAL
; RESPONSE RECEIVED FROM THE UDA50. THERE ARE FOUR SPECIAL CASE RESPONSES WHICH
; ARE PROCESSED INTERNALLY, ALL OTHERS ARE IN RESPONES TO AN I/O PACKET OUT-
; STANDING.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	C  = 0 AND IF THE RESPONSE END CODE IS:
;		OP.END!OP.SCC, OP.END!OP.ONL, OR OP.END!OP.SUC
;		THEN THESE ARE PROCESSED INTERNALLY.
;
;	C        = 1 IF THE RESPONSE END CODE IS NONE OF THE ABOVE AND
;	C.IOSB   = IS.SUC&377 OR IE.VER&377 DEPENDING ON THE STATUS/EVENT CODE
;	C.IOSB+2 = P.BCNT FROM THE MSCP PACKET
;
;-

DURSP1:	CALL	DUPOLL		;POLL RESPONSE RINGS
	BCC	10$		;IF CC WE GOT A RESPONSE
	JMP	DUEXIT		;OTHERWISE SEE IF WE SHOULD EXIT

;
;	R0 = CONTENTS OF MESSAGE TYPE FIELD
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R2 = HI ORDER REF NUMBER FROM THE RESPONSE PACKET
;

10$:				;REF LABEL


	.IF DF	DEBUG

11$:	BPT			;GET       TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	BITB	#OP.AVA,P.OPCD(R1)  ;IS IT AN AVAILABLE ATTENTION RESPONSE?
	BEQ	20$		;IF EQ NO
	CALL	DUATN		;YES, HANDLE AVAILABLE ATTENTION MESSAGE
	BCS	69$		;IF CS, NO UCB FOR THIS UNIT
15$:	CALL	RLPKT		;RELEASE PACKET
	BITB	#US.OFL,U.ST2(R5)  ;UNIT MARKED OFF-LINE?
	BNE	DURSP1		;IF NE YES
	BITB	#US.SPU,U.STS(R5)  ;UNIT MARKED SPINNING UP?
	BEQ	DURSP1		;IF EQ NO
	CALL	DUSTAT		;ATTEMPT TO GET UNIT STATUS
	BCC	DURSP1		;IF CC EXIT
	CALLR	REINIT	      	;NO, RE-INIT THE CONTROLLER
20$:				;REF LABEL


	.IF DF	DEBUG

21$:	BPT			;GET TO XDT
	MOV	#NOP,21$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	BITB	#OP.END,P.OPCD(R1)  ;DOES THIS PACKET HAVE AN END CODE?
	BEQ	69$		;IF EQ NO, SOMETHING'S WRONG
	CMP	R2,R5		;IS THIS PACKET FOR THE CURRENT UCB?
	BEQ	30$		;IF EQ YES

	.IF DF	DEBUG

	CMP	R2,R4		;IS POSSIBLE UCB ADDRESS OUT OF RANGE?
	BLO	25$		;IF LO NO
	CRASH			;YES, CRASH
25$:				;REF LABEL

	.ENDC	;DEBUG


	MOV	R2,R5		;YES, COPY HI ORDER RE      F NUMBER AS UCB ADDRESS
30$:				;REF LABEL


	.IF DF	E$$DVC

	BITB	#EF.LOG,P.FLGS(R1)  ;ERROR LOG GENERATED?
	BNE	40$		;IF NE YES
	TST	P.STS(R3)	;STATUS INDICATE SUCCESS?
	BEQ	50$		;IF EQ YES
40$:	CALL	DULERR		;NO, LOG ERROR LOG PACKET

	.ENDC	;E$$DVC


50$:	CMP	P.CRF+2(R1),R3	;IS LO ORDER REF NUMBER SAME AS CONTROLLER ...
				;... STATE TABLE POINTER?
	BNE	90$		;IF NE NO
	CMPB	#OP.END!OP.SCC,P.OPCD(R1)  ;IS THIS A "SET CONTROLLER 
				;CHARACTERISTICS" END CODE?
	BNE	70$		;IF NE NO
	CA      LL	STCCR		;YES, SET CONTROLLER CHARACTERISTICS
	CALL	RLPKT		;RELEASE PACKET

;
; MUST SCAN THROUGH ALL THE UCB'S ASSOCIATED WITH THIS CONTROLLER TO
; GET EACH UNIT "UNIT'S STATUS".
;


	.IF DF	DEBUG

51$:	BPT			;GET TO XDT
	MOV	#NOP,51$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	#SCUCB,-(SP)	;PUSH "SCAN UCB'S" ROUTINE ON THE STACK
60$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	DURSP1		;IF CS, ALL DONE

;
; GOT A UCB, TRY TO GET STATUS OF ITS ASSOCIATED UNIT
;



	.IF DF	DEBUG

61$:	BPT      			;GET TO XDT
	MOV	#NOP,61$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CALL	DUSTAT		;ATTEMPT TO GET UNIT STATUS
	BCC	60$		;IF CC TRY FOR THE NEXT UCB
	ADD	#10,SP		;FLUSH THE STACK
	CALLR	REINIT		;ATTEMPT TO RE-INIT THE CONTROLLER
69$:				;REF LABEL


	.IF DF	DEBUG

	CRASH			;SOMETHING'S WRONG

	.ENDC	;DEBUG


	CALL	RLPKT		;RELEASE THE PACKET
	BR	DURSP1		;TRY AGAIN
70$:	CMPB	#OP.END!OP.ONL,P.OPCD(R1)  ;IS THIS AN "ON-LINE" END CODE
	BNE	80$		;IF NE NO
	CALL	ONLINE		;YES, SET UNIT ON-LINE
	C      ALL	RLPKT		;RELEASE PACKET
	BITB	#US.OFL,U.ST2(R5)  ;UNIT MARKED OFF-LINE?
	BNE	DURSP1		;IF NE YES
	CLR	R1		;CLR R1 TO NOTE INITIALIZATION REQUEST
	CALL	RQRCT		;REQUEST RCT FOR UNIT INITIALIZATION
	BR	DURSP1		;TRY AGAIN
80$:	CMPB	#OP.END!OP.GUST,P.OPCD(R1)  ;IS THIS A "GET UNIT STATUS" END CODE
	BNE	85$		;IF NE NO
	CALL	GTUST		;YES, SET UNIT'S STATUS
	CALL	RLPKT		;RELEASE PACKET
	BR	DURSP1		;TRY AGAIN
85$:	CMPB	#OP.END!OP.GCS,P.OPCD(R1)  ;IS THIS A "GET COMMAND STATUS" END CODE?
	BNE	69$		;IF NE       NO


	.IF DF	E$$DVC

	CALL	GTCST		;YES, GET COMMAND'S STATUS

	.ENDC	;E$$DVC


	CALL	RLPKT		;RELEASE PACKET
	BR	DURSP1		;TRY AGAIN
90$:	MOV	#IS.SUC&377,C.IOSB(R3)  ;ASSUME SUCCESS STATUS


	.IF DF	D$$IAG

	MOV	P.CRF+2(R1),R2	;GET I/O PACKET POINTER FROM MSCP PACKET
	BIT	#IQ.UMD,I.FCN(R2)  ;IS IT A DIAGNOSTIC FUNCTION?
	BNE	100$		;IF NE YES

	.ENDC	;D$$IAG


	MOV	P.STS(R1),R2	;GET STATUS/EVENT CODE
	BIC	#^C<ST.MSK>,R2	;SUCCESSFUL?
	BEQ	100$		;IF EQ YES
	MOV	#IE.WLK&377,C.IOSB(R3)        ;ASSUME WRITE LOCK STATUS
	CMP	#ST.WPR,R2	;DRIVE WRITE PROTECTED?
	BEQ	100$		;IF EQ YES
	MOV	#IE.DNR&377,C.IOSB(R3)  ;ASSUME DRIVE NOT READY STATUS
	CMP	#ST.OFL,R2	;DRIVE OFF-LINE?
	BEQ	100$		;IF EQ YES


	.IF DF	DEBUG

91$:	BPT			;GET TO XDT
	MOV	#NOP,91$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	#IE.VER&377,C.IOSB(R3)  ;NO, SET FAILURE IN STATUS
	CMP	RCTTCB,U.ATT(R5)  ;IS RCT ATTACHED?
	BNE	100$		;IF NE NO
	CMP	#ST.FER,P.STS(R1)  ;IS IT A FORCED ERROR?
	BNE	100$		;IF NE NO
	MOV	#IS.RDD&      377,C.IOSB(R3)  ;YES, SET READ DELETED DATA IN STATUS
100$:	CMPB	#OP.END!OP.GUS,P.OPCD(R1)  ;IS THIS A "GET UNIT STATUS" END CODE 
	BNE	110$		;IF NE NO
	CALL	GTUST		;YES, GET UNIT'S STATUS
	BR	120$		;AND GO ON
110$:	CMP	#ST.UNK,P.STS(R1)  ;IS UNIT TOTALLY UNKOWN?
	BNE	120$		;IF NE NO
	BISB	#US.OFL,U.ST2(R5)  ;YES, SET IT OFF-LINE
	BICB	#US.SPU!US.VV,U.STS(R5)  ;AND CLR SPIN-UP AND VOLUME VALID FLAGS
120$:	BITB	#EF.BBR,P.FLGS(R1)  ;BAD BLOCK REPORTED?
	BEQ	130$		;IF EQ NO


	.IF DF	DEBUG

121$      :	BPT			;GET TO XDT
	MOV	#NOP,121$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CALL	RQRCT		;YES, REQUEST RCT FOR BLOCK REPLACEMENT
	BCS	130$		;IF CS, NO BLOCK REPLACEMENT REQUIRED

;
; REMOVE I/O PACKET FROM I/O ACTIVE QUEUE
;

	MOV	R3,-(SP)	;SAVE CONTROLLER STATE TABLE POINTER
	MOV	P.CRF+2(R1),R1	;GET I/O PACKET ADDRESS FROM LO ORDER REF NUMBER
	MOV	R5,R0		;LOCATE THE I/O PACKET QUEUE FOR THIS UCB
	ADD	#U.LHD,R0	;ADD OFFSET TO I/O PACKET QUEUE
	CALL	$QRMVT		;GET I/O PACKET FROM UNIT'S I/O QUEUE

      ;
; INSERT I/O PACKET INTO BAD BLOCK REPLACEMENT QUEUE
;

	MOV	R5,R0		;COPY UCB ADDRESS INTO R0
	ADD	#U.BPKT,R0	;ADD OFFSET TO BAD BLOCK WAITING QUEUE
	CALL	$QINSF		;INSERT I/O PACKET INTO BAD BLOCK WAITING QUEUE
	MOV	(SP)+,R3	;RESTORE CONTROLLER STATE TABLE POINTER
	CALL	RLPKT		;RELEASE PACKET
	JMP	DURSP1		;TRY AGAIN
130$:	MOV	P.BCNT(R1),C.IOSB+2(R3)  ;PUT BYTE COUNT FROM PACKET INTO ...
				;... 2ND STATUS WORD OF CURRENT RESPONSE BLOCK
140$:				;REF LABEL


	.IF DF	DEBUG

141$:	BPT			;GE      T TO XDT
	MOV	#NOP,141$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	P.CRF+2(R1),R1	;GET I/O PACKET ADDRESS FROM LO ORDER REF NUMBER
	MOV	R5,R0		;LOCATE THE I/O PACKET QUEUE FOR THIS UCB
	ADD	#U.LHD,R0	;ADD OFFSET TO I/O PACKET QUEUE
	MOV	(R0),-(SP)	;SAVE POINTER TO FIRST I/O PACKET
	MOV	R3,-(SP)	;SAVE CONTROLLER STATE TABLE POINTER
	CALL	$QRMVT		;GET I/O PACKET FROM UNIT'S I/O QUEUE
	MOV	(SP)+,R3	;RESTORE CONTROLLER STATE TABLE POINTER
	MOV	R1,S.PKT(R4)	;STORE I/O PACKET ADDRESS IN SCB (FOR $IODON)      
	CMP	R1,(SP)+	;IS THIS THE FIRST ONE IN THE UNIT'S QUEUE?
	BNE	150$		;IF NE NO
	TST	U.LHD(R5)	;ARE THERE ANY MORE I/O PACKETS IN THE QUEUE?
	BEQ	150$		;IF EQ NO
	MOV	C.CTMO(R3),U.UTMO(R5)  ;RESTART UNIT TIMEOUT COUNT
	MOV	#-1,U.CMST(R5)	;INITIALIZE COMMAND STATUS PROGRESS REGISTER ...
	MOV	#-1,U.CMST+2(R5)  ;... AS A DOUBLE PRECISION VALUE
150$:				;REF LABEL


	.IF DF	D$$IAG

	BIT	#IQ.UMD,I.FCN(R1)  ;DIAGNOSTIC FUNCTION?
	BEQ	170$		;IF EQ NO
	MOV	C.CRSP+2(R3),R2	;GET POINTER TO CURRENT MSCP       RESPONSE PACKET

	CLRB	S.ROFF(R4)	;ZERO OFFSET TO FIRST REGISTER OF MSCP RESPONSE 
				;PACKET
	MOV	#MSGLNG,R1	;GET OFFSET TO FIRST REGISTER
	ADD	R2,R1		;ADD BASE ADDRESS OF RESPONSE PACKET
	MOV	(R1),-(SP)	;GET MESSAGE LENGTH
	TSTB	1(SP)		;DID WE OVERFLOW A BYTE VALUE
	BEQ	160$		;IF EQ NO

	MOV	#IE.VER&377,C.IOSB(R3)  ;NOTE FAILURE, UNABLE TO RETURN MSCP 
				;RESPONSE PACKET
	CLR	C.IOSB+2(R3)	;ZERO BYTES TRANSFERRED
	TST	(SP)+		;CLN THE STACK
	BR	170$		;AND CONTINUE

160$:	ASR	(SP)		;MAKE I      T A WORD VALUE
	MOVB	(SP)+,S.RCNT(R4)  ;SET NUMBER OF REGISTERS TO COPY FOR MSCP
				;RESPONSE PACKET

	CALL	$CRPAS		;PASS MSCP PACKET BACK TO USER

	.ENDC	;D$$IAG


170$:	CALL	RLPKT		;RELEASE RESPONSE RING TO CONTROLLER

;+
; **- DUDON - UDA50 DISK DRIVER I/O DONE ROUTINE
;
; THE UDA50 DISK DRIVER I/O DONE ROUTINE WILL COLLECT PERTINENT STATUS
; CONCERNING THE I/O FOR THE PACKET CONTAINED IN S.PKT(R4), RETURN 
; THAT STATUS TO THE REQUESTING TASK, RELEASE SPECIAL RESOURCES 
; (I.E. UMR'S),       AND JUST GENERALLY FINISH UP.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	CURRENT I/O PACKET CONTAINED IN S.PKT(R4) IS FINISHED UP.
;	STATUS IS OBTAINED FROM C.IOSB(R3)
;	BYTES TRANSFERED IS OBTAINED FROM C.IOSB+2(R3)
;
;-

DUDON:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	.IF DF	M$$EXT

	MOV	S.PKT(R4),R1	;GET I/O PACKET ADDRESS
	CMPB	#IO.RLB/256.,I.FCN+1(R      1)  ;DATA TRANSFER FUNCTION?
	BLO	10$		;IF LO NO
	BIT	#DV.EXT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?
	BNE	10$		;IF NE YES
	MOV	R3,-(SP)	;SAVE R3
	CALL	DUUNMP		;UNMAP THE UMR MAPPING ASSIGNMENT BLOCK
	CALL	$DEUMR		;DEASSIGN THESE UMR'S
	CLR	(R2)+		;FREE UP UMR WAIT BLOCK
	CLR	(R2)+		;...
	MOV	(SP)+,R3	;RESTORE R3
	INC	S.UMCT(R4)	;INC UMR ASSIGNMENT BLOCK COUNT

	.ENDC	;M$$EXT


10$:	MOV	C.IOSB(R3),R0  ;GET STATUS CODE FROM RESPONSE STATUS BLOCK
	MOV	C.IOSB+2(R3),R1  ;GET BYTE COUNT FROM RESPO      NSE STATUS BLOCK
	MOV	#RETRY*256.,R2	;SET TOTAL RETRIES INTO R2
	BISB	C.RTRY(R3),R2	;SET FINAL RETRY COUNT
	MOV	U.SCB(R5),R4	;RETRIEVE SCB ADDRESS
	CALL	$IODON		;FINISH I/O OPERATION
	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS
	CLR	S.PKT(R4)	;CLR I/O PACKET POINTER IN SCB
	MOVB	S.CON(R4),R3	;GET CONTROLLER INDEX
	MOV	CTTBL(R3),R3	;GET CONTROLLER STATE TABLE POINTER

;+
; **- DUEXIT - UDA50 DISK DRIVER EXIT ROUTINE
;
; THE UDA50 DISK DRIVER EXIT ROUTINE WILL DETERMINE IF THE DRIVER SHOULD EXIT 
; TO       THE SYSTEM OR IF IT HAS MORE WORK TO DO.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE DRIVER CHECKS FOR ANY MORE I/O PACKETS WAITING UNLESS THE DRIVER 
;	IS BLOCKED WAITING FOR UMR'S, IN WHICH CASE THE DRIVER TRIES TO EXIT 
;	BY QUEUING A CLOCK BLOCK IF THE DRIVER HAS I/O OUTSTANDING WITH THE 
;	CONTROLLER OTHERWISE THE DRIVER WILL JUST RETURN TO THE SYSTEM.
;
;-

DUEXIT:	TST	(R4)		;MORE I/O TO DEQUEUE?
	BEQ	10$		;IF EQ NO      


	.IF DF	M$$EXT

	TST	U.CNT(R5)	;YES, BUT ARE WE WAITING FOR UMR'S
	BNE	10$		;IF NE YES

	.ENDC	;M$$EXT


	DECB	C.CLCC(R3)	;LOOP COUNT CONTROL GO NEGATIVE?
	BMI	DUCLIN		;IF MI YES
	CALLR	DUINI		;NO, TRY TO DEQUEUE MORE I/O

10$:	MOV	#SCUCB,-(SP)	;PUSH "SCAN UCB'S" ROUTINE ON THE STACK
20$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	30$		;IF CS, ALL DONE
	TST	U.LHD(R5)	;ANY I/O OUTSTANDING?
	BEQ	20$		;IF EQ NO
	BISB	#C1.CQR,C.STAT(R3)  ;YES, SET CLOCK QUEUE REQUEST 
	BR	20$		;TRY SOME MORE      
30$:	BITB	#C1.CQR,C.STAT(R3)  ;CLOCK QUEUE REQUEST SET?
	BNE	DUCLIN		;IF NE YES
	RETURN			;NO, EXIT

	.PAGE
;+
; **- DUCAN - CANCEL I/O ENTRY POINT
;
; THIS ROUTINE WILL CANCEL THE I/O OPERATION IN PROGRESS
;
; INPUTS:
;
;	R0 = I/O PACKET ADDRESS
;	R1 = TCB ADDRESS
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-

DUCAN:				;;;CANCEL I/O ENTRY POINT


	.IF DF	DU$KIL 


	.IF DF	DEBUG

1$:	BPT			;;;GET TO XDT
	MOV	#NOP,1$		;;;NOP THE BRK PNT

	.ENDC	;DEBUG

      
	MOV	R1,-(SP)	;;;SAVE TCB ADDRESS
	MOV	R5,R0		;;;LOCATE THE I/O PACKET QUEUE FOR THIS UCB
	ADD	#U.LHD,R0	;;;ADD OFFSET TO I/O PACKET QUEUE
	CALL	$QRMVT		;;;GET THE FIRST I/O PACKET IN THE QUEUE FOR 
				;;;THE  TCB SPEICIFIED BY R1
	BCC	10$		;;;IF CC, FOUND THE DESIRED ENTRY
	ADD	#<U.BPKT-U.LHD>,R0  ;;;ADD OFFSET TO BAD BLOCK REPLACEMENT QUEUE
	CALL	$QRMVT		;;;GET THE FIRST I/O PACKET IN THE QUEUE FOR
				;;;THE  TCB SPECIFIED BY R1


	.IF DF	DEBUG

	BCC	10$		;;;IF CC, ALL'S OK
	CRASH			;;;C      RASH, CANNOT FIND THE I/O PACKET ANYWHERE

	.ENDC	;DEBUG


10$:	MOV	R1,R0		;;;COPY THE REAL I/O PACKET ADDRESS INTO R0
	MOV	(SP)+,R1	;;;RESTORE R1


	.IF DF	DEBUG

11$:	BPT			;;;GET TO XDT
	MOV	#NOP,11$	;;;NOP THE BRK PNT

	.ENDC	;DEBUG


	RETURN			;;;

	.IFF	;DU$KIL

	RETURN			;;;NOP FOR FILE STRUCTURED DEVICES

	.ENDC	;DU$KIL

 
	.PAGE
;+
; **- DUOUT - DEVICE TIMEOUT ENTRY POINT
;
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED.
; IF THE OPERATION WAS DIAG      NOSTIC, THE QIO REQUEST IS TERMINATED.
; TIMEOUTS ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE
; RESULT OF HARDWARE CONSIDERATIONS.
;
; INPUTS:
;
;	R0 = I/O COMPLETION CODE (IE.DNR)
;	R2 = CSR ADDRESS
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-

	.ENABL	LSB

DUOUT:				;;;TIMEOUT ENTRY POINT


	.IF DF	DEBUG

1$:	BPT			;;;GET TO XDT
	MOV	#NOP,1$		;;;NOP THE BRK PNT

	.ENDC	;DEBUG


	INCB	S.CTM(R4)	;;;RESET TIMEOUT COUNT
10$:	RETURN			;;;EXIT

;+
      ; **- DUCLIN - CLOCK QUEUE INSERTION
;
; THE CLOCK INSERTION ROUTINE CAUSES THE UDA50 DRIVER'S CLOCK BUFFER TO
; BE INSERTED INTO THE CLOCK QUEUE.  IT IS SET FOR ONE SECOND.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE UDA50 DRIVER'S CLOCK BUFFER IS INSERTED INTO THE CLOCK QUEUE
;
;-

DUCLIN:	BICB	#C1.CQR,C.STAT(R3)  ;CLR CLOCK QUERE REQUEST FLAG
	BITB	#C1.CLK,C.STAT(R3)  ;CLOCK BLOCK ACTIVE?
	BNE	10$		;IF NE YES
	BISB	#C1      .CLK,C.STAT(R3)  ;SET CLOCK RUNNING FLAG
	MOV	R4,R0		;GET SCB ADDRESS
	ADD	#S.DUCK,R0	;COMPUTE ADDRESS OF CLOCK BLOCK
	MOV	#DUTICK,C.SUB(R0)  ;LOAD TIMEOUT ADDRESS
	CLR	R1		;ZERO HI ORDER DELTA TIME
	MOV	$TKPS,R2	;GET TICKS FOR ONE SECOND FOR LO ORDER DELTA TIME
	MOV	#C.SYST,R4	;DECLARE SYSTEM ROUTINE
	CALLR	$CLINS		;REQUEST INSERTION INTO CLOCK QUEUE

;+
; **- DUTICK - UDA50 CLOCK HANDLER
;
; THE UDA50 CLOCK HANDLER ROUTINE IS THE ENTRY POINT FOR ALL CLOCK QUEUE 
; TIMEOUTS
;
; INPUTS:
;
;      	R4 = POINTER TO CLOCK BLOCK
;
; OUTPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS (RETRIEVED FROM "CNTBL(R3)")
;
;-

DUTICK:				;REF LABEL


	.IF DF	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	SUB	#S.DUCK,R4	;POINT BACK TO SCB
	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOV	CNTBL(R3),R5	;RETRIEVE LAST SAVED UCB ADDRESS
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE
	MOV	U.DCB(R5),R0	;YES, GET DCB ADDRESS      
	TST	D.DSP(R0)	;IS THE DRIVER IN MEMORY?
	BEQ	10$		;IF EQ NO
				;EXIT, DRIVER HAS JUST BEEN UNLOADED
	BICB	#C1.CLK,C.STAT(R3)  ;MARK CLOCK BLOCK AS FREE
	TST	C.STAT(R3)	;INITIALIZATION IN PROGRESS?
	BMI	30$		;IF MI YES
	BITB	#C2.PWF,C.STAT+1(R3)  ;POWERFAIL OCCUR?
	BEQ	20$		;IF EQ NO
	CALLR	DUINIT		;YES, INITIALIZE THE UDA50
20$:	BITB	#C2.ONL,C.STAT+1(R3)  ;CONTROLLER ON-LINE IN PROGRESS?
	BEQ	50$		;IF EQ NO
	BITB	#C1.OFF,C.STAT(R3)  ;CONTROLLER OFF-LINE?
	BNE	40$		;IF NE YES
30$:				;REF LA      BEL


	.IF DF	DEBUG

31$:	BPT			;GET TO XDT
	MOV	#NOP,31$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	DEC	C.CTMO+2(R3)	;DEC CONTROLLER INITIALIZATION TIMEOUT, IS IT ZERO?
	BNE	DUCLIN		;IF NE NO


	.IF DF	E$$DVC

	CALL	DUCERR		;LOG CONTROLLER TIME OUT PACKET

	.ENDC	;E$$DVC


	TST	C.RTRY(R3)	;RETRIES EXHAUSTED?
	BNE	100$		;IF NE NO
	BISB	#C1.OFF,C.STAT(R3)  ;HOPELESS, MARK CONTROLLER OFF-LINE

;
; MUST SCAN THROUGH ALL THE UCB'S ASSOCIATED WITH THIS CONTROLLER TO 
; SET EACH UNIT OFF-LINE      
;

40$:	CALLR	OFFLIN		;SET ALL UNITS ASSOCIATED WITH THIS CONTROLLER ...
				;... OFFLINE
50$:	MOV	#SCUCB,-(SP)	;PUSH "SCAN UCB'S" ROUTINE ON THE STACK
60$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	70$		;IF CS, ALL DONE
	TST	U.LHD(R5)	;ANY I/O OUTSTANDING?
	BEQ	60$		;IF EQ NO
	DEC	U.UTMO(R5)	;DEC TIMEOUT COUNT, IS IT ZERO?
	BNE	60$		;IF NE NO


	.IF DF	E$$DVC

	CALL	DUGCS		;ISSUE "GET COMMAND STATUS" PACKET

	.ENDC	;E$$DVC


	BR	60$		;GO AGAIN
70$:				;REF LABEL

;
; SEE IF THE CONTRO      LLER IS LURKING ABOUT
;


	.IF DF	DEBUG

71$:	BPT			;GET TO XDT
	MOV	#NOP,71$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	S.CSR(R4),R2	;RETRIEVE CSR ADDRESS
	TST	UDASA(R2)	;DID CONTROLLER DIE?
	BNE	100$		;IF NE YES
80$:				;REF LABEL


	.IF DF 	DEBUG

81$:	BPT			;GET TO XDT
	MOV	#NOP,81$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOVB	C.ILCC(R3),C.CLCC(R3)  ;INITIALIZE LOOP COUNT CONTROL
	MOV	C.RING(R3),R0	;RETRIEVE BASE OF RINGS
	TST	RSPINT(R0)	;IS INTERRUPT FOR RESPONSE RING NOT EMPTY?
	BN      E	90$		;IF NE YES
	CALLR	DUINI		;NO, ATTEMPT DEQUEUE ANY COMMANDS (IF AVAILABLE)
90$:	CLR	RSPINT(R0)	;CLR INTERRUPT STATUS WORD
	CALLR	DURSP		;GO PROCESS ANY RESPONSES
100$:				;REF LABEL


	.IF DF 	DEBUG

101$:	BPT			;GET TO XDT
	MOV	#NOP,101$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CALLR	REINIT		;YES, RE-INITIALIZATION REUIRED

	.DSABL	LSB
	.PAGE
;+
; **- DUPWF - DEVICE POWERFAIL RECOVERY ENTRY
;
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES
; NO IMMEDIATE A      CTION ON THE DEVICE.  THIS IS DONE TO AVOID A RACE CONDITION
; THAT COULD EXIST IN RESTARTING THE I/O OPERATION.
;
; INPUTS:
;
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	LOCATION OF DEVICE-COMMON RING AND PACKET AREA IS COMPUTED
;	AND A REQUEST IS MADE TO INITIALIZE THE CONTROLLER.
;
;-

DUPWF:				;POWERFAIL ENTRY POINT


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	BISB	#US.SPU,U.STS(R5)  ;MARK UNIT AS "      SPINNING UP"
	BICB	#US.VV,U.STS(R5)  ;CLR VOLUME VALID FLAG
	BIT	#C2.PWF*400,@CTTBL(R3)  ;CONTROLLER ALREADY MARKED FOR POWERFAIL?
	BEQ	DUPWF1		;IF EQ NO
	RETURN			;EXIT
DUPWF1:	TST	DUDCB		;DO WE HAVE DU:'S FIRST DCB ADDRESS
	BNE	10$		;IF NE YES
	MOV	U.DCB(R5),DUDCB	;NO, ASSUME THIS UCB POINTS TO THE FIRST DU: DCB
10$:	MOV	R5,CNTBL(R3)	;SAVE THE UCB ADDRESS FOR INITIALIZATION INTERRUPTS
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINTER
	BIC	#^C<C1.CLK>,C.STAT(R3)  ;RESET ALL FLAGS BUT CLO      CK ACTIVE FLAG
	BISB	#C2.PWF,C.STAT+1(R3)  ;SET CONTROLLER POWERFAIL INDICATOR
	MOV	#SCUCB,-(SP)	;PUSH ADDRESS OF "SCAN UCB'S" ON THE STACK
20$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	DUPWF2		;IF CS, NO MORE UCB'S
	TST	U.LHD+2(R5)	;I/O PACKET QUEUE ALREADY INITIALIZED?
	BNE	30$		;IF NE YES
	MOV	#U.LHD,U.LHD+2(R5)  ;NO, SET UP FOR ZERO ENTRY QUEUE
	ADD	R5,U.LHD+2(R5)	;SHOW IT IS EMPTY
30$:	TST	U.BPKT+2(R5)	;REPLACEMENT QUEUE ALREADY INITIALIZED?
	BNE	40$		;IF NE YES
	MOV	#U.BPKT,U.BPKT+2(R5)  ;NO       SET UP FOR ZERO ENTRY QUEUE
	ADD	R5,U.BPKT+2(R5)	;SHOW IT IS EMPTY
40$:	MOV	#-1,U.CMST(R5)	;INITIALIZE COMMAND STATUS PROGRESS REGISTER ...
	MOV	#-1,U.CMST+2(R5)  ;... AS A DOUBLE PRECISION VALUE
	BR	20$		;TRY FOR ANOTHER ONE
DUPWF2:	MOVB	#RETRY,C.RTRY(R3)  ;SET RETRY COUNT
	MOV	C.PKT(R3),C.PKT+2(R3)	;POINT TO FIRST FREE PACKET
	MOVB	C.PKTS(R3),C.NMBR(R3)  ;INITIALIZE NUMBER OF AVAILABLE PACKETS
	CLR	C.CMDS(R3)	;INITIALIZE COMMANDS ISSUED COUNT
	RETURN			;AND EXIT

	.PAGE
;+
; **- DUINIT - UDA5      0 CONTROLLER INITIALIZATION ROUTINE
;
; THE UDA50 CONTROLLER INITIALIZATION ROUTINE WILL START THE INITIALIZATION
; PROCESS FOR THE UDA50 CONTROLLER.  IT WILL INSURE THE PROPER PARAMETERS 
; ARE SET UP AND INITIATE OPENING THE "VIRTUAL CIRCUIT".
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	SET INITIALIZATION BITS IN THE CONTROLLER STATE TABLE
;
;-

DUINIT:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		      ;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOVB	#C2.INI,C.STAT+1(R3)  ;SET CONTROLLER INITIALIZATION IN
				;PROGRESS ...
	MOV	#10.,C.CTMO(R3)  ;SET 10 SEC TIMER IN CONTROLLER TIMEOUT 
	MOV	C.CTMO(R3),C.CTMO+2(R3)  ;SET TIMER VALUE
	CALL	STINT		;SET INITIALIZATION PARAMETERS
	MOVB	S.VCT(R4),(R1)	;SET INTERRUPT VECTOR
	BISB	#INTE,(R1)+	;SET INTERRUPT ENABLE
$STEPI	==	.-2
	MOVB	C.STP1(R3),(R1)  ;STORE COMMAND/RESPONSE RING SIZE AWAY
	BISB	#ERROR/256.,(R1)+  ;FINISH SET UP OF THIS ENTRY
$STEP1	==	.-2
	      MOV	#DUCLIN,-(SP)	;RETURN BY INSERTING UDA50 CLOCK BLOCK
	CALLR	DUOPEN		;INITIALIZE CONTROLLER

;+
; **- DUINT1 - UDA50 INITIALIZATION CONTINUATION AFTER "VIRTUAL CIRCUIT" IS 
; OPENED
;
; THE UDA50 INITIALIZATION CONTINUATION OCCURS AFTER THE FINAL INTERRRUPT 
; FROM OPENING THE CONTROLLER'S "VIRTUAL CIRCUIT".  AT THIS POINT, THOSE 
; CONTROLLER CHARACTERISTICS WHICH ARE SETTABLE ARE SET.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:      
;
;	SET CONTROLLER ON-LINE AND THOSE CHARACTERISTICS OF INTEREST
;
;-

DUINT1:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOVB	#C2.ONL,C.STAT+1(R3)  ;SET CONTROLLER ON-LINE IN PROGRESS FLAG
	MOV	C.CTMO(R3),C.CTMO+2(R3)  ;SET TIMER VALUE
10$:	MOV	#P.LENG,R0	;SET-UP COMMAND PACKET LENGTH
	MOV	#1,R1		;SET-UP VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELD
	CALL	GTPKT		;DID WE GET THE CURRENT COMMAND PACKET IN THE RING?
	BCS	10$		;IF CS NO      , ... TRY, TRY AGAIN
	MOV	R5,P.CRF(R1)	;YES, SET HI ORDER REF NUMBER TO UCB ADDRESS
	MOV	R3,P.CRF+2(R1)	;SET LO ORDER REF NUMBER TO CONTROLLER STATE TABLE
	MOVB	#OP.SCC,P.OPCD(R1)  ;SET "SET CONTROLLER CHARACTERISTICS" 
				;OP CODE


	.IF DF	E$$DVC

	MOV	#CF.ATN!CF.MSC!CF.THS,P.CNTF(R1)  ;SET HOST FLAGS ...
				;... ALLOW ATTENTION MESSAGES, MISCELLANEOUS 
				;... ERROR LOGS, AND THIS HOST'S ERROR LOGS

	.IFF	;E$$DVC

	MOV	#CF.ATN,P.CNTF(R1)  ;SET HOST FLAGS ...
				;... ALLOW ATTENTION ME      SSAGES

	.ENDC	;E$$DVC


	MOV	#0,P.HTMO(R1)	;SET HOST TIMEOUT
				;ZERO KEEPS THE UDA50 FROM TIMING THE HOST OUT
	CALLR	DUCMD3		;ISSUE I/O

	.PAGE

;+
; **- SETR - SET UP RING BUFFER POINTERS TO MSCP PACKETS
;
; THIS ROUTINE SETS UP THE RING BUFFER POINTERS TO MSCP PACKETS
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;
; OUTPUTS:
;
;	RING BUFFERS ARE POINTING TO MSCP PACKETS
;
;-

SETR:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT      

	.ENDC	;DEBUG


	MOVB	C.RSP(R3),-(SP)	;GET NUMBER OF RESPONSE RINGS REQUIRED
	MOV	#L.LENG,R0	;SET LENGTH OF A RESPONSE PACKET
	MOV	C.CRSP(R3),R1	;GET POINTER TO CURRENT RESPONSE RING BUFFER
	ADD	#LADDR,R1	;ADD OFFSET TO LO ORDER ADDRESS WORD
	CALL	ALPKT		;ALLOCATE AN MSCP PACKET


	.IF DF	DEBUG

	BCC	10$		;IF CC, ALL'S OK
	CRASH			;CRASH, FAILURE TO ALLOCATE A PACKET

	.ENDC	;DEBUG


10$:	MOV	R2,C.CRSP+2(R3)  ;STORE PACKET POINTER IN CURRENT RESPONSE RING
				;BUFFER POINTER TABLE
	M      OV	R2,C.FRSP+2(R3)  ;AND IN THE FIRST RESPONSE RING BUFFER POINTER
	MOV	R2,C.LRSP+2(R3)	;PREPARE TO FIND LAST RESPONSE RING BUFFER 
				;PACKET
20$:	MOV	R2,(R1)		;INSERT ADDRESS INTO THE LOW PART OF RING
	ADD	C.RELC+2(R3),(R1)+  ;ADD RELOCATION CONSTANT
	ADC	(R1)		;ADD CARRY
	ADD	C.RELC(R3),(R1)	;NOW THE HIGH RELOCATION CONSTANT
	BIT	#DV.EXT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?


	.IF DF	M$$EXT

	BNE	25$		;IF NE YES
	BIC	#^C<3>,(R1)	;BIT CLEAR ALL BUT LOW TWO ADDRESS BITS
25$:				;REF LABEL      

	.IFF	;M$$EXT

	BIC	#^C<3>,(R1)	;BIT CLEAR ALL BUT LOW TWO ADDRESS BITS

	.ENDC	;M$$EXT


	BIS	#OWN!FLAG,(R1)+  ;MARK RESPONSE RING BUFFER UDA "OWN'ED" AND 
				;INTERRUPTABLE
	DECB	(SP)		;COUNT THIS ONE, ARE WE DONE?
	BEQ	40$		;IF EQ YES
	CALL	ALPKT		;ALLOCATE ANOTHER PACKET


	.IF DF	DEBUG

	BCC	30$		;IF CC, ALL'S WELL
	CRASH			;CRASH, FAILURE TO ALLOCATE A PACKET

	.ENDC	;DEBUG


30$:	ADD	R0,C.LRSP+2(R3)  ;LOCATE NEW LAST RESPONSE PACKET
	BR	20$		;TRY ANOTHER PACKET
40$:	MOVB	C      .CMD(R3),(SP)	;GET NUMBER OF COMMAND RINGS
	MOV	#P.LENG,R0	;SET LENGTH OF A COMMAND PACKET
	MOV	C.CCMD(R3),R1	;GET CURRENT COMMAND PACKET POINTER
	ADD	#LADDR,R1	;ADD OFFSET TO LO ORDER ADDRESS WORD
	CALL	ALPKT		;ALLOCATE AN MSCP PACKET


	.IF DF	DEBUG

	BCC	50$		;IF CC, ALL'S OK
	CRASH			;CRASH, FAILURE TO ALLOCATE A PACKET

	.ENDC	;DEBUG


50$:	MOV	R2,C.CCMD+2(R3)  ;STORE PACKET POINTER IN CURRENT COMMAND RING
				;BUFFER POINTER TABLE
	MOV	R2,C.FCMD+2(R3)  ;AND IN THE FIRST COMMAD RING BU      FFER POINTER
	MOV	R2,C.LCMD+2(R3)  ;PREPARE TO FIND LAST COMMAND RING BUFFER 
				;PACKET
60$:	MOV	R2,(R1)		;INSERT ADDRESS INTO THE LOW PART OF RING
	ADD	C.RELC+2(R3),(R1)+  ;ADD RELOCATION CONSTANT
	ADC	(R1)		;ADD CARRY


	.IF DF	M$$EXT

	ADD	C.RELC(R3),(R1)+  ;NOW THE HIGH RELOCATION CONSTANT
	BIT	#DV.EXT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?
	BNE	65$		;IF NE YES
	BIC	#^C<3>,-2(R1)	;BIT CLEAR ALL BUT LOW TWO ADDRESS BITS
65$:				;REF LABEL

	.IFF	;M$$EXT

	ADD	C.RELC(R3),(R1)	;NOW THE       HIGH RELOCATION CONSTANT
	BIC	#^C<3>,(R1)+	;BIT CLEAR ALL BUT LOW TWO ADDRESS BITS

	.ENDC	;M$$EXT


	DECB	(SP)		;COUNT THIS ONE, ARE WE DONE?
	BEQ	80$		;IF EQ YES
	CALL	ALPKT		;ALLOCATE ANOTHER PACKET


	.IF DF	DEBUG

	BCC	70$		;IF CC, ALL'S WELL
	CRASH			;CRASH, FAILURE TO ALLOCATE A PACKET

	.ENDC	;DEBUG

70$:	ADD	R0,C.LCMD+2(R3)  ;LOCATE NEW LAST COMMAND PACKET
	BR	60$		;TRY ANOTHER PACKET
80$:	TST	(SP)+		;CLEAN UP THE STACK
	RETURN			;EXIT

;+
; **- GTPKT - GET A COMMAND PACKET      
;
; THIS ROUTINE WILL CHECK THE COMMAND RING BUFFER FOR THE FIRST AVAILABLE
; COMMAND PACKET.  IT WILL RETURN THE ADDRESS IF ONE IS FREE, OTHERWISE 
; IT RETURNS CARRY SET IF THERE IS NONE.
;
; INPUTS:
;
;	R0 = COMMAND PACKET LENGTH
;	R1 = VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELD VALUE
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	IF SUCCES:
;	C  = 0 IF COMMAND PACKET IS AVAILABLE
;	R1 = ADDRESS OF CURRENT COMMAND RING PACKET
;
;	IF FAILURE:
      ;	C  = 1 IF COMMAND PACKET IS NOT AVAILABLE
;
;-

GTPKT:	TST	@C.CCMD(R3)	;DOES THE UDA50 OWN THE CURRENT COMMAND RING 
				;POINTER
	SEC			;ASSUME FAILURE
	BMI	20$		;IF MI YES
	MOV	R1,-(SP)	;SAVE R1
	MOV	C.CCMD+2(R3),R1	;RETRIEVE CURRENT COMMAND PACKET POINTER
	MOV	R0,MSGLNG(R1)	;SET MESSAGE LENGTH
	MOV	(SP)+,CREDIT(R1)  ;SET VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELDS
	MOV	#P.LENG/2,R0	;SET LENGTH OF AN MSCP COMMAND PACKET
10$:	CLR	(R1)+		;INITIALIZE MSCP PACKET
	SOB	R0,10$		;LOOP
	MOV	C.CCMD+2(      R3),R1	;RETRIEVE CURRENT COMMAND PACKET POINTER
	CLC			;CLR CARRY
20$:	RETURN			;RETURN

;+
; **- RLPKT - RELEASE A RESPONSE PACKET
;
; THIS ROUTINE WILL CHECK THE RESPONSE RING BUFFER FOR THE FIRST AVAILABLE
; RESPONSE PACKET.  IT WILL MARK IT "UDA OWN".
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	RESPONSE PACKET IS MARKED "UDA OWN'ED"
;
;-

RLPKT:	TST	@C.CRSP(R3)	;DOES THE UDA50 OWN THIS ENTRY?


	.IF DF	DEBUG

	BPL	      10$		;IF PL NO
	CRASH			;SOMETHING'S WRONG
	BR	RLPKT		;TRY AGAIN

	.IFF	;DEBUG

	BMI	RLPKT		;IF MI YES, LOOP

	.ENDC	;DEBUG


10$:	BIS	#OWN!FLAG,@C.CRSP(R3)  ;NO, THEN MARK IT UDA "OWN" AND INTERRUPTABLE
	ADD	#RNGSIZ,C.CRSP(R3)  ;POINT TO NEXT ENTRY IN RESPONSE RING
	ADD	#RSPLNG,C.CRSP+2(R3)  ;AND ITS PACKET
	CMP	C.LRSP(R3),C.CRSP(R3)  ;IS THIS THE LAST ONE?
	BHIS	20$		;IF HIS NO
	MOV	C.FRSP(R3),C.CRSP(R3)  ;RESET POINTER TO FIRST ONE
	MOV	C.FRSP+2(R3),C.CRSP+2(R3)  ;AND ITS PACKET
20$:	RE      TURN			;RETURN

;+
; **- ALPKT - ALLOCATE MSCP PACKET
;
; THIS ROUTINE IS CALLED TO ALLOCATE AN MSCP PACKET. 
;
; INPUTS:
;
;	R0 = LENGTH OF PACKET TO BE ALLOCATED
;
; OUTPUTS:
;
;	IF SUCCESS:
;	C  = 0 IF THE PACKET IS ALLOCATED.
;	R2 = POINTER TO PACKET
;
;	IF FAILURE:
;	C  = 1 IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE PACKET.
;
;-

ALPKT:	SEC			;ASSUME FAILURE
	DECB	C.NMBR(R3)	;ANY MORE PACKETS?
	BLT	20$		;IF LT NO
	MOV	C.PKT+2(R3),R2	;FREE PACKET?

	.IF DF	DEBUG

	CMP      	#DUEND,R2
	BLO	1$
	CMP	DUEND,R2
	BLOS	2$
1$:	BPT
2$:

	.ENDC	;DEBUG


	MOV	R2,C.PKT+2(R3)	;COPY ADDRESS OF CURRENT PACKET TO FIND THE NEXT
	ADD	R0,C.PKT+2(R3)	;ADD THE LENGTH OF THE PACKET ...
	ADD	#ENVLP,C.PKT+2(R3)  ;... PLUS THE ENVELOPE
10$:	MOV	R0,(R2)+	;SET MSCP COMMAND/RESPONSE LENGTH 
	CLR	(R2)+		;CLEAR VIRTUAL CIRCUIT IDENTIFIER
20$:	RETURN			;EXIT


;+
; **- DUPOLL - POLL RESPONSE RING ROUTINE
;
; THIS ROUTINE WILL SCAN THE RESPONSE RING LOOKING FOR ANY RESPONSES
; RETURNED       BY THE UDA50.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	IF SUCCES:
;	C  = 0 IF RESPONSE PACKET IS AVAILABLE
;	R0 = MESSAGE TYPE FIELD
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R2 = HI ORDER REF NUMBER FROM PACKET
;
;	IF FAILURE:
;	C  = 1 IF RESPONSE PACKET IS NOT AVAILABLE
;
;-

DUPOLL:	TST	C.STAT(R3)	;IS CONTROLLER OPERATIONAL?
	BLE	60$		;IF LE NO
	TST	@C.CRSP(R3)	;DOES THE UDA50 OWN THIS ENTRY?
	BMI	60$		;IF MI       YES
	MOV	C.CRSP+2(R3),R1  ;GET CURRENT RESPONSE RING PACKET POINTER
	MOV	P.CRF(R1),R2	;GET HI ORDER REF NUMBER FROM PACKET
	CLR	-(SP)		;GET A WORKING REGISTER
	MOVB	CREDIT(R1),(SP)	;OBTAIN MESSAGE/CREDIT FIELDS
	BIC	#^C<CRDDBT>,(SP)  ;CLR ALL BUT CREDIT/DEBIT FIELD
	ADD	(SP)+,C.CMDS(R3)  ;INC CONTROLLER'S COMMAND LIMIT
	MOV	CREDIT(R1),R0	;OBTAIN MESSAGE/CREDIT FIELDS
	BIC	#^C<MSGTYP>,R0	;CLR ALL BUT MESSAGE TYPE FIELD


	.IF DF	DEBUG

	TSTB	VCID(R1)	;IS THIS FROM A DISK MSCP VIRTUAL CIRCUIT?
      	BEQ	10$		;IF NE NO
	CRASH			;SOMETHING'S WRONG
	BR	60$		;TRY TO EXIT

	.ENDC	;DEBUG


;
;	R0 = CONTENTS OF MESSAGE TYPE FIELD
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R2 = HI ORDER REF NUMBER FROM THE RESPONSE PACKET
;

10$:	CMPB	#<MSGMNT*MSGMUL>,R0  ;IS THIS RESPONSE FOR A MAINTENANCE PACKET?
	BNE	30$		;IF NE NO


	.IF DF	D$$IAG


	.IF DF	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CALL	DUDPKT		;YES, HANDLE ALL DIAGNOSTIC PACKETS

	.      ENDC	;D$$IAG


20$:	CALL	RLPKT		;RELEASE PACKET
	BR	DUPOLL		;
30$:	CMPB	#<MSGCRD*MSGMUL>,R0  ;IS THIS RESPONSE A CREDIT NOTICE PACKET?
	BEQ	20$		;IF EQ YES
	CMPB	#<MSGDAT*MSGMUL>,R0  ;IS THIS RESPONSE A DATAGRAM PACKET?


	.IF DF	E$$DVC

	BNE	40$		;IF NE NO, 


	.IF DF	DEBUG

31$:	BPT			;GET TO XDT
	MOV	#NOP,31$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CALL	DULERR		;MUST BE SOME KIND OF ERROR LOG PACKET
	BR	20$		;

	.IFF	;E$$DVC

	BEQ	20$		;IF EQ YES

	.ENDC	;E$$DVC


40$:	CMP	#<M      SGSEQ*MSGMUL>,R0  ;IS THIS RESPONSE A SEQENTIAL PACKET?
	BNE	60$		;IF NE NO
	CLC			;YES, FORCE CARRY CLR
50$:	RETURN			;AND EXIT
60$:	SEC			;SET CARRY TO SHOW FAILURE
	RETURN			;AND EXIT

;+
; **- DUINIO - DEVICE I/O INITIATION ENTRY POINT
;
; THE DEVICE I/O INITIATION ENTRY POINT IS USED TO PROVIDE
; A CENTRALIZED PLACE TO MAKE MSCP COMMAND PACKETS "KNOWN"
; TO THE HARDWARE SUBSYTEM.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
      ;
;	IF C = 0 THEN REQUESTED I/O IS INSERTED INTO COMMAND RING
;
;		 CURRENT COMMAND RING POINTER IS UPDATED TO POINT TO NEXT 
;		 COMMAND RING ENTRY
;
;	IF C = 1 THEN REQUESTED I/O IS NOT INSERTED INTO COMMAND RING
;
;-

DUINIO:	MOV	S.CSR(R4),R2	;RETRIEVE CSR ADDRESS
	TST	UDASA(R2)	;IS UDA50 ON-LINE?
	SEC			;ASSUME NOT
	BNE	10$		;IF NE NO
	BIS	#OWN!FLAG,@C.CCMD(R3) ;SET RING TO UDA "OWN" AND INTERRUPTABLE
	TST	UDAIP(R2)	;FORCE A POLL
	BIC	#^C<CRDDBT>,R0	;CLR ALL BUT CREDIT/DEBIT FIELD
	SUB	      R0,C.CMDS(R3)	;DEC CONTROLLER'S COMMAND LIMIT BY DEBIT AMOUNT
	ADD	#RNGSIZ,C.CCMD(R3)  ;POINT TO NEXT ENTRY IN COMMAND RING
	ADD	#CMDLNG,C.CCMD+2(R3)  ;AND ITS PACKET
	CMP	C.LCMD(R3),C.CCMD(R3)  ;IS THIS THE LAST ONE?
	BHIS	10$		;IF HIS NO
	MOV	C.FCMD(R3),C.CCMD(R3)  ;RESET POINTER TO FIRST ONE
	MOV	C.FCMD+2(R3),C.CCMD+2(R3)  ;AND ITS PACKET
	CLC			;SHOW SUCCESS
10$:	RETURN			;RETURN

;+
; **- PRTST - TEST I/O PORT
;
; INPUTS:
;
;	R1 = I/O PACKET ADDRESS
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRES      S
;
; OUTPUTS:
;
;	IF THERE IS (POTENTIALLY) A PACKET IN THE I/O QUEUE THAT
;	CAN BE PROCESSED:
;
;		RETURN TO THE CALLER 
;
;	IF NOT:
;
;		RETURN TO THE CALLER'S CALLER
;
;		EXCEPT WHEN A CONTROLLER POWERFAIL HAS OCCURRED,
;		THEN ADJUST RETURN ADDRESS TO POINT TO UDA50 
;		CONTROLLER INITIALIZATION ROUTINE.
;
;-

PRTST:					;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	R3,-(SP)	;SAVE R3
	MOVB	S.CON(R4),R3	;RETRIEVE CON      TROLLER INDEX
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINTER
	BITB	#C2.PWF,C.STAT+1(R3)  ;CONTROLLER POWERFAIL INDICATED?
	BNE	50$		;IF NE YES
	TST	@C.CCMD(R3)	;DOES UDA50 "OWN" THIS ENTRY?
	BMI	60$		;IF MI YES
	TST	C.CMDS(R3)	;CONTROLLER COMMAND LIMIT EXHAUSTED?
	BLE	30$		;IF LE YES
	BITB	#US.VV,U.STS(R5)  ;UNIT VOLUME VALID SET?
	BEQ	40$		;IF EQ NO
	BITB	#US.SPU,U.STS(R5)  ;UNIT BEING BROUGHT ON-LINE?
	BNE	60$		;IF NE YES
	CMPB	#IO.RLB/256.,I.FCN+1(R1)  ;DATA TRANSFER FUNCTION?
	B      LO	10$		;IF LO NO, ACCEPT THE PACKET


	.IF DF	M$$EXT

	TST	U.CNT(R5)	;IS THIS UNIT WAITING FOR UMR'S
	BNE	30$		;IF NE YES
	TST	S.UMCT(R4)	;DO WE HAVE ANY MORE UMR WAIT BLOCK(S)?
	BEQ	30$		;IF EQ NO

	.ENDC	;M$$EXT


;
; ACCEPT PACKET
;

10$:	CLC			;CLR CARRY -- ACCEPT THE PACKET
20$:	MOV	(SP)+,R3	;RESTORE R3
	RETURN			;RETURN

;
; REJECT PACKET
;

30$:	SEC			;SET CARRY -- REJECT THE PACKET
	BR	20$		;AND EXIT

;
; DRIVE NEEDS TO BE BROUGHT ON-LINE
;

40$:				;REF LABEL


	      .IF DF	DEBUG

41$:	BPT			;GET TO XDT
	MOV	#NOP,41$	;NOP THE BRK PNT

	.ENDC	;DEBUG

	BISB	#US.VV,U.STS(R5)  ;NOTE THAT UNIT IS BEING BROUGHT ON-LINE
	MOV	#DUONL,G$$SPA+2(SP)  ;ADJUST THE RETURN ADDRESS IN ORDER
				;TO GO TO UNIT ON-LINE ROUTINE
	BR	60$		;AND GO ON

;
; CONTROLLER REQUIRES INITIALIZATION
;

50$:				;REF LABEL


	.IF DF	DEBUG

51$:	BPT			;GET TO XDT
	MOV	#NOP,51$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	#DUINIT,G$$SPA+2(SP)  ;ADJUST THE RETURN ADDRESS IN ORDER
				;      TO GO TO CONTROLLER INITIALIZATION ROUTINE

;
; FOUND A PACKET THAT CAN BE DEQUEUED IF THE CONTROLLER WILL FREE UP
; A COMMAND PACKET SLOT
;

60$:				;REF LABEL


	.IF DF	DEBUG

61$:	BPT			;GET TO XDT
	MOV	#NOP,61$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	ADD	#G$$SPA+2,SP	;FLUSH THE STACK
	RETURN			;RETURN TO ADDRESS ON THE STACK

;+
; **- MAPR - MAP DRIVER'S RING BUFFER AREA
;
; THIS ROUTINE MAPS THE DRIVER'S PRIVATE DATA BASE OF RINGS AND 
; PACKETS.
;
; INPUTS:
;
;	R3 = CONTROLLER       STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	DRIVER'S PRIVATE DATA BASE OF RINGS AND PACKETS ARE MAPPED
;	ON A CONTROLLER SPECIFIC BASIS.
;
;-

MAPR:					;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	CLR	R0		;CLR R0 ...
	CLR	R1		;... AND R1
	CMP	#DUSTRT,#120000	;LOADABLE DRIVER?
	BLO	40$		;IF LO NO
	MOV	@#KINAR5,R0	;GET START OF DRIVER CODE
	MOV	R0,C.PAR5(R3)	;SAVE THE DRIVER'S MAPPING


	.IF DF	      DU$BIG

	MOV	R0,C.PAR6(R3)	;COPY THE START FOR GREATER THAN 4K WORDS
	ADD	#200,C.PAR6(R3)	;MAKE IT CONTIGUOUS TO THE START OF THE DRIVER

	.ENDC	;DU$BIG


	MOV	R0,R1		;COPY REAL START OF DRIVER AREA


	.IF DF	M$$EIS

	CLR	R0		;INITIALIZE R0
	ASHC	#6.,R0		;CALCULATE PHYSICAL ADDRESS

	.IFF	;M$$EIS

	MOV	R1,R0		;GET START OF PHYSICAL ADDRESS
	SWAB	R0		;USE NON-EIS EMULATION OF "ASHC #6.,R0" ...
	BIC	#177400,R0	;... TO CALCULATE PHYSICAL ADDRESS
	SWAB	R1		;
	BIC	#377,R1		;
	ROR	R0		;
	R      OR	R1		;
	ROR	R0		;
	ROR	R1		;

	.ENDC	;M$$EIS


	.IF DF	 M$$EXT

;
; 	SET UP SELECTED UMR TO MAP ALL OF THE DRIVER DATA AREA.
;	SAVE THE UMR VALUES IN THE UMR WORK AREA IN THIS CONTROLLER'S 
;	SCB.
;

	BIT	#DV.EXT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?
	BNE	40$		;IF NE YES
	TST	@#$UMRPT	;UNIBUS MAP AVAILABLE?
	BEQ	20$		;IF EQ NO
	TST	S.MPR+M.UMRN+2(R4)  ;STATIC UMR ALREADY SET-UP?
	BNE	20$		;IF NE YES
	MOV	R1,S.MPR+M.BFVL+2(R4)  ;SET UP LO 16-BITS OF ADDRESS
	MOVB	R0,S.MPR+M.BFVH+2(R4      )  ;SET UP HI 6-BITS OF ADDRESS


	.IF NDF	DU$BIG

	MOV	#4,S.MPR+M.UMRN+2(R4)  ;SET UP COUNT FOR 1 UMR

	.IFF	;DU$BIG

	MOV	#8.,S.MPR+M.UMRN+2(R4)  ;SET UP COUNT FOR 2 UMR'S

	.ENDC	;DU$BIG


10$:	MOV	R4,R0		;COPY SCB POINT TO R0
	ADD	#S.MPR+2,R0	;POINT R0 TO UMR MAPPING BLOCK + 2
	CALL	$ASUMR		;GO ASSIGN UMR'S
	BCS	10$		;IF CS, TRY AGAIN

;
; LOAD SELECTED UMR FOR THIS CONTROLLER TO MAP DRIVER WITH 18-BIT ADDRESSES 
; TRANSFORMED FROM DRIVER VIRTUAL ADDRESSES
;

20$:	TST	$UMRPT		;IS       UNIBUS MAP AVAILABLE?
	BEQ	30$		;IF EQ NO
	MOV	R4,R0		;COPY SCB ADDRESS
	ADD	#S.MPR+2,R0	;POINT TO UMR MAPPING BLOCK + 2
	TST	M.UMRN(R0)	;HAVE WE ASSIGNED THE UMR'S
	BEQ	30$		;IF EQ YES
	CALL	$MPUB1		;MAP THE UNIBUS
30$:	MOV	S.MPR+M.UMVL+2(R4),R1  ;GET LO 16-BITS OF VIRTUAL ADDRESS
	MOVB	S.MPR+M.UMVH+2(R4),R0  ;GET HI 2-BITS OF VIRTUAL ADDRESS
	ASR	R0		;SHIFT BITS <4:5> RIGHT TO <0:1>
	ASR	R0		;...
	ASR	R0		;...
	ASR	R0		;...
	SUB	#120000,R1	;SUBTRACT DRIVER BASE VIRTUAL ADDRESS
	SBC	R0		;SUB      TRACT CARRY FROM R0
	BIC	#^C<3>,R0	;CLEAR ALL BUT BITS <0:1>

	.IFF	;M$$EXT

	SUB	#120000,R1	;SUBTRACT DRIVER BASE VIRTUAL ADDRESS
	SBC	R0		;SUBTRACT CARRY FROM R0
	BIC	#^C<3>,R0	;CLEAR ALL BUT BITS <0:1>

	.ENDC	;M$$EXT


;
; RELOCATION CONSTANT IS USED TO TRANSFORM A VIRTUAL ADDRESS WITHIN THE 
; DRIVER TO A PHYSICAL ADDRESS. THIS RELOCATION IS REQUIRED WHENEVER MEMORY
; MANAGEMENT IS PRESENT. THE FORMAT OF THE DOUBLE WORD RELOCATION CONSTANT 
; IS SUCH THAT WHEN IT IS ADDED TO A VIRTUAL A      DDRESS IN THE RANGE 
; 120000-157777 (CARRY IS ADDED TO BIT 0 OF THE HIGH ORDER WORD), THE RESULT 
; IS THE 18-BIT PHYSICAL ADDRESS (2 HIGH BITS IN BITS 0-1 OF C.RELC, 16 LOW 
; BITS IN C.RELC+2).
;
; THE RELOCATION CONSTANT IS CALCULATED AND STORED HERE BY THE 
; INITIALIZATION CODE.
;

;
; COMPUTE AND SAVE THE DOUBLE WORD RELOCATION CONSTANT TO TRANSFORM A 
; DRIVER VIRTUAL ADDRESS INTO AN 18-BIT ADDRESS.
;

40$:	MOV	R0,C.RELC(R3)	;SAVE RELOCATION CONSTANT
	MOV	R1,C.RELC+2(R3)	;...


	.I      F DF	DU$BIG

	CMP	#DUSTRT,#120000	;LOADABLE DRIVER?
	BHIS	60$		;IF HIS YES
	CMP	#DUEND,#140000	;DRIVER GREATER THAN 4K WORDS
	BLO	60$		;IF LO NO


	.IF DF	DEBUG

41$:	BPT			;GET TO XDT
	MOV	#NOP,41$	;NOP THE BRK PNT

	.ENDC	;DEBUG


50$:	CRASH			;SOMETHING'S WRONG
	HALT			;HALT THE PROCESS IF USER TRIES TO GO ON!
	BR	50$		;DON'T GO ANY FURTHER

	.ENDC	;DU$BIG


60$:	MOVB	C.RSP(R3),R1	;GET NUMBER ENTRIES IN RESPONSE RING BUFFER
	MOV	#RNGSIZ,R0	;GET SIZE OF A RING ENTRY
	CALL	$MUL		;C      OMPUTE SIZE OF RESPONSE RING BUFFER
	MOV	R1,-(SP)	;SAVE SIZE OF RESPONSE RINGS
	SUB	#RNGSIZ,(SP)	;LESS ONE RING ENTRY
	MOV	C.RING(R3),R1	;DEFINE START OF RESPONSE RING FOR THIS CONTROLLER
	TST	(R1)+		;POINT HI ORDER ENTRY OF RING 
	MOV	R1,C.CRSP(R3)	;STORE IT IN CURRENT RESPONSE RING BUFFER 
				;POINTER
	MOV	R1,C.FRSP(R3)	;AND IN FIRST RESPONSE RING BUFFER POINTER
	ADD	(SP)+,R1	;LOCATE LAST MESAGE RING BUFFER
	MOV	R1,C.LRSP(R3)	;AND STORE IT IN LAST RESPONSE RING BUFFER 
				;POINTER
	ADD	#RNGSI      Z,R1	;LOCATE COMMAND RING BUFFER
	MOV	R1,C.CCMD(R3)	;STORE IT IN CURRENT COMMAND RING BUFFER 
				;POINTER
	MOV	R1,C.FCMD(R3)	;AND IN FIRST COMMAND RING BUFFER POINTER
	MOVB	C.CMD(R3),R1	;GET NUMBER OF ENTRIES IN COMMAND RINGS
	MOV	#RNGSIZ,R0	;GET SIZE OF A RING ENTRY
	CALL	$MUL		;COMPUTE SIZE OF COMMAND RING BUFFER
	SUB	#RNGSIZ,R1	;COMPENSATE FOR FIRST ENTRY
	ADD	C.FCMD(R3),R1	;LOCATE LAST COMMAND RING BUFFER
	MOV	R1,C.LCMD(R3)	;AND STORE IT IN LAST COMMAND RING BUFFER 
				;POINTER
	MOV	C.INIT+      2(R3),R1  ;RETRIEVE CURRENT STEP WORD POINTER
	MOV	C.FRSP(R3),(R1)  ;START SET UP OF LO ORDER RING BYTE ADDRESS
$STEP2	==	.-2
	ADD	#LADDR,(R1)	;ADD OFFSET TO LO ORDER RING BYTE ADDRESS
	ADD	C.RELC+2(R3),(R1)+  ;ADD LO ORDER RELOCATION CONSTANT
	MOV	#HADDR,(R1)	;INITIALIZE HI BYTE ADDRESS
	ADC	(R1)		;ADD CARRY
	ADD	C.RELC(R3),(R1)+  ;NOW ADD THE HI ORDER RELOCATION CONSTANT
$STEP3	==	.-2


	.IF DF	E$$DVC

	MOV	#LFAIL!GO,(R1)+ ;SET LAST FAILURE FLAG AND ...
				;... CONTROLLER GO-BIT
$STEP4	==	      .-2

	.IFF	;E$$DVC

	MOV	#GO,(R1)+	;SET CONTROLLER GO-BIT
$STEP4	==	.-2

	.ENDC	;E$$DVC


	RETURN			;EXIT

;+
; **- DUOPEN - OPEN "VIRTUAL CIRCUIT" WITH UDA50 CONTROLLER
;
; THE OPEN "VIRTUAL CIRCUIT" ENTRY POINT IS USED TO INITIALIZE (RE-INIT) THE 
; UDA50 PORT INTERFACE.  CALLED ONCE PER CONTROLLER.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	C = 0 IF CONTROLLER IS INITIALIZED 
;	C = 1 IF CONTROLLER IS NOT INITIALIZE      D 
;
;-

	.ENABL	LSB

DUOPEN:	CALL	MAPIT		;MAP TO INITIALIZATION TABLE
	MOV	#STEP1,UDAIP(R2)  ;HARD INIT CONTROLLER
	CALL	50$		;STEP FUNCTION SUCCESSFUL?
	BCS	20$		;IF CS, NO
	RETURN			;EXIT
DUOPN2:	CALL	MAPIT		;MAP TO INITIALIZATION TABLE
10$:	CMPB	-1(R1),UDASA(R2)  ;DID THE RING'S LENGTH ECHO SUCCESSFULLY?
	BNE	20$		;IF NE NO
	CALL	50$		;STEP FUNCTION SUCCESSFUL?
	BCS	20$		;IF CS, NO
	RETURN			;WAIT FOR INTERRUPT
DUOPN3:	CALL	MAPIT		;MAP TO INITIALIZATION TABLE
	CMPB	-4(R1),UDASA(R2)  ;D      ID THE INTERRUPT VECTOR ECHO SUCCESSFULLY?
	BNE	20$		;IF NE NO
	CALL	50$		;STEP FUNCTION SUCCESSFUL?
	BCS	20$		;IF CS, NO
	RETURN			;WAIT FOR INTERRUPT
DUOPN4:	CALL	SETR		;SET UP RING BUFFER AREA
	CALL	MAPIT		;MAP TO INITIALIZATION TABLE
	CALL	50$		;STEP FUNCTION SUCCESSFUL?
	BCS	20$		;IF CS, NO
	RETURN			;EXIT
20$:	DECB	C.RTRY(R3)	;ANY MORE RETRIES?
	BEQ	40$		;IF EQ NO
	CALL	STINT		;SET INITIALIZATION PARAMETERS
	MOVB	#C2.INI,C.STAT+1(R3)  ;SET CONTROLLER INITIALIZATION IN PROGRESS
	BISB	#C1.      INI,C.STAT(R3)  ;SET RE-INITIALIZATION REQUIRED FLAG
	TST	(SP)+		;FLUSH FIRST RETURN ADDRESS
30$:	BR	DUOPEN		;RESTART AND RE-INIT CONTROLLER
40$:	BISB	#C1.OFF,C.STAT(R3)  ;MARK CONTROLLER OFF-LINE


	.IF DF	E$$DVC

	CALL	DUCERR		;LOG CONTROLLER ERROR LOG PACKET

	.ENDC	;E$$DVC


;
; MUST SCAN THROUGH ALL THE UCB'S ASSOCIATED WITH THIS CONTROLLER TO 
; SET EACH UNIT OFF-LINE
;

	CALLR	OFFLIN		;SET ALL UNITS ASSOCIATED WITH THIS CONTROLLER ...
				;... OFFLINE
50$:	TST	UDASA(R2)	;ERROR BIT      ?
	BMI	60$		;IF MI YES
	BIT	R0,UDASA(R2)	;STEP BIT?
	BEQ	50$		;IF EQ NO
	MOV	(R1)+,UDASA(R2)  ;WRITE INITIALIZATION WORD TO UDA50
	RETURN			;EXIT
60$:	SEC			;MARK FAILURE
	RETURN			;EXIT

	.DSABL	LSB

;+
; **- MAPIT - MAP TO DRIVER'S INITIALIZATION TABLE
;
; THIS ROUTINE MAPS TO THE DRIVER'S INITIALIZATION TABLE.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R0 = CURRENT STEP VALUE
;	R1 = ADDRESS OF CURRENT STEP IN INITIAL      IZATION TABLE
;	R2 = CSR ADDRESS
;
;-

	.ENABL	LSB

MAPIT:	MOV	C.INIT(R3),R0	;GET CURRENT STEP VALUE
	MOV	C.INIT+2(R3),R1	;GET CURRENT STEP WORD POINTER
	MOV	S.CSR(R4),R2	;GET CSR ADDRESS
	CALL	@(SP)+		;CALL CALLER BACK AS CO-ROUTINE
	MOV	R1,C.INIT+2(R3)	;SAVE INIT TABLE POINTER
	ASL	C.INIT(R3)	;MOVE TO NEXT STEP
	BPL	10$		;IF PL EXIT
				;OTHERWISE SET UP INITIALIZATION PARAMETERS

;+
; **- STINT - SET INITIALIZATION PARAMETERS
;
; THIS ROUTINE SETS THE INITIALIZATION PARAMETERS FOR CONT      ROLLER INITIALIZATION
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = ADDRESS OF BEGINNING OF INITIALIZATION TABLE
;
;-

STINT:	MOV	R3,R1		;COPY POINTER TO STATE TABLE
	ADD	#C.ITBL,R1	;ADJUST IT TO INITIALIZATION TABLE
	MOV	#STEP1,C.INIT(R3)  ;START CONTROLLER INIT AT STEP 1 AND ...
	MOV	R1,C.INIT+2(R3)	;... AT BEGINNING OF INITIALIZATION TABLE
10$:	RETURN			;EXIT

	.DSABL	LSB

;+
; **- $DUINT - UDA50 CONTROLLER INTERRUPT       HANDLER
;
; INTERRUPTS ARE RECEIVED FROM A CONTROLLER UNDER FOUR CIRCUMSTANCES
; THEY ARE AS FOLLOWS:
;	1.  DURING THE INITIALIZATION PROCESS (OPEN THE "VIRTUAL CIRCUIT") 
;	2.  WHEN THE "COMMAND RING BUFFER" TRANSITIONS FROM "FULL" TO "NOT FULL" 
;	3.  WHEN THE "RESPONSE RING BUFFER"  TRANSITIONS FROM "EMPTY" TO "NOT EMPTY"
;	4.  WHEN A FATAL CONTROLLER ERROR IS DETECTED AND AN INTERRUPT CAN BE GENERATED
;		FATAL CONTROLLER ERRORS ARE:
;			A.  FAILURE TO BECOME UNIBUS MASTER FOR DATA TRANSFER
;	      		B.  FAILURE TO BECOME UNIBUS MASTER FOR INTERRUPT
;			C.  FAILURE TO ACCESS I/O PAGE REGISTERS OR COMMUNICATIONS AREA
;			    (I.E. NON-EXISTENT MEMORY)
;			D.  UNIBUS PARITY ERROR DETECTED
;
;-

	INTSE$	DU,PR5,R$$UDA	;;;GENERATE INTERRUPT SAVE CODE
	MOV	R4,-(SP)	;;;SAVE R4
	MOV	U.SCB(R5),R4	;;;POINT TO CONTROLLER STATUS BLOCK
	CLRB	S.CTM(R4)	;;;DISABLE TIMEOUT
	ADD	#S.FRK+6,R4	;;;POINT TO END OF FORK BLOCK
	TST	-4(R4)		;;;FORK BLOCK ALREADY IN USE?
	BEQ	10$		;;;IF EQ NO
	MOV	(SP)+,R4	;;;RES      TORE R4
	RETURN			;;;EXIT FROM INTERRUPT
10$:	MOV	(SP)+,(R4)	;;;PUT SAVED R4 IN FORK BLOCK
	CALL	$FORK1		;;;CREATE A SYSTEM PROCESS
	MOV	CTTBL(R4),R3	;RETRIEVE CONTROLLER STATE TABLE ADDRESS
	MOV	U.SCB(R5),R4	;RETREIVE SCB ADDRESS
	CLR	S.FRK+2(R4)	;FREE FORK BLOCK FOR FURTHER INTERRUPTS


	.IF DF 	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	S.CSR(R4),R2	;RETRIEVE CSR ADDRESS
	TST	UDASA(R2)	;DID THE CONTROLLER SUFFER A FATAL ERROR?
	BMI	60$		;IF MI YE      S
	TSTB	C.STAT+1(R3)	;CONTROLLER INITIALIZATION IN PROGRESS?
	BPL	40$		;IF PL NO


	.IF DF 	DEBUG

12$:	BPT			;GET TO XDT
	MOV	#NOP,12$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	BIT	#STEP2,C.INIT(R3)  ;READY FOR STEP 2?
	BEQ	20$		;IF EQ NO


	.IF DF	M$$EXT

	CALL	DUEXTM		;CHECK EXTENDED MEMORY SUPPORT

	.ENDC	;M$$EXT


	CALL	MAPR		;MAP DRIVER'S RINGS AND PACKETS
	CALLR	DUOPN2		;CONTINUE WITH STEP 2
20$:	BIT	#STEP3,C.INIT(R3)  ;READY FOR STEP 3?
	BEQ	30$		;IF EQ NO
	CALLR	DUOPN3		;CONTIN      UE WITH STEP 3
30$:	CALL	DUOPN4		;CONTINUE WITH STEP 4
	CALLR	DUINT1		;YES, GO SET CONTROLLER ON-LINE
40$:				;REF LABEL


	.IF DF 	DEBUG

41$:	BPT			;GET TO XDT
	MOV	#NOP,41$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	C.RING(R3),R0	;RETRIEVE BASE OF RINGS
	TST	CMDINT(R0)	;IS INTERRUPT FOR COMMAND RING NOT FULL?
	BNE	50$		;IF NE YES
	CLR	RSPINT(R0)	;CLR INTERRUPT STATUS WORD
	CALLR	DURSP		;GO PROCESS ANY RESPONSES
50$:	CLR	CMDINT(R0)	;CLR INTERRUPT STATUS WORD
	CALLR	DUINI		;GO DEQUEUE ANY C      OMMANDS (IF AVAILABLE)
60$:				;REF LABEL


	.IF DF 	DEBUG

61$:	BPT			;GET TO XDT
	MOV	#NOP,61$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CALLR	REINIT		;YES, RE-INITIALIZATION REUIRED

	.PAGE

;+
; **- REGPAS - REGISTER PASS ROUTINE
;
; THE REGPAS ROUTINE IS USED TO MOVE VALUES FROM ONE SET OF LOCATIONS
; TO ANOTHER (I.E. FROM AN MSCP PACKET TO UCB).
;
; INPUTS:
;
;	R0 = DESTINATION LOCATION
;	R1 = SOURCE LOCATION
;	R2 = NUMBER OF WORDS TO MOVE
;
; OUTPUTS:
;
;	THE SPECIFIED WORDS AR      E MOVED FROM SOURCE TO DESTINATION
;
;-

REGPAS:	MOV	(R1)+,(R0)+	;MOVE THEM A WORD AT A TIME
	SOB	R2,REGPAS	;LOOP
	RETURN			;EXIT

;+
; **- DUEXTM - EXTENDED MEMORY SUPPORTED ROUTINE
;
; THIS ROUTINE WILL DETERMINE IF THIS CONTROLLER SUPPORTS EXTENDED 
; MEMORY ADDRESSING OR NOT.  BASED ON THESE FINDINGS, IT WILL SET/CLR 
; THE "DV.EXT" BIT IN U.CW1 FOR EACH UNIT ATTACHED TO THIS CONTROLLER.
;
; INPUTS:
;
;	R2 = CSR ADDRESS
;	R3 = POINTER TO CONTROLLER STATE TABLE
;	R4 = SCB ADDRESS
;	R5       = UCB ADDRESS
;
; OUTPUTS:
;
;	R2 = CSR ADDRESS
;	R3 = POINTER TO CONTROLLER STATE TABLE
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-


	.IF DF	M$$EXT

DUEXTM:				;REF LABEL


	.IF DF 	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	#SCUCB,-(SP)	;PUSH "SCAN UCB'S" ROUTINE ON THE STACK
10$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	20$		;IF CS, ALL DONE
	MOV	S.CSR(R4),R2	;RETRIEVE CSR ADDRESS
	BIC	#DV.EXT,U.CW1(R5)  ;ASSUME NO EXTENDED MEMORY SUPPORT      
	BIT	#EXTMEM,UDASA(R2)  ;EXTENDED MEMORY SUPPORTED?
	BEQ	10$		;IF EQ NO
	BIS	#DV.EXT,U.CW1(R5)  ;YES, SET EXTENDED MEMORY SUPPORT
	BR	10$		;GO AGAIN
20$:	MOV	S.CSR(R4),R2	;RETRIEVE CSR ADDRESS
	RETURN			;EXIT

	.ENDC	;M$$EXT


;+
; **- RQRCT - REQUEST REPLACEMENT CONTROL TASK
;
; THIS ROUTINE IS CALLED TO REQUEST THE REPLACEMENT CONTROL TASK
; TO INITIALIZE THE SPECIFIED UNIT OR TO REPLACE A BAD BLOCK ON 
; THE SPECIFIED UNIT.
;
; INPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET       IF REPLACEMENT
;	     OR ELSE ZERO IF INITIALIZATION
;	R3 = ADDRESS OF CONTROLLER STATE TABLE
;	R4 = ADDRESS OF THE SCB
;	R5 = ADDRESS OF THE UCB.
;
; OUTPUTS:
;
;	THE REPLACEMENT CONTROL TASK IS REQUESTED TO REPLACE
;	THE BAD BLOCK ON THE SPECIFIED UNIT.
;
;-

RQRCT:				;REF LABEL

	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	R1,-(SP)	;SAVE R1 AND ...
	MOV	R3,-(SP)	;... CONTROLLER STATE TABLE POINTER
	BIT	#UF.RPL,U.UNFL(R5)  ;CONTROLLER       INITIATED BAD BLOCK ...
				;... REPLACEMENT?
	BNE	30$		;IF NE YES
	MOV	#RCTNAM,R3	;NO, POINT TO RCT'S NAME
	CALL	$SRSTD		;IS RCT INSTALLED?
	BCC	40$		;IF CC YES
	MOV	#T.NRCT,R0	;NO, SET MESSAGE ...
				;... "REPLACEMENT CONTROLL TASK NOT INSTALLED"
10$:	CALL	$DVMSG		;GO PRINT IT ...
	BR	30$		;... AND GO ON
20$:				;REF LABEL


	.IF DF	DEBUG

21$:	BPT			;GET TO XDT
	MOV	#NOP,21$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	(SP),R3		;RETRIEVE CONTROLLER STATE TABLE POINTER
	MOV	2(SP),R1	;RET      RIEVE R1, DOES IT POINT TO CURRENT ...
				;... RESPONSE RING PACKET?
	BEQ	30$		;IF EQ NO
	MOVB	P.FLGS(R1),C.IOSB+1(R3)  ;SET FLAGS BYTE INTO HI BYTE OF ...
				;... I/O STATUS BLOCK
30$:	SEC			;SET CARRY TO INDICATE NO NEED TO REQUEST RCT
	BR	80$		;EXIT
40$:				;REF LABEL

	.IF DF	DEBUG

41$:	BPT			;GET TO XDT
	MOV	#NOP,41$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CMP	U.ATT(R5),R0	;IS RCT ATTACHED?
	BEQ	20$		;IF EQ YES
	MOV	R0,RCTTCB	;SAVE TCB ADDRESS
	MOV	#12.,R1		;SET LENGTH OF BLOCK NEEDED      
	CALL	$ALOCB		;GET A CORE BLOCK
	BCC	50$		;IF CC GOT ONE
	MOV	#T.NUER,R0	;SET MESSAGE
	BR	10$		;GO ON
50$:	MOV	R0,R3		;SET ADDRESS OF MESSAGE BLOCK
	TST	(R0)+		;POINT TO SECOND WORD IN BLOCK
	MOV	2(SP),R1	;DO WE HAVE INITIALIZATION REQUEST?
	BEQ	60$		;IF EQ YES
	MOV	P.CRF+2(R1),(R0)+  ;NO, INSERT I/O PACKET ADDRESS (REPLACEMENT 
				;REQUIRED INDICATOR)
	MOV	R5,(R0)+	;INSERT UCB ADDRESS
	MOV	P.FBBK+2(R1),(R0)+  ;INSERT HI LBN TO BE REPLACED
	MOV	P.FBBK(R1),(R0)+  ;INSERT LO LBN TO BE REPLACED      
	BR	70$		;AND CONTINUE
60$:	CLR	(R0)+		;INSERT INITIALIZATION INDICATOR
	MOV	R5,(R0)+	;INSERT UCB ADDRESS
	CLR	(R0)+		;CLR HI LBN POSITION
	CLR	(R0)+		;CLR LO LBN POSITION
70$:	MOV	R3,R1		;COPY ADDRESS OF MESSAGE BLOCK
	MOV	RCTTCB,R0	;PICK UP RCT'S TCB ADDRESS	
	CALL	$EXRQF		;REQUEST RCT TO RUN
	CLC			;CLR CARRY TO INDICATE RCT REQUESTED
80$:	MOV	(SP)+,R3	;RESTORE CONTROLLER STATE TABLE POINTER AND ...
	MOV	(SP)+,R1	;... R1
	RETURN			;EXIT

;+
; **- DUGCS - UDA50 GET COMMAND STATUS ROUTINE
;      
; THIS ROUTINE WILL ISSUE A "GET COMMAND STATUS" PACKET
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-


	.IF DF	E$$DVC

DUGCS:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	CMP	U.LHD(R5),U.OTRF(R5)  ;IS AN OUTSTANDING COMMAND STATUS REQUEST ...
				;... PENDING FOR THE OLDEST I/O RE      QUEST?
	BEQ	20$		;IF EQ YES
10$:	MOV	#P.LENG,R0	;SET-UP COMMAND PACKET LENGTH
	MOV	#1,R1		;SET-UP VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELD
	CALL	GTPKT		;GET THE CURRENT COMMAND PACKET IN THE RING
	BCS	10$		;IF CS NO, ... TRY, TRY AGAIN
	MOV	R5,P.CRF(R1)	;YES SET HI ORDER REF NUMBER TO UCB ADDRESS
	MOV	R3,P.CRF+2(R1)	;SET LO ORDER REF NUMBER TO CONTROLLER STATE TABLE
	MOVB	#OP.GCS,P.OPCD(R1)  ;SET "GET COMMAND STATUS" OP CODE
	MOVB	U.UNIT(R5),P.UNIT(R1)  ;SET UNIT
	MOV	R5,P.OTRF(R1)	;SET HI ORDER OUT      STANDING COMMAND REF NUMBER
	MOV	U.LHD(R5),P.OTRF+2(R1)  ;SET LO ORDER OUTSTANDING COMMAND ...
				;... REF NUMBER
	MOV	U.LHD(R5),U.OTRF(R5)  ;SAVE OLDEST I/O REQUEST IN OUTSTANDING ...
				;... COMMAND REF NUMBER STATUS REGISTER
	CALLR	DUCMD3		;ISSUE I/O
20$:				;REF LABEL


	.IF DF	DEBUG

21$:	BPT			;GET TO XDT
	MOV	#NOP,21$	;NOP THE BRK PNT

	.ENDC	;DEBUG


;
; WE HAVE TIMED OUT THE OLDEST I/O REQUEST TWICE.
; IT WILL BE ASSUMED THAT THE CONTROLLER IS INSANE OR
; OR HOPELESSLY DEADLOC      KED.  RE-INITIALIZATION SEEMS 
; APPROPRIATE AT THIS TIME.
;

	TST	(SP)+		;FLUSH THE STACK

	.ENDC	;E$$DVC


;+
; **- REINIT - RE-INITIALIZE ROUTINE
;
; THE RE-INITIALIZE ROUTINE IS ENTERED WHENEVER THE CONTROLLER MUST BE RE-
; INITIALIZED.
;
; INPUTS:
;
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE CONTROLLER INITIALIZATION TABLE IS SET-UP AND THE CONTROLLER
;	RE-INITIALIZATION IS STARTED.
;
;-

REINIT:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	      #NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINT
	MOV	S.CSR(R4),R2	;AND RETRIEVE CSR ADDRESS


	.IF DF	E$$DVC

	CALL	DUCERR		;LOG CONTROLLER ERROR LOG PACKET

	.ENDC	;E$$DVC


	DECB	C.RTRY(R3)	;ANY MORE RETRIES LEFT?
	BEQ	OFFLIN		;IF EQ NO
	TST	UDASA(R2)	;DID CONTROLLER SUFFER A FATAL ERROR?
	BEQ	10$		;IF EQ NO
	BISB	#C1.INI,C.STAT(R3)  ;SET RE-INITIALIZATION REQUIRED FLAG
	CALL	DUPWF2		;IN      #NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOVB	S.CON(R4),R3	;RETRIEVE CONTROLLER INDEX
	MOV	CTTBL(R3),R3	;RETRIEVE CONTROLLER STATE TABLE POINT
	MOV	S.CSR(R4),R2	;AND RETRIEVE CSR ADDRESS


	.IF DF	E$$DVC

	CALL	DUCERR		;LOG CONTROLLER ERROR LOG PACKET

	.ENDC	;E$$DVC


	DECB	C.RTRY(R3)	;ANY MORE RETRIES LEFT?
	BEQ	OFFLIN		;IF EQ NO
	TST	UDASA(R2)	;DID CONTROLLER SUFFER A FATAL ERROR?
	BEQ	10$		;IF EQ NO
	BISB	#C1.INI,C.STAT(R3)  ;SET RE-INITIALIZATION REQUIRED FLAG
	CALL	DUPWF2		;IN      ITIALIZE CONTROLLER PARAMETERS
	CALLR	DUINIT		;RE-INITIALIZE THE UDA50 CONTROLLER
10$:				;REF LABEL


	.IF DF	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	C.RING(R3),R0	;RETRIEVE BASE OF RINGS
	TST	CMDINT(R0)	;NEED TO SERVICE COMMAND RING FULL CASE?
	BNE	20$		;IF NE YES
	TST	RSPINT(R0)	;NEED TO SERVICE RESPONSE RING NOT EMPTY CASE?
	BEQ	30$		;IF EQ NO
	CLR	RSPINT(R0)	;CLR INTERRUPT STATUS WORD
	CALLR	DURSP		;CHECK ON ANY RESPONSES (IF AVAILABLE)
20$      :	CLR	CMDINT(R0)	;CLR INTERRUPT STATUS WORD
	CALLR	DUINI		;GO DEQUEUE ANY COMMANDS (IF AVAILABLE)
30$:	CALLR	DUEXIT		;THEN SEE HOW WE SHOULD EXIT

;+
; **- OFFLIN - UDA50 OFFLINE ROUTINE
;
; THE OFFLINE ROUTINE SCANS THROUGH ALL THE UCB'S ASSOCIATED WITH THIS 
; CONTROLLER TO SET EACH UNIT OFF-LINE
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	ALL UNITS ASSOCIATED WITH THIS CONTROLLER HAVE BEEN SET OFFLINE.
;
;-

OFFLIN:	MOV	      #SCUCB,-(SP)	;PUSH "SCAN UCB'S" ROUTINE ON THE STACK
10$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	20$		;IF CS, ALL DONE
	BISB	#US.OFL,U.ST2(R5)  ;MARK UNIT AS OFF-LINE
	BICB	#US.SPU!US.VV,U.STS(R5)  ;AND CLR SPIN-UP AND VOLUME VALID FLAGS
	BR	10$		;GO AGAIN
20$:	RETURN			;EXIT

;+
; **- DUSTAT - UDA50 GET UNIT STATUS ROUTINE
;
; THE GET UNIT STATUS ROUTINE WILL OBTAIN THE SPECIFIED DEVICE'S 
; CHARACTERISTICS.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB       ADDRESS
;
; OUTPUTS:
;
;	THE STATUS OF THE SPECIFIED UNIT IS OBTAINED
;
;-

DUSTAT:	MOV	#P.LENG,R0	;SET-UP COMMAND PACKET LENGTH
	MOV	#1,R1		;SET-UP VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELD
	CALL	GTPKT		;GET THE CURRENT COMMAND PACKET
	BCS	DUSTAT		;IF CS TRY AGAIN
	MOV	R5,P.CRF(R1)	;SET HI ORDER REF NUMBER TO UCB ADDRESS
	MOV	R3,P.CRF+2(R1)	;SET LO ORDER REF NUMBER TO CONTROLLER
				;STATE TABLE
	MOVB	U.UNIT(R5),P.UNIT(R1)  ;SET UNIT NUMBER
	MOV	#0,P.MOD(R1)	;SET MODIFIERS
	MOVB	#OP.GUS,P.OP      CD(R1)  ;ASSUME "GET UNIT STATUS" OP CODE
	CALLR	DUCMD3		;ISSUE I/O

;+
; **- DUONL - UDA50 UNIT INITIALIZATION AND ON-LINE ROUTINE
;
; THE UNIT INITIALIZATION AND ON-LINE ROUTINE WILL DO WHAT IS 
; NECESSARY TO OBTAIN THE SPECIFIED DEVICE'S CHARACTERISTICS AND,
; IF POSSIBLE, SET THE UNIT ON-LINE
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE SPECIFIED UNIT IS FIRST BROUGHT ON-LINE.
;
;-

DUONL:	MOV	#P.LENG,R0	;SET-UP COM      MAND PACKET LENGTH
	MOV	#1,R1		;SET-UP VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELD
	CALL	GTPKT		;GET THE CURRENT COMMAND PACKET
	BCS	DUONL		;IF CS TRY AGAIN
	MOV	R5,P.CRF(R1)	;SET HI ORDER REF NUMBER TO UCB ADDRESS
	MOV	R3,P.CRF+2(R1)	;SET LO ORDER REF NUMBER TO CONTROLLER
				;STATE TABLE
	MOVB	U.UNIT(R5),P.UNIT(R1)  ;SET UNIT NUMBER
	MOV	#0,P.MOD(R1)	;SET MODIFIERS
	MOVB	#OP.ONL,P.OPCD(R1)  ;ASSUME "ONLINE" OP CODE
	CALLR	DUCMD3		;ISSUE I/O

;+
; **- STCCR - SET UDA50 CONTROLLER'S CHARACTERISTICS      
;
; THE STCCR ROUTINE WILL REQUEST A COMMAND PACKET, FILL IT IN WITH THE 
; REQUIRED MSCP ITEMS, AND REQUEST THE PACKET TO BE ISSUED AS I/O.
; THE ENTIRE PROCEDURE IS REQUIRED TO SET THE UDA50 CONTROLLER'S CHARACTER-
; ISTICS ANY TIME THE CONTROLLER IS INITIALIZED.
;
; INPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE       POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;	R2 IS DESTROYED
;
;-

STCCR:	MOV	P.STS(R1),R2	;GET STATUS/EVENT CODE
	BIC	#^C<ST.MSK>,R2	;CLR ALL BUT STATUS/EVENT ...
				;... IS IT SUCCESS?
	SEC			;ASSUME FAILURE
	BNE	40$		;IF NE NO
	BISB	#C1.ON,C.STAT(R3)  ;SET CONTROLLER ON-LINE FLAG
	BIC	#^C<C1.ON!C1.CLK>,C.STAT(R3)  ;CLR ALL OTHER FLAGS
	MOV	R1,-(SP)	;YES, SAVE POINTER TO MSCP PACKET
	MOV	R3,R0		;COPY CONTROLLER STATE TABLE POINTER
	ADD	#P.VRSN,R1	;POINT TO CONTROLLER CHARACTERISTICS      
	ADD	#C.VRSN,R0	;AND WHERE TO PUT THEM
	MOV	#<P.CNTI+8.-P.BCNT>/2,R2  ;AND HOW MANY
	CALL	REGPAS		;MOVE VALUES FROM MSCP PACKET TO CONTROLLER
				;STATE TABLE
	MOV	(SP)+,R1	;RESTORE R1
	MOVB	C.CMDS(R3),C.ILCC(R3)  ;DEFINE MAXIMUM VALUE FOR LOOP COUNT CONTROL


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?
	BNE	30$		;IF NE YES
	TST	S.UMHD(R4)	;HAVE WE ALLOCATED THE UMR WAIT BLOCK(S)?
	BNE	30$		;IF NE YES
	MOV	R1,-(SP)	;SAVE R1
	MOV	C.CMDS(R3),R0	;GET CONTROLLER'S COMMAN      D LIMIT
	CLR	-(SP)		;GET A WORKING REGISTER
	MOVB	C.CMD(R3),(SP)	;GET COMMAND RING BUFFER SIZE
	ASL	(SP)		;DOUBLE IT
	CMPB	(SP)+,R0	;IS COMMAND LIMIT TWICE COMMAND RING BUFFER SIZE?
;	BR	10$		;ALWAYS BRANCH FOR NOW
	BHIS	10$		;IF HIS NO
	CLR	R0		;SET UP FOR "BISB"
	BISB	C.CMD(R3),R0	;YES, USE COMMAND RING BUFFER SIZE ...
	ASL	R0		;... AND DOUBLE IT
10$:	MOV	R0,C.CMDS(R3)	;SET CONTROLLER'S COMMAND LIMIT ...
	MOV	R0,S.UMCT(R4)	;... AND THE NUMBER OF UMR WAITING BLOCK(S)
	MOV	#20.,R1		;NUMBER OF BY      TES REQUIRED FOR A UMR ASSIGNMENT 
				;BLOCK
	CALL	$MUL		;MULTIPLY THEM
	CALL	$ALOCB		;ALLOCATE A CORE BLOCK FOR UMR ASSIGNMENTS
	MOV	R0,S.UMHD(R4)	;SAVE THE POINTER TO CORE BLOCK ...
	MOV	R1,S.UMHD+2(R4)	;... AND ITS LENGTH
	ADD	R0,S.UMHD+2(R4)	;MAKE IT AN ADDRESS
	ASR	R1		;MAKE IN A WORD COUNT
20$:	CLR	(R0)+		;CLR UMR WAIT BLOCK WORDS
	SOB	R1,20$		;LOOP UNTIL DONE
	MOV	(SP)+,R1	;RESTORE R1
30$:				;REF LABEL

	.ENDC	;M$$EXT


40$:	RETURN			;EXIT

;+
; **- GTUST - GET DRIVE'S UNIT STATU      S
;
; THIS ROUTINE WILL GET THE DRIVE'S UNIT STATUS AFTER IT HAS 
; BEEN BROUGHT ONLINE.  
;
; INPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;	R2 IS DESTROYED
;
;-

GTUST:	MOV	P.STS(R1),R2	;GET STATUS/EVENT CODE
	BIC	#^C<ST.MSK>,R2	;CLR ALL BUT STATUS/EVENT COD      E ...
				;... IS IT SUCCESS?
	BEQ	10$		;IF EQ YES
	CMP	#ST.OFL,R2	;THEN IS IT OFF-LINE?
	BNE	10$		;IF NE NO
	BISB	#US.OFL,U.ST2(R5)  ;YES, MARK UNIT AS BEING OFF-LINE
	BICB	#US.SPU!US.VV,U.STS(R5)  ;AND CLR SPIN-UP AND VOLUME VALID FLAGS
	BR	20$		;AND EXIT
10$:	MOV	R1,-(SP)	;SAVE CURRENT MSCP PACKET POINTER
	MOV	R5,R0		;COPY POINTER TO UCB
	ADD	#P.MLUN,R1	;POINT TO UNIT CHARACTERISTICS
	ADD	#U.MLUN,R0	;AND WHERE TO PUT THEM
	MOV	#<P.END-P.MLUN>/2,R2  ;AND HOW MANY
	CALL	REGPAS		;MOVE VALUES FR      OM MSCP PACKET TO UCB
	MOV	(SP)+,R1	;RESTORE R1
20$:	CLR	C.IOSB+2(R3)	;ZERO 2ND STATUS WORD OF CURRENT RESPONSE BLOCK
	RETURN			;AND RETURN

;+
; **- ONLINE - DRIVE ONLINE ROUTINE
;
; THIS ROUTINE IS USED TO PUT A DRIVE ON-LINE FROM THE AVAILABLE STATE.
;
; INPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
      ;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;	R2 IS DESTROYED
;
;-

ONLINE:	MOV	P.STS(R1),R2	;GET STATUS/EVENT CODE
	BIC	#^C<ST.MSK>,R2	;CLR ALL BUT STATUS/EVENT CODE ...
				;... IS IT SUCCESS?
	BNE	10$		;IF NE NO
	MOV	R1,-(SP)	;YES, SAVE CURRENT MSCP PACKET POINTER
	MOV	R5,R0		;COPY POINTER TO UCB
	ADD	#P.UNSZ,R1	;POINT TO UNIT COMMAND LIMIT
	ADD	#U.UNSZ,R0	;AND WHERE TO PUT THEM
	MOV	#<P.END-P.UNSZ>/2,R2  ;AND HOW MANY
	CALL	REGPAS		;MOVE VALUES FROM MSCP PACKET TO UCB
	MOV	(SP)+,R1	;... AND       R1
	MOV	U.UNSZ(R5),U.CW3(R5)  ;SET UP THE MAX LBN ...
	MOVB	U.UNSZ+2(R5),U.CW2(R5)  ;... FOR PROPER OPERATION
	BICB	#US.SPU,U.STS(R5)  ;CLR UNIT SPINNING UP BIT
	BICB	#US.OFL,U.ST2(R5)  ;CLR OFF-LINE BIT 
	RETURN			;
10$:	BISB	#US.OFL,U.ST2(R5)  ;MARK UNIT AS BEING OFF-LINE
	BICB	#US.SPU!US.VV,U.STS(R5)  ;AND CLR SPIN-UP AND VOLUME VALID FLAGS
	RETURN			;

;+
; **- GTCST - GET DRIVE'S COMMAND STATUS
;
; THIS ROUTINE WILL GET THE DRIVE'S COMMAND STATUS AFTER IT HAS 
; BEEN TIMED OUT.
;
; INP      UTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;	R2 IS DESTROYED
;
;-


	.IF DF	E$$DVC

GTCST:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	U.CMST+2(R5),P.CMST+6(R1)  ;STORE PREVIOUS COMMAND'S STA      TUS ...
	MOV	U.CMST(R5),P.CMST+4(R1)  ;... AS A DOUBLE PRECISION VALUE
	ADD	#4,MSGLNG(R1)	;CORRECT PACKET LENGTH FOR EXTRA INFO FOR ERROR LOG
	CALL	DULERR		;LOG UNIT'S COMMAND STATUS
	MOV	P.STS(R1),R2	;GET STATUS/EVENT CODE
	BIC	#^C<ST.MSK>,R2	;CLR ALL BUT STATUS/EVENT CODE ...
				;... IS IT SUCCESS?
	BNE	30$		;IF NE NO
	CMP	U.LHD(R5),P.OTRF(R1)  ;IS THIS PACKET FOR CURRENT OLDEST ...
				;... OUTSTANDING COMMAND
	BNE	20$		;IF NE NO
	TST	P.CMST(R1)	;IS THE COMMAND DONE?
	BNE	10$		;IF NE NO
	TS      T	P.CMST+2(R1)	;MAYBE?
	BEQ	20$		;IF EQ YES
10$:				;REF LABEL


	.IF DF	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	CMP	U.CMST+2(R5),P.CMST+2(R1)  ;IS PROGRESS BEING MADE?
	BHI	20$		;IF HI YES
	CMP	U.CMST(R5),P.CMST(R1)  ;MAYBE?
	BLOS	30$		;IF LOS NO	
20$:				;REF LABEL

;
; SAVE THIS COMMAND'S STATUS FOR NEXT TIME WE TIME THIS COMMAND OUT OR 
; WE HAVE JUST RECEIVED A COMMAND'S STATUS FOR AN I/O REQUEST WHICH 
; MAY HAVE ALREADY COMPLETED.
;


      
	.IF DF	DEBUG

21$:	BPT			;GET TO XDT
	MOV	#NOP,21$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	P.CMST(R1),U.CMST(R5)  ;SAVE THIS COMMAND'S STATUS ...
	MOV	P.CMST+2(R1),U.CMST+2(R5)  ;... AS A DOUBLE PRECISION VALUE
	CLR	U.OTRF(R5)	;ZERO OLDEST OUTSTANDING I/O REQUEST
	RETURN			;AND EXIT
30$:				;REF LABEL


	.IF DF	DEBUG

31$:	BPT			;GET TO XDT
	MOV	#NOP,31$	;NOP THE BRK PNT

	.ENDC	;DEBUG


;
; NO PROGRESS IS BEING MADE ON THE OUTSTANDING I/O REQUEST WE 
; JUST ISSUED A "GET COMMAND S      TATUS" FOR OR THE CONTROLLER RETURNED
; SOME KIND OF ERROR.  THIS SITUATION IMPLIES THAT THE CONTROLLER HAS 
; GONE INSANE OR IS IRREVOCABLY DEADLOCKED.  LOOKS AS THOUGH WE SHOULD 
; RE-INITIALIZE THE CONTROLLER, IF POSSIBLE.
;

	CALLR	REINIT		;RE-INITIALIZE THE CONTROLLER

	.ENDC	;E$$DVC


;+
; **- DUATN - UDA50 UNIT ATTENTION ROUTINE
;
; THE UNIT ATTENTION ROUTINE WILL OBTAIN THE SPECIFIED
; DEVICE'S CHARACTERISTICS.
;
; INPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = C      ONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE ATTENTION SPECIFIED UNIT'S UCB IS DETERMINED
;
;-

DUATN:					;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	CMPB	#OP.AVA,P.OPCD(R1)  ;IS THIS RESPONSE AN AVAILABLE ATTENTION?
	BNE	30$		;IF NE NO
	MOV	#SCUCB,-(SP)	;YES, PUSH "SCAN UCB'S" ROUTINE ON THE STACK
10$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	20$		;IF CS, NO MORE UCB'S
	CMPB	P.UNIT(R1      ),U.UNIT(R5)  ;IS THIS ATTENTION MESSAGE FOR THIS UCB
	BNE	10$		;IF NE NO
	BICB	#US.OFL,U.ST2(R5)  ;YES, CLR ANY OFF-LINE CONDITION
	BICB	#US.VV,U.STS(R5)  ;CLR ANY VOLUME VALID CONDITIONS
	BISB	#US.SPU,U.STS(R5)  ;MARK THE UNIT AS SPINNING UP
	ADD	#10,SP		;FLUSH THE STACK
20$:	RETURN			;EXIT
30$:	CLC			;FORCE CARRY CLR
	RETURN			;

;+
; **- DUCERR - UDA50 CONTROLLER ERROR LOGGING ROUTINE
;
; THE CONTROLLER ERROR LOGGING ROUTINE WILL CAUSE THE CREATION OF AN ERROR 
; LOG PACKET, COPY THE VALUE      S OF THE TWO I/O PAGE REGISTERS INTO THE ERROR 
; LOG PACKET AND REQUEST THE ERROR LOGGING SUB-SYSTEM TO CAPTURE THE DATA.
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE ERROR (OR TIME OUT) FROM THE SPECIFIED CONTROLLER IS LOGGED
;
;-


	.IF DF	E$$DVC

	.ENABL	LSB

DUCERR:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	R0,-(SP)	;SAVE R0
	MOV	R1,-(SP)	;SAV      E R1
	MOV	R2,-(SP)	;SAVE R2
	MOV	R3,-(SP)	;SAVE R3
	MOV	R4,-(SP)	;SAVE R4
	CLRB	C.STAT+1(R3)	;RESET INITIALIZATION IN PROGRESS FLAGS
	MOV	S.CSR(R4),R2	;RETRIEVE CSR ADDRESS
;
; SETUP CONTROLLER ERROR LOG PACKET
;
	MOV	#4,C.MLNG(R3)	;SET PACKET LENGTH
	MOVB	#-2,C.VCID(R3)	;SET VIRTUAL CIRCUIT ID
	MOVB	#20,C.CRED(R3)	;SET CREDIT FIELD TO DATAGRAM
	MOV	UDAIP(R2),C.IP(R3)  ;SAVE UDAIP REGISTER
	MOV	UDASA(R2),C.SA(R3)  ;SAVE UDASA REGISTER
	MOV	#C.IP,R1	;ADJUST R1 TO ...
	ADD	R3,R1		;... POINT TO       CONTROLLER ERROR LOG PACKET
	BR	30$		;AND CONTINUE TO LOG PACKET

;+
; **- DULERR - UDA50 UNIT ERROR LOGGING ROUTINE
;
; THE UNIT ERROR LOGGING ROUTINE WILL CAUSE THE CREATION OF AN ERROR LOG
; PACKET, COPY THE CONTENTS OF THE MSCP ERROR LOG PACKET INTO THE ERROR 
; LOG PACKET AND REQUEST THE ERROR LOGGING SUB-SYSTEM TO CAPTURE THE DATA.
;
; INPUTS:
;
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;      	THE ERROR ON THE SPECIFIED UNIT IS LOGGED.
;
;-

DULERR:				;REF LABEL


	.IF DF	DEBUG

11$:	BPT			;GET TO XDT
	MOV	#NOP,11$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	R0,-(SP)	;SAVE R0
	MOV	R1,-(SP)	;SAVE R1
	MOV	R2,-(SP)	;SAVE R2
	MOV	R3,-(SP)	;SAVE R3
	MOV	R4,-(SP)	;SAVE R4
	MOV	#SCUCB,-(SP)	;YES, PUSH "SCAN UCB'S" ROUTINE ON THE STACK
20$:	CALL	@(SP)+		;CALL THE CO-ROUTINE
	BCS	80$		;IF CS, NO MORE UCB'S
	CMPB	P.UNIT(R1),U.UNIT(R5)  ;IS THIS ERROR LOG PACKET FOR THIS UCB
	BNE	20$		;      IF NE NO
	ADD	#10,SP		;YES, FLUSH THE STACK
30$:	CLRB	S.ROFF(R4)	;ZERO OFFSET TO FIRST REGISTER OF ERROR LOG PACKET
	MOV	#MSGLNG,R2	;GET OFFSET TO BEGINNING OF ENVELOPE
	ADD	R1,R2		;ADD BASE ADDRESS OF RESPONSE PACKET
	MOV	(R2),-(SP)	;GET MESSAGE LENGTH
	ADD	#ENVLP,(SP)	;ADD EXTRA FOR THE ENVELOPE
	CMP	#64.,(SP)	;DID WE OVERFLOW MAXIMUM PACKET SIZE?
	BHIS	40$		;IF HIS NO


	.IF DF	DEBUG

	CRASH			;YES, CRASH
				;PACKET GREATER THAN MAXIMUM SIZE

	.IFF	;DEBUG

	TST	(SP)+		;YES, FLUSH STACK      
				;PACKET GREATER THAN MAXIMUM SIZE
	BR	80$		;AND EXIT

	.ENDC	;DEBUG


40$:	MOV	(SP),R2		;COPY NUMBER OF BYTES TO R2
	ASR	(SP)		;MAKE IT REGISTERS (WORDS)
	MOVB	(SP)+,S.RCNT(R4)  ;SET NUMBER OF REGISTERS TO COPY FOR ERROR LOG
	CLR	S.PKT(R4)	;ASSUME NO I/O PACKET ACTIVE
	CMP	P.CRF+2(R1),R3	;INTERNAL I/O FUNCTION?
	BEQ	50$		;IF EQ YES
	MOV	P.CRF+2(R1),S.PKT(R4)  ;NO, COPY I/O PACKET ADDRESS FOR ERROR LOGGER
				;IS I/O ACTIVE?
	BNE	60$		;IF NE YES
50$:	CLR	R4		;NO, CLR R4
60$:	MOV	R1,-(SP      )	;SAVE R1 AGAIN
	MOV	R2,R1		;COPY NUMBER OF BYTES INTO R1

;
; INTERFACE TO $LOGER:
;
; INPUTS:
;
;	R1 = LENGTH OF DATA TO BE LOGGED, IN BYTES
;	R4 = SCB ADDRESS (ZERO IF NO I/O PACKET)
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	C = 1 UNABLE TO LOG ERROR
;
;	C = 0 ABLE TO LOG ERROR
;
;		R1 = ADDRESS OF DATA AREA IN ERROR LOG PACKET
;		R3 = ADDRESS OF ERROR LOG PACKET
;
;	NOTE:
;
;	R4 AND R5 ARE PRESERVED
;	R0, R2, AND R3 MAY BE DESTROYED
;

	CALL	$LOGER		;ATTEMPT TO LOG ERROR PACKET
	M      OV	R1,R0		;COPY R1 INTO R0 FOR DESTINATION
	MOV	(SP)+,R1	;RESTORE POINTER TO MSCP PACKET FOR SOURCE
	BCS	80$		;IF CS, UNABLE TO LOG ERROR PACKET
	ADD	#MSGLNG,R1	;OFFSET TO BEGINNING OF ENVELOPE
	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS
	CLR	R2		;SETUP FOR "BISB"
	BISB	S.RCNT(R4),R2	;SET NUMBER OF REGISTERS (WORDS) TO COPY
	CALL	REGPAS		;COPY MSCP PACKET INTO ERROR LOG PACKET
	MOV	#IS.SUC&377,R0	;ASSUME A SUCCESSFUL STATUS WORD
	CLR	R2		;AND ZERO RETRY COUNTS
	TST	S.PKT(R4)	;IS I/O ACITVE?
	BNE	70$		      ;IF NE YES
	CLR	R4		;NO, CLR R4

;
;
; INTERFACE TO $FNERL:
;
; INPUTS:
;
;	R0 = FIRST I/O STATUS WORD
;	R2 = STARTING AND FINAL ERROR RETRY COUNTS
;	R3 = ADDRESS OF ERROR LOG PACKET
;	R4 = SCB ADDRESS (ZERO IF NO I/O PACKET)
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE SPECIFIED ERROR LOG PACKET IS LOGGED
;
;	NOTE:
;
;	R4 AND R5 ARE PRESERVED
;	R1, R2, AND R3 MAY BE DESTROYED
;

70$:	CALL	$FNERL		;FINISH LOGGING THIS ERROR LOG PACKET
80$:	MOV	(SP)+,R4	;RESTORE R4
	MOV	(SP)+,R3	;RESTOR      E R3
	MOV	(SP)+,R2	;RESTORE R2
	MOV	(SP)+,R1	;RESTORE R1
	MOV	(SP)+,R0	;RESTORE R0
	RETURN			;EXIT

	.DSABL	LSB

	.ENDC	;E$$DVC


;+
; **- DUDPKT - UDA50 UNIT DIAGNOSTIC PACKET PROCESSING ROUTINE
;
; THE UNIT DIAGNOSTIC PACKET PROCESSING ROUTINE WILL DO WHAT IS 
;
; INPUTS:
;
;	R0 = ADDRESS OF CURRENT RESPONSE RING POINTER
;	R1 = ADDRESS OF CURRENT RESPONSE RING PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	THE SPECIFIED UNIT IS       FIRST BROUGHT ON-LINE.
;
;-


	.IF DF	D$$IAG

DUDPKT:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT
	CRASH			;WHAT ARE WE DOING HERE?

	.ENDC	;DEBUG


	RETURN			;SHORT CIRCUIT

	.ENDC	;D$$IAG


;+
; **- DURSN - UDA50 VOLUME SERIAL NUMBER ROUTINE
;
; THIS ROUTINE COPIES THE UDA50 VOLUME SERIAL NUMBER INTO A BUFFER 
; SPECIFIED BY THE USER.
;
; INPUTS:
;
;	R1 = I/O PACKET ADDRESS
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;	
; OUTPUTS:
;
      ;	VOLUME SERIAL NUMBER IS COPIED INTO USER'S BUFFER
;
;-

DURSN:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	MOV	R1,R3		;COPY I/O PACKET ADDRESS INTO R3
	MOV	I.PRM+2(R3),R1	;SET UP LO 16-BITS FOR RELOCATION


	.IF DF	M$$MGE


	.IF DF	M$$EXT

	MOVB	I.PRM+1(R3),R0	;SET UP HI 6-BITS FOR RELOCATION

	.IFF	;M$$EXT

	MOVB	I.PRM(R3),R0	;SET UP HI 2-BITS FOR RELOCATION
	ASR	R0		;ADJUST HI 2-BITS
	ASR	R0		;...
	ASR	R0		;...
	AS      R	R0		;...

	.ENDC	;M$$EXT


	.IFF	;M$$MGE

	CLR	R0		;

	.IFT	;M$$MGE


	.IF DF	M$$EIS

	ASHC	#10.,R0		;CALCULATE DISPLACEMENT AND BIAS
	ASHC	#-10.,R1	;...

	.IFF	;M$$EIS

	MOV	#10.,-(SP)	;SET COUNT FOR 10 SHIFTS
10$:	DEC	(SP)		;ANY MORE SHIFTS TO PERFORM
	BLT	20$		;IF LT NO
	ASL	R1		;DOUBLE LEFT SHIFT R1 ...
	ROL	R0		;... INTO R0
	BR	10$		;
20$:	SWAB	R1		;SWAP BYTES
	ASR	R1		;SHIFT RIGHT R1
	ASR	R1		;...
	TST	(SP)+		;CLR THE STACK

	.ENDC	;M$$EIS


	MOV	@#KISAR6,-(SP)	;SAVE       APR 6
	MOV	R0,@#KISAR6	;SET RELOCATION BIAS
	ADD	#140000,R1	;SET DISPLACEMENT

	.IFTF	;M$$MGE

	MOV	U.VSER(R5),(R1)+  ;COPY LO ORDER VOLUME SERIAL NUMBER
	MOV	U.VSER+2(R5),(R1)  ;COPY HI ORDER VOLUME SERIAL NUMBER

	.IFT	;M$$MGE

	MOV	(SP)+,@#KISAR6	;RESTORE APR 6

	.ENDC	;M$$MGE


	MOV	#IS.SUC&377,R0	;SET SUCCESS
	MOV	#4,R1		;SET BYTES TRANSFERRED
	CLR	R2		;
	RETURN			;EXIT

;+
; **- DUMAP - MAP UNIBUS TO EXTENDED MEMORY ROUTINE
;
; THE DUMAP ROUTINE WILL TAKE THE ADDRESS CONTAINED       IN THE I/O
; PACKET TO BE INSERTED INTO THE UCB LOCATIONS REQUIRED TO SET
; UP THE UMR AND ALLOCATE AN UMR MAPPING ASSIGNMENT BLOCK FROM
; A POOL OF UMR ASSIGNMENT BLOCKS WHICH THE DRIVER OBTAINED WHEN
; IT SET THE CONTROLLER ON-LINE.
;
; INPUTS:
;
;	R1 = I/O PACKET ADDRESS
;	R2 = PHYSICAL UNIT NUMBER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = UMR MAPPING BLOCK POINTER
;	R2 = I/O PACKET ADDRESS
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-


	.IF DF	M$$EXT

DUMAP:	MOV      	S.PKT(R4),R2	;RETRIEVE I/O PACKET ADDRESS
	MOV	S.UMHD(R4),R0	;RETRIEVE POINTER TO UMR WAIT BLOCK(S)
	DEC	S.UMCT(R4)	;DEC COUNT OF UMR WAIT BLOCKS
	CLR	R1		;INITIALIZE UMR WAIT BLOCK INDEX
10$:	TST	10(R0)		;IS THIS BLOCK FREE?
	BEQ	30$		;IF EQ MAYBE
20$:				;REF LABEL


	.IF DF	DEBUG

21$:	BPT			;GET TO XDT
	MOV	#NOP,21$	;NOP THE BRK PNT

	.ENDC	;DEBUG


	ADD	#20.,R0		;NO, MOVE TO NEXT ONE


	.IF DF	DEBUG

	CMP	S.UMHD+2(R4),R0  ;AT THE END OF UMR WAIT BLOCK(S)
	BHI	25$		;IF HI NO
	CR      ASH			;YES, SOMETHING'S WRONG
25$:				;REF LABEL

	.ENDC	;DEBUG


	INC	R1		;INC INDEX TO THE NEXT ONE ...
	BR	10$		;... AND GO AGAIN
30$:	TST	M.UMRA+10(R0)	;IS IT REALLY FREE?
	BNE	20$		;IF NE NO
	MOV	I.PRM(R2),U.BUF(R5)  ;SET UP FOR UMR ASSIGNMENT BLOCK PROCESSING ...
	MOV	I.PRM+2(R2),U.BUF+2(R5)  ;... BUFFER ADDRESS ...
	MOV	I.PRM+4(R2),U.CNT(R5)  ;... AND BYTE COUNT
	MOVB	R1,I.PRM(R2)	;YES, SAVE UMR WAIT BLOCK INDEX IN I/O PACKET
	MOV	R0,R1		;... AND COPY UMR WAIT BLOCK POINTER TO R1
	RETU      RN			;

;+
; **- DUUNMP - UNMAP UNIBUS TO EXTENDED MEMORY ROUTINE
;
; THE DUUNMP ROUTINE WILL FIND THE UMR MAPPING ASSIGNMENT BLOCK
; TO ALLOW THE UMR'S USED TO BE DE-ALLOCATED
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R2 = POINTER TO UMR MAPPING AREA
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-

DUUNMP:	MOV	S.UMHD(R4),R2	;COPY POINTER TO HEAD OF UMR WAIT BLOCK(S)
	MOV	S.PKT(R4),R1	;R      ETRIEVE POINTER TO I/O PACKET
	MOVB	I.PRM(R1),R1	;RETRIEVE INDEX OF UMR WAIT BLOCK
	MOV	#20.,R0		;NUMBER OF BYTES / UMR WAIT BLOCK
	CALL	$MUL		;OFFSET INTO UMR WAIT BLOCK(S)
	ADD	R1,R2		;ADD OFFSET INTO UMR WAIT BLOCK(S)
	ADD	#10,R2		;ADD OFFSET TO MAPPING INFO IN UMR WAITING BLOCK(S)
	RETURN			;

	.ENDC	;M$$EXT


;+
; **- MKPKT - MAKE PACKET ROUTINE
;
; THE MKPKT ROUTINE IS CALLED TO FILL IN AN MSCP PACKET.  
;
; INPUTS:
;
;	R2 = I/O PACKET
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = S      CB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R1 = POINTER TO CURRENT COMMAND RING BUFFER PACKET
;
;	AN MSCP PACKET IS REQUESTED AND THE APPROPRIATE VALUES
;	FROM THE I/O PACKET ARE FILLED IN.
;
;	R2 IS DESTROYED
;
;-

MKPKT:				;REF LABEL


	.IF DF	DEBUG

	MOV	#2,120$		;INITIALIZE TIMEOUT LOOP

	.ENDC	;DEBUG


10$:	MOV	#P.LENG,R0	;SET-UP COMMAND PACKET LENGTH
	MOV	#1,R1		;SET-UP VIRTUAL CIRCUIT AND CREDIT/DEBIT FIELD
	CALL	GTPKT		;GET AN MSCP PACKET
	BCC	20$		;IF CC -- ALL'S OK      


	.IF DF	DEBUG

	DEC	120$		;TIMEOUT?
	BNE	10$		;IF NE NO
19$:	CRASH			;SOMETHING'S WRONG

	.ENDC	;DEBUG


	BR	MKPKT		;GO AGAIN
20$:	MOV	R5,P.CRF(R1)	;SET HI ORDER REF NUMBER TO UCB ADDRESS
	MOV	R2,P.CRF+2(R1)	;SET LO ORDER REF NUMBER TO I/O PACKET
	MOVB	U.UNIT(R5),P.UNIT(R1)  ;SET UNIT NUMBER
	CMPB	#IO.RLB/256.,I.FCN+1(R2)  ;DATA TRANSFER FUNCTION?
	BHIS	50$		;IF HIS YES
	CMPB	#IO.RPL,I.FCN(R2)  ;REPLACE FUNCTION?
	BNE	30$		;IF NE NO
	MOV	#OP.RPL,P.OPCD(R1)  ;SET REPLACE OP-CODE
	MOV	I      .PRM(R2),P.RBN+2(R1)  ;SET UP HI ORDER RBN
	MOV	I.PRM+2(R2),P.RBN(R1)  ;SET UP LO ORDER RBN
	MOV	I.PRM+4(R2),P.LBN+2(R1)  ;SET UP HI ORDER LBN
	MOV	I.PRM+6(R2),P.LBN(R1)  ;SET UP LO ORDER LBN
	MOV	I.PRM+10(R2),P.MOD(R1)  ;SET PRIMARY REPLACEMENT MODIFIER
	RETURN			;AND EXIT
30$:				;REF LABEL


	.IF DF	DEBUG

	CMPB	#IO.SEC,I.FCN(R2)  ;SENSE CHARACTERISTIC?
	BEQ	40$		;IF EQ YES
	CMPB	#IO.TRM,I.FCN(R2)  ;TERMINATE FUNCTION?
	BEQ	19$		;IF EQ YES, WHAT ARE WE DOING HERE?
	CMPB	#IO.INL,I.FCN(R2)        ;INITIALIZE FUNCTION?
	BNE	19$		;IF NE NO, THEN WHAT ARE WE DOING HERE?

	.ENDC	;DEBUG


40$:	MOV	#OP.GUS,P.OPCD(R1)  ;SET GET UNIT STATUS OP-CODE
	MOV	#0,P.MOD(R1)	;SET OP-CODE MODIFIERS
	RETURN			;AND EXIT
50$:	MOVB	#OP.RD,P.OPCD(R1)  ;ASSUME READ OP-CODE
	CMPB	#IO.RLB/256.,I.FCN+1(R2)  ;IS FUNCTION CODE A READ?
	BEQ	60$		;IF EQ YES
	MOVB	#OP.WR,P.OPCD(R1)  ;NO, SET WRITE OP-CODE


	.IF DF	D$$WCK

	BITB	#US.WCK,U.STS(R5)  ;WRITE CHECK REQUIRED?
	BEQ	60$		;IF EQ NO
	BIS	#MD.CMP,P.MOD(R1)        ;YES, SET COMPARE MODIFIER

	.ENDC	;D$$WCK


60$:	MOVB	I.FCN(R2),-(SP)	;ANY SUB-FUNCTION BITS SET?
	BEQ	100$		;IF EQ NO
	BITB	#IQ.Q,(SP)	;EXPRESS REQUEST?
	BEQ	70$		;IF EQ NO
	BIS	#MD.EXP,P.MOD(R1)  ;YES, SET EXPRESS MODIFIER
70$:	BICB	#7,(SP)		;CLR ANY GENERAL MODIFIERS
	CMPB	#IO.RLC&IO.WLC,(SP)  ;WRITE/READ CHECK FUNCTION?
	BEQ	80$		;IF EQ YES
	CMPB	#IO.RPB&IO.WPB,(SP)  ;SPECIAL WRITE/READ CHECK FUNCTION?
	BNE	90$		;IF NE NO
80$:	BIS	#MD.CMP,P.MOD(R1)  ;YES, SET COMPARE MODIFIER
90$:	CMP      B	#IO.WDD,(SP)	;SPECIAL WRITE W/FORCED ERROR FUNCTION?
	BNE	100$		;IF NE NO
	BIS	#MD.ERR,P.MOD(R1)  ;YES, SET FORCE ERROR MODIFIER
100$:	TST	(SP)+		;CLN THE STACK
	MOVB	I.PRM+10(R2),P.LBN+2(R1)  ;SET HI ORDER LBN
	MOV	I.PRM+12(R2),P.LBN(R1)  ;SET LO ORDER LBN
	MOV	I.PRM+4(R2),P.BCNT(R1)  ;SET BYTE COUNT
	MOV	I.PRM+2(R2),P.BUFF(R1)  ;SET LO 16 BITS OF ADDRESS
	MOV	R2,S.PKT(R4)	;SAVE I/O PACKET ADDRESS IN SCB


	.IF DF	 M$$EXT

	MOVB	I.PRM+1(R2),P.BUFF+2(R1)  ;SET HI 6 BITS OF ADDRESS
	BIT	#DV.E      XT,U.CW1(R5)  ;EXTENDED MEMORY SUPPORTED?
	BNE	110$		;IF NE YES
	MOV	R1,-(SP)	;SAVE R1
	CALL	DUUNMP		;LOCATE UMR WAIT BLOCK
	MOV	(SP)+,R1	;RETRIEVE POINTER TO CURRENT MSCP COMMAND PACKET
	MOV	M.UMVL(R2),P.BUFF(R1)  ;SET LO 16 BITS OF VIRTUAL ADDRESS
	MOVB	M.UMVH(R2),P.BUFF+2(R1)  ;SET HI 2 BITS OF VIRTUAL ADDRESS
	ASR	P.BUFF+2(R1)	;ADJUST HI 2 BITS OF ADDRESS
	ASR	P.BUFF+2(R1)	;...
	ASR	P.BUFF+2(R1)	;...
	ASR	P.BUFF+2(R1)	;...
	BIC	#^C<3>,P.BUFF+2(R1)  ;CLEAR ALL BUT LO ORDER TWO BITS

	.IFF	;M      $$EXT

	MOVB	I.PRM(R2),P.BUFF+2(R1)  ;SET HI 2 BITS OF ADDRESS
	ASR	P.BUFF+2(R1)	;ADJUST HI 2 BITS OF ADDRESS
	ASR	P.BUFF+2(R1)	;...
	ASR	P.BUFF+2(R1)	;...
	ASR	P.BUFF+2(R1)	;...
	BIC	#^C<3>,P.BUFF+2(R1)  ;CLEAR ALL BUT LO ORDER TWO BITS

	.ENDC	;M$$EXT


110$:	RETURN			;RETURN


	.IF DF	DEBUG

120$:	.WORD	0		;TIMEOUT LOOP COUNT

	.ENDC	;DEBUG


;+
; ** - SCUCB - SCAN UCB'S ASSOCIATED WITH SPECIFIED CONTROLLER (SCB ADDRESS)
;
;
; INPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;      	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;
;	R3 = CONTROLLER STATE TABLE POINTER
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
;-

SCUCB:	MOV	(SP)+,R2	;RETRIEVE RETURN ADDRESS
	MOV	R5,-(SP)	;SAVE R5
	MOV	R3,-(SP)	;SAVE R3
	MOV	#DUDCB,R3	;GET ADDRESS OF DU:'S FIRST DCB
10$:	MOV	(R3),R3		;GET ADDRESS OF NEXT DCB, IS IT THE LAST
	BEQ	40$		;IF EQ YES
	MOV	D.UCB(R3),R5	;GET ADDRESS OF FIRST UCB 
	BIT	#DV.PSE,U.CW1(R5)  ;IS IT A PSUEDO DEVICE?
	BNE	40$		;IF NE YES
	CMP	#"DU,D.NAM(R3)	;IS IT       A DCB FOR "DU"?
	BNE	10$		;IF NE NO
	MOV	R3,DUDCB2	;YES, SAVE THIS DU: DCB ADDRESS
	MOVB	D.UNIT+1(R3),-(SP)  ;GET HIGHEST UNIT NUMBER
	SUB	D.UNIT(R3),(SP)	 ;SUBTRACT OFF LOWEST
	INCB	(SP)		;BUT ACCOUNT FOR IT
20$:	CMP	U.SCB(R5),R4	;IS THIS UCB FOR THIS CONTROLLER
	BNE	30$		;IF NE NO
	MOV	2(SP),R3	;RETRIEVE CALLER'S R3
	MOV	R2,-(SP)	;PUT RETURN ADDRESS BACK ON STACK
	CLC			;CLR CARRY TO SHOW WE FOUND ONE
	CALL	@(SP)+		;CALL THE CALLER BACK
	MOV	(SP)+,R2	;RETRIEVE THE RETURN ADDRESS
	MOV	DUDCB2,      R3	;GET POINTER TO CURRENT DU:'S DCB
30$:	ADD	D.UCBL(R3),R5	;ADD LENGTH OF UCB FOR NEXT
	DECB	(SP)		;IS THIS THE LAST ONE?
	BNE	20$		;IF NE NO
	TST	(SP)+		;YES, CLEAN UP THE STACK
	BR	10$		;TRY THE NEXT DCB
40$:	CLR	DUDCB2		;NO, RESET CURRENT DU:'S DCB ADDRESS
	MOV	(SP)+,R3	;RESTORE ORIGINAL R3
	MOV	(SP)+,R5	;RESTORE ORIGINAL R5
	MOV	R2,-(SP)	;PUT RETURN ADDRESS BACK ON THE STACK
	SEC			;SET CARRY TO SHOW THE END
	RETURN			;

	.PAGE


	.IF DF	DU$BIG

;+
; **- MAPD - MAP DRIVER DATA SPACE       ROUINE
;
; THIS ROUTINE WILL PRESERVE THE PREVIOUS VALUE FOR APR6 AND 
; LOAD APR6 WITH THE VALUE TO MAP THE RINGS AND PACKETS WHEN 
; THE DRIVER IS GREATER THAN 4K WORDS.
;
; INPUTS:
;
;	NONE
;
; OUTPUTS:
;
;	PREVIOUS VALUE OF APR6 IS SAVED AND APR6 IS LOADED 
;	WITH THE VALUE TO MAP THE DRIVER'S RINGS AND PACKETS
;
;-

MAPD:				;REF LABEL


	.IF DF	DEBUG

1$:	BPT			;GET TO XDT
	MOV	#NOP,1$		;NOP THE BRK PNT

	.ENDC	;DEBUG


	CMP	#DUSTRT,#120000	;LOADABLE DRIVER?
	BLO	30$		;IF       LO NO
	MOV	KINAR6,C.SAPR(R3)  ;SAVE PREVIOUS MAPPING OF APR 6
	CMP	#DUEND,#140000	;DRIVER GREATER THAN 4K WORDS
	BLO	20$		;IF LO NO
	MOV	C.PAR6(R6),KINAR6  ;YES, SET APR 6 TO MAP DRIVER'S RINGS AND PACKETS
10$:	CALL	@(SP)+		;CALL CALLER BACK
20$:	MOV	C.SAPR(R3),KINAR6  ;RESTORE KISAR6
30$:	RETURN			;EXIT

	.ENDC	;DU$BIG


	.PAGE

;+
; DU DRIVER CONTROLLER STATE TABLES
;-

DUTBL:	DUTBL$	DU,R$$UDA	;CONTROLLER STATE TABLES
	
;+
; DU DRIVER RING SPACE
;-

DURNG:	DURNG$	DU,R$$UDA,RNGSIZ
   p   
;+
; DU DRIVER PACKET SPACE
;-

DUBUF:	DUPKT$	DU,R$$UDA,RSPLNG,CMDLNG

DUEND:	.BLKW	CMDLNG		;

	.END
p          Ñ€kQ	› c,        	.TITLE	DRATP
	.IDENT	/01.04/

;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.04
;
; D. N. CUTLER 31-AUG-73
;
; MODIFIED BY:
;
;	M. S. HARVEY	2-JAN-80
;		MSH045 -- CREATE THIS MODULE FROM DRRES TO REMOVE
;			  THIS CODE FROM THE DIRECTIVE COMMON
;
;	M. S. HARVEY	5-MAY-81
;		MSH165 -- MODIFY SO THAT THIS DIREC      TIVE CODE MAY BE
;			  PLACED IN THE SECOND EXECUTIVE COMMON
;
;
; THIS MODULE CONTAINS THE ALTER PRIORITY DIRECTIVE PROCESSING CODE.
;
; MACRO LIBRARY CALLS
;
	.MCALL	TCBDF$,PCBDF$,HDRDF$,PKTDF$
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS
	PCBDF$			;DEFINE PARTITION CONTROL BLOCK OFFSETS
	HDRDF$			;DEFINE TASK HEADER OFFSETS
	PKTDF$			;DEFINE I/O PACKET OFFSETS



;+
; **-$DRATP-ALTER TASK PRIORITY
; **-$DRAP1-ALTER TASK PRIORITY FOR DIRECTIVE				;MSH165
; **-$DRAP2-ALTER TASK PRIORITY       FOR TASK				;MSH165
;
; THIS DIRECTIVE INSTRUCTS THE SYSTEM TO CHANGE THE TASK PRIORITY
; OF THE SPECIFIED TASK.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(9.),DPB SIZE(4.)
;	WD. 01 -- FIRST HALF OF TASK NAME.
;	WD. 02 -- SECOND HALF OF TASK NAME.
;	WD. 03 -- NEW PRIORITY.
;
; INPUTS:
;
;	R0=ADDRESS OF THE TCB OF THE TASK TO BE ALTERED.
;	R1=ADDRESS OF THE TASK STATUS WORD OF THE TASK TO BE ALTERED.
;	R2=ADDRESS OF THE TASK STATUS WORD OF THE CURRENT TASK.
;	R3=POINTER TO DESIRED TASK PRIORITY IF EN      TRY AT			;MSH165
;		$DRATP OR $DRAP1.					;MSH165
;	R3=DESIRED TASK PRIORITY IF ENTRY AT $DRAP2.			;MSH165
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.			;**-1
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS: (DIRECTIVE STATUS AND PS RETURNED TO TASK)
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.
;	C=1 IF DIRECTIVE IS REJECTED.
;		DIRECTIVE STATUS OF 'D.RS7' IS RETURNED IF THE
;			TASK IS NOT ACTIVE.
;		DIRECTIVE STATUS OF 'D.RS95' IS RETURNE      D IF THE
;			NEW PRIORITY SPECIFIED IS INVALID.
;									;MSH165
; NOTE: FOR SYSTEMS WITHOUT SUPPORT FOR THIS DIRECTIVE, THE GLOBAL	;MSH165
; ENTRY POINT, $DRATP, IS DEFINED IN THE PROCESSING ROUTINE FOR THE	;MSH165
; DECLARE SIGNIFICANT EVENT DIRECTIVE.					;MSH165
;
;-


	.IF DF	A$$PRI
									;MSH165
	.IF NDF	D$$PAR							;MSH165

$DRATP::			;REF LABEL

	.ENDC								;MSH165
									;MSH165
$DRAP1::MOV	(R3),R3		;GET NEW PRIORITY			;MSH165
$DRAP2::			;REF LABEL				;MSH165

	.IF DF	      M$$MUP

	BIT	#T3.PRV,T.ST3(R5) ;ISSUING TASK PRIVILEGED?
	BNE	35$		;IF NE YES
	CMP	R0,R5		;MODIFYING OWN PRIORITY?
	BNE	180$		;IF NE NO - PRIVILEGE VIOLATION
	CMPB	R3,T.DPRI(R0)	;RAISING ABOVE INSTALLED PRIORITY?	;MSH165
	BHI	180$		;IF HI YES - PRIVILEGE VIOLATION	;**-1
35$:				;REF LABEL

	.ENDC


	MOV	R0,R5		;SAVE TCB ADDR OF TASK TO BE ALTERED
	TST	(R1)		;TASK ACTIVE?
	BMI	175$		;IF MI NO
	TST	R3		;WAS A NEW PRIORITY SPECIFIED?		;MSH165
	BNE	40$		;IF NE ONE WAS SPECIFIED		;**-1
	BISB	T.      DPRI(R5),R3	;USE DEFAULT PRIORITY
40$:	CMP	R3,#250.	;NEW PRIORITY .GT. 250?
	BHI	170$		;IF HI YES
	MOVB	R3,T.PRI(R5)	;SET NEW PRIORITY
	TSTB	T.IOC(R5)	;ANY I/O ACTIVE?
	BEQ	100$		;IF EQ NO
	CLR	-(SP)		;PUSH INITIAL LUN NUMBER - 1
50$:	MOV	T.PCB(R5),R4	;GET PCB ADDR
	MOV	P.HDR(R4),R4	;GET TASK HEADER OF TASK TO BE ALTERED
	CMP	(SP),H.NLUN(R4)	;PAST LAST LUN?
	BHIS	90$		;IF HIS YES
	MOV	(SP),R1		;GET LUN -1
	CALL	$MPLNE		;MAP LUN TO UCB ADDRESS
	BCS	80$		;IF CS LUN IS NOT ASSIGNED


	.IF DF	A$      $CPS

	MOV	R0,-(SP)	;SAVE UCB ADDRESS

	.IFTF

	MOV	U.SCB(R0),R4	;GET PTR TO SCB FOR THIS UCB
	CALL	130$		;REORDER I/O QUEUE

	.IFT

	MOV	(SP)+,R0	;RETRIEVE UCB ADDRESS
	TST	U.CW1(R0)	;DEVICE MOUNTABLE?
	BPL	80$		;IF PL NO
	BITB	#US.MNT!US.FOR,U.STS(R0) ;MOUNTED AND NOT FOREIGN?
	BNE	80$		;IF NE NO
	MOV	U.ACP(R0),R4	;PICK UP TCB OF ACP
	ADD	#T.RCVL,R4	;POINT TO RECEIVE QUEUE LISTHEAD
	CALL	130$		;REORDER ACP QUEUE

	.ENDC


80$:	INC	(SP)		;UPDATE LUN NUMBER
	BR	50$		;CONTINUE THROUGH       LUN LOOP
90$:	TST	(SP)+		;POP LUN NUMBER FROM STACK
100$:	MOV	R5,R0		;GET TCB ADDR OF TASK TO BE ALTERED
	CALL	$ACTRM		;REMOVE TCB FROM ATL
	BCS	110$		;IF CS TCB NOT YET IN ATL
	CALL	$ACTTK		;RE-INSERT TCB IN ATL
110$:				;REF LABEL


	.IF DF	D$$ISK

	MOV	T.PCB(R5),R4	;GET PCB ADDR
	MOV	P.MAIN(R4),R0	;GET MAIN PCB ADDR
	ADD	#P.WAIT,R0	;GET LISTHEAD FOR PARTITION WAIT QUEUE
	MOV	R5,R1		;POINT TO TASK TCB
	CALL	$QRMVT		;TRY TO REMOVE TCB FROM QUEUE
	BCS	120$		;IF CS TCB NOT IN WAIT QUEUE
	CA      LL	$QINSP		;RE-INSERT TCB BY NEW PRIORITY
120$:	MOV	R4,R0		;GET PCB ADDR
	CALL	$NXTSK		;RE-SCHEDULE PARTITION

	.ENDC


	CALLR	$DRDSE		;DECLARE SIGNIFICANT EVENT
130$:	MOV	#-2,-(SP)	;CONSTRUCT TEMPORARY LISTHEAD ON STACK
	ADD	SP,(SP)		;
	CLR	-(SP)		;
140$:	MOV	R4,R0		;GET I/O PACKET LISTHEAD ADDR
	MOV	R5,R1		;GET TCB ADDR OF TASK TO BE ALTERED
	CALL	$QRMVT		;REMOVE I/O PACKET BY TCB ADDR
	BCS	150$		;IF CS NO I/O PACKET FOUND
	CMPB	I.PRI(R1),#250.	;PRIORITY HIGHER THAN 250?
	BHI	145$		;IF HI       YES, DON'T CHANGE, BRKTHRU WRITE
	MOVB	T.PRI(R5),I.PRI(R1) ;SET NEW PRIORITY
145$:	MOV	SP,R0		;SET TEMPORARY LISTHEAD ADDR
	CALL	$QINSF		;INSERT I/O PACKET IN TEMPORARY LIST
	BR	140$		;CONTINUE THROUGH PACKET REMOVAL LOOP
150$:	MOV	SP,R0		;SET TEMPORARY LISTHEAD ADDR
	CALL	$QRMVF		;REMOVE FIRST I/O PACKET FROM LIST
	BCS	160$		;IF CS NO I/O PACKET FOUND
	MOV	R4,R0		;GET I/O PACKET LISTHEAD ADDR
	CALL	$QINSP		;RE-INSERT I/O PACKET BY NEW PRIORITY
	BR	150$		;CONTINUE THROUGH PACKET INSERTION LOOP
16   ü   0$:	CMP	(SP)+,(SP)+	;CLEAN TEMPORARY LISTHEAD OFF STACK
	RETURN			;
170$:	DRSTS	D.RS95		;SET DIRECTIVE STATUS
175$:	DRSTS	D.RS7		;SET DIRECTIVE STATUS


	.IF DF	M$$MUP

180$:	DRSTS	D.RS16		;PRIVILEGE VIOLATION

	.ENDC


	.ENDC


	.END
ü          ×p:kQ	› c,     š  	.TITLE	DRGIN
	.IDENT	/01.01/

;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.01
;
; M. S. HARVEY	2-JAN-80
;
;
;


	.IF DF	D$$GIN

$DRGIN::
	DRSTS	D.RS99		;ILLEGAL DIRECTIVE FOR NOW !!

	.ENDC


	.END
 š         óQ�ƒkQ	› c,        	.TITLE	MDSUB
	.IDENT	/01.10/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.10
;
; M. S. HARVEY 21-AUG-80
;
; PREVIOUSLY MODIFIED BY:
;
; MODIFIED BY:
;
;	M. S. HARVEY	17-SEP-79
;		MSH062 -- DEFINE $BLKCK ROUTINE FOR TU58 DRIVER
;			  AND ML11 DRIVER
;
;	P. J. CARR	18-APR-80
;		PJC003 -- REMOVE M$$IXD ST      UFF
;
;	M. S. HARVEY	9-MAY-80
;		MSH099 -- CORRECT LOCK BLOCK LENGTH SYMBOL
;
;	M. S. HARVEY	21-AUG-80
;		MSH112 -- CREATE THIS SOURCE MODULE FROM IOSUB.
;			  ALL CORRECTIONS LISTED ABOVE CAME FROM IOSUB.
;
;	P. J. BEZEREDI 13-NOV-80
;		PB194 -- USE EIS INSTRUCTION SET WHERE APPLICABLE.
;
;	R. T. PERRON	21-NOV-80
;		RP041 -- CHANGE INTERFACE TO COMMON ECC ROUTINE
;
;	M. Pettengill	6-May-81
;		MLP035 -- Upgrade RMS block lock processing to include
;			real reader locks and shared locks for       all
;			reader requests and specified writer reads
;		MLP036 -- Support file by file write checking
;
;	R. T. PERRON	24-AUG-81
;		RP072 -- DEFINE $BLKCK FOR RF11, RX01,RX02,
;			AND THE UDA50
;
;	M. Pettengill	12-Oct-81
;		MLP066 -- Correct problem with lock without I/O and
;			don't create a lock for a reader to allow use
;			of RMS-11 V1.8
;
;
; MASS STORAGE DEVICE RELATED ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	F11DF$,PKTDF$,HWDDF$
	F11DF$			;DEFINE WINDOW AND LOCK BLOCK OFFSETS
      	PKTDF$			;DEFINE I/O PACKET OFFSETS
	HWDDF$			;DEFINE HARDWARE REGISTERS



;+
; **-$BLKCK-LOGICAL BLOCK CHECK ROUTINE
; **-$BLKC1-LOGICAL BLOCK CHECK ROUTINE (ALTERNATE ENTRY)
;
; THIS ROUTINE IS CALLED BY I/O DEVICE DRIVERS TO CHECK THE STARTING
; AND ENDING LOGICAL BLOCK NUMBERS OF AN I/O TRANSFER TO A FILE
; STRUCTURED DEVICE. IF THE RANGE OF BLOCKS IS NOT LEGAL, THEN $IODON
; IS ENTERED WITH A FINAL STATUS OF "IE.BLK" AND A RETURN TO THE
; DRIVER'S INITIATOR ENTRY POINT IS EXECUTED. ELSE       A RETURN TO THE
; DRIVER IS EXECUTED.
;
; INPUTS:
;
;	R1=ADDRESS OF I/O PACKET.
;	R5=ADDRESS OF THE UCB.
;
; OUTPUTS:
;
;	IF THE CHECK FAILS, THEN $IODON IS ENTERED WITH A FINAL STATUS
;	OF "IE.BLK" AND A RETURN TO THE DRIVER'S INITIATOR ENTRY POINT
;	IS EXECUTED.
;
;	IF THE CHECK SUCCEEDS, THEN THE FOLLOWING REGISTERS ARE RETURNED
;		R0=LOW PART OF LOGICAL BLOCK NUMBER.
;		R1=POINTS TO I.PRM+12 (LOW PART OF USER LBN)
;		R2=HIGH PART OF LOGICAL BLOCK NUMBER.
;		R3=ADDRESS OF I/O PACKET.
;      -


	.IIF DF	R$$JP1!R$$K11!R$$L11!R$$M11!R$$P11 BLKCK=0		;MSH062
	.IIF DF	R$$JS1!R$$611!T$$C11!T$$U58!M$$L11 BLKCK=0		;MSH062
	.IIF DF	R$$F11!R$$X11!R$$X21!R$$UDA BLKCK=0			; RP072
									;MSH062
	.IF DF	BLKCK							;MSH062
									;**-1
$BLKCK::MOV	R1,R3		;SAVE ADDRESS OF I/O PACKET
	ADD	#I.PRM+11,R1	;POINT PAST HIGH PART OF LBN
	CLRB	(R1)+		;CLEAR EXCESS BYTE
$BLKC1::			;ALTERNATE ENTRY POINT
	MOV	(R1),R0		;GET LOW PART OF LBN
	MOV	-(R1),R2	;GET HIGH PART OF LBN
	MOV	I.PRM+4(R3),-(SP) ;G      ET NUMBER OF BYTES TO TRANSFER
	ADD	#777,(SP)	;ROUND TO NEXT BLOCK
	ROR	(SP)		;CALCULATE NUMBER OF BLOCKS IN HIGH BYTE
	CLRB	(SP)		;CLEAR EXCESS BYTE
	SWAB	(SP)		;CALCULATE NUMBER OF BLOCK IN TRANSFER
	ADD	(SP)+,R0	;CALCULATE HIGHEST BLOCK NUMBER + 1
	ADCB	R2		;
	BCS	20$		;IF CS ILLEGAL BLOCK NUMBER
	CMPB	R2,U.CW2(R5)	;HIGH PART OF LBN LEGAL?
	BHI	20$		;IF HI NO
	BLO	10$		;IF LO YES
	CMP	R0,U.CW3(R5)	;LOW PART OF LBN LEGAL?
	BHI	20$		;IF HI NO
10$:	MOV	(R1)+,R2	;RETRIEVE HIGH PART OF LBN
	MOV	      (R1),R0		;RETRIEVE LOW PART OF LBN
	RETURN			;
20$:	MOV	(R5),R0		;GET ADDRESS OF DEVICE DCB
	MOV	@D.DSP(R0),(SP)	;REPLACE RETURN ADDRESS TO INITIATOR
	MOV	#IE.BLK&377,R0	;SET FINAL I/O STATUS
	CALLR	$IOALT		;FINISH THE I/O REQUEST			;MSH112

	.ENDC



;+
; **-$MPPKT-MAP I/O PACKET FUNCTION
;
; THIS ROUTINE IS CALLED TO MAP A READ/WRITE VIRTUAL FUNCTION IN AN I/O PACKET
; TO A READ/WRITE LOGICAL FUNCTION. IF THE CURRENT WINDOW DOES NOT MAP THE VIRTU
; FUNCTION, THEN A FAILURE INDICATION IS RE      TURNED. ELSE IF THE WINDOW COMPLETELY
; MAPS THE VIRTUAL FUNCTION, THEN THE LOGICAL BLOCK NUMBER IS STORED IN THE I/O
; PACKET AND THE READ/WRITE VIRTUAL FUNCTION IS CONVERTED TO ITS LOGICAL COUNTER
; PART. ELSE THE PARTIAL MAPPING RESULTS ARE RETURNED TO THE CALLER.
;
; INPUTS:
;
;	R1=ADDRESS OF THE I/O PACKET.
;
; OUTPUTS:
;
;	C=1 IF MAPPING FAILURE.
;	C=0 IF MAPPING WAS SUCCESSFUL.
;		IF R0 EQ 0, THEN
;			I.FCN+1(R1)=IO.WLB/IO.RLB.
;			I.PRM+10(R1)=HIGH PART OF MAPPED LBN.
;			I.PRM+12(R1      )=LOW PART OF MAPPED LBN..
;		ELSE
;			R0=NUMBER OF BLOCKS NOT MAPPED.
;			R2=HIGH PART OF MAPPED LBN.
;			R3=LOW PART OF MAPPED LBN.
;
;	R1 IS PRESERVED ACROSS CALL.
;-


	.IF DF	A$$CPS

$MPPKT::MOV	I.PRM+12(R1),R3	;PICKUP LOW PART OF VBN
	MOV	I.PRM+10(R1),R2	;PICKUP HIGH PART OF VBN
	MOV	R1,-(SP)	;SAVE I/O PACKET ADDRESS
	MOV	I.PRM+4(R1),R0	;GET LENGTH OF TRANSFER IN BYTES
	MOV	@I.LN2(R1),R1	;GET ADDRESS OF WINDOW BLOCK
	BIC	#1,R1		;MAKE SURE LOW BIT OF ADDRESS IS ZERO
	CALL	$MPVBN		;MAP       VIRTUAL BLOCK NUMBER
	MOV	(SP)+,R1	;RETRIEVE I/O PACKET ADDRESS
	BCS	20$		;IF CS MAPPING FAILURE
	TST	R0		;REQUEST COMPLETELY MAPPED?
	BNE	20$		;IF NE NO
	MOVB	R2,I.PRM+10(R1) ;SET HIGH PART OF LBN
	MOV	R3,I.PRM+12(R1) ;SET LOW PART OF LBN
	MOV	#IO.RLB,-(SP)	;ASSUME READ REQUEST			; MLP036
	CMPB	#IO.WVB/256.,I.FCN+1(R1) ;WRITE VIRTUAL FUNCTION?	;**-1
	BNE	10$		;IF NE NO				; MLP036
									; MLP036
	.IF DF	D$$WCH							; MLP036
									; MLP036
	MOV	#IO.WLC,(SP)	;ASSUME WRITE CHECK			; MLP03      6
	MOV	@I.LN2(R1),-(SP) ;GET ADDRESS OF WINDOW			; MLP036
	BIC	#1,(SP)		;CLEAR LUN INTERLOCK			; MLP036
;	ASSUME	WI.WCK,100000						; MLP036
	TST	@(SP)+		;DATA CHECKING REQUESTED?		; MLP036
	BMI	10$		;IF MI YES				; MLP036
	CLRB	(SP)		;DEMOTE TO WRITE LOGICAL (IO.WLB)	; MLP036
									; MLP036
	.IFF								; MLP036
									; MLP036
	MOV	#IO.WLB,(SP)	;CONVERT TO WRITE LOGICAL		; MLP036
									; MLP036
	.ENDC								; MLP036
									; MLP036
10$:	MOV	(SP)+,I.FCN(R1)	;SET NEW FUNCTION CODE		      	;**-2


	.IF DF	M$$MGE

	MOV	R1,R3		;SAVE I/O PACKET ADDRESS
	MOV	I.PRM(R3),R1	;GET RELOCATION BIAS
	MOV	I.PRM+2(R3),R2	;GET DISPLACEMENT ADDRESS
	CALL	$MPPHY		;MAP TO 18 BIT PHYSICAL ADDRESS
	MOV	R1,I.PRM(R3)	;INSERT 18 BIT PHYSICAL ADDRESS BACK
	MOV	R2,I.PRM+2(R3)	;INTO I/O PACKET
	MOV	R3,R1		;RESTORE I/O PACKET ADDRESS
	CLC			;MAKE SURE CARRY IS CLEAR

	.ENDC


20$:	RETURN			;



;+
; **-$MPVBN-MAP VIRTUAL BLOCK NUMBER
;
; THIS ROUTINE IS CALLED TO MAP A VIRTUAL BLOCK NUMBER (VBN      ) TO A LOGICAL BLOCK
; NUMBER (LBN) VIA A WINDOW BLOCK THAT CONTAINS A SET OF MAPPING POINTERS.
;
; INPUTS:
;
;	R0=NUMBER OF CONSECUTIVE BYTES THAT MUST BE MAPPED.
;	R1=ADDRESS OF THE WINDOW BLOCK.
;	R2=HIGH PART OF VBN.
;	R3=LOW PART OF VBN.
;
; OUTPUTS:
;
;	C=1 IF VBN CANNOT BE MAPPED VIA WINDOW BLOCK.
;	C=0 IF VBN SUCCESSFULLY MAPPED TO LBN.
;		PARTIAL MAPPING IS A SUCCESS
;		R0=NUMBER OF UNMAPPED BLOCKS.
;		R2=HIGH PART OF LBN.
;		R3=LOW PART OF LBN.
;-

$MPVBN::SAVNR			;SAVE NONVOLA      TILE REGISTERS
	MOVB	(R1),R5		;GET THE NUMBER OF ACTIVE PTRS
	BEQ	20$		;IF EQ NO MAP POSSIBLE
	ADD	#777,R0		;ROUND BYTES TO NEXT 256. WORD BLOCK
	ROR	R0		;CONVERT TO WORDS
	CLRB	R0		;CLEAR RESIDUAL BITS
	SWAB	R0		;SWAP NUMBER OF BLOCKS TO LOW BYTE
	MOVB	W.VBN(R1),R4	;GET 7 BITS OF HI VBN
	SUB	R4,R2		;NORMALIZE HIGH PART OF VBN
	SUB	W.VBN+2(R1),R3	;NORMALIZE LOW VBN
	SBC	R2		;
	BLO	20$		;BRANCH ON MAPPING FAILURE
	ADD	#W.RTRV,R1	;POINT R1 TO WINDOW MAPPING POINTERS
10$:	SUB	(R1)+,R3	;SUBTRACT EX      TENT SIZE FROM VBN
	SBC	R2		; ALSO HIGH VBN
	BLO	30$		;BRANCH IF VBN IS IN THIS EXTENT
	CMP	(R1)+,(R1)+	;SKIP OVER THE LBN
	DEC	R5		;DECREMENT ACTIVE POINTER COUNT
	BGT	10$		;IF GT YES
20$:	SEC			;INDICATE MAPPING FAILURE
	BR	70$		;
;
30$:	ADD	R3,R0		;TEST FOR ALL BLOCKS IN EXTENT
	BGT	40$		;BRANCH IF NOT - ONLY PARTIAL MAP
	CLR	R0		;ZERO R0 FOR FULL MAPPING
40$:	ADD	-2(R1),R3	;R3=OFFSET WITHIN EXTENT
	ADC	R2		;R2=HIGH OFFSET (=0)
	ADD	(R1)+,R2	;ADD THE EXTENTS BEGINNING
	ADD	(R1)+,R3	; LBN T      O THE OFFSET
	ADC	R2		;  TO GET DESIRED LBN
; NOTE:	AT THIS POINT THE CARRY IS CLEAR
70$:				;
	RETURN			;

	.ENDC


;+
; **-$LCKPR-LOCK PROCESSING ROUTINE
;
; THIS ROUTINE FIRST DETERMINES IF A FILE I/O REQUEST IS TO A SHARED
; FILE.  IF SO, IT DETERMINES IF THE REQUEST IS AN UNLOCK QIO OR A
; VIRTUAL BLOCK I/O REQUEST.  IT THEN EITHER PERFORMS THE UNLOCK QIO
; OR THE LOCK PROCESSING RESPECTIVELY.
;
; INPUTS:
;
;	R1=I/O PACKET ADDRESS OF THE REQUEST
;
; OUTPUTS:
;
;	C=0 IF NO LOCK PR      OCESSING WAS REQUIRED.
;
;	C=1 IF AN UNLOCK WAS PERFORMED OR AN ERROR CONDITION OCCURED
;		DURING THE LOCK PROCESSING.
;		R0=I/O STATUS
;
;	R1 IS PRESERVED.
;-


	.IF DF	R$$LKL

$LCKPR::MOV	@I.LN2(R1),R3	;POINT TO WINDOW BLOCK
	BIC	#1,R3		;CLEAR INTERLOCK BIT
	MOV	#IE.ULK&377,R0	;SET FOR UNLOCK ERROR STATUS
	MOV	W.LKL(R3),R2	;POINT TO FIRST ENTRY IN LOCK LIST
	BEQ	50$		;IF EQ THERE IS NONE
									; MLP035
;									; MLP035
; At this point we know that block locking is enabled for the f      ile.	; MLP035
;									; MLP035
; The type of lock requested is either shared or exclusive depending	; MLP035
; on the type of accessor and the I/O function.				; MLP035
;									; MLP035
; If request is from a reader then I.FCN(R1) is				; MLP035
;	IO.RVB to read with shared lock					; MLP035
;	IO.ULK to unlock any or all existing locks			; MLP035
;	IO.ULK!IQ.LCK to request a shared lock without any I/O		; MLP035
;									; MLP035
; If the request is from a writer then I.FCN(R1) is			; MLP035      
;	IO.RVB to read with an exclusive lock				; MLP035
;	IO.RVB!IQ.LCK to read with a shared lock			; MLP035
;	IO.WVB to write with exclusive lock				; MLP035
;	IO.ULK to unlock any or all existing locks			; MLP035
;	IO.ULK!IQ.LCK to request a exclusive lock without I/O		; MLP035
;									; MLP035
									; MLP035
	SAVNR			;SAVE R4 AND R5
	MOV	I.PRM+4(R1),R4	;PICK UP BYTE COUNT FOR REQUEST
	ADD	#777,R4		;ROUND TO NEXT DISK BLOCK
	ROR	R4		;CONVERT TO SIZE IN BLOCKS
	CLRB	R4		;
	SWAB	R4		;
	CMPB	      I.FCN+1(R1),#IO.ULK/256. ;IS THIS AN UNLOCK REQUEST?
	BNE	100$		;IF NE NO
;	ASSUME	IQ.LCK,200						; MLP035
	TSTB	I.FCN(R1)	;LOCK WITHOUT I/O REQUEST?		; MLP035
	BPL	5$		;IF PL NO				; MLP035
	CALL	100$		;DO LOCK PROCESSING			; MLP035
	DEC	@I.PRM+16(R1)	;UNBUSY LOCK BLOCK SINCE NO I/O		; MLP066
	CLR	I.PRM+16(R1)	;DON'T DO IT TWICE			; MLP066
	BR	50$		;JOIN COMMON CODE			; MLP035
5$:				;REFERENCE LABEL			; MLP035

;
; UNLOCK PROCESSING
;
; THIS SECTION OF THE ROUTINE PERFORMS THE UNLOCK PROCES      SING.  RELEVANT
; REGISTER CONTENTS AT THIS POINT ARE:
;
;	R0=UNLOCK ERROR STATUS
;	R1=I/O PACKET ADDRESS
;	R2=ADDRESS OF THE FIRST LOCK BLOCK IN THE LOCK LIST
;	R3=POINTER TO CURRENT WINDOW
;	R4=BYTE COUNT OF CURRENT UNLOCK REQUEST
;

	MOV	I.PRM+12(R1),R5	;CREATE BLOCK NUMBER SPECIFIED FLAG
	BISB	I.PRM+10(R1),R5	;
10$:	TSTB	L.CNT(R2)	;THIS LOCK BLOCK IN USE?
	BEQ	40$		;IF EQ NO
	TST	R5		;BLOCK NUMBER SPECIFIED?
	BEQ	20$		;IF EQ NO
	CALL	180$		;EXACT VBN AND COUNT MATCH?
	BNE	40$		;IF NE NO      
20$:	CMP	L.WI1(R2),R3	;SAME OWNER?
	BNE	40$		;IF NE NO
	CLRB	L.CNT(R2)	;UNLOCK THE LOCK
	MOV	#IS.SUC&377,R0	;SET FOR SUCCESSFUL RETURN
	TST	R5		;WAS THIS FOR AN EXPLICIT BLOCK NUMBER?
	BNE	50$		;IF NE YES
40$:	MOV	(R2),R2		;POINT TO NEXT LOCK BLOCK
	BNE	10$		;IF NE THERE IS ONE

;
; NO LOCK LIST EXISTS
;
; IF THE FUNCTION IS NOT AN UNLOCK FUNCTION, A SIMPLE RETURN OCCURS
; WITH CARRY CLEAR.  AN UNLOCK IN THIS CASE IS AN ERROR.  (NOTE THAT
; ALL UNLOCK REQUESTS FALL THROUGH HERE AS WELL.)
;      

50$:	CMPB	I.FCN+1(R1),#<IO.ULK/256.>+1 ;SET CARRY IF UNLOCK
	RETURN			;

;
; LOCK PROCESSING
;
; THIS ROUTINE CHECKS FOR ATTEMPTED LOCK OVERLAPS, ATTEMPTS TO SET THE
; NEW LOCK, AND PERFORMS THE IMPLIED UNLOCK.  IF A NEW LOCK REQUEST
; FOR AN EXPLICIT UNLOCKER IS DETECTED WHICH EXACTLY MATCHES AN EXISTING
; LOCK FOR THAT WINDOW IN BOTH STARTING VBN AND SIZE, THE LOCK BLOCK IS
; SIMPLY REUSED.  RELEVANT REGISTER CONTENTS AT THIS POINT ARE:
;
;	R1=I/O PACKET ADDRESS
;	R2=ADDRESS OF FIRST LOCK       BLOCK IN LOCK LIST
;	R3=ADDRESS OF FILE WINDOW
;	R4=BLOCK COUNT FOR CURRENT REQUEST
;
;									; MLP035
; The following cases are considered:					; MLP035
;									; MLP035
; 1. If the request is for a window with implicit (not explicit,	; MLP035
;    WI.EXL) unlocking and there exists a current lock for that		; MLP035
;    window with I/O still in progress then return a lock error		; MLP035
;    (IE.LCK).								; MLP035
;									; MLP035
; 2. If the request is an exact match for a lock whic      h is an		; MLP035
;    exact match of window (owner), LBN, and size and which		; MLP035
;    has I/O still in progress then return a lock error (IE.LCK).	; MLP035
;									; MLP035
; 3. If the request is from a window with only read access or a		; MLP035
;    read request requesting only shared access from a writer		; MLP035
;    attempt to grant a shared lock.  If there is no existing		; MLP035
;    lock with overlap then grant the shared lock.  In the case		; MLP035
;    of a conflict see table b      elow.					; MLP035
;									; MLP035
; 4. If the request is from a window with write access and is a		; MLP035
;    write or a read without a shared lock request attempt to		; MLP035
;    grant an exclusive lock.  If there is no existing lock with	; MLP035
;    overlap then grant an exclusive lock.  In the case of conflict	; MLP035
;    see table below.							; MLP035
;									; MLP035
; 5. Decision table for resolving conflicts:				; MLP035
;									; MLP035
;				     I/O request			; MLP035
;      	Lock		Shared			Exclusive		; MLP035
;									; MLP035
; Exact match		grant shared		granted exclusive	; MLP035
;						if no other conflict	; MLP035
;			(reuse lock block)	(reuse lock block)	; MLP035
;									; MLP035
; Conflict shared	grant shared		reject IE.LCK		; MLP035
;									; MLP035
; Conflict exclusive	reject IE.LCK		reject IE.LCK		; MLP035
;									; MLP035

100$:	CLR	R5		;INIT FREE NODE POINTER
	MOV	#IE.LCK&377,-(SP) ;PUSH LOCK ERROR STATUS
	CLR	-(SP)		;ASSUME SHARED LOCK			; MLP03      5
	BIT	#WI.WRV,(R3)	;IS THIS REQUEST FOR A WRITER?		; MLP035
	BEQ	110$		;IF EQ NO, ALWAYS SHARED LOCK		; MLP035
	CMPB	I.FCN+1(R1),#IO.RVB/400 ; IS THIS A READ REQUEST?	; MLP035
	BNE	105$		;IF NE NO, ALWAYS EXCLUSIVE LOCK	; MLP035
;	ASSUME	IQ.LCK,200						; MLP035
	TSTB	I.FCN(R1)	;SHARED LOCK REQUESTED?			; MLP035
	BMI	110$		;IF MI YES				; MLP035
105$:	INC	(SP)		;SET EXCLUSIVE LOCK REQUESTED		; MLP035
110$:	TSTB	L.CNT(R2)	;IS LOCK BLOCK IN USE?
	BNE	120$		;IF NE YES
	TST	R5		;ALREADY HAVE FREE BL      OCK?
	BNE	150$		;IF NE YES, LOOK AT NEXT LOCK BLOCK
	BR	130$		;ELSE CLAIM THIS BLOCK
120$:	MOV	L.WI1(R2),R0	;PICK UP OWNER WORD
	BIC	#1,R0		;CLEAR BIT FOR NO UNLOCK FLAG
	CMP	R0,R3		;LOCK BELONG TO THIS WINDOW?
	BNE	140$		;IF NE NO, CHECK FOR OVERLAPS
	BIT	#WI.EXL,(R3)	;EXPLICIT UNLOCKER?
	BEQ	125$		;IF EQ NO, SAVE BLOCK FOR IMPLIED UNLOCK
	CALL	180$		;EXACT VBN AND COUNT?
	BNE	140$		;IF NE NO				; MLP035
125$:	MOV	L.WI1(R2),R0	;RETRIEVE OWNER WORD			;**-1
	ROR	R0		;CAN LOCK BLOCK BE REUSED?
	B      CS	153$		;IF CS NO				; MLP035
130$:	MOV	R2,R5		;SET TO REUSE THIS LOCK BLOCK		;**-1
	BR	150$		;LOOK AT NEXT LOCK BLOCK
140$:	MOVB	L.CNT(R2),R0	;PICKUP LOCK BLOCK COUNT, EXCLUSIVE?	; MLP035
	BMI	141$		;IF MI YES				; MLP035
	TST	(SP)		;REQUEST EXCLUSIVE LOCK?		; MLP035
	BEQ	150$		;IF NE NO				; MLP035
	BR	142$		;DO CONFLICT CHECK			; MLP035
141$:	NEG	R0		;CONVERT TO MAGNITUDE			; MLP035
142$:	ADD	L.VB1+2(R2),R0	;CALCULATE NUMBER OF HIGHEST BLOCK + 1	; MLP035
	MOVB	L.VB1(R2),-(SP)	;PUSH HIGH ORDER       BYTE			;**-3
	ADCB	(SP)		;PROPAGATE CARRY
	CMPB	I.PRM+10(R1),(SP)+ ;OVERLAP?
	BNE	145$		;IF NE USE BRANCH BELOW
	CMP	I.PRM+12(R1),R0	;OVERLAP?
145$:	BHIS	150$		;IF HIS NO
	MOV	R4,R0		;COPY SIZE OF CURRENT REQUEST
	ADD	I.PRM+12(R1),R0	;CALCULATE NUMBER OF HIGHEST BLOCK +1
	MOVB	I.PRM+10(R1),-(SP) ;PUSH HIGH ORDER BYTE
	ADCB	(SP)		;PROPAGATE CARRY
	CMPB	L.VB1(R2),(SP)+	;OVERLAP?
	BNE	146$		;IF NE USE BRANCH BELOW
	CMP	L.VB1+2(R2),R0	;OVERLAP?
146$:	BLO	153$		;IF LO YES, (CARRY SET)			; MLP035
15      0$:	MOV	(R2),R2		;POINT TO NEXT LOCK BLOCK		;**-1
	BNE	110$		;IF NE THERE IS ONE
									; MLP066
;									; MLP066
; Hack:	In order to phase in real reader locks which are not supported	; MLP066
; by rms-11 v1.8, the following code is included to prevent them from	; MLP066
; being created.  At some future time this code will be removed.	; MLP066
;									; MLP066
									; MLP066
	.IF NE	1							; MLP066
									; MLP066
	BIT	#WI.WRV,(R3)	;READER?				; MLP066
	BEQ	170$		;IF EQ YES				; MLP      066
									; MLP066
	.ENDC								; MLP066
									; MLP066
	MOV	R5,R0		;COPY POINTER TO SAVED LOCK BLOCK	;**-3
	BNE	160$		;IF NE ONE WAS IN FACT SAVED
	MOV	#IE.NOD&377,2(SP) ;ASSUME ALLOCATION FAILURE STATUS	; MLP035
	MOV	R1,-(SP)	;SAVE I/O PACKET ADDRESS		;**-1
	MOV	#L.LKSZ,R1	;PICK UP SIZE OF LOCK BLOCK		;MSH099
	CALL	$ALOCB		;ALLOCATE LOCK BLOCK			;**-1
	MOV	(SP)+,R1	;RESTORE I/O PACKET ADDRESS
	BCC	155$		;IF CC SUCCESS				; MLP035
153$:	ROL	(SP)		;SAVE CARRY				; MLP035
	BR	170$		;JOIN       COMMON EXIT CODE			; MLP035
155$:	MOV	@W.LKL(R3),(R0)	;POINT NEW BLOCK TO SECOND IN LIST	; MLP035
	MOV	R0,@W.LKL(R3)	;POINT FIRST BLOCK IN LIST TO NEW ONE	;**-2
160$:	TST	(R0)+		;ADVANCE TO OWNER WORD
	MOV	R0,I.PRM+16(R1)	;SAVE POINTER TO OWNER WORD
	MOV	R3,(R0)		;SET OWNER WORD
	INC	(R0)+		;SET NO UNLOCK FLAG
	MOVB	I.PRM+10(R1),(R0)+ ;SET HIGH PART OF VBN
	ROR	(SP)		;EXCLUSIVE LOCK?			; MLP035
	BCC	165$		;IF CC NO				; MLP035
	NEG	R4		;SET FOR EXCLUSVE LOCK			; MLP035
165$:	MOVB	R4,(R0)+	;SET BL      OCK COUNT			; MLP035
	MOV	I.PRM+12(R1),(R0) ;SET LOW PART OF VBN			;**-1
	MOV	#IS.SUC&377,2(SP) ;SET SUCCESS FOR LOCK WITHOUT I/O CASE; MLP035
170$:	ROR	(SP)+		;SET CARRY, CLEAN STACK			; MLP035
	MOV	(SP)+,R0	;PICKUP ERROR STATUS			; MLP035
	RETURN			;					;**-1

;
; ROUTINE TO CHECK FOR EXACT VBN AND BLOCK COUNT MATCH
;
; INPUTS:
;
;	R1=I/O PACKET ADDRESS
;	R2=LOCK BLOCK ADDRESS
;	R4=BYTE COUNT
;
; OUTPUTS:
;
;	ALL REGISTERS PRESERVED.
;
;	Z=1 IF EXACT MATCH.
;
;	Z=0 IT NO MATCH.
;
      
180$:	CMP	L.VB1+2(R2),I.PRM+12(R1) ;MATCH ON LOW ORDER?
	BNE	190$		;IF NE NO
	CMPB	L.VB1(R2),I.PRM+10(R1) ;MATCH ON HIGH ORDER?
	BNE	190$		;IF NE NO
	TST	R4		;COUNT SPECIFIED?
	BEQ	190$		;IF EQ NO
	MOVB	L.CNT(R2),-(SP)	;GET LOCK BLOCK COUNT, NEGATIVE?	; MLP035
	BPL	185$		;IF PL NO				; MLP035
	NEGB	(SP)		;COMPUTE MAGNITUDE			; MLP035
185$:	CMPB	(SP)+,R4	;CLEAN STACK, MATCH ON COUNT?		; MLP035
190$:	RETURN			;					;**-1

	.ENDC


;+
; **-$ECCOR-COMMON ECC CORRECTION CODE FOR RP04/RK06.
;
      ; THIS ROUTINE APPLIES THE ECC CORRECTION ALGORITHM AND DETERMINES
; IF OFFSET RECOVERY IS REQUIRED (IF SUPPORTED).
;
; INPUTS:
;
;	R0=BYTES ACTUALLY TRANSFERED					; RP041
;	R1=ECC ERROR POSITION (FROM HARDWARE REGISTER)			; RP041
;	R2=WORD COUNT (FROM HARDWARE REGISTER)				; RP041
;	R3=ECC ERROR CORRECTION PATTERN (FROM HARDWARE REGISTER)	; RP041
;	R5=UCB ADDRESS							;**-3
;
; OUTPUTS:
;
;	R0=IS.SUC&377							; RP041
;	R1=BYTES ACTUALLY TRANSFERED					; RP041
;	R2=CSR ADDRESS							; RP04      1
;	R3=CONTROLLER INDEX						; RP041
;-									;**-12


	.IF DF	S$$ECC

									; RP041
$ECCOR::MOV	R0,-(SP)	;SAVE BYTES ACCUTALLY TRANSFERED	; RP041
	CLR	R0		;CLEAR HIGH ORDER ERROR POSITION	; RP041
	DEC	R1		;CONVERT TO RELATIVE BIT NUMBER		; RP041
									; RP041
									; RP041
	.IF DF	 M$$EIS							; RP041
									; RP041
	DIV	#20,R0		;DIVIDE FOR:				; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
									; RP041
	.IFF	;M$$EIS							; RP041      
									; RP041
	MOV	R1,R0		;COPY ECC ERROR POSITION		; RP041
	MOV	#20,R1		;SET DIVISOR TO CALCULATE:		; RP041
				; R0=WORD POSITION (0-377)		; RP041
				; R1=BIT POSITION (0-17)		; RP041
	CALL	$DIV		;PERFORM DIVISION			; RP041
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
	MOV	R0,-(SP)	;SAVE WORD POSITION			; RP041
	MOV	R2,-(SP)	;SAVE REMAINING WORD COUNT		; RP041
	CLR	R2		;CLEAR HIGH ORDER ERROR PATTERN		; RP041
									; RP041
									; RP041
	.IF DF	      M$$EIS							; RP041
									; RP041
10$:	ASHC	R1,R2		;SHIFT PATTERN INTO CORRECT POSITION	; RP041
									; RP041
	.IFF	;M$$EIS							; RP041
									; RP041
10$:	DEC	R1		;ANY MORE SHIFTS LEFT TO PERFORM	; RP041
	BLT	20$		;IF LT NO				; RP041
	ASL	R3		;DOUBLE LEFT SHIFT			; RP041
	ROL	R2		;					; RP041
	BR	10$		;					; RP041
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
20$:	MOV	4(SP),R0	;RETRIEVE ACTUAL BYTES TRANSFERED	; RP041
	SUB	#510.,R0	;BACKUP TO       BLOCK IN ERROR ...		; RP041
				;... OFFSET TO HIGH WORD IN ERROR	; RP041
	CALL	$RELOP		;COMPUTE LOCATION IN PHYSICAL MEMORY	; RP041
	MOV	(SP)+,R0	;RETRIEVE REMAINING WORD COUNT		; RP041
	BPL	30$		;IF PL THIS MAY HAVE BEEN A PARTIAL BLOC; RP041
				;TRANSFER				; RP041
	CLR	R0		;ASSUME A WHOLE BLOCK WAS TRANSFERRED	; RP041
30$:	ADD	(SP),R1		;ADD IN ERROR WORD POSITION OFFSET ...	; RP041
	ADD	(SP),R1		;... FOR BYTE ADDRESSING		; RP041
	ADD	(SP)+,R0	;ADD CORRECTION OFFSET TO CORRECTION LIM; RP041
	C      MP	R0,#377		;IS THE CORRECTION ENTIRELY IN THIS BLOC; RP041
	BHI	50$		;IF HI NOT AT ALL			; RP041
	BEQ	40$		;IF EQ THEN ONLY ONE WORD		; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
									; RP041
	XOR	R2,(R1)		;CORRECT HIGH ORDER WORD		; RP041
40$:	XOR	R3,-(R1)	;CORRECT LOW ORDER WORD			; RP041
									; RP041
	.IFF	;M$$EIS							; RP041
									; RP041
	MOV	(R1),R0		;COPY HIGH ORDER DATA WORD		; RP041
	BIC	R2,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R2		      ;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R2,(R1)		;PATTERN.OR.DATA WORD			; RP041
40$:	MOV	-(R1),R0	;COPY LOW ORDER DATA WORD		; RP041
	BIC	R3,(R1)		;.NOT.PATTERN.AND.DATA WORD		; RP041
	BIC	R0,R3		;.NOT.DATA WORD.AND.PATTERN		; RP041
	BIS	R3,(R1)		;PATTERN.OR.DATA WORD			; RP041
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
50$:	MOV	#IS.SUC&377,R0	;ASSUME SUCCESSFUL TRANSFER		; RP041
	MOV	(SP)+,R1	;RESTORE BYTES TRANSFERRED		; RP041
	MOV	S.CSR(R4),R2	;RESTORE       CSR ADDRESS			; RP041
	MOVB	S.CON(R4),R3	;RESTORE CONTROLLER INDEX		; RP041
	RETURN			;					; RP041
									;**-89
	.ENDC



;+
; **-$CRPAS - COMMON REGISTER PASS ROUTINE
;
; THIS SUBROUTINE IS USED TO PASS THE CONTENTS OF THE DEVICE REGISTERS
; BACK TO THE DIAGNOSTIC TASK.  ALL REGISTERS ARE PASSED IN THE ORDER
; IN WHICH THEY APPEAR ON THE UNIBUS.
;
; NOTE: THIS ROUTINE MAKES USE OF THE ERROR LOGGING ENTRIES S.ROFF AND
;	S.RCNT IN THE SCB.  THEREFORE ERROR LOGGING MUST BE ENABLED IN
;	OR      DER TO USE THIS ROUTINE.
;
; INPUTS:
;
;	R1=I/O PACKET ADDRESS
;	R2=CSR ADDRESS
;	R4=SCB ADDRESS
;	R5=UCB ADDRESS
;
; OUTPUTS:
;
;	R1=DESTROYED
;	R0,R2 ARE PRESERVED
;-


	.IF DF	D$$IAG

$CRPAS::MOV	R0,-(SP)	;SAVE R0


	.IF DF	M$$MGE

	MOV	I.PRM+14(R1),KISAR6 ;SET RELOCATION BIAS

	.ENDC


	MOV	I.PRM+16(R1),R0	;GET REGISTER BUFFER ADDRESS
	MOV	R2,-(SP)	;PRESERVE INITIAL CSR ADDRESS
	MOVB	S.ROFF(R4),R2	;GET OFFSET TO FIRST REGISTER
	ADD	(SP),R2		;ADD CSR ADDRESS
	MOVB	S.RCNT(R   À  4),R1	;GET NUMBER OF REGISTERS TO XFER
10$:	MOV	(R2)+,(R0)+	;TRANSFER A REGISTER
	DEC	R1		;DONE YET?
	BNE	10$		;IF NE NO


	.IF DF	M$$EXT

	BIT	#DV.EXT,U.CW1(R5)  ;IS IT AN EXTENDED MEMORY DEVICE?	; RP041
	BEQ	20$		;IF EQ NO				;**-1
	MOV	(R2)+,(R0)+	;TRANSFER RHBAE				;**-10
	MOV	(R2),(R0)	;TRANSFER RHCS3
									;**-3
	.ENDC


20$:	MOV	(SP)+,R2	;RESTORE CSR ADDRESS
	MOV	(SP)+,R0	;RESTORE R0
	RETURN

	.ENDC



	.END
 À         #wkQ	› c,        	.TITLE	EXESB
	.IDENT	/01.11/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.11
;
; M. S. HARVEY	21-AUG-80
;
; PREVIOUSLY MODIFIED BY:
;
; MODIFIED BY:
;
;	M. S. HARVEY	15-AUG-79
;		MSH049 -- DETECT GROUP GLOBAL EVENT FLAG CONVERSION.
;
;	M. S. HARVEY	11-SEP-79
;		MSH045 -- ADD DIRECTIVE PARTITION SUPPORT      
;
;	M. S. HARVEY	19-DEC-79
;		MSH076 -- IMPLEMENT GROUP GLOBAL EVENT FLAG USE CONTROL
;			  FOR SLAVE TASKS
;
;	M. S. HARVEY	21-AUG-80
;		MSH112 -- CREATE THIS SOURCE MODULE FROM IOSUB.
;			  ALL CORRECTIONS LISTED ABOVE CAME FROM IOSUB.
;
;	P. J. BEZEREDI 13-NOV-80
;		PB194 -- USE EIS INSTRUCTION SET WHERE APPLICABLE.
;
;	M. S. HARVEY	5-MAY-81
;		MSH165 -- $GTGEF MOVED TO SECOND EXECUTIVE COMMON
;
;	M. S. HARVEY	14-SEP-81
;		MSH189 -- RETURN MORE INFORMATION ABOUT ADDRESS
;			  CHECK FAIL      URE
;
;	M. S. HARVEY	17-SEP-81
;		MSH190 -- UPDATE CONDITIONALIZATION
;
; EXECUTIVE GENERAL ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	HDRDF$,HWDDF$,PKTDF$,TCBDF$				;MSH049
	HDRDF$			;DEFINE TASK HEADER OFFSETS		;**-1
	HWDDF$			;DEFINE HARDWARE REGISTERS
	PKTDF$			;DEFINE GROUP GLOBAL CONTROL BLK OFFSETS;MSH049
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS


;+
; **-$ACHKP-ADDRESS CHECK PARAMETER BLOCK
; **-$ACHKW-ADDRESS CHECK PARAMETER BLOCK WORD ALIGNED
; **-$ACHK2-ADDRESS CHECK 2 BY      TE DIRECTIVE PARAMETER BLOCK
;
; THESE ROUTINES ARE CALLED TO ADDRESS CHECK A TASK SPECIFIED PARAMETER
; BLOCK TO INSURE IT IS WITHIN THE TASK'S ADDRESS SPACE AND ALIGNED PROPERLY.
; IF EITHER CHECK FAILS, THEN A DIRECTIVE STATUS OF 'D.RS98' IS RETURNED.
;
; INPUTS:
;
;	R0=STARTING ADDRESS OF THE BLOCK TO BE CHECKED.
;	R1=LENGTH OF THE BLOCK TO BE CHECKED IN BYTES.
;
; OUTPUTS:
;
;	THE SPECIFIED BLOCK IS CHECKED FOR PROPER ALIGNMENT AND WHETHER
;	IT IS WITHIN THE TASK'S ADDRESS SPACE. IF EITHE      R CHECK FAILS,
;	THEN A DIRECTIVE STATUS OF 'D.RS98' IS RETURNED. ELSE A RETURN
;	TO THE CALLER IS EXECUTED.
;
;	R0 AND R3 ARE PRESERVED ACROSS CALL.
;-


	.IF DF	A$$CHK!M$$MGE

	.ENABL	LSB


	.IF NDF	M$$MGE

$ACHK2::MOV	#2,R1		;SET TO CHECK 2 BYTES

	.IFTF

$ACHKP::MOV	R3,R0		;SET ADDRESS OF BLOCK TO CHECK

	.IFF

	CALL	$ACHCK		;ADDRESS CHECK WORD ALIGNED
	BCS	10$		;IF CS CHECK FAILURE
	CALL	$RELOC		;RELOCATE PARAMETER BLOCK ADDRESS
	MOV	R1,KISAR6	;MAP TO PARAMETER BLOCK
	MOV	R2,      R3		;REDEFINE PARAMETER BLOCK ADDRESS
	RETURN			;

	.ENDC


$ACHKW::CALL	$ACHCK		;ADDRESS CHECK WORD ALIGNED
	BCC	50$		;IF CC OKAY
10$:	DRSTS	D.RS98		;SET DIRECTIVE STATUS


;+
; **-$ACHKB-ADDRESS CHECK BYTE ALIGNED
; **-$ACHCK-ADDRESS CHECK WORD ALIGNED
;
; THIS ROUTINE IS CALLED TO ADDRESS CHECK A BLOCK OF MEMORY TO SEE WHETHER
; IT LIES WITHIN THE ADDRESS SPACE OF THE CURRENT TASK.
;
; INPUTS:
;
;	R0=STARTING ADDRESS OF THE BLOCK TO BE CHECKED.
;	R1=LENGTH OF THE BLOCK TO BE CHECKED       IN BYTES.
;
; OUTPUTS:
;
;	C=1 IF ADDRESS CHECK FAILED.
;		N=0 IF FAILURE RETURNED ONLY BECAUSE THE BLOCK LIES	;MSH189
;		    WITHIN A READ-ONLY REGION				;MSH189
;		N=1 IF FAILURE RETURNED FOR ANY OTHER REASON		;MSH189
;	C=0 IF ADDRESS CHECK SUCCEEDED.
;
;	R0 AND R3 ARE PRESERVED ACROSS CALL.
;-

$ACHCK::ASR	R0		;ODD ADDRESS?
	BCS	50$		;IF CS YES
	ASL	R0		;REALIGN ADDRESS
$ACHKB::			;REFERENCE LABEL


	.IF NDF	M$$MGE

	SAVNR			;SAVE R4 AND R5

	.IFTF

	MOV	$TKTCB,R2	;GET TCB ADDRES      S OF CURRENT TASK
	CLC			;ASSUME TASK IS PRIVILEGED
	BIT	#T3.PRV,T.ST3(R2) ;PRIVILEGED TASK?
	BNE	50$		;IF NE YES
	DEC	R1		;CALCULATE HIGHEST ADDRESS OF BLOCK
	ADD	R0,R1		;
	BCS	50$		;IF CS ADDRESS WRAP AROUND

	.IFF

	MOV	$HEADR,R2	;GET ADDRESS OF CURRENT TASK HEADER
	MOV	H.WND(R2),R2	;POINT TO NUMBER OF WINDOW BLOCKS
	MOV	(R2)+,-(SP)	;PUSH NUMBER OF WINDOW BLOCKS

	.IFT

	MOV	$HEADR,R4	;GET ADDRESS OF CURRENT TASK HEADER
	MOV	H.WND(R4),R2	;POINT TO NUMBER OF WINDOW BLOCKS
	MOV	(R2)+,-(SP      )	;PUSH NUMBER OF WINDOW BLOCKS
	MOV	(R2),R5		;SAVE PCB ADDRESS OF TASK PARTITION

	.IFTF

15$:	TST	(R2)+		;IS NEXT WINDOW MAPPED? (W.BPCB)
	BEQ	20$		;IF EQ NO
	CMP	R0,(R2)		;COMPARE LOW LIMITS (W.BLVR)
	BLO	20$		;IF LO NOT IN DESCRIPTOR
	CMP	R1,2(R2)	;COMPARE HIGH LIMITS (W.BHVR)
	BLOS	25$		;IF LOS BUFFER IS IN DESCRIPTOR
20$:	ADD	#W.BLGH-2,R2	;POINT TO NEXT DESCRIPTOR
	DEC	(SP)		;MORE DESCRIPTORS TO GO?
	BGT	15$		;IF GT YES
	BR	30$		;ELSE EXIT WITH CS
25$:				;REFERENCE LABEL

	.IFT

	C      MP	-(R2),R5	;TASK PARTITION?
	BNE	40$		;IF NE NO
	CMP	R0,H.GARD(R4)	;HEADER VIOLATION?
	BHI	40$		;IF HI NO

	.IFF

	BIT	#4,W.BLPD-W.BLVR(R2) ;WRITE ACCESS PERMITTED?
	BNE	40$		;IF NE YES
	COM	(SP)		;READ-ONLY REGION, RETURN N=0		;MSH189

	.ENDC


30$:	COM	(SP)+		;CLEAN STACK AND SET CARRY
	RETURN			;
40$:	TST	(SP)+		;CLEAN STACK AND CLEAR CARRY
50$:	RETURN			;
	.DSABL	LSB

	.ENDC

;+									;MSH049
; **-$CEFNG-CONVERT EVENT FLAG AND LOCK GROUP GLOBALS FOR DIRECTIVE	;MSH049
; **-$CEF      IG-CONVERT EVENT FLAG AND LOCK GROUP GLOBALS FOR I/O		;MSH049
;									;MSH049
; THIS ROUTINE IS CALLED TO CONVERT AN EVENT FLAG NUMBER TO AN		;MSH049
; EVENT FLAG MASK WORD AND EVENT FLAG MASK ADDRESS. IF THE EVENT	;MSH049
; FLAG IS GROUP GLOBAL, POINT THE GROUP GLOBAL USE COUNT POINTER IN	;MSH049
; SYSTEM COMMON TO THE FLAG WORD RETURNED IN R1. IF R1 IS ODD, R1	;MSH049
; IS POINTING TO THE SECOND GROUP OF GROUP GLOBAL EVENT FLAGS.		;MSH049
;									;MSH049
; INPUTS:								;MSH049
;									;MS      H049
;	R0=EVENT FLAG TO BE CONVERTED.					;MSH049
;	R3=ADDRESS CONTAINING EVENT FLAG NUMBER ($CEFNG ONLY)		;MSH049
;	R5=TCB ADDRESS OF THE TASK THE EFN APPLIES TO.			;MSH049
;									;MSH049
; OUTPUTS:								;MSH049
;									;MSH049
;	C=1 IF NO EVENT FLAG NUMBER WAS SPECIFIED.			;MSH049
;		R0=ZERO.						;MSH049
;		R1=ZERO.						;MSH049
;	C=0 IF AN EVENT FLAG NUMBER WAS SPECIFIED.			;MSH049
;		R0=EVENT FLAG MASK WORD.				;MSH049
;		R1=EVENT FLAG MASK ADDRESS.				;MSH049
;			R1 IS EVEN IF THE       EVENT FLAG NUMBER = 65.-80.	;MSH049
;			R1 IS ODD IF THE EVENT FLAG NUMBER = 81.-96.	;MSH049
;									;MSH049
;	R3 IS PRESERVED ACROSS CALL IF ENTRY AT $CEFIG, ELSE R3 IS	;MSH049
;	   ADVANCED BY 2.						;MSH049
;									;MSH049
;-									;MSH049
									;MSH049
	.ENABLE	LSB							;MSH049
									;MSH049
	.IF DF	G$$EFN							;MSH049
									;MSH049
$CEFIG::CALL	$CEFI		;CONVERT THE EVENT FLAG			;MSH049
	BR	5$		;JOIN COMMON CODE			;MSH049
$CEFNG::CALL	$CEFN		;CONVERT THE EVENT FLAG			;MSH0      49
5$:	BCS	30$		;IF CS RETURN				;MSH049
	BNE	30$		;IF NE RETURN				;MSH049
	MOV	R1,-(SP)	;SAVE GROUP GLOBAL MASK ADDRESS		;MSH049
	ASSUME	G.CNT+2,G.EFLG	;MUST BE CONTIGUOUS			;MSH049
	ASR	R1		;GET SECOND MASK INDICATOR		;MSH049
	SBC	R1		;IF SECOND MASK, SUBTRACT FOR IT	;MSH049
	DEC	R1		;POINT TO GROUP GLOBAL USE COUNT	;MSH049
	ASL	R1		;RESTORE TO WORD ADDRESS		;MSH049
	MOV	R1,@#$GEFPT	;LOAD GROUP GLOBAL USE COUNT POINTER	;MSH049
	MOV	(SP)+,R1	;RESTORE EVENT FLAG MASK ADDRESS	;MSH049
									;MS      H076
	.IF DF	R$$SND!A$$CLI						;MSH190
									;MSH076
	MOV	R5,$GFTCB	;DISPATCHER WILL MAINTAIN THE CORRECT	;MSH076
	ADD	#T.GGF,$GFTCB	; GRP GBL USE COUNT PER TASK W/THIS PNTR;MSH076
									;MSH076
	.ENDC								;MSH076
									;MSH076
30$:	RETURN								;MSH049
									;MSH049
	.DSABL	LSB							;MSH049

;+
; **-$CEFN-CONVERT EVENT FLAG NUMBER FOR DIRECTIVE
; **-$CEFI-CONVERT EVENT FLAG NUMBER FOR I/O
;
; THIS ROUTINE IS CALLED TO CONVERT AN EVENT FLAG NUMBER TO AN
; EVENT FLAG MASK W      ORD AND EVENT FLAG MASK ADDRESS. IF AN ILLEGAL
; EVENT FLAG IS SPECIFIED, THEN A DIRECTIVE STATUS OF 'D.RS97' IS
; RETURNED. ELSE THE EVENT FLAG NUMBER IS CONVERTED AND THE COM-
; PONENT PARTS ARE RETURNED TO THE CALLER.
;
; INPUTS:
;
;	R0=EVENT FLAG NUMBER TO BE CONVERTED.
;	R3=ADDRESS CONTAINING EVENT FLAG NUMBER ($CEFN ONLY)		;MSH049
;	R5=TCB ADDRESS OF THE TASK THE EFN APPLIES TO.
;
; OUTPUTS:
;
;	C=1 IF NO EVENT FLAG NUMBER WAS SPECIFIED.
;		R0=ZERO.
;		R1=ZERO.
;	C=0 IF AN EVENT FLAG N      UMBER WAS SPECIFIED.
;		R0=EVENT FLAG MASK WORD.
;		R1=EVENT FLAG MASK ADDRESS.
;			R1 IS EVEN IF THE EVENT FLAG < 81.		;MSH049
;			R1 IS ODD IF THE EVENT FLAG > 81.		;MSH049
;	Z=1 IF GROUP GLOBAL EVENT FLAG CONVERTED			;MSH049
;	Z=0 IF LOCAL OR COMMON EVENT FLAG CONVERTED			;MSH049
;
;	R3 IS PRESERVED ACROSS CALL IF ENTRY AT $CEFI, ELSE R3 IS ADVANCED BY 2.
;-

	.ENABL	LSB
									;MSH049
	.IFF								;MSH049
									;MSH049
$CEFNG::			;REF LABEL				;MSH049
									;MSH049
	.IFTF							      	;MSH049
									;MSH049
$CEFN:: MOVB	(R3)+,R0	;GET EVENT FLAG NUMBER
	INC	R3		;ADVANCE TO NEXT WORD
									;MSH049
	.IFF								;MSH049
									;MSH049
$CEFIG::			;REF LABEL				;MSH049
									;MSH049
	.IFTF								;MSH049
									;MSH049
$CEFI::				;REF LABEL				;MSH049
									;MSH049
	.IFT								;MSH049
									;MSH049
	CLR	-(SP)		;INIT GROUP GLOBAL INDICATOR		;MSH049
									;MSH049
	.IFTF								;MSH049
									;MSH049
	MOV	R0,R1		;COPY EFN				;MSH049
	SEC			;ASSUME NONE       SPECIFIED			;**-1
	BEQ	30$		;IF EQ NO EFN SPECIFIED
	DEC	R0		;BACK OFF EFN BY ONE
	MOV	#32.,R2		;SET EFN DIVIDER
	MOV	R5,R1		;POINT TO FIRST TASK MASK WORD
	ADD	#T.EFLG,R1	;
	CMP	R0,R2		;IN TASK EFN SET?
	BLO	10$		;IF LO YES
	SUB	R2,R0		;NORMALIZE TO COMMON SET
	CMP	R0,R2		;LEGAL EFN?

	.IFT								;MSH049
									;**-1
	BLO	5$		;IF LO YES
	SUB	R2,R0		;NORMALIZE TO GROUP GLOBAL SET
	CMP	R0,R2		;LEGAL EFN?
	BHIS	40$		;IF HIS NO
									;MSH045
	.IF DF	D$$PAR							;MSH045
									;MSH0      45
	MOV	KISAR5,-(SP)	;SAVE OLD KERNEL APR 5 MAPPING		;MSH045
	MOV	$XCOM2,KISAR5	;MAP THE SECOND EXECUTIVE COMMON	;MSH165
									;MSH045
	.IFTF								;MSH045
									;MSH045
	CALL	$GTGEF		;GET ADDRESS OF GROUP GLOBAL EF'S
									;MSH045
	.IFT								;MSH045
									;MSH045
	MOV	(SP)+,KISAR5	;RESTORE KISAR5 MAPPING			;MSH045
									;MSH045
	.ENDC								;MSH045
									;MSH045
	BCS	40$		;IF CS NO SUCH FLAG OR TASK CHECKPOINTED;MSH049
	DEC	(SP)		;FLAG THAT FLAG WAS FOUND		;MSH049
	BR	      10$		;USE GROUP GLOBAL SET
5$:				;REF LABEL
	.IFF								;MSH049
									;MSH049
	BHIS	40$		;IF HIS NO				;MSH049

	.IFTF								;MSH049
									;MSH049
	MOV	#$COMEF,R1	;POINT TO FIRST COMMON MASK WORD	;**-1
10$:	ASR	R2		;HALVE DIVIDER
	CMP	R0,R2		;FIRST MASK WORD?
	BLO	20$		;IF LO YES
	SUB	R2,R0		;NORMALIZE EFN
	TST	(R1)+		;POINT TO SECOND MASK WORD
									;MSH049
	.IFT								;MSH049
									;MSH049
	TST	(SP)		;GROUP GLOBAL FLAG FOUND?		;MSH049
	BEQ	20$		;IF EQ NO				;MSH049
	INC	      R1		;MARK AS SECOND GROUP GLOBAL WORD	;MSH049
									;MSH049
	.IFTF								;MSH049
									;MSH049
20$:	ASL	R0		;CONVERT EFN TO WORD INDEX
	MOV	$BTMSK(R0),R0	;GET PROPER MASK WORD
30$:				;REF LABEL				;MSH049
	.IFT								;MSH049
									;MSH049
	INC	(SP)+		;CLEAN STACK,PRESRV C-BIT,SET Z-BIT	;MSH049
									;MSH049
	.ENDC								;MSH049
									;MSH049
35$:	RETURN								;MSH049
40$:	DRSTS	D.RS97		;SET DIRECTIVE STATUS			;**-1


;+
; **-$DVMSG-DEVICE MESSAGE OUTPUT
;
; THIS ROUTI      NE IS CALLED TO SUBMIT A MESSAGE TO THE TASK TERMINATION
; NOTIFICATION TASK. MESSAGES ARE EITHER DEVICE RELATED OR A CHECKPOINT
; WRITE FAILURE FROM THE LOADER.
;
; INPUTS:
;
;	R4=ADDITIONAL PARAMETER
;	R5=ADDRESS OF THE UCB OR TCB THAT THE MESSAGE APPLIES TO.
;
; OUTPUTS:
;
;	A FOUR WORD PACKET IS ALLOCATED, R0 AND R5 ARE STORED IN THE
;	SECOND AND THIRD WORDS RESPECTIVELY, AND THE PACKET IS THREADED
;	INTO THE TASK TERMINATION NOTIFICATION TASK MESSAGE QUEUE.
;
;	NOTE: IF THE TASK TERMINAT      ION NOTIFICATION TASK IS NOT INSTALLED
;		OR NO STORAGE CAN BE OBTAINED, THEN THE MESSAGE REQUEST
;		IS IGNORED.
;-

$DVMSG::			;REF LABEL


	.IF DF	T$$KMG

	MOV	R0,R3		;SAVE MESSAGE NUMBER
	TST	$TKNPT		;TKTN INSTALLED?
	BEQ	35$		;IF EQ NO				;MSH049
	MOV	#8.,R1		;SET LENGTH OF BLOCK NEEDED		;**-1
	CALL	$ALOCB		;GET A CORE BLOCK
	BCS	35$		;IF CS DIDN'T GET ONE			;MSH049
	MOV	R0,R1		;SET ADDRESS OF MESSAGE BLOCK		;**-1
	TST	(R0)+		;POINT TO SECOND WORD IN BLOCK
	MOV	R3,(R0)+	;INSERT MESSAGE       NUMBER
	MOV	R5,(R0)+	;INSERT UCB OR TCB ADDRESS		;MSH049
	MOV	R4,(R0)		;INSERT ADDITIONAL PARAMETER		;**-2
	MOV	$TKNPT,R0	;PICK UP TKTN TCB ADDRESS
	CALLR	$EXRQF		;REQUEST TKTN AND QUEUE MESSAGE

	.IFF

	RETURN			;

	.ENDC


	.DSABL	LSB


;+
; **-$MPLNE-MAP LOGICAL UNIT NUMBER FOR EXIT
; **-$MPLUN-MAP LOGICAL UNIT NUMBER
;
; THIS ROUTINE IS CALLED TO VALIDATE A LOGICAL UNIT NUMBER (LUN) AND TO MAP
; THE LUN INTO A UCB POINTER. IF AN ILLEGAL LUN IS SPECIFIED, THEN A
; DIRECTIVE STATUS       OF 'D.RS96' IS RETURNED. ELSE THE LUN IS MAPPED AND A
; POINTER TO THE LUN AND UCB ARE RETURNED TO THE CALLER.
;
; INPUTS:
;
;	R3=ADDRESS OF THE LUN.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS:
;
;	C=1 IF NO DEVICE IS ASSIGNED TO THE SPECIFIED LUN.
;		R0=0.
;	C=0 IF A DEVICE IS ASSIGNED TO THE SPECIFIED LUN.
;		R0=ADDRESS OF THE UCB OF THE ASSIGNED DEVICE.
;
;	IN EITHER CASE R1 IS RETURNED AS THE ADDRESS OF THE SECOND LUN
;	WORD       IN THE TASK HEADER AND R3 IS ADVANCED BY 2.
;-

	.ENABL	LSB
$MPLUN::CLR	R1		;GET LOGICAL UNIT NUMBER
	BISB	(R3)+,R1	;
	INC	R3		;POINT TO NEXT WORD
	DEC	R1		;BACK OFF LUN BY 1
	CMP	R1,H.NLUN(R4)	;LEGAL LUN?
	BHIS	40$		;IF HIS NO
$MPLNE::ASL	R1		;MULTIPLY LUN-1 BY 4
	ASL	R1		;
	ADD	R4,R1		;CALCULATE ADDRESS OF FIRST LUN WORD
	ADD	#H.NLUN+2,R1	;IN TASK HEADER
	SEC			;ASSUME LUN NOT ASSIGNED
	MOV	(R1)+,R0	;GET POINTER TO DEVICE UCB
	BEQ	30$		;IF EQ NO DEVICE ASSIGNED
$MPLND::CMP	R0,U.RED(R0)	;I      S DEVICE REDIRECTED?
	BEQ	10$		;IF EQ NO
	MOV	U.RED(R0),R0	;GET POINTER TO REDIRECT UCB
	BR	$MPLND		;TRY AGAIN
10$:	MOV	(R0),R2		;GET ADDRESS OF DEVICE DCB
	CMP	#"TI,D.NAM(R2)	;TERMINAL INPUT PSEUDO DEVICE?
	BNE	20$		;IF NE NO
	MOV	T.UCB(R5),R0	;GET ADDRESS OF "TI" UCB
	BR	$MPLND		;
20$:	CLC			;INDICATE DEVICE ASSIGNED
30$:	RETURN			;
40$:	DRSTS	D.RS96		;SET DIRECTIVE STATUS
	.DSABL	LSB


;+
; **-$MUL-INTEGER MULTIPLY MAGNITUDE NUMBERS
;
; INPUTS:
;
;	R0=MULTIPLIER.
;	R1=MULTIPLICAND.
      ;
; OUTPUTS:
;
;	DOUBLE WORD RESULT IS RETURNED WITH THE
;	HIGH PART IN R0 AND THE LOW PART IN R1.
;
;	REGISTERS R2, R3, R4, AND R5 ARE PRESERVED ACROSS CALL.
;-

	.ENABL	LSB
$MUL::				;INTEGER MULTIPLY			; PB194
									; PB194
									; PB194
	.IF DF	M$$EIS							; PB194
									; PB194
	MUL	R1,R0		;DO THE MULTIPLY			; PB194
	RETURN			;					; PB194
									; PB194
	.IFF								; PB194
									; PB194
	MOV	R0,-(SP)	;SAVE MULTIPLIER FOR ADDS		; PB194
	MOV	#21,-(SP)	;SET REPEAT COUN      T			;**-1
	CLR	R0		;CLEAR HIGH PART
10$:	ROR	R0		;DOUBLE RIGHT SHIFT
	ROR	R1		;
	BCC	20$		;IF CC DO NOT ADD
	ADD	2(SP),R0	;
20$:	DEC	(SP)		;DECREMENT REPEAT COUNT
	BGT	10$		;IF GT MORE TO GO
	BR	50$		;EXIT TO CALLER

	.ENDC								; PB194
									; PB194

;+
; **-$DIV-INTEGER DIVIDE MAGNITUDE NUMBERS
;
; INPUTS:
;
;	R0=DIVIDEND.
;	R1=DIVISOR.
;
; OUTPUTS:
;
;	QUOTIENT IS RETURNED IN R0 AND REMAINDER IN R1.
;
;	REGISTERS R2, R3, R4, AND R5 ARE PRESERVED ACROSS CALL.
;-

$DIV::			      	;INTEGER DIVIDE				; PB194
									; PB194
									; PB194
	.IF DF	M$$EIS							; PB194
									; PB194
	MOV	R2,-(SP)	;SAVE WORKING REGISTER			; PB194
	MOV	R1,R2		;COPY DIVISOR				; PB194
	MOV	R0,R1		;MOVE DIVIDEND				; PB194
	CLR	R0		;ZERO QUOTENT				; PB194
	DIV	R2,R0		;DIVIDE					; PB194
	MOV	(SP)+,R2	;RESTORE WORKING REGISTER		; PB194
	RETURN			;					; PB194
									; PB194
	.IFF								; PB194
									; PB194
	MOV	#20,-(SP)	;SET LOOP COUNT				; PB194
	MOV	R1,-(SP)	;SAVE DIVISOR FO   °  R SUBTRACTS		;**-1
	CLR	R1		;CLEAR REMAINDER
30$:	ASL	R0		;DOUBLE LEFT SHIFT
	ROL	R1		;
	CMP	R1,(SP)		;SUBTRACT OUT DIVISOR?
	BLO	40$		;IF LO NO
	SUB	(SP),R1		;SUBTRACT OUT DIVISOR
	INC	R0		;ADD IN LOW BIT
40$:	DEC	2(SP)		;DECREMENT REPEAT COUNT
	BGT	30$		;IF GT MORE TO GO
50$:	CMP	(SP)+,(SP)+	;CLEAN STACK
	RETURN			;
									; PB194
	.ENDC								; PB194
									; PB194
									; PB194
	.DSABL	LSB

	.END
 °         RÀkQ	› c,        	.TITLE	MEMAP
	.IDENT	/01.09/
 
;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
; 
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.09
;
; M. S. HARVEY	21-AUG-80
;
; PREVIOUSLY MODIFIED BY:
;
; MODIFIED BY:
;
;	M. S. HARVEY	19-JUN-79
;		MSH037 -- DON'T ALLOCATE EXTRA UMR FOR N*4096 BUFFERS.
;			  ALSO, CLEAN UP CODE A BIT.
;
;	M. S. HARVEY	21-AUG-80
;		MSH112       -- CREATE THIS SOURCE MODULE FROM IOSUB.
;			  ALL CORRECTIONS LISTED ABOVE CAME FROM IOSUB.
;
;	P. J. BEZEREDI 13-NOV-80
;		PB194 -- USE EIS INSTRUCTION SET WHERE APPLICABLE.
;
;	R. T. PERRON	21-NOV-80
;		RP041 -- CHANGE INTERFACE TO $RELOP ROUTINE.
;			 REQUIRED BY CHANGE TO $ECCOR ROUTINE.
;
;	D. R. DONCHIN	09-JUN-81
;		DD098 -- ADD ANCILLARY CONTROL DRIVER SUPPORT.
;
;	R. T. PERRON	24-AUG-81
;		RP071 -- CLARIFY COMMENTS CONCERNING EXTENDED MEMORY SUPPORT
;
;	R. T. PERRON	16-OCT-81
;
;      		RP075 -- CORRECT NON-EIS ADDRESS CALCULATION IN $RELOP
;
; MEMORY MAPPING ROUTINES
;
; MACRO LIBRARY CALLS
;

	.MCALL	HWDDF$
	HWDDF$			;DEFINE HARDWARE REGISTERS



;+
; **-$MPPHY-MAP TO PHYSICAL ADDRESS
;
; THIS ROUTINE IS CALLED TO MAP A RELOCATION BIAS AND DISPLACEMENT ADDRESS TO AN
; 18 BIT PHYSICAL ADDRESS. IF THE INDICATED DEVICE IS NOT AN NPR AN DEVICE,
; THEN THE RELOCATION BIAS AND DISPLACEMENT ADDRESS ARE RETURNED TO THE CALLER.
; ELSE THE RELOCATION BIAS AND DISPLACEMENT ADDRE      SS ARE CONVERTED TO AN 18 BIT
; PHYSICAL ADDRESS WHICH IS RETURNED TO THE CALLER.
;
; INPUTS:
;
;	R1=RELOCATION BIAS.
;	R2=DISPLACEMENT ADDRESS.
;	R5=ADDRESS OF THE UNIT CONTROL BLOCK.
;
; OUTPUTS:
;
;	IF DEVICE IS AN NPR DEVICE ON AN 18-BIT MACHINE, THEN
;		R1=HIGH ORDER 2 BITS OF PHYSICAL ADDRESS IN BITS 4 AND 5.
;		R2=LOW ORDER 16 BITS OF PHYSICAL ADDRESS.
;	IF DEVICE IS AN NPR DEVICE ON AN 11/70, THEN
;		R1=HIGH ORDER 6 BITS OF PHYSICAL ADDRESS IN HIGH BYTE.
;		R2=LOW ORDER 16 BITS OF PH      YSICAL ADDRESS.
;	IF DEVICE IS NOT AN NPR DEVICE, THEN
;		R1=RELOCATION BIAS.
;		R2=DISPLACEMENT ADDRESS.
;
;	R0 AND R3 ARE PRESERVED ACROSS CALL.
;-


	.IF DF	M$$MGE

$MPPHY::BITB	#UC.NPR,U.CTL(R5) ;NPR DEVICE?
	BEQ	10$		;IF EQ NO
	ASL	R2		;REMOVE APR6 BIAS FROM DISPLACEMENT
	ASL	R2		;
	CLC			;GET 2 BITS OF RELOCATION BIAS
	ROR	R1		;
	RORB	R2		;TO FILL 8 LOW ORDER BITS OF ADDRESS
	ASR	R1		;
	RORB	R2		;
	SWAB	R2		;SWAP TO COLLECT 8 MORE BITS
	BISB	R1,R2		;INSERT UPPER 8 BITS OF ADDRESS      
	SWAB	R2		;SWAP BACK TO REAL ADDRESS
	CLRB	R1		;CLEAR LOW BYTE OF UPPER BITS


	.IF NDF	M$$EXT

									; PB194
	.IF DF	M$$EIS							; PB194
									; PB194
	ASH	#-4,R1		;POSITION ADDRESS BITS			; PB194
									; PB194
	.IFF								; PB194
									; PB194
	ASR	R1		;SHIFT BITS 17 AND 18 OF ADDRESS
	ASR	R1		;INTO BITS 4 AND 5
	ASR	R1		;
	ASR	R1		;
									; PB194
	.ENDC								; PB194

	.ENDC


10$:	RETURN			;

	.ENDC



;+
; **-$MPUB1-MAP UNIBUS TO MEMORY (ALTERNATE ENTRY)      
;
; THIS ROUTINE IS CALLED BY UNIBUS NPR DEVICE DRIVERS TO LOAD THE 	; RP071
; NECESSARY UNIBUS MAP REGISTERS TO EFFECT A TRANSFER TO MAIN 		; RP071
; MEMORY ON PDP-11 PROCESSORS WITH EXTENDED MEMORY. THIS ALTERNATE 	; RP071
; ENTRY POINT ALLOWS THE DRIVER TO SPECIFY A NON-STANDARD UMR MAPPING 	; RP071
; ASSIGNMENT BLOCK.							; RP071
;									;**-5
; INPUTS:
;
;	R0=ADDRESS OF A UMR MAPPING ASSIGNMENT BLOCK
;	R4=ADDRESS OF DEVICE SCB					;MSH037
;	R5=ADDRESS OF DEVICE UCB					;MSH037
;
; OU      TPUTS:
;
;	THE UNIBUS MAP REGISTERS NECESSARY TO EFFECT THE
;	TRANSFER ARE LOADED
;
; NOTE: REGISTER R3 IS PRESERVED ACROSS CALL.
;-


	.IF DF M$$EXT&M$$MGE

$MPUB1::MOV	M.UMRN(R0),-(SP) ;SET COUNT OF REGISTERS TO LOAD
	MOVB	M.BFVH(R0),R1	;GET HIGH 6 BITS OF ADDRESS
	MOV	M.BFVL(R0),R2	;GET LOW 16 BITS OF ADDRESS
	MOV	M.UMRA(R0),R0	;GET ADDRESS OF FIRST MAP REGISTER
	BR	MPUB2		;GO LOAD THE UMRS			;MSH037
									;**-4

;+
; **-$MPUBM-MAP UNIBUS TO MEMORY
;
; THIS ROUTINE IS CALLED BY UN      IBUS NPR DEVICE DRIVERS TO LOAD THE 	; RP071
; NECESSARY UNIBUS MAP REGISTERS TO EFFECT A TRANSFER TO MAIN MEM-	; RP071
; ORY ON PDP-11 PROCESSORS WITH EXTENDED MEMORY.			; RP071
;									;**-3
; INPUTS:
;
;	R4=ADDRESS OF DEVICE SCB.
;	R5=ADDRESS OF DEVICE UCB.
;
; OUTPUTS:
;
;	THE UNIBUS MAP REGISTERS NECESSARY TO EFFECT THE  TRANSFER
;	ARE LOADED.
;
; NOTE: REGISTER R3 IS PRESERVED ACROSS CALL.
;-

									;**-2
$MPUBM::MOV	S.MPR+M.UMRA(R4),R0 ;GET ADDRESS OF FIRST MAP REGISTER
	MOV	S      .MPR+M.UMRN(R4),-(SP) ;SET COUNT OF REGISTERS TO LOAD
	MOVB	S.MPR+M.BFVH(R4),R1 ;GET HIGH 6 BITS OF ADDRESS
	MOV	S.MPR+M.BFVL(R4),R2 ;GET LOW 16 BITS OF ADDRESS
MPUB2:	MOV	R2,(R0)+	;LOAD LOW 16 BITS OF ADDRESS		;MSH037
	MOV	R1,(R0)+	;LOAD HIGH 6 BITS OF ADDRESS		;**-1
	ADD	#20000,R2	;ADVANCE 8K BYTES
	ADC	R1		;
	SUB	#4,(SP)		;ALL REGISTERS LOADED?
	BGT	MPUB2		;IF GT NO				;MSH037
	TST	(SP)+		;CLEAN STACK				;**-1
	RETURN

	.ENDC



;+
; **-$RELOC-RELOCATE USER VIRTUAL ADDRESS
;
; THIS ROU      TINE IS CALLED TO TRANSFORM A 16 BIT USER VIRTUAL ADDRESS
; INTO A RELOCATION BIAS AND DISPLACEMENT IN BLOCK RELATIVE TO APR6.
;
; INPUTS:
;
;	R0=USER VIRTUAL ADDRESS TO RELOCATE.
;
; OUTPUTS:
;
;	R1=RELOCATION BIAS TO BE LOADED INTO PAR6.
;	R2=DISPLACEMENT IN BLOCK PLUS 140000 (PAR6 BIAS).
;
;	R0 AND R3 ARE PRESERVED ACROSS CALL.
;-

$RELOC::			;REF LABEL


	.IF NDF	M$$MGE

	MOV	R0,R2		;COPY PHYSICAL ADDRESS
	CLR	R1		;CLEAR RELOCATION BIAS

	.IFF

	MOV	R0,R1		;COPY VIRTUAL ADDRESS      
									; PB194
	.IF DF	M$$EIS							; PB194
									; PB194
	ASH	#-6,R1		;CALCULATE BLOCK NUMBER			; PB194
	BIC	#177600,R1	;ISOLATE IT				; PB194
	MOV	R0,R2		;COPY VIRTUAL ADDRESS			; PB194
	ASH	#-12.,R2	;CALCULATE APR INDEX			; PB194
	BIC	#177761,R2	;ISOLATE IT				; PB194
									; PB194
	.IFF								; PB194
									; PB194
	CLR	R2		;ZERO APR NUMBER ACCUMULATOR
	ASL	R1		;COLLECT APR NUMBER
	ROL	R2		;
	ASL	R1		;
	ROL	R2		;
	ASL	R1		;
	ROL	R2		;
	ASL	R2		;CONVERT TO APR INDEX
	CLRB	R      1		;CLEAR EXTRANEOUS BITS
	SWAB	R1		;COLLECT BLOCK NUMBER IN LOW BYTE
	ROR	R1		;
									; PB194
	.ENDC								; PB194
									; PB194
									; PB194
	ADD	UISAR0(R2),R1	;CALCULATE RELOCATION BIAS
	MOV	R0,R2		;COPY VIRTUAL ADDRESS
	BIC	#177700,R2	;CLEAR ALL BUT DISPLACEMENT IN BLOCK
	BIS	#140000,R2	;SET APR 6 BIAS

	.ENDC


	RETURN			;


;+
; **-$RELOM-RELOCATE AND MAP ADDRESS
;
; THIS ROUTINE IS CALLED TO TRANSFORM A 16 BIT USER VIRTUAL ADDRESS
; INTO A RELOCATION BIAS AND DISPLACE      MENT IN BLOCK RELATIVE TO APR6
; AND LOAD THESE VALUES FOR ACCESS BY THE CALLER.
;
; INPUTS:
;
;	R0=USER VIRTUAL ADDRESS TO RELOCATE.
;
; OUTPUTS:
;
;	R0=DISPLACEMENT IN BLOCK.
;	KISAR6 IS LOADED WITH THE RELOCATION BIAS.
;
;	R3 IS PRESERVED ACROSS CALL.
;-


	.IF DF	M$$MGE

$RELOM::CALL	$RELOC		;RELOCATE USER VIRTUAL ADDRESS
	MOV	R1,KISAR6	;SET KERNEL MAPPING REGISTER
	MOV	R2,R0		;SET DISPLACEMENT IN BLOCK ADDRESS
	RETURN			;

	.ENDC


;+
; **-$ASUMR-ASSIGN UNIBUS MAPPING REGISTE      RS
;
; THIS ROUTINE IS CALLED TO ASSIGN A CONTIGUOUS SET OF UMR'S.  NOTE THAT
; FOR THE SAKE OF SPEED, THE LINK WORD OF EACH MAPPING ASSIGNMENT BLOCK
; POINTS TO THE UMR ADDRESS (2ND) WORD OF THE BLOCK, NOT THE FIRST WORD.
; THE CURRENT STATE OF UMR ASSIGNMENT IS REPRESENTED BY A LINKED LIST OF
; MAPPING ASSIGNMENT BLOCKS, EACH BLOCK CONTAINING THE ADDRESS OF THE
; FIRST UMR ASSIGNED AND THE NUMBER OF UMR'S ASSIGNED TIMES 4.  THE
; BLOCKS ARE LINKED IN THE ORDER OF INCREASING FIRST UMR ADDRESS.
;
      ; INPUTS:
;
;	R0=POINTER TO A MAPPING REGISTER ASSIGNMENT BLOCK.
;	M.UMRN(R0)=NUMBER OF UMR'S REQUIRED * 4.
;
; OUTPUTS:
;
;	ALL REGISTERS ARE PRESERVED.
;
;	C=0 IF THE UMR'S WERE SUCCESSFULLY ASSIGNED.
;		ALL FIELDS OF THE MAPPING REGISTER ASSIGNMENT BLOCK
;			ARE INITIALIZED AND THE BLOCK IS LINKED INTO
;			THE ASSIGNMENT LIST.
;	C=1 IF THE UMR'S COULD NOT BE ASSIGNED.
;-


	.IF DF	M$$EXT

$ASUMR::SAVNR			;SAVE R4 AND R5
	TST	(R0)+		;SKIP OVER LINK WORD (M.LNK)
	MOV	#$UMRHD+2,R5	;POIN      T TO UMR ASSIGNMENT LISTHEAD + 2
10$:	MOV	R5,R4		;SAVE POINTER TO PREVIOUS
	BEQ	30$		;IF EQ ASSIGNMENT FAILURE
	MOV	(R5),(R0)	;POINT TO NEXT FREE UMR (M.UMRA)(M.UMRA)
	ADD	M.UMRN-M.UMRA(R5),(R0) ;(M.UMRA)
	MOV	#UBMPR+<31.*4>,-(SP) ;PUSH POINTER PAST LAST UMR
	MOV	-(R5),R5	;POINT TO NEXT ASSIGNMENT BLOCK (M.LNK)
	BEQ	20$		;IF EQ THERE IS NONE
	MOV	(R5),(SP)	;SET NEXT ALLOCATED UMR ADDRESS (M.UMRA)
20$:	SUB	(R0),(SP)	;CALCULATE # OF FREE UMR'S * 4 (M.UMRA)
	CMP	(SP)+,M.UMRN-M.UMRA(R0) ;ENOUGH UMR'S       AVAILABLE?
	BLO	10$		;IF LO NO
	MOV	R0,-(R4)	;LINK NEW BLOCK TO PREVIOUS (M.LNK)
	MOV	(R0),R4		;SAVE FIRST UMR ADDRESS (M.UMRA)
	MOV	R5,-2(R0)	;POINT NEW BLOCK TO NEXT IN LIST (M.LNK)
	MOV	R4,R5		;DUPLICATE FIRST UMR ADDRESS
	BICB	#UBMPR!34,R5	;MASK OUT ALL BUT HI 2 BITS IN LOW BYTE
	BIC	R5,R4		;CLEAR OUT HIGH BYTE AND HIGH 2 BITS
	ASR	R5		;SHIFT HIGH 2 BITS TO BITS 4 & 5
	ASLB	R4		;CALCULATE HIGH BYTE OF LOW 16 BITS
	ASL	R4		;   (LOSING BIT 200 FIRST)
	ASL	R4		;
	SWAB	R4		;FORM LOW SIXTEEN BITS       OF ADDRESS
	MOV	M.BFVL-2(R0),M.UMVL-2(R0) ; GET ORIGINAL BUFFER ADDRESS
	BIC	#^C<1>,M.UMVL-2(R0) ; WAS IT ODD ?
	ADD	R4,M.UMVL-2(R0)	; IF IT WAS, THEN M.UMVL SHOULD BE
	MOVB	R5,M.UMVH-2(R0)	;SET BITS 4 & 5
30$:	DEC	R0		;PNT BACK TO LINK WORD PRESERVING CARRY
	DEC	R0		;
	RETURN			;


;+
; **-$DEUMR-DEASSIGN UNIBUS MAPPING REGISTERS
;
; THIS ROUTINE IS CALLED TO DEASSIGN A CONTIGUOUS BLOCK OF UMR'S. IF
; THE MAPPING ASSIGNMENT BLOCK IS NOT IN THE LIST, NO ACTION IS TAKEN.
; NOTE THAT FOR THE S      AKE OF ASSIGNMENT SPEED, THE LINK WORD POINTS TO
; THE UMR ADDRESS (2ND) WORD OF THE ASSIGNMENT BLOCK.
;
; INPUTS:
;
;	R2=POINTER TO ASSIGNMENT BLOCK.
;
; OUTPUTS:
;
;	R0 AND R1 ARE PRESERVED.
;-

$DEUMR::TST	(R2)+		;SKIP OVER LINK WORD (M.LNK)
	MOV	#$UMRHD+2,R3	;POINT TO ASSIGNMENT LISTHEAD + 2
10$:	CMP	-(R3),R2	;IS IT THE NEXT ONE? (M.LNK)
	BEQ	20$		;IF EQ YES
	MOV	(R3),R3		;ELSE POINT TO NEXT IN LIST (M.LNK)
	BNE	10$		;IF NE THERE IS ONE
	BR	30$		;ELSE MAPPING ASSIGNMENT BLK NOT IN LIST      
20$:	MOV	-(R2),(R3)	;UNLINK THE BLOCK (M.LNK)(M.LNK)
30$:	RETURN			;


;+
; **-$STMP1-SET UP UNIBUS MAPPING ADDRESS (ALTERNATE ENTRY)
;
; THIS ENTRY CODE SETS UP AN ALTERNATE DATA STRUCTURE USED AS
; A UMR MAPPING ASSIGNMENT BLOCK AND CONTEXT STORAGE BLOCK, IN
; THE SAME MANNER AS $STMAP USES THE FORK BLOCK AND MAPPING
; BLOCK IN THE SCB. THE FORMAT OF THE STRUCTURE IS AS FOLLOWS:
;
;	---------------------
;	!		    !		4 WORDS USED FOR SAVING
;	!		    !		DRIVER'S CONTEXT IN CASE
;	!		    !		      UMR'S CAN'T BE MAPPED
;	!		    !		IMMEDIATELY.
;	---------------------
;	!		    !
;	!		    !		6 WORDS USED AS A UMR
;	!		    !		MAPPING ASSIGNMENT BLOCK.
;	!		    !
;	!		    !
;	!		    !
;	---------------------
;
;
; INPUTS:
;
;	R0=ADDRESS OF THE DATA STRUCTURE DEPICTED ABOVE
;	R4=ADDRESS OF DEVICE SCB
;	R5=ADDRESS OF DEVICE UCB
;
; OUTPUTS:
;
;	DATA STRUCTURE POINTERS SET UP FOR ENTRY TO $STMP2 IN $STMAP
;
;-


$STMP1::MOV	S.FRK+10(R4),6(R0) ;SAVE DRIVER'S MAPPING
	MOV	R0,R4		;COP      Y BLOCK POINTER
	ADD	#M.LGTH+10,R0	;POINT PAST MAPPING BLOCK
	CMP	(R4)+,(R4)+	;POINT TO CONTEXT SAVE BLOCK		;MSH037
	BR	STMP2		;SET UP THE UMR ADDRESS			;MSH037
									;**-2

;+
; **-$STMAP-SET UP UNIBUS MAPPING ADDRESS
;
; THIS ROUTINE IS CALLED BY UNIBUS NPR DEVICE DRIVERS TO SET UP THE
; UNIBUS MAPPING ADDRESS, FIRST ASSIGNING THE UMR'S.  IF THE UMR'S
; CANNOT BE ALLOCATED, THE DRIVER'S MAPPING ASSIGNMENT BLOCK IS PLACED
; IN A WAIT QUEUE AND A RETURN TO THE DRIVER'S CALLER IS EXECUTED.  TH      E
; ASSIGNMENT BLOCK WILL EVENTUALLY BE DEQUEUED WHEN THE UMR'S ARE
; AVAILABLE AND THE DRIVER WILL BE REMAPPED AND RETURNED TO WITH R1-R5
; PRESERVED AND THE NORMAL OUTPUTS OF THIS ROUTINE.  THE DRIVER'S
; CONTEXT IS STORED IN THE ASSIGNMENT BLOCK AND FORK BLOCK WHILE IT IS
; BLOCKED AND IN THE WAIT QUEUE.  ONCE A DRIVER'S MAPPING ASSIGNMENT
; BLOCK IS PLACED IN THE UMR WAIT QUEUE, IT IS NOT REMOVED FROM THE
; QUEUE UNTIL THE UMR'S ARE SUCCESSFULLY ASSIGNED.  THIS STRATEGY
; ASSURES THAT WAITING DR      IVERS WILL BE SERVICED FIFO AND THAT DRIVER'S
; WITH LARGE REQUESTS FOR UMR'S WILL NOT WAIT INDEFINATELY.
;
; INPUTS:
;
;	R4=ADDRESS OF DEVICE SCB.
;	R5=ADDRESS OF DEVICE UCB.
;	(SP)=RETURN TO DRIVER'S CALLER.
;
; OUTPUTS:
;
;	UNIBUS MAP ADDRESSES ARE SET UP IN THE DEVICE UCB AND THE
;	ACTUAL PHYSICAL ADDRESS IS MOVED TO THE SCB.
;
; NOTE: REGISTERS R1, R2, AND R3 ARE PRESERVED ACROSS CALL.
;-

$STMAP::MOV	R4,R0		;COPY SCB POINTER
	ADD	#S.MPR+M.LGTH,R0 ;POINT PAST MAPPING ASSIGNMENT BLOCK      
	ADD	#S.FRK+6,R4	;POINT INTO FORK BLOCK
STMP2:	MOV	U.BUF+2(R5),-(R0) ;SAVE LOW 16 BITS OF ADDRESS (M.BFVL)	;MSH037
	MOVB	U.BUF+1(R5),-(R0) ;SAVE HIGH 6 BITS OF ADDRESS (M.BFVH)	;**-1
	DEC	R0		;POINT BACK TO NEXT WORD
	MOV	U.CNT(R5),-(R0)	;TEMORARILY STORE BYTE COUNT (M.UMVL)
	CLR	-(R0)		;INITIALIZE UMR COUNT (M.UMRN)
	BIT	#1,M.BFVL-M.UMRN(R0) ; BUFFER ADDRESS ODD ?
	BEQ	10$		; IF EQ NO, ALL IS NORMAL
	INC	2(R0)		; IT'S ODD, WE MUST MAP ONE EXTRA BYTE
10$:	ADD	#4,(R0)		;INCREASE COUNT FOR ONE UMR (      M.UMRN)
	SUB	#20000,2(R0)	;REDUCE BYTE COUNT BY 8K BYTES (M.UMVL)
	BHI	10$		;IF HI MORE BYTES TO GO			;MSH037
	TST	-(R0)		;(M.UMRA)				;**-1
	MOV	-(R0),-(SP)	;SAVE POSSIBLE WAIT QUEUE LINK (M.LNK)
	CALL	$ASUMR		;ATTEMPT TO ASSIGN REQUIRED UMR'S
	BCC	20$		;IF CC SUCCESSFUL, CHECK FOR UMR WAIT
	TST	(SP)+		;CLEAR STACK
	MOV	R5,(R4)		;SAVE R5 IN FORK BLOCK (S.FRK+6)
	MOV	(SP)+,-(R4)	;SAVE DRIVER'S RETURN ADDRESS (S.FRK+4)
	MOV	R0,-(R4)	;SAVE MAPPING BLOCK POINTER (S.FRK+2)
	CALL	$WTUMR		;WAIT FOR CHA      NGE IN UMR ASSIGNMENT
	MOV	(R4)+,R0	;RESTORE MAPPING BLOCK POINTER (S.FRK+2)
	ADD	#M.LGTH,R0	;POINT PAST MAPPING BLOCK
	MOV	(R4)+,-(SP)	;RESTORE DRIVER'S RETURN ADDR (S.FRK+4)
	MOV	(R4),R5		;RESTORE R5 (S.FRK+6)
	MOV	2(R4),KISAR5	;REMAP DRIVER (S.FRK+10)
	BR	STMP2		;TRY AGAIN				;MSH037
20$:	MOV	U.SCB(R5),R4	;RESTORE R4				;**-1
	MOV	M.UMVL(R0),U.BUF+2(R5) ;STORE LOW WORD OF UMR VIRT ADDR
	MOVB	M.UMVH(R0),U.BUF(R5) ;STORE HIGH SIX BITS
	CLRB	U.BUF+1(R5)	;CLEAR HIGH-ORDER BYTE
	CMP	$UMRWT,R0	;WAS       THIS CALLER WAITING?
	BNE	30$		;IF NE NO
	MOV	(SP),$UMRWT	;DEQUEUE CURRENT CALLER'S BLOCK
	BNE	30$		;IF NE NOT END OF LIST
	MOV	#$UMRWT,$UMRWT+2 ;UPDATE LAST IN LIST POINTER
30$:	TST	(SP)+		;CLEAR STACK


;+
; **-$DQUMR-DEQUEUE FROM UMR WAIT
;
; CONTROL IS TRANSFERRED HERE TO SEE IF A DRIVER IS WAITING FOR UMR
; ASSIGNMENT.  FIRST THE CALLING DRIVER IS CALLED BACK AS A COROUTINE.
; WHEN THE CALLING DRIVER ISSUES A RETURN BACK TO THIS ROUTINE, A CHECK
; IS MADE TO SEE IF ANY DRIVERS ARE WAITING       FOR UMR'S.  IF SO THE WAIT-
; ING DRIVER'S CONTEXT IS RESTORED WITHOUT ACTUALLY DEQUEUEING THE
; MAPPING ASSIGNMENT BLOCK AND CONTROL IS PASSED BACK TO THE ORIGINAL
; UMR ASSIGNMENT ROUTINE.
;
; INPUTS:
;
;	(SP)=RETURN ADDRESS TO DRIVER'S CALLER..
;
; OUTPUTS:
;
;	IF ANYONE IS WAITING THEIR CONTEXT IS RESTORED AND THE ALLOCA-
;	TION ROUTINE IS CALLED BACK.
;-

	.ENABL	LSB
$DQUMR::CALL	@(SP)+		;CALL THE CALLER AS COROUTINE
	MOV	$UMRWT,R0	;ANYONE WAITING FOR UMR ASSIGNMENT?
	BEQ	10$		;IF EQ       HE HAS SINCE GONE AWAY
	TST	(R0)+		;POINT TO SAVED R1
	MOV	(R0)+,R1	;RESTORE SAVED REGISTERS
	MOV	(R0)+,R2	;
	MOV	(R0)+,R3	;
	MOV	(R0)+,R4	;
	JMP	@(R0)+		;JUMP BACK TO ALLOCATION ROUTINE


;+
; **-$WTUMR-WAIT FOR CHANGE IN UMR STATE
;
; THIS ROUTINE STORES R1-R4 AND THE RETURN PC IN THE MAPPING ASSIGNMENT
; AND QUEUES THE BLOCK IN THE UMR WAIT QUEUE FOR A SUBSEQUENT RECALL TO
; THE CALLER WHEN THE STATE OF UMR ASSIGNMENT CHANGES.  NOTE THAT IT IS
; POSSIBLE FOR THE MAPPING ASSIGNMENT BLOCK T      O ALREADY BE IN THE WAIT
; QUEUE, BUT IF IT IS IT CAN ONLY BE AT THE HEAD OF THE QUEUE.
;
; INPUTS:
;
;	R0=POINTER TO UMR ASSIGNMENT BLOCK
;
; OUTPUTS:
;
;	THE ASSIGNMENT BLOCK IS QUEUED IN THE UMR WAIT QUEUE.
;	THE CALLER IS EVENTUALLY RETURNED TO AT SYSTEM STATE WITH R1-R4
;		PRESERVED.
;-

$WTUMR::MOV	(SP)+,12(R0)	;STORE RETURN ADDR TO ALLOCATE ROUTINE
	CMP	R0,$UMRWT	;MAPPING ASSIGNMENT BLK ALREADY IN LIST?
	BEQ	5$		;IF EQ YES
	MOV	R0,@$UMRWT+2	;LINK BLOCK TO LAST IN QUEUE
	MOV	R0,$UMRW      T+2	;UPDATE LAST IN LIST POINTER
	CLR	(R0)		;ZERO LINK WORD
5$:	TST	(R0)+		;POINT PAST LINK WORD
	MOV	R1,(R0)+	;SAVE CALLER'S REGISTERS
	MOV	R2,(R0)+	;
	MOV	R3,(R0)+	;
	MOV	R4,(R0)+	;
10$:	RETURN			;RETURN TO CALLER'S CALLER
	.DSABL	LSB

	.ENDC



;+
; **-$RELOP-RELOCATE UNIBUS PHYSICAL ADDRESS
;
; THIS ROUTINE RELOCATES A UNIBUS PHYSICAL ADDRESS TO A KISAR6
; BIAS AND DISPLACEMENT.
;
; INPUTS:
;
;	R0=BYTE OFFSET FROM ADDRESS IN U.BUF+1 AND U.BUF+2		; RP041
;	R4=SCB ADDRESS							; RP      041
;	R5=UCB ADDRESS							; RP041
;									; RP041
;	IF DEVICE IS AN NPR DEVICE ON AN 18-BIT MACHINE, THEN		; RP041
;		U.BUF+1(R5)=HIGH ORDER BITS OF PHYSICAL ADDRESS		; RP041
;		U.BUF+2(R5)=LOW ORDER BITS OF PHYSICAL ADDRESS		; RP041
;	IF DEVICE IS AN NPR DEVICE ON A 22-BIT MACHINE, THEN		; RP041
;		M.BFVL+S.MPR(R4)=LOW ORDER BITS OF PHYSICAL BUFFER ADDRE; RP041
;		M.BFVH+S.MPR(R4)=HIGH ORDER BITS OF PHYSICAL BUFFER ADDR; RP041
;	IF DEVICE IS AN NPR DEVICE ON A 22-BIT MACHINE AND CAN DIRECTLY	;       RP041
;	ADDRESS MAIN MEMORY, THEN					; RP041
;		U.BUF+1(R5)=HIGH ORDER BITS OF PHYSICAL ADDRESS		; RP041
;		U.BUF+2(R5)=LOW ORDER BITS OF PHYSICAL ADDRESS		; RP041
;									;**-4
; OUTPUTS:
;
;	KISAR6=CALCULATED BIAS (MAPPED SYSTEM)
;	R1=REAL ADDRESS OR DISPLACEMENT
;-


	.IF DF	D$$IAG!S$$ECC

$RELOP::			;
	MOV	R0,-(SP)	;SAVE BYTE OFFSET ON STACK		; RP041
	MOV	U.BUF+2(R5),R1	;GET LOW 16 BITS OF ADDRESS		; RP041


	.IF DF	M$$MGE

	MOVB	U.BUF+1(R5),R0	;GET HIGH BITS OF REAL ADDRESS		; R      P041
									; RP041
									; RP041
	.IF DF	M$$EXT							; RP041
									; RP041
	BIT	#DV.EXT,U.CW1(R5)  ;CAN THIS CONTROLLER/UNIT DIRECTLY ..; RP041
				;... ADDRESS ALL OF PHYSICAL MEMORY	; RP041
	BNE	10$		;IF NE YES, ADDRESS IS OK		; RP041
	ADD	#<S.MPR+M.LGTH>,R4  ;POINT PAST PHYSICAL BUFFER ADDRESS ; RP041
				;... CONTAINED IN UMR AREA		; RP041
	MOV	-(R4),R1	;REPLACE STARTING PHSYICAL BUFFER ...	; RP041
				;... ADDRESS IN R1			; RP041
	TSTB	-(R4)		;SKIP NEXT BYTE				; RP041
	MOVB	-(R4      ),R0	;MOVE HIGH BITS IN PLACE OF MEM EXT BITS; RP041
10$:	MOV	U.SCB(R5),R4	;RESTORE SCB ADDRESS			; RP041
									; RP041
	.ENDC	;M$$EXT							; RP041
									; RP041
	.IFF	;M$$MGE							; RP041
									; RP041
	CLR	R0		;					; RP041
									; RP041
	.IFTF	;M$$MGE							; RP041
									; RP041
	ADD	(SP),R1		;CALCULATE NEW STARTING ADDRESS ...	; RP041
	ADC	R0		;...					; RP041
									; RP041
	.IFT	;M$$MGE							; RP041
									; RP041
									; RP041
	.IF DF	M$$EIS							; RP041
		      							; RP041
	ASHC	#10.,R0		;CALCULATE DISPLACEMENT AND BIAS	; RP041
	ASHC	#-10.,R1	;...					; RP041
									; RP041
	.IFF	;M$$EIS							; RP041
									; RP041
	MOV	#10.,-(SP)	;SET COUNT FOR 10 SHIFTS		; RP041
20$:	DEC	(SP)		;ANY MORE SHIFTS TO PERFORM		; RP041
	BLT	30$		;IF LT NO				; RP041
	ASL	R1		;DOUBLE LEFT SHIFT R1 ...		; RP075
	ROL	R0		;... INTO R0				; RP075
	BR	20$		;					; RP075
30$:	SWAB	R1		;SWAP BYTES				; RP075
	ASR	R1		;SHIFT RIGHT R1				; RP075
	ASR	R1		;...					; RP075
      	TST	(SP)+		;CLR THE STACK				; RP075
									; RP041
	.ENDC	;M$$EIS							; RP041
									; RP041
									; RP041
	MOV	R0,KISAR6	;SET RELOCATION BIAS			; RP041
	ADD	#140000,R1	;SET DISPLACEMENT			; RP041
									; RP041
	.IFTF	;M$$MGE							; RP041
									; RP041
	MOV	(SP)+,R0	;RETRIEVE BYTE OFFSET			; RP041
									; RP041
	.ENDC	;M$$MGE							; RP041
									;**-36

	RETURN			;

	.ENDC



;+									; DD098
; **-$SWACD-SAVE MAPPING, CALL ACD AS A CO-ROUTINE, THEN REMAP DRIVE      R	; DD098
; **-$SWAC1-CALL ACD AS A CO-ROUTINE, THEN REMAP DRIVER			; DD098
;									; DD098
; THESE ROUTINES ARE CALLED BY THE FULL DUPLEX TERMINAL DRIVER TO	; DD098
; SWITCH PROCESSING TO AN ANCILLARY CONTROL DRIVER (ACD).  SINCE THE	; DD098
; ACD REQUIRES APRS 5 AND 6, THE DRIVER MAPPING IS FIRST SAVED (IF ENTRY; DD098
; AT $SWACD), THEN THE ACD IS CALLED AS A CO-ROUTINE VIA A DISPATCH	; DD098
; TABLE CONTAINED IN THE ANCILLARY CONTROL BLOCK (ACB).  WHEN THE ACD	; DD098
; RETURNS, THIS ROUTINE R      EMAPS THE DRIVER AND RETURNS CONTROL TO IT.	; DD098
;									; DD098
; INPUTS:								; DD098
;									; DD098
;	R0=DISPATCH TABLE OFFSET (IF ENTRY AT $SWACD).			; DD098
;	R0=ACB ADDRESS (IF ENTRY AT $SWAC1).				; DD098
;	R5=POINTER TO OFFSET U.TSTA WITHIN THE TERMINAL'S UCB.		; DD098
;	2(SP)=DISPATCH TABLE OFFSET (IF ENTRY AT $SWAC1).		; DD098
;	4(SP)=APR5 BIAS OF TERMINAL DRIVER (IF ENTRY AT $SWAC1).	; DD098
;									; DD098
; OUTPUTS:								; DD098
;									; DD098
;	R0 IS DESTROYED.				      		; DD098
;-									; DD098
									; DD098
	.IF DF	T$$CPW&T$$ACD						; DD098
									; DD098
$SWACD::MOV	KINAR5,-(SP)	;SAVE TERMINAL DRIVER MAPPING		; DD098
	MOV	R0,-(SP)	;PUT ENTRY POINT OFFSET ON STACK	; DD098
	MOV	U.ACD-U.TSTA(R5),R0 ;GET ACB ADDRESS			; DD098
$SWAC1::MOV	(R0),KINAR5	;MAP THE ANCILLARY CONTROL DRIVER	; DD098
	ADD	A.DIS(R0),(SP)	;ADD DISPATCH TABLE ADDR TO THE OFFSET	; DD098
	MOV	@(SP),(SP)	;GET THE ENTRY POINT ADDRESS		; DD098
	CALL	@(SP)+		;CALL THE ACD				; DD098
	MOV	   Ì   (SP)+,KINAR5	;UPON RETURN, REMAP THE TERMINAL DRIVER	; DD098
	RETURN			;AND THEN RETURN TO IT			; DD098
									; DD098
	.ENDC	;T$$CPW&T$$ACD						; DD098
									; DD098
									; DD098
	.END
 Ì          L!ðskQ	› c,        	.TITLE	EMDRV
	.IDENT	/01.0/
 
; 
; COPYRIGHT (C) 1981
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
; 
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
; 
; VERSION 01.0
; 
; T. LEKAS 2-FEB-81
;
; RH11-ML-11 MEMORY SYSTEM DRIVER
; 
; MACRO LIBRARY CALLS
; 
 
	.MCALL	HWDDF$,PKTDF$
	HWDDF$			; DEFINE HARDWARE REGISTERS
	PKTDF$			; DEFINE I/O PACKET OFFSETS
	
	
	.IF DF	D$$IAG
	
	.MCALL	UMDIO$
	UMDIO$			; DE      FINE USER-MODE DIAGNOSTIC DEFINITIONS
	
	.ENDC
	
 
; 
; EQUATED SYMBOLS
; 
 
RETRY=8.			; ERROR RETRY COUNT
MLWC=2				; WORD COUNT REGISTER
MLBA=4				; UNIBUS ADDRESS REGISTER
MLDS=12				; DRIVE STATUS REGISTER
MLCS2=10			; SECOND STATUS REGISTER
MLER1=14			; ERROR REGISTER
MLAS=16				; ATTENTION SUMMARY REGISTER
MLDA=6				; DESIRED ADDRESS REGISTER
MLBAE=50			; BUS ADDRESS EXTENSION REGISTER

; 
; LOCAL DATA
; 
; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER)
; 
 
CNT      BL:	.BLKW	M$$L11		; ADDRESS OF CURRENT UNIT CONTROL BLOCK
RTTBL:	.BLKW	M$$L11		; RETRY COUNT FOR CURRENT OPERATION
 
 
	.IF GT	M$$L11-1
 
TEMP:	.BLKW	1		; TEMPORARY STORAGE FOR CONTROLLER NUMBER
 
	.ENDC
 
; 
; DRIVER DISPATCH TABLE
; 
 
$EMTBL::.WORD	EMINI		; DEVICE INITIATOR ENTRY POINT
	.WORD	EMCAN		; CANCEL I/O OPERATION ENTRY POINT
	.WORD	EMOUT		; DEVICE TIMEOUT ENTRY POINT
	.WORD	EMPWF		; POWERFAIL ENTRY POINT
 
; +
; **-EMINI-RH11-ML-11 MEMORY SYSTEM INITIATOR
; 
; THIS ROUTINE       IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU-
; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT
; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS
; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER-
; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED.
; 
; INPUTS:
; 
; 	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED      .
; 
; OUTPUTS:
; 
; 	IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT-
; 	ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER-
; 	ATION IS INITIATED.
; -
 
	.ENABL	LSB
EMINI:	CALL	$GTPKT		; GET AN I/O PACKET TO PROCESS
	BCS	EMCAN		; IF CS CONTROLLER BUSY OR NO REQUEST
 
; 
; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT:
; 
; 	R1=ADDRESS OF THE I/O REQUEST PACKET.
; 	R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
; 	R3=CONTROLLER INDEX.
; 	R4=ADDRESS OF THE       STATUS CONTROL BLOCK.
; 	R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
; 
; RH11-ML-11 MEMORY SYSTEM I/O REQUEST PACKET FORMAT:
; 
; 	WD. 00 -- I/O QUEUE THREAD WORD.
; 	WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER.
; 	WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK.
; 	WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER.
; 	WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADER (UCB).
; 	WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB).
; 	WD. 06 -- VIRTUAL ADD      RESS OF I/O STATUS BLOCK.
; 	WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK.
; 	WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000).
; 	WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
; 	WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER.
; 	WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER.
; 	WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED.
; 	WD. 15 -- NOT USED.
; 	WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED.
; 	WD. 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST.
; 	WD. 20 -      - RELOCATION BIAS OF DIAGNOSTIC REG. ADRS ELSE NOT USED
; 	WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000)
; 
 
	MOV	R5,CNTBL(R3)	; SAVE ADDRESS OF REQUEST UCB
	
	
	.IF DF	M$$EXT&M$$MGE

	BIT	#DV.MBC,U.CW1(R5)  ; IS IT A 22 BIT MASS BUS DEVICE?
	BNE	1$		; IF NE YES -- DOES NOT USE UMR'S
	CALL	$STMAP		; SET UP UNIBUS MAP

	.ENDC


	ASL	U.BUF(R5)	; SHIFT ADDRESS EXTENSION BITS INTO PLACE
	ASL	U.BUF(R5)	; 
	ASL	U.BUF(R5)	; 
	ASL	U.BUF(R5)	; 
1$:				; REF LABEL
	
	
	.IF DF	D$$I      AG
	
	CMP	#IO.WCK!IQ.UMD,I.FCN(R1)  ; DIAGNOSTIC WRITE CHECK?
	BNE	5$		; IF NE NO
	BIS	#151,U.BUF(R5)	; YES, SET FUNCTION CODE
	BR	10$		; 
	
	.ENDC
	
	
5$:	MOV	#IE.IFC&377,R0	; ASSUME ILLEGAL FUNCTION
	BIS	#171,U.BUF(R5)	; ASSUME READ LOGICAL FUNCTION
	CMPB	#IO.RLB/256.,I.FCN+1(R1) ; READ LOGICAL FUNCTION?
	BHIS	6$		; IF HIS FUNCTION IS LEGAL
	JMP	70$		; FUNCTION IS ILLEGAL
6$:	BEQ	10$		; IF EQ FUNCTION IS READ
	SUB	#10,U.BUF(R5)	; CONVERT TO WRITE LOGICAL FUNCTION
10$:	MOV	#RETRY,RTTBL(R3)       ; SET RETRY COUNT
	CALL	$BLKCK		; CHECK LOGICAL BLOCK NUMBER
	MOV	R0,I.PRM+12(R3)	; SAVE DISK ADDRESS
 
; 
; INITIATE I/O OPERATION
; 
 
30$:				; REF LABEL


	.IF DF	M$$EXT&M$$MGE

	BIT	#DV.MBC,U.CW1(R5)  ; IS IT A 22 BIT MASS BUS DEVICE?
	BNE	300$		; IF NE YES -- DOES NOT USE UMR'S
	CALL	$MPUBM		; MAP UNIBUS TO MEMORY
300$:				; REF LABEL

	.ENDC


	MOV	S.CSR(R4),R2	; GET ADDRESS OF CSR
	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS
	MOVB	S.ITM(R4),S.CTM(R4)  ; SET CURRENT DEVICE TIMEO      UT COUNT
	MOV	#40,MLCS2(R2)	; CLEAR RH11 CONTROLLER AND ALL DRIVES
	MOVB	U.UNIT(R5),MLCS2(R2)  ; SELECT PROPER DRIVE
	MOV	I.PRM+12(R1),MLDA(R2)  ; INSERT DISK ADDRESS
	ADD	#MLBA,R2	; POINT TO BUS ADDRESS REGISTER
	MOV	U.BUF+2(R5),(R2)  ; INSERT BUFFER ADDRESS
	MOV	U.CNT(R5),-(R2)	; INSERT NUMBER OF BYTES TO TRANSFER
	ROR	(R2)		; CONVERT TO WORD COUNT
	NEG	(R2)		; MAKE NEGATIVE WORD COUNT
	TST	-(R2)		; POINT TO CSR REGISTER
	MOV	#IE.DNR&377,R0	; ASSUME DRIVE NOT READY
	MOV	MLDS(R2),R3	; GET CONTEN      TS OF DRIVE STATUS REGISTER
	COM	R3		; COMPLEMENT STATUS
	BIT	#10600,R3	; DRIVE READY AND ON-LINE?
	BEQ	32$		; IF EQ YES


	.IF DF	D$$IAG

	BITB	#IQ.UMD,I.FCN(R1)  ; DIAGNOSTIC OPERATION?
	BEQ	31$		; IF EQ NO
	JMP	45$		; LOG DIAGNOSTIC DRIVE NOT READY
31$:				; REF LABEL

	.ENDC


	.IF DF	E$$DVC

	CALL	$DVCER		; LOG DRIVE NOT READY ERROR

	.ENDC


	JMP	60$		; FINISH I/O
32$:				; REF LABEL

	
	
	.IF DF	E$$DVC
	
	CALL	$BMSET		; SET I/O ACTIVE BIT IN MAP
	
	.ENDC
	
	
	.IF DF      	M$$EXT&M$$MGE

	BIT	#DV.MBC,U.CW1(R5)  ;;; IS IT A 22 BIT MASS BUS DEVICE?
	BEQ	34$		;;; IF EQ NO -- DOES USE UMR'S
	MOVB	U.BUF+1(R5),MLBAE(R2)  ;;; SET ADDRESS EXTENSION BITS
	MOVB	U.BUF(R5),(R2)	;;; START FUNCTION
	RETURN			;;; 

	.ENDC


34$:	MOV	U.BUF(R5),(R2)	;;; START FUNCTION
	
 
; 
; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES.
; 
 
EMCAN:	RETURN			;;; NOP FOR ML-11

; +
; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND
; CAUSES NO IMMEDIATE ACTION ON TH      E UNIT.
; -

EMPWF:				; POWERFAIL ENTRY POINT


	.IF DF	P$$RFL

	BISB	#US.SPU,U.STS(R5)  ; SET UNIT "SPINNING UP"

	.ENDC


	RETURN			; WAIT FOR UNIT TO RESPOND
	
 
; +
; **-$EMINT-RH11-ML-11 MEMORY SYSTEM CONTROLLER INTERRUPTS
; -
 
	INTSE$	EM,PR5,M$$L11	;;; SAVE REGISTERS AND SET PRIORITY
	CALL	$FORK		;;; CREATE A SYSTEM PROCESS
	MOV	R4,R3		; COPY CONTROLLER INDEX
	MOV	U.SCB(R5),R4	; GET ADDRESS OF SCB
	MOV	#IS.SUC&377,R0	; ASSUME SUCCESSFUL TRANSFER
	MOV	S.CSR(R4),R2	; GET ADDRE      SS OF CSR
	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS
	
	
	.IF DF	D$$IAG
	
	BITB	#IQ.UMD,I.FCN(R1)  ; DIAGNOSTIC FUNCTION EXECUTED?
	BNE	45$		; IF NE YES
	
	.ENDC
	
	
	BIT	#60000,(R2)	; ANY ERRORS?
	BEQ	55$		; IF EQ NO
	

	.IF DF	E$$DVC
	
	CALL	$DVCER		; LOG DEVICE ERROR
	
	.ENDC

	
	MOV	#IE.VER&377,R0	; ASSUME UNRECOVERABLE ERROR
	MOV	MLER1(R2),R1	; GET CONTENTS OF ERROR REGISTER
	BIT	#43007,R1	; HARD ERROR?
	BNE	57$		; IF NE YES
	BIT	#14000,MLCS2(R2)  ; NEM OR NED?
	BEQ	50$		; I      F EQ NO
	BR	57$		; YES, HARD ERROR
 
; 
; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED
; UNLESS THE REQUEST WAS DIAGNOSTIC.
; 
 
EMOUT:				;;; TIMEOUT ENTRY POINT


	.IF DF	P$$RFL

	BITB	#US.SPU,U.STS(R5)  ;;; IS DRIVE "SPINNING UP"?
	BEQ	44$		;;; IF EQ NO
	BICB	#US.SPU,U.STS(R5)  ;;; RESET DRIVE "SPINNING UP"
	MTPS	#0		;;; ALLOW INTERRUPTS
	JMP	30$		; RETRY ENTIRE OPERATION
44$:	INCB	S.STS(R4)	;;; LEAVE CONTROLLER BUSY

	.ENDC


	CALL	$DTOER		;;; LOG DEVICE TIMEOUT      
	
	
	.IF DF	D$$IAG
	
	BCC	50$		; IF CC TIMEOUT DURING NORMAL FUNCTION
45$:	CALL	$CRPAS		; PASS CONTROLLER REGISTERS TO TASK
	BR	60$		; DIAGNOSTIC PROCESSING COMPLETE
	
	.ENDC
	
	
50$:	MOV	S.PKT(R4),R1	; GET I/O PACKET ADDRESS
	BITB	#IQ.X,I.FCN(R1)	; INHIBIT RETRIES?
	BNE	57$		; IF NE YES
	DEC	RTTBL(R3)	; RETRY FUNCTION?
	BLE	57$		; IF LE NO
51$:	JMP	30$		; RETRY OPERATION

55$:				; REF LABEL


	.IF DF	D$$WCK

	BITB	#IO.WLC&377,I.FCN(R1)  ; WRITE FOLLOWED BY WRITE CHECK?
	BNE	56$		;       IF NE YES
	BITB	#US.WCK,U.STS(R5)  ; WRITE CHECK ENABLED BY MCR?
	BEQ	57$		; IF EQ NO
56$:	MOVB	U.BUF(R5),R1	; GET LAST FUNCTION
	CMPB	#171,R1		; WAS IT A READ?
	BEQ	60$		; IF EQ YES
	MOVB	#151,U.BUF(R5)	; ASSUME A WRITE CHECK OPERATION
	CMPB	#161,R1		; WAS LAST FUNCTION A WRITE?
	BNE	57$		; IF NE NO
	MOV	#RETRY,RTTBL(R3); REINITIALIZE RETRY COUNT
	BR	51$		; START WRITE CHECK OPERATION

	.IFTF

57$:				; REF LABEL

	.IFT

	BIT	#40000,MLCS2(R2)  ; WRITE CHECK ERROR?
	BEQ	60$		; IF EQ NO
      	MOV	#IE.WCK&377,R0	; SET WRITE CHECK ERROR

	.ENDC


60$:	MOV	MLWC(R2),R1	; GET WORDS REMAINING TO TRANSFER
	ASL	R1		; CONVERT TO BYTES LEFT TO TRANSFER
	ADD	U.CNT(R5),R1	; CALCULATE BYTES ACTUALLY TRANSFERED
	MOV	#40011,(R2)	; CLEAR CONTROLLER AND DRIVE
70$:				; REF LABEL
	

	.IF DF	E$$DVC
	
	MOVB	S.CON(R4),R3	; RETREIVE CONTROLLER INDEX
	MOVB	RTTBL(R3),R2	; GET FINAL ERROR RETRY COUNT
	BIS	#RETRY*256.,R2	; MERGE STARTING RETRY COUNT
	
	.ENDC
 
	CALL	$IODON		; FINISH I/O OPERATION
	J   :   MP	EMINI		; PROCESS NEXT REQUEST
	.DSABL	LSB
 
	.END
 :          ÔMðskQ	› c,        	.TITLE	LRDRV
	.IDENT	/05/

; COPYRIGHT (C) 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
; DIGITAL EQUIPMENT OF CANADA LTD, KANATA, ONTARIO
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 05
;
; DAVID R. CROWE
;
; PREVIOUSLY MODIFIED BY:
;
;	DAVID H. CHAN
;	HELEN GORDON
;	PATRICIA C. LEE
;
; MODIFIED BY:
;
;	R. E. CALDWELL 21-AUG-79
;
;		RC011 -- USE CORRECT FORM OF GTPKT$.
;
; PARALLE      L COMMUNICATIONS LINK (PCL) RECEIVER DRIVER FOR RSX-11M-PLUS.
;
; MACRO LIBRARY CALLS.
;
	.MCALL	PKTDF$,TCBDF$,UCBDF$

	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS.
	UCBDF$			;DEFINE UCB OFFSETS

;+
; THIS DRIVER IS IN ONE OF A NUMBER OF SOFTWARE STATES DURING ITS
; OPERATION.  ITS CURRENT STATE IS DEFINED IN THE LOW ORDER BYTE
; OF U.CW2 IN THE UCB.  HANDLER STATES ARE DEFINED BELOW.
;
;     INDEX		MEANING
;	0	NO TASK CONNECTED.
;	2	TASK CONNECTED BUT N      OT TRIGGERED.
;	4	TASK TRIGGERED & AWAITING ATF OR RTF.
;	6	TASK CONNECTED & TIMED OUT AWAITING ATF OR RTF.
;
; ... BUSY STATES ...
; THE CONTROLLER IS CONSIDERED BUSY BY RSX-11M WHILE THE
; HANDLER IS IN THESE STATES.  THEREFORE ONLY THE INTERRUPT PROCESSOR
; NEED CONCERN ITSELF WITH THEM.  BUSY STATES ARE AS FOLLOWS:
;
;	-2	ATF IN PROGRESS.
;	-4	TASK CONNECTED, NOT TRIGGERED, & HAS ATF PENDING.
;	-6	RTF IN PROGRESS.
;
; LEGAL FUNCTIONS BY STATE.
;    FUNCTION	LEGAL STATES
;	CRX	0
;	RTF	4,       6
;	ATF	2, 4, 6
;	DRX	2, 4, 6
;-

;+
; HANDLER UCB WORK AREA OFFSET DEFINITIONS.
;-

U.TASK	=	U.CNT+2		;TCB ADDR OF CONNECTED TASK [WORD]
U.TEF	=	U.TASK+2	;TRIGGER EVENT FLAG NO. [WORD]
U.TRSB	=	U.TEF+2		;REAL ADDRESS OF TRIGGER STATUS
U.BUF1	=	U.TRSB+4	;ADDRESS OF RETURN BUFFER (2 WDS)
U.AADA	=	U.BUF1+4	;ATACHMENT DESCR. STORAGE
				; BUFFER [2 WORDS]

;+
; THE HARDWARE REGISTERS ARE DEFINED RELATIVE TO THE RCR, WHOSE
; ADDRESS IS FOUND IN THE  S.CSR  FIELD OF THE  SCB  AT RUN TIME.
;-
      
RCR	=	0		;RECEIVER COMMAND REGISTER.
RSR	=	2		;RECEIVER STATUS REGISTER.
RDDB	=	4		;RECEIVER DESTINATION DATA BUFFER.
RDBC	=	6		;RECEIVER DESTINATION BYTE COUNT.
RDBA	=	10		;RECEIVER DESTINATION BUS ADDRESS.
RDCRC	=	12		;RECEIVER DESTINATION CRC

;+
; RECEIVER COMMAND REGISTER (RCR).
;-

REJ	=	100000		;REJECT (R/W)
RCNPR	=	40000		;RECEIVER NPR (R/W)
RCVWD	=	20000		;RECEIVE WORD (R/W)
IB04	=	10000		;IDENTIFICATION BITS (RO)
IB03	=	4000		; "
IB02	=	2000		; "
IB01	=	1000		; "
IB00	=	400		;       "
LDSILO	=	200		;LOAD SILO (R/W)
IE	=	100		;INTERRUPT ENABLE (R/W)
A17	=	40		;EXTENDED ADDRESS BITS (R/W)
A16	=	20		; "
DTIRDY	=	10		;DATA INPUT READY (RO)
INHADI	=	4		;INHIBIT ADDRESS INCREMENT (R/W)
BDINIT	=	2		;BOARD INITIALIZE (WO)
RCVDAT	=	1		;RECEIVE DATA (R/W)

IB	=	IB04!IB03!IB02!IB01!IB00 ;UNION OF IDENTIFICATION BITS


;+
; RECEIVER STATUS REGISTER (RSR).
;-

ERR	=	100000		;ERROR (RO)
NEXLOC	=	40000		;NONEXISTENT LOCATION (RO)
MEMOFL	=	20000		;MEMORY OVERFLOW (R/W)
TXMERR	=	100      00		;TRANSMISSION ERROR (R/W)
PAR	=	4000		;PARITY (R/W)
TIMOUT	=	2000		;TIME OUT (R/W)
BCOFL	=	1000		;BYTE COUNT OVERFLOW (R/W)
DTORDY	=	400		;DATA OUTPUT READY (RO)
SUCTXF	=	200		;SUCCESSFUL TRANSFER (R/W)
BUSY	=	100		;BUSY (RO)
RECOM	=	40		;REJECT COMPLETE (R/W)
CHNOPN	=	20		;CHANNEL OPEN (RO)
RSPB1	=	10		;RESPONSE B1 (RO)
RSPB0	=	4		;RESPONSE B0 (RO)
RSPA1	=	2		;RESPONSE A1 (RO)
RSPA0	=	1		;RESPONSE A0 (RO)

;+
; FUNCTION DISPATCH TABLE
;-

FUNTBL:	.IRP	X,<CRX,ATF,RTF,DRX>
	.WORD	IO.'X      , X
	.ENDM
	.WORD	0		;TERMINATOR

;+
; DEVICE DISPATCH TABLE
;-

	DDT$	LR,L$$R11,,CHK	;GENERATE DISPATCH TABLE

;+
; LRCHK - PCL RECEIVER DRIVER PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O
; REQUEST IS RECEIVED FOR THE PARALLEL COMMUNICATIONS LINK RECEIVER.
; SOME PCL RECEIVER REQUESTS CONTAIN INFORMATION THAT MUST BE CHECKED
; IN THE CONTEXT OF THE ISSUING TASK; THEREFORE, THE I/O REQUEST IS NOT
; QUEUED BEFORE CALLING THE DRIVER.
;
; INPUTS:
      ;
;	R1 = ADDRESS OF THE I/O PACKET
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK
;	R5 = ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED
;
; OUTPUTS:
;
;	IF FUNCTION IS IO.CRX, ADDRESS CHECK IS PERFORMED FOR IOSB(8 BYTES)
;
;	IF THE QIO FUNCTION IS IO.ATF THEN THE RETURN BUFFER ADDRESS IS
;	CHECKED TO DETERMINE WHETHER IT LIES WITHIN THE ISSUING
;	TASK'S ADDRESS SPACE. IF IT DOES THEN THE RETURN BUFFER ADDRESS IS
;	RELOCATED AND STORED IN THE I/O PACKET. IF IT IS NOT A VALID
;	ADDRESS THEN AN       ILLEGAL BUFFER STATUS IS RETURNED AS THE FINAL
;	I/O STATUS OF THE REQUEST.
;
;	FOR ALL FUNCTION CODES, THE I/O PACKET IS INSERTED IN THE
;	CONTROLLER QUEUE AND THE DEVICE INITIATOR IS ENTERED TO START
;	THE CONTROLLER.
;-

LRCHK:	CMP	#IO.CRX,I.FCN(R1)  ;IS FUNCTION 'CRX'?
	BNE	5$		;IF NE NO
	MOV	R1,R3		;SAVE IO PACKET ADDRESS
	MOV	I.PRM+2(R3),R0	;GET VIRTUAL ADDRESS OF BUFFER
	MOV	#4.,R1		;GET LENGTH 4 BYTES
	CALL	$ACHKB		;CHECK THE ADDRESS
	BCS	10$		;IF CS BAD
	MOV	W.BATT(R2),R2	;GET ATT. D      ESC. ADD.
	INCB	A.IOC(R2)	;INCREMENT I/O COUNT
	MOV	R2,I.PRM+6(R3)	;SAVE ATT. DESC. ADDR
	CALL	$RELOC		;RELOCATE THE BUFFER
	MOV	R1,I.PRM+2(R3)	;STORE BIAS
	MOV	R2,I.PRM+4(R3)	;STORE ADDRESS
	MOV	R3,R1		;RESTORE IO PACKET ADDRESS
	BR	20$		;CONTINUE
5$:	CMP	#IO.ATF,I.FCN(R1)  ;IS FUNCTION CODE = 'ATF'?
	BNE	20$		;IF NE NO
;
; 'ATF' FUNCTION - SET UP REGISTERS FOR ADDRESS CHECK AND RELOCATION
;
;	R0 = ADDRESS TO CHECK AND RELOCATE
;	R3 = ADDRESS OF THE I/O PACKET
;
	MOV	R1,R3		;SAVE ADDRESS OF       THE I/O PACKET
	MOV	I.PRM+6(R3),R0	;GET VIRTUAL ADDRESS OF RETURN BUFFER
;
; VALIDATE THE RETURN BUFFER ADDRESS FOR THIS TASK
;
	MOV	#12.,R1		;SET LENGTH OF RETURN BUFFER TO 6 WORDS
	CALL	$ACHCK		;CHECK THE ADDRESS
	BCC	15$		;IF CC OK
;
; INVALID RETURN BUFFER ADDRESS - SET ILLEGAL BUFFER STATUS AND FINISH
;
10$:	MOV	#IE.SPC&377,R0	;SET ILLEGAL BUFFER STATUS
	CALLR	$IOFIN		;FINISH I/O OPERATION
;
; RELOCATE THE RETURN BUFFER ADDRESS
;
15$:	MOV	W.BATT(R2),R2	;GET ATT. DESC. ADDR.
	INCB	A.IO      C(R2)	;INCREMENT I/O COUNT
	MOV	R2,I.AADA+2(R3)	;SAVE PTR FOR $IODONE
	CALL	$RELOC		;RELOCATE ADDRESS
	MOV	R1,I.PRM+6(R3)	;RELOCATION BIAS ==> I/O PACKET
	MOV	R2,I.PRM+10(R3)	;16-BIT ADDRESS ==> I/O PACKET
	MOV	R3,R1		;RESTORE R1 TO I/O PACKET
;
; INSERT THE I/O PACKET IN THE QUEUE
;
20$:	MOV	R4,R0		;R0 = I/O QUEUE LISTHEAD
	CALL	$QINSP		;GO INSERT PACKET IN QUEUE
;
; NOW GET THE I/O PACKET TO PROCESS.
;
LRINI:	GTPKT$	LR,L$$R11,,,T	;GET I/O PACKET MACRO

; THE FOLLOWING ARGUMENTS ARE RETURNE      D BY $GTPKT:
;
;	R1 = ADDRESS OF THE I/O PACKET.
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB.
;	R3 = CONTROLLER INDEX.
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK.
;	R5 = ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED.
;
; I/O REQUEST PACKET FORMAT:
;
;	WD.00 = I/O QUEUE THREAD WORD
;	WD.01 = REQUEST PRIORITY, EVENT FLAG NUMBER.
;	WD.02 = TCB ADDRESS OF REQUESTER TASK.
;	WD.03 = POINTER TO 2ND LUN WORD IN REQUESTER TASK HEADER.
;	WD.04 = CONTENTS OF 1ST LUN WORD IN REQUESTER TASK HEADE      R (UCB).
;	WD.05 = I/O FUNCTION CODE.
;	WD.06 = VIRTUAL ADDRESS OF I/O STATUS BLOCK.
;	WD.07 = RELOCATION BIAS OF I/O STATUS BLOCK.
;	WD.10 = I/O STATUS BLOCK ADDRESS DISPLACEMENT + 140000.
;	WD.11 = VIRTUAL ADDRESS OF AST SERVICE ROUTINE.
;	WD.12 = FIRST PARAMETER OR RELOCATION BIAS OF DATA BUFFER
;	WD.13 = SECOND PARAMETER OR 16-BIT ADDRESS OF DATA BUFFER
;	WD.14 = THIRD PARAMETER OR LENGTH OF DATA BUFFER
;	WD.15 = FOURTH PARAMETER OR RELOCATION BIAS OF RETURN BUFFER
;	WD.16 = FIFTH PARAMETER OR       16-BIT ADDRESS OF RETURN BUFFER
;
	MOV	I.TCB(R1),R0	;GET TCB ADDRESS OF REQUESTOR
	BITB	#T2.ABO,T.ST2(R0)  ;IS TASK BEING ABORTED?
	BEQ	10$		;IF EQ NO
	CALLR	IEVER		;YES, IT'S FATAL
10$:	MOV	#FUNTBL,R0	;GET ADDRESS OF FUNCTION TABLE
20$:	CMP	(R0),I.FCN(R1)	;FUNCTION CODES MATCH?
	BEQ	30$		;IF EQ YES
	CMP	(R0)+,(R0)+	;MOVE TO NEXT ENTRY
	TST	(R0)		;END OF TABLE?
	BNE	20$		;IF NE NO
	CALLR	IEIFC		;YES, ILLEGAL FUNCTION
30$:	JMP	@2(R0)		;GO TO FUNCTION PROCESSOR

;+
; PROCESS 'CRX' FUNCTION
;      -

CRX:	CMP	I.PRM(R1),#96.	;IF TRIGGER EVENT FLAG > 64,
	BHI	20$		;IF HI BAD
	TSTB	U.CW2(R5)	;IS A TASK ALREADY CONNECTED ?
	BNE	10$		;IF NE YES
	MOV	I.PRM(R1),U.TEF(R5)  ;SAVE TRIGGER EVENT FLAG NO.
	MOV	I.PRM+2(R1),U.TRSB(R5)	;SAVE THE ADDRESS OF THE TRIGGER
	MOV	I.PRM+4(R1),U.TRSB+2(R5)  ;STATUS BUFFER
	MOV	I.TCB(R1),U.TASK(R5)  ;SAVE TCB ADDRESS
	MOV	I.PRM+6(R1),U.AADA(R5)	;SAVE ATT. DESC. ADDR.
	CALL	PRCRX		;CONNECT TASK FOR RECEPTION
	CALLR	ISSUC		;INDICATE SUCCESS AND EXIT

10$:	CALLR	I      EDAA		;SOMEONE ALREADY CONNECTED
20$:	CALLR	IEBAD		;BAD PARAMETER SPECIFIED

;+
; **-PRCRX-PERFORM ACTUAL CONNECT FOR RECEPTION
;
; THIS ROUTINE IS CALLED TO CONNECT THE RECEIVER FOR RECEPTION.
; IT ACTIVATES THE HARDWARE TO RECEIVE A WORD, WHICH WILL BE
; TREATED AS A FLAGS WORD.  IT SETS THE SOFTWARE STATE OF THE HANDLER
; TO 2. THE ROUTINE SHOULD BE CALLED WHENEVER THE HANDLER WISHES
; TO RECEIVE A FLAGS WORD.
;
; INPUTS:
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK (SCB)
;	R5 = ADDRESS OF TH      E UNIT CONTROL BLOCK (UCB)
;
; OUTPUTS:
;	THE RECEIVER IS INITIALIZED (BDINIT) & RCVWD IS SET.
;	THE HANDLER IS SET TO SOFTWARE STATE 2.
;	R0 IS SET POINTING TO THE RCR.
;-

PRCRX:	MOV	U.BUF(R5),-(SP)	;SAVE BUFFER
	MOV	U.BUF+2(R5),-(SP)  ;ADDRESS
	MOV	U.CNT(R5),-(SP)	;& COUNT.
	MOV	U.TRSB(R5),U.BUF(R5)  ;MOVE TRIGGER STATUS
	MOV	U.TRSB+2(R5),U.BUF+2(R5)  ;BUFFER ADDR TO U.BUF.
	MOV	#4,U.CNT(R5)	;LOAD BYTE COUNT.
	CLR	-(SP)		;SET STATUS BYTE TO ZERO.
	CALL	$PTBYT		; "
	MOV	(SP)+,U.CNT(R5)	;RE      STORE BUFFER
	MOV	(SP)+,U.BUF+2(R5)  ;ADDRESS
	MOV	(SP)+,U.BUF(R5)	;& COUNT.
	MOV	S.CSR(R4),R0	;GET ADDRESS OF RCR
	BIS	#BDINIT,(R0)	;INITIALIZE RECEIVER.
	BIS	#RCVWD!IE,(R0)	;PREPARE TO RECEIVE A FLAG WD.
	MOVB	#2,U.CW2(R5)	;SET HANDLER STATE TO 2.
	RETURN			;

;+
; PROCESS 'RTF' FUNCTION
;-

RTF:	CMP	I.TCB(R1),U.TASK(R5)  ;RTF FROM CONNECTED TASK?
	BEQ	10$		;IF EQ YES
	CALLR	IEDNA		;NO, DEVICE NOT AVAILABLE
10$:	MOVB	U.CW2(R5),R0	;GET HANDLER STATE.
	BIC	#^C6,R0		;MASK OUT UNWANTED BITS
      	JMP	@RTFJMP(R0)	;PROCESS FUNCTION ACCORDING STATE

RTFJMP:	.WORD	IEDNA		;STATE 0
	.WORD	IENTR		;STATE 2
	.WORD	RTFS4		;STATE 4
	.WORD	RTFS6		;STATE 6

RTFS4:	MOV	S.CSR(R4),R0	;GET ADDRESS OF RCR
	BIS	#REJ!IE,(R0)	;SET REJECT & INT ENABLE.
	MOVB	#-6,U.CW2(R5)	;SET HANDLER STATE TO -6.
	MOVB	S.ITM(R4),S.CTM(R4)  ;SET TIME OUT
	RETURN			;

RTFS6:	MOVB	#2,U.CW2(R5)	;SET HANDLER STATE TO 2.
	CALLR	IEDNR		;FORCE DRIVE NOT READY

;+
; PROCESS 'ATF' FUNCTION
;-

ATF:				;REF LABEL


	.IF DF	      M$$EXT

	CALL	$STMAP		;SET UP UNIBUS MAP ADDRESS

	.ENDC


	MOV	I.PRM+6(R1),U.BUF1(R5)	;RELOCATION BIAS ==> UCB
	MOV	I.PRM+10(R1),U.BUF1+2(R5) ;16-BIT ADDRESS ==> UCB
	CMP	I.TCB(R1),U.TASK(R5)  ;ATF FROM CONNECTED TASK?
	BEQ	10$		;IF EQ YES
	CALLR	IEDNA		;NO, DEVICE NOT AVAILABLE
10$:	MOVB	U.CW2(R5),R0	;GET HANDLER STATE.
	BIC	#^C6,R0		;CLEAR UNWANTED BITS
	JMP	@ATFJMP(R0)	;PROCESS FUNCTION ACCORDING TO STATE

ATFJMP:	.WORD	IEDNA		;STATE 0
	.WORD	ATFS2		;STATE 2
	.WORD	PRATF		;STATE 4
	.W      ORD	RTFS6		;STATE 6

ATFS2:	MOVB	#-4,U.CW2(R5)
	CLRB	S.CTM(R4)		;NO TIME OUT ON THIS
	RETURN				;

;+
; **-PRATF-PERFORM ACCEPTANCE OF TRANSFER
;
; THIS ROUTINE IS CALLED TO INITIATE THE RECEPTION OF THE MESSAGE
; WHICH HAS JUST BEEN ACCEPTED.  THE STATE OF THE HANDLER IS SET
; TO -2, WHICH INDICATES THAT THE HANDLER IS BUSY PERFORMING
; THE ACCEPT TRANSFER FUNCTION.
;
; INPUTS:
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK (SCB)
;	R5 = ADDRESS OF THE UNIT CONTROL BLOCK (UCB)
;
; OUTPUTS:
;	      THE RDBC & RDBA ARE SET UP, & AN NPR RCVDAT FUNCTION IS INITIATED.
;	THE HANDLER IS SET TO STATE -2.
;	R0 IS SET POINTING TO THE RCR.
;	R2 IS DESTROYED.
;-

PRATF:				;REF LABEL


	.IF DF	M$$EXT

	CALL	$MPUBM		;MAP UNIBUS TO MEMORY
	MOV	S.PKT(R4),R1	;RETREIVE I/O PACKET ADDRESS

	.ENDC


	MOV	S.CSR(R4),R0	;GET ADDRESS OF RCR
	MOV	U.BUF+2(R5),RDBA(R0)  ;LOAD BUFFER ADDRESS REGISTER.
	MOV	U.CNT(R5),R2	;GET BYTE COUNT.
	NEG	R2		;NEGATE IT & LOAD
	MOV	R2,RDBC(R0)	;BYTE COUNT REGISTER.
	MOV      B	#-2,U.CW2(R5)	;SET HANDLER STATE TO -2.
	BIS	#RCNPR!RCVDAT!IE,U.BUF(R5) ;SET RCNPR, RCVDAT, IE, &
	BIS	U.BUF(R5),(R0)  ;EXTENDED ADDR BITS IN RCR.
	MOVB	S.ITM(R4),S.CTM(R4)  ;SET TIME OUT
	RETURN			;

;+
; PROCESS 'DRX' FUNCTION
;-

DRX:	TSTB	U.CW2(R5)	;IS ANY TASK CONNECTED ?
	BEQ	10$		;IF EQ NO
	MOV	I.TCB(R1),R1	;YES, GET TCB ADDRESS.
	CMP	R1,U.TASK(R5)	;IS THIS TASK CONNECTED ?
	BNE	10$		;IF NE NO
	CALL	PRDRX		;DO THE DISCONNECT
	CALLR	ISSUC		;EXIT WITH SUCCESS

10$:	CALLR	IEDNA		;DEV      ICE NOT AVAILABLE

;+
; **-PRDRX-PERFORM ACTUAL DISCONNECT FROM RECEPTION
;
; THIS ROUTINE DISCONNECTS THE RECEIVING TASK FROM RECEPTION.
;
; INPUTS:
;	R1 = ADDRESS OF TCB FOR TASK.
;	R4 = SCB ADDRESS.
;	R5 = UCB ADDRESS.
;
; OUTPUTS:
;	THE I/O REQUEST COUNT FOR THE TASK IS DECREMENTED.
;	THE RECEIVER IS INITIALIZED (BDINIT).
;	THE HANDLER STATE IS SET TO 0.
;	R0 IS SET POINTING TO THE RCR.
;-

PRDRX:	MOV	U.AADA(R5),R0	;GET ATTACHMENT DESCRIPTOR ADDRESS
	DECB	A.IOC(R0)	;DECREMENT I/O COU      NT
	MOV	S.CSR(R4),R0	;GET ADDRESS OF RCR
	BIS	#BDINIT,(R0)	;INITIALIZE RECEIVER BOARD.
	CLR	U.AADA(R5)	;CLEAR ATTACHED REGION DESC.
	CLR	U.TASK(R5)	;CLEAR TCB ADDRESS OF CONNECTED TASK
	CLR	U.TEF(R5)	;CLEAR EVENT FLAG ALSO
	CLRB	U.CW2(R5)	;SET HANDLER STATE TO 0.
	RETURN			;

;+
; **-$LRINT-PCL RECEIVER INTERRUPT PROCESSOR
;
; INTERRUPTS ARE PROCESSED DEPENDING UPON THE HANDLER STATE.
;-

$LRINT::
	INTSV$	LR,PR5,L$$R11	;;;GENERATE INTERRUPT SAVE STUFF
	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS.
      	MOV	S.CSR(R4),R4	;;;GET RCR ADDRESS.
	BIC	#IE,(R4)	;;;DISABLE PCL INTERRUPTS.
	CALL	$FORK		;;;CREATE A FORK PROCESS.
	MOV	R4,R0		;COPY RCR ADDRESS
	MOV	U.SCB(R5),R4	;GET SCB ADDRESS.
	MOVB	U.CW2(R5),R2	;GET HANDLER STATE.
	JMP	@INTJMP(R2)	;PROCESS INTERRUPT ACCORDING TO STATE

	.WORD	INTM6		;STATE -6
	.WORD	INTM4		;STATE -4
	.WORD	INTM2		;STATE -2
INTJMP:	.WORD	INTP0		;STATE  0
	.WORD	INTP2		;STATE  2
	.WORD	INTP4		;STATE  4
	.WORD	INTP6		;STATE  6

;
; THE VARIOUS INTERRUPT STATE PROCESSO      RS WHICH ARE JUMPED TO
; THROUGH THE  INTJMP  TABLE ARE ENTERED WITH REGISTERS SET AS FOLLOWS:
;	R0 = RCR ADDRESS
;	R2 = HANDLER STATE
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;

INTM6:	BIT	#ERR!SUCTXF,RSR(R0)  ;ERROR OF SUCTXF?
	BNE	10$		;IF NE YES
	BIT	#RECOM,RSR(R0)	;IS RECOM SET?
	BEQ	10$		;IF EQ NO
	CALL	PRCRX		;RECONNECT FOR RECEPTION
	CALLR	ISSUC		;EXIT WITH SUCCESS

10$:	CALLR	IEFHE		;FATAL HARDWARE ERROR

INTM4:
INTP2:
INTP6:	TST	RSR(R0)		;ANY ERRORS?
	BMI	10$		;IF MI YES
	BIT	#RE      COM,RSR(R0)	;REJECT COMPLETION?
	BNE	20$		;IF NE YES
	BIT	#DTORDY,RSR(R0)	;DATA OUTPUT READY?
	BNE	40$		;IF NE YES
	CALLR	PRCRX		;RECONNECT FOR RECEPTION AND EXIT

10$:	BIT	#PAR,(R0)	;IS IT PARITY ERROR ?
	BNE	20$		;IF NE YES
	NOP
20$:	CALL	PRCRX		;RECONNECT FOR RECEPTION
	MOVB	R2,U.CW2(R5)	;MOVE STATE TO AS BEFORE.
	RETURN			;

40$:	TST	R2		;IS HANDLER STATE -4 ?
	BGE	60$		;IF GE NO, GIVE FLAGS WORD TO TASK
	TST	RDDB(R0)	;
	CALLR	PRATF		;ACCEPT TRANSFER

60$:	MOV	U.BUF(R5),-(SP)	;SAVE BUF      FER ADDR & COUNT.
	MOV	U.BUF+2(R5),-(SP)  ;
	MOV	U.CNT(R5),-(SP)	;
	MOV	U.TRSB(R5),U.BUF(R5)  ;LOAD TRIGGER STATUS BLOCK ADDRESS
	MOV	U.TRSB+2(R5),U.BUF+2(R5)  ;
	MOV	#4,U.CNT(R5)	;LOAD A BIG ENOUGH COUNT.
	CMP	R2,#2		;IS THE STATUS=2?
	BEQ	70$		;IF EQ YES
	MOV	#<IE.DAO*2>&377,R2  ; STATE 6 ==> STATUS IE.DAO
70$:	ASRB	R2		; 
	MOV	(R0),R3		;GET CONTENTS OF RCR
	BIC	#^C<IB>,R3	;ISOLATE TRANSMITTER ID.
	BIS	R3,R2		;MERGE WITH STATUS.
	MOV	R2,-(SP)	;GET FIRST STATUS WORD
	CALL	$PTWRD		;PUT IN USER      S BUFFER
	MOV	RDDB(R0),-(SP)	;GET SECOND STATUS WORD
	CALL	$PTWRD		;PUT IN USERS BUFFER
	MOV	(SP)+,U.CNT(R5)	;RESTORE COUNT AND BUFFER ADDRESS
	MOV	(SP)+,U.BUF+2(R5)  ;
	MOV	(SP)+,U.BUF(R5)	;
	MOVB	#4,U.CW2(R5)	;SET STATE TO 4.
	BIS	#IE,(R0)	;REENABLE INTERRUPTS.
	MOV	U.TEF(R5),R0	;GET TRIGGER EVENT FLAG NO.
	MOV	U.TASK(R5),R5	;GET TCB ADDR FOR CONNECTED TASK.
	BEQ	90$		;IF EQ NONE
	CALL	$CEFI		;CONV EVENT FLAG TO MASK & ADDR.
	BCS	90$		;IF CS NO FLAG SPECIFIED
	BIS	R0,(R1)		;SET FLAG
90$:	CAL      LR	$DRDSE		;DECLARE SIGNIFICANT EVENT.

INTM2:	TST	RSR(R0)		;ANY ERRORS?
	BMI	M2ERR		;IF MI YES
	TSTB	RSR(R0)		;SUCCESSFUL TRANSFER?
	BPL	M2PAR		;IF PL NO

M2SUC:	MOV	(R0),R2		;GET CONTENTS OF RCR.
	BIC	#^C<IB>,R2	;RETRIEVE TRANSMITTER ID.
	BIS	#IS.SUC,R2	;MERGE IN RETURN STATUS
	BIT	#RECOM,RSR(R0)	;REJECT COMPLETE?
	BEQ	10$		;IF EQ NO
	INC	R2		; +2 FOR TRUNCATED RECEPTION
10$:	MOV	RDBC(R0),R1	;COMPUTE LENGTH OF RECEPTION.
	ADD	U.CNT(R5),R1	;
	MOV	U.BUF(R5),-(SP)	;SAVE U.BUF
	MOV	U.BUF+2(R5)      ,-(SP)  ;SAVE U.BUF+2
	MOV	U.CNT(R5),-(SP)	;SAVE U.CNT
	MOV	U.BUF1(R5),U.BUF(R5)  ;RELOCATION BIAS ==> UCB
	BEQ	20$		;IF EQ ZERO
	MOV	U.BUF1+2(R5),U.BUF+2(R5) ;16-BIT ADDRESS ==> UCB
	BR	30$		;GO MOVE THE REGISTERS
;
; RELOCATION BIAS = 0 CHECK FOR NON-ZERO 16-BIT ADDRESS
;
20$:	MOV	U.BUF1+2(R5),U.BUF+2(R5) ;16-BIT ADDRESS ==> UCB
	BEQ	40$		;IF EQ NO RETURN ADDRESS
;
; REGISTERS REQUESTED - RETURN THEM
;
30$:	MOV	(R0)+,-(SP)	;GET CONTENTS OF REGISTER
	CALL	$PTWRD		;PUT IT IN USERS BUFFER
	MO      V	(R0)+,-(SP)	;GET CONTENTS OF REGISTER
	CALL	$PTWRD		;PUT IT IN USERS BUFFER
	MOV	(R0)+,-(SP)	;GET CONTENTS OF REGISTER
	CALL	$PTWRD		;PUT IT IN USERS BUFFER
	MOV	(R0)+,-(SP)	;GET CONTENTS OF REGISTER
	CALL	$PTWRD		;PUT IT IN USERS BUFFER
	MOV	(R0)+,-(SP)	;GET CONTENTS OF REGISTER
	CALL	$PTWRD		;PUT IT IN USERS BUFFER
;
; CONTINUE PROCESSING
;
40$:	MOV	(SP)+,U.CNT(R5)	;RESTORE U.CNT
	MOV	(SP)+,U.BUF+2(R5)  ;RESTORE U.BUF+2
	MOV	(SP)+,U.BUF(R5)	;RESTORE U.BUF
	CALL	PRCRX		;RECONNECT FOR RECEPT      ION
	MOV	R2,R0		;COPY STATUS CODE
	CALLR	IODON		;FINISH I/O AND EXIT

M2ERR:	MOV	RSR(R0),R1	;GET CONTENTS OF RSR
	BIT	#BCOFL,R1	;CHECK FOR BYTE COUNT
	BNE	10$		;IF NE OVERFLOW
	BIT	#PAR!TXMERR,R1	;PARITY OR TRANSMISSION ERROR?
	BNE	M2PAR		;IF NE YES
	BIT	#TIMOUT,R1	;CHECK FOR TIME OUT.
	BNE	M2TIME		;IF NE YES
	BIT	#MEMOFL!NEXLOC,R1  ;NEM OR OVERFLOW?
	BNE	M2OFL		;IF NE YES
	CALLR	IEBBE		;INDICATE TRANSMISSION ERROR
;
; BYTE COUNT OVERFLOW
;
10$:	BIC	#BCOFL,RSR(R0)	;CLEAR ERROR CONDITION.
	      BIS	#REJ!IE,(R0)	;TRUNCATE MESSAGE
	RETURN			;
;
; PARITY OR TRANSMISSION ERROR
;
M2PAR:	CALL	PRCRX		;RECONNECT FOR RECEPTION
	BR	IEBBE		;FLAG IE.BBE
;
; RECEIVER TIMEOUT
;
M2TIME:	CALL	PRCRX		;RECONNECT FOR RECEPTION
	BR	IEDNR		;FLAG DEVICE NOT READY
;
; NONEXISTENT LOCATION OR MEMORY OVERFLOW.
;
M2OFL:	CALL	PRCRX		;RECONNECT FOR RECEPTION
	BR	IESPC		;INDICATE NONEXISTENT LOCATION


INTP0:	BIS	#BDINIT,(R0)	;INITIALIZE BOARD.
	RETURN			;

INTP4:	CALL	PRCRX		;RECONNECT FOR RECEPTION
	M      OVB	#6,U.CW2(R5)	;SET HANDLER STATE TO 6.
	RETURN			;

;+
; **-LRCAN-CANCEL I/O SERVICE ROUTINE
;
; THIS ENTRY POINT IS ENTERED WHEN AN  IO.KIL  FUNCTION IS
; ISSUED REGARDLESS OF WHETHER THE DEVICE IS BUSY OR NOT.
;
; INPUTS:
;	R0 = ADDRESS OF ACTIVE I/O PACKET (IF ANY)
;	R1 = ADDRESS OF TCB OF CURRENT TASK
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;
; OUTPUTS:
;	1. IF TASK TERMINATION IS IN PROGRESS, THEN BOARD IS
;	   INITIALIZED & TASK (IF ANY) IS DISCONNECTED.
;	2      . OTHERWISE, IF REQUEST IS OUTSTANDING, THEN TASK IS
;	   RECONNECTED FOR RECEPTION.
;	3. REGARDLESS OF RUN DOWN STATUS, IF REQUEST IS OUTSTANDING,
;	   THEN COMPLETION IS INDICATED WITH STS=IE.ABO.
;-

LRCAN:	CMP	R1,U.TASK(R5)	;;;REQUEST FOR CONNECTED TASK?
	BNE	10$		;;;IF NE NO
	MOV	S.CSR(R4),R3	;;;GET RCR ADDRESS.
	BIC	#IE,(R3)	;;;DISABLE INTERRUPTS.
	MTPS	#0		;;;LOWER PRIORITY
	BITB	#T2.HLT,T.ST2(R1) ;TASK BEING TERMINATED?
	BEQ	20$		;IF EQ NO
	MOVB	U.CW2(R5),R2	;YES, RETRIEVE HANDLER STATE      .
	CALL	PRDRX		;DISCONNECT TASK
	TSTB	R2		;IS UNIT BUSY?
	BLT	30$		;IF LT YES
10$:	RETURN			;

20$:	TSTB	U.CW2(R5)	;IS UNIT BUSY?
	BGE	10$		;IF GE YES
	CALL	PRCRX		;ABORT OPERATION AND RECONNECT
30$:	BR	IEABO		;


;+
; POWERFAIL AND TIMEOUT
;-

LROUT:	TSTB	U.CW2(R5)	;IS TASK CONNECTED?
	BEQ	10$		;IF EQ YES
	CALL	PRCRX		;RECONNECT FOR RECEPTION
10$:	BITB	#US.BSY,U.STS(R5)  ;IS THE UNIT BUSY?
	BEQ	LRPWF		;IF EQ NO
	BR	IEDNR		;YES, ABORT OUTSTANDING REQUEST

LRPWF:	RETURN			;

;+
; PR      OCESS ERROR CONDITIONS AND CALL I/O DONE.
;-

IEABO:	MOV	#IE.ABO&377,R0	;ABORT TASK
	BR	IODON		;

IEBAD:	MOV	#IE.BAD&377,R0	;BAD PARAMETERS
	BR	IODON		;

IEDAA:	MOV	#IE.DAA&377,R0	;DEVICE ALREADY CONNECTED
	BR	IODON		;

IEBBE:	MOV	#IE.BBE&377,R0	;BAD TRANSMISSION ERROR
	BR	IODON		;

IEDNA:	MOV	#IE.DNA&377,R0	;DEVICE NOT AVAILABLE
	BR	IODON		;

IEDNR:	MOV	#IE.DNR&377,R0	;DEVICE NOT READY
	BR	IODON		;

IEFHE:	MOV	#IE.FHE&377,R0	;FATAL HARDWARE ERROR
	BR	IODON		;

IEIFC:	MOV	#IE.IFC&377   p  ,R0	;INVALID FUNCTION CODE
	BR	IODON		;

IENTR:	MOV	#IE.NTR&377,R0	;TASK NOT TRIGGERED
	BR	IODON		;

IESPC:	MOV	#IE.SPC&377,R0	;ILLEGAL BUFFER
	BR	IODON		;

IEVER:	MOV	#IE.VER&377,R0	;PARITY OR HARD DEVICE ERROR
	BR	IODON		;

ISSUC:	MOV	#IS.SUC&377,R0	;SUCCESSFUL OPERATION

IODON:	CALL	$IOALT		;PROCESS I/O DONE
	JMP	LRINI		;AND TRY FOR MORE

	.END
p         $NðskQ	› c,        	.TITLE	LTDRV
	.IDENT	/05/

; COPYRIGHT (C) 1979
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
; DGITAL EQUIPMENT OF CANADA LTD, KANATA, ONTARIO
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 05
;
; DAVID R. CROWE
;
; PREVIOUSLY MODIFIED BY:
;
;	DAVID H. CHAN
;	HELEN GORDON
;	PATRICIA C. LEE
;
;
; MODIFIED BY:
;
;	R. E. CALDWELL 21-AUG-79
;
;		RC010 -- FIX BUG IN CANCEL I/O
;			AND USE CORR      ECT FORM OF GTPKT$.
;
; PARALLEL COMMUNICATION LINK (PCL) TRANSMITTER DRIVER FOR RSX-11M-PLUS.
;
; MACRO LIBRARY CALLS
;
	.MCALL	PKTDF$,TCBDF$,UCBDF$

	PKTDF$			;DEFINE I/O PACKET OFFSETS
	TCBDF$			;DEFINE TASK CONTROL BLOCK OFFSETS.
	UCBDF$			;DEFINE UCB OFFSETS

;+
; STATE SETTINGS FOR 'STC' FUNCTION
;-

SS.MAS	=	1		;MASTER STATE
;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED
;SS.SEC	=	2		;SECONDARY STATE
SS.NEU	=	4		;NEUTRAL STATE

;+
; MODE SETTINGS FOR 'STC'       FUNCTION
;-

MS.AUT	=	20		;AUTO ADDRESS
MS.ADS	=	40		;ADDRESS SILO

;+
; CHARACTERISTIC WORD USAGE.
; U.CW2  IS USED BY THE HANDLER AS FOLLOWS:
;   BITS 7-0 CONTAIN NUMBER OF RETRIES TO BE PERFORMED AFTER CURRENT
;	     TRY IF NECESSARY.
;-

;+
; HANDLER UCB WORK AREA OFFSET DEFINITIONS.
;-

U.EFN	=	U.CNT+2		;'NOWMST' EVENT FLAG NUMBER
U.TCB	=	U.EFN+2		;TCB ADDRESS OF EVENT FLAG REQUESTOR
U.BUF1	=	U.TCB+2		;RELOCATION BIAS FOR RETURN REG. BUFFER

;+
; THE HARDWARE REGISTERS ARE DEFINED       RELATIVE TO THE  TCR, WHOSE
; ADDRESS IS FOUND IN THE  S.CSR  FIELD OF THE SCB AT RUN TIME.
;-

TCR	=	0		;TRANSMITTER COMMAND REGISTER.
TSR	=	2		;TRANSMITTER STATUS REGISTER.
TSDB	=	4		;TRANSMITTER SOURCE DATA BUFFER.
TSBC	=	6		;TRANSMITTER SOURCE BYTE COUNT.
TSBA	=	10		;TRANSMITTER SOURCE BUS ADDRESS.
TMMR	=	12		;TRANSMITTER MASTER/MAINTENANCE REG.
TSCRC	=	14		;TRANSMITTER SOURCE CRC

;+
; TRANSMITTER COMMAND REGISTER (TCR).
;-

RIB	=	100000		;RETRY IF BUSY (R/W).
TXNPR	=	40000		;TRANSMIT      TER NPR (R/W).
SNDWD	=	20000		;SEND WORD (R/W).
DC04	=	10000		;DESTINATION CODE BITS (R/W).
DC03	=	4000		; "
DC02	=	2000		; "
DC01	=	1000		; "
DC00	=	400		; "
RDSILO	=	200		;READ SILO (R/W).
IE	=	100		;INTERRUPT ENABLE (R/W).
A17	=	40		;EXTENDED ADDRESS BITS (R/W).
A16	=	20		; "
DTORDY	=	10		;DATA OUTPUT READY (RO).
INHADI	=	4		;INHIBIT ADDRESS INCREMENT (R/W).
BDINIT	=	2		;BOARD INITIALIZE (WO).
STTXM	=	1		;START TRANSMISSION (R/W).

DC	=	DC04!DC03!DC02!DC01!DC00 ;UNION OF DESTINATION CODE       BITS.


;+
; TRANSMITTER STATUS REGISTER (TSR).
;-

ERR	=	100000		;ERROR (RO).
NEXLOC	=	40000		;NONEXISTENT LOCATION (RO).
MEMOFL	=	20000		;MEMORY OVERFLOW (R/W).
TXMERR	=	10000		;TRANSMISSION ERROR (R/W).
MSTDWN	=	4000		;MASTER DOWN (R/W).
TIMOUT	=	2000		;TIME OUT (R/W).
OVERUN	=	1000		;OVERRUN (R/W).
DTIRDY	=	400		;DATA INPUT READY (RO).
SUCTXF	=	200		;SUCCESSFUL TRANSFER (R/W).
BUSY	=	100		;BUSY (RO).
SORE	=	40		;SOFTWARE REJECT (R/W).
TDMBSY	=	20		;TDM BUS BUSY (R/W).
RSPB1	=	10		;RES      PONSE B1 (RO).
RSPB0	=	4		;RESPONSE B0 (RO).
RSPA1	=	2		;RESPONSE A1 (RO).
RSPA0	=	1		;RESPONSE A0 (RO).


;+
; TRANSMITTER MASTER/MAINTENANCE REGISTER (TMMR).
;-

; LOW ORDER BYTE (TMMR+0).

TXMAD4	=	20		;TRANSMITTER ADDRESS BITS (R/W).
TXMAD3	=	10		;  "
TXMAD2	=	4		;  "
TXMAD1	=	2		;  "
TXMAD0	=	1		;  "

; HIGH ORDER BYTE (TMMR+1).

AOPRDY	=	200		;ADDRESS OUTPUT READY (RO).
AIPRDY	=	100		;ADDRESS INPUT READY (RO).
CLRADR	=	40		;CLEAR ADDRESS SILO (WO).
AUTADR	=	20		;AUTO ADDRESS (R/      W).
CHNOPN	=	10		;CHANNEL OPEN (RO).
NOWMST	=	4		;NOW MASTER (R/W).
SEC	=	2		;SECONDARY MASTER (R/W).
MASTER	=	1		;MASTER (R/W).

;+
; PAD TRANSMITTER ID
;-

PAD	=	31.		;PAD TRANSMITTER ID

;+
; DEVICE DISPATCH TABLE
;-

	DDT$	LT,L$$T11,,CHK	;GENERATE DISPATCH TABLE

;+
; LOCAL IMPURE DATA TABLES
;-

PRVAL:	.BLKW	L$$T11		;PREVIOUS VALUE
ASCNT:	.BLKW	L$$T11		;ADDRESS SILO COUNTER
LFVAL:	.BLKW	L$$T11		;VALUES LEFT IN USER BUFFER
FRVAL:	.BLKW	L$$T11		;FIRST VALUE IN SILO

;+
; LTCHK       - PCL TRANSMITTER DRIVER PARAMETER CHECKING
;
; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST
; IS RECEIVED FOR THE PARALLEL COMMUNICATIONS LINK TRANSMITTER. SOME
; PCL TRANSMITTER REQUESTS CONTAIN INFORMATION THAT MUST BE CHECKED IN
; THE CONTEXT OF THE ISSUING TASK; THEREFORE, THE I/O REQUEST IS NOT
; QUEUED BEFORE CALLING THE DRIVER.
;
; INPUTS:
;
;	R1 = ADDRESS OF THE I/O PACKET
;	R4 = ADDRESS OF THE STATUS CONTROL BLOCK
;	R5 = ADDRESS OF THE UCB OF THE CONTROLLER       TO BE INITIATED
;
; OUTPUTS:
;
;	IF THE QIO FUNCTION IS IO.STC THEN NO PRIOR ADDRESS CHECKING HAS
;	BEEN PERFORMED BY THE SYSTEM BECAUSE IO.STC IS CLASSED AS A CONTROL
;	FUNCTION. IT IS THEREFORE NECESSARY TO FIRST MOVE ALL THE
;	PARAMETERS SO THAT THE ADDRESS DOUBLEWORD FOR THE DATA BUFFER MAY
;	BE MOVED TO I.PRM AND I.PRM+2 AFTER IS HAS BEEN ADDRESS CHECKED
;	AND RELOCATED. IF THE LENGTH OF THE DATA BUFFER IS ZERO, THE
;	ADDRESS CHECK WILL NOT TAKE PLACE AND THE ZERO LENGTH BUFFER WILL
;	BE CO      NSIDERED VALID.
;
;	IF THE QIO FUNCTION IS IO.STC OR IO.ATX THEN THE RETURN BUFFER
;	ADDRESS IS CHECKED TO DETERMINE WHETHER IT LIES WITHIN THE
;	ISSUING TASK'S ADDRESS SPACE. IF IT DOES THEN THE RETURN BUFFER
;	ADDRESS IS RELOCATED AND STORED IN THE I/O PACKET. IF IT IS NOT
;	A VALID ADDRESS THEN AN ILLEGAL BUFFER STATUS IS RETURNED AS THE
;	FINAL I/O STATUS OF THE REQUEST.
;
;	FOR ALL FUNCTION CODES, THE I/O PACKET IS INSERTED IN THE
;	CONTROLLER QUEUE AND THE DEVICE INITIATOR IS ENTERED TO STAR      T
;	THE CONTROLLER.
;-

LTCHK:	CMP	#IO.ATX,I.FCN(R1) ;IS FUNCTION CODE = 'ATX'?
	BEQ	30$		;IE EQ YES
	CMP	#IO.STC,I.FCN(R1) ;IS FUNCTION CODE = 'STC'?
	BNE	60$		;IF NE NO
;
; 'STC' FUNCTION - MOVE ALL PARAMETERS TO MAKE WAY FOR DATA BUFFER
; ADDRESS DOUBLEWORD
;
10$:	MOV	R1,R3		;SAVE ADDRESS OF THE I/O PACKET
	MOV	I.PRM+12(R3),I.PRM+14(R3)  ;MOVE RETURN BUFFER ADDRESS
	MOV	I.PRM+10(R3),I.PRM+12(R3)  ;MOVE EVENT FLAG NUMBER
	MOV	I.PRM+6(R3),I.PRM+10(R3)  ;MOVE MODE
	MOV	I.PRM+4(R3),I.PRM+6(R3      )  ;MOVE STATUS
	MOV	I.PRM+2(R3),I.PRM+4(R3)  ;MOVE LENGTH OF BUFFER
	BEQ	30$		;IF EQ LENGTH = 0
	BLT	15$		;IF LT INVALID BUFFER LENGTH
;
; SET UP REGISTERS FOR ADDRESS CHECK AND RELOCATION
;
	MOV	I.PRM(R3),R0	;DATA BUFFER ADDRESS ==> R0
	MOV	I.PRM+2(R3),R1	;LENGTH ==> REG 1
	CALL	$ACHCK		;CHECK THE LENGTH
	BCS	15$		;IF CS, ERROR
	MOV	W.BATT(R2),R2	;PICK UP ATTACHMENT DESC. ADDR.
	INCB	A.IOC(R2)	;LOCK REGION
	MOV	R2,I.AADA(R3)	;SAVE PTR IN PKT FOR $IODONE
	BR	20$		;CONTINUE
;
; INVALID BUFFE      R
;
15$:	MOV	#IE.SPC&377,R0	;SET ILLEGAL BUFFER STATUS
	CALLR	$IOFIN		;CALL FINISH I/O OPERATION AND EXIT
;
; RELOCATE THE DATA BUFFER ADDRESS
;
20$:	CALL	$RELOC		;GO RELOCATE THE DATA BUFFER ADDRESS
	MOV	R1,I.PRM(R3)	;SET RELOCATION BIAS
	MOV	R2,I.PRM+2(R3)	;SET 16-BIT ADDRESS
	BR	40$		;GO CHECK RETURN BUFFER ADDRESS
;
; 'STC' OR 'ATX' FUNCTION
;
30$:	MOV	R1,R3		;SAVE I/O PACKET
40$:	MOV	I.PRM+14(R3),R0	;GET VIRTUAL ADDRESS OF RETURN BUFFER
	MOV	#14.,R1		;SET LENGTH OF RETURN BUFFER TO 7 WO      RDS
	CALL	$ACHCK		;CHECK THE ADDRESS
	BCS	15$		;IF CS BAD
	MOV	W.BATT(R2),R2	;PICK UP ATTACHMENT DESC. ADDR.
	INCB	A.IOC(R2)	;LOCK REGION
	MOV	R2,I.AADA+2(R3)	;SAVE PTR IN PKT FOR $IODONE
;
; RELOCATE THE RETURN BUFFER ADDRESS
;
	CALL	$RELOC		;RELOCATE USER BUFFER
	MOV	R1,I.PRM+14(R3)	;SET RELOCATION BIAS OF RETURN BUFFER
	MOV	R2,I.PRM+16(R3)	;SET 16-BIT ADDRESS OF RETURN BUFFER
	MOV	R3,R1		;COPY I/O PACKET ADDRESS
;
; INSERT THE I/O PACKET IN THE QUEUE
;
60$:	MOV	R4,R0		;SET R0 = I/O QUEUE       LISTHEAD
	CALL	$QINSP		;GO INSERT PACKET IN QUEUE
;
; GET THE QUEUED I/O PACKET
;
LTINI:	GTPKT$	LT,L$$T11,,,T	;GET I/O PACKET MACRO
;
; ANALYZE THE CONTENTS OF THE I/O PACKET
;
;	R1 = I/O PACKET
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB
;	R3 = CONTROLLER INDEX
;	R4 = STATUS CONTROL BLOCK
;	R5 = UNIT CONTROL BLOCK
;
; I/O REQUEST PACKET FORMAT
;
;	WD.00 = I/O QUEUE THREAD WORD
;	WD.01 = REQUEST PRIORITY, EVENT FLAG NUMBER
;	WD.02 = TSB ADDRESS OF REQUESTER TASK
;	WD.03 = POINTER TO 2      ND LUN WORD IN REQUESTER TASK HEADER
;	WD.04 = CONTENTS OF 1ST LUN WORD IN REQUESTER TASK HEADER
;	WD.05 = I/O FUNCTION CODE
;	WD.06 = VIRTUAL ADDRESS OF I/O STATUS BLOCK
;	WD.07 = RELOCATION BIAS OF I/O STATUS BLOCK
;	WD.10 = I/O STATUS BLOCK ADDRESS
;	WD.11 = VIRTUAL ADDRESS OF AST SERVICE ROUTINE
;	WD.12 = RELOCATION BIAS OF DATA BUFFER
;	WD.13 = 16-BIT ADDRESS OF DATA BUFFER
;	WD.14 = LENGTH OF DATA BUFFER
;	WD.15 = FLAG WORD OR STATE
;	WD.16 = ID OR MODE
;	WD.17 = NUMBER OF RETRIES OR EVENT       FLAG NUMBER
;	WD.20 = RELOCATION BIAS OF RETURN BUFFER
;	WD.21 = 16-BIT ADDRESS OF RETURN BUFFER
;
	TST	U.EFN(R5)	;WAS EFN FOR 'NOWMST' SPECIFIED?
	BEQ	5$		;IF EQ NO
	MOV	S.CSR(R4),R0	;YES, RETREIVE CSR ADDRESS
	BIS	#IE,(R0)	;ENABLE INTERRUPTS
5$:	MOV	I.TCB(R1),R0	;GET REQUESTER TCB ADDRESS.
	BITB	#T2.ABO,T.ST2(R0)  ;IS TASK BEING ABORTED?
	BEQ	10$		;IF EQ NO
	CALLR	IEVER		;YES, REJECT REQUEST
;
; DISPATCH PACKET FOR PROCESSING ACCORDING TO FUNCTION CODE
;
10$:	CMP	#IO.ATX,I.FCN(R1) ;IS IT '      ATX' FUNCTION?
	BEQ	ATX		;IF EQ YES
	CMP	#IO.SEC,I.FCN(R1) ;IS IT 'SEC' FUNCTION?
	BEQ	IOSEC		;IF EQ YES
	CMP	#IO.STC,I.FCN(R1) ;IS IT 'STC' FUNCTION?
	BEQ	STC		;IF EQ YES
	CALLR	IEIFC		;INVALID FUNCTION CODE

;+
; PROCESS 'ATX' FUNCTION
;
; REQUIRED INPUTS:
;	R1 = I/O PACKET
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB
;	R3 = CONTROLLER INDEX
;	R4 = STATUS CONTROL BLOCK
;	R5 = UNIT CONTROL BLOCK
;-

ATX:				;REF LABEL


	.IF DF	M$$EXT

	CALL	$STMAP		;SET UP UNIBUS MAP ADDRESS
	CA      LL	$MPUBM		;MAP UNIBUS TO MEMORY
	MOV	S.PKT(R4),R1	;RESTORE REG 1

	.ENDC


	CMPB	I.PRM+11(R1),#DC/400  ;CPU ID > MAXIMUM?
	BHI	LTBAD		;IF HI YES
	TSTB	I.PRM+11(R1)	;CPU ID = 0?
	BEQ	LTBAD		;IF EQ YES
	TSTB	I.PRM+13(R1)	;RETRY COUNT > 255?
	BNE	LTBAD		;IF NE YES
	MOVB	I.PRM+12(R1),U.CW2(R5)	;SAVE RETRY COUNT BYTE.
;
; SET UP RETURN REGISTER BUFFER ADDRESS IN UCB
;
	MOV	I.PRM+14(R1),U.BUF1(R5)  ;RELOCATION BIAS ==> UCB
	MOV	I.PRM+16(R1),U.BUF1+2(R5)  ;16-BIT ADDRESS==> UCB
RETRY:	MOV	S.CSR(      R4),R0	;GET DEVICE ADDRESS (TSR).
	MOV	#BDINIT,(R0)	;BOARD INITIALIZE.
	MOV	I.PRM+6(R1),TSDB(R0)  ;MOVE FLAGS WORD TO DATA SILO.
	MOV	U.BUF+2(R5),TSBA(R0)  ;SET UP BUFFER ADDRESS.
	MOV	U.CNT(R5),R2	;GET BYTE COUNT
	NEG	R2		;NEGATE IT.
	MOV	R2,TSBC(R0)	;PUT IT IN PCL REGISTER.
	MOVB	I.PRM+11(R1),TCR+1(R0)	;SET CPU ID.
	BIS	#RIB!TXNPR!SNDWD!IE!STTXM,U.BUF(R5) ;SET EXTENDED
	BIS	U.BUF(R5),(R0)  ;ADDR & GO BITS IN TCR.
	MOVB	S.ITM(R4),S.CTM(R4)  ;- SET TIME OUT
	RETURN			;

LTBAD:	CALLR	IEBAD		;BAD       PARAMETERS

;+
; PROCESS 'SEC' FUNCTION
;
; REQUIRED INPUTS:
;	R4 = STATUS CONTROL BLOCK
;-

IOSEC:	MOV	S.CSR(R4),R0	;GET DEVICE ADDRESS
	MOV	TMMR(R0),R1	;MOVE SECOND WORD FOR IOSB TO R1
	MOV	#IS.SUC&377,R0	;GET SUCCESS STATUS CODE
	CALL	$IODON		;GO EXIT THIS REQUEST
	BR	LTINI		;GO LOOK FOR MORE WORK

;+
; PROCESS 'STC' FUNCTION
;
; REQUIRED INPUTS:
;	R1 = I/O PACKET
;	R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB
;	R3 = CONTROLLER INDEX
;	R4 = STATUS CONTROL BLOCK
;	R5 = UNIT CONTROL       BLOCK
;-

STC:	MOV	I.TCB(R1),R0	;GET TASK'S TCB ADDRESS
	BIT	#T3.PRV,T.ST3(R0)  ;IS THE TASK PRIVLEGED?
	BEQ	35$		;IF EQ NO
	TST	I.PRM+6(R1)	;'STATE' SPECIFIED?
	BEQ	10$		;IF EQ NO
	CMP	#SS.MAS,I.PRM+6(R1)  ;IS IT 'MASTER'?
	BEQ	10$		;IF EQ YES
;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED
;	CMP	#SS.SEC,I.PRM+6(R1)  ;IS IT 'SECONDARY'?
;	BEQ	10$		;IF EQ YES
	CMP	#SS.NEU,I.PRM+6(R1)  ;IS IT 'NEUTRAL'?
	BNE	LTBAD		;IF NE NO, BAD PARAMETERS
;
; VALIDATE THE 'MODE' PARAME      TER
;
10$:	TST	I.PRM+10(R1)	;'MODE' SPECIFIED?
	BEQ	20$		;IF EQ NO
	CMP	#MS.AUT,I.PRM+10(R1)  ;IS 'AUTO' SPECIFIED?
	BEQ	20$		;IF EQ YES
	CMP	#MS.ADS,I.PRM+10(R1)  ;IS 'ADDRESS SILO' SPECIFIED?
	BNE	LTBAD		;IF NE NO, BAD PARAMETERS
;
;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED
; VALIDATE THE EVENT FLAG NUMBER
;
20$:
	BR	40$
;	TST	I.PRM+12(R1)	;EVENT FLAG > 0?
;	BLE	30$		;IF LE NO
;	CMP	#96.,I.PRM+12(R1)  ;IS IT > 96?
;	BGT	40$		;IF GT NO
30$:	CALLR	IEIEF		;INVALID       EVENT FLAG
35$:	CALLR	IEPRI		;PRIVLEGE VIOLATION
;
; VALIDATE THE SIZE AND CONTENTS OF THE DATA BUFFER
;
40$:	TST	I.PRM+4(R1)	;IS SIZE OF BUFFER > OR = 0?
	BLT	54$		;IF LT NO
	BEQ	60$		;IF EQ SIZE=0
;
; INITIALIZE VALUES FOR LOOPING THROUGH BUFFER
;
	MOV	#50.,ASCNT(R3)	;SAVE MAX NUMBER OF VALUES ALLOWED
	CMP	I.PRM+4(R1),ASCNT(R3)  ;IS # OF VALUES > MAXIMUM?
	BGT	54$		;IF GT YES
	CLR	PRVAL(R3)	;INITIALIZE PREVIOUS VALUE TO ZERO
	MOV	I.PRM+4(R1),LFVAL(R3)  ;GET # OF VALUES
	MOV	I.PRM(R1),U.BUF      (R5)  ;GET RELOCATION BIAS
	MOV	I.PRM+2(R1),U.BUF+2(R5)  ;GET VITUAL ADDRESS
;
; CHECK ALL VALUES IN THE BUFFER FOR WITHIN VALID RANGE
;
;	PRVAL(R3) = PREVIOUS VALUE
;	ASCNT(R3) = # VALUES STILL POSSIBLE TO ADD TO SILO
;	LFVAL(R3) = # VALUES STILL IN USER BUFFER
;
50$:	CALL	$GTBYT		;RETRIEVE NEXT BYTE ON THE STACK
	TSTB	(SP)		;IS VALUE > 0?
	BEQ	51$		;IF EQ NO
	CMPB	(SP),#DC/400	;IS VALUE > MAXIMUM?
	BLE	52$		;IF LE NO
51$:	MOVB	(SP)+,PRVAL(R3)	;CLEAN UP THE STACK
	BR	54$		;INVALID DATA BUFFE      R
;
; CHECK FOR PAD VALUE NEEDED
;
52$:	CMPB	(SP),PRVAL(R3)	;IS IT = LAST VALUE?
	BNE	53$		;IF NE NO
	DEC	ASCNT(R3)	;DECREMENT MAXIMUM VALUES ALLOWED
;
; DECREMENT COUNTERS AND SAVE PREVIOUS VALUE
;
53$:	MOVB	(SP)+,PRVAL(R3)	;SAVE THIS VALUE AS PREVIOUS
	DEC	ASCNT(R3)	;DECREMENT MAXIMUM VALUES ALLOWED
	BGE	55$		;IF GE STILL WITHIN LIMITS
54$:	CALLR	IESPC		;ILLEGAL BUFFER FORMAT
;
; DECREMENT NUMBER OF BYTES STILL IN USER BUFFER AND GO GET NEXT BYTE
;
55$:	DEC	LFVAL(R3)	;DECREMENT # BYTES YE      T TO CHECK
	BGT	50$		;IF GT GET NEXT
;
; ALL PARAMETERS ARE VALID - PROCESS THE REQUEST
;
60$:
	BR	70$
;	TST	U.TCB(R5)	;HAS A TASK REQUESTED AN EVENT FLAG?
;	BEQ	62$		;IF EQ NO
;	CMP	I.TCB(R1),U.TCB(R5)  ;IS THIS THE SAME REQUESTOR?
;	BEQ	61$		;IF EQ YES
;	CALLR	IEFLG		;EVENT FLAG ALREADY SPECIFIED
;
; DECREMENT I/O COUNT FOR PREVIOUS EVENT FLAG
;
;61$:	MOV	U.TCB(R5),R0	;GET PREVIOUS REQUESTOR
;	DECB	T.IOC(R0)	;DECREMENT REQUESTOR'S I/O COUNT
;;
; SET UP TCB & EVENT FLAG
;
;62$:	MOV	I.PR      M+12(R1),U.EFN(R5)	;SET UP EVENT FLAG NUMBER
;	BNE	63$		;IF NE NON-ZERO EVENT FLAG
;	CLR	U.TCB(R5)	;ZERO REQUESTORS TCB
;	BR	70$		;GO PROCESS NEXT PARAMETER
;
; EVENT FLAG HAS BEEN SPECIFIED, SETUP TCB IN UCB AND INCREMENT
; I/O COUNT.
;
;63$:	MOV	I.TCB(R1),R0	;SAVE REQUESTORS TCB
;	MOV	R0,U.TCB(R5)	;
;	INCB	T.IOC(R0)	;LOCK DOWN TASK
;
; INITIALIZE BASE REGISTER ADDRESS
;
70$:	MOV	S.CSR(R4),R0	;TSR ==> REG 0
	TST	I.PRM+6(R1)	;WAS A 'STATE' SPECIFIED?
	BEQ	80$		;IF EQ NO
	CMP	#SS.MAS,I.PRM+6      (R1)  ;IS MASTER STATE DESIRED?
	BNE	71$		;IF NE NO
	MOV	#MASTER,ASCNT(R3)  ;SET MASK FOR MASTER
	BR	73$		;GO CHANGE TMMR

71$:
;	CMP	#SS.SEC,I.PRM+6(R1)  ;IS SECONDARY STATE DESIRED?
;	BNE	72$		;IF NE NO
;	MOV	#SEC,ASCNT(R3)	;SET MASK FOR SECONDARY
;	BR	73$		;GO CHANGE TMMR

72$:	CLR	ASCNT(R3)	;SET NEUTRAL MASK
73$:	MOVB	TMMR+1(R0),PRVAL(R3);GET HIGH ORDER BYTE OF TMMR
	BICB	#MASTER!SEC,PRVAL(R3)  ;CLEAR PREVIOUS STATE
	BISB	ASCNT(R3),PRVAL(R3)  ;SET NEW STATE
	MOVB	PRVAL(R3),TMMR+1(R0)  ;ST      ORE NEW HIGH ORDER BYTE
	MOVB	TMMR+1(R0),PRVAL(R3)  ;GET NEW HIGH ORDER BYTE AGAIN
	BICB	#374,PRVAL(R3)	;CLEAR ALL BUT DESIRED BITS
	CMPB	ASCNT(R3),PRVAL(R3)  ;IS ACTUAL = DESIRED?
	BEQ	80$		;IF EQ YES
;
; NOT DESIRED STATE - CHECK FOR VALID EXCEPTION (SECONDARY==>MASTER)
;
	BITB	#MASTER,PRVAL(R3)  ;IS IT NOW MASTER?
	BNE	80$		;IF NE YES
	CALLR	IEVER		;HARDWARE REJECTED STATE
;
; SET UP ADDRESS SILO
;
80$:	TST	I.PRM+4(R1)	;IS LENGTH OF DATA BUFFER = 0?
	BEQ	90$		;IF EQ YES
	MOVB	TMMR+1(R0),P      RVAL(R3);RETRIEVE HIGH ORDER BYTE OF TMMR
	BISB	#CLRADR!AUTADR,PRVAL(R3)  ;CLEAR SILO AND SET AUTO ADRS
	MOVB	PRVAL(R3),TMMR+1(R0)  ;STORE NEW HIGH ORDER BYTE
;
; REINITIALIZE UCB FOR THE DATA TRANSFER
;
	MOV	I.PRM(R1),U.BUF(R5)  ;RELOCATION BIAS ==> UCB
	MOV	I.PRM+2(R1),U.BUF+2(R5)	 ;16-BIT ADDRESS ==> UCB
	CLR	ASCNT(R3)	;ZERO ADDRESS SILO ENTRY COUNTER
	CLR	PRVAL(R3)	;SET PREVIOUS VALUE TO ZERO
	MOV	I.PRM+4(R1),LFVAL(R3)  ;INITIALIZE DATA BUFFER COUNTER
;
; MOVE EACH BYTE OF THE DATA BUFFER TO       THE ADDRESS SILO
;
;	PRVAL(R3) = PREVIOUS VALUE
;	ASCNT(R3) = ADDRESS SILO COUNTER
;	LFVAL(R3) = # BYTES STILL IN DATA BUFFER
;	FRVAL(R3) = FIRST VALUE IN SILO
;
81$:	CALL	$GTBYT		;RETRIEVE A BYTE FROM USER BUFFER
	CMPB	(SP),PRVAL(R3)	;IS IT = PREVIOUS?
	BNE	82$		;IF NE NO
	MOVB	#PAD,TMMR(R0)	;INSERT A PAD VALUE
	INC	ASCNT(R3)	;INCREMENT ADDRESS SILO ENTRY COUNTER
82$:	MOVB	(SP),PRVAL(R3)	;SAVE THIS VALUE AS PREVIOUS
	TST	ASCNT(R3)	;IS THIS FIRST BYTE?
	BGT	83$		;IF GT NO
	MOVB	(SP),FRVAL(R3      )	;SAVE FIRST VALUE
83$:	MOVB	(SP)+,TMMR(R0)	;INSERT THE USER VALUE IN SILO
	INC	ASCNT(R3)	;INCREMENT ADDRESS SILO COUNTER
	DEC	LFVAL(R3)	;DECREMENT # BYTES YET TO MOVE
	BGT	81$		;IF GT GET NEXT BYTE
	CMP	#20.,ASCNT(R3)	;HAVE AT LEAST 20 VALUES BEEN INSERTED?
	BLE	84$		;IF LE YES
;
; LESS THAN THE MINIMUM NUMBER OF VALUES HAVE BEEN MOVED - REPEAT THE
; PATTERN AGAIN
;
	MOV	I.PRM(R1),U.BUF(R5)  ;RELOCATION BIAS ==> UCB
	MOV	I.PRM+2(R1),U.BUF+2(R5)	 ;16-BIT ADDRESS ==> UCB
	MOV	I.PRM+4(R1),LFVAL(      R3)  ;SET UP # BYTES TO MOVE
	BR	81$		;GO MOVE THE VALUES
;
; ALL BYTES MOVED - CHECK FOR FIRST = LAST
;
84$:	CMPB	PRVAL(R3),FRVAL(R3)  ;IS FIRST = LAST?
	BNE	90$		;IF NE NO
	MOVB	#PAD,TMMR(R0)	;MOVE A PAD VALUE TO SILO
90$:	TST	I.PRM+10(R1)	;WAS A MODE SPECIFIED?
	BEQ	100$		;IF EQ NO
	MOVB	TMMR+1(R0),PRVAL(R3);RETRIEVE HIGH BYTE OF TMMR
	CMP	#MS.AUT,I.PRM+10(R1)  ;AUTO ADDRESS SPECIFIED?
	BNE	91$		;IF NE NO
	BISB	#AUTADR,PRVAL(R3)  ;SET AUTO ADDRESS
	BR	92$		;GO RESTORE TMMR+1
;
; ADDRESS S      ILO REQUESTED
;
91$:	BICB	#AUTADR,PRVAL(R3)  ;CLEAR AUTO ADDRESS (IMPLIES SILO)
92$:	MOVB	PRVAL(R3),TMMR+1(R0);RESTORE HIGH BYTE OF TMMR
100$:	MOV	I.PRM+14(R1),U.BUF1(R5)	;RELOCATION BIAS ==> UCB
	MOV	I.PRM+16(R1),U.BUF1+2(R5) ;16-BIT ADDRESS ==> UCB
	BEQ	110$		;IF EQ NO
	CALL	REGRET		;GO RETURN REGISTERS
110$:	CALLR	ISSUC		;INDICATE SUCCESS AND EXIT

;+
; REGRET -- SERVICE ROUTINE TO RETURN THE CONTENTS OF THE TRANSMITTER
; SIDE REGISTERS TO THE USER BUFFER WHOSE ADDRESS IS SPECIFIED IN
; U.BU      F1 AND U.BUF1+2 IN THE UCB. THE CONTROL REGISTER ADDRESS IS
; CONTAINED IN R0. U.BUF AND U.BUF+2 ARE PRESERVED ACROSS CALL.
;-

REGRET:	TST	U.BUF1(R5)	;RELOCATION BIAS = 0?
	BNE	10$		;IF NE NO
	TST	U.BUF1+2(R5)	;IS 16 BIT ADDRESS = 0?
	BEQ	20$		;IF EQ YES
10$:	MOV	U.BUF(R5),-(SP)	;SAVE U.BUF
	MOV	U.BUF+2(R5),-(SP)  ;SAVE U.BUF+2
	MOV	U.BUF1(R5),U.BUF(R5)  ;GET RELOCATION BIAS
	MOV	U.BUF1+2(R5),U.BUF+2(R5)  ;GET VIRTUAL ADDRESS
	.REPT	7
	MOV	(R0)+,-(SP)	;GET WORD TO STORE
	CALL	$PTWRD		;PUT WOR      D INTO BUFFER
	.ENDR
	MOV	(SP)+,U.BUF+2(R5)  ;RESTORE U.BUF+2
	MOV	(SP)+,U.BUF(R5)	;RESTORE U.BUF
20$:	RETURN			;

;+
; INTERRUPT SERVICE ROUTINE
;-

	.ENABL	LSB
$LTINT::
	INTSV$	LT,PR5,L$$T11	;;;EXECUTE INTERRUPT SAVE CODE
	MOV	U.SCB(R5),R4	;;;GET SCB ADDRESS.
	MOV	S.CSR(R4),R4	;;;GET TCR ADDRESS.
	BIC	#IE,(R4)	;;;DISABLE INTERRUPTS.
	BITB	#US.BSY,U.STS(R5)  ;;;IS UNIT BUSY?
	BEQ	10$		;;;IF EQ NO
	TST	TSR(R4)		;;;ERROR CONDITION?
	BPL	5$		;;;IF PL, NO ERROR
	CALL	$FORK		;;;CREATE A SYST      EM PROCESS
	JMP	ERROR		;GO HANDLE ERRORS
5$:	TSTB	TSR(R4)		;;;SUCTXF?
	BMI	30$		;;;IF MI YES
	BIT	#SORE,TSR(R4)	;;;HAVE WE A SOFTWARE REJECT ?
	BNE	20$		;;;IF NE YES
10$:
;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED
;	BITB	#NOWMST,TMMR+1(R4)  ;;;HAVE WE BECOME MASTER?
;	BNE	50$		;;;IF NE YES
	BIS	#BDINIT,(R4)	;;;TX INIT JUST IN CASE
	RETURN			;;;RETURN FOR MORE
;
; PROCESS SOFTWARE REJECT
;
20$:	BIC	#SORE,(R4)	;;;CLEAR THE INTERRUPTING BIT
	CALL	$FORK		;;;CREATE FORK       PROCESS
	MOV	R4,R0		;COPY CSR ADDRESS
	CALL	REGRET		;RESTORE REGISTERS
	CALLR	IEREJ		;REJECT REQUEST

30$:	BIC	#SUCTXF,TSR(R4)	;;;CLEAR THE INTERRUPTING BIT
	CALL	$FORK		;;;CREATE FORK PROCESS
	MOV	R4,R0		;COPY CSR ADDRESS
	CALL	REGRET		;RESTORE REGISTERS
	MOV	#IS.SUC&377,R0	;GET SUCCESS STATUS CODE
	BIT	#SORE,TSR(R4)	;WAS TRANSMISSION TRUNCATED?
	BEQ	40$		;IF EQ NO
	BIC	#SORE,TSR(R4)	;CLEAR THE SORE BIP ALSO
	INC	R0		;BUMP STATUS TO IS.TNR
40$:	MOV	U.CNT(R5),R1	;GET # OF BYTES TRANSFERED
	CA      LL	$IODON		;FINISH I/O
	JMP	LTINI		;TRY FOR MORE
;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED
;
; NOWMST INTERRUPT - SET EVENT FLAG
;
;50$:	CALL	$FORK		;;;CREATE FORK PROCESS
;	MOV	U.SCB(R5),R3	;RETREIVE SCB ADDRESS
;	MOVB	S.CON(R3),R3	;RETREIVE CONTROLLER INDEX
;	MOVB	TMMR+1(R4),PRVAL(R3)  ;RETRIEVE TMMR+1
;	BICB	#NOWMST,PRVAL(R3)  ;CLEAR 'NOWMST' BIT
;	MOVB	PRVAL(R3),TMMR+1(R4)  ;RESTORE TMMR+1
;	MOV	R5,PRVAL(R3)	;SAVE REG 5
;	MOV	U.EFN(R5),R0	;EVENT FLAG # ==> R0
;	M      OV	U.TCB(R5),R5	;REQUESTORS TCB ==> R5
;	BEQ	51$		;IF EQ NONE
;	CALL	$CEFI		;GO CONSTRUCT EVENT FLAG MASK
;	BCS	51$		;IF CS NO EVENT SPECIFIED
;	BIS	R0,(R1)		;SET EVENT FLAG
;	CALL	$DRDSE		;DECLARE SIGNIFICANT EVENT
;	DECB	T.IOC(R5)	;UNLOCK TCB, EFN IS GOING AWAY
;51$:	MOV	PRVAL(R3),R5	;RESTORE REG 5
;	CLR	U.EFN(R5)	;
;	CLR	U.TCB(R5)	;
;	RETURN			;RETURN TO INTERRUPTED PROGRAM
	.DSABL	LSB

;+
; WE HAVE AN ERROR CONDITION.  WE WILL DETERMINE THE CAUSE OF THE
; ERROR AND TAKE THE APPROPRIATE AC      TION AS FOLLOWS:
;
;	OVERRUN		= IE.BBE
;	TIMEOUT		= IE.DNR
;	MASTER DOWN	= IE.DNR
;	XMIT ERROR
;	  RSP B = 00	= IE.DNR
;	  RSP B = 01,10,11  = IE.BBE
;	MEM OVERFLOW	= INCREMENT A16-17, CLEAR ERROR, ENABLE IE,
;			  SET STTXM
;	NEM		= SET BDINIT, IE.SPC
;-

ERROR:	MOV	R4,R0		;COPY CSR ADDRESS
	CALL	REGRET		;RESTORE REGISTERS
	MOV	TSR(R4),R1	;GET CONTENTS OF TSR.
	BIT	#OVERUN,R1	;CHECK FOR OVER RUN.
	BNE	110$		;IF NE OVERRUN
	BIT	#MSTDWN,R1	;CHECK FOR MASTER DOWN.
	BNE	130$		;IF NE MASTER D      OWN
	BIT	#TIMOUT,R1	;CHECK FOR TIME OUT.
	BNE	120$		;IF NE TIMEOUT
	BIT	#TXMERR,R1	;CHECK FOR TRANSMISSION ERROR.
	BNE	140$		;IF NE TRANSMISSION ERROR
	BIT	#MEMOFL!NEXLOC,R1  ;OVERFLOW OR NEM?
	BNE	170$		;IF NE YES
	BIS	#BDINIT,(R4)	;INIT THE BOARD AGAIN
	RETURN			;

;+
; PROCESS OVERRUN CONDITION
;-

110$:	BIC	#OVERUN,TSR(R4)	;CLEAR THE INTERRUPTING BIT
	CALLR	IEBBE		;TRANSMISSION ERROR

;+
; PROCESS TIMEOUT
;-

120$:	BIC	#TIMOUT,TSR(R4)	;CLEAR THE INTERRUPTING BIT
	CALLR	IEDNR		;DEVI      CE NOT READY

;+
; PROCESS MASTER DOWN.
;-

130$:	BIC	#MSTDWN,TSR(R4)	;CLEAR THE INTERRUPTING BIT
	MOV	#IE.DNR&377,R0	;GET DEVICE NOT READY CODE
	BR	150$		;GO TRY FOR A RETRY

;+
; PROCESS TRANSMISSION ERROR.
;-

140$:	BIC	#TXMERR,TSR(R4)	;CLEAR INT BIT
	BIT	#RSPB1!RSPB0,R1	;IF RSPB IS 00
	BEQ	120$		;IF EQ TREAT AS TIMEOUT
	MOV	#IE.BBE&377,R0	;GET TRANSMIT ERROR STATUS CODE
150$:	MOV	U.SCB(R5),R4	;GET SCB ADDRESS
	MOV	S.PKT(R4),R1	;LOAD ADDRESS OF I/O PACKET
	DECB	U.CW2(R5)	;DECREMENT RE      TRY COUNT.
	BGE	160$		;IF GE RETRY
	CALLR	IODON		;FINISH UP

160$:	JMP	RETRY		;GO TRY AGAIN

;+
; PROCESS MEMORY OVERFLOW & NONEXISTENT LOCATION.
;-

170$:	BIS	#BDINIT,(R4)	;INITIALIZE BOARD.
	CALLR	IESPC		;RETURN NON-EXISTANT ERROR

;+
; CANCEL I/O OPERATION
;
; INPUTS:
;
;	R0 = I/O PACKET ADDRESS
;	R1 = TCB ADDRESS
;	R3 = CONTROLLER INDEX
;	R4 = SCB ADDRESS
;	R5 = UCB ADDRESS
;-

LTCAN:	MTPS	#0		;;;LOWER PRIORITY
	CMP	R1,U.TCB(R5)	;DID THIS TASK ASK FOR AN EVENT FLAG?
	BNE	10$		      ;IF NE NO
	DECB	T.IOC(R1)	;UNLOCK TCB, EFN IS GOING AWAY
	CLR	U.EFN(R5)	;CLEAR EVENT FLAG NUMBER
	CLR	U.TCB(R5)	;CLEAR REQUESTORS TCB
10$:	TSTB	S.STS(R4)	;IS UNIT BUSY?				;IZ003
	BEQ	LTPWF		;IF EQ THEN YES				;IZ003
	CMP	R1,I.TCB(R0)	;IS CANCEL REQUEST FOR THE CURRENT TASK?;IZ003
	BNE	LTPWF		;IF NE, NO SIMPLY RETURN		;**-1
	MOV	#IE.ABO&377,R0	;LOAD ABORT STATUS CODE
	BR	ABORT		;ABORT THIS OPERATION
LTPWF:	RETURN			;NO, JUST RETURN

;+
; TIMEOUT SERVICE
;-

LTOUT:	MOV	#IE.DNR&377,R0	;LOAD NO      T READY STATUS CODE.
ABORT:	MOV	S.CSR(R4),R2	;GET TSR ADDRESS.
	BIS	#BDINIT,(R2)	;INITIALIZE PCL TRANSMITTER.
	BR	IODON		;FINISH I/O

;+
; PROCESS ERROR CONDITIONS AND CALL I/O DONE
;-

IEBAD:	MOV	#IE.BAD&377,R0	;BAD PARAMETERS
	BR	IODON		;

IEBBE:	MOV	#IE.BBE&377,R0	;TRANSMISSION ERROR
	BR	IODON		;

IEDNR:	MOV	#IE.DNR&377,R0	;DEVICE NOT READY
	BR	IODON		;

IEFLG:	MOV	#IE.FLG&377,R0	;EVENT FLAG ALREADY SPECIFIED
	BR	IODON		;

IEIEF:	MOV	#IE.IEF&377,R0	;INVALID EVENT FLAG
	BR	IODON		;
   ²  
IEIFC:	MOV	#IE.IFC&377,R0	;INVALID FUNCTION CODE
	BR	IODON		;

IEPRI:	MOV	#IE.PRI&377,R0	;PRIVLEGE VIOLATION
	BR	IODON		;

IEREJ:	MOV	#IE.REJ&377,R0	;TRANSFER REJECTED
	BR	IODON		;

IESPC:	MOV	#IE.SPC&377,R0	;INVALID PARAMETERS
	BR	IODON		;

IEVER:	MOV	#IE.VER&377,R0	;PARITY ERROR
	BR	IODON		;

ISSUC:	MOV	#IS.SUC&377,R0	;SUCCESSFUL OPERATION

IODON:	CALL	$IOALT		;FINISH I/O
	JMP	LTINI		;TRY FOR MORE

	.END
 ²         ãXRkQ	› c,        	.TITLE	DRSMG
	.IDENT	/01.03/

;
; THIS  SOFTWARE  IS FURNISHED UNDER A LICENSE AND MAY
; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE  TERMS
; OF SUCH LICENSE.
;
; COPYRIGHT (c) 1981 BY DIGITAL EQUIPMENT CORPORATION.
; ALL RIGHTS RESERVED.
;
; VERSION 01.03
;
; D. T. BROWN 30-DEC-80
;
; PREVIOUSLY MODIFIED BY:
;
; MODIFIED BY:
;
;	DAN BROWN	22-FEB-81
;		DTB001 -- FIX PROBLEMS WITH INCORRECT PRIVILEGE CHECKING
;			  AND INCORRECT STACK USAGE.
;
;	M. S. HARVEY	16-JUL-81
;		MSH179 --       CLEAN UP CODE A BIT
;
;	M. S. HARVEY	2-OCT-81
;		MSH192 -- REJECT DIRECTIVE IF SPECIFIED LUN IS
;			  ASSIGNED TO NON-MASS STORAGE DEVICE
;
; MACRO LIBRARY CALLS
;
	.MCALL	EPKDF$
	EPKDF$			;DEFINE ERROR PACKET OFFSETS
	.IF DF E$$LOG

;+
; **-$DRSMG-SEND MESSAGE
;
; THIS DIRECTIVE SENDS A MESSAGE TO A SYSTEM PROCESS.
;
; DPB FORMAT:
;
;	WD. 00 -- DIC(171.),DPB SIZE
;	WD. 01 -- TARGET IDENTIFIER
;	WD. 02 -- BUFFER ADDRESS
;	WD. 03 -- BUFFER LENGTH
;	WD. 04 -- BEGINNING OF TARGET SPECIF      IC PARAMETER LIST
;
; PARAMETER LIST FOR TARGET IDENTIFIER SM.SER:				;DTB001
;									;**-1
;	WD. 04 -- ERROR LOG PACKET TYPE CODE
;	WD. 05 -- ERROR LOG PACKET SUBTYPE CODE
;	WD. 06 -- LOGICAL UNIT NUMBER (OPTIONAL)
;	WD. 07 -- CONTROL MASK WORD (OPTIONAL)
;
; INPUTS:
;
;	R2=ADDRESS OF THE SECOND TASK STATUS WORD OF THE CURRENT TASK.
;	R3=ADDRESS OF THE NEXT WORD IN THE DIRECTIVE DPB.
;	R4=ADDRESS OF THE HEADER OF THE CURRENT TASK.
;	R5=ADDRESS OF THE TCB OF THE CURRENT TASK.
;
; OUTPUTS:      
;
;	C=0 IF DIRECTIVE IS SUCCESSFULLY COMPLETED.
;		DIRECTIVE STATUS OF +1 IS RETURNED.			;MSH179
;	C=1 IF DIRECTIVE IS REJECTED.					;MSH179
;		DIRECTIVE STATUS OF 'D.RS1' IS RETURNED IF THERE IS	;MSH179
;			NOT ENOUGH POOL, OR IF THE TOTAL MESSAGE	;MSH179
;			LENGTH IS GREATER THAN 512. BYTES.		;MSH179
;		DIRECTIVE STATUS OF 'D.RS5' IS RETURNED IF THE		;MSH192
;			SPECIFIED LUN IS ASSIGNED TO A NON-MASS		;MSH192
;			STORAGE DEVICE, OR IF THE LUN IS NOT		;MSH192
;			ASSIGNED.					;MSH192
;		DIRE      CTIVE STATUS OF 'D.RS7' IS RETURNED IF ERROR	;MSH179
;			LOGGING IS NOT ACTIVE AND PACKET CANNOT		;MSH179
;			BE QUEUED.					;MSH179
;		DIRECTIVE STATUS OF 'D.RS8' IS RETURNED IF AN		;MSH179
;			INVALID MESSAGE TARGET IS SPECIFIED.		;MSH179
;		DIRECTIVE STATUS OF 'D.RS16' IS RETURNED IF THE		;MSH179
;			ISSUING TASK IS NOT PRIVILEGED.			;MSH179
;		DIRECTIVE STATUS OF 'D.RS99' IF THE SIZE OF THE		;MSH179
;			DPB IS INVALID.					;MSH179
;-									;**-12
$DRSMG::
;
; CHECK THE TARGET CODE
;
	MO      VB	-(R3),R0	;GET THE DPB SIZE			;MSH179
	CMPB	(R3)+,#6.	;DPB OF MINIMUM LENGTH?			;MSH179
	BHIS	10$		;IF HIS YES				;MSH179
	DRSTS	D.RS99		;DPB HAS INVALID DPB LENGTH		;MSH179
									;MSH179
10$:	CMP	(R3)+,#SM.SER	;IS THE TARGET ERROR LOGGING?		;MSH179
	BEQ	30$		;IF EQ YES				;MSH179
20$:	DRSTS	D.RS8		;INVALID TARGET OR INCORRECT FLAGS	;MSH179
;									;**-6
; OBTAIN THE CONTROL MASK WORD
;
30$:	MOV	#SM.HDR!SM.TSK,-(SP) ;INITIALIZE THE FLAGS TO USE	;MSH179
	CMPB	R0,#8.		;CHECK IF A CONTROL MA      SK WORD EXISTS	;**-1
	BLO	40$		;IF LO THERE IS NO CONTROL MASK WORD	;MSH179
	BIS	12(R3),(SP)	;OBTAIN THE CONTROL MASK WORD		;**-1
;
; CHECK THE CONTROL MASK WORD FOR VALIDITY
;
	BIT	#SM.DID!SM.DOP!SM.DAC!SM.DAT,(SP) ;DON'T ALLOW THESE	;DTB001
	BNE	20$		;IF NE USER ATTEMPTED TO SPECIFY THEM	;MSH179
	BIT	#SM.ZER,(SP)	;ZERO I/O COUNTS?			;MSH179
	BEQ	40$		;IF EQ NO				;MSH179
	BIT	#T3.PRV,T.ST3(R5) ;IS THE TASK PRIVILEGED?		;**-5
	BNE	40$		;IF NE YES				;DTB001
	DRSTS	D.RS16		;PRIVILEGED OPERATION	      		;**-4
;
; VALIDATE MESSAGE CREATION
;
40$:	TST	$ERRPT		;IS THERE AN ERROR LOG TASK INSTALLED?	;MSH179
	BEQ	45$		;IF EQ NO				;MSH179
	BIT	#ES.DAT,$ERFLA	;DATA ALLOWED?				;**-2
	BNE	50$		;IF NE YES, LET IT THROUGH		;MSH179
	BIT	#SM.CMD,(SP)	;IF DATA NOT ALLOWED, MUST BE A COMMAND	;**-1
	BNE	50$		;IF NE YES, LET IT THROUGH		;MSH179
45$:	DRSTS	D.RS7		;NOT ACTIVE				;MSH179
;									;**-2
; GET THE TYPE CODE AND SUBTYPE CODE INTO A SINGLE WORD
;
50$:	CMP	(R3)+,(R3)+	;POINT AT THE CODE WORD			;      MSH179
	MOV	(R3)+,-(SP)	;GET THE ENTIRE CODE WORD		;**-1
	MOVB	(R3)+,1(SP)	;OVERWRITE THE HIGH BYTE WITH THE
				; SUBCODE.
	INC	R3		;ADJUST TO POINT TO THE LUN WORD
;
; GET THE UCB ADDRESS OF THE REFERENCED DEVICE, IF PRESENT, INTO R0, AND
; GET THE CONTROL MASK WORD INTO R1 WITH THE FLAG SET FOR THE DEVICE
; IDENTIFICATION SUBPACKET IF THERE IS A DEVICE REFERENCED.
;
	CMPB	R0,#7.		;CHECK TO SEE IF A LUN WORD EXISTS
	BLO	60$		;IF LO THERE IS NO LUN WORD		;MSH179
	TST	(R3)		;CHECK TO SEE IF A L      UN IS PRESENT	;**-1
	BEQ	60$		;IF EQ THERE IS NO LUN SPECIFIED	;MSH179
	CALL	$MPLUN		;MAP THE LUN				;**-1
	BCC	55$		;IF CC LUN IS ASSIGNED TO SOMETHING	;MSH192
53$:	DRSTS	D.RS5		;NOT ASSIGNED TO ERROR LOGGING DEVICE	;MSH192
									;MSH192
55$:	BIT	#DV.MSD,U.CW1(R0) ;MASS STORAGE DEVICE?			;MSH192
	BEQ	53$		;IF EQ NO, NOT AN ERROR LOGGING DEVICE	;MSH192
	TST	-(R3)		;POINT TO LUN (ADVANCED BY $MPLUN)	;MSH192
	BIS	#SM.DID,2(SP)	;FLAG THE PRESENCE OF A DEVICE		;**-3
				; IDENTIFICATION SUBPACKET.      
;
; SAVE THE UCB POINTER FUTURE USAGE.
;
60$:	MOV	R0,-(SP)	;SAVE THE UCB POINTER			;MSH179
				; NOTE THAT THE CONTENTS ARE UNDEFINED	;**-1
				; IF THERE WAS ACTUALLY NO LUN.
;
; GET AND ADDRESS CHECK THE BUFFER PARAMETERS
;
	CMP	-(R3),-(R3)	;POINT BACK TO THE BUFFER LENGTH
	MOV	-(R3),R1	;GET THE BUFFER LENGTH IN BYTES
	BEQ	75$		;IF EQ THERE IS NO BUFFER		;MSH179
	BIS	#SM.DAT,4(SP)	;FLAG THAT THERE IS A DATA SUBPACKET	;**-1
	MOV	-(R3),	R3	;GET THE BUFFER POINTER

	.IF DF	A$$CHK!M$$MGE

	M      OV	R1,-(SP)	;SAVE THE BUFFER LENGTH
	CALL	$ACHKP		;PERFORM ADDRESS CHECK AND MAP BUFFER
	MOV	(SP)+,R1	;RESTORE THE BUFFER LENGTH

	.ENDC	; A$$CHK!M$$ME
;
; WE NOW HAVE:
;
;	R0	UNDEFINED
;	R1	BUFFER LENGTH IN BYTES
;	R2	UNDEFINED
;	R3	BUFFER ADDRESS, POSSIBLY REMAPPED
;	R4	UNDEFINED
;	R5	UNDEFINED
;
;	0(SP)	POINTER TO DEVICE UCB (UNDEFINED IF NO UCB)
;	2(SP)	ENTRY TYPE CODE AND TYPE SUBCODE BYTES
;	4(SP)	CONTROL MASK WORD
;
75$:	MOV	(SP)+,R5	;OBTAIN THE UCB POINTER			;DTB001
	MOV	(SP)+,R      0	;OBTAIN THE ENTRY TYPE CODE AND SUBCODE	;DTB001
	MOV	(SP)+,R2	;OBTAIN THE CONTROL MASK WORD		;**-2
	MOV	$TKTCB,R4	;OBTAIN THE TASK TCB
;
; WE NOW HAVE:
;
;	R0	ENTRY TYPE CODE AND SUBCODE
;	R1	BUFFER LENGTH IN BYTES
;	R2	CONTROL MASK WORD
;	R3	BUFFER ADDRESS, POSSIBLY REMAPPED
;	R4	POINTER TO TASK TCB OF CALLING TASK
;	R5	POINTER TO DEVICE UCB
;
	CALL	$CRPKT		;CREATE THE PACKET
	BCC	80$		;IF CC PACKET CREATED			;MSH179
	DRSTS	D.RS1		;INSUFFICIENT POOL			;**-1
80$:	CALLR	$QUPKT		;QUEUE THE P   F   ACKET AND RETURN		;MSH179
									;**-1
	.ENDC	; E$$LOG

	.END
 F          4RðskQ	› c,        ;
;		COPYRIGHT (c) 1981 BY
;	DIGITAL EQUIPMENT CORPORATION, MAYNARD
;	 MASSACHUSETTS.  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 TRANSFERED.
;
; THE IN      FORMATION  IN THIS DOCUMENT 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 THAT IS NOT SUPPLIED BY DIGITAL.
;
;

	.TITLE	MFDRV	RSX11M TU78 MAG TAPE DRIVER
	.IDENT	/V00.0/

;+
;  MFDRV is the software interface between the RSX11M Operating 
; System and TM78/TU78 DEC Magtape System.  
;
;  The TM78/TU78 DEC Magtape System has       the following characteristics:
;
; TM78 Control Unit - May have up to four (4) TU78 Tape Units attached.
; TU78 Tape Unit - Data Recording Mode is 6250BPI (GCR) or 1600BPI (PE)
;  at 125IPS (Inches/Sec.)  Data recording is per ANSI X3.39 (1600BPI)
;  and ANSI X3.54 (6250BPI).
;-

;+
; ***** CAUTION - See Note on Page 5 for strapping Device Registers. *****
;-

; 	
; C. SESTOKAS	JUL '81
;
; EDIT	DATE		AUTHOR		REASON
; ____	____		______		______
;  001
;
;
;

	.ENABL	LC		; Lower Case - C      omments Field, Only !
	.PAGE
	.SBTTL	MACROS
;+
; MACRO LIBRARY CALLS
;-
	.MCALL	HWDDF$,PKTDF$,UCBDF$
	HWDDF$		; Hardware Registers
	PKTDF$		; I/O Packet Offsets
	UCBDF$		; Unit Control Block Offsets

;+
; MACRO DEFENITIONS
;-

; -- PUSH -- following forms:
;
; 1. Arguments may be defined or undefined. They are enclosed in < >
;    and separated by commas. Undefined Arguments entered as null elements
;    position signified by a comma.
; 2. No Arguments.

.MACRO	PUSH  ARGS		; Push Items       on Stack.

.NARG	HWMNY			; Number of Arguments in Call.
  .IF EQ HWMNY			; IF  No Arguments,
	CLR	-(SP)		;  THEN  Reserve Stack Space.
	.MEXIT	;HWMNY
  .IFF				; IF  Arguments.
    .IRP	X,<ARGS>
      .IF B   	X		; IF  Argument missing,
	CLR	-(SP)		; THEN  Reserve Stack Space.
      .IFF			; IF  Arguments
	MOV	X,-(SP)		; THEN  Put Them on Stack.
      .ENDC	;X
    .ENDM      ;X,<ARGS>
  .ENDC	      ;HWMNY
.ENDM	PUSH

; -- POP -- same forms as for PUSH.

.MACRO	POP   ARGS		; Pop Items fro      m Stack.

.NARG	HWMNY			; Number of Arguments in Call.
  .IF EQ HWMNY			; IF  No Arguments,
	TST	(SP)+		;  THEN  Skip Stack Element.
	.MEXIT	;HWMNY
  .IFF				; IF  Arguments.
    .IRP	X,<ARGS>
      .IF B	X		; IF  Argument missing,
	TST	(SP)+		; THEN  Skip Stack Element.
      .IFF			; IF  Arguments
	MOV	(SP)+,X		; THEN  Pop Them off Stack & to ARG.
      .ENDC	;X
    .ENDM      ;X,<ARGS>
  .ENDC	      ;HWMNY
.ENDM	POP

; **** Note PUSH/POP Usage: IF PUSH R2,R3  THEN POP R3,R2.

;+
; Lin      kage Macros - Used by this Driver servicing TM78/TU78 interrupts.
;-


; -- SUBR --

.MACRO	SUBR	ARG
	MOV	#.+12,@#ARG-2	; Setup Linkage Address
	JMP	ARG		;  and GO TO Subroutine.
.ENDM	SUBR


; -- RTRN --

.MACRO	RTRN	ARG
	JMP	@ARG-2		; Return from Subroutine.
.ENDM	RTRN	
	.PAGE
	.SBTTL	TM78 DEVICE, MASSBUS REGISTERS

TMREGS  =  22.		; # TM78 Device Registers - not including MFBAE, MFCS3.

MFCS1	= +00		; Control and Status 1
MFWC	= + 2		; Word Count
MFBA	=   4		; UNIBUS Address
MFBC      	=   6		; Byte Count
MFCS2	=  10		; Control and Status 2
MFDI	=  12		; Data Interrupt
MFDM	=  14		; Data Mode
MFAS	=  16		; Attention Summary
MFDS	=  20		; Drive Status
MFDB	=  22		; Data Buffer
MFDE	=  24		; Diagnostic Error
MFDT	=  26		; Drive Type
MFSN	=  30		; Serial Number
MFDR	=  32		; Diagnostic Request
MFDD	=  34		; Diagnostic Data
MFNDI	=  36		; Non Data Interrupt
MFND0	=  40		; Non Data Command - Tape Unit 0
MFND1	=  42		;  |	|     |	   - Tape Unit 1
MFND2	=  44		;  |	|     |	   - T      ape Unit 2
MFND3	=  46		; Non Data Command - Tape Unit 3
MFIA	=  50		; Internal Address
MFCR	=  52		; Control register


; ***** CAUTION *****

; TM78 Attached to RH70 MASSBUS Controller -
;  
;  DEV REG(s) - MFBAE/MFCS3 Registers physical address is determined by
;    strapping options in the RH70 Controller.
;
;    IF  TM78 ONLY DEVICE on the RH70, 
;      THEN  MFBAE/MFCS3 expected to be adjacent to other DEVICE Registers.
;        1. Strap RH70 properly.
;        2. Remove the following       defenition by placing a ; before the line.
;
;    IF  TM78.and.Other Devices on the same RH70,
;      THEN  MFBAE/MFCS3 expected to be at end of that MASSBUS 
;       controller address space.
;        1. Delete strapping in RH70.
;	 2. Following defenition remains.
;

XTREG=0		; RH Controller - BAE and CS3 Reg's at end of 32 Word Boundary

.IIF NDF XTREG,	MFBAE = 54	; Bus Address Extension Register
.IIF DF XTREG,	MFBAE = 74	

.IIF NDF XTREG,	MFCS3 = 56	; Control and Status 3
.IIF DF XTREG,	M      FCS3 = 76
	.PAGE
	.SBTTL	REGISTER BIT/FIELD DEFENITIONS
;+
; MFCS1 REGISTER	RH/TM Shareable Register.
;-

C1.SC	= 100000	; RH Reg - Special Condition
C1.TRE	=  40000	; RH Reg - Transfer Error 
C1.CPE	=  20000	; RH Reg - Control Bus Parity Error
C1.DVA	=   4000	; TM Reg - Drive Available
C1.PSL	=   2000	; RH Reg - Port Select
C1.A17	=   1000	; RH Reg - UNIBUS @ 	   - A17
C1.A16	=    400	; RH Reg -  Extension Bits  - A16
C1.RDY	=    200	; RH Reg - Ready (for Data Transfer)
C1.IE	=    100	; RH R      eg - Interrupt Enable
C1.DFC	=     76	; TM Reg - Data Transfer Function Code
C1.GO	=      1	; TM Reg - Go. Initiate data transfer

;+
; Data Transfer Function Codes - GO and IE Bit set.
;-

FC.PE	= 61 ! C1.IE	; Write 1600 (PE)
FC.GCR	= 63 ! C1.IE	; Write 6250 (GCR)
FC.RDF	= 71 ! C1.IE	; Read Forward
FC.RDR	= 77 ! C1.IE	; Read Reverse
FC.XSN	= 73 ! C1.IE	; Extended Sense

;+
; MFWC REGISTER		MASSBUS Word Count Register
;-			 2's complement WORD COUNT.

;+
; MFBA REGISTER		UNIBUS Address Re      gister.
;-			 177776. LSB not used.

;+
; MFBC REGISTER		TM (Read/Write) Byte Count Register.
;-

;+
; MFCS2 REGISTER	RH REGISTER
;-

C2.DLT	= 100000	; Data Late
C2.WCE	=  40000	; Write Check Error
C2.UPE	=  20000	; UNIBUS Parity Error
C2.NED	=  10000	; Non-existent Drive
C2.NEM	=   4000	; Non-existent Memory
C2.PGE	=   2000	; Program Error
C2.MXF	=   1000	; Missed Transfer
C2.DPE	=    400	; MASSBUS Data Parity Error
C2.OR	=    200	; Output Ready
C2.IR	=    100	; Input Ready
C2.CLR	=           40	; Controller Clear
C2.PAT	=     20	; Parity Test
C2.BAI	=     10	; UNIBUS Address Increment Inhibit
C2.UNT	=      7	; TM Unit Select (0-7)

;+
; MFDI REGISTER		TM Register
;-

DTFLCD	= 176000	; Data Transfer Failure Code
DPR	=    400	; "1" - Drive Present
DTINTC	=     77	; Data Interrupt Code

;+
; MFDM REGISTER		TM Register
;-

DM.SER	= 100000	; Suppress Error Recovery
DM.FMT	=  70000	; Data (assembly/disassembly) Format Mode
DM.SKP	=   7400	; Skip Count - Read:'0' fill followed by       data.
DM.CNT	=    374	; Record Count - number of to be read/written.

;+
; MFAS REGISTER		TM Register
;-

AS.BTS	=    377	; Attention Summary: Bit0-Drive0, Bit7-Drive7.

;+
; MFDS REGISTER		TM Register
;-

DS.RDY	= 100000	; Unit online - ready for execution.
DS.PRS	=  40000	; Unit has power applied.
DS.ONL	=  20000	; Unit online.
DS.REW	=  10000	; Unit is Rewinding.
DS.PE	=   4000	; Unit in 1600(PE) recording mode.
DS.BOT	=   2000	; Unit at tape BOT.
DS.EOT	=   1000	; Unit detected tape E      OT.
DS.FPT	=    400	; Unit write protected (No Write Ring).  
DS.AVL	=    200	; Drive available to MASSBUS.
DS.SHR	=    100	; Drive shareable to both MASSBUS ports.
DS.MNT	=     40	; Drive in maintenance mode - unavailable for use.
DS.DSE	=     20	; Unit in erase portion of DSE operation.

;+
; MFDB REGISTER		RH REGISTER - Data Buffer
;-

;+
; MFDE REGISTER		TM Register - Diagnostic Error
;-

;+
; MFDT REGISTER		TM Register - Drive Type
;-

DT.TAP	=  40000	; '1' - Tape Device
DT.DPT	=         4000	; Dual Port Feature
DT.WCS	=   2000	; '1' - Writeable Control Store
DT.DTP	=    777	; Drive Type - TM78 = 101

;+
; MFSN REGISTER		TM Register - Serial Number
;-

SN.SN3	= 170000	; BCD Serial Number 3
SN.SN2	=   7400	;  |     |      |   2
SN.SN1	=    360	;  |     |      |   1
SN.SN0	=     17	; BCD Serial Number 0


;+
; MFDR REGISTER		TM Register - Diagnostic Request
;-


;+
; MFDD REGISTER		TM Register - Diagnostic Data
;-


;+
; MFNDI REGISTER	TM Register - Non Data Interrupt       Status
;-

NDFLCD	= 176000	; Non Data Failure Code
NDUNIT	=   1400	; Tape Unit Number


;+
; MFNDx REGISTER(S)	TM Register - Non Data Command, Tape Unit (x) 0-4.
;-

CMCNTx	= 177400	; Command Count for Tape Unit x.
NDFCTx	=     76	; Non Data Function Code for Tape Unit x.
GOBITx	=      1	; Go Bit for Non Data Command for Tape Unit x.


; Non Data Transfer Commands - GO Bit set.

ERGGCR=	      37	; Erase 3" Gap, GCR.
ERGPE=	      35	; Erase 3" Gap, PE.
WTMGCR=	      17	; Write Tape Mark,       GCR.
WTMPE=	      15	; Write Tape Mark, PE.
DSE= 	      13	; Data Security Erase.
SNSE=	      11	; Sense Tape Unit Characteristics.
RWND=	       7	; Rewind Tape on Tape Unit.
UNLD=	       5	; Rewind and Unload Tape on Tape Unit.
SFTMK=	      25	; Space Forward TMK.
SRTMK=	      27	; Space Reverse TMK.
SLTMK=	      47	; Space Forward TMK/LEOT. IF LEOT, position AEOV.
SFREC=	      21	; Space Forward REC.
SRREC=	      23	; Space Reverse REC.





;+
; MFIA REGISTER		TM Register - TM78 Interna      l Address
;-

;+
; MFCR REGISTER		TM Register - TM78 Control Register
;-

TMRDY	= 100000	; TM78 available for command execution
TMCLR	=  40000	; TM78 Clear
MCPE	=  20000	; TM78 ROM parity error
ILR	=  10000	; TM78 reference to nonexistent MASSBUS register
CPE	=   4000	; TM78 parity error detect - write to MASSBUS reg
EVPAR	=   2000	; TM78 even parity generate/check on MASSBUS cntl bus
HLDA	=   1000	; TM78 microprogram sequencing inhibited
HOLD	=    400	; TM78 HOLD bit - inhibit microprogram se      quencing
INTDT	=    377	; Internal Data

;+
; MFBAE REGISTER	RH REGISTER - Bus Address Extension Register
;-

BA.BTS	=     77	; Bus Address bits 21-16. Logical extn of MFBA register


;+
; MFCS3 REGISTER	RH REGISTER - Control and Status Reg 3
;-

C3.APE	= 100000	; Address Parity Error
C3.PEO	=  40000	; Data Parity Error - Odd Word
C3.PEE	=  20000	; Data Parity Error - Even Word  
C3.CEO	=  10000	; Write Check Error - Odd Word
C3.CEE	=   4000	; Write Check Error - Even Word
C3.DW	=   2000	      ; Double Word
C3.IE	=    100	; Interrupt Enable
C3.IPC	=     17	; Inverted Parity Check
	.PAGE
	.SBTTL	TM78 INTERRUPT CODES
;+
; TM78 INTERRUPT CODES - Data/Non Data Transfers and TM78 Initiated
;-

; Bit Mask Values		       Int Code 
ILG  = 1		; Illegal       0.
DON  = 2		; NDT or DT.    1, Done.
TMK  = 4		; NDT or DT.    2, Tape Mark.
BOT  = 10		; NDT or DT.    3, Beginning of Tape.
EOT  = 20		; NDT or DT.	4, End of Tape.
LEOT = 40		; NDT.	 	5, Logical End of Tape.
NOOP = 100		; NDT.		6, N      O OP Command.
RWD  = 200		; NDT.		7, Rewinding.
FPT  = 400		; NDT or DT.   10, Write Protect.
NRDY = 1000		; NDT or DT.   11, TM78 not ready to execute command.
NAVL = 2000		; NDT or DT.   12, TU78 not avail to this port.
OFLN = 4000		; NDT or DT.   13, TU78 Offline.
NTEX = 10000		; NDT or DT.   14, TU78 Non Existant.
NTCP = 20000		; NDT or DT.   15, Read initiated, not performed.
UNDF = 40000		; Undefined.   16,
ONLN = 100000		; TM Initiated 17, TU78 < Online. TU78 Sense Data.

RLL  = 1		; DT.	             20, Read data OK. GT requested.
RLS  = 2		; DT.	       21, Read data OK. LT requested.
RTRY = 4		; DT.	       22, Retry operation - same direction.
RDOP = 10		; DT.	       23, Read Data in opposite direction.
UNRD = 20		; DT.	       24, Data Unreadable after retries.
ERR  = 40		; DT.	       25, Data Transfer error - Surp Err Rcvry
EOTE = 100		; DT.	       26, Write err after EOT - Surp Err Rcvry
BDTP = 200		; NDT or DT.   27, Bad tape- Write failure ! Lost Posit
TMFA = 400		; NDT or DT.   30,       TM Fault A - Failure, I/O operation
TUFA = 1000		; NDT or DT.   31, TU Fault A - Failure, I/O operation
TMFB = 2000		; TM Initiated 32, TM Fault B - Failure, no I/O
TMFB = 4000		; Not Used.    33,
MBFL = 10000		; TM Initiated 34, Massbus Control Bus Fault.


; TM78 Initiated Interrupts.

TMI1=	ONLN
TMI2=	TMFB ! MBFL


; Data Transfer Operation Interrupts.
							; WRITE
WRTI1=	DON ! EOT ! FPT ! NRDY ! NAVL ! OFLN ! NTEX
WRTI2=	RTRY ! ERR ! EOTE ! BDTP ! TMFA ! TUFA
							; READ FWD
RDFI1=      	DON ! TMK ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
RDFI2=	RLL ! RLS ! RTRY ! RDOP ! UNRD ! ERR ! BDTP ! TMFA ! TUFA
							; READ REV
RDRI1=	DON ! TMK ! BOT ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
RDRI2=	RLL ! RLS ! RTRY ! RDOP ! UNRD ! ERR ! BDTP ! TMFA ! TUFA
							; XTND SNS
XNSI1=	DON

; Non Data Transfer Operation Interrupts.
							; WRITE TMK
WTMI1=	DON ! EOT ! FPT ! NRDY ! NAVL ! OFLN ! NTEX
WTMI2=	BDTP ! TMFA ! TUFA
							; SENSE
SNSI1=	DON
SNSI2=	TMFA ! TUFA
							; SPACE TMK, FWD
SFTMI1=       DON ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
SFTMI2=	BDTP ! TMFA ! TUFA
							; SPACE TMK, REV 
SRTMI1=	DON ! BOT ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
SRTMI2=	BDTP ! TMFA ! TUFA
							; SPACE TMK/LEOT, FWD
SLTMI1=	DON ! LEOT ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
SLTMI2=	BDTP ! TMFA ! TUFA
							; SPACE RECORD, FWD
SFRCI1=	DON ! TMK ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
SFRCI2=	BDTP ! TMFA ! TUFA
							; SPACE RECORD, REV
SRRCI1=	DON ! TMK ! BOT ! NRDY ! NAVL ! OFLN ! NTEX ! NTCP
SRRCI2=	BDTP ! TMFA !TUF      A
							; ERASE 3" GAP
ERGI1=	DON ! EOT ! FPT ! NRDY ! NAVL ! OFLN ! NTEX
ERGI2=	BDTP ! TMFA ! TUFA
							; DATA SECURITY ERASE
DSEI1=	DON ! FPT ! NRDY ! NAVL ! OFLN ! NTEX
DSEI2=	TMFA ! TUFA
							; REWIND
RWDI1=	DON ! RWD ! NRDY ! NAVL ! OFLN ! NTEX
RWDI2=	TMFA ! TUFA
							; UNLOAD
UNLI1=	DON ! NRDY ! NAVL ! OFLN ! NTEX
UNLI2=	TMFA ! TUFA

	.SBTTL	Function Tables
;+
;TM78/TU78 Spacing Subfunction Table
;-

.MACRO	SPCFCT	SPCGCR,SPCPE,TIMOUT,TIMES,SPCVL1,SPCVL2
	.BYTE	SPCGCR		; Comm      ands: 6250BPI,
	.BYTE	SPCPE		; 	    1600BPI.
	.BYTE	TIMOUT,TIMES	; Subcycle Time (S.CTM), Subcycles (S.STS).
	.WORD	SPCVL1		; Interrupt validation Mask 1.
	.WORD	SPCVL2		; Interrupt validation Mask 2.
	.ENDM	SPCFCT

SVALI1=	+4	; > Spacing Validation Mask(s).


SPFTMK:	SPCFCT	SFTMK,SFTMK, 2,120., SFTMI1,SFTMI2    ;Space FWD TMK.
SPRTMK:	SPCFCT	SRTMK,SRTMK, 2,120., SRTMI1,SRTMI2    ;Space REV TMK.
SPLTMK:	SPCFCT	SLTMK,SLTMK, 2,120., SLTMI1,SLTMI2    ;Space FWD TMK/LEOT
SPFREC:	SPCFCT	SFREC,SFREC,       2,120., SFRCI1,SFRCI2    ;Space FWD REC.
SPRREC:	SPCFCT	SRREC,SRREC, 2,120., SRRCI1,SRRCI2    ;Space REV REC.

;+
; Valid TM78/TU78 Function Table
;-

.MACRO 	FUNCT	FCT,PREPRO,CMNDGC,CMNDPE,TIMOUT,TIMES,VALI1,VALI2,ISRSRV
	.WORD	IO.'FCT		; I/O Function Code
	.WORD	PREPRO		; Preprocessing indications.
	.BYTE	CMNDGC		; Commands: 6250BPI,
	.BYTE	CMNDPE		;    |	    1600BPI.	
	.BYTE	TIMOUT,TIMES	; Subcycle Time (S.CTM), Subcycles (S.STS).
	.WORD	VALI1		; Interrupt Validation Mask 1.
	.WORD	VALI2		      ; Interrupt Validation Mask 2.
	.WORD	ISRSRV		; > ISR Service Routine.
	.ENDM	FUNCT

PWR=	1	; Test US.PWF Indication.
WRT=	2	; Test M.SWL Indication.
WTPW= PWR!WRT 	; Test US.PWF and M.SWL Indication.
REV=	4	; Test for Read Reverse.
DT=	8.	; Test for Data Request.
REWIND= 16.	; Test for Rewind Request.
UNLOAD= 32.	; Test for Unload Request.

PREPRO= +2	; > Pre process I/O request.
CMDGCR= +4	; > GCR Command.
CMDPE=  +5	; > PE Command.
TMOUT=  +6	; > Time out information.
VALI1=  +10	; > Vali      dation Mask(s).
ISRSRV= +14	; > ISR Service Routine.

IO.XSN=	37400	; Function - Not in QIO.MAC.

FTBL:

FUNCT	WLB, WTPW!DT,    FC.GCR,FC.PE,    3,1, WRTI1,WRTI2, WRTISR  ; WRITE
FUNCT	RLB, PWR!DT,     FC.RDF,FC.RDF, 20.,1, RDFI1,RDFI2, RDFISR  ; READ FWD
FUNCT   RLV, PWR!REV!DT, FC.RDR,FC.RDR, 20.,1, RDRI1,RDRI2, RDRISR  ; READ REV
FUNCT	EOF, WTPW,       WTMGCR,WTMPE,    3,1, WTMI1,WTMI2, WTMISR  ; WRITE TMK
FUNCT	STC,  0,         SNSE,  SNSE,     2,1, SNSI1,SNSI2, SNSISR  ; SET CHAR
FUNCT	SEC,        0,         SNSE,  SNSE,     2,1, SNSI1,SNSI2, SNSISR  ; SNS CHAR
FUNCT	SMO,  0,         SNSE,  SNSE,     2,1, SNSI1,SNSI2, SNSISR  ; S/MOU CHR
FUNCT	SPF, PWR,         0,     0,    2,120.,  0,    0,      0     ; SPC TMKS
FUNCT	SPB, PWR,         0,     0,    2,120.,  0,    0,      0     ; SPC BLCKS
FUNCT	ERS, WTPW,       ERGGCR,ERGPE,    3,1, ERGI1,ERGI2, ERGISR  ; ERS 3" GP
FUNCT	DSE, WTPW,       DSE,  DSE,    2,160., DSEI1,DSEI2, DSEISR  ; DSE
IORWD:
FUNCT	RWD, REWIND,     RWND,  RWND,   2,40., RWD      I1,RWDI2, RWDISR  ; REWIND
LNGHT=.-IORWD
FUNCT	RWU, UNLOAD,     UNLD,  UNLD,     2,1, UNLI1,UNLI2, UNLISR  ; RWND/UNLD
	
	.IF DF 	E$$DVC
FUNCT	XSN,  0,         FC.XSN,FC.XSN,   2,1, XNSI1,  0,   XNSISR  ; XTND SNS
	.ENDC	;E$$DVC

ENDFTB=.

	.PAGE
	.SBTTL	OPERATION RETURN CODES

;+
; I/O Operation Return Codes per TM78 Interrupt Code Values.
;-

				; Interrupt Designation/Code
RTRNTB:	.BYTE	     0		;  ILG   0 - Illegal.
	.BYTE	IS.SUC		;  DON   1 - Done.
	.BYTE	IE.EOF		;  TMK   2 - Tape M      ark.
	.BYTE	IS.SUC		;  BOT   3 - Beginning of Tape. 
	.BYTE	IE.EOT		;  EOT   4 - End of Tape.
	.BYTE	IE.EOV		;  LEOT  5 - Logical End of Tape.
	.BYTE	     0		;  NOOP  6 - No operation.
	.BYTE	IS.SUC		;  RWD   7 - Start of Rewind.
	.BYTE	IE.WLK		;  FPT  10 - File Protected.
	.BYTE	IE.DNR		;  NRDY 11 - Not ready for Command.
	.BYTE	IE.FHE		;  NAVL 12 - Not available to this port.
	.BYTE	IE.OFL		;  OFLN 13 - TU78 Offline. 
	.BYTE	IE.FHE		;  NTEX 14 - TU78 non-existant. 
	.BYTE	IE.FHE		;  NTCP 15 - N      ot cpbl- Rd Init, Not Prfrmd.
	.BYTE	     0		;  UNDF 16 - Undefined.
	.BYTE	     0		;  ONLN 17 - Online (Unsolicited).
	.BYTE	IE.DAO		;  RLL  20 - Long Record.
	.BYTE	IS.SUC		;  RLS  21 - Short Record.
	.BYTE	IE.VER		;  RTRY 22 - Retry operation.
	.BYTE	IE.VER		;  RDOP 23 - Read opposite.
	.BYTE	IE.VER		;  UNRD 24 - Unreadable.
	.BYTE	IE.VER		;  ERR  25 - Error, Retries suppressed.
	.BYTE	IE.VER		;  EOTE 26 - Error/EOT. Retries suppressed.
	.BYTE	IE.VER		;  BDTP 27 - Bad Tape. Write err/Posit lost      .
	.BYTE	IE.FHE		;  TMFA 30 - TM Fault A.
	.BYTE	IE.FHE		;  TUFA 31 - TU Fault A.
	.BYTE	     0		;  TMFB 32 - TM Fault B (Unsolicited). 
	.BYTE	     0		;  TUFB 33 - Undefined. 
	.BYTE	     0		;  MBFL 34 - MASSBUS Control Bus Fault
				;			(Unsolicited).
	.EVEN
	.PAGE
	.SBTTL	DEFENITION OF U.CW2/U.CW3

;+
; U.CW2 - Characteristics Word
; U.CW3 - Supported Tape Density Identification (Set up by SYSGEN)
;-


;+
; TAPE CHARACTERISTICS (U.CW2) WORD
;  Bits 6,7 and 11 user settable via IO.STC o      r IO.SMO. 
;   Bit 11 only allowed to be updated when tape unit not beyond BOT.
;  Returned per IO.SEC request in second status word.
;-

M.PEOV=	100000	; Returned to user as '0' - Driver internal use.
		;  Unlabelled tape operation - Tape in gap after EOV 
		;  (double TMK) having completed forward motion operation.
M.AEOV=	 40000	; Unlabelled tape operation - Tape positioned in gap
		;  between double TMK's (EOV) after forward motion operation.
M.BOT=	 20000	; Tape at BOT.
M.1600=	  4000	; * Ta      pe density control - '0'=6250BPI, '1'=1600.
M.HWL=	  2000	; Hardware Write Lock.
M.RWD=	  1000	; Driver indication that unit is rewinding.
M.SER=	   400	; Tape Unit select error (Tape Unit Offline).
M.IWR=	   200	; * Inhibit Write with Extended Inter-record gap (IRG).
M.SWL=	   100	; * Software write locked.
M.TMK=	    40	; Last Tape Command encountered TMK.
M.EOT=	    20	; Last command encountered EOT mark.

NEWBTS= M.AEOV ! M.BOT ! M.EOT ! M.HWL ! M.SER ! M.TMK
NWBTS1=		 M.BOT ! M.EOT ! M.HWL !       M.SER
NWBTS2=		 M.BOT ! M.EOT	       ! M.SER


;+
; SUPPORTED TAPE DENSITY (U.CW3) IDENTIFICATION
;
;  Low byte:  U.CW2, Bit11='0' - UD.625, 6250BPI.
;  High byte: U.CW2, Bit11='1' - UD.160, 1600BPI.
;-

	.PAGE
	.SBTTL	DRIVER PARAMETERS

US.SUP=2			; Supress Error Recovery

;+
; Driver Parameters - Indexed by RH Controller Number
;-

CNTBL:	.BLKW	T$$M78		; > UCB, I/O Dequeued.
DQDIO:	.BLKW	T$$M78		; I/O Dequeued - NEQ=Yes.
INPROG:	.BLKW	T$$M78		; I/O Status - NEQ= Lo Byte,I/O in Progre      ss;
				;		Hi Byte,Passed DEV REG's(UMD).
DTCMD:	.BLKW	T$$M78		; I/O Status - NEQ=Data Transfer.
XNSCMD:	.BLKW	T$$M78		; I/O Status - NEQ= Lo Byte,XND SNS Operation;
				;		Hi Byte,Unsolicited I/O.
IOFCT:	.BLKW	T$$M78		; > FTBL, Current I/O Request.
RTRNAD:	.BLKW	T$$M78		; Driver Return @: TU78 Offline/TM78 Not Ready.

DTCNT:	.BLKW	T$$M78		; Current DATA I/O Byte Count.
DTADR1:	.BLKW	T$$M78		; Current Address - U.BUF,U.BUF+1.
DTADR2:	.BLKW	T$$M78		;   | |     | |   - U.BUF+2.
RDOPCM:	.BLKW	T$$M78      		; > FTBL - Read Opposite Function.

INTCD1:	.BLKW	T$$M78		; Interrupt code to   Int 0 - 17
INTCD2:	.BLKW	T$$M78		;  Bit Code value:	  20 - 34
RSTATN:	.BLKW	T$$M78		; MFAS Reg Reset Mask - NDT Commands.
IOSTAT:	.BLKW	T$$M78		; I/O Operation Return Code.

SPCNT:	.BLKW	T$$M78		; Residual BLCK/TMK count - To be yet spaced
				;  .OR. Tape Char(s) - For SMO/STC.
SPACED:	.BLKW	T$$M78		; Spaced BLCK/TMK count - Already spaced.
SPCIO:	.BLKW	T$$M78		; Current I/O Space Count.
SPCNG:	.BLKW	T$$M78		; > Sp      acing Subfunction Table.

RTTBL:	.BLKW	T$$M78		; Retry count: +0,Rtrs left. +1,Total rtrs.
ERRPKT:	.BLKW	T$$M78		; > Error Log Packet.

	.IF GT	T$$M78-1
TEMP:	.BLKW	1		; PS Save Area. Lo 4 bits - Controller #.
	.ENDC

DCBPTR:	.WORD	0		; > DCB.

WTRTRY=	50.			; # Re-write attempts.
RDRTRY=	21.			; # Re-read attempts (embedded tape cleans).

;+
; DRIVER DISPATCH TABLE
;-

$MFTBL::
	.WORD	MFINI		; Initiate I/O Operation 
	.WORD	MFCAN		; Cancel I/O Operation
	.WORD	MFOUT		; Device Timeout
      	.WORD	MFPWF		; Powerfail Entry
	.PAGE
	.SBTTL	INITIATE I/O OPERATIONS
;+
; -- MFINI -- Initiate TU78/TM78 Mag Tape I/O Operation 
;
; Service QIO Directive or Completed I/O request, services remaining requests.
;
; IF the Dqu successful, THEN service the request.  ELSE RETURN to Caller. 
;
; Prior to CALL $GTPKT:
;    R5 - > UCB.
;
; Return from $GTPKT:
;
;   C=1	- Dequeue unsuccessful.  Controller Busy or No Request to DQU.
;
;   C=0 - Dequeue successful.
;    R1 - > I/O Pckt.
;    R2 -       Physical Tape Unit # (U.UNIT).
;    R3 - RH Controller Index (S.CON).
;    R4 - > SCB.
;    R5 - > UCB.
;-

MFINI:	CALL	$GTPKT		; Outstanding I/O request ?
	BCC	10$		; IF CC, Yes. Service it.
	RETURN			; Controller Busy or No I/O Request.

10$:	MOV	S.CSR(R4),R2	; R2=CSR.
	MOV	R5,CNTBL(R3)	; Save > UCB, Dqud I/O Request.
	MOV	I.FCN(R1),R1	; R1 - Function code.
	MOV	#FTBL,R0	; R0 > TM78/TU78 Function Table.
	BICB	#US.SUP,U.STS(R5) ; Assume Error recovery allowed.
	CLR	RTTBL(R3)	; Assume recove      ry count = 0.

	.IF DF	D$$IAG

	BITB	#IQ.UMD,R1	; Diagnostic function ?
	BEQ	15$		; IF EQ, No.
	MOV	#100000,RTTBL(R3) ; Diagnostic function,
	BISB	#US.SUP,U.STS(R5) ;  No error recovery.
 
15$:	.ENDC	;D$$IAG

	BITB	#IQ.X,R1	; Suppress error recovery ?
	BEQ	20$		; IF EQ, No.
	BISB	#US.SUP,U.STS(R5) ; No error recovery.

; Validate I/O Request Support.
20$:	BICB	#IQ.X!IQ.UMD!IQ.Q,R1 ; Cleanup function code for validation.
22$:	CMP	R1,(R0)		; I/O supported by TM78/TU78 ?
	BEQ	30$		; IF EQ, Ye      s. 
	ADD	#LNGHT,R0	; Next I/O function.
	CMP	R0,#ENDFTB	; Any more TM78/TU78 Functions ?
	BNE	22$		; IF NE, No. Keep looking for match/end.
	MOV	#IE.IFC&377,R0	;  Unsupported request. Notify user,
25$:	SUBR	ENDRQS		; End I/O request
	BR	MFINI		;  & Service other I/O requests.

; Preprocess I/O Request.
30$:	MOV	R0,IOFCT(R3)	; Save > FTBL, Dqud I/O request.
	TST	(R0)+		; > Preprocess functions.
; Function allowed if Powerfailure occured ?
	BIT	#PWR,(R0)	; I/O allowed if powerfailure occured?
	BE      Q	40$		; IF EQ, Yes.
	BITB	#US.PWF,U.STS(R5) ; Powerfailure occurence?
	BEQ	40$		; IF EQ, No.
	MOV	#IE.ABO&377,R0	; Function not allowed until US.PWF Reset.
	BR	25$		;  Endup this request.
; Function allowed if Software write locked ?
40$:	BIT	#WRT,(R0)	; Verify user write locking?
	BEQ	50$		; IF EQ, No.
	BIT	#M.SWL,U.CW2(R5)  ; User software write locked device?
	BEQ	50$		; IF EQ, No.
	MOV	#IE.WLK&377,R0	; Indicate write locked and
	BR	25$		;  endup this request.

; No I/O to Rewinding Tape Un      it.
50$:	INC	DQDIO(R3)	; Indicate DQD I/O pending.
	CLR	INPROG(R3)	; In case, 
	CLR	DTCMD(R3)	;   set.
	BIT	#M.RWD,U.CW2(R5) ; Tape Unit Rewinding ?
	BEQ	60$		; IF EQ, No.
	CMP	#IO.SEC,-2(R0)	; Sense Characteristics Request ?
	BNE	55$		; IF NE, No.
	BIC	#NWBTS2,U.CW2(R5) ; M.BOT, M.EOT, M.SER bits unpredictable.
	MOV	#IS.SUC&377,R0	; Indicate success and
	MOV	U.CW2(R5),R1	;  Characteristics Word.
	BR	25$		; . . Cont.

55$:	MOVB	#40.,S.STS(R4)	; Must wait for tape unit RWD completion.
	BR	65$		      ; . . Cont.

; I/O - only if TM78 Ready.
60$:	MOV	U.SUB(R5),MFCS2(R2) ; Select TM UNIT.
	TST	MFCR(R2)	; TM78 Ready for command ?
	BMI	INIOPR		; IF MI, Yes.
65$:	MOV	#INIOPR,RTRNAD(R3) ; Return to if TM becomes ready.
	MOVB	S.ITM(R4),S.CTM(R4) ; TMO for TM78 to become ready and
	RETURN			;  Defer Dqud I/O till TM78 becomes avail.

; To return here after RWD completes (have DQD PKT), need to re-establish:
;  R0 - > FTBL, Preprocess,     R2 - CSR,    	
;  R3 - RH Cont Index(S.CON),   R4 - > SCB,  R      5 - > UCB.
;
; GOTO I/O Initiate Routine.
INIOPR:	CLR	DQDIO(R3)	; No DQD I/O pending.
	INC	INPROG(R3)	; I/O Busy.
	BIT	#DT,(R0)	; Data Transfer ?
	BNE	DTIO		; IF NE, Yes.
	JMP	NDTIO		; Initiate NDT I/O.
	.PAGE
	.SBTTL	INITIATE DATA (I/O) SERVICING 
;+
;   Register configuration - Initiate Data (I/O) servicing:
;	R0 - > FTBL, Preprocess.  R3 - Controller Index (S.CON).
;	R2 - CSR.		  R4 - > SCB.
;				  R5 - > UCB.
;-

DTIO:	INC	DTCMD(R3)		; Data transfer I/O.
	MOVB	U.UNIT(R5),-(SP)	; Tape U      nit selection.
	BIC	#^C<3>,(SP)		; Perhaps won't suppress retries.
	BITB	#US.SUP,U.STS(R5)	; No error recovery this I/O request?
	BNE	9$			; IF NE, Yes.
	MOV	#RDRTRY,RTTBL(R3)	; Read recovery retries.
	MOV	IOFCT(R3),RDOPCM(R3)	; > Read Opposite 
	ADD	#LNGHT,RDOPCM(R3)	;  Function.
	BIT	#WRT,(R0)		; Write request?
	BEQ	10$			; IF EQ, No.
	BIT	#M.IWR,U.CW2(R5)	; Suppress recovery for user?
	BNE	8$			; IF NE, Yes.
	MOV	#WTRTRY,RTTBL(R3)	; Set up for Write recovery.
	BR	10$			; . . Cont.	
8$:	CLR	R      TTBL(R3)		; No retries allowed.
9$:	BIS	#DM.SER,(SP)		; Inhibit error recovery.
10$:	MOVB	RTTBL(R3),RTTBL+1(R3)	; Error Recovery Retries.
	POP	MFDM(R2)		; Data transfer for Tape Unit x.

	.IF DF	M$$EXT		; 22 Bit Extnd Addr (11/70, 11/44).

	BIT	#DV.MBC,U.CW1(R5)	; RH11 ?
	BNE	20$			; IF NE, No - RH70.
	CALL	$STMAP			; Setup UNIBUS mapping.
	ASL	U.BUF(R5)		; Setup A17,A16
	ASL	U.BUF(R5)		;  address bits
	ASL	U.BUF(R5)		;   into 
	ASL	U.BUF(R5)		;    HI Byte.
	CALL	$MPUBM			; Setup UMRs for tran      sfer.
	MOV	S.CSR(R4),R2		; Restore R2 - CSR
	MOV	IOFCT(R3),R0		; R0 >
	TST	(R0)+			;  Preprocessing.

20$:	.ENDC	;M$$EXT

	MOV	R5,R1			; R1 >
	ADD	#U.BUF,R1		;   U.BUF.

	.IF NDF	M$$EXT
	.IF  DF M$$MGE		; 18 Bit Addressing.

	ROL	(R1)			; Setup A17,A16
	ROL	(R1)			;  address bits
	ROL	(R1)			;   into
	ROL	(R1)			;    HI Byte.

	.ENDC	;M$$MGE
	.ENDC	;M$$EXT

	BIT	#REV,(R0)		; Read Reverse request ?
	BEQ	30$			; IF EQ, No.
	SUB	#2,U.CNT(R5)		; Read Reverse -
	ADD	U.CNT(R5),U.BUF+2(R5)	      ;  Adjust Buffer Pointer
	BCC	28$			;   to end of 
	ADCB	U.BUF+1(R5)		;    Buffer Area.
28$:	ADD	#2,U.CNT(R5)		; Restore Transfer Count.
	SUB	#2*LNGHT,RDOPCM(R3)	; > Read Opposite Function.


30$:	MOV	#DTIOGO,RTRNAD(R3)	; Return @ if need restart operation.
	MOV	U.CNT(R5),DTCNT(R3)	; Current Data I/O Byte Count,
	MOV	U.BUF(R5),DTADR1(R3)	; HI BYTE: 6@ (RH70/22 bit @) bits or
					;  2@ (RH11/18 bit @) bits
					;   [A16,A17/Bit8,9] 
	MOV	U.BUF+2(R5),DTADR2(R3)	;    and low 16 Address bits.

;+      
; Register Configuration - per DTIO entry.
;-

DTIOGO:	MOV	DTCNT(R3),MFBC(R2)	; Data byte count for TM.
	MOV	MFBC(R2),MFWC(R2)	;   Word 
	CLC				;    count
	ROR	MFWC(R2)		;     for RH.
	NEG	MFWC(R2)		;   (2's complement)
	MOV	DTADR2(R3),MFBA(R2)	; Transfer address - 16 lo order bits.
	TST	(R0)+			; > I/O Function Code.
	MOVB	(R0),DTADR1(R3)		; I/O code - 6250BPI mode.
	BIT	#M.1600,U.CW2(R5)	; 1600BPI mode ?
	BEQ	10$			; IF EQ, No.
	MOVB	1(R0),DTADR1(R3)	; I/O code - 1600BPI mode.
10$:	BIC	#N      EWBTS,U.CW2(R5) 	; I/O operation changes SENSE data.
	MOVB	2(R0),S.CTM(R4)		; Start I/O Timeout.

	MTPS	#PR7			; INHIBIT INTERRUPTS
				; Start I/O
	.IF DF	M$$EXT		
	BIT	#DV.MBC,U.CW1(R5)	;;; RH70 (MASSBUS Controller) ?
	BEQ	20$			;;; IF EQ, No.
	MOVB	DTADR1+1(R3),MFBAE(R2)	;;; Start transfer
	MOVB	DTADR1(R3),MFCS1(R2)	;;;  on 11/70.
	BR	22$			;;; . . cont .

	.IFTF
20$:	MOV	DTADR1(R3),MFCS1(R2)	;;; Start transfer on others.
22$:	.ENDC

	MTPS	#0			;;; ALLOW INTERRUPTS

	RETURN				; EXIT wh      ile I/O in progress.
	.PAGE
	.SBTTL	INITIATE NONDATA (I/O) SERVICING
;+
;   Register configuration - Initiate Non Data (I/O) servicing:
;	R0 - > FTBL, Preprocess.  R3 - Controller Index (S.CON).
;	R2 - CSR.		  R4 - > SCB.
;				  R5 - > UCB.
;-

	.ENABL	LSB
NDTIO:	BIT	#REWIND,(R0)		; Rewind request ?
	BEQ	5$			; IF EQ, No.
	BIS	#M.RWD,U.CW2(R5)	; Rewind indication.
5$:	MOV	U.BUF(R5),SPCNT(R3)	; Save Space Count/Tape Char(s).
	MOV	#STRTIO,RTRNAD(R3)	; Return @ if need restart operation.
	TST	(      R0)+			; > I/O Command.
	TST	(R0)			; Space via TMKS or Blocks ?
	BEQ	SPACE			; IF EQ, Yes.
	CLR	U.BUF(R5)		; Setup NDT
	MOVB	(R0),U.BUF(R5)		;  6250BPI Command Word.
	BIT	#M.1600,U.CW2(R5)	; 1600BPI Command?
	BEQ	STRTIO			; IF EQ, No.
	MOVB	1(R0),U.BUF(R5)		; Setup NDT 1600BPI Command Word.

STRTIO:	TST	-2(R0)			; SENSE request ?
	BEQ	10$			; IF EQ, Yes.
SPSTRT:	BIC	#M.AEOV!M.TMK,U.CW2(R5)	; Update M.AEOV/M.TMK and
10$:	BIC	#NWBTS1,U.CW2(R5)	;  M.BOT, M.EOT, M.HWL, M.SER bits.
	TST	(R0)+			; >       Timeouts.
	MOVB	(R0)+,S.CTM(R4)		; Start I/O
	MOVB	(R0)+,S.STS(R4)		;  Timeout.

	MTPS	#PR7			; INHIBIT INTERRUPTS
	MOV	#C1.TRE,MFCS1(R2)	;;; Make sure no previous transfer
	BIC	#C1.TRE,MFCS1(R2)	;;;  error holds up this I/O transfer.
	MOV	#C1.IE!C1.DVA,MFCS1(R2) ;;; Allow interrupts on this RH.
	MOVB	U.UNIT(R5),R3		;;; Prepare 
	ASL	R3			;;;  for MFNDx
	ADD	R3,R2			;;;    accessing.
	MOV	U.BUF(R5),MFND0(R2)	;;; Start Non Data Transfer.
	MTPS	#0			;;; ALLOW INTERRUPTS
	RETURN				; EXIT While I      /O in progress.
	.DSABL	LSB

	.ENABL	LSB
SPACE:	TST	SPCNT(R3)		; Space count =0 ?
	BNE	10$			; IF NE, No.
	CLR	INPROG(R3)		; No active I/O. 
	MOV	#IS.SUC&377,R0		; Successful end, no Rcrds/TMKs 
	CALL	$IOALT			;   spaced and endup request.
	JMP	MFINI			; Service any pending requests.
; Handle Spacing Count.
10$:	CLR	R1			; R1 - Space Dir; EQ-FWD, NEQ-REV.
	TST	SPCNT(R3)		; Space Forward ?
	BPL	20$			; IF PL, Yes.
	NEG	SPCNT(R3)		; Count adjustment and
	INC	R1			;  REV indication.

; Space F      iles/Block's ?
20$:	CMP	#IO.SPF,-4(R0)		; Space via TMK's ?
	BEQ	40$			; IF EQ, Yes.

; Determine Space Blocks Command.
	MOV	#SPFREC,SPCNG(R3)	; > Space FWD blocks.
	TST	R1			; Space records FWD ?
	BEQ	30$			; IF EQ, Yes.
	MOV	#SPRREC,SPCNG(R3)	; > Space REV blocks.

; Setup NDT Command.
30$:	CLR	SPACED(R3)		; No Blks/TMK's yet spaced.
	MOVB	@SPCNG(R3),U.BUF(R5)	; Set up NDT Function Code.
SPCAGN:	MOV	#255.,R1		; R1 - Spacing command count.
	CMP	SPCNT(R3),R1		; Space GT 255 Blcks/TMKs ?
	BHI	      35$			; IF HI, Yes.
	MOV	SPCNT(R3),R1		; Space LT 255 Blcks/TMKs.
35$:	SUB	R1,SPCNT(R3)		; SPCNT - to yet space.
	MOVB	R1,U.BUF+1(R5)		; Set up NDT command (spacing) count.
	MOV	R1,SPCIO(R3)		; Current I/O space count.
	MOV	SPCNG(R3),R0		; R0 > Spacing Subfunction Table.
	BR	SPSTRT			; Now issue I/O.

; Determine Space Files Command.
40$:	MOV	#SPRTMK,SPCNG(R3)	; > Space REV TMK.
	TST	R1			; REV TMK ?
	BNE	30$			; IF NE, Yes.
	MOV	#SPFTMK,SPCNG(R3)	; > Space FWD TMK.
	BITB	#US.LAB,U.STS(R5)	; La      belled tape ?
	BNE	30$			; IF NE, Yes.
	MOV	#SPLTMK,SPCNG(R3)	; > Space FWD TMK/LEOT.
	BR	30$			; . . cont .
	
	.DSABL LSB
	.PAGE
	.SBTTL	CANCEL I/O OPERATION
;+
; -- MFCAN -- 
;
;  Driver called as result of QIO IO.KIL request or EXEC Task rundown.
;  Called because UC.KIL set in U.CTL or US.BSY set in U.STS.
;
;  Inprogress I/O then ends by one of two ways.
;   1. Normal end - ISR, release packet. RD/WRT - Normal completion.
;    If error recovery required and marked for abort, RD/WRT ende      d.
;   2. Abnormal end - Terminate other I/O requests via TMO routine.
;
; Register configuration upon entry to MFCAN:
;	R0 - > Current I/O Packet.	R3 - RH Controller Index.
;	R1 - > Current Task TCB.	R4 - > SCB.
;					R5 - > UCB.
;-

MFCAN:	CMP	I.TCB(R0),R1	;; I/O owned by requesting task?
	BNE	10$		;; IF NE, No.
	BISB	#US.ABO,U.STS(R5) ;; Indicate I/O abort request (no recovery).
10$:	RETURN


	.SBTTL	POWERFAIL ENTRY POINT
;+
; -- MFPWF --
;
;  Driver called after:
;	1. System power fa      ilure and subsequent recovery.
;	2. System Bootstrapped.
;	3. Driver loaded.
;
; The driver performs the following:
;   1. Sets US.PWF that powerfailure occured. Normal QIO functions are 
;	disallowed with the exception of IO.RWD, IO.RWU, IO.SEC, IO.STC,
;	and IO.SMO. Successful IO.RWD, IO.RWU and IO.SMO reset the 
;	powerfailed indication and allow normal operations to resume.
;
; Register configuration upon entry to MFPWF:
;	R3 - RH Controller index
;	R4 - > SCB
;	R5 - > UCB
;-

MFPWF:	.IF       DF	P$$RFL
	BISB	#US.PWF,U.STS(R5)	; Set Powerfailed Indication.
	.ENDC	;P$$RFL

	MOV	S.CSR(R4),R2		; R2 > Device REGS.
	CLR	U.CW2(R5)		; Reset Tape Characteristics word.
	BIS	#C2.CLR,MFCS2(R2)	; Reset RH/TM78's.
	MOV	#C1.IE!C1.DVA,MFCS1(R2) ; Allow Interrupts on this RH.
	MOV	U.DCB(R5),DCBPTR	; DCB > - Driver restart fallback.
	MOV	R5,CNTBL(R3)		; UCB > - Unsolicited Intrpt Hndlng.
	RETURN			
	.PAGE
	.SBTTL	TIMEOUT ENTRY POINT
;+
; -- MFOUT --
;
; Called by Exec due to S.CTM timeout per the       following situations:
;
;  1. I/O in progress - may be I/O requested or spawned I/O.
;   a. US.ABO pending - End request, abort I/O.
;   b. Timeout - End request. Operation should have completed.
;  2. DQDIO - I/O busy. Could not issue I/O request.
;   a. TU78 in previous Rewind mode. 
;   b. TM78 Clear issued.
;   c. TM78 put Offline.
;
; Register configuration upon entry to MFOUT:
;	R0 = IE.DNR, Device Not Ready.	R3 - RH Cntrlr Index, S.CON.
;	R2 - CSR, S.CSR.		R4 - > SCB.
;					R5 - > UCB.      
;-

MFOUT:	DECB	S.STS(R4)	;; Completed Timeout Subcycle.
	BITB	#US.ABO,U.STS(R5) ;; Abort I/O request ?
	BEQ	10$		;; IF EQ, No.
	BICB	#US.ABO,U.STS(R4) ;; Aborting request -
	MOV	#IE.ABO&377,R0	;; Request end status.
5$:	BIC	#C1.IE,@S.CSR(R4) ;; Disable TM Interrupt.
	MTPS	#0		;; Allow interrupts.
	SUBR	ENDRQS		 ; End I/O request.
	CALL	CLRTM		 ; Abort physical I/O.
	RETURN

10$:	TST	INPROG(R3)	;; I/O In Progress ?
	BEQ	20$		;; IF EQ, No.
	TSTB	S.STS(R4)	;; Timeout Subcycles left ?
	BNE	15$      		;; IF NE, Yes. Restart Timer.

12$:	.IF DF	D$$IAG		;; If Diagnostics.

	CALL	MFDGNT		;; Pass TM78 REG's if diagnostics.
	.ENDC

	MOV	#IE.TMO&377,R0	;; Timeout occured.

	.IF DF	E$$DVC		;; If Error Logging Device.

	CALL	$DTOER		;; Log Device Timeout.
	.ENDC

	BR	5$		;; End request.


; Restart TIMER.

15$:	MOVB	S.ITM(R4),S.CTM(R4) ;; Restart timer.
	RETURN			;; Until next Timeout.


; DQD Request. Could not previously issue I/O request. 

20$:	TSTB	S.STS(R4)	;; Timeout Subcycles l      eft ?
	BNE	15$		;; IF NE, Yes. Restart Timer.

; DQD Request. Timeout.

	BIT	#M.RWD,U.CW2(R5) ;; Tape Drive Rewinding ?
	BNE	12$		;; IF NE, Yes. End request.
	MOV	U.SUB(R5),MFCS2(R2) ;; Select TM UNIT.
	TST	MFCR(R2)	;; TM78 Ready for Command ?
	BPL	12$		;; IF PL, No. End request.
	MTPS	#0		 ; Allow interrupts.
	MOV	IOFCT(R3),R0	 ; > IOFCT table,
	TST	(R0)+		 ;  Preprocess.
	JMP	@RTRNAD(R3)	 ; Service DQD request.
	.PAGE
	.SBTTL	INTERRUPT SERVICING
;+
; $MFINT - TM78/TU78 Mag Tape Interrupt       Service Routine
;-
	INTSE$	MF,PR5,T$$M78	;;; Map ISR, Set Processor Priority.
;
; R5 > UCB. R4= RH Controller Index.
;
	MOV	U.SCB(R5),R4	;;; R4 > SCB
	BIC	#C1.IE,@S.CSR(R4) ;;; Make sure no unsolicited INTRPTS.
	MOVB	S.CON(R4),R4	;;; Restore RH Controller Index.
	CALL	$FORK		;;; MFINT - Another Intrptbl System Process.
				; Current timeout count, S.CTM, cleared.
;+
; The TM78 generates both solicited and unsolicited interrupts:
;   Unsolicited interrupts can not be disabled. Unsolicited interr      upts
;     indicate tape units coming on line and hardware failure.
;   Solicited interrupts occur as a result of Data/Non Data Transfer Requests.
;
; Starting a data transfer request defers non data transfer interrupts 
;   pending data transfer completion. 
;
; Potential hazard: A data transfer is initiated. Driver resets and 
;  maintains C1.IE (MFCS1) reset at time Data Transfer Interrupt occurs.
;  The data transfer interrupt will be lost.
;
; Interrupt servicing is prioritized to handle Dat      a Transfer interrupts 
;  first - followed by servicing all Non Data Transfer Atentions present.
;-

	MOV	R4,R3		; R3 - RH Controller Index.
	MOV	U.SCB(R5),R4	; R4 - > SCB.  R5 - > UCB.
	MOV	S.CSR(R4),R2	; R2=CSR.
	TST	DTCMD(R3)	; Data Transfer started that RH ?
	BEQ	10$		; IF EQ, No.
	BIT	#C1.TRE,MFCS1(R2) ; RH transfer error indicated?
	BEQ	5$		; IF EQ, No.
;+
;  **** INCOMPLETE ****
; DTCMD - TRANSFER ERRROR.  Determine whether RECOVERABLE - Recovery procedure.
;-
5$:	SUBR	DTINT		; Service       Data Transfer Interrupt.
10$:	TST	MFAS(R2)	; Attention Interrupts ?
	BEQ	20$		; IF EQ, No.
	SUBR	NDINT		; Service Non Data Transfer Interrupts.
20$:	TST	INPROG(R3)	; I/O still active on this RH (Rtry Oprt) ?
	BNE	30$		; IF NE, Yes.
	TST	DQDIO(R3)	; Request yet pending ?
	BNE	30$		; IF NE, Yes.
	BIT	#M.RWD,U.CW2(R5) ; Rewind incomplete ?
	BNE	30$		; IF NE, Yes.
	JMP	MFINI		; Dequeue another I/O request.
30$:	MOV	#C1.IE!C1.DVA,MFCS1(R2) ; Allow further interrupts on this RH.
	RETURN			; Till next       interruption.
	.PAGE
	.SBTTL	NDT INTERRUPT SERVICING
;+
; Non Data Transfer Interrupt Servicing.
;
;  Service active ATTNS - both solicited and unsolicited.
;
;  The ATTN bit position identifies the TM Unit, Register MFNDI identifies 
; NDT Interrupt Code/Tape Unit (Attn Adr).
;
;  If unsolicited: appropriate measures are taken and ATTN is reset.
;
;  If solicited: verify interrupt an expected value.
; Unexpected values end the request and driver dependencies.
; If expected, call I/O ending       routine.
;  
;  Control is returned to the ATTN scan routine to service active ATTN's.
;-

	.BLKW			; Reserve space - Return address.
NDINT:	SUBR	FNDUNT		; Obtain a TM Unit, ATTN pending.
	BCC	10$		; IF CC, Found a TM Unit.
	RTRN	NDINT		; No further ATTN's.
10$:	SUBR	UNSLCT		; Unsolicited Interrupt ?
	BCS	NDINT		; IF CS, Yes. Any more ?
	SUBR	VALNDI		; Reasonable Interrupt ?
	BCC	20$		; IF CC, Yes.
	SUBR	LOGERR		; Log Error.
	MOV	#IE.FHE&377,R0	; Indicate Unrecoverable Situation
	SUBR	ENDRQS	      	;  and End Request.
	RTRN	NDINT		; Service pending NDT Interrupts.

20$:	CALL	RTRNCD		; Set up I/O Return Code - R0.
	BIC	#^C<377>,R1	; R1 - MFAS Reset Mask.
	MOV	IOFCT(R3),R4	; R4 > I/O function.
	BIT	#M.RWD,U.CW2(R5) ; Perhaps previous RWD operation ?
	BEQ	30$		; IF EQ, No.
	MOV	#IORWD,R4	; R4 > RWD function.
30$:	ADD	#ISRSRV,R4	; R4 > I/O Interrupt servicing. 
	TST	(R4)		; Spacing operation ?
	BEQ	35$		; IF EQ, Yes.
	MOV	(R4),R4		; > and Service 
33$:	MOV	#.+10,-2(R4)	;  NDT I/O 
	JMP	(R4)      		;   Endup.
	BR	NDINT		; Service other ATTN's.

35$:	MOV	#SPCISR,R4	; R4 > Space ISR endup.
	BR	33$		; . . Cont.
	.PAGE	
	.SBTTL	NDT INTRPT ROUTINES
;+
; -- FNDUNT --
;
; Find and service an ATTN request.
;
; The subroutine scans MFAS R -> L, to obtain a TM Unit #.
;  IF NO TM Unit found, CS.
;  IF TM Unit found, CC, NDT Interrupt code, TM UNIT#, MFAS Reset Mask.
;
; INPUTS - 
;
;  R2 - CSR,	 R3 - RH CNTRL INDX.
;
; OUTPUTS - 
;
;  ATTN Not Found - CS.
;
;  ATTN Found - CC,
;   R0       - [MFNDI]  R1 - TM UNIT#, MFAS Reset Mask.
;   R2 - CSR,	  R3 - RH CNTRL INDX.
;   R4 - > SCB,	  R5 - > UCB.
;-

	.BLKW			; Reserve space - Return Address.
FNDUNT:	MOV	#1,R1		; R1- HI Byte,TM UNIT#. LO Byte,MFAS Rst Mask.
	MOV	MFAS(R2),-(SP)	; (SP) - ATTN's,
	MOVB	#8.,1(SP)	; 1(SP) - # of ATTN's to be checked.
10$:	ASRB	(SP)		; This ATTN ?
	BCS	20$		; IF CS, Yes.
	ASLB	R1		; Update MFAS Rst Mask,
	SWAB	R1		;  and
	INCB	R1		;   next 
	SWAB	R1		;    UNIT.
	DECB	1(SP)		; One less ATTN to check.      
	BNE	10$		; IF NE, Check for other ATTN's active.
	SEC			; No TM UNIT found.
	BR	30$

20$:	SWAB	R1		; Select
	MOVB	R1,MFCS2(R2)	;    TM UNIT.
	SWAB	R1		; R1- TM UNIT#, MFAS Rst Mask.
	MOV	R1,RSTATN(R3)	; NDT Command -
	CLRB	RSTATN+1(R3)	;  ATTN Reset Mask.
	MOV	MFNDI(R2),R0	; R0- [MFNDI].
	CLC			; TM UNIT found.
30$:	INC	(SP)+		; Return Stack as found.
	RTRN	FNDUNT
	.PAGE	
;+
; -- UNSLCT --
;
; Validate NDT INTRPT for unsolicited input.
;
; ATTN's may come from TM UNITS I/O active (solic      ited)/inactive (unsolicited).
;
;  Unsolicited ATTN's result from tape units coming ONLINE/equipment failure.
;   ONLINE interrupts are dismissed. IF Driver has a request DQD, such I/O
;    request is reissued.
;   Equipment Failures require TM Clear's before any further I/O may proceed.
; 
; INPUTS - 
;
;  R0 - [MFNDI]		R1 - TM UNIT#, MFAS Rst Mask
;  R2 - CSR		R3 - RH CNTL INDX
;
; OUTPUTS - CS, Unsolicited.  CC, Solicited.
;
;  R0 - HI BYTE: Tape Unit #, LO BYTE: NDT INTRPT Code.
;  R1 - H      I BYTE: TM UNIT #,   LO BYTE: MFAS Rst Mask.
;  R2 - CSR
;  R3 - RH CNTL INDX
;-

	.BLKW			; Reserve space - Return Address.
UNSLCT:	BIC	#^C<1477>,R0	; R0- HI Byte, Tape Unit#. LO Byte, INTRPT code
	CMPB	#17,R0		; Tape Unit put Online ?
				;  MFDS Valid if Online - until reset MFAS.
	BNE	5$		; IF NE, No.
	MOVB	R1,MFAS(R2)	; Reset ATTN.
	TST	DQDIO(R3)	; Driver has a DQD pending request?
	BEQ	20$		; IF EQ, No.
	JMP	@RTRNAD(R3)	; Reissue pending request.
			
5$:	CMPB	#32,R0		; TM Fault B (TM De      tected Failure) ?
	BEQ	10$		; IF EQ, Yes.
	CMPB	#34,R0		; MB Fault (MASSBUS Control Bus Fault) ?
	BEQ	10$		; IF EQ, Yes.
	CLC			; Solicited interrupt.
	BR	22$

10$:	CLR	R4		; Indicate unsolicited interrupt and
	SUBR	LOGERR		;  Log Device Error - Device Regs, XND SNS Data
	CALL	CLRTM		; Clear TM78 - Resets ATTN's. 
20$:	SEC			; Unsolicited interrupt.
22$:	RTRN	UNSLCT
	.PAGE	
;+
; -- VALNDI --
; 
; Validate Non Data Interrupts. Obtain UCB/SCB for ATTN.
;
; 1. If not in configuration, not INP      ROG or Tape Unit not 
;  previously set into Rewind - will take no action. 
;  Reset the ATTN and continue scanning for additional ATTN's.
;
; This happens when OS systems moved about without correcting the system data 
; bases or by adding on equipment that data bases have not been generated for.
;
; 2. Validate NDT Interrupt for I/O INPROG or Tape Unit in previous RWD.
;
; INPUTS -
;  R0 - Tape Unit#,Intrpt Code	R2 - CSR
;  R1 - TM UNIT#,MFAS Rst Mask	R3 - RH CNTL INDX
;
; OUTPUTS - CS, INVAL      ID. CC, Valid.  Registers preserved.
;-
	.BLKW			; Reserve space - Return Address.
VALNDI:	MOV	DCBPTR,R5	; R5 > DCB.
	PUSH	<R1,R0>		; TM UNIT#, MFAS Rst Mask, Tape Unit#, INT Code
	MOV	D.UCBL(R5),-(SP) ; UCB lenght,
	MOV	D.UNIT(R5),-(SP) ; HI/LO UCB unit #s on Stack.
	MOV	D.UCB(R5),R5	; R5 > 1st UCB.
5$:	CMP	R5,U.RED(R5)	; UCB Redirected ?
	BNE	20$		; IF NE, Yes.
	TST	INPROG(R3)	; I/O Active ?
	BEQ	10$		; IF EQ, No.
	CMP	R5,CNTBL(R3)	; UCB same as for I/O INPROG ?
	BEQ	40$		; IF EQ, Yes.
10$:	      BIT	#M.RWD,U.CW2(R5) ; Tape Unit prev set RWD ?
	BEQ	20$		; IF EQ, No.
	CMPB	U.UNIT(R5),5(SP) ; Same Tape Unit ?
	BNE	20$		; IF NE, No.
	CMPB	U.SUB(R5),7(SP) ; Same TM UNIT ?
	BNE	20$		; IF NE, No.	
	MOV	U.SCB(R5),R4	; R4 > SCB.
	CMPB	S.CON(R4),R3	; Same RH ?
	BEQ	42$		; IF EQ, Yes.
20$:	CMPB	(SP),1(SP)	; Last UCB ?
	BEQ	30$		; IF EQ, Yes.
	ADD	2(SP),R5	; R5 > next UCB.
	INCB	(SP)		; LO # - Current UCB #.
	BR	5$		; Keep Checking rest of MF UCB's.

30$:	ADD	#10,SP		; Adjust Stack ->. UCB not f      ound.
	MOVB	R1,MFAS(R2)	; Reset ATTN,
	SEC			; Unreasonable Interrupt.
	RTRN	VALNDI

40$:	MOV	U.SCB(R5),R4	; R4 > SCB.
42$:	ADD	#10,SP		; Maintain stack integrity.
	CALL	VALIDT		; Validate NDT Interrupt.
	RTRN	VALNDI
	.PAGE	
;+
; -- VALIDT --	
;
; Validate INTRPT Code for INPROG or prev RWD request. 
;
; Verify INTRPT Code in range and per valid interrupt mask.
; Valid: CC. Invalid, CS. 
;
; INPUTS - 
;  R0 - Tape Unit#,Intrpt Code	R3 - RH CNTL INDX
;  R1 - TM UNIT#,MFAS Rst Mask	R4 - >       SCB.
;  R2 - CSR			R5 - > UCB.
;
; OUTPUT - CS, Invalid. CC, Valid.  Registers preserved.
;-

VALIDT:	PUSH	<R2,R1,R0>	; Reference values.
	MOV	IOFCT(R3),R1	; R1 > I/O active table entry.
	CMP	R5,CNTBL(R3)	; INPROG Validation ?
	BEQ	10$		; IF EQ, Yes.
	MOV	#IORWD,R1	; R1 > RWD table entry.
10$:	ADD	#VALI1,R1	; R1 > 1st validation mask.	
	TST	(R1)		; Spacing operation ?
	BNE	12$		; IF NE, No.
	MOV	SPCNG(R3),R1	; R1 > 1st validation mask 
	ADD	#SVALI1,R1	;  in Spacing Subfunction table.
12$:	MO      VB	(SP),R0		; R0 - Interrupt Code.
	CMPB	R0,#35		; Interrupt code out of range ?
	BGE	30$		; IF GE, Yes.
	CLR	INTCD1(R3)	; Initialize 0-17 and 20-34 
	CLR	INTCD2(R3)	;  interrupt bit descriptors.
	MOV	#INTCD1,R2	; R2 > Interrupt 0-17 bit descriptor.
	CMP	R0,#17		; Interrupt 0-17 range?
	BLOS	20$		; IF BLOS, Yes.
	MOV	#INTCD2,R2	; R2 > Interrupt 20-34 bit descriptor.
	BIC	#20,R0		; Interrupt code in binary/bit range.
	TST	(R1)+		; R1 > 2nd validation mask.
20$:	ADD	R3,R2		; R2 now > correct Interr      upt bit descriptor.
	ASL	R0		; Convert Interrupt Code
	ADD	#$BTMSK,R0	;  TO
	MOV	(R0),R0		; Bit Mask Value.
	MOV	R0,(R2)		; Current Interrupt code - per Bit descrition.
	BIT	R0,(R1)		; Valid Interrupt ?
	BEQ	30$		; IF EQ, No.
	CLC			; Indicate Interrupt Code Valid.
25$:	POP	<R0,R1,R2>	; Maintain stack integrity.
	RETURN	

30$:	SEC			; Indicate interrupt code Invalid.
	BR	25$
	.PAGE
	.SBTTL	NDT INTRPT SERVICING
;+
; Non Data Interrupt Servicing.
;-

;+
; Sense Tape Charecteristics - Compl      etion.
;  Result of servicing IO.SMO, IO.STC and IO.SEC requests.
;
; INPUTS -
;  R0 - LO BYTE; I/O Request Return Code  HI BYTE; 0's.
;  R1 - MFAS Reg Reset Mask.
;  R2 - CSR.   R3 - RH CNTL INDX.   R5 - > UCB.
;
; OUTPUTS -
;  R2 - CSR, R3 - RH CNTL INDX, R4 - > SCB, R5 - > UCB.
;-

	.BLKW			; Reserve space - Return Address.
SNSISR:	CMPB	#IS.SUC,R0	; Successful ?
	BEQ	5$		; IF EQ, Yes.
	SUBR	LOGERR		; Log Error.
3$:	MOV	#IE.FHE&377,R0	; Hardware problems. 
	BIS	#M.SER,U.CW2(R5) ; Select p      roblems.
	BR	25$
5$:	PUSH	MFDS(R2)	; Local copy - Tape Drive Status.
	BIT	#DS.BOT,(SP)	; BOT ?
	BEQ	10$		; IF EQ, No.
	BIS	#M.BOT,U.CW2(R5)  ; Status- BOT.
10$:	BIT	#DS.EOT,(SP)	; EOT ?
	BEQ	12$		; IF EQ, No.
	BIS	#M.EOT,U.CW2(R5)  ; Status- EOT.
12$:	BIT	#DS.FPT,(SP)	; Write Locked ?
	BEQ	14$		; IF EQ, No.
	BIS	#M.HWL,U.CW2(R5)  ; Status- Write locked.
14$:	BIT	#DS.RDY,(SP)	; Ready ?
	BEQ	15$		; IF EQ, No.
	BIT	#DS.AVL,(SP)	; Available to this MASSBUS ?
	BNE	20$		; IF NE, Yes.
15$:	BIS	#M.S      ER,U.CW2(R5) ; Status- Select Error (Not available for use)
20$:	POP			; Maintain Stack.
	CMP	#IO.SEC,@IOFCT(R3) ; IO.SEC request ?
	BNE	30$		; IF NE, No.
25$:	MOV	U.CW2(R5),R1	; Second I/O Status Word - Tape Characteristics
	SUBR	ENDRQS		; End Request.
	RTRN	SNSISR		; Return to NDT Interrupt Servicing.

; IO.SMO.or.IO.STC - Tape Characteristics M.IWR, M.SWL, M.1600 bits involved.
30$:	BIC	#M.SWL!M.IWR,U.CW2(R5) ; Perhaps - No Soft Write Lock, IWR. 
	BIT	#M.SWL,SPCNT(R3) ; User - Software Write Lo      ck ?
	BEQ	32$		; IF EQ, No.
	BIS	#M.SWL,U.CW2(R5) ; Software - No write to tape.
32$:	BIT	#M.IWR,SPCNT(R3) ; User - Inhibit writing with extended gap ?
	BEQ	34$		; IF EQ, No.
	BIS	#M.IWR,U.CW2(R5) ; User- No write extended gap(Error Recovery).
34$:	BIT	#M.1600,SPCNT(R3) ; User - 6250BPI Mode ?
	BEQ	40$		; IF EQ, 6250BPI Mode.
; User desires 1600BPI mode.
	BIT	#M.1600,U.CW2(R5) ; TM78 in 1600BPI Mode ?
	BNE	25$		; IF NE, Yes. No change needed. End Request.
	BIT	#M.BOT,U.CW2(R5) ; TU78 at BOT ?
	B      EQ	3$		; IF EQ, No. Can't change DENSITY CONTROL.
	BIS	#M.1600,U.CW2(R5) ; TM78 Commands via 1600 BPI mode.
	BR	45$		; End Request.
; User desires 6250BPI mode.
40$:	BIT	#M.1600,U.CW2(R5) ; TM78 in 6250BPI Mode ?
	BEQ	25$		; IF EQ, Yes. No change needed. End Request.
	BIT	#M.BOT,U.CW2(R5) ; TU78 at BOT ?
	BEQ	3$		; IF EQ, No. Can't change DENSITY CONTROL.
	BIC	#M.1600,U.CW2(R5) ; TM78 Commands via 6250 BPI mode.
45$:	BICB	#US.PWF,U.STS(R5) ; Reset Power Failed Indication.
	BR	25$		; End Request.
      
;+
; Completed Space Tape Operation:
;   FWD/REV via TMKS,  FWD to LEOT,  FWD/REV via Blocks (Records).
;
; INPUTS -
;  R0 - LO BYTE; I/O Request Return Code  HI BYTE; 0's.
;  R1 - MFAS Reg Reset Mask.
;  R2 - CSR.   R3 - RH CNTL INDX.   R5 - > UCB.
;
; OUTPUTS -
;  R2 - CSR, R3 - RH CNTL INDX, R4 - > SCB, R5 - > UCB.
;-

	.BLKW			; Reserve space - Return Address.
SPCISR:	BIT	#DON!TMK!BOT!LEOT!NAVL!NTEX!NTCP,INTCD1(R3) ; End request?
	BNE	20$		; IF NE, Yes.
	BIT	#NRDY!OFLN,INTCD1(R3) ; Not       ready for command or Unit Offline ?
	BNE	40$		; IF NE, Yes.
	SUBR	LOGERR		; Log Error.
10$:	MOV	SPACED(R3),R1	; Indicate TMK's/Blocks Spaced.
	SUBR	ENDRQS		; End Request.
18$:	RTRN	SPCISR		; return to NDT Interrupt Servicing.

; IS.SUC (Normal End). IF Interrupt code is DON, THEN may need to Restart I/O. 
20$:	PUSH	R0		; Save R0 - Temp use.
	MOVB	MFNDI+1(R2),R0	; R0= 
	BIC	#^C<3>,R0	;   Tape Unit #.
	ASL	R0		; Make word index -
	ADD	R2,R0		;  To access Residual 
	MOVB	MFND0+1(R0),R0	;    TMK/B      lock Count.
	BIC	#^C<377>,R0	; R0= Residual TMK/Block Count.
	BEQ	30$		; IF EQ, Current requested count exhausted.
	SUB	R0,SPCIO(R3)	; SPCIO - TMK's/Block's spaced.
30$:	ADD	SPCIO(R3),SPACED(R3) ; Maintain TMK's/Block's spaced.
	POP	R0		; Maintain Reg.
	BIT	#DON,INTCD1(R3) ; Interrupt code DON ?
	BEQ	10$		; IF EQ, No. End Request.
	TST	SPCNT(R3)	; Further TMK's/Blocks to Space ?
	BEQ	10$		; IF EQ, No.
	MOV	U.SCB(R5),R4	; R4 > SCB.
	JMP	SPCAGN		; Restart I/O to complete request.	

; Can't commun      icate with unit - Offline or Not Ready to Execute Command.
40$:	TST	U.ACP(R5)	; MTAACP ?
	BNE	10$		; IF NE, Yes. End request.
	CALL	MSG		; Console message - Unit condition.
	BR	18$		; Return to NDT Interrupt Servicing.


;+
; Completed:  Write Tape Mark;  Erase 3" Gap;  Data Security Erase;
;	      Rewind Tape;  Rewind/unload Tape.
;
; INPUTS -
;  R0 - LO BYTE; I/O Request Return Code  HI BYTE; 0's.
;  R1 - MFAS Reg Reset Mask.
;  R2 - CSR.   R3 - RH CNTL INDX.   R5 - > UCB.
;
; OUTPUTS -
;        R2 - CSR, R3 - RH CNTL INDX, R4 - > SCB, R5 - > UCB.
;-

RWDRET:	.BLKW			; Reserve space - Return Address.
RWDISR:	TST	INPROG(R3)	; Interrupt to initial Rewind ?
	BNE	30$		; IF NE, Yes.
	BIC	#M.RWD,U.CW2(R5) ; Rewind over.
	CMPB	#IS.SUC,R0	; Any complications.
	BEQ	10$		; IF EQ, No.
	CLR	R4		; TMFA/TUFA error - Request previously ended.
	SUBR	LOGERR		; Log it.
10$:	MOVB	R1,MFAS(R2)	; Reset ATTN.
	TST	DQDIO(R3)	; Driver need complete previously DQD request?
	BEQ	20$		; IF EQ, No.
	JMP	@RTRNAD      (R3)	; Execute DQD/pending request.
20$:	RTRN	RWDISR		; Return to NDT Interrupt Servicing.

30$:	BIT	#RWD,INTCD1(R3) ; Rewind initiated?
	BNE	40$		; IF NE, Yes.
	BIC	#M.RWD,U.CW2(R5) ; Rewind I/O completed.
40$:	MOV	RWDRET,WTMRET	; Maintain linkage.
	BR	WTMISR		; End Request.


WTMRET:	.BLKW			; Reserve space - Return Address.
WTMISR:
ERGISR:
DSEISR:
UNLISR:	BIT	#DON!RWD,INTCD1(R3) ; Clear Power Failed Indication ?
	BEQ	5$		; IF EQ, No.
	BICB	#US.PWF,U.STS(R5) ; Reset Power Failed Indication      .
5$:	BIT	#DON!EOT!FPT!NAVL!NTEX,INTCD1(R3) ; End Request ?
	BNE	10$		; IF NE, Yes.
	BIT	#NRDY!OFLN,INTCD1(R3) ; Not ready for command, Unit Offline ?
	BNE	30$		; IF NE, Yes.
	SUBR	LOGERR		; Log Error.
10$:	SUBR	ENDRQS		; End Request.
20$:	RTRN	WTMISR		; Return to NDT Interrupt Servicing.	

; Can't communicate with unit - Offline or Not Ready to Execute Command.
30$:	TST	U.ACP(R5)	; MTAACP ?
	BNE	10$		; IF NE, Yes. End request.
	CALL	MSG		; Console message - Unit condition.
	BR	20$		; . . Conti      nue.


;+
; Send 'Device Not Ready' Message if TU78 Offline
;  and 'Select Error' Message if TM78 Not Ready for Command.
;-

MSG:	PUSH	<R2,R1,R0>	; Save REG's.
	MOV	#T.NDNR,R0	; 'Device Not Ready' message.
	CMPB	#IE.OFL,(SP)	; Tape Unit Offline?
	BEQ	10$		; IF EQ, Yes.
	MOV	#T.NDSE,R0	; 'Select Error' message.
10$:	CALL	$DVMSG		; Output message.
	POP 	<R0,R1,R2>	; Restore REG's.
	CLR	INPROG(R3)	; No I/O active,
	INC	DQDIO(R3)	;  I/O Request to be completed.
	MOVB	R1,MFAS(R2)	; Reset ATTN.
      	MOV	U.SCB(R5),R4	; R4 > SCB.
	MOVB	#1,S.STS(R4)	; Start 15 sec timeout.
	MOVB	#15.,S.CTM(R4)	;   Try again in 15 sec. 
	RETURN

	.PAGE
	.SBTTL	DT INTERRUPT SERVICING
;+
; Data Transfer Interrupt Servicing.
;
;  Service Read/Write/Extended Sense Requests.
; 
; INPUTS -
;
;  R2 - CSR	R3 - RH CNTRL INDX
;  R4 - > SCB	R5 - > UCB
;
;  XNSCMD - NEQ=XND SNS Operation.
;-
	.BLKW			; Reserve space - Return Address.
DTINT:	TST	XNSCMD(R3)	; Extended Sense Request ?
	BEQ	5$		; IF EQ, No.
	.IF DF	      E$$DVC
	JMP	XNSISR		; Endup Extended Sense Request.
	.ENDC	;E$$DVC
5$:	MOV	MFDI(R2),R0	; R0 - Dt Failure Cd, DPR, Dt Interrupt Cd.
	CALL	VALIDT		; Validate DT Interrupt.
	BCC	10$		; IF CC, Valid - Complete request.
	SUBR	LOGERR		; Log Error.
	MOV	#IE.FHE&377,R0	; Indicate Unrecoverable Situation
	SUBR	ENDRQS		;  and end request.
	RTRN	DTINT		; Service pending NDT Interrupts.

10$:	CALL	RTRNCD		; Set up I/O Return Code - R0.
	BIT	#DON!TMK!BOT!EOT!FPT!NRDY!NAVL!OFLN!NTEX!NTCP,INTCD1(R3)
				; Int      errupt Code 0-17 range ?
	BEQ	100$		; IF EQ, No. Code 20-34 Range.
	BIT	#DON!EOT,INTCD1(R3) ; Successful end ?
	BNE	12$		; IF NE, Yes.
	BIT	#NRDY!OFLN,INTCD1(R3) ; Not ready for command, Unit Offline?
	BNE	20$		; IF NE, Yes.
	BIT	#BOT,INTCD1(R3)	; Backed into BOT?
	BEQ	15$		; IF EQ, No.
	CLR	R1		; No Data Transfered.
	BR	15$		; . . Continue.	
12$:	MOV	U.CNT(R5),R1	; Second I/O Status Word - # Bytes Transferred.
15$:	SUBR	ENDRQS		; End Request.
19$:	RTRN	DTINT		; Service NDT ATTN's.

20$:	TST	U      .ACP(R5)	; MTAACP ?
	BNE	15$		; IF NE, Yes. End request.
	CALL	MSG		; Console message - Unit condition.
	BR	19$		; . . Continue.

100$:
WRTISR:
RDFISR:
RDRISR:	
	RTRN	DTINT
	.PAGE
	.SBTTL	LOG DEVICE ERRORS 
;+
; -- LOGERR --
;
;  INPUTS -
;   R2 - CSR	R3 - RH CNTRL INDX	R5 - > UCB
;   R4 = EQ; Unsolicited I/O error, R0 - Don't care.
;   R4 - >SCB; Solicited I/O error, R0 - I/O Status Code.
;
;  OUTPUTS -  REG's Preserved.  R1 Altered.
;-

	.BLKW			; Reserve space - Return Address.
LO      GERR:	
	.IF DF	E$$DVC		; IF Log Device Errors -

	MOV	#108.,R1	; R1 - # Error Log Data Bytes - Assume RH70.
				;  54. Reg's - 24. Dev Reg's, 30. Ext Sns Data.
	.IF DF	M$$EXT		; IF 22 Bit Extended Addressing (11/70,11/44) -
	BIT	#DV.MBC,U.CW1(R5) ; RH11 ?
	BNE	10$		; IF NE, No - RH70.
	SUB	#4,R1		; No MFBAE/MFCS3 Reg(s) to log.
10$:	.ENDC

	.IF DF	D$$IAG		; If Diagnostics -
	TSTB	INPROG+1(R3)	; Passed DEV REG's already ?
	BNE	15$		; IF NE, Yes.
	CALL	MFDGNT		; Pass TM78 REG's.
	BCC	15$		; IF       CC, Not UMD Request.
	INC	INPROG+1(R3)	; Passed DEV REG's.
	.ENDC

15$:	PUSH	<,R3,R2,R0>	; > Error Packet, Save R3,R2,R0 Reg(s). 
	CALL	$LOGER		; Request Error Packet.
	MOV	R3,-6(SP)	; Save > Error Packet.
	POP	<R0,R2,R3,ERRPKT(R3)> ; Restore R0,R2,R3 & > to Error Packet.
	BCS	RTNLGR		; IF CS, Can't log error.
	PUSH	<R2,R0>		; Save R2,R0. R1 > Error Packet Data Area.
	MOV	#TMREGS,R0	; R0 - # Dev Reg(s).
20$:	MOV	(R2)+,(R1)+	; Move a Device Register.
	DEC	R0		; One less Device Register to move.
      	BNE	20$		; IF NE, more device registers to move.
	POP	<R0,R2>		; Restore R0,R2.

	.IF DF	M$$EXT		; IF 22 bit Extended Addressing (11/70, 11/44)
	BIT	#DV.MBC,U.CW1(R5) ; RH11 ?
	BEQ	30$		; IF EQ, Yes.
	
	.IF DF	M$$IXD		; IF Mixed MASSBUS
	MOV	74(R2),(R1)+	; Move MFBAE Reg
	MOV	76(R2),(R1)+	; Move MFCS3 Reg
	.IFF
	MOV	MFBAE(R2),(R1)+	; Move MFBAE Reg
	MOV	MFCS3(R2),(R1)+ ; Move MFCS3 Reg
	.ENDC

30$:	.ENDC

	MOV	#60.,DTCNT(R3)	; Extended Sense - 60. bytes.
	CLR	DTADR1(R3)	; Error Packet in       Exec POOL area.
	MOV	R1,DTADR2(R3)	; R1 > Dt Area in Error packet- after DEV REG's
	INC	XNSCMD(R3)	; Almost ready to request Extended Sense data.
	TST	R4		; Logging error from Solicited I/O ?
	BNE	40$		; IF NE, Yes.
	MOVB	XNSCMD(R3),XNSCMD+1(R3) ; Remember - Log Error,Unsolicited I/O.
40$:	JMP	DTIOGO		; Request Extended Sense data.


XNSISR:	TSTB	XNSCMD+1(R3)	; Log error (Unsolicited I/O) ?
	BEQ	RTNLGR		; IF EQ, No. Return to caller.
	PUSH	<R3,R2>		; Save REG's.
	CLR	R2		; Retry count EQ.
	MOV	      ERRPKT(R3),R3	; R3 > Error Packet.
	CLR	R4		; R4 .EQ. (Unsolicited I/O).
	CALL	$FNERL		; End Error Logging.
	POP	<R2,R3>		; Restore REG's.
	MOV	RSTATN(R3),MFAS(R2) ; Reset TM ATTN.

	.ENDC	;E$$DVC

RTNLGR:	RTRN	LOGERR		; Return to Caller.

	.PAGE
	.SBTTL	ABORT TM78 OPERATION/DRIVER DATA BASE DEPENDENCIES

;+
; -- CLRTM --
;
; Called to regain TM78 control.
;
;  1. Reset TM78 via TM CLR.
;  2. Update driver data base - for all TU78's on that TM78.
;    a. U.CW2 - M.RWD bit.
;    b. S.CTM      /S.STS bytes.
;
; Caller need update/maintain other current driver dependencies.
; For RSX11M, for a given RH, the driver only supports single thread I/O.
;
; INPUTS -
;
;  R2 - CSR,  R3 - RH controller Index, S.CON.
;  R4 - > SCB,  R5 - > UCB.
;
; OUTPUTS -
;
;  Registers preserved.
;-

CLRTM:	MOVB	U.SUB(R5),MFCS2(R2)	; Select TM78 -
	BICB	#C1.IE,MFCS1(R2)	; RH Interrupt Disabled,
	BIS	#TMCLR,MFCR(R2)		; Reset/End TM I/O.
	PUSH	<R5,R0>			; Save 'em.
	MOV	U.SUB(R5),R0		; R0 - TM#.
	ASL	R      0			; Compatibility with S.CON.
	MOV	DCBPTR,R5		; R5 > DCB.
	MOV	D.UCBL(R5),-(SP)	; UCB lenght,
	MOV	D.UNIT(R5),-(SP)	; HI/LO UCB unit #s on Stack.
	MOV	D.UCB(R5),R5		; R5 > 1st UCB.
10$:	CMP	U.SUB(R5),R0		; Same TM Subcontroller ?
	BNE	20$			; IF NE, NO.
	CMPB	S.CON(R4),R0		; Same RH Controler ?
	BNE	20$			; IF NE, No.
	CMP	R5,U.RED(R5)		; UCB Redirected ?
	BNE	20$			; IF NE, Yes.
	BIC	#M.RWD,U.CW2(R5)	; Tape unit not Rewinding.
	CLRB	S.CTM(R4)		; No current timeout
	CLRB	S.STS(R4)		;  or time      out subcycles.
20$:	CMPB	(SP),1(SP)		; Last UCB ?
	BEQ	30$			; IF EQ, Yes.
	ADD	2(SP),R5		; R5 > next UCB.
	INCB	(SP)			; LO # - Current UCB #.
	BR	10$			; Handle other TU's on same RH/TM78.

30$:	ADD	#4,SP			; Maintain Stack integrity.
	POP	<R0,R5>			; Restore 'em.
	RETURN	
	.PAGE
	.SBTTL	SETUP I/O RETURN CODE
;+
; -- RTRNCD --
;
; INPUT -
;
;  R0 - LO BYTE: Interrupt Code, Octal value.
;  R3 - RH Cntl Index.
;
; OUTPUT -
; 
;  R0 - LO BYTE: I/O Request Return Code. 
;	HI BYTE: 0's.      
;
;  Other Reg(s) preserved.
;-

RTRNCD:	BIC	#^C<377>,R0	; R0 - Interrupt Code only.
	ADD	#RTRNTB,R0	; > I/O Request Return Code
	MOVB	(R0),R0		;  and provide it to
	BIC	#^C<377>,R0	;   Caller.
	MOV	R0,IOSTAT(R3)	; Save I/O Return Code.
	RETURN	
	.PAGE
	.SBTTL	END I/O REQUEST

;+
; -- ENDRQS--
;
; INPUT -
;
;  R0 - I/O Request Return Code.
;  R1 - 2nd I/O Status Word.
;  R2 - CSR.
;  R3 - RH CNTRL INDX.
;  R5 - > UCB.
;-

	.BLKW			; Reserve space - Return Address.
ENDRQS:	MOV	U.SC      B(R5),R4	; R4 > SCB.

; If Usermode Diagnostic - Pass Device Reg's.

	.IF DF	D$$IAG		; If Diagnostics -

	TSTB	INPROG+1(R3)	; Passed DEV REG's already ?
	BNE	5$		; IF NE, Yes.
	CALL	MFDGNT		; Pass TM78 REG's.
5$:	.ENDC


; If Logged an Error - Endup Error Logging.

	.IF DF	E$$DVC		; If Error Logging Device -
	
	BITB	#SP.EIP,S.PRI(R4) ; Logged an Error ?
	BEQ	10$		; IF EQ, No.
	MOV	RTTBL(R3),R2	; Setup Error Retry Counts,
	MOV	ERRPKT(R3),R3	;  > Error Log Packet and
	CALL	$FNERL		;   Endu      p Error Logging for this request.
10$:	.ENDC	


; End Request.
	CALL	$IODON		; End Request.
	MOV	U.SCB(R5),R4	; Restore R4, >SCB.
	MOVB	S.CON(R4),R3	;         R3, RH CNTL INDX.
	MOV	S.CSR(R4),R2	;         R2, CSR.
	
	TST	DTCMD(R3)	; Completed Data request ?
	BNE	20$		; IF NE, Yes.
	TST	DQDIO(R3)	; Dequeued/never issued request ?
	BNE	20$		; IF NE, Yes.
	TST	INPROG(R3)	; I/O issued ?
	BEQ	20$		; IF EQ, No.
	MOV	RSTATN(R3),MFAS(R3) ; Reset TM ATTN.
20$:	CLR	DTCMD(R3)	; Clear
	CLR	INPROG(R3)	      ;  Driver
	CLR	XNSCMD(R3)	;   Request
	CLR	DQDIO(R3)	;    Processing indicators.
	RTRN	ENDRQS
	.PAGE
	.SBTTL	USER MODE DIAGNOSTIC REQUEST - ENDING SEQUENCING
;+
; -- MFDGNT --
;
; Determine if User Mode Diagnostic Function Call.
;
;  If so - Then pass TM78 device registers.
;
; INPUTS -
;  R2 - CSR
;  R4 - > SCB.
;
; OUTPUTS -
;  Reg(s) preserved
;  CC - Not User Mode Diagnostic Function Call
;  CS - User Mode Diagnostic Function Call. TM78 device reg(s) passed.
;-

MFDGNT:	MOV	R1,-(S      P)	; Save R1. $CRPAS mungs it.
	MOV	S.PKT(R4),R1	; R1 > current I/O packet.
	BITB	#IQ.UMD,I.FCN(R1) ; User Mode Diagnostic Function Call?
	BEQ	20$		; IF EQ, No.
	MOVB	S.RCNT(R4),-(SP) ; Pass TM78 Device Reg(s)-
	MOVB	#TMREGS,S.RCNT(R4) ; XND SNS not included.
	MOV	R1,-(SP)	; Save > I/O packet.
	CMPB	#IO.EOF/256.,I.FCN+1(R1) ; QIO Control Code #6 ?
	BEQ	10$		; IF EQ, Yes.
	CMPB	#IO.RWD/256.,I.FCN+1(R1) ; QIO Control Code #5 ?
	BEQ	10$		; IF EQ, Yes.
	CALL	$CRPAS		; Pass device reg(s) - Other QIO's      .
	MOV	(SP)+,R1	; Maintain Stack.
	BR	15$
10$:	MOV	I.PRM+14(R1),I.PRM+16(R1) ; Setup I/O packet
	MOV	I.PRM+12(R1),I.PRM+14(R1) ;  for $CRPAS.
	CALL	$CRPAS		; Pass device reg(s).
	MOV	(SP)+,R1	; Maintain Stack. R1 > I/O packet.
	MOV	I.PRM+14(R1),I.PRM+12(R1) ; Re-setup I/O packet
	MOV	I.PRM+16(R1),I.PRM+14(R1) ;  after $CRPAS.
15$:	MOVB	(SP)+,S.RCNT(R4) ; Restore # REG(s) passed to ERR LOG.
	SEC			; User Mode Diagnostic Function Call.
18$:	MOV	(SP)+,R1	; Restore R1.
	RETURN	

20$:	CLC			; No Us   :   er Mode Diagnostic Function Call.
	BR	18$



	.END
 :                       