	.TITLE	GRDRV
	.IDENT	/02/

;
; COPYRIGHT   1976,  DIGITAL  EQUIPMENT  CORP.,  MAYNARD,   MASS.
;
; THIS SOFTWARE IS FURNISHED TO PURCHASER UNDER A LICENSE FOR USE
; ON A  SINGLE COMPUTER SYSTEM AND CAN BE  COPIED (WITH INCLUSION
; OF DEC'S COPYRIGHT  NOTICE) ONLY FOR USE IN SUCH SYSTEM, EXCEPT
; AS MAY OTHERWISE BE PROVIDED IN WRITING BY 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.
;
; VT11/VS60 DISPLAY PROCESSOR DRIVER
;
; VERSION 02
;
; NOTE:	THIS IS A SINGLE CONTROLLER DRIVER
;
; WRITTEN  BY HANK MAURER 13-JUL-75
;
; MODIFIED BY HANK MAURER 11-AUG-75
;	TO INCLUDE LIGHT PEN HIT AST'S
;	AND STOP AND CONTINUE FUNCTIONS
;
; MODIFIED BY HANK MAURER 11-SEP-75
;	TO DO DISPLAY STOPS WITHOUT DPC JAMMING
;	AND TO HANDLE BUSS-ERROR/SHIFT-OUT INTERRUPTS PROPERLY
;
; MODIFIED BY HANK MAURER 21-NOV-75
;	TO CONFORM WITH RSX11M IO CODE DEFINITIONS
;
; MODIFIED BY HANK MAURER 09-FEB-76
;	TO SUPPORT VS60 HARDWARE (CONDITIONALLY)
;
;
; SELECTED OPTIONS
;

	VS60=1			;ASSEMBLE VS60 VERSION

;
; EQUATED SYMBOLS
;

	IO.CON=33		;CONNECT TO DRIVER
	IO.DIS=34		;DISCONNECT FROM DRIVER
	IO.STP=35		;STOP VT11/VS60
	IO.CNT=36		;CONTINUE AFTER STOP
	BFHDR=52.		;DISPLAY BUFFER HEADER SIZE
	NAMSIZ=18.		;NAME LIST SIZE
	DPC=172000		;DPU PROGRAM COUNTER ADDRESS
	DSR=2			;PDPU STATUS REGISTER
	DRB=10			;DPU RELOCATION 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=173000		;DPU HALT WITHOUT INTERRUPTING
	DHINT=400		;DPU INTERRUPT ON HALT
	LSRA=170000		;DPU LOAD STATUS REGISTER A
	LPINT=200		;DPU INTENSIFY LP HITS
	NOITAL=40		;DPU NON-ITALICS
	LINE0=4			;DPU SOLID LINE TYPE
	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

;
; ASSEMBLY SWITCH DEFAULTS
;

	.IF NDF	VS60
	VS60=0			;DEFAULT IS FOR VT11
	.ENDC

	.IF NDF	SCOPES
	SCOPES=0		;DEFAULT IS FOR SINGLE SCOPE
	.ENDC

;
; LOCAL DATA  *** WARNING *** THE ORDER OF THE LOCAL DATA IS FIXED
;


	.IF NE	VS60

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 HIT)

	.ENDC

	.IFF

GRSTK:	.BLKW	8.		;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


	.IF DF	A$$TRP

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
LPFRK:	.BLKW	3		;LP INTERRUPT FORK BLOCK
TIP1:	.WORD	0		;TIP SWITCH 1 STATUS

	.IF NE	SCOPES

TIP2:	.WORD	0		;TIP SWITCH 2 STATUS
LPFLAG:	.WORD	0		;SCOPE 1 OR 2 FLAG ON LP HIT

	.ENDC

;
; DELAY IN CASE THE USER'S DISPLAY LIST IS VERY SHORT
;

DELAY:	.WORD	POINT+LPOFF+NBLINK+INT3+LINE0

	.IFT

	.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

	.ENDC

DSTART:	.WORD	DHALT,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
	MOV	#X,DSTART
	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 (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.
;-

GRCHK:	MOV	R1,-(SP)	;SAVE I/O PACKET ADDRESS
	MOVB	I.FCN+1(R1),R2	;GET IO 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		;YES
	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:	BIT	#TS.CHK!TS.FXD,T.STAT(R1) ;TASK FIXED OR NOT CHECKPOINTABLE?
	BEQ	GRPRI		;IF EQ NO
	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 NE	VS60

	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 PHYS TASK START ADDR
	ASL	R1
	ASL	R1
	ASL	R1
	ASL	R1
	ASL	R1
	MOV	R1,(R3)+	;SAVE IT

	.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
	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

	.IFTF

	MOV	(SP),R1		;RESTORE PACKET POINTER
	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

	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 ADDRESS

	.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	(SP)+,R5	;RESTORE UCB ADDRESS
;+
; **-GRCNT-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:

	.IF NE	VS60

	MOV	GR.PC,R0	;GET DPU PC ADDRESS
	MOV	#SRESET,DSP(R0)	;RESET DPU STACK

	.IF DF	M$$MGE

	MOV	#DHALT+DHINT,DSTART ;INTERRUPT AT END OF DELAY

	.IFF

	MOV	BUFST,DSTART+2	;GET USER'S BUFFER ADDRESS
	ADD	#BFHDR,DSTART+2	;ADD HEADER SIZE
	MOV	#DJMPA,DSTART	;MAKE DELAY LIST JUMP TO USER'S LIST

	.ENDC


	.IFF

	MOV	BUFST,DSTART+2	;GET THE START OF THE USER'S BUFFER
	ADD	#BFHDR,DSTART+2	;SKIP OVER LP STUFF
	MOV	#DJMPA,DSTART	;SWITCH FROM A HALT TO A DJMP
	MOV	#GRSTK,GR.SP	;RESET DPU STACK

	.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	GRERR		;

;
; PRIVILEGE VIOLATION
;

GRPRI:	MOV	#IE.PRI&377,R0	;SET PRIVILEGE VIOLATION STATUS
	BR	GRCMN		;BUT DON'T DISTURB THE DISPLAY

;
; ILLEGAL BUFFER SPECIFICATION
;

GRSPC:	MOV	#IE.SPC&377,R0	;SET ILLEGAL BUFFER STATUS

;
; COMMON ERROR EXIT
;

GRERR:	MOV	#DHALT,DSTART	;DISPLAY IDLE
	BR	GRBGN		;TAKE COMMON EXIT

;
; SUCCESSFUL COMPLETION
;

GRSUC:	MOV	#IS.SUC&377,R0	;SET SUCCESSFUL COMPLETION STATUS

;
; COMMON FUNCTION EXIT
;

GRBGN:	MOV	#DELAY,@GR.PC	;RESTART DPU
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
	MTPS	#0		;;;ALLOW DEVICE INTERRUPTS

;
; SUBROUTINE TO HALT DPU
;
; INPUTS:
;	R4=ADDRESS OF SCB
;	R5=ADDRESS OF UCB
;

GRHLT:	MOV	#DHALT,DSTART	;HALT (NO INTERRUPT) AFTER DELAY
	MOV	GR.PC,R3	;GET DPC ADDRESS
	MOV	$INTCT,R2	;GET CURRENT TICK COUNT
	ADD	#120.,R2	;ALLOW 2 SECONDS TO FINISH THE DISPLAY LIST
10$:	CMP	(R3),#DSTART+2	;HAS HALT BEEN REACHED ?

	.IF NE	VS60

	BNE	20$		;NO
	TST	DRB(R3)		;WAS IT THE REAL THING
	BEQ	GROUT		;YES, DPU RB WAS 0
20$:

	.IFF

	BEQ	GROUT		;YES

	.IFTF

	CMP	R2,$INTCT	;TIMEOUT EXCEEDED ?
	BGT	10$		;NO, NOT YET

	.IFT

	CLR	DRB(R3)		;MAKE SURE DPU RB IS 0

	.ENDC

	MOV	#DELAY,(R3)	;JAM DPC, WE'VE LOST CONTROL
	BR	GRHLT		;TRY AGAIN
;
; POWERFAILURE
;
;
; POWERFAILURE MERELY CAUSES THE DPU TO BE RESTARTED AT THE START OF
; THE DISPLAY BUFFER WITH THE DPU STACK RESET.
;
;	INPUTS:
;
;	R4=ADDRESS OF SCB
;


GRPWF:	MOV	S.CSR(R4),R2	;;;GET VT11/VS60 CSR ADDRESS

	.IF NE	VS60

	MOV	#SRESET,DSP-2(R2) ;;;RESET THE DPU STACK
	CLR	DRB-2(R2)	;;;CLEAR THE DPU RB

	.IFF

	MOV	#GRSTK,GR.SP	;;;SET UP THE STACK POINTER

	.ENDC

	MOV	#DELAY,-(R2)	;;;START THE DPU
	MOV	R2,GR.PC	;;;SAVE THE DPC ADDRESS

;
; DEVICE TIMEOUT
;
; DEVICE TIMEOUT CANNOT OCCUR SINCE THE TIMEOUT COUNT IS NEVER SET.
;

GROUT:	RETURN			;;;
;
; DPU STOP INTERRUPT
;
; THE DPU STOP INTERRUPT OCCURS IN THE VT11 ON EITHER A DJSR, DJMP, OR DRET PSEUDO
; INSTRUCTION. IN EACH CASE THE INTERRUPT HANDLER PERFORMS THE NECESSARY FUNCTIONS.
; FOR THE VS60, IT OCCURRS ONLY AT THE END OF THE DELAY LIST AND AT THE
; END OF THE DISPLAY LIST.
;

$GRSTP::CALL	$INTSV,PR4	;;;START INTERRUPT ROUTINE

	.IF NE	VS60

	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 OF USER'S SPACE
	ADD	#BFHDR,R5	;;;PLUS HEADER SIZE
	MOV	R5,(R4)		;;;START IN USER'S LIST
	JMP	$INTXT		;;;EXIT FROM INTERRUPT
10$:	CLR	DRB(R4)		;;;CLEAR DPU RB
	MOV	#DELAY,(R4)	;;;START DPU IN DELAY LIST
	JMP	$INTXT		;;;EXIT FROM INT

	.IFF

	MOV	#SRESET,DSP(R4)	;;;RESET DPU STACK
	MOV	#DELAY,(R4)	;;;RESTART IN DELAY LIST
	JMP	$INTXT		;;;EXIT FROM INT

	.ENDC

	.IFF

	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 PHYSICAL 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+16.,R3	;;;FULL STACK ?
	BLOS	50$		;;;YES
	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

	MOV	R3,GR.SP	;;;SAVE DPU STACK POINTER
	MOV	(SP)+,R3	;;;RESTORE REGS
	MOV	(SP)+,R2
	JMP	$INTXT

40$:	CMP	R3,#GRSTK	;;;STACK EMPTY ?
	BLOS	90$		;;;YES, RESTART AT THE TOP
	MOV	-(R3),R4	;;;GET VIRTUAL RETURN ADDRESS
	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
	MOV	#DELAY,(R2)	;;;RESTART DISPLAY AT THE BEGINNING
	BR	20$

	.ENDC
;
; 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
	TST	FRKIP		;;;FORK CURRENTLY IN PROGRESS ?
	BNE	65$		;;;YES, FORGET INTERRUPT

	.IF NE	VS60

	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 NE	SCOPES

	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	65$		;;;NO, JUST EXIT
	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	65$		;;;NO, JUST EXIT

	.ENDC

	.ENDC

	.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 NE	VS60


	.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	(R5)+,(R4)+	;;;NAME SEARCH REG.

	.IFF

	MOV	(R5)+,(R4)+	;;;PUT IN DPC AT HIT
	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
	CLR	(R4)+		;;;NO EXTENDED STATUS FOR VT11
	CLR	(R4)+		;;;ALSO NO X OFFSET
	CLR	(R4)+		;;;ALSO NO Y OFFSET
	CLR	(R4)+		;;;ALSO NO NAME SEARCH REG.

	.IFTF

	MOV	TIP1,(R4)+	;;;COPY TIP SWITCH 1 STATUS

	.IF EQ	SCOPES

	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

	MOV	DSP-DCS(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-DCS(R5)	;;;NO, SELECT THIS LEVEL
	MOV	DST-DCS(R5),(R4)+;;;COPY DPC FOR THIS LEVEL
	ADD	#4,R3		;;;MOVE UP ONE LEVEL
	BR	40$		;;;LOOP
45$:	MOV	(SP)+,DSP-DCS(R5);;;RESTORE ORRIGINAL LEVEL

	.IFF

	MOV	GR.SP,R3	;;;GET DPU STACK POINTER
40$:	CMP	R3,#GRSTK	;;;AT TOP YET ?
	BLOS	45$		;;;YES
	MOV	-(R3),(R4)+	;;;COPY DPC FOR THIS LEVEL
	BR	40$		;;;LOOP
45$:

	.ENDC

	.ENDC

	MOV	(SP)+,R3	;;;RESTORE R3
	MOV	#-2,(R4)	;;;INSERT TERMINATOR

	.IF DF	M$$MGE

	MOV	(SP)+,KISAR6	;;;RESTORE MAPPING

	.IFTF

	MOV	#LPFRK+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
	BITB	#TS.ABO,T.STAT+2(R4) ;TASK CURRENTLY BEING ABORTED ?
	BNE	55$		;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	#TS.AST!TS.DST,T.STAT(R4) ;AST IN PROGRESS OR DISABLED ?
	BNE	50$		;YES, DON'T START ANOTHER (Q MIGHT GET FULL)
	MOV	#16.,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	#16.,(R0)+	;SAVE BLOCK SIZE
	MOV	#14.,(R0)+	;SPACE TO ALLOC 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 LISTHEAD
	CALL	$QINSF		;INSERT AST IN Q

	.ENDC

50$:	MOV	R4,R0		;COPY TCB ADDRESS
	CALLR	$SETCR		;REQUEST USER'S TASK
55$:	RETURN			;RETURN FROM FORK


60$:

	.IFT

	MOV	(SP)+,KISAR6	;;;RESTORE MAPPING

	.ENDC

65$:	INC	(R5)		;;;RESTART DPU
	JMP	$INTXT		;;;EXIT
;
; BUSS-ERROR / SHIFT-OUT INTERRUPT
;
; A BUSS ERROR OCCURS WHEN THE DPU ATTEMPTS TO EXECUTE DISPLAY INSTRUCTIONS
; FROM NON-EXISTANT MEMORY. A SHIFT OUT INTERRUPT OCCURRS WHEN A CHARACTER >40(8) IS ENCOUNTERRED
; WHILE IN THE SHIFT OUT MODE. IN EITHER CASE, MERELY RESTART THE DPU
; AT THE BEGINNING OF THE BUFFER.
;

$GRBSE::

	.IF NE	VS60

	JMP	$GRSTP		;RESTART ON BUSS ERROR/SHIFT OUT INT

	.IFF

	MOV	#GRSTK,GR.SP	;;;RESET DPU STACK POINTER
	MOV	#DELAY,@GR.PC	;;;RESTART DISPLAY AT THE BEGINNING
	RTI			;;;INTERRUPT FINISHED

	.ENDC

	.END
                                                                                                                                                                                                                                                                                                                