/
BIOS_Next186.ASM
4593 lines (4239 loc) · 134 KB
/
BIOS_Next186.ASM
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
; This file is part of the Next186 SoC PC project
; http://opencores.org/project,next186
; Filename: BIOS_Next186.asm
; Description: Part of the Next186 SoC PC project, ROM BIOS code
; Version 1.0
; Creation date: Feb-Jun 2013
; Author: Nicolae Dumitrache
; e-mail: ndumitrache@opencores.org
; -------------------------------------------------------------------------------------
; Copyright (C) 2013 Nicolae Dumitrache
; This source file may be used and distributed without
; restriction provided that this copyright statement is not
; removed from the file and that any derivative work contains
; the original copyright notice and the associated disclaimer.
; This source file is free software; you can redistribute it
; and/or modify it under the terms of the GNU Lesser General
; Public License as published by the Free Software Foundation;
; either version 2.1 of the License, or (at your option) any
; later version.
; This source is distributed in the hope that it will be
; useful, but WITHOUT ANY WARRANTY; without even the implied
; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
; PURPOSE. See the GNU Lesser General Public License for more
; details.
; You should have received a copy of the GNU Lesser General
; Public License along with this source; if not, download it
; from http://www.opencores.org/lgpl.shtml
; -----------------------------------------------------------------------
; Additional Comments:
; Assembled with MASM v6.14.8444
; Next186 SoC PC have no ROM, only RAM. The bootstrap code is the initial value of cache
; (last half 1K = 4 lines of 256bytes each), initially marked as "dirty", in order to
; be saved in RAM at first flush
; The bootstrap code may load the BIOS from SD, or from RS232, and place it at F000:E000
.186
.model tiny
.code
SCANCODE1 equ 1
;-------------------------- BIOS data area (BDA) -----------------
;40:0000 2 Base port address of first RS-232 adapter (COM1) See COM Ports
;40:0002 2 Port of COM2
;40:0004 2 Port of COM3
;40:0006 2 Port of COM4
;40:0008 2 Base port addr of first parallel printer (LPT1) Printer Ports
;40:000A 2 Port of LPT2
;40:000C 2 Port of LPT3
;40:000E 2 Port of LPT4
;40:0010 2 Equipment/hardware installed/active; see Equipment List
;40:0012 1 Errors in PCjr infrared keyboard link
;40:0013 2 Total memory in K-bytes (same as obtained via INT 12H)
;40:0015 2 Scratch pad for manufacturing error tests
;
;40:0017 2 Keyboard status bits; see Keyboard Shift Status Flags
;40:0019 1 Current (accumulating) value of Alt+numpad pseudo-key input;
; normally 0. When [Alt] is released, value is stored in
; keyboard buffer at 001e.
;40:001a 2 Addr of keyboard buffer head (keystroke at that addr is next)
;40:001c 2 Address of keyboard buffer tail
;40:001e 32 Keyboard buffer. BIOS stores keystrokes here (head and tail
; point to addresses from 041eH to 043dH inclusive).
;
;40:003e 1 Diskette drive needs recalibration (bit 0=A, bit 1=B, etc.)
; bits 4-5 indicate which drive is currently selected
;40:003f 1 Diskette motor is running (bit 0=drive A, bit 1=B, etc.)
;40:0040 1 Time until motor off. INT 08H turns motor off when this is 0.
;40:0041 1 Diskette error status; same as status returned by INT 13H
;40:0042 7 Diskette controller status information area
;
;40:0049 1 Current active video mode. See Video Modes and INT 10H.
;40:004a 2 Screen width in text columns
;40:004c 2 Length (in bytes) of video area (regen size)
;40:004e 2 Offset from video segment of active video memory page
;40:0050 16 Cursor location (8 byte-pairs; low byte=clm, hi byte=row)
;40:0060 2 Cursor size/shape. Low byte=end scan line; hi byte=start line.
;40:0062 1 Current active video page number
;40:0063 2 Port address for 6845 video controller chip; see CGA I/O Ports
;40:0065 1 Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
;40:0066 1 Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
;
;40:0067 5 Cassette data area or POST data area
; 40:0067: 1 byte mouse buffer counter (DataCounter)
; 40:0068: 1 byte mouse packet size (PacketSize): 0 for 3 bytes, 1 for 4 bytes (Intellimouse)
; 40:0069: 1 byte palette paging status
; 40:006a: 1 byte PalPagingCounter - guards pal paging re-entrance
;
;40:006c 4 Timer tick counter (count of 55ms ticks since CPU reset)
;40:0070 1 Timer overflow flag (timer has rolled over 24 hr)
;40:0071 1 Ctrl-Break flag. Bit 7=1 when break was pressed. This never
; gets reset unless you do it yourself.
;
;40:0072 2 1234H means Ctrl+Alt+Del reboot is in progress. BIOS checks
; this to avoid doing a "cold boot" with the time-consuming POST
; 4321H means reset, preserving memory
; 5678H, 9abcH, and abcdH (are internal PC Convertible codes)
;
;40:0074 4 PCjr diskette or AT hard disk control area
; (0074) 1 Status of last fixed-disk drive operation
; (0075) 1 Number of hard disk drives for AT
; (0077) 1 Hard disk port for XT. See XT Hard Disk Ports.
;40:0078 4 Printer time-out values (478H=Lpt1, 478H=Lpt2...)
;40:007c 4 RS-232 time-out values (47cH=Com1, 47dH=Com2...)
;
;40:0080 2 AT PS/2 keyboard buffer offset start address (usually 01eH)
;40:0082 2 end address (usually 003eH)
;
;40:0084 1 EGA text rows-1 (maximum valid row value)
;40:0085 2 EGA bytes per character (scan-lines/char used in active mode)
;40:0087 1 EGA flags; see EgaMiscInfoRec
;40:0088 1 EGA flags; see EgaMiscInfo2Rec
;40:0089 1 VGA flags; see VgaFlagsRec
; See also: EGA/VGA Data Areas
;
;40:008b 1 AT PS/2 Media control: data rate, step rate
;40:008c 1 AT PS/2 Hard disk drive controller status
;40:008d 1 AT PS/2 Hard disk drive error status
;40:008e 1 AT PS/2 Hard disk drive interrupt control
;
;40:0090 1 AT PS/2 Disk media state bits for drive 0
;40:0091 1 for drive 1
;40:0092 1 AT PS/2 Disk operation started flag for drive 0
;40:0093 1 for drive 1
;40:0094 1 AT PS/2 Present cylinder number for drive 0
;40:0095 1 for drive 1
; 2 - Number of 512bytes sectors of HD0
;
;40:0096 1 AT Keyboard flag bit 4=1 (10H) if 101-key keyboard is attached
;40:0097 1 AT Keyboard flag for LED 'key lock' display
; bits 0-2 are ScrollLock, NumLock, CapsLock
;
;40:0098 4 AT Pointer to 8-bit user wait flag; see INT 15H 86H
;40:009c 4 AT Microseconds before user wait is done
;40:00a0 1 AT User wait activity flag:
; 01H=busy, 80H=posted, 00H=acknowledged
;
;40:00a1 7 AT Reserved for network adapters
; 40:00a1: 4 bytes far pointer to mouse callback (HandlerPtr)
; 40:00a5: 3 bytes mouse buffer (DataBuffer)
;
;40:00a8 4 EGA Address of table of pointers; see EgaSavePtrRec
;40:00ac 68 Reserved
;40:00f0 16 (IAC) Inter-Aapplication Communication area. Programs may use
; this area to store status, etc. Might get overwritten by
; another program.
; http://www.ctyme.com/intr/int.htm
org 0e000h
bios:
biosmsg db 'Next186 SoC PC BIOS (C) 2022 Nicolae Dumitrache [22.04.16]', 0
msgmb db 'MB SD Card', 13, 10, 0
msgkb db 'PS2 KB detected', 13, 10, 0
org 0e05bh
coldboot:
warmboot:
; jmp start ; Uncomment this line to execute BIOS from BRAM (SD to malfunction and the OS to not boot)
; ------------------ MAP init
mov ax, cs
cmp ax, 0f000h
jz check_f_map_7
mov ax, 07h ; f_map_f
out 8fh, ax
db 0eah
dw coldboot, 0f000h
check_f_map_7:
in al, 8fh
cmp al, 07h
jz f_map_7
push 07e00h
pop es
push 0fe00h
pop ds
xor si, si
xor di, di
mov cx, 1000h
rep movsw ; copy BRAM BIOS over physical segment (SRAM)
db 0eah
dw coldboot, 07000h
f_map_7:
call flush
in al, 98h
cmp al, 1
jz start
mov ax, 0fh
out 87h, ax
; ------------------ MAP END
start:
in al, 98h
cmp al, 2
jz bios2mb
mov word ptr cs:[ramsize], 0008h
bios2mb:
cli
cld
mov ax, 30h
mov ss, ax
mov sp, 100h
push 0
popf
mov al, 36h
out 43h, al
xor ax, ax
out 7, ax ; NMIonIORQ_HI = 0
out 40h, al
out 40h, al ; 18Hz PIT CH0
out 61h, al ; speaker off
not al
out 21h, al ; disable all interrupts
out 0a1h, al
out 6, ax ; NMIonIORQ_LO = 255 -> disabled
; -------------------- Interrupt table init
push 0
pop ds
push ds
pop es
xor si, si
mov di, 4
mov word ptr [si], offset defint
mov word ptr [si+2], cs
mov cx, 256-2
rep movsw
mov word ptr ds:[7*4], offset int07
mov word ptr ds:[8*4], offset int08
mov word ptr ds:[9*4], offset int09
mov word ptr ds:[10h*4], offset int10
mov word ptr ds:[11h*4], offset int11
mov word ptr ds:[12h*4], offset int12
mov word ptr ds:[13h*4], offset int13
mov word ptr ds:[15h*4], offset int15
mov word ptr ds:[16h*4], offset int16
mov word ptr ds:[18h*4], offset int18
mov word ptr ds:[19h*4], offset int19
mov word ptr ds:[1ah*4], offset int1a
mov word ptr ds:[1dh*4], offset int_1D
mov word ptr ds:[70h*4], offset int70
mov word ptr ds:[74h*4], offset int74
; ------------------- BDA init
push 40h
pop ds
push ds
pop es
xor di, di
xor si, si
xor ax, ax
mov cl, 80h
rep stosw
mov word ptr [si+08h], 378h ; LPT1 base port address
mov byte ptr [si+10h], 24h ; equipment word (color 80x25, PS2 mouse present)
mov word ptr [si+13h], 640 ; memory size in KB
add word ptr [si+1ah], 1eh ; next char pointer in kb buffer
add word ptr [si+1ch], 1eh ; last char pointer in kb buffer
mov word ptr [si+60h], 0e0fh ; cursor shape
mov word ptr [si+63h], 3d4h ; video port address
add word ptr [si+80h], 1eh ; start kb buffer
add word ptr [si+82h], 3eh ; end kb buffer
mov word ptr [si+87h], 0940h ; video adapter options (512Kb video)
mov word ptr [si+89h], 0b71h ; VGA video flags: 400 line text mode, default palette loading on (0), blinking on
mov byte ptr [si+96h], 10h ; 101 keyboard installed
in al, 98h
cmp al, 2
jz bios2mb_2
mov word ptr [si+13h], 504 ; memory size in KB
bios2mb_2:
; ------------------- Graph mode init
mov ax, 3
int 10h
mov al, 0
out 97h, al ; cpu_speed max
cmp byte ptr cs:[kbbios], 01h
jz short no_initkb
mov al, 0aeh
out 64h, al ; enable kb
mov al, 0a7h
out 64h, al ; disable mouse
call KbInit
no_initkb:
mov al, 0adh
out 64h, al ; disable kb interface
mov al, 0a8h
out 64h, al ; enable mouse
call MouseInit
call enableKbIfPresent
mov al, 20h
out 64h, al
in al, 60h
or al, 3
mov ah, al
mov al, 60h
out 64h, al
mov al, ah
out 60h, al ; enable 8042 mouse and kb interrupts
mov ax, 0 ; 1000-1 ; 1ms
out 70h, ax ; set RTC frequency (stop)
; mov al, 0
out 21h, al ; enable all PIC interrupts (8h, 9h, 0ch)
out 0a1h, al ; enable all PIC interrupts (70h, 74h)
out 1, al ; intialize COM mux
inc ax
out 1, ax ; enable auto flush on vblank
sti ; enable CPU interrupts
mov al, 1
out 97h, al ; cpu_speed setted
; --------------------- HDD init
call sdinit
mov HDSize, ax
push cs
pop es
mov si, offset biosmsg
call prts
mov si, offset bioscont
call prts
mov si, offset bioscont2
in al, 98h
cmp al, 2
jz bios2mb_3
mov si, offset bioscont512
bios2mb_3:
call prts
mov ax, HDSize
shr ax, 1
call dispAX
mov si, offset msgmb
call prts
test byte ptr KbdFlags3, 10h
jz nokbmsg
mov si, offset msgkb
call prts
nokbmsg:
test byte ptr EquipmentWord, 4
jz nomousemsg
mov si, offset msgmouse
call prts
nomousemsg:
;-------------- HD bootstrap
mov ax, 305h
xor bx, bx
int 16h ; set typematic rate and delay to fastest
int 19h
msgmouse db 'PS2 Mouse detected', 13, 10, 0
bioscont db 13, 10, 'ZX-UNO port by DistWave', 13, 10
db 'Graphics Gremlin Integration by @spark2k06', 13, 10, 13, 10
db 'CPU: 80186 @ 12Mhz. Throttle down option: CTRL + ALT + [-/+]', 13, 10
db 'Graphics: CGA/Tandy. MonochromeRGB option: CTRL + ALT + ScrLock', 13,10
db 'Sound: Adlib (JTOPL2) and PC Speaker', 0
bioscont512 db 13, 10, 'RAM: 512KB SRAM 8-bit', 13, 10
db 'Cache: 8x256 bytes data/inst', 13, 10
db 'HD0: ', 0
bioscont2 db 13, 10, 'RAM: 2MB SRAM 8-bit (1MB available + 1MB EMS)', 13, 10
db 'Cache: 8x256 bytes data/inst', 13, 10
db 'HD0: ', 0
; ---------------------------- INT 07 ---------------------
int07 proc near ; coprocessor ESC sequence
push ax
push bx
push ds
push bp
mov bp, sp
lds bx, [bp+8]
int07_pfx:
mov al, [bx]
inc bx
and al, 0f8h
cmp al, 0d8h ; ESC code
jne short int07_pfx
cmp byte ptr [bx], 0c0h ; mod reg r/m of ESC 8087 instruction
sbb al, al
and al, [bx]
and ax, 0c7h
cmp al, 6
jne int072
mov al, 80h
int072:
shr al, 6
inc ax
add ax, bx
mov [bp+8], ax
pop bp
pop ds
pop bx
pop ax
iret
int07 endp
; ---------------------------- INT 08 ---------------------
int08 proc near
push ds
push bx
push 40h
pop ds
mov bx, 40h
cmp word ptr [bx], 0
jz int08_nodec
dec word ptr [bx]
int08_nodec:
push ax
mov al, 20h
out 20h, al
pop ax
mov bx, 6ch
add word ptr [bx], 1
adc word ptr [bx+2], 0
cmp word ptr [bx+2], 18h
jne short int081
cmp word ptr [bx], 0b0h
jne short int081
mov word ptr [bx], 0
mov word ptr [bx+2], 0
mov byte ptr [bx+4], 1
int081:
int 1ch
sti
push ax
mov ah, 4
kloop:
in al, 64h
test al, 1
jz short nokey
dec ah
jnz short kloop
test al, 20h
jz short kbdata
int 74h
jmp short nokey
kbdata:
int 9h
nokey:
pop ax
pop bx
pop ds
iret
int08 endp
; --------------------- INT 09 - keyboard ------------------
KbdFlags1 equ <ds:[17h]>
KbdFlags2 equ <ds:[18h]>
AltKpd equ <ds:[19h]>
CtrlBreak equ <ds:[71h]>
KbdFlags3 equ <ds:[96h]>
KbdFlags4 equ <ds:[97h]>
; Bits for the KbdFlags1
RShfDown equ 1
LShfDown equ 2
CtrlDown equ 4
AltDown equ 8
ScrLock equ 10h
NumLock equ 20h
CapsLock equ 40h
Insert equ 80h
; Bits for the KbdFlags2
LCtrDown equ 1
LAltDown equ 2
SysReqDown equ 4
Pause equ 8
ScrLockDown equ 10h
NumLockDown equ 20h
CapsLockDown equ 40h
InsDown equ 80h
; Bits for the KbdFlags3
LastE1 equ 1
LastE0 equ 2
RCtrDown equ 4
RAltDown equ 8
LastF0 equ 20h
; Bits for the KbdFlags4
ScrLockLED equ 1
NumLockLED equ 2
CapsLockLED equ 4
SetRepeat equ 8 ; Set auto repeat command in progress
AckReceived equ 10h
LEDUpdate equ 40h
IFDEF SCANCODE1
int09 proc near
pusha
push ds
push es
push 40h
pop ds
in al, 60h ; al contains the scan code
mov dx, KbdFlags1
mov cx, KbdFlags3
cmp al, 0fah ; ACK
jne short noACK
; ------------ manage ACK response
test ch, LEDUpdate
jz short ToggleACK ; no LED update
test ch, AckReceived
jnz short SecondACK ; second ACK received
mov ah, ch ; LED update command sent, ACK received, need to send second byte
and ah, ScrLockLED or NumLockLED or CapsLockLED
mov bl, 0
call sendps2byte
jmp short ToggleACK
SecondACK:
xor ch, LEDUpdate ; second ACK, clear LED update bit
ToggleACK:
xor ch, AckReceived ; toggle ACK bit
SetFlags1:
jmp SetFlags
; ------------ no ACK
noACK:
mov ah,4fh
stc
int 15h
jnc int09Exit
cmp al, 0e0h
jne short noE0
or cl, LastE0
jmp short SetFlags1
noE0:
cmp al, 0e1h
jne short noE1
or cl, LastE1
jmp short SetFlags1
noE1:
cmp al, 53h ; is DEL?
jne short noDEL
mov ah, dl
and ah, CtrlDown or AltDown
cmp ah, CtrlDown or AltDown
jne NormalKey ; is DEL, but no CTRL+ALt+DEL
mov word ptr ds:[72h], 1234h ; warm boot flag
db 0eah
dw 0, 0ffffh ; reboot
noDEL:
test cl, LastE0
jnz short noRSUp ; ignore fake shifts
cmp al, 2ah ; left shift
jne short noLSDown
or dl, LShfDown
jmp short SetFlagsKey2
noLSDown:
cmp al, 2ah or 80h
jne short noLSUp
and dl, not LShfDown
jmp short SetFlagsKey2
noLSUp:
cmp al, 36h ; right shift
jne short noRSDown
or dl, RShfDown
jmp short SetFlagsKey2
noRSDown:
cmp al, 36h or 80h
jne short noRSUP
and dl, not RShfDown
jmp short SetFlagsKey2
noRSUp:
cmp al, 38h ; ALT
jne short noALTDown
test cl, LastE0
jz short LALTDn
or cl, RAltDown
or dl, AltDown
jmp short SetFlagsKey2
LALTDn:
or dx, (LAltDown shl 8) or AltDown
jmp short SetFlagsKey2
noALTDown:
cmp al, 38h or 80h
jne short noALTUp
test cl, LastE0
jz short LALTUp
and cl, not RAltDown
and dl, not AltDown
jmp short ALTup
LALTUp:
and dx, not ((LAltDown shl 8) or AltDown)
ALTUp:
xor ax, ax
xchg al, AltKpd
test al, al
jz short SetFlagsKey2
jmp pushKey
noALTUp:
cmp al, 1dh ; CTL
jne short noCTLDown
test cl, lastE0
jz short LCTLDn
or cl, RCtrDown
or dl, CtrlDown
SetFlagsKey2:
jmp short SetFlagsKey1
LCTLDn:
or dx, (LCtrDown shl 8) or CtrlDown
jmp short SetFlagsKey1
noCTLDown:
cmp al, 1dh or 80h
jne short noCTLUp
test cl, LastE0
jz short LCTLUp
and cl, not RCtrDown
and dl, not CtrlDown
jmp short SetFlagsKey1
LCTLUp:
and dx, not ((LCtrDown shl 8) or CtrlDown)
jmp short SetFlagsKey1
noCTLUp:
mov bx, 3a00h + CapsLock
call KeyLock
jnc short SetFlagsKey1
mov bx, 4600h + ScrLock
push dx ; save ScrLock state bit (dl)
call KeyLock
pop bx ; restore ScrLock state bit (bl)
jc short noScrLock
test dl, CtrlDown
jz short SetFlagsKey1; no break, just ScollLock
mov dl, bl ; restore ScrLock flag
test bh, ScrLockDown
jnz short SetFlagsKey1
mov byte ptr CtrlBreak, 80h ; CTRL+BREAK flag
mov ax, Buffer
mov HeadPtr, ax
mov TailPtr, ax
int 1bh
xor ax, ax
jmp pushkey
noScrLock:
test cl, LastE0 ; INS
jnz short testINS
test dl, RShfDown or LShfDown
jnz short testINS
test dl, NumLock
jnz short NoIns
testINS:
mov bx, 5200h + Insert
call KeyLock
noIns:
mov bx, 4500h + NumLock
push dx ; save NumLock state bit (dl)
call KeyLock
pop bx ; restore NumLock state bit (bl)
jc short NormalKey ; CTRL+NumLock = Pause
test dl, CtrlDown
jz short SetFlagsKey1
mov dl, bl ; restore NumLock flag
or dh, Pause ; set Pause bit
SetFlagsKey1:
jmp SetFlagsKey
E0Key:
mov di, offset E0KeyList
push cx
mov cx, E0KeyIndex - E0KeyList
cld
push cs
pop es
repne scasb
pop cx
jne short SetFlagsKey
mov al, es:[di + E0KeyIndex - E0KeyList - 1]
jmp short KeyDown
NormalKey:
test al, 80h
jnz short SetFlagsKey ; key up
test cl, LastE0
jnz short E0Key
cmp al, 59h
sbb ah, ah
and al, ah
mov bx, offset KeyIndex
xlat cs:[bx]
KeyDown:
xor bx, bx
test dl, RShfDown or LShfDown
jz short noShift
mov bl, 2
noShift:
cmp al, 26
ja short noCaps
test dl, CapsLock
jz short noNum
xor bl, 2
jmp short noNum
noCaps:
cmp al, 37
ja short noNum
test dl, NumLock
jnz short NumDown
mov bl, 2
NumDown:
xor bl, 2
noNum:
test dl, CtrlDown
jz short noCtrl
mov bl, 4
noCtrl:
test dl, AltDown
jz short noAlt
mov bl, 6
noAlt:
cbw
shl ax, 3
add bx, ax
mov ax, cs:KeyCode[bx]
cmp ax, 000ah
ja short pushKey
dec ax
js short SetFlagsKey ; ax was 0
mov ah, AltKpd
aad
mov AltKpd, al
jmp short SetFlagsKey
pushKey:
push cx
mov cx, ax
mov ah, 5
int 16h
pop cx
and dh, not Pause ; clear Pause bit
SetFlagsKey:
and cl, not (LastE0 or LastE1) ; not prefix key code, clear all prefixes
SetFlags:
mov al, dl
shr al, 4
xor al, ch
and al, 7
jz short SF1 ; no LEDs to update
test ch, SetRepeat or AckReceived or LEDUpdate
jnz short SF1 ; can not update LEDS, so just write the flags and exit
or al, LEDUpdate
xor ch, al ; insert the LEDs in KbdFlags4
mov ah, 0edh ; set LED
mov bl, 0
call sendps2byte
SF1:
mov KbdFlags1, dx
mov KbdFlags3, cx
int09Exit:
mov al, 20h
out 20h, al
pop es
pop ds
popa
iret
int09 endp
ELSE ; SCANCODE2
int09 proc near
pusha
push ds
push es
push 40h
pop ds
in al, 60h ; al contains the scan code
mov dx, KbdFlags1
mov cx, KbdFlags3
cmp al, 0fah ; ACK
jne short noACK
; ------------ manage ACK response
test ch, LEDUpdate
jz short ToggleACK ; no LED update
test ch, AckReceived
jnz short SecondACK ; second ACK received
mov ah, ch ; LED update command sent, ACK received, need to send second byte
and ah, ScrLockLED or NumLockLED or CapsLockLED
mov bl, 0
call sendps2byte
jmp short ToggleACK
SecondACK:
xor ch, LEDUpdate ; second ACK, clear LED update bit
ToggleACK:
xor ch, AckReceived ; toggle ACK bit
SetFlags1:
jmp SetFlags
; ------------ no ACK
noACK:
cmp al, 0e0h
jne short noE0
or cl, LastE0
jmp short SetFlags1
noE0:
cmp al, 0e1h
jne short noE1
or cl, LastE1
jmp short SetFlags1
noE1:
cmp al, 0f0h
jne short noF0
or cl, LastF0
jmp short SetFlags1
noF0:
cmp al, 71h ; is DEL?
jne short noDEL
mov ah, dl
and ah, CtrlDown or AltDown
cmp ah, CtrlDown or AltDown
je short noF01
NormalKey1:
jmp NormalKey
noF01:
mov word ptr ds:[72h], 1234h ; warm boot flag
db 0eah
dw 0, 0ffffh ; reboot
noDEL:
cmp al, 83h ; is F7
je short NormalKey1
ja short SetFlags1
test cl, LastF0 ; key up?
jz short noKeyUp
or al, 80h ; key up flag
noKeyUp:
test cl, LastE0
jnz short noRSUp ; ignore fake shifts
cmp al, 12h ; left shift
jne short noLSDown
or dl, LShfDown
jmp short SetFlagsKey2
noLSDown:
cmp al, 12h or 80h
jne short noLSUp
and dl, not LShfDown
jmp short SetFlagsKey2
noLSUp:
cmp al, 59h ; right shift
jne short noRSDown
or dl, RShfDown
jmp short SetFlagsKey2
noRSDown:
cmp al, 59h or 80h
jne short noRSUP
and dl, not RShfDown
jmp short SetFlagsKey2
noRSUp:
cmp al, 11h ; ALT
jne short noALTDown
test cl, LastE0
jz short LALTDn
or cl, RAltDown
or dl, AltDown
jmp short SetFlagsKey2
LALTDn:
or dx, (LAltDown shl 8) or AltDown
jmp short SetFlagsKey2
noALTDown:
cmp al, 11h or 80h
jne short noALTUp
test cl, LastE0
jz short LALTUp
and cl, not RAltDown
and dl, not AltDown
jmp short ALTup
LALTUp:
and dx, not ((LAltDown shl 8) or AltDown)
ALTUp:
xor ax, ax
xchg al, AltKpd
test al, al
jz short SetFlagsKey2
jmp pushKey
noALTUp:
cmp al, 14h ; CTL
jne short noCTLDown
test cl, lastE0
jz short LCTLDn
or cl, RCtrDown
or dl, CtrlDown
SetFlagsKey2:
jmp short SetFlagsKey1
LCTLDn:
or dx, (LCtrDown shl 8) or CtrlDown
jmp short SetFlagsKey1
noCTLDown:
cmp al, 14h or 80h
jne short noCTLUp
test cl, LastE0
jz short LCTLUp
and cl, not RCtrDown
and dl, not CtrlDown
jmp short SetFlagsKey1
LCTLUp:
and dx, not ((LCtrDown shl 8) or CtrlDown)
jmp short SetFlagsKey1
noCTLUp:
mov bx, 5800h + CapsLock
call KeyLock
jnc short SetFlagsKey1
mov bx, 7e00h + ScrLock
push dx ; save ScrLock state bit (dl)
call KeyLock
pop bx ; restore ScrLock state bit (bl)
jc short noScrLock
test dl, CtrlDown
jz short SetFlagsKey1; no break, just ScollLock
mov dl, bl ; restore ScrLock flag
test bh, ScrLockDown
jnz short SetFlagsKey1
mov byte ptr CtrlBreak, 80h ; CTRL+BREAK flag
mov ax, Buffer
mov HeadPtr, ax
mov TailPtr, ax
int 1bh
xor ax, ax
jmp pushkey
noScrLock:
test cl, LastE0 ; INS
jnz short testINS
test dl, RShfDown or LShfDown
jnz short testINS
test dl, NumLock
jnz short NoIns
testINS:
mov bx, 7000h + Insert
call KeyLock
noIns:
mov bx, 7700h + NumLock
push dx ; save NumLock state bit (dl)
call KeyLock
pop bx ; restore NumLock state bit (bl)
jc short noPause
test dl, CtrlDown
jz short SetFlagsKey1
mov dl, bl ; restore NumLock flag
or dh, Pause ; set Pause bit
SetFlagsKey1:
jmp SetFlagsKey
E0Key:
mov di, offset E0KeyList
push cx
mov cx, E0KeyIndex - E0KeyList
cld
push cs
pop es
repne scasb
pop cx
jne short SetFlagsKey
mov al, es:[di + E0KeyIndex - E0KeyList - 1]
jmp short KeyDown
noPause:
and al, 07fh ; delete up bit
NormalKey:
test cl, LastF0
jnz short SetFlagsKey ; key up
test cl, LastE0
jnz short E0Key
mov bx, offset KeyIndex
xlat cs:[bx]
KeyDown:
xor bx, bx
test dl, RShfDown or LShfDown
jz short noShift
mov bl, 2
noShift:
cmp al, 26
ja short noCaps
test dl, CapsLock