Page 1 of 1

Real hardware FDC initialization problems

Posted: Wed Aug 28, 2024 10:08 am
by LoveProgramming
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.

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.

Re: Real hardware FDC initialization problems

Posted: Thu Aug 29, 2024 2:41 pm
by thewrongchristian
LoveProgramming wrote: 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.

Code: Select all

 
 asm code with no delays

This is the code which somehow leaves FIO set when I want to send the sense interrupts.
I've never personally coded a FDC driver, but one difference I do know between virtual devices in QEMU and real hardware devices is that real hardware needs lots of delays between different steps.

Review Floppy_Disk_Controller, and perhaps an existing driver such as FreeBSD fdc and its reset:

https://xref.landonf.org/source/s?refs= ... -13-stable

Note all the calls to DELAY() in that driver at various points.

Re: Real hardware FDC initialization problems

Posted: Sun Sep 01, 2024 6:54 am
by LoveProgramming
I figured it out. Turns out:

Code: Select all

test al, 11000000b ;Bits set
    jne read_data_floppy_loop_done
Will branch if EITHER bit is set, not ONLY if both are set. Once I figured this out most things worked like a charm. Still not sure why the DIO bit gets cleared before reading the last byte from the 4 sense interrupts when initializing (what puzzles me is this happens both on QEMU and on hardware), but this is something I can live with.