                     	.TITLE	KB
;
;	VERSION	V005A
;		001
;
;	KEYBOARD AND TELEPRINTER DRIVER - PART 1
;
;	THE KB DRIVER IS IN THREE PARTS TO FACILITATE
;	PAPER TAPE HANDLING.
;
;	COPYRIGHT 1973,1974 DIGITAL EQUIPMENT CORP. MAYNARD MASS. 
;
;
;	GLOBAL DEFINITIONS
;
	.GLOBL	CMDST	;KB KEYBOARD TYPE-AHEAD BUFFER.
	.GLOBL	KB	;KB DRIVER.
	.GLOBL	KBDDB	;KB KEYBOARD DDB.
	.GLOBL	K.ENFL	;KEYBOARD END-OF-FILE FLAG(BYTE).
	.GLOBL	TPDDB	;KB TELEPRINTER DDB.
;
;	GLOBAL REFERENCES
;
	.GLOBL	DV.A2	;CREATE A002 MESSAGE SUBROUTINE.
	.GLOBL	HSASI	;HIGH SPEED ACTIVATE SUBROUTINE.
	.GLOBL	KBBUF	;ADDRESS OF KB KEYBOARD EXEC BUFFER.
	.GLOBL	OPERT	;OPERR TASK AND SLOT NUMBER.
	.GLOBL	PAN$	;PANIC DUMP ADDRESS.
	.GLOBL	SRTI	;COMMON SYSTEM  EXIT.
	.GLOBL	STRG	;COMMON SYSTEM  ENTRY SUBROUTINE.
	.GLOBL	SY.DFL	;DDB-FLAG BYTE.
	.GLOBL	SY.DPR	;DDB-PERMANENT DDB BIT.
	.GLOBL	SY.DWN	;DDB-DEVICE IS DOWN FLAG (NOT READY).
	.GLOBL	SY.MUD	;DRIVER MULTI-ACCESS BIT.
	.GLOBL	SY.RES	;DDB-RESERVED FLAG.
	.GLOBL	SY.RTN	;DDB-TASK DDB RESERVED FOR (BYTE)
	.GLOBL	SY.TO	;DDB-TIME OUT COUNT (0=NOT ACTIVE)
	.GLOBL	TKI.CS	;ADDRESS OF LIST OF KB&TT INPUT STATUS REGISTER
	.GLOBL	TKO.CS	;ADDRESS OF LIST OF KB&TT OUTPUT STATUS REGISTE
	.GLOBL	TPBUF	;ADDRESS OF KB OUTPUT EXEC BUFFER.
	.GLOBL	TTOPT	;TT OPERATOR TASK SLOT NUMBER.
	.GLOBL	UTILT	;UTILITY TASK SLOT.
                        
R0=%0
R1=%1
R2=%2
R3=%3
R4=%4
R5=%5
SP=%6
PC=%7
;
;	KEYBOARD PREAMBLE
;
KB:	.WORD	0		;DDB PTR
	.BYTE	KB.BP		;FACILITIES
	.BYTE	1		;TERMINAL DEVICE
	.BYTE	4		;BUFF SIZE/16
	.BYTE	KB.INT-KB	;INTERRUPT ENTRY
	.BYTE	200		;PRIORITY=4
	.BYTE	KB.OP-KB	;OPEN
	.BYTE	KB.TF-KB	;TRANSFER
	.BYTE	KB.CL-KB	;CLOSE
	.BYTE	0		;SPECIAL FCN
	.BYTE	KB.TB-KB	;MISCELLANEOUS ENTRY
KB.NM:	.RAD50	/KB/		;NAME
;
;	TELEPRINTER PREAMBLE
;
KBO:	.WORD	0		;DDB PTR
	.BYTE	KBO.BP+SY.MUD	;FACILITIES
	.BYTE	1		;TERMINAL DEVICE
	.BYTE	4		;BUFF SIZE/16
	.BYTE	KBO.IN-KBO	;INTERRUPT ENTRY
	.BYTE	200		;PRIORITY=4
	.BYTE	KBO.OP-KBO	;OPEN
	.BYTE	KBO.TF-KBO	;TRANSFER
	.BYTE	KBO.CL-KBO	;CLOSE
	.BYTE	0		;SPECIAL FCN
	.BYTE	KBO.TB-KBO	;MISCELLANEOUS ENTRY
KBO.NM:	.RAD50	/KB/
;MISCELLANEOUS ENTRY DISPATCH TABLE FOR KEYBOARD
KB.TB:	0
	0
	0
	KB.S	;CANCEL
;MISCELLANEOUS ENTRY DISPATCH TABLE FOR PRINTER
KBO.TB:	0
	KBO.TO	;TIME OUT
	0
	0
	.IFNDF	TK.NOU
TK.NOU=0
	.ENDC
	.IFNZ	TK.NOU
;
;	MULTI-KEYBOARD/TELEPRINTER DRIVER
;
;	GLOBAL DEFINITIONS
;
	.GLOBL	TODDB	;TT TELEPRINTER DDB.
	.GLOBL	TT	;TT DRIVER.
	.GLOBL	TTDDB	;TT KEYBOARD DDB.
;
;	GLOBAL REFERENCES
;
	.GLOBL	TKBUF	;ADDRESS OF TT KEYBOARD EXEC BUFFER.
	.GLOBL	TOBUF	;ADDRESS OF TT OUTPUT EXEC BUFFER.
;
;PARAMETER TK.NOU DEFINES THE NUMBER OF UNITS
;
;
;	KEYBOARD PREAMBLE
TT:TK:	.WORD	0		;DDB POINTER ON ENTRY
	.BYTE	TK.BP		;FACILITIES
	.BYTE	1		;TERMINAL DEVICE
	.BYTE	4		;STD BUFF SIZE
	.BYTE	TK.INT-TK	;INTERRUPT ENTRY
	.BYTE	200+TK.NOU-1	;PRIORITY 4 PLUS MAX UNIT NUMBER.
	.BYTE	TK.OP-TK	;OPEN
	.BYTE	TK.TF-TK	;TRANSFER
	.BYTE	TK.CL-TK	;CLOSE
	.BYTE	0		;SPECIAL FCN
	.BYTE	TK.TB-TK	;MISCELLANEOUS ENTRY

TK.NM:	.RAD50	/TT/		;NAME
;	TELEPRINTER PREAMBLE
TKO.TF=TT.TF			;TRANSFER
TKO.INT=TT.INT			;INTERRUPT
TKO:	.WORD	0		;DDB PTR
	.BYTE	TKO.BP+SY.MUD	;FACILITIES
	.BYTE	1		;TERMINAL DEVICE
	.BYTE	4		;STD BUFF SIZE
	.BYTE	TKO.INT-TKO	;INTERRUPT ENTRY
	.BYTE	200+TK.NOU-1	;PRIORITY 4 PLUS MAX UNIT #
	.BYTE	TKO.OP-TKO	;OPEN
	.BYTE	TKO.TF-TKO	;TRANSFER
	.BYTE	TKO.CL-TKO	;CLOSE
	.BYTE	0		;SPECIAL FCN
	.BYTE	TKOTB-TKO	;MISCELLANEOUS ENTRY
TKO.NM:	.RAD50 	/TT/		;NAME
;MISCELLANEOUS ENTRY DISPATCH TABLE FOR TT KEYBOARD
TK.TB:	0
	0
	0
	TT.S	;CANCEL
;MISCELLANEOUS ENTRY DISPATCH TABLE FOR TT PRINTER
TKOTB:	0
	TKO.TO	;TIME OUT
	0
	0
	.ENDC
;	TRANSFERS TO KB
KB.INT:	JMP	KB.INA		;INTERRUPT
KB.OP:	JMP	KB.OPA		;OPEN
KB.CL=KB.OP			;CLOSE
KB.TF:	JMP	KB.TFA		;TRANSFER
	.IFNZ	TK.NOU
;	TRANSFERS TO TT KEYBOARD
TK.INT:	JMP	TK.INA		;INTERRUPT
TK.OP:	JMP	TK.OPA		;OPEN
TK.CL:	JMP	TK.CLA		;CLOSE
TK.TF:	JMP	TK.TFA		;TRANSFER
	.ENDC
;
;	PARAMETERS
;
	.IFNDF	KBSZ
KBSZ=72.			;KEYBOARD TYPE AHEAD BUFFER SIZE
	.ENDC
	.IFNDF	EBSZ
EBSZ=10.			;ECHO BUFFER SIZE
	.ENDC
S.STAT=-2			;ADDRESS OF STATUS REGISTER
KBO.BP=322			;FACILITIES=OUTPUT, ASCII, OPEN, CLOSE
TKO.BP=322
KB.BP=324			;FACILITIES=INPUT, ASCII, OPEN, CLOSE
TK.BP=324
;
;	CONSOLE OUTPUT OPEN ENTRY
;
KBO.OP:				;USE CLOSE ENTRY.
;
;	CONSOLE OUTPUT CLOSE ENTRY
KBO.CL:	MOV	#-2,R5		;UNIT #
	.IFNZ	TK.NOU
	BR	TKO.CA
;
;	NON-CONSOLE OUTPUT CLOSE AND OPEN.
TKO.OP:
TKO.CL:	CLR	TKO		;NOT BUSY
	JSR	PC,TT.GU	;GET UNIT #
	.ENDC
TKO.CA:	MOV	#-2,R4		;PREPARE TO OUTPUT CR,LF
	MOV	#KBO.CR,TKO.BF(R5)  ;SET DATA POINTER
	BR	TKO.A		;CONTINUE AS NORMAL TRANSFER.
;
;	CONSOLE OUTPUT TRANSFER ENTRY
;
KBO.TF:	MOV	#-2,R5		;UNIT #
	.IFNZ	TK.NOU
	BR	TT.TFA		;JOIN NON-CONSOLE ENTRY.
;	NON-CONSOLE OUTPUT TRANSFER ENTRY
;
TT.TF:	CLR	TKO		;NOT BUSY
	JSR	PC,TT.GU	;GET UNIT #
	.ENDC
TT.TFA:	MOV	6(R0),TKO.BF(R5) ;SET INTERNAL DATA POINTER.
	MOV	10(R0),R4	;GET WORD COUNT.
	ASL	R4		;CHANGE TO BYTE COUNT
TKO.A:
	MOV	R4,TKO.CT(R5)	;SET INTERNAL COUNT.
	MOV	R0,TKO.TS(R5)	;SAVE THE DDB POINTER.
	MOVB	#-2,SY.TO(R0)	;ENABLE TIME OUT
	BIS	#100,@TKO.CS(R5)	;ENABLE INTERRUPT
	RTS	PC
;
;CONSOLE OUTPUT TIME OUT
KBO.TO:	MOV	#-2,R5		;UNIT #
	.IFNZ	TK.NOU
	BR	TT.INC
;NON CONSOLE TIME OUT
TKO.TO:	JSR	PC,TT.GU	;GET UNIT #
	.ENDC
	BR	TT.INC		;TRY AGAIN
;
;	CONSOLE OUTPUT INTERRUPT ENTRY
;
KBO.IN:	JSR	R5,STRG		;SAVE REGISTERS
	SUB	PC,R5		;SET CONSOLE UNIT NUMBER
	.IFNZ	TK.NOU
	BR	TT.INB		;JOIN NON-CONSOLE ENTRY                        
;
;	NON-CONSOLE OUTPUT INTERRUPT ENTRY
;
TT.INT:	MOV	S.STAT,TT.TMP	;SAVE CURRENT STATUS TO GET UNIT #.
	JSR	R5,STRG		;SAVE REGISTERS.
	MOV	(PC)+,R5	;GET UNIT #
TT.TMP:	0
	JSR	PC,TT.GUA	;GO SAVE UNIT #
	.ENDC
TT.INB:	MOV	#SRTI,-(SP)	;DRIVER EXIT ADDRESS
	MOV	TKO.TS(R5),R0	;DDB ADDRESS
	CLR	SY.TO(R0)	;NO TIME OUT
TT.INC:	MOVB	#200,S.STAT	;DROP PRIORITY
	CLR	@TKO.CS(R5)	;DISABLE INTS.
	MOV	TKO.TS(R5),R0	;GET PROPER DDB POINTER.
	TSTB	TKO.TP(R5)	;REPEAT OUTPUT IN PROGRESS.
	BEQ	.+6
	JMP	TKO.T		;YES-
	MOVB	@K.MPTR(R5),R2	;SOMETHING IN SPECIAL OUTPUT STRING?
	BNE	TKO.JI		;IF NE, YES, GO PRINT IT
	MOVB	CCTMP(R5),R2	;CONTROL CHARACTER TO OUTPUT?
	BNE	TKO.JJ		;YES-
TKO.JA:	TSTB	EF(R5)		;ECHO IN PROGRESS?
	BMI	TKO.JB		;YES-
TKO.JH:	INC	TKO.CT(R5)	;COUNT THIS CHARACTER
	BGT	TKO.B		;DONE-
	MOVB	@TKO.BF(R5),R2	;GET CHARACTER FOR OUTPUT.
	INC	TKO.BF(R5)	;ADVANCE DATA POINTER.
TKO.JG:	MOV	#KO.MA,R4	;GET POINTER TO CHECK STRING
	CMPB	R2,(R4)+	;CR?
	BEQ	TKO.DX		;
	CMPB	R2,(R4)+	;LF?
	BEQ	TKO.H		;
	CMPB	R2,(R4)+	;NULL?
	BEQ	TKO.JA		;YES-IGNORE
	CMPB	R2,#177		;R/O?
	BEQ	TKO.JA		; YES-IGNORE.
	CMPB	R2,(R4)+	;OVER 40 (PRINTING?)
	BHIS	TKO.F		;YES-GO PRINT
	CMPB	R2,(R4)+	;TAB?
	BEQ	TKO.ST
	CMPB	R2,(R4)+	;VT?
	BEQ	TKO.FB		;YES-
	CMPB	R2,(R4)+	;FF?
	BEQ	TKO.KA		;YES
	CMPB	R2,(R4)+	;BELL?
	BEQ	TKO.F		;YES- PRINT IT
	CMPB	R2,(R4)+	;BACKSPACE?
	BEQ	TKO.F		;YES-PRINT IT
                        ;CONTROL CHARACTER FOUND-PRINT ^ CHAR.
;PUT ASSOCIATED CHARACTER INTO CCTMP FOR OUTPUT NEXT.
;
	ADD	#100,R2		;CONVERT CONTROL CHARACTER TO R
	MOVB	R2,CCTMP(R5)	;AND SET IT FOR OUTPUT NEXT.
	MOVB	#'^,R2		;GET AN UP ARROW
	BR	TKO.F		;GO PRINT.
;
;	DETECTED A FORM FEED - SET UP TO REPEAT 8 LF'S
;
TKO.KA:	MOV	#5010,TKO.TB(R5) ;SET TABLE FOR LF IN HIGH ORDER
				;AND "8" IN LOW ORDER
	BR	TKO.T		;INITIATE EXECUTION
;
;OUTPUT NEXT ECHO CHARACTER
;
TKO.JB:	DECB	EC(R5)		;ANY CHARACTER TO OUTPUT?
	BMI	TKO.JC		;NO-DONE WITH ECHO
	MOV	EPO(R5),R1	;GET A CHARACTER FROM THE BUFFER
	MOVB	(R1)+,R2
	BMI	TKO.JD		;BRANCH TO OUTPUT A BACKSLASH
	JSR	PC,K.CWR	;CHECK PTR FOR WRAP AROUND TO
	MOV	R1,EPO(R5)	;AND PUT BACK.
	BR	TKO.JG		;CONTINUE AS NORMAL CHARACTER.
                        
;
;ECHO DONE-SEE IF TRANSFER IN PROGRESS.
TKO.JC:	CLR	EF(R5)		;NO ECHO NOW. ALSO CLEAR ECHO COUNT
	TST	TKO.CT(R5)	;ANY NORMAL OUTPUT TO DO?
	BLE	TKO.JH		;YES-GO DO IT.
	RTS	PC		;NO-EXIT
;
;OUTPUT A "\" FOR RUBOUT ECHO. PUT OUT CURRENT CHARACTER NEXT TIME.
TKO.JD:	BIC	#-177-1,R2	;SAVE LOW 7 BITS OF CHARACTER.
	MOVB	R2,-(R1)	;PUT BACK INTO ECHO BUFFER.
	MOVB	#'\,R2		;GET A BACKSLASH.
	INCB	EC(R5)		;FUDGE COUNT BACK.
	BR	TKO.JG		;NORMAL FROM HERE.
;
;	OUTPUT CHARACTERS FROM SPECIAL STRING FOR CNTRL-U AND
;	CNTRL-C
;
;
TKO.JI:	INC	K.MPTR(R5)	;ADVANCE THE POINTER
	BR	TKO.JG		;GO PROCESS FOR OUTPUT.
;	OUTPUT SECOND CHAR OF CNTRL-CHAR.  CLEAR CURRENT CHARACTER.
;
;
TKO.JJ:	CLRB	CCTMP(R5)	;CLEAR THE CHARACTER STORAGE.
	TSTB	EF(R5)		;IS ECHO IN PROGRESS?
	BPL	TKO.JG		;NO - GO PRINT JUST THE CHARACTER.
	CMPB	R2,#125		;YES - CHECK FOR CNTRL-U.
	BEQ	TKO.JK
	.IFNZ	TK.NOU
	TST	R5		;MUST ALSO BE CONSOLE.
	BPL	TKO.JM		;NOT CONSOLE-
	.ENDC
	CMPB	R2,#103		;MAYBE A CNTRL-C?
	BNE	TKO.JG		;NO - GO PRINT
	MOV	#KO.MB,K.MPTR(R5)	;SET PTR TO SPECIAL STRING.
	BR	TKO.JG		;FOR CNTRL-C
;
TKO.JM:	CMPB	R2,#130		;IS IT A CONTROL X?
	BNE	TKO.JG		;IF NE, NOT ^X - GO PRINT THE CHAR
;
TKO.JK:	MOV	#KO.MA,K.MPTR(R5)	;SPECIAL STRING FOR CNTRL-U.
	BR	TKO.JG
;
TKO.DX:	BR	TKO.D		;AUX. BRANCH
;
TKO.F:	MOV	TKO.CS(R5),R1	;GET ADR OF TELEPRINTER STATUS REGISTER
	MOVB	#-2,SY.TO(R0)	;ENABLE TIME OUT
	BIS	#100,(R1)+	;ENABLE INTERRUPT
	MOVB	R2,(R1)		;OUTPUT CHARACTER.
TKO.EX:	RTS	PC
;
;	OPERATION DONE.
;
TKO.B:
	CLR	@TKO.CS(R5)	;DISABLE INTERRUPTS
	JMP	@14(R0)		;COMPLETION EXIT
;
;	ROUTINE TO OUTPUT A CHAR "N" TIMES
;
TKO.ST:	MOV	#20010,TKO.TB(R5) ;SET "SPACE" AND REPEAT COUNT IN LOW ORDER
TKO.T:	MOVB	TKO.TP(R5),R2	;GET REPEAT CHARACTER
	BIC	#177600,R2	;CLEAR EXTRA BITS
	DECB	TKO.TB(R5)	;LAST REPEAT?
	BGT	TKO.F		;IF GT BRANCH TO PRINT
	CLR	TKO.TB(R5)	;RESET COUNT AND FLAG.
	CMP	#12,R2		;IF REPEAT CHAR = LF...
	BNE	TKO.F		;IF NE, BRANCH TO DO LAST REPEAT
TKO.H:	NEGB	EF(R5)		;OTHERWISE, RE-ENABLE ECHO PROCESS
	BGT	.-4
	MOVB	TKO.LF(R5),TKO.TB(R5) ;SET <LF> FILL COUNT
TKO.H1:	BEQ	TKO.F		;IF EQ, NO FILL -- GO OUTPUT TERMINATOR
	MOVB	#200,TKO.TP(R5)	;SET "REPEAT" INDICATOR
	BR	TKO.F		;GO DO LAST <LF> BEFORE DOING REPEAT NULLS
;
;	VT COMES HERE
;
TKO.FB:	NEGB	EF(R5)		;SET ECHO FLAG.
	BGT	.-4
	JMP	TKO.JA		;IGNORE VT
;
;	SET UP TO FILL NULLS AFTER <CR> IS OUTPUT
;
TKO.D:	MOVB	TKO.FC(R5),TKO.TB(R5) ;SET <CR> FILL COUNT
	BR	TKO.H1		;GO DO <CR> BEFORE STARTING REPEAT NULLS
	.IFNZ	TK.NOU

;
;	COME HERE ON CNTRL-X FROM NON CONSOLE KEYBOARD.
;
;	HALT ANY TASK INITER TO THE KEYBOARD
;	  AND CLEAR INPUT BUFFER.
;
KB.CX:	TST	R0		;ANY DDB POINTER?
	BEQ	KB.CXA		;NO-CAN'T BE INITED.
	BITB	#SY.RES,SY.DFL(R0);ANYONE INITED?
	BEQ	KB.CXA		;NO-SKIP TASK HALTING.
	MOVB	SY.RTN(R0),R2	;GET TASK #
	SWAB	R2		;PUT IN HIGH BYTE
	CLRB	R2
	INCB	R2		;OFF REQUEST IN LOW BYTE.
	MOVB	#UTILT,R0	;TASK INSEX TO R0
	JSR	R5,HSASI	;ACTIVATE TASK
	BR	KB.CXB		;ERROR
KB.CXA:	JSR	PC,KB.RES	;RESTORE INPUT POINTERS,FLAGS.
	MOVB	#30,R2		;PUT CNTRL/X IN R2
	BR	KB.INI		;GO ECHO CNTRL-X
KB.CXB:	JSR	PC,PAN$		;SYSTEM ERROR
	.EOT
                                                                                                            