I'm having some serious problems with the floppy drive controller (in protected mode). I've found no information on anything needed to be done before sending commands, so I'm basically on square one.
I've tried to send some commands (like seek), MSR goes to 0x1, and very shortly to 0x81, but thats it. Nothing more happens, and no sign of the head moving, and the register do not change again (or at least not during the up to 10 seconds I've waited). Neither do I see/hear anything happen when I do recalibrate. Motor is on, and I've waited like 700ms before sending commands
The only thing I've done before I send these commands is to reset the controller and set DOR to 0x1C. Not using the DMA, only writing directly to the ports. Have I missed something critical? I prefer examples in ASM, but C is okay too.
// Steven
Problems with Floppy drive controller
-
- Posts: 2
- Joined: Sun Jun 08, 2008 10:31 pm
- Location: 40 miles north of Stockholm, Sweden
- Contact:
Problems with Floppy drive controller
As long as you try, you can't say you'll fail in the end!
Current project name: tP/OS (The Parsing OS)
Progress: Standing on ground, scratching head. Codename: "Crash and burn"
The place where the magic happens
Current project name: tP/OS (The Parsing OS)
Progress: Standing on ground, scratching head. Codename: "Crash and burn"
The place where the magic happens
You can take a look at DexOS Fdd driver
Note: Rename the bellow file FddInfo.asm to FddInfo.inc
Code: Select all
;=========================================================;
; Fdd 11/12/03 ;
;---------------------------------------------------------;
; DOS EXTREME OS V0.01 ;
; by Craig Bamford (Dex) ;
; ;
; Pmode floppy disk driver. ;
;=========================================================;
include 'FddInfo.inc'
;----------------------------------------------------;
; 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
;----------------------------------------------------;
; FddReSet ;ResetController. ;
;----------------------------------------------------;
; ;
; Input: ;
; none. ;
; Output: ;
; ;
; (100%) ;
;....................................................;
FddReSet:
; **** RESET ****
mov dx,DorReg ; DorReg = 0x3F2
mov al,00001000b ; no motors enabled, DMA Enabled, held FDC at reset
out dx,al ; drive A selected.
mov [Timer],5 ; 5 = 250us
mov [TimerOn],1 ; start couting
call WaitTimer ; wait for timer
; **** PROGRAM DATE VIA CCR ****
mov dx,CcrReg ; CcrReg = 0x3f7
mov al,00000000b ; 500Kb/sec mode
out dx,al
mov dx,DorReg ; DorReg = 0x3F2
or al,00001100b ; FDC completed reset, al =0x0c.
out dx,al
; **** WAIT FOR INTERRUPT ****
mov [done],0 ; we need to wait
call WaitDone ; for floppy int.
jc ResetControllerError ; jump to error exit,if timeout.
mov cx,0x04 ; number of loops.
; **** ISSUE SENSE INTERRUPT ****
SenseStatusLoop: ; After a reset, the interrupts must be
; cleared by (four) dummy-reads.
call FdcSendByteReady ; can we send a byte ?.
jc ResetControllerError ; 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 ResetControllerError ; Is CF 1, if so timeout error.
mov dx,DtReg ; Should read ST0 ,(DtReg = 0x3f5 )
in al,dx
call FdcGetByteReady ; can we get a byte ?.
jc ResetControllerError ; Is CF 1, if so timeout error.
mov dx,DtReg ; Should read PCN ,(DtReg = 0x3f5 )
in al,dx
loop SenseStatusLoop ; Is cx,0 no then loop to lable.
; **** PARAMETERS DIFFERENT FROM DEFAULT ****
call FdcSendByteReady ; can we send a byte ?.
jc ResetControllerError ; Is CF 1, if so timeout error.
mov [Timer],1 ; 5 = 250us
mov [TimerOn],1 ; start couting
call WaitTimer ; wait for timer
; **** SPECIFY COMMAND ****
mov dx,DtReg ; DtReg = 0x3f5
mov al,0x03 ; Specify Command (includes next two bytes sent)
out dx,al
call FdcSendByteReady ; can we send a byte ?.
jc ResetControllerError ; 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,0xDF ; SRT = 3ms, HUT = 240ms
out dx,al
call FdcSendByteReady ; can we send a byte ?.
jc ResetControllerError ; 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,0x02 ; HLT = 16ms, ND = 0
out dx,al
ResetControllerSuccsess:
clc
ret
ResetControllerError:
stc
ret
;----------------------------------------------------;
; 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
;----------------------------------------------------;
; Fdd recalibrate ;
;----------------------------------------------------;
; ;
; Input: ;
; none. ;
; Output: ;
; ;
; (100%) ;
;....................................................;
FddRecalibrate:
test [MotorOn],1
jnz @f
call FddMotorOn ; **** ENABLE MOTOR VIA DOR ****
@@:
call FdcSendByteReady ; can we send a byte ?.
jc FddRecalibrateError ; Is CF 1, if so timeout error.
mov [Timer],1 ; 5 = 250us
mov [TimerOn],1 ; start couting
call WaitTimer ; wait for timer
; **** ISSUE A RECALIBRATE COMMAND ****
mov dx,DtReg ; DtReg = 0x3f5
mov al,0x07 ; recalibrate Command
out dx,al
call FdcSendByteReady ; can we send a byte ?.
jc FddRecalibrateError ; 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,00h ; Selects drive A:
out dx,al
; **** WAIT FOR INTERRUPT ****
mov [done],0 ; we need to wait
call WaitDone ; for floppy int.
jc FddRecalibrateError ; jump to error exit,if timeout.
; **** ISSUE SENSE INTERRUPT STATUS COMMAND ****
call FdcSendByteReady ; can we send a byte ?.
jc FddRecalibrateError ; 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 FddRecalibrateError ; 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 FddRecalibrateError ; Is CF 1, if so timeout error.
mov dx,DtReg ; Should read PCN ,(DtReg = 0x3f5 )
in al,dx
test ah,00100000b ; test sr0 is 0x20
jz FddRecalibrateError ; if not we have a error :-(.
test ah,00010000b ; test sr0 is 0x80
jnz FddRecalibrateError ; if not we have a error :-(.
FddRecalibrateSuccsess: ; succsess we hope :-)
mov [ResultC],0
clc
ret
FddRecalibrateError: ; we have a error (blame M$)
stc
ret
;----------------------------------------------------;
; Fdd read ;
;----------------------------------------------------;
; ;
; Input: ;
; CH = Track/cylinder ;
; CL = Sector ;
; DH = Head ;
; DL = Drive (only A: drive used 00 ) ;
; ;
; Output: ;
; AH = Status ;
; AL = Sector number read ;
; CF = 0 If successful ;
; = 1 If error ;
; (100%) ;
;....................................................;
FddRead:
pushad
and dh,00000001b ; is it set to head 0 or 1 ?.
mov [Head],dh ; store it.
shl dh,2 ; make the first 2 bits = 00 for A:.
mov [DriveHead],dh ; store it.
mov [FddErrorStatus],0x04 ; put error code in ah,just incase
cmp ch,0x51 ; cmp if track number, is above 80 decimal (51 hex) ?.
jae FddReadError ; if above jump error.
mov [cTrack],ch ; if not above,store it.
cmp cl,0x13 ; cmp if sector number, is above 18 decimal (12 hex) ?.
jae FddReadError ; if above jump error.
mov [Sector],cl ; if not above,store it.
; Make shore fdd motor timer is off
mov [FddMTimer],0 ; 36 = 2 seconds
and [FddMotorTimer0n],0 ; mov floppy time switch off
test [MotorOn],1 ; **** ENABLE MOTOR VIA DOR ****
jnz @f
call FddMotorOn
@@: ; **** PROGRAM DATE VIA CCR ****
mov dx,CcrReg ; CcrReg = 0x3f7
mov al,00000000b ; 500Kb/sec mode
out dx,al
mov [FddErrorStatus],0x80 ; put basic error code,just in case.
; **** RECALIBRATE ****
;call FddRecalibrate ; we need to calibrate
;jc FddReadError
xor ecx,ecx ; **** SEEK ****
mov cx,3 ; we want to try seek 3 times
@@:
call FddReadWriteSeek ; we need to move to the, right track.
jnc @f ; we should be on the right track.
loop @b
jmp FddReadError ; FddReadError
@@:
mov dx,MsReg ; check status reg (to see if DMA bit set)
in al,dx
test al,00100000b ; test sr0 is 0x80
jnz FddReadError
Call Setup_DMA2_Read ; **** SETUP DMA ****
; set up to read, 512 bytes
; **** ISSUE READ COMMAND ****
;******************************
; 1. Read Sector Command
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,0xe6 ; read sector Command
out dx,al
;******************************
; 2. Drive
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,[DriveHead] ; Head no. 0, Drive A:
out dx,al
;******************************
; 3. Cylinder
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,[cTrack] ; Cylinder
out dx,al
;******************************
; 4. Head
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,[Head] ; Head/side 0 or 1
out dx,al
;******************************
; 5. Sector
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,[Sector] ; Sector number,starts at 1
out dx,al
;******************************
; 6. Sector Size
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,0x02 ; Sector Size - 512 bytes
out dx,al
;******************************
; 7. Sectors to a track
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,0x12 ; 18 decimal sectors to a track.
out dx,al
;******************************
; 8. Gap Length
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,0x01B ; 27 should be the Gap Length for a 3 1/2 inch 1.44Mb
out dx,al
;******************************
; 9. Data Length
;******************************
call FdcSendByteReady ; can we send a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; DtReg = 0x3f5
mov al,0xFF ; not used Data Length, because Sector Size has been filled
out dx,al
;****************************** ; **** FLOPPT INTERRUPT ****
; Wait floppy int
;******************************
mov [done],0 ; we need to wait
call WaitDone ; for floppy int.
jc FddReadError ; jump to error exit,if timeout.
; **** READ RESULT BYTES ****
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; Should read ST0 ,(DtReg = 0x3f5 )
in al,dx
mov [ResultST0],al ; save result of ST0 in var
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; Should read PCN ,(DtReg = 0x3f5 )
in al,dx
mov [ResultST1],al ; save result of ST1 in var
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; Should read ST2 ,(DtReg = 0x3f5 )
in al,dx
mov [ResultST2],al ; save result of ST2 in var
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; (DtReg = 0x3f5 )
in al,dx
mov [ResultC],al ; save result of cylinder
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; (DtReg = 0x3f5 )
in al,dx
mov [ResultH],al ; save result of head
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; (DtReg = 0x3f5 )
in al,dx
mov [ResultR],al ; save result of sector number.
call FdcGetByteReady ; can we get a byte ?.
jc FddReadError ; Is CF 1, if so timeout error.
mov dx,DtReg ; (DtReg = 0x3f5 )
in al,dx
mov [ResultN],al ; save result of sector size
test [ResultST0],11000000b ; test sr0 is 0xC0
jnz FddReadError ; if so, we have a error :-(.
mov [FddErrorStatus],0x00 ; **** STATUS PASS? ****
FddReadSuccsess: ; succsess we hope :-)
popad
mov ah,[FddErrorStatus] ; move error status into ah
mov al,[ResultR]
clc
ret
FddReadError:
popad
mov ah,[FddErrorStatus] ; move error status into ah
stc
ret
;----------------------------------------------------;
; Wait Timer. ;waits for timer to finish. ;
;----------------------------------------------------;
WaitTimer:
push eax
WaitTimerLoop:
mov al,[TimerOn]
or al,al
jnz WaitTimerLoop
pop eax
ret
;----------------------------------------------------;
; Wait Done ;waits for a floppy int. ;
;----------------------------------------------------;
WaitDone:
mov [Timer],30 ; 20 = about 1 second,we use (1.5 seconds).
mov [TimerOn],1 ; start couting.
WaitDoneLoop:
mov al,[TimerOn] ; we test if
or al,al ; timeout is up yet?.
jz WaitDoneError ; if it is we exit,with error.
mov ax,[done] ; if not we check for floppt int.
or ax,ax
jz WaitDoneLoop ; if not do another loop.
clc ; we end here if we have a int:-)
ret
WaitDoneError: ;we end up here if we run out of time:-(.
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 couting.
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
- Attachments
-
- DMA.asm
- (50 Bytes) Downloaded 56 times
-
- FddInfo.asm
- (2.25 KiB) Downloaded 59 times