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

📄 gpmlib.inc

📁 AMI 主板的BIOS源码
💻 INC
📖 第 1 页 / 共 5 页
字号:
;		     <> 0ffh program (dh) in sector count reg	;
;			     actual time = (dh) * 5 seconds	;
;		STACK PRESENT					;
;	Output: (CY) 00 for no error				;
;		(CY) 01 for error				;
;	Register destroyed : (AX)				;
;								;
; This subroutine is called to write low power command to the	;
; ide drive. This routine checks for the drive presence.       	;
;								;
; assumption:   Hardware interrupt for the ide is masked on	;
;		entry to this subroutine.                       ;
;---------------------------------------------------------------;

ide_low_power_cmd_ext	proc	near

	test	byte ptr [bx+hdd_misc_control_info],hdd_present_bit_equ; current drive present ?
	jz	short low_power_cmd_ext_00	; no...
	test	dl,00010000b			; request for standby/standby immediate ?
	jz	short low_power_cmd_ext_01	; no...
	call	ide_exec_standby_command	; execute standby/standby immediate
low_power_cmd_ext_00:
	ret

low_power_cmd_ext_01:
	test	dl,00100000b			; request for idle/idle immediate ?
	jz	short low_power_cmd_ext_00	; no...
	call	ide_exec_idle_command		; execute idle/idle immediate
	ret

ide_low_power_cmd_ext	endp

;---------------------------------------------------------------;
;                  IDE_EXEC_STANDBY_COMMAND                	;
;---------------------------------------------------------------;
;	Input : (DS) PM BIOS data segment			;
;		(BX) control information pointer for the drive	;
;		(DH) 0ffh do not program timer into sec count reg
;		     <> 0ffh program (dh) in sector count reg	;
;			     actual time = (dh) * 5 seconds	;
;		STACK PRESENT					;
;	Output: (CY) 00 for no error				;
;		(CY) 01 for error				;
;	Register destroyed : (AX)				;
;								;
; This subroutine is called to write standby command to the ide	;
; drive                                                 	;
;								;
; assumption:   Hardware interrupt for the ide is masked on	;
;		entry to this subroutine.                       ;
;---------------------------------------------------------------;

ide_exec_standby_command	proc	near

	push	di				;
	push	cx				;	
	cmp	dh,0ffh				; standby immediate ?
	jz	short exec_standby_cmd_00	; yes...
	mov	cx,standby_old_cmd*256+standby_cmd; STANDBY command with count
						; if count is zero, drive's automatic
						; power management is disabled
	mov	di,hdd_standby_cmd_save		; offset for standby command save
	jmp	short exec_standby_cmd_01	;

exec_standby_cmd_00:
	mov	cx,standby_immediate_old_cmd*256+standby_immediate_cmd; STANDBY command with no count
						; controller should use previous count
	mov	di,hdd_standby_imm_cmd_save	; offset for standby immediate command save
exec_standby_cmd_01:

;-----------------------------------------------;

exec_idle_cmd_01::

	call	ide_exec_power_mode_dup_func	; execute STANDBY command
	pop	cx				;
	pop	di				;
	ret

ide_exec_standby_command	endp

;---------------------------------------------------------------;
;                  IDE_EXEC_IDLE_COMMAND                	;
;---------------------------------------------------------------;
;	Input : (DS) PM BIOS data segment			;
;		(BX) control information pointer for the drive	;
;		(DH) 0ffh do not program timer into sec count reg
;		     <> 0ffh program (dh) in sector count reg	;
;			     actual time = (dh) * 5 seconds	;
;		STACK PRESENT					;
;	Output: (CY) 00 for no error				;
;		(CY) 01 for error				;
;	Register destroyed : (AX)				;
;								;
; This subroutine is called to write idle command to the ide	;
; drive                                                 	;
;								;
; assumption:   Hardware interrupt for the ide is masked on	;
;		entry to this subroutine.                       ;
;---------------------------------------------------------------;

ide_exec_idle_command	proc	near

	push	di				;
	push	cx				;	
	cmp	dh,0ffh				; idle immediate ?
	jz	short exec_idle_cmd_00		; yes...
	mov	cx,idle_old_cmd*256+idle_cmd	; IDLE command with count
						; if count is zero, drive's automatic
						; power management is disabled
	mov	di,hdd_idle_cmd_save		; offset for idle command save
	jmp	short exec_idle_cmd_01		;

exec_idle_cmd_00:
	mov	cx,idle_immediate_old_cmd*256+idle_immediate_cmd; IDLE command with no count
						; controller should use previous count
	mov	di,hdd_idle_imm_cmd_save	; offset for idle immediate command save
	jmp	short exec_idle_cmd_01		;

ide_exec_idle_command	endp

;---------------------------------------------------------------;
;                  IDE_EXEC_POWER_MODE_DUP_FUNC                	;
;---------------------------------------------------------------;
;	Input : (DS) PM BIOS data segment			;
;		(BX) control information pointer for the drive	;
;		(DI) offset to command save			;
;		(CL) primary command				;
;		(CH) alternate command				;
;		(DH) 0ffh do not program timer into sec count reg
;		     <> 0ffh program (dh) in sector count reg	;
;			     actual time = (dh) * 5 seconds	;
;		STACK PRESENT					;
;	Output: (CY) 00 for no error				;
;		(CY) 01 for error				;
;	Register destroyed : (AX)				;
;								;
; This subroutine is called to write a power control command to ;
; the ide drive                                                 ;
;								;
; assumption:   Hardware interrupt for the ide is masked on	;
;		entry to this subroutine.                       ;
;---------------------------------------------------------------;

ide_exec_power_mode_dup_func	proc	near

	mov	al,[bx+di]			; (al) = power management command to be used with the drive
	cmp	al,0ffh				; any command supported by this drive ?
	jz	short exec_dup_func_00		; no...
	cmp	al,00h				; any valid command already established for this drive ?
	jnz	short exec_dup_func_01		; yes...use that command
	mov	al,cl				; (al) = primary command
	call	ide_execute			; execute the command
	jnc	short exec_dup_func_02		; no error
	mov	al,ch				; (al) = alternate command
	call	ide_execute			; execute the command
	jnc	short exec_dup_func_02		; no error...
	mov	byte ptr [bx+di],0ffh		; set for no command supported
exec_dup_func_00:
	stc					; (cy) = 01 for error
exec_dup_func_02:
	ret

exec_dup_func_01:
	call	ide_execute			; execute the command
	ret

ide_exec_power_mode_dup_func	endp

;---------------------------------------------------------------;
;			IDE_EXECUTE				;
;---------------------------------------------------------------;
;	Input : (DS) PM BIOS data segment			;
;		(BX) control information pointer for the drive	;
;		(DI) offset to command save			;
;		(AL) power mode control command			;
;		(DH) 0ffh do not program timer into sec count reg
;		     <> 0ffh program (dh) in sector count reg	;
;			     actual time = (dh) * 5 seconds	;
;		STACK PRESENT					;
;	Output: (CY) 00 for no error				;
;		(CY) 01 for error & (AH) has error code		;
;	Register destroyed : (AX)				;
;								;
; This subroutine is called to write a power control command to ;
; the ide drive                                                 ;
;								;
; assumption:   Hardware interrupt for the ide is masked on	;
;		entry to this subroutine.                       ;
;---------------------------------------------------------------;

ide_execute	proc	near

	mov	ah,dh				; (ah) = timer information
	mov	[bx+di],al			; save primary/alternate command
	call	ide_exec_power_mode_func	; execute the command
	ret

ide_execute	endp

;---------------------------------------------------------------;
;                     IDE_EXEC_POWER_MODE_FUNC                	;
;---------------------------------------------------------------;
;	Input : (DS) PM BIOS data segment			;
;		(BX) control information pointer for the drive	;
;		(AL) power mode control command			;
;		(AH) 0ffh do not program timer into sec count reg
;		     <> 0ffh program (ah) in sector count reg	;
;			     actual time = (ah) * 5 seconds	;
;		STACK PRESENT					;
;	Output: (CY) 00 for no error				;
;		(CY) 01 for error & (AH) has error code		;
;	Register destroyed : (AX)				;
;								;
; This subroutine is called to write a power control command to ;
; the ide drive                                                 ;
;								;
; assumption:   Hardware interrupt for the ide is masked on	;
;		entry to this subroutine.                       ;
;---------------------------------------------------------------;

ide_exec_power_mode_func	proc	near

	push    di				;
	push    dx				;
	push    cx				;

	pushf					; save current interrupt status
	cli					; disable interrupts

	push    ax                      	; save (al) = power mode controller command
	mov     di,primary_ide_cntlr	   	; (di) = base address for primary IDE controller
	test    byte ptr [bx+hdd_misc_control_info],hdd_port_select_bit_equ ; secondary IDE controller ?
	jz      short exec_power_mode_func_00	; no..primary IDE controller
	mov     di,secondary_ide_cntlr		; (di) = base address for secondary IDE controller
exec_power_mode_func_00:
	mov	dx,di				; (dx) = base address for IDE controller
	add	dx,status_reg_off		; (dx) = ide status reg (1f7h/177h)
	in	al,dx				; (al) = current status
	test	al,ide_cntlr_busy_bit		; is controller busy ?
	jnz	short exec_power_mode_func_03	; yes...error...exit

	mov     al,10100000b			; drive/head reg data for drive 0
	test    byte ptr [bx+hdd_misc_control_info],hdd_drive_select_bit_equ; drive 0 ?
	jz      short exec_power_mode_func_05	; yes..
	mov     al,10110000b            	; drive/head reg data for drive 1
exec_power_mode_func_05:
	mov	dx,di				; (dx) = base address for IDE controller
	add	dx,drive_head_reg_off		; (dx) = drive/head reg (1f6h/176h)
	out	dx,al				; select the drive
	mov	cx,8				; 120 micro sec delay (TIME might be more if slow refresh)
	call	pm_fixed_delay			;
	mov	dx,di				; (dx) = base address for IDE controller
	add	dx,status_reg_off		; (dx) = ide status reg (1f7h/177h)
	in	al,dx				; (al) = read current status
	and	al,ide_drv_rdy_bit or ide_drv_seek_complete_bit
	cmp	al,ide_drv_rdy_bit or ide_drv_seek_complete_bit; is drive ready and seek complete ?
	jnz	short exec_power_mode_func_03	; no...error...exit

	cmp     ah, 0ffh                	; program sector count ?
	jz      short skip_sector_count_prg	; no...
	mov     dx, di                  	; (dx) = base address for IDE controller
	add     dx, sector_count_reg_off	; (dx) = sector count reg (1f2h/172h)
	mov     al, ah				; (al) = count of 5 seconds IDLE timer
	out     dx, al				; program the counter
	smi_io_delay				; i/o delay
skip_sector_count_prg:  
	pop     ax				; (al) = power mode drive command
	mov	dx,di				; (dx) = base address for IDE controller
	add	dx,command_reg_off		; (dx) = command register (1f7h/177h)
	out	dx,al				; output command to controller

	call    ide_wait_for_interrupt		; interrupt came ?
	jz      short exec_power_mode_func_01	; no...error...exit

	mov	dx,di				; (dx) = base address for IDE controller
	add	dx,status_reg_off		; (dx) = ide status reg (1f7h/177h)
	in	al,dx				; (al) = current status
	test	al,ide_drv_rdy_bit		; drive ready ?
	jz	short exec_power_mode_func_01	; no...error...exit
	test	al,ide_drv_seek_complete_bit	; seek complete ?
	jz	short exec_power_mode_func_01	; no...error...exit
	test	al,ide_drv_wt_fault_bit or ide_data_corrected_bit; write fault or data corrected error ?
	jnz	short exec_power_mode_func_01	; yes...error...exit
	test	al,ide_err_reg_bit		; error reg has any error info
	jz	short exec_power_mode_func_02	; no...eror free completion...(CY) set to (NC)

	mov	dx,di				; (dx) = base address for IDE controller
	add	dx,error_reg_off		; (dx) = error reg (1f7h/177h)
	in	al,dx				; (al) = current error reg status
						; this read will clear the error status

exec_power_mode_func_01:
	mov	ah,undefined_err		; undefined error
exec_power_mode_func_04:
	popf					; restore interrupt status
	stc					; (cy) = 01 for error

exec_power_mode_func_10:
	pop     cx				;
	pop     dx				;
	pop     di				;
	ret

exec_power_mode_func_03:
	pop     ax				;
	mov	ah,time_out_err			; timeout error
	jmp	short exec_power_mode_func_04	;

exec_power_mode_func_02:
	popf					; restore interrupt status
	clc					; (cy) = 00 for no error
	jmp	short exec_power_mode_func_10	;

ide_exec_power_mode_func	endp

;---------------------------------------------------------------;
;                      IDE_WAIT_FOR_INTERRUPT             	;
;---------------------------------------------------------------;
;	Input : (DI) base address for IDE controller		;
;		(DX) command/status reg for IDE controller	;
;		(BX) control information pointer for the drive	;
;		(DS) PM BIOS data segment			;
;		STACK PRESENT					;
;	Output: (ZF) 00 (NZ) interrupt active			;
;		(ZF) 01 (ZR) interrupt not active 		;
;	Register destroyed : (AX),(CX),(DX)			;
;								;
; This subroutine is called after a command is writen to the IDE;
; command port to wait for the interrupt to be returned by the	;
; IDE. It will poll the IDE intr level until an IRQ or time-out.;
;---------------------------------------------------------------;

ide_wait_for_interrupt	proc	near

	push	si				;

IF	IRQ_HANDLING_SUPPORT
	call	check_irq_pm			; IRQ based power management ?
	jnz	short ide_wait_for_interrupt_12	; yes...
ENDIF

	mov     cl,[bx+hdd_misc_control_info]	; (cl) = IDE miscellaneous control information
	mov     dx,control_8259_slave 	        ; (dx) = 8259 slave control port (0a0h)
	test	cl,00001000b			; IRQ level 0 thru 7 ?
	jnz	short ide_wait_for_interrupt_01	; no...level 8 thru 15
	mov     dx,control_8259_master 	        ; (dx) = 8259 master control port (020h)
ide_wait_for_interrupt_01:
	and     cl,00000111b                    ; make the level 0 thru 7
	mov     ah,00000001b			;
	shl     ah,cl                           ; get in proper bit position

⌨️ 快捷键说明

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