?? fdd.8
字號:
call fd_seek2 ;seek to track 1
dec byte [bp._ch]
fd_seek1b: call fd_seek2 ;seek to track 0 / wanted track
mov dx,fdc_chg ;disk change line still active ?
in al,dx
and al,80h
jz fd_seek1c ;no: ok
mov byte [m_fdstat],80h ;set time-out error
fd_seek1c: ret
; recalibrate if required
fd_seek1x: test byte [m_fdrecal],1 ;need recalibration ?
jnz fd_seek2 ;:no
fd_seek1z: mov al,7 ;recalibrate
call fd_cmd
jb fd_seek9
mov al,0 ;drive 0
call fd_cmd
jb fd_seek9
call fd_wsk ;wait for seek complete
jb fd_seek9
or byte [m_fdrecal],1 ;set bit - done
mov byte [m_fdtrk0],0 ;set current track
or bx,bx ;motor settling time ?
jnz fd_seek2 ;yes, bigger than head settling time
mov bl,[es:si+9] ;m_fdbase -> head settling time
; seek to track if required
fd_seek2: mov al,[bp._ch] ;destination track
cmp al,[m_fdtrk0] ;= current track ?
jz fd_seek9 ;:done (implied clc)
mov al,0fh ;seek command
call fd_cmd
jb fd_seek9
mov al,0 ;drive number
call fd_cmd
jb fd_seek9
mov al,[bp._ch] ;destination track
call fd_cmd
jb fd_seek9
mov [m_fdtrk0],al ;set new position
call fd_wsk ;wait for seek complete
or bx,bx ;motor settling time ?
jnz fd_seek9 ;yes, bigger than head settling time
mov bl,[es:si+9] ;m_fdbase -> head settling time
fd_seek9: ret
;
; wait for seek to complete, get status
;
fd_wsk: call fd_wait ;wait for interrupt
jb fd_wsk8 ;:error
fd_wsk2: mov al,8 ;sense interrupt
call fd_cmd
jb fd_wsk8
call fd_res ;get results
jb fd_wsk8
mov al,[m_fdfile]
and al,01100000xb ;error, seek end bits
cmp al,00100000xb ;no error, seek end ?
jz fd_wsk9 ;:ok
fd_wsk8: or byte [m_fdstat],40h ;set seek error bit
stc
fd_wsk9: ret
;
; initialize DMA controller
;
; ES = buffer segment
; BX = buffer offset
;
fd_dma: ; ES:BX -> physical address CH:DX, init ES:SI, AH
mov dx,es ;buffer segment
rol dx,4
mov ch,dl ;high 4 bits
and dl,0f0h ;mask off low bits
add dx,bx ;add buffer offset
adc ch,0
les si,[m_fdbase] ;load ^ floppy parameters
mov ah,[es:si+3] ;get shift count
add ah,7 ;shift count + 7 (128 byte base)
ret
;
; second half of DMA setup
;
; AL = DMA mode
; AH = shift count (for sector -> byte calculation)
; DX = address (low 16 bits)
; CH = address (high 4 bits)
;
fd_dma2: mov cl,ah ;shift count
mov bl,[bp._al] ;number of sectors
mov bh,0
shl bx,cl ;-> byte count
dec bx ;-1 for DMA
add bx,dx ;test for DMA overflow
jb fd_dma9 ;:error
sub bx,dx ;restore count
fd_dma3: cli ;critical section
push ax
mov al,6 ;disable DRQ2
out dma0+10,al
out iowait,ax
pop ax
out dma0+12,al ;dummy access -> reset hi/lo FF
out iowait,ax
out dma0+11,al ;write DMA mode
out iowait,ax
mov al,dl ;low address
out dma0+4,al
out iowait,ax
mov al,dh ;high address
out dma0+4,al
mov al,ch ;DMA page register
and al,15
out fd_page,al
#if def GX_FDFIX
push dx
mov al,0 ;clear high page register !!!
mov dx,fd_page+0400h
out dx,al
pop dx
#endif
mov al,bl ;low count
out dma0+5,al
out iowait,ax
mov al,bh ;high count
out dma0+5,al
out iowait,ax
mov al,2 ;enable DRQ2
out dma0+10,al
sti ;end of critical section
clc
ret
fd_dma9: mov byte [m_fdstat],9 ;DMA overflow error
ret
;
; write command byte AL to FDC
;
fd_cmd: mov ah,al ;save data
mov dx,fdc_stat
xor cx,cx
fd_cmd1: in al,dx ;read status
and al,0c0h ;RQM / DIO
xor al,80h ;RQM set, DIO clear = write to FDC
jz fd_cmd2 ;:ok
loop fd_cmd1 ;keep trying
or byte [m_fdstat],80h ;time out
stc
ret
fd_cmd2: mov al,ah ;restore data
inc dx
out dx,al ;write data to fdc_data
ret ;(carry clear)
;
; get results from FDC
;
fd_res: mov dx,fdc_stat
xor cx,cx
mov di,m_fdfile ;destination pointer
fd_res1: xor cx,cx ;clear time-out
fd_res2: out iowait,ax
in al,dx ;read status
cmp al,0c0h ;FDC ready for data read ?
jnb fd_res3 ;:yes
loop fd_res2
fd_res8: or byte [m_fdstat],80h ;time out
stc
ret
fd_res3: out iowait,ax
inc dx
in al,dx ;read fdc_data
dec dx
mov [di],al ;store result
inc di
out iowait,ax ;give FDC some time to update status
out iowait,ax
out iowait,ax
out iowait,ax
cmp di,m_fdfile+7 ;max bytes ?
jz fd_res9 ;:done
;
; wait for next byte
;
fd_res4: in al,dx ;get controller status
cmp al,0c0h
jae fd_res3 ;:ready with data
and al,0f0h ;ready for next command ?
cmp al,80h
jz fd_res9 ;:yes, done
loop fd_res4 ;keep trying
jmp fd_res8 ;time-out
fd_res9: clc
ret
;
; Floppy interrupt
;
irq6: push ax
push ds
xor ax,ax
mov ds,ax
or byte [m_fdrecal],80h ;set interrupt flag
mov al,eoi ;end of interrupt
out pic0,al
pop ds
pop ax
iret
;
; Did we get interrupt ? CY set if time-out
;
fd_wait: mov byte [m_fdcnt],0ffh ;keep motor running
push cx
mov cx,[m_timer] ;start time
add cx,19 ;time-out 1 second
fd_wait2: test byte [m_fdrecal],80h ;did we get interrupt ?
jnz fd_wait3 ;:yes
cmp cx,[m_timer]
js fd_wait4 ;:time-out
hlt ;wait for next interrupt
jmp fd_wait2 ;look again
fd_wait3: pop cx
and byte [m_fdrecal],7Fh ;clear interrupt flag
ret
fd_wait4: or byte [m_fdstat],80h ;set time-out status
stc
pop cx
ret
;
; AH=08: read drive parameters
;
fd_drvprm: xor bx,bx ;for non-existent drive
xor cx,cx
xor dx,dx
xor si,si
xor di,di
mov [m_fdstat],bl ;clear status
mov [bp._ax],bx ;clear AX
cmp byte [m_fdmed0],0 ;drive present ?
jz fd_drvp9 ;:no
mov si,cs ;segment -> ES
mov di,fd_ptab
mov bx,4 ;drive type = 1.44 MB
mov cx,79*256+18 ;80 tracks, 18 sectors per track
mov dx,1*256+1 ;1 head, 1 drive
fd_drvp9: mov [bp._bx],bx
mov [bp._cx],cx
mov [bp._dx],dx
mov [bp._es],si
mov [bp._di],di
jmp fd_exit ;return ok status
;
; AH=15: get drive type
;
fd_gettyp: mov al,0 ;drive not present
mov byte [m_fdstat],al ;clear status
cmp dl,0 ;drive 0 ?
jnz fd_gett2
cmp byte [m_fdmed0],0 ;drive present ?
jz fd_gett2 ;:no
mov al,2 ;change line available
fd_gett2: mov [bp._ah],al ;return in AH
jmp fd_exit2 ;don't set CY
;
; AH=17: set drive type for format
;
; since we only support 1.44 MB, basically a no-op
;
fd_fmttyp: cmp al,5
jae fd_fmtt2
cmp al,0
jnz fd_dskchg
fd_fmtt2: jmp fd_badcmd
;
; AH=16: get disk change status
;
fd_dskchg: les si,[m_fdbase] ;^disk parameters
mov al,80h ;drive not ready (no drive)
cmp dl,0 ;drive 0 ?
jnz fd_dsk2
cmp byte [m_fdmed0],0 ;drive present ?
jz fd_dsk2 ;:no
call fd_motor ;turn on motor
call cs_waitbx ;wait for motor startup time
mov byte [m_fdcnt],36 ;restore motor timer
mov dx,fdc_chg ;read disk change line
in al,dx
and al,80h
jz fd_dsk2 ;:not active, AL = 0
mov al,6 ;disk change active
fd_dsk2: mov [m_fdstat],al
jmp fd_exit1 ;set CY if not 0
;
; AH=18: set media type for format
;
fd_medtyp: mov al,80h ;drive not ready (no drive)
cmp dl,0 ;drive 0 ?
jnz fd_medt9
cmp byte [m_fdmed0],0 ;drive present ?
jz fd_medt9 ;:no
mov al,0ch ;invalid format
cmp ch,79 ;80 tracks ?
jnz fd_medt9 ;:no, error
cmp cl,18 ;18 sectors ?
jnz fd_medt9 ;:no, error
mov [bp._es],cs ;return ^disk parameters
mov word [bp._di],fd_ptab
mov al,0 ;ok status
fd_medt9: mov [m_fdstat],al ;set status
jmp fd_exit1 ;set CY if not 0
;
; Initialize floppy drive: detect FDC presence,
; reset FDC, turn on floppy motor, recalibrate
;
fd_init: mov dx,fdc_ctrl ;make sure FDC is present - control
mov al,0 ;register should read / write
out dx,al
dec ax
out iowait,al
in al,dx ;read back
cmp al,0ffh
jz fd_init9 ;:doesn't exist
or byte [m_devflg],1 ;floppy drive present
mov byte [m_fdmed0],17h ;drive A: present
mov ah,0 ;reset drive
int 13h
call fd_motor ;turn on floppy motor
mov al,7 ;recalibrate
call fd_cmd
jb fd_init9
mov al,0 ;drive 0
call fd_cmd
fd_init9: ret
;
; secondary floppy init
;
fd_inb: cmp byte [m_fdmed0],0
jz fd_inb9 ;:no FDC
or byte [m_fdrecal],1 ;set bit - done
mov byte [m_fdtrk0],0 ;set current track
mov byte [m_fdstat],0 ;clear errors
call fd_wsk ;wait for seek complete
jb fd_inb7 ;:error
jmp short fd_inb9 ;ok
; error: drive not present
fd_inb7: mov al,[m_devflg] ;decrement drive count
sub al,40h
jnb fd_inb8 ;there is another "floppy" (e.g. flash)
and al,00111110xb ;no floppy drives present
fd_inb8: mov [m_devflg],al
mov byte [m_fdmed0],0 ;disable drive
fd_inb9: ret
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -