forked from skiselev/8088_bios
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbios.asm
1813 lines (1622 loc) · 50.1 KB
/
bios.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
;=========================================================================
; main.asm - BIOS main file
; Skeleton for the BIOS
; Power On Self Test (POST)
; Interrupt table setup
; INT 11h - Get equipment list
; INT 12h - Get memory size
;-------------------------------------------------------------------------
;
; Compiles with NASM 2.11.08, might work with other versions
;
; Copyright (C) 2010 - 2020 Sergey Kiselev.
; Provided for hobbyist use on the Xi 8088 and Micro 8088 boards.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program 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 General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;=========================================================================
;-------------------------------------------------------------------------
; Fixed BIOS Entry Points
; Source:
; Intel(R) Platform Innovation Framework for EFI
; Compatibility Support Module Specification
; Section 5.2
;
; Location Description
; -------- -----------
; F000:E05B POST Entry Point
; F000:E2C3 NMI Entry Point
; F000:E401 HDD Parameter Table
; F000:E6F2 INT 19 Entry Point
; F000:E6F5 Configuration Data Table
; F000:E729 Baut Rate Generator Table
; F000:E739 INT 14 Entry Point
; F000:E82E INT 16 Entry Point
; F000:E987 INT 09 Entry Point
; F000:EC59 INT 13 (Floppy) Entry Point
; F000:EF57 INT 0E Entry Point
; F000:EFC7 Floppy Disk Controller Parameter Table
; F000:EFD2 INT 17
; F000:F065 INT 10 (Video) Entry Point
; F000:F0A4 INT 1D MDA and CGA Video Parameter Table
; F000:F841 INT 12 Entry Point
; F000:F84D INT 11 Entry Point
; F000:F859 INT 15 Entry Point
; F000:FA6E Low 128 Characters of Graphic Video Font
; F000:FE6E INT 1A Entry Point
; F000:FEA5 INT 08 Entry Point
; F000:FF53 Dummy Interrupt Handler (IRET)
; F000:FF54 INT 05 (Print Screen) Entry Point
; F000:FFF0 Power-On Entry Point
; F000:FFF5 ROM Date in ASCII "MM/DD/YY" Format (8 Characters)
; F000:FFFE System Model (0xFC - AT, 0xFE - XT)
cpu 8086
%include "macro.inc"
%include "config.inc"
%include "errno.inc"
bioscseg equ 0F000h
biosdseg equ 0040h
pic1_reg0 equ 20h
pic1_reg1 equ 21h
pit_ch0_reg equ 40h
pit_ch1_reg equ 41h
pit_ch2_reg equ 42h
pit_ctl_reg equ 43h
; 8255 PPI port A I/O register - Read - keyboard data
ppi_pa_reg equ 60h ; 8255 PPI port A I/O register
; Port 61h - 8255 PPI Port B - Write only
ppi_pb_reg equ 61h ; 8255 PPI port B I/O register
iochk_disable equ 08h ; clear and disable ~IOCHK NMI
refresh_flag equ 10h ; refresh flag, toggles every 15us
iochk_enable equ 0F7h ; enable ~IOCHK NMI
iochk_status equ 40h ; ~IOCHK status - 1 = ~IOCHK NMI signalled
%ifdef MACHINE_XT or MACHINE_FE2010A
; Port 62h - 8255 PPI Port C - Read only
ppi_pc_reg equ 62h ; 8255 PPI port C I/O registerA
; XT DIP switches 1-4 (read when bit 3 of PPI Port B is 1)
sw_post_loop equ 01h ; XT DIP switch 1 - 1 = Loop on POST
sw_fpu_present equ 02h ; XT DIP switch 2 - 1 = FPU present
sw_ram_256k equ 00h ; XT DIP switches 3-4 - 256 KiB
sw_ram_512k equ 04h ; XT DIP switches 3-4 - 512 KiB
sw_ram_576k equ 08h ; XT DIP switches 3-4 - 576 KiB
sw_ram_640k equ 0Ch ; XT DIP switches 3-4 - 640 KiB
; XT DIP switches 5-8 (read when bit 3 of PPI Port B is 0)
sw_vid_none equ 00h ; XT DIP switches 5-6 - No video, EGA, or VGA
sw_vid_color_40 equ 01h ; XT DIP switches 5-6 - CGA, 80x25
sw_vid_color_80 equ 02h ; XT DIP switches 5-6 - CGA, 40x25
sw_vid_mono equ 03h ; XT DIP switches 5-6 - Monochome, 80x25
sw_one_floppy equ 00h ; XT DIP switches 7-8 - One floppy
sw_two_floppies equ 01h ; XT DIP switches 7-8 - Two floppies
sw_three_floppies equ 02h ; XT DIP switches 7-8 - Three floppies
sw_four_floppies equ 03h ; XT DIP switches 7-8 - Four floppies
%endif ; MACHINE_XT or MACHINE_FE2010A
; FE2010/FE2010 - Ports 62h-63h
%ifdef MACHINE_FE2010A
; Port 62h - Chipset Control Register - Write
fe_control_reg equ 62h
fe_fpu_present equ 02h ; FPU present
fe_ram_256k equ 00h ; XT DIP switches 3-4 - 256 KiB
fe_ram_512k equ 04h ; XT DIP switches 3-4 - 512 KiB
fe_ram_576k equ 08h ; XT DIP switches 3-4 - 576 KiB
fe_ram_640k equ 0Ch ; XT DIP switches 3-4 - 640 KiB
fe_one_floppy equ 00h ; XT DIP switches 7-8 - One floppy
fe_two_floppies equ 40h ; XT DIP switches 7-8 - Two floppies
; Port 63h - Chipset Configuration Register - Write only
fe_config_reg equ 63h ; Chipset configuration register
fe_par_disable equ 01h ; Disable memory parity checking
fe_fpu_nma_ena equ 02h ; Enable FPU NMI
fe_config_lock equ 08h ; Write lock of control register and
; bits 0-4 of configuration register
fe_clk_7_16mhz equ 40h ; FE2010A 7.16 MHz CPU clock frequency
fe_clk_9_55mhz equ 80h ; FE2010A 9.55 MHz CPU clock frequency
%endif ; MACHINE_FE2010A
; IBM PC/XT - Port 63h - 8255 PPI Control Word
%ifdef MACHINE_XT
ppi_cwd_reg equ 63h ; 8255 PPI control word register
ppi_cwd_value equ 99h ; 8255 PPI control word value for IBM XT:
; Port A - mode 0 (simple I/O), input
; Port B - mode 0 (simple I/O), output
; Port C - output
%endif ; MACHINE_XT
post_reg equ 80h ; POST status output port
nmi_mask_reg equ 0A0h
%ifdef SECOND_PIC
pic2_reg0 equ 0A0h
pic2_reg1 equ 0A1h
%endif ; SECOND_PIC
unused_reg equ 0C0h ; used for hardware detection and I/O delays
cga_mode_reg equ 3D8h
mda_mode_reg equ 3B8h
; NMI mask (written to 0A0h)
nmi_disable equ 00h ; disable NMI
nmi_disa_mask equ 7Fh ; disable NMI AND mask (bit 7 = 0)
nmi_enable equ 80h ; enable NMI OR mask (bit 7 = 1)
pic_freq equ 1193182 ; PIC input frequency - 14318180 MHz / 12
;========================================================================
; BIOS data area variables
;------------------------------------------------------------------------
equip_serial equ 00h ; word[4] - addresses of serial ports
; or 0 if port doesn't exist
equip_parallel equ 08h ; word[3] - addresses of parallel ports
; or 0 if port doesn't exist
ebda_segment equ 0Eh ; word - address of EBDA segment
equipment_list equ 10h ; word - equpment list
equip_floppies equ 0000000000000001b ; floppy drivers installed
equip_fpu equ 0000000000000010b ; FPU installed
equip_mouse equ 0000000000000100b
equip_video equ 0000000000110000b ; video type bit mask
equip_color_40 equ 0000000000010000b ; color 40x24 (mode 1)
equip_color_80 equ 0000000000100000b ; color 80x25 (mode 3)
equip_mono equ 0000000000110000b ; mono 80x25 (mode 7)
equip_floppy2 equ 0000000001000000b ; 2nd floppy drive installed
; |||||||||||||||`-- floppy drives installed
; ||||||||||||||`-- FPU installed
; |||||||||||||`-- PS/2 mouse installed
; ||||||||||||`-- reserved
; ||||||||||`--- initial video mode
; ||||||||`---- number of floppy drives - 1
; |||||||`---- O = DMA installed
; ||||`------ number of serial ports
; |||`------ game adapter installed
; ||`------ internal modem?!
; `------- number of parallel ports
post_flags equ 12h ; byte - post flags
post_setup equ 01h ; run NVRAM setup
memory_size equ 13h ; word - memory size in KiB
kbd_flags_1 equ 17h ; byte - keyboard shift flags 1
kbd_flags_2 equ 18h ; byte - keyboard shift flags 2
kbd_alt_keypad equ 19h ; byte - work area for Alt+Numpad
kbd_buffer_head equ 1Ah ; word - keyboard buffer head offset
kbd_buffer_tail equ 1Ch ; word - keyboard buffer tail offset
kbd_buffer equ 1Eh ; byte[32] - keyboard buffer
fdc_calib_state equ 3Eh ; byte - floppy drive recalibration status
fdc_motor_state equ 3Fh ; byte - floppy drive motor status
fdc_motor_tout equ 40h ; byte - floppy drive motor off timeout (ticks)
fdc_last_error equ 41h ; byte - status of last diskette operation
fdc_ctrl_status equ 42h ; byte[7] - FDC status bytes
video_mode equ 49h ; byte - active video mode number
video_columns equ 4Ah ; word - number of text columns for active mode
video_page_size equ 4Ch ; word - size of video page in bytes
video_page_offt equ 4Eh ; word - offset of the active video page
video_cur_pos equ 50h ; byte[16] - cursor position for each page
video_cur_shape equ 60h ; word - cursor shape
video_page equ 62h ; byte - active video page
video_port equ 63h ; word - I/O port for the display adapter
video_mode_reg equ 65h ; byte - video adapter mode register
video_palet_reg equ 66h ; byte - color palette
last_irq equ 6Bh ; byte - Last spurious IRQ number
ticks_lo equ 6Ch ; word - timer ticks - low word
ticks_hi equ 6Eh ; word - timer ticks - high word
new_day equ 70h ; byte - 1 = new day flag
break_flag equ 71h ; byte - bit 7 = 1 if Ctrl-Break was pressed
warm_boot equ 72h ; word - Warm boot if equals 1234h
printer_timeout equ 78h ; byte[3] - parallel port timeout values
serial_timeout equ 7Ch ; byte[4] - serial port timeout values
kbd_buffer_start equ 80h ; word - keyboard buffer start offset
kbd_buffer_end equ 82h ; word - keyboard buffer end offset
video_rows equ 84h ; byte - number of text rows (EGA+)
fdc_last_rate equ 8Bh ; byte - last data rate / step rate
fdc_info equ 8Fh ; byte - floppy dist drive information
fdc_media_state equ 90h ; byte[4] - drive media state (drives 0 - 3)
fdc_cylinder equ 94h ; byte[2] - current cylinder (drives 0 - 1)
kbd_flags_3 equ 96h ; byte - keyboard status flags 3
kbd_flags_4 equ 97h ; byte - keyboard status flags 4
prt_scrn_flags equ 100h ; byte - print screen flags
prt_scrn_ready equ 00h ; print screen is not in progress
prt_scrn_run equ 01h ; print screen is in progress
prt_scrn_fail equ 0FFh ; last print screen attempt has failed
;=========================================================================
; Extended BIOS data area variables
;-------------------------------------------------------------------------
ebda_size equ 0h
mouse_driver equ 22h ; 4 bytes - pointer to mouse driver
mouse_flags_1 equ 26h
mouse_flags_2 equ 27h
mouse_data equ 28h ; 8 bytes - mouse data buffer
org START ; Use only upper 32 KiB of ROM
;=========================================================================
; Includes
;-------------------------------------------------------------------------
%include "messages.inc" ; POST messages
%ifndef MACHINE_XT ; No space in XT ROM for font
%include "fnt80-FF.inc" ; font for graphics modes
%endif ; MACHINE_XT
;%include "inttrace.inc" ; Uncomment for interrupt debugging
%ifdef AT_RTC
%include "rtc.inc" ; RTC and CMOS read / write functions
%endif ; AT_RTC
%ifdef FLASH_NVRAM
%include "flash.inc" ; Flash ROM configuration functions
%endif ; FLASH_NVRAM
%ifdef BIOS_SETUP
%include "setup.inc" ; NVRAM setup functions
%endif ; BIOS_SETUP
%include "delay.inc" ; delay function
%include "time1.inc" ; time services
%include "floppy1.inc" ; floppy services
%ifdef AT_KEYBOARD
%include "at_kbc.inc" ; keyboard controller functions
%endif ; AT_KEYBOARD
%include "scancode.inc" ; keyboard scancodes translation func.
%include "serial1.inc" ; serial port services & detection
%include "printer1.inc" ; parallel printer services & detection
%ifdef PS2_MOUSE
%ifndef SECOND_PIC
%error "PS2_MOUSE depends on SECOND_PIC. Please fix config.inc."
%endif ; SECOND_PIC
%include "ps2aux.inc"
%endif
%include "sound.inc" ; sound test
%include "cpu.inc" ; CPU and FPU detection
%ifdef SECOND_PIC
;=========================================================================
; int_ignore2 - signal end of interrupt to PIC if hardware interrupt, return
;-------------------------------------------------------------------------
int_ignore2:
push ax
mov al,20h
out pic2_reg0,al ; signal EOI to the slave PIC
out pic1_reg0,al ; signal EOI to the master PIC
pop ax
iret
;=========================================================================
; int_71 - IRQ9 ISR, emulate IRQ2
;-------------------------------------------------------------------------
int_71:
push ax
mov al,20h
out pic2_reg0,al ; signal EOI to the slave PIC
pop ax
int 0Ah ; call IRQ2 ISR
iret
;=========================================================================
; int_75 - IRQ13 ISR, emulate NMI by FPU
;-------------------------------------------------------------------------
int_75:
push ax
mov al,20h
out pic2_reg0,al ; signal EOI to the slave PIC
out pic1_reg0,al ; signal EOI to the master PIC
pop ax
int 02h ; call NMI ISR
iret
%endif ; SECOND_PIC
;=========================================================================
; boot_os -Boot the OS
;-------------------------------------------------------------------------
boot_os:
;-------------------------------------------------------------------------
; Check for F1 (setup key), run setup utility if pressed
mov ah,01h
int 16h
jz .no_key
mov ah,00h
int 16h ; read the keystroke
cmp ax,3B00h ; F1?
jne .no_key
or byte [post_flags],post_setup
.no_key:
test byte [post_flags],post_setup
jz .no_setup
%ifdef BIOS_SETUP
call nvram_setup
%endif ; BIOS_SETUP
.no_setup:
%ifdef TURBO_MODE
call get_config_a ; read BIOS configuration byte A
and al,nvram_trbo_mask
call set_cpu_clk ; set CPU clock
%endif ; TURBO_MODE
mov al,e_boot ; boot the OS POST code
out post_reg,al
mov si,msg_boot
call print
int 19h ; boot the OS
;=========================================================================
; print - print ASCIIZ string to the console
; Input:
; CS:SI - pointer to string to print
; Output:
; none
;-------------------------------------------------------------------------
print:
pushf
push ax
push bx
push si
push ds
push cs
pop ds
cld
.1:
lodsb
or al,al
jz .exit
mov ah,0Eh
mov bl,0Fh
int 10h
jmp .1
.exit:
pop ds
pop si
pop bx
pop ax
popf
ret
;=========================================================================
; print_hex - print 16-bit number in hexadecimal
; Input:
; AX - number to print
; Output:
; none
;-------------------------------------------------------------------------
print_hex:
xchg al,ah
call print_byte ; print the upper byte
xchg al,ah
call print_byte ; print the lower byte
ret
;=========================================================================
; print_byte - print a byte in hexadecimal
; Input:
; AL - byte to print
; Output:
; none
;-------------------------------------------------------------------------
print_byte:
rol al,1
rol al,1
rol al,1
rol al,1
call print_digit
rol al,1
rol al,1
rol al,1
rol al,1
call print_digit
ret
;=========================================================================
; print_dec - print 16-bit number in decimal
; Input:
; AX - number to print
; Output:
; none
;-------------------------------------------------------------------------
print_dec:
push ax
push cx
push dx
mov cx,10 ; base = 10
call .print_rec
pop dx
pop cx
pop ax
ret
.print_rec: ; print all digits recursively
push dx
xor dx,dx ; DX = 0
div cx ; AX = DX:AX / 10, DX = DX:AX % 10
cmp ax,0
je .below10
call .print_rec ; print number / 10 recursively
.below10:
mov ax,dx ; reminder is in DX
call print_digit ; print reminder
pop dx
ret
;=========================================================================
; print_digit - print hexadecimal digit
; Input:
; AL - bits 3...0 - digit to print (0...F)
; Output:
; none
;-------------------------------------------------------------------------
print_digit:
push ax
push bx
and al,0Fh
add al,'0' ; convert to ASCII
cmp al,'9' ; less or equal 9?
jna .1
add al,'A'-'9'-1 ; a hex digit
.1:
mov ah,0Eh ; Int 10 function 0Eh - teletype output
mov bl,07h ; just in case we're in graphic mode
int 10h
pop bx
pop ax
ret
%ifdef EBDA_SIZE
;=========================================================================
; reserve_ebda - reserve EBDA (Extended BIOS Data Area) if using PS2_MOUSE
; Input:
; AX = memory size in KiB
; Notes:
; - Assumes that EBDA memory was cleaned
; - Does not reserve EBDA if PS/2 auxiliary device is not detected
;-------------------------------------------------------------------------
reserve_ebda:
push ax
push cx
test word [equipment_list],equip_mouse
jz .no_mouse
mov ax,word [memory_size] ; get conventional memory size
sub ax,EBDA_SIZE ; substract EBDA size
mov word [memory_size],ax ; store new conventional memory size
mov cl,6
shl ax,cl ; convert to segment
mov word [ebda_segment],ax ; store EBDA segment to BIOS variable
push ds
mov ds,ax
mov ax,EBDA_SIZE
mov byte [ebda_size],al ; store EBDA size to EBDA
pop ds
push si
mov si,msg_ebda
call print
call print_dec
mov si,msg_kib
call print
pop si
.no_mouse:
pop cx
pop ax
ret
%endif ; EBDA_SIZE
;=========================================================================
; print display type
;-------------------------------------------------------------------------
print_display:
mov si,msg_disp
call print
mov al,byte [equipment_list] ; get equipment - low byte
and al,equip_video ; get video adapter type
mov si,msg_disp_mda
cmp al,equip_mono ; monochrome?
jz .print_disp
mov si,msg_disp_cga_80
cmp al,equip_color_80 ; CGA 80x25?
jz .print_disp
mov si,msg_disp_cga_40
cmp al,equip_color_40 ; CGA 40x25?
jz .print_disp
mov si,msg_disp_ega ; otherwise EGA or later
.print_disp:
call print
ret
%ifdef PS2_MOUSE
;=========================================================================
; print PS/2 mouse presence
;-------------------------------------------------------------------------
print_mouse:
mov si,msg_mouse
call print
mov si,msg_absent
test byte [equipment_list],equip_mouse
jz .print_mouse
mov si,msg_present
.print_mouse:
call print
ret
%endif ; PS2_MOUSE
;=========================================================================
; interrupt_table - offsets only (BIOS segment is always 0F000h)
;-------------------------------------------------------------------------
interrupt_table:
dw int_dummy ; INT 00 - Divide by zero
dw int_dummy ; INT 01 - Single step
dw int_02 ; INT 02 - Non-maskable interrupt
dw int_dummy ; INT 03 - Debugger breakpoint
dw int_dummy ; INT 04 - Integer overlow (into)
dw int_05 ; INT 05 - BIOS Print Screen
dw int_dummy ; INT 06
dw int_dummy ; INT 07
dw int_08 ; INT 08 - IRQ0 - Timer Channel 0
dw int_09 ; INT 09 - IRQ1 - Keyboard
dw int_ignore ; INT 0A - IRQ2
dw int_ignore ; INT 0B - IRQ3
dw int_ignore ; INT 0C - IRQ4
dw int_ignore ; INT 0D - IRQ5
dw int_0E ; INT 0E - IRQ6 - Floppy
dw int_ignore ; INT 0F - IRQ7
dw int_10 ; INT 10 - BIOS Video Services
dw int_11 ; INT 11 - BIOS Get Equipment List
dw int_12 ; INT 12 - BIOS Get Memory Size
dw int_13 ; INT 13 - BIOS Floppy Disk Services
dw int_14 ; INT 14 - BIOS Serial Communications
dw int_15 ; INT 15 - BIOS Misc. System Services
dw int_16 ; INT 16 - BIOS Keyboard Services
dw int_17 ; INT 17 - BIOS Parallel Printer svc.
dw int_18 ; INT 18 - BIOS Start ROM BASIC
dw int_19 ; INT 19 - BIOS Boot the OS
dw int_1A ; INT 1A - BIOS Time Services
dw int_dummy ; INT 1B - DOS Keyboard Break
dw int_dummy ; INT 1C - User Timer Tick
dw int_1D ; INT 1D - Video Parameters Table
dw int_1E ; INT 1E - Floppy Parameters Table
%ifndef MACHINE_XT
dw int_1F ; INT 1F - Font For Graphics Mode
%else ; MACHINE_XT
dw int_ignore
%endif ; MACHINE_XT
%ifdef SECOND_PIC
interrupt_table2:
dw int_70 ; INT 70 - IRQ8 - RTC
dw int_71 ; INT 71 - IRQ9 - redirection
dw int_ignore2 ; INT 72 - IRQ10
dw int_ignore2 ; INT 73 - IRQ11
%ifndef PS2_MOUSE
dw int_ignore2 ; INT 74 - IRQ12 - PS/2 mouse
%else
dw int_74 ; INT 74 - IRQ12 - PS/2 mouse
%endif
dw int_75 ; INT 75 - IRQ13 - FPU
dw int_ignore2 ; INT 76 - IRQ14
dw int_ignore2 ; INT 77 - IRQ15
%endif ; SECOND_PIC
;=========================================================================
; cold_start, warm_start - BIOS POST (Power on Self Test) starts here
;-------------------------------------------------------------------------
setloc 0E05Bh ; POST Entry Point
cold_start:
mov ax,biosdseg
mov ds,ax
mov word [warm_boot],0 ; indicate cold boot
warm_start:
cli ; disable interrupts
cld ; clear direction flag
mov al,e_cpu_test
out post_reg,al ; POST start code
;-------------------------------------------------------------------------
; test CPU's FLAG register
xor ax,ax ; AX = 0
jb cpu_fail
jo cpu_fail
js cpu_fail
jnz cpu_fail
jpo cpu_fail
add ax,1 ; AX = 1
jz cpu_fail
jpe cpu_fail
sub ax,8002h
js cpu_fail
inc ax
jno cpu_fail
shl ax,1
jnb cpu_fail
jnz cpu_fail
shl ax,1
jb cpu_fail
;-------------------------------------------------------------------------
; Test CPU registers
mov ax,0AAAAh
.1:
mov ds,ax
mov bx,ds
mov es,bx
mov cx,es
mov ss,cx
mov dx,ss
mov bp,dx
mov sp,bp
mov si,sp
mov di,si
cmp di,0AAAAh
jnz .2
mov ax,di
not ax
jmp .1
.2:
cmp di,5555h
jz cpu_ok
cpu_fail:
mov al,e_cpu_fail
out post_reg,al
;-------------------------------------------------------------------------
; CPU error: continious beep - 400 Hz
mov al,0B6h
out pit_ctl_reg,al ; PIT - channel 2 mode 3
mov ax,pic_freq/400 ; 400 Hz signal
out pit_ch2_reg,al
mov al,ah
out pit_ch2_reg,al
in al,ppi_pb_reg
or al,3 ; turn speaker on and enable
out ppi_pb_reg,al ; PIT channel 2 to speaker
.1:
hlt
jmp .1
;-------------------------------------------------------------------------
; CPU test passed
cpu_ok:
;-------------------------------------------------------------------------
; disable NMI, turbo mode, and video output on CGA and MDA
mov al,e_init_cfg
out post_reg,al
%ifdef AT_NMI
mov al,0Dh & nmi_disa_mask
out rtc_addr_reg,al ; disable NMI
jmp $+2
in al,rtc_data_reg ; dummy read to keep RTC happy
%else
mov al,nmi_disable
out nmi_mask_reg,al ; disable NMI
%endif ; AT_NMI
%ifdef MACHINE_XI8088
mov al,iochk_disable ; clear and disable ~IOCHK
out ppi_pb_reg,al
mov al,00h ; clear turbo bit
out ppi_pb_reg,al ; and also turn off the speaker
%endif ; MACHINE_XI8088
%ifdef MACHINE_FE2010A
mov al,fe_par_disable ; Disable parity checking
out fe_config_reg,al ; FE2010A chipset configuration register
mov al,10110000b ; Clear keyboard, disable keyb clock
out ppi_pb_reg,al ; Disable parity and IOCHK
%endif ; MACHINE_FE2010A
%ifdef MACHINE_XT
mov al,ppi_cwd_value ; PPI port A and port C inputs
out ppi_cwd_reg,al ; PPI control word register
mov al,10100101b ; FIXME: Add documentation
out ppi_pb_reg,al
%endif ; MACHINE_XT
mov al,00h
mov dx,cga_mode_reg
out dx,al ; disable video output on CGA
inc al
mov dx,mda_mode_reg ; disable video output on MDA
out dx,al ; and set MDA high-resolution mode bit
;-------------------------------------------------------------------------
; Initialize DMAC (8237)
mov al,e_init_dmac
out post_reg,al
out 0Dh,al ; DMA Master Clear register - reset DMA
mov al,40h ; single mode, verify, channel 0
out dmac_mode_reg,al ; DMA Mode register
mov al,41h ; single mode, verify, channel 1
out dmac_mode_reg,al ; DMA Mode register
mov al,42h ; single mode, verify, channel 2
out dmac_mode_reg,al ; DMA Mode register
mov al,43h ; single mode, verify, channel 3
out dmac_mode_reg,al ; DMA Mode register
mov al,0 ; DMA Command register bits:
; DACK active low, DREQ active high,
; late write, fixed priority,
; normal timing, controller enable
; channel 0 addr hold disable
; memory to memory disable
out 08h,al ; DMA Command register
out 81h,al ; DMA Page, channel 2
out 82h,al ; DMA Page, channel 3
out 83h,al ; DMA Page, channels 0,1
;-------------------------------------------------------------------------
; Test first 32 KiB (MIN_RAM_SIZE) of RAM
mov al,e_low_ram_test
out post_reg,al
xor si,si
xor di,di
mov ds,di
mov es,di
mov dx,word [warm_boot+biosdseg*16] ; save soft reset flag to DX
mov ax,55AAh ; first test pattern
mov cx,MIN_RAM_SIZE*512 ; RAM size to test in words
rep stosw ; store test pattern
mov cx,MIN_RAM_SIZE*512 ; RAM size to test in words
.1:
lodsw
cmp ax,55AAh ; compare to the test pattern
jne low_ram_fail
loop .1
xor si,si
xor di,di
mov ax,0AA55h ; second test pattern
mov cx,MIN_RAM_SIZE*512 ; RAM size to test in words
rep stosw ; store test pattern
mov cx,MIN_RAM_SIZE*512 ; RAM size to test in words
.2:
lodsw
cmp ax,0AA55h ; compare to the test pattern
jne low_ram_fail
loop .2
xor di,di
xor ax,ax ; zero
mov cx,MIN_RAM_SIZE*512 ; RAM size to test in words
rep stosw ; zero the memory
jmp low_ram_ok ; test passed
low_ram_fail:
mov al,e_low_ram_fail ; test failed
out post_reg,al
;-------------------------------------------------------------------------
; Low memory error: beep - pause - beep - pause ... - 400 Hz
mov al,0B6h
out pit_ctl_reg,al ; PIT - channel 2 mode 3
mov ax,pic_freq/400 ; 400 Hz signal
out pit_ch2_reg,al
mov al,ah
out pit_ch2_reg,al
in al,ppi_pb_reg
.1:
or al,3 ; turn speaker on and enable
out ppi_pb_reg,al ; PIT channel 2 to speaker
mov cx,0
.2:
nop
loop .2
and al,0FCh ; turn of speaker
out ppi_pb_reg,al
mov cx,0
.3:
nop
loop .3
jmp .1
;-------------------------------------------------------------------------
; Low memory test passed
low_ram_ok:
mov word [warm_boot+biosdseg*16],dx ; restore soft reset flag
;-------------------------------------------------------------------------
; Set up stack - using upper 256 bytes of interrupt table
mov ax,0030h
mov ss,ax
mov sp,0100h
;-------------------------------------------------------------------------
; Initialize interrupt table
mov al,e_int_table
out post_reg,al
push cs
pop ds
xor di,di
mov es,di
mov si,interrupt_table
mov cx,0020h ; 32 Interrupt vectors
mov ax,bioscseg
.1:
movsw ; copy ISR address (offset part)
stosw ; store segment part
loop .1
%ifdef SECOND_PIC
mov di,70h*4 ; starting from IRQ 70
mov si,interrupt_table2
mov cx,8 ; 8 Interrupt vectors
.2:
movsw ; copy ISR address (offset part)
stosw ; store segment part
loop .2
%endif ; SECOND_PIC
;-------------------------------------------------------------------------
; set DS to BIOS data area
mov ax,biosdseg ; DS = BIOS data area
mov ds,ax
;-------------------------------------------------------------------------
; Initialize PIT (8254 timer)
mov al,36h ; channel 0, LSB & MSB, mode 3, binary
out pit_ctl_reg,al
mov al,0
out pit_ch0_reg,al
out pit_ch0_reg,al
mov al,54h ; channel 1, LSB only, mode 2, binary
out pit_ctl_reg,al ; used for DRAM refresh on IBM PC/XT/AT
mov al,12h ; or for delays (using port_b, bit 4)
out pit_ch1_reg,al ; pulse every 15ms
mov al,40h ; channel 1, counter latch
out pit_ctl_reg,al ; FIXME - not needed?
;-------------------------------------------------------------------------
; Play "power on" sound - also tests PIT functionality
mov al,e_pit_init
out post_reg,al
call sound
;-------------------------------------------------------------------------
; Initialize PIC (8259)
mov al,e_pic_init
out post_reg,al
%ifdef SECOND_PIC
mov al,11h ; ICW1 - edge triggered, cascade, ICW4
out pic1_reg0,al
out pic2_reg0,al
mov al,8 ; ICW2 - interrupt vector offset = 8
out pic1_reg1,al
mov al,70h ; ICW2 - interrupt vector offset = 70h
out pic2_reg1,al
mov al,4 ; ICW3 - slave is connected to IR2
out pic1_reg1,al
mov al,2 ; ICW3 - slave ID = 2 (IR2)
out pic2_reg1,al
mov al,1 ; ICW4 - 8086/8088
out pic1_reg1,al
out pic2_reg1,al
%else
mov al,13h ; ICW1 - edge triggered, single, ICW4
out pic1_reg0,al
mov al,8 ; ICW2 - interrupt vector offset = 8
out pic1_reg1,al
mov al,9 ; ICW4 - buffered mode, 8086/8088
out pic1_reg1,al
%endif ; SECOND_PIC
;-------------------------------------------------------------------------
; initialize keyboard controller (8242), keyboard and PS/2 auxiliary device
mov al,e_kbd_init
out post_reg,al
%ifdef AT_KEYBOARD
call kbc_init
%else ; AT_KEYBOARD
in al,ppi_pb_reg
and al,00111111b ; set keyboard clock low
out ppi_pb_reg,al
mov cx,10582 ; hold clock low for 20 ms
.kbd_reset_wait:
loop .kbd_reset_wait
or al,11000000b ; set keyboard clear bit, enable clock
out ppi_pb_reg,al
and al,01111111b ; unset keyboard clear bit
out ppi_pb_reg,al
mov cx,1000
.kbd_flush:
mov ah,01h
int 16h
jz .kbd_no_key
mov ah,00h
int 16h
.kbd_no_key:
loop .kbd_flush
%endif ; AT_KEYBOARD
call kbd_buffer_init ; setup keyboard buffer
;-------------------------------------------------------------------------
; enable interrupts
mov al,e_int_ena
out post_reg,al
%ifdef SECOND_PIC
mov al,0B8h ; OSW1: unmask timer, keyboard, IRQ2 and FDC
out pic1_reg1,al
%ifndef PS2_MOUSE
mov al,0FDh ; OSW1: unmask IRQ9
%else
mov al,0EDh ; OSW1: unmask IRQ9 and IRQ12
%endif ; PS2_MOUSE
out pic2_reg1,al
%else
mov al,0BCh ; OSW1: unmask timer, keyboard and FDC
out pic1_reg1,al
%endif ; SECOND_PIC
sti
mov al,nmi_enable
out nmi_mask_reg,al ; enable NMIs
%ifdef MACHINE_FE2010A or MACHINE_XT
;-------------------------------------------------------------------------
; Read video mode switches into equipment_list
in al,ppi_pb_reg
%ifdef MACHINE_FE2010A
and al,0FDh ; clear switch select bit - select SW5-SW8
%endif ; MACHINE_FE2010A
%ifdef MACHINE_XT
and al,0F7h ; clear switch select bit - select SW5-SW8
%endif ; MACHINE_XT
out ppi_pb_reg,al
in al,ppi_pc_reg ; read switches SW5-SW8
and al,03h ; video mode is in SW5 and SW6