.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, 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, 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, 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 ;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 RETURN RCVEND: MOV TCLCB(R5),R0 ;wait out the end of the input message TRACE TRCDQF, 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, 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, ;trace character written CLC ;indicate all ok RETURN ; here if the last chunk has run out. MSGCYC: SAVE 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 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 ;append block of repeated character TRACE TRCXLD,;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 ;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 ;clear a chunk MOV #CHSIZE/2,R1 ;no. of words in a chunk 10$: CLR (R0)+ SOB R1,10$ RESTOR RETURN CLRMHD: SAVE ;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