	.TITLE UNSLCT
	.IDENT /24MY89/
;
;	File:[22,310]UNSLCT.MAC
;	Author: Philip Hannay.  24-May-89.
;	History: 
;         24-May-89.  Philip Hannay.  Created from Pascal-1 Thunder Bay
;           TBPASUTL UNSLCT source.
;         17-Jul-89.  Philip Hannay.  Fixed bug - failed to specify efn
;           in QIOW, so QIOW behaved like a "no wait" QIO.
;
;	Last Edit: 17-JUL-1989 09:53:51 

.rem |

Procedure UNSLCT(lun: integer; efn:Event_Flag; VAR stat: integer);
  External;

{*USER*

This is the unsolicited input ast control routine package.  Facility
is provided to use an event flag to signal unsolicted input.  

Calling this procedure will activate unsolicted input detection
using the unsolicted input AST coupled with a local or global
event flag.  The lun specified in LUN will be attached with
unsolicted input detection activated.  When unsolicted input
is detected, the program will enter into an enclosed AST routine
that will set the event flag specified in EFN.  The AST will then
exit normally, and the caller can decide what to do.  

This provides
the capability to wait for input (stop/wait on event flag) without committing
ourselves to a QIO, and the capability to detect "input in progress"
while active elsewhere in the program.  STATUS will return a success
code (+1) if the port attaches okay, a negative number error code if it
does not.  To cancel unsolicted input notification, the lun need
only be detached using QIOW IO_DET, or call UNSLCT for the lun and specify
a zero event flag (f0) for the event flag EFN.  As you might expect, this module
must be linked into the root of the program since it contains AST
code that may be executed anywhere in the program.  

The lun number specified in LUN can vary from 1 to 30.
UNSLCT can be called multiple times to map multiple luns to multiple flags.
You can associate each lun with a unique flag, letting
you determine which lun tripped the AST, and thus which lun to 
service.  Or you can associate each lun with
a single flag, simplifying your wait processing. 

If you use multiple luns and event flags, you can use the flag 
to indicate IO in progress on the associated lun.  This will not affect
the other flags, so that you must check each flag as needed to determine
if IO is in progress on other luns.  

If you call UNSLCT for the same lun twice, the last call will
determine the event flag that is used EFN.  

IMPORTANT:  The unsolicited input ast is armed for a lun after calling
procedure UNSLCT.  The ast remains armed for that lun 
until an unsolicted character
in input on that lun and the ast jumped to.  Thereafter, the ast is not armed
FOR THAT LUN,
and subsequent characters will NOT activate the ast (set the flag).
After a QIO (READLN) has been successfully done for the specific
lun, the unsolicited character ast will be rearmed and any SUBSEQUENT
unsolicited input will activate the ast (set the flag).  This means
that there is a time between jumping to the ast (setting the flag)
and completing the QIO when more characters can be typed in without
activating the ast and setting the flag.  Thus, to insure airtight
input, you should do your QIO (READLN) and CLEF (clear the flag)
(the order is not important), and THEN examine the typeahead count
with PASUTL routine TYPBUF (or QIOW SF_GMC).  If the count is zero 
(no chars in typeahead),
you need do nothing as you already got all the input in your QIO call.
If the count is non-zero (characters in typeahead),
you should continue reading from the lun (using QIO/READLN), or
you should SETF (set the flag) to simulate the action of the ast
so that you will be signalled to read the rest of those characters 
on your next cycle.

This routine uses local EFN 24, which is normally reserved for use by
P3UTIL routines.

}


|

;
; Assemble with PASMAC.MAC as prefix file.
;


	.MCALL 	QIOW$S,CLEF$S
	
	PROC UNSLCT
	PARAM LUN, INTEGER
	PARAM EFN, CHAR
        PARAM STAT, ADDRESS

	VAR IOSTAT,2*INTEGER

	SAVE <R0,R1,R2,R3>
	BEGIN

	MOV	SP,R3		;COPY OF STACK POINTER IN R3
	ADD	#IOSTAT,R3	;R3 NOW POINTER TO IO STATUS BLOCK
	MOVB	EFN(SP),R1	;EFN NUMBER GOES TO R1
	MOV	LUN(SP),R0	;LUN NUMBER GOES TO R0
	TST	R0		;CHECK LUN NUMBER VALIDITY
	BLE	2$		;BRANCH IF LESS THAN OR EQUAL TO ZERO - INVALID
	CMP	R0,#30.		;SEE IF IT IS GT 30.
	BGT	2$		;BRANCH IF GT 30 - INVALID
	QIOW$S	#IO.DET,R0,#24.,,R3	;DETACH LUN IF NOT ALREADY DONE SO
	BCS	1$		;BRANCH IS DIRECTIVE FAILURE
	CMPB	#IS.SUC,(R3)	;SEE IF DETACH WAS SUCCESSFUL
	BEQ	6$		;BRANCH IF SUCCESSFUL
	CMPB	#IE.DNA,(R3)	;SEE IF "NOT ATTACHED" ERROR
	BEQ	6$		;BRANCH IF "NOT ATTACHED" ERROR WHICH IS OKAY
	BIS	#^O177400,(R3)	;SET HIGH ORDER BIT IN IOERR WORD TO 
					;MAKE NEGATIVE WORD
	MOV	(R3),@STAT(SP)	;SAVE ERROR CODE IN STAT
	BR	5$		;AND RETURN
6$:	TST	R1		;CHECK EFN - IF ZERO, NOTHING ELSE TO DO
	BEQ	1$		;BRANCH IF ZERO - EXIT RETURNING SUCCESS
	CLEF$S	R1		;NOW CLEAR THE SPECFIED EFN - ALSO VALIDATES 
	BCS	1$		;BRANCH IF DIRECTIVE FAILURE
	MOV	R0,R2		;LUN NUMBER TO R2
	ADD	R0,R2		;DOUBLE LUN NUMBER TO OBTAIN OFFSET FOR PPQEFN
	SUB	#2,R2		;ADJUST FOR LUN NUMBER STARTING AT 1
	MOV	R1,PPQEFN(R2)	;PUT THE EFN # IN PPQEFN FOR PPUNSL AST USE
	QIOW$S	#IO.ATA!TF.NOT!TF.XCC,R0,#24.,,R3,,<#PPUNSL,R0>
	BCS	1$		;BRANCH IF DIRECTIVE FAILURE
	CMPB	#IS.SUC,(R3)	;SEE IF ATTACH WAS SUCCESSFUL
	BEQ	1$		;BRANCH IF SUCCESSFUL
	BIS	#^O177400,(R3)	;SET HIGH ORDER BIT IN IOERR WORD TO 
					;MAKE NEGATIVE WORD
	MOV	(R3),@STAT(SP)	;SAVE ERROR CODE IN STAT
	BR	5$		;AND RETURN
2$:	MOV	#IE.ILU,@STAT(SP)	;LUN NUMBER GT 30 OR LT 1
	BR	5$
1$:	MOV	$DSW,@STAT(SP)	;PUT DIRECTIVE STATUS IN MAINSTAT VAR
5$:
;
;  WE HAVE ATTACHED THE TERMINAL AND ASKED THE EXEC
;   TO DECLARE AN AST TO ADDRESS PPUNSL WHENEVER UNSOLICITED INPUT COMES
;   IN.  WE ALSO SET IT TO NO TOUCH THE TYPE AHEAD BUFFER AND TO PASS
;   CONTROL-C TO MCR.  NOTE THAT THE LUN NUMBER MUST RESIDE BETWEEN 1 AND
;   30, WHICH IS DETERMINED BY THE SIZE OF OUR FLAG TABLE IN PPQEFN
;
	.PSECT	PPUNSD,RW,D,GBL,OVR
PPQEFN:
	.BLKW	30.			;THIS IS WHERE THE EFN FLAGS WILL BE
					;STORED FOR PPUAST AST USE, EACH
					;WORD CORRESSPONDS TO LUNS 1 THRU 30.
;
;
	.PSECT	PPUNSI,I,GBL,OVR	;GO TO A DIFFERENT PSECT FOR
					;UNSOLICITED CHAR AST CODE -- NOTE
					;THIS CODE MUST RESIDE IN MEMORY AT
					;ANY TIME IT MIGHT BE CALLED.  THIS
					;WILL NORMALLY MEAN THAT IT MUST 
					;RESIDE IN THE ROOT.
;
	.MCALL	ASTX$S,SETF$S
PPUNSL:
	MOV	R0,-(SP)	;PUSH R0 SO WE CAN USE IT
	MOV	2(SP),R0	;UNSL CHAR IN LOW BYTE, LUN NUMBER IN HIGH BYTE
	BIC	#255.,R0	;CLEAR LOW BYTE ZAPPING UNSL CHAR
	SWAB	R0		;PUT LUN NUMBER IN LOW BYTE, R0 IS NOW LUN #
	ADD	R0,R0		;DOUBLE R0 TO OBTAIN OFFSET TO PPQEFN
	SUB	#2,R0		;ADJUST SINCE LUNS BEGIN WITH 1
	ADD	#PPQEFN,R0	;R0 IS NOW POINTER TO PROPER EVENT FLAG TO SET
	MOV	(R0),R0		;R0 IS NOW PROPER EVENT FLAG TO SET
	SETF$S	R0		;SET THE EFN EVENT FLAG TO SIGNAL TASK
	BCC	1$		;BRANCH IF FLAG SET OKAY
	MOV	R0,R1		;DIRECTIVE ERROR
	MOV	$DSW,R2		;
	MOV	#11,R0		;FLAG SET FAILURE, PUT ID CODE IN R0 AND
	TST	1		;ABORT PROGRAM - ODD ADDRESS TRAP
1$:	MOV	(SP)+,R0	;RESTORE R0 BY POPPING SAVED VALUE OFF STACK
	TST	(SP)+		;POP IDENTIFICATION WORD OFF STACK AND TOSS
	ASTX$S			;RETURN FROM AST TO WHERE WE LEFT OFF
	MOV	#10,R0		;OPPS... ASTX FAILED, PUT ID CODE IN R0
	MOV	$DSW,R2		;PUT ERROR CODE IN R2
	TST	1		;ABORT PROGRAM - ODD ADDRESS TRAP
;
;
	.PSECT			;RETURN TO THE BLANK PSECT


	ENDPR
	.END
