Why is the floppy driver always busy in seek mode ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Hello !

As this is my first post here with this account, I'll present myself :-)

I'm a 17 years old Moroccan . I like doing SEO ( search engine optimization ) and programming . I learned to program first in PASCAL ( and now I forgot how to program in this language, because I didn't use it since many years :oops: ) at 9~10 years I think, then C and ASM in the following years .

At 15 years, I've created my first hobby kernel in C running in 32 pmode ( without multi-tasking or ELF support ), then I dropped it because it was written too poorly even if it works .

Now I've decided to entirely rewrite my OS, but in pure ASM language, with its own bootloader, and without using BIOS interrupts to load the sectors with the bootloader . A little bit crazy, but I think I can improve my skills a lot if I can achieve that :-) .

I've read some online documentations about the floppy controller and I think I'm ready now .

So I've written some little code just to test the SEEK command ( head 0, cyl 0 ) :

Code: Select all

;; SEEK COMMAND ;;
mov dx, 0x3F5 ;; data register
mov al, 0x0F ;; seek command
out dx, al
xor al, al
out dx, al ;; head 0
out dx, al ;; cyl 0

;; POLLING
dec dx ;; MSR Port
poll_seek:
in al, dx
shl al, 7
cmp al, 0x80 ;; Testing the first bit of the MSR
je poll_seek ;; The first bit is 1, so the floppy controller is still busy in seek mode ? Then check again .

mov dx, 0x1 ;; If the "Busy in seek mode" bit is 0, then I must see dx with the value 0x1 in BOCHS
jmp $
But after testing with BOCHS, I see that the floppy controller is always busy in seek mode as the first bit in the MSR is always at 1 .

Am I missing something ?

Thanks !

PS : BTW, can the administrator of this forum remove or correct the IP checking at posting ? It thinks my IP is a spammer's one :s
User avatar
Thor
Member
Member
Posts: 51
Joined: Mon Jul 06, 2009 12:55 am
Location: Kamloops, BC, Canada

Re: Why is the floppy driver always busy in seek mode ?

Post by Thor »

Are you starting the motor? Whenever you perform any kind of seek, read, write, etc. command, you must start the motor by setting bit 4 (0x10) in the digital output register (0x3F2)
Vancouver Canucks fan for life
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Thor wrote:Are you starting the motor? Whenever you perform any kind of seek, read, write, etc. command, you must start the motor by setting bit 4 (0x10) in the digital output register (0x3F2)
Ah I forgot that... I'll try it, thanks :)

PS : isn't the motor already started when the BIOS boots from the floppy drive ?
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Well it didn't change anything... Here's how I started the motor :

Code: Select all

;; STARTING THE MOTOR
mov dx, 0x3F2
mov al, 0x1C ;; Turn ON motor 1, enable interrupts/DMA, controller enabled, drive 00
out dx, al
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: Why is the floppy driver always busy in seek mode ?

Post by Dex »

Here is the seek from my OS

Code: Select all

 ;----------------------------------------------------;
 ; Fdd seek                                           ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;          none.                                     ;
 ;  Output:                                           ;
 ;                                                    ;
 ;                                             (100%) ;
 ;....................................................;

FddReadWriteSeek:
        pushad
        mov   al,[ResultC]                              ; put what track/cylinder we are at in al
        cmp   [cTrack],al                               ; is it the same,as we want
        je    FddSeekControllerSuccsess                 ; yes leave.
        call  FdcSendByteReady                          ; can we send a byte ?.
        jc    FddSeekControllerError                    ; Is CF 1, if so timeout error.

        mov   [Timer],1                                 ; 5 = 250us
        mov   [TimerOn],1                               ; start couting
        call  WaitTimer                                 ; wait for timer
                                                        ;  **** ISSUE A SEEK COMMAND ****
        mov   dx,DtReg                                  ; DtReg = 0x3f5 
        mov   al,0x0F                                   ; Seek Command 
        out   dx,al

        call  FdcSendByteReady                          ; can we send a byte ?.
        jc    FddSeekControllerError                    ; Is CF 1, if so timeout error.

        mov   [Timer],1                                 ; 5 = 250us
        mov   [TimerOn],1                               ; start couting
        call  WaitTimer                                 ; wait for timer

        mov  dx,DtReg                                   ; DtReg = 0x3f5 
        mov  al,[DriveHead]                             ; Drive # (00 = A)
        out  dx,al 

        call  FdcSendByteReady                          ; can we send a byte ?.
        jc    FddSeekControllerError                    ; Is CF 1, if so timeout error.

        mov   [Timer],1                                 ; 5 = 250us
        mov   [TimerOn],1                               ; start couting
        call  WaitTimer                                 ; wait for timer

        mov  dx,DtReg                                   ; DtReg = 0x3f5 
        mov  al,[cTrack]                                ; Cylinder #                
        out  dx,al
                                                        ;  **** WAIT FOR INTERRUPT ****
        mov   [done],0                                  ; we need to wait
        call  WaitDone                                  ; for floppy int.
        jc    FddSeekControllerError                    ; jump to error exit,if timeout.
       
                                                        ;  **** ISSUE SENSE INTERRUPT STATUS COMMAND ****
        call  FdcSendByteReady                          ; can we send a byte ?.
        jc    FddSeekControllerError                    ; Is CF 1, if so timeout error.

        mov   [Timer],1                                 ; 5 = 250us
        mov   [TimerOn],1                               ; start couting
        call  WaitTimer                                 ; wait for timer

        mov   dx,DtReg                                  ; DtReg = 0x3f5 
        mov   al,0x08                                   ; Sense Interrupt Status Command
        out   dx,al

        call  FdcGetByteReady                           ; can we get a byte ?.
        jc    FddSeekControllerError                    ; Is CF 1, if so timeout error.

        mov   dx,DtReg                                  ; Should read ST0 ,(DtReg = 0x3f5 )
        in    al,dx
 
        mov   ah,al                                     ; save ST0 in ah

        call  FdcGetByteReady                           ; can we get a byte ?.
        jc    FddSeekControllerError                    ; Is CF 1, if so timeout error.

        mov   dx,DtReg                                  ; Should read PCN ,(DtReg = 0x3f5 )
        in    al,dx

       ; mov   al,FddErrorSeekFail

        test  ah,00100000b                              ; test sr0 is 0x20
        jz    FddSeekControllerError                    ; if not we have a error :-(.
   
        test  ah,10000000b                              ; test sr0 is 0x80
        jnz    FddSeekControllerError                   ; if not we have a error :-(.
       

FddSeekControllerSuccsess:                              ; succsess we hope :-)
        popad
        clc
        ret

FddSeekControllerError:                                 ; we have a error (blame M$)
        popad
        stc
        ret

 ;----------------------------------------------------;
 ; FdcSendByteReady   ;floppy control  sendbyte ready ;
 ;----------------------------------------------------;

FdcSendByteReady:
        push  eax
        push  edx
        mov   [Timer],30 	                        ; 20 = about 1 second,we use (1.5 seconds).
        mov   [TimerOn],1                               ; start counting.
FdcSendByteReadyLoop:
        mov   al,[TimerOn]                              ; we test if 
	or    al,al                                     ; timeout is up yet?.  
        jz    FdcSendByteReadyError                     ; if it is we exit,with error.
        mov   dx,MsReg                                  ; check status reg
        in    al,dx
        and   al,11000000b
        cmp   al,10000000b                              ; are we ok to write
        jnz   FdcSendByteReadyLoop                      ; if not do another loop.
        pop   edx
        pop   eax
        clc                                             ; we end here if we write:-)
	ret

FdcSendByteReadyError:                                  ; we end up here if we run out of time:-(.
        pop   edx
        pop   eax
        stc
        ret


 ;----------------------------------------------------;
 ; FdcGetByteReady     ;floppy control  getbyte ready ;
 ;----------------------------------------------------;

FdcGetByteReady:
        push  eax
        push  edx
        mov   [Timer],30	                        ; 20 = about 1 second,we use (1.5 seconds).
        mov   [TimerOn],1                               ; start couting.
FdcGetByteReadyLoop:
        mov   al,[TimerOn]                              ; we test if 
	or    al,al                                     ; timeout is up yet?.  
        jz    FdcGetByteReadyError                      ; if it is we exit,with error.
        mov   dx,MsReg                                  ; check status reg
        in    al,dx
        and   al,11000000b
        cmp   al,11000000b                              ; are we ok to read
        jnz   FdcGetByteReadyLoop                       ; if not do another loop.
        pop   edx
        pop   eax
        clc                                             ; we end here if we can getbyte:-)
	ret

FdcGetByteReadyError:                                   ; we end up here if we run out of time:-(.
        pop   edx
        pop   eax
        stc
        ret
 ;----------------------------------------------------;
 ; Fdd motor off         ;TURNS MOTOR OFF WITH DELAY. ;
 ;----------------------------------------------------;

Fdd_motor_off:
        mov   dx,DorReg                                 ; DorReg = 0x3F2
        mov   al,0
        out   dx,al
        mov   [MotorOn],0                               ; mov the on bit 0,this means motor off.
        ret

 ;----------------------------------------------------;
 ; Fdd Motor On           ;TURNS MOTOR ON WITH DELAY. ;
 ;----------------------------------------------------;

FddMotorOn:                                             
        mov   dx,DorReg                                 ; DorReg = 0x3F2
        mov   al,00011100b                              ; motor 0 on, DMA enabled, no reset, drive A:(00011100b)
        out   dx,al
        mov   [Timer],20                                ; 5 = 250us
        mov   [TimerOn],1                               ; start couting
        call  WaitTimer                                 ; wait for timer
        mov   [MotorOn],1                               ; mov the on bit 1
        ret
It may help you to fix yours, note the comments go with the intel floppy controler pdf perdo code.
Also note its hook into the fdd int.
And motor needs spin up time.
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Thanks for your code ( even if I don't search code snippets as I want just to write everything from scratch ) :-)

So if I understand correctly, I have to check the "FIFO Ready" bit ( last bit ) in the MSR after each "out" instruction ?

And why "sleep" commands ? Can I just use polling instead ? Because I can't implement IRQs right now ...
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Sorry for bumping...

No one has a clue ? :?

Thanks !
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: Why is the floppy driver always busy in seek mode ?

Post by mathematician »

You can use polling. The floppy is easily the most temperamental piece of hardware in a PC.

However, why write your own driver the boot loader? You are going to get more than enough practice later on, when you have got no choice but to write your own protected mode drivers.
The continuous image of a connected set is connected.
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

mathematician wrote:You can use polling. The floppy is easily the most temperamental piece of hardware in a PC.

However, why write your own driver the boot loader? You are going to get more than enough practice later on, when you have got no choice but to write your own protected mode drivers.
Well, that's something like a "challenge" for me; I want to write a bootsector without using BIOS interrupts . It's a little crazy yea, but hey, there's no difference between a floppy driver in the bootsector and a floppy driver in the kernel ( probably the difference is the size, but as I just want something really basic to load just the second sector, I think it will perfectly fit into one floppy sector ) .

I tried everything but without results... Is there a mistake in my code ? Do I have skipped some steps somewhere ? Is the order of the commands sent to the floppy controller correct ? If not, can someone give me that exact order ?

Thanks !
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

No one ? :(
User avatar
Thor
Member
Member
Posts: 51
Joined: Mon Jul 06, 2009 12:55 am
Location: Kamloops, BC, Canada

Re: Why is the floppy driver always busy in seek mode ?

Post by Thor »

2 things: You're polling the wrong bit and you're doing a je instead of a jne.

You'll want to poll the DRV 0 BSY bit (bit 0) and the CMD BSY bit (bit 4) until both clear.

Something like this:

Code: Select all

in        al, 0x3F4
test      al, 0x11
jnz       PollingLoop
Vancouver Canucks fan for life
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Thor wrote:2 things: You're polling the wrong bit and you're doing a je instead of a jne.

You'll want to poll the DRV 0 BSY bit (bit 0) and the CMD BSY bit (bit 4) until both clear.

Something like this:

Code: Select all

in        al, 0x3F4
test      al, 0x11
jnz       PollingLoop
I've already checked bit 0 in the MSR, but I didn't check the 4th bit, thank you ! I'll try that quickly :)

And yea that's right, I'm doing a je instead of a jne because it must loop until the bits clear .

--

After testing, it didn't change anything and the floppy driver is always busy in seek mode ...

Here's my polling code :

Code: Select all

poll_seek:
in al, dx
shl al, 4 ;; Checking CTRL BUSY ( bit 4 )
jc poll_seek
shl al, 4 ;; Checking DRV 0 BUSY ( bit 0 )
jc poll_seek
And after debugging, I saw that the MSR is always at 0x81, which means that FIFO RDY ( bit 7 ) and DRV 0 BUSY ( bit 0 ) are set .

I don't know why the MSR isn't changing ...

Here's the complete code of my bootloader ( you need fasm to assemble it, or just modify one or two lines to make it work with nasm&co ) :

Code: Select all

use16
org 0x7C00

xor ax, ax
mov ds, ax

cli

;; STARTING THE MOTOR
mov dx, 0x3F2
mov al, 0x1C
out dx, al
poll_motor_start:
mov dx, 0x3F4
in al, dx
shr al, 8
jnc poll_motor_start

;; SEEK COMMAND ;;
inc dx ; 0x3F5
mov al, 0x0F
out dx, al
xor al, al
out dx, al
out dx, al

;; POLLING
dec dx
poll_seek:
in al, dx
shl al, 4 ;; Checking CTRL BUSY ( bit 4 )
jc poll_seek
shl al, 4 ;; Checking DRV 0 BUSY ( bit 0 )
jc poll_seek

mov dx, 1 ;; I must see DX = 0x1 in Bochs' debugger if everything works fine
jmp $

times 510-($-$$) db 0x90
dw 0xAA55
User avatar
Thor
Member
Member
Posts: 51
Joined: Mon Jul 06, 2009 12:55 am
Location: Kamloops, BC, Canada

Re: Why is the floppy driver always busy in seek mode ?

Post by Thor »

It's hanging before you even get to the seek_poll.

I made it work fine, but I have some advice for you: Learn how it works for yourself. If you don't understand how your own code works, of course you won't be able to solve problems with it. This is the best resource there is for the FDC:
FDC Data Sheet

This is what I did:

Code: Select all

;; STARTING THE MOTOR
mov dx, 0x3F2
mov al, 0x1C
out dx, al

;; SEEK COMMAND ;;
mov dx, 0x3F5
mov al, 0x0F
out dx, al
xor al, al
out dx, al
out dx, al

;; POLLING
dec dx
poll_seek:
in	al, dx
test	al, 0x11
jnz	poll_seek

mov dx, 1 ;; I must see DX = 0x1 in Bochs' debugger if everything works fine
jmp $

times 510-($-$$) db 0x90
dw 0xAA55
Next time please read the material first #-o
Last edited by Thor on Thu Jul 30, 2009 2:56 pm, edited 1 time in total.
Vancouver Canucks fan for life
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

You're using the port 0x3F3 to issue the Seek command ... ?
User avatar
WhiteSpirit
Posts: 16
Joined: Sat Jul 18, 2009 2:53 pm

Re: Why is the floppy driver always busy in seek mode ?

Post by WhiteSpirit »

Err... Wait a minute, the code is totally wrong . You're using the wrong ports !

0x3F5 for DSR and not 0x3F3
0x3F4 for MSR and not 0x3F2

And no, I'm getting to the poll loop with my code, so it's not hanging before .
Post Reply