; ==========================
; # 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