Google
 

Trailing-Edge - PDP-10 Archives - CFS_TSU04_19910205_1of1 - update/ietsrc/msghdl.p11
There are 8 other files named msghdl.p11 in the archive. Click here to see a list.
	.SBTTL	MSGHDL - message handling

; subroutines in this section manipulate messages.  there is
;  a subroutine to get a character from a message, three for
;  terminating the get process, one to append a character
;  to a message and one to terminate the append process.

.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
	.SBTTL		MSGGTC - get a character from the input stream.

;	R3 = chars gotten from this chunk already
;	R4 = pointer to current chunk (initially 0)
;	R5 = pointer to tcb
;	LB.ALR in line block might be set or not

; on return: 

;	R1 = next char, C is clear; or, C is set if no more data.

	.ENABL	LSB

MSGGTC:	MOV	R0,-(SP)	;save r0
11$:	TST	R4		;is there a chunk?
	BNE	12$		;yes, get a char from it.
	BIT	#LS.XGO!LS.XRN,@TCLCB(R5) ;transmitter still going?
	BNE	16$		;yes, wait for receiver
	CALL	DEQCHK		;no, try to get a chunk from receiver
	BCS	14$		;there is none.
	MOV	R0,R4		;there is one, put pointer in r4
	CLR	R3		;we have taken nothing from it yet
	TRACE	TRCDQF,<R5,R4,CHLEN(R4),JIFCLK>
GTCDEQ:
12$:	CMP	R3,CHLEN(R4)	;have we emptied the chunk?
	BNE	17$		;no, get its next character
13$:	BIT	#LS.RRN!LS.RGO,@TCLCB(R5) ;is receiver running?
	BNE	15$		;yes.
	MOV	R4,R0		;no, put chunk in r0
	TRACE	TRCDQF,<R5,R4,CHLEN(R4),R3,JIFCLK>
GTCFL0:	CALL	FRECHK		;send it the chunk to free
	CLR	R4		;no current chunk
	BR	11$		;see if any more chunks

; here to give error return.  there are no more chunks queued
;  and either the receiver has stopped or time is up or
;  there has been an error.

14$:	MOV	(SP)+,R0	;restore r0
				;trace failure and reasons
	TRACE	TRCDQD!TRCLIN,<(SP),R5,R4,R3,(R5),TCWKEV(R5),@TCLCB(R5),JIFCLK>
GTCFAL:	SEC			;signal error
	RETURN

; here when the receiver is running but we have processed all
;  of the characters it has stored in the current chunk.
;  if we have more wait time, consider processing more characters.

15$:	BITB	#EBALR,TCEV(R5)	;check if response timer went off
	BNE	14$		;yes, we have waited too long

; here when we appear to have processed all of the characters.
;  however, the line driver may have stored some characters since it
;  last interrupted.  if it has, process them.  if not, wait.

	CALL	@T.INW(R5)	;check if the line driver is hiding characters
	BCS	11$		;if there were, go process them.

; here if the line driver has stored no more characters since
;  the last one we have processed.  we are enabled for special
;  character interrupts so we should be awakened as soon as
;  there is anything interesting to process.
; also come here if the transmitter is running.  the presumption
;  is that completion of the transmission will start the receiver.
;  if this is false (a transmitter error) we will catch it by
;  noticing that the line driver goes idle without returning any
;  characters.

16$:	DSCHED	#EBINTR!EBQCHK!EBALR,#5. ;wait for something to happen

GTCSLP:	BIT	#EBQCHK,TCWKEV(R5);any action?
	BNE	11$		;yes - check it out
	BIT	#EBINTR,TCWKEV(R5);interrupt condition?
	BNE	20$
	BIT	#EBALR,TCWKEV(R5);alarm?
	BNE	14$		;yes - fail
				;timed out
	CALL	@T.INW(R5)	;check if the line driver is hiding characters
	BCS	11$		;if there were, go process them.

	MOV	TCLCB(R5),R0	;check if alarm set
	TST	LB.ALR(R0)
	BEQ	14$		;no - message started but mysteriously stopped
	BR	11$		;try again.

20$:	BIT	#TCIAB,TCFG2(R5);check input abort
	BNE	14$		;yes - fail
	BIT	#LS.ENB,@TCLCB(R5);line turned off?
	BEQ	14$		;yes - fail here also
	BR	11$		;must be a line driver interrupt

; here when the current chunk has at least one unprocessed character

17$:	MOV	R3,R0		;get current count
	ADD	R4,R0		;add chunk base address
	MOVB	CHDAT(R0),R1	;get next character from chunk
	INC	R3		;increment count of chars
	CMP	#CHDATL,R3	;have we gotten them all?
	BNE	18$		;no, return to user.

; come here when we have gotten the last character from the
;  current chunk.

	MOV	R1,-(SP)	;save the character
	MOV	R4,R0		;put chunk pointer in r0
	TRACE	TRCDQF,<R5,R4,CHLEN(R4),R3,JIFCLK>
GTCFLS:	CALL	FRECHK		;flush the chunk
	MOV	(SP)+,R1	;restore character
	CLR	R4		;note no current chunk
18$:	MOV	(SP)+,R0
	TRACE	TRCDQD,<(SP),R5,R4,R1> ;trace a character read
GTCSUC:	CLC			;signal success
	RETURN


	.DSABL	LSB
	.SBTTL		MSGGTE - clear out the receiver

; called when the end of a message is recognized.

; called with R5 pointing to tcb

MSGGTT:
MSGGT2:
MSGGTE:	SAVE	<R0,R1,R3>	;terminate receiving gracefully
	CALL	RCVEND		;find end of input stream
	SAVE	R4		;save possible message ptr
	MOV	TCLCB(R5),R4	;point R4 to lcb
	CALL	@T.KIL(R5)	;stop all line driver operations
	RESTOR	R4		;get msg ptr back
	BEQ	10$		;no exists
	MOV	R4,R0
	CALL	FRECHK		;throw it away
	CLR	R4		;chunk no longer there
10$:	DSCHED	,#1		;force a wait before reply
	TRACE	TRCDQF!TRCLIN,<6(SP),R5,JIFCLK>
MSGEND:	RESTOR	<R3,R1,R0>
	RETURN

RCVEND:	MOV	TCLCB(R5),R0	;wait out the end of the input message
	TRACE	TRCDQF,<R0,(R0),R4,R3,LB.ALR(R0),JIFCLK>
	CALL	CLRALR		;no alarms here
	TST	R4		;if we don't have a chunk
	BEQ	25$		;...the receiver never started

10$:	BIT	#LS.RRN,(R0)	;check if the receiver is still running
	BEQ	25$		;no - must have terminated in error

	CALL	MSGGTC		;get a char
	BCS	25$
	CMPB	#EBCDLE,R1	;check transparent input
	BNE	20$
	CALL	MSGGTC		;maybe - gobble next character
	BCS	25$
	BR	10$

20$:	CMPB	#EBCPAD,R1	;scan for pad at end
	BNE	10$

25$:				;receiver not running,time out or end of msg
	TRACE	TRCDQF,<R0,(R0),R4,R3,JIFCLK>
	RETURN
	.SBTTL		MSGAPC - append a character to a message.

;  R0 = pointer to the first chunk of the message
;  R1 = the character to append
;  R5 = pointer to this task's tcb
;
;  on return, C = 0 is ok, C = 1 means out of chunks.
;	note: MSGAPC will not fail for translate tasks - only for TENTSK and
;		BSC tasks.

MSGAPC:	DEC	MSGCNT(R0)	;check for room left
	BGE	10$		;yes - continue
	CALL	MSGCYC		;no - get another chunk
	BCC	MSGAPC
	RETURN

10$:	MOVB	R1,@MSGPTR(R0)	;store character in chunk
	INC	MSGPTR(R0)	;point to next position
	INC	@MSGCLP(R0)	;increment count in last chunk
	INC	MSGLEN(R0)	; count one more char in message
	TRACE	TRCXLD,<R1,R0,R5> ;trace character written
	CLC			;indicate all ok
	RETURN


; here if the last chunk has run out.

MSGCYC:	SAVE	<R1,R0>
	MOV	@MSGLCH(R0),R0	;any pre-allocated chunks?
	BNE	13$		;yes, use them.
12$:	CALL	GETSTG		;get a hunk - will wait if not bsc task
	BCS	14$		;branch if unable to get it
13$:	RESTOR	R1		;point r1 to message
	MOV	R0,@MSGLCH(R1)	;append chunk to list of chunks
	MOV	R0,MSGLCH(R1)	;new chunk is last chunk
	ADD	#CHLEN,R0	;point to count field in chunk
	MOV	R0,MSGCLP(R1)	;store pointer to count field
	ADD	#CHDAT-CHLEN,R0	;point to data part of chunk
	MOV	R0,MSGPTR(R1)	;point to front of chunk
	MOV	R1,R0		;put message pointer in r0
	MOV	#CHDATL,MSGCNT(R0) ;mark new chunk empty
	RESTOR	R1		;restore character to store
	CLC
	RETURN

; here if we run out of chunks.  give error return.

14$:	RESTOR	<R0,R1>
	SEC			;flag failure
	RETURN
	.SBTTL		MSGAPN - append block of characters to a message

;	R0/message ptr
;	R1/character to be written
;	R2/number to write
;	NOTE: MSGAPN will not fail for translate tasks - only for TENTSK and
;		BSC tasks.


MSGAPN:	SAVE	<R3,R4>		;append block of repeated character
	TRACE	TRCXLD,<R1,R0,R2,R5>;TRACE CHARACTER WRITTEN

10$:	MOV	MSGPTR(R0),R3	;get buffer ptr
	MOV	MSGCNT(R0),R4	;get remaining space in current chunk
	BGT	20$		;room left
15$:	CALL	MSGCYC		;need more space
	BCC	10$		;got it - keep going
	BR	35$		;lost in the end

20$:	MOVB	R1,(R3)+	;stuff one more
	INC	@MSGCLP(R0)	;INCREMENT COUNT IN LAST CHUNK
	INC	MSGLEN(R0)	;COUNT ONE MORE CHAR IN MESSAGE
	DEC	R4		;count character into message
	BGT	25$		;more left
	DEC	R2		;current chunk full - check if done
	BGT	15$		;no - get more space
	BR	30$		;yes - wind it up

25$:	SOB	R2,20$		;space left in chunk - count character

30$:	MOV	R3,MSGPTR(R0)	;satisfied request - update msg parameters
	MOV	R4,MSGCNT(R0)
	CLC			;this request suc'd

35$:	RESTOR	<R4,R3>		;go away
	RETURN
	.SBTTL		GETMHD,CREATM and other message utilities

GETMHD:	CALL	GETCHK		;create message header, no waiting
	BCC	MHDINI		;init it
	RETURN

CREATM:	CALL	GETSTG		;create message header, wait for it
	BCC	MHDINI		;init it
	RETURN

MHDINI:	CALL	CLRMHD		;R0/message header - init for filling message
	MOV	#MHDATL,MSGCNT(R0);header has this much space for data
	MOV	R0,MSGCLP(R0)
	ADD	#CHLEN,MSGCLP(R0);ptr to counter for current chunk

FMSGI:	MOV	R0,MSGLCH(R0)	;R0/message header - init for unloading
	MOV	R0,MSGPTR(R0)	;header is current chunk
	ADD	#MHDAT,MSGPTR(R0);point to 1st full byte
	CLC			;this return sucs
	RETURN

	.ENABL	LSB
CLRCHK:	SAVE	<R0,R1>		;clear a chunk
	MOV	#CHSIZE/2,R1	;no. of words in a chunk

10$:	CLR	(R0)+
	SOB	R1,10$

	RESTOR	<R1,R0>
	RETURN

CLRMHD:	SAVE	<R0,R1>		;clear message header
	MOV	#MSGHDL/2,R1	;no. words in header
	BR	10$
	.DSABL	LSB

CNTMSG:	CLR	-(SP)		;count length of message in R0
	TST	R0
	BR	20$
10$:	INC	(SP)		;count current chunk
	MOV	(R0),R0		;get next one
20$:	BNE	10$
	MOV	(SP)+,R0	;get final count
	RETURN
	.SBTTL		MSGAPE - return unused pre-allocated chunks

;  at the end of a message.

; R0 = pointer to the first chunk of the message

MSGAPE:	MOV	@MSGLCH(R0),R1	;any unused pre-alloacted chunks?
	BEQ	11$		;no.
	MOV	R0,-(SP)	;yes, save pointer to message
	CLR	@MSGLCH(R0)	;remove pointer to unused chunks
	MOV	R1,R0		;put pointer to unused chunks in r0
	CALL	FREMSG		;send it the unused chunks to free
	MOV	(SP)+,R0	;restore pointer to message
11$:	RETURN