	.TITLE	RSX FAST CLOCK HANDLER
/
/  16 MAR 77 (015; PDH) CHANGE ARGUMENT FETCH PHILOSOPHY
/   4 MAR 77 (014; PDH) ADD RELAY CLOSURE DURING TIMED INTERVAL
/   2 MAR 77 (013; PDH) INSERT ESTIMATED SYSTEM DELAY
/  25 FEB 77 (011; PDH) CHANGE INTERVAL CALCULATION TO FPP
/  23 FEB 77 (008; PDH) EMPIRIC DETERMINATION OF SYSTEM OVERHEAD YIELDS
/			A VALUE OF 730 (OCTAL) FAST CLOCK TICKS.
/  23 FEB 77 (007; PDH) PROVIDE A 'DEBUG' PARAMETER FOR TIMING
/  21 FEB 77 (002; PDH) CONTINUE BY INSERTING CODE FOR THE 'FC' REQUESTS
/  15 FEB 77 (001; PDH) BUTCHER 'LP.32' TO GET A SKELETON HANDLER
/
/ THE FOLLOWING CAL PARAMETER BLOCKS ARE USED TO QUEUE REQUESTS FOR
/ PRINTER SERVICE:
/
/	CPB	3600	HANDLER INFORMATION (HINF)
/		EV	(RETURN 77 TO SIGNIFY NO I/O)
/		LUN
/
/	CPB	2400	ATTACH FAST CLOCK
/		EVA
/		LUN
/
/	CPB	3100	ESTABLISH TIME DELAY (PUT)
/		EVA
/		LUN
/		COMMAND WORD (1=INTERVAL;2=RELAY, BEGIN & END;4=RELAY, BEGIN ONLY)
/		POINTER TO TABLE OF VALUES
/		0
/
/	TABLE	NUMBER OF MICROSECONDS (MOST SIGNIFICANT HALF)
/		NUMBER OF MICROSECONDS (LEAST SIGNIFICANT HALF)
/		BIT PATTERN FOR RELAY CLOSURE AT BEGINNING OF INTERVAL
/		BIT PATTERN FOR RELAY CLOSURE AT END OF INTERVAL
/
/	CPB	2500	DETACH FAST CLOCK
/		EVA
/		LUN
/
	.EJECT
/ THE REQUESTOR'S EVENT VARIABLE IS CLEARED (ZEROED) WHEN THE REQUEST
/ IS QUEUED BY THE "QUEUE I/O" DIRECTIVE.  IF THE REQUEST CAN BE 
/ PERFORMED, THE EVENT VARIABLE IS SET TO ONE (+1) UPON COMPLETION.
/ IF THE REQUEST CANNOT BE PERFORMED, THE EVENT VARIABLE IS SET TO ONE 
/ OF THE FOLLOWING NEGATIVE VALUES:
/
/	 -6 -- ILLEGAL REQUEST FUNCTION
/	 -7 -- ILLEGAL DATA MODE
/	-24 -- LUN HAS BEEN REASSIGNED WHILE REQUEST WAS IN QUEUE
/	-30 -- OUT-OF-PARTITION TRANSFER (NORMAL MODE)
/	-203 - ILLEGAL TO ATTACH OR DETACH FROM OTHER THAN TASK LEVEL
/
/  IF THE PARAMETER 'DEBUG' IS DEFINED, MANY IOT'S ARE CHANGED TO 'FCDI'
/  TO ALLOW AN EXTERNAL ROUTINE TO TIME THE SYSTEM DELAY IN THE HANDLER.
/
/DEBUG=1
/
	.EJECT
X12=12		/AUTO-INCREMENT REG 12
X13=13		/AUTO-INCREMENT REG 13
X17=17		/AUTO-INCREMENT REG 17 (USED TO SET REQUESTOR'S EV)
R1=101		/RE-ENTRANT REGISTER ONE
R2=102		/RE-ENTRANT REGISTER TWO
R3=103		/RE-ENTRANT REGISTER THREE
R4=104		/RE-ENTRANT REGISTER FOUR
NADD=107	/NODE ADDITION ROUTINE ENTRY POINT
SNAM=123	/NAME SCAN ROUTINE ENTRY POINT
POOL=240	/LISTHEAD FOR POOL OF EMPTY NODES
PDVL=252	/LISTHEAD FOR PHYSICAL DEVICE LIST
ALAD=325	/ATTACH LUN & DEVICE ENTRY POINT
DLAD=332	/DETACH LUN & DEVICE ENTRY POINT
DQRQ=337	/DE-QUEUE REQUEST ENTRY POINT
VAJX=342	/VERIFY & ADJUST ENTRY POINT
IOCD=345	/DECLARE I/O REQUEST COMPLETE ENTRY POINT
DMTQ=361	/DETACH & EMPTY QUEUE ENTRY POINT
D.TG=10		/POSITION OF TRIGGER EVENT VARIABLE IN PDVL NODE
.INH=705522	/INHIBIT INTERRUPTS
.ENB=705521	/ENABLE INTERRUPTS
/
I=400000
ISB=710400
IDV=712000
ELD=713100
EST=713700
APISLT=77-40
FCRS=702601		/ FAST CLOCK: RESET BUFFER TO ZERO, CLEAR FLAG,
			/		STOP CLOCK
FCLG=702607		/ FAST CLOCK: CLEAR FLAG, LOAD CLOCK BUFFER FROM AC,
			/		START CLOCK
FCST=702621		/ FAST CLOCK: STOP
FCRB=702632		/ FAST CLOCK: READ CLOCK BUFFER INTO AC
FCCF=702624		/ FAST CLOCK: CLEAR FLAG
FCSF=702641		/ FAST CLOCK: SKIP ON FLAG
FCEI=702642		/ FAST CLOCK: ENABLE INTERRUPTS
FCDI=702644		/ FAST CLOCK: DISABLE INTERRUPTS
/
ORC=702101		/ RELAY BUFFER: CLEAR (OPEN) RELAY BUFFER
ORS=702104		/ RELAY BUFFER: SET RELAYS PER AC BITS
/
SET=ISZ			/ SET FLAG NON-ZERO (NEVER SKIPS)
/
	.IFDEF	DEBUG
FCRS=FCDI		/ RE-DEFINE ONLY THOSE IOT'S
FCLG=FCDI		/ THAT WOULD CAUSE PROBLEMS
FCST=FCDI		/ WITH A TIMING ROUTINE
FCEI=FCDI
	.ENDC
	.EJECT
FC	LAC	(PDVL	/SCAN PHYSICAL DEVICE LIST FOR NODE
	DAC*	(R1)	/FOR THIS DEVICE.
	LAC	(HNAM
	DAC*	(R2)
	JMS*	(SNAM	/(R1, R2, R6, X17, XR, & AC ARE ALTERED)
			/NODE FOUND?
	CAL	(10)	/NO -- EXIT
	DAC	PDVNA	/SAVE PDVL NODE ADDRESS
	AAC	+D.TG	/AND
	DAC	PDVTA	/TRIGGER EVENT VARIABLE ADDRESS ADDRESS.
	CAL	CCPB	/CONNECT INTERRUPT LINE
	LAC	EV	/CONNECT OKAY?
	SPA
	CAL	(10)	/NO -- EXIT
	LAC	(TG	/YES -- SET TRIGGER EVENT VARIABLE ADDRESS
	DAC*	PDVTA	/IN PHYSICAL DEVICE NODE
	AND	(70000	/DETERMINE "XR-ADJ"
	TCA
	DAC	XADJ
/
/
/ WAIT FOR TASK TO BE TRIGGERED BY 'QUEUE I/O' DIRECTIVE OR BY 'ABORT'
/ TO SIGNAL THAT A REQUEST HAS BEEN QUEUED.
/
WFTGR	CAL	WFTCPB	/WAIT FOR TRIGGER EVENT VARIABLE TO BE SET
/
/ THE TASK HAS BEEN TRIGGERED -- PICK A REQUEST FROM QUEUE (IF ANY)
/
	DZM	TG	/CLEAR TRIGGER
PQ	LAC	PDVNA	/DEQUE A REQUEST
	DAC*	(R1)
	JMS*	(DQRQ)	/(R1, R2, R4, R5, R6, XR, & AC ARE ALTERED)
			/WAS A REQUEST FOUND?
	JMP	WFTGR	/NO -- WAIT FOR TRIGGER
	DAC	RN	/YES -- SAVE ADDRESS OF REQUEST NODE
	TAD	XADJ	/SETUP XR TO ACCESS NODE
	PAX
/
	.EJECT
/  THE FORMAT OF AN I/O REQUEST NODE (RN) IS AS FOLLOWS:
/
/	 (0) FORWARD LINKAGE
/	 (1) BACKWARD LINKAGE
/	 (2) REQUESTOR'S STL NODE ADDRESS
/	 (3) NORMAL/EXEC MODE INDICATOR
/	 (4) TASK PRIORITY (TO BE CHANGED!)
/	 (5) I/O FUNCTION CODE IN BITS 9-17, AND
/	     LUN IN BITS 0-8.
/	 (6) CPB WD 1 -- EVENT VARIABLE ADDRESS
/	 (7) CPB WD 3 -- (UNIQUE TO CAL)
/	(10) CPB WD 4 -- (UNIQUE TO CAL)
/	(11) CPB WD 5 -- (UNIQUE TO CAL)
/
/  IF AN I/O REQUEST IS QUEUED BY AN INTERRUPT SERVICE ROUTINE, ZERO IS
/  USED IN PLACE OF AN STL NODE ADDRESS.
/
/  IF AN I/O REQUEST IS QUEUED BY A "NORMAL MODE" TASK, ITS PARTITION
/  BLOCK ADDRESS IS SET IN THE MODE INDICATOR.  FOR AN "EXEC" MODE TASK,
/  THE MODE INDICATOR IS SET TO ZERO.
/
	LAC	5,X	/FETCH CAL FUNCTION CODE
	AND	(777)
	SAD	(017)	/ABORT REQUEST?
	JMP	ABORT	/YES -- ABORT TASK I/O
	SAD	(777)	/NO -- EXIT (DEASSIGNED) REQUEST?
	JMP	DAEX	/YES -- DETACH & EXIT
	SAD	(31	/ PUT REQUEST?
	JMP	PUT	/YUP
	SAD	(36	/HINF CODE REQ?
	JMP	HINF
	CLL!RAR		/SEARCH ATTACH DETACH IN COMMON
	SAD	(12	/24/2 AND 25/2  ARE 12
	JMP	ATTACH	/GO DO EITHER
ILFUNC	LAW	-6	/NO -- UNIMPLEMENTED FUNCTION -- SET
	JMP	SEV	/EVENT VARIABLE TO -6
/
	.EJECT
/ ABORT ALL I/O INITIATED BY THE INDICATED TASK.
/
ABORT	XOR	5,X	/ABORT IS AN ILLEGAL FUNCTION FOR ALL TASKS
	SZA!CLA!CMA	/EXCEPT 'IORD', WHO SETS THE LUN=0.
	JMP	ILFUNC
	LAC	PDVNA	/PHYSICAL DEVICE NODE ADR
	DAC*	(R1)
	LAC	RN	/REQUEST NODE ADR
	DAC*	(R2)
	JMS*	(DMTQ)	/DETACH LUN & DEVICE, IF NECESSARY, AND THEN
			/EMPTY THE QUEUE OF ALL I/O REQUESTS MADE BY THE
			/TASK BEING ABORTED. (R1, R2, R3, R5, R6, X10,
			/X11, X12, XR & AC ARE ALTERED).
	JMP	SP1	/DONE.
/
/  ATTACH TO  OR  DETACH FROM A TASK
/
ATTACH	CLA!RAL		/LINK TO AC; ATTACH-DETACH COMMON CODE
	PAX		/XR 0 FOR ATTACH, 1 FOR DETACH
	LAC	PDVNA	/LUN AND DEVICE
	DAC*	(R1)
	LAC	RN
	DAC*	(R2)
	XCT	ATTDET,X /(R3, R4, R5, R6, X10, X11, XR, & AC ARE ALTERED)
			/WAS LUN DETACHED?
	JMP	SEV	/NO -- SET REQUESTOR'S EVENT VARIABLE TO -24 OR -203
SP1	CLA!IAC		/YES -- SET REQUESTOR'S EVENT VARIABLE TO +1
	JMP	SEV
/
ATTDET	JMS*	(ALAD		/ MONITOR CALLS FOR ATTACH-DETACH
	JMS*	(DLAD
/
HINF	LAC	(77)		/ RETURN HANDLER INFORMATION
	JMP	SEV		/ IN EVENT VARIABLE
/
ERR30	LAW	-30
/
/  COMMON TERMINATION OF NON-PRINTING REQUESTS
/
SEV	JMS	SEVRN	/SET EVENT VARIABLE, DECLARE SIGNIFICANT
	LAC	RYFLAG		/ PUT END-OF-INTERVAL RELAY FLAG IN LINK
	RAR
	LAC	RYEND		/ GET BITS FOR RELAY AT END OF INTERVAL
	SZL
	ORC!ORS			/ SET RELAYS ONLY WHEN REQUESTED
	JMP	PQ	/EVENT, RETURN NODE, PICK NEXT REQ.
/
	.EJECT
/  PUT REQUEST.  ESTABLISH WHAT WAS REQUESTED.
/
PUT	LAC	7,X		/ GET COMMAND WORD FROM REQUEST NODE
	DAC	COMAND		/ SAVE FOR LATER INSPECTION
	LAC	10,X		/ GET PARAMETER TABLE ADDRESS
	DAC*	(R3
	LAC	RN
	DAC*	(R2
	LAC	(4
	DAC*	(R4
	JMS*	(VAJX		/ VERIFY & ADJUST TABLE (LENGTH 4)
	JMP	ERR30
	ELD;	I+R3		/ LOAD TIME INTERVAL VALUE
	LAC*	(R3
	TAD	XADJ
	PAX			/ POINT TO PARAMETER TABLE
	LAC	2,X		/ GET RELAY SETTING FOR
	DAC	RYBGIN		/ BEGINNING OF INTERVAL
	LAC	3,X		/ GET RELAY SETTING FOR
	DAC	RYEND		/ END OF INTERVAL
	LAC	COMAND
	RAR			/ PREPARE TO INSPECT COMMAND
	AND	(3		/ KEEP ONLY RELAY BITS
	SNA			/ DO WE HAVE RELAYS TO SET?
	JMP	TSET		/ NO.  SEE IF THERE IS A TIME INTERVAL.
	CLL!RAR
	DAC	RYFLAG		/ CLEAR OR SET FLAG FOR RELAYS AT END.
	LAC	RYBGIN
	ORC!ORS			/ SET RELAYS FOR BEGINNING OF INTERVAL
	LAC	COMAND
	RAR			/ PUT INTERVAL SET BIT IN LINK
/
	.EJECT
TSET	SNL
	JMP	SP1		/ NO TIME REQUEST.
	FCDI			/ MAKE ABSOLUTELY SURE WE'RE TURNED OFF
	IDV;	(10		/ DIVIDE BY 8 (RESOLUTION OF CLOCK)
	ISB;	(730		/ ACCOUNT FOR ESTIMATED SYSTEM OVERHEAD
	EST+3;	MOST		/ STORE NEGATIVE OF FINAL CLOCK PERIOD
	LAC	MOST		/ RETRIEVE NEW VALUE OF 'MOST'
	ISZ	MOST		/ IS IT A SINGLE INTEGER RESULT?
	SKP
	JMP	LESS		/ YES.  ONLY 1 ITERATION REQUIRED
	SPA			/ WAS REQUESTED TIME TOO SHORT?
	JMP	MOREOK		/ NO.  MULTI-ITERATIONS WILL DO IT
	LAC	(5		/ TOO SHORT.  SET REQUESTOR'S EV=5 TO
	JMP	SEV		/ SO SIGNIFY, AND EXIT WITHOUT CLOCK ACTION
/
MOREOK	LAC	JMANY		/ SET BRANCH ADDRESS IN INTERRUPT SERVICE
	DAC	BRANCH		/ FOR SEVERAL EXPIRIES
	CLA
	JMP	STARTC		/ THEN START CLOCK FOR MAXIMUM DELAY
/
LESS	LAC	JLAST		/ SET BRANCH ADDRESS IN INTERRUPT SERVICE
	DAC	BRANCH		/ FOR LAST (OR SINGLE) CLOCK EXPIRY
	LAC	LEAST
STARTC	DZM	EV		/ HERE IS WHERE WE WIND UP THE CLOCK
	FCLG
	FCEI			/ ENABLE INTERRUPTS
	.IFDEF	DEBUG
	SET	EV		/ THIS PREVENTS A HUNG SYSTEM
	.ENDC			/ WHEN IN 'DEBUG' MODE
	JMS	WFAB		/ AND WAIT FOR THE INTERVAL TO FINISH
	FCRS			/ STOP (AND RESET) THE BEAST
	FCDI			/ AND DISABLE IT!
	JMP	SP1		/ SET REQUESTOR'S EV=1, AND CONTINUE
/
	.EJECT
/ WFAB -- SUBROUTINE TO WAIT FOR EVENT VARIABLE TO BE SET AND THEN TO
/ CHECK THE TRIGGER EVENT VARIABLE TO SEE IF AN ABORT REQUEST SHOULD
/ BE PROCESSED.
/
WFAB	0
	CAL	WFECPB	/WAITFOR EV TO BE SET.
	LAC	TG	/IS BIT 2 OF THE TRIGGER SET?
	RTL
	SMA
	JMP*	WFAB	/NO -- RETURN
/
/ DE-QUEUE THE ABORT REQUEST.
/
	DZM	TG
	LAC	PDVNA	/PHYSICAL DEVICE NODE ADR
	DAC*	(R1)
	JMS*	(DQRQ)	/(R1, R2, R4, R5, XR & AC ARE ALTERED).
			/WAS A REQUEST FOUND?
	JMP*	WFAB	/NO -- SHOULD NEVER RETURN HERE.
	DAC	RN	/YES -- SAVE NODE ADR
	DAC*	(R2)
	LAC	PDVNA	/PHYSICAL DEVICE NODE ADR
	DAC*	(R1)
	JMS*	(DMTQ)	/DETACH LUN & DEVICE, IF NECESSARY, AND THEN
			/EMPTY THE REQUEST QUEUE OF ALL I/O REQUESTS
			/MADE BY THE TASK BEING ABORTED. (R1, R2, R3,
			/R5, R6, X10, X11, X12, XR & AC ARE ALTERED).
	JMS	SEVRN	/SET REQUESTER'S ('IORD'S') EV, DECRE-
			/MENT THE I/O PENDING COUNT, AND RETURN NODE TO POOL.
	JMP*	WFAB
/
	.EJECT
/ SEVRN -- SUBROUTINE TO SET THE REQUESTOR'S EVENT VARIABLE TO THE
/ QUANTITY IN AC, DECLARE A SIGNIFICANT EVENT, DECREMENT I/O TRANSFERS
/ PENDING COUNT (NORMAL MODE), AND RETURN REQUEST NODE TO THE POOL.
/
SEVRN	0
	PAL		/SAVE EV VALUE
	LAC	RN	/REQUEST NODE ADR
	TAD	XADJ
	PAX
	LAC	6,X	/REQUESTER'S EV
	SNA
	JMP	NOSET	/NONE SPECIFIED
	TAD	XADJ
	PAX
	PLA
	DAC	0,X	/SET EV
/
NOSET	LAC	RN	/DECLARE I/O REQUEST COMPLETED (DECREMENT
	DAC*	(R2)	/TRANSFERS PENDING COUNT).
	JMS*	(IOCD)	/(R5, XR, & AC ARE ALTERED)
	LAC	(401000 /DECLARE A SIGNIFICANT EVENT
	ISA
	LAC	(POOL)	/RETURN REQUEST NODE TO POOL
	DAC*	(R1)	/ (R2 IS ALREADY SETUP)
	JMS*	(NADD)
	JMP*	SEVRN	/EXIT 'SEVRN' SUBROUTINE
/
/ EXIT REQUEST (FROM TASK "...REA")
/
DAEX	LAC	(POOL)	/RETURN REQUEST NODE TO POOL
	DAC*	(R1)
	LAC	RN
	DAC*	(R2)
	JMS*	(NADD)
/
/  TURN OFF FAST CLOCK
/
	FCRS		/ TURN OFF, THEN
	FCDI		/ DISABLE FAST CLOCK INTERRUPTS
	CAL	DCPB	/DISSCCCONNECT
	ISZ	PDVTA	/CLEAR ASSIGN INHIBIT FLAG IN PDVL NODE
	.INH
	DZM*	PDVTA
	.ENB
	CAL	(10)	/EXIT
/
	.EJECT
/ INTERRUPT SERVICE ROUTINE
/
JMANY	JMP	MANY		/ INSTRUCTIONS INSERTED
JLAST	JMP	LAST		/ AT 'BRANCH'
/
FCINT	0			/ INTERRUPT ENTRY POINT
	DBA			/ ENTER INDEX (PAGE) MODE
	DAC	ACBF		/ SAVE AC
	FCCF			/ CLEAR FLAG, BUT LEAVE CLOCK RUNNING
BRANCH	XX			/ 'JMP MANY' OR 'JMP LAST'
/
MANY	ISZ	MOST		/ IS IT TIME FOR FINAL PASS?
	JMP	NOTSIG		/ NOT YET.  RETURN TO INTERRUPTED PROGRAM
	LAC	JLAST		/ SET SO THAT NEXT TIME THROUGH WILL BE
	DAC	BRANCH		/ LAST TIME FOR THIS REQUEST.
	LAC	LEAST		/ GET FINAL CLOCK PERIOD
	FCLG
	JMP	NOTSIG		/ NO SIGNIFICANT EVENT YET.
/
LAST	SET	EV		/ SET EVENT VARIABLE NON-ZERO
	LAC	(401000		/ DECLARE A SIGNIFICANT EVENT
	ISA
NOTSIG	LAC	ACBF		/ RESTORE AC
	DBR			/ RETURN TO INTERRUPTED PROGRAM
	JMP*	FCINT
/
	.EJECT
/  VARIABLE STORAGE AND CPB'S
/
MOST;LEAST; .LOC MOST		/ HNAME IS USED ONLY INITIALLY
HNAM	.SIXBT	'FC@@@@'	/ DEVICE NAME (HANDLER TASK NAME IS FC....)
COMAND;RYBGIN;RYEND;RYFLAG
XADJ	0	/XR ADJUST CONSTANT TO SUBTRACT PAGE BITS
ACBF	0	/AC BUFFER
EV	0	/EVENT VARIABLE
RN	0	/ADDRESS OF REQUEST NODE PICKED FROM QUEUE
TG	0	/TRIGGER EVENT VARIABLE
/
PDVNA	0	/PHYSICAL DEVICE NODE ADDRESS
PDVTA	0	/ADDRESS OF ADR OF TRIGGER EV IN PHY DEV NODE
/
WFTCPB	20		/WAIT FOR TRIGGER
	TG
CCPB	11	/CONNECT CPB
	EV
	APISLT
	FCINT
/
DCPB	12	/DISCONNECT CPB
	0
	APISLT
	FCINT
/
WFECPB	20	/WAIT FOR EVENT VARIABLE CPB
	EV
/
	.END	FC
