;	[]===========================================================[]
;
;	NOTICE: THIS PROGRAM BELONGS TO AWARD SOFTWARE INTERNATIONAL(R)
;	        INC. IT IS CONSIDERED A TRADE SECRET AND IS NOT TO BE 	
;	        DIVULGED OR USED BY PARTIES WHO HAVE NOT RECEIVED	
;	        WRITTEN AUTHORIZATION FROM THE OWNER.
;
; 	[]===========================================================[]
;

;----------------------------------------------------------------------------
;Rev	Date	 Name	Description
;----------------------------------------------------------------------------
;R14A	03/18/99 RAY	The bug of SCO-UNIX described in R14 has been 
;			fixed in their new version of SCO-UNIX. Thus recover
;			R14
;R30	03/04/99 JDN	Added Use_CPU_IDLE_In_APM12 define for APM1.2
;			In APM1.2 Timer is disable ,so CPU Idle can't work
;R29	02/23/99 RCH	Added AMD/K7 CPU support.
;R28	02/08/99 ATN	Disable APM when PM_option_item is disabled by user
;			to prevent problem generated by SCO/UNIX. This is
;			an option feature.
;
;R27	01/27/99 RAY	HCT8.x HDD time out failure if tester test the
;			whole HCT APM test.
;
;			It is found that the HCTs (7.x & 8.0) do not call
;			function 0Dh to disable the HDD timer before waiting
;			a 5 minute period to see whether HDD will time out
;			or not. Thus it rely on the OS(Win98) to disable
;			the HDD timer.
;
;			For HCT 8.x, after one of the test before the 
;			Device Power Management test, it issues a call 
;			to function 08h to enable system power managament.
;			We also enable the HDD timer in 08h and thus cause
;			the symtom.
;
;			Patch: do not touch the HDD timer in Function 08
;
;R26	09/29/98 RAY	Moved the "Set_HDD_Standby_Timer" from PMKERNAL.ASM
;			to APM.ASM. Inside function 08h & function 0Dh ,
;			invode this routine to disable/enable HDD timer.
;
;			Reason:
;			-------
;			New HCT Test required the BIOS to disable HDD
;			time-out if the following functions are being 
;			called:
;
;			 - "PM Disabled"(Function 08)
;			 - "Secondary storage PM Disabled (Function 0Dh)
;
;R24B	08/13/98 TNY	Fix coding error.(Win95 APM1.2 fail if "APM_IN_SMBASE"
;			defined)
;R25	07/03/98 TNY	Add "SET_APM_FUNC05_HALT" option.
;R24A	06/26/98 RAX	Support device power management for Function 0Dh & 0Fh
;R24	06/17/98 RAY	Support device power management for Function 0Dh & 0Fh
;R20A	03/26/98 RAX	Fixed mistake.
;R23	03/25/98 RAX	Change compiler to MASM6.X.
;R22	03/04/98 RCH	Fixed system sometimes hang up while compiling this
;			file
;R21	02/03/98 RAY	To let Win95 Shutdown-->PowerOff functionality
;			still exist if PM is disabled in CMOS Setup.
;R20	12/19/97 RAX	Add define for move APM code to SMBASE.
;R19	11/24/97 JKY	Power source change no issue SMI , HCT APM test
;			for change normal notify will fail , please define
;			'POWER_CHANGE_PASSIVE'.
;R18	10/27/97 KGN	move defin LCD_CRT_OPTION to common.equ
;R17	05/06/97 DNL	Added ACPI function support
;R16	04/30/97 KVN	Merge APM and APM32 into APM.ASM
;R15	04/25/97 DNL	Add batery function for APM 1.2
;R14	12/06/96 RAY	Problem:
;			
;			  Fail to install APM under SCO-UNIX.
;			
;			Fixed:
;			
;			  In function 03h, the output SI which according to 
;			  the specification describes the 32bit code segment
;			  size. We found that under a SCO-UNIX environment,
;			  we must not destroy the input SI in order for the
;			  system to install APM successfully. Furthermore,
;			  this workaround will not affect the test result
;			  of the WIN95 SCT test
;			
;R13	10/11/96 DNL	Added LCD only model support
;R12	09/20/96 DNL	Added APM1.2 function support
;R11	09/11/96 RCH	Don't report PCMCIA capabilty due to WIN95 SCT v5.10
;			don't like it for desktop system
;R10	09/06/96 DNL	Added codes for Notebook Power Management.
;R09	09/06/96 DNL	Return correct SI to solve windows95 SCT test fail
;R08A	09/05/96 DNL	Rewrite code to solve windows95 SCT test fail
;R08	08/15/96 DWR	Remove Need_Chk_All_Devices from APM_FUNC0A
;R07	07/16/96 RAY	Do not issue any SW SMI in Function 08h if NO_SUPPORT_APM12
;			is defined even though this is not a new feature of
;			APM v1.2
;R06	07/03/96 RAY	We should also return the remaining battery life 
;			(percentage of time unit) as UNKNOWN or 0FFFFh, i.e.
;			DX=0FFFFh in desktop system.
;R05	06/05/96 RAY	Save codes
;R04	06/04/96 RAX	Add define for make Non PM_SUPPORT bios
;R03A	05/30/96 RAY	R03A will destroy the parameters of Function 11h
;R03	05/29/96 DNL	Fixed bug of system halt while the POWER.EXE installed 
;R00A	05/29/96 DNL	Fixed coding mistake
;R02	05/28/96 RCH	Move "APM_INIT" to MISC.ASM due to not run-time code
;R01	05/24/96 RAY	Reason: run time code overflow starting from F8000
;				when CD_ROM & DMI stuff is added
;
;			Solution:
;
;			Move CRT control related routines to a include file:
;			CRT_CTRL.INC. This include file can be placed in
;			PMUPOST.ASM which locates at F0000-F7FFF or E segment.
;
;			Define CRT_Control_Not_In_APM to save space for
;			F8000-FFFFF. All 586 BIOS are recommanded to add 
;			this switch
;
;R00	05/23/96 RAY	Initial revision to support APM 1.2
;			The old file is placed in OLDFILE\APM.11

;R23 start
ifdef	MASM611
.MODEL  SMALL, BASIC
OPTION	PROC: PRIVATE
endif	;MASM611
;R23 end

.386p
		PAGE	56,132
		TITLE	APM.ASM   --   APM Real/16 bit Interface
.XLIST
		INCLUDE	BIOS.CFG
		INCLUDE	COMMON.EQU
		INCLUDE	COMMON.MAC
;R22		INCLUDE	POST.MAC
;R22		INCLUDE	BSETUP.INC
;R22		include	CMOS.EQU
;R17 - start
ifdef 	ACPI_Support
		include	acpi_ct.inc
		include	acpi.inc
endif;	ACPI_Support
;R17 - end

ifdef	ADVANCE_POWER_MANAGEMENT
;R22		extrn	Get_Cmos:near			;ATORGS.ASM
;R22		extrn	Set_Cmos:near			;ATORGS.ASM
;R22		extrn	BIOS_IDT:WORD			;ATORGS.ASM
ifndef	K7_CPU_SUPPORT					;R29
		extrn	Open_PM_RAM:near		;PMU.ASM
		extrn	Close_PM_RAM:near		;PMU.ASM
endif;	K7_CPU_SUPPORT					;R29
;R22		extrn	Get_PMU:near			;PMU.ASM
;R22		extrn	Set_PMU:near			;PMU.ASM
		extrn	Ct_APM_Func01:near		;PMU.ASM
		extrn	Ct_APM_Func04:near		;PMU.ASM
		extrn	Ct_APM_Func05:near		;PMU.ASM
		extrn	Ct_APM_Func06:near		;PMU.ASM
		extrn	APM_16_Standby:near		;PMU.ASM
		extrn	APM_16_Suspend:near		;PMU.ASM
		extrn	APM_16_PowerOff:near
		extrn	Ct_Check_If_LowBat:near		;PMU.ASM
		extrn	Get_PM_RAM_Seg:near		;PMU.ASM
		extrn	APM_32BIT_ENTRY:near

	ifndef	NO_SUPPORT_APM12
		extrn	CT_RING_WAKEUP_STATUS:near	;pmu.asm
		extrn	CT_PMU_TIMER_STATUS:near	;pmu.asm
		extrn	CT_APM_FUNC10:near		;pmu.asm
	endif	;NO_SUPPORT_APM12

		extrn	Issue_SW_SMI:near

;R16		EXTRN	APM_32Bit_Func00:NEAR
;R16		EXTRN	APM_32Bit_Func01:NEAR
;R16		EXTRN	APM_32Bit_Func02:NEAR
;R16		EXTRN	APM_32Bit_Func03:NEAR
;R16		EXTRN	APM_32Bit_Func04:NEAR
;R16		EXTRN	APM_32Bit_Func05:NEAR
;R16		EXTRN	APM_32Bit_Func06:NEAR
;R16		EXTRN	APM_32Bit_Func07:NEAR
;R16		EXTRN	APM_32Bit_Func08:NEAR
;R16		EXTRN	APM_32Bit_Func09:NEAR
;R16		EXTRN	APM_32Bit_Func0A:NEAR
;R16		EXTRN	APM_32Bit_Func0B:NEAR
;R16		EXTRN	APM_32Bit_Func0C:NEAR
;R16		EXTRN	APM_32Bit_Func0D:NEAR
;R16		EXTRN	APM_32Bit_Func0E:NEAR
;R16		EXTRN	APM_32Bit_Func0F:NEAR

;R16ifndef	NO_SUPPORT_APM12
;R16		EXTRN	APM_32Bit_FUNC10:NEAR
;R16		EXTRN	APM_32Bit_FUNC11:NEAR
;R16		EXTRN	APM_32Bit_FUNC12:NEAR
;R16		EXTRN	APM_32Bit_FUNC13:NEAR
;R16endif	;NO_SUPPORT_APM12

ifdef	VGA_Chip_Control
		extrn	Ct_VGA_Control:near
endif	;VGA_Chip_Control

;R18ifdef	Notebook_Power_Management
;R18	ifndef	NO_LCD_DISPLAY				;R13
;R18		LCD_CRT_OPTION		EQU	1	;R13
;R18	endif	;NO_LCD_DISPLAY				;R13
;R13		EXTRN	LCD_BACKLIGHT_ON:NEAR
;R13		EXTRN	LCD_BACKLIGHT_OFF:NEAR
;R18endif	;Notebook_Power_Management

	ifdef	LCD_CRT_OPTION				;R13
		EXTRN	LCD_BACKLIGHT_ON:NEAR		;R13
		EXTRN	LCD_BACKLIGHT_OFF:NEAR		;R13
	endif	;LCD_CRT_OPTION				;R13

endif	;ADVANCE_POWER_MANAGEMENT

ifdef	PM_SUPPORT				;R04
		extrn	Issue_SW_SMI:near
		extrn	APM_R31_Added:near
endif	;PM_SUPPORT				;R04
;R20  start
ifdef	APM_IN_SMBASE
		extrn	PMI_Handler:near
		extrn	SMI_Handler_Start:near
		extrn	SMI_Handler_End:near
		extrn	SMI_Handler_Len:ABS
endif	;APM_IN_SMBASE
;R20  end

ifdef	Notebook_Power_Management
;R18	ifndef	NO_LCD_DISPLAY
;R18		LCD_CRT_OPTION		EQU	1
;R18	endif	;NO_LCD_DISPLAY
	ifndef	NO_BATTERY_SYSTEM
		BATTERY_SYSTEM		EQU	1
	endif	;NO_BATTERY_SYSTEM
ifdef	Use_CPU_IDLE_In_APM12				;R30
		extrn	Put_CPU_IDLE:near		;R30
endif	;Use_CPU_IDLE_In_APM12				;R30
endif	;Notebook_Power_Management

ifdef	LCD_CRT_OPTION
	ifdef	CHIP_65545
		CHIP_655XX		EQU	1
	endif	;CHIP_65545
endif	;LCD_CRT_OPTION

;R20 start
ifdef	APM_IN_SMBASE
Reallocate	macro	LableName
_&LableName	label	near
LableName	EQU 	$ - offset APM_SMI_START
		ENDM
endif	;APM_IN_SMBASE
;R20 end
G_RAM		SEGMENT	USE16 AT 0

		ORG	04H*4
		INCLUDE	SEG_0.INC

		ORG	400H
		INCLUDE	G_RAM.INC

G_RAM		ENDS

PM_RAM		SEGMENT	USE16 AT 0 	; define PM RAM segment

		ORG	0
		INCLUDE	PM_RAM.INC

PM_RAM		ENDS

.LIST

ifndef	APM_IN_SMBASE			;R20
DGROUP		GROUP	FCODE
FCODE		SEGMENT	USE16 DWORD Public 'CODE'
		ASSUME	CS:DGROUP

ifndef	ADVANCE_POWER_MANAGEMENT

		Public	APM_Service
APM_Service	Proc	Far
		mov	ah,ERROR_APM_NOT_PRESENT	;APM not supported!
		stc
		retf	2
APM_Service	Endp

else	;ADVANCE_POWER_MANAGEMENT

;R02;[]=================================================================[]
;R02;Procedure:	APM_INIT
;R02;
;R02;Function :	Initialize the APM low level interface.
;R02;
;R02;Input    :	ES = PM_RAM
;R02;		AL = 0 ---> call from POST when PM is disabled
;R02;		AL = 1 ---> call from POST when PM is enabled
;R02;
;R02;Output   :	None
;R02;
;R02;[Note]	  :	Called from PM_INIT of POST 79
;R02;[]==================================================================[]
;R02		Public	APM_INIT
;R02APM_INIT	Proc	Near
;R02		push	ds				;save data segment
;R02		push	es
;R02		pop	ds
		ASSUME	DS:PM_RAM
;R02
;R02		or	[APM_STATUS],IS_32BIT_SUPPORTED\
;R02				     +IS_16BIT_SUPPORTED\
;R02				     +IS_PM_ENABLED\
;R02				     +IS_APM_SUPPORTED
;R02		or	al, al
;R02		jnz	short @F
;R02		and	[APM_STATUS],not IS_PM_ENABLED
;R02	@@:
;R02
;R02		or	[EXTEND_APM_STATUS],IS_PM_ENGAGED+PM_ALLOWED_BY_APM
;R02
;R02	ifndef	NO_SUPPORT_APM12
;R02		or	al, al
;R02		jz	short @F
;R02		call	Ct_PMU_Timer_Status
;R02		and	al, PMU_TIMER_ENABLED
;R02		or	[EXTEND_APM_STATUS], al
;R02	@@:
;R02		call	Ct_Ring_WakeUp_Status
;R02		and	al, RING_WAKEUP_ENABLED
;R02		or	[EXTEND_APM_STATUS], al
;R02	endif	;NO_SUPPORT_APM12
;R02
;R02		call	Clear_Events
;R02
;R02		pop	ds				;Restore data segment
;R02		ret
;R02APM_INIT	Endp

;R29 - start
ifdef	K7_CPU_SUPPORT
		extrn	Issue_SW_Smi:near
;Note : The shadow attributes are controlled by K7 MSR, Read & Write
;	to those registers cause system trap under virtual 8086 mode.
;	To prevent this problem, we issue software and program those
;	registers in SMI handler.

;Function : Set F-segment as R/W for APM access
;Input    : none
;Output   : none
Open_PM_RAM	Proc	Near
		mov	al, F_SHADOW_RW
		call	Issue_SW_Smi
		ret
Open_PM_RAM	endp

;Function : Set F-segment as Write Protect
;Input    : none
;Output   : none
Close_PM_RAM	Proc	Near
		mov	al, F_SHADOW_WP
		call	Issue_SW_Smi
		ret
Close_PM_RAM	endp
endif;	K7_CPU_SUPPORT
;R29 - end

;===========================================================================
Need_Chk_BIOS_Device		EQU	00000001b
Need_Chk_All_Devices		EQU	00000010b
Need_Chk_APM10_All_Devices	EQU	00000100b
Need_Chk_Not_Connected		EQU	00001000b
Need_Chk_PM_Disabled		EQU	00010000b
Need_Chk_PM_Engaged		EQU	00100000b
Need_Chk_Param_Range_01		EQU	01000000b
Need_chk_APM_Presence		EQU	10000000b
;===========================================================================
		Public	Chk_Error_Tbl
Chk_Error_Tbl:

	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func00h
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func01h
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func02h
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func03h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected		;func04h
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func05h
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func06h
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged+\
		Need_Chk_PM_Disabled		;func07h
	db	Need_Chk_Not_Connected+\
		Need_Chk_APM10_All_Devices+\
		Need_Chk_PM_Engaged+\
		Need_Chk_Param_Range_01		;func08h
	db	Need_Chk_Not_Connected+\
		Need_Chk_APM10_All_Devices+\
		Need_Chk_PM_Engaged		;func09h
;R08	db	Need_Chk_All_Devices+\
;R08		Need_chk_APM_Presence		;func0Ah
;R08A	db	Need_chk_APM_Presence		;R08 func0Ah
;R08A - start
	db	Need_Chk_All_Devices+\
		Need_chk_APM_Presence		;func0Ah
;R08A - end
	db	Need_Chk_PM_Engaged+\
		Need_Chk_Not_Connected		;func0Bh
	db	Need_Chk_PM_Disabled+\
		Need_chk_APM_Presence		;func0Ch
;R24	db	Need_Chk_All_Devices+\
;R24		Need_Chk_Not_Connected+\
;R24		Need_Chk_PM_Disabled+\
;R24		Need_Chk_PM_Engaged+\
;R24		Need_Chk_Param_Range_01		;func0Dh
;R24 - starts
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Disabled+\
		Need_Chk_PM_Engaged+\
		Need_Chk_Param_Range_01		;func0Dh
;R24 - ends
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func0Eh
;R24	db	Need_Chk_All_Devices+\
;R24		Need_Chk_Not_Connected+\
;R24		Need_Chk_PM_Disabled+\
;R24		Need_Chk_Param_Range_01		;func0Fh
;R24 - starts
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Disabled+\
		Need_Chk_Param_Range_01		;func0Fh
;R24 - ends
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func10h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func11h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func12h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func13h

;===========================================================================
;===========================================================================
		ALIGN	4
		Public	Err_Checking_Routines

Err_Checking_Routines:

		dw	offset Chk_BIOS_Device
		dw	offset Chk_All_Devices
		dw	offset Chk_APM10_All_Devices
		dw	offset Chk_Not_Connected
		dw	offset Chk_PM_Disabled
		dw	offset Chk_PM_Engaged
		dw	offset Chk_Param_Range_01
		dw	offset Chk_APM_Presence

;===========================================================================
;===========================================================================
Check_Errors	Proc	Near

		push	dx
		push	si

		xor	dx,dx
		mov	dl,al
		mov	si,offset Chk_Error_Tbl
		add	si,dx
		mov	dh,cs:[si]		;DH = patterns
		mov	dl,1			;starting from bit 0

		mov	si,offset Err_Checking_Routines
						;routines table

	;=======================================================
	Chk_Nxt_Err:

		test	dh,dl			;this error checking needed?
		jz	short No_Chk_This	;no need to check this error!

		push	dx
		mov	dl,[APM_STATUS]
		mov	dh,[EXTEND_APM_STATUS]
		call	cs:[si]			;call the error checking routine
		pop	dx
		jc	short Chk_Ret		;error found!

	No_Chk_This:

		add	si,2			;point to next chking routine
		shl	dl,1			;test next bit
		jnc	short Chk_Nxt_Err	;all bit tested? NC means no!

	;=======================================================

		clc				;no error found!

	Chk_Ret:

		pop	si
		pop	dx
		ret

Check_Errors	Endp

;[]==================================================================[]
;
; Procedure Name: APM_Service
;
;	APM service routines entry point.
;
; Saves: all
;
; Input:
;	ah=53h
;       al=00h : Installation check
;	  =01h : Interface connect
;	  =02h : 16 bit protect mode connect
;	  =03h : 32 bit protect mode connect
;	  =04h : Interface disconnect
;	  =05h : CPU idle
;	  =06h : CPU busy
;	  =07h : Set power state, standby,suspend
;	  =08h : Enable/disable power management function
;	  =09h : Restore power on defaults
;	  =0ah : Get power status
;	  =0bh : Get PM event
;	bx,cx,dx dependent on the function requested
;
; Output:
;	ax,bx,cx,dx depend the function requested
;
; [Note]:
;	This is the high level dispatch routine for APM interface.
;[]==================================================================[]
		Public	APM_Service
APM_Service	Proc	Far

		ASSUME	DS:PM_RAM

		pushf
		cli
;R17 - start
ifdef 	ACPI_Support
;Return error for all APM function calls if ACPI is enabled
		push	dx
		push	ax
		mov	dx, PM1a_CNT_BLK      	;
		in	al, dx			;Read control register
		test	al, SCI_EN		;Set SCI_EN bit 
		pop	ax
		pop	dx
		jz	short @f 		;No, then continue on
		mov	ah,ERROR_APM_NOT_PRESENT	;APM not supported!
		jmp	short APM_Fail
@@: 
endif;	ACPI_Support
;R17 - end

		push	bp
		push	ds			;save callers ds

	;prepare PM_RAM segment

		push	ax
		call	Get_PM_RAM_Seg
		mov	ds,ax			;DS point to PM_RAM
		pop	ax

	;1. open PM_RAM
	;2. invoke the corresponding function
	;3. close PM_RAM

		xor	bp,bp			;indicates real mode call
		call	Open_Invoke_Close

		pop	ds			;restore callers ds
		pop	bp
		jc	short APM_Fail
APM_Succ:
		popf
		clc
		retf	2
APM_Fail:
		popf
		stc
		retf	2

APM_Service	Endp

;[]--------------------------------------------------------------------------[]
;
; Procedure Name: APM_16Bit_Entry
;
;	This is the main procedure that handles the APM 16 bit call.
;
; Saves: ALL
;
; Inputs:
;	ah=53h
;	al=04h : Interface disconnect
;	  =05h : CPU idle
;	  =06h : CPU busy
;	  =07h : Set power state, standby,suspend
;	  =08h : Enable/disable power management function
;	  =09h : Restore power on defaults
;	  =0ah : Get power status
;	  =0bh : Get PM event
;	bx,cx,dx dependent on the function requested
;
; Outputs:
;	carry flag set if error
;
; [Notes]:
;	1. This procedure should be called in 16-bit mode only.
;	2. The caller should ensure the I/O privilege
;
;[]==========================================================================[]
		ALIGN	4
		public	APM_16BIT_ENTRY	;R16
APM_16BIT_ENTRY:
APM_16BIT_SERVICE	Proc	Far

		pushf
		cli

		push	bp
		push	ds

	;prepare PM_RAM segment

		mov	bp,cs
		add	bp,8				;data decsciptor is second (next after cs)
		mov	ds,bp				;for ds

	;1. open PM_RAM
	;2. invoke the corresponding function
	;3. close PM_RAM

;R16 start
		xor	bp,bp
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		je	short @F
;R16 end
		mov	bp,APM_16BIT_FUNC_MODE		;indicates 16 bit mode call
@@:							;R16
		call	Open_Invoke_Close

		pop	ds
		pop	bp
		jc	short APM16_Fail		;APM function not successful

	APM16_Succ:

		popf
		clc
		retf

	APM16_Fail:

		popf
		stc
		retf

APM_16BIT_SERVICE Endp

;[]==========================================================================[]
;[]==========================================================================[]
Open_Invoke_Close	Proc	Near

		cmp	al,NO_OF_APM_CALL
		jbe	short @F

		mov	ah,ERROR_BAD_PARAM
		stc				;function out of range
		ret
	@@:
		cmp	al,05H
		je	short Corresponding_APM_Func
		cmp	al,06H
		je	short Corresponding_APM_Func

		pushad
		call	Open_PM_RAM
		popad

	;invoke the corrresponding function

		and	word ptr [EXTEND_APM_STATUS],not APM_16BIT_FUNC_MODE
		or	word ptr [EXTEND_APM_STATUS],bp
		call	Corresponding_APM_Func

	;Close PM_RAM

		pushad
		pushf
		mov	al,[OPTION_ROM_EXIST]		;tell if option ROM in this area or not
		call	Close_PM_RAM
		popf
		popad

		ret

Open_Invoke_Close	Endp

;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
		ALIGN	4
Corresponding_APM_Func	Proc	Near

		call	Check_Errors
		jc	short @F

;R03		push	offset Return_From_Apm_Funcs

;R03		push	si
;R03		movzx	si, al
;R03		shl	si, 1
;R03		mov	bp, cs:[si+(offset APM_FUNC_TBL)]
;R03		pop	si

;R03		push	bp
;R03		retn

;R03	Return_From_Apm_Funcs:

;R03A - starts
ifndef	NO_SUPPORT_APM12
		cmp	al, 11h
		jne	short Not_ApmF11
		call	APM_FUNC11
		jmp	short @F

	Not_ApmF11:
endif;	NO_SUPPORT_APM12
;R03A - ends

		push	si				;R03
		push	ax				;R03
		xor	ah,ah				;R03
		shl	ax,1				;R03
		mov	si,offset APM_FUNC_TBL		;R03
		add	si,ax				;R03
		pop	ax				;R03
		call	cs:[si]				;R03
		pop	si				;R03
	@@:
		ret

Corresponding_APM_Func	Endp

		ALIGN	4
APM_FUNC_TBL:
		DW	offset DGROUP:APM_FUNC00
		DW	offset DGROUP:APM_FUNC01
		DW	offset DGROUP:APM_FUNC02
		DW	offset DGROUP:APM_FUNC03
		DW	offset DGROUP:APM_FUNC04
		DW	offset DGROUP:APM_FUNC05
		DW	offset DGROUP:APM_FUNC06
		DW	offset DGROUP:APM_FUNC07
		DW	offset DGROUP:APM_FUNC08
		DW	offset DGROUP:APM_FUNC09
		DW	offset DGROUP:APM_FUNC0A
		DW	offset DGROUP:APM_FUNC0B
		DW	offset DGROUP:APM_FUNC0C
		DW	offset DGROUP:APM_FUNC0D
		DW	offset DGROUP:APM_FUNC0E
		DW	offset DGROUP:APM_FUNC0F

NO_OF_APM_CALL_FOR_APM11  EQU ($-APM_FUNC_TBL)/2-1

ifndef	NO_SUPPORT_APM12
		DW	offset DGROUP:APM_FUNC10
		DW	offset DGROUP:APM_FUNC11
		DW	offset DGROUP:APM_FUNC12
		DW	offset DGROUP:APM_FUNC13
endif	;NO_SUPPORT_APM12

NO_OF_APM_CALL  EQU ($-APM_FUNC_TBL)/2-1

;R16		PUBLIC	APM_32Bit_FUNC_TBL
;R16		PUBLIC	NO_OF_32Bit_APM_CALL
;R16APM_32Bit_FUNC_TBL:
;R16		DW	offset DGROUP:APM_32Bit_Func00
;R16		DW	offset DGROUP:APM_32Bit_Func01
;R16		DW	offset DGROUP:APM_32Bit_Func02
;R16		DW	offset DGROUP:APM_32Bit_Func03
;R16		DW	offset DGROUP:APM_32Bit_Func04
;R16		DW	offset DGROUP:APM_32Bit_Func05
;R16		DW	offset DGROUP:APM_32Bit_Func06
;R16		DW	offset DGROUP:APM_32Bit_Func07
;R16		DW	offset DGROUP:APM_32Bit_Func08
;R16		DW	offset DGROUP:APM_32Bit_Func09
;R16		DW	offset DGROUP:APM_32Bit_Func0A
;R16		DW	offset DGROUP:APM_32Bit_Func0B
;R16		DW	offset DGROUP:APM_32Bit_Func0C
;R16		DW	offset DGROUP:APM_32Bit_Func0D
;R16		DW	offset DGROUP:APM_32Bit_Func0E
;R16		DW	offset DGROUP:APM_32Bit_Func0F
;R16
;R16;R00A NO_OF_32BIT_APM_CALL_FOR_APM11  EQU ($-APM_FUNC_TBL)/2-1
;R16NO_OF_32BIT_APM_CALL_FOR_APM11  EQU ($-APM_32Bit_FUNC_TBL)/2-1	;R00A
;R16
;R16ifndef	NO_SUPPORT_APM12
;R16		DW	offset DGROUP:APM_32Bit_FUNC10
;R16		DW	offset DGROUP:APM_32Bit_FUNC11
;R16		DW	offset DGROUP:APM_32Bit_FUNC12
;R16		DW	offset DGROUP:APM_32Bit_FUNC13
;R16endif	;NO_SUPPORT_APM12
;R16
;R16NO_OF_32Bit_APM_CALL  EQU ($-APM_32Bit_FUNC_TBL)/2-1

;[]==================================================================[]
;Procedure:	APM_FUNC00
;
;Function :	APM function 0 - Installation check.
;
;Saves    :	all
;
;Input    : 	DS = PM_RAM
;		AH = 53h
;       	AL = 00h
;		BX = 0000h
;
;Output   :	if function successful:
;			carry = 0
;		ah = major version number (in BCD format)
;		al = minor version number (in BCD format)
;		bh = 'P'
;		bl = 'M'
;		cx = flags
;			bit 0 = 1 if 16 bit protected mode interface is supported
;			bit 1 = 1 if 32 bit protected mode interface is supported
;			bit 2 = 1 if CPU idle call slows processor clock speed
;			bit 3 = 1 if BIOS power management is disabled
;			all other bits reserved
;
;		if function unsuccessful:
;			carry = 1
;			ah = 86h APM not present
;[]==================================================================[]
		Public	APM_FUNC00
APM_FUNC00	Proc	Near

		ASSUME	DS:PM_RAM

;R28 - start
ifdef Disable_APM_when_PM_Disabled	
		test	[APM_STATUS],SETUP_PM_DISABLED

		mov	ah,ERROR_APM_NOT_PRESENT
		jnz	short af0_bad
endif ;Disable_APM_when_PM_disabled
;R28 - end

;R16 start
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		je	short af0_good
;R16 end
		test	[EXTEND_APM_STATUS],APM_16BIT_FUNC_MODE
		jnz	short af0_good

		test	[APM_STATUS],IS_APM_SUPPORTED
		mov	ah,ERROR_APM_NOT_PRESENT
		jz	short af0_bad

ifdef	NO_SUPPORT_APM12
		mov	ax,0101h
else	;NO_SUPPORT_APM12
		mov	ax,0102h
endif	;NO_SUPPORT_APM12
		mov	bx,"PM"
		mov	cx,00000111b			;return apm support flags in cx

		test	[APM_STATUS], SETUP_PM_DISABLED	;R21
		jz	short af0_good			;R21
		mov	cx, 00001000b			;R21
af0_good:
		clc
		ret
af0_bad:
		stc
		ret

APM_FUNC00	Endp

;[]=======================================================================[]
;Procedure:	APM_FUNC01
;
;Function :	APM function 1 - Interface connect
;
;Saves    :	all
;
;Input    :	DS = PM_RAM
;		AH = 53h
;       	AL = 01h
;		BX = 0000h - system BIOS
;
;Output   :	if function successful:
;			carry = 0
;		if function unsuccessful:
;			carry = 1
;			ah = eoror code
;				02h interface connect already in effect
;				09h unrecognized device ID
;[]==================================================================[]
		Public	APM_FUNC01
APM_FUNC01	Proc	Near

;R16 start
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		je	short af1_good
;R16 end
		test	[EXTEND_APM_STATUS],APM_16BIT_FUNC_MODE
		jnz	short af1_good

	;check if any APM drivers already connected

		call	Chk_32Bit_Connected	;32 bit mode APM connected?
		jc	short af1_bad		;yes, return error!
		call	Chk_16Bit_Connected	;16 bit mode APM connected?
		jc	short af1_bad		;yes, return error!
		call	Chk_Real_Connected	;real mode APM connected?
		jc	short af1_bad		;yes, return error!

	;set flag for real mode connected

		and	[APM_STATUS],0Fh
		or	[APM_STATUS],IS_CONNECT_CALL_MADE
		or	[EXTEND_APM_STATUS],PM_ALLOWED_BY_APM+IS_PM_ENGAGED

	;clear events

		call	Clear_Events

	;chipset dependent routine for APM connection

		pusha
		pushf
		call	Ct_APM_Func01
		popf
		popa
af1_good:
		clc
		ret

af1_bad:
		stc
		ret

APM_FUNC01	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	CY : AH = ERROR_16BIT_ALREADY_CONN
;			  i.e. 16 bit function already connected
;[]========================================================================[]
Chk_16Bit_Connected	Proc	Near
		push	ax
		mov	al,[APM_STATUS]
		and	al,IS_CONNECT_CALL_MADE+IS_16BIT_ESTABLISHED
		cmp	al,IS_CONNECT_CALL_MADE+IS_16BIT_ESTABLISHED
		pop	ax
		clc
		jne	short @F			;16 bit mode not connected
		mov	ah,ERROR_16BIT_ALREADY_CONN	;16 bit mode APM already conn.
		stc
	@@:
		ret
Chk_16Bit_Connected	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	CY : AH = ERROR_32BIT_ALREADY_CONN
;			  i.e. 32 bit function already connected
;[]========================================================================[]
Chk_32Bit_Connected	Proc	Near
		push	ax
		mov	al,[APM_STATUS]
		and	al,IS_CONNECT_CALL_MADE+IS_32BIT_ESTABLISHED
		cmp	al,IS_CONNECT_CALL_MADE+IS_32BIT_ESTABLISHED
		pop	ax
		clc
		jne	short @F			;32 bit mode not connected
		mov	ah,ERROR_32BIT_ALREADY_CONN	;32 bit mode APM already conn.
		stc
	@@:
		ret
Chk_32Bit_Connected	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	CY : AH = ERROR_REAL_ALREADY_CONN
;			  i.e. real mode function already connected
;[]========================================================================[]
Chk_Real_Connected	Proc	Near
		push	ax
		mov	al,[APM_STATUS]
		and	al,IS_CONNECT_CALL_MADE
		cmp	al,IS_CONNECT_CALL_MADE
		pop	ax
		clc
		jne	short @F
		mov	ah,ERROR_REAL_ALREADY_CONN	;real mode APM already conn.
		stc
	@@:
		ret
Chk_Real_Connected	Endp

;[]==================================================================[]
;
; Procedure Name: APM_FUNC02
;
;	APM function 2 - Protect mode 16 bit interface connect
;
; Saves: all
;
; Input:
;	ah=53h
;       al=02h
;	bx=0000 - system BIOS
;
; Output:
;	if function successful:
;		carry = 0
;	ax = PM 16 bit code segment (real mode segmnt base address)
;	bx = offset of entry point
;	cx = PM 16 bit data segment
;
;	if function unsuccessful:
;		carry = 1
;		ah = error code
; 		 05h = 16 bit protected mode interface already established
;	 	 06h = 16 bit protected mode interface not supported
;		 09h = unrecognized device ID
;[]==================================================================[]
		Public	APM_FUNC02
APM_FUNC02	Proc	Near

		test	[APM_STATUS],IS_16BIT_SUPPORTED	;i6 bit supported?
		mov	ah,ERROR_NO_SUPPORT_16BIT		;
		jz	short af2_bad			;no, return error!

		call	APM_FUNC01			;successful check in?
		jc	short af2_bad			;no, return error!

	;set flag for 16 bit APM connection

		or	[APM_STATUS],IS_16BIT_ESTABLISHED

	;Prepare segment registers

		mov	ax,cs				;code seg.
		mov	cx,ds				;data seg.
		mov	bx,offset APM_16BIT_ENTRY
af2_good:
		xor	si,si
;R14		mov	ss:[esp+2],si			;R09
		mov	ss:[esp+2],si			;R14A
		xor	di,di
		ret
af2_bad:
		stc
		ret

APM_FUNC02	Endp

;[]==================================================================[]
; Procedure Name: APM_FUNC03
;
;	APM function 3 - Protect mode 32 bit interface connect
;
; Saves: all
;
; Input:
;	ah = 53h
;       al = 03h
;	bx = 0000h - system BIOS
;	DS = PM_RAM
;
; Output:
;	if function successful:
;		carry = 0
;	ax = PM 32 bit code segment (real mode segmnt base address)
;	ebx = offset of entry point
;	cx = PM 16 bit code segmetn
;	dx = PM data segment
;
;	if function unsuccessful:
;		carry = 1
;		ah = error code
; 		 07h = 32 bit protected mode interface already established
;	 	 08h = 32 bit protected mode interface not supported
;		 09h = unrecognized device ID
;[]==================================================================[]
APM_FUNC03	Proc	Near

		test	[APM_STATUS],IS_32BIT_SUPPORTED	;i6 bit supported?
		mov	ah,ERROR_NO_SUPPORT_32BIT		;
		jz	short af3_bad			;no, return error!

		call	APM_FUNC01			;successful check in?
		jc	short af3_bad			;no, return error!

	;set flag for 32 bit APM connection

		or	[APM_STATUS],IS_32BIT_ESTABLISHED

	;Prepare segment registers

		mov	cx,cs				;code seg.
		xor	ebx,ebx
		mov	bx,offset DGROUP:APM_32bit_Entry
		mov	ax,cs				;code seg.
		mov	dx,ds				;data seg.
		xor	si, si
;R14		mov	ss:[esp+2],si			;R09
		mov	ss:[esp+2],si			;R14A
		xor	di, di
af3_good:
		clc
		ret
af3_bad:
		stc
		ret

APM_FUNC03	Endp

;[]==================================================================[]
; Procedure Name: APM_FUNC04
;
;	APM function 4 - Interface disconnect
;
; Saves: all
;
; Input:
;	ah = 53h
;       al = 04h
;	bx = 0000h - system BIOS
;	DS = PM_RAM
;
; Output:
;	if function successful:
;		carry = 0
;
;	if function unsuccessful:
;		carry = 1
;		ah = error code
;		 03h = interface not connected
;		 09h = unrecognized device ID
;[]==================================================================[]
APM_FUNC04	Proc	Near

		and	[APM_STATUS],not IS_CONNECT_CALL_MADE
		test	[EXTEND_APM_STATUS],APM_16BIT_FUNC_MODE
		jz	short @F
		and	[APM_STATUS],not IS_16BIT_ESTABLISHED
		jmp	short APM_STATUS_done
	@@:
;R16 start
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		jne	short APM_STATUS_done
		and	[APM_STATUS],not IS_32BIT_ESTABLISHED
APM_STATUS_done:
;R16 end
		and	[EXTEND_APM_STATUS],not (APM11_INSTALLED+APM12_INSTALLED)
		call	Clear_Events

	;chipset dependent routine for APM disconnection

		pusha
		pushf
		call	Ct_APM_Func04
		popf
		popa

		clc
		ret

APM_FUNC04	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC05 (CPU Idle Call)
;
;Function :	Put CPU in DOZE mode
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 05h
;
;Output   :	CF - Error
;		     AH = 03h Interface not connected
;		NC - Success
;[]==================================================================[]
APM_FUNC05	Proc	Near

ifdef	SET_APM_FUNC05_HALT				;R25
		sti					;R25
		hlt					;R25
else;	SET_APM_FUNC05_HALT				;R25

;R30 - start	
ifdef	Notebook_Power_Management
ifdef	Use_CPU_IDLE_In_APM12
		test	[EXTEND_APM_STATUS], APM12_INSTALLED
		jz	short Not_APM12
		call	Put_CPU_IDLE
		jmp	short af5_fini
Not_APM12:
endif	;Use_CPU_IDLE_In_APM12
endif	;Notebook_Power_Management
;R30 - end
	;
	;we only call Ct_APM_Func05 if:
	;	i. it is in FULL_ON mode &
	;	ii. CPU_IDLE_FLAG is set
	;
		cmp	[PM_MODE],DOZE_MODE
		je	short af5_fini
		cmp	[PM_MODE],SLEEP_MODE
		je	short af5_fini

		test	[PM_CTRL_FLAG],CPU_IDLE_FLAG
		jz	short Af5_Fini

	;chipset dependent sleep actions

		pushad
		call	Open_PM_RAM
		call	Ct_APM_Func05
		mov	[PM_MODE],DOZE_MODE
		and	[PM_CTRL_FLAG],NOT CPU_IDLE_FLAG
		call	Close_PM_RAM
		popad

af5_fini:
endif;	SET_APM_FUNC05_HALT				;R25
		clc
		ret

APM_FUNC05	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC06 (CPU Busy Call)
;
;Function :	Put CPU in Full ON mode
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 06h
;
;Output   :	CF - Error
;		     AH = 03h Interface not connected
;		NC - Success
;[]==================================================================[]
APM_FUNC06	Proc	Near

		clc
		ret

APM_FUNC06	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC07 (Set Power State)
;
;Function :	To set system to requested state
;		Here we only handle suspend request
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 07h
;		BX = Power device ID
;		     0001h	 All devices managed by the APM BIOS
;		     01XXh	 Display
;		     02XXh	 Secondary Storage
;		     03XXh	 Parallel Ports
;		     04XXh	 Serial Ports
;		     E000h-EFFFh OEM-defined Power Devices IDs
;		CX = Power State
;		     0000h	 APM Enabled
;		     0001h	 Standby
;		     0002h	 Suspend
;		     0003h	 Off
;		     0004h-001Fh Reserved system states
;		     0020h-003Fh OEM defined system states
;		     0040h-007Fh OEM defined device states
;		     0080h-FFFFh Reserved device states
;
;Output   :	CF - Error
;		     AH = 01h Power Management functionality disabled
;			  03h Interface not connected
;			  09h Unrecognized device ID
;			  0Ah Parameter value out of range
;			  60h Unable to enter requested state
;		NC - Success
;[]==================================================================[]
APM_FUNC07	Proc	Near

		call	Check_PM_Allowed
		jc	short af7_bad

		call	Check_F07_Bad_Param
		jc	short af7_bad

		cmp	bh, 01h
		je	short F07_Control_Disp

		call	Chk_All_Devices
		jc	short af7_bad

		push	ds
		push	es
		push	fs
		push	gs
		pushad

	;------------------------------------------------------------
	;no matter reject or accept, Posted events must be cleared
	;------------------------------------------------------------

		not	cl
		and	[APM_EVENT_POST],cl
		not	cl

	;------------------------------------------------------------
	;under some conditions, we must reject requests
	;e.g. do not suspend if APMEventSave = RESUME_CRITICAL_NOTIFY
	;------------------------------------------------------------

		mov	al,[APMEventSave]
		call	Skip_Request
		jc	short af7_skip

	;------------------------------------------------------------
	;call chip dependent SUSPEND/STANDBY routine
	;------------------------------------------------------------

		mov	[APMEventSave],NO_EVENTS

		cmp	cl, APM_OFF_REQ			;power off request?
		jne	short @f			;no, check other states

		stc					;for dummy return
		call	APM_16_PowerOff
		jnc	short af7_skip
		popad
		mov	ah, ERROR_NO_STATE_REQUEST
		jmp	short af7_exit1
	@@:

		cmp	cl,APM_SUSPEND_REQ
		jne	short @F

	;add delay for clearing pending IRQs before going into suspend

		sti
		mov	bh, 5
		xor	cx,cx
	_hh:
		mov	al, bh
		NEWIODELAY
		loop	short _hh
		dec	bh
		jnz	short _hh

		call	APM_16_Suspend
	ifndef	No_Stpclk_When_Suspend
		mov	[APMEventSave],RESUME_NORMAL_NOTIFY
	endif	;No_Stpclk_When_Suspend
		jmp	short af7_skip
	@@:
		call	APM_16_Standby
		mov	[APMEventSave],STANBY_RESUME_NOTIFY

	af7_skip:
		clc
	af7_exit:
		popad
	af7_exit1:
		pop	gs
		pop	fs
		pop	es
		pop	ds

		ret
af7_bad:
		stc
		ret

F07_Control_Disp:
		pushad
		mov	al, CRT_ON_REQ
		cmp	cl, APM_READY_REQ
		je	short @F
		mov	al, CRT_OFF_REQ
	@@:
		mov	[Software_SMI_Type], al
		call	Issue_SW_SMI
		popad
		mov	[DISP_PM_MODE], cl
		mov	[Software_SMI_Type], 0
		clc
		ret

APM_FUNC07	Endp

;-----------------------------------------------------------------------
;Check BAD parameters
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;-----------------------------------------------------------------------
		Public	Check_F07_Bad_Param
Check_F07_Bad_Param	Proc	Near

		or	ch,ch
		jnz	short Param_Bad

		cmp	cl, APM_OFF_REQ		;valid request?
		jbe	short Req_Accepted	;yes, continue

	Param_Bad:

		mov	ah,ERROR_BAD_PARAM
		or	ch,ch
		jnz	short @F
		cmp	cl,05h
		ja	short @F
		mov	ah,ERROR_NO_STATE_REQUEST
	@@:
		stc
		ret

	Req_Accepted:

		clc
		ret

Check_F07_Bad_Param	Endp

;--------------------------------------------------------------------------
;
;SUSPEND request: check RESUME_NORMAL_NOTIFY & RESUME_CRITICAL_NOTIFY
;STANDBY request: check items of SUSPEND plus STANBY_RESUME_NOTIFY
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;--------------------------------------------------------------------------
		Public	Skip_Request
Skip_Request	Proc	Near

		cmp	al,RESUME_NORMAL_NOTIFY
		je	short Event_Reject
		cmp	al,RESUME_CRITICAL_NOTIFY
		je	short Event_Reject
		cmp	cl, APM_OFF_REQ
		je	short Do_Request
		cmp	cl,APM_SUSPEND_REQ
		je	short Do_Request
		cmp	al,STANBY_RESUME_NOTIFY
		jne	short Do_Request
Event_Reject:
		stc
		ret
Do_Request:
		clc
		ret
Skip_Request	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC08
;
;Function :	Enable/Disable Power Management
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 08h
;		BX = Power Device ID
;		     0001h	All devices power managed by the APM BIOS
;		     FFFFh	All devices power managed by the APM BIOS
;				(Compatible with APM 1.0)
;		CX = Function code
;		     0000h	Disable power management
;		     0001h	Enable power management
;
;Output   :	CF - Error
;		     AH = 01h Power Management functionality disabled
;			  03h Interface not connected
;			  09h Unrecognized device ID
;			  0Ah Parameter value out of range
;		NC - Success
;[]==================================================================[]
APM_FUNC08	Proc	Near

		call	Clear_Events		;must clear events first
		push	dx
		mov	dx, word ptr [APM_STATUS]
		call	Do_Func08
		jc	short @F
		mov	[EXTEND_APM_STATUS], dh

;R05		pushad
;R05		mov	al, ENABLE_PM_REQ
;R05		or	dh, dh
;R05		jnz	short _kk
;R05		mov	al, DISABLE_PM_REQ
;R05	_kk:
;R05		mov	byte ptr [Software_SMI_Type], al

;R27		call	Prg_HDD_Timer				;R26

ifndef	NO_SUPPORT_APM12				;R07
		pushad						;R05
		mov	byte ptr [Software_SMI_Type], dl	;R05
		call	Issue_SW_SMI
		mov	byte ptr [Software_SMI_Type], 0
		popad
endif	;NO_SUPPORT_APM12				;R07
		clc
	@@:
		pop	dx
		ret

;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
		Public	Do_Func08
Do_Func08	Label	Near		;R23 
;R23 Do_Func08:
		test	dh, APM12_INSTALLED
		jnz	short @F
		test	dl, IS_PM_ENABLED
		jz	short Func08_PM_Dis_Error
	@@:
		or	cl, cl			;enable request?
		clc
		jnz	short Update_PM_Bit	;yes, continue

To_Disable_PM:
		test	dh, PM_ALLOWED_BY_APM
		jnz	short Update_PM_Bit

Func08_PM_Dis_Error:

		mov	ah, ERROR_PM_DISABLED
		stc
		ret

Update_PM_Bit:
		and	dh, not PM_ALLOWED_BY_APM
		or	dh, cl

;R05 - starts
		mov	dl, ENABLE_PM_REQ
		or	cl, cl
		jnz	short _kk
		mov	dl, DISABLE_PM_REQ
	_kk:
;R05 - ends

		ret

APM_FUNC08	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC09
;
;Function :	Restore APM Power-On Default
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 09h
;		BX = Power Device ID
;		     0001h	All devices power managed by the APM BIOS
;		     FFFFh	All devices power managed by the APM BIOS
;				(Compatible with APM 1.0)
;
;Output   :	CF - Error
;		     AH = 03h Interface not connected
;			  09h Unrecognized device ID
;		NC - Success
;[]==================================================================[]
APM_FUNC09	Proc	Near
		pushad
		mov	byte ptr [Software_SMI_Type], RESTORE_POWERON_D4_REQ
		call	Issue_SW_SMI
		mov	byte ptr [Software_SMI_Type], 0
		popad
		clc
		ret
APM_FUNC09	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0A
;
;Function :	Get Power Status
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Ah
;		BX = Power Device ID
;		     0001h	All devices power managed by the APM BIOS
;		     All other values reserved
;
;Output   :	CF - Error
;		     AH = 09h Unrecognized device ID
;
;		NC - Success
;		     BH = AC line status
;			       00h Off-line
;			       01h On-line
;			       02h On backup-power
;			       FFh Unknown
;			       All other values reserved
;		     BL = Battery status
;		     	       00h High
;			       01h Low
;			       02h Critical
;			       03h Charging
;			       FFh Unknown
;			       All Other values unknow
;		     CH = Battery flag
;		     	  bit0 = 1 High
;			  bit1 = 1 Low
;			  bit2 = 1 Critical
;			  bit3 = 1 Charging
;			  bit7 = 1 No System battery
;			       FFh Unknown
;			       All Other values unknow
;		     CL = Remaining battery life - percentage of charge
;			       0-100 = Percentage of full charge
;			       255 = Unknown
;			       All Other values unknow
;		     DX = Remaining battery life - time units
;			       Bit 15 = 0 Time units are seconds
;			       Bit 14-0 = Number of seconds or minutes
;				       0-7FFFh Valid number of seconds
;				       0-7FFEh Valid number of minutes
;			       FFFFh = Unknown
;[]==================================================================[]
APM_FUNC0A	Proc	Near
;R06		mov	cl,UNKNOWN		;exact battery life unknown
;R06		mov	al,0
;R06		call	Ct_Check_If_LowBat
;R06ifndef	BATTERY_SYSTEM
;R06		mov	ch,80H			;no battery
;R06endif	;BATTERY_SYSTEM

;R06 - starts
ifdef	BATTERY_SYSTEM
;R10 - start
		cmp	bh,BATTERY_DEVICES SHR 8
		jne	short Chk_Battery_ID
		
		cmp	bl,MAX_BATTERY_UNIT
;R15		ja	short Chk_Battery_ID
		ja	short Invalid_Device_ID		;R15

		pusha
		mov	cl,bl
		dec	cl
		mov	al,01h
		shl	al,cl

		test	PM_RAM:BATTERY_UNIT,al
		popa
		jnz	short Chk_Battery_ID

;R15 - start
		mov	bl,UNKNOWN
		mov	ch,BAT_NOT_PRESENT
		mov	cl,UNKNOWN
		mov	dx,0FFFFh
		clc
		ret
Invalid_Device_ID:
;R15 - end
		mov	ah,ERROR_UNKNOWN_DEVICE_ID
		stc
		ret
Chk_Battery_ID:
;R10 - end
		mov	cl, UNKNOWN
		xor	al, al
		call	Ct_Check_If_LowBat
		mov	ss:[esp+2],si			;R09
else	;BATTERY_SYSTEM
		mov	cx, 080FFh
		mov	dx, 0FFFFh
		mov	bx, 01FFh
endif	;BATTERY_SYSTEM
;R06 - ends

		clc
		ret

APM_FUNC0A	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0B
;
;Function :	Get PM Event
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Bh
;
;Output   :	CF - Error
;		     AH = 03h	Interface not connected
;			  80h	No power management events pending
;		NC - Success
;		     BX = PM event code
;[]==================================================================[]
APM_FUNC0B	Proc	Near

		push	dx

		xor	bh,bh
		mov	bl,[APMEventSave]
		mov	dh,[APM_EVENT_POST]

		mov	si,offset Event_Table		;si point to even table
Post_Next_Event:
		cmp	bl,cs:[si]			;event exist?
		jne	short @F			;this event not exist
		or	dh,cs:[si+1]			;set record
ifdef	POWER_CHANGE_PASSIVE				;R19
		mov	[APMEventSave],NO_EVENTS	;R19
endif	;POWER_CHANGE_PASSIVE				;R19
		jmp	short End_Post_Event		;finish!
	@@:
		add	si,2				;check next event
		cmp	si,offset End_Event_Table	;end of table?
		jb	short Post_Next_Event		;not yet!

		mov	bl,NO_EVENTS			;no event found
		call	Battery_Check			;if low battery
							;  BL=BATT_LOW_NOTIFY
End_Post_Event:

ifndef	POWER_CHANGE_PASSIVE				;R19
		mov	[APMEventSave],NO_EVENTS	;event done
endif	;POWER_CHANGE_PASSIVE				;R19
		mov	[APM_EVENT_POST],dh		;set record

		cmp	bl,NO_EVENTS			;no event?
		clc
		jne	short @F			;no, exit
		stc					;set error
		mov	ah,ERROR_NO_EVENT_PENDING	;return error code
	@@:
		pop	dx
		ret

APM_FUNC0B	Endp

Battery_Check	Proc	Near

		pusha
		mov	al,1
		call	Ct_Check_If_LowBat
		cmp	bh,AC_ON_LINE
		je	short @F
		cmp	bl,BAT_HIGH
	@@:
		popa

		je	short @F		;BATT high or AC power
		test	dh,BATT_LOW_POST	;already posted to APM?
		jnz	short @F		;yes, skip
		or	dh,BATT_LOW_POST	;set indication
		mov	bl,BATT_LOW_NOTIFY	;return
	@@:
		ret

Battery_Check	Endp

;===================================================
		Public	Event_Table
		Public	End_Event_Table
Event_Table:
		db	SUSPENDREQUEST		,SUSPEND_POST
		db	USER_SUSPENDREQUEST	,SUSPEND_POST
		db	STANDBYREQUEST		,STANDBY_POST
		db	USER_STANDBYREQUEST	,STANDBY_POST
		db	UPDATE_TIME_NOTIFY	,0
		db	RESUME_NORMAL_NOTIFY	,0
		db	RESUME_CRITICAL_NOTIFY	,0
		db	STANBY_RESUME_NOTIFY	,0
		db	PM_STATUS_CHANGE_NOTIFY	,0		;R12
End_Event_Table:
;===================================================

;[]==================================================================[]
;Procedure:	APM_FUNC0C
;
;Function :	Get Power State
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Ch
;		BX = Power device ID
;		     0001h : All devices power managed by the APM BIOS
;		     01XXh : Display
;		     02XXh : Secondary Storage
;		     03XXh : Parallel Ports
;		     04XXh : Serial Ports
;		     05XXh : Network Adapters
;		     06XXh : PCMCIA Sockets
;		     E000h - EFFFh OEM-defined Power Device IDs
;		     All other values reserved
;
;		     where:
;
;		     XX h = Unit Number (0 based)
;		     Unit Number of FFh means all devices in this class.
;
;Output   :	CF - Error
;		     AH = 01h	Power management functionality disabled
;			  09h	Unrecognized device ID
;		NC - Success
;		     CX = Power State
;			  0000h	APM Enabled
;			  0001h Stanby
;			  0002h Suspend
;			  0003h Off
;			  0004h-001Fh Reserved system states
;			  0020h-003Fh OEM-defined system states
;			  0040h-007Fh OEM-defined device states
;			  0084h-FFFFh Reserved device states
;
;[]==================================================================[]
APM_FUNC0C	Proc	Near

		cmp	bh, 01h
		jne	short @F
		mov	cl, [DISP_PM_MODE]
		ret
	@@:
		call	Chk_All_Devices
		jc	short afc_Ret

		mov	cl,[PM_MODE]
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
		Public	Do_Func0C
Do_Func0C	Label	Near		;R23 
;R23 Do_Func0C:
		cmp	cl,2		;	  Award	     APM
		jb	short @F	;Full-on  0(Full-on) 0(APM enabled)
		dec	cl		;Doze	  1	     ?
	@@:				;Standby  2	     1
		clc			;Suspend  3	     2
	afc_Ret:
		ret

APM_FUNC0C	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0D
;
;Function :	Enable/Disable Device Power Management
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Dh
;		BX = Power device ID
;		     0001h : All devices power managed by the APM BIOS
;		     01XXh : Display
;		     02XXh : Secondary Storage
;		     03XXh : Parallel Ports
;		     04XXh : Serial Ports
;		     05XXh : Network Adapters
;		     06XXh : PCMCIA Sockets
;		     E000h - EFFFh OEM-defined Power Device IDs
;		     All other values reserved
;
;		     where:
;
;		     XX h = Unit Number (0 based)
;		     Unit Number of FFh means all devices in this class.
;
;Output   :	CF - Error
;		     AH = 01h	Power management functionality disabled
;			  03h	Interface not connected
;			  09h	Unrecognized device ID
;		NC - Success
;[]==================================================================[]
APM_FUNC0D	Proc	Near
;R24		call	APM_FUNC08
;R24 - starts
		call	Decode_APM_Devices	;decode the input BX
		jc	short APM_FUNC0D_End	;CF=invalid device input

		cmp	bx, ALL_DEVICES
		je	APM_FUNC08
		clc

	APM_FUNC0D_End:
;R24 - ends
		ret
APM_FUNC0D	Endp

;R24 - starts
Decode_APM_Devices	Proc	Near

		push	dx
		push	si
		mov	si, offset APM_Device_Tbl	;si point to device
							; table
	Decode_Next_APM_Device:

		cmp	si, offset APM_Device_Tbl_End	;end of table
		je	Wrong_Device			;yes, post error!

		cmp	bx, word ptr cs:[si]		;device found?
		je	APM_Device_Found		;yes, go do it.
		add	si, One_APM_Device_Len		;point to next device
		jmp	Decode_Next_APM_Device		;go decode next

	APM_Device_Found:

		mov	dx, cs:[si+2]			;dx=value for updating
							;   flag in PM_RAM
	;---------------------------------------------------

		cmp	bx, ALL_DEVICES		;all devices?
		je	Update_Dev_PM_Flg	;yes, skip ERROR_PM_DISABLED

	;---------------------------------------------------

		test	[DEVICE_PM_STATUS], dx	;assume device PM to be enabled
		jnz	Dev_PM_Now_Enabled	;NZ --> device PM is now enabled
		or	cx, cx			;disable request?
		jz	Dev_PM_Already_Disabled	;yes, Post error: ERROR_PM_DISABLED

	Dev_PM_Now_Enabled:

	;---------------------------------------------------
	;If function 0Dh, check for corresponding device 
	;engage status
	;---------------------------------------------------

		cmp	al, 0Dh
		jne	No_Chk_Engaged
;R26 - starts
		cmp	bh, 02h			;Storage device control?
		jne	@F			;no
		call	Prg_HDD_Timer
	@@:
;R26 - ends
		shl	dx, 1
		test	[DEVICE_PM_STATUS], dx	;assume device PM to be enabled
		jz	Interface_Not_Engaged
		shr	dx, 1

	No_Chk_Engaged:

	;---------------------------------------------------
	;set flags for device power management
	;---------------------------------------------------

	Update_Dev_PM_Flg:

		cmp	al, 0Fh			;PM engage/dis-engage?
		jne	@F			;no!
		shl	dx, 1			;set flg for engage/dis-engage
	@@:
		or	[DEVICE_PM_STATUS], dx	;assume device PM to be enabled
		or	cx, cx			;really to be enabled?
		jnz	End_Decode_APM_Devices	;yes!
		not	dx			;about to clear the flag
		and	[DEVICE_PM_STATUS], dx	;clear device flag

	End_Decode_APM_Devices:

		clc
		jmp	Dev_PM_Exit

	Wrong_Device:

		mov	ah, ERROR_UNKNOWN_DEVICE_ID
		jmp	Dev_PM_Err_Exit

	Interface_Not_Engaged:

		mov	ah, ERROR_PM_NOT_ENGAGED
		jmp	Dev_PM_Err_Exit

	Dev_PM_Already_Disabled:

		mov	ah, ERROR_PM_DISABLED

	Dev_PM_Err_Exit:

		stc

	Dev_PM_Exit:

		pop	si
		pop	dx
		ret

Decode_APM_Devices	Endp

APM_Device_Tbl	Label	Near
		dw	0001h, ALL_DEVICES_PM_ENABLED
One_APM_Device_Len	EQU	$ - offset APM_Device_Tbl

		dw	0100h, DISP_PM_ENABLED
		dw	01FFh, DISP_PM_ENABLED
		dw	0200h, STORAGE_PM_ENABLED
		dw	02FFh, STORAGE_PM_ENABLED
		dw	0300h, LPT_PM_ENABLED
		dw	03FFh, LPT_PM_ENABLED
		dw	0400h, COM1_PM_ENABLED
		dw	0401h, COM2_PM_ENABLED
		dw	04FFh, COM1_PM_ENABLED+COM2_PM_ENABLED
		dw	0500h, LAN_PM_ENABLED
		dw	05FFh, LAN_PM_ENABLED
		dw	0600h, PCMCIA_PM_ENABLED
		dw	06FFh, PCMCIA_PM_ENABLED

APM_Device_Tbl_End	Label	Near
;R24 - ends

;[]==================================================================[]
;Procedure:	APM_FUNC0E
;
;Function :	APM Driver Version
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Eh
;		BX = 0000h : APM BIOS
;		CH = APM Driver major version number (in BCD format)
;		CL = APM Driver minor version number (in BCD format)
;
;Output   :	CF - Error
;		     AH = 03h	Interface not connected
;			  09h	Unrecognized device ID
;			  0Bh	Interface not engaged
;		NC - Success
;		     AH = APM Connection major version number (in BCD format)
;		     AL = APM Connection minor version number (in BCD format)
;
;[]==================================================================[]
APM_FUNC0E	Proc	Near

		push	dx
		mov	dl, [EXTEND_APM_STATUS]
		and	dl, not (APM11_INSTALLED+APM12_INSTALLED)
		call	Do_Func0E
		jc	short @F
		mov	[EXTEND_APM_STATUS], dl
	@@:
		pop	dx
		ret

;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
		Public	Do_Func0E
Do_Func0E	Label	Near		;R23 
;R23 Do_Func0E:

	;check APM driver version = 1.1?

		cmp	ch,01h
		jne	short @F

		mov	dh, APM11_INSTALLED
		cmp	cl,01h
ifndef	NO_SUPPORT_APM12
		je	short _0E_Accecpted

		mov	dh, APM12_INSTALLED
		cmp	cl,02h
endif	;NO_SUPPORT_APM12

	@@:
		stc
		jne	short afe_bad		;no, return error!

	_0E_Accecpted:

		or	dl, dh

		mov	ah,ch			;APM BIOS version in AX
		mov	al,cl
		clc
afe_bad:
		ret

APM_FUNC0E	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0F
;
;Function :	Engage/Disengage Power Management
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Fh
;		BX = Power device ID
;		     0001h : All devices power managed by the APM BIOS
;		     01XXh : Display
;		     02XXh : Secondary Storage
;		     03XXh : Parallel Ports
;		     04XXh : Serial Ports
;		     05XXh : Network Adapters
;		     06XXh : PCMCIA Sockets
;		     E000h - EFFFh OEM-defined Power Device IDs
;		     All other values reserved
;
;		     where:
;
;		     XX h = Unit Number (0 based)
;		     Unit Number of FFh means all devices in this class.
;		CX = Function code
;		     0000h = Disengage power management
;		     0001h = Engage power management
;
;Output   :	CF - Error
;		     AH = 01h	Power management functionality disabled
;			  03h	Interface not connected
;			  09h	Unrecognized device ID
;			  0Ah	Parameter value out of range(function code)
;		NC - Success
;[]==================================================================[]
APM_FUNC0F	Proc	Near

;R24 - starts
		call	Decode_APM_Devices
		jc	aff_Exit

		cmp	bx, ALL_DEVICES	  
		jne	aff_good
;R24 - ends
		call	Check_PM_Allowed
		jc	short aff_Exit

		and	[EXTEND_APM_STATUS],not IS_PM_ENGAGED
		or	cx,cx			;disable request?
		jz	short aff_good		;yes
		or	[EXTEND_APM_STATUS],IS_PM_ENGAGED
		call	Clear_Events
aff_good:
		clc
aff_Exit:
		ret

APM_FUNC0F	Endp

Check_PM_Allowed:
		test	[EXTEND_APM_STATUS], PM_ALLOWED_BY_APM
		clc
		jnz	short @F
		stc
		mov	ah,ERROR_PM_DISABLED
	@@:
		ret

ifndef	NO_SUPPORT_APM12

;R11 - start
PM_CAP	=	STANDBY_CAP+SUSPEND_CAP+STANDBY_RING_CAP+SUSPEND_RING_CAP+\
			    STANDBY_RESUME_TIMER_CAP+SUSPEND_RESUME_TIMER_CAP

ifdef	Notebook_Power_Management
PM_CAP	= PM_CAP+STANDBY_PCMCIA_RING_CAP+SUSPEND_PCMCIA_RING_CAP
endif;	Notebook_Power_Management
;R11 - end

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC10
APM_FUNC10	Proc	Near

ifdef	BATTERY_SYSTEM				;R15
		mov	bl,MAX_BATTERY_UNIT	;R15
else	;BATTERY_SYSTEM				;R15
		xor	bl, bl					;no battery
endif	;BATTERY_SYSTEM				;R15


;R11		mov	cx, STANDBY_CAP+SUSPEND_CAP+\
;R11			    STANDBY_RING_CAP+SUSPEND_RING_CAP+\
;R11			    STANDBY_PCMCIA_RING_CAP+SUSPEND_PCMCIA_RING_CAP+\
;R11			    STANDBY_RESUME_TIMER_CAP+SUSPEND_RESUME_TIMER_CAP
		mov	cx,PM_CAP				;R11
		cmp	word ptr [APM_MODEM_IRQ], 0
		jne	short @F
		and	cl, not (STANDBY_RING_CAP+\
				 SUSPEND_RING_CAP+\
			         STANDBY_PCMCIA_RING_CAP+\
				 SUSPEND_PCMCIA_RING_CAP)
	@@:
		mov	[APM12_CAPABILTY], cl

		call	Ct_APM_Func10

		ret

APM_FUNC10	endp

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC11
APM_FUNC11	Proc	Near

		cmp	cl, 2
		jbe	short @F

	Func11_Bad_Para:

		mov	ah, ERROR_BAD_PARAM
		stc
		ret
	@@:

	;------ Try to disable Resume Timer ------------

		or	cl, cl
		jz	short F11_SW_SMI

	;------ Trying to set Resume Timer -------------

		cmp	cl, 2
		jne	short Not_Set_Resume_Timer

		push	cx
		xor	cl, cl
		call	Check_Func11_Para_Range
		pop	cx
		jc	short Func11_Bad_Para

		mov	byte ptr [RESUME_SECOND], ch
		mov	word ptr [RESUME_MINUTE], dx
		mov	word ptr [RESUME_DAY], si
		mov	word ptr [RESUME_YEAR], di

	F11_SW_SMI:

		pushad

		;-------
		and	[EXTEND_APM_STATUS], not RESUME_TIMER_ENABLED
		or	cl, cl
		jz	short @F
		or	[EXTEND_APM_STATUS], RESUME_TIMER_ENABLED
	@@:
		;-------
		or	cl, cl
		mov	cl, DISABLE_RESUME_TIMER_REQ
		jz	short @F
		mov	cl, ENABLE_RESUME_TIMER_REQ
	@@:
		mov	[Software_SMI_Type], cl
		call	Issue_SW_SMI
		mov	[Software_SMI_Type], 0
		;-------

		popad

		clc
		ret

	Not_Set_Resume_Timer:

	;----- Try to get Resume Timer------------------

		test	[EXTEND_APM_STATUS], RESUME_TIMER_ENABLED
		jnz	short @F
		mov	ah, ERROR_RESUME_TIMER_OFF
		stc
		ret
	@@:
		mov	ch, byte ptr [RESUME_SECOND]
		mov	dx, word ptr [RESUME_MINUTE]
		mov	si, word ptr [RESUME_DAY]
		mov	di, word ptr [RESUME_YEAR]
		clc
		ret

APM_FUNC11	endp

;[]------------------------------------------------------------------------[]
;input	:	CL = 1 : call from 32 bit protected mode
;		     0 : call from real mode or 16 bit protected mode
;output	:	CF : input time out of range
;[]------------------------------------------------------------------------[]
		Public	Check_Func11_Para_Range
Check_Func11_Para_Range	Proc	Near

;-------------------------------------------------------------------
; Code for 16 bit/real mode	;equivalent to 32 bit protected mode
;-------------------------------------------------------------------

   pusha			;	pushad
				;
;bp=0: indicates no error	;;bp=0: indicates no error
   				;
   xor	bp, bp			;	xor	ebp, ebp
   				;
;****				;;****
;if year < 1995 then error	;;if year < 1995 then error
   mov	ax, di			;	mov	eax, edi
   cmp	ah, 19h			;	cmp	ah, 19h
   jne	short @F		;	jne	short @F
   cmp	al, 95h			;	cmp	al, 95h
   jae	short @F		;	jae	short @F
   inc	bp	;error		;	inc	ebp	;error
@@:				;@@:
;****				;;****
				;
;push input resume timer	;;push input resume timer
;settings into stack for	;;settings into stack for
;later checking			;;later checking
   				;
   ror	cx, 8			;	ror	ecx, 8
   push	cx	;second		;	push	ecx		;second
   rol	cx, 8			;	rol	ecx, 8
   push	dx	;minute		;	push	edx		;minute
   shr	dx, 8			;	shr	edx, 8
   push	dx	;hour		;	push	edx		;hour
   push	si	;day		;	push	esi		;day
   shr	si, 8			;	shr	esi, 8
   push	si	;month		;	push	esi		;month
   push	di	;year		;	push	edi		;year
   shr	di, 8			;	shr	edi, 8
   push	di	;century	;	push	edi		;century
   				;
;~~~~~~~~~~~~~~~~~~~		;;~~~~~~~~~~~~~~~~~~~
   or	cl, cl			;	or	cl, cl
   jz	short _16_		;	jz	short _16_
_32_:				;_32_:
   mov	si,offset TimeRangeTbl	;	mov	esi, offset TimeRangeTbl	;mov esi, offset 
   dw	0			;
   mov di,offset EndTimeRangeTbl;	mov	edi, offset EndTimeRangeTbl
   dw	0			;
   jmp	short _JJJJ		;	jmp	short _JJJJ
_16_:				;_16_:
   mov	si,offset TimeRangeTbl	;	--------
   mov di,offset EndTimeRangeTbl;	--------
_JJJJ:				;_JJJJ:
;~~~~~~~~~~~~~~~~~~~		;;~~~~~~~~~~~~~~~~~~~
				;
Chk_Next_Range:			;Chk_Next_Range:
				;
   pop	ax	;retrieve	;	pop	eax	;retrieve
		;input settings	;			;input settings
;-------------------------------;;--------------------------------------------------
   push	dx			;	push	edx
				;
;////////////////////////////	;;////////////////////////////
;retrieve low/high limit into 	;;retrieve low/high limit into 
;DL/DH correspondingly		;;DL/DH correspondingly
				;
   or	cl, cl			;	or	cl, cl
   jz	short _16		;	jz	short _16
_32:				;_32:
   db	2eh,66h,8bh,16h		;	mov	dx, cs:[esi]
   jmp	short _KKK		;	jmp	short _KKK
_16:				;_16:
   mov	dx, cs:[si]		;	db	2Eh, 8bh, 14h
_KKK:				;_KKK:
				;
;////////////////////////////	;;////////////////////////////
				;
   cmp	al, dl	;low limit	;	cmp	al, dl		;low limit
   jae	short @F		;	jae	short @F
   inc	bp			;	inc	ebp
@@:				;@@:
   cmp	al, dh	;high limit	;	cmp	al, dh		;high limit
   jbe	short @F		;	jbe	short @F
   inc	bp			;	inc	ebp
@@:				;@@:
   and	al, 0Fh	;BCD check	;	and	al, 0Fh		;BCD check
   cmp	al, 09h			;	cmp	al, 09h
   jbe	short @F		;	jbe	short @F
   inc	bp			;	inc	ebp
@@:				;@@:
   pop	dx			;	pop	edx
				;
;-------------------------------;;--------------------------------------------------
				;
   inc	si			;	inc	esi
   inc	si			;	inc	esi
   cmp	si, di			;	cmp	esi, edi
   jb	short Chk_Next_Range	;	jb	short Chk_Next_Range
				;
   clc				;	clc
   or	bp, bp			;	or	ebp, ebp
   jz	short @F		;	jz	short @F
   stc				;	stc
@@:				;@@:
   popa				;	popad
				;
   ret				;	ret

Check_Func11_Para_Range	Endp

TimeRangeTbl:
		db	19h, 20h		;century
		db	0  , 99h		;year
		db	1  , 12h		;month
		db	1  , 31h		;day
		db	0  , 23h		;hour
		db	0  , 59h		;minute
		db	0  , 59h		;second

EndTimeRangeTbl:

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC12
APM_FUNC12	Proc	Near

		test	byte ptr [APM12_CAPABILTY],STANDBY_RING_CAP+\
						   SUSPEND_RING_CAP+\
						   STANDBY_PCMCIA_RING_CAP+\
						   SUSPEND_PCMCIA_RING_CAP
		jnz	short APM_FUNC12_SUPPORTED
		stc
		mov	ah, ERROR_FUNCTION_NOT_SUPPORT
		ret

	APM_FUNC12_SUPPORTED:

		push	dx
		push	bx

		mov	dh, RING_WAKEUP_ENABLED
		mov	bl, DISABLE_RESUME_RING
		mov	bh, ENABLE_RESUME_RING
		jmp	short _FFFFF

APM_FUNC12	endp

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC13
APM_FUNC13	Proc	Near

		push	dx
		push	bx

		mov	dh, PMU_TIMER_ENABLED
		mov	bl, DISABLE_TIMER_REQ
		mov	bh, ENABLE_TIMER_REQ

		Public	_FFFFF			;R23 
_FFFFF	Label	Near				;R23 
;R23 	_FFFFF:
		mov	dl, [EXTEND_APM_STATUS]
		call	Do_Func12_13
		jc	short APM_FUNC13_Exit
		mov	[EXTEND_APM_STATUS], dl

		cmp	dh, 2
		je	short APM_FUNC13_Exit

		pushad
		or	dh, dh
		jz	short @F
		xchg	bl, bh
	@@:
		mov	byte ptr [Software_SMI_Type], bl
		call	Issue_SW_SMI
		mov	byte ptr [Software_SMI_Type], 0
		popad
		clc

	APM_FUNC13_Exit:

		pop	bx
		pop	dx
		ret

APM_FUNC13	endp

;[]========================================================================[]
;Input	:	DL = PM_RAM:[EXTEND_APM_STATUS]
;		DH = bit to test/update
;		CL = parameters from APM driver
;
;Output	:	CF : function failed
;		NC : DH = Input CL
;		     DL = for updating PM_RAM:[EXTEND_APM_STATUS]
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Do_Func12_13
Do_Func12_13	Proc	Near

		or	ch, ch
		jnz	short F12_F13_Out_Of_Range

		cmp	cl, 2
		ja	short F12_F13_Out_Of_Range
		je	short Return_Status

		or	dl, dh			;assume set enabled !
		or	cl, cl			;request = enabled ?
		jnz	short @F		;yes !
		xor	dl, dh			;set flag for disabled !
	@@:
		mov	dh, cl			;input CL --> DH
		clc
		ret

	;return the enable/disable status

	Return_Status:

	;-------------------------------------------------------------------
	;the following 3 lines are equivalent to "test dl, dh". Since this
	;code is shared with APM32.ASM, & this "test dl, dh" will be
	;interpreted as "test dh, dl" when CPU is in 32 bit protected mode,
	;I use the following 3 lines to
	;-------------------------------------------------------------------
							;32 bit proteced mode
							;--------------------
		push	dx				;push edx
		and	dl, dh	;current enabled ?	;and  dl, dh
		pop	dx				;pop  edx

	;-----------------------------

		mov	dh, cl			;input CL --> DH
		mov	cl, 1			;assume enabled !
		jnz	short F12_F13_Success	;is enabled !
		xor	cl, cl			;return CL=0 i.e. disabled !

	F12_F13_Success:

		clc
		ret

	F12_F13_Out_Of_Range:

		mov	ah, ERROR_BAD_PARAM

		stc
		ret

Do_Func12_13	Endp
endif	;NO_SUPPORT_APM12

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_NOT_CONNECTED
;			  i.e. real mode function not connected
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_Not_Connected
Chk_Not_Connected	Proc	Near
		test	dl,IS_CONNECT_CALL_MADE		;[APM_STATUS]
		clc
		jnz	short @F
		mov	ah,ERROR_NOT_CONNECTED		;real mode APM not conn.
		stc
	@@:
		ret
Chk_Not_Connected	Endp

;[]========================================================================[]
;input	:	BX = input from APM driver
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : ah = ERROR_UNKNOWN_DEVICE_ID
;			  i.e. BX not EQUAL to BIOS_DEVICE_ID(0000h)
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_BIOS_Device
Chk_BIOS_Device	Proc	Near

		cmp	bh,BIOS_DEVICE_ID SHR 8
		jne	short Chk_BIOS_Device_Bad

		cmp	bl,BIOS_DEVICE_ID AND 0FFh
		clc
		je	short Chk_BIOS_Device_Ret

Chk_BIOS_Device_Bad:

		mov	ah,ERROR_UNKNOWN_DEVICE_ID
		stc

Chk_BIOS_Device_Ret:

		ret
Chk_BIOS_Device	Endp

;[]========================================================================[]
;input	:	BX = input from APM driver
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	NC : BX = APM10_ALL_DEVICES (FFFFh) or
;		     BX = ALL_DEVICES (0001h)
;		CY : AH = ERROR_UNKNOWN_DEVICE_ID
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_APM10_All_Devices
Chk_APM10_All_Devices	Proc	Near
		cmp	bh,APM10_ALL_DEVICES SHR 8
		jne	short Chk_All_Devices
		cmp	bl,APM10_ALL_DEVICES AND 0FFh
		je	short All_Devices_OK
Chk_APM10_All_Devices	Endp

;[]========================================================================[]
;input	:	BX = input from APM driver
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	NC : BX = ALL_DEVICES (0001h)
;		CY : AH = ERROR_UNKNOWN_DEVICE_ID
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_All_Devices
Chk_All_Devices	Proc	Near

;R08A - start
ifdef	BATTERY_SYSTEM	
		cmp	al,0Ah
		jne	short Not_Chk_Battery_ID

		cmp	bh,BATTERY_DEVICES SHR 8
		jne	short Not_Chk_Battery_ID
		
		cmp	bl,MAX_BATTERY_UNIT
		ja	short Chk_All_Device_Bad

		clc
		jmp	short All_Devices_OK
Not_Chk_Battery_ID:
endif	;BATTERY_SYSTEM	
;R08A - end
		cmp	bh,ALL_DEVICES SHR 8
		jne	short Chk_All_Device_Bad
		cmp	bl,ALL_DEVICES AND 0FFh
		je	short All_Devices_OK

Chk_All_Device_Bad:

		mov	ah,ERROR_UNKNOWN_DEVICE_ID
		stc
		Public	All_Devices_OK	;R23 
All_Devices_OK	Label	Near		;R23 
;R23 All_Devices_OK:
		ret

Chk_All_Devices	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_PM_DISABLED
;			  i.e. PM functionality is disabled
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_PM_Disabled
Chk_PM_Disabled	Proc	Near

		test	dl,IS_PM_ENABLED
		clc
		jnz	short @F

		mov	ah,ERROR_PM_DISABLED
		stc
	@@:
		ret

Chk_PM_Disabled	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_PM_NOT_ENGAGED
;			  i.e. PM is disengaged
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_PM_Engaged
Chk_PM_Engaged	Proc	Near
		test	dh,IS_PM_ENGAGED		;[EXTEND_APM_STATUS]
		clc
		jnz	short @F
		mov	ah,ERROR_PM_NOT_ENGAGED
		stc
	@@:
		ret
Chk_PM_Engaged	Endp

;[]========================================================================[]
;Input	:	CX
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : ah = ERROR_BAD_PARAM
;			  i.e. CX > 1
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_Param_Range_01
Chk_Param_Range_01	Proc	Near

		or	ch,ch
		jne	short Chk_Param_Range_01_Bad
		cmp	cl,0				;must use cmp to clc
		je	short Chk_Param_Range_01_Ret	;input parameter valid
		cmp	cl,1				;maximum function = 1
		je	short Chk_Param_Range_01_Ret	;input parameter valid

Chk_Param_Range_01_Bad:

		mov	ah,ERROR_BAD_PARAM		;return error code
		stc

Chk_Param_Range_01_Ret:

		ret

Chk_Param_Range_01	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_PM_NOT_ENGAGED
;			  i.e. PM is disengaged
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
Chk_APM_Presence	Proc	Near

		clc

ifndef	NO_SUPPORT_APM12
		test	dl, IS_APM_SUPPORTED
		jnz	short @F
		stc
		mov	ah, ERROR_APM_NOT_PRESENT
	@@:
endif	;NO_SUPPORT_APM12

		ret

Chk_APM_Presence	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	clear [APMEventSave] to NO_EVENTS
;		      [APM_EVENT_POST] to 0
;[]========================================================================[]
		public	Clear_Events			;R02
Clear_Events	Proc	Near
		mov	[APMEventSave],NO_EVENTS
		mov	[APM_EVENT_POST],0
		ret
Clear_Events	Endp

;[]========================================================================[]
;Input	:	DS = PM_RAM
;output	:	CY : PM is not control by APM
;		NC : APM BIOS (PMU.ASM) must wait for
;		     APM's prompt before entering any PM modes
;[]========================================================================[]
		Public	Chk_Control_By_APM
Chk_Control_By_APM	Proc	Near

		test	[APM_STATUS],IS_CONNECT_CALL_MADE
		jz	short No_APM_Control
		test	[EXTEND_APM_STATUS],IS_CONNECT_CALL_MADE
		jz	short No_APM_Control

		stc
		ret

	No_APM_Control:

		clc
		ret

Chk_Control_By_APM	Endp

endif	;ADVANCE_POWER_MANAGEMENT

;R26 - starts
Prg_HDD_Timer	Proc	Near
		push	ax
		mov	al, cl
		call	Set_HDD_Standby_Timer
		pop	ax
		ret
Prg_HDD_Timer	Endp

;[]------------------------------------------[]
;Function :	Set the IDE HDD Standby Timer
;
;Input    :	AL = 0  - disable HDD timer
;		  ELSE  - enable HDD timer according
;			  to [APM_HDD_TIMER_VALUE]
;
;Output   :	None
;
;Destroy  :	FLAGS
;[]------------------------------------------[]
		Public	APM_HDD_EXIST_Flag
		Public	APM_HDD_Drive_Port
		Public	APM_HDD_TIMER_VALUE
APM_HDD_EXIST_Flag	db	0
APM_HDD_Drive_Port	db	0
APM_HDD_TIMER_VALUE	db	0

		Public	fPROC_Set_HDD_Standby_Timer
fPROC_Set_HDD_Standby_Timer	Proc	Far
		call	Set_HDD_Standby_Timer
		ret
fPROC_Set_HDD_Standby_Timer	Endp
Set_HDD_Standby_Timer	Proc	Near

		pusha
		push	ds

		or	al, al
		jz	@F
		mov	al, cs:[APM_HDD_TIMER_VALUE]
	@@:
		xor	bl, bl

		mov	cl, 12			;1 unit is 5 second
		mul	cl			;one minute is 12 units
		mov	ch, al

	Set_4_IDE_Loop:

		cmp	cs:[APM_HDD_EXIST_Flag],bl	;Drive number available?
		jbe	No_Else_HDD		;No,skip
		mov	dx, 1F2h		;sector count register
		mov	cl, bl			;get drive number
		shl	cl, 1			;*2

		mov	bh, cs:[APM_HDD_Drive_Port]	;get drive scheme
		shr	bh, cl			;shift to correspond bits
		test	bh, 2			;Is primary channel?
		jz	@F			;Yes,jump
		sub	dl, 80h			;set to secondary channel
	@@:
		out	dx, al			;set the seconds time
		iodelay

		add	dl, 4			;1X6h
		mov	al, 0a0h		;assume master
		test	bh, 1			;Is master drive?
		jz	@F			;Yes,jump
		mov	al, 0b0h		;set slave drive
	@@:
		out	dx, al			;out to port
		iodelay
		inc	dl			;1X7h

		call	Wait_Ctrl_Idle		;wait controller idel

		mov	al, 0e3h		;set feature command
		out	dx, al			;send to drive
		iodelay

		call	Wait_Ctrl_Idle

		in	al, dx			;get drive status
		iodelay

		inc	bl			;next drive

		mov	al, ch			;get timer value
		jmp	Set_4_IDE_Loop
No_Else_HDD:
		pop	ds
		popa
		ret

;--------------------------
Wait_Ctrl_Idle:
		push	cx
		xor	cx, cx
	@@:
		in	al, dx
		newiodelay
		test	al, 80h
		jz	@F
		loop	@B
	@@:
		pop	cx
		ret
;--------------------------

Set_HDD_Standby_Timer	EndP
;R26 - ends

ifndef	CRT_Control_Not_In_APM				;R01
		include	CRT_Ctrl.inc			;R01
endif	;CRT_Control_Not_In_APM				;R01

;R01 ifdef	PM_SUPPORT
;R01 ifndef	No_CRT_Control
;R01 
;R01 ;[]===============================================================[]
;R01 ;Procedure:	Enable_CRT
;R01 ;
;R01 ;Function :	Routine to enable CRT display signal output
;R01 ;
;R01 ;Registers:	DX, AX - destroyed
;R01 ;
;R01 ;Input    :	DS = PM_RAM
;R01 ;
;R01 ;Output   :	None
;R01 ;
;R01 ;[Note]	  :	This is a public routine which the users(PMI Handler)
;R01 ;		can called during any PM mode
;R01 ;[]==================================================================[]
;R01 		ASSUME	DS:PM_RAM
;R01 		Public	Enable_CRT
;R01 Enable_CRT	Proc	Near
;R01 
;R01 ifdef	LCD_CRT_OPTION
;R01 ifdef	CHIP_655XX
;R01 	CRT_OUTPUT	EQU	00h
;R01 endif	;CHIP_655XX
;R01 ifdef	CL_GD754X
;R01 	CRT_OUTPUT	EQU	01h
;R01 endif	;CL_GD754X
;R01 		cmp	byte ptr ds:Display_Mode,CRT_OUTPUT
;R01 		je	short No_LCD_Exist
;R01 
;R01 		Call	Enable_LCD
;R01 No_LCD_Exist:
;R01 endif	;LCD_CRT_OPTION
;R01 
;R01 ifdef	VGA_Chip_Control
;R01 		xor	al,al
;R01 		Call	Ct_VGA_Control
;R01 endif	;VGA_Chip_Control
;R01 
;R01 ifdef	Notebook_Power_Management
;R01 		Call	LCD_BACKLIGHT_ON
;R01 endif	;Notebook_Power_Management
;R01 
;R01 ifndef	None_DPMS_STANDARD
;R01 		cmp	dword ptr DPMS_LABEL,'DPMS'	; Is DPMS support ?
;R01 		jne	short @F
;R01 		mov	bh,0
;R01 		call	DPMS_Function
;R01 		jmp	short End_Enable_CRT
;R01 	@@:
;R01 endif	;None_DPMS_STANDARD
;R01 
;R01 		call	Decide_3D4_Or_3B4
;R01 
;R01 		mov	bl,80h			;Enable V/H SYNC signals
;R01 		call	Prg_VH_SYN		;  of the VGA card
;R01 
;R01 		xor	bl,bl			;enable screen
;R01 		call	En_Dis_Screen
;R01 
;R01 End_Enable_CRT:
;R01 		ret
;R01 
;R01 Enable_CRT	Endp
;R01 
;R01 ifdef	LCD_CRT_OPTION
;R01 		Public	Enable_LCD
;R01 Enable_LCD	Proc	Near
;R01 
;R01 ifdef	CHIP_655XX
;R01 		mov	ax,5f51h
;R01 		mov	bl,0
;R01 		Call	Video_Func
;R01 
;R01 		mov	ax,5f54h
;R01 		mov	bl,0
;R01 		Call	Video_Func
;R01 
;R01 		mov	ax,5f51h
;R01 		mov	bl,ds:Display_Mode
;R01 		Call	Video_Func
;R01 endif	;CHIP_655XX
;R01 
;R01 ifdef	CL_GD754X
;R01 		mov	cl,20h
;R01 		Call	Get_Cr_reg
;R01 		and	al,11101111b		;Disable Activate Standby mode
;R01 		Call	Set_Cr_reg
;R01 endif	;CL_GD754X
;R01 		ret
;R01 Enable_LCD	Endp
;R01 
;R01 		Public	Disable_LCD
;R01 Disable_LCD	Proc	Near
;R01 
;R01 ifdef	CHIP_655XX
;R01 		mov	ax,5f54h
;R01 		mov	bl,1
;R01 		Call	Video_Func
;R01 endif	;CHIP_655XX
;R01 ifdef	CL_GD754X
;R01 		mov	cl,20h
;R01 		Call	Get_Cr_reg
;R01 		or	al,00010000b		;Enable Activate Standby mode
;R01 		Call	Set_Cr_reg
;R01 endif	;CL_GD754X
;R01 		ret
;R01 Disable_LCD	Endp
;R01 
;R01 endif	;LCD_CRT_OPTION
;R01 
;R01 ;[]==================----============================================[]
;R01 ;Procedure:	Disable_CRT
;R01 ;
;R01 ;Function :	Routine to disable CRT display signal output
;R01 ;
;R01 ;Registers:	DX, AX - destroyed
;R01 ;
;R01 ;Input    :	DS = PM_RAM
;R01 ;
;R01 ;	ifdef	DPMS_STANDARD
;R01 ;		PM_RAM:DPMS_Request_State = 0 DPMS ON
;R01 ;					  = 1 DPMS STANDBY
;R01 ;					  = 2 DPMS SUSPEND
;R01 ;					  = 4 DPMS OFF
;R01 ;					  = 8 DPMS REDUCE ON
;R01 ;	endif	;DPMS_STANDARD
;R01 ;
;R01 ;Output   :	None
;R01 ;
;R01 ;[Note]	  :	This is a public routine which the users(PMI Handler)
;R01 ;		can called during any PM mode
;R01 ;[]==================================================================[]
;R01 		Public	Disable_CRT
;R01 Disable_CRT	Proc	Near
;R01 
;R01 ifdef	LCD_CRT_OPTION
;R01 		cmp	byte ptr ds:Display_Mode,CRT_OUTPUT
;R01 		je	short No_LCD
;R01 
;R01 		Call	Disable_LCD
;R01 NO_LCD:
;R01 endif	;LCD_CRT_OPTION
;R01 
;R01 ifdef	VGA_Chip_Control
;R01 		mov	al,1
;R01 		Call	Ct_VGA_Control
;R01 endif	;VGA_Chip_Control
;R01 
;R01 ifdef	Notebook_Power_Management
;R01 		Call	LCD_BACKLIGHT_OFF
;R01 endif	;Notebook_Power_Management
;R01 
;R01 ifndef	None_DPMS_STANDARD
;R01 		cmp	dword ptr DPMS_LABEL,'DPMS'	; Is DPMS support ?
;R01 		jne	short @F
;R01 		mov	bh,PM_RAM:DPMS_Request_State	; BH = request state
;R01 		test	PM_RAM:DPMS_Capability,bh	; Is request match ?
;R01 		jz	short @F			; NO , skip ...
;R01 		call	DPMS_Function
;R01 		jmp	short End_Disable_CRT
;R01 	@@:
;R01 endif	;None_DPMS_STANDARD
;R01 
;R01 		call	Decide_3D4_Or_3B4
;R01 
;R01 		mov	bl,20h			;Disable screen
;R01 		call	En_Dis_Screen
;R01 
;R01 		xor	bl,bl			;Disable V/H SYNC signals
;R01 		call	Prg_VH_SYN		;  of the VGA card
;R01 
;R01 End_Disable_CRT:
;R01 		ret
;R01 
;R01 Disable_CRT	Endp
;R01 
;R01 ;-------------------------------------------
;R01 ;-------------------------------------------
;R01 Decide_3D4_Or_3B4	Proc	Near
;R01 		mov	dx,3cch
;R01 		in	al,dx
;R01 		mov	dx,3d4h
;R01 		test	al,1
;R01 		jnz	short @F
;R01 		mov	dx,3b4h
;R01 	@@:
;R01 		ret
;R01 Decide_3D4_Or_3B4	Endp
;R01 
;R01 ;-------------------------------------------
;R01 ;Input	:	BL = 80h : enable VH SYN
;R01 ;		     00h : disable VH SYN
;R01 ;-------------------------------------------
;R01 Prg_VH_SYN	Proc	Near
;R01 
;R01 		push	dx
;R01 		test	byte ptr PM_RAM:[PM_CTRL_FLAG],V_H_SYNC_ENABLE
;R01 		jz	short @F
;R01 
;R01 		mov	al,17h
;R01 		out	dx,al
;R01 		IODELAY
;R01 		inc	dx
;R01 		in	al,dx
;R01 		IODELAY
;R01 		and	al,7Fh
;R01 		or	al,bl
;R01 		out	dx,al
;R01 		IODELAY
;R01 @@:
;R01 		pop	dx
;R01 		ret
;R01 
;R01 Prg_VH_SYN	Endp
;R01 
;R01 ;-------------------------------------------
;R01 ;Input	:	BL = 00h : enable screen
;R01 ;		     20h : disable screen
;R01 ;-------------------------------------------
;R01 ATTREG		EQU    3C0H
;R01 SEQ_INDEX	EQU    3C4H
;R01 En_Dis_Screen	Proc	Near
;R01 		push	dx
;R01 
;R01 		add     dx,06h
;R01                 in      al,dx
;R01 		IODELAY
;R01 
;R01                 mov     dx,ATTREG
;R01 		in	al,dx
;R01 		IODELAY
;R01 		mov	al,bl
;R01 		xor	al,20h
;R01                 out     dx,al
;R01 		IODELAY
;R01 
;R01                 mov     dx,SEQ_INDEX
;R01 		in	al,dx
;R01 		IODELAY
;R01 
;R01 		push	ax		;Save SEQ index value
;R01 
;R01                 mov     al,01h
;R01                 out     dx,al
;R01 		IODELAY
;R01                 inc     dx
;R01                 in      al,dx
;R01 		IODELAY
;R01                 and     al,not 20h
;R01 		or	al,bl
;R01                 out     dx,al
;R01 		IODELAY
;R01 
;R01 		pop	ax		;Restore SEQ index value
;R01 		dec	dx
;R01 		out	dx,al
;R01 		IODELAY
;R01 
;R01 		pop	dx
;R01 		ret
;R01 
;R01 En_Dis_Screen	Endp
;R01 
;R01 ifndef	None_DPMS_STANDARD
;R01 ;-----------------------------------------------------------------
;R01 ;Input	:	BH = 0	DPMS_ON
;R01 ;		   = 1	DPMS_STANDBY
;R01 ;		   = 2	DPMS_SUSPEND
;R01 ;		   = 4	DPMS_OFF
;R01 ;		   = 8	DPMS_REDUCE_ON
;R01 ;------------------------------------------------------------------
;R01 DPMS_Function	proc	near
;R01 		pushad
;R01 		push	es
;R01 
;R01 		in	al,21h
;R01 		IODELAY
;R01 		push	ax		; Save IRQ mask
;R01 		in	al,0a1h
;R01 		IODELAY
;R01 		push	ax		; Save IRQ mask
;R01 		mov	al,0ffh		; mask all of IRQ
;R01 		out	21h,al
;R01 		out	0a1h,al
;R01 
;R01 		mov     dx,03c4h
;R01 		in	al,dx
;R01 		push	dx
;R01 		push	ax		; Save sequence register index
;R01 ifndef	DPMS_No_Save_Int10_Vector
;R01 		mov	ax,G_RAM
;R01 		mov	es,ax
;R01 		mov	eax,es:INT10
;R01 		push	eax		; Save current INT10 vector
;R01 		push	es
;R01 		mov	eax,PM_RAM:INT10_Save
;R01 		mov	dword ptr es:INT10,eax	; Set to original INT10 vector
;R01 endif	;DPMS_No_Save_Int10_Vector
;R01 
;R01 		mov	ax,4f10h	; VESA Extentsion & VBE/PM Service
;R01 		mov	bl,01h		; Set display power state
;R01 		xor	cx,cx		; Controller unit number (cx=00 primary)
;R01 		mov	es,cx		; ES:DI = 0000:0000
;R01 		xor	di,di
;R01 		mov	si,offset PM_RAM:Int10_Save
;R01 		pushf
;R01 		call	dword ptr PM_RAM:[si]
;R01 
;R01 ifndef	DPMS_No_Save_Int10_Vector
;R01 		pop	es
;R01 		pop	eax
;R01 		mov	dword PTR es:INT10,eax	; Restore current INT10 vector
;R01 endif	;DPMS_No_Save_Int10_Vector
;R01 
;R01 		pop	ax
;R01 		pop	dx
;R01 		out	dx,al		; Restore sequence register index
;R01 
;R01 		pop	ax
;R01 		out	0a1h,al		; Restore IRQ mask
;R01 		pop	ax
;R01 		out	21h,al		; Restore IRQ mask
;R01 
;R01 		pop	es
;R01 		popad
;R01 
;R01 		ret
;R01 DPMS_Function	endp
;R01 endif	;None_DPMS_STANDARD
;R01 
;R01 ifdef	LCD_CRT_OPTION
;R01 ifdef	CL_GD754X
;R01 CR_Index	EQU	3D4h
;R01 CR_Data		EQU	3D5h
;R01 
;R01 		Public	Get_Cr_reg
;R01 Get_Cr_reg	Proc	Near
;R01 
;R01 		mov	al,cl
;R01 		mov	dx,CR_Index
;R01 		out	dx,al
;R01 		NEWIODELAY
;R01 		mov	dx,CR_Data
;R01 		in	al,dx
;R01 		ret
;R01 
;R01 Get_Cr_reg	Endp
;R01 
;R01 		Public	Set_Cr_reg
;R01 Set_Cr_reg	Proc	Near
;R01 
;R01 		xchg	al,cl
;R01 		mov	dx,CR_Index
;R01 		out	dx,al
;R01 		NEWIODELAY
;R01 		xchg	al,cl
;R01 		mov	dx,CR_Data
;R01 		out	dx,al
;R01 		ret
;R01 
;R01 Set_Cr_reg	Endp
;R01 endif	;CL_GD754X
;R01 endif	;LCD_CRT_OPTION
;R01 
;R01 endif	;No_CRT_Control
;R01 
;R01 		Public	VIDEO_FUNC
;R01 VIDEO_FUNC	Proc	Near
;R01 
;R01 		push	ds
;R01 		push	es
;R01 
;R01 		push	eax
;R01 		call	Get_PM_RAM_Seg
;R01 		mov	ds, ax
;R01                 ASSUME  DS:PM_RAM
;R01 
;R01 		mov	ax,G_RAM
;R01 		mov	es,ax
;R01 		pop	eax
;R01 
;R01 		mov	esi,dword ptr es:INT10
;R01 		push	dword ptr PM_RAM:INT10_Save
;R01 		pop	dword ptr es:INT10		; Set to original INT10 vector
;R01 
;R01 		pop	es
;R01 		push	es
;R01 		push	esi
;R01 		mov	si,offset PM_RAM:INT10_Save
;R01 		pushf
;R01 		call	dword ptr PM_RAM:[si]
;R01 
;R01 		push	G_RAM
;R01 		pop	es
;R01 		pop	dword PTR es:INT10		; Restore current INT10 vector
;R01 
;R01 		pop	es
;R01 		pop	ds
;R01 
;R01 		ret
;R01 
;R01 VIDEO_FUNC	Endp
;R01 ENDIF	;PM_SUPPORT

FCODE		ENDS

;R20 start
else	;APM_IN_SMBASE
DGROUP		GROUP	FCODE
FCODE		SEGMENT	USE16 DWORD Public 'CODE'
		ASSUME	CS:DGROUP

;R22 ifndef	ADVANCE_POWER_MANAGEMENT
;R22 
;R22 		Public	APM_Service
;R22 APM_Service	Proc	Far
;R22 		mov	ah,ERROR_APM_NOT_PRESENT	;APM not supported!
;R22 		stc
;R22 		retf	2
;R22 APM_Service	Endp
;R22 
;R22 else	;ADVANCE_POWER_MANAGEMENT

;[]==================================================================[]
;
; Procedure Name: APM_Service
;
;	APM service routines entry point.
;
; Saves: all
;
; Input:
;	ah=53h
;       al=00h : Installation check
;	  =01h : Interface connect
;	  =02h : 16 bit protect mode connect
;	  =03h : 32 bit protect mode connect
;	  =04h : Interface disconnect
;	  =05h : CPU idle
;	  =06h : CPU busy
;	  =07h : Set power state, standby,suspend
;	  =08h : Enable/disable power management function
;	  =09h : Restore power on defaults
;	  =0ah : Get power status
;	  =0bh : Get PM event
;	bx,cx,dx dependent on the function requested
;
; Output:
;	ax,bx,cx,dx depend the function requested
;
; [Note]:
;	This is the high level dispatch routine for APM interface.
;[]==================================================================[]
		Public	APM_Service
APM_Service	Proc	Far

		ASSUME	DS:PM_RAM

		pushf
		cli
ifdef 	ACPI_Support
;Return error for all APM function calls if ACPI is enabled
		push	dx
		push	ax
		mov	dx, PM1a_CNT_BLK      	;
		in	al, dx			;Read control register
		test	al, SCI_EN		;Set SCI_EN bit 
		pop	ax
		pop	dx
		jz	short @f 		;No, then continue on
		mov	ah,ERROR_APM_NOT_PRESENT	;APM not supported!
		jmp	short APM_Fail
@@: 
endif;	ACPI_Support

		push	bp
		push	ds			;save callers ds

	;prepare PM_RAM segment

		push	ax
		call	Get_PM_RAM_Seg
		mov	ds,ax			;DS point to PM_RAM
		Assume	DS:PM_RAM
		pop	ax

	;1. open PM_RAM
	;2. invoke the corresponding function
	;3. close PM_RAM

		xor	bp,bp			;indicates real mode call
		call	Open_SMInvoke_Close

		pop	ds			;restore callers ds
		pop	bp
		jc	short APM_Fail
APM_Succ:
		popf
		clc
		retf	2
APM_Fail:
		popf
		stc
		retf	2

APM_Service	Endp

;[]--------------------------------------------------------------------------[]
;
; Procedure Name: APM_16Bit_Entry
;
;	This is the main procedure that handles the APM 16 bit call.
;
; Saves: ALL
;
; Inputs:
;	ah=53h
;	al=04h : Interface disconnect
;	  =05h : CPU idle
;	  =06h : CPU busy
;	  =07h : Set power state, standby,suspend
;	  =08h : Enable/disable power management function
;	  =09h : Restore power on defaults
;	  =0ah : Get power status
;	  =0bh : Get PM event
;	bx,cx,dx dependent on the function requested
;
; Outputs:
;	carry flag set if error
;
; [Notes]:
;	1. This procedure should be called in 16-bit mode only.
;	2. The caller should ensure the I/O privilege
;
;[]==========================================================================[]
		ALIGN	4
		public	APM_16BIT_ENTRY	;R16
APM_16BIT_ENTRY:
APM_16BIT_SERVICE	Proc	Far

		pushf
		cli

		push	bp
		push	ds

	;prepare PM_RAM segment

		mov	bp,cs
		add	bp,8				;data decsciptor is second (next after cs)
		mov	ds,bp				;for ds

	;1. open PM_RAM
	;2. invoke the corresponding function
	;3. close PM_RAM

		xor	bp,bp
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		je	short @F
		mov	bp,APM_16BIT_FUNC_MODE		;indicates 16 bit mode call
@@:							;R16
		call	Open_SMInvoke_Close

		pop	ds
		pop	bp
		jc	short APM16_Fail		;APM function not successful

	APM16_Succ:

		popf
		clc
		retf

	APM16_Fail:

		popf
		stc
		retf

APM_16BIT_SERVICE Endp

	Public	Open_SMInvoke_Close
Open_SMInvoke_Close	proc	near
		cmp	al,NO_OF_APM_CALL
		jbe	short @F

		mov	ah,ERROR_BAD_PARAM
		stc				;function out of range
		ret
	@@:
		pushad
		call	Open_PM_RAM
		popad

	;function 5,6 direct call because they issued busy
		cmp	al,05H
		je	APM_FUNC05
		cmp	al,06H
		je	APM_FUNC06
;;;;RAX		cmp	al,0BH
;;;;RAX		je	APM_FUNC0B

		mov	[APM_EAX],eax			;transfer to SMI
		mov	[APM_EBX],ebx			;transfer to SMI
		mov	[APM_ECX],ecx			;transfer to SMI
		mov	[APM_EDX],edx			;transfer to SMI
		mov	[APM_EDI],edi			;transfer to SMI
		mov	[APM_ESI],esi			;transfer to SMI
		lahf					;transfer to SMI
		mov	[APM_FLAG],ah			;transfer to SMI

		mov	[Software_SMI_Type],APM_SMI	;invoke SMI
		mov	dx,DEBUG_PORT
		in	al,dx
		push	ax
		push	dx
		call	Issue_SW_SMI
		pop	dx
		pop	ax
		out	dx,al

	; Check  2nd SMI? For follow old procedure.
		cmp	[APM_SMIFlag],Standby_Req
		jne	short _AA
		mov	[Software_SMI_Type],0
		call	APM_16_Standby
		mov	[APMEventSave],STANBY_RESUME_NOTIFY
		jmp	short _BB
	_AA:
		cmp	[APM_SMIFlag],Suspend_Req
		jne	short _BB
		mov	[Software_SMI_Type],0
		call	APM_16_Suspend
		mov	[APMEventSave],RESUME_NORMAL_NOTIFY
		jmp	short @F
	_BB:
		cmp	[APM_SMIFlag],Func07_call
		je	short NeedSMI
		cmp	[APM_SMIFlag],Func08_call
		je	short NeedSMI
		cmp	[APM_SMIFlag],Func09_call
		je	short NeedSMI
		cmp	[APM_SMIFlag],Func11_call
		je	short NeedSMI
		cmp	[APM_SMIFlag],Func13_call
		je	short NeedSMI
		jmp	short @F
	NeedSMI:
		mov	dx,DEBUG_PORT
		in	al,dx
		push	ax				;Save Post Code
		push	dx
		call	Issue_SW_SMI
		pop	dx
		pop	ax				;Restore Post Code
		out	dx,al
	@@:
		mov	[APM_SMIFlag], 0
		mov	[Software_SMI_Type],0

		mov	ah,[APM_FLAG]
		sahf
		mov	eax,[APM_EAX]			;get para returned from SMI
		mov	ebx,[APM_EBX]			;get para returned from SMI
		mov	ecx,[APM_ECX]			;get para returned from SMI
		mov	edx,[APM_EDX]			;get para returned from SMI
		mov	edi,[APM_EDI]			;get para returned from SMI
		mov	esi,[APM_ESI]			;get para returned from SMI

		pushf
		pushad
		call	Close_PM_RAM
		popad
		popf

		ret
Open_SMInvoke_Close	ENDP

;[]==================================================================[]
;Procedure:	APM_FUNC05 (CPU Idle Call)
;
;Function :	Put CPU in DOZE mode
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 05h
;
;Output   :	CF - Error
;		     AH = 03h Interface not connected
;		NC - Success
;[]==================================================================[]
APM_FUNC05	Proc	Near

	;
	;we only call Ct_APM_Func05 if:
	;	i. it is in FULL_ON mode &
	;	ii. CPU_IDLE_FLAG is set
	;
		cmp	[PM_MODE],DOZE_MODE
		je	short af5_fini
		cmp	[PM_MODE],SLEEP_MODE
		je	short af5_fini

		test	[PM_CTRL_FLAG],CPU_IDLE_FLAG
		jz	short Af5_Fini

	;chipset dependent sleep actions

		pushad
		call	Open_PM_RAM
		call	Ct_APM_Func05
		mov	[PM_MODE],DOZE_MODE
		and	[PM_CTRL_FLAG],NOT CPU_IDLE_FLAG
		call	Close_PM_RAM
		popad

af5_fini:
		clc
		ret

APM_FUNC05	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC06 (CPU Busy Call)
;
;Function :	Put CPU in Full ON mode
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 06h
;
;Output   :	CF - Error
;		     AH = 03h Interface not connected
;		NC - Success
;[]==================================================================[]
APM_FUNC06	Proc	Near

		clc
		ret

APM_FUNC06	Endp


		Public	Ct_APMSMI_Func01
Ct_APMSMI_Func01	label	far
		call	Ct_APM_Func01
		retf

		Public	Ct_APMSMI_Func04
Ct_APMSMI_Func04	label	far
		call	Ct_APM_Func04
		retf

		Public	APMSMI_16_PowerOff
APMSMI_16_PowerOff	label	far
		call	APM_16_PowerOff
		retf

		Public	Ct_SMICheck_If_LowBat
Ct_SMICheck_If_LowBat	label	far
		mov	[APM_SMIFlag], APM_SMICall
		call	Ct_Check_If_LowBat
		and	[APM_SMIFlag], not APM_SMICall	;Clear flag
		retf

		Public	Ct_APMSMI_Func10
Ct_APMSMI_Func10	label	far
		call	Ct_APM_Func10
		retf

		Public	Far_Open_PM_RAM
Far_Open_PM_RAM	PROC	FAR
		call	Open_PM_RAM
		retf
Far_Open_PM_RAM	ENDP

		Public	Far_Close_PM_RAM
Far_Close_PM_RAM	PROC	FAR
;R20A		call	Open_PM_RAM
		call	Close_PM_RAM			;R20A
		retf
Far_Close_PM_RAM	ENDP


;R22 endif	;ADVANCE_POWER_MANAGEMENT

ifndef	CRT_Control_Not_In_APM
		include	CRT_Ctrl.inc
endif	;CRT_Control_Not_In_APM

FCODE		ENDS


DGROUP		GROUP	@DATAC
@DATAC		SEGMENT	USE16 DWORD COMMON 'DATAC'
		ASSUME	CS:DGROUP
@DATAC		ENDS

XGROUP		GROUP	XCODE
XCODE		SEGMENT USE16 PARA PUBLIC 'XCODE'
		ASSUME	CS:XGROUP,ES:XGROUP
		ASSUME	DS:PM_RAM


;[]=======================================================================[]
;!!!!!! Note : APM_SMI_HANDLER routine must be head of APM_SMI_START !!!!!
;[]=======================================================================[]
		Public	APM_SMI_START
APM_SMI_START:

ifdef	ADVANCE_POWER_MANAGEMENT

		Public	APM_SMI_Handler
APM_SMI_Handler	proc	near

		cli
		push	PM_RAM_SEGMENT
		pop	ds
		assume	DS:PM_RAM

		cmp	[Software_SMI_Type], APM_SMI
		jne	short @F

		mov	ah,[APM_FLAG]
		sahf
		mov	eax,[APM_EAX]
		mov	ecx,[APM_ECX]
		mov	edx,[APM_EDX]
		mov	ebx,[APM_EBX]
		mov	edi,[APM_EDI]
		mov	esi,[APM_ESI]

 		call	Open_Invoke_Close

		mov	[APM_EAX],eax
		mov	[APM_ECX],ecx
		mov	[APM_EDX],edx
		mov	[APM_EBX],ebx
 		mov	[APM_EDI],edi
		mov	[APM_ESI],esi
		lahf
		mov	[APM_FLAG],ah

@@:
		ret
APM_SMI_Handler	ENDP

;===========================================================================
Need_Chk_BIOS_Device		EQU	00000001b
Need_Chk_All_Devices		EQU	00000010b
Need_Chk_APM10_All_Devices	EQU	00000100b
Need_Chk_Not_Connected		EQU	00001000b
Need_Chk_PM_Disabled		EQU	00010000b
Need_Chk_PM_Engaged		EQU	00100000b
Need_Chk_Param_Range_01		EQU	01000000b
Need_chk_APM_Presence		EQU	10000000b
;===========================================================================
		Public	Chk_Error_Tbl
Chk_Error_Tbl:
Reallocate	Chk_Error_Tbl_offset

	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func00h
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func01h
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func02h
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func03h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected		;func04h
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func05h
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func06h
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged+\
		Need_Chk_PM_Disabled		;func07h
	db	Need_Chk_Not_Connected+\
		Need_Chk_APM10_All_Devices+\
		Need_Chk_PM_Engaged+\
		Need_Chk_Param_Range_01		;func08h
	db	Need_Chk_Not_Connected+\
		Need_Chk_APM10_All_Devices+\
		Need_Chk_PM_Engaged		;func09h
	db	Need_Chk_All_Devices+\
		Need_chk_APM_Presence		;func0Ah
	db	Need_Chk_PM_Engaged+\
		Need_Chk_Not_Connected		;func0Bh
	db	Need_Chk_PM_Disabled+\
		Need_chk_APM_Presence		;func0Ch
;R24A 	db	Need_Chk_All_Devices+\
;R24A 		Need_Chk_Not_Connected+\
;R24A 		Need_Chk_PM_Disabled+\
;R24A 		Need_Chk_PM_Engaged+\
;R24A 		Need_Chk_Param_Range_01		;func0Dh
;R24A start
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Disabled+\
		Need_Chk_PM_Engaged+\
		Need_Chk_Param_Range_01		;func0Dh
;R24A end
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func0Eh
;R24A 	db	Need_Chk_All_Devices+\
;R24A 		Need_Chk_Not_Connected+\
;R24A 		Need_Chk_PM_Disabled+\
;R24A 		Need_Chk_Param_Range_01		;func0Fh
;R24A start
	db	Need_Chk_Not_Connected+\
		Need_Chk_PM_Disabled+\
		Need_Chk_Param_Range_01		;func0Fh
;R24A end
	db	Need_Chk_BIOS_Device+\
		Need_chk_APM_Presence		;func10h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func11h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func12h
	db	Need_Chk_BIOS_Device+\
		Need_Chk_Not_Connected+\
		Need_Chk_PM_Engaged		;func13h

;===========================================================================
;===========================================================================
		ALIGN	4
		Public	Err_Checking_Routines

Err_Checking_Routines:
Reallocate	Err_Checking_Routines_offset
;R23 		dw	Chk_BIOS_Device_offset 		+ SMI_Handler_Len
;R23 		dw	Chk_All_Devices_offset 		+ SMI_Handler_Len
;R23 		dw	Chk_APM10_All_Devices_offset 	+ SMI_Handler_Len
;R23 		dw	Chk_Not_Connected_offset 	+ SMI_Handler_Len
;R23 		dw	Chk_PM_Disabled_offset 		+ SMI_Handler_Len
;R23 		dw	Chk_PM_Engaged_offset 		+ SMI_Handler_Len
;R23 		dw	Chk_Param_Range_01_offset 	+ SMI_Handler_Len
;R23 		dw	Chk_APM_Presence_offset 	+ SMI_Handler_Len
;R23 start
;Change Routines address re-calculate to APM.INC (before move code to SMBase)
		dw	Chk_BIOS_Device_offset
		dw	Chk_All_Devices_offset
		dw	Chk_APM10_All_Devices_offset
		dw	Chk_Not_Connected_offset
		dw	Chk_PM_Disabled_offset
		dw	Chk_PM_Engaged_offset
		dw	Chk_Param_Range_01_offset
		dw	Chk_APM_Presence_offset
;R23 end
;===========================================================================
;===========================================================================
Check_Errors	Proc	Near
Reallocate	Check_Errors_offset

		push	dx
		push	si

		xor	dx,dx
		mov	dl,al
		mov	si, Chk_Error_Tbl_offset
		add	si, SMI_Handler_Len
		add	si,dx
		mov	dh,cs:[si]		;DH = patterns
		mov	dl,1			;starting from bit 0

		mov	si,Err_Checking_Routines_offset
		add	si, SMI_Handler_Len
						;routines table

	;=======================================================
	Chk_Nxt_Err:

		test	dh,dl			;this error checking needed?
		jz	short No_Chk_This	;no need to check this error!

		push	dx
		mov	dl,[APM_STATUS]
		mov	dh,[EXTEND_APM_STATUS]
		call	cs:[si]			;call the error checking routine
		pop	dx
		jc	short Chk_Ret		;error found!

	No_Chk_This:

		add	si,2			;point to next chking routine
		shl	dl,1			;test next bit
		jnc	short Chk_Nxt_Err	;all bit tested? NC means no!

	;=======================================================

		clc				;no error found!

	Chk_Ret:

		pop	si
		pop	dx
		ret

Check_Errors	Endp


;[]==========================================================================[]
;[]==========================================================================[]
Open_Invoke_Close	Proc	Near
Reallocate	Open_Invoke_Close_offset

		cmp	al,NO_OF_APM_CALL
		jbe	short @F

		mov	ah,ERROR_BAD_PARAM
		stc				;function out of range
		ret
	@@:

		pushad
		call	far ptr Far_Open_PM_RAM
		popad

	;invoke the corrresponding function

		and	word ptr [EXTEND_APM_STATUS],not APM_16BIT_FUNC_MODE
		or	word ptr [EXTEND_APM_STATUS],bp
		call	Corresponding_APM_Func

	;Close PM_RAM

		pushad
		pushf
		mov	al,[OPTION_ROM_EXIST]		;tell if option ROM in this area or not
		popf
		popad

		ret

Open_Invoke_Close	Endp

;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
		ALIGN	4
Corresponding_APM_Func	Proc	Near
Reallocate	Corresponding_APM_Func_offset

		call	Check_Errors
		jc	short @F

ifndef	NO_SUPPORT_APM12
		cmp	al, 11h
		jne	short Not_ApmF11
		call	APM_FUNC11
		jmp	short @F

	Not_ApmF11:
endif;	NO_SUPPORT_APM12

		push	si
		push	ax
		xor	ah,ah
		shl	ax,1
		mov	si, APM_FUNC_TBL_offset
		add	si, SMI_Handler_Len
		add	si,ax
		pop	ax
		call	cs:[si]
		pop	si
	@@:
		ret

Corresponding_APM_Func	Endp

		ALIGN	4
		Public	APM_FUNC_TBL			;R23
APM_FUNC_TBL:
Reallocate	APM_FUNC_TBL_offset
;R23 ;Change Routines address re-calculate to APM.INC (before move code to SMBase)
		DW	APM_FUNC00_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC01_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC02_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC03_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC04_offset 	;R23 + SMI_Handler_Len
		DW	0h			;R23 0FFFFh
		DW	0h			;R23 0FFFFh
		DW	APM_FUNC07_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC08_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC09_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC0A_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC0B_offset 	;R23 + SMI_Handler_Len		;0ffffh
		DW	APM_FUNC0C_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC0D_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC0E_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC0F_offset 	;R23 + SMI_Handler_Len

NO_OF_APM_CALL_FOR_APM11  EQU ($-APM_FUNC_TBL)/2-1

ifndef	NO_SUPPORT_APM12
		DW	APM_FUNC10_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC11_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC12_offset 	;R23 + SMI_Handler_Len
		DW	APM_FUNC13_offset 	;R23 + SMI_Handler_Len
endif	;NO_SUPPORT_APM12

NO_OF_APM_CALL  EQU ($-APM_FUNC_TBL)/2-1

;[]==================================================================[]
;Procedure:	APM_FUNC00
;
;Function :	APM function 0 - Installation check.
;
;Saves    :	all
;
;Input    : 	DS = PM_RAM
;		AH = 53h
;       	AL = 00h
;		BX = 0000h
;
;Output   :	if function successful:
;			carry = 0
;		ah = major version number (in BCD format)
;		al = minor version number (in BCD format)
;		bh = 'P'
;		bl = 'M'
;		cx = flags
;			bit 0 = 1 if 16 bit protected mode interface is supported
;			bit 1 = 1 if 32 bit protected mode interface is supported
;			bit 2 = 1 if CPU idle call slows processor clock speed
;			bit 3 = 1 if BIOS power management is disabled
;			all other bits reserved
;
;		if function unsuccessful:
;			carry = 1
;			ah = 86h APM not present
;[]==================================================================[]
		Public	APM_FUNC00
APM_FUNC00	Proc	Near
Reallocate	APM_FUNC00_offset

		ASSUME	DS:PM_RAM

		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		je	short af0_good
		test	[EXTEND_APM_STATUS],APM_16BIT_FUNC_MODE
		jnz	short af0_good

		test	[APM_STATUS],IS_APM_SUPPORTED
		mov	ah,ERROR_APM_NOT_PRESENT
		jz	short af0_bad

ifdef	NO_SUPPORT_APM12
		mov	ax,0101h
else	;NO_SUPPORT_APM12
		mov	ax,0102h
endif	;NO_SUPPORT_APM12
		mov	bx,"PM"
		mov	cx,00000111b			;return apm support flags in cx
		test	[APM_STATUS], SETUP_PM_DISABLED	;R21
		jz	short af0_good			;R21
		mov	cx, 00001000b			;R21
af0_good:
		clc
		ret
af0_bad:
		stc
		ret

APM_FUNC00	Endp

;[]=======================================================================[]
;Procedure:	APM_FUNC01
;
;Function :	APM function 1 - Interface connect
;
;Saves    :	all
;
;Input    :	DS = PM_RAM
;		AH = 53h
;       	AL = 01h
;		BX = 0000h - system BIOS
;
;Output   :	if function successful:
;			carry = 0
;		if function unsuccessful:
;			carry = 1
;			ah = eoror code
;				02h interface connect already in effect
;				09h unrecognized device ID
;[]==================================================================[]
		Public	APM_FUNC01
APM_FUNC01	Proc	Near
Reallocate	APM_FUNC01_offset

;R16 start
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		je	short af1_good
;R16 end
		test	[EXTEND_APM_STATUS],APM_16BIT_FUNC_MODE
		jnz	short af1_good

	;check if any APM drivers already connected

		call	Chk_32Bit_Connected	;32 bit mode APM connected?
		jc	short af1_bad		;yes, return error!
		call	Chk_16Bit_Connected	;16 bit mode APM connected?
		jc	short af1_bad		;yes, return error!
		call	Chk_Real_Connected	;real mode APM connected?
		jc	short af1_bad		;yes, return error!

	;set flag for real mode connected

		and	[APM_STATUS],0Fh
		or	[APM_STATUS],IS_CONNECT_CALL_MADE
		or	[EXTEND_APM_STATUS],PM_ALLOWED_BY_APM+IS_PM_ENGAGED

	;clear events

		call	Clear_Events

	;chipset dependent routine for APM connection

		pusha
		pushf
		call	far ptr Ct_APMSMI_Func01
		popf
		popa
af1_good:
		clc
		ret

af1_bad:
		stc
		ret

APM_FUNC01	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	CY : AH = ERROR_16BIT_ALREADY_CONN
;			  i.e. 16 bit function already connected
;[]========================================================================[]
Chk_16Bit_Connected	Proc	Near
Reallocate	Chk_16Bit_Connected_offset
		push	ax
		mov	al,[APM_STATUS]
		and	al,IS_CONNECT_CALL_MADE+IS_16BIT_ESTABLISHED
		cmp	al,IS_CONNECT_CALL_MADE+IS_16BIT_ESTABLISHED
		pop	ax
		clc
		jne	short @F			;16 bit mode not connected
		mov	ah,ERROR_16BIT_ALREADY_CONN	;16 bit mode APM already conn.
		stc
	@@:
		ret
Chk_16Bit_Connected	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	CY : AH = ERROR_32BIT_ALREADY_CONN
;			  i.e. 32 bit function already connected
;[]========================================================================[]
Chk_32Bit_Connected	Proc	Near
Reallocate	Chk_32Bit_Connected_offset
		push	ax
		mov	al,[APM_STATUS]
		and	al,IS_CONNECT_CALL_MADE+IS_32BIT_ESTABLISHED
		cmp	al,IS_CONNECT_CALL_MADE+IS_32BIT_ESTABLISHED
		pop	ax
		clc
		jne	short @F			;32 bit mode not connected
		mov	ah,ERROR_32BIT_ALREADY_CONN	;32 bit mode APM already conn.
		stc
	@@:
		ret
Chk_32Bit_Connected	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	CY : AH = ERROR_REAL_ALREADY_CONN
;			  i.e. real mode function already connected
;[]========================================================================[]
Chk_Real_Connected	Proc	Near
Reallocate	Chk_Real_Connected_offset
		push	ax
		mov	al,[APM_STATUS]
		and	al,IS_CONNECT_CALL_MADE
		cmp	al,IS_CONNECT_CALL_MADE
		pop	ax
		clc
		jne	short @F
		mov	ah,ERROR_REAL_ALREADY_CONN	;real mode APM already conn.
		stc
	@@:
		ret
Chk_Real_Connected	Endp

;[]==================================================================[]
;
; Procedure Name: APM_FUNC02
;
;	APM function 2 - Protect mode 16 bit interface connect
;
; Saves: all
;
; Input:
;	ah=53h
;       al=02h
;	bx=0000 - system BIOS
;
; Output:
;	if function successful:
;		carry = 0
;	ax = PM 16 bit code segment (real mode segmnt base address)
;	bx = offset of entry point
;	cx = PM 16 bit data segment
;
;	if function unsuccessful:
;		carry = 1
;		ah = error code
; 		 05h = 16 bit protected mode interface already established
;	 	 06h = 16 bit protected mode interface not supported
;		 09h = unrecognized device ID
;[]==================================================================[]
		Public	APM_FUNC02
APM_FUNC02	Proc	Near
Reallocate	APM_FUNC02_offset

		test	[APM_STATUS],IS_16BIT_SUPPORTED	;i6 bit supported?
		mov	ah,ERROR_NO_SUPPORT_16BIT		;
		jz	short af2_bad			;no, return error!

		call	APM_FUNC01			;successful check in?

		jc	short af2_bad			;no, return error!

	;set flag for 16 bit APM connection

		or	[APM_STATUS],IS_16BIT_ESTABLISHED

	;Prepare segment registers

		mov	ax,DGROUP
		mov	cx,ds		;;;
		mov	bx,offset DGROUP:APM_16BIT_ENTRY
af2_good:
		xor	si,si
;R14		mov	ss:[esp+2],si			;R09
		mov	ss:[esp+2],si			;R14A
		xor	di,di
		ret
af2_bad:
		stc
		ret

APM_FUNC02	Endp

;[]==================================================================[]
; Procedure Name: APM_FUNC03
;
;	APM function 3 - Protect mode 32 bit interface connect
;
; Saves: all
;
; Input:
;	ah = 53h
;       al = 03h
;	bx = 0000h - system BIOS
;	DS = PM_RAM
;
; Output:
;	if function successful:
;		carry = 0
;	ax = PM 32 bit code segment (real mode segmnt base address)
;	ebx = offset of entry point
;	cx = PM 16 bit code segmetn
;	dx = PM data segment
;
;	if function unsuccessful:
;		carry = 1
;		ah = error code
; 		 07h = 32 bit protected mode interface already established
;	 	 08h = 32 bit protected mode interface not supported
;		 09h = unrecognized device ID
;[]==================================================================[]
APM_FUNC03	Proc	Near
Reallocate	APM_FUNC03_offset

		test	[APM_STATUS],IS_32BIT_SUPPORTED	;i6 bit supported?
		mov	ah,ERROR_NO_SUPPORT_32BIT		;
		jz	short af3_bad			;no, return error!

		call	APM_FUNC01			;successful check in?
		jc	short af3_bad			;no, return error!

	;set flag for 32 bit APM connection

		or	[APM_STATUS],IS_32BIT_ESTABLISHED

	;Prepare segment registers

		mov	cx,DGROUP			;code seg.
		xor	ebx,ebx
		mov	bx,offset DGROUP:APM_32bit_Entry
		mov	ax,DGROUP			;code seg.
		mov	dx,ds	;DGROUP			;data seg.
		xor	si, si
		mov	ss:[esp+2],si			;R14A
		xor	di, di
af3_good:
		clc
		ret
af3_bad:
		stc
		ret

APM_FUNC03	Endp

;[]==================================================================[]
; Procedure Name: APM_FUNC04
;
;	APM function 4 - Interface disconnect
;
; Saves: all
;
; Input:
;	ah = 53h
;       al = 04h
;	bx = 0000h - system BIOS
;	DS = PM_RAM
;
; Output:
;	if function successful:
;		carry = 0
;
;	if function unsuccessful:
;		carry = 1
;		ah = error code
;		 03h = interface not connected
;		 09h = unrecognized device ID
;[]==================================================================[]
APM_FUNC04	Proc	Near
Reallocate	APM_FUNC04_offset

		and	[APM_STATUS],not IS_CONNECT_CALL_MADE
		test	[EXTEND_APM_STATUS],APM_16BIT_FUNC_MODE
		jz	short @F
		and	[APM_STATUS],not IS_16BIT_ESTABLISHED
		jmp	short APM_STATUS_done
	@@:
;R16 start
		ror	ebp,16
		cmp	bp,APM_32BIT_MARK
		ror	ebp,16
		jne	short APM_STATUS_done
		and	[APM_STATUS],not IS_32BIT_ESTABLISHED
APM_STATUS_done:
;R16 end
		and	[EXTEND_APM_STATUS],not (APM11_INSTALLED+APM12_INSTALLED)
		call	Clear_Events

	;chipset dependent routine for APM disconnection

		pusha
		pushf
		call	far ptr	Ct_APMSMI_Func04
		popf
		popa

		clc
		ret

APM_FUNC04	Endp


;[]==================================================================[]
;Procedure:	APM_FUNC07 (Set Power State)
;
;Function :	To set system to requested state
;		Here we only handle suspend request
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 07h
;		BX = Power device ID
;		     0001h	 All devices managed by the APM BIOS
;		     01XXh	 Display
;		     02XXh	 Secondary Storage
;		     03XXh	 Parallel Ports
;		     04XXh	 Serial Ports
;		     E000h-EFFFh OEM-defined Power Devices IDs
;		CX = Power State
;		     0000h	 APM Enabled
;		     0001h	 Standby
;		     0002h	 Suspend
;		     0003h	 Off
;		     0004h-001Fh Reserved system states
;		     0020h-003Fh OEM defined system states
;		     0040h-007Fh OEM defined device states
;		     0080h-FFFFh Reserved device states
;
;Output   :	CF - Error
;		     AH = 01h Power Management functionality disabled
;			  03h Interface not connected
;			  09h Unrecognized device ID
;			  0Ah Parameter value out of range
;			  60h Unable to enter requested state
;		NC - Success
;[]==================================================================[]
APM_FUNC07	Proc	Near
Reallocate	APM_FUNC07_offset

		call	Check_PM_Allowed
		jc	short af7_bad

		call	Check_F07_Bad_Param
		jc	short af7_bad

		cmp	bh, 01h
		je	short F07_Control_Disp

		call	Chk_All_Devices
		jc	short af7_bad

		push	ds
		push	es
		push	fs
		push	gs
		pushad

	;------------------------------------------------------------
	;no matter reject or accept, Posted events must be cleared
	;------------------------------------------------------------

		not	cl
		and	[APM_EVENT_POST],cl
		not	cl

	;------------------------------------------------------------
	;under some conditions, we must reject requests
	;e.g. do not suspend if APMEventSave = RESUME_CRITICAL_NOTIFY
	;------------------------------------------------------------

		mov	al,[APMEventSave]
		call	Skip_Request
		jc	short af7_skip

	;------------------------------------------------------------
	;call chip dependent SUSPEND/STANDBY routine
	;------------------------------------------------------------

		mov	[APMEventSave],NO_EVENTS

		cmp	cl, APM_OFF_REQ			;power off request?
		jne	short @f			;no, check other states

		stc					;for dummy return
		call	far ptr APMSMI_16_PowerOff
		jnc	short af7_skip
		popad
		mov	ah, ERROR_NO_STATE_REQUEST
		jmp	short af7_exit1
	@@:

		cmp	cl,APM_SUSPEND_REQ
		jne	short @F

	;add delay for clearing pending IRQs before going into suspend

		mov	[APM_SMIFlag],Suspend_Req
		jmp	short af7_skip
	@@:
		mov	[APM_SMIFlag],Standby_Req

	af7_skip:
		clc
	af7_exit:
		popad
	af7_exit1:
		pop	gs
		pop	fs
		pop	es
		pop	ds

		ret
af7_bad:
		stc
		ret

F07_Control_Disp:
		pushad
		mov	al, CRT_ON_REQ
		cmp	cl, APM_READY_REQ
		je	short @F
		mov	al, CRT_OFF_REQ
	@@:
		mov	[Software_SMI_Type], al
		mov	[APM_SMIFlag], Func07_call
		popad
		mov	[DISP_PM_MODE], cl
		clc
		ret

APM_FUNC07	Endp

;-----------------------------------------------------------------------
;Check BAD parameters
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;-----------------------------------------------------------------------
		Public	Check_F07_Bad_Param
Check_F07_Bad_Param	Proc	Near
Reallocate	Check_F07_Bad_Param_offset

		or	ch,ch
		jnz	short Param_Bad

		cmp	cl, APM_OFF_REQ		;valid request?
		jbe	short Req_Accepted	;yes, continue

	Param_Bad:

		mov	ah,ERROR_BAD_PARAM
		or	ch,ch
		jnz	short @F
		cmp	cl,05h
		ja	short @F
		mov	ah,ERROR_NO_STATE_REQUEST
	@@:
		stc
		ret

	Req_Accepted:

		clc
		ret

Check_F07_Bad_Param	Endp

;--------------------------------------------------------------------------
;
;SUSPEND request: check RESUME_NORMAL_NOTIFY & RESUME_CRITICAL_NOTIFY
;STANDBY request: check items of SUSPEND plus STANBY_RESUME_NOTIFY
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;--------------------------------------------------------------------------
		Public	Skip_Request
Skip_Request	Proc	Near
Reallocate	Skip_Request_offset

		cmp	al,RESUME_NORMAL_NOTIFY
		je	short Event_Reject
		cmp	al,RESUME_CRITICAL_NOTIFY
		je	short Event_Reject
		cmp	cl, APM_OFF_REQ
		je	short Do_Request
		cmp	cl,APM_SUSPEND_REQ
		je	short Do_Request
		cmp	al,STANBY_RESUME_NOTIFY
		jne	short Do_Request
Event_Reject:
		stc
		ret
Do_Request:
		clc
		ret
Skip_Request	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC08
;
;Function :	Enable/Disable Power Management
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 08h
;		BX = Power Device ID
;		     0001h	All devices power managed by the APM BIOS
;		     FFFFh	All devices power managed by the APM BIOS
;				(Compatible with APM 1.0)
;		CX = Function code
;		     0000h	Disable power management
;		     0001h	Enable power management
;
;Output   :	CF - Error
;		     AH = 01h Power Management functionality disabled
;			  03h Interface not connected
;			  09h Unrecognized device ID
;			  0Ah Parameter value out of range
;		NC - Success
;[]==================================================================[]
APM_FUNC08	Proc	Near
Reallocate	APM_FUNC08_offset

		call	Clear_Events		;must clear events first ;;;;1201	
		push	dx
		mov	dx, word ptr [APM_STATUS]
		call	Do_Func08			;;;;1201	
		jc	short @F
		mov	[EXTEND_APM_STATUS], dh

;R27		call	Prg_HDD_Timer				;R26

ifndef	NO_SUPPORT_APM12				;R07
		pushad						;R05
		mov	byte ptr [Software_SMI_Type], dl	;R05
		mov	[APM_SMIFlag], Func08_call	;1208
		popad
endif	;NO_SUPPORT_APM12				;R07
		clc
	@@:
		pop	dx
		ret

;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
		Public	Do_Func08
Do_Func08	Label	Near		;R23
;R23 Do_Func08:
Reallocate	Do_Func08_offset
		test	dh, APM12_INSTALLED
		jnz	short @F
		test	dl, IS_PM_ENABLED
		jz	short Func08_PM_Dis_Error
	@@:
		or	cl, cl			;enable request?
		clc
		jnz	short Update_PM_Bit	;yes, continue

To_Disable_PM:
		test	dh, PM_ALLOWED_BY_APM
		jnz	short Update_PM_Bit

Func08_PM_Dis_Error:

		mov	ah, ERROR_PM_DISABLED
		stc
		ret

Update_PM_Bit:
		and	dh, not PM_ALLOWED_BY_APM
		or	dh, cl

;R05 - starts
		mov	dl, ENABLE_PM_REQ
		or	cl, cl
		jnz	short _kk
		mov	dl, DISABLE_PM_REQ
	_kk:
;R05 - ends

		ret

APM_FUNC08	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC09
;
;Function :	Restore APM Power-On Default
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 09h
;		BX = Power Device ID
;		     0001h	All devices power managed by the APM BIOS
;		     FFFFh	All devices power managed by the APM BIOS
;				(Compatible with APM 1.0)
;
;Output   :	CF - Error
;		     AH = 03h Interface not connected
;			  09h Unrecognized device ID
;		NC - Success
;[]==================================================================[]
APM_FUNC09	Proc	Near
Reallocate	APM_FUNC09_offset
		pushad
		mov	byte ptr [Software_SMI_Type], RESTORE_POWERON_D4_REQ
		mov	[APM_SMIFlag], Func09_call
		popad
		clc
		ret
APM_FUNC09	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0A
;
;Function :	Get Power Status
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Ah
;		BX = Power Device ID
;		     0001h	All devices power managed by the APM BIOS
;		     All other values reserved
;
;Output   :	CF - Error
;		     AH = 09h Unrecognized device ID
;
;		NC - Success
;		     BH = AC line status
;			       00h Off-line
;			       01h On-line
;			       02h On backup-power
;			       FFh Unknown
;			       All other values reserved
;		     BL = Battery status
;		     	       00h High
;			       01h Low
;			       02h Critical
;			       03h Charging
;			       FFh Unknown
;			       All Other values unknow
;		     CH = Battery flag
;		     	  bit0 = 1 High
;			  bit1 = 1 Low
;			  bit2 = 1 Critical
;			  bit3 = 1 Charging
;			  bit7 = 1 No System battery
;			       FFh Unknown
;			       All Other values unknow
;		     CL = Remaining battery life - percentage of charge
;			       0-100 = Percentage of full charge
;			       255 = Unknown
;			       All Other values unknow
;		     DX = Remaining battery life - time units
;			       Bit 15 = 0 Time units are seconds
;			       Bit 14-0 = Number of seconds or minutes
;				       0-7FFFh Valid number of seconds
;				       0-7FFEh Valid number of minutes
;			       FFFFh = Unknown
;[]==================================================================[]
APM_FUNC0A	Proc	Near
Reallocate	APM_FUNC0A_offset

;R06 - starts
ifdef	BATTERY_SYSTEM
;R10 - start
		cmp	bh,BATTERY_DEVICES SHR 8
		jne	short Chk_Battery_ID
		
		cmp	bl,MAX_BATTERY_UNIT
;R15		ja	short Chk_Battery_ID
		ja	short Invalid_Device_ID		;R15

		pusha
		mov	cl,bl
		dec	cl
		mov	al,01h
		shl	al,cl

		test	PM_RAM:BATTERY_UNIT,al
		popa
		jnz	short Chk_Battery_ID

;R15 - start
		mov	bl,UNKNOWN
		mov	ch,BAT_NOT_PRESENT
		mov	cl,UNKNOWN
		mov	dx,0FFFFh
		clc
		ret
Invalid_Device_ID:
;R15 - end
		mov	ah,ERROR_UNKNOWN_DEVICE_ID
		stc
		ret
Chk_Battery_ID:
;R10 - end
		mov	cl, UNKNOWN
		xor	al, al
		call	far ptr Ct_SMICheck_If_LowBat
		mov	ss:[esp+2],si			;R09
else	;BATTERY_SYSTEM
		mov	cx, 080FFh
		mov	dx, 0FFFFh
		mov	bx, 01FFh
endif	;BATTERY_SYSTEM
;R06 - ends

		clc
		ret

APM_FUNC0A	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0B
;
;Function :	Get PM Event
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Bh
;
;Output   :	CF - Error
;		     AH = 03h	Interface not connected
;			  80h	No power management events pending
;		NC - Success
;		     BX = PM event code
;[]==================================================================[]
APM_FUNC0B	Proc	Near
Reallocate	APM_FUNC0B_offset

		push	dx

		xor	bh,bh
		mov	bl,[APMEventSave]
		mov	dh,[APM_EVENT_POST]

		push	di
		mov	di, End_Event_Table_offset
		add	di, SMI_HANDLER_LEN

		mov	si,Event_Table_offset		;si point to even table
		add	si, SMI_HANDLER_LEN
Post_Next_Event:
		cmp	bl,cs:[si]			;event exist?
		jne	short @F			;this event not exist
		or	dh,cs:[si+1]			;set record
		jmp	short End_Post_Event		;finish!
	@@:
		add	si,2				;check next event
		cmp	si, di				;end of table?
		jb	short Post_Next_Event		;not yet!

		mov	bl,NO_EVENTS			;no event found
		call	Battery_Check			;if low battery
							;  BL=BATT_LOW_NOTIFY
End_Post_Event:
		pop	di

		mov	[APMEventSave],NO_EVENTS	;event done
		mov	[APM_EVENT_POST],dh		;set record

		cmp	bl,NO_EVENTS			;no event?
		clc
		jne	short @F			;no, exit
		stc					;set error
		mov	ah,ERROR_NO_EVENT_PENDING	;return error code
	@@:
		pop	dx
		ret

APM_FUNC0B	Endp

Battery_Check	Proc	Near

		pusha
		mov	al,1
		call	Ct_SMICheck_If_LowBat
		cmp	bh,AC_ON_LINE
		je	short @F
		cmp	bl,BAT_HIGH
	@@:
		popa

		je	short @F		;BATT high or AC power
		test	dh,BATT_LOW_POST	;already posted to APM?
		jnz	short @F		;yes, skip
		or	dh,BATT_LOW_POST	;set indication
		mov	bl,BATT_LOW_NOTIFY	;return
	@@:
		ret

Battery_Check	Endp

;===================================================
		Public	Event_Table
		Public	End_Event_Table
Event_Table:
Reallocate	Event_Table_offset
		db	SUSPENDREQUEST		,SUSPEND_POST
		db	USER_SUSPENDREQUEST	,SUSPEND_POST
		db	STANDBYREQUEST		,STANDBY_POST
		db	USER_STANDBYREQUEST	,STANDBY_POST
		db	UPDATE_TIME_NOTIFY	,0
		db	RESUME_NORMAL_NOTIFY	,0
		db	RESUME_CRITICAL_NOTIFY	,0
		db	STANBY_RESUME_NOTIFY	,0
		db	PM_STATUS_CHANGE_NOTIFY	,0		;R12
End_Event_Table:
Reallocate	End_Event_Table_offset
;===================================================

;[]==================================================================[]
;Procedure:	APM_FUNC0C
;
;Function :	Get Power State
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Ch
;		BX = Power device ID
;		     0001h : All devices power managed by the APM BIOS
;		     01XXh : Display
;		     02XXh : Secondary Storage
;		     03XXh : Parallel Ports
;		     04XXh : Serial Ports
;		     05XXh : Network Adapters
;		     06XXh : PCMCIA Sockets
;		     E000h - EFFFh OEM-defined Power Device IDs
;		     All other values reserved
;
;		     where:
;
;		     XX h = Unit Number (0 based)
;		     Unit Number of FFh means all devices in this class.
;
;Output   :	CF - Error
;		     AH = 01h	Power management functionality disabled
;			  09h	Unrecognized device ID
;		NC - Success
;		     CX = Power State
;			  0000h	APM Enabled
;			  0001h Stanby
;			  0002h Suspend
;			  0003h Off
;			  0004h-001Fh Reserved system states
;			  0020h-003Fh OEM-defined system states
;			  0040h-007Fh OEM-defined device states
;			  0084h-FFFFh Reserved device states
;
;[]==================================================================[]
APM_FUNC0C	Proc	Near
Reallocate	APM_FUNC0C_offset

		cmp	bh, 01h
		jne	short @F
		mov	cl, [DISP_PM_MODE]
		ret
	@@:
		call	Chk_All_Devices
		jc	short afc_Ret

		mov	cl,[PM_MODE]
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
		Public	Do_Func0C
Do_Func0C	Label	Near		;R23 
;R23 Do_Func0C:
Reallocate	Do_Func0C_offset
		cmp	cl,2		;	  Award	     APM
		jb	short @F	;Full-on  0(Full-on) 0(APM enabled)
		dec	cl		;Doze	  1	     ?
	@@:				;Standby  2	     1
		clc			;Suspend  3	     2
	afc_Ret:
		ret

APM_FUNC0C	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0D
;
;Function :	Enable/Disable Device Power Management
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Dh
;		BX = Power device ID
;		     0001h : All devices power managed by the APM BIOS
;		     01XXh : Display
;		     02XXh : Secondary Storage
;		     03XXh : Parallel Ports
;		     04XXh : Serial Ports
;		     05XXh : Network Adapters
;		     06XXh : PCMCIA Sockets
;		     E000h - EFFFh OEM-defined Power Device IDs
;		     All other values reserved
;
;		     where:
;
;		     XX h = Unit Number (0 based)
;		     Unit Number of FFh means all devices in this class.
;
;Output   :	CF - Error
;		     AH = 01h	Power management functionality disabled
;			  03h	Interface not connected
;			  09h	Unrecognized device ID
;		NC - Success
;[]==================================================================[]
APM_FUNC0D	Proc	Near
Reallocate	APM_FUNC0D_offset
;R24A 		call	APM_FUNC08
;R24A start
		call	Decode_APM_Devices	;decode the input BX
		jc	short APM_FUNC0D_End	;CF=invalid device input

		cmp	bx, ALL_DEVICES
		je	APM_FUNC08
		clc

	APM_FUNC0D_End:
;R24A end
		ret
APM_FUNC0D	Endp
;R24A start
Decode_APM_Devices	Proc	Near
Reallocate	Decode_APM_Devices_offset

		push	dx
		push	si
		mov	si, APM_Device_Tbl_offset	;si point to device
							; table
	Decode_Next_APM_Device:

		cmp	si, offset APM_Device_Tbl_End_offset	;end of table
		je	Wrong_Device			;yes, post error!

		cmp	bx, word ptr cs:[si]		;device found?
		je	APM_Device_Found		;yes, go do it.
		add	si, One_APM_Device_Len		;point to next device
		jmp	Decode_Next_APM_Device		;go decode next

	APM_Device_Found:

		mov	dx, cs:[si+2]			;dx=value for updating
							;   flag in PM_RAM
	;---------------------------------------------------

		cmp	bx, ALL_DEVICES		;all devices?
		je	Update_Dev_PM_Flg	;yes, skip ERROR_PM_DISABLED

	;---------------------------------------------------

		test	[DEVICE_PM_STATUS], dx	;assume device PM to be enabled
		jnz	Dev_PM_Now_Enabled	;NZ --> device PM is now enabled
		or	cx, cx			;disable request?
		jz	Dev_PM_Already_Disabled	;yes, Post error: ERROR_PM_DISABLED

	Dev_PM_Now_Enabled:

	;---------------------------------------------------
	;If function 0Dh, check for corresponding device 
	;engage status
	;---------------------------------------------------

		cmp	al, 0Dh
		jne	No_Chk_Engaged

;R26 - starts
		cmp	bh, 02h			;Storage device control?
		jne	@F			;no
		call	Prg_HDD_Timer
	@@:
;R26 - ends

		shl	dx, 1
		test	[DEVICE_PM_STATUS], dx	;assume device PM to be enabled
		jz	Interface_Not_Engaged
		shr	dx, 1

	No_Chk_Engaged:

	;---------------------------------------------------
	;set flags for device power management
	;---------------------------------------------------

	Update_Dev_PM_Flg:

		cmp	al, 0Fh			;PM engage/dis-engage?
		jne	@F			;no!
		shl	dx, 1			;set flg for engage/dis-engage
	@@:
		or	[DEVICE_PM_STATUS], dx	;assume device PM to be enabled
		or	cx, cx			;really to be enabled?
		jnz	End_Decode_APM_Devices	;yes!
		not	dx			;about to clear the flag
		and	[DEVICE_PM_STATUS], dx	;clear device flag

	End_Decode_APM_Devices:

		clc
		jmp	Dev_PM_Exit

	Wrong_Device:

		mov	ah, ERROR_UNKNOWN_DEVICE_ID
		jmp	Dev_PM_Err_Exit

	Interface_Not_Engaged:

		mov	ah, ERROR_PM_NOT_ENGAGED
		jmp	Dev_PM_Err_Exit

	Dev_PM_Already_Disabled:

		mov	ah, ERROR_PM_DISABLED

	Dev_PM_Err_Exit:

		stc

	Dev_PM_Exit:

		pop	si
		pop	dx
		ret
Decode_APM_Devices	Endp

APM_Device_Tbl	Label	Near
Reallocate	APM_Device_Tbl_offset
		dw	0001h, ALL_DEVICES_PM_ENABLED
;R24B One_APM_Device_Len	EQU	$ - offset APM_Device_Tbl
One_APM_Device_Len	EQU	$ - offset APM_Device_Tbl_offset	;R24B

		dw	0100h, DISP_PM_ENABLED
		dw	01FFh, DISP_PM_ENABLED
		dw	0200h, STORAGE_PM_ENABLED
		dw	02FFh, STORAGE_PM_ENABLED
		dw	0300h, LPT_PM_ENABLED
		dw	03FFh, LPT_PM_ENABLED
		dw	0400h, COM1_PM_ENABLED
		dw	0401h, COM2_PM_ENABLED
		dw	04FFh, COM1_PM_ENABLED+COM2_PM_ENABLED
		dw	0500h, LAN_PM_ENABLED
		dw	05FFh, LAN_PM_ENABLED
		dw	0600h, PCMCIA_PM_ENABLED
		dw	06FFh, PCMCIA_PM_ENABLED

Reallocate	APM_Device_Tbl_End_offset
;R24A end

;[]==================================================================[]
;Procedure:	APM_FUNC0E
;
;Function :	APM Driver Version
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Eh
;		BX = 0000h : APM BIOS
;		CH = APM Driver major version number (in BCD format)
;		CL = APM Driver minor version number (in BCD format)
;
;Output   :	CF - Error
;		     AH = 03h	Interface not connected
;			  09h	Unrecognized device ID
;			  0Bh	Interface not engaged
;		NC - Success
;		     AH = APM Connection major version number (in BCD format)
;		     AL = APM Connection minor version number (in BCD format)
;
;[]==================================================================[]
APM_FUNC0E	Proc	Near
Reallocate	APM_FUNC0E_offset

		push	dx
		mov	dl, [EXTEND_APM_STATUS]
		and	dl, not (APM11_INSTALLED+APM12_INSTALLED)
		call	Do_Func0E
		jc	short @F
		mov	[EXTEND_APM_STATUS], dl
	@@:
		pop	dx
		ret

;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
		Public	Do_Func0E
Do_Func0E	Label	Near		;R23 
;R23 Do_Func0E:
Reallocate	Do_Func0E_offset

	;check APM driver version = 1.1?

		cmp	ch,01h
		jne	short @F

		mov	dh, APM11_INSTALLED
		cmp	cl,01h
ifndef	NO_SUPPORT_APM12
		je	short _0E_Accecpted

		mov	dh, APM12_INSTALLED
		cmp	cl,02h
endif	;NO_SUPPORT_APM12

	@@:
		stc
		jne	short afe_bad		;no, return error!

	_0E_Accecpted:

		or	dl, dh

		mov	ah,ch			;APM BIOS version in AX
		mov	al,cl
		clc
afe_bad:
		ret

APM_FUNC0E	Endp

;[]==================================================================[]
;Procedure:	APM_FUNC0F
;
;Function :	Engage/Disengage Power Management
;
;Input    :	DS = PM_RAM
;		AH = 53h
;		AL = 0Fh
;		BX = Power device ID
;		     0001h : All devices power managed by the APM BIOS
;		     01XXh : Display
;		     02XXh : Secondary Storage
;		     03XXh : Parallel Ports
;		     04XXh : Serial Ports
;		     05XXh : Network Adapters
;		     06XXh : PCMCIA Sockets
;		     E000h - EFFFh OEM-defined Power Device IDs
;		     All other values reserved
;
;		     where:
;
;		     XX h = Unit Number (0 based)
;		     Unit Number of FFh means all devices in this class.
;		CX = Function code
;		     0000h = Disengage power management
;		     0001h = Engage power management
;
;Output   :	CF - Error
;		     AH = 01h	Power management functionality disabled
;			  03h	Interface not connected
;			  09h	Unrecognized device ID
;			  0Ah	Parameter value out of range(function code)
;		NC - Success
;[]==================================================================[]
APM_FUNC0F	Proc	Near
Reallocate	APM_FUNC0F_offset

;R24A start
		call	Decode_APM_Devices
		jc	aff_Exit

		cmp	bx, ALL_DEVICES	  
		jne	aff_good
;R24A end
 		call	Check_PM_Allowed
		jc	short aff_Exit

		and	[EXTEND_APM_STATUS],not IS_PM_ENGAGED
		or	cx,cx			;disable request?
		jz	short aff_good		;yes
		or	[EXTEND_APM_STATUS],IS_PM_ENGAGED
		call	Clear_Events
aff_good:
		clc
aff_Exit:
		ret

APM_FUNC0F	Endp

Check_PM_Allowed:
Reallocate	Check_PM_Allowed_offset

		test	[EXTEND_APM_STATUS], PM_ALLOWED_BY_APM
		clc
		jnz	short @F
		stc
		mov	ah,ERROR_PM_DISABLED
	@@:
		ret

ifndef	NO_SUPPORT_APM12

;R11 - start
PM_CAP	=	STANDBY_CAP+SUSPEND_CAP+STANDBY_RING_CAP+SUSPEND_RING_CAP+\
			    STANDBY_RESUME_TIMER_CAP+SUSPEND_RESUME_TIMER_CAP

ifdef	Notebook_Power_Management
PM_CAP	= PM_CAP+STANDBY_PCMCIA_RING_CAP+SUSPEND_PCMCIA_RING_CAP
endif;	Notebook_Power_Management
;R11 - end

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC10
APM_FUNC10	Proc	Near
Reallocate	APM_FUNC10_offset

ifdef	BATTERY_SYSTEM				;R15
		mov	bl,MAX_BATTERY_UNIT	;R15
else	;BATTERY_SYSTEM				;R15
		xor	bl, bl					;no battery
endif	;BATTERY_SYSTEM				;R15


		mov	cx,PM_CAP				;R11
		cmp	word ptr [APM_MODEM_IRQ], 0
		jne	short @F
		and	cl, not (STANDBY_RING_CAP+\
				 SUSPEND_RING_CAP+\
			         STANDBY_PCMCIA_RING_CAP+\
				 SUSPEND_PCMCIA_RING_CAP)
	@@:
		mov	[APM12_CAPABILTY], cl

		call	far ptr Ct_APMSMI_Func10

		ret

APM_FUNC10	endp

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC11
APM_FUNC11	Proc	Near
Reallocate	APM_FUNC11_offset

		cmp	cl, 2
		jbe	short @F

	Func11_Bad_Para:

		mov	ah, ERROR_BAD_PARAM
		stc
		ret
	@@:

	;------ Try to disable Resume Timer ------------

		or	cl, cl
		jz	short F11_SW_SMI

	;------ Trying to set Resume Timer -------------

		cmp	cl, 2
		jne	short Not_Set_Resume_Timer

		push	cx
		xor	cl, cl
		call	Check_Func11_Para_Range
		pop	cx
		jc	short Func11_Bad_Para

		mov	byte ptr [RESUME_SECOND], ch
		mov	word ptr [RESUME_MINUTE], dx
		mov	word ptr [RESUME_DAY], si
		mov	word ptr [RESUME_YEAR], di

	F11_SW_SMI:

		pushad

		;-------
		and	[EXTEND_APM_STATUS], not RESUME_TIMER_ENABLED
		or	cl, cl
		jz	short @F
		or	[EXTEND_APM_STATUS], RESUME_TIMER_ENABLED
	@@:
		;-------
		or	cl, cl
		mov	cl, DISABLE_RESUME_TIMER_REQ
		jz	short @F
		mov	cl, ENABLE_RESUME_TIMER_REQ
	@@:
		mov	[Software_SMI_Type], cl
		mov	[APM_SMIFlag], Func11_call
		;-------

		popad

		clc
		ret

	Not_Set_Resume_Timer:

	;----- Try to get Resume Timer------------------

		test	[EXTEND_APM_STATUS], RESUME_TIMER_ENABLED
		jnz	short @F
		mov	ah, ERROR_RESUME_TIMER_OFF
		stc
		ret
	@@:
		mov	ch, byte ptr [RESUME_SECOND]
		mov	dx, word ptr [RESUME_MINUTE]
		mov	si, word ptr [RESUME_DAY]
		mov	di, word ptr [RESUME_YEAR]
		clc
		ret

APM_FUNC11	endp

;[]------------------------------------------------------------------------[]
;input	:	CL = 1 : call from 32 bit protected mode
;		     0 : call from real mode or 16 bit protected mode
;output	:	CF : input time out of range
;[]------------------------------------------------------------------------[]
		Public	Check_Func11_Para_Range
Check_Func11_Para_Range	Proc	Near
Reallocate	Check_Func11_Para_Range_offset

;-------------------------------------------------------------------
; Code for 16 bit/real mode	
;-------------------------------------------------------------------

		   pusha

	;bp=0: indicates no error

		   xor	bp, bp

	;**********************************************************
	;if year < 1995 then error
		   mov	ax, di
		   cmp	ah, 19h
		   jne	short @F
		   cmp	al, 95h
		   jae	short @F
		   inc	bp			;error
	@@:
	;**********************************************************

	;push input resume timer	
	;settings into stack for
	;later checking

		   ror	cx, 8
		   push	cx			;second
		   rol	cx, 8
		   push	dx			;minute
		   shr	dx, 8
		   push	dx			;hour
		   push	si			;day
		   shr	si, 8
		   push	si			;month
		   push	di			;year
		   shr	di, 8
		   push	di			;century

	;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		   mov	si, TimeRangeTbl_offset
		   add	si, SMI_Handler_Len
		   mov	di, EndTimeRangeTbl_offset
		   add	di, SMI_Handler_Len

	;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	Chk_Next_Range:

		   pop	ax			;retrieve
						;input settings
	;-----------------------------------------------------------
		   push	dx

	;////////////////////////////////////////////////////////
	;retrieve low/high limit into
	;DL/DH correspondingly

		   mov	dx, cs:[si]

	;////////////////////////////////////////////////////////

		   cmp	al, dl			;low limit
		   jae	short @F
		   inc	bp
	@@:
		   cmp	al, dh			;high limit
		   jbe	short @F
		   inc	bp
	@@:
		   and	al, 0Fh			;BCD check
		   cmp	al, 09h
		   jbe	short @F
		   inc	bp
	@@:
		   pop	dx

	;--------------------------------------------------------

		   inc	si
		   inc	si
		   cmp	si, di
		   jb	short Chk_Next_Range

		   clc
		   or	bp, bp
		   jz	short @F
		   stc
	@@:
		   popa
				
		   ret

Check_Func11_Para_Range	Endp

TimeRangeTbl:
Reallocate	TimeRangeTbl_offset
		db	19h, 20h		;century
		db	0  , 99h		;year
		db	1  , 12h		;month
		db	1  , 31h		;day
		db	0  , 23h		;hour
		db	0  , 59h		;minute
		db	0  , 59h		;second

EndTimeRangeTbl:
Reallocate	EndTimeRangeTbl_offset

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC12
APM_FUNC12	Proc	Near
Reallocate	APM_FUNC12_offset

		test	byte ptr [APM12_CAPABILTY],STANDBY_RING_CAP+\
						   SUSPEND_RING_CAP+\
						   STANDBY_PCMCIA_RING_CAP+\
						   SUSPEND_PCMCIA_RING_CAP
		jnz	short APM_FUNC12_SUPPORTED
		stc
		mov	ah, ERROR_FUNCTION_NOT_SUPPORT
		ret

	APM_FUNC12_SUPPORTED:

		push	dx
		push	bx

		mov	dh, RING_WAKEUP_ENABLED
		mov	bl, DISABLE_RESUME_RING
		mov	bh, ENABLE_RESUME_RING
		jmp	short _FFFFF

APM_FUNC12	endp

;[]========================================================================[]
;[]========================================================================[]
		Public	APM_FUNC13
APM_FUNC13	Proc	Near
Reallocate	APM_FUNC13_offset

		push	dx
		push	bx

		mov	dh, PMU_TIMER_ENABLED
		mov	bl, DISABLE_TIMER_REQ
		mov	bh, ENABLE_TIMER_REQ

		Public	_FFFFF				;R23 
_FFFFF		Label	Near				;R23 
;R23 	_FFFFF:
		mov	dl, [EXTEND_APM_STATUS]
		call	Do_Func12_13
		jc	short APM_FUNC13_Exit
		mov	[EXTEND_APM_STATUS], dl

		cmp	dh, 2
		je	short APM_FUNC13_Exit

		pushad
		or	dh, dh
		jz	short @F
		xchg	bl, bh
	@@:
		mov	byte ptr [Software_SMI_Type], bl
		mov	[APM_SMIFlag], Func13_call	;1208
		popad
		clc

	APM_FUNC13_Exit:

		pop	bx
		pop	dx
		ret

APM_FUNC13	endp

;[]========================================================================[]
;Input	:	DL = PM_RAM:[EXTEND_APM_STATUS]
;		DH = bit to test/update
;		CL = parameters from APM driver
;
;Output	:	CF : function failed
;		NC : DH = Input CL
;		     DL = for updating PM_RAM:[EXTEND_APM_STATUS]
;
;WARNING :	The below codes is shared with the APM32 function 08h!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Do_Func12_13
Do_Func12_13	Proc	Near
Reallocate	Do_Func12_13_offset

		or	ch, ch
		jnz	short F12_F13_Out_Of_Range

		cmp	cl, 2
		ja	short F12_F13_Out_Of_Range
		je	short Return_Status

		or	dl, dh			;assume set enabled !
		or	cl, cl			;request = enabled ?
		jnz	short @F		;yes !
		xor	dl, dh			;set flag for disabled !
	@@:
		mov	dh, cl			;input CL --> DH
		clc
		ret

	;return the enable/disable status

	Return_Status:

	;-------------------------------------------------------------------
	;the following 3 lines are equivalent to "test dl, dh". Since this
	;code is shared with APM32.ASM, & this "test dl, dh" will be
	;interpreted as "test dh, dl" when CPU is in 32 bit protected mode,
	;I use the following 3 lines to
	;-------------------------------------------------------------------
							;32 bit proteced mode
							;--------------------
		push	dx				;push edx
		and	dl, dh	;current enabled ?	;and  dl, dh
		pop	dx				;pop  edx

	;-----------------------------

		mov	dh, cl			;input CL --> DH
		mov	cl, 1			;assume enabled !
		jnz	short F12_F13_Success	;is enabled !
		xor	cl, cl			;return CL=0 i.e. disabled !

	F12_F13_Success:

		clc
		ret

	F12_F13_Out_Of_Range:

		mov	ah, ERROR_BAD_PARAM

		stc
		ret

Do_Func12_13	Endp
endif	;NO_SUPPORT_APM12

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_NOT_CONNECTED
;			  i.e. real mode function not connected
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_Not_Connected
Chk_Not_Connected	Proc	Near
Reallocate	Chk_Not_Connected_offset
		test	dl,IS_CONNECT_CALL_MADE		;[APM_STATUS]
		clc
		jnz	short @F
		mov	ah,ERROR_NOT_CONNECTED		;real mode APM not conn.
		stc
	@@:
		ret
Chk_Not_Connected	Endp

;[]========================================================================[]
;input	:	BX = input from APM driver
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : ah = ERROR_UNKNOWN_DEVICE_ID
;			  i.e. BX not EQUAL to BIOS_DEVICE_ID(0000h)
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_BIOS_Device
Chk_BIOS_Device	Proc	Near
Reallocate	Chk_BIOS_Device_offset

		cmp	bh,BIOS_DEVICE_ID SHR 8
		jne	short Chk_BIOS_Device_Bad

		cmp	bl,BIOS_DEVICE_ID AND 0FFh
		clc
		je	short Chk_BIOS_Device_Ret

Chk_BIOS_Device_Bad:

		mov	ah,ERROR_UNKNOWN_DEVICE_ID
		stc

Chk_BIOS_Device_Ret:

		ret
Chk_BIOS_Device	Endp

;[]========================================================================[]
;input	:	BX = input from APM driver
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	NC : BX = APM10_ALL_DEVICES (FFFFh) or
;		     BX = ALL_DEVICES (0001h)
;		CY : AH = ERROR_UNKNOWN_DEVICE_ID
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_APM10_All_Devices
Chk_APM10_All_Devices	Proc	Near
Reallocate	Chk_APM10_All_Devices_offset
		cmp	bh,APM10_ALL_DEVICES SHR 8
		jne	short Chk_All_Devices
		cmp	bl,APM10_ALL_DEVICES AND 0FFh
		je	short All_Devices_OK
Chk_APM10_All_Devices	Endp

;[]========================================================================[]
;input	:	BX = input from APM driver
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	NC : BX = ALL_DEVICES (0001h)
;		CY : AH = ERROR_UNKNOWN_DEVICE_ID
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_All_Devices
Chk_All_Devices	Proc	Near
Reallocate	Chk_All_Devices_offset

;R08A - start
ifdef	BATTERY_SYSTEM
		cmp	al,0Ah
		jne	short Not_Chk_Battery_ID

		cmp	bh,BATTERY_DEVICES SHR 8
		jne	short Not_Chk_Battery_ID
		
		cmp	bl,MAX_BATTERY_UNIT
		ja	short Chk_All_Device_Bad

		clc
		jmp	short All_Devices_OK
Not_Chk_Battery_ID:
endif	;BATTERY_SYSTEM	
;R08A - end
		cmp	bh,ALL_DEVICES SHR 8
		jne	short Chk_All_Device_Bad
		cmp	bl,ALL_DEVICES AND 0FFh
		je	short All_Devices_OK

Chk_All_Device_Bad:

		mov	ah,ERROR_UNKNOWN_DEVICE_ID
		stc
		Public	All_Devices_OK			;R23 
All_Devices_OK	Label	Near				;R23 
;R23 All_Devices_OK:
		ret

Chk_All_Devices	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_PM_DISABLED
;			  i.e. PM functionality is disabled
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_PM_Disabled
Chk_PM_Disabled	Proc	Near
Reallocate	Chk_PM_Disabled_offset

		test	dl,IS_PM_ENABLED
		clc
		jnz	short @F

		mov	ah,ERROR_PM_DISABLED
		stc
	@@:
		ret

Chk_PM_Disabled	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_PM_NOT_ENGAGED
;			  i.e. PM is disengaged
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_PM_Engaged
Chk_PM_Engaged	Proc	Near
Reallocate	Chk_PM_Engaged_offset
		test	dh,IS_PM_ENGAGED		;[EXTEND_APM_STATUS]
		clc
		jnz	short @F
		mov	ah,ERROR_PM_NOT_ENGAGED
		stc
	@@:
		ret
Chk_PM_Engaged	Endp

;[]========================================================================[]
;Input	:	CX
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : ah = ERROR_BAD_PARAM
;			  i.e. CX > 1
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
		Public	Chk_Param_Range_01
Chk_Param_Range_01	Proc	Near
Reallocate	Chk_Param_Range_01_offset

		or	ch,ch
		jne	short Chk_Param_Range_01_Bad
		cmp	cl,0				;must use cmp to clc
		je	short Chk_Param_Range_01_Ret	;input parameter valid
		cmp	cl,1				;maximum function = 1
		je	short Chk_Param_Range_01_Ret	;input parameter valid

Chk_Param_Range_01_Bad:

		mov	ah,ERROR_BAD_PARAM		;return error code
		stc

Chk_Param_Range_01_Ret:

		ret

Chk_Param_Range_01	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;		DH = [EXTEND_APM_STATUS]
;		DL = [APM_STATUS]
;output	:	CY : AH = ERROR_PM_NOT_ENGAGED
;			  i.e. PM is disengaged
;
;WARNING :	The below codes is shared with the APM32 function!
;		- DO NOT use WORD/DWORD/MEMORY access!
;		- DO NOT issue any subroutine CALL neither!
;
;[]========================================================================[]
Chk_APM_Presence	Proc	Near
Reallocate	Chk_APM_Presence_offset

		clc

ifndef	NO_SUPPORT_APM12
		test	dl, IS_APM_SUPPORTED
		jnz	short @F
		stc
		mov	ah, ERROR_APM_NOT_PRESENT
	@@:
endif	;NO_SUPPORT_APM12

		ret

Chk_APM_Presence	Endp

;[]========================================================================[]
;input	:	DS = PM_RAM
;output	:	clear [APMEventSave] to NO_EVENTS
;		      [APM_EVENT_POST] to 0
;[]========================================================================[]
		public	Clear_Events
Clear_Events	Proc	Near
Reallocate	Clear_Events_offset
		mov	[APMEventSave],NO_EVENTS
		mov	[APM_EVENT_POST],0
		ret
Clear_Events	Endp

;[]========================================================================[]
;Input	:	DS = PM_RAM
;output	:	CY : PM is not control by APM
;		NC : APM BIOS (PMU.ASM) must wait for
;		     APM's prompt before entering any PM modes
;[]========================================================================[]
		Public	Chk_Control_By_APM
Chk_Control_By_APM	Proc	Near
Reallocate	Chk_Control_By_APM_offset

		test	[APM_STATUS],IS_CONNECT_CALL_MADE
		jz	short No_APM_Control
		test	[EXTEND_APM_STATUS],IS_CONNECT_CALL_MADE
		jz	short No_APM_Control

		stc
		ret

	No_APM_Control:

		clc
		ret

Chk_Control_By_APM	Endp

;R26 - starts
Prg_HDD_Timer	Proc	Near
		push	ax
		mov	al, cl
		call	Set_HDD_Standby_Timer
		pop	ax
		ret
Prg_HDD_Timer	Endp

;[]------------------------------------------[]
;Function :	Set the IDE HDD Standby Timer
;
;Input    :	AL = 0  - disable HDD timer
;		  ELSE  - enable HDD timer according
;			  to [APM_HDD_TIMER_VALUE]
;
;Output   :	None
;
;Destroy  :	FLAGS
;[]------------------------------------------[]
		Public	APM_HDD_EXIST_Flag
		Public	APM_HDD_Drive_Port
		Public	APM_HDD_TIMER_VALUE
APM_HDD_EXIST_Flag	db	0
APM_HDD_Drive_Port	db	0
APM_HDD_TIMER_VALUE	db	0

		Public	fPROC_Set_HDD_Standby_Timer
fPROC_Set_HDD_Standby_Timer	Proc	Far
		call	Set_HDD_Standby_Timer
		ret
fPROC_Set_HDD_Standby_Timer	Endp
Set_HDD_Standby_Timer	Proc	Near

		pusha
		push	ds

		or	al, al
		jz	@F
		mov	al, cs:[APM_HDD_TIMER_VALUE]
	@@:
		xor	bl, bl

		mov	cl, 12			;1 unit is 5 second
		mul	cl			;one minute is 12 units
		mov	ch, al

	Set_4_IDE_Loop:

		cmp	cs:[APM_HDD_EXIST_Flag],bl	;Drive number available?
		jbe	No_Else_HDD		;No,skip
		mov	dx, 1F2h		;sector count register
		mov	cl, bl			;get drive number
		shl	cl, 1			;*2

		mov	bh, cs:[APM_HDD_Drive_Port]	;get drive scheme
		shr	bh, cl			;shift to correspond bits
		test	bh, 2			;Is primary channel?
		jz	@F			;Yes,jump
		sub	dl, 80h			;set to secondary channel
	@@:
		out	dx, al			;set the seconds time
		iodelay

		add	dl, 4			;1X6h
		mov	al, 0a0h		;assume master
		test	bh, 1			;Is master drive?
		jz	@F			;Yes,jump
		mov	al, 0b0h		;set slave drive
	@@:
		out	dx, al			;out to port
		iodelay
		inc	dl			;1X7h

		call	Wait_Ctrl_Idle		;wait controller idel

		mov	al, 0e3h		;set feature command
		out	dx, al			;send to drive
		iodelay

		call	Wait_Ctrl_Idle

		in	al, dx			;get drive status
		iodelay

		inc	bl			;next drive

		mov	al, ch			;get timer value
		jmp	Set_4_IDE_Loop
No_Else_HDD:
		pop	ds
		popa
		ret

;--------------------------
Wait_Ctrl_Idle:
		push	cx
		xor	cx, cx
	@@:
		in	al, dx
		newiodelay
		test	al, 80h
		jz	@F
		loop	@B
	@@:
		pop	cx
		ret
;--------------------------

Set_HDD_Standby_Timer	EndP
;R26 - ends

		Public	APM_SMI_END
APM_SMI_END:

endif	;ADVANCE_POWER_MANAGEMENT

XCODE		ENDS

endif	;APM_IN_SMBASE

;R20 end
		END
