forked from skiselev/8088_bios
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bios.asm
1757 lines (1542 loc) · 45.5 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.07, might work with other versions
;
; Copyright (C) 2011 - 2014 Sergey Kiselev.
; Provided for hobbyist use on the Xi 8088 board.
;
; 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
port_b_reg equ 61h
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
post_reg equ 80h ; POST status output port
pic2_reg0 equ 0A0h
pic2_reg1 equ 0A1h
unused_reg equ 0C0h ; used for hardware detection and I/O delays
cga_mode_reg equ 3D8h
mda_mode_reg equ 3B8h
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 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
%include "fnt80-FF.inc" ; font for graphics modes
;%include "inttrace.inc" ; XXX
%include "rtc.inc" ; RTC and CMOS read / write functions
%include "time1.inc" ; time services
%include "floppy1.inc" ; floppy services
%include "kbc.inc" ; keyboard controller functions
%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 AT_COMPAT
%error "PS2_MOUSE depends on AT_COMPAT. Please fix config.inc."
%endif ; AT_COMPAT
%include "ps2aux.inc"
%endif
%include "sound.inc" ; sound test
%include "cpu.inc" ; CPU and FPU detection
%ifdef AT_COMPAT
;=========================================================================
; 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 ; AT_COMPAT
;=========================================================================
; extension_scan - scan for BIOS extensions
; Input:
; DX - start segment
; BX - end segment
; Returns:
; DX - address for the continuation of the scan
; biosdseg:67h - address of the extension, 0000:0000 if not found
;-------------------------------------------------------------------------
extension_scan:
mov word [67h],0
mov word [69h],0
.scan:
mov es,dx
es cmp word [0],0AA55h ; check for signature
jnz .next ; no signature, check next 2 KiB
es mov al,byte [2] ; AL = rom size in 512 byte blocks
mov ah,0
mov cl,5
shl ax,cl ; convert size to paragraphs
add dx,ax
add dx,007Fh ; round DX to the nearest 2 KiB
and dx,0FF80h ; (2 KiB = 128 x 16 bytes)
mov cl,4
shl ax,cl ; convert size to bytes
mov cx,ax
mov al,0
xor si,si
.checksum:
es add al,byte [si]
inc si
loop .checksum
or al,al ; AL == 0?
jnz .next ; AL not zero - bad checksum
mov word [67h],3 ; extension initialization offset
mov word [69h],es ; extension segment
jmp .exit
.next:
add dx,80h ; add 2 KiB
cmp dx,bx
jb .scan
.exit:
ret
;=========================================================================
; ipl - Initial Program Load - try to read and execute boot sector
;-------------------------------------------------------------------------
ipl:
sti
xor ax,ax
mov ds,ax
mov word [78h],int_1E
mov word [7Ah],cs
.retry:
mov al,4 ; try booting from floppy 4 times
.fd_loop:
push ax
mov ah,00h ; reset disk system
mov dl,00h ; drive 0
int 13h
jb .fd_failed
mov ah,08h ; get drive parameters
mov dl,00h ; drive 0
int 13h
jc .fd_failed
cmp dl,00h
jz .fd_failed ; jump if zero drives
mov ax,0201h ; read one sector
xor dx,dx ; head 0, drive 0
mov es,dx ; to 0000:7C00
mov bx,7C00h
mov cx,0001h ; track 0, sector 1
int 13h
jc .fd_failed
es cmp word [7DFEh],0AA55h
jnz .fd_failed
jmp 0000h:7C00h
.fd_failed:
pop ax
dec al
jnz .fd_loop
; try booting from HDD
mov ah,0Dh ; reset hard disks
mov dl,80h ; drive 80h
int 13h
jc .hd_failed
mov ax,0201h ; read one sector
mov dx,0080h ; head 0, drive 80h
xor bx,bx
mov es,bx ; to 0000:7C00
mov bx,7C00h
mov cx,0001h ; track 0, sector 1
int 13h
jc .hd_failed
es cmp word [7DFEh],0AA55h
jnz .hd_failed
jmp 0000h:7C00h
.hd_failed:
mov si,msg_boot_failed
call print
mov ah,00h
int 16h
jmp .retry
;=========================================================================
; get_line - read an ASCIIZ string from the console
; Input:
; ES:DI - pointer to the buffer
; AX - max string length
; Output:
; AX - string length
; Notes:
; Buffer must have size of max string length + 1 to accomodate 00h
;-------------------------------------------------------------------------
get_line:
push bx
push dx
push si
push di
cld
mov si,di
add si,ax ; SI = last character position
xor dx,dx ; DX = 0 - string length
.read_char_loop:
mov ah,00h ; read character from keyboard
int 16h
cmp al,08h ; <Backspace> key
jz .backspace
cmp al,0Dh ; <Enter> key
jz .enter
cmp al,20h ; below printable ASCII code?
jb .error_input
cmp al,7Eh ; above printable ASCII code?
ja .error_input
cmp di,si ; end of buffer reached?
jae .error_input
stosb ; store character in the buffer
inc dx ; increment strng length
mov ah,0Eh ; teletype output (echo)
mov bx,0007h
int 10h
jmp .read_char_loop
.backspace:
or dx,dx ; empty string?
jz .error_input
dec di ; move pointer back
dec dx ; decrement string size
mov ax,0E08h ; move the cursor back
mov bx,0007h
int 10h
mov ax,0E20h ; erase the character under the cursor
mov bx,0007h
int 10h
mov ax,0E08h ; move the cursor back again
mov bx,0007h
int 10h
jmp .read_char_loop
.error_input:
mov ax,0E07h ; beep
mov bx,0007h
int 10h
jmp .read_char_loop
.enter:
mov al,00h ; store 00h at the end of the string
stosb
mov ax,0E0Dh ; CR
mov bx,0007h
int 10h
mov ax,0E0Ah ; LF
mov bx,0007h
int 10h
mov ax,dx ; string length to AX
pop di
pop si
pop dx
pop bx
ret
;=========================================================================
; atoi - convert ASCIIZ string to an 16-bit integer number
; Input:
; ES:DI - pointer to string
; Output:
; AX - number
; ES:DI - pointer moved to the position following the number
;-------------------------------------------------------------------------
atoi:
push bx
push cx
push dx
xor ax,ax ; zero the result
mov bx,10 ; multiplier
.atoi_loop:
es mov cl,byte [di]
cmp cl,'0' ; ASCII code below '0'
jb .exit
cmp cl,'9' ; ASCII code above '9'
ja .exit
inc di ; move to the next character
sub cl,'0' ; convert to ASCII to binary
mul bx ; DX:AX = AX * 10
mov ch,0
add ax,cx ; AX = AX + CX
jmp .atoi_loop
.exit:
pop dx
pop cx
pop bx
ret
;=========================================================================
; bin_to_bcd - convert binary number to a packed BCD
; Input:
; AX - binary number
; Output:
; AX - packed BCD number
;-------------------------------------------------------------------------
bin_to_bcd:
push bx
push cx
push dx
push si
mov cl,0 ; shift amount
xor si,si ; zero result
mov bx,10 ; BX - divisor
.bin_to_bcd_loop:
xor dx,dx ; DX - zero for 32-bit div operand
div bx
shl dx,cl ; shift digit to the required position
add cl,4 ; calculate next position
add si,dx ; add reminder to the result
or ax,ax ; quotient is zero?
jnz .bin_to_bcd_loop
mov ax,si ; result to AX
pop si
pop dx
pop cx
pop bx
ret
;=========================================================================
; 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
;=========================================================================
; 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:
%ifdef PS2_MOUSE
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
%endif ; PS2_MOUSE
ret
;=========================================================================
; detect_ram - Determine the size of installed RAM and test it
; Input:
; none
; Output:
; AX = RAM size
; CX, SI - trashed
;-------------------------------------------------------------------------
detect_ram:
mov al,e_ram_start ; RAM scan start
out post_reg,al
push ds
mov cl,6 ; for SHL - converting KiB to segment
mov ax,MIN_RAM_SIZE
.fill_loop:
push ax
shl ax,cl ; convert KiB to segment (mult. by 64)
mov ds,ax
mov word [RAM_TEST_BLOCK-2],ax
pop ax
add ax,RAM_TEST_BLOCK/1024
cmp ax,MAX_RAM_SIZE
jne .fill_loop
mov ax,MIN_RAM_SIZE
.size_loop:
push ax
shl ax,cl ; convert KiB to segment (mult. by 64)
mov ds,ax
cmp word [RAM_TEST_BLOCK-2],ax
jne .size_done
pop ax
add ax,RAM_TEST_BLOCK/1024
cmp ax,MAX_RAM_SIZE
jnb .size_exit
jmp .size_loop
.size_done:
pop ax
.size_exit:
pop ds
mov word [memory_size],ax ; store it for now... might change later
; AX = detected memory size, now test the RAM
cmp word [warm_boot],1234h ; warm boot - don't test RAM
je .test_done
mov si,msg_ram_testing
call print
mov ax,MIN_RAM_SIZE ; start from 32 KiB
.test_loop:
push ax
mov ah,03h ; INT 10h, AH=03h - get cursor position
mov bh,00h ; page 0
int 10h ; position returned in DX
pop ax
call print_dec
push ax
mov ah,02h ; INT 10h, AH=02h - set cursor position
mov bh,00h ; page 0
int 10h
mov ah,01h
int 16h
jz .test_no_key
mov ah,00h
int 16h ; read the keystroke
cmp al,1Bh ; ESC?
je .test_esc
cmp ax,3B00h ; F1?
jne .test_no_key
or byte [post_flags],post_setup
.test_no_key:
pop ax
call ram_test_block
jc .test_error ; error in last test
add ax,RAM_TEST_BLOCK/1024 ; test the next block
cmp ax,word [memory_size]
jb .test_loop
push ax
mov al,e_ram_complete ; RAM scan complete
out post_reg,al
pop ax
jmp .test_done
.test_esc:
pop ax
mov ax,word [memory_size]
push ax
mov al,e_ram_esc ; RAM scan canceled
out post_reg,al
pop ax
jmp .test_done
.test_error:
mov word [memory_size],ax ; store size of good memory
mov si,msg_ram_error
call print
call print_dec
mov si,msg_kib
call print
mov si,msg_crlf
call print
push ax
mov al,e_ram_fail ; RAM scan failed
out post_reg,al
pop ax
.test_done:
ret
;=========================================================================
; ram_test_block - Test a 16 KiB (RAM_TEST_BLOCK) of RAM
; Input:
; AX = address of the memory to test (in KiB)
; Output:
; CF = status
; 0 = passed
; 1 = failed
;-------------------------------------------------------------------------
ram_test_block:
push ax
push bx
push cx
push si
push di
push ds
push es
mov cl,6 ; convert KiB to segment address
shl ax,cl ; (multiply by 64)
mov ds,ax
mov es,ax
xor si,si
xor di,di
mov bx,RAM_TEST_BLOCK/2 ; RAM test block size in words
mov ax,55AAh ; first test pattern
mov cx,bx
rep stosw ; store test pattern
mov cx,bx ; RAM test block size
.1:
lodsw
cmp ax,55AAh ; compare to the test pattern
jne .fail
loop .1
xor si,si
xor di,di
mov ax,0AA55h ; second test pattern
mov cx,bx ; RAM test block size
rep stosw ; store test pattern
mov cx,bx ; RAM test block size
.2:
lodsw
cmp ax,0AA55h ; compare to the test pattern
jne .fail
loop .2
xor di,di
xor ax,ax ; zero
mov cx,bx ; RAM test block size
rep stosw ; zero the memory
clc ; test passed, clear CF
jmp .exit
.fail:
stc ; test failed, set CF
.exit:
pop es
pop ds
pop di
pop si
pop cx
pop bx
pop ax
ret
;=========================================================================
; 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
cmp al,equip_color ; CGA?
jz .print_disp
mov si,msg_disp_ega ; otherwise EGA or later
.print_disp:
call print
ret
;=========================================================================
; 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
;=========================================================================
; detect_rom_ext - Look for BIOS extensions, initialize if found
;-------------------------------------------------------------------------
detect_rom_ext:
mov al,e_ext_start ; ROM extension scan start
out post_reg,al
mov dx,0C800h
mov bx,0F800h
.ext_scan_loop:
call extension_scan
cmp word [67h],0
jz .ext_scan_done ; No ROM extension found
mov al,e_ext_detect ; ROM extension found
out post_reg,al
mov si,msg_rom_found
call print
mov ax,word [69h] ; ROM extension's segment
call print_hex
mov si,msg_rom_init
call print
push bx
push dx
call far [67h]
mov ax,biosdseg ; DS = BIOS data area
mov ds,ax
mov al,e_ext_init_ok ; ROM extension initialized
out post_reg,al
pop dx
pop bx
jmp .ext_scan_loop
.ext_scan_done:
mov al,e_ext_complete ; ROM extension scan complete
out post_reg,al
ret
;=========================================================================
; 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 Paameters Table
dw int_1F ; INT 1F - Font For Graphics Mode
%ifdef AT_COMPAT
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 ; AT_COMPAT
;=========================================================================
; cold_start, warm_start - BIOS POST (Power on Self Test) starts here
;-------------------------------------------------------------------------
setloc 0E05Bh ; POST Entry Point
cold_start:
mov ax,biosdseg