Menu

[r791]: / mk88 / new / src / bios.asm  Maximize  Restore  History

Download this file

950 lines (888 with data), 37.7 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
; ==========================
; # Main BIOS Code #
; ==========================
CPU 8086
%use masm
%include "inttable.inc"
%include "bconst.inc"
%include "bdata.inc"
%include "mdata.inc"
BIOS_F SEGMENT
ORG OFS_BIOS
extrom_start dw BIOS_MAGIC ; signature
db 10h ; ext rom checksum
%include "monitor.asm"
alt_encoding: ; cp866 font
%include "font_hi2.inc"
%include "tape.asm"
%include "keyb2.asm"
%include "menu.asm"
main_encoding: ; original font
%include "font_hi1.inc"
BIOS_ENTRY(0E000h)
main_rom_start:
bios_title db 'MK-88 '
%if MK_REV == 3
db 'R1..3'
%elif MK_REV == 4
db 'R4'
%elif MK_REV == 5
db 'R5'
%endif
db ' BIOS v4.26', 0
off_cont dw offset bios_cont_init
init_ptr dw offset csum_ret
kb_ok db 'KB OK',KEY_CR, 0
; RAM test subroutine
; CX = count of words, DS = ES = seg => ZF if OK
; 1. fill forward with AA
; 2. check backward, fill with 55
; 3. check forward, fill with FF
; 4. check backward, fill with 01
; 5. check forward, fill with 00
; 6. check backward
do_mem_test proc near
cld
xor di, di
xor ax, ax
mov bx, cx
shl bx, 1
mov ax, 0AAAAh
mov dx, 0FF55h
rep stosw ; fill with AAAA
mem_third_code: dec di
std
mem_second_code:
mov si, di
mov cx, bx
mem_check_loop: lodsb
xor al, ah ; check with AH
jnz short mem_end
and ah, ah
jz short mem_zero
mov al, dl
stosb ; fill with DL
mem_zero: loop mem_check_loop
and ah, ah
jz short mem_end
mov ah, al
xchg dh, dl ; swap 55 and FF
cld
inc di
jz short mem_second_code
dec di
mov dx, 0001h
jmp short mem_third_code
mem_end: cld
retn
do_mem_test endp
; BIOS ENTRY POINT
BIOS_ENTRY(0E05Bh)
start_0 proc near
cli
mov ah, 0D5h
sahf
jnb short do_halt
jnz short do_halt
jnp short do_halt
jns short do_halt
lahf
mov cl, 5
shr ah, cl
jnb short do_halt
mov al, 40h
shl al, 1
jno short do_halt
xor ah, ah
sahf
jbe short do_halt
js short do_halt
jp short do_halt
lahf
mov cl, 5
shr ah, cl
jb short do_halt
shl ah, 1
jo short do_halt
mov ax, ~0
stc
check_seg: mov ds, ax
mov bx, ds
mov es, bx
mov cx, es
mov ss, cx
mov dx, ss
mov sp, dx
mov bp, sp
mov si, bp
mov di, si
jnc short end_check_seg ; after second pass
xor ax, di ; AX = 0
jnz short do_halt
clc
jmp short check_seg ; second pass
end_check_seg: or ax, di
jz short start_mem_refresh
do_halt: hlt ; CPU check failed
start_mem_refresh: ; at this point all regs are zero
out IO_DMA_CH1_PAGE, al ; DMA page register Channel 1 (address bits 16-23)
mov dx, IO_CGA_MODE
out dx, al
mov al, 88h ; original value was 89h, C = out, this is wrong
out IO_PPI_CTL, al ; ppi mode: A=out, B=out, C=out/in
mov al, 025h ; CAPS=off, NUM=off, RUS=on => START TESTING
out IO_PPI_PORT_B, al ; output to port B
mov ax, cs
mov ss, ax ; SS = CS
mov ds, ax ; DS = CS
cld
mov bx, offset main_rom_start
mov sp, offset off_cont
jmp calc_rom_cs ; DS:BX = start address, size = 2000h
bios_cont_init: je rom_is_good
mov al, 05Ah ; CAPS=on, NUM=on, RUS=off => ROM BAD
halt_with_err: out IO_PPI_PORT_B, al
hlt
rom_is_good: mov al, 00000100b ; DMA controller disable
out IO_DMA_CMD_STATUS, al ; DMA 8237A-5. cmd reg
mov al, 01010100b ; counter 1, LSB only, mode 2 (rate gen), binary
out IO_TIMER_CTL, al ; timer control reg
mov al, cl ; AL = 00h
out IO_TIMER1_DIV, al ; program divizor to 0
timer_test_loop: mov al, 01000000b ; counter 1 latch
out IO_TIMER_CTL, al ; latch counter
cmp bl, ~0 ; all bits are connected
je short timer_good
in al, IO_TIMER1_DIV ; latched value
or bl, al ; test all bits
loop timer_test_loop
mov al, 00010000b ; CAPS=on, NUM=off, RUS=off => timer failed
jmp short halt_with_err
timer_good: mov al, bl ; AL = 0FFh
xor cx, cx
out IO_TIMER1_DIV, al ; program divizor to 255
timer_next_loop: mov al, 01000000b ; counter 1 latch
out IO_TIMER_CTL, al ; latch counter
nop
nop
in al, IO_TIMER1_DIV ; latched value
and bl, al
jz short timer_good_2 ; all bits are zeroable
loop timer_next_loop
mov al, 00010000b ; CAPS=on, NUM=off, RUS=off => timer failed
jmp short halt_with_err
timer_good_2: out IO_DMA_CLR_MASTER, al ; DMA controller master clear.
mov al, ~0 ; first, test DMA with FF
dma_test_again: mov bl, al
mov bh, al
mov cx, 8 ; number of DMA registers to test
xor dx, dx ; DMA controller first port
dma_test_loop: out dx, al
push ax ; some bus access
out dx, al
mov al, 1 ; some delay
in al, dx
mov ah, al
in al, dx
cmp bx, ax ; compare base and current address
jz short dma_regs_ok ; test next DMA channel
mov al, 00001000b ; CAPS=off, NUM=on, RUS=off => DMA failed
halt_err_1: jmp short halt_with_err
dma_regs_ok: inc dx ; test next DMA channel
loop dma_test_loop
inc al
jz short dma_test_again ; second, test DMA with 00
mov ds, bx ; DS = 0
mov es, bx ; ES = 0
mov al, ~0
out IO_DMA_CH0_CNT, al ; DMA refresh word count LOW
push ax ; some delay
out IO_DMA_CH0_CNT, al ; DMA refresh word count HIGH
mov al, 01_01_10_00b ; channel 0, read, auto, decrement, single
out IO_DMA_MODE, al ; program DRAM refresh mode
xor al, al ; AL = 0
mov ch, al ; CH = 0
out IO_DMA_CMD_STATUS, al ; enable DMA controller
push ax ; some delay
out IO_DMA_MASK, al ; enable channel 0 (DRAM refresh)
mov al, RAM_REGEN_DIVISOR
out IO_TIMER1_DIV, al ; program refresh timer divisor
mov al, 01_00_00_01b ; channel 1, verify, no auto init, decrement, single
out IO_DMA_MODE, al ; default setup for channel 1
push ax ; some delay
in al, IO_DMA_CMD_STATUS
and al, 10h ; check for request on channel 0
jz short dma_status_good
mov al, 00001000b ; CAPS=off, NUM=on, RUS=off => DMA failed
jmp short halt_err_1
dma_status_good:
mov al, 01_00_00_10b ; channel 2, verify, no auto init, decrement, single
out IO_DMA_MODE, al ; default setup for channel 2
inc al
out IO_DMA_MODE, al ; default setup for channel 3
mov bx, word ptr ZERO_BDATA + is_warm_boot ; keep old value of warm boot
mov bp, word ptr ZERO_BDATA + mem_size_kb ; keep old value of mem size
mov cx, BIOS_LOW_MEMORY_SIZE_KB * 1024 / 2 ; low memory size to clear
cmp bx, WARM_BOOT_MAGIC
jz short do_soft_boot
mov sp, offset init_ptr
jmp do_mem_test ; test start of ram, CX = word count => BX = byte count
csum_ret: jz short csum_ok
mov al, 00010100b ; CAPS=on, NUM=off, RUS=on => LOW RAM failed
jmp short halt_err_1
do_soft_boot: xor ax, ax
rep stosw ; clear low ram
csum_ok: mov word ptr ZERO_BDATA + is_warm_boot, bx ; restore old value of warm boot
mov word ptr ZERO_BDATA + mem_size_kb, bp ; restore old value of mem size
; detect RAM size
mov dx, BIOS_LOW_MEMORY_SIZE_KB * 1024 / 16 ; start test from 800h
mov bx, BIOS_LOW_MEMORY_SIZE_KB ; skip 2 KB
bios_mem_test: mov es, dx
sub di, di
mov ax, 0AA55h
mov cx, ax
mov es:[di], ax
mov al, 0Fh
mov ax, es:[di]
xor ax, cx
jnz short mem_test_done
mov cx, 1024 / 2 ; 1 kilobyte block
rep stosw
add dx, 1024 / 16 ; next block segment
inc bx
cmp dh, BIOS_MAX_MEMORY_SIZE_KB * 1024 / 16 / 256
jnz short bios_mem_test
mem_test_done: cmp word ptr ZERO_BDATA + is_warm_boot, WARM_BOOT_MAGIC
je short keep_mem_size
mov word ptr ZERO_BDATA + mem_size_kb, bx
keep_mem_size: mov ax, SEG_BSTACK ; init BIOS stack
mov ss, ax
mov sp, OFS_BSTACK ; at this point stack may be used
mov al, 00010011b ; ICW1: VECTOR 0, EDGE, INTERVAL 8, SINGLE, ICW4
out IO_PIC_CMD_STATUS, al ; program PIT ICW1
mov al, 00001000b ; ICW2: INT8
out IO_PIC_MASK, al ; program PIT ICW2
mov al, 00001001b ; ICW3: ID 0?
out IO_PIC_MASK, al ; program PIT ICW3
mov al, 11111111b ; ICW4: 8088 mode, ?
out IO_PIC_MASK, al ; program PIT ICW4
; init INT table with initial values
push ds ; store DS = 0
mov cx, 20h
xor di, di
mov es, di ; ES = 0
init_int_loop: mov ax, offset default_irq_handler
stosw
mov ax, cs
stosw
loop init_int_loop
; init bios services
mov di, 4 * 10h ; int 10h, start of BIOS services
mov ax, cs
mov ds, ax ; DS = CS
mov si, offset bios_services
mov cx, 10h ; count of bios services
init_bios_int_loop:
movsw ; install bios services
inc di ; skip SEGMENT initialization
inc di ; already points to CS
loop init_bios_int_loop ; install bios services
pop ds ; restore DS = 0
push ds ; store DS = 0
mov word ptr ZERO_BDATA + eq_list_flags, BIOS_EQ_FLAGS ; Printer + GamePort + RS-232 + 2 floppy + 80x25 color
mov al, 88h ; A = out, B = out, C[0..3] = out, C[4..7] = in
out IO_PPI_CTL, al ; program working PPI mode
cmp word ptr ZERO_BDATA + is_warm_boot, WARM_BOOT_MAGIC
mov es, bx
mov ds, bx ; DS = ES = B800
je short vmem_is_good ; do not test vmem on warm boot
%if MK_REV > 3
mov bx, offset alt_encoding
call font_init_04 ; load default font (alt encoding, cp866) for revision 04
%endif ; MK_REV
call set_mode_3 ; set initial mode to test video memory
mov bx, SEG_VIDEO
mov dx, IO_CGA_MODE ; video port
mov cx, 2000h ; test 8K
out dx, al
call do_mem_test ; test video ram
jz short vmem_is_good
jmp short video_failure
vmem_is_good: call set_mode_3 ; clear VRAM again
mov ax, 7020h ; default attribute
sub di, di
mov cx, 40 ; fill first line with AX
rep stosw
mov dx, IO_CGA_STATUS ; video status register
mov ah, 8 ; check vsync
retry_with_hsync: xor cx, cx
vsync_loop1: in al, dx ; get video status
and al, ah
jnz short vsync_found
loop vsync_loop1
jmp short video_failure
vsync_found: xor cx, cx
vsync_loop2: in al, dx ; Video status bits
and al, ah
jz short vsync_end
loop vsync_loop2
video_failure: pop ds ; restore DS = 0
push ds ; store DS = 0
mov dx, 102h ; long + 2 short
call error_beep ; dh = long beeps, dl = short beeps
jmp short vtest_done
vsync_end: mov cl, 3 ; check retrace bit
shr ah, cl
jnz short retry_with_hsync
vtest_done: call set_mode_3 ; clear screen again
mov si, offset bios_title
call print_msg_eol
mov si, offset bios_subtitle
call print_msg_eol
mov si, offset cpu_info
call print_msg_dots
xor al, al ; ZF = 1
mov al, 40h ; ZF not changed, this value is magic
mul al ; 40 * 40 => ZF = 0 on 8088, 1 on v20
mov si, offset cpu_8088
jnz cpu_is_8088
mov si, offset cpu_v20
cpu_is_8088: call print_msg
mov si, offset test_space_ok
call print_msg_eol
mov si, offset rom_test
call print_msg_dots
mov ax, cs
mov ds, ax ; DS = CS
mov bx, offset extrom_start
call calc_rom_cs ; DS:BX = start address, size = 2000h
jnz short pic_pit_failed
mov si, offset test_ok
call print_msg_eol
pop ds ; retore DS = 0
mov si, offset pic_test
call print_msg_dots
mov al, 0 ; enable all IRQ
out IO_PIC_MASK, al ; Interrupt controller, 8259A.
in al, IO_PIC_MASK ; Interrupt controller, 8259A.
or al, al ; read actual mask
jnz short pic_pit_failed ; PIC test failed
mov al, ~0 ; disable all IRQ
out IO_PIC_MASK, al ; Interrupt controller, 8259A.
in al, IO_PIC_MASK ; Interrupt controller, 8259A.
jmp short start_continue
start_0 endp ; sp-analysis failed
; =============== S U B R O U T I N E =======================================
BIOS_ENTRY(0E2C3h)
nmi_handler proc far
iret
nmi_handler endp
; =============== S U B R O U T I N E =======================================
start_continue proc near
add al, 1 ; check mask
jnz short pic_pit_failed ; PIC test failed
mov byte ptr ZERO_BDATA + last_irq_bits, al ; write 0 to test memory cell
sti
xor cx, cx
loop $ ; 274 ms
loop $ ; 274 ms
cmp byte ptr ZERO_BDATA + last_irq_bits, 0 ; check after ~0.5 sec delay
jz short pic_is_good
pic_pit_failed: ; PIC or PIT test failed
mov si, offset test_fail
call print_msg_eol
cli
hlt ; PIC failed
pic_is_good: mov si, offset test_ok
call print_msg_eol
mov si, offset pit_test
call print_msg_dots
mov al, ~1 ; disable all IRQs except for timer
out IO_PIC_MASK, al ; program PIC mask
mov al, 00_01_000_0b; counter 0, load LSB, mode 0, binary
out IO_TIMER_CTL, al ; program system timer
mov cl, 16h
mov al, cl
out IO_TIMER0_DIV, al ; set divisor = 16h
pit_wait: test byte ptr ZERO_BDATA + last_irq_bits, 1
jnz short pit_cont
loop pit_wait
jmp short pic_pit_failed
pit_cont: mov cl, 0Ch
mov al, ~0
out IO_TIMER0_DIV, al ; program timer divisor = 255
mov byte ptr ZERO_BDATA + last_irq_bits, 0 ; reset bit flags
mov al, ~1
out IO_PIC_MASK, al ; enable channel IRQ 0 (timer)
pit_test_loop: test byte ptr ZERO_BDATA + last_irq_bits, 1 ; test for IRQ 0
jnz short pic_pit_failed
loop pit_test_loop
mov si, offset test_ok
call print_msg_eol
mov al, ~0
out IO_PIC_MASK, al ; disable all IRQs
mov al, 00110110b ; counter 0, load LSB+MSB, mode 3
out IO_TIMER_CTL, al ; program system timer
mov al, 0
out IO_TIMER0_DIV, al ; set default divisor
out IO_TIMER0_DIV, al ; 65536
push ds
xor ax, ax
mov es, ax ; ES = 0
mov cx, 8 ; number of IRQs
push cs
pop ds ; DS = CS
mov si, offset irq_handlers
mov di, 8 * 4 ; first IRQ offset
irq_handlers_loop:
movsw
inc di
inc di
loop irq_handlers_loop
pop ds ; restore DS = 0
mov word ptr int_2_nmi, offset nmi_handler ; parity check is not used in MK88
mov word ptr int_5_prtscr, offset print_screen_handler
call set_ds_40 ; set DS = 40h
call keyb_init_data
push ds
xor bp, bp ; clear error flag
cmp word ptr is_warm_boot, WARM_BOOT_MAGIC
jnz short not_warm_boot
mov si, offset ram_test
call print_msg_dots
xor cx, cx
inc cx
mov ax, word ptr mem_size_kb
push cx
push bx
jmp short mem_print_size
not_warm_boot: mov al, 06h
out IO_PPI_PORT_C, al ; write keyboard column code
mov si, offset press_esc ; "press esc"
call print_info
mov ax, BIOS_LOW_MEMORY_SIZE_KB ; tested amount of memory
mov cx, word ptr mem_size_kb ; kilobytes to test
dec cx
dec cx ; skip first 2 kb
mov bx, BIOS_LOW_MEMORY_SIZE_KB * 1024 / 16 ; starting segment
mem_test_loop: push ax
push bx
mov si, offset ram_test
call print_msg_dots
pop bx
in al, IO_KBD_SCAN_DATA ; read keyboard data
cmp al, ~02h ; ESC
pop ax
jne short test_not_esc
mov si, offset clear_info ; clear "press esc"
call print_info
mov si, offset test_abort
call print_msg
test_wait_esc_release:
in al, IO_KBD_SCAN_DATA
cmp al, ~02h ; ESC
je short test_wait_esc_release
mov dx, ~WARM_BOOT_MAGIC
jmp short mem_test_end
test_not_esc: mov ds, bx
mov es, bx
add bx, 1024 / 16
push cx
push bx
push ax
mov cx, 1024 / 2
call do_mem_test
jnz short mem_fail_error
pop ax
inc ax ; next kilobyte
mem_print_size: push ax
mov bx, 10 ; decimal conversion
mov cx, 3 ; number of digits
div_size_loop: xor dx, dx
div bx
or dl, '0'
push dx ; push digit
loop div_size_loop
mov cx, 3 ; print in reverse order
print_size_loop:
pop ax ; pop digit
call print_tty ; AL = char
loop print_size_loop
mov si, offset kb_ok
call print_msg
pop ax ; restore memory size
pop bx
pop cx
loop mem_test_loop ; !!!!!!!!!!!
mov si, offset clear_info ; clear "press esc"
call print_info
mov dx, WARM_BOOT_MAGIC ; test OK
mem_test_end: call print_eol
jmp short mem_good
mem_fail_error: mov ch, al ; keep AL (failed bits)
mov si, offset clear_info ; clear "press esc"
call print_info
pop ax
pop si
pop si ; drop BX and CX
pop ds ; restore DS = 40h
push ds
mov word ptr mem_size_kb, ax ; correct memory size
call print_mem_addr ; ES:DI = addr
mov al, ch ; print failed bits
call hex_print_byte ; AL = hex value => AX, CL destroyed, BH = 0
mov si, offset ram_error ; "ram error"
call print_msg_eol_bp
mov dx, ~WARM_BOOT_MAGIC ; test is not OK
mem_good: pop ds ; restore DS = 40h
mov word ptr is_warm_boot, dx
mov si, offset press_del ; "press del"
call print_info
mov si, offset fdd_test
call print_msg_dots
mov si, offset keyb_buffer
mov word ptr keyb_buf_ptr, si
mov word ptr keyb_buf_start, si
mov word ptr keyb_buf_start_ofs, si
add si, KEYB_BUFFER_SIZE
mov word ptr keyb_buf_end_ofs, si
in al, IO_PIC_MASK ; get current PIC mask
and al, ~49h ; enable IRQ 0 (timer), 3 (keyboard), 6 (floppy)
out IO_PIC_MASK, al ; set new PIC mask
sti
mov ah, 0
mov dl, ah
int 13h ; reset floppy drives
test ah, ~0
jnz short floppy_is_failed
mov dx, IO_FLOPPY_SELECT
mov al, 1Ch
out dx, al ; enable controller, dma and drive 1 motor
xor cx, cx
loop $
loop $
xor dx, dx
inc ch ; set ch = 1
mov byte ptr floppy_seek_status, dl
call floppy_seek_track
jc short floppy_is_failed
mov ch, 34
call floppy_seek_track
jc short floppy_is_failed
call floppy_read_id
jc short floppy_is_failed
mov al, byte ptr floppy_result_c
cmp al, 34 ; test track
jne not_sd
mov si, offset test_sd
call print_msg
jmp short floppy_ok
not_sd: cmp al, 34 * 2
jne floppy_is_failed
mov si, offset test_dd
call print_msg
or byte ptr floppy_seek_status, 40h
floppy_ok: mov si, offset test_ok
call print_msg_eol
jmp short floppy_cont
floppy_is_failed:
mov si, offset test_fail
call print_msg_eol_bp
mov si, offset disk_error
call print_msg_eol_bp
floppy_cont: mov al, 0Ch ; enable floppy controller
mov dx, IO_FLOPPY_SELECT
out dx, al
mov byte ptr last_irq_bits, 0
; reset/detect LPT ports
mov di, offset printer_timeout
push ds
pop es
mov ax, 1414h ; set printer timeout to 14h
stosw
stosw
mov ax, 101h ; set serial port timeout to 0101
stosw
stosw
mov si, offset lpt_test
call print_msg_dots
mov dx, IO_PRINTER1_INIT
mov al, 10000010b ; PORT B = INPUT, other = OUTPUT
out dx, al
mov di, offset parallel_ports
xor bx, bx
next_printer_detect:
mov dx, cs:[di]
mov al, 0AAh
out dx, al
push ds
in al, dx
pop ds
cmp al, 0AAh
jnz short printer_not_found
call print_3addr
mov al, ' '
call print_tty
mov word ptr prn_port_addr[bx], dx
inc bx
inc bx
printer_not_found:
inc di
inc di
cmp di, offset parallel_ports_end
jne short next_printer_detect
mov si, offset test_none
or bx, bx
jz end_printer_test
mov si, offset test_ok
end_printer_test:
call print_msg_eol
; reset/detect COM ports
mov si, offset com_test
call print_msg_dots
mov dx, IO_SERIAL1_SCRATCH
mov al, 0AAh
out dx, al
nop
in al, dx
cmp al, 0AAh
mov si, offset test_none
jnz end_serial_test
mov dl, byte (IO_SERIAL1_DATA & 0FFh)
mov word ptr [serial_port_addr], dx
call print_3addr
mov si, offset test_space_ok
end_serial_test:
call print_msg_eol
call set_ds_40
push ds
pop es
mov dx, 1 ; 1 short beep
or bp, bp
jz bios_beep
mov si, offset press_f1 ; "press F1"
call print_msg
mov dx, 2 ; 2 short beeps
bios_beep call error_beep ; dh = long beeps, dl = short beeps
mov si, offset clear_info ; clear "press del"
call print_info
call print_eol
or bp, bp
jz short test_all_ok
f1_wait_loop: xor ah, ah
int 16h ; wait for keypress
cmp ah, XT_SCAN_M
je short do_mon
cmp ah, XT_SCAN_DEL
je short test_main_screen
cmp ah, XT_SCAN_F1
jne short f1_wait_loop
jmp short normal_boot
do_mon: call print_eol
xor ax, ax
inc ax ; return to new boot
jmp monitor_entry
test_main_screen:
%if MK_REV == 3
in al, IO_PPI_PORT_B
and al, ~80h
out IO_PPI_PORT_B, al ; disable cp866 encoding for revision 01...03
%endif ; MK_REV
xor ax, ax
mov es, ax
mov bx, offset main_encoding
mov word ptr es:[4 * 1Fh], bx
%if MK_REV > 3
call font_init_04 ; load original font (main encoding) for revision 04
%endif ; MK_REV
cmp word ptr is_warm_boot, WARM_BOOT_MAGIC
jz near main_menu_dialog
jmp near show_bios_screen
test_all_ok: sti
mov bx, 1000
call msleep ; sleep for 1 second
kb_flush_loop: mov ah, 01h
int 16h
jz normal_boot
xor ah, ah
int 16h
cmp ah, XT_SCAN_M
je short do_mon
cmp ah, XT_SCAN_DEL
je short test_main_screen
jmp short kb_flush_loop
normal_boot: call print_eol
%if MK_REV == 3
in al, IO_PPI_PORT_B
or al, 80h
out IO_PPI_PORT_B, al ; enable cp866 encoding
%endif ; MK_REV
clc
int 19h ; DISK BOOT
mov si, offset boot_error
call print_msg_eol_bp
boot_retry: mov si, offset press_f1 ; "press F1"
call print_msg
jmp short f1_wait_loop
start_continue endp
bios_subtitle db 'By Oleg A. Odintsov (nopmeister@xmail.ru). Moscow, 2026', 0
cpu_info db 'CPU', 0
rom_test db 'ROM', 0
pic_test db 'PIC', 0
pit_test db 'PIT', 0
ram_test db 'RAM', 0
fdd_test db 'FDD', 0
lpt_test db 'LPT', 0
com_test db 'COM', 0
str_dots db ' ... ', 0
test_space_ok db ' '
test_ok db 'OK', 0
cpu_8088 db '8088', 0
cpu_v20 db 'v20', 0
test_fail db 'FAIL', 0
test_none db 'NONE'
test_empty db 0
test_abort db 'SKIPPED ', 0
test_sd db 'SD ', 0
test_dd db 'DD ', 0
ram_error db ' ERROR', 0
boot_error db 'BOOT ERROR', 0
program_floppy_parameter_2 proc
test byte ptr floppy_seek_status, 40h ; double density?
jnz floppy_dd
add ah, ah
floppy_dd: jmp program_floppy_parameter
program_floppy_parameter_2 endp
floppy_get_info proc
mov bl, 03h ; 720K
mov cx, 4F09h ; cyl and sec
test byte ptr floppy_seek_status, 40h ; double density?
jnz floppy_info_dd
mov bl, 01h ; 360K
mov cx, 2709h ; cyl and sec
floppy_info_dd: mov dx, 0102h
push cs
pop es
mov di, offset dpt_pointer
pop ax ; return address
pop ax ; DX
pop bp
pop ax ; DI
pop si
pop ds
pop ax ; CX
pop ax ; BX
xor ax, ax
clc
retf 2
floppy_get_info endp
monitor_cmd_l proc
call read_cx_si ; => SI = start address, CX = count, DS = current DS
mov ah, 02h
push ds
pop es
mov bx, si
int 15h
jnc short monitor_tape_ok
monitor_tape_fail:
mov al, ah
call mon_print_byte
jmp cmd_reenter
monitor_tape_ok:ret
monitor_cmd_l endp
monitor_cmd_w proc
call read_cx_si ; => SI = start address, CX = count, DS = current DS
mov ah, 03h
push ds
pop es
mov bx, si
int 15h
jc short monitor_tape_fail
ret
monitor_cmd_w endp
%include "boot.asm"
%include "serial.asm"
%include "keyb.asm"
%include "floppy.asm"
%include "printer.asm"
%include "video.asm"
press_esc db '[ Press ESC to skip test ]', 0
press_del db '[ Press DEL to enter menu ]', 0
clear_info db ' ', 0
press_f1 db KEY_CR, 'Press F1 to continue, DEL to menu, M to monitor...', 0
disk_error db 'NO DISK OR DISK ERROR', 0
%include "services.asm"
mon_help db "checksum", 0
db "dump area", 0
db "compare data", 0
db "fill area", 0
db "run program", 0
db "add/sub", 0
db "move data", 0
db "i/o ports", 0
db "edit data", 0
db "trace program", 0
db "edit reg/flags", 0
db "quit", 0
db "input text", 0
db "dump text", 0
db "print text", 0
db "load tape", 0
db "write tape", 0
db "help", 0
BIOS_ENTRY(0FA6Eh)
font_low:
%include "font_low.inc"
%include "timer.asm"
BIOS_ENTRY(0FEF3h)
irq_handlers dw offset timer_irq_handler
dw offset keyb_irq_handler
dw offset default_irq_handler
%if MK_REV < 5
dw offset keyb2_irq_handler
%else
dw offset default_irq_handler
%endif
dw offset default_irq_handler
dw offset default_irq_handler
dw offset floppy_irq_handler
dw offset default_irq_handler
bios_services dw offset int_10h
dw offset int_11h
dw offset int_12h
dw offset int_13h
dw offset int_14h
dw offset int_15h
dw offset int_16h
dw offset int_17h
dw offset monitor_start
dw offset int_19h
dw offset int_1Ah
dw offset empty_int_handler
dw offset empty_int_handler
dw offset vpt_pointer
dw offset dpt_pointer
dw offset alt_encoding
%include "handlers.asm"
print_mem_addr proc near ; ES:DI = addr
call print_far_addr
mov al, '~'
call print_tty ; AL = char
retn
print_mem_addr endp
set_ds_40 proc near
push ax
mov ax, SEG_BDATA
mov ds, ax
pop ax
retn
set_ds_40 endp
BIOS_ENTRY(0FFF0h)
start jmp SEG_BIOS:start_0 ; RESET startup code
BIOS_ENTRY(0FFF5h)
bios_date db '04/09/26',0
BIOS_ENTRY(0FFFEh)
db BIOS_TYPE_CODE
db 0 ; for checksum
BIOS_F ENDS
end start
MongoDB Logo MongoDB