⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdd.8

📁 PC x386 bios source code
💻 8
📖 第 1 页 / 共 2 页
字号:
	;
	; 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 + -