Google
 

Trailing-Edge - PDP-10 Archives - BB-J724B-SM_1982 - sources/hbsc.p11
There are 30 other files named hbsc.p11 in the archive. Click here to see a list.
	.SBTTL	HBSC - line protocol driver

; this section contains the bsc (or bisync) and hasp task.
;  this task uses line driver subroutines to communicate with
;  an ibm-compatable bsc device, point-to-point.
;  many error and statistical counters are kept.
;  communication with the translate task is by sending and
;  receiving messages, and by changing and observing status
;  bits in the task control block.

.REPT 0


                          COPYRIGHT (c) 1982,1981,1980, 1979
            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.

.ENDR
;			REVISION HISTORY

; 3(001) BS	MODIFY (UN)/SUSPEND ROUTINES TO ALLOW CALLING FROM ANY TASK
;
; 3(002) BS	SUSPEND DEVICE IF MORE THAN 2 MESSAGES QUEUED TO IT
;
; 3(003) BS	CLEAR SYSTEM SUSPEND AFTER ACK RECEIVED FOR EMULATION
;
; 3(004) BS	UNSUSPEND DEVICE ONLY FIRST TIME INPUT PERMISSION IS GRANTED
;
; 3(005) BS	SEND NULL MESSAGE IF DEVICE STATUS CHANGED AND NO MESSAGES 
;
; 3(006) BS	SUSPEND DEVICE AFTER ONE MESSAGE IF FE SHORT ON CHUNKS
;
; 3(007) BS	INCREASE TIME TO SEE IF OTHER SIDE IS BIDDING
;
; 3(010) BS	SEND NULL MESSAGES ONLY AFTER LINE IS SIGNED ON
;
; 3(011) BS	REDUCE THE WAIT TIME BETWEEN SENDING MESSAGES WITH HASP
;
; 3(012) BS	TERMINATE TRANSMISSION IN 2780/3780 IF LINE IS DISABLED
;
;
; 3(013) BS	INDICATE COMMUNICATIONS ESTABLISHED IN  LINE FLAGS
;		SET H/W ABORT IF DSR GOES AWAY AFTER COMMUNICATION ESTABLISHED
;
; 3(014) BS	SET AND CLEAR CDR ACTIVE BIT FOR SIGNON
;
; 3(015) BS	SET H/W ABORT FOR HASP IF RX OR TX TIMES OUT OR ERROR
;
; 3(016) BS	SET H/W ABORT FOR 3780/2780 IF RX OR TX PROBLEM
;
; 3(017) BS	SET ALL DEVICE ACTIVE BITS FOR 2780/3780/HASP H/W ABORT
;
; 3(020) BS	SET DEVICE ACTIVE BIT FOR 3780/2780 DEVICE ABORT
;
; 3(021) BS	CLEAR DEVICE ACTIVE BIT FOR 3780/2780 ABORT ACK FROM PDP-10
;
; 3(022) BS	CLEAR DTR WHEN LINE IS DISABLED TO HANG UP LINE
;
;
; 3(023) BS	FREE SIGNON MESSAGE SENT TO BSC FROM XLHASP AFTER IT IS PUT IN
;		TRANSMISSION BLOCK
;
; 3(024) KR	If we receive input permission request from HASP while input
;		is already running, set new TCIRH bit to indicate input request
;		was held
;
; 4(025) BS	MODIFY CODE TO ACCEPT TRAILING BCB AND 2 FCS BYTES FROM IBM
;		IN LARGE MESSAGES.
;
; 4(026) BS	MODIFY CODE TO READ AND SEND TRANSPARENT MESSAGES CORRECTLY
;
; 4(027) BS	CORRECT FCS CODE TO TEST AND SET PUNCH STATUS CHANGE
;
; 4(030) BS	SEND NAK INSTEAD OF EOT TO REFUSE INPUT PERMISSION IN 3780 MODE
;
; 4(031) BS	ACCEPT SIGNON CONTROL RCB IN EMULATION TO HANDLE DISCONNECT
;		MESSAGE AND ROUTE MESSAGE TO CONSOLE
;
; 4(032) BS	ACCEPT TRANSMIT ABORT SCB IN HASP MODE AND TREAT AS END OF FILE
;
; 4(033) SMJ	Fix HSRXPM so that the BCB is stored correctly if a "reset
;		BCB count" BCB is read.  This means that the 3 bits (160)
;		are cleared before the next expected BCB is stored.
;
; 4(034) RLS	MAKE CHANGES REFLECTING NEW STORAGE MGT. MAINLY SEND GARBAGE
;		TO FRECHK INSTEAD OF IDLE.
;
; 4(035) RLS	30-JUL-80
;		HSCDOT - DROP CALL TO HSTSUS TO CHECK FOR CHANGE IN DEVICE STATUS
;		AND USE INLINE CODE...CLEAR TCHGST IN TCST2 ONLY IF NULL MSG IS
;		SUCCESSFULLY SENT. FLUSH FCN HSTSUS.
;
; 4(036) RLS	3-SEP-80
;		HSINIT - DON'T CLEAR LF.SON, NOW SET OR CLEARED INITIALLY IN
;		LINE ENABLE CODE.
;
; 4(037) RLS	2-OCT-80
;		REMOVE (011) EDIT AND RESTORE OLD CODE: 1 SEC IDLE ACK'S,
;		IMMEDIATE DATA ACKS
; 4(040) RLS	17-OCT-80
;		ADD DETECTION OF SOH-ENQ SEQUENCE TO HSARSP; RETURN RESPONSE
;		CODE 7 TO HSPXM2 WHICH CAUSES IMMEDIATE ABORT. DISCOVERED WHEN
;		IN LOOPBACK MODE, ONE LINE SAW BID AND FIRED UP BUT BID SENDER
;		APPARENTLY LOST ACK0 AND KEPT BIDDING. UNFORTUNATELY THE FIRST
;		SIDE THEN TREATED BIDS AS SIMPLY STRANGE MSGS. EVENTUALLY IT
;		ABORTED AFTER A LONG TIME. IBM CODE ALWAYS CAUSES IMMEDIATE 
;		LINE ABORT WHEN SOH-ENQ RECEIVED AFTER INITIAL BID COMPLETE.
;
; 4(041) KR	31-Oct-80
;		Code used absolute limit on block size (398.) but still
;		sometimes overflowed (for example in transparent mode).
;		Changed it to use LB.MBL and to correctly never exceed it.
;
; 4(042) KR	17-Oct-80
;		Add 2780/3780 flow control (primarily WACKO routine).

; 4(043) RLS	26-FEb-81
;		add detection of DLE-EOT for hangup; TCDIS set in TCST2 of BSC
;		tcb when detected.
;		uniformly reply NAK for bid refusal (2780/3780)(WACK is also
;		acceptable).
;		use XNRTY,RNRTY for retry counts for transmission,reception.
;		calling sequence for DQRXPM changed.
;		detect transparent bid(DLE-ENQ) in HSPLIN.

; 4(044) KR	26-Feb-81
;		Fix HSEOB to check for duplicate messages by checking for BCB
;		equal to previous received message and flush if so.
;		Following scenario gave rise to this fix:

;		IBM	DEC
;		    <-	msg(1)	- received ok
;		    ->	msg(2)	- received ok
;		    <-	msg(3)	- lost in noise
;		(time out)
;		    ->	NAK	- lost in noise
;		(time out)
;		    <-	NAK	- recieved ok
;		    ->	msg(2)	- received ok

; 4(045) RLS	9-Mar-81
;		Fix DQBCTL to treat LF.DIS as a line disable.
;		Also make BSC sleep at DQBCTL til EBINTR event occurs instead
;		of timing out.

; 4(046) rls	12-Mar-81
;		Begin centralizing device active bit hacking.
;		Create new functions SACTI,SACTO,CACTI,CACTO. Eliminate HSTAOA,
;		HSTAIA,HCLAOA,HCLAIA. Rewrite HSACMP function.

; 4(047) RLS	07-APR-81
;		Changes reflecting use of message headers for data storage.

; 4(050) RLS	17-APR-81
;		Transform static flow control to static/line control
; 4(051) RLS	Add checking for DLE-EOT to DQXNAV in TTD loop.

; 4(052) RLS	5-MAR-82	gco 4.2.1248
;		do HSDISL when DSR drops rather than DQFLSM.

; 4(053) RLS	16-MAR-82	gco 4.2.1269
;		Add data integrity checker under conditional DB.SEQ.

; 4(054) RLS	18-MAR-82	GCO 4.2.1274
;		Clear LS.ERR after transmitter errors have been cleaned up.
; 4(055) RLS	21-MAR-82	GCO 4.2.1282
;		Check for dsr on before check for aborts at LINCTL.
;		Add signon event traces
; 4(056) RLS	14-APR-82	GCO 4.2.1315
;		Check for ENQ response to data message in 2780/3780
; 4(057) RLS	15-APR-82	GCO 4.2.1322
;		Flush XNRTY,RNRTY usage...use LB.ERC
; 4(060) RLS	15-APR-82	GCO 4.2.1323
;		make DQXNAV think about about bad line conditions.
; 4(061) RLS	19-APR-82	GCO 4.2.1327
;		Have to check LS.ERR after waking up after T.WRT call, not
;		just EBALR wakeup.
; 4(062) RLS	GCO 4.2.1329 - INFLO,OUTFLO : distinguish HASP and non-HASP
;		flow conditions.
; 4(063) RLS	18-JUN-82	GCO 4.2.1392
;		do input abort processing similar to input eof. Do eot 
;		processing according to IBM conventions.
; 4(064) RLS	29-JUN-82	GCO 4.2.1412
;		apply threshold(NORPLY) to number of successive attempts at
;		communications ending with LF.HWA set(LB.NHA counter)
; 4(065) RLS	05-JUL-82	GCO 4.2.1419
;		set TCHGST in HSINIT - make status get sent when no signon
;		is sent
; 4(066) RLS	06-JUL-82	GCO 4.2.1421
;		in DQDTAS check for LF.OFL when bid fails and don't clear TCOPR
;		if so.
; 4(067) RLS	16-JUL-82	GCO 4.2.1450
;		in DQXNAV, make sure R4/line number on exit
; 4(070) RLS	27-JUL-82	GCO 4.2.1466
;		make sure DLE-EOT receipt causes return to control level
; 4(071) RLS	09-AUG-82	GCO 4.2.1485
;		delineate hasp/non-hasp in LF.HWA situations
; 4(072) RLS	17-SEP-82	GCO 4.2.1511
;		split HMSGTC into transparent and non-transparent branches
;		to do special character handling.
; 4(073) RLS	22-OCT-82	GCO 4.2.1521
;		in HSRQPT, check for permission already granted before sending
;		a permission request.

VHBSC=072

VEDIT=VEDIT+VHBSC
	.SBTTL		LINSTR,LINCTL - where all transactions start

; enter here from the dispatcher

LINSTR:	MOV	TCLCB(R5),R4	;point r4 to lcb

	BEQ	1$		;does not exist, exit
	BIT	#LS.ENB,(R4)	;is the line enabled ?
	BEQ	1$		;not enabled yet
	BIT	#LF.EIP,(R4)	;check if we are still doing it
	BEQ	2$		;no - ok to initialize

1$:				;no, set up wait and exit
	DSCHED	,#20		;wait for a while
	BR	LINSTR		;check again

2$:	CALL	@T.INI(R5)	;initialize the line driver
.IF NE,DB.SEQ
	CALL	PCHKI		;init sequence checker
.ENDC	;.IF NE,DB.SEQ
	BR	LINCTL

; here to be in bsc "control" mode.
;  wait for the line to be enabled and for data set ready.  then,
;  if "output permission requested" is set, bid for the line.
;  otherwise just listen for a bid.  if a bid arrives we must
;  get permission from the pdp-10 before replying "ACK-0".

LINCT0:	DSCHED	#EBINTR,#10	;sleep til something happens

LINCTL:	BIC	#TCEOT,TCST2(R5) ;new aborts will need eot again
	MOV	TCLCB(R5),R4	;point R4 to lcb

	CALL	CLRALR		;flush any alarm debris hanging around
	BIC	#LS.ERR,(R4) 	;clear error bit
	BIC	#LF.LAP!LF.DIP,LB.FGS(R4) ;clear these in case line just aborted
	BIT	#LS.ENB,(R4)	;is the line enabled?
	BEQ	21$		;no, see if genuine disable
	BIT	#LF.DIS,LB.FGS(R4) ;line disabled by dte ?
	BNE	21$		;treat this as disable command from 10
	BIT	#TCDIS,TCST2(R5);check for disconnect state
	BNE	21$		;yes - disable from the line
	CALL	HSCMDS		;check modem status
	BCC	11$		;dsr is on

; here if the data set is not ready.

	BIT	#LF.CME,LB.FGS(R4) ; communications established ? 3(013)
	BEQ	LINCT0		;no need to do more til we establish contact
	BIS	#LF.HWA,LB.FGS(R4) ;indicate a h/w  abort
21$:	JMP	HSDISL		;start disable sequence

11$:	BIT	#LF.HWA,LB.FGS(R4) ;check for hard aborts
	BEQ	15$
	BIT	#LF.CME,LB.FGS(R4) ;only a problem if we were talking
	BEQ	15$
	INC	LB.NHA(R4)	;count it
.IF NE,FT.HSP
	CMP	#TTHASP,LB.DVT(R4) ;in HASP, this is always fatal
	BEQ	21$		;its dead
.ENDC	;.IF NE,FT.HSP
	CMP	LB.NHA(R4),#NORPLY ; too many?
	BGE	21$		; yes - declare line down
	BR	16$

15$:	CLR	LB.NHA(R4)	;clear the successive abort counter
16$:	BIC	#LF.HWA,LB.FGS(R4) ;clear the abort

	BIT	#TCOAB!TCOAC!TCIAB!TCIAC,TCFG2(R5) ;abort in progress?
	BEQ	DSRON		;no - try something
	CALL	DQFLSM		;flush the queue
	BR	LINCT0		; and try again.
	.SBTTL		DSRON - 2780/3780...receive bid
; here when we have data-set-ready and the line is enabled.

; check for hasp line and if not default is 2780/3780.

	.ENABL	LSB
DSRON:
12$:
.IF NE,FT.HSP
	CMPB	#TTHASP,LB.DVT(R4) ;hasp line?
	BNE	13$		;no, must be 2780 or 3780
	JMP	HSPLIN		;yes, it is hasp line
.ENDC	;.IF NE,FT.HSP

; here the line is 2780 or 3780 

13$:	BIT	#TCOPR,TCFG2(R5) ;has output permission been requested?
	BEQ	15$
14$:	JMP	DQDTAS		;yes, bid for the line.

15$:	CALL	@T.RED(R5)	;no, see if other side is bidding
	MOV	#2*JIFSEC,LB.ALR(R4) ;wait about 2 seconds to make sure
	CLR	R4		;no data as yet
	CALL	MSGGTC		;get character
	BCS	16$		;none.
	CALL	CLRALR		;flush the alarm
	CMPB	#EBCENQ,R1	;an ENQ?
	BEQ	RCVBID		;yes - go do bid
	CMPB	#EBCDLE,R1	;check for disconnect
	BNE	16$		;no - nothing else here
	CALL	MSGGTC		;maybe
	BCS	16$		;died early
	CMPB	#EBCEOT,R1	;EOT?
	BNE	16$		;no - very confusing
	CALL	RCVDSC		;record intent of other end to disconnect

; here if we get an unrecognizable unsolicited message.

16$:	CALL	MSGGTT		;end message and wait the second
	JMP	LINCTL		;look for a bid again.

RCVBID:	CALL	TENQ		;record this
	CALL	MSGGTE		;process bid request
	CALL	HSETCE		;communications established 3(013)
	CALL	DQRQIP		;request input permission
	BCS	17$		;refused, clear the line.
	CALL	DQRECV		;accepted, receive data
	JMP	LINCTL		;when done, check again.

; here when input permission is refused.  send a NAK(WACK also valid) to refuse bid.

17$:	CALL	DQSNAK		;send NAK when input permission refused 4(030)
	JMP	LINCTL		;start over. 4(030)
	.DSABL	LSB
	.SBTTL		line event recording functions

RCVDSC:	BIS	#TCDIS,TCST2(R5) ;disconnect
	ATRACE	<(SP),R5,JIFCLK>
RCVDIS:	RETURN

TENQ:	TRACE	TRCLIN,<(SP),R5,JIFCLK>	;received an ENQ
RCVENQ:	RETURN

TACK0:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received ACK0
RCVAK0:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC1(R4)	;count message sent successfully
P4J:	RESTOR	R4
	RETURN

TACK1:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received ACK1
RCVAK1:	BR	RCVAK0

TIACK:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received implicit ACK(HASP)
RCVIAK:	BR	RCVAK0

TEOT:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received EOT
RCVEOT:	SAVE	R4
	MOV	TCLCB(R5),R4	;get pointer to lcb
	INC	LB.IC6(R4)	;count aborts
	BR	P4J

TNAK:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received NAK
RCVNAK:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC2(R4)	;count naks received
	BR	P4J

TTMO:	TRACE	TRCLIN,<(SP),R5,R4,R0,JIFCLK> ;time out on receive
RSPTMO:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.IC7(R4)	;count invalid messages due to timeout
	BR	P4J

TCRF:	TRACE	TRCLIN,<(SP),R5,R4,R0,JIFCLK> ;received cruft
RCVCRF:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC4(R4)	;record invalid reply to data
	BR	P4J

TWACK:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received WACK
RCVWAK:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC6(R4)	;count wacks received
	BR	P4J

TTTD:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received TTD
RCVTTD:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.IC5(R4)	;count ttd messages
	BR	P4J1

TRVI:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;recieved RVI
RCVRVI:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC9(R4)	;count rvis received
	BR	P4J1

TBCC:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received BCC error
RCVBCC:	SAVE	R4
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.IC2(R4)	;count instances of bad bcc
P4J1:	RESTOR	R4
	RETURN

.IF NE,FT.HSP

TBCB:	TRACE	TRCLIN,<(SP),R5,JIFCLK> ;received BCB error
RCVBCB:	INC	TCBCBE(R5)	;count bcb errors received
	RETURN

.ENDC	;.IF NE,FT.HSP
	.SBTTL		DQDTAS - 2780/3780...bid for the line
; here when we have data to send.  bid for the line.

DQDTAS:	MOV	LB.EQN(R4),LB.RTY(R4) ;number of tries to get the line
11$:	BIT	#TCOAB!TCOAC,TCFG2(R5) ;has stream been aborted?
	BEQ	12$		;no.
	CALL	DQFLSM		;yes, flush the queue
	BIC	#TCOPR,TCFG2(R5) ;no longer bidding
	JMP	LINCT0		; and try again.

12$:	MOV	#ENQMSG,R0	;send an ENQ
	MOV	#ENQLEN,R1
	CALL	CTLMSG		;send bid message and read response
	MOV	LB.EQW(R4),LB.ALR(R4) ;time to wait for reply
	CLR	R4		;no data yet
	CALL	MSGGTC		;get character from receiver
	BCS	15$		;nothing received
	CALL	CLRALR		;flush alarm now
	CMPB	#EBCENQ,R1	;did we get an ENQ?
	BNE	14$		;no, check for ACK
	BIC	#TCOPR,TCFG2(R5) ;no longer bidding
	JMP	RCVBID		;yes - go process bid

; come here if the response to ENQ is not ENQ

14$:	CMPB	#EBCDLE,R1	;is it DLE?
	BNE	15$		;no.
	CALL	MSGGTC		;yes, get next char
	BCS	15$		;timeout
	CMPB	#EBCAK0,R1	;is it ACK-0?
	BNE	15$		;no.
	CALL	TACK0		;yes - record it

; we have ACK-0, granting permission to send data.

	CALL	MSGGTE		;end of message
	BIS	#TCOPG,TCFG2(R5) ;note output permission granted
	BIC	#TCOPR,TCFG2(R5) ;no longer bidding
	CALL	HSETCE		;communications established 3(013)
	MOV	TCLCB(R5),R4	;point to lcb
	CALL	DQAWXL		;awaken xlate task
	CALL	DQXMIT		;go transmit
	MOV	TCLCB(R5),R4	;point to lcb
	CALL	DQAWXL		;awaken xlate task
	JMP	LINCTL		;back to bsc control mode

; here when the response to ENQ is bidrefusal(NAK,WACK) or is unrecognizable
;  finish waiting if necessary and bid again.

15$:	CALL	MSGGTT		;empty the receiver and wait
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC8(R4)	;record nonaffirmative bid response
	BIT	#TCOPR,TCFG2(R5) ;still want to bid for the line?
	BEQ	16$		;no.
	DEC	LB.RTY(R4)	;yes, have we tried often enough?
	BGE	11$		;no, try again.
16$:	BIT	#LF.OFL,LB.FGS(R4) ;check if offline and trying to get restarted
	BNE	30$		;yes - do not clear bid flag
	BIC	#TCOPR,TCFG2(R5) ;yes, no longer bidding
	CALL	DQAWXL		;awaken the xlate task
	BIT	#LF.CME,LB.FGS(R4) ;are we trying to restablish the link?
	BEQ	20$		;no - initial bid
	BIS	#LF.HWA,LB.FGS(R4) ;yes - looks like the other end is dead

20$:	MOV	#10.,-(SP)	;retry count
	CALL	DQSEOT		;send EOT to clear the line
	BCC	21$
	BIT	#LS.ENB,(R4)	;failed - check for permanent reasons
	BEQ	21$		;can't ever suc
	DEC	(SP)
	BGT	20$		;try again
21$:	TST	(SP)+

30$:	JMP	LINCTL		;back to control mode
	.SBTTL		DQFLSM - abort all line io


DQFLSM:	MOV	TCLCB(R5),R4	;point to lcb
	BIS	#LF.LAP,LB.FGS(R4) ;line abort in progess
	ATRACE	<(SP),R4,(R4),LB.FGS(R4),TCST2(R5),TCFG2(R5)>

.IF NE,FT.HSP
	CMPB	#TTHASP,LB.DVT(R4) ;check for hasp line
	BEQ	8$		;yes, continue
.ENDC	;.IF NE,FT.HSP
	MOV	LB.MSG(R4),R0	;no, point to last message
	BEQ	7$		;no message, continue
	CALL	FREMSG		;flush it
	CLR	LB.MSG(R4)	;clear line pointer to message
7$:	BIC	#LF.OFL,LB.FGS(R4) ;device is no longer off line

8$:	CALL	DEQCHK		;check for incoming - anything here has not
	BCS	11$		;been ack'd...I think.
9$:	CALL	FRECHK		;throw them away
	BR	8$

11$:	CALL	DEQMSG		;check for outgoing
	BCS	13$		;got them all
12$:	CALL	FREMSG		;send it the message to free
	BR	11$		;get more messages

; here when the message queue is empty.  wait a bit to be sure
;  it stays that way.

13$:	DSCHED	#EBINTR!EBQMSG,#10. ;wait a short while

	CALL	DEQCHK		;any more incoming?
	BCC	9$		;yes - toss them
	CALL	DEQMSG		;any messages?
	BCC	12$		;yes, free them and wait some more
.IF NE,FT.HSP
	CMP	#TTHASP,LB.DVT(R4) ;hasp line?
	BNE	21$		;no.

; multileaving processing

	CALL	BLOHSP		;blow away all the devices
23$:	RETURN
.ENDC	;.IF NE,FT.HSP

; 2780/3780 processing

21$:	BIT	#TCOAB!TCIAB,TCFG2(R5) ;is stream still in abort state?
	BNE	25$
	MOV	LB.TCD(R4),R3	;now flush anything left queued to the 10
	CALL	QDRAIN
	RETURN			;no, just return.

25$:	MOV	LB.TCD(R4),R1	; get the xlate tcb
	BIT	#TCOAB,TCFG2(R5) ;yes, output abort?
	BEQ	14$		;no.  check for input abort.
	BIS	#TCOAC,TCFG2(R5) ;yes, flag output abort complete
	BIS	#TCOAB,TCFG2(R1) ; make sure xlate knows what is happening
14$:	BIT	#TCIAB,TCFG2(R5) ;input abort?
	BEQ	15$		;no.
	BIS	#TCIAC,TCFG2(R5) ;yes, complete input abort.
	BIS	#TCIAB,TCFG2(R1) ; make sure xlate knows what is happening
15$:	SIGNAL	R1,EBINTR	; rudely awaken the xlate task
	BR	13$		;wait for "abort" to clear.

.IF NE,FT.HSP

;BLOHSP aborts all devices on an a HASP line
;	R4/LCB

BLOHSP:	SAVE	<R0,R1>
	MOV	LB.NTC(R4),R1	;get max dev #
	BEQ	23$		;field not setup
22$:	MOV	R1,R0		;point to lcb
	ASL	R0		; *2
	ADD	R4,R0
	MOV	LB.TCD(R0),R0	;point to xlate tcb
30$:	BIT	#TCIAB!TCOAB,TCFG2(R0) ;device stream aborted?
	BEQ	26$
	CALL	HSAWXL		;yes - wake the xlate task
	DSCHED	#EBINTR,#10.	;wait for xlate to abort
				;but can't trust the sequencing
	BR	30$

26$:	MOV	R0,R3		;now flush anything left queued to the 10
	CALL	QDRAIN
	SOB	R1,22$		;loop for all devices
	BIC	#TCIAC!TCIAB!TCOAC!TCOAB,TCFG2(R5) ;clear abort

23$:	RESTOR	<R1,R0>
	RETURN
.ENDC	;.IF NE,FT.HSP
	.SBTTL		HSDISL - disable line and release all storage

HSDISL:	MOV	TCLCB(R5),R4	;point to lcb
	ATRACE	<R4,(R4),LB.FGS(R4),TCST2(R5),TCFG2(R5)>
	BIS	#LF.DIP,LB.FGS(R4) ;line disable in progress
	BIC	#LS.ENB,(R4)	;mark line disabled in case it isn't already
	CALL	@T.KIL(R5)	;stop all line activity

	CALL	ABTLIN		;abort all io on line
	CALL	HSTBTS		;set all device active bits for 10
	CALL	DQFLSM		;clean up io debirs

	BIT	#LF.CME,LB.FGS(R4);if we have been talking - need to disconnect
	BEQ	20$
	BIT	#TCDIS,TCST2(R5) ;unless he disconnected from us
	BNE	20$
	CALL	HSCMDS		;or unless he hung up the line already
	BCS	20$

	BIS	#LS.ENB,(R4)	;enable line long enogh to send disconnect
	BIC	#LS.ERR,(R4) 	;clear error bit
	CALL	DQSDIS		;send disconnect message
	DSCHED	,#JIFSEC*3	;wait awhile and repeat
	CALL	DQSDIS		;send disconnect message
	BIC	#LS.ENB,(R4)
	CALL	@T.KIL(R5)	;make sure driver is quiesced

20$:	CALL	HSRMRL		;release all received messages
	CALL	HSRLOM		;also all outgoing messages

	MOV	R4,R0		; get lcb for arg
	CALL	@T.DOF(R5)	;drop dtr

	MTPS	#BR7		;prevent interference during last cleanup
	MOV	#PDL,SP		;get scheduler pdl
	CALL	FLSTCB		;release all tcb's and associated buffers
	CALL	FLOSHR		;recalculate available resources
	BIC	#LF.EIP!LF.LAP!LF.DIP,LB.FGS(R4) ;disable no longer in progress
	BIS	#LF.DAC,LB.FGS(R4) ;line abort,disable complete
	JMP	SKDINI		;restart scheduler
	.SBTTL		DQXMIT - 2780/3780...message tranmission
; we have received ack-0 response to bid enq.  send messages.

DQXMIT:	BIS	#TCAK1,TCST2(R5) ;note ack-1 needed next
				; and doing output.
11$:	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.ERC(R4),LB.RTY(R4) ;retry count is 15.
	BIC	#TCNRD,TCST2(R5) ;no "no responses" yet
	BIT	#TCOAB,TCFG2(R5) ;has transmission been aborted?
	BEQ	2$
	CALL	16$		;yes, send eot and exit.
	RETURN

2$:	BIC	#LS.ERR,(R4)	;clear any previous errors
	BIT	#LF.OFL,LB.FGS(R4) ;did device go off line before ?
	BEQ	22$		;no, continue as before
	BIC	#LF.OFL,LB.FGS(R4) ;yes, clear the flag that says it did
	TST	LB.MSG(R4)	;any messages ready to transmit again ?
	BNE	13$		;retransmit message
22$:	CALL	DEQMSG		;no, get message to send
	BCC	12$		;got one.
	CALL	DQXNAV		;worry about no msgs available.
	MOV	TCLCB(R5),R4	;this could have been munged
	BCC	9$		;try to do something now
	CALL	16$		;line cruftiness
	RETURN
9$:	BIT	#TCOEC,TCFG2(R5) ;check terminating conditions
	BNE	23$		;EOF
	BIT	#LF.OFL,LB.FGS(R4) ; check for device offline
	BEQ	11$		;no - must be a message now

21$:	BIS	#TCOPR,TCFG2(R5) ;yes - remember we were sending

23$:	BIC	#TCORN!TCOPG,TCFG2(R5) ;no longer doing output
	RETURN

; here if there is a message available to send.

12$:	MOV	R0,LB.MSG(R4)	;store message pointer

; here to send the message again.

13$:	MOV	LB.MSG(R4),R0	;point to message
	MOV	MSGLEN(R0),LB.ALR(R4) ;no more than one jiffie per char
	ADD	LB.CSD(R4),LB.ALR(R4) ;plus clear-to-send delay
	CALL	@T.WRT(R5)	;start sending message
	BCS	16$		;only fails for line disable or abort set

	CALL	@T.RED(R5)	;set up to read response
	DSCHED	#EBINTR!EBALR
	BIT	#LS.ERR,(R4)	;check for hard error wakeup
	BNE	14$
	BIT	#EBINTR,TCWKEV(R5) ;interrupt
	BNE	15$		;yes
	INC	LB.TTO(R4)	;count transmitter timeouts

14$:	CALL	@T.KIL(R5)	;error - zonk the hardware
	BIC	#LS.ERR,(R4) 	;clear error bit
	CALL	@T.RED(R5)	;reissue the read
				;the protocol will handle the error
	DSCHED	,#10.		;displace timeouts...in case transmitter quit
				;early in message

; here if the transmission of the data message was successful.

15$:	CALL	CLRALR		;flush alarm now
	CALL	DQXRSP		;read and analyze response
	BCC	19$		;successful acknowledgment
				;WACK falls through, LB.RTY has been incremented
				; so it doesn't count as a failure

	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LS.ENB,(R4)	;is the line still enabled?
	BEQ	16$		;no - die gracefully
	BIT	#TCDIS,TCST2(R5) ;is the other end hanging up??
	BNE	16$		;yes - die with similar grace
	BIT	#LF.OFL,LB.FGS(R4) ;did device go off line
	BNE	21$		;stop transmitting and bid for the line again

	BIT	#TCOAB,TCFG2(R5) ;has operation been aborted?
	BNE	16$		;yes, error return.
	DEC	LB.RTY(R4)	;no, decrement retry count
	BGT	18$		;send enq or data
	CALL	16$		;error - blow away the stream
	RETURN

; here to terminate the message stream because
;  the 10 requested termination, because we received
;  an EOT in response to a data block, because of transmitter 
;  error or timeout or because the retry counter ran out.


16$:	TRACE	TRCLIN,<R5,2(SP),(R4),LB.FGS(R4),TCFG2(R5),TCST2(R5)>

	CALL	@T.KIL(R5)	;make sure the driver is quiescent
	CALL	CLRALR		;make sure alarm is flushed
	CALL	DQSEOT		;send eot if necessary to clear line
	CALL	DQABRO		;flag output aborted.
	BIC	#TCORN!TCOPG,TCFG2(R5) ;no longer doing output
	MOV	TCLCB(R5),R4	;point to lcb
	BIC	#LF.OFL,LB.FGS(R4) ;device no longer considered off line
	MOV	LB.MSG(R4),R0	;is there a message trying to go?
	BEQ	17$		;no
	CALL	FREMSG		;yes - flush it
	CLR	LB.MSG(R4)	;there is no longer a message to go [1(624)]
17$:	RETURN

; here to send an ENQ or data because the response was unreasonable

18$:	CMP	R0,#2		;DQXRSP indicates send ENQ?
	BEQ	13$		;no, just send data.
	MOV	#ENQMSG,R0	;yes, send ENQ
	MOV	#ENQLEN,R1
	CALL	CTLMSG
	BR	15$		;analyze response to ENQ 3(016)

; here when a block has been transmitted successfully.

19$:	CALL	XLCLRM		;clear the message buffer
	JMP	11$		;try for another message


;this subroutine clears the transmitted message buffer after
;a message has been successfully transmitted

XLCLRM:	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.MSG(R4),R0	;point to message sent
	BEQ	29$		;no message, buffer has been cleared
	CALL	FREMSG		;send it the message to free
	CLR	LB.MSG(R4)	;no longer a message being sent
	BIS	#TCORN,TCFG2(R5) ;flag output running
	BIC	#TCOPG,TCFG2(R5) ;clear "output permission granted"
	DEC	LB.MSC(R4)	;one fewer msg waiting to transmit
	CALL	XLCSAB		;set or clear the device active bit
29$:	RETURN
	.SBTTL		DQXRSP - 2780/3780...read and analyze the response

; on return:

;	C is clear if the block is acknowledged.

;	C is set if the block is not acknowledged.
;	  if LS.ABO is set, the operation is aborted.
;	  otherwise:
;	  	R0 = 1, send ENQ or (if too many retries) EOT
;		R0 = 2, send data again or (if too many retries) EOT


DQXRSP:	MOV	TCLCB(R5),R4	; point to lcb
	CALL	KOSHL		;check out the line
	BCC	9$		;all is kosher
				;something broken
	CLR	R4		;flag no data yet

8$:	CALL	MSGGTT		;clean up after ourselves
	CALL	CLRALR		;flush alarm
	BR	12$

9$:	MOV	#3*JIFSEC,LB.ALR(R4) ;wait for three seconds max
	CLR	R4		;flag no data yet
	CALL	MSGGTC		;get data from reader
	BCS	13$		;nothing.
	CALL	CLRALR		;flush alarm
	CMPB	#EBCDLE,R1	;start with dle?
	BEQ	14$		;yes - probably ACK, WACK or RVI
	CMPB	#EBCNAK,R1	;NAK?
	BEQ	18$		;yes.
	CMPB	#EBCEOT,R1	;EOT?
	BEQ	19$		;yes.
	CMPB	#EBCENQ,R1	;ENQ?
	BNE	11$		;no - nothing we would expect
	CALL	TENQ		;yes - other side didn't hear us or has aborted
	BR	25$		;...send the data message again

; here if the response to a message is omitted or unrecognizable

11$:	CALL	MSGGTT		;flush remainder of message
				; and wait the three seconds
	CALL	TCRF		;record it
12$:	MOV	#1,R0		;indicate reply with "ENQ"
	SEC			; flag block not acknowledged
	RETURN

; here if timeout

13$:	CALL	KOSHL		;check error status
	BCS	8$
	BIS	#TCNRD,TCST2(R5) ;flag timeout
	BR	11$		;treat as garbage

; here if the first character of the response is "dle".

14$:	CALL	MSGGTC		;get second character
	BCS	11$		;not there, unrecognizable
	CMPB	#EBCWAK,R1	;is response "wack"?
	BEQ	20$		;yes.
	CMPB	#EBCRVI,R1	;no, is it "rvi"?
	BEQ	21$		;yes.
	CMPB	#EBCEOT,R1	;check disconnect command
	BEQ	22$		;yes - set the state
	BIT	#TCAK1,TCST2(R5) ;no, do we want ack-1?
	BEQ	15$		;no.  we want ack-0
	CMPB	#EBCAK1,R1	;yes, is this ack-1?
	BEQ	16$		;yes.
	CMPB	#EBCAK0,R1	;no, ack-0?
	BEQ	17$		;yes.
	BR	11$		;no, unrecognizable.

; here if we are looking for ack-0

15$:	CMPB	#EBCAK0,R1	;is this ack-0?
	BEQ	31$		;yes.
	CMPB	#EBCAK1,R1	;no, ack-1?
	BEQ	32$		;yes
	BR	11$		;no, unrecognizable.

; here when we have received the proper ack

16$:	CALL	TACK1		;record it

30$:	MOV	#TCAK1,R1	;bit to change
	XOR	R1,TCST2(R5)	;complement ack-0/ack-1 bit
	CALL	MSGGTE		;end of message
	BIC	#TCNRD,TCST2(R5) ;we have received a response
	CLC			;indicate success
	RETURN

31$:	CALL	TACK0		;recieved proper ack-0
	BR	30$

; here if we have the wrong ack.  if we have previously had
;  no response, resend the last data message (i.e., treat as nak).
;  otherwise, send an enq.

32$:	CALL	TACK1		;recieved wrong ack-1
	BR	33$

17$:	CALL	TACK0		;record it

33$:	BIT	#TCNRD,TCST2(R5) ;have we timed out before?
	BEQ	11$		;no, send an enq.
	BR	25$

; here if we receive a nak or wrong ack after timeout

18$:	CALL	TNAK		;record it

25$:	CALL	MSGGTE		;end of message
	MOV	TCLCB(R5),R4	;point to lcb
	BIC	#TCNRD,TCST2(R5) ;we have received a response
	TST	LB.MSG(R4)	;check if we have previously received WACK
	BEQ	12$		;yes - this should be ENQ'd as inappropriate
	MOV	#2,R0		;indicate data to be sent again
	SEC			;indicate failure--send msg again
	RETURN

22$:	CALL	RCVDSC		;record intent of other end to disconnect
	CALL	MSGGTE		;terminate msg
	SEC
	RETURN			;fail

; here on receiving eot in response to a message

19$:	CALL	TEOT		;record it
	CALL	MSGGTE		;end of message
	CALL	EOTRSP		;this is special
	SEC			;indicate failure
	RETURN

; here on receiving wack in response to a data message

20$:	CALL	TWACK		;record it
	CALL	MSGGTE		;end of message
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.RTY(R4)	;dont decrement retry count
	CALL	XLCLRM		;clear the message buffer
	BIC	#TCNRD,TCST2(R5) ;we have received a response
	BR	12$		;ask for the ack now

; here if we receive an rvi in response to a data message.
;  since it is complicated to unbuffer and later continue
;  the transmission, we define "unbuffering" as sending
;  all of the data.  thus we can mearly treat rvi as ack.

21$:	CALL	TRVI		;record it
	BR	30$		;treat as ack.

EOTRSP:	MOV	TCLCB(R5),R4	;received EOT in response to data message
	BIT	#LF.SIM,LB.FGS(R4) ;check mode
	BEQ	15$		;termination
	BIS	#TCOAB,TCFG2(R5) ;emulation - this is an abort
	BIS	#TCEOT,TCST2(R5) ;no need to send an eot
	BR	16$

15$:	BIS	#LF.OFL,LB.FGS(R4) ;device went off line

16$:	TRACE	TRCLIN,<(SP),R5,TCST2(R5),TCFG2(R5),LB.FGS(R4)>
	RETURN
	.SBTTL		DQXNAV - 2780/3780...TTD transmission

; subroutine called when data is not available.
;  this will be because either the message stream is complete
;  or because there is more data to come but it is not here yet.

; on return:
;
;	C clear -- message stream complete(EOF),device offline, message to send

;	C set -- message stream incomplete - line failure or output aborted


DQXNAV:	MOV	TCLCB(R5),R4	;point to lcb
	CALL	KOSHL		;check for bad things
	BCC	11$		;no - proceed

10$:	MOV	TCLCB(R5),R4	;point to lcb because callers expect this
	SEC			;yes, indicate transmission incomplete
	RETURN

; here if the transmission has not been aborted.

11$:	BIC	#LS.ERR,(R4)	;clear any previous errors
	TST	TCMSG1(R5)	;is data available yet? [2(773)]
	BNE	15$		;yes, process it. [2(773)]
	BIT	#TCOEF,TCFG2(R5) ;no, is this the end of the stream?
	BEQ	13$		;no, data is just delayed.
	SAVE	LB.OC7(R4)	;protect this statistic
	CALL	DQSEOT		;no, send eot.
	RESTOR	LB.OC7(R4)
	BCS	DQXNAV		;transmitter timeout
	BIS	#TCOEC,TCFG2(R5) ;set "eof completed" bit

8$:	CLC			;flag transmission successful
	RETURN

; here if we got transmitter timeout trying to send the eot.
;  its too bad, but the whole stream must be considered
;  aborted.
; also come here if we got an error sending the ttd
;  or receiving its response.

12$:	CALL	HSETHA		;set h/w abort 3(016)
	CALL	DQABRO		;abort the stream
	SEC			;signal failure
	RETURN

; here if the data is just delayed.  wait 2 seconds.  if there
;  is still no data, send "ttd" and receive its nak,
;  then check again.

13$:	DSCHED	#EBQMSG,#2*JIFSEC ;wait for time to expire
				; or for a message
	TST	TCMSG1(R5)	;is there a message?
	BNE	15$		;yes, go send it.
	BIT	#TCOAB,TCFG2(R5) ;check aborts
	BNE	10$
	MOV	#TTDMSG,R0	;no, send ttd
	MOV	#TTDLEN,R1
	CALL	CTLMSG		;send message
	INC	LB.OC5(R4)	;count ttds sent
	MOV	#3*JIFSEC,LB.ALR(R4);set the alarm
	CLR	R4		;no data yet
	CALL	MSGGTC		;get first char of response
	BCS	30$		;none.
	CMPB	#EBCDLE,R1	;check for DLE-EOT
	BEQ	18$		;maybe
	CMPB	#EBCEOT,R1	;IS IT EOT?
	BEQ	16$		;yes, receiver aborted.
	CMPB	#EBCNAK,R1	;no, is it nak?
	BNE	31$		;no.
	CALL	TNAK		;record it
	CALL	MSGGTE		;yes, end of message
	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.ERC(R4),LB.RTY(R4) ;reset retry counter
	BR	DQXNAV		;send ttd unless abort or eof.

; here if the response to ttd is not "nak" or "eot"

30$:	CALL	KOSHL		;check error status
	BCS	10$
	CALL	TTMO		;no response
	BR	14$

31$:	CALL	TCRF		;invalid response

14$:	CALL	MSGGTT		;end of message and wait
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.OC3(R4)	;count invalid responses to ttd
	DEC	LB.RTY(R4)	;check retries
	BLE	12$		;other end is in trouble
	BR	DQXNAV		;try to send anyway.

; here if there is now a message available.

15$:	CMP	#TTDMSG,LB.CMA(R4);if last control msg was TTD
	BNE	8$
	INC	LB.CMA(R4)	;make it not but leave it recognizable for debugging
	BR	8$		;if somebody else croaks as a result of this that
				; is probably a bug anyhow.

18$:	CALL	MSGGTC		;got d dle...look for d eot
	BCS	30$
	CMPB	#EBCEOT,R1	;got something
	BNE	31$		;strange
	CALL	RCVDSC		;record intent of other end to disconnect
	CALL	MSGGTE		;terminate msg
	BR	10$		; and abort the transmission

; here if we get eot in response to ttd.  the receiver has
;  aborted the transmission.

16$:	CALL	TEOT		;record it

25$:	CALL	MSGGTT		;end of message and wait
	CALL	EOTRSP		;this is special
	BR	10$		;indicate no more to transmit now
	.SBTTL		DQRQIP - 2780/3780...signal input permission requested to 10
; subroutine to request input permission.
;
; on return:
;
; C is set if permission has been refused, clear if granted.

DQRQIP:	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LF.OFL,LB.FGS(R4) ;check if we were previously receiving
	BNE	12$		;yes - grant permission automatically
	BIS	#TCIPR!TCIWR,TCFG2(R5) ;request input permission
				; and note it was req. [2(770)]

	CALL	SACTI		;set device active

	CALL	DQAWXL		;awaken xlate task
	MOV	#<JIFSEC*2>/3,R0 ;wait up to 2/3 sec
11$:	DSCHED	#EBINTR,R0	;for "grant" signal
	BIT	#TCIPG,TCFG2(R5) ;were we given permission?
	BNE	12$		;yes, send ack-0
	MOV	TCTIM(R5),R0	;no, is time up?
	BNE	11$		;no, keep waiting.
	BIC	#TCIPR,TCFG2(R5) ;yes, no longer requesting
	CALL	DQAWXL		;wake up xlate task
	SEC			;indicate permission refused
	RETURN

; here if permission has been granted.

12$:	BIC	#TCIPR,TCFG2(R5) ;no longer requesting
	BIC	#LF.OFL,LB.FGS(R4) ;no longer offline either
	CALL	DQAWXL		;wake up xlate task
	CLC			;indicate permission granted
	RETURN

; subroutine to awaken the translate task

; R4 points to the lcb

DQAWXL:	SIGNAL	LB.TCD(R4),EBINTR ;inform xlate task something is up
	RETURN
	.SBTTL		DQRECV - 2780/3780...receive messages

; subroutine to process input message stream.  called when we
;  receive an enq in control mode.

DQRECV:	CALL	INFLO		;see if too few chunks
	BCC	DQREC1		;no, go accept bid

; here to refuse the bid by sending "nak".

DQSNAK:	MOV	#NAKMSG,R0	;refuse the bid.
	MOV	#NAKLEN,R1
	BIS	#LS.LWR,@TCLCB(R5) ;dont follow with a read
	CALL	CTLMSG
	RETURN

; here if there are enough chunks that we can accept the bid.

DQREC1:	MOV	#AK0MSG,TCCMA(R5) ;accept the bid
	MOV	#AK0LEN,TCCMC(R5)
	BIC	#TCAK1,TCST2(R5) ;next ack will be ack-1

; here to receive the next transmission block

11$:	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.ERC(R4),LB.RTY(R4)

12$:	CALL	KOSHL		;check error status
	BCS	15$
	MOV	TCLCB(R5),R4	;no, point to lcb
	BIC	#LS.ERR,(R4)	;clear any previous errors
	MOV	TCCMA(R5),R0	;any control message to send?
	BEQ	13$		;no, just issue a read
	MOV	TCCMC(R5),R1	;yes, get address and count

35$:	CALL	CTLMSG		;send the msg
	BR	32$

; here if there is no prompting control message.
;  just issue a read.

13$:	CALL	@T.RED(R5)	;read the text block

32$:	CLR	TCCMA(R5)	;don't send control msg twice
	MOV	#<3*JIFSEC>+<JIFSEC/4>,LB.ALR(R4);set the response alarm
	CLR	R4		;no data yet
	CALL	MSGGTC		;get input character
	BCS	14$		;timeout
	CALL	CLRALR		;flush alarm now
	CMPB	#EBCEOT,R1	;end of transmission?
	BNE	33$
	CALL	TEOT		;record it
	JMP	25$		;yes, end of file or abort
33$:	CMPB	#EBCENQ,R1	;NO, "ENQ"?
	BEQ	20$		;yes, give positive response.
	CMPB	#EBCDLE,R1	;no, data link escape?
	BEQ	17$		;yes, read transparent text
	CMPB	#EBCSTX,R1	;no, start of text?
	BEQ	16$		;yes, read normal data
	CMPB	#EBCSOH,R1	;start of header?
	BEQ	16$		;treat the same as stx
	CALL	TCRF		;record cruft
	BR	44$

; here on invalid message or timeout

14$:	CALL	KOSHL		;check error status
	BCS	44$
	CALL	TTMO		;record time out

44$:	CALL	MSGGT2		;end of msg and wait 2 sec from start

	MOV	TCLCB(R5),R4	;point to lcb
	DEC	LB.RTY(R4)	;had enough (20 sec worth?)
	BGT	12$		;no, try again.

36$:	CALL	HSETHA		;yes, set the h/w line abort 3(016)
	BR	23$

; here if the stream has been aborted, probably by the
;  pdp-10.  send eot and return.

15$:	CALL	DQSEOT		;send eot (unless not needed)
	RETURN

; here on stx to process a normal (non-transparent) message

16$:	CALL	BLKMSG		;check for blocked messages
	CALL	DQRNRM		;process the block
	BR	18$		;analyze c bit and r0 value

; here on "dle" to read a transparent data message

17$:	CALL	MSGGTC		;get next char to determine case
	BCS	14$
	CMPB	#EBCSTX,R1	;DLE-STX => transparent data
	BEQ	27$
	CMPB	#EBCSOH,R1	;as does DLE-SOH
	BNE	30$

27$:	CALL	BLKMSG		;check for blocked messages
	CALL	DQRXPM		;read text

; here after reading a text block to respond as
;  indicated by DQRXRM or DQRNRM.

18$:	BCC	19$		;success

; error in message, send nak or eot.

	CALL	DQRNRP		;set up a nak
	BCS	24$		;retry counter exhausted, abort
	BR	12$		;send nak and read data again.

; message read successfully, acknowledge it.

19$:	MOV	#TCAK1,R0	;complement ack-0/ack-1 bit
	XOR	R0,TCST2(R5)
	BIS	#TCIRN,TCFG2(R5) ;flag input running
	BIC	#TCIPG,TCFG2(R5) ;clear "input permission granted"

; here to give positive response: ack-0, ack-1 or wack.

21$:	CALL	DQRPRP		;set up ack-0, ack-1 or wack
	JMP	11$		;send it and wait for next transmission block

; here on enq - repeat last response

20$:	CALL	TENQ		;record this
	BIT	#LS.CTL,@TCLCB(R5);check if last msg was a control msg
	BEQ	39$		;if not, ENQ is not appropriate
	CALL	MSGGTE		;end of input text
	MOV	TCLCB(R5),R4	;get the lcb
	DEC	LB.RTY(R4)	;don't do this forever
	BLE	36$

37$:	MOV	LB.CMA(R4),R0	;other end didn't understand last msg
	CMP	#WAKMSG,R0	;if last response was WACK - check if it still is
	BEQ	21$
	MOV	LB.CMC(R4),R1	;send it again
	JMP	35$

; here if the message after a message ending in etx
;  (which was acked) did not start with eot or enq.

22$:	CALL	MSGGT2		;end of input and wait 2 sec since start

; here if the message after the last message did
;  not start with enq or eot, or on transmitter timeout.

23$:	CALL	DQSEOT		;send eot if necessary

; here to abort the message stream.

24$:	MOV	TCLCB(R5),R4	;point to lcb
	TRACE	TRCLIN,<R5,TCST2(R5)>
	CALL	DQABRI		;flag stream aborted
	BIC	#TCXET,TCST2(R5) ;dont expect eot next
	BR	26$		;clear grant and running flags and return.

; here on receiving "eot".  if the last message did not end
;  with etx this means abort.

25$:	CALL	MSGGTE		;end of message
	CALL	DQREOT		;receive eot
	BCS	24$		;this is an abort

; here to clear grant and running flags and return.

26$:	BIC	#TCIPG!TCIRN,TCFG2(R5) ;clear grant and running flags
	RETURN

; DLE control sequence of some kind

30$:	CMPB	#EBCEOT,R1	;check for disconnect
	BNE	31$
	CALL	RCVDSC		;record intent of other end to disconnect
	CALL	MSGGTE		;terminate msg
	BR	26$

31$:				;DLE-garbage
	BIT	#TCXET,TCST2(R5);check for great expectations of an EOT
	BNE	22$

39$:	CALL	TCRF		;record cruft
	JMP	44$		;nothing else is really valid here so it's either
				;garbage or unxpected...whatever the difference is.

BLKMSG:	BIC	#TCXET,TCST2(R5) ;not expecting an eot at this point
10$:	BIT	#TCIEC,TCFG2(R5) ;check for input eof pending
	BNE	20$		;yes - messages are blocked back to back
	RETURN			;no - begin new message
20$:	DSCHED	#EBINTR		;wait til xlate task wakes us
	BR	10$		;and check again
	.SBTTL		DQRPRP - 2780/3780...positive response to received message
; subroutine to set up a positive response, either ack-0, ack-1
;  or wack.


DQRPRP:	BIT	#TCXET,TCST2(R5) ;last message end in etx?
	BNE	11$		;yes, always send ack.
	CALL	INFLO		;shall we send WACK?
	BCS	12$		;yes, go do it
11$:	BIT	#TCAK1,TCST2(R5) ;yes, send ack-1?
	BEQ	13$		;no, ack-0.
	MOV	#AK1MSG,R0	;yes.
	MOV	#AK1LEN,R1
	BR	14$

; here if there are not many chunks left.  send "wack" to
;  acknowledge the message but start an enq-wack exchange
;  until we have plenty of chunks again.

12$:	MOV	#JIFSEC,R1	;wait  seconds before sending WACK
				;...this was shortened from the normal 2 seconds
				;   to accomodate a marginal DN22.

16$:	DSCHED	#EBINTR,R1
	BIT	#TCIAB,TCFG2(R5);check for abort
	BEQ	15$		;none, continue
	JMP	DQSEOT		;yes, send EOT
15$:	CALL	INFLO		;check conditions now (we may be able to send an ACK)
	BCC	11$		;yup, go send ACK
	MOV	TCTIM(R5),R1	;check if time up
	BGT	16$		;no - don't WACK yet
	MOV	TCLCB(R5),R0	;point to lcb
	INC	LB.IC4(R0)	;count WACK's sent
	MOV	#WAKMSG,R0
	MOV	#WAKLEN,R1
	BR	14$

; here to send ACK-0

13$:	MOV	#AK0MSG,R0
	MOV	#AK0LEN,R1
14$:	MOV	R0,TCCMA(R5)	;store control message address
	MOV	R1,TCCMC(R5)	; and count
	RETURN			;read next block
	.SBTTL		DQRNRP - 2780/3780...negative response to received message
; subroutine to set up a negative response, either NAK
;  or EOT.

; on return:

;	C clear -- set up a NAK

;	C set - retry counter exhausted, abort the stream.

DQRNRP:	MOV	TCLCB(R5),R4	;point to lcb
	DEC	LB.RTY(R4)	;should we send nak again?
	BLE	11$		;no, abort the stream.

10$:	INC	LB.IC3(R4)	;yes, increment nak counter
	MOV	#NAKMSG,TCCMA(R5) ;set up a nak
	MOV	#NAKLEN,TCCMC(R5)
	CLC			;give success return
	RETURN

; here if the retry counter is exhausted.

11$:	CALL	HSETHA		;set the h/w abort 3(016)
	SEC			;flag counter exhausted
	RETURN
	.SBTTL		DQREOT - 2780/3780...receiving process received EOT

; on return:

;	C clear -- we have reached end of file

;	C set -- the EOT aborted the stream.

DQREOT:	MOV	TCLCB(R5),R4	;point r4 to lcb
	BIS	#TCEOT,TCST2(R5) ;no eot needed to abort
	BIT	#TCXET,TCST2(R5) ;are we expecting this eot?
	BEQ	11$		;no, this is an abort.
	BIC	#TCXET,TCST2(R5) ;yes, no longet expecting eot
	BIC	#TCIRN!TCIPG,TCFG2(R5) ;no longer doing input
	DEC	LB.IC6(R4)	;uncount aborts
	CALL	DQAWXL		;awaken xlate task
.IF NE,DB.SEQ
	CALL	PCHKI		;init sequence checker
.ENDC	;.IF NE,DB.SEQ
	CLC			;signal eof
	RETURN

; here if the eot is unexpected.  this is abort.

11$:	BIS	#LF.OFL,LB.FGS(R4) ;sender is offline
	SEC			;signal abort
	RETURN
	.SBTTL		DQRNRM - 2780/3780...read a non-transparent message

; on return:

;	C clear - all ok, reply with ack or wack

;	C set - error in message:
;	  R0 = 1 - send "NAK" or (if too many retries) "EOT"
;	  R0 = 2 - send nothing (let sender time out)

DQRNRM:	KGLOAD	#0		;initialize kg11-a
	BIC	#TCDTA,TCST2(R5) ;no data as yet
	CALL	GETMHD		;get a message header
	BCC	11$		;got one.
	CALL	MSGGT2		;terminate reading and wait 2 sec
	BR	DQRNRE		;give error return.

11$:

; here to get next character of block.

DQRNRC:	CALL	MSGGTC		;get character
	BCS	DQRNTO		;timeout

; here to process the character in r1

DQRNRA:	BIT	#300,R1		;control character?
	BNE	11$		;no.
	MOVB	EBCSPC(R1),R2	;yes, get its code
	MOV	DQRNRD(R2),R2	;get dispatch address
	BEQ	11$		;not a data link control char
	JMP	(R2)		;data link control -- dispatch
				; here if the character is not a data-link control character.

11$:	KGACUM	R1		;accumulate bcc
	BIS	#TCDTA,TCST2(R5) ;we have some real data
	CALL	MSGAPC		;append to output string
	BCS	DQRNRT		;out of chunks
	TST	MSGLEN(R0) 	;is message unreasonably long?
	BGT	DQRNRC		;no, get another character.
	CALL	TCRF		;record crufty data
	BR	DQRNRT

; here if we run out of chunks, get read timeout, or the message gets too long.

DQRNTO:	CALL	KOSHL		;check error status
	BCS	DQRNRT
	CALL	TTMO		;record time out

DQRNRT:	CALL	MSGGT2		;terminate the read and wait 2 sec
	CALL	FREMSG		;send it partial msg to free
DQRNRE:	MOV	#2,R0		;allow timeout to happen

; here to give error exit from dqrnrm.

DQRNRX:	BIC	#TCXET,TCST2(R5) ;not expecting eot next
	SEC			;signal failure
	RETURN

; dispatch table for data link control characters

DQRNRD:	.WORD	0		;CODE 0 = miscellaneous
	.WORD	DQRNRC		;CODE 2 = SYN
	.WORD	12$		;CODE 4 = ETB
	.WORD	11$		;CODE 6 = ETX
	.WORD	14$		;CODE 10 = IUS
	.WORD	0		;CODE 12 = IRS
	.WORD	18$		;CODE 14 = ENQ
	.WORD	0		;CODE 16 = DLE
; here on receiving an ETX.  this is the last message in the stream.

11$:	BIS	#TCXET,TCST2(R5) ;flag last message

; here on receiving etb or, from above, etx.  this is the
;  last block in the message.  on the ibm 2780 etx and etb provide
;  the irs function.

12$:	KGACUM	R1		;accumulate bcc
	CALL	DQRBCC		;check bcc
	BCS	DQRNTO		;timeout
	BIT	#TCOBS,TCFG1(R5) ;old bsc protocol?
	BEQ	13$		;no, irs already in data
	MOV	#EBCIRS,R1	;yes, include an explicit irs
	CALL	MSGAPC		; to simplify xlate
	BCS	DQRNRT		;out of chunks
13$:	CALL	DQRNDM		;do the end processing
	BCS	17$		;bad bcc
	BIT	#TCXET,TCST2(R5) ;check for etx seen
	BEQ	20$
	BIS	#TCIEC,TCFG2(R5) ;yes - set eof
20$:	RETURN

; here on receiving an IUS.  on the ibm 2780 this also
;  provides the IRS function.  in any case it is
;  followed by two characters of bcc.

14$:	KGACUM	R1		;include ius in bcc
	CALL	DQRBCC		;include next two chars in bcc
	BCS	DQRNTO		;timeout
	KGTEST			;is bcc right?
	BNE	16$		;no.
	BIT	#TCOBS,TCFG1(R5) ;yes, using old bsc?
	BEQ	15$		;no, no irs function.
	MOVB	#EBCIRS,R1	;yes, include an irs
	CALL	MSGAPC		; to simplify xlate.
	BCS	DQRNRT		;out of chunks.

; here to absorb the optional syn's and stx that
;  may appear between blocks.

15$:	CALL	MSGGTC		;get next character (after bcc)
	BCS	DQRNTO		;timeout
	CMPB	#EBCSYN,R1	;skip syncs
	BEQ	15$
	CMPB	#EBCSTX,R1	;is this stx?
	BNE	DQRNRA		;no, include in data
	KGACUM	R1		;yes, include in bcc
	JMP	DQRNRC		;but not in data

; here if the bcc proves to be bad.

16$:	CALL	MSGGT2		;terminate read and wait 2 sec
17$:	CALL	FREMSG		;send it the bad msg to be freed
	CALL	TBCC		;record bad BCC
	MOV	#1,R0		;give "nak" reply
	BR	DQRNRX		;give error return.

; here if we find an enq in the data.  this is probably a ttd
;  or forward abort.  in either case, send a nak.

18$:	BIT	#TCDTA,TCST2(R5) ;have we had any real data?
	BNE	19$		;yes, this is forward abort.
	CALL	MSGGTE		;no, end of input.
	CALL	FREMSG		;send it message to free
	CALL	TTTD		;record it
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.RTY(R4)	;dont count this nak towards
				; retry threshold
	DEC	LB.IC3(R4)	;or in statistics
	MOV	#1,R0		;indicate send nak
	JMP	DQRNRX		;give error return

; here if the enq is a forward abort rather than part of a ttd.

19$:	CALL	MSGGT2		;end of input and wait 2 sec
	CALL	FREMSG		;flush the msg
	MOV	#1,R0		;indicate send nak
	JMP	DQRNRX		;will probably get aborting eot

DQRNDM:	CALL	MSGGTE		;end of message processing
	KGTEST			;did bcc come out zero?
	BNE	10$		;no, there is a bcc error.
	CALL	KOSHL		;check error status
	BCS	10$		;if we can't ack the message, don't queue it

	MOV	TCLCB(R5),R4	;yes, point to lcb
.IF NE,DB.SEQ
	CALL	PCHK		;call sequence checker
.ENDC	;.IF NE,DB.SEQ
	INC	LB.IC1(R4)	;count a block received successfully
	MOV	LB.TCD(R4),R1	;point to translate task
	INC	TCIMC(R1)	;count this message
	SAVE	R0
	CALL	CNTMSG		;find number of chunks in message
	ADD	R0,LB.RES(R4)	;reserve this many for xlate
	RESTOR	R0
	CALL	QUEMSG		; send it the block
	CLC			;flag success 
	RETURN
10$:	SEC
	RETURN

.IF NE,DB.SEQ

;PCHK - force all input files to have sequentially numbered records
;	used to detect protocol bugs at the lowest level
;	assumes lines begin with a 4 digit line number beginning at 0000
;
;	R0/message to queued to xlate task

PCHK:	SAVE	<R0,R1,R2,R3,R4>
	CALL	FMSGI
	MOV	MSGPTR(R0),R1
	MOV	CHLEN(R0),R2

10$:	CALL	LSCAN		;scan for beg of this line
	BCS	20$		;end of message
	CALL	LCHK		;check this line
	BCC	10$
20$:	RESTOR	<R4,R3,R2,R1,R0>
	RETURN

LCHK:	MOV	#4,R3
	CLR	LCHKN

10$:	CALL	PNXTCH		;get next digit
	BCC	15$
	RETURN
15$:	SUB	#360,R4
	MOV	R4,-(SP)
	MOV	LCHKN,R4	;get current accumulated number
	ASL	R4
	ADD	R4,(SP)
	ASL	R4
	ASL	R4
	ADD	(SP)+,R4
	MOV	R4,LCHKN	;the new accumulated number
	SOB	R3,10$
	SUB	LCHKP,R4	;done - check sequentiality
	DEC	R4
	BNE	20$		;loser
	MOV	LCHKN,LCHKP	;new previous line number
	CLC
	RETURN

20$:	STOPCD	BUG
LSEQER:	RETURN

LCHKP:	0			;previous line number
LCHKN:	0			;current accumulator

PCHKI:	MOV	#-1,LCHKP	;init line number sequence checking
	CLR	LCHKN
	RETURN

PNXTCH:	DEC	R2		;R1/ptr,R2/byte cnt
	BLE	10$
	CLR	R4
	BISB	(R1)+,R4
	CLC
	RETURN

10$:	MOV	(R0),R0
	BNE	20$
	SEC
	RETURN

20$:	MOV	R0,R1
	TST	(R1)+
	MOV	(R1)+,R2
	BR	PNXTCH


LSCAN:	CALL	PNXTCH		;find next line beginning
	BCS	25$
	CMPB	R4,#113		;scan for .
	BNE	26$
	CLC
25$:	RETURN

26$:	CMPB	R4,#EBCESC
	BNE	LSCAN
	CALL	PNXTCH		;gobble carriage control
	BCC	LSCAN
	RETURN

.ENDC	;.IF NE,DB.SEQ
	.SBTTL		DQRXPM - 2780/3780...read a transparent message

;  the DLE has already been read.
;	R1/character following DLE (should be STX or SOH)

; on return:

;	C clear - all ok, reply ACK or WACK

;	C set - failure:
;	  R0 = 1 - send NAK or (if retry counted to zero) ENQ
;	  R0 = 2 - send nothing (let sender time out)

DQRXPM:	KGLOAD	#0		;initialize kg11-a
	CMPB	#EBCSOH,R1	;[1007]is it soh?
	BEQ	11$		;[1007]yes, do as though an stx.
	CMPB	#EBCSTX,R1	;is it stx?
	BEQ	11$		;yes.
	CALL	TCRF		;record cruft
	CALL	MSGGT2		;no, terminate read, wait 2 sec
	BR	DQRXPE		; and ignore message

; here to begin reading a record.

11$:	CALL	GETMHD		;get a message header
	BCC	12$		;got one
	CALL	MSGGT2		;terminate reading and wait 2 sec
	BR	DQRXPE		;give error return.

12$:	BIS	#MSGTSP,MSGFGS(R0) ;flag message as transparent
	KGLOAD	#0		;initialize kg11-a

DQRXPC:	CALL	MSGGTC		;get character from block
	BCS	DQRXTO		;timeout
	CMPB	#EBCDLE,R1	;is it dle?
	BEQ	DQRXPB		;yes.

; here on a non-dle character or on a dle following a dle.
;  append the character to the message being built.

DQRXPG:	KGACUM	R1		;no, accumulate in bcc
	CALL	MSGAPC		;build message for translator
	BCC	DQRXPC		;ok - get next character.
	JMP	DQRXPT		;ugh, terminate the message.

; here on dle character except a dle following a dle

DQRXPB:	CALL	MSGGTC		;get next character (after dle)
	BCS	DQRXTO		;timeout
	BIT	#300,R1		;control character?
	BNE	11$		;no, invalid.
	MOVB	EBCSPC(R1),R2	;yes, get its code
	MOV	DQRXPD(R2),R2	;get dispatch address
	BEQ	11$		;not a valid character in this context
	JMP	(R2)		;dispatch to char handler

; here on invalid character after dle.

11$:	CALL	MSGGT2		;terminate reading and wait 2 sec
	CALL	FREMSG		;flush the garbage
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.IC8(R4)	;count invalid chars after dle
	MOV	#1,R0		;respond with nak
	SEC			;signal failure
	RETURN

; here if we must ignore the message because of chunk depletion
;  or receive timeout.

DQRXTO:	CALL	KOSHL		;check error status
	BCS	DQRXPT
	CALL	TTMO		;record time out

DQRXPT:	CALL	MSGGT2		;terminate reading and wait 2 sec
	CALL	FREMSG		;flush the garbage
DQRXPE:	MOV	#2,R0		;indicate no response

; here to give the error return from DQRXPM

DQRXPX:	BIC	#TCXET,TCST2(R5) ;not expecting eot next
	SEC			;flag failure
	RETURN
; dispatch table for special characters after DLE

DQRXPD:	.WORD	0		;CODE 0 = miscellaneous
	.WORD	DQRXPC		;CODE 2 = SYN
	.WORD	12$		;CODE 4 = ETB
	.WORD	11$		;CODE 6 = ETX
	.WORD	13$		;CODE 10 = IUS
	.WORD	0		;CODE 12 = IRS
	.WORD	0		;CODE 14 = ENQ
	.WORD	DQRXPG		;CODE 16 = DLE

; here on DLE ETX.  this is the last message of the stream.

11$:	BIS	#TCXET,TCST2(R5) ;expect eot next

; here on dle etb and (from above) dle etx.  this is the last
;  record in the message.

12$:	KGACUM	R1		;accumulate bcc
	CALL	DQRBCC		;accumulate next two chars, too
	BCS	DQRXPT		;timeout
	CALL	DQRNDM		;do the end processing
	BCS	16$		;bad bcc
	BIT	#TCXET,TCST2(R5) ;check for etx seen
	BEQ	20$
	BIS	#TCIEC,TCFG2(R5) ;yes - set eof
20$:	RETURN
; here on DLE IUS.  this signals that a BCC will follow.
;  on the IBM 2780 it also performs the IRS function.

13$:	KGACUM	R1		;accumulate bcc
	CALL	DQRBCC		;accumulate next two chars, too
	BCS	DQRXPT		;timeout
	KGTEST			;is bcc ok?
	BNE	15$		;no.

; here to absorb the optional syncs between records.

14$:	CALL	MSGGTC		;get next character
	BCS	17$		;timeout
	CMPB	#EBCSYN,R1	;sync?
	BEQ	14$		;yes, ignore them.
	CMPB	#EBCDLE,R1	;no, dle?
	BNE	17$		;no, invalid continuation.
	CALL	MSGGTC		;yes, get next character
	BCS	17$		;timeout
	CMPB	#EBCSYN,R1	;syn? (dle syn)
	BEQ	14$		;yes, ignore it.
	CMPB	#EBCSTX,R1	;no, stx?
	BNE	17$		;no, error: stx mandatory
	KGACUM	#EBCDLE		;yes, load "dle" into bcc
	KGACUM	R1		;include stx in bcc
	JMP	DQRXPC		;but not in data

; here on bcc error.

15$:	CALL	MSGGT2		;terminate reading and wait 2 sec
16$:	CALL	FREMSG		;flush the garbage
	CALL	TBCC		;record bad BCC
	MOV	#1,R0		;reply with a nak (or eot)
	BR	DQRXPX		;give error return.

; here on invalid character sequence between blocks,timeouts and aborts

17$:	CALL	MSGGT2		;terminate reading and wait 2 sec
	CALL	FREMSG		;flush the garbage
	MOV	TCLCB(R5),R4	;point to lcb
	CALL	KOSHL		;check error status
	BCS	25$
	INC	LB.IC9(R4)	;count invalid sequences
25$:	JMP	DQRXPE		;give error return.
	.SBTTL		DQRBCC - read BCC

; subroutine to accumulate the next two characters of the
;  message into the BCC

;	R3 = chars gotten from this chunk already
;	R4 = pointer to current chunk (initially 0)

; on return:

;	C clear means all ok

;	C set means timeout

;	the crc accumulation register will be 0 only if the crc checks

DQRBCC:
.IF NE,DEBUG
	KGSAVE	-(SP)		;save current bcc accumulator
	CLR	-(SP)		;sapce for the received bcc
.ENDC ;.IF NE,DEBUG
	CALL	MSGGTC		;get next character
	BCS	11$		;timeout
	KGACUM	R1		;accumulate in bcc
.IF NE,DEBUG
	MOVB	R1,(SP)
.ENDC ;.IF NE,DEBUG
	CALL	MSGGTC		;get second character
	BCS	11$		;timeout
	KGACUM	R1		;accumulate in bcc
.IF NE,DEBUG
	MOVB	R1,1(SP)
;trace caller,bsc task,calculated BCC,received BCC

	TRACE	TRCBCC,<4(SP),R5,6(SP),6(SP)>
	CMP	(SP)+,(SP)+	;check if ok
	BEQ	10$
	BIT	#TRCBCC,TRCBTS	;stop if we are interested in bcc's
	BEQ	10$
	STOPCD	BCE
.IFTF
10$:	CLC			;flag success
.IFT
	RETURN
.ENDC ;.IF NE,DEBUG
11$:
.IF NE,DEBUG
	TST	(SP)+
	TST	(SP)+
	SEC
.ENDC ;.IF NE,DEBUG
	RETURN
	.SBTTL		CTLMSG - send a control message and start reading response.  

;  R0 points to the text of the message
;  R1 contains the length of the message proper, pads must be counted in
;  R5 points to the tcb

;  LS.LWR is set if no response is expected.

; on return:
;
;	R4/lcb ptr
;	C is clear if the message went, set if we timed out
;	  or had an error.

CTLMSG:	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LS.ENB,(R4)	;just for the hell of it
	BEQ	69$		;whadayano!
	ADD	LB.TRL(R4),R1	;add count of trailing pads(driver dependent)
	MOV	R1,LB.ALR(R4)	;allow 1 tick per character
	ADD	LB.CSD(R4),LB.ALR(R4) ;plus clear-to-send delay
	PIOFF	#BR4		;protect line driver from scheduler til all setup
	CALL	@T.CTL(R5)	;send the message
				;DQCNTL cannot fail
	BIT	#LS.LWR,(R4)	;should we expect a response?
	BNE	11$		;no.
	CALL	@T.RED(R5)	;yes, set up to read response.
	BCS	14$		;couldn't get chunks
11$:	PION
	DSCHED	#EBINTR!EBALR
	BIT	#LS.ERR,(R4)	;check for transmitter hardware error
	BNE	12$		;yes - take error path
	BIT	#EBINTR,TCWKEV(R5) ;did transmitter finish in time?
	BNE	15$		;yes

; here when the transmitter timed out.  stop it and
;  indicate error.

12$:	TRACE	TRCLIN,<(SP),R5,TCWKEV(R5),(R4)>
	BIT	#LS.ERR,(R4)	;check for hard error wakeup
	BNE	16$
	INC	LB.TTO(R4)	;count timeouts

16$:	CALL	@T.KIL(R5)	;stop the transmitter [1(637)]
	BIC	#LS.ERR,(R4) 	;clear error bit
	BIT	#LS.LWR,(R4)	;did we kill a read also?
	BEQ	13$		;no
	CALL	@T.RED(R5)	;yes - start it again

13$:	DSCHED	,#10.		;wait awhile to skew timeouts since the caller
				; will think everything is ok
69$:	CALL	15$		;return error here for the few cases where the
	SEC			;caller must be sure that the control message suc'd
	RETURN

15$:	BIC	#LS.LWR,(R4)	;clear "last" bit
	CALL	CLRALR		;flush alarm now
	CLC			;yes, indicate success
	RETURN

14$:	PION
	TRACE	TRCLIN,<(SP),R5,TCWKEV(R5),(R4)>
	BR	15$
	.SBTTL		STOBCC - append BCC to message

; subroutine to store into a message the BCC value accumulated in the KG11 so far.

; on return:

;	C clear - BCC stored, KG11-a BCC register zero.

;	C set - out of chunks.


STOBCC:	KGSAVE	-(SP)		;get current bcc
	MOVB	(SP),R1		;get first byte
	KGACUM	R1		;accumulate in bcc
	CALL	MSGAPC		;append to string
	BCS	12$		;out of chunks
	MOVB	1(SP),R1	;get second byte of bcc
	KGACUM	R1		;accumulate in bcc
	CALL	MSGAPC		;append to string
	BCS	12$		;out of chunks
.IF NE,FT.CHK
	KGTEST			;is total bcc now zero?
	BEQ	11$		;yes.
	STOPCD	BCE		;no, bcc accumulation error.
11$:
.ENDC ;.IF NE,FT.CHK
	MOV	(SP)+,R1	;delete bcc from stack
	TRACE	TRCBCC,<R5,R0,R1>;trace bsc task,message,calculated bcc
	CLC			;signal ok
	RETURN

; here if we run out of chunks

12$:	CALL	FREMSG		;flush the garbage
	MOV	(SP)+,R1	;delete bcc from stack
	SEC			;signal error
	RETURN
	.SBTTL		DQABRO - 2780/3780...abort output

; subroutines to abort the message stream due to the device
;  at the other end of the line.  for example, running out
;  of retries will abort the stream.

;  to simplify the coding of the bsc routines, these subroutines
;  can be called several times for the same abort -- subsequent
;  calls for a message stream are no-ops.

; subroutine to abort an output stream

DQABRO:	TRACE	TRCABO,<(SP),R5,R1> ;trace abort call
.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT	;are we asked to stop on abort?
	BEQ	11$		;no.
	STOPCD	DBG		;yes, debug stop.
11$:
.ENDC ;.IF NE,DEBUG
	MOV	TCLCB(R5),R4	;no, point to lcb
	MOV	LB.TC1(R4),R1	;point to bsc tcb
	BIS	#TCOAB,TCFG2(R1) ;signal abort
	MOV	LB.TCD(R4),R1	;point to translation task
	BIS	#TCOAB,TCFG2(R1) ;signal abort, too.
	CALL	SACTO		;set the device active
	RETURN
	.SBTTL		DQABRI - 2780/3780...abort input

DQABRI:	TRACE	TRCABO,<(SP),R5,R1> ;trace abort call
.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT	;are we asked to stop on abort?
	BEQ	11$		;no.
	STOPCD	DBG		;yes, debug stop.
11$:
.ENDC ;.IF NE,DEBUG
	MOV	TCLCB(R5),R4	;no, point to lcb
	MOV	LB.TC1(R4),R1	;point to bsc tcb
	BIS	#TCIAB,TCFG2(R1) ;signal abort
	MOV	LB.TCD(R4),R1	;point to translation task
	BIS	#TCIAB,TCFG2(R1) ;signal abort, too.
	CALL	SACTI		;set device active for input
	RETURN
	.SBTTL		ABTLIN - abort all io on line
ABTLIN:	MOV	TCLCB(R5),R4	;abort all io on line
.IF NE,FT.HSP
	CMP	#TTHASP,LB.DVT(R4) ;check for HASP
	BNE	10$		;2780/3780
	CALL	HSABTO		;abort HASP output devices
	CALL	HSABTI		;abort HASP input devices
	RETURN
.ENDC	;.IF NE,FT.HSP

10$:	CALL	DQABRO		;abort 2780/3780 output
	CALL	DQABRI		;abort 2780/3780 input
	RETURN
	.SBTTL		DQSEOT - 2780/3780...send EOT to abort or EOF

;  the device at the other end to control state.  this
;  is used to abort the stream and after receiving
;  acknowledgment of the last message in an output stream.
;
; to simplify the coding of the error routines this
;  subroutine may be called redundently.  extra calls for a
;  particular message stream are ignored.
;
; on return:
;
;	C is set if the message failed because of error or
;	  transmitter timeout, clear if the message was sent
;	  ok or if no message needed to be sent.
;
;	all registers but R5 are destroyed.

DQSEOT:	BIT	#TCEOT,TCST2(R5) ;do we need an eot to clear the line?
	BNE	11$		;no, one is enough.
	MOV	#EOTMSG,R0	;send an eot
	MOV	#EOTLEN,R1
	BIS	#LS.LWR,@TCLCB(R5) ;last message of the stream
	CALL	CTLMSG
	BCS	10$		;failed to send it
	BIS	#TCEOT,TCST2(R5) ;suc'd, only one required per stream
	INC	LB.OC7(R4)	;count aborting eot's sent
10$:	RETURN

; here if there is no need to send a message

11$:	CLC			;indicate success
	RETURN

DQSDIS:	MOV	#DISMSG,R0	;send disconnect sequence
	MOV	#DISLEN,R1
	BIS	#LS.LWR,@TCLCB(R5) ;last message of the stream
	CALL	CTLMSG
	RETURN

; this subroutine check s for input and output aborts
; and flushes all messages queued to the bsc task

HSCKAB:				;r4/lcb
	CALL	HSWALX		;wake up all xlate tasks
	CLR	TCDTB(R5)	;initialize device for abort
11$:	INC	TCDTB(R5)	;start with console and inc
	CMP	TCDTB(R5),LB.NTC(R4) ;done with all devices
	BHI	12$		;yes, exit
	MOV	TCDTB(R5),R1	;need device # in r1
	CALL	HSCKDO		;do abort processing
				;r0/device xlate tcb
	BR	11$		; for all devices
12$:	CLC			;indicate success
	RETURN
	.SBTTL		HSPLIN - HASP...multileaving protocol functions

.IF NE,FT.HSP

; the following code (from here to end of this module) 
; is used only if line is in hasp-mode.
;
; here if the line is found to be in hasp mode. 

HSPLIN:	MOV	TCLCB(R5),R4	;get lcb ptr
	MOV	#JIFSEC,LB.ALR(R4) ;for acking once in 2 secs
	BIT	#TCOPG,TCFG2(R5) ;is bid complete?
	BEQ	11$		;no.
	BIC	#LS.ERR,(R4)	;clear any previous errors
	BIT	#TCDIDO,TCBSCF(R5) ;were we xmitting last?
	BNE	13$		;yes, prepare to receive now
	BR	19$		;no, go xmit 

; here when bid is not complete.

11$:	CALL	HSCKAB		;check for aborts
	BIT	#TCOPR,TCFG2(R5) ;see if requested bid?
	BNE	16$		;yes, try bidding SOH-ENQ
	CALL	@T.RED(R5)	;see if other side is bidding
	CLR 	R4		;no data as yet
	CALL	MSGGTC		;get character from msg read
	BCS	15$		;none
12$:	CMPB	#EBCDLE,R1	;check for transparent bid
	BNE	9$
	CALL	MSGGTC		;maybe - check for ENQ following
	BCS	15$
	CMPB	#EBCEOT,R1	;check for disconnect
	BNE	10$		;nope

8$:	CALL	RCVDSC		;record intent of other end to disconnect
	CALL	MSGGTE		;terminate msg
	BR	14$

9$:	CMPB	#EBCSOH,R1	;recvd soh?
	BNE	15$		;no, unrecognized response
	CALL	MSGGTC		;yes,get next char
	BCS	15$		;none

10$:	CMPB	#EBCENQ,R1	;enq following soh or dle ?
	BNE	15$		;no, unrecognized response
	CALL	TENQ		;record this
	CALL	HSETCE		;communications established
	CALL	HSINIR		;yes, initialize message headers
	BCS	14$		;trouble transmitting ACK0

; here SOH-ENQ sequence has been received. an ACK0 has been sent.
; get ready to receive response

13$:	CALL	HSRECV		;go receive data
14$:	JMP	LINCTL		;when done check again

15$:	CALL	MSGGTT		;end message and wait the second
	BR	20$		;wait and wake up all xlate tasks

; here when we have data to send , bid for the line

16$:	MOV	LB.EQN(R4),LB.RTY(R4) ;no. of tries to get the line
18$:	MOV	#BIDMSG,R0	;send soh-enq bid sequence
	MOV	#BIDLEN,R1	;length of the bid sequence
	CALL	CTLMSG		;send as control msg
	MOV	LB.EQW(R4),LB.ALR(R4) ;time to wait for reply
	CLR	R4		;no data yet
	CALL	MSGGTC		;get char from recver
	BCS	21$		;nothing recvd
	CMPB	#EBCDLE,R1	;is it dle?
	BNE	9$		;no, check for soh-enq sequence
	CALL	MSGGTC		;get next char
	BCS	21$		;none
	CALL	CLRALR		;flush alarm now
	CMPB	#EBCEOT,R1	;disconnect ?
	BEQ	8$		;yes
	CMPB	#EBCAK0,R1	;is it ack0 after dle?
	BNE	21$		;no, unrecognized msg
	CALL	TACK0		;yes - record it
	CALL	MSGGTE		;clear the receiver
	CALL	HSETCE		;communications established
	BIC	#TCDIDO,TCBSCF(R5) ;operation was receive

; here we have received acknowledgement for the bid
; the line is marked as bid complete and set to send messages
; after awakening allthe xlate device tasks

	CALL	HSINIT		;initialize bcb,fcs and mark line bid
19$:	MOV	TCLCB(R5),R4	;point to lcb
	CALL	HSWALX		;awaken all translate tasks
	CALL	HPXMIT		;go transmit signon block
20$:	MOV	TCLCB(R5),R4	;point to lcb
	CALL	HSWALX		;awaken all translate tasks
	JMP	LINCTL

; here when the response to bid is unrecognizable - finish waiting if
; necessary and bid again.

21$:	CALL	MSGGTT		;empty the receiver and wait
	MOV	TCLCB(R5),R4	;point to lcb
	CALL	KOSHL		;check error status
	BCS	25$
	INC	LB.OC8(R4)	;record unrecognizable bid response
	BIT	#TCOPR,TCFG2(R5) ;still want to bid for the line?
	BEQ	20$		;no.
22$:	DEC	LB.RTY(R4)	;yes, have we tried often enough?
	BNE	18$		;no, try again
25$:	BIC	#TCOPR,TCFG2(R5) ;yes, no longer bidding
	BR	20$		;awaken all xlate tasks

; this subroutine initializes bcb and fcs bytes besides clearing the receiver
; and marking line as bid complete.

HSINIT:	BIC	#TCOPR,TCFG2(R5) ;no longer bidding
	BIS	#TCOPG,TCFG2(R5) ;bid complete
	CLR	TCSDM(R5)	;initialize dev ptr
	CLR	TCDPG(R5)	;permission cell
	CLR	TCRQPT(R5)	;for sending req to hasp
	MOV	#200,TCTBCB(R5)	;initialize transmit block count
	MOV	#200,TCXBCB(R5)	;initialize receive block count
	MOV	#104301,TCTFCS(R5) ;initialize transmit fcs
	MOV	#104301,TCPFCS(R5) ;and prev fcs too
	BIS	#TCHGST,TCST2(R5) ;note that status is changed
	CLC			;indicate success
	RETURN

; this subroutine sends an ack0 and initializes BCB and FCS bytes

HSINIR:	CALL	MSGGTE		;clear the receiver
	MOV	#AK0MSG,R0	;set up to send ack0
	MOV	#AK0LEN,R1
	CALL	CTLMSG		;send the conrol message
	BIS	#TCDIDO,TCBSCF(R5) ;last operation was xmit
	CALL	HSINIT		;initilize bcb and fcs
11$:	RETURN
	.SBTTL		HSRECV - HASP...receive messages

HSRECV:	CALL	INFLO		;check on line flow control thresholds
	BR	HSPXM5		;yes - go try to send something
	.SBTTL		HPXMIT - HASP...send messages or ACK0 if idle

HPXMIT:	CALL	HSCMDS		;data set ready?
	BCS	HSPXAB		;no, abort output
	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LS.ENB,(R4)	;line disabled?
	BEQ	HSPXAB		;yes....gone
	CLR	TCCMA(R5)	;so we dont send it again
	MOV	LB.ERC(R4),LB.RTY(R4) ;retry count is 15.
	BIC	#LS.ERR,(R4)	;clear any previous errors
	CALL	HSGTMS		;get message to xmit (if any)
	TST	LB.MSG(R4)	;did we get a message
	BNE	HSPXM1		;yes, start sending

HSPXM4:	MOV	#AK0MSG,R0	;no, set up to send an ak0
	MOV	#AK0LEN,R1	;length of ack0 msg
	CALL	CTLMSG		;send the ack0
	BIS	#TCDIDO,TCBSCF(R5) ;just did output
	BR	HSRECV		;start receiving now

; here with a message to be sent in LB.MSG

HSPXM1:	MOV	TCLCB(R5),R4	;point to lcb for re-entry
	MOV	LB.MSG(R4),R0	;point to message
	BEQ	HSPXM4		;send ack0 if no message
	MOV	MSGLEN(R0),LB.ALR(R4) ;no more than one jiffie per char
	ADD	LB.CSD(R4),LB.ALR(R4) ;plus clear-to-send delay
	CALL	@T.WRT(R5)	;start sending message
	BCS	HSPXAB		;only fails for line disable or abort set

	BIS	#TCSTMS!TCDIDO,TCBSCF(R5) ;a message was sent, expect ack
	CALL	@T.RED(R5)	;setup to read response
	DSCHED	#EBALR!EBINTR	;wait for msg to go
	BIT	#LS.ERR,(R4)	;check for hard error wakeup
	BNE	14$
	BIT	#EBINTR,TCWKEV(R5) ;timed out?
	BNE	HSRECV		;no, got an interrupt.

14$:	CALL	@T.KIL(R5)	;stop the transmitter [1(637)]
	INC	LB.TTO(R4)	;count transmitter timeouts
	BIC	#LS.ERR,(R4) 	;clear error bit
	CALL	@T.RED(R5)	;reissue the read

	DSCHED	,#10.		;displace timeouts...in case transmitter quit
				;early in message
	BR	HSRECV		;and let the protocol handle the recovery

; here to terminate the message stream because
; the 10 requested termination, because of transmitter 
;  error or timeout or because the retry counter ran out.

HSPXAB:	CALL	HSETHA		;set h/w abort 3(015)
	MOV	TCLCB(R5),R4	;point to lcb
	CALL	@T.KIL(R5)	;kill all dq/dup action
	CALL	CLRALR		;make sure alarm is flushed
	CALL	HSABTO		;flag output aborted.
	CALL	HSRLOM		;release all out going messages
	CALL	HSABTI		;inputs also
	CALL	HSRMRL		;release messages
	RETURN
; here if the transmission of the data message was successful.
; here to receive data or response from hasp

HSPXM5:
	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.ERC(R4),LB.RTY(R4)

HSPXM2:	CALL	HSCMDS		;dsr on?
	BCS	HSPXAB		;no, abort input
	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LS.ENB,(R4)	;line disabled?
	BEQ	HSPXAB		;yes, abort operation
	BIC	#LS.ERR,(R4)	;clear any previous errors
	CALL	HSARSP		;read and analyze response
	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LF.HWA,LB.FGS(R4) ;h/w abort ? 3(015)
	BNE	20$		;yes, abort the streams 3(015)
				;no 3(015)
	ASL	R0		;no, for word pointer
11$:	MOV	12$(R0),R2	;get adr of response routine
	JMP	(R2)		;jump to the routine

; table of addresses of response routines

12$:	.WORD	13$		;R0=0, received an ACK0
	.WORD	34$		;R0=1, received good data
	.WORD	16$		;R0=2, received NAK
	.WORD	18$		;R0=3, BCC error in receive data
	.WORD	17$		;R0=4, unrecognized data
	.WORD	23$		;R0=5, BCB error in received data
	.WORD	21$		;R0=6, BCB error in xmit reported by hasp
	.WORD	20$		;R0=7, SOH-ENQ(BID) received - abort line
	.WORD	40$		;R0=8., failed to get chunks while building msg



; here when an ack0 is received

13$:	BIT	#FCSUNV,TCRFCS(R5)
	BEQ	14$
	TRACE	TRCFLO,<(SP),R5,TCRFCS(R5)>
14$:	BIC	#FCSUNV,TCRFCS(R5);ACK0 => clear universal suspend
	BIC	#TCDSP,TCFG2(R5)
	BIT	#TCSTMS,TCBSCF(R5) ;was a message sent?
	BEQ	15$		;no, we must have sent an ack0
	CALL	HSMSAK		;yes, release message
	JMP	HPXMIT		;attempt to send another message without waitng

; here when line is idling, i,e recvd ack0 for ack0
; or when a wait to do after receive of data

15$:	DSCHED	#EBINTR!EBQCHK!EBQMSG,#JIFSEC ;wait for something to happen
	JMP	HPXMIT		;and think about it

; here when a message has been received correctly.

34$:	BIT	#20,TCRBCB(R5)	;was bcb for bypass?
	BNE	36$		;yes.
	BIT	#40,TCRBCB(R5)	;was it reset bcb?
	BNE	36$		;yes, note it was set to receive count in HSARSP
	TST	TCERB(R5)	;error in received bcb?
	BNE	37$		;yes, bypass inc of expected
	INC	TCXBCB(R5)	;expect this bcb for next
	BR	36$		;and use block as is
37$:	SAVE	R1		;check for duplicate block
	MOV	TCERB(R5),R1	;get error BCB
	INC	R1
	BIC	#20,R1		;clear possible overflow
	CMPB	TCXBCB(R5),R1	;was it ?
	BNE	38$		;no - continue with error
	CLR	TCERB(R5)	;yes - not an error
38$:	RESTOR	R1
36$:	BIC	#160,TCXBCB(R5)	;make it modulo 16
	BIT	#TCSTMS,TCBSCF(R5);was a message sent ?
	BEQ	35$		;no
	CALL	HSMSAK		;yes - release the message
35$:	JMP	HPXMIT		;attempt to send another message without waitng


; here when a nak is received

16$:
26$:	DEC	LB.RTY(R4)	;decrement retry count
	BGT	27$
	JMP	HSPXAB		;tried enough, abort output
27$:	JMP	HSPXM1		;send data again

; here when unrecognized data received.

17$:	CALL	TCRF		;record invalid reply
	BR	19$		;retry before giving up

; here when message received with bad bcc

18$:	CALL	HSRMRL		;release messages formed
19$:	MOV	TCLCB(R5),R4	;point to lcb
	DEC	LB.RTY(R4)	;tried enough times?
	BLE	20$		;yes, abort input

40$:	MOV	#NAKMSG,TCCMA(R5) ;set up nak reply
	MOV	#NAKLEN,TCCMC(R5) ;length of message
	JMP	HSPXM2		;try reading again
20$:	
.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT
	BEQ	69$
	STOPCD	DBG
69$:
.ENDC	;.IF NE,DEBUG
	INC	LB.IC6(R4)	;count aborts
	JMP	HSPXAB		;flag streams aborted

; here when a bcb error has been reported by hasp

21$:	INC	LB.OC3(R4)	;count bcb errors on xmit
	BR	26$		;treat the bcb error as nak

23$:	BR	18$		;release messages and send nak
	.SBTTL		HSMSAK - HASP...process ACK of message sent

; this subroutine is called to process the acknowledgement
; received for a message sent. it frees the message
; and takes care of signon message acks also.

	.ENABL	LSB
HSMSAK:	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.MSG(R4),R0	;point to message sent
	BNE	10$
	STOPCD	BUG
10$:	CALL	FREMSG		;flush the garbage
	CLR	LB.MSG(R4)	;no longer a message to send
	CALL	TIACK		;record implicit ack
	CLR	TCERB(R5)	;clear any prev bcb error indicator
	BIC	#TCSTMS!TCDTMS,TCBSCF(R5) ;last message sent accounted for
	BIT	#TCHGST,TCST2(R5)	;are we in process of changing status?
	BNE	68$
	MOV	TCTFCS(R5),TCPFCS(R5) ;make transmitted fcs as previous
68$:	MOV	R4,R1		;keep r4 intact with lcb pointer
	BIT	#TCSONM,TCBSCF(R5) ;was the message a signon?
	BEQ	11$		;no.
	BIC	#TCSONM,TCBSCF(R5) ;signon accounted for
	BIS	#LF.SON,LB.FGS(R4) ;indicate signed on
	MOV	LB.TCD+6(R1),R1	;point to card reader xlate tcb
	BIC	#TCOTC!TCDMP,TCFG1(R1) ;signon complete.
	MOV	#223,TCCTP(R1)	;restore original rcb
	TRACE	TRCLIN,<R5,JIFCLK>
SNTSON:
11$:	RETURN
	.DSABL	LSB
	.SBTTL		HSGTMS - HASP...create transmission block

; this subroutine gets transmission block full of device
; messages (if any) or status, grant, or request messages.
; it looks for signon block and if found that goes as a 
; lone block in the t.b..

HSGTMS:	BIT	#LF.SIM,LB.FGS(R4)	;check for sim line
	BEQ	10$		;if not, don't worry about signon
	BIT	#LF.SON,LB.FGS(R4) ;if so, ...worry!
	BNE	10$		;already signed on
	CALL	HSONB		;not signed on - wait patiently til we get a signon msg
	BCS	11$		;trouble in making t.b.
	BR	12$		; send it alone as a record

10$:	CALL	HSRQPT		;check request permission to xmit
	CALL	HSDPG		;check for any device permission granted
	CALL	HSMTBK		;make transmission block
	BCC	13$		;no errors in building t.b.
11$:	CLR	TCSTB(R5)	;out of chunks, can't send message
	BR	13$		;set up lb.msg also
12$:	BIS	#TCSONM,TCBSCF(R5) ;indicate signon being sent
13$:	MOV	TCLCB(R5),R4	;point to lcb
	MOV	TCSTB(R5),LB.MSG(R4) ;set up t.b. adr
	CLC			;indicate success
	RETURN
	.SBTTL		HSRQPT - HASP...check for permission requests to send

; this subroutine checks for any requests for transmission 
; to be sent to hasp. a request is never sent twice and 
; for that a flag tcowr (output was requested) is set 
; once the request is sent to hasp. this ensures all 
; outstanding requests to go thru.

HSRQPT:	MOV	TCLCB(R5),R4	;point to lcb
	TST	TCRQPT(R5)	;request already sitting there?
	BNE	13$		;yes, exit
	MOV	#1,R1		;start with console output
11$:	MOV	TCLCB(R5),R2	;point to lcb
	ASL	R1		;dev no * 2
	ADD	R1,R2		;add offset for the device
	ASR	R1		;restore dev no 
	MOV	LB.TCD(R2),R2	;point to device's xlate tcb
	BEQ	12$		;just in case tcb pointer is wiped
	BIT	#TCOPR,TCFG2(R2) ;request outstanding?
	BNE	14$		;yes, check if request was sent
12$:	INC	R1		;advance to next device
	CMP	R1,LB.NTC(R4)	;done with all devices?
	BLOS	11$		;no, loop for next device
	CLR	TCRQPT(R5)	;no request to send
13$:	RETURN

14$:	BIT #LF.SIM,LB.FGS(R4)	;sim mode?
	BEQ	24$		;no.
	CMPB	#222,TCCTP(R2)	;console out msg?
	BNE	24$		;no.
25$:	BIS	#TCOPG!TCORN,TCFG2(R2) ;set grant, permit run
	BIC	#TCOPR,TCFG2(R2) ;clear request bit
	BR	12$		;check for other devices
24$:	CMPB	#221,TCCTP(R2)	;output permission unneccessary if
	BEQ	25$		;operator display request (console output)
	CMPB	#RCBCTL,TCCTP(R2) ;check for signon
	BNE	15$		;its not
	BIS	#TCORN!TCOPG,TCFG2(R2) ;give it run and grant
	BIC	#TCOPR,TCFG2(R2) ;clear the request
	RETURN			;dont set for signon

15$:	BIT	#TCOWR!TCOPG!TCORN,TCFG2(R2) ;was request sent before
					     ;or already granted?
	BNE	12$		;yes, try next device
	BIS	#TCOWR,TCFG2(R2) ;request gone in the t.b.
	MOV	TCCTP(R2),TCRQPT(R5) ;save rcb for message building
	INC	TCCRQT(R2)	;count requests sent
	RETURN
	.SBTTL		HSDPG - HASP...check for permission grants to send

; this subroutine checks for any permissions grants to be sent to hasp.
; rcb for the device is set in TCDPG offset in bsc tcb.

HSDPG:	TST	TCDPG(R5)	;pending permission?
	BNE	13$		;yes, exit
	MOV	#1,R1		;start with console input
11$:	MOV	TCLCB(R5),R2	;point to lcb
	ASL	R1		;device no * 2
	ADD	R1,R2		;get device's
	ASR	R1		;restore dev no
	MOV	LB.TCD(R2),R2	;translate tcb adr
	BEQ	12$		;just in case tcb pointer is wiped
	BIT	#TCIPG!TCIRN,TCFG2(R2) ;input permission granted?
	BNE	14$		;yes, check if request is on
12$:	INC	R1		;move to next device
	CMP	R1,LB.NTC(R4)	;done with all the devices
	BLOS	11$		;no, loop for the next one
	CLR	TCDPG(R5)	;no permisssions to send
13$:	RETURN

14$:	BIT	#TCIPH,TCFG1(R2) ;permission already sent?
	BEQ	12$		;yes, check next device
	CALL	HSUNSP		;unsuspend the device
	MOV	TCCTP(R2),TCDPG(R5) ;set rcb for the device
	BIC	#TCIPH,TCFG1(R2) ;input permission sent to hasp
	RETURN
	.SBTTL		HSONB - HASP...build signon message to send to host

; here to build a signon block to be sent to host

HSONB:	CLR	TCSTB(R5)	;no signon to send yet

5$:	MOV	LB.LNU(R4),R1	;get the line #
	SWAB 	R1		;put in left byte
	ADD	#RCBCTL,R1	;make it signon i.d.
	CALL	DEQMID		;look for signon block
	BCC	11$		;found it
	MOV	#3,R1
	CALL	HSAWXL		;have to wait - wake cdr task
	CALL	20$		;check if all is ok
	RETURN

20$:	DSCHED	#EBINTR!EBQMSG,#30.
	CALL	HSCMDS		;check modem status
	BCS	10$		;line went away
	BIT	#LS.ENB,(R4)	;check if whole world went to hell while
	BEQ	10$		; we were sawing logs
	BIT	#TCOAB!TCIAB,TCFG2(R5)	;line still up - check aborts
	BNE	10$		;yeeecchh!
	CLC			;it all suc's
	RETURN

10$:	CALL	HSETHA		;make sure whole world knows
	CALL	HSWALX		;death mode - wake everybody
	SEC			;complain and allow further disintegration
	RETURN

11$:	MOV	R0,-(SP)	;save message pointer for later 3(023)
	MOV	R0,-(SP)	;save message pointer
	CALL	MSGSUP		;set up transmission block
	BCS	16$		;out of chunks
	MOV	R0,TCSTB(R5)	;save pointer to t.b.
	CALL	MSGHDR		;set up BCB,FCS etc in t.b. header
	BCS	16$		;ran out of chunks in msghdr
	MOV	(SP)+,R4	;message ptr in R4
	MOV	CHLEN(R4),R2	;get bytes in current chunk
	BEQ	12$		;empty header
	MOV	MSGPTR(R4),R3	;get ptr to 1st byte
	BR	13$

12$:	MOV	(R4),R3		;point to data chunk
	BEQ	14$		;end of message
	MOV	R3,R4		;save chunk ptr for ref later
	MOV	CHLEN(R3),R2	;length of data in chunk
	BEQ	12$		;empty chunk
	ADD	#CHDAT,R3	;point to start of data
13$:	MOVB	(R3)+,R1	;get with actual signon message from chunk
	KGACUM	R1		;accumulate BCC
	CALL	MSGAPC		;append char to message
	BCS	17$		;out of chunks
	SOB	R2,13$		;loop till done with chunk
	BR	12$		;get next chunk

14$:	CLR	R1		;put a zero RCB to indicate EOB
	KGACUM	R1		;accumulate RCB(0) IN BCC
	CALL	MSGAPC		;append the RCB (00)
	BCS	17$		;out of chunks
	CALL	HSTRL		;set trailer to message
	BCS	17$		;out of chunks
	MOV	TCLCB(R5),R4	;point to lcb
	DEC	LB.MSC(R4)	;one less message to xmit

	MOV	(SP)+,R0	;get message pointer 3(023)
	CALL	FREMSG		;flush the garbage

	CLC			;indicate success
15$:	RETURN

; OUT OF CHUNKS

16$:	RESTOR	R0		;flush top msg ptr - 2 on stack here
17$:	CALL	20$		;ruminate awhile- 1 copy of msg ptr on stack here
	RESTOR	R0		;get the msg ptr
	BCC	11$		;and try to build the transmission block again

25$:	CALL	FREMSG		;flush the message
	SEC
	RETURN
	.SBTTL		HSCDEF - HASP...check for dump or eof on output

; and when all messages are sent, indicates so to xlate
;
; Parameters:	R0/xlate tcb
;		R1/device id
;		R4/lcb
; Returns:	R0/transmission block ptr
;		R4/message

HSCDEF:	SAVE	R3
	MOV	R0,R3		;preserve the xlate tcb for awhile
	CALL	DEQMID		;get message for device, i.d in r1
				;remember i.d. is in r1
	BCC	12$		;got a message
	BIC	#TCOTC,TCFG1(R3) ; last output to device done
11$:	SEC			;indicate no messages for device
	BR	30$

12$:	DEC	TCMSC(R3)	;count down messages to go for device

	SAVE	R1
	MOV	TCCTP(R3),R1	;get device number
	TST	TCCHKQ(R3)	;any chunks queued to xlate task ?
	BEQ	21$		;no, check queued messages
25$:	CALL	HCLRAC		;yes, clear device active bit
	BR	22$		;restore registers and continue
21$:	CALL	HSETAC		;no, set the device active bit
22$:	RESTOR	R1

	MOV	R0,TCSDM(R5)	;ptr to device message saved
	MOV	R0,R4		;return message  here
	MOV	TCSTB(R5),R0	;r0 must point to t.b. built
	CLC			;indicate message found
30$:	RESTOR	R3
	RETURN
	.SBTTL		HSMTBK - HASP...build transmission block from device msgs

; this subroutine makes a transmission block from different 
; or same device records. the block  may also contain 
; request for device output permission as last record only 
; or may have the last record as device permission granted
; for a request previously made. the devices are polled 
; for data in the following priorities:
; console output, card reader, line printer and lastly 
; card punch output (if any)

HSMTBK:	CALL	HSCDOT		;check for output data & make message
	BCS	19$		;out of chunks
	MOV	TCSTB(R5),R0	;point to message t.b. if output to go
	BNE	11$		;yes, go set up header
	CLC			;no, exit
19$:	RETURN

11$:	CALL	MSGHDR		;set up bcb, fcs etc.
	BCS	30$		;out of chunks
	MOV	TCLCB(R5),R4	;get line block [4(41)]
	MOV	LB.MBL(R4),TCSLFT(R5) ;store maximum block size [4(41)]
	SUB	MSGLEN(R0),TCSLFT(R5) ;minus what we just put in [4(41)]
	SUB	#5,TCSLFT(R5) 	;minus room for trailer and BCC [4(41)]
				;i.e. zero RCB, [DLE], ETB, BCC1, BCC2
	TST	TCERB(R5)	;any bcb errors in last receive?
	BNE	23$		;yes, make a complaint and send
	TST	TCDPG(R5)	;any dev grants to go
	BNE	24$		;send alone
	TST	TCRQPT(R5)	;any permissions to ask
	BNE	24$		;yes, send alone
	CLR	TCDTB(R5)	;no current device in t.b.
	BIT	#TCDSP,TCFG2(R5) ;output suspended?
	BNE	23$		;send requests only
24$:	MOV	TCSDM(R5),R4	;any message left
	BEQ	12$		;none
	MOV	TCSTB(R5),R0	;t.b. must be set up

25$:	MOV	CHLEN(R4),R2	;get data amount in header
	BEQ	14$		;empty head
	MOV	MSGPTR(R4),R3	;get ptr to 1st byte
	BR	15$

12$:	INC	TCDTB(R5)	;start from console output
20$:	MOV	TCDTB(R5),R1	;any messages for this device?
	MOV	TCLCB(R5),R4	;point to lcb
	CMP	R1,LB.NTC(R4)	;done with all devices?
	BHI	23$		;yes, check for requests
	CALL	HSCKDO		;check device for output
				;r0/device xlate tcb
	BCS	12$		;suspended or permission not granted
	CALL	HSCDEF		;check for device message
	BCS	12$		;none there
				;r0/transmission block
				;r4/message
	CMP	MSGLEN(R4),TCSLFT(R5) ;does this message fit in t.b.
	BLE	25$		;yes, put it in t.b.

23$:	CALL	HSCKRQ		;check for requests
30$:	BCS	29$		;out of chunks
	RETURN

14$:	MOV	(R4),R3		;point to data chunk
	BEQ	17$		;end of current device message
	MOV	R3,R4		;save chunk ptr for looping over message
	MOV	CHLEN(R3),R2	;length of data in this chunk
	BEQ	14$		;empty chunk
	ADD	#CHDAT,R3	;point to start of data in chunk


;the following loop copies device message chunks into t.b.

15$:	MOVB	(R3)+,R1	;get char from chunk
	KGACUM	R1		;accumulate bcc
	CALL	HSCKTP		;check for transparent output
	BCS	29$		;out of chunks
16$:	CALL	MSGAPC		;append char to message
	BCS	29$		;out of chunks
	SOB	R2,15$		;loop till done with the chunk
	BR	14$		;start with next chunk

; here on end-of-device message or end of record also

17$:	MOV	TCLCB(R5),R4	;point to lcb
	DEC	LB.MSC(R4)	;one less message to send
	BIS	#TCDTMS,TCBSCF(R5) ;its a data message
	MOV	TCSDM(R5),R4	;point to message just put in tb
	SUB	MSGLEN(R4),TCSLFT(R5) ;this much space left
	SUB	MSGLEN(R4),MSGSNL(R0) ;deplete syn count
	MOV	R4,R0		;device message pointer in r0
	CALL	FREMSG		;flush the garbage
	CLR	TCSDM(R5)	;clear message pointer
	MOV	TCSTB(R5),R0	;point back to message being formed
	TST	MSGSNL(R0)	;do we need to append a syn
	BGT	20$		;not yet, any more data for the device
	BIT	#TCTSP,TCFG1(R5) ;output transparent?
	BEQ	18$		;no, insert syn only
	CMP	TCSLFT(R5),#2	;need at least two holes left
	BLT	20$		;can't oblige
	MOV	#EBCDLE,R1	;insert dle-syn in transparency
	CALL	MSGAPC		;append to the message
	BCS	29$		;out of chunks
	DEC	TCSLFT(R5)	;one byte less space left
	
18$:	CMP	TCSLFT(R5),#1	;need at least one holes left
	BLT	20$		;can't oblige
	MOV	#EBCSYN,R1	; syn alone for non-transparent
	CALL	MSGAPC		;append to message
	BCS	29$		;out of chunks
	DEC	TCSLFT(R5)	;one byte less
	MOV	#SYNLEN,MSGSNL(R0) ;reset syn length counter
	BR	20$		;check for more data

; here if trouble building message

29$:	STOPCD	HSA		;trouble building message
; this subroutine checks for transparent mode on output 
; and inserts dle before a data dle or syn for tranparency.

HSCKTP:	MOV	R1,-(SP)	;save r1, it has the original character
	BIT	#TCTSP,TCFG1(R5) ;output transparent?
	BEQ	11$		;no.
	CMPB	#EBCDLE,R1	;a dle?
	BNE	12$		;no, check for syn
	CALL	MSGAPC		;append a dle before dle
	BCS	13$		;failure return
11$:	MOV	(SP)+,R1	;restore r1, orignal char
	CLC			;indicate success
	RETURN

12$:	CMPB	#EBCSYN,R1	;is it a syn?
	BNE	11$		;no, exit
	MOV	#EBCDLE,R1	;append a dle
	CALL	MSGAPC		;before the syn
	BCC	11$		;for clean exit
13$:	MOV	(SP)+,R1	;restore original char
	SEC			;indicate failure
	RETURN

; this subroutine checks if there is data to xmit

HSCDOT:	TST	TCERB(R5)	;any bcb errors in last receive?
	BNE	14$		;yes.
	TST	TCRQPT(R5)	;any request to go?
	BNE	14$		;yes, setup message
	TST	TCDPG(R5)	;any permission grants?
	BNE	14$		;yes, setup msg
	BIT	#TCDSP,TCFG2(R5) ;all output suspended ?
	BNE	16$		;yes. don't send any output
	CLR	TCDTB(R5)	;initialise device for t.b.
	TST	TCSDM(R5)	;any message left from last time
	BNE	14$		;lets get that out first
11$:	INC	TCDTB(R5)	;start with console
	MOV	TCLCB(R5),R4	;point to lcb
	CMPB	TCDTB(R5),LB.NTC(R4) ;device # in limits
	BLOS	12$		;yes, check device for messages

	BIT	#LF.SIM,LB.FGS(R4) ; simulation mode ?
	BEQ	19$		;no,support, send message
				;yes, check for signon
	BIT	#LF.SON,LB.FGS(R4) ;is the line signed on ?
	BEQ	18$		;no, don't send null message
19$:	BIT	#TCHGST,TCST2(R5) ;check if status of device changed
	BEQ	16$		; no change - continue
	CALL	14$		;send an fcs
	BCS	15$		;failed
	BIC	#TCHGST,TCST2(R5) ; status changed noticed
	BR	13$		;suc'd

18$:


;end of code to send a null message


16$:	CLR	TCSTB(R5)	;nothing to send
13$:	CLC			;success
	RETURN

12$:	MOV	TCDTB(R5),R1	;device for t.b.
	MOV	TCLCB(R5),R4	;get the lcb
	CALL	HSCKDO		;allowed to output?
				;r0/device xlate tcb
	BCS	11$		;no, check next device
14$:	CALL	MSGSUP		;setup message
	BCS	15$		;failed
	MOV	R0,TCSTB(R5)	;point to t.b.
	BR	13$		;return
15$:	SEC			;signal failure
	RETURN
	.SBTTL		HSCKRQ - HASP...build permission requests and grants to send

; subroutine to check requests to be sent 
; or any permission granted to be sent to hasp

HSCKRQ:	MOV	TCSTB(R5),R0	;point to t.b. formed
	CMP	TCSLFT(R5),#3	;room for request? [4(41)]
	BLT	69$		;no, just put in zero RCB [4(41)]
	TST	TCERB(R5)	;any bcb error to complain to remote?
	BNE	21$		;yes.
	TST	TCRQPT(R5)	;any request permission to go?
	BEQ	15$		;no, check for permission granted
	MOVB	#RCBRQP,R1	;get rcb for request block
	KGACUM	R1		;accumulate in bcc
	CALL	MSGAPC		;append to the message
	BCS	14$		;out of chunks
	MOVB	TCRQPT(R5),R1	;device rcb goes into srcb place
	CLR	TCRQPT(R5)	;request taken care of
11$:	MOV	#3,R2		;for scb and zero rcb
12$:	KGACUM	R1		;accumulate srcb in bcc
	CALL	MSGAPC		;append char to message
	BCS	14$		;out of chunks
13$:	CLR	R1		;zero byte for scb(eor) and rcb
	SOB	R2,12$		;append them to end message
17$:	CALL	HSTRL		;set trailer for the message
	BCS	14$		;out of storage
	CLC			;success
	RETURN

14$:	SEC			;signal failure
	RETURN

; here for any permission grants to be sent

15$:	TST	TCDPG(R5)	;any grants to go
	BNE	16$		;yes, set up rcb and srcb in message
69$:	CLR	R1		;clear for zero rcb
	MOV	#1,R2		;put rcb(00) at end of data
	BR	12$		;to indicate end-of-block

16$:	MOV	#RCBPRG,R1	;get rcb for permission grant
	KGACUM	R1		;include in bcc
	CALL	MSGAPC		;append the rcb to message
	BCS	14$		;out of chunks
	MOV	TCDPG(R5),R1	;set up srcb as the device's rcb
	CLR	TCDPG(R5)	;permission grant sent
	BR	11$		;set up the trailer also

; here for bcb error reporting to remote

21$:	MOV	#RCBCBE,R1	;get rcb for bcb error
	KGACUM	R1		;accumulate in bcc
	CALL	MSGAPC		;append to message
	BCS	14$		;out of chunks
	MOV	TCERB(R5),R1	;set srcb to expected bcb count
	BR	11$		;put srcb and rcb(00)
	.SBTTL		HSTRL - HASP...build transmission block trailer

; here to set trailer DLE-ETB and crc and the pads at the end of the t.b.

HSTRL:	MOV	R4,-(SP)	;save r4
	MOV	TCLCB(R5),R4	;point to lcb 4(026)
	BIT	#LF.TSP,LB.FGS(R4) ;output transparent? 4(026)
	BEQ	11$		;no, use etb 4(026)
	MOV	#EBCDLE,R1	;yes, insert dle-etb 4(026)
	CALL	MSGAPC		;append the char to message 4(026)
	BCS	13$		;out of chunks 4(026)
11$:	MOV	#EBCETB,R1	;now the etb
	KGACUM	R1		;must be included in bcc
	CALL	MSGAPC		;append char to message
	BCS	13$		;out of chunks
	CALL	STOBCC		;append bcc
	BCS	13$		;out of chunks
	CALL	XLPADS		;append pads at the end
	BCS	13$		;out of chunks
	CALL	MSGAPE		;return unused chunks
	MOV	TCSTB(R5),LB.MSG(R4) ;point to message to be sent
	CLC			;signal success
12$:	MOV	(SP)+,R4	;restore r4
	RETURN

13$:	CLR	LB.MSG(R4)	;signal failure
	SEC			;indicate failure
	BR	12$		;and exit
	.SBTTL		MSGHDR - HASP...build a transmission block header

; to set up BCB, FCS etc.

MSGHDR:	BIT	#TCTSP,TCFG1(R5) ;output transparent?
	BNE	15$		;yes, then dont include stx
	MOV	#EBCSTX,R1	;hasp needs stx in bcc
	KGACUM	R1		;count in bcc
15$:	TST	TCERB(R5)	;bcb error to report?
	BNE	13$		;yes, set up different tbcb
	MOV	TCTBCB(R5),R1	;get current bcb
	KGACUM	R1		;include in bcc
	CALL	MSGAPC		;append bcb to message
	BCS	11$		;out of chunks
	CMPB	TCTBCB(R5),#BCBINI ;reset bcb?
	BEQ	12$		;yes, don't increment for next
	INC	TCTBCB(R5)	;block count for transmit
12$:	BIC	#160,TCTBCB(R5)	;make bcb modulo 16
14$:	MOVB	TCTFCS+1(R5),R1	;get first fcs byte
	KGACUM	R1		;include fcs byte in bcc
	CALL	MSGAPC		;append it to message
	BCS	11$		;out of chunks
	MOVB	TCTFCS(R5),R1	;get second fcs byte to transmit
	KGACUM	R1		;include in bcc
	CALL	MSGAPC		;append to message
				;ret suc/fail from MSGAPC
11$:	RETURN

13$:				;here for header to report bcb error
	MOV	TCRBCB(R5),R1	;get recvd bcb
	BIC	#177760,R1	;make count
	ADD	#220,R1		;make bcb for bypass
	MOV	R1,TCPBCB(R5)	;keep track of this bcb sent
	KGACUM	R1		;include in bcc
	CALL	MSGAPC		;and message to go
	BCS	11$		;exit with c set for error
	BR	14$		;join the main path
	.SBTTL		HSARSP - HASP...process received transmission block

; this module processes data received from hasp
; on return R0 = 0,1,2,3 or 4 depending on whether 
; we received ACK0,DATA,NAK,status or unrecognized 
; message block. 

HSARSP:	MOV	TCLCB(R5),R4	;no, point to lcb
	CALL	CLRALR		;clear any existing alarm
	MOV	TCCMA(R5),R0	;any control message to send?
	BEQ	11$		;no, just issue a read
	MOV	TCCMC(R5),R1	;yes, get address and count

9$:	CALL	CTLMSG		;send control message
	CLR	TCCMA(R5)	;dont send message twice
	BIS	#TCDIDO,TCBSCF(R5) ;last oper was xmit
11$:	MOV	#3*JIFSEC,LB.ALR(R4) ;set alarm - t.read called earlier
	CLR	R4		;no data yet
	BIC	#TCDIDO,TCBSCF(R5) ;last operation was read
	CALL	MSGGTC		;get input character
	BCS	5$		;timeout
	CALL	CLRALR		;flush alarm

10$:	CMPB	#EBCSTX,R1	;start of text?
	BEQ	22$		;yes.
	CMPB	#EBCDLE,R1	;no, data link escape?
	BEQ	14$		;yes,ack0 or stx next
	CMPB	#EBCSOH,R1	;soh?
	BEQ	18$		;possibly non-transparent data
	CMPB	#EBCNAK,R1	;nak?
	BEQ	17$		;yes,process nak
	CMPB	#EBCENQ,R1	;enq?
	BNE	12$		;no - not good stuff
	CALL	TENQ		;record this
	BIT	#LS.CTL,@TCLCB(R5) ;was last message a control msg?
	BEQ	12$		;no - cruftiness
	CALL	MSGGTE		;terminate this msg
	MOV	TCLCB(R5),R4	;yes - send it again
	DEC	LB.RTY(R4)	;count these so we don't hang here
	BLE	12$
				;ignore retry limit - host must abort
8$:	MOV	LB.CMA(R4),R0	;still ok - get the last control msg
	MOV	LB.CMC(R4),R1
	BR	9$


5$:	CALL	KOSHL		;check error status
	BCS	6$
	CALL	TTMO		;record time out
	BR	6$

; here when received data is unrecognizable.

12$:	CALL	TCRF		;record it

6$:	CALL	HSRXPT		;release messages and return
	RETURN			;returns R0/4

; here when DLE is recvd

14$:	CALL	MSGGTC		;get next char
	BCS	5$		;timeout
	CMPB	#EBCAK0,R1	;ack0?
	BEQ	16$		;yes,process ack0
	CMPB	#EBCEOT,R1	;dle-eot?
	BEQ	29$		;yes - other end is disconnecting
	CMPB	#EBCSTX,R1	;is it transparent data?
	BNE	12$		;no, unrecognized data
	BIS	#TCITSP,TCBSCF(R5) ;yes, set transparency flag
	BR	23$		;receive meassge

; here to process receipt of an ack0

16$:	CALL	TACK0		;record it
	CALL	MSGGTE		;clear the receiver
	CLR	R0		;indicate received ack0
	RETURN

;here when a nak is received.

17$:	CALL	TNAK		;record it
	CALL	MSGGTE		;end message
	MOV	#2,R0		;indicate nak received
	RETURN

; here when soh is received in non-transparent mode

18$:	KGLOAD	#0		;initialize kg11-a
19$:	CALL	MSGGTC		;get next char
	BCS	5$		;timeout
	KGACUM	R1		;accumulate in bcc
	CMPB	#EBCENQ,R1	; is this a bid ??
	BEQ	30$		;yes - abort line immediately
	CMPB	#EBCSTX,R1	;stx after soh?
	BNE	12$		;unrecognized seq 4(026)
	BIC	#TCITSP,TCBSCF(R5) ;non-transparent mode
21$:	CALL	HSRXPM		;get the received message
	RETURN

22$:	BIC	#TCITSP,TCBSCF(R5) ;indicate non-transparent mode
23$:	KGLOAD	#0		;initialize kg11-a
	BR	21$		;and receive message

29$:	CALL	RCVDSC		;record intent of other end to disconnect
	BR	31$

30$:	CALL	TENQ		;record this

31$:	CALL	MSGGTE		;terminate reading
	MOV	#7,R0		;;(040) unexpected bid sequence - abort line
	TRACE	TRCLIN,<(SP),R5,TCST2(R5)>
	RETURN
	.SBTTL		HSRXPM - HASP...process received non-transparent block

; here for processing received data ( device request, permission 
; grant, or data block )

HSRXPM:	CLR	TCRMSG(R5)	;initialize ptr to start of current messages
	CLR	TCCRCB(R5)	;& current received rcb
	CLR	TCSRCB(R5)	;  and srcb
	BIC	#^C<TCHGST>,TCST2(R5);clear status except for status change bit
	CLR	TCERB(R5)	;clear any prev bcb error flag

; check the bcb received against expected

	CALL	HMSGTC		;get char from block
	BCS	15$		;timeout
	MOVB	R1,TCRBCB(R5)	;save received bcb
.IF NE,DEBUG
	MOV	TCXBCB(R5),R2	;put expected bcb
	SWAB	R2		;in left side
	BISB	R1,R2		;and received in right bye
	TRACE	TRCBCB,R2	;trace bcb expected,received
.ENDC ;.IF NE DEBUG
	CMPB	TCXBCB(R5),R1	;bcb match?
	BEQ	14$		;yes.
	TSTB	R1		;proper bcb (high order bit must be set)
	BPL	13$		;no, error
	BIT	#20,R1		;ignore (bypass bcb check) bcb?
	BNE	14$		;yes, bypass checking
	BIT	#40,R1		;reset bcb?
	BNE	11$		;yes.,put receive bcb in expected
	MOV	TCRBCB(R5),TCERB(R5) ;mark bcb error and save bcb
	CALL	TBCB		;record BCB error
	BR	14$		;proceed as normal bcb

13$:	CALL	TBCB		;record BCB error
	CALL	MSGGTT		;clear receiver after 2-sec wait

	MOV	#5,R0		;bcb error in recvd data
	RETURN

11$:	BIC	#160,R1		;clear extra bits in bcb, other than count
	MOVB	R1,TCXBCB(R5)	;Store next expected BCB into task block

; now set up fcs (function control seq recd) from hasp

14$:	CALL	HSTFCB		;set fcs byte
15$:	BCS	HSRXTO		;timeout

HSRXP1:	CALL	HSTRCB		;set rcb and srcb bytes
	BCS	HSRXTO		;timeout
	BIT	#TCETB,TCST2(R5) ;received eob?
	BEQ	11$		;no.
	CALL	HSEOB		;received e-o-b.
	RETURN

; check rcb for error, request or permission for device

11$:	CMPB	#220,TCCRCB(R5)	;request for device?
	BEQ	HSRQMS		;yes, process request message
12$:
	CMPB	#240,TCCRCB(R5)	;permission grant message?
	BEQ	HSRQMS		;yes, permission message
13$:
	CMPB	#340,TCCRCB(R5) ;bcb error reported by hasp?
	BNE	14$		;no
	JMP	HSETBC		;yes, error in last xmit
14$:
	MOV	TCRMSG(R5),R0	;any messages formed yet?
	BEQ	16$		;no, start a new one
15$:	CMPB	TCCRCB(R5),MSGID(R0) ;message for current device?
	BEQ	20$		;yes
	MOV	MSGNXT(R0),R0	;no, check next message in chain
	BNE	15$		;for match with device
16$:	CALL	GETMHD		;get a message header
	BCC	19$		;got one
17$:	CALL	HSRXPT		;terminate message and flush things
	MOV	#8.,R0		;indicate chunk depletion
18$:	RETURN


19$:	MOV	TCRCID(R5),MSGID(R0) ;put received i.d in message
	MOV	TCRMSG(R5),MSGNXT(R0) ;link message in chain
	MOV	R0,TCRMSG(R5)	;update current message ptr
	BIT	#TCITSP,TCBSCF(R5) ;input transparency?
	BEQ	20$		;no, normal mode
	BIS	#MSGTSP,MSGFGS(R0) ;flag message as transparent
20$:	MOV	TCCRCB(R5),R1	;set up record header
	CALL	MSGAPC		;rcb at beginning of record
	BCS	HSRXET		;out of chunks
	MOV	TCSRCB(R5),R1	;srcb also
	CALL	MSGAPC		;in message to xlate
	BCS	HSRXET		;out of chunks
	CMPB	#RCBCTL,TCCRCB(R5) ;is it a signon record?
	BNE	21$
	JMP	HSRSON		;yes, received a signon
21$:	CALL	HMSGTC		;get first scb of the record
	BCS	HSRXTO		;timeout
	CALL	MSGAPC		;put char in message
	BCS	HSRXET		;out of chunks
	TSTB	R1		;end-of-file (dataless record)
	BNE	22$		;get next char
	BR	HSRXP1		;eof received

22$:	CMPB	#100, R1	;is this a transmission abort scb ?
	BEQ	21$		;yes, get end of record (scb=0)
	TSTB	R1		;no, check for legal scb
	BMI	23$		;legal scb?
25$:	CALL	MSGGTT		;terminate reading
	JMP	HSEOB1		;give error return
23$:	BIT	#100,R1		;dup string?
	BEQ	30$		;yes, get dup char
	MOV	R1,R2		;get the scb char
	BIC	#177700,R2	;get count of non-dup chars
	BEQ	25$		;zero count illegal
24$:	CALL	HMSGTC		;get char
	BCS	HSRXTO		;timeout
	CALL	MSGAPC		;put char in mesage to xlate
	SOB	R2,24$		;loop for all char of string
	BR	21$		;get next scb
30$:	BIT	#40,R1		;dup char blank?
	BEQ	21$		;yes, look for next scb
	MOV	#1,R2		;get the non-blank char
	BR	24$		;put it in message being built

; here for error return

HSRXTO:	CALL	TTMO		;record time out

HSRXET:	CALL	HSRXPT		;receive timeout or out of chunks
	RETURN
	.SBTTL		HSRQMS - HASP...process request for input permission

; here when hasp requested permission for (input) a device

HSRQMS:	MOV	TCSRCB(R5),R1	;srcb has the rcb of the requested device
	BIC	#177770,R1	;get the device # from rcb
	MOV	R4,-(SP)	;save r4
	MOV	TCLCB(R5),R4	;point to the lcb
	ASL	R1		;dev no * 2
	MOV	R1,R2		;preserve dev no * 2 in r1
	ADD	R4,R2		;point to the device's
	MOV	LB.TCD(R2),R2	;translate tcb
	CMPB	#240,TCCRCB(R5)	;is it permission granted msg?
	BEQ	11$		;yes
	BIT	#TCIRN,TCFG2(R2) ; is input already running 3(024)
	BEQ	5$		; no, just continue 3(024)
	BIS	#TCIRH,TCFG1(R2) ; yes, set bit to remember it 3(024)
	BR	HSRQM1		; and exit 3(024)
5$:				; new label 3(024)
	BIS	#TCIPH,TCFG1(R2) ;send reply when permission granted.
	CALL	HSDRIP		;request input permission
	BR	HSRQM1		;check next character for rcb
11$:	ASR	R1		;get back the device number
	CMPB	R1,LB.NTC(R4)	;if out of limit, check for rcb
	BHI	20$		;yes, its out of limits
	CMPB	TCSRCB(R5),TCCTP(R2) ;does it match the rcb?
	BEQ	21$		;yes.
20$:	CLR	R1		;initialize device # for hunt
22$:	INC	R1		;for match thru all devices
	CMPB	R1,LB.NTC(R4)	;within limits
	BLOS	23$		;its in limits
	STOPCD	HDO		;device out of limits
23$:	MOV	R1,R2		;r1 has to be preserved
	ASL	R2		;device # * 2
	ADD	R4,R2		;point to device's xlate tcb
	MOV	LB.TCD(R2),R2
	CMPB	TCSRCB(R5),TCCTP(R2) ;match?
	BNE	22$		;no, loop till match found
21$:	BIS	#TCOPG!TCORN,TCFG2(R2) ;set output permission granted?
	BIC	#TCOPR!TCOWR!TCDSP,TCFG2(R2) ;no pending requests
	SIGNAL	R2,EBINTR	;signal interrupt condition to  xlate
12$:	INC	TCCDPG(R2)	;count permissions recvd

HSRQM1:	MOV	(SP)+,R4	;restore r4
HSRQM2:	CALL	HMSGTC		;get the scb(00) for eor
	BCS	HSRXTO		;timeout
	TSTB	R1		;it must be zero scb
	BNE	13$		;its not, format error
	JMP	HSRXP1		;yes, look at next rcb

13$:
.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT
	BEQ	69$
	STOPCD	DBG
69$:
.ENDC	;.IF NE,DEBUG
	CALL	MSGGTT		;clear receiver
	CALL	HSRMRL		;release received messages
	MOV	#5,R0		;wrong data format received
	RETURN
	.SBTTL		HSRSON - HASP...process received signon message

; here when received rcb indicates a signon record

HSRSON:	TRACE	TRCLIN,<R5,JIFCLK>
RCVSON:	CALL	HMSGTC		;get next character
	BCS	11$		;timeout
	BIT	#TCETB,TCST2(R5) ;did we receive etb?
	BNE	20$		;yes.
	CALL	MSGAPC		;append char to message
	BCC	HSRSON		;loop for next character
	BR	15$

11$:	CALL	TTMO		;record time out

15$:	CALL	HSRXPT		;error return for timeout or out of chunks
	RETURN

20$:	CALL	HSEOB		;process end of block
	RETURN

; here when hasp reported a bcb error in xmit

HSETBC:	MOV	#240,TCTBCB(R5) ;send a reset bcb
	BR	HSRQM2		;receive the rest of the message
	.SBTTL		HSEOB - HASP...end of received transmission BLOCK PROCESSING

;	R3 = chars gotten from this chunk already
;	R4 = pointer to current chunk (initially 0)

	.ENABL	LSB
HSEOB:	CALL	DQRBCC		;accumulate next two characters
	BCC	10$
	CALL	TTMO		;record time out
	CALL	HSRXPT		;timeout
	RETURN

10$:	CALL	MSGGTE		;terminate reading
	KGTEST			;is bcc correct?
	BNE	14$		;no. got bcc error
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.IC1(R4)	;count blocks recvd successfully
	MOV	TCRMSG(R5),R0	;yes, que messages formed (if any)
	BEQ	13$		;data-less message, must be status block
12$:	MOV	MSGID(R0),R1	;get message i.d.
	CMPB	#RCBCTL,R1	;signon record?
	BNE	18$		;no
	MOV	#3,R1		;yes, que it up for card reader
18$:	BIC	#177770,R1	;get device # from i.d.
.IF NE DEBUG
	BNE	19$		;halt only for zero dev
	STOPCD	DBG		;error from ibm
19$:
.ENDC ;.IF NE DEBUG
	ASL	R1		;dev no * 2
	MOV	R1,R2		;preserve r1
	ADD	R4,R2		;point to device's
	MOV	LB.TCD(R2),R2	;xlate tcb
	CMPB	#RCBCTL,MSGID(R0) ;if this is a signon record
	BNE	23$
	BIS	#TCIRN,TCFG2(R2) ; set TCIRN so any fast device requests for
				 ; cdr will be remembered instead of generating
				 ; a permission grant immediately - note that
				 ; this can happen before 10 gets around to
				 ; issuing grant for the signon record and,
				 ; since none was requested, things are unmatched
	BR	24$
23$:	BIT	#TCIRN,TCFG2(R2); check if input already running
	BNE	25$		;yes - no need to drip
24$:	CALL	HSDRIP		;indicate input coming
25$:
	SAVE	R1		;check for duplicate message
	MOV	TCERB(R5),R1	;get the error BCB
	BEQ	50$		;no error
	BIT	#60,R1		;was it an error because of reset or ignore BCB
	BNE	50$		;yes - all is kosher
	INC	R1		;no -check for previous BCB
	BIC	#20,R1		;flush overflow
	CMPB	TCXBCB(R5),R1	;was it ?
	BNE	50$		;no - not a duplicate, must have skipped one
	TRACE	TRCLIN,<R5,R0,R1,R2>;trace BSC task,duplicate message,BCB,xlate task
	RESTOR	R1
	MOV	MSGNXT(R0),-(SP);save next msg in chain
16$:	CALL	FREMSG		;flush the garbage
	BR	20$

50$:	RESTOR	R1
	INC	TCIMC(R2)	;one more message queued to xlate

	CALL	BSCFLO		;check flow control for BSC task

	MOV	MSGNXT(R0),-(SP) ;get next message in chain
	MOV	R2,R1		;copy TCB into correct register for QUEMSG
	SAVE	R0
	CALL	CNTMSG		;find number of chunks in message
	MOV	TCLCB(R5),R4	;make sure we have the lcb
	ADD	R0,LB.RES(R4)	;reserve this many for xlate
	RESTOR	R0
	CALL	QUEMSG		;que message for the devices translate task
20$:
	MOV	(SP)+,R0
	BNE	12$		;yes, que it
	CLR	TCRMSG(R5)	;clear message ptr
13$:	CALL	HSCHST		;check for status change
	CLC			;indicate success
	MOV	#1,R0		;indicate real data received
	RETURN

; here for bcc error

14$:	CALL	TBCC		;record BCC error

	.DSABL	LSB

HSEOB1:	MOV	TCRMSG(R5),R0	;any messages to release
	BEQ	HSEOB2		;none left
15$:	MOV	MSGNXT(R0),-(SP) ;get next message to free
	CALL	FREMSG		;flush the garbage
	MOV	(SP)+,R0
	BNE	15$		;yes, loop till done

HSEOB2:	CALL	TBCC		;record bad BCC
	CLR	TCERB(R5)	;clear bad bcb indicator
	CLR	TCRMSG(R5)	;clear received message ptr
	MOV	#5,R0		;indicate invalid data
	RETURN

; here for error return on chunk depletion or timeout

HSRXPT:
;trace task,line sts,wake events,current receive block,current output msg
	TRACE	TRCLIN,<(SP),R5,@TCLCB(R5),TCWKEV(R5),R4,R0>
	CALL	MSGGTT		;clear receiver
	CALL	HSRMRL		;release messages formed
	MOV	TCLCB(R5),R4	;point to lcb
	INC	LB.IC7(R4)	;count messages ignored
	MOV	#4,R0		;unrecog messages
	RETURN
; this subroutine gets a character from
; input and checks for DLE or SYN and excludes them from bcc

HMSGTC:	CALL	MSGGTC		;get character
	BCS	15$		;timeout
	BIT	#TCITSP,TCBSCF(R5) ;input transparent?
	BEQ	10$		;no - go check special characters
				;yes - handle special characters different
	CMPB	#EBCDLE,R1	;transparent mode - check for DLE
	BNE	14$		;its not a DLE so it can't be special
	CALL	MSGGTC		;look at char after DLE
	BCS	15$		;timeout

10$:	CMPB	#EBCSYN,R1	;check for special characters
	BEQ	HMSGTC		;yes - flush it
	CMPB	#EBCETB,R1	;received ETB?
	BNE	14$		;no
	BIS	#TCETB,TCST2(R5) ;mark ETB recvd

14$:	KGACUM	R1		;include in bcc
	CLC			;indicate success
15$:	RETURN
	.SBTTL		HSTFCB - HASP...extract fcs from transmission block

; this subroutine sets the fcs from hasp

HSTFCB:	CALL	HMSGTC		;get fcs char
	BCS	11$		;timeout
	MOVB	R1,TCRFCS+1(R5)	;save fcs byte recd
	CALL	HMSGTC		;get next fcs byte
	BCS	11$		;none there
	MOVB	R1,TCRFCS(R5)	;save second byte of fcs
11$:	RETURN

; this subroutine sets up the rcb and srcb

HSTRCB:	CLR	TCCRCB(R5)	;initialize recvd rcb
	CLR	TCSRCB(R5)	;initialize recvd srcb
	CALL	HMSGTC		;get rcb byte
	BCS	12$		;timeout
	BIT	#TCETB,TCST2(R5) ;ETB received?
	BNE	12$		;yes.
	MOVB	R1,TCCRCB(R5)	;save received rcb
	BEQ	14$		;EOB received

;4(031)- route control message to console in emulation

	MOV	R4, -(SP)
	MOV	TCLCB(R5), R4	;point to lcb
	BIC	#177400, R1	;clear junk
	CMPB	R1,#RCBCTL	;is it a signon ?
	BNE	20$		;no, treat normally
	BIT	#LF.SIM,LB.FGS(R4) ;yes, is it simulation mode ?
	BEQ	20$		;no, treat normally
	MOVB	#221,TCCRCB(R5) ;yes,save console in as current rcb
	MOVB	#221,R1		;send message to console in
20$:	MOV	(SP)+,R4

;4(031)- end of code to route control message to console in emulation

	CMPB	R1,#220		;check for legal rcb's
	BHIS	11$
	TRACE	TRCLIN,<R5,2(SP),R1,TCRFCS(R5)>	;trace task,caller,rcb,fcs bytes
	BR	1$

11$:	BIC	#177770,R1	;find device type
	MOV	R1,TCRDVT(R5)	;save current device type
	MOV	R4,-(SP)	;save r4, it has ptr to rec chunk
	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.LNU(R4),R1	;get line no. in left byte
	SWAB	R1
	ADD	TCCRCB(R5),R1	;put rcb in right byte
	MOV	R1,TCRCID(R5)	;save current i.d. received
	MOV	(SP)+,R4	;restore r4
	CALL	HMSGTC		;get srcb byte
	BCS	12$		;timeout
	MOVB	R1,TCSRCB(R5)	;save srcb received
12$:	RETURN


14$:	CALL	HMSGTC		;get the next char
	BCS	12$		;timeout
	BIT	#TCETB,TCST2(R5) ;received ETB yet?
	BNE	12$		;yes.
	TST	R1		;check for extra zero rcb's inserted by HARRIS 1600
	BEQ	14$		;ignore them

	CMPB	#128., R1	;(025) is it a bcb ?
	BNE	1$		;(025) no, error
	CALL	HMSGTC		;(025) yes, read fcs byte #1
	BCS	1$		;(025) timeout, error
	CALL	HMSGTC		;(025) read fcs byte #2
	BCS	1$		;(025) timeout, error
	CALL	HMSGTC		;(025) look for etb
	BCS	1$		;(025) timeout, error
	BIT	#TCETB,TCST2(R5) ;(025) received etb yet?
	BNE	12$		;(025) yes.	
1$:				;(025) 

	SEC			;indicate error
	RETURN
	.SBTTL		HSCHST - HASP...process status block

; here for status block processing

HSCHST:	MOV	TCRFCS(R5),R1
	MOV	TCLCB(R5),R4	;point to lcb
	MOV	R4,R2		;save for ref
	BIT	#FCSUNV,R1	;suspend all?
	BEQ	11$		;no, check for card reader
	BIS	#TCDSP,TCFG2(R5) ;set universal suspend bit
	BR	12$		;start checking devices
11$:	BIC	#TCDSP,TCFG2(R5) ;unsuspend system
12$:				;here to check card reader or lpt
	ADD	#6,R2		;find device's
	BIT	#LF.SIM,LB.FGS(R4) ;simulate mode?
	BNE	13$		;yes, treat device as cdr
	ADD	#2,R2		;lpt for support mode
13$:	MOV	LB.TCD(R2),R2	;point to device's xlate tcb
	BIT	#FCSRD1,R1	;device suspended?
	BNE	14$		;no.
	BIS	#TCDSP,TCFG2(R2) ;suspend the device
	BR	15$		;check next device
14$:	BIC	#TCDSP,TCFG2(R2) ;unsuspend device
15$:	MOV	R4,R2		;get ptr to lcb
	ADD	#2,R2		;point to device's
	MOV	LB.TCD(R2),R2	;xlate tcb
	BIT	#FCSCSL,R1	;console suspended?
	BNE	16$		;no
	BIS	#TCDSP,TCFG2(R2) ;suspend console output
	BR	17$		;check next device
16$:	BIC	#TCDSP,TCFG2(R2) ;unsuspend console
17$:	MOV	R4,R2		;get ptr to lcb
	ADD	#12,R2		;point to punch 4(027)
	MOV	LB.TCD(R2),R2	;xlate tcb
	BEQ	19$		;jump if no punch
	BIT	#FCSPU1,R1	;punch suspended?
	BNE	18$		;no
	BIS	#TCDSP,TCFG2(R2) ;suspend punch device
	RETURN
18$:	BIC	#TCDSP,TCFG2(R2) ;unsuspend the device
19$:	RETURN
	.SBTTL		HSDRIP - HASP...signal input permission request for device

; subroutine to request input permission.
; on entry R1= device number of the requested device * 2
;          R2= device's xlate tcb ptr
; this subroutine is called by HSRXPM while processing 
; the received record for device permission
;
; on return:

HSDRIP:	BIS	#TCIPR!TCIWR,TCFG2(R2) ;request input permission

	ASR	R1		;get dev # back
	CALL	HSETAC		;set the active bit
	MOV	R4,-(SP)	;save r4
	BIT	#TCIOM,TCFG1(R2) ;device in input mode?
	BNE	14$		;yes.
	STOPCD	HSE		;asking input permission from output device
14$:
	BIT	#TCIPG!TCIRN,TCFG2(R2) ;permission granted?
	BNE	13$		;yes
				; and note it was req. [2(770)]
	CALL	HSUSPD		;suspend device if not running
	CALL	HSAWXL		;wake up xlate task

13$:	MOV	(SP)+,R4
	RETURN
	.SBTTL		HSUSPD,HSUNSP - HASP...device suspend/unsuspend

; subroutine to suspend a device when input permission refused

HSUSPD:	MOV	R2,-(SP)
	MOV	R3,-(SP)
	MOV	R5,R3			;point R3 to calling tcb
	MOV	TCLCB(R3), R3		;point to lcb
	MOV	LB.TC1(R3), R3		;point to bsc tcb
	ASL	R1			;dev no * 2
	MOV	SUSTBL(R1),R2		;R1 has device # on entry
	ASR	R1
	BIT	R2,TCTFCS(R3)		;don't if already clear
	BEQ	10$
	BIC	R2,TCTFCS(R3)		;suspend the device
	BIS	#TCHGST,TCST2(R3)	;indicate status changed
	TRACE	TRCFLO,<4(SP),R5,R1,TCTFCS(R5)>
10$:	MOV	(SP)+,R3
	MOV	(SP)+,R2
	RETURN

SUSTBL:	.WORD	0			;start of suspend table
	.WORD	FCSCSL			;suspend console output
	.WORD	FCSCSL			;suspend console input
	.WORD	FCSRD1			;suspend card reader
	.WORD	FCSPR1			;suspend line printer
	.WORD	FCSPU1			;suspend card punch


; this subroutine unsuspends a device when input permission 
; is granted for that device
; R1=device #

HSUNSP:	MOV	R2,-(SP)
	MOV	R3,-(SP)
	MOV	R5, R3			;point R3 to calling tcb
	MOV	TCLCB(R3), R3		;point to lcb
	MOV	LB.TC1(R3), R3		;point to bsc tcb
	ASL	R1			;dev no * 2
	MOV	SUSTBL(R1),R2		;get the unsuspend word for device
	ASR	R1
	BIT	R2,TCTFCS(R3)		;check if already done
	BNE	10$			; and don't do it again
	BIS	R2,TCTFCS(R3)		;unsuspend the device
	BIS	#TCHGST,TCST2(R3)	;indicate status changed
	TRACE	TRCFLO,<4(SP),R5,R1,TCTFCS(R5)>
10$:	MOV	(SP)+,R3
	MOV	(SP)+,R2
	RETURN
	.SBTTL		HSABRO,HSABRI - HASP...device stream aborts

; this subroutine sets abort flag for a device stream.

HSABRO:	ASL	R1		;r1 has dev no
	MOV	TCLCB(R5),R4	;point to lcb
	ADD	R1,R4		;device's xlate tcb
	ASR	R1		;restore dev no
	MOV	LB.TCD(R4),R4	;get pointer to 
	BEQ	12$		;for missing tcb
	BIT	#TCIOM,TCFG1(R4) ;output dev?
	BNE	12$		;no.
	BIS	#TCOAB,TCFG2(R4) ;set abort flag
	TRACE	TRCABO,<(SP),R4>
.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT
	BEQ	69$
	STOPCD	DBG
69$:
.ENDC	;.IF NE,DEBUG
12$:	RETURN

; this subroutine sets input abort flag for a device.

HSABRI:	ASL	R1		;on entry r1 has dev no
	MOV	TCLCB(R5),R4	;point to lcb
	ADD	R1,R4		;get device's 
	ASR	R1		;get dev # back
	MOV	LB.TCD(R4),R4	;point to xlate tcb
	BEQ	12$		;for missing tcb??
	BIT	#TCIOM,TCFG1(R4) ;input device?
	BEQ	12$		;no, exit
	BIS	#TCIAB,TCFG2(R4) ;set abort flag
	TRACE	TRCABO,<(SP),R4>
.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT
	BEQ	69$
	STOPCD	DBG
69$:
.ENDC	;.IF NE,DEBUG
12$:	RETURN

; this subroutine sets abort for all output devices

HSABTO:	MOV	TCLCB(R5),R4	;point to lcb
	TRACE	TRCABO,<(SP),R4>
	MOV	LB.NTC(R4),R1	;get max device #
11$:	CALL	HSABRO		;abort the device
	SOB	R1,11$		;all done
	BIS	#TCOAB,TCFG2(R5) ;set output abort started by bsc
	MOV	TCLCB(R5),R4	;point to lcb
	RETURN

; this subroutine sets abort for all input devices.

HSABTI:	MOV	TCLCB(R5),R4	;point to lcb
	TRACE	TRCABO,<(SP),R4>
	MOV	LB.NTC(R4),R1	;get max device #
11$:	CALL	HSABRI		;abort the device
	SOB	R1,11$		;loop till all done
	BIS	#TCIAB,TCFG2(R5) ;set input abort started by bsc
	MOV	TCLCB(R5),R4	;point to lcb
	RETURN

.ENDC	;.IF NE,FT.HSP
	.SBTTL		BSCFLO,INFLO,OUTFLO - HASP...device/line flow control


;input flow control


.IF NE,FT.HSP

BSCFLO:				;check flow control thresholds for BSC task
				; and suspend/unsuspend dev input appropriately
				; R2/xlate tcb ptr
	SAVE	<R1>
	MOV	TCCTP(R2),R1	;get the device type
	BIC	#177770,R1	;isolate device number
	CMP	TCIMC(R2),#DSRFIT;check msgs queued to xlate for that stuffy feeling
	BLT	10$		;branch if not too full
	CALL	HSUSPD		;suspend the device
	BR	20$

10$:	CMP	TCIMC(R2),#DHNGRY;not too full , check emptiness
	BGT	20$		;let it be
	CALL	HSUNSP		;unspend the device
20$:	RESTOR	<R1>
	RETURN

.ENDC	;.IF NE,FT.HSP

	.ENABL	LSB
INFLO:	SAVE	<R0,R4>			;check line flow control thresholds
					; and do universal suspend/unspend accordingly
	MOV	TCLCB(R5),R4		;get the lcb
	MOV	LB.FRE(R4),R0		;calc the available resources
	SUB	LB.RES(R4),R0
.IF EQ,FT.HSP
	CMP	R0,#CHDRTH		;have we plenty of chunks?
	BLT	30$			;no
.IFF
	CMP	#TTHASP,LB.DVT(R4)	;check if HASP device
	BNE	29$			;no - simple test
	CMP	R0,#CHDRTH		;have we plenty of chunks?
	BGE	20$			;yes
					;no - shut off hasp input

; here to send a universal suspension to hasp

10$:	BIT	#FCSUNV,TCTFCS(R5)	;check if already suspended
	BNE	35$			;yes - don't bother
	BIS	#FCSUNV,TCTFCS(R5)	;set suspend
	BIS	#TCHGST,TCST2(R5)	;indicate status chnge

; here if there are enough chunks to receive data

20$:
	CMP	R0,#CHSRPL		;have we got enough to restart line
	BLT	35$			;let current state ride
	BIT	#FCSUNV,TCTFCS(R5)	; check if already clear
	BEQ	25$			;yes - don't do again
	BIC	#FCSUNV,TCTFCS(R5) 	;unsuspend hasp data
	BIS	#TCHGST,TCST2(R5)	;set up to receive
.ENDC	;.IF EQ,FT.HSP

25$:					;on the input
.IF NE,FT.HSP
	TRACE	TRCFLO,<4(SP),R5,LB.FRE(R4),LB.RES(R4),TCTFCS(R5)>
.IFF
	TRACE	TRCFLO,<4(SP),R5,LB.FRE(R4),LB.RES(R4)>
.ENDC	;.IF NE,FT.HSP
INPON:	CLC
	BR	35$

.IF NE,FT.HSP
29$:	CMP	R0,#CHDRTH		;2780/3780 -  plenty of chunks?
	BGE	25$			;yes
.ENDC	;.IF NE,FT.HSP

30$:					;off the input
.IF NE,FT.HSP
	TRACE	TRCFLO,<4(SP),R5,LB.FRE(R4),LB.RES(R4),TCTFCS(R5)>
.IFF
	TRACE	TRCFLO,<4(SP),R5,LB.FRE(R4),LB.RES(R4)>
.ENDC	;.IF NE,FT.HSP

INPOFF:	SEC

35$:	RESTOR	<R4,R0>			;flush the resource calc
	RETURN
	.DSABL	LSB


;output flow control

	.ENABL	LSB
OUTFLO:					;check if device is suspended for output
					;R3/xlate tcb for device
	SAVE	<R1,R2,R4>
	MOV	TCLCB(R3),R4		;get the line block
	MOV	LB.TC1(R4),R2		;get the BSC task
	BIT	#TCDSP,TCFG2(R3)	;device output suspended ?
	BNE	5$			;yes - no need to look further
	BIT	#TCSTG,TCFG1(R3)	;is the xlate task suspended for storage?
.IF EQ,FT.HSP
	BEQ	10$			;if not, all is ok
.IFF
	BNE	5$			;if so, off the ten

	CMP	#TTHASP,LB.DVT(R4)	;check if HASP device
	BNE	10$			;no - just say ok
	MOV	LB.TC1(R4),R2		;get the BSC task
	MOV	TCCTP(R3),R1		;get the device type
	CMP	#360,R1			;never suspended for signon device
	BEQ	10$
	BIC	#177770,R1		;isolate generic type
	ASL	R1			;word offset
	BIT	SUSTBL(R1),TCRFCS(R2)	;check if we have received a device suspend
	BEQ	5$			;yes - answer "no!" to the burning question
	BIT	#FCSUNV,TCRFCS(R2)	;check universal suspend
	BEQ	10$			;no - all is go
.ENDC	;.IF EQ,FT.HSP

5$:
.IF NE,FT.HSP
	TRACE	TRCFLO,<6(SP),R5,LB.FRE(R4),LB.RES(R4),TCRFCS(R2)>
.IFF
	TRACE	TRCFLO,<6(SP),R5,LB.FRE(R4),LB.RES(R4)>
.ENDC	;.IF NE,FT.HSP
OUTOFF:	SEC				;tell caller to go away
	BR	15$

10$:	MOV	LB.FRE(R4),-(SP)	;calc the available resources
	SUB	LB.RES(R4),(SP)
.IF NE,FT.HSP
	CMP	#TTHASP,LB.DVT(R4)	;check if HASP device
	BNE	11$			;no - just say ok
	CMP	(SP)+,#HLDRTH		;have we plenty of chunks?
	BLT	5$			;no -  off the ten
	BR	12$			;yes - on the ten
.ENDC	;.IF NE,FT.HSP

11$:	CMP	(SP)+,#XLDRTH		;have we plenty of chunks?
	BLT	5$			;no -  off the ten

12$:					;the 10 should go on
.IF NE,FT.HSP
	TRACE	TRCFLO,<6(SP),R5,LB.FRE(R4),LB.RES(R4),TCRFCS(R2)>
.IFF
	TRACE	TRCFLO,<6(SP),R5,LB.FRE(R4),LB.RES(R4)>
.ENDC	;.IF NE,FT.HSP
OUTON:	CLC				;tell caller it's ok to stuff it

15$:	RESTOR	<R4,R2,R1>
	RETURN
	.DSABL	LSB
	.SBTTL		HSAWXL,POKBSC - task wakers

; subroutine to awaken the translate task

; r1 = has the device # whose xlate task needs to be awakened.
; r4 points to the lcb

	.ENABL	LSB
HSAWXL:	SAVE	R4
	ADD	R1,R4			;point to specific device's
	ADD	R1,R4			;point to specific device's
	MOV	LB.TCD(R4),R4		;get adr of xlate tcb
10$:	BEQ	12$			;for missiing or released tcb's
	SIGNAL	R4,EBINTR		;signal interrupt condition to xlate task

12$:	RESTOR	R4
	RETURN

;wake the BSC task

POKBSC:	SAVE	R4
	MOV	TCLCB(R5),R4		;get the calling task's lcb
	MOV	LB.TC1(R4),R4		;get the line's BSC task
	BR	10$
	.DSABL	LSB

; this subroutine wakes up all device's xlate tasks

HSWALX:					;R4/lcb
	MOV	LB.NTC(R4),R1		;max dev number
	BEQ	11$			;exit if zero tcbs
12$:	CALL	HSAWXL			;wake the xlate task
	SOB	R1,12$			;loop for all devices
11$:	RETURN
	.SBTTL		device active sets/clears

SACTO:				;set device active for 2780/3780 output
	CALL	ODEV		; get proper device  code
	BR	HSACMP		; and set the bit

SACTI:	CALL	IDEV		;set device active for 2780/3780 input
	BR	HSACMP

CACTO:	CALL	ODEV		;clear device active for 2780/3780 output
	BR	HSAMPC

CACTI:	CALL	IDEV		;clear device active for 2780/3780 input
	BR	HSAMPC

ODEV:	MOV	TCLCB(R5),R1	;set device code for 2780/3780 output direction
	MOV	LB.LNU(R1),R0	;get line number
	BIT	#LF.SIM,LB.FGS(R1) ;simulation or support ?
	BEQ	10$		;support
	MOV	#3,R1		;simulation, must be cdr
	RETURN
10$:	MOV	#4,R1		;support, must be lpt
	RETURN

IDEV:	MOV	TCLCB(R5),R1	;set device code for 2780/3780 input direction
	MOV	LB.LNU(R1),R0	;get line number
	BIT	#LF.SIM,LB.FGS(R1) ;simulation or support ?
	BEQ	10$		;support
	MOV	#4,R1		;simulation, must be lpt
	RETURN
10$:	MOV	#3,R1		;support, must be cdr
	RETURN


; subroutine to set all the device active bits  when a hardware abort occurs.
	.ENABL	LSB
HSTBTS:.IF NE,DEBUG
	BIT	#TRCABO,TRCHLT	;check for abort halt
	BEQ	1$
	STOPCD	DBG
1$:
.ENDC	;.IF  NE,DEBUG
	SAVE	R0
	MOV	#-1,-(SP)	;push active status
	BR	20$

;this subroutine clears the device active bits on an abort or on a line disable


DABCLR:	SAVE	R0
	CLR	-(SP)		; push active status

20$:	MOV	TCLCB(R5),R0	;point to lcb
	MOV	LB.LNU(R0),R0	;get line number
	BIC	#177770,R0	;clear junk
	ASL	R0		;make even
	ASL	R0		;point to first word of 2 word status
	MOV	(SP),D60ACT(R0)	;set active status bits
	MOV	(SP)+,D60ACT+2(R0) ;set active status bits
	RESTOR	R0
	RETURN
	.DSABL	LSB

HSETAC:	SAVE	R0		;set  hasp device active
				;r1/dev code
	MOV	TCLCB(R5),R0	;get the lcb
	MOV	LB.LNU(R0),R0	;but only to retrieve line number
	CALL	HSACMP		;set the bit
	RESTOR	R0
	RETURN

HCLRAC:	SAVE	R0		;clear hasp device active bit
				;r1/dev code
	MOV	TCLCB(R5),R0	;get the lcb
	MOV	LB.LNU(R0),R0	;but only to retrieve line number
	CALL	HSAMPC		;clear the bit
	RESTOR	R0
	RETURN

;the following routines set or clear the device and any device 
;active bits.

;to clear a device active bit, the entry is: jsr pc, hsampc
;to set a device active bit, the entry is: jsr pc, hsacmp

;if no devices are active, the any device active bit is cleared

;on entry:	r0 = the line number
;		r1 = the device number


;this is the entry point to clear a device active


HSAMPC:	SAVE	<R0,R1,R2>
	CALL	HSACT		;find the bit and word
	BIC	R1,D60ACT(R0)	;clear the active bit
	BR	HSAXIT

;this is the entry point to set a device active

HSACMP:	SAVE	<R0,R1,R2>
	CALL	HSACT		;find the bit and word
	BIS	R1,D60ACT(R0)	;set the active bit

HSAXIT:	RESTOR	<R2,R1,R0>
	RETURN

;convert line number to offset into status table

HSACT:	BIC	#177770,R0	;clear junk
	ASL	R0		;make line number even
	ASL	R0		;point to first word of
				;two word status

	BIC	#177400,R1	;clear junk
	MOV	R1,R2		;get device number

	CMP	#360,R2		;is this a signon ?
	BNE	20$		;no, continue 3(014)
	MOV	#223,R2		;yes, convert to cdr 3(014)
	MOV	R2,R1		;convert to cdr 3(014)

20$:
	BIC	#177770,R2	;get offset into device table
	BEQ	21$		;yes, error
	ASL	R2		;make even

	CMP	R2,#12		;is the device unknown ?
	BLE	22$		;no, continue
21$:	STOPCD	RNG		;out of range
22$:

	JMP	@HSASER-2(R2)	;set or clear the unit bit


;these are the handlers for the setting or clearing of a device active bit


;console out handler


HSCTYO:	MOV	#B7,R1		;get unique unit bit
	RETURN			;set in 1st word

;CONSOLE IN HANDLER

HSCTYI:	MOV	#B6,R1		;get unique unit bit
	RETURN			;set in 1st word

;CARD READER HANDLER

HSDCDR:	CALL	UDEV		;get unit bit
	SWAB	R1		;left half of 1st word
	RETURN			;set in 1st word

;LINE PRINTER HANDLER

HSDLPT:	CALL	UDEV		;get unit bit
	BR	HSCET2		;right half of 2nd word

;card punch handler

HSDCDP:	CALL	UDEV		;get unit bit
	SWAB	R1		;left half of 2nd word

HSCET2:	INC	R0		;mask 2nd word
	INC	R0
	RETURN

UDEV:	SUB	#220,R1		;generate mask for unit
	BMI	9$
	ASR	R1
	ASR	R1
	ASR	R1
	ASR	R1
	CMP	R1,#7		;check range
	BLE	10$
5$:	STOPCD	RNG		;bad news

9$:	CLR	R1		;must be 2780/3780 device

10$:	MOVB	UTAB(R1),R1	;get the mask
	BIC	#177400,R1	;in case its  the last one
	RETURN

UTAB:	.BYTE	B0,B1,B2,B3,B4,B5,B6,B7


;dispatch table to device handlers for setting and clearing active bit


HSASER:	.WORD	HSCTYO		;console out
	.WORD	HSCTYI		;console in
	.WORD	HSDCDR		;card reader
	.WORD	HSDLPT		;line printer
	.WORD	HSDCDP		;card punch
	.SBTTL		test/set miscellaneous line conditions

; subroutine to indicate communications established

HSETCE:	MOV	R4,-(SP)	;save r4
	MOV	TCLCB(R5),R4	;point to lcb
	BIS	#LF.CME,LB.FGS(R4) ;indicate communication established
	MOV	(SP)+,R4	;restore r4
	RETURN


; subroutine to set h/w abort 


HSETHA:	MOV	R4,-(SP)	;save r4
	MOV	TCLCB(R5),R4	;point to lcb
	BIT	#LS.ENB,(R4)	;if line was disabled - no hardware abort
	BEQ	10$
	BIS	#LF.HWA,LB.FGS(R4) ;indicate a h/w  abort
10$:	CALL	HSTBTS		;set all the active bits 3(017)
	MOV	(SP)+,R4	;restore r4
	RETURN

KOSHL:	SAVE	R4
	MOV	TCLCB(R5),R4
	BIT	#LS.ENB,(R4)	;check if all is kosher with line
	BEQ	10$
	CALL	HSCMDS		;check if DSR is still up
	BCS	10$		;no - he gave up
	BIT	#TCIAB!TCOAB,TCFG2(R5)
	BNE	10$
	BIT	#TCDIS,TCST2(R5)
	BNE	10$

	CLC			;all is ok
	BR	15$

10$:	TRACE	TRCLIN,<2(SP),R4,(R4),TCFG2(R5),TCST2(R5)>
	SEC

15$:	RESTOR	R4
	RETURN

;the following subroutine checks the modem status

HSCMDS:	SAVE	<R0,R1>
	MOV	TCLCB(R5),R0	;point to lcb
	CLR	R1		;clear for status
	CALL	@T.DTS(R5)	;get modem status
	BIT	#B2,R1		;data set ready?
	BEQ	11$		;no
	BIT	#B1,R1		;DTR up?
	BEQ	11$		;no, set c
	CLC			;indicate success, DSR on
	BR	15$

11$:	SEC			;no, set carry

15$:	RESTOR	<R1,R0>
	RETURN
	.SBTTL		HSCKDO - check if device can do output

; this subroutine checks if the device is permitted to 
; do output to hasp. if c set -- cannot output
;
; Parameters:	R1/device number
;		R4/LCB
;
; Returns:	R0/device xlate tcb
;		R1/id for device msg

HSCKDO:	MOV	R1,R0		;for ref later
	ASL	R0
	ADD	R4,R0		;get device's tcb adr
	MOV	LB.TCD(R0),R0	;using device # in r1 as index
	BEQ	12$		;for non-existant xlate tcb
	BIT	#TCOAB!TCIAB,TCFG2(R0) ;device output or input aborted?
	BNE	10$		;no
11$:	BIT	#TCORN,TCFG2(R0) ;output permission granted?
	BEQ	12$		;no, can't do output

	BIT	#TCDSP, TCFG2(R0) ;device suspended ?
	BNE	12$		;yes, cannot do output
				;no, set up for message

	MOV	LB.LNU(R4),R1	;get line number
	SWAB	R1		;put line # in left byte
	ADD	TCCTP(R0),R1	;make i.d. for the device msg
	CLC			;yes, all o.k for output
	RETURN

10$:	CALL	HSDOAB

12$:	SEC			;indicate cannot do output
	RETURN

HSDOAB:	SAVE	R0		;r0/xlate tcb
				;r4/lcb
	MOV	LB.LNU(R4),R1	;get line number
	SWAB	R1		;in left byte
	ADD	TCCTP(R0),R1	;make i.d. for the device message
	SAVE	R1
12$:	CALL	DEQMID		;is there a message for device?
	BCS	13$		;no message
14$:	CALL	FREMSG		;flush the garbage
	mov	(sp),r1		;get the i.d.
	BR	12$		;check for more messages
13$:	DSCHED	#EBQMSG,#10.
	MOV	(SP),R1		;get the i.d.
	CALL	DEQMID		;any messages for device
	BCC	14$		;yes, free them
16$:	RESTOR	R1
	RESTOR	R0
	CLC
	RETURN
	.SBTTL		miscellaneous cruft

; subroutine to release messages formed from current block

HSRMRL:	MOV	TCRMSG(R5),R0	;any messages formed?
	BEQ	12$		;none
11$:	MOV	MSGNXT(R0),-(SP) ;get next message in chain
	CALL	FREMSG		;flush the garbage
	MOV	(SP)+,R0
	BNE	11$		;go release it
	CLR	TCRMSG(R5)	;clear so we dont release again
12$:	RETURN

; this subroutine releases all outgoing messages if any

HSRLOM:	MOV	TCLCB(R5),R4	;point to lcb
	MOV	LB.MSG(R4),R0	;message to be released?
	BEQ	11$		;no, check for any device msg stuck
	CALL	FREMSG		;flush the garbage
	CLR	LB.MSG(R4)	;clear message ptr
11$:	MOV	TCSDM(R5),R0	;any dev msg stuck in bsc
	BEQ	12$		;no, exit
	CALL	FREMSG		;flush the garbage
	CLR	TCSDM(R5)	;clear dev message ptr
12$:	RETURN