                                                   ;	KEYBOARD AND TELEPRINTER DRIVER - PART 2
;
;	VERSION	V005A
;		001
;
;	COPYRIGHT 1973,1974 DIGITAL EQUIPMENT CORP. MAYNARD, MASS.
;
;	NON-CONSOLE INPUT INTERRUPT
;
TK.INA:	MOV	S.STAT,#0	;SAVE CURRENT STATUS
TK.INB=.-2
	JSR	R5,STRG		;SAVE REGISTERS
	MOV	TK.INB,R5	;GET STATUS
	JSR	PC,TT.GUA	;SAVE UNIT #
	BR	TK.INC		;JOIN CONSOLE
	.ENDC
;
;	CONSOLE INPUT INTERRUPT ENTRY
;
KB.INA:	JSR	R5,STRG		;SAVE REGISTERS
	SUB	PC,R5		;#-2 TO R5
TK.INC:	MOVB	#200,S.STAT	;DROP PRIORITY
	MOV	#SRTI,-(SP)	;DRIVE EXIT ADDRESS
	MOV	TKI.TS(R5),R0	;GET DDB POINTER
	MOV	TKI.CS(R5),R2	; GET ADDRESS OF STATUS REQ
	MOVB	2(R2),R2	;GET CHARACTER FROM KEYBOARD
	CMPB	EC(R5),#EBSZ	;ECHO BUFF FULL?
	BGE	TKO.EX		;YES-DROP THE CHARACTER
	BIC	#-177-1,R2	;SAVE LOW 7 BITS + IGNORE NULLS.
	BEQ	TKO.EX		;IGNORE NULLS.

	MOV	#KO.MA-1,R1	;SET ADR OF CHECK STRING
	.IFNZ	TK.NOU
	TST	R5		;CONSOLE?
	BMI	KB.INN		; YES-
	CMPB	R2,#30		;CNTRL-X?
	BEQ	KB.CX		;YES-GO TURN OFF CURRENT TASK
	BR	KB.INC		;GO INPUT THE CHARACTER
	.ENDC
KB.INN:
	CMPB	R2,(R1)	;CNTRL-C?
	BNE	.+6
	JMP	KB.INB	;YES-
	TSTB	(PC)+		;COMMAND MODE?
K.CCF:	.WORD	0
	BEQ	KB.INS		;NO-
;	COME HERE IF IN CNTRL-CMODE
	MOV	#-4,R5		;SWITCH TO UNIT -2
	BR	KB.INC
KB.INS:	BITB	#SY.RES,SY.DFL(R0);INITED?
	BEQ	KB.EX		;NO-EXIT
KB.INC:	JSR	PC,KB.CRP	;GET POINTERS
	TSTB	K.TRM(R5)	;IS BUFFER TERMINATOR SET?
	BNE	KB.EX		;BRANCH IF YES TO IGNORE CHAR
	CMPB	R2,-(R1)	;CNTRL-U?
	BEQ	KB.INH
	CMPB	R2,-(R1)	;RUBOUT?
	BEQ	KB.ING
	CMPB	#32,R2		;IS THIS CONTROL Z
	BNE	KB.XR2		;IF NE, NOT CONTROL Z
	INCB	K.ENFL(R5)	;SET EOD INDICATOR
	BR	KB.INI		;GO ECHO IT
KB.XR2:	MOV	#KBSZ-2,-(SP)	;CREATE POINTER TO END OF BUFFER.
	ADD	K.BUF(R5),(SP)
	CMP	(R4),(SP)+	;ROOM FOR ONE CHARACTER?
	BHI	KB.EX		;NO-DROP CURRENT CHARACTER.
KB.XR1:
	MOVB	R2,@(R4)+	;PUT CHARACTER INTO BUFFER
	INC	-(R4)		;UPDATE POINTER.
	DEC	K.CT(R5)	;DECR MAX USER BYTE COUNT
;
;	ECHO THE CHARACTER
;
KB.INI:	TSTB	K.ESF(R5)	;ECHO SUPPRESS?
	BNE	KB.INM		;YES-
	MOVB	K.ROM(R5),R1	;ADD RUBOUT MODE INTO CHARACTER FOR
	ADD	R1,R2		;PROPER ECHO.
	CLR	R3		;SET RUBOUT MODE PROPERLY
	ADD	R2,R1		;DEPENDING ON ORIGINAL MODE,
	TSTB	R1		;AND CURRENT CHARACTER.
	BPL	.+6
	MOV	#200,R3
	MOVB	R3,K.ROM(R5)
	MOV	R5,-(SP)	;SAVE CURRENT R5
	BPL	.+6		;SKIP IF POSITIVE
	MOV	#-2,R5		;ELSE, CHANGE -4 TO -2.
	MOV	EPI(R5),R1	;PUT CHARACTER INTO ECHO BUFFER
	MOVB	R2,(R1)+	;-ADVANCE POINTER.
	JSR	PC,K.CWR	;CHECK FOR WRAP AROUND.
	MOV	R1,EPI(R5)
	INCB	EC(R5)		;COUNT THE CHARACTER.
	CMPB	EC(R5),#EBSZ	;ECHO BUFFER FULL?
	BGE	KB.INV		;YES-FORCE ECHO OUT
	TSTB	EF(R5)		;ECHO FLAG SET?
	BNE	.+6		;YES-
	INCB	EF(R5)		;NO-SET IT TO +1.
	TSTB	TKO.CT(R5)	;XFER INPROGRESS?
	BLE	KB.INJ		;YES--
                            
KB.INV:	MOVB	#-1,EF(R5)	;NO-START ECHO OUT
	MOVB	#100,@TKO.CS(R5) ;AND START PRINTER.
KB.INJ:	BIC	#-177-1,R2	;GET ORIGINAL CHARACTER.
	MOV	(SP)+,R5	;GET ORIGINAL R5
KB.INM:	TSTB	K.OPF(R5)	;OPEN CALL?
	BNE	KB.INR		;YES-
	TSTB	K.ENFL(R5)	;IS EOD SET?
	BNE	KB.IM4		;IF NE EOD IS SET..GO START XFER
	TST	K.BC(R5)	;IS THIS UNSOLICITED INPUT?
	BGT	KB.IM1		;IF GT, IT IS UNSOLICITED
	BITB	#2,30(R0)	;UNFORMATTED TRANSFER?
	BEQ	KB.IM1		;BRANCH IF FORMATTED TRANSFER
	TST	K.CT(R5)	;DECREMENT USER BYTE COUNT
	BLE	KB.IM4		;IF LT, BRANCH TO START TRANSFER
KB.IM1:
	CMPB	R2,#15		;IF CHAR IS <CR>...
	BNE	KB.IM2	;
	MOV	#12,R2		;...CHANGE IT TO<LF>
	BR	KB.XR1		;AND GO ECHO IT
KB.IM2:
	CMPB	R2,#15		;NOW CHECK FOR LINE TERMINATORS
	BHI	KB.EX		;NO-
	CMPB	R2,#12		
	BLO	KB.EX		;NO-
	INCB	K.TRM(R5)	;SET TERMINATOR INDICATOR
	.IFNZ	TK.NOU
	TST	R5		;CONSOLE?
	BPL	KB.IM3		;NO-SKIP CNTRL-C TEST.
	.ENDC
	TSTB	K.CCF		;COMMAND MODE?
	BNE	KB.INK		;YES-GO START OPERATOR TASK
KB.IM3:	TST	K.BC(R5)	;IS THIS UNSOLICITED INPUT
	BGT	KB.INW		;IF GT, IT IS UNSOLICITED
	BITB	#2,30(R0)	;UNFORMATTED TRANSFER?
	BEQ	KB.INW		;BRANCH IF FORMATTED TRANSFER
	CLRB	K.TRM(R5)	;IF UNFORMATTED, CLEAR TERMINATOR
	BR	KB.EX		;AND EXIT
KB.IM4:	INCB	K.TRM(R5)	;SET BUFFER TERMINATOR
KB.INW:	TST	K.BC(R5)	;ELSE-CHECK IF A TRANSFER IS REQUESTED.
	BLE	KB.TFB		;GO DO TRANSFER
;	IF A NON-CONSOLE UNIT,CHECK IF INITED.
;	IF NOT,SCHEDULE A TASK(USER SUPPLIED)
	.IFNZ	TK.NOU
	TST	R5		;CONSOLE?
	BPL	KB.INU		; NO-GO CHECK.
	.ENDC
KB.EX:
	RTS	PC
;
KB.INH:	MOV	K.BUF(R5),(R4)	;CNTRL-U SEEN - RESET
	MOV	@2(R0),K.CT(R5)	;RESTORE MAX USER BYTE COUNT
	BR	KB.INI		;INPUT PTR.
;
KB.ING:	DEC	(R4)+		;RUB OUT SEEN - BACK UP INPUT POINTER
	MOVB	@-(R4),R2	;AND GET CHARACTER FOR ECHO.
	BEQ	KB.INL		;IF NULL, THIS IS BEGINNING OF BUFF - I
	BIS	#200,R2		;ELSE, SET HIGH BIT FOR "\" ECH
	INC	K.CT(R5)	;BUMP MAX USER BYTE COUNT
	BR	KB.INI
;
KB.INL:	INC	(R4)		;RESTORE INPUT PTR.
	RTS	PC
;
KB.INK:	CLRB	K.CCF		;EXIT FROM COMMAND MODE.
	SUB	#2,(R4)+	;BACK UP INPUT PTR
	CLRB	@-(R4)		;TERMINATE COMMAND LINE WITH NULL.
	JSR	PC,KB.RES	;RESET INPUT POINTERS
	CLR	R2		;NO DATA TO PASS
	MOVB	#OPERT,R0	;TASK INDEX TO R0
KB.IND:	JSR	R5,HSASI	;ACTIVATE TASK.
	RTS	PC
	RTS	PC
;	DATA FOR OPERATOR START CALL & NON CONSOLE OPERATOR TASK
                        
;
KB.INB:	MOVB	#-1,K.CCF	;CNTRL-C SEEN-SWITCH TO
	MOV	#-4,R5		;COMMAND MODE.
	JSR	PC,KB.RES
	JMP	KB.INI
;	OPEN CALL
KB.INR:	CLRB	K.OPF(R5)
	BR	KB.TFI
	.IFNZ	TK.NOU
;
KB.INU:	BITB	#SY.RES,SY.DFL(R0);INITED?
	BNE	KB.EX		;YES-EXIT TO WAIT FOR A READ.
	ASR	R5
	MOV	R5,R2		;DATA TO R2
	MOVB	#TTOPT,R0	;TASK INDEX TO R0
	BR	KB.IND		;GO START THE TASK
;
;	NON-CONSOLE INPUT TRANSFER
;
TK.TFA:	CLR	TK		;NOT BUSY
	JSR	PC,TT.GU	;GET UNIT #
	BR	TK.TFB		;JOIN CONSOLE
	.ENDC
;
;	CONSOLE INPUT TRANSFER ENTRY
;
KB.TFA:	MOV	#-2,R5		;UNIT #
TK.TFB:
	MOV	R0,TKI.TS(R5)	;SAVE DDB POINTER
	MOVB	12(R0),R4	;GET ECHO SUPPRESS BIT
	BIC	#-10-1,R4
	MOVB	R4,K.ESF(R5)	;PUT INTO FLAG.
	MOV	10(R0),R4	;SET BYTE COUNT
	ASL	R4
	MOV	R4,K.BC(R5)
	MOV	6(R0),K.DP(R5)	;SET DATA POINTER
	BITB	#2,30(R0)	;IS UNFORMATTED ASCII?
	BEQ	KBTR		;BRANCH IF FORMATTED
	MOV	@2(R0),K.CT(R5)	;GET USER MAX BYTE COUNT
	MOV	K.IN(R5),-(SP)	;TYPE AHEAD INPUT POINTER
	SUB	K.OUT(R5),(SP)	;CALCULATE BYTE COUNT OF CHARS
				;ALREADY TYPED
	SUB	(SP)+,K.CT(R5)	;IF MAX BYTE COUNT OVERFLOWED ...
	BLE	KB.TFB		;...BRANCH TO START TRANSFER
KBTR:				;..OTHERWISE CONTINUE TO PROCESS
	TSTB	K.TRM(R5)	;LINE AVAILABLE FOR TRANSFER?
	BNE	KB.TFB		;YES-GO TO IT.
	RTS	PC
KB.TFB:	MOV	#K.OUT,R4	;YES-SET POINTERS
	MOV	#K.BC,R3	;INTERNAL BYTE COUNT POINTER
	MOV	#K.DP,R1
	ADD	R5,R4		;ADJUST FOR UNIT #.
	ADD	R5,R3
	ADD	R5,R1
KB.TFH:	MOVB	@(R4)+,@(R1)+	;GET A CHARACTER
	INC	-(R4)		;ADVANCE POINTER
	INC	-(R1)		;ADVANCE POINTER
	CMP	(R4),K.IN(R5)	;ALL CHARS GONE?
	BHIS	KB.TFE		; YES-
	INC	(R3)		;NO  - IS REQUEST DONE?
	BLT	KB.TFH		;NO - GO GET ANOTHER CHARACTER.
	BR	KB.TFI		;YES - TAKE COMPLETION EXIT.
                                       KB.TFF:	CLRB	@(R1)+		;GIVE A NULL TO REQUESTOR
	INC	-(R1)		;ADVANCE POINTER
	TSTB	K.ENFL(R5)	;IS EOD FLAG SET?
	BNE	KB.TFG		;IF NE, FLAG IS SET
KB.TFE:	INC	(R3)		;BUMP INTERNAL BYTE COUNT
	BLT	KB.TFF		;INSERT A NULL IF LT
KB.TFG:	BIT	#1,(R3)		;BYTE COUNT EVEN?
	BEQ	KB.TFK		;IF EQ,BYTE COUNT IS EVEN
	INC	(R3)		;MAKE BYTE COUNT EVEN
KB.TFK:
	ASR	(R3)		;MAKE REMAINING BYTE COUNT A WORD COUNT
	MOV	(R3),16(R0)	;SET REMAINING BYTE COUNT
KB.TFJ:	JSR	PC,KB.RES	;RESET THE INDICATORS AND POINTERS
KB.TFI:	JMP	@14(R0)		;COMPLETION EXIT.
	.IFNZ	TK.NOU
;
;NON CONSOLE INPUT OPEN
;
TK.OPA:	CLR	TK		;NOT BUSY
	JSR	PC,TT.GU	;GET UNIT #
	BR	TK.OPC		;JOIN NORMAL OPEN/CLOSE
;
;	NON-CONSOLE INPUT CLOSE
;
TK.CLA:	CLR	TK		;NOT BUSY
	JSR	PC,TT.GU	;GET UNIT #
	BR	TK.OPB		;JOIN CONSOLE
	.ENDC
;
;	CONSOLE INPUT OPEN/CLOSE
;
KB.OPA:	MOV	#-2,R5		;UNIT #
TK.OPB:
	JSR	PC,KB.RES
TK.OPC:	MOV	#1,K.OPF(R5)	;SET OPEN FLAG AND CLEAR ECHO SUPPRESS 
	MOV	#15,R2		;GET A CR TO PUT INTO ECHO BUFF.
	.IFNZ	TK.NOU
	CMPB	EC(R5),#EBSZ	;ECHO BUFF FULL?
	BLT	TK.OPD		;NO-
	JMP	KB.INR		;YES-SKIP OUTPUT OF CR,LF
	.ENDC
TK.OPD:	JMP	KB.INI		;GO ECHO CR,LF
;	COME HERE IF END OF DATA SEEN.
	.IFNZ	TK.NOU
;NON CONSOLE CANCEL
TT.S:	JSR	PC,TT.GU	;GET UNIT #
	BR	KB.SA
	.ENDC
;CONSOLE CANCEL
KB.S:	MOV	#-2,R5		;UNIT #
KB.SA:
	MOV	#-2,16(R0)	;FORCE NON-ZERO BYTE COUNT AND EXIT
	BR	KB.TFJ		;EXIT.
;	PUT POINTERS TO IN AND OUT POINTERS INTO R4 AND R3
KB.CRP:	MOV	R5,R4		;CREATE POINTERS TO BUFFER POINTERS
	MOV	R5,R3
	ADD	#K.IN,R4
	ADD	#K.OUT,R3
KBO.SX:	RTS	PC
;SUBROUTINE TO GET PTRS TO BUFF PTRS
;	AND TO RESET BUFF POINTERS,
;	TERMINATOR FLAG AND ECHO SUPPRESS FLAG
;
KB.RES:	JSR	PC,KB.CRP	;GET PTRS TO POINTERS.
	MOV	K.BUF(R5),(R3);RESET BUFF POINTERS.
	MOV	(R3),(R4)
	CLR	K.TRM(R5)	;NO TERMINATOR AND RUBOUT
	CLRB	K.ESF(R5)	;NO ECHO SUPPRESS
	CLRB	K.ENFL(R5)	;RESET EOD FLAG
	MOV	#1,K.BC(R5)	;RESET INTERNAL BYTE COUNT
	RTS	PC

;
;	CHECK FOR WRAP AROUND OF ECHO POINTER
;	CALL WITH		;R5=UNIT #
;	JSR	PC,K.CWR	;R1=PTR OF INTEREST
;				;BLOWS R3
;
K.CWR:	MOV	R1,R3		;FORM DIFFERENCE BETWEEN CURRENT
	SUB	EBP(R5),R3	;PTR AND BEGINNING OF BUFF.
	CMP	R3,#EBSZ	;GONE TOO FAR?
	BLT	.+4		;NO -
	SUB	R3,R1		;YES - BACK UP THE POINTER
	RTS	PC
;
;	ROUTINE TO FETCH UNIT #*2 FROM DDB
;
;	ALTERNATE ENTRY AT TT.GUA WILL FETCH
;	  UNIT #*2 FROM R5
;
;	CALL	JSR  PC,TT.GU	;R0=DDB ADDR.
;
;	OR CALL	JSR	PC,TT.GUA	;R5=UNIT #
;
TT.GU:	MOVB	13(R0),R5	;GET UNIT # FROM DDB
TT.GUA:	BIC	#-7-1,R5	;SAVE LOW 3 BITS
	ASL	R5		;CONVERT TO UNIT #*2
	RTS	PC
;
                        ;
;
;
;	DATA AREAS FOR CONSOLE AND NON-CONSOLE TELEPRINTERS
;
;	INTERNAL BYTE COUNT
	.WORD	1		;CONSOLE COUNT
TKO.CT:
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.WORD	1		;OTHER UNITS.
	.=TKO.CT+TK.NOU+TK.NOU
;	INTERNAL BUFFER POINTER
	.WORD	0		;CONSOLE
TKO.BF:
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.=TKO.BF+TK.NOU+TK.NOU
;	TAB COUNTERS AND FLAGS
	.WORD	0		;CONSOLE
TKO.TB:
TKO.TP=.+1
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.=TKO.TB+TK.NOU+TK.NOU
;
;	<CR> FILL COUNT
;
	.IFNDF	KBCR
KBCR=0
	.ENDC
;
	.IFNDF	TT0CR
TT0CR=0
	.ENDC
;
	.IFNDF	TT1CR
TT1CR=0
	.ENDC
;
	.IFNDF	TT2CR
TT2CR=0
	.ENDC
;
	.IFNDF	TT3CR
TT3CR=0
	.ENDC
;
	.IFNDF	TT4CR
TT4CR=0
	.ENDC
;
	.IFNDF	TT5CR
TT5CR=0
	.ENDC
;
	.IFNDF	TT6CR
TT6CR=0
	.ENDC
;
	.IFNDF	TT7CR
TT7CR=0
	.ENDC
;
;
;	<LF> FILL COUNT
;
	.IFNDF	KBLF
KBLF=0
	.ENDC
;
	.IFNDF	TT0LF
TT0LF=0
	.ENDC
;
	.IFNDF	TT1LF
TT1LF=0
	.ENDC
;
	.IFNDF	TT2LF
TT2LF=0
	.ENDC
;
	.IFNDF	TT3LF
TT3LF=0
	.ENDC
;
	.IFNDF	TT4LF
TT4LF=0
	.ENDC
;
	.IFNDF	TT5LF
TT5LF=0
	.ENDC
;
	.IFNDF	TT6LF
TT6LF=0
	.ENDC
;
	.IFNDF	TT7LF
TT7LF=0
	.ENDC
;
	.BYTE	KBCR,KBLF		;CONSOLE
TKO.FC:
TKO.LF=TKO.FC+1
	.BYTE	TT0CR,TT0LF		;REMAINING TERMINALS 0-7
	.BYTE	TT1CR,TT1LF
	.BYTE	TT2CR,TT2LF
	.BYTE	TT3CR,TT3LF
	.BYTE	TT4CR,TT4LF
	.BYTE	TT5CR,TT5LF
	.BYTE	TT6CR,TT6LF
	.BYTE	TT7CR,TT7LF
;
	.=TKO.FC+TK.NOU+TK.NOU
;
;	STORE FOR DDB POINTERS
;
	.WORD	0		;CONSOLE
TKO.TS:
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.WORD	0		;OTHER UNITS
	.=TKO.TS+TK.NOU+TK.NOU
;
;	KEYBOARD DATA AREAS
;
;
;	STORE FOR DDB POINTERS
	.WORD	0
TKI.TS:
	.WORD	0
	.WORD	0
	.WORD	0
	.WORD	0
	.WORD	0
	.WORD	0
	.WORD	0
	.WORD	0
	.=TKI.TS+TK.NOU+TK.NOU
;	ECHO FLAG/ECHO COUNT
	.WORD	0		;CONSOLE
EF:	EC=.+1
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.=EF+TK.NOU+TK.NOU
;
;	STORAGE FOR USER MAX BYTE COUNT
;
	.WORD	0		;CONSOLE COMMAND MODE
	.WORD	0		;CONSOLE INPUT TRAN
K.CT:
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.WORD	0		;NON-CONSOLE
	.=K.CT+TK.NOU+TK.NOU
	.EOT
                                                                                                                                                   