?? fdd.8
字號:
;
; Floppy BIOS
;
; (C)1997-2001 Pascal Dornier / PC Engines; All rights reserved.
; This file is licensed pursuant to the COMMON PUBLIC LICENSE 0.5.
;
; Limitations:
;
; - Only 3.5" floppy drives supported.
; - Only 1.44 MB mode supported.
; - Only one drive supported.
;
#if def DEBUG
FD_DEBUG: ;& enable debug code, comment out for
;production code
#endif
;
; INT 13 entry
;
int13: sti
push ds ;save registers
push es
pusha
mov bp,sp ;access to stack frame
#if def FD_DEBUG
call v_dump ;& dump registers
#endif
xor di,di ;access BIOS segment
mov ds,di
cmp ah,0 ;reset doesn't care about drive #
jz int13_1
cmp dl,0 ;valid drive ?
jnz fd_badcmd ;:bail out
int13_1: cmp byte [m_fdmed0],0 ;drive doesn't exist ?
jz fd_badcmd ;:bail out
mov di,ax ;command -> index
shr di,8
add di,di
and byte [bp+18h],0feh ;clear return carry
cmp di,19h*2 ;limit command vector
jae fd_badcmd
jmp [cs:di.fd_vectab] ;jump to command
;
; floppy vector table
;
fd_vectab: dw fd_rst ;AH=00: recalibrate drive
dw fd_status ;AH=01: get status
dw fd_read ;AH=02: read
dw fd_write ;AH=03: write
dw fd_verify ;AH=04: verify
dw fd_format ;AH=05: format track
dw fd_badcmd ;AH=06: bad
dw fd_badcmd ;AH=07: bad
dw fd_drvprm ;AH=08: read drive parameters
dw fd_badcmd ;AH=09: bad
dw fd_badcmd ;AH=0A: bad
dw fd_badcmd ;AH=0B: bad
dw fd_badcmd ;AH=0C: bad
dw fd_badcmd ;AH=0D: bad
dw fd_badcmd ;AH=0E: bad
dw fd_badcmd ;AH=0F: bad
dw fd_badcmd ;AH=10: bad
dw fd_badcmd ;AH=11: bad
dw fd_badcmd ;AH=12: bad
dw fd_badcmd ;AH=13: bad
dw fd_badcmd ;AH=14: bad
dw fd_gettyp ;AH=15: get drive type
dw fd_dskchg ;AH=16: get disk change status
dw fd_fmttyp ;AH=17: set drive type for format
dw fd_medtyp ;AH=18: set media type for format
;
; Illegal command
;
fd_badcmd: mov byte [m_fdstat],1 ;illegal command
;
; AH=01: get status
;
fd_status:
fd_exit: mov al,[m_fdstat] ;get error code
fd_exit1: mov [bp._ah],al ;return in AH
and al,al ;error ?
jz fd_exit2
or byte [bp+18h],1 ;yes: set carry
fd_exit2:
#if def FD_DEBUG
call v_dump2 ;& dump registers
#endif
popa ;restore registers
pop es
pop ds
iret ;return from interrupt
;
; AH=00: recalibrate floppy drives
;
fd_rst: les si,[m_fdbase]
in al,pic0+1 ;enable floppy interrupt
and al,0bfh
out iowait,al
out pic0+1,al
mov dx,fdc_rate ;set 500 kb/s data rate
mov al,0
out dx,al
mov dx,fdc_ctrl
mov word [m_fdstat],0 ;clear error status
mov byte [m_fdcnt],0ffh ;prevent motor off event
mov al,[m_fdmot] ;digital output register
rol al,4
and al,11110011b
or al,8 ;enable interrupts
out dx,al ;reset FDC
and byte [m_fdrecal],70h ;clear interrupt and recal flags
mov cx,100 ;wait a bit
fd_rstw: out iowait,ax
loop fd_rstw
xor al,4 ;end reset pulse
out dx,al
call fd_wait ;wait for interrupt
jb fd_rst1 ;:bad controller
mov bl,0c0h ;expected result
fd_rst0: mov al,8 ;sense interrupt
call fd_cmd ;send command
jb fd_rst1 ;:error
call fd_res ;get results
jb fd_rst1 ;:error
cmp byte [m_fdfile],bl ;drive ready changed state ?
jnz fd_rst1 ;no: error
inc bl
cmp bl,0c4h ;done all drives ?
jb fd_rst0
;
; FDC specify command
;
mov al,3 ;specify command
call fd_cmd ;send to FDC
jb fd_spec9
mov al,[es:si] ;m_fdbase -> step rate, head unload
call fd_cmd ;send to FDC
jb fd_spec9
mov al,[es:si+1] ;m_fdbase -> motor on time, DMA mode
call fd_cmd
#if def FDC_FIFO ;NSC PC87306
jb fd_spec9
mov al,13h ;configure command
call fd_cmd
jb fd_spec9
mov al,0
call fd_cmd
jb fd_spec9
mov al,00001000xb ;enable FIFO
call fd_cmd
jb fd_spec9
mov al,0 ;precompensation track
call fd_cmd
#endif
fd_spec9: mov al,[es:si+2] ;m_fdbase -> motor count
mov [m_fdcnt],al ;restore motor timer
jmp fd_exit
fd_rst1: or byte [m_fdstat],20h ;bad controller
fd_rst2: jmp fd_exit
;
; AH=05: format track
;
fd_format: call fd_dma ;convert address ES:BX -> CH:DX
mov ax,0200h+4ah ;sectors * 4 shift, DMA mode write
call fd_dma2 ;complete DMA initialization
jb fd_rw90 ;:error
call fd_seek ;turn on motor, seek to track
jb fd_rw90 ;:error
call cs_waitbx ;wait BX milliseconds
mov al,3 ;specify command
call fd_cmd ;send to FDC
jb fd_rw90
mov al,[es:si] ;m_fdbase -> step rate, head unload
call fd_cmd ;send to FDC
jb fd_rw90
mov al,[es:si+1] ;m_fdbase -> motor on time, DMA mode
call fd_cmd
jb fd_rw90
mov al,4dh ;format command
call fd_cmd
jb fd_rw90
mov al,[bp._dh] ;head
shl al,2
call fd_cmd
jb fd_rw90
mov al,[es:si+3] ;bytes per sector
call fd_cmd
jb fd_rw90
mov al,[es:si+4] ;sectors per track
call fd_cmd
jb fd_rw90
mov al,[es:si+7] ;gap length
call fd_cmd
jb fd_rw90
mov al,[es:si+8] ;fill byte
jmp short fd_rw3 ;continue as read / write
;
; AH=03: write sectors
;
fd_write: call fd_dma ;convert address ES:BX -> CH:DX
mov al,4ah ;DMA mode: write
call fd_dma2 ;complete DMA initialization
jb fd_rw90 ;:error
call fd_seek ;turn on motor, seek to track
jb fd_rw90 ;:error
call cs_waitbx ;wait BX milliseconds
mov al,0c5h ;write command
jmp short fd_rw1
fd_rw90: jmp fd_rw9
;
; AH=04: verify
;
fd_verify: call fd_dma ;convert address ES:BX -> CH:DX
xor dx,dx ;clear offset -> no DMA errors
mov al,42h ;DMA mode: verify
jmp short fd_read2 ;rest like read
;
; AH=02: read
;
fd_read: call fd_dma ;convert address ES:BX -> CH:DX
mov al,46h ;DMA mode: read
fd_read2: call fd_dma2 ;complete DMA initialization
jb fd_rw90 ;:error
call fd_seek ;turn on motor, seek to track
jb fd_rw90 ;:error
fd_read3: mov al,0e6h ;FDC read command
;
; execute read / write command
;
fd_rw1: call fd_cmd ;command
jb fd_rw9 ;:error
mov al,0 ;drive 0
test byte [bp._dh],1 ;other head ?
jz fd_rw2
or al,4 ;set head bit
fd_rw2: call fd_cmd
jb fd_rw9
mov al,[bp._ch] ;track number
call fd_cmd
jb fd_rw9
mov al,[bp._dh] ;head number
call fd_cmd
jb fd_rw9
mov al,[bp._cl] ;sector number
call fd_cmd
jb fd_rw9
mov al,[es:si+3] ;m_fdbase -> bytes / sector
call fd_cmd
jb fd_rw9
mov al,[es:si+4] ;m_fdbase -> end of track sector
call fd_cmd
jb fd_rw9
mov al,[es:si+5] ;m_fdbase -> gap length
call fd_cmd
jb fd_rw9
mov al,[es:si+6] ;m_fdbase -> data length
fd_rw3: call fd_cmd
jb fd_rw9
call fd_wait ;wait for interrupt
jb fd_rw9
call fd_res ;get results
jb fd_rw9
cmp byte [bp._al],3 ;write ?
jz fd_rw4
cmp byte [bp._al],5 ;format ?
jnz fd_rw5
fd_rw4: mov bx,1 ;wait 1 ms after write -> write gate
call cs_waitbx ;delay (prevent immediate step away)
fd_rw5: test byte [m_fdfile],0c0h ;any error ?
jz fd_rw99 ;:no
call fd_error ;translate error
fd_rw9: cmp byte [bp._ah],5 ;format ?
jz fd_rw99
mov byte [bp._al],0 ;clear sector count
fd_rw99: mov al,[es:si+2] ;m_fdbase -> motor count
mov [m_fdcnt],al
jmp fd_exit
;
; translate error code
;
fd_error: mov al,20h ;(FDC error)
test byte [m_fdfile],80h ;invalid command ?
jnz fd_err9 ;:yes
mov al,[m_fdfile+1] ;ST1 status
and al,10110111b ;mask off unused status bits
mov bx,fd_errtab+9 ;^error table
stc ;ensure termination
fd_err1: dec bx
rcr al,1 ;test bit
jnb fd_err1 ;try next
mov al,[cs:bx] ;get correct error code
fd_err9: or [m_fdstat],al
ret
;
; error codes
;
fd_errtab: db 20h ;(bit overflow)
db 4 ;sector not found
db 20h ;(not used)
db 10h ;CRC error
db 8 ;DMA overrun
db 20h ;(not used)
db 4 ;sector not found
db 3 ;write protect
db 2 ;address mark not found
;
; Floppy parameters
;
fd_ptab: db 0dfh ;step rate, head unload
db 02 ;head load, DMA mode
db 25h ;motor wait
db 02 ;512 bytes per sector
db 18 ;end of track
db 24h ;normal gap
db 0ffh ;DTL
db 54h ;gap length for format
db 0f6h ;fill byte for format
db 15 ;head settle time (x 1 ms)
db 8 ;motor start time (x 125 ms)
;
; turn on motor
;
; out: BX = turn-on delay in ms
;
fd_motor: xor bx,bx ;no settling time required
; turn on motor if required
mov byte [m_fdcnt],255 ;prevent motor shutdown
mov byte [m_fdstat],0 ;clear error code
test byte [m_fdmot],1 ;motor running ?
jnz fd_mot1 ;:yes
or byte [m_fdmot],1 ;set motor flag
mov dx,fdc_ctrl ;turn on motor
mov al,00011100xb ;drive 0, DMA enable, not reset
out dx,al
mov bl,[es:si+10] ;m_fdbase -> motor start time
shl bx,7 ;x 128 -> value in ms
fd_mot1: ret
;
; turn on motor, seek to track if needed
;
; -> settling time in ms in BX
;
fd_seek: call fd_motor ;turn on motor
; check and reset disk change
mov dx,fdc_chg ;disk change line active ?
in al,dx
and al,80h
jz fd_seek1x ;:no
#if def FD_DEBUG
pusha ;& write a message on disk change
mov si,deb_dskch ;&
call v_msg ;&
popa ;&
#endif
call fd_seek1z ;recalibrate
cmp byte [bp._ch],0 ;destination = track 0 ?
jnz fd_seek1b
inc byte [bp._ch]
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -