Trailing-Edge
-
PDP-10 Archives
-
BB-D351C-SM_3-16-83
-
sources/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