PAGE 118,121
TITLE KYBD ----- 06/10/85  KEYBOARD BIOS
.LIST
CODE	SEGMENT BYTE PUBLIC

	PUBLIC	K16
	PUBLIC	KEYBOARD_IO_1
	PUBLIC	KB_INT_1
	PUBLIC 	SND_DATA

	EXTRN	BEEP:NEAR
	EXTRN	DDS:NEAR
	EXTRN	START_1:NEAR
	EXTRN	K10:BTTE
	EXTRN	K11:BYTE
	EXTRN	K12:BYTE
	EXTRN	K13:BYTE
	EXTRN	K14:BYTE
	EXTRN	K15:BYTE
	EXTRN	K6:BYTE
	EXTRN	K6L:ABS
	EXTRN	K7:BYTE
	EXTRN	K8:BYTE
	EXTRN	K9:BYTE

;--- INT 16 H --------------------------------------------------------------------
; KEYBOARD I/O			:
;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT	:
; INPUT				:
;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,	:
;			RETURN THE RESULT IN	(AL), SCAN CODE IN (AH).	:
;					:
;	(AH)= 01H	SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS	:
;			AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	:
;			(ZF)= 1 -- NO CODE AVAILABLE	:
;			(ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER	:
;			IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS	:
;			IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.	:
;	(AH)= 02H	RETURN THE CURRENT SHIFT STATUS IN (AL) REGISTER	:
;			THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE	:
;			EQUATES FOR @KB_FLAG		:
; OUTPUT					:
;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	:
;	ALL REGISTERS RETAINED		:
;---------------------------------------------------------------------------------
	ASSUME	CS:CODE,DS:DATA

KEYBOARD_IO_1	PROC	FAR 	;>>> ENTRY POINT FOR ORG 0E82EH
	STI				; INTERRUPTS BACK ON
	PUSH	DS			; SAVE CURRENT DS
	PUSH	BX			; SAVE BX TEMPORARILY
	CALL	DDS			; ESTABLISH POINTER TO DATA REGION
	OR	AH,AH			; CHECK FOR (AH)= 00H
	JZ	K1B			; ASCII_READ
	DEC	AH			; CHECK FOR	(AH)= 01H
	JZ	K2			; ASCII_STATUS
	DEC	AH			; CHECK FOR (AH)= 02H
	JZ	K3			; SHIFT STATUS
	POP	BX			; RECOVER REGISTER
	POP	DS
	IRET				; INVALID COMMAND EXIT

;-----	READ THE KEY TO FIGURE OUT WHAT TO DO

K1B:	MOV	BX,@BUFFER_HEAD		; GET POINTER TO HEAD OF BUFFER
	CMP	BX,@BUFFER_TAIL		; TEST END OF BUFFER
	JNE	K1C			; IF ANYTHING IN BUFFER SKIP INTERRUPT

	MOV	AX,09002H		; MOVE IN WAIT CODE A TYPE
	INT	15H			; PERFORM OTHER FUNCTION
K1:					; ASCII READ
	STI				; INTERRUPTS BACK ON DURING LOOP
	NOP				; ALLOW AN INTERRUPT TO OCCUR
K1C:	CLI				; INTERRUPTS BACK OFF
	MOV	BX,@BUFFER_HEAD		; GET POINTER TO HEAD OF BUFFER
	CMP	BX,@BUFFER_TAIL		; TEST END OF BUFFER
	PUSH	BX			; SAVE ADDRESS
	PUSHF				; SAVE FLAG
	CALL	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
	MOV	BL,@KB_FLAG_2		; GET PREVIOUS BITS
	XOR	BL,AL			; SEE IF ANY DIFFERENT
	AND	BL,KB_LEDS		; ISOLATE INDICATOR BITS
	JZ	K1A			; IF NO CHANGE BYPASS UPDATE

	CALL	SND_LED1		; GO TURN ON MODE INDICATORS
	CLI				; DISABLE INTERRUPTS
K1A:	POPF				; RESTORE FLAGS
	POP	BX			; RESTORE ADDRESS
	JZ	K1			; LOOP UNTIL SOMETHING IN BUFFER

	MOV	AX,[BX]			; GET SCAN CODE AND ASCII CODE
	CALL	K4			; MOVE POINTER TO NEXT POSITION
	MOV	@BUFFER_HEAD,BX		; STORE VALUE IN VARIABLE

	POP	AX			; RECOVER REGISTER
	POP	DS			; RECOVER SEGMENT
	IRET				; RETURN TO CALLER

;-----	ASCII STATUS
K2:
	CLI				; INTERRUPTS OFF
	MOV	BX,@BUFFER_HEAD		; GET HEAD POINTER
	CMP	BX,@BUFFER_TAIL		; IF EQUAL (Z=1) THEN NOTHING THERE
	MOV	AX,[BX]
	PUSHIF				; SAVE FLAGS
	PUSH	AX			; SAVE CODE
	CALL	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
	MOV	BL,@KB_FLAG_2		; GET PREVIOUS BITS
	XOR	BL,AL			; SEE IF ANY DIFFERENT
	AND	BL,KB_LEDS		; ISOLATE INDICATOR BITS
	JZ	SK2			; IF NO CHANGE BYPASS UPDATE

	CALL	SND_LED1		; GO TURN ON MODE INDICATORS
SK2:	POP	AX			; RESTORE CODE
	POPF				; RESTORE FLAGS
	STI				; INTERRUPTS BACK ON
	POP	BX			; RECOVER REGISTER
	POP	DS			; RECOVER SEGMENT
	RET	2			; THROW AWAY FLAGS

;-----	SHIFT STATUS

K3:
	MOV	AL,@KB_FLAG		; GET THE SHIFT STATUS FLAGS
	POP	BX			; RECOVER REGISTER
	POP	DS			; RECOVER REGISTERS
	IRET				; RETURN TO CALLER
KEYBOARD_IO_1 	ENDP

;-----	INCREMENT A BUFFER POINTER

K4	PROC	NEAR
	INC	BX			; MOVE TO NEXT WORD IN LIST
	INC	BX
	CMP	BX,@BUFFER_END		; AT END OF BUFFER?
	JNE	K5			; NO, CONTINUE
K5T	MOV	BX,@BUFFER_START	; YES, RESET TO BUFFER BEGINNING
	RET
K4	ENDP

;--- HARDWARE INT 09 H - ( IRQ LEVEL 1 )------------------------------------------
;
;	KEYBOARD INTERRUPT ROUTINE
;
;---------------------------------------------------------------------------------

KB_INT_1 PROC 	FAR
	STI				; ENABLE INTERRUPTS
	PUSH	BP
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	DI
	PUSH	DS
	PUSH	ES
	CLD				; FORWARD DIRECTION
	CALL	DDS			; SET UP ADDRESSING

;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED

	MOV	AL,DIS_KBD		; DISABLE THE KEYBOARD COMMAND
	CALL	SHIP_IT			; EXECUTE DISABLE
	CLI				; DISABLE INTERRUPTS
	SUB	CX,CX			; SET MAXIMUM TIMEOUT
KB_INT_01:
	IN	AL,STATUS_PORT		; READ ADAPTER STATUS
	TEST	AL,INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
	LOOPNZ	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED

;-----	READ CHARACTER FROM KEYBOARD INTERFACE

	IN	AL,PORT_A		; READ IN THE CHARACTER

I ----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INTERRUPT LEVEL 9HI

	MOV	AH,04FH			; SYSTEM INTERCEPT - KEY CODE FUNCTION
	STC				; SET CY= 1 (IN CASE OF IRET)
	INT	15H			; CASSETTE CALL   (AL)= KEY SCAN CODE
					; RETURNS CY= 1 FOR INVALID FUNCTION
	JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)

	JMP	K26			; EXIT IF SYSTEM HANDLED SCAN CODE
					; EXIT HANDLES HARDWARE EOI AND ENABLE

;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD

KB_INT_02:				; 	  (AL)= SCAN CODE
	STI				; ENABLE INTERRUPTS AGAIN
	CMP	AL,KB_RESEND		; IS THE INPUT A RESEND
	JE	KB_INT_4		; GO IF RESEND

;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD

	CMP	AL,KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
	JNZ	KB_INT_2		; GO IF NOT

;-----	A COMMAND TO THE KEYBOARD WAS ISSUED

	CLI				; DISABLE INTERRUPTS
	OR	@KB_FLAG_2,KB_FA	; INDICATE ACK RECEIVED
	JMP	K26			; RETURN IF NOT (ACK RETURNED FOR DATA)

;-----	RESEND THE LAST BYTE

KB_INT_4:
	CLI				; DISABLE INTERRUPTS
	OR	@KB_FLAG_2,KB_FE	; INDICATE RESEND RECEIVED
	JMP	K26			; RETURN IF NOT TACK RETURNED FOR DATA)

KB_INT_2:

;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE

	PUSH	AX			; SAVE DATA IN
	CALL	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
	MOV	BL,@KB_FLAG_2		; GET PREVIOUS BITS
	XOR	BL,AL			; SEE IF ANY DIFFERENT
	AND	BL,KB_LEDS		; ISOLATE INDICATOR BITS
	JZ	UP0			; IF NO CHANGE BYPASS UPDATE

	CALL	SND_LED			; GO TURN ON MODE INDICATORS
UP0:	POP	AX			; RESTORE DATA IN
	MOV	AH,AL			; SAVE SCAN CODE IN AH ALSO

;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD

	CMP	AL,KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
	JNZ	K16			; NO, TEST FOR SHIFT KEY
	JMP	K62			; BUFFER_FULL_BEEP

;-----	THIS CODE CONTAINS THE KBX SUPPORT FOR INT 09H

;	EQUATES
F11_M	EQU	217			; FUNC 11 MAKE
F11_B	EQU	215			; FUNC 11 BREAK
F12_M	EQU	218			; FUNC 12 MAKE
F12_B	EOU	216			; FUNC 12 BREAK
K102_M	EQU	86			; KEY 102 MAKE
K102_B	EQU	214			; KEY 102 BREAK

INS_M	EQU	82			; INSERT KEY MAKE
DEL_M	EQU	83			; DELETE KEY MAKE
LEFT_M	EQU	75			; CURSOR LEFT MAKE
RIGHT_M	EQU	77			; CURSOR RIGHT MARE
UP_M 	EQU	72			; CURSOR UP MAKE
DN_M	EQU	80			; CURSOR DOWN MAKE
PGUP_M	EQU	73			; PG UP MAKE
PGDN_M	EQU	81			; PG DN MAKE
HOME_M	EQU	71			; HOME MAKE
END_M	EQU	79			; END MAKE

FUNC11	EQU	133			; FUNCTION 11 KEY
HC	EQU	224			; HIDDEN CODE

;-----	TABLE OF KEYPAD CURSOR		; CONTROL KEYS

K_TAB1	DB	UP_M,DN_M,INS_M,DEL_M,LEFT_M,RIGHT_M
	DB	PGUP_M,PGDN_M,HOME_M,END_M
L_TAB1	EQU	$-K_TAB1

K16:
	AND	AL,07FH			; REMOVE BREAK BIT
	PUSH	CS
	POP	ES			; ESTABLISH ADDRESS OF TABLES

	TEST	@KB_FLAG_3,RD_ID+LC_AB	; ARE WE DOING A READ ID?
	JZ	NOT_ID			; CONTINUE IF NOT
	JNS	TST_ID_2		; IS THE RD_ID FLAG ON?
	CMP	AH,ID_1			; IS THIS THE 1ST ID CHARACTER?
	JNE	RST_RD_ID
	OR	@KB_FLAG_3,LC_AB	; INDICATE 1ST ID WAS OK
RST_RD_ID:
	AND	@KB_FLAG_3,NOT RD_ID	; RESET THE READ ID FLAG
	JMP	SHORT DO_EXT

TST_ID_2:
	AND	@KB_FLAG_3,NOT LC_AB	; RESET FLAG
	CMP	AH,ID_2			; IS THIS THE 2ND ID CHARACTER?
	JNE	DO_EXT			; LEAVE IF NOT

;-----	A READ ID SAID THAT IT WAS KBX

	OR	@KB_FLAG_3,KBX		; INDICATE KBX WAS FOUND
	TEST	@KB_FLAG_3,SET_NUM_LK	; SHOULD WE SET NUM LOCK?
	JZ	DO_EXT			; EXIT IF NOT
	OR	@KB_FLAG,NUM_STATE	; FORCE NUM LOCK ON
	CALL	SND_LED			; GO SET THE NUM LOCK INDICATOR
	JMP	SHORT EXIT

NOT_ID:
	TEST	@KB_FLAG_3,LC_HC	; WAS THE LAST CHARACTER A HIDDEN CODE
	JZ	NOT_LC_HC		; JUMP IF NOT

;-----	THE LAST CHARACTER WAS A HIDDEN CODE

	AND	@KB_FLAG_3,NOT LC_HC	; RESET LAST CHAR HIDDEN CODE FLAG
	CMP	AL,INS M		; WAS IT THE INSERT KEY?
	JE	NOT_I
	TEST	AH,80H			; IS THIS A BREAK CODE
	JNZ	EXIT			; IGNORE BREAK ON REST OF THESE KEYS
NOT_I:
	MOV	DI,OFFSET K_TAB1	; TEST FOR ONE OF THE KEYPAD CURSOR FUNC
	MOV	CX,L_TAB1
	REPNE	SCASB			; SCAN FOR THE KEY
	JNE	NOT_CUR			; GO ON IF NOT FOUND
	TEST	@KB_FLAG_1,HOLD_STATE	; ARE WE IN HOLD STATE?
	JZ	N_HLD
	AND	@KB_FLAG_1,NOT HOLD_STATE	; EXIT HOLD STATE
DO_EXT:
	JMP	SHORT EXIT		; IGNORE THIS KEY
N_HLD:
	TEST	@KB_FLAG,ALT_SHIFT	; IS ALT DOWN?
	JZ	NOT_ALT
	TEST	@KB_FLAG,CTL_SHIFT	; HOW ABOUT CTRL?
	JZ	EXIT			; IGNORE ALL IF ONLY ALT DOWN
	CMP	AL,DEL_M		; WAS IT THE DELETE KEY'
	JNE	EXIT			; IGNORE IF NOT
	JMP	K29			; GO DO THE CTL, ALT, DEL RESET

NOT_ALT:
	TEST	@KB_FLAG,CTL_SHIFT	; IS CTL DOWN?
	JNZ	CTL_ON			; SPECIAL CASE IF SO
	CMP	AL,INS_M		; IS THIS THE INSERT KEY?
	JNE	N_INS

;-----	SPECIAL HANDLING FOR INSERT KEY

	MOV	AL,AH			; RECOVER SCAN CODE
	MOV	AM,INS_SHIFT		; AH = MASK FOR INSERT
	TEST	AL,80H			; WAS THIS A BREAK CODE?
	JNZ	B_C
	JMP	K22			; GO HANDLE INSERT SHIFT

B_C:
	JMP	K24			; HANDLE BREAK
N_INS:
	JMP	K49			; HANDLE & IGNORE NUMLOCK
CTL_ON:
	CMPL	CL,5			; WAS IT INS, DEL, UP OR DOWN?
	JA	EXIT			; IGNORE IF DO
	JMP	K42			; GO HANDLE CTRL CASE

NOT_LC_HC:				; LAST CHARACTER WAS NOT A HIDDEN CODE
	CMP	AH,HC			; IS THIS CHARACTER A HIDDEN CODE?
	JNE	NOT_CUR
	OR	@KB_FLAG_3,LC_HC+KBX	; SET LAST CHAR WAS A HIDDEN CODE & KOX
EXIT:
	JMP	K26			; THROW AWAY THIS CODE

NOT_CUR:
	CMP	AH,F11_M		; WAS IT F11?
	JNE	T_F12			; HANDLE IF SO
	MOV	CL,FUNC11		; SET BASE FUNCTION 11
	JMP	SHORT DO_FN
T_F12:
	CMP	AH,F12_M		; WAS IT F12?
	JNE	T_SYS_KEY		; GO TEST FOR SYSTEM KEY
	MOV	CL,FUNC11+1		; SET BASE FUNCTION 12
DO_FN:
	CMP	AH,F11_B		; IS THIS A BREAK CODE
	JE	EXIT			; IGNORE SPEAK CODES
	CMP	AH,F12_B		; IS THIS A BREAK CODE
	JE	EXIT			; IGNORE BREAK CODES
	TEST	@KB_FLAG_1,HOLD_STATE	; ARE WE IN HOLD STATE?
	JZ	N_HLD1
	AND	@KB_FLAG_1,NOT HOLD_STATE	; EXIT HOLD STATE
	JMP	SHORT EXIT		; IGNORE THIS KEY
N_HLD1:
	MOV	AH,CL

	TEST	@KB_FLAG,ALT_SHIFT	; ARE WE IN ALT
	JZ	T_CTL
	ADD	AH,6			; CNVT TO ALT FN 11-12
	JMP	SHORT SET_FN
T_CTL:
	TEST	@KB_FLAG,CTL_SHIFT	; ARE WE IN CTRL
	JZ	T_SHF
	ADD	AH,4			; CNVT TO CTRL FN 11-12
	JMP	SHORT SET_FN
T_SHF:
	TEST	@KB_FLAG,LEFT_SHIFT+RIGHT_SHIFT	; IS EITHER SHIFT ON?
	JZ	SET_FN
	ADD	AH,2			; CNVT TO SHIFT FN 11-12
SET_FN:
	SUB	AL,AL			; FORCE PSEUDO SCAN CODE
	JMP	K61			; PUT IT INTO BUFFER

;-----	TEST FOR SYSTEM KEY

T_SYS_KEY:
	CMP	AL,SYS_KEY		; IS IT THE SYSTEM KEY?
	JNZ	K16A			; CONTINUE IF NOT

	TEST	AH,080H			; CHECK IF THIS A BREAK CODE
	JNZ	K16C			; DO NOT TOUCH SYSTEM INDICATOR IF TRUE

	TEST	@KB_FLAG_1,SYS_SHIFT	; SEE IF IN SYSTEM KEY HELD DOWN 
	JNZ	K16B			; IF YES, DO NOT PROCESS SYSTEM INDICATOR

	OR	@KB_FLAG_1,SYS_SHIFT	; INDICATE SYSTEM KEY DEPRESSED
	MOV	AL,EOI			; END OF INTERRUPT COMMAND
	OUT	INTA00,AL		; SEND COMMAND TO INTERRUPT CONTROL PORT
					; INTERRUPT-RETURN-NO-EOI
	MOV	AL,ENA_KBD		; INSURE KEYBOARD 15 ENABLED
	CALL	SHIP_IT			; EXECUTE ENABLE
	MOV	AX,08500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
	STI				; MAKE SURE INTERRUPTS ENABLED
	INT	15H			; USER INTERRUPT
	JMP	K27A			; END PROCESSING
K16B:
	JMP	K26			; IGNORE SYSTEM KEY

K16C:
	AND	@KB_FLAG_1,NOT SYS_SHIFT	; TURN OFF SHIFT KEY HELD DOWN
	MOV	AL,EOI			; END OF INTERRUPT COMMAND
	OUT	INTA00,AL		; SEND COMMAND TO INTERRUPT CONTROL PORT
					; INTERRUPT-RETURN-NO-EOI
	MOV	AL,ENA_KBD		; INSURE KEYBOARD IS ENABLED
	CALL	SHIP_IT			; EXECUTE ENABLE
	MOV	AX,08501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
	STI				; MAKE SURE INTERRUPTS ENABLED
	INT	15H			; USER INTERRUPT
	JMP	K27A			; IGNORE SYSTEM KEY
K16A:
	MOV	DI,OFFSET K6		; SHIFT KEY TABLE
	MOV	CX,OFFSET K6L		; LENGTH
	REPNE	SCASB			; LOOK THROUGH THE TABLE FOR A MATCH
	MOV	AL,AH			; RECOVER SCAN CODE
	JE	K17			; JUMP IF MATCH FOUND
	JMP	K25			; IF NO MATCH, THEN SHIFT NOT FOUND

;------	SHIFT KEY FOUND
K17:
	SUB	DI,OFFSET K6+1		; ADJUST PTR TO SCAN CODE MATCH
	MOV	AH,CS:K7[DI]		; GET MASK INTO AH
	TEST	AL,80H			; TEST FOR BREAK KEY
	JZ	K17C			; BREAK_SHIFT_FOUND
	JMP	SHORT K23		; CONTINUE

;-----	DETERMINE SET OR TOGGLE
K17C:
	CMP	AH,SCROLL_SHIFT
	JAE	K18			; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY

;-----	PLAIN SHIFT KEY, SET SHIFT ON
	OR	@KB_FLAG,AH		; TURN ON SHIFT BIT
	JMP	K26			; INTERRUPT_RETURN

;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT

K18:					; SHIFT-TOGGLE
	TEST	@KB_FLAG, CTL_SHIFT	; CHECK CTL SHIFT STATE
	JNZ	K25			; JUMP IF CTL STATE

	CMP	AL,INS_KEY		; CHECK FOR INSERT KEY
	JNZ	K22			; JUMP IF NOT INSERT KEY
	TEST	@KB_FLAG, ALT_SHIFT	; CHECK FOR ALTERNATE SHIFT
	JNZ	K25			; JUMP IF ALTERNATE SHIFT

	TEST	@KB_FLAG, NUM_STATE	; CHECK FOR BASE STATE
	JNZ	K21			; JUMP IF NUM LOCK IS ON
	TEST	@KB_FLAG, LEFT_SHIFT+RIGHT_SHIFT
	JZ	K22			; JUMP IF BASE STATE

K20:					; NUMERIC ZERO, NOT INSERT KEY
	MOV	AX, 5230H		; PUT OUT AN ASCII ZERO
	JMP	K57			; BUFFER FILL
K21:					; MIGHT BE NUMERIC
	TEST	@KB_FLAG, LEFT_SHIFT+RIGHT_SHIFT
	JZ	K20			; JUMP NUMERIC, NOT INSERT

K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
	TEST	AH,@KB_FLAG_1		; IS KEY ALREADY DEPRESSED
	JZ	K22A0			; GO IF NOT
	JMP	SHORT K26		; JUMP IF KEY ALREADY DEPRESSED
K22A0:
	ON	@KB_FLAG_1,AH		; INDICATE THAT THE KEY IS DEPRESSED
	XOR	@KB_FLAG,AH		; TOGGLE THE SHIFT STATE

;-----	TOGGLE LED IF CAPS OR NUM KEY DEPRESSED

	TEST	AH,CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT	; SHIFT TOGGLE?
	JZ	K228			; GO IF NOT

	PUSH	AX			; SAVE SCAN CODE AND SHIFT MASK
	CALL	SND_LED			; GO TURN MODE INDICATORS ON
	POP	AX			; RESTORE SCAN CODE
K22B:
	CMP	AL,INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
	JNE	K26			; JUMP IF NOT INSERT KEY
	MOV	AX,INS_KEY*H		; SET SCAN CODE INTO AH, 0 INTO AL
	JMP	K57			; PUT INTO OUTPUT BUFFER

;-----	BREAK SHIFT FOUND

K23:					; BREAK-SHIFT-FOUND
	CMP	AH,SCROLL_SHIFT		; IS THIS A TOGGLE KEY
	JAE	K24			; YES, HANDLE BREAK TOGGLE
	NOT	AH			; INVERT MASK
	AND	@KB_FLAG,AH		; TURN OFF SHIFT BIT
	CMP	AL,ALT_KEY+80H		; IS THIS ALTERNATE SHIFT RELEASE
	JNE	K26			; INTERRUPT_RETURN

;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER

	MOV	AL,@ALT_INPUT
	MOV	AH,0			; SCAN CODE OF 0
	MOV	@ALT_INPUT,AH		; ZERO OUT THE FIELD
	CMP	AL,0			; WAS THE INPUT=0
	JE	K26			; INTERRUPT_RETURN
	JMP	K58			; IT WASN'T, SO PUT IN BUFFER

K24:					; BREAK-TOGGLE
	NOT	AH			; INVERT MASK
	AND	@KB_FLAG_1,AH		; INDICATE NO LONGER DEPRESSED
	JMP	SHORT K26		; INTERRUPT_RETURN

;-----	TEST FOR HOLD STATE

K25:					; NO-SHIFT-FOUND
	CMP	AL,80H			; TEST FOR BREAK KEY
	JAE	K26			; NOTHING FOR BREAK CHARS FROM HERE ON
	TEST	@KB_FLAG_1,HOLD_STATE	; ARE WE IN HOLD STATE
	JZ	K28			; BRANCH AROUND TEST IF NOT
	CMP	AL,NUM_KEY
	JE	K26			; CAN'T END HOLD ON NUM_LOCK
	AND	@KB_FLAG_1,NOT HOLD_STATE	; TURN OFF THE HOLD STATE BIT

K26:					; INTERRUPT-RETURN
	CLI				; TURN OFF INTERRUPTS
	MOV	AL,EOI			; END OF INTERRUPT COMMAND
	OUT	INTA00,AL		; SEND COMMAND TO INTERRUPT CONTROL PORT
K27:					; INTERRUPT-RETURN-NO-EOI
	MOV	AL,ENA_KBD		; INSURE KEYBOARD IS ENABLED
	CALL	SHIP_IT			; EXECUTE ENABLE
K27A:
	CLI				; DISABLE INTERRUPTS
	POP	ES			; RESTORE REGISTERS
	POP	DS
	POP	DI
	POP	SI
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	POP	BP
	IRET				; RETURN, INTERRUPTS ON WITH FLAG CHANGE

;-----	NOT IN	HOLD STATE

K28:					; NO-HOLD-STATE
	TEST	@KB_FLAG,ALT_SHIFT	; ARE WE IN ALTERNATE SHIFT
	JNZ	K29			; JUMP IF ALTERNATE SHIFT
	JMP	K38			; JUMP IF NOT ALTERNATE

;-----	TEST FOR CONTROL KEY AND RESET KEY SEQUENCE (CTL ALT DEL)

K29:					; TEST-RESET
	TEST	@KB_FLAG,CTL_SHIFT	; ARE WE IN CONTROL SHIFT ALSO
	JZ	K31			; NO RESET
	CMP	AL,NUM_KEY		; CHECK FOR INVALID NUM LOCK KEY
	JE	K26			; THROW AWAY IF (ALT-CTL)+NUM-LOCK
	CMP	AL,SCROLL_KEY		; CHECK FOR INVALID SCROLL-LOCK KEY
	JE	K2B			; THROW AWAY IF (ALT-CTL)+SCROLL_LOCK
	CMP	AL,DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
	JNE	K31			; NO-RESET

;-----	CTL-ALT-DEL HAS BEEN FOUND
	MOV	@RESET_FLAG,1234H	; SET FLAG FOR RESET FUNCTION
	JMP	START_1			; JUMP TO POWER ON DIAGNOSTICS

;-----	ALT-INPUT-TABLE
K30	LABEL	BYTE
	DB	82,79,80,81,75,76
	DB	77,71,72,73		; 10 NUMBERS ON KEYPAD

;----- 	SUPER-SHIFT-TABLE
	DB	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
	DB	22,23,24,25,30,31
	DB	32,33,34,35,36,37
	DB	38,44,45,46,47,48
	DB	49,50

;-----	IN ALTERNATE SHIFT, RESET NOT FOUND

K31:					; NO-RESET
	CMP	AL,57			; TEST FOR SPACE KEY
	JNE	K32			; NOT THERE
	MOV	AL,' '			; SET SPACE CHAR
	JMP	K57			; BUFFER_FILL

;-----	LOOK FOR KEY PAD ENTRY

K32:					; ALT-KEY-PAD
	MOV	DI,OFFSET K30		; ALT-INPUT-TABLE
	MOV	CX,10			; LOOK FOR ENTRY USING KEYPAD
	REPNE	SCASB			; LOOK FOR MATCH
	JNE	K33			; NO_ALT_KEYPAD
	SUB	DI01,OFFSET K30+1	; DI-NOW-HAS ENTRY VALUE
	MOV	AL,@ALT_INPUT		; GET THE CURRENT BYTE
	MOV	AH,10			; MULTIPLY BY 10
	MUL	AH
	ADD	AX,DI			; ADD IN THE LATEST ENTRY
	MOV	@ALT_INPUT,AL		; STORE IT AWAY
	JMP	K26			; THROW AWAY THAT KEYSTROKE

;-----	LOOK FOR SUPERSHIFT ENTRY

K33:					; NO-ALT-KEYPAD
	MOV	@ALT_INPUT,0		; ZERO ANY PREVIOUS ENTRY INTO INPUT
	MOV	CX,26			; (DI),(ES) ALREADY POINTING
	REPNE	SCASB			; LOOK FOR MATCH IN ALPHABET
	JNE	K34			; NOT FOUND, FUNCTION KEY OR OTHER
	MOV	AL,0			; ASCII CODE OF ZERO
	JMP	K57			; PUT IT IN THE BUFFER

;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT

K34Z					; ALT-TOP-ROW
	CMP	AL,2			; KEY WITH '1' ON IT
	JE	K35			;  NOT ONE OF INTERESTING KEYS
	CMP	AL,14			;  IS IT IN THE REGION
	JAE	K35			;  ALT-FUNCTION
	ADD	AH,118			;  CONVERT PSEUDO SCAN CODE TO RANGE
	MOV	AL,0			;  INDICATE AS SUCH
	JMP	K57			;  BUFFER_FILL

;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES

K35:					; ALT-FUNCTION
	CMP	AL,59			; TEST FOR IN TABLE
	JAE	K37			; ALT-CONTINUE
K36:					; CLOSE-RETURN
	JMP	K26			; IGNORE THE KEY
K37:					; ALT-CONTINUE
	CMP	AL,71			; IN KEYPAD REGION
	JAE	K36			; IF SO, IGNORE
	MOV	BX,OFFSET K13		; ALT SHIFT PSEUDO SCAN TABLE
	JMP	K63			; TRANSLATE THAT

;-----	NOT IN ALTERNATE SHIFT

K38T					; NOT-ALT-SHIFT
	TEST	@KB_FLAG,CTL_SHIFT	; ARE WE IN CONTROL SHIFT
	JZ	K44			; NOT-CTL-SHIFT

;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
;-----	TEST FOR BREAK AND PAUSE KEYS

	CMP	AL,SCROLL_KEY		; TEST FOR BREAK
	JNE	K39			; NO-BREAK
	MOV	BX,@BUFFER_START	; RESET BUFFER TO EMPTY
	MOV	@BUFFER_HEAD,BX
	MOV	@BUFFER_TAIL,BX
	MOV	@BIOS_BREAK,80H		; TURN ON @BIOS_BREAK BIT

;-----	ENABLE KEYBOARD

	MOV	AL,ENA_KBD		; ENABLE KEYBOARD
	CALL	SHIP_IT			; EXECUTE ENABLE
	INT	1BH			; BREAK INTERRUPT VECTOR
	SUB	AX,AX			; PUT OUT DUMMY CHARACTER
	JMP	K57			; BUFFER_FILL

K39:					; NO_BREAK
	CMP	AL,NUM_KEY		; LOOK FOR PAUSE KEY
	JNE	K41			; NO-PAUSE
	OR	@KB_FLAG_1,HOLD_STATE	; TURN ON THE HOLD FLAG

;-----	ENABLE KEYBOARD
	MOV	AL,ENA_KBD		; ENABLE KEYBOARD
	CALL	SHIP_IT			; EXECUTE ENABLE
	MOV	AL,EOI			; END OF INTERRUPT TO CONTROL PORT
	OUT	INTA00,AL		; ALLOW FURTHER KEYSTROKE INTERRUPTS

;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON

	CMP	@CRT_MODE,7		; IS THIS THE MONOCHROME CARD
	JE	K40			; YES, NOTHING TO DO
	MOV	DX,03D8H		; PORT FOR COLOR CARD
	MOV	AL,@CRT_MODE_SET	; GET THE VALUE OF THE CURRENT MODE
	OUT	DX,AL			; SET THE CRT MODE, SO THAT CRT 15 ON

;-----	SUSPEND SYSTEM OPERATION (LOOP) TILL NEXT KEY CLEARS HOLD STATE FLAG

K40:					; PAUSE-LOOP
	TEST	@KB_FLAG_1,HOLD_STATE	; CHECK HOLD STATE FLAG
	JNZ	K40			; LOOP UNTIL FLAG TURNED OFF

	JMP	K27A			; INTERRUPT_RETURN_NO_EOI

;-----	TEST SPECIAL CASE KEY 55
K41:					; NO-PAUSE
	CMP	AL,55
	JNE	K42			; NOT-KEY-55
	MOV	AX,114*H		; START/STOP PRINTING SWITCH
	JMP	K57		; BUFFER_FILL

;-----	SET UP TO TRANSLATE CONTROL SHIFT
K42:					; NOT-KEY-55
	MOV	BX,OFFSET K8		; SET UP TO TRANSLATE C7L
	CMP	AL,59			; IS IT IN TABLE
	JS	K56			; YES, GO TRANSLATE CHAR
					; CTL-TABLE-TRANSLATE
	MOV	BX,OFFSET K9		; CTL TABLE SCAN
	JMP	K63			; TRANSLATE_SCAN

;-----	NOT IN CONTROL SHIFT

K44:					; NOT-CTL-SHIFT
	CMP	AL,71			; TEST FOR KEYPAD REGION
	JAE	K48			; HANDLE KEYPAD REGION
	TEST	@KB_FLAG,LEFT_SHIFT+RIGHT_SHIFT
	JZ	K54			; TEST FOR SHIFT STATE

;-----	UPPER CASE, HANDLE SPECIAL CASES

	CMP	AL,15			; BACK TAB KEY
	JNE	K45			; NOT-BACK-TAB
	MOV	AX,15*H			; SET PSEUDO SCAN CODE
	JMP	SHORT K57		; BUFFER_FILL

K45:					; NOT-BACK-TAB
	CMP	AL,55			; PRINT SCREEN KEY
	JNE	K46			; NOT-PRINT-SCREEN

;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION

	MOV	AL,ENA_KBD		; INSURE KEYBOARD IS ENABLED
	CALL	SHIP_IT			; EXECUTE ENABLE
	MOV	AL,EOI			; END OF CURRENT INTERRUPT
	OUT	INTA00,AL		; SO FURTHER THINGS CAN HAPPEN
	PUSH	BP			; SAVE POINTER
	INT	05H			; ISSUE PRINT SCREEN INTERRUPT
	POP	BP			; RESTORE POINTER
	JMP	K27			; GO BACK WITHOUT EOI OCCURRING

K46:					; NOT-PRINT-SCREEN
	CMP	AL,59			; FUNCTION KEYS
	JS	K47			; NOT-UPPER-FUNCTION
	MOV	BX,OFFSET K12		; UPPER CASE PSEUDO SCAN CODES
	JMP	K63			; TRANSLATE_SCAN

K47:					; NOT-UPPER-FUNCTION
	MOV	BX,OFFSET K11		; POINT TO UPPER CASE TABLE
	JMP	SHORT K56		; OK, TRANSLATE THE CHAR

;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION

K48:					; KEYPAD-REGION
	TEST	@KB_FLAG,NUM_STATE	; ARE WE IN NUM LOCK
	JNZ	K52			; TEST FOR SURE
	TEST	@KB_FLAG,LEFT_SHIFT+RIGHT_SHIFT		; ARE WE IN SHIFT STATE
	JNZ	K53			; IF SHIFTED, REALLY NUM STATE

;-----	BASE CASE FOR KEYPAD

K49:					; BASE-CASE
	CMP	AL,74			; SPECIAL CASE FOR A COUPLE OF KEYS
	JE	K50			; MINUS
	CMP	AL,78
	JE	K51
	SUB	AL,71			; CONVERT ORIGIN
	MOV	BX,OFFSET K15		; BASE CASE TABLE
	JMP	K64			; CONVERT TO PSEUDO SCAN
K50:
	MOV	AX,74*H+'-'		; MINUS
	JMP	SHORT K57		; BUFFER_FILL
K51:
	MOV	AX,78*H+'+'		; PLUS
	JMP	SHORT K57		; BUFFER_FILL

;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS

K52:					; ALMOST-NUM-STATE
	TEST	@KB_FLAG,LEFT_SHIFT+RIGHT_SHIFT
	JNZ	K49			; SHIFTED TEMP OUT OF NUM STATE

K53:					; REALLY NUM STATE
	SUB	AL,70			; CONVERT ORIGIN
	MOV	BX,OFFSET K14		; NUM STATE TABLE
	JMP	SHORT K56		; TRANSLATE_CHAR

;-----	PLAIN OLD LOWER CASE 

K54:					; NOT-SHIFT
	CMP	AL,59			; TEST FOR FUNCTION KEYS
	Jb	K55			; NOT-LOWER-FUNCTION
	MOV	AL,0			; SCAN CODE IN AH ALREADY
	JMP	SHORT K57 		; BUFFER_FILL

K55:					; NOT-LOWER-FUNCTION
	MOV	BX,OFFSET K10		; LC TABLE

;-----	TRANSLATE THE CHARACTER

K56:					; TRANSLATE-CHAR
	DEC	AL			; CONVERT ORIGIN
	XLAT	CS:K11			; CONVERT THE SCAN CODE TO ASCII

;-----	PUT CHARACTER INTO BUFFER

K57:					; BUFFER_FILL
	CMP	AL,-1			; IS THIS AN IGNORE CHAR
	JE	K59			; YES, DO NOTHING WITH IT
	CMP	AH,-1			; LOOK FOR -1 PSEUDO SCAN
	JA	K59			; NEAR_INTERRUPT_RETURN

;-----	HANDLE THE CAPS LOCK PROBLEM

K58:					; BUFFER_FILL-NOTEST
	TEST	@KB_FLAG,CAPS_STATE	; ARE WE IN CAPS LOCK STATE
	JZ	K61			; SKIP IF NOT

;-----	IN CAPS LOCK STATE

	TEST	@KB_FLAG,LEFT_SHIFT+RIGHT_SHIFT		; TEST FOR SHIFT STATE
	JZ	K60			; IF NOT SHIFT, CONVERT LOWER TO UPPER

;-----	CONVERT ANY UPPER CASE TO LOWER CASE

	CMP	AL,'A'			; FIND OUT IF ALPHABETIC
	JB	K61			; NOT-CAPS-STATE
	CMP	AL,'Z'
	JA	K61			; NOT_CAPS STATE
	ADD	AL,'a'-'A'		; CONVERT TO LOWER CASE
	JMP	SHORT K61		; NOT_CAPS_STATE
	
K59:					; NEAR-INTERRUPT-RETURN
	JMP	K26			; INTERRUPT_RETURN

;-----	CONVERT ANY LOWER CASE TO UPPER CASE

K60:					; LOWER-TO-UPPER
	CMP	AL,'a'			; FIND OUT IF ALPHABETIC
	JB	K61			; NOT_CAPS_STATE
	CMP	AL,'z'
	JA	K61			; NOT CAPS STATE
	SUB	AL,'a'-'A'		; CONVERT TO UPPER CASE

K61:					; NOT-CAPS-STATE
	MOV	BX,@BUFFER_TAIL		; GET THE END POINTER TO THE BUFFER
	MOV	SI,BX			; SAVE THE VALUE
	CALL	K4			; ADVANCE THE TAIL
	CMP	BX,@BUFPER_HEAD		; HAS THE BUFFER WRAPPED AROUND
	JE	K62			; BUFFER_FULL_BEEP
	MOV	[SI],AX			; STORE THE VALUE
	MOV	@BUFFER_TAIL,BX		; MOVE THE POINTER UP
	CLI				; TURN OFF INTERRUPTS
	MOV	AL,EOI			; END OF INTERRUPT COMMAND
	OUT	INTA00,AL		; SEND COMMAND TO INTERRUPT CONTROL PORT
	MOV	AL,ENA_KBD		; INSURE KEYBOARD IS ENABLED
	CALL	SHIP_IT			; EXECUTE ENABLE
	MOV	AX,09102H		; MOVE IN POST CODE & TYPE
	INT	15H			; PERFORM OTHER FUNCTION
	JMP	K27A			; INTERRUPT_RETURN

;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES

K63:					; TRANSLATE-SCAN
	SUB	AL,59			; CONVERT ORIGIN TO FUNCTION KEYS
K64:					; TRANSLATE-SCAN-ORGD
	XLAT	CS:K9			; CTL TABLE SCAN
	MOV	AH,AL			; PUT VALUE INTO AH
	MOV	AL,0			; ZERO ASCII CODE
	JMP	K57			; PUT IT INTO THE BUFFER
KB_INT_1	ENDP

K62:
	MOV	AL,EOI			; ENABLE INTERRUPT CONTROLLER CHIP
	OUT	INTA00,AL
	MOV	CX,678			; DIVISOR FOR 1760 HZ
	MOV	BL,4			; SHORT BEEP COUNT (1/16  1/64 DELAY)
	CALL	BEEP			; GO TO COMMON BEEP HANDLER
	JMP	K27			; EXIT

;---------------------------------------------------------------------------------
; SND_DATA
;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
;	HANDLES ANY RETRIES IF REQUIRED
;---------------------------------------------------------------------------------
SND_DATA PROC 	NEAR
	PUSH	AX			; SAVE REGISTERS
	PUSH	BX
	PUSH	CX
	MOV	BH,AL			; SAVE TRANSMITTED BYTE FOR RETRIES
	MOV	BL,3			; LOAD RETRY COUNT SOOT
	CLI				; DISABLE INTERRUPTS
	AND	@KB_FLAG_2,NOT (KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS

;-----	WAIT FOR ANY PENDING COMMAND TO BE ACCEPTED
	SUB	CX,CX			; MAXIMUM WAIT COUNT
SD1:
	IN	AL,STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
	TEST	AL,INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
	LOOPNZ	SD1			; WAIT FOR COMMAND TO BE ACCEPTED

	MOV	AL,BH			; REESTABLISH BYTE TO TRANSMIT
	OUT	PORT_A,AL		; SEND BYTE
	STI				; ENABLE INTERRUPTS
	MOV	CX,01A00H		; LOAD COUNT FOR 10 ms+
SD3:
	TEST	@KB_FLAG_2,KB_FE+KB_FA	; SEE IF EITHER BIT SET
	JNZ	SD7			; IF SET, SOMETHING RECEIVED GO PROCESS

	LOOP	SD3			; OTHERWISE WAIT
SD5:
	DEC	BL			; DECREMENT RETRY COUNT
	JNZ	SD0			; RETRY TRANSMISSION

	OR	@KB_FLAG_2,KB_ERR	; TURN ON TRANSMIT ERROR FLAG
	JMP	SHORT SD9		; RETRIES EXHAUSTED FORGET TRANSMISSION
SD7:
	TEST	@KB_FLAG_2,KB_FA	; SEE IF THIS IS AN ACKNOWLEDGE
	JZ	SD5			; IF NOT, GO RESEND
	
	POP	CX			; RESTORE REGISTERS
	POP	BX
	POP	AX
	RET				; RETURN, GOOD TRANSMISSION
SND_DATA ENDP

;---------------------------------------------------------------------------------
; SND_LED
; SND_LED1
;
;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
;
;---------------------------------------------------------------------------------
SND_LED	PROC	NEAR

	CLI				; TURN OFF INTERRUPTS
	TEST	@KB_FLAG_2,KB_PR_LED	; CHECK FOR MODE INDICATOR UPDATE
	JNZ	SL9			; DON'T UPDATE AGAIN IF UPDATE UNDERWAY

	OR	@KB_FLAG_2,KB_PR_LED	; TURN ON UPDATE IN PROCESS
	MOV	AL,EOI			; END OF INTERRUPT COMMAND
	OUT	INTA00,AL		; SEND COMMAND TO INTERRUPT CONTROL PORT
	JMP	SHORT SL3		; GO SEND MODE INDICATOR COMMAND

SND_LED1:
	CLI				; TURN OFF INTERRUPTS
	TEST	OKS_FLAG_2,KB_PR_LED	; CHECK FOR MODE INDICATOR UPDATE
	JNZ	SL9			; DON'T UPDATE AGAIN IF UPDATE UNDERWAY

	OR	@KB_FLAG_2,KB_PR_LED	; TURN ON UPDATE IN PROCESS
SL3:
	MOV	AL,LED_CMD		; LED CMD BYTE
	CALL	SND_DATA		; SEND DATA TO KEYBOARD
	CLI
	CALL	MAKE_LED		; GO FORM INDICATOR DATA BYTE
	AND	@KB_FLAG_2,NOT KB_LEDS	; CLEAR MODE INDICATOR BITS
	OR	@KB_FLAG_2,AL		; SAVE INDICATORS STATES FOR NEXT TIME
	TEST	@KB_FLAG_2,KB_ERR	; TRANSMIT ERROR DETECTED
	JNZ	SL5			; IF SO, BYPASS SECOND BYTE TRANSMISSION

	CALL	SND_DATA		; SEND DATA TO KEYBOARD
	CLI				; TURN OFF INTERRUPTS
	TEST	@KB_FLAG_2,KS_ERR	; TRANSMIT ERROR DETECTED
	JZ	SL7			; IF NOT, DON'T SEND AN ENABLE COMMAND
SL5:
	MOV	AL,KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
	CALL	SND_DATA		; SEND DATA TO KEYBOARD
	CLI				; TURN OFF INTERRUPTS
SL7:
	AND	@KB_FLAG_2,NOT(KB_PR_LED+KB_ERR)	; TURN OFF MODE INDICATOR
SL9:					; UPDATE AND TRANSMIT ERROR FLAG
	STI				; ENABLE INTERRUPTS
	RET				; RETURN TO CALLER
SND_LED ENDP

;---------------------------------------------------------------------------------
; MAKE_LED
;
;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
;	THE MODE INDICATORS.
;
;---------------------------------------------------------------------------------
MAKE_LED PROC 	NEAR
	PUSH	CX			; SAVE CX
	MOV	AL,@KB_FLAG		; GET CAPS & NUM LOCK INDICATORS
	AND	AL,CAPS_STATE+NUM_STATE+SCROLL_STATE 	; ISOLATE INDICATORS
	MOV	CL,4			; SHIFT COUNT
	ROL	AL,CL			; SHIFT BITS OVER TO TURN ON INDICATORS
	AND	AL,07H			; MAKE SURE ONLY MODE BITS ON
	POP	CX
	RET				; RETURN TO CALLER
MAKE_LED ENDP

;---------------------------------------------------------------------------------
; SHIP_IT
;
;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES	I
;	TO THE KEYBOARD CONTROLLER.
;
;---------------------------------------------------------------------------------
SHIP_IT	PROC	NEAR
	PUSH	AX			; SAVE DATA TO SEND

;-----	WAIT FOR COMMAND TO ACCEPTED
	CLI				; DISABLE INTERRUPTS TILL DATA SENT
	SUB	CX,CX			; CLEAR TIMEOUT COUNTER
S10:
	IN	AL,STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
	TEST	AL,INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
	LOOPNZ	S10			; WAIT FOR COMMAND TO BE ACCEPTED

	POP	AX			; GET DATA TO SEND
	OUT	STATUS_PORT,AL		; SEND TO KEYBOARD CONTROLLER
	STI				; ENABLE INTERRUPTS AGAIN
	RET				; RETURN TO CALLER
SHIP_IT	ENDP
CODE	ENDS
	END
