Real hardware FDC initialization problems
Posted: Wed Aug 28, 2024 10:08 am
My floppy driver works on both Linux and QEMU. I wanted to try it on real hardware, thus I acquired an old school floppy drive connected to the motherboard with a ribbon cable. To make a long story short, I finally manged to write my OS to a floppy and boot from it. My floppy driver however doesn't work at all. After lots of tries I discovered that:
1 It can't recalibrate
2 It can't seek
3 The DIO bit is set when I send the 4 sense interrupts.
Considering that 3 is the first thing in the chain of commands that fails I focused on that.
This is the code which somehow leaves FIO set when I want to send the sense interrupts.
1 It can't recalibrate
2 It can't seek
3 The DIO bit is set when I send the 4 sense interrupts.
Considering that 3 is the first thing in the chain of commands that fails I focused on that.
Code: Select all
initialize_floppy_controller: ;Ui16 base
push edx
push esi
movzx edx, word [esp+12]
push floppy_initializing
push word 0x0F
call console_write
push edx
push word 0x0F
call console_write_ui32
push word 1
call update_screen
add dx, 2 ;DOR offset
mov byte [FLOPPY_IRQ_RECEIVED], 0 ;Reset interrupt here if it occurs very fast
;Send reset
mov al, 0
out dx, al
out dx, al
;Clear reset
mov al, 00001100b ;Normal operation
out dx, al
mov [FLOPPY_DOR_COPY], al
push word 50
call floppy_wait_irq
cmp eax, 1
je initialize_floppy_controller_timed_out
;Sense interupt here after reset as poll isn't disabled yet
push word [esp+12]
push word 0x08
call write_command_floppy
push word [esp+12]
call read_data_floppy
push word [esp+12]
call read_data_floppy
;Set preliminary transfer speed
mov dx, [esp+12]
add dx, 7 ;CCR offset
mov al, 00000000b ;500kb/s
out dx, al
;Write sense interrupt for each drive
;TODO write_command_floppy fails here on hardware as DIO is set
write_command_floppy: ;Ui16 base, Ui16 command, Returns Ui32 timed_out
push edx
mov ebx, 100000
mov dx, [esp+10] ;Base
add dx, 4 ;MSR
write_command_floppy_loop:
cmp ebx, 0
je write_command_floppy_timeout
in al, dx
test al, 10000000b ;RQM bit set
jne write_command_floppy_done
dec ebx
jmp write_command_floppy_loop
write_command_floppy_done:
test al, 01000000b
jne write_command_floppy_error ;DIO bit set
;Write command
inc dx ;FIFO
mov ax, [esp+8]
out dx, al
mov eax, 0
pop edx
ret 4
write_command_floppy_timeout:
mov eax, 1
pop edx
;Int for debug purposes
int 1
ret 4
write_command_floppy_error:
mov eax, 2
pop edx
;Int for debug purposes
int 1
ret 4
read_data_floppy: ;Ui16 base, Returns Ui32 data, Ui32 timed_out
push edx
mov ebx, 100000
mov dx, [esp+8]
add dx, 4 ;MSR
read_data_floppy_loop:
cmp ebx, 0
je read_data_floppy_timeout
in al, dx
test al, 11000000b ;Bits set
jne read_data_floppy_loop_done
dec ebx
jmp read_data_floppy_loop
read_data_floppy_loop_done:
inc dx ;FIFO
in al, dx
mov ebx, 0
pop edx
ret 2
read_data_floppy_timeout:
mov eax, 0
mov ebx, 1
pop edx
;Int for debug purposes
int 1
ret 2
This is the code which somehow leaves FIO set when I want to send the sense interrupts.