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

📄 hdd.8

📁 PC x386 bios source code
💻 8
📖 第 1 页 / 共 3 页
字号:
	; AH=0C: seek
	;
hd_seek:	call	hd_sel	;select drive
	jb	hd_seek9	
	call	hd_chs	;set CHS value
	mov	al,70h
	call	hd_cmd	;seek command
	jb	hd_seek9
	call	hd_stat	;check status
hd_seek9:	cmp	al,40h	;seek error ?
	jnz	hd_seek91
	mov	al,0	;don't show it... (Core test will fail
hd_seek91: jmp	hd_exit0	;otherwise)
	;
	; AH=10: test drive ready
	;
hd_trdy:	mov	cx,0ffffh	;no time-out
	call	hd_sel0	;select drive, test ready
	jb	hd_trdy9
	mov	dl,low(hdc_stat)	;check status
	in	al,dx
	mov	[m_hdst],al
	mov	ah,0aah	;not ready
	test	al,40h
	jz	hd_trdy8
	mov	ah,40h	;seek error
	test	al,10h
	jz	hd_trdy8
	mov	ah,0cch	;write fault
	test	al,20h
	jnz	hd_trdy8
	mov	ah,0	;ok status	
hd_trdy8:	mov	al,ah
hd_trdy9:	jmp	hd_exit0
	;
	; AH=11: recalibrate
	;
hd_recal:	call	hd_sel	;select drive
	mov	al,10h
	call	hd_cmd	;recalibrate command
	jb	hd_rec9
	call	hd_stat	;get status
hd_rec9:	jmp	hd_exit0
	;
	; AH=14: controller diagnostics
	;
hd_diag:	call	hd_busy18	;wait for not busy
	mov	al,20h	;bad controller
	jb	hd_diag9	;:bad
	mov	al,90h	;diagnostic command
	mov	dx,hdc_cmd
	out	dx,al
	out	iowait,al
	mov	cx,18*6	;max. 6 seconds (!!!)
	call	hd_busy	;wait for not busy
	mov	al,80h	;time-out
	jb	hd_diag9
	mov	dx,hdc_err	;check error register
	in	al,dx
	and	al,7fh
	sub	al,1
	jz	hd_diag9	;:ok
	mov	al,20h	;bad controller
hd_diag9:	jmp	hd_exit0	
	;
	; AH=15: read DASD type
	;
hd_gettyp: call	hd_parm	;get pointer to parameter block
	jb	hd_gett8	;:not present
	mov	al,[cs:di.dpt_head]	;number heads
	mul 	byte [cs:di.dpt_sec]	;number sectors
	mov	dx,[cs:di.dpt_cyl]	;number cylinders
	dec	dx	;minus one for diagnostics
	mul	dx
	mov	cl,3	;drive present
	jmp	short hd_gett9
		
hd_gett8:	xor	ax,ax	;0 = drive not present
	xor	cx,cx
	xor	dx,dx
hd_gett9:	mov	byte [bp._ah],cl	;0 = not present, 3 = present
	mov	[bp._cx],dx	;CX = MSB sector count
	mov	[bp._dx],ax	;DX = LSB sector count
	mov	al,0	;ok status
	mov	[m_hdstat],al
	jmp	hd_exit1
	;
	; AH = 24: set multiple mode
	;
hd_setmul: call	hd_sel	;select drive
	mov	dl,low(hdc_cnt)
	mov	al,[bp._al]	;number of sectors
	out	dx,al
	mov	al,0c6h
	call	hd_cmd	;set multiple mode command
	jb	hd_setm9
	call	hd_stat	;get status
hd_setm9:	jmp	hd_exit0
	;
	; AH=25: identify drive
	;
hd_id:	call	hd_selb	;select drive
			;ignore time-out here, if drive not ready
			;(ATAPI drive doesn't report ready
			;until spoken to)
	mov	al,0ech	;identify drive
	call	hd_cmd	;issue command
	jb	hd_id9	;:bad drive
	in	al,dx	;hdc_stat
	test	al,1	;error ?
	jz	hd_id1	;:no

hd_id0:	mov	al,0a1h	;ATAPI identify drive
	call	hd_cmd	;issue command
	jb	hd_id9	;:time-out

hd_id1:	xor	cx,cx
hd_id2:	in	al,dx	;hdc_stat
	test	al,8	;DRQ ?
	jnz	hd_id3	;:yes
	loop	hd_id2
	mov	al,80h	;time-out
	jmp	short hd_id9

hd_id3:	cld		;forward direction
	mov	dl,low(hdc_dat)
	mov	cx,256	;512 bytes
	mov	di,bx	;destination
	rep	insw	;read data
	call	hd_stat	;get status
hd_id9:	jmp	hd_exit0	;exit

#if def	HD_EDD
	;
	; AH=41: detect EDD support
	;
hd_edd41:	cmp	bx,55aah	;magic cookie ?
	jnz	hd_edd419	;no: bad
	mov	word [bp._bx],0aa55h	;return cookie
	mov	word [bp._cx],1	;support packet commands; no lock /
			;eject
	mov	byte [bp._ah],1	;major version
	mov	byte [m_hdstat],0
	jmp	hd_exit2	;return carry clear

hd_edd419: jmp	hd_badcmd	;return error
	;
	; AH=42: extended read
	;
hd_xrd:	call	hd_sel	;select drive
	jb	hd_xrd9
	call	hd_xadr	;handle address
	jb	hd_xrd9
	mov	byte [m_hdflag],0	;clear interrupt flag
	mov	al,20h	;issue read command
	mov	dx,hdc_cmd
	out	dx,al
	
hd_xrd1:	call	hd_int	;wait for interrupt
	jb	hd_xrd9
	mov	dl,low(hdc_stat)	;read status
	in	al,dx
	mov	byte [m_hdflag],0	;clear interrupt flag for next
	test	al,1	;ERR ?
	jnz	hd_xrd8
	test	al,8	;DRQ ?
	jz	hd_xrd8	;:no
	mov	dl,low(hdc_dat)	;read 512 bytes from drive
	mov	cx,256
	rep	insw
	dec	bl	;another sector ?
	jnz	hd_xrd1	;:yes
hd_xrd8:	mov	es,[bp._ds]	;access address packet
	sub 	byte [es:si+drq_blk],bl	;adjust sector count to reality
	call	hd_stat	;get status
hd_xrd9:	jmp	hd_exit0
	;
	; AH=43: extended write
	;
hd_xwr:	call	hd_sel	;select drive
	jb	hd_xwr9
	call	hd_xadr	;handle address
	jb	hd_xwr9
	mov	si,di	;buffer ^
	mov	al,30h	;issue write command
	mov	dx,hdc_cmd
	out	dx,al
	
hd_xwr1:	mov	dl,low(hdc_stat)	;read status
	xor	cx,cx
	mov	byte [m_hdflag],0	;clear interrupt flag for next
hd_xwr2:	in	al,dx
	test	al,8	;DRQ ?
	jnz	hd_xwr3	;:yes
	test	al,21h	;error ?
	jnz	hd_xwr8
	loop	hd_xwr2
	mov	al,80h	;time-out
	jmp	short hd_xwr9
	
hd_xwr3:	mov	dl,low(hdc_dat)	;write 512 bytes from drive
	mov	cx,256
	es: rep	outsw
	call	hd_int	;wait for interrupt
	jb	hd_xwr9
	dec	bl	;another sector ?
	jnz	hd_xwr1	;:yes
		
hd_xwr8:	call	hd_stat	;get status
hd_xwr9:	mov	es,[bp._ds]	;access address packet
	mov	si,[bp._si]
	sub 	byte [es:si+drq_blk],bl	;adjust sector count to reality
	jmp	hd_exit0
	;
	; AH=44: extended verify
	;
hd_xver:	call	hd_sel	;select drive
	jb	hd_xver9
	call	hd_xadr	;handle address
	jb	hd_xver9
	mov	al,40h
	call	hd_cmd	;read verify command	
	jb	hd_xver9
	call	hd_stat	;get status
hd_xver9:	jmp	hd_exit0
	;
	; AH=47: extended seek
	;
hd_xsk:	call	hd_sel	;select drive
	jb	hd_xsk9	
	call	hd_xadr	;handle address
	jb	hd_xsk9
	mov	al,70h
	call	hd_cmd	;seek command
	jb	hd_xsk9
	call	hd_stat	;check status
hd_xsk9:	jmp	hd_exit0
	;
	; AH=48: return drive parameters
	;
	; Note: Phoenix spec says we should return PHYSICAL geometry, but
	; Award BIOS returns LOGICAL... Users of this function are most
	; interested in the max sector count anyway.
	;
hd_edd48:	call	hd_parm	;get ^parameter block -> DI
	jb	hd_edd489
	mov	si,di	;^parameter block
	cld		;forward direction
	mov	es,[bp._ds]	;buffer segment
	mov	di,[bp._si]	;buffer offset
	mov	al,1	;(error code)
	cmp 	word [es:di],26	;buffer at least 26 bytes long
	jb	hd_edd489	;less -> error
	mov	ax,26	;buffer length
	stosw
	mov	ax,2	;flags: valid geometry
	stosw
	xor 	eax,eax
	mov	ax,[cs:si.dpt_cyl]	;number of cylinders
	stosd
	mov 	al,[cs:si.dpt_head]	;number of heads
	mov	ah,0
	stosd
	mov	al,[cs:si.dpt_sec]	;number of sectors
;	mov	ah,0
	stosd
	mov	al,[cs:si.dpt_head]	;number heads
	mul	byte [cs:si.dpt_sec]	;number sectors
	mov	dx,[cs:si.dpt_cyl]	;number cylinders
	mul	dx
	stosw		;-> physical sector count
	xchg	ax,dx
	stosw
	xor 	eax,eax
	stosd
	mov	ax,512	;bytes per sector
	stosw
	mov	al,0	;ok status
hd_edd489: jmp	hd_exit0
	;
	; write LBA address to command file
	;
	; returns sector count in BL, transfer address in ES:DI
	;
	; this will break on old drives that don't support LBA
	;
hd_xadr:	mov	es,[bp._ds]	;restore segment, SI still OK
	cmp 	byte [es:si+drq_len],16	;at least 16 bytes
	jb	hd_xadr9	;:error
	mov	dx,hdc_cnt	;sector count
	mov	al,[es:si+drq_blk]
	mov	bl,al	;return in BL
	out	dx,al
	inc	dx
	mov 	eax,[es:si+drq_lba]	;LBA sector number
	out	dx,al	;hdc_sec sector = LBA 7..0
	inc	dx
	shr	ax,8
	out	dx,al	;hdc_cyl cylinder low = LBA 15..8
	inc	dx
	shr 	eax,16
	out	dx,al	;hdc_cyh cylinder high = LBA 23..16
	inc	dx
	in	al,dx	;hdc_drv get drive
	and	al,0b0h	;keep reserved, drive select bits
	or	al,40h	;set LBA mode
	or	al,ah
	out	dx,al	;hdc_drv heads = LBA27..24
	mov 	di,[es:si+drq_ofs]	;get ^transfer buffer
	mov 	es,[es:si+drq_seg]
	cld		;forward mode
	clc		;ok
	ret
	
hd_xadr9:	mov	al,1	;return error
	stc
	ret
#endif
	;
	; wait for not busy, check status
	;
hd_stat0:	call	hd_busy18	;wait until not busy
	jb	hd_stat9
	
	; Enter here for faster service (assuming normally not busy)
	; This is arranged to get fastest response when no error.
	
hd_stat:	mov	dx,hdc_stat	;test whether busy
	in	al,dx
	test	al,80h
	jnz	hd_stat0	;:busy
	mov	[m_hdst],al
	mov	ah,al	;save status
	test	al,24h	;write fault / ECC ?
	jnz	hd_stat1
	and	al,50h	;not ready, or seek error ?
	cmp	al,50h
	jnz	hd_stat2
	test	ah,1	;other error ?
	jnz	hd_stat3
	mov	al,0	;return ok status
	ret
	
hd_stat1:	mov	al,11h	;ECC corrected data
	test	ah,4
	jnz	hd_stat9
	mov	al,0cch	;no - must be write fault
hd_stat9:	stc
	ret
	
hd_stat2:	mov	al,0aah	;not ready
	test	ah,40h
	jz	hd_stat9
	mov	al,40h	;no - must be seek error
	stc
	ret
	
hd_stat3:	mov	dl,low(hdc_err)	;read error register
	in	al,dx
	mov	[m_hderr],al
	mov	si,hd_errtab
	cmp	al,0	;nothing set -> undefined error
	jz	hd_stat5
hd_stat4:	inc	si
	shl	al,1
	jnb	hd_stat4
hd_stat5:	mov 	al,[cs:si]	;get error code
	stc
	ret
	;
	; error register -> error code translation
	;
hd_errtab: db	0e0h	;nothing set - status error
	db	0ah	;80 - bad sector flag detected
	db	10h	;40 - bad ECC
	db	0bbh	;20 - undefined error
	db	04h	;10 - record not found
	db	01h	;08 - abort -> bad command
	db	0bbh	;04 - undefined error
	db	40h	;02 - seek error
	db	02h	;01 - address mark not found
	;
	; get pointer to parameter block
	;
	; entry: DL = drive
	; exit:  CS:DI = parameter block
	;
hd_parm:	and	dl,7fh
	cmp	dl,[m_hdcnt]	;legal drive number ?
	jae	hd_parm9	;:bad
	mov	di,hd_prm1
	test	dl,1	;(clc)
	jnz	hd_parm2
	mov	di,hd_prm0
hd_parm2:	ret

hd_parm9:	mov	al,1	;error code
	stc
	ret
	;
	; wait while HD busy, CX ticks
	;
hd_busy18: mov	cx,18	;18 ticks = 1 second
hd_busy:	add	cx,[m_timer]	;start time + max number of ticks
	mov	dx,hdc_stat
hd_busy1:	in	al,dx
	test	al,80h	;busy ?
	jz	hd_busy9	;:no, carry clear
	cmp	cx,[m_timer]
	jns	hd_busy1	;keep waiting
hd_busy8:	stc		;time-out
	mov	al,80h	;status code
hd_busy9:	ret
	;
	; select drive, wait for drive ready
	;
	; -> CS:DI = ^parameter block
	;
	
	; special entry: no drive number check
	
hd_selb:	mov	cx,18	;1 s time-out
	and	dl,7fh	;mask drive number
	jmp	short hd_sel0a

	; normal entry
	
hd_sel:	mov	cx,18	;1 s time-out for ready wait
hd_sel0:	and	dl,7fh	;legal drive number ?
	cmp	dl,[m_hdcnt]
	jae	hd_parm9	;:bad
hd_sel0a:	mov	di,hd_prm1
	test	dl,1	;(clc)
	jnz	hd_sel1
	mov	di,hd_prm0
hd_sel1:	mov	byte [m_hdflag],0	;clear interrupt flag

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -