Page 1 of 2
Why is the floppy driver always busy in seek mode ?
Posted: Sat Jul 18, 2009 3:37 pm
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
) 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
Re: Why is the floppy driver always busy in seek mode ?
Posted: Sat Jul 18, 2009 7:47 pm
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)
Re: Why is the floppy driver always busy in seek mode ?
Posted: Sun Jul 19, 2009 3:16 am
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 ?
Re: Why is the floppy driver always busy in seek mode ?
Posted: Sun Jul 19, 2009 3:46 am
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
Re: Why is the floppy driver always busy in seek mode ?
Posted: Sun Jul 19, 2009 6:18 am
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.
Re: Why is the floppy driver always busy in seek mode ?
Posted: Sun Jul 19, 2009 8:27 am
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 ...
Re: Why is the floppy driver always busy in seek mode ?
Posted: Tue Jul 21, 2009 11:16 am
by WhiteSpirit
Sorry for bumping...
No one has a clue ?
Thanks !
Re: Why is the floppy driver always busy in seek mode ?
Posted: Tue Jul 21, 2009 12:45 pm
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.
Re: Why is the floppy driver always busy in seek mode ?
Posted: Thu Jul 23, 2009 6:16 am
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 !
Re: Why is the floppy driver always busy in seek mode ?
Posted: Tue Jul 28, 2009 1:44 pm
by WhiteSpirit
No one ?
Re: Why is the floppy driver always busy in seek mode ?
Posted: Wed Jul 29, 2009 7:20 am
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
Re: Why is the floppy driver always busy in seek mode ?
Posted: Thu Jul 30, 2009 11:34 am
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
Re: Why is the floppy driver always busy in seek mode ?
Posted: Thu Jul 30, 2009 12:33 pm
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
Re: Why is the floppy driver always busy in seek mode ?
Posted: Thu Jul 30, 2009 2:00 pm
by WhiteSpirit
You're using the port 0x3F3 to issue the Seek command ... ?
Re: Why is the floppy driver always busy in seek mode ?
Posted: Thu Jul 30, 2009 2:51 pm
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 .