.TITLE MOSTTY - TERMINAL INTERFACE HANDLERS .INSRT ../moscnf-1.sml .INSRT ../mosmac.sml .INSRT ../mostbl.sml $CNFIG $DFDCT $DFIOR $DFIST .GLOBL .TTYIN .GLOBL .TTYOT .GLOBL TTYINI .GLOBL TTYOTI .GLOBL .TTYUP .GLOBL .CTYUP .GLOBL .CTYIN .GLOBL $IOCMP ;I/O TRANSFER COMPLETION ROUTINE .GLOBL $MTTTP,$MTTBT ;CODE TOP/BOTTOM .CSECT MOS .PAGE .SBTTL TERMINAL HANDLERS .SBTTL .TTYUP - TERMINAL DEVICE INITIALIZATION ; ; CALLED WITH: R2 - ADDR OF DCT ; $MTTTP: .TTYUP: MOV #100,@DCTCSR(R2) ;ENABLE INTERRUPTS .CTYUP: CLR DCTRC(R2) ;RESET RING BUFFER BYTE COUNT $PUSH R1 MOV R2,R1 ADD #DCTRNG,R1 ;CALCULATE ADDR OF RING BUFFER START MOV R1,DCTHD(R2) ;SET HEAD & MOV R1,DCTTL(R2) ; TAIL POINTERS MOV R1,DCTFNT(R2) ;AND BUFFER LOW LIMIT ADD #DCTTLN-DCTRNG,R1 ;CALCULATE BUFFER HI ADDRESS MOV R1,DCTEND(R2) $POP R1 CLRB DCTFLG(R2) ;RESET ALL DEVICE SPECIFIC FLAGS BIC #DF.OFL,DCTFLG(R2) ;AND MARK AS ON-LINE RTS PC .PAGE .SBTTL .TTYIN - TTY INPUT TRANSFER INITIALIZATION ROUTINE ; ; CALLED WITH: R0 - ADDR OF IORB ; R2 - ADDR OF DCT ; .CTYIN: .TTYIN: TST DCTRC(R2) ;TTY INPUT RING BUFFER EMPTY BNE 1$ ;IF NOT, COMPLETE REQUEST NOW RTS PC ;ELSE, WAIT FOR INPUT CHARACTERS 1$: MOVB @DCTHD(R2),@DCTUVA(R2) ;TRANSFER INPUT BYTE DEC DCTRC(R2) ;INDICATE 1 LESS IN RING BUFFER MOV #1,IRBX(R0) ;SET BYTE COUNT TO 1 INC DCTHD(R2) ;BUMP HEAD POINTER CMP DCTHD(R2),DCTEND(R2) ;REACHED END OF BUFFER? BLO 2$ ;IF NOT, SIP MOV DCTFNT(R2),DCTHD(R2) ;ELSE, RESET TO FRONT OF RING BUFFER 2$: MOV (SP),-(SP) ;DUPLICATE RETURN ADDRESS MOV #340,2(SP) ;SIMULATE INTERRUPT PS $PUSH R0 ;SAVE R0 MOV R2,R0 ;GET DCT ADDR JMP $IOCMP ;AND ENTER I/O COMPLETION .PAGE .SBTTL .TTYOT - TTY OUTPUT TRANSFER INITIALIZATION ROUTINE ; ; CALLED WITH: R0 - ADDR OF IORB ; R2 - ADDR OF DCT ; .TTYOT: MOV IRBR(R0),IRBX(R0) ;SET BYTES TRANSFERED CLRB DCTCRF(R2) ;RESET PADDING COUNTER $PUSH #340 ;SIMULATE INTERRUPT JSR PC,DCTIHX(R2) ;TO OUTPUT ROUTINE RTS PC .PAGE .SBTTL TTYOTI - TTY OUTPUT INTERRUPT SERVICE ROUTINE ; ; CALLED WITH: R0 - ADDRESS OF DCT ; (SP) - OLD R0 ; TTYOTI: TSTB DCTCRF(R0) ;NEED TO PAD AFTER CR BEQ 1$ ;IF NOT, SKIP CLR @DCTBUF(R0) ;OUTPUT A NULL CHARACTER DEC DCTCRF(R0) ;BUMP COUNTER BR 4$ ;AND EXIT 1$: BIT #DF.HLD,DCTFLG(R0) ;SHOULD WE HOLD OUTPUT? BEQ 2$ ;IF NOT, SKIP $PUSH R1 MOV DCTLNK(R0),R1 ;GET ASSOCIATED DCT ADDRESS BIS #DF.STP,DCTFLG(R1) ;INDICATE THAT WE HAVE STOPPED $POP R1 BR 4$ ;AND EXIT 2$: TST DCTBR(R0) ;CHECK BYTES REMAINING BEQ 5$ ;IF NONE, EXIT MOVB @DCTUVA(R0),@DCTBUF(R0) ;GET NEXT BYTE TO DATA REG CMPB @DCTUVA(R0),#15 ;WAS IT A CARRIAGE RETURN BNE 3$ ;IF NOT, SKIP MOVB #5,DCTCRF(R0) ;SET CR FILL COUNT 3$: INC DCTUVA(R0) ;BUMP POINTER ADDRESS DEC DCTBR(R0) ;AND DECREMENT BYTE COUNT 4$: $POP R0 ;RECOVER OLD R0 $RTT ;AND RETURN 5$: JMP $IOCMP ;AND FINISH I/O TRANSFER TTYOTS: $PUSH R0 ;SET-UP STACK MOV R1,R0 ;GET OUTPUT DCT ADDR BR TTYOTI ;AND ENTER INTERRUPT HANDLER .PAGE .SBTTL TTYINI - TTY INPUT INTERRUPT SERVICE ROUTINE ; ; CALLED WITH: R0 - ADDRESS OF DCT ; (SP) - OLD R0 ; TTYINI: $PUSH R1 MOV @DCTBUF(R0),R1 ;GET INPUT CHARACTER BIT #DF.HLD,DCTFLG(R0) ;OUTPUT BEING HELD? BEQ 3$ ;IF NOT, SKIP $PUSH R1 MOV DCTLNK(R0),R1 ;GET ASSOCIATED DCT ADDR BIC #DF.HLD,DCTFLG(R0) ;INDICATE OUTPUT NOT BEING HELD BIC #DF.HLD,DCTFLG(R1) ;INDICATE OUTPUT NOT BEING HELD BIT #DF.STP,DCTFLG(R0) ;HAS INTERRUPT ROUTINE STOPPED? BEQ 1$ ;IF NOT, JUST CLEAR HOLD FLAG BIC #DF.STP,DCTFLG(R0) ;CLEAR STOPPED FLAG $PUSH #340 ;SIMULATE INTERRUPT TO JSR PC,TTYOTS ; START OUTPUT GOING AGAIN 1$: $POP R1 2$: CMPB R1,#37 ;HOLD OUTPUT CHARACTER? BEQ 8$ ;IF SO, DON'T GIVETO USER BR 4$ ;ELSE, CHECK FOR ^O 3$: CMPB R1,#37 ;HOLD OUTPUT CHARACTER? BNE 4$ ;IF NOT, SKIP MOV DCTLNK(R0),R1 ;GET ASSOCIATED DCT ADDRESS BIS #DF.HLD,DCTFLG(R0) ;INDICATE OUTPUT SHOULD BE HELD, SET BIS #DF.HLD,DCTFLG(R1) ; IN BOTH DCTS BR 8$ ;AND EXIT W/O SIGNALLING W/ CHAR 4$: CMPB R1,#17 ;OUTPUT ABORT CHAR, CONTROL-O? BNE 6$ ;IF NOT, SKIP $PUSH R1 MOV DCTLNK(R0),R1 ;GET ASSOCIATED DCT ADDRESS CLR DCTBR(R1) ;INDICATE ALL BYTES TRANSFERRED MOV (R1),R1 ;GET CURRENT IORB ADDRESS BEQ 5$ ;IF NONE, SKIP MOV #I.ERR!I.FLSH,IRSTA(R1) ;INDICATE OUTPUT FLUSHED 5$: $POP R1 6$: TST (R0) ;CHECK FOR ACTIVE IORB BEQ 7$ ;IF NONE, ENQUEUE IN RING BUFFER MOVB R1,@DCTUVA(R0) ;TRANSFER THE BYTE MOV (R0),R1 ;GET IORB MOV #1,IRBX(R1) ; AND SET BYTE COUNT $POP R1 JMP $IOCMP ;AND INDICATE I/O COMPLETE 7$: CMP DCTRC(R0),#DCTTLN-DCTRNG ;SPACE LEFT IN BUFFER? BHIS 8$ ;IF NOT, SKIP MOVB R1,@DCTTL(R0) ;PLOP IN BYTE INC DCTRC(R0) ;BUMP COUNTER INC DCTTL(R0) ; AND TAIL POINTER CMP DCTTL(R0),DCTEND(R0) ;REACHED END OF BUFFER BLO 8$ ;IF NOT, SKIP MOV DCTFNT(R0),DCTTL(R0) ;ELSE, RESET POINTER 8$: $POP R1,R0 $RTT ;RETURN $MTTBT: .END