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