-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeybd.asm
More file actions
1017 lines (847 loc) · 29.2 KB
/
keybd.asm
File metadata and controls
1017 lines (847 loc) · 29.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
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