;	[]===========================================================[]
;
;	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
;----------------------------------------------------------------------------
;R67	04/28/99 PAL	Location sensor restore after chipset and device restore
;R65A	04/20/99 PAL	Fixed coding error 
;R66	04/19/99 TNY	Add some code for "STR" support.
;R65	04/15/99 PAL	Added "Save_Sensor" and redo "Init_Onboard_Generator" 
;R60b	04/01/99 VIN	Added codes for	setting HDD-PIO-MODE that it reduse times.  
;R64a	03/29/98 JKY	added define for no ide 32bit decode access chipset
;R64	03/29/98 JKY	0V_Suspend & S4_Suspend speed up.
;R63a	03/25/99 JDN	Fix coding error
;R63	03/23/99 JDN	Support other VGA Wake up in S4
;R60A	03/22/99 KGN	Add code for defing No_Support_4_IDE reduse resume time
;R62    03/12/99 MIL	For SIS 620 ACPI S3 Function Support.
;R61	03/04/99 MIL	Support SIS 530, 620 Onboard 6306 AGP VGA, Wake Up in
;			S4 State.
;R60	02/24/99 VIN	Support four HDD drive reset and fixed Ultra_DMA_MODE
;			restore error.
;R59	02/22/99 KGN	Add define UseHWVGASuspend for hardware suspend vga when STR
;R44B	01/26/99 GAR	Support W83627F/HF
;R58	12/31/98 KVN	Change the year of copyright from 1998 to 1999
;R57	12/10/98 JDN	Patch if choose IR restore will hang and define No_Save_Sound
;R44A 	12/02/98 DNL	Add define for those keyboard controller that can't read A20M#
;			pin status.
;R56	11/03/98 KVN	Patch Hdd set large mode can't do S2D
;R55	10/09/98 JDN	Save 8042&P6 Patch code in ACPI S3,Wake up VGA in S4
;R54	08/20/98 KEN	Add declaration of "NO_ISA_PNP" to unsupport ISA/PNP
;			cards for the system doesn't contain ISA bus.
;R53	08/11/98 JDN	Added "No_resume_KBC_In_STR" Definition
;R52b	07/31/98 JDN	Fixed code mistake
;R52a	07/29/98 JDN	Move more code and delete unuse codes
;R52	07/28/98 JDN	Move Suspend/Resume message from F segment to E segment
;R51	07/03/98 JDN	Added codes for S3_Support
;R50	06/11/98 RCH	Change BIOS name from "EliteBIOS" to "AwardBIOS"
;R49	06/09/98 DNL	Move "Five_Volt_Resume_Byte" definition to common.equ
;R48	05/26/98 JKY	Fixed code destory DS if no define 'NO_STR_PASSWORD_CHECK'
;			Added define for move restore PS2 mouse before restore
;			BASE DRAM & EXT DRAM (define:Restore_mouse_befor_DRAM)
;R47	05/14/98 JDN	Fixed coding bug
;R46	04/29/98 JDN	Added codes for P6 STR suspend/resume procedure
;R45	03/26/98 JKY	Added KBC STR suspend/resume procedure.
;R43B	03/19/98 DNL	Fixed coding mistake
;R43A	03/13/98 DNL	Fixed coding mistake
;R44 	03/11/98 JDN 	Add define for those keyboard controller that can't read A20M#
;			pin status.
;R43	03/10/98 DNL	Reduce ACPI S4/BIOS code size to save more space
;R42	02/26/98 JDN 	Fixed OS/2 mouse driver will disable G_RAM COM port
;			status.
;R41	02/25/98 DNL	Added ACPI S4/BIOS support
;R32C	02/24/98 JKY	Fixed bug for P6 A20 early turn on.
;R40	02/24/98 DNL	Added ACPI S2,S3 state support
;R39	02/16/98 JKY	Change Version message.
;R38	01/05/98 DNL	Added ACPI BIOS support
;R37	12/29/97 JKY	Modify PM Beep tone length . define Beep_Len
;R36	12/26/97 JKY	Change suspend to disk title copyright year.
;R35	12/24/97 JKY	Don't save superio state if system dual I/O
;R32B 	12/09/97 DNL	Some motherboard can not automatic recognized the A20M#
;			pin, so we always turn on A20M# pin before save/restore
;			extend memory
;R34	11/13/97 JKY	Add routing in before into suspend zv . because some
;			VGA chip need turn-on on suspend-0v before .
;R32A	10/03/97 KGN	Some MB ( 2a59id1g ) if resume from 0V will hang at 5%
;			so add defin Resume_Turn_on_A20 to Fix Bug.
;R33	09/18/97 DNL	Fixed bug of system reset while resume from 0v suspend
;R32	09/18/97 DNL	Because the A20M# pin is recognized while CPU is in
;			SMM. so we do not need enable A20 gate again
;R31	08/21/97 RAX	Fixed some COM port mouse and driver combine, 0V resume
;			mouse can't work.
;R30	08/16/97 DNL	When KBC control using W83977 internal control, syst-
;			em will	hang , because kbc read command D0 (read 8255
;			port2) read error , cause A20 abnormal OFF , therefore
;			change way
;R29	08/12/97 KVN	Fixed QUANTUM HDD (model-NO : QUANTUM FIREBALL ST2.1A)
;			hang up on 0V resume.(M/B NO. is 2A5IIG3A)
;R07A	08/01/97 RAX	1.Remove define
;			2.Fixed ZV suspend restore PS/2 mouse will hang in
;			OS/2 and Windows NT.
;R28	07/29/97 JKY	Fixed ZV suspend resume will hang when restore 8259
;R27A	07/21/97 KVN	Fixed R27 coding mistake that cause DL be destroyed
;R27	07/04/97 KVN	Fixed 0V suspend HDD connect to any channel not only
;			for primary master but still only support first HDD
;R26	07/02/97 RAX	Add define to skip PNP device save and restore
;R25	07/02/97 DNL	Add defin for W977TF IO sus2disk save 8042 will ERROR
;R24	06/20/97 JKY	Patch VGA chip S3 86cm65 resume grabage
;R23	06/13/97 AVN	Fixed when ring in turn on power, resume from disk and
;			if OS in telix HOST mode, and keyboard no respond.
;R22	06/04/97 DNL	Fixed bug of monitor no display when system resume from
;			STD (Suspend-To-Disk)
;R14B	05/31/97 DNL	Fixed coding mistake
;R14A	05/30/97 DNL	Fixed coding mistake
;R21	05/26/97 DNL	Add "No_ZV_Suspend_Beep" definition for customer special
;			request
;R20	05/22/97 RAX	Fix system hang at POST 52 when ZV-suspend function
;			BIOS use JTS C3000-3AF Hdd
;R19	04/17/97 RAX	Patch CHIP VGA ZV-resume screen garbage
;R18	04/15/97 JKY	change save sound & restore sound become zv-suspend
;			always support
;R17A	04/14/97 KVN	Fix system hang at POST during HDD_transfer subroutine
;			when use dual Seagate-ST32132A connect to same channel
;R17	04/10/97 KVN	Fix different mode Hdd connect Master & Slave will hang
;			at HDD_Transfer Routing
;R08B	04/09/97 DNL	Change routine name to solve complier fail
;R16	04/07/97 DNL	Added STD resume password check support
;R15	03/31/97 DNL	Added STD progress percent display
;R14	03/20/97 DNL	Fix when DRAM size above 64M , get Extend DRAM size
;			ERROR, Extended DRAM save to disk will not all clear
;			and when no MODEM , Don't save modem status
;R13	03/12/97 DNL	Let routine "save_chipset","restore_chipset" be public
;R12	03/12/97 DNL	Added codes to support STR function
;R11	03/05/97 DNL	Fixed bug of system halt when resume from STD and
;			C&T65550 VGA installed
;R08A	02/19/97 DNL	Do not save/restore modem state while no modem exist
;R10	02/13/97 DNL	Added VESA BIOS 1.X support
;R09	02/03/97 DNL	FIxed buf of somd VGA chip (like S3) save video state
;			in failure
;R08	02/03/97 DNL	Added codes for save/restore PnP cards,Sound cards,
;			Modem cards
;R07	02/03/97 DNL	Fix When NT restore from save to disk will hang at
;			restore PS/2 mouse
;R06	01/27/97 DNL	Added switch Special_Save_VGA_status to support special
;			customer
;R05	01/13/97 DNL	Added codes for super I/O chip support
;R04	01/06/97 KVN	Added codes for large mode HDD support
;R03	01/06/97 DNL	Added codes for STD & STR function
;R02	12/05/96 DNL	Added revision 4.51PGM for notebook BIOS
;R01	11/01/96 DNL	Added "NEW_SUPERVGA_KERNEL" definition to support
;			notebook VGA chips
;R00	10/01/96 DNL	Move codes of Zero-Volte suspend to E8000-EFFFF to reduce
;			F0000-FFFFF code size. old file save as sus2disk.A01
;----------------------------------------------------------------------------

.386p
		PAGE	56,132
		TITLE	SUS2DISK.ASM   --   Suspend to/resume from DISK Interface
.XLIST
		INCLUDE	BIOS.CFG
		INCLUDE	COMMON.EQU
		INCLUDE	COMMON.MAC
		INCLUDE	POST.MAC
		INCLUDE	BSETUP.INC
		include	CMOS.EQU
		include	akbrd.equ			;R16

;R43 - start
ifdef	ACPI_Support
		extrn	ACPINVSAddress:near		;R38
		extrn	ACPITableAddress:near		;R38
ifdef	S3_SUPPORT					;R40
		extrn	Save_S3_Chipset:near		;R40
endif	;S3_SUPPORT					;R40
ifdef	S4_SUPPORT					;R41
;R60		extrn	Wait_For_Port:near		;R55
		extrn	Wakeup_Device:near		;R41
endif	;S4_SUPPORT					;R41
endif	;ACPI_Support
if	STD_Function		EQ	1
		INCLUDE	8042.EQU
		extrn	Wait_For_Port:near		;R60
		extrn	ExtMem128Mb:near		;R14
		EXTRN	SET_CT:NEAR
		EXTRN	GET_CT:NEAR
		extrn	E000_64K_shadow_R:near
		extrn	Disable_E000_ROM_Shadow:near
		extrn	Get_PM_RAM_Seg:near
		EXTRN	BUFFER_8042_FULL:NEAR
		EXTRN	OUT_8042_FULL:NEAR
		extrn	VIDEO_FUNC:near
		extrn	Save_Ct_device:near
		extrn	Restore_Ct_device:near
		EXTRN	SUSPEND_CHIPSET_TABLE:NEAR
		EXTRN	CT_SMBASE_OFF:NEAR
		EXTRN	CT_SMBASE_ON:NEAR
		EXTRN	Display_String:NEAR
		EXTRN	Enable_CRT:NEAR
		extrn	VGA_Buffer:near
		EXTRN	CT_ALLSHADOW_RW:NEAR
		EXTRN	CT_SKIP_ZV_SHADOW:NEAR
		EXTRN	CT_0V_SHUTDOWN:NEAR
		EXTRN	CT_SYSTEM_WAKEUP:NEAR
		extrn	Display_Char:near
		extrn	AX_To_DEC2:near
		extrn	Show_SIX_DIGIT:near
		EXTRN	GET_SMBASE_SEG:NEAR
		EXTRN	A20_ON:NEAR
		EXTRN	SND_SPKR_TONE:NEAR
ifndef	P6_BIOS_ONLY				;R43A
		extrn	Check_Cyrix_Cpu:near	;R43A
		extrn	Get_Cyrix:near		;R43A
endif	;P6_BIOS_ONLY				;R43A
ifdef	NEW_SUPERIO_KERNEL
		extrn	Suspend_Super_IO:near
		extrn	Restore_Super_IO:near
endif	;NEW_SUPERIO_KERNEL
endif	;STD_Function		EQ	1
;R43 - end

ifdef	Notebook_Power_Management
		INCLUDE	8259.EQU
;R43		INCLUDE	8042.EQU
		INCLUDE	8254.EQU
;R43		extrn	Get_PM_RAM_Seg:near		;PMU.ASM
;R43		EXTRN	Enable_CRT:NEAR
;R43		EXTRN	BUFFER_8042_FULL:NEAR
;R43		EXTRN	OUT_8042_FULL:NEAR
		EXTRN	OUT_AUX:NEAR
;R32		EXTRN	A20_ON:NEAR
;R32B ifdef	Resume_Turn_on_A20				;R32A
;R43		EXTRN	A20_ON:NEAR			;R32A
;R32B endif	;Resume_Turn_on_A20				;R32A
		EXTRN	Multi_Service:near
		EXTRN	Detect_LBA_Mode:near
;R43		EXTRN	Display_String:NEAR
		EXTRN	Get_Color_Off:NEAR
		EXTRN	Check_Display_Mode:NEAR
;R43		EXTRN	SND_SPKR_TONE:NEAR
;R43		EXTRN	SUSPEND_CHIPSET_TABLE:NEAR
;R43		EXTRN	GET_CT:NEAR
;R43		EXTRN	SET_CT:NEAR
;R43		EXTRN	GET_SMBASE_SEG:NEAR
		EXTRN	CT_DISABLE_SMI:NEAR
;R43		EXTRN	CT_0V_SHUTDOWN:NEAR
;R43		EXTRN	CT_SYSTEM_WAKEUP:NEAR
		EXTRN	CT_SAVE_COMA:NEAR
		EXTRN	CT_SAVE_COMB:NEAR
		EXTRN	CT_SAVE_FDC:NEAR
		EXTRN	CT_RESTORE_FDC:NEAR
		EXTRN	CT_SAVE_8259:NEAR
ifdef	NEW_SUPERVGA_KERNEL				;R01
		extrn	Suspend_Vga:near		;R01
		extrn	Resume_Vga:near			;R01
		extrn	Save_VRAM:near			;R01
		extrn	Restore_VRAM:near		;R01
else	;NEW_SUPERVGA_KERNEL				;R01
		EXTRN	CT_SAVE_VGA:NEAR
		EXTRN	CT_RESTORE_VGA:NEAR
endif	;NEW_SUPERVGA_KERNEL				;R01
;R43		EXTRN	CT_ALLSHADOW_RW:NEAR
;R43		EXTRN	CT_SKIP_ZV_SHADOW:NEAR
;R43		EXTRN	CT_SMBASE_OFF:NEAR
;R43		EXTRN	CT_SMBASE_ON:NEAR
		extrn	Set_Full_On_SMM:near
ifndef	NEW_SUPERVGA_KERNEL				;R01
		extrn	Ct_Save_VRAM:near
		extrn	Ct_Restore_VRAM:near
endif	;NEW_SUPERVGA_KERNEL				;R01
;R43		extrn	VIDEO_FUNC:near
;R43		extrn	VGA_Buffer:near
;R41		extrn	ZV_Resume_Byte:ABS
;R43		extrn	E000_64K_shadow_R:near
;R43		extrn	Disable_E000_ROM_Shadow:near
;R43A ifndef	P6_BIOS_ONLY
;R43A 		extrn	Check_Cyrix_Cpu:near
;R43A 		extrn	Get_Cyrix:near
;R43A endif	;P6_BIOS_ONLY
;R43		extrn	Save_Ct_device:near	;R03
;R43		extrn	Restore_Ct_device:near	;R03
ifdef	NEW_SUPERKBC_KERNEL			;R03
		extrn	Suspend_KBC:near	;R03
		extrn	Resume_KBC:near		;R03
endif	;NEW_SUPERKBC_KERNEL			;R03
ifdef	NEW_SUPERIO_KERNEL			;R05
ifndef	DONT_SAVE_SUPER_IO	;R35
;R43		extrn	Suspend_Super_IO:near	;R05
;R43		extrn	Restore_Super_IO:near	;R05
endif	;DONT_SAVE_SUPER_IO	;R35
endif	;NEW_SUPERIO_KERNEL			;R05
	ifdef	Special_Save_VGA_status			;R06
		extrn	Ct_Special_restore_VGA:near	;R06
	endif	;Special_Save_VGA_status		;R06
	ifdef	PNP_BIOS			;R08
	ifndef	NO_ISA_PNP			;R54
	ifndef	ZV_DONT_SAVE_PNP		;R26
		extrn	Suspend_PnP_Device:near	;R08
		extrn	Restore_PnP_Device:near	;R08
	endif	;ZV_DONT_SAVE_PNP		;R26
	endif	;NO_ISA_PNP			;R54
	endif	;PNP_BIOS			;R08
	ifdef	Onboard_Modem_Card		;R08
		extrn	COMM_VECT:far		;R08
	endif	;Onboard_Modem_Card		;R08
;R18	ifdef	AUDIO_KERNEL			;R08
ifndef	No_Save_Sound				;R57
		extrn	Save_Sound:near		;R08
		extrn	Restore_Sound:near	;R08
endif	;No_Save_Sound				;R57
;R18	endif	;AUDIO_KERNEL			;R08
	;R12 - start
	ifndef	NO_STR_SUPPORT
		extrn	Ct_5V_suspend_VGA:near
		extrn	Ct_5V_Resume_VGA:near
		extrn	CT_5V_Shutdown:near
		extrn	Save_5V_Chipset:near
	ifndef	NO_STR_PASSWORD_CHECK			;R16
		extrn	kb_cntrlr_out:near		;R16
		extrn	buffer_8042_full:near		;R16
		extrn	keys:near			;R16
		extrn	kyb_enable:near			;R16
		extrn	KB_Out:near			;R16
		extrn	Ct_Enable_CRT:near		;R16
		extrn	Read_Cmos_To_Stack:near		;R16
		extrn	Fproc_Verify_Password:far	;R16
		extrn	KEYBOARD:near			;R16
	endif	;NO_STR_PASSWORD_CHECK			;R16
	endif	;NO_STR_SUPPORT
	;R12 - end
;R43 ifdef	ACPI_Support
;R43 		extrn	ACPINVSAddress:near		;R38
;R43 		extrn	ACPITableAddress:near		;R38
;R43 ifdef	S3_SUPPORT					;R40
;R43 		extrn	Save_S3_Chipset:near		;R40
;R43 endif	;S3_SUPPORT					;R40
;R43 ifdef	S4_SUPPORT					;R41
;R43 		extrn	Wakeup_Device:near		;R41
;R43 endif	;S4_SUPPORT					;R41
;R43 endif	;ACPI_Support
;R43		extrn	ExtMem128Mb:near		;R14
;R43		extrn	AX_To_DEC2:near			;R15
;R43		extrn	Show_SIX_DIGIT:near		;R15
;R43		extrn	Display_Char:near		;R15
ifdef	Patch_VGA_Resume_Garbage			;R19
		extrn	Disable_CRT:near		;R19
endif	;Patch_VGA_Resume_Garbage			;R19
endif	;Notebook_Power_Management

		extrn	F000_call_proc:near
		extrn	Post_call_proc:near

;R28 - start
ifndef	DONT_RELEASE_E000_FOR_PCI
		extrn	GET_CMOS:near
		extrn	SET_CMOS:near
else	;DONT_RELEASE_E000_FOR_PCI
		extrn	F000_GET_CMOS:near
		extrn	F000_SET_CMOS:near
endif	;DONT_RELEASE_E000_FOR_PCI
;R28 - end
;R32		extrn	Read_A20_Status:near		;R30
;R44A - start
WINBOND_KBC		=	0
ifdef	W83967AF
WINBOND_KBC		=	1
endif	;W83967AF
ifdef	W83977AF
WINBOND_KBC		=	1
endif	;W83977AF
ifdef	W83977ATF
WINBOND_KBC		=	1
endif	;W83977ATF
ifdef	W83977TF
WINBOND_KBC		=	1
endif	;W83977TF
ifdef	W83977EF
WINBOND_KBC		=	1
endif	;W83977EF
;R44A - end
;R44B - start
ifdef	W83627F
WINBOND_KBC		=	1
endif	;W83627F
ifdef	W83627HF
WINBOND_KBC		=	1
endif	;W83627HF
;R44B - end
;R63a	- start
if	STR_Function	EQ	1
if	DESKTOP_POWER_MANAGEMENT	EQ	1
RES_KBD_RESET   	EQU	1
endif	;DESKTOP_POWER_MANAGEMENT	EQ	1
endif	;STR_Function	EQ	1
;R63a   - end		
	 				
G_RAM		SEGMENT	USE16 AT 0

		ORG	04H*4
		INCLUDE	SEG_0.INC

		ORG	400H
		INCLUDE	G_RAM.INC

G_RAM		ENDS

;R43 ifdef	Notebook_Power_Management
SM_RAM		SEGMENT	USE16 AT 0
		INCLUDE	SM_RAM.INC
SM_RAM		ENDS

ZV_Temp_Stack	SEGMENT	USE16 AT 0
		org	1000h
VIDEO_BUFFER	LABEL	WORD
		org	0FFF0h
ZV_STACK_TOP	LABEL	DWORD
ZV_Temp_Stack	ENDS
;R43 endif	;Notebook_Power_Management

PM_RAM		SEGMENT	USE16 AT 0 	; define PM RAM segment

		ORG	0
		INCLUDE	PM_RAM.INC

PM_RAM		ENDS

.LIST

EGROUP		GROUP	ECODE
DGROUP		GROUP	FCODE
FCODE		SEGMENT	USE16 DWORD Public 'CODE'
		ASSUME	CS:DGROUP

;R43 - start
ifdef	ACPI_SUPPORT
if	ACPI_RESUME		EQ	1
		extrn	Sx_Resume_Point:near
endif	;ACPI_RESUME		EQ	1
if	ACPI_CPU_POWEROFF	EQ	1
		PUBLIC	Save_S3_Status
Save_S3_Status	PROC	FAR

		Call	E000_64K_shadow_R
		FAR_Call	<offset E_Save_S3_Status>,<Seg Egroup>
		Call	Disable_E000_ROM_Shadow

		ret
Save_S3_Status	Endp
endif	;ACPI_CPU_POWEROFF	EQ	1

ifdef	S2_SUPPORT
		PUBLIC	Restore_S2_Status
Restore_S2_Status	PROC	FAR

		Call	E000_64K_shadow_R
		FAR_Call	<offset E_Restore_S2_Status>,<Seg Egroup>
		Call	Disable_E000_ROM_Shadow

		ret

Restore_S2_Status	Endp
endif	;S2_SUPPORT

ifdef	S3_SUPPORT
		PUBLIC	Restore_S3_Status
Restore_S3_Status	PROC	FAR

		Call	E000_64K_shadow_R
		FAR_Call	<offset E_Restore_S3_Status>,<Seg Egroup>
		Call	Disable_E000_ROM_Shadow

		ret
Restore_S3_Status	Endp
endif	;S3_SUPPORT

ifdef	S4_SUPPORT
;[]========================================================================[]
;
;	Put system into S4 state.
;
;[]=========================================================================[]

		ASSUME	DS:G_RAM
		Public	Do_S4_Suspend
Do_S4_Suspend	Proc	Far

		Call	E000_64K_shadow_R
		FAR_Call 	<offset E_S4_Suspend>,<Seg Egroup>
		Call	Disable_E000_ROM_Shadow

		ret
Do_S4_Suspend	Endp
;R55 - start
		ASSUME	DS:G_RAM
		Public	WakeUp_VGA
WakeUP_VGA	Proc	Far

		Call	E000_64K_shadow_R
		FAR_Call 	<offset E_WakeUP_VGA>,<Seg E_WakeUP_VGA>
		Call	Disable_E000_ROM_Shadow

		ret
WakeUP_VGA	Endp
;R55 - end
endif	;S4_SUPPORT
endif	;ACPI_SUPPORT
;R43 - end

ifdef	Notebook_Power_Management
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;л
;л	Zero-Volt-Suspend Kernal for NoteBook Power Management
;л
;л	Code for after boot run-time.
;л
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

;R43 ;R40 - start
;R43 ifdef	ACPI_SUPPORT
;R43 if	ACPI_RESUME		EQ	1
;R43 		extrn	Sx_Resume_Point:near
;R43 endif	;ACPI_RESUME		EQ	1
;R43 if	ACPi_CPU_POWEROFF	EQ	1
;R43 		PUBLIC	Save_S3_Status
;R43 Save_S3_Status	PROC	FAR
;R43
;R43 		Call	E000_64K_shadow_R
;R43 		FAR_Call	<offset E_Save_S3_Status>,<Seg Egroup>
;R43 		Call	Disable_E000_ROM_Shadow
;R43
;R43 		ret
;R43 Save_S3_Status	Endp
;R43 endif	;ACPI_CPU_POWEROFF	EQ	1
;R43 ifdef	S2_SUPPORT
;R43 		PUBLIC	Restore_S2_Status
;R43 Restore_S2_Status	PROC	FAR
;R43
;R43 		Call	E000_64K_shadow_R
;R43 		FAR_Call	<offset E_Restore_S2_Status>,<Seg Egroup>
;R43 		Call	Disable_E000_ROM_Shadow
;R43
;R43 		ret
;R43
;R43 Restore_S2_Status	Endp
;R43 endif	;S2_SUPPORT
;R43
;R43 ifdef	S3_SUPPORT
;R43 		PUBLIC	Restore_S3_Status
;R43 Restore_S3_Status	PROC	FAR
;R43
;R43 		Call	E000_64K_shadow_R
;R43 		FAR_Call	<offset E_Restore_S3_Status>,<Seg Egroup>
;R43 		Call	Disable_E000_ROM_Shadow
;R43
;R43 		ret
;R43 Restore_S3_Status	Endp
;R43 endif	;S3_SUPPORT
;R43 ;R41 - start
;R43 ifdef	S4_SUPPORT
;R43 ;[]========================================================================[]
;R43 ;
;R43 ;	Put system into S4 state.
;R43 ;
;R43 ;[]=========================================================================[]
;R43
;R43 		ASSUME	DS:G_RAM
;R43 		Public	Do_S4_Suspend
;R43 Do_S4_Suspend	Proc	Far
;R43
;R43 		Call	E000_64K_shadow_R
;R43 		FAR_Call 	<offset E_S4_Suspend>,<Seg Egroup>
;R43 		Call	Disable_E000_ROM_Shadow
;R43
;R43 		ret
;R43 Do_S4_Suspend	Endp
;R43 endif	;S4_SUPPORT
;R43 ;R41 - end
;R43 endif	;ACPI_SUPPORT
;R43 ;R40 - end

;[]========================================================================[]
;
; Suspend_0V:
;
;	Put system into Zero-Volt-Suspend state.
;
;
;[]=========================================================================[]

		ASSUME	DS:G_RAM
		PUBLIC	Suspend_0V
Suspend_0V	PROC	NEAR

		Call	E000_64K_shadow_R
		FAR_Call	<offset E_Suspend_0V>,<Seg Egroup>
		Call	Disable_E000_ROM_Shadow

		ret

Suspend_0V	ENDP

;[]========================================================================[]
;
; Resume_0V:
;
;	Resume system from Zero-Volt-Suspend.
;
;
;[]=========================================================================[]
		PUBLIC	Resume_0V
Resume_0V	PROC	NEAR

		Call	E000_64K_shadow_R
		Far_Call	<offset E_Resume_0V>,<Seg Egroup>
		Call	Disable_E000_ROM_Shadow

		ret

Resume_0V	ENDP

ifdef	NO_ZV_REALTIME_MESSAGE
;[]========================================================================[]
;Procedure:	ZV_Display_MSG
;
;Function :	To show message for Suspend/Resume.
;
;Input	  :	SI = Resume_ZV_MSG for display resume message.
;		SI = Suspend_ZV_MSG for display suspend message.
;
;Output   :	None
;
;[]========================================================================[]
		public	ZV_Display_MSG
ZV_Display_MSG	proc	near

		push	ds
		push	si

		push	cs
		pop	ds

		mov	bp,sp
		sub	bp,DATAAREASIZE
		mov	byte ptr CALLTYPE[bp],SMM_CALL

		mov	word ptr Color_Offset[bp],offset VGA_Buffer
		mov	byte ptr MONOCHROME[bp],1

		mov	ax,3				; Clear screen
		Call	Video_Func

		mov	si,offset Border_0V_Str
		call	Display_String
		pop	si

		call	Display_String

		pop	ds
		ret
ZV_Display_MSG	endp

;[]========================================================================[]
;
;	Border for suspend/resume message
;
;[]========================================================================[]
ZV_Msg_Start_Y	EQU	8
Border_0V_Str:
			db	V_REVERSE
			db	V_BLINK
		BORDER1	<,0,ZV_Msg_Start_Y+2,79,ZV_Msg_Start_Y+6,1+Empty_Border>
			db	0

;[]========================================================================[]
;
;	Zero-Volt Resume message
;
;[]========================================================================[]
		PUBLIC	Resume_ZV_MSG
Resume_ZV_MSG:
		POS	<,4,ZV_Msg_Start_Y+4>
			db	V_REVERSE
			db	'Your saved system information will now be restored,'
			db	' Please wait .... '
			db	0

ifndef	SMM_Show_String

Resume_From_SMI:
		FAR_JMP	<offset Show_Address>,<Seg Egroup>

;[]===============================================================[]
;Procedure:	Save_SMRAM_State
;
;Function :	Routine to save system SMRAM state
;
;Input    :	DS = PM_RAM
;
;Output   :	None
;[]==================================================================[]
		Public	Save_SMRAM_State
Save_SMRAM_State	Proc	Near

		push	ds
		push	es
		POSt_Func_Call	Get_SMBASE_ADD

		mov	ebx,eax
		xor	ax,ax
		mov	es,ax
		mov	ds,ax
		mov	esi,ebx
		mov	edi,ebx
		add	edi,offset BIOS_Entry_Save
		add	esi,offset Intel_SMM_State
		mov	cx,200h/4
		cld
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B
		pop	es
		pop	ds
		ret
Save_SMRAM_State	Endp

endif	;SMM_Show_String
endif	;NO_ZV_REALTIME_MESSAGE

endif	;Notebook_Power_Management

FCODE		ENDS

ECODE		SEGMENT USE16 PARA PUBLIC 'ECODE'
		ASSUME	CS:EGROUP,DS:G_RAM,ES:EGROUP

;R55 - start
if	STR_function	EQ	1
;R60 - start
Reset_HDD	Proc	Near
		pusha
		xor	si,si			;start from drive 0
Next_Device_Reset:
		cmp	ds:[SECTOR_PER_BLOCK_0+si],0
	        je	Not_Reset_Hdd

		mov	dx,3f6h
                cmp     si, 1			        ;drive 0 & 1 ?
                jbe     short @F
                mov     dl,76h		         	;for drive 2 & 3
@@:
                mov     bl,0a0h				;for drive 0 & 2
                test    si, 1
                jz      short @F
                mov     bl,0b0h	           		;for drive 1 & 3
@@:
		mov	al,4
		out	dx,al

		xor	cx,cx
		loop	$
		mov	al,8
		out	dx,al

		mov	dh,01h
@@:
		mov	al,bl
		out	dx,al
		inc	dl
		in	al,dx
		dec	dl
		test	al,80h
		jnz	short @B

		mov	al,bl
		out	dx,al

		inc	dl
@@:
		in	al,dx
		test	al,80h
		jnz	short @B

		sub	dl,5
		mov	al,ds:[SECTOR_PER_BLOCK_0+si]
		out	dx,al

		add	dl,5
		mov	al,0c6h
		out	dx,al

Not_Reset_HDD:
		inc	si			;next drive
ifndef	No_Support_4_IDE			;R60A
		cmp	si,4
else	;No_Support_4_IDE			;R60A
		cmp	si,2			;R60A
endif	;No_Support_4_IDE			;R60A
		jb	Next_device_Reset

		popa
		ret
Reset_HDD	Endp

Set_PIO_Mode	proc	near

                pusha

		xor	si,si			;start from drive 0
Next_Pio_Mode:
		cmp	ds:[SECTOR_PER_BLOCK_0+si],0	;R60b
	        je	Not_Mode3_Above			;R60b

		xor	cx,cx			;time-out loop
		mov	dx,1f7h
                cmp     si, 1			;drive 0 & 1 ?
                jbe     short @F
                mov     dl,77h			;for drive 2 & 3

		align	4
@@:
		in      al, dx
                newiodelay
		test    al, 80h
		jz	short Ready
		loop	short @B		;time out ?
Ready:

		dec	dx				;dx = 1f6h or 176h
                mov     al,0a0h				;for drive 0 & 2
                test    si, 1
                jz      short @F
                mov     al, 0b0h			;for drive 1 & 3
		align	4
@@:
                out     dx,al

                newiodelay
		inc	dl
		mov	bh,2			;
		mov	cx,33333/2		; 0.5 second time out
		mov	ax,8000h		; check for bit 7 = 0
		call	F000_Wait_For_Port	; wait for not busy
	       	or	ah,ah			;set zero flag => time?
		jnz     Not_Mode3_Above
                sub     dl,6
                mov     al,03h
                out     dx,al
                newiodelay

                inc     dx

;R60b		push	dx
      		push	ds
;R60b		Call	F000_Get_PM_RAM_Seg
		mov	ax,PM_RAM_SEGMENT		;R60b
		mov	ds,ax
		mov	ax,ds:[HDD_PIO_MODE]
		pop	ds
;R60b		pop	dx

		mov	cx,si
		shl	cl,2
		shr	ax,cl
		and	al,0fh
	        cmp     al,3
		jb	short Not_PIO_Mode3_Above
                mov     bl,08h
                add     al,bl
                out     dx,al
                newiodelay

                add     dl,5
                mov     al,0efh
                out     dx,al
                newiodelay
		xor	cx,cx
@@:
		newiodelay
		newiodelay
		loop	@B
		sub	dl,5
Not_PIO_Mode3_Above:
ifdef	Ultra_DMA33_support

;R60b		push	dx
		push	ds
;R60b		Call	F000_Get_PM_RAM_Seg
		mov	ax,PM_RAM_SEGMENT		;R60b
		mov	ds,ax
		mov	al,ds:[Ultra_Dma_Mode]
		pop	ds
;R60b		pop	dx

	        mov	cx,si
		shl	cl,1
		shr	al,cl
 		and	al,00000011b
		cmp	al,3				;not support?
		je	short No_IDE_UDMA_MODE		;Yes,jump next drive
                or	al,40h				;Ultra DMA mode 0=40H
                out     dx,al				;	   mode	1=41H
                newiodelay				;	   mode	2=42H

                add     dl,5
                mov     al,0efh				;set feature command
                out     dx,al
                newiodelay
		xor	cx,cx
@@:
		newiodelay
		newiodelay
		loop	@B
No_IDE_UDMA_MODE:
endif	;Ultra_DMA33_support
Not_Mode3_Above:
		inc	si			;next drive
ifndef	No_Support_4_IDE			;R60A
		cmp	si,4
else	;No_Support_4_IDE			;R60A
		cmp	si,2			;R60A
endif	;No_Support_4_IDE			;R60A
		jb	Next_Pio_Mode

                popa

		ret
Set_PIO_Mode	endp

F000_Wait_For_Port:
		F000_call	Wait_For_Port
		ret
;R60 - end
if	BIOS_SUPPORT_686
Update_P6code	proc	near
		push	ds
		push	ebx

		shr	ebx,4
		mov	ds,bx	  		;point ds:bx
		mov	bx,offset P6_Microcode_Save

		push	ebx
		mov	eax,1			;eax = 1 to read CPU ID
		db	0fh,0A2h		;CPU ID instruction
		pop	ebx

		cmp	ax,word ptr ds:[bx+0ch]	;CPU ID
		jne	short No_patch

		mov	ecx,79H			;CPU register
		xor	eax,eax
		xor	edx,edx
		mov	ax,ds

		shl	eax,4			;segment of data

		add	bx,48			;point to data area
		mov	ax,bx
		WRMSR
No_patch:
		pop	ebx
		pop	ds
		ret
Update_P6code	endp
endif	;BIOS_SUPPORT_686
endif	;STR_function	EQ	1
;R55 - end
;R43 - start
ifdef	ACPI_SUPPORT
if	ACPI_CPU_POWEROFF	EQ	1
		PUBLIC	E_Save_S3_Status
E_Save_S3_Status	PROC	FAR

		push	ds
		push	es

		cld

		Call	Save_8042		;R55
		push	bx			;R55

		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

		pop	cx					;R55
		mov	BYTE PTR es:[ebx+Save_8042_Output],cl	;R55
		mov	BYTE PTR es:[ebx+Save_8042_Command],ch	;R55

	; Save peripherial devices
ifdef	NEW_SUPERKBC_KERNEL			;R51
 		Call	Suspend_KBC		;R51
endif	;NEW_SUPERKBC_KERNEL			;R51

ifdef	NEW_SUPERIO_KERNEL
		Call	Suspend_Super_IO
endif	;NEW_SUPERIO_KERNEL

	; Save chipset state

		Call	Save_Ct_device
		call	Save_Chipset

ifdef	S3_SUPPORT
		call	Save_S3_Chipset
		call	Save_Sensor			;R65
endif	;S3_SUPPORT

	; Save stack pointer & save SMBASE

		pop	es
		pop	ds
		ret

E_Save_S3_Status	ENDP
;R65 - start
Save_Sensor:
ifdef	W83782D_Support
		extrn	Save_W83782D_Status:near
		call	Save_W83782D_Status
endif;	W83782D_Support
		ret
;R65 - end

		PUBLIC	E_Restore_S2_Status
E_Restore_S2_Status	PROC	FAR

		push	ds
		push	es

		cld

		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

		call	PM_Beep

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

		Call	Restore_Sx_SMBASE

		mov	edi,ebx
		add	edi,0ff00h
		xor	eax,eax
		mov	es:[edi],eax		; clear I/O trap & halt restart
		mov	ax,offset DGROUP:Sx_Resume_Point
		mov	es:[edi+0f0h],eax	; IP for exit SMM

	; Restore chipset state

		pop	es
		pop	ds

		ret

E_Restore_S2_Status	Endp

		PUBLIC	E_Restore_S3_Status
E_Restore_S3_Status	PROC	FAR

		push	ds
		push	es

		cld

		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

		call	PM_Beep

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

	; Restore chipset state

;R67		Call	Restore_Sensor			;R65
		call	Restore_Chipset
		Call	Restore_Ct_device
		Call	Restore_Sensor			;R67

if	BIOS_SUPPORT_686				;R55
		Call	Update_P6code			;R55
endif	;BIOS_SUPPORT_686				;R55

	; Restore peripherial devices

ifdef	NEW_SUPERIO_KERNEL
		Call	Restore_Super_IO
endif	;NEW_SUPERIO_KERNEL
ifdef	NEW_SUPERKBC_KERNEL			;R51
		Call	Resume_KBC		;R51
endif	;NEW_SUPERKBC_KERNEL			;R51

		Call	Reset_HDD		;R60
		Call	Set_PIO_Mode		;R60

		mov	al,BYTE PTR es:[ebx+Save_8042_Output]	;R55
		mov	ah,BYTE PTR es:[ebx+Save_8042_Command]	;R55
		push	ax					;R55

		Call	Restore_Sx_SMBASE

		mov	edi,ebx
		add	edi,0ff00h
		xor	eax,eax
		mov	es:[edi],eax		; clear I/O trap & halt restart
		mov	ax,offset DGROUP:Sx_Resume_Point
		mov	es:[edi+0f0h],eax	; IP for exit SMM

		pop	bx					;R55
		call	Restore_8042				;R55
IF	CLKCNTL_KERNEL						;R65A
		extrn	Prg_ClkGen_Chip:near			;R65A
		call	Prg_ClkGen_Chip				;R65A
ENDIF;	CLKCNTL_KERNEL						;R65A
;R65A		extrn	Init_Onboard_Generator:near		;R65
;R65A		call	Init_Onboard_Generator			;R65

		pop	es
		pop	ds

		ret

E_Restore_S3_Status	Endp
;R65 - start
Restore_Sensor:
ifdef	W83782D_Support
		extrn	Restore_W83782D_Status:near
		call	Restore_W83782D_Status
endif;	W83782D_Support
		ret
;R65 - end
Sx_SMBASE	EQU	38000h
Sx_SMBASE1	EQU	3E000h

		Public	Restore_Sx_SMBASE
Restore_Sx_SMBASE	Proc	Near

		push	ds
		push	ebx

		cld
		push	es
		pop	ds

ifNdef	SIS5595_ID					;R62
		mov	esi,ebx
else	;SIS5595_ID                                     ;R62
		mov	esi,0A8000h                     ;R62
endif	;SIS5595_ID                                     ;R62

		mov	edi,offset Sx_SMBASE
		mov	cx,3000h/4			;restore 12K
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

		mov	edi,offset Sx_SMBASE1
		mov	cx,2000h/4			;restore 8K
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

		pop	ebx
		pop	ds

		ret
Restore_Sx_SMBASE	Endp
endif	;ACPI_CPU_POWEROFF	EQ	1
ifdef	S4_SUPPORT
;[]========================================================================[]
;
;	Put system into S4 state.
;
;[]=========================================================================[]

		ASSUME	DS:G_RAM
		Public	E_S4_Suspend
E_S4_Suspend	Proc	Far

		pushad
		push	ds
		push	es
		push	fs
		push	gs

		cld

		call	Save_8042
		push	bx
		in	al,92h			; get a20 states
		push	ax
		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

	; Save port 92H status

		pop	ax
		pop	cx
		push	cx
		push	ax
		mov	BYTE PTR es:[ebx+Save_8042_Output],cl
 		mov	BYTE PTR es:[ebx+Port92_Save],al

	; Turn off speaker & save port 61H

		in	al,61h				; save port_b status
		mov	BYTE PTR es:[ebx+Port61_Save],al
		and	al,0fch				; turn off speaker
		out	61h,al

	; Save chipset state

		Call	Save_Ct_device
		call	Save_Chipset
		call	Wakeup_Device

	; Save peripherial devices

ifdef	NEW_SUPERIO_KERNEL
		Call	Suspend_Super_IO
endif	;NEW_SUPERIO_KERNEL
if	BIOS_SUPPORT_686
		Call	Check_P6_A20_Status
endif	;BIOS_SUPPORT_686

	; Save all memory data

		mov	ax,ZV_Temp_Stack
		call	Save_BASEMem			; Save for temp stack

		call	Disable_SMM_Map
		Call	Suspend_Status
		call	Save_Base_DRAM
		call	Save_Ext_DRAM
		call	Save_Shadow
		call	Enable_SMM_Map

	; Save stack pointer & save SMBASE

		mov	word ptr es:[ebx+SS_Save],ss
		mov	dword ptr es:[ebx+ESP_Save],esp
		call	Save_S4_SMBASE

	; Shutdown byte with NMI off

		mov	al,0Fh NMI_OFF
		mov	ah,S4_Resume_Byte
		call	E_Set_CMOS

ifdef	ZV_Suspend_Beep_loop
		mov	cx,ZV_Suspend_Beep_loop
;R43B Suspend_Beep_loop:
Suspend_Beep_loop1:
		push	cx
		call	PM_Beep
		pop	cx
;R43B		loop	Suspend_Beep_loop
		loop	Suspend_Beep_loop1		;R43B
else	;ZV_Suspend_Beep_loop
ifndef	No_ZV_Suspend_Beep
		call	PM_Beep
		call	PM_Beep
		call	PM_Beep
		call	PM_Beep
		call	PM_Beep
endif	;No_ZV_Suspend_Beep
endif	;ZV_Suspend_Beep_loop

		POST_CODE	66h

	; Begin to Shutdown the system

		call	CT_0V_Shutdown
	@@:
		call	PM_Beep
		jmp	short @B

E_S4_Suspend	Endp

;[]========================================================================[]
;Procedure:	Save_S4_SMBASE
;
;Function :	Save SMBASE for the CPU was reseted by chipset
;		during system reume.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;[]========================================================================[]
Save_S4_SMBASE	PROC	NEAR

		push	es
		push	ds
		push	ebx

		push	es
		pop	ds
		mov	esi,ebx
		add	esi,offset SMI_Entry

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_SMBASE_Sector
		mov	ah,30h			; Write command
		mov	al,(26*1024)/512	; Sector Count
		call	HDD_Transfer

		pop	ebx
		pop	ds
		pop	es

		ret
Save_S4_SMBASE	ENDP

;[]========================================================================[]
;
;	Put system into S0 state.
;
;[]=========================================================================[]

		Public	E_S4_Resume
E_S4_Resume	PROC	FAR

		cld

	; Clear shutdown byte with NMI off

		mov	al,0Fh NMI_OFF
		mov	ah,0
		call	E_Set_CMOS

	; Turn off speaker

		in	al,61h
		and	al,0fch				; turn off speaker
		or	al,0ch
		out	61h,al

		call	CT_System_Wakeup
		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

ifndef	No_ZV_Suspend_Beep
		call	PM_Beep
endif	;No_ZV_Suspend_Beep

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

	; Restore all memory data

		call	Restore_S4_SMBASE
		call	Disable_SMM_Map
		Call	Resume_Status
		call	Restore_Shadow
		call	Restore_Ext_DRAM
		call	Restore_Base_DRAM
		Call	Sx_Clear_Screen
		call	Enable_SMM_Map

	; Restore for temp stack area

		mov	ax,ZV_Temp_Stack
		call	Restore_BASEMem

	; Restore chipset state

		call	Restore_Chipset
		Call	Restore_Ct_device

	; Restore peripherial devices

ifdef	NEW_SUPERIO_KERNEL
		Call	Restore_Super_IO
endif	;NEW_SUPERIO_KERNEL

		mov	al,BYTE PTR es:[ebx+Port61_Save]
		out	61h,al

	; Restore stack pointer

		mov	ss,word ptr es:[ebx+SS_Save]
		mov	esp,dword ptr es:[ebx+ESP_Save]

	; Set restore address

		mov	edi,ebx
		add	edi,0ff00h
		xor	eax,eax
		mov	es:[edi],eax		; clear I/O trap & halt restart
		mov	ax,Seg Dgroup
		mov	es:[edi+0ach],eax	; CS for exit SMM
		mov	ax,offset DGROUP:Sx_Resume_Point
		mov	es:[edi+0f0h],eax	; IP for exit SMM

		pop	ax
		out	92h,al
		pop	bx
 		call	Restore_8042

		pop	gs
		pop	fs
		pop	es
		pop	ds
		popad

		ret
E_S4_Resume	ENDP

Sx_Clear_Screen:
		push	ebx
		mov	ax,3				; Clear screen
		F000_Call	Video_Func
		pop	ebx
		ret

;[]========================================================================[]
;Procedure:	Restore_S4_SMBASE
;
;Function :	Restore SMBASE for the CPU was reseted by chipset
;		during system reume.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;[]========================================================================[]
Restore_S4_SMBASE	Proc	Near

		pop	ebp

		mov	ax,ZV_Temp_Stack
		mov	ss,ax
		mov	esp,offset ZV_STACK_TOP

		push	es
		push	ebx

		mov	edi,ebx
		add	edi,offset SMI_Entry

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_SMBASE_Sector
		mov	ah,20h			; Read command
		mov	al,(26*1024)/512	; Sector Count
		call	HDD_Transfer

		pop	ebx
		pop	es
		mov	esp,dword ptr es:[ebx+ESP_Save]
		mov	ax,word ptr es:[ebx+SS_Save]
		mov	ss,ax

		push	ebp

		ret
Restore_S4_SMBASE	Endp
;R55 - start
		Public	E_WakeUP_VGA
E_WakeUP_VGA	PROC	far
		pusha

		xor	ax,ax
		mov	al,ds:[VGA_DEV_ID]
		cmp	al,0ffh
		je	No_Restore_VGA
		shl	ax,11  			;Device NUM
		add	ax,01			;Device ID
		mov	cx,ax

		mov	bl,ds:[VGA_SLOT_ID]
		call	Get_PCI1
		mov	bl,al
		push	bx

		sub	cx,1			;Device ID 0h
		mov	bl,ds:[VGA_SLOT_ID]
		call	Get_PCI1
		pop	bx
				
		mov	ah,bl
		push	ax			;R63
;R63		cmp	ax,1002h
;R63		jne	No_Restore_VGA

ifdef	AGP_SLOTID
		cmp	byte ptr ds:[VGA_SLOT_ID],0
		je	Is_slot0
		push	cx
		mov	cx,( AGP_SLOTID shl 8 ) + 04h
		mov	al,07h
		F000_call	Set_CT

		mov	cx,( AGP_SLOTID shl 8 ) + 1ch
		mov	al,byte ptr ds:[AGP_IO_ADD]
		F000_call	Set_CT

		mov	cx,( AGP_SLOTID shl 8 ) + 1dh
		mov	al,byte ptr ds:[AGP_IO_ADD]
		F000_call	Set_CT

		mov	cx,( AGP_SLOTID shl 8 ) + 3eh
		mov	al,088h
		F000_call	Set_CT

		pop	cx
Is_slot0:
endif	;AGP_SLOTID
		add	cx,04h	 		;04h
		mov	bl,ds:[VGA_SLOT_ID]
		call	Get_PCI1

		or	al,07h			;Enable IO/MEM
		mov	bl,ds:[VGA_SLOT_ID]
		call	Set_PCI1

		pop	ax			;R63
		cmp	ax,1002h		;R63
;R63a		jne	_EndWakeUpVGA		;R63
     		jne	No_Restore_VGA		;R63a
													
		add	cx,11h	 		;15h
		mov	bl,ds:[VGA_SLOT_ID]
		mov	al,ds:[VGA_IO_ADD]
		call	Set_PCI1

		mov	ax,0a010h		;ATI Special Function call
		mov	cl,0
		F000_call	Video_Func

		mov	ax,0a00ch		;ATI Special Function call
		mov	cl,0
		F000_call	Video_Func

		mov	ax,0a00eh		;ATI Special Function call
		mov	cl,0
		F000_call	Video_Func
			
		jmp	_EndWakeUpVGA          ;R61
			
No_Restore_VGA:

;R61 - starts
ifdef	SHARE_SIS6306
		;-----------------------------
		;P2P Bridge
		mov	ch,AGP_SLOTID
		mov	cl,4			;Command Reg
		mov	al,07h
		mov	bl,0
		call	Set_PCI1
		;-----------------------------
		mov	ch,AGP_SLOTID
		mov	cl,1ch                  ;I/O Base Reg
		mov	al,0c0h
		mov	bl,0
		call	Set_PCI1

		mov	ch,AGP_SLOTID
		mov	cl,1dh                  ;I/O Limit Reg
		mov	al,0c0h
		mov	bl,0
		call	Set_PCI1

		mov	ch,AGP_SLOTID
		mov	cl,3eh			;P2P Control Reg
		mov	al,008h
		mov	bl,0
		call	Set_PCI1

		;-----------------------------
		;P2P VGA
		mov	ch,(0 SHL 3)
		mov	cl,4                    ;Command Reg
		mov	al,07h
		mov	bl,1
		call	Set_PCI1

		mov	ch,(0 SHL 3)
		mov	cl,13h                  ;IO Address
		mov	al,0e4h
		mov	bl,1
		call	Set_PCI1

		mov	ch,(0 SHL 3)
		mov	cl,34h			;Get PM base
		mov	bl,1
		call	Get_PCI1
		add	al,4			;Add PM offset
		mov	cl,al
		call	Get_PCI1		;Get PM Status
		and	al, NOT 03h             ;Clear PM Bit
		call	Set_PCI1                ;
		;-----------------------------
		;VESA Function
	       	mov	ax,04f10h		;
	       	mov	bx,0001h                ;
	       	F000_call	Video_Func      ;Turn On Video

		jmp	_EndWakeUpVGA
endif	;SHARE_SIS6306

	_EndWakeUpVGA:		
						
;R63a		;VESA Function
;R63a	       	mov	ax,04f10h		;R63
;R63a	       	mov	bx,0001h                ;R63
;R63a	       	F000_call	Video_Func      ;R63Turn On Video
			
;R61 - starts

		popa
		retf
E_WakeUp_VGA	Endp
		public	GET_PCI1
GET_PCI1:
CONFIG_ADDR	EQU	0cf8h
		mov	ax,8000H	;enable PCI config.
		or	al,bl
		shl	eax,16
		mov	ax,cx
		and	al,NOT 03h	;32 bit access for PCI
		mov	dx,CONFIG_ADDR	;index is 0cf8h
		out	dx,eax
		add	dl,4		;start from 0cfch
		mov	al,cl
		and	al,03h
		add	dl,al	  	;byte index to read
		in	al,dx
		ret
		public	SET_PCI1
SET_PCI1:
		xchg	ax,cx
		shl	ecx,16		;save value
		xchg	ax,cx		;restore cx
		mov	ax,8000H	;enable PCI config.
		or	al,bl
		shl	eax,16
		mov	ax,cx
		and	al,NOT 03h	;32 bit access for PCI
		mov	dx,CONFIG_ADDR	;index is 0cf8h
		out	dx,eax
		add	dl,4		;start from 0cfch
		mov	al,cl
		and	al,03h
		add	dl,al	  	;byte index to read

		mov	eax,ecx
		shr	eax,16

		out	dx,al
		ret
;R55 - end
endif	;S4_SUPPORT
endif	;ACPI_SUPPORT

if	STD_Function		EQ	1

Show_Base_Percent	Proc	Near

		pushad

		shr	ax,12
		mov	bl,10
		mul	bl
		jmp	short Show_Percent

Show_Base_Percent	Endp

Show_Ext_Percent	Proc	Near

		pushad

		mov	ax,word ptr PAGE_START[bp]
		sub	ax,cx
		inc	ax
		mov	bx,100
		mul	bx
		mov	bx,word ptr PAGE_START[bp]
		div	bx
Show_Percent:
		mov	byte ptr CURSOR_X[bp],58
;R52A		F000_call	AX_To_DEC2
		call	SMM_AX_To_DEC2			;R52A
;R52A		F000_Call	Show_SIX_DIGIT
		call	SMM_Show_SIX_DIGIT
		mov	al,'%'
;R52A		F000_call	Display_Char
		call	SMM_Display_Char		;R52A
Show_Percent_Exit:
		popad
		ret
Show_Ext_Percent	Endp

;[]========================================================================[]
;Procedure:	Restore_Shadow
;
;Function :	Restore Shadow RAM C0000h-FFFFFh
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	DS,ES
;
;Note	  :	Called by Resume_0V
;[]========================================================================[]
Restore_Shadow	PROC	NEAR
		push	ds
		push	es
		push	ebx

		mov	al,1
		call	CT_AllShadow_RW

		mov	ax,0c000h
	@@:
		call	CT_Skip_ZV_Shadow
		je	short Skip_ZV_Shadow_Restore

		call	Restore_BASEMem

Skip_ZV_Shadow_Restore:

		add	ax,1000h
		cmp	ax,0000h
		jne	short @B

		pop	ebx
		pop	es
		pop	ds
		ret
Restore_Shadow	ENDP

;[]========================================================================[]
;Procedure:	Restore_BASEMem
;
;Function :	Restore Base DRAM (below 1M) from HDD.
;
;Input	  :	AX = Base memory segment for restore.
;
;Output   :	None
;
;Preserve :	DS,ES
;
;Note	  :	1. System is in SMM.
;		2. Save location = start location + 32KB + AX shl 4
;
;[]========================================================================[]
Restore_BASEMem	PROC	NEAR

	; Restore Memory 00000h-0ffffh

		push	ds
		push	es
		push	ax
		push	ebx

		mov	es,ax

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_BASEMEM_Sector
		shr	ax,5
		and	eax,0780h
		add	ebx,eax			; Start sector

		xor	edi,edi
		mov	ah,20h			; Read command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer
		pop	ebx
		pop	ax
		pop	es
		pop	ds

		ret
Restore_BASEMem	ENDP

;[]========================================================================[]
;Procedure:	Restore_Base_DRAM
;
;Function :	Restore Base DRAM (640K) from HDD.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	All
;
;Note	  :	1. System is in SMM.
;		2. called by Resume_0V
;
;[]========================================================================[]
Restore_Base_DRAM	proc	near

ifndef	NO_ZV_REALTIME_MESSAGE
		push	ebx
		mov	si,offset Base_Mem_POS
		Call	Show_Transfer_MSG
endif	;NO_ZV_REALTIME_MESSAGE

		mov	ax,0000h
	@@:
		cmp	ax,ZV_Temp_Stack	; If this segment is current
		je	short skip_Restore_Base	; Stack then skip restore it.
		call	Restore_BASEMem
skip_Restore_Base:
		add	ax,1000h
ifndef	NO_ZV_REALTIME_MESSAGE
		Call	Show_Base_Percent
endif	;NO_ZV_REALTIME_MESSAGE
		cmp	ax,0a000h
		jb	short @B

ifndef	NO_ZV_REALTIME_MESSAGE
		mov	si,offset Base_Mem_POS
		Call	Transfer_OK_MSG
		pop	ebx
endif	;NO_ZV_REALTIME_MESSAGE
		ret
Restore_Base_DRAM	endp

;[]========================================================================[]
;Procedure:	Restore_Ext_DRAM
;
;Function :	Restore Extended memory from HDD.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	All
;
;Note	  :	1. System is in SMM.
;		2. called by Resume_0V
;		3. Extended memory save location = start location + 1536KB
;
;[]========================================================================[]
Restore_Ext_DRAM	proc	near

		push	ds
		push	es
		push	ebx

ifndef	NO_ZV_REALTIME_MESSAGE
		mov	si,offset Ext_Mem_POS
		Call	Show_Transfer_MSG
endif	;NO_ZV_REALTIME_MESSAGE

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_EXTMEM_Sector	; Start sector

	; Get extended memory size

		call	Get_EXT_Memory

		mov	edi,1024*1024
		xor	ax,ax
		mov	es,ax
	@@:
		mov	ah,20h				; Read command
		mov	al,(64*1024)/512		; Sector Count
		call	HDD_Transfer
		add	ebx,(64*1024)/512
		add	edi,64*1024
ifndef	NO_ZV_REALTIME_MESSAGE
		Call	Show_ext_Percent
endif	;NO_ZV_REALTIME_MESSAGE
		loop	short @B

ifndef	NO_ZV_REALTIME_MESSAGE
		mov	si,offset Ext_Mem_POS
		Call	Transfer_OK_MSG
endif	;NO_ZV_REALTIME_MESSAGE
		pop	ebx
		pop	es
		pop	ds

		ret
Restore_Ext_DRAM	endp

;[]========================================================================[]
;Procedure:	Get_EXT_Memory
;
;Function :	To return extended memory size.
;
;Input	  :	None
;
;Output   :	CX = Extended memory size (K Byte).
;
;[]========================================================================[]

		Public	Get_EXT_Memory
Get_EXT_Memory	proc	near
		push	es
		mov	si,seg ExtMem128Mb
		mov	es,si
		mov	si,offset ExtMem128Mb
		mov	ecx,dword ptr es:[si+08h]
ifdef	ACPI_Support
		mov	si,offset ACPITableAddress
		cmp	dword ptr es:[si],-1
		je	short ACPI_off
		add	ecx,dword ptr es:[si+08h]
		mov	si,offset ACPINVSAddress
		add	ecx,dword ptr es:[si+08h]
ACPI_off:
endif	;ACPI_Support
		shr	ecx,16				;64K block
		mov	word ptr PAGE_START[bp],cx
		pop	es
		ret
Get_EXT_Memory	endp

;[]========================================================================[]
;Procedure:	Disable_SMM_Map
;
;Function :	Disable SMBASE map function for access the memory which
;		locate same with SMBASE.
;
;Input	  :	None
;
;Output   :	None
;
;Note     :	The memory is unvisible within SMM mode when the location is
;		same with SMBASE.
;	     **	We must assign new stack (0000-0FFFF) in here because
;		the SMBASE is disable.
;
;[]========================================================================[]
		public	Disable_SMM_Map		;R66
Disable_SMM_Map	proc	near

		pop	ebp			; save return address

		mov	dx,ss
		mov	ecx,esp

		mov	ax,ZV_Temp_Stack
		mov	ss,ax			; New stack pointer
		mov	esp,offset ZV_STACK_TOP	; = 0000H:FFF0H

		push	dx
		push	ecx

	; Disable SMBASE

		call	CT_SMBASE_Off

		push	ebp			; Restore return address

		ret
Disable_SMM_Map	endp

;[]========================================================================[]
;Procedure:	Enable_SMM_Map
;
;Function :	Re-enable SMBASE map function for access the memory which
;		locate same with SMBASE.
;
;Input	  :	None
;
;Output   :	None
;
;Note	  :  **	We must assign old stack in here.
;
;[]========================================================================[]
		public	Enable_SMM_Map		;R66
Enable_SMM_Map	proc	near

		pop	ebp			; save return address

	; Enable SMBASE

		call	CT_SMBASE_On

	; Assign old stack pointer

		pop	ecx
		pop	dx
		mov	ss,dx
		mov	esp,ecx

		push	ebp			; Restore return address

		ret

Enable_SMM_Map	endp

;[]========================================================================[]
;Procedure:	Save_Shadow
;
;Function :	Save Shadow RAM C0000h-FFFFFh
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;Note	  :	Called by Suspend_0V
;[]========================================================================[]
Save_Shadow	PROC	NEAR
		push	ds
		push	es
		push	ebx

		mov	al,0
		call	CT_AllShadow_RW

		mov	ax,0c000h
	@@:
		call	CT_Skip_ZV_Shadow
		je	short Skip_ZV_Shadow_Save

		call	Save_BASEMem

Skip_ZV_Shadow_Save:

		add	ax,1000h
		cmp	ax,0000h
		jne	short @B

		pop	ebx
		pop	es
		pop	ds
		ret
Save_Shadow	ENDP

;[]========================================================================[]
;Procedure:	Save_BASEMem
;
;Function :	Save Base DRAM (below 1M) to HDD.
;
;Input	  :	AX = Base memory segment for save.
;
;Output   :	None
;
;Preserve :	DS,ES
;
;Note	  :	1. System is in SMM.
;		2. Save location = start location + 32KB + AX shl 4
;
;[]========================================================================[]
Save_BASEMem	PROC	NEAR
		push	ds
		push	es
		push	ax
		push	ebx

		mov	ds,ax

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_BASEMEM_Sector
		shr	ax,5
		and	eax,0780h
		add	ebx,eax			; Start sector

		xor	esi,esi
		mov	ah,30h			; Write command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer

		pop	ebx
		pop	ax
		pop	es
		pop	ds
		ret
Save_BASEMem	ENDP

;[]========================================================================[]
;Procedure:	Save_Base_DRAM
;
;Function :	Save Base DRAM (640K) to HDD.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ALL
;
;Note	  :	1. System is in SMM.
;		2. called by Suspend_0V
;[]========================================================================[]
Save_Base_DRAM	proc	near

ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE
ifndef	NO_ZV_REALTIME_MESSAGE
		push	ebx
		mov	si,offset Base_Mem_POS
		Call	Show_Transfer_MSG
endif	;NO_ZV_REALTIME_MESSAGE
endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE

		mov	ax,0000h
	@@:
		cmp	ax,ZV_Temp_Stack	; If this segment is current
		je	short skip_Save_Base	; Stack then skip save it.
		call	Save_BASEMem
skip_Save_Base:
		add	ax,1000h
ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE
ifndef	NO_ZV_REALTIME_MESSAGE
		Call	Show_Base_Percent
endif	;NO_ZV_REALTIME_MESSAGE
endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE
		cmp	ax,0a000h
		jb	short @B

ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE
ifndef	NO_ZV_REALTIME_MESSAGE
		mov	si,offset Base_Mem_POS
		Call	Transfer_OK_MSG
		pop	ebx
endif	;NO_ZV_REALTIME_MESSAGE
endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE

		ret
Save_Base_DRAM	endp

;[]========================================================================[]
;Procedure:	Save_Ext_DRAM
;
;Function :	Save Extended memory to HDD.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	All
;
;Note	  :	1. System is in SMM.
;		2. Called by Suspend_0V.
;		3. Extended memory save location = start location + 1536KB
;
;[]========================================================================[]

Save_Ext_DRAM	proc	near

		push	es
		push	ds
		push	ebx

ifndef	NO_ZV_REALTIME_MESSAGE
		mov	si,offset Ext_Mem_POS
		Call	Show_Transfer_MSG
endif	;NO_ZV_REALTIME_MESSAGE

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_EXTMEM_Sector

	; Get extended memory size

		call	Get_EXT_Memory

		mov	esi,1024*1024
		xor	ax,ax
		mov	ds,ax
	@@:
		mov	ah,30h			; Write command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer
		add	ebx,(64*1024)/512
		add	esi,64*1024
ifndef	NO_ZV_REALTIME_MESSAGE
		Call	Show_ext_Percent
endif	;NO_ZV_REALTIME_MESSAGE
		loop	short @B

ifndef	NO_ZV_REALTIME_MESSAGE
		mov	si,offset Ext_Mem_POS
		Call	Transfer_OK_MSG
endif	;NO_ZV_REALTIME_MESSAGE
		pop	ebx
		pop	ds
		pop	es

		ret
Save_Ext_DRAM	endp

;[]===============================================================[]
;
; Save_Chipset:
;
;		Routine to Save chipset register for suspend.
;
; Saves    :	ES,DS
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
;[]==================================================================[]
		Public	Save_Chipset			;R13
Save_Chipset	proc	near

		push	ebx
		mov	edi,ebx
		add	edi,offset Chipset_State_Save
		mov	si,offset Suspend_Chipset_Table

		cld
Save_Chipset_Loop:

		mov	cx,word ptr cs:[si]
		mov	bx,word ptr cs:[si+2]
		cmp	cx,0ffffh
		je	short End_Save_Chipset
	@@:
		F000_call	Get_CT
		stos	byte ptr es:[edi]
		inc	cx
		dec	bx
		jne	short @B
		add	si,4
		jmp	short Save_Chipset_Loop

End_Save_Chipset:
		pop	ebx
		ret
Save_Chipset	endp

;[]===============================================================[]
;
; Restore_Chipset:
;
;		Routine to restoree chipset register for resume.
;
; Saves    :	ES,DS
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
;[]==================================================================[]
		Public	Restore_Chipset
Restore_Chipset	proc	near

		push	ds
		push	ebx

		push	es
		pop	ds
		mov	esi,ebx
		add	esi,offset Chipset_State_Save
		mov	di,offset Suspend_Chipset_Table

Restore_Chipset_Loop:

		mov	bx,word ptr cs:[di+2]
		mov	cx,word ptr cs:[di]
		cmp	cx,0ffffh
		je	short End_Restore_Chipset
	@@:
		lods	byte ptr ds:[esi]
		F000_call	Set_CT
		inc	cx
		dec	bx
		jne	short @B
		add	di,4
		jmp	short Restore_Chipset_Loop

End_Restore_Chipset:

		pop	ebx
		pop	ds
		ret
Restore_Chipset	endp

F000_Buffer_8042_Full:
		F000_Call	Buffer_8042_Full
		ret
F000_Out_8042_Full:
		F000_call	Out_8042_Full
		ret
F000_A20_ON:
		F000_Call	A20_ON
		ret

if	BIOS_SUPPORT_686
Check_P6_A20_Status	Proc	Near

		mov	ah,P6_A20_Status	;assume A20 is high
		mov	al,byte ptr es:[ebx+Port92_Save]
		test	al,02h
		jnz	short A20M_Is_High

		mov	al,byte ptr es:[ebx+Save_8042_Output]
		test	al,02h
		jnz	short A20M_Is_High

		xor	ah,ah			;A20 is low
A20M_Is_High:
		mov	al,P6_A20_CMOS NMI_OFF
		call	E_Get_CMOS
		and	al,not P6_A20_Status
		or	ah,al
		mov	al,P6_A20_CMOS NMI_OFF
		call	E_Set_CMOS

		ret
Check_P6_A20_Status	endp
endif	;BIOS_SUPPORT_686

;[]=======================================================================[]
;
; Save_8042:
;
; 		This routine is used to save the status of the keyboard
;		before power off.
;
; Saves :	all but flags
;
; Input :	ES = G_RAM
;		DS = PM Save area
;
; Output :	None
;
;[]=======================================================================[]
		ASSUME	DS:G_RAM
Save_8042	Proc	Near

	; Clear 8042 Output Buffer.

		call	Clear_8042_OBF

	; Save 8042 Command Byte.

		mov	al,020h		;Read Command Byte
		out	064h,al
	@@:
		in	al,064h
		test	al,02h		;InputBuffer Full
		jnz	short @B
	@@:
		in	al,064h
		test	al,01h		;OutputBuffer Full
		jz	short @B
		in	al,060h
		mov	bh,al

	; Save 8042 Output Port state.

		mov	al,0D0h		;Read output port
		out	064h,al
	@@:
		in	al,064h
		test	al,02h		;InputBuffer Full
		jnz	short @B
	@@:
		in	al,064h
		test	al,01h		;OutputBuffer Full
		jz	short @B
		in	al,060h
;R44A ifdef		W83977AF					;R44
if	WINBOND_KBC	EQ	1			;R44A
		or	al,02h
endif	;WINBOND_KBC	EQ	1			;R44A
;R44A endif		;W83977AF					;R44
		mov	bl,al

	; Disable 8042 A20 gate line for reset.

		mov	al,0FDh		;Pulse A20 low to high
		out	064h,al		;at KBC
	@@:
		in	al,064h
		test	al,02h		;InputBuffer Full
		jnz	short @B


		ret
Save_8042	Endp

;[]=======================================================================[]
; Restore_8042:
;
; 		This routine is used to restore the status of the
;		keyboard when system resume .
;
; Saves :	all but flags
;
; Input :	ES = G_RAM
;		DS = PM Save area
;
; Output :
;
;[]=======================================================================[]
		ASSUME	DS:G_RAM
Restore_8042	PROC	NEAR

Reset_8042:

		call	Clear_8042_OBF		; Clear 8042 OBF,IBF

IFDEF	RES_KBD_RESET
  	
	; Soft reset the 8042.

		mov	al,0AAH
		out	64H,al

		call	F000_Buffer_8042_Full
		jnz	short Reset_8042

	; Wait for response in Output Buffer limit up to 25mS.

		call	F000_Out_8042_Full
		jz	short Reset_8042

		in	al,60H
		cmp	al,55H				;Is It Successful ?
		jnz	short Reset_8042

ENDIF	;RES_KBD_RESET

	; Restore 8042 Output Port.

		mov	al,0D1H
		out	64H,al
		call	F000_Buffer_8042_Full

		mov	al,bl
		out	60H,al
		call	F000_Buffer_8042_Full
		jnz	short RESET_8042

	; Restore 8042 Command Byte.

		mov	al,60H
		out	64H,al
		call	F000_Buffer_8042_Full

		mov	al,bh
		out	60H,al
		call	F000_Buffer_8042_Full
		jnz	short RESET_8042

	; Enable the keyboard interface.

		mov	al,0AEH
		out	64H,al
		call	F000_Out_8042_Full
		in	al,60H

IFDEF	RES_KBD_SELF_TEST

;---------------------------------------------------------------------------
;
;	8042 is now functioning, reset keyboard.
;
;---------------------------------------------------------------------------

		call	F000_Buffer_8042_Full

		mov	al,0FFH				;KYBRST = 0FFH.
		out	60H,al

	; Wait for ACK response.

		call	F000_Out_8042_Full
		in	al,60H

	; Wait for BAT Completion Code response up to 500mS.

		call	F000_Out_8042_Full
		in	al,60H

ENDIF	;RES_KBD_SELF_TEST


IFNDEF	RES_NO_KBD_LED_UPDATE
;---------------------------------------------------------------------------
;
;	Restore keyboard LED's.
;	Note: this should be fixed when 8042 support
;	is available to read flags.
;	Recover flags in BIOS data area.
;
;---------------------------------------------------------------------------

		mov	al,G_RAM:[SHFT_STAT]

		shr	al,4
		and	al,07h
		push	ax

	; Issue Set Mode Command.

		call	F000_Buffer_8042_Full
		mov	al,0EDH				;Set mode indicators = 0EDH.
		out	60H,al

	; Wait for ACK response.

		call	F000_Out_8042_Full
		in	al,60H

	; Write option byte.

		call	F000_Buffer_8042_Full
		pop	ax
		out	60h,al

	; Wait for ACK response.

		call	F000_Out_8042_Full
		in	al,60H

ENDIF	;RES_NO_KBD_LED_UPDATE

Clear_8042_OBF:

	; Clear 8042 Output Buffer.

		in	al,60h
		mov	cx,02000h
		call	Small_Delay

		in	al,STAT8042
		test	al,OBF_8042
		jnz	short Clear_8042_OBF

		ret

Restore_8042	ENDP

;[]===============================================================[]
;Procedure:	Large_Delay
;Function :	Delay loop
;Input    :	AX = delay loop count.
;Output   :	None
;Preserve :	ALL
;[]===============================================================[]
		Public	Large_Delay
Large_Delay	PROC	NEAR

		push	ax
		push	cx

Large_Delay_Loop:
		mov	cx,4000h
	@@:
		NEWIODELAY
		loop	short @B
		dec	ax
		jnz	short Large_Delay_Loop

		pop	cx
		pop	ax

		ret
Large_Delay	ENDP

;[]===============================================================[]
;Procedure:	Small_Delay
;Function :	Delay loop
;Input    :	CX = delay loop count.
;Output   :	None
;Preserve :	ALL
;[]===============================================================[]
Small_Delay	Proc	Near
		push	cx
	@@:
		NEWIODELAY
		loop	short @B
		pop	cx
		ret
Small_Delay	Endp

PM_Beep		Proc	Near

ifdef	Beep_Len
		mov	bl,Beep_Len
else	;Beep_Len
		mov	bl,8
endif	;Beep_Len
		mov	cx,350h
		F000_call	SND_SPKR_TONE
	@@:
		NEWIODELAY
		NEWIODELAY
		loop	@B

		ret

PM_Beep		Endp

		Public	Get_SMBASE_ADD
Get_SMBASE_ADD	Proc	Near

ifndef	P6_BIOS_ONLY
		F000_call	Check_Cyrix_Cpu
		jnz	short Not_Cy

		push	cx

		mov	cl,0CDh
		Call	F000_Get_Cyrix
		mov	bh,al

		mov	cl,0CEh
		Call	F000_Get_Cyrix
		mov	bl,al
		shl	ebx,16

		mov	cl,0CFh
		Call	F000_Get_Cyrix
		and	al,0F0h
		mov	bh,al
		sub	ebx,8000h
		mov	eax,ebx

		pop	cx
		ret
Not_Cy:
endif	;P6_BIOS_ONLY

		call	Get_SMBASE_Seg
		ret

Get_SMBASE_ADD	Endp

E_GET_CMOS	PROC	NEAR
		ALIGN	4
		OUT	CMOS,AL			; address to interface
		jcxz	short $+2
		jcxz	short $+2
		ALIGN	4
		IN	AL,CMOS+1
		jcxz	short $+2
		jcxz	short $+2
		RET
E_GET_CMOS	ENDP

E_SET_CMOS	PROC	NEAR
		ALIGN	4
		OUT	CMOS,AL			; address to interface
		jcxz	short $+2
		jcxz	short $+2
		xchg	al,ah			;ah=index,al=value
		ALIGN	4
		OUT	CMOS+1,AL		; and output it
		jcxz	short $+2
		jcxz	short $+2
		RET
E_SET_CMOS	ENDP

F000_Get_PM_RAM_Seg:
		F000_call	Get_PM_RAM_Seg
		ret

F000_Enable_CRT:
		push	ds			;R22
		Call	F000_Get_PM_RAM_Seg	;R22
		mov	ds,ax			;R22
		F000_call	Enable_CRT
		pop	ds			;R22
		ret
;[]===============================================================[]
;
; HDD_Transfer :
;
;	The routine does data transfer to/from HDD.
;
; Entry:
;	AH = 30h  write
;          = 20h  read
;	AL = sector count.
;       DS:SI = Address for writing.
;       ES:DI = Address for reading.
;       CX = cylinder number.
;       DH = Head number.
;       DL = starting sector number.
;
; Exit:
;	JNC = successful. JC = failed
;       ESI Or EDI updated pointer after the Write / Read operation.
;
; Note:
;
;[]==================================================================[]
Hdd_Register		EQU	03f6h	; Hdd register.
Hdd_Rdy			EQU	40h	; Drive ready bit.
Hdd_Busy		EQU	80h	; Drive busy bit.
Hdd_Drq			EQU	08h	; Drive DRQ bit.
Hdd_Seek_Cmd		EQU	70h	; Drive seek command.
Write_command		EQU	30h	; Hdd write multi-sector command.
Read_command		EQU	20h	; Hdd read multi-sector command.

		Public	HDD_Transfer
HDD_Transfer	proc	near

		pushad

		call	Get_HDD_Parm		; Get the Location parameter

		push	eax
		push	ecx
		push	dx
		push	bp

		mov	ebp,esp			; Get stack top.
Resend_HDD_Cmd:
		call	Test_CTLR_Busy

		mov	al,[bp+3]
		call	Get_HDD_Port_Base
		add	dl,6
		out	dx,al
		call	Test_CTLR_Busy
		call	Test_HDD_Rdy

; Feed the task file of HDD with relevent values.

		mov	al,[bp+8]
		call	Get_HDD_Port_Base
		add	dl,2
		out	dx,al

		mov	al,[bp+2]
		inc	dx			; Starting sector number.(1F3)
		out	dx,al

		mov	al,[bp+4]
		inc	dx			; Cylinder low.(1F4)
		out	dx,al

		mov	al,[bp+5]
		inc	dx			; Cylinder high.(1F5)
		out	dx,al

		inc	dx			; SDH reg.(1F6)
		mov	al,[bp+3]
		out	dx,al
		push	dx
		call	Test_CTLR_Busy
		call	Test_HDD_Rdy
		pop	dx

;Now we flash the command.

		mov	al,[bp+9]
		inc	dx			; Get command reg.(1F7)
		out	dx,al			; Flash the command.

		newiodelay
		call	Test_CTLR_Busy
		in	al,dx
		test	al,1
		jnz	short error_xfer

		mov	ah,3
		xor	cx,cx
	@@:
		NEWIODELAY
		NEWIODELAY
		in	al,dx
		test	al,HDD_DRQ

		jnz	short HDD_Cmd_OK
		loop	@B
		dec	ah
		jnz	short @B
		test	al,HDD_DRQ
		jz	short Resend_HDD_Cmd
HDD_Cmd_OK:

;Now we need to find out if it is read or write command.

		mov	al,[bp+9]
		cmp	al,Write_command
		jz	fill_buffer

;It is a read command so we need to read the buffer.

read_buffer:
		xor	ecx,ecx			; 32 bit type uses ecx.
;R64		mov	cx,100h
ifndef	STD_IDE_16Bit_RW			;R64A
		mov	cx,100h/2		;R64
else	;STD_IDE_16Bit_RW			;R64A
		mov	cx,100h			;R64A
endif	;STD_IDE_16Bit_RW			;R64A
		call	Get_HDD_Port_Base
		cld
		push	edi
		ALIGN	4
		db	67h			; Address size over-ride.
;R64		rep 	insw
ifndef	STD_IDE_16Bit_RW			;R64A
		rep	insd			;R64
else	;STD_IDE_16Bit_RW			;R64A
		rep	insw			;R64A
endif	;STD_IDE_16Bit_RW			;R64A
		pop	edi
		xor	eax,eax
		mov	ax,200h
		add	edi,eax
		add	dx,7
	@@:
		in	al,dx
		test	al,HDD_BUSY
		jnz	short @B
		in	al,dx
		test	al,HDD_DRQ
		jnz	read_buffer
		jmp	done_xfer

fill_buffer:
		xor	ecx,ecx
;R64		mov	cx,100h
ifndef	STD_IDE_16Bit_RW			;R64A
		mov	cx,100h/2		;R64
else	;STD_IDE_16Bit_RW			;R64A
		mov	cx,100h			;R64A
endif	;STD_IDE_16Bit_RW			;R64A
		call	Get_HDD_Port_Base
		cld
		push	esi
		ALIGN	4
		db	67h			; Address size over-ride.
;R64		rep 	outsw
ifndef	STD_IDE_16Bit_RW			;R64A
		rep	outsd			;R64
else	;STD_IDE_16Bit_RW			;R64A
		rep	outsw			;R64A
endif	;STD_IDE_16Bit_RW			;R64A
		pop	esi
		xor	eax, eax
		mov	ax, 200h
		add	esi, eax
		add	dx,7
	@@:
		in	al,dx
		test	al,HDD_BUSY
		jnz	short @B
		in	al,dx
		test	al,HDD_DRQ
		jnz	fill_buffer

done_xfer:
		jmp	short no_error_xfer

error_xfer:
		stc
		POST_CODE	0edh
		jmp	$

no_error_xfer:
		call	Test_CTLR_Busy
		pop	bp
		pop	dx
		pop	ecx
		pop	eax
		popad
		ret
HDD_Transfer	endp

;===========================================================================
;FUNC:  TEST_HDD_RDY
;
;DESC:  Tests if the HDD controller is ready to accept commands.
;
;IN:    None
;
;OUT:   None
;===========================================================================
Test_CTLR_Busy:
		call	Get_HDD_Port_Base
		add	dl,7
	@@:
		in	al,dx			; Get Status value.
		test	al,HDD_BUSY
		jz	short @F
		mov	cx,40h
		call	Small_Delay
		jmp	short @B

	@@:
		ret

Test_HDD_Rdy	proc	near

		call	Get_HDD_Port_Base
		add	dl,7
	@@:
		in	al,dx			; Get Status value.
		test	al,HDD_RDY		; HDD_BUSY
		jnz	short @F
		mov	cx,40h
		call	Small_Delay
		jmp	short @B
	@@:

		ret
Test_HDD_Rdy	endp

;[]===============================================================[]
;
; Get_HDD_Parm
;
;	The routine to return HDD location parameter for R/W.
;
; Entry:
;	EBX = absolute sector number.
;
; Exit:
;       CX = cylinder number.
;       DH = Head number.
;       DL = starting sector number.
;
; Note:
;
;[]==================================================================[]
Get_HDD_Parm	Proc	Near

		push	ds
		push	ax
		push	ebx

		call	F000_Get_PM_RAM_Seg
		mov	ds,ax

		mov	dl,ds:[ZV_HDD_Scheme]
		shr	dl,2
		and	dl,3
		cmp	dl,1			;HDD is LBA mode?
		jne	short @F		;No,jump to Large or Normal mode

		mov	dl,bl
		mov	cl,bh
		shr	ebx,16
		mov	ch,bl
		mov	dh,bh
		and	dh,0fh
		or	dh,0E0H			; LBA SDH

		test	byte ptr ds:[ZV_HDD_Scheme],1	;check on master
		jz	short ZV_HDD_on_master		;Yes,jump
		or	dh,10h				;set to slave
ZV_HDD_on_master:

		jmp	short End_Get_HDD_Parm
@@:

		xor	ecx,ecx
		mov	ax,bx
		shr	ebx,16
		mov	dx,bx
		mov	cx,word ptr ds:[Cylinder_Sector]
		div	cx			; Get Cylinder
		mov	cx,ax
		mov	ax,dx
		mov	bl,byte ptr ds:[Head_Sector]
		div	bl
		mov	dl,ah
		inc	dl

		mov	bl,ds:[ZV_HDD_Scheme]
		shr	bl,2
		and	bl,3
		cmp	bl,2
		jne	short @F		;No,jump to Large or Normal mode

;R56		shr	al,1			;head/2
;R56		shl	cx,1			;cylinder*2
;R56 - Start
		mov	bl,ds:[Logical_Heads]	;get logical head number
		mov	bh,ds:[Hdd_Head]	;get real head number
Process_Head_Loop:
		cmp	bl,bh			;if logical below phicial head
		jbe	short Process_Head_Over	;yes , process over
		shl	cx,1			;otherwise cylinder*2
		shr	bl,1			;Hdd logical head/2
		jmp	short Process_Head_Loop	;do it again
Process_Head_Over:
		movzx	ax,al			;head number
		div	bh			;devide real head number
		movzx	bx,al			;
		add	cx,bx			;add it to cilinder number
		mov	al,ah			;real to access head number
@@:
;R56 - end
@@:						;
		and	al,0fh
		or	al, 0A0h		; sector size = 512 bytes

		test	byte ptr ds:[ZV_HDD_Scheme],1	;check on master
		jz	short ZV_HDD_on_master0		;Yes,jump
		or	al,10h				;set to slave
ZV_HDD_on_master0:
		mov	dh,al

End_Get_HDD_Parm:

		pop	ebx
		pop	ax
		pop	ds
		ret
Get_HDD_Parm	endp

;[]===============================================================[]
;
; Get_ZV_HDD_Loc:
;
;	The routine to return ZV partition
;
; Entry:	NONE
; Exit:
;		EBX = absolute sector number of 0V-Suspend partition.
;
; Note:
;
;[]==================================================================[]
		Public	Get_ZV_HDD_Loc
Get_ZV_HDD_Loc	proc	near
		push	ds
		push	ax
		call	F000_Get_PM_RAM_Seg
		mov	ds,ax
		mov	ebx,dword ptr ds:ZV_HDD_Sector
		pop	ax
		pop	ds
		ret
Get_ZV_HDD_Loc	endp

Get_HDD_Port_Base:
		push	ax
		push	ds
		call	F000_Get_PM_RAM_Seg
		mov	ds,ax
		mov	dx,1f0h
		test	byte ptr ds:[ZV_HDD_Scheme],2	;check on primary?
		jz	short @F
		sub	dl,80h
@@:
		pop	ds
		pop	ax
		ret

SMM_ZV_Display_MSG	proc	near

		push	ds
		push	si

		push	cs
		pop	ds

		mov	bp,sp
		sub	bp,DATAAREASIZE
;R52b		mov	byte ptr CALLTYPE[bp],SMM_CALL

		mov	word ptr Color_Offset[bp],offset VGA_Buffer
;R52b		mov	byte ptr MONOCHROME[bp],1

		mov	ax,3				; Clear screen
		F000_Call	Video_Func

		mov	si,offset E_Border_0V_Str
;R52		call	F_Display_String
		call	SMM_Display_String		;R52
		pop	si

;R52		call	F_Display_String
		call	SMM_Display_String		;R52

		pop	ds
		ret
SMM_ZV_Display_MSG	endp

ifndef	NO_ZV_REALTIME_MESSAGE

Suspend_Status	Proc	Near

		push	ebx

		Call	F000_Enable_CRT

	ifdef	Special_Save_VGA_status
		Call	Ct_Special_restore_VGA
	endif	;Special_Save_VGA_status

		mov	si,offset Suspend_ZV_MSG
		call	SMM_ZV_Display_MSG

		pop	ebx
		ret

Suspend_Status	Endp

Resume_Status	Proc	Near

		push	ebx

		Call	F000_Enable_CRT

		mov	si,offset Resume_ZV_MSG
		call	SMM_ZV_Display_MSG

		pop	ebx
		ret

Resume_Status	Endp

Show_Transfer_MSG	Proc	Near

		push	ds

		push	cs
		pop	ds

;R52		Call	F_Display_String
		call	SMM_Display_String		;R52
		mov	si,offset Transfer_MSG
;R52		Call	F_Display_String
		call	SMM_Display_String		;R52

		pop	ds
		ret

Show_Transfer_MSG	Endp

Transfer_OK_MSG	Proc	Near

		push	ds

		push	cs
		pop	ds

;R52		Call	F_Display_String
		call	SMM_Display_String		;R52
		mov	si,offset Transferred_MSG
;R52		Call	F_Display_String
		call	SMM_Display_String		;R52

		pop	ds
		ret

Transfer_OK_MSG	endp
;R52 - start
;[]========================================================================[]
;Function :	Display a string on screen in which the control bytes defined
;		in Display_Control is allowed
;		e.g. POS, BORDER1, CLEAR...
;
;Input	:	SI - string offset
;
;Output	:	None
;
;Registers :	----
;[]========================================================================[]
SMM_Display_String	Proc	Near
		push	es
		push	di
		push	bx
Display_Str1:
		lodsb
		cmp	al,V_DONE
		je	short Display_Str_End
		cmp	al,V_DONE_1
		je	short Display_Str_End

		cmp	al,V_Special
		jbe	short Display_Str2
		call	SMM_Display_Char
		jmp	short Display_Str1
Display_Str2:
		xor	bh,bh
		shl	al,1
		mov	bl,al
		call	word ptr cs:Display_Control[bx]
		jmp	short Display_Str1

Display_Str_End:
		pop	bx
		pop	di
		pop	es
		ret

SMM_Display_String	Endp

VDone:
		ret
Display_Control:
		dw	offset VDone
		dw	offset VDone
		dw	offset VBorder
		dw	offset VDone
		dw	offset VDone
		dw	offset VPos
		dw	offset VDone
		dw	offset VReverse
		dw	offset VNormal
		dw	offset VBlink
		dw	offset VDone
		dw	offset VDone
		dw	offset VDone
		dw	offset VDone
		dw	offset VDone
		dw	offset VDone
		dw	offset VDone
		dw	offset VCHG_COLOR

;[]========================================================================[]
;Function:	Write a border on screen
;
;Input	:	DS = CS
;		SI = (offset BORDER STRUCT + 1)
;		e.g. BORDER <,0,0,20,20>
;
;Output	:	None
;
;Destroy:	All except BX
;[]========================================================================[]
VBorder		proc	near
		push	bx
		dec	si
		mov	bx,si

		test	byte ptr [bx].Btype,Empty_Border
		jz	short _Not_Empty_Border
		push	bx
		push	cx
		mov	ax,0600h
		mov	cl,[bx].LeftX
		mov	ch,[bx].LeftY
		mov	dl,[bx].RightX
		mov	dh,[bx].RightY
		mov	bh,ATTRIBUTE[bp]
		Call	SMM_Check_Call_Source
		pop	cx
		pop	bx
_Not_Empty_Border:
		test	byte ptr [bx].Btype,No_Border
;R52A		jz	Draw_Border
		jmp	No_Angle
;R52ADraw_Border:
;R52A
;R52A;----------------------------------------------------------------
;R52A		mov	al,[bx].LeftX
;R52A		mov	CURSOR_X[bp],al
;R52A		mov	al,[bx].LeftY
;R52A		mov	CURSOR_Y[bp],al
;R52A
;R52A_VBorder_1:
;R52A		mov	al,205			;'Э'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short _VBorder_1_1
;R52A		mov	al,196			;'Ф'
;R52A_VBorder_1_1:
;R52A		call	SMM_Display_Char
;R52A
;R52A		mov	ah,CURSOR_X[bp]
;R52A		cmp	ah,[bx].RightX
;R52A		jbe	short _VBorder_1
;R52A
;R52A;----------------------------------------------------------------
;R52A
;R52A		mov	al,[bx].LeftX
;R52A		mov	CURSOR_X[bp],al
;R52A		mov	al,[bx].RightY
;R52A		mov	CURSOR_Y[bp],al
;R52A
;R52A_VBorder_2:
;R52A		mov	al,205			;'Э'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short _VBorder_2_1
;R52A		mov	al,196			;'Ф'
;R52A_VBorder_2_1:
;R52A		call	SMM_Display_Char
;R52A
;R52A		mov	ah,CURSOR_X[bp]
;R52A		cmp	ah,[bx].RightX
;R52A		jb	short _VBorder_2
;R52A;----------------------------------------------------------------
;R52A
;R52A		mov	al,186			;'К'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short _VBorder_2_3
;R52A		mov	al,179			;'Г'
;R52A_VBorder_2_3:
;R52A		mov	dl,[bx].LeftX		;start point X
;R52A		mov	dh,[bx].LeftY		;start point Y
;R52A		inc	dh
;R52A		mov	cl,[bx].RightY		;count of chars
;R52A		sub	cl,dh
;R52A
;R52A		mov	ch,[bx].LeftX
;R52A		cmp	ch,[bx].RightX
;R52A		jne	short @F
;R52A		add	cl,2
;R52A		dec	dh
;R52A	@@:
;R52A		call	Show_Vertical
;R52A
;R52A		mov	dl,[bx].RightX		;start point X
;R52A		call	Show_Vertical
;R52A
;R52A;----------------------------------------------------------------
;R52A		mov	al,[bx].LeftX
;R52A		cmp	al,[bx].RightX
;R52A		je	No_Angle
;R52A
;R52A		mov	al,[bx].LeftY
;R52A		cmp	al,[bx].RightY
;R52A		je	No_Angle
;R52A
;R52A;----------------------------------------------------------------
;R52A;Top Left
;R52A		mov	al,[bx].LeftX
;R52A		mov	CURSOR_X[bp],al
;R52A		mov	al,[bx].LeftY
;R52A		mov	CURSOR_Y[bp],al
;R52A
;R52A		mov	al,201			;'Щ'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short VBorder_TL
;R52A		mov	al,218			;'к'
;R52AVBorder_TL:
;R52A		call	SMM_Display_Char
;R52A;----------------------------------------------------------------
;R52A;Top Right
;R52A		mov	al,[bx].RightX
;R52A		mov	CURSOR_X[bp],al
;R52A		mov	al,[bx].LeftY
;R52A		mov	CURSOR_Y[bp],al
;R52A
;R52A		mov	al,187			;'Л'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short VBorder_TR
;R52A		mov	al,191			;'П'
;R52AVBorder_TR:
;R52A		call	SMM_Display_Char
;R52A;----------------------------------------------------------------
;R52A;Bottom Left
;R52A		mov	al,[bx].LeftX
;R52A		mov	CURSOR_X[bp],al
;R52A		mov	al,[bx].RightY
;R52A		mov	CURSOR_Y[bp],al
;R52A
;R52A		mov	al,200			;'Ш'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short VBorder_BL
;R52A		mov	al,192			;'Р'
;R52AVBorder_BL:
;R52A		call	SMM_Display_Char
;R52A;----------------------------------------------------------------
;R52A;Bottom Right
;R52A		mov	al,[bx].RightX
;R52A		mov	CURSOR_X[bp],al
;R52A		mov	al,[bx].RightY
;R52A		mov	CURSOR_Y[bp],al
;R52A
;R52A		mov	al,188			;'М'
;R52A		test	[bx].Btype,01h
;R52A		jnz	short VBorder_BR
;R52A		mov	al,217			;'й'
;R52AVBorder_BR:
;R52A		call	SMM_Display_Char
;R52A;----------------------------------------------------------------
No_Angle:

		add	si,6		;to next pattern
		pop	bx
		ret
VBorder		endp
;R52AShow_Vertical	proc	near
;R52A		push	cx
;R52A
;R52A		cmp	cl,0
;R52A		jl	short SV_End
;R52A
;R52A		xor	ch,ch
;R52A		mov	byte ptr CURSOR_X[bp],dl
;R52A		mov	byte ptr CURSOR_Y[bp],dh
;R52A
;R52AShow_Ver:
;R52A		call	SMM_Display_Char
;R52A		dec	byte ptr CURSOR_X[bp]
;R52A		inc	byte ptr CURSOR_Y[bp]
;R52A
;R52A		loop	short Show_Ver
;R52ASV_End:
;R52A		pop	cx
;R52A		ret
;R52AShow_Vertical	endp

;[]========================================================================[]
;Function :	Program the cursor position according to the position
;		specified in POS STRUCT
;
;Input	:	DS = CS
;		SI = (offset POS STRUCT) + 1
;		e.g. POS <,0,0>
;
;Output :	CURSOR_X[bp] & CURSOR_Y[bp] updated
;
;Registers:	FLAG,SI - destroyed
;		others  - preserved
;[]========================================================================[]
VPos		Proc	Near
		push	ax
		lodsb
		cmp	al,-1
		je	short @F
		mov	CURSOR_X[bp],al
	@@:
		lodsb
		cmp	al,-1
		je	short @F
		mov	CURSOR_Y[bp],al
	@@:

		pop	ax
		ret
VPos		Endp
;[]========================================================================[]
;Function :	Set the display attrib to REVERSE
;
;Input	:	None
;
;Output :	byte ptr ATTRIBUTE[bp] updated
;
;Registers:	All preserved
;[]========================================================================[]
Vreverse 	proc	near
		push	ax
		push	bx
		mov	bx,Color_Offset[bp]
;R52b		mov	al,ds:[bx+1]		;R52Anext color
		mov	al,cs:[bx+1]		;R52bnext color
;R52A		push	ds
;R52A		mov	ax,SEG	DGROUP
;R52A		mov	ds,ax
;R52A		mov	al,ds:[bx].CREVERSE
;R52A		pop	ds
		mov	ATTRIBUTE[bp],al
		pop	bx
		pop	ax
		ret
Vreverse	endp

;[]========================================================================[]
;Function :	Set the display attrib to NORMAL
;
;Input	:	None
;
;Output :	byte ptr ATTRIBUTE[bp] updated
;
;Registers:	All preserved
;[]========================================================================[]
Vnormal		proc	near
		push	ax
		push	bx
		mov	bx,Color_Offset[bp]
		mov	al,cs:[bx]		;R52A
;R52A		push	ds
;R52A		mov	ax,SEG	DGROUP
;R52A		mov	ds,ax
;R52A		mov	al,ds:[bx].CNORMAL
;R52A		pop	ds
		mov	ATTRIBUTE[bp],al
		pop	bx
		pop	ax
		ret
Vnormal		endp

;[]========================================================================[]
;Function :	Set the display attrib to BLINK
;
;Input	:	None
;
;Output :	byte ptr ATTRIBUTE[bp] updated
;
;Registers:	FLAG   - detroyed
;		Others - preserved
;[]========================================================================[]
VBlink		Proc	Near
		or	byte ptr ATTRIBUTE[bp],80h
		ret
VBlink		Endp

;[]========================================================================[]
;Function :	call a specified subroutine
;[]========================================================================[]
VCHG_COLOR	Proc	Near

		lodsb
;R52A - start
		cmp	al,0
		jne	short IS_Next_color
		mov	ax,offset color_pattern
		mov	Color_Offset[bp],ax
		ret
Is_next_color:
		mov	ax,offset color_pattern
		add	ax,2
		mov	Color_Offset[bp],ax
;R52A - end
;R52A		call	SMM_Get_Color_Off		;Get color status from CMOS
		ret

VCHG_COLOR	Endp

;[]========================================================================[]
;Funtion :	Display 1 character on screen
;
;Input	:	al = ASCII code
;
;Output	:	CURSOR_X[bp] & CURSOR_Y[bp] changed
;
;Registers:	FLAG    - Destroyed
;		Others	- Preserved
;[]========================================================================[]
SMM_Display_Char	proc	near
		push	ax
		push	bx
		push	cx
		push	dx

		pushf
		push	ax
		;Set cursor position to display item name
		mov	dl,CURSOR_X[bp]		;get column position
		mov	dh,CURSOR_Y[bp]		;get row position
		xor	bh,bh			;first page
		mov	ah,2			;set cursor position
		Call	SMM_Check_Call_Source
		pop	ax

		mov	ah,09h			;write TTY
		mov	bl,byte ptr ATTRIBUTE[bp]
		mov	cx,1
		Call	SMM_Check_Call_Source
Exit_Display_Char:
		inc	byte ptr CURSOR_X[bp]
		popf
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		ret
SMM_Display_Char	endp
;R52A;[]========================================================================[]
;R52A;Function :	Get the color set according to bit 7654 of
;R52A;		input AL
;R52A;
;R52A;Input	:	AL
;R52A;
;R52A;Output	:	word ptr Color_offset[bp] = offset of color set
;R52A;
;R52A;Registers :	CX, AX - Destroyed
;R52A;[]========================================================================[]
;R52ASMM_Get_Color_Off	Proc	Near
;R52A
;R52A		shr	al,4
;R52A		mov	cl,size Color_style
;R52A		mul	cl
;R52A		mov	cx,offset VGA_Buffer
;R52A
;R52A		add	ax,cx
;R52A		mov	Color_Offset[bp],ax
;R52A
;R52A		ret
;R52ASMM_Get_Color_Off	Endp

SMM_Check_Call_Source	Proc	Near
		push	si
		F000_Call	Video_Func
		pop	si
		ret
SMM_Check_Call_Source	Endp
;R52 - end
;R52A - start
Factor_Ten	dw	10
SMM_Show_SIX_DIGIT	Proc	Near
		push	ds

		mov	si,bp
		add	si,SIX_DIGIT

		push	ss
		pop	ds				;DS point to SS
		call	SMM_Display_String

		pop	ds
		ret
SMM_Show_SIX_DIGIT	Endp

SMM_AX_To_DEC2	label	near
		mov	cx,1		;1 iterations
		mov	di,offset Factor_Ten
		mov	si,SIX_DIGIT
Convert_3Byte:
		xor	dl,dl		;for leading space judge
		mov	byte ptr [bp+si],30h
Not_O:
Sub_Again:
		inc	byte ptr [bp+si]
		sub	ax,cs:[di]
		je	short Next_Digit
		jnc	short Sub_Again
Add_Back:
		add	ax,cs:[di]
		dec	byte ptr [bp+si]
Next_Digit:
		cmp	byte ptr [bp+si],30h
		jne	short Non_Zero
		or	dl,dl
		jnz	short Non_Zero
		mov	byte ptr [bp+si],20h	;leading space
		jmp	short Zero_Space
Non_Zero:
		inc	dl
Zero_Space:
		inc	di
		inc	di
		inc	si
		mov	byte ptr [bp+si],30h
		loop	short Sub_Again

		add	[bp+si],al
		mov	byte ptr [bp+si+1],0	;ending string

		ret
Color_pattern:
		normal		db	1Fh
		reverse		db	4Fh
		normal2		db	70h
		reverse2	db	07h
;R52A - end
;[]========================================================================[]
;
;	Border for suspend/resume message
;
;[]========================================================================[]
ZV_Msg_Y	EQU	3
ZV_Msg_Y1	EQU	8
ZV_Msg_Y2	EQU	13
E_Border_0V_Str:
			db	V_CHG_COLOR,00h
			db	V_NORMAL
		BORDER1	<,0,0,79,24,Empty_Border+NO_BORDER>

			db	V_CHG_COLOR,0A0h
			db	V_NORMAL
		BORDER1	<,12,ZV_Msg_Y-1,68,ZV_Msg_Y+2,Empty_Border+NO_BORDER>
		BORDER1	<,12,ZV_Msg_Y1-1,68,ZV_Msg_Y1+2,Empty_Border+NO_BORDER>
		BORDER1	<,16,ZV_Msg_Y2-1,64,ZV_Msg_Y2+8,Empty_Border+NO_BORDER>

		  	db	V_CHG_COLOR,00h
			db	V_NORMAL
		BORDER1	<,13,ZV_Msg_Y,67,ZV_Msg_Y+1,Empty_Border+NO_BORDER>
		BORDER1	<,13,ZV_Msg_Y1,67,ZV_Msg_Y1+1,Empty_Border+NO_BORDER>
		BORDER1	<,17,ZV_Msg_Y2,63,ZV_Msg_Y2+7,Empty_Border+NO_BORDER>

		POS	<,14,ZV_Msg_Y>
			db	'AwardBIOS v4.51GPM Save To Disk Manager ';R50

		POS	<,14,ZV_Msg_Y+1>
			db	'Copyright (c) Award Software International, Inc. 1999 ';R58

		POS	<,37,ZV_Msg_Y1>
			db	'Status'

		POS	<,36,ZV_Msg_Y2>
			db	'Progress'
		POS	<,22,ZV_Msg_Y2+2>
			db	'System Information  : '
		POS	<,22,ZV_Msg_Y2+4>
			db	'Conventional Memory : '
		POS	<,22,ZV_Msg_Y2+6>
			db	'Extended Memory     : '
			db	0

;[]========================================================================[]
;
;	Zero-Volt Resume message
;
;[]========================================================================[]
		PUBLIC	Resume_ZV_MSG
Resume_ZV_MSG:
		POS	<,16,ZV_Msg_Y1+1>
			db	V_CHG_COLOR,000h
			db	V_REVERSE
			db	' Resume from disk in progress.  Please wait....  '
			db	0

;[]========================================================================[]
;
;	Zero-Volt Suspend message
;
;[]========================================================================[]
Suspend_ZV_MSG:
		POS	<,16,ZV_Msg_Y1+1>
			db	V_CHG_COLOR,000h
			db	V_REVERSE
			db	'   Save to disk in progress.  Please wait....    '

		POS	<,44,ZV_Msg_Y2+2>
Transferred_MSG:
			db	V_NORMAL
			db	' Transferred 100% '
ifdef	SAVE_BASE_DRAM_BEFORE_MESSAGE
		POS	<,44,ZV_Msg_Y2+4>
			db	V_NORMAL
			db	' Transferred 100% '
endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE
			db	0

Transfer_MSG:
			db	V_REVERSE
			db	V_BLINK
			db	' Transferring  5% '
			db	0

Base_Mem_POS:
		POS	<,44,ZV_Msg_Y2+4>
			db	0

Ext_Mem_POS:
		POS	<,44,ZV_Msg_Y2+6>
			db	0

endif	;NO_ZV_REALTIME_MESSAGE

;R52F_Display_String:
;R52		F000_Call	Display_String
;R52		ret

;[]==================================================================[]
;
; Procedure Name: VIDEO_STATE
;
;	This routine is save/restore Video state
;
; Saves: All
; Input:
;	 AL = 1   save Video state
;	 AL = 2   restore Video state
;
; Output:
;	 none
;
; [Note]:
;
; Author: Daniel Huang
; Date: December, 05, 1995
;
; Name	| Date		| Description
; -----------------------------------------------------------------
; DNL	| 12/05/95	| Initial version for notebook
;[]==================================================================[]
		Public	VIDEO_STATE
VIDEO_STATE	Proc	Near

		pushad
		push	ds
		push	es

		mov	bx,ZV_Temp_Stack
		mov	es,bx
ifndef	NO_VESA_BIOS_SUPPORT
		mov	dl,al
		mov	ax,4f04h
		xor	ebx,ebx
		mov	bx,ZV_Temp_Stack
		shl	ebx,4
		add	ebx,offset VIDEO_BUFFER
		shr	ebx,4
		mov	es,bx
		xor	bx,bx
		mov	cx,0Fh
else	;NO_VESA_BIOS_SUPPORT
		mov	ah,1Ch
		mov	bx,offset VIDEO_BUFFER
		mov	cx,07h
endif	;NO_VESA_BIOS_SUPPORT
		F000_Call	VIDEO_FUNC

		pop	es
		pop	ds
		popad

		ret

VIDEO_STATE	Endp

ifndef	P6_BIOS_ONLY
F000_Get_Cyrix:
		F000_Call	Get_Cyrix
		ret
endif	;P6_BIOS_ONLY

endif	;STD_Function		EQ	1
;R43 - end

ifdef	Notebook_Power_Management

;R43 ;R40 - start
;R43 ifdef	ACPI_SUPPORT
;R43 ;R41 - start
;R43 ifdef	S4_SUPPORT
;R43 ;[]========================================================================[]
;R43 ;
;R43 ;	Put system into S4 state.
;R43 ;
;R43 ;[]=========================================================================[]
;R43
;R43 		ASSUME	DS:G_RAM
;R43 		Public	E_S4_Suspend
;R43 E_S4_Suspend	Proc	Far
;R43
;R43 		pushad
;R43 		push	ds
;R43 		push	es
;R43 		push	fs
;R43 		push	gs
;R43
;R43 		cld
;R43
;R43 		call	Save_8042
;R43 		push	bx
;R43 		in	al,92h			; get a20 states
;R43 		push	ax
;R43 		Call	F000_A20_ON
;R43
;R43 		mov	ax,G_RAM
;R43 		mov	ds,ax
;R43
;R43 		Call	Get_SMBASE_ADD
;R43 		mov	ebx,eax
;R43 		xor	ax,ax
;R43 		mov	es,ax
;R43
;R43 	; Save port 92H status
;R43
;R43 		pop	ax
;R43 		pop	cx
;R43 		push	cx
;R43 		push	ax
;R43 		mov	BYTE PTR es:[ebx+Save_8042_Output],cl
;R43  		mov	BYTE PTR es:[ebx+Port92_Save],al
;R43
;R43 	; Turn off speaker & save port 61H
;R43
;R43 		in	al,61h				; save port_b status
;R43 		mov	BYTE PTR es:[ebx+Port61_Save],al
;R43 		and	al,0fch				; turn off speaker
;R43 		out	61h,al
;R43
;R43 	; Save chipset state
;R43
;R43 		Call	Save_Ct_device
;R43 		call	Save_Chipset
;R43 		call	Wakeup_Device
;R43
;R43 	; Save peripherial devices
;R43
;R43 ifdef	NEW_SUPERIO_KERNEL
;R43 		Call	Suspend_Super_IO
;R43 endif	;NEW_SUPERIO_KERNEL
;R43 if	BIOS_SUPPORT_686
;R43 		Call	Check_P6_A20_Status
;R43 endif	;BIOS_SUPPORT_686
;R43
;R43 	; Save all memory data
;R43
;R43 		mov	ax,ZV_Temp_Stack
;R43 		call	Save_BASEMem			; Save for temp stack
;R43
;R43 		call	Disable_SMM_Map
;R43 		Call	Suspend_Status
;R43 		call	Save_Base_DRAM
;R43 		call	Save_Ext_DRAM
;R43 		call	Save_Shadow
;R43 		call	Enable_SMM_Map
;R43
;R43 	; Save stack pointer & save SMBASE
;R43
;R43 		mov	word ptr es:[ebx+SS_Save],ss
;R43 		mov	dword ptr es:[ebx+ESP_Save],esp
;R43 		call	Save_S4_SMBASE
;R43
;R43 	; Shutdown byte with NMI off
;R43
;R43 		mov	al,0Fh NMI_OFF
;R43 		mov	ah,S4_Resume_Byte
;R43 		call	E_Set_CMOS
;R43
;R43 ifdef	ZV_Suspend_Beep_loop
;R43 		mov	cx,ZV_Suspend_Beep_loop
;R43 Suspend_Beep_loop:
;R43 		push	cx
;R43 		call	PM_Beep
;R43 		pop	cx
;R43 		loop	Suspend_Beep_loop
;R43 else	;ZV_Suspend_Beep_loop
;R43 ifndef	No_ZV_Suspend_Beep
;R43 		call	PM_Beep
;R43 		call	PM_Beep
;R43 		call	PM_Beep
;R43 		call	PM_Beep
;R43 		call	PM_Beep
;R43 endif	;No_ZV_Suspend_Beep
;R43 endif	;ZV_Suspend_Beep_loop
;R43
;R43 		POST_CODE	66h
;R43
;R43 	; Begin to Shutdown the system
;R43
;R43 		call	CT_0V_Shutdown
;R43 	@@:
;R43 		call	PM_Beep
;R43 		jmp	short @B
;R43
;R43 E_S4_Suspend	Endp
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Save_S4_SMBASE
;R43 ;
;R43 ;Function :	Save SMBASE for the CPU was reseted by chipset
;R43 ;		during system reume.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	ES,DS
;R43 ;
;R43 ;[]========================================================================[]
;R43 Save_S4_SMBASE	PROC	NEAR
;R43
;R43 		push	es
;R43 		push	ds
;R43 		push	ebx
;R43
;R43 		push	es
;R43 		pop	ds
;R43 		mov	esi,ebx
;R43 		add	esi,offset SMI_Entry
;R43
;R43 		call	Get_ZV_HDD_Loc
;R43 		add	ebx,ZV_HDD_SMBASE_Sector
;R43 		mov	ah,30h			; Write command
;R43 		mov	al,(26*1024)/512	; Sector Count
;R43 		call	HDD_Transfer
;R43
;R43 		pop	ebx
;R43 		pop	ds
;R43 		pop	es
;R43
;R43 		ret
;R43 Save_S4_SMBASE	ENDP
;R43
;R43 ;[]========================================================================[]
;R43 ;
;R43 ;	Put system into S0 state.
;R43 ;
;R43 ;[]=========================================================================[]
;R43
;R43 		Public	E_S4_Resume
;R43 E_S4_Resume	PROC	FAR
;R43
;R43 		cld
;R43
;R43 	; Clear shutdown byte with NMI off
;R43
;R43 		mov	al,0Fh NMI_OFF
;R43 		mov	ah,0
;R43 		call	E_Set_CMOS
;R43
;R43 	; Turn off speaker
;R43
;R43 		in	al,61h
;R43 		and	al,0fch				; turn off speaker
;R43 		or	al,0ch
;R43 		out	61h,al
;R43
;R43 		call	CT_System_Wakeup
;R43 		Call	F000_A20_ON
;R43
;R43 		mov	ax,G_RAM
;R43 		mov	ds,ax
;R43
;R43 ifndef	No_ZV_Suspend_Beep
;R43 		call	PM_Beep
;R43 endif	;No_ZV_Suspend_Beep
;R43
;R43 		Call	Get_SMBASE_ADD
;R43 		mov	ebx,eax
;R43 		xor	ax,ax
;R43 		mov	es,ax
;R43
;R43 	; Restore all memory data
;R43
;R43 		call	Restore_S4_SMBASE
;R43 		call	Disable_SMM_Map
;R43 		Call	Resume_Status
;R43 		call	Restore_Shadow
;R43 		call	Restore_Ext_DRAM
;R43 		call	Restore_Base_DRAM
;R43 		Call	Sx_Clear_Screen
;R43 		call	Enable_SMM_Map
;R43
;R43 	; Restore for temp stack area
;R43
;R43 		mov	ax,ZV_Temp_Stack
;R43 		call	Restore_BASEMem
;R43
;R43 	; Restore chipset state
;R43
;R43 		call	Restore_Chipset
;R43 		Call	Restore_Ct_device
;R43
;R43 	; Restore peripherial devices
;R43
;R43 ifdef	NEW_SUPERIO_KERNEL
;R43 		Call	Restore_Super_IO
;R43 endif	;NEW_SUPERIO_KERNEL
;R43
;R43 		mov	al,BYTE PTR es:[ebx+Port61_Save]
;R43 		out	61h,al
;R43
;R43 	; Restore stack pointer
;R43
;R43 		mov	ss,word ptr es:[ebx+SS_Save]
;R43 		mov	esp,dword ptr es:[ebx+ESP_Save]
;R43
;R43 	; Set restore address
;R43
;R43 		mov	edi,ebx
;R43 		add	edi,0ff00h
;R43 		xor	eax,eax
;R43 		mov	es:[edi],eax		; clear I/O trap & halt restart
;R43 		mov	ax,Seg Dgroup
;R43 		mov	es:[edi+0ach],eax	; CS for exit SMM
;R43 		mov	ax,offset DGROUP:Sx_Resume_Point
;R43 		mov	es:[edi+0f0h],eax	; IP for exit SMM
;R43
;R43 		pop	ax
;R43 		out	92h,al
;R43 		pop	bx
;R43  		call	Restore_8042
;R43
;R43 		pop	gs
;R43 		pop	fs
;R43 		pop	es
;R43 		pop	ds
;R43 		popad
;R43
;R43 		ret
;R43 E_S4_Resume	ENDP
;R43
;R43 Sx_Clear_Screen:
;R43 		push	ebx
;R43 		mov	ax,3				; Clear screen
;R43 		F000_Call	Video_Func
;R43 		pop	ebx
;R43 		ret
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Restore_S4_SMBASE
;R43 ;
;R43 ;Function :	Restore SMBASE for the CPU was reseted by chipset
;R43 ;		during system reume.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	ES,DS
;R43 ;
;R43 ;[]========================================================================[]
;R43 Restore_S4_SMBASE	Proc	Near
;R43
;R43 		pop	ebp
;R43
;R43 		mov	ax,ZV_Temp_Stack
;R43 		mov	ss,ax
;R43 		mov	esp,offset ZV_STACK_TOP
;R43
;R43 		push	es
;R43 		push	ebx
;R43
;R43 		mov	edi,ebx
;R43 		add	edi,offset SMI_Entry
;R43
;R43 		call	Get_ZV_HDD_Loc
;R43 		add	ebx,ZV_HDD_SMBASE_Sector
;R43 		mov	ah,20h			; Read command
;R43 		mov	al,(26*1024)/512	; Sector Count
;R43 		call	HDD_Transfer
;R43
;R43 		pop	ebx
;R43 		pop	es
;R43 		mov	esp,dword ptr es:[ebx+ESP_Save]
;R43 		mov	ax,word ptr es:[ebx+SS_Save]
;R43 		mov	ss,ax
;R43
;R43 		push	ebp
;R43
;R43 		ret
;R43 Restore_S4_SMBASE	Endp
;R43 endif	;S4_SUPPORT
;R43 ;R41 - end
;R43 if	ACPI_CPU_POWEROFF	EQ	1
;R43 		PUBLIC	E_Save_S3_Status
;R43 E_Save_S3_Status	PROC	FAR
;R43
;R43 		push	ds
;R43 		push	es
;R43
;R43 		cld
;R43
;R43 		Call	F000_A20_ON
;R43
;R43 		mov	ax,G_RAM
;R43 		mov	ds,ax
;R43
;R43 		Call	Get_SMBASE_ADD
;R43 		mov	ebx,eax
;R43 		xor	ax,ax
;R43 		mov	es,ax
;R43
;R43 	; Save peripherial devices
;R43
;R43 ifdef	NEW_SUPERIO_KERNEL
;R43 		Call	Suspend_Super_IO
;R43 endif	;NEW_SUPERIO_KERNEL
;R43
;R43 	; Save chipset state
;R43
;R43 		Call	Save_Ct_device
;R43 		call	Save_Chipset
;R43 ifdef	S3_SUPPORT
;R43 		call	Save_S3_Chipset
;R43 endif	;S3_SUPPORT
;R43
;R43 	; Save stack pointer & save SMBASE
;R43
;R43 		pop	es
;R43 		pop	ds
;R43 		ret
;R43
;R43 E_Save_S3_Status	ENDP
;R43
;R43 		PUBLIC	E_Restore_S2_Status
;R43 E_Restore_S2_Status	PROC	FAR
;R43
;R43 		push	ds
;R43 		push	es
;R43
;R43 		cld
;R43
;R43 		Call	F000_A20_ON
;R43
;R43 		mov	ax,G_RAM
;R43 		mov	ds,ax
;R43
;R43 		call	PM_Beep
;R43
;R43 		Call	Get_SMBASE_ADD
;R43 		mov	ebx,eax
;R43 		xor	ax,ax
;R43 		mov	es,ax
;R43
;R43 		Call	Restore_Sx_SMBASE
;R43
;R43 		mov	edi,ebx
;R43 		add	edi,0ff00h
;R43 		xor	eax,eax
;R43 		mov	es:[edi],eax		; clear I/O trap & halt restart
;R43 		mov	ax,offset DGROUP:Sx_Resume_Point
;R43 		mov	es:[edi+0f0h],eax	; IP for exit SMM
;R43
;R43 	; Restore chipset state
;R43
;R43 		pop	es
;R43 		pop	ds
;R43
;R43 		ret
;R43
;R43 E_Restore_S2_Status	Endp
;R43
;R43 		PUBLIC	E_Restore_S3_Status
;R43 E_Restore_S3_Status	PROC	FAR
;R43
;R43 		push	ds
;R43 		push	es
;R43
;R43 		cld
;R43
;R43 		Call	F000_A20_ON
;R43
;R43 		mov	ax,G_RAM
;R43 		mov	ds,ax
;R43
;R43 		call	PM_Beep
;R43
;R43 		Call	Get_SMBASE_ADD
;R43 		mov	ebx,eax
;R43 		xor	ax,ax
;R43 		mov	es,ax
;R43
;R43 	; Restore chipset state
;R43
;R43 		call	Restore_Chipset
;R43 		Call	Restore_Ct_device
;R43
;R43 	; Restore peripherial devices
;R43
;R43 ifdef	NEW_SUPERIO_KERNEL
;R43 		Call	Restore_Super_IO
;R43 endif	;NEW_SUPERIO_KERNEL
;R43
;R43 		Call	Restore_Sx_SMBASE
;R43
;R43 		mov	edi,ebx
;R43 		add	edi,0ff00h
;R43 		xor	eax,eax
;R43 		mov	es:[edi],eax		; clear I/O trap & halt restart
;R43 		mov	ax,offset DGROUP:Sx_Resume_Point
;R43 		mov	es:[edi+0f0h],eax	; IP for exit SMM
;R43
;R43 		pop	es
;R43 		pop	ds
;R43
;R43 		ret
;R43
;R43 E_Restore_S3_Status	Endp
;R43
;R43
;R43 Sx_SMBASE	EQU	38000h
;R43 Sx_SMBASE1	EQU	3E000h
;R43
;R43 		Public	Restore_Sx_SMBASE
;R43 Restore_Sx_SMBASE	Proc	Near
;R43
;R43 		push	ds
;R43 		push	ebx
;R43
;R43 		cld
;R43 		push	es
;R43 		pop	ds
;R43 		mov	esi,ebx
;R43 		mov	edi,offset Sx_SMBASE
;R43 		mov	cx,3000h/4			;restore 12K
;R43 @@:
;R43 		lods	dword ptr ds:[esi]
;R43 		stos	dword ptr es:[edi]
;R43 		loop	short @B
;R43
;R43 		mov	edi,offset Sx_SMBASE1
;R43 		mov	cx,2000h/4			;restore 8K
;R43 @@:
;R43 		lods	dword ptr ds:[esi]
;R43 		stos	dword ptr es:[edi]
;R43 		loop	short @B
;R43
;R43 		pop	ebx
;R43 		pop	ds
;R43
;R43 		ret
;R43 Restore_Sx_SMBASE	Endp
;R43 endif	;ACPI_CPU_POWEROFF	EQ	1
;R43 endif	;ACPI_SUPPORT
;R43 ;R40 - end

;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
;л
;л	Zero-Volt-Suspend Kernal for NoteBook Power Management
;л
;л	Code for after boot run-time.
;л
;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

;R12 - start
ifndef	NO_STR_SUPPORT
;[]==================================================================[]
;Procedure:	Save_SMI_State
;
;Function :	Routine to save system SMRAM state
;
;Input    :	DS = PM_RAM
;
;Output   :	None
;[]==================================================================[]
		Public	Save_SMI_STATE
Save_SMI_STATE	Proc	Near

		push	ds
		push	es
		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax
		mov	ds,ax
		mov	esi,ebx
		mov	edi,ebx
		add	esi,offset Intel_SMM_State
		add	edi,offset BIOS_Entry_Save
		mov	cx,200h/4
		cld
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B
		pop	es
		pop	ds
		ret
Save_SMI_STATE	ENDP

;[]========================================================================[]
;
; E_Suspend_5V:
;
;	Put system into Five-Volt-Suspend state.
;
;
;[]=========================================================================[]

		ASSUME	DS:G_RAM
		PUBLIC	E_Suspend_5V
E_Suspend_5V	PROC	FAR

		pushad
		push	ds
		push	es
		push	fs
		push	gs

		cld

;R32B - start
		call	Save_8042
		push	bx
		in	al,92h			; get a20 states
		push	ax
		Call	F000_A20_ON
;R32B - end
;R32		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

	; Save port 92H status

		pop	ax				;R32C
		pop	cx				;R32C
		push	cx				;R32C
		push	ax				;R32C
		mov	BYTE PTR es:[ebx+Save_8042_Output],cl	;R32C
 		mov	BYTE PTR es:[ebx+Port92_Save],al	;R32C
;R32B		in	al,92h				; get a20 states
;R32B		mov	BYTE PTR es:[ebx+Port92_Save],al; save port 92h status

	; Turn off speaker & save port 61H

		in	al,61h				; save port_b status
		mov	BYTE PTR es:[ebx+Port61_Save],al
		and	al,0fch				; turn off speaker
		out	61h,al

		call	Save_8259
		call	Save_8237
		call	Save_8254

	; Save chipset state

if	BIOS_SUPPORT_686			;R46
       		call	Save_L2Cache_Reg	;R46
endif	;BIOS_SUPPORT_686			;R46

		Call	Save_Ct_device
		call	Save_Chipset
		call	Save_5V_Chipset

	; Disable SMI trigger after chipset saved

		call	CT_Disable_SMI

	; Save peripherial devices
;R32B ifndef	Dont_Save_8042_Status		;R25
;R32B		call	Save_8042
;R32B endif	;Dont_Save_8042_Status		;R25
		call	Save_Mouse
		call	Save_FDC
		call	Save_COMA
		call	Save_COMB
		call	Save_FPU
ifndef	UseHWVGASuspend				;R59
		call	Suspend_VGA
endif	;UseHWVGASuspend			;R59
if	BIOS_SUPPORT_686			;R46
		Call	Check_P6_A20_Status	;R46
endif	;BIOS_SUPPORT_686			;R46
		call	Ct_5V_suspend_VGA
;R18	ifdef	AUDIO_KERNEL
ifndef	No_Save_Sound				;R57
		Call	Save_Sound
endif	;No_Save_Sound				;R57
;R18	endif	;AUDIO_KERNEL
ifdef	NEW_SUPERIO_KERNEL
ifndef	DONT_SAVE_SUPER_IO	;R35
		Call	Suspend_Super_IO
endif	;DONT_SAVE_SUPER_IO	;R35
endif	;NEW_SUPERIO_KERNEL
ifdef	NEW_SUPERKBC_KERNEL			;R45
ifndef	No_resume_KBC_In_STR			;R53
 		Call	Suspend_KBC		;R45
endif	;No_resume_KBC_In_STR			;R53
endif	;NEW_SUPERKBC_KERNEL			;R45

	; Save stack pointer & save SMBASE

		Call	Save_Original_SMBASE
		Call	Save_SMI_State
		Call	Save_SMI_STACK

		mov	word ptr es:[ebx+SS_Save],ss
		mov	dword ptr es:[ebx+ESP_Save],esp

	; Shutdown byte with NMI off

;R49		Public	Five_Volt_Resume_Byte
;R49 Five_Volt_Resume_Byte	EQU	1Eh

		mov	al,0Fh NMI_OFF
		mov	ah,Five_Volt_Resume_Byte
		call	E_Set_CMOS

		call	F000_Get_PM_RAM_Seg
		mov	ds,ax
		mov	ds:[Software_SMI_Type],SMI_5V_Resume

		POST_CODE	0BBh

	; Begin to Shutdown the system

		call	CT_5V_Shutdown

		jmp	short $

E_Suspend_5V	ENDP

		ALIGN	4
		Public	Save_SMI_stack
Save_SMI_stack	Proc	Near

		pop	dx

		mov	esi,ebx
		mov	edi,ebx
		add	esi,esp
		add	edi,offset SMM_Temp_Buffer

		mov	cx,offset STACK_TOP
		sub	cx,sp
@@:
		lods	byte ptr es:[esi]
		stos	byte ptr es:[edi]
		loop	short @b

		push	dx
		ret
Save_SMI_stack	Endp

;[]========================================================================[]
;[]========================================================================[]
Original_SMBASE	EQU	38000h
		Public	Save_Original_SMBASE
Save_Original_SMBASE	Proc	Near

		push	ds
		push	es
		push	ebx

		xor	ax,ax
		mov	es,ax
		mov	ds,ax
		mov	esi,offset Original_SMBASE
		mov	edi,ebx
		mov	cx,8000h/4			;Save 32K
		cld
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

		pop	ebx
		pop	es
		pop	ds

		ret
Save_Original_SMBASE	Endp
;[]========================================================================[]
;[]========================================================================[]
		Public	Restore_Original_SMBASE
Restore_Original_SMBASE	Proc	Near

		push	ds
		push	es
		push	ebx

		xor	ax,ax
		mov	es,ax
		mov	ds,ax
		mov	esi,ebx
		mov	edi,offset Original_SMBASE
		mov	cx,8000h/4			;Save 32K
		cld
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

		pop	ebx
		pop	es
		pop	ds

		ret
Restore_Original_SMBASE	Endp
endif	;NO_STR_SUPPORT
;R12 - end

;[]========================================================================[]
;
; E_Suspend_0V:
;
;	Put system into Zero-Volt-Suspend state.
;
;
;[]=========================================================================[]

		ASSUME	DS:G_RAM
		Public	E_Suspend_0V
E_Suspend_0V	PROC	FAR

		pushad
		push	ds
		push	es
		push	fs
		push	gs

ifdef	NEW_SUPERVGA_KERNEL			;R34
		Call	SAVE_BEFORE_PROCESS	;R34
endif	;NEW_SUPERVGA_KERNEL			;R34

		cld

;R32;R30 - start
;R32		call	Save_8042
;R32		F000_Call	Read_A20_Status
;R32		jnc	short @f		;A20 off ?
;R32		or	bl,02h			;set Gate A20 high
;R32@@:
;R32		push	bx
;R32;R30 - end
;R32B - start
		call	Save_8042
		push	bx
		in	al,92h			; get a20 states
		push	ax
		Call	F000_A20_ON
;R32B - end

;R32		Call	F000_A20_ON

		mov	ax,G_RAM
		mov	ds,ax

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

	; Save port 92H status

		pop	ax				;R32C
		pop	cx				;R32C
		push	cx				;R32C
		push	ax				;R32C
		mov	BYTE PTR es:[ebx+Save_8042_Output],cl	;R32C
 		mov	BYTE PTR es:[ebx+Port92_Save],al	;R32C
;R32B		in	al,92h				; get a20 states
;R32B		mov	BYTE PTR es:[ebx+Port92_Save],al; save port 92h status

	; Turn off speaker & save port 61H

		in	al,61h				; save port_b status
		mov	BYTE PTR es:[ebx+Port61_Save],al
		and	al,0fch				; turn off speaker
		out	61h,al

		call	Save_8259
		call	Save_8237
		call	Save_8254
;R18 ifdef	AUDIO_KERNEL				;R08
ifndef	No_Save_Sound				;R57
		Call	Save_Sound		;R08
endif	;No_Save_Sound				;R57
;R18 endif	;AUDIO_KERNEL				;R08

	; Save chipset state

		Call	Save_Ct_device		;R03
		call	Save_Chipset

	; Disable SMI trigger after chipset saved

		call	CT_Disable_SMI

	; Save peripherial devices

ifdef	NEW_SUPERIO_KERNEL			;R05
ifndef	DONT_SAVE_SUPER_IO	;R35
		Call	Suspend_Super_IO	;R05
endif	;DONT_SAVE_SUPER_IO	;R35
endif	;NEW_SUPERIO_KERNEL			;R05
;R30 ifndef	Dont_Save_8042_Status		;R25
;R30 		call	Save_8042
;R30 endif	;Dont_Save_8042_Status		;R25
;R32B 		call	Save_8042		;R32
ifdef	NEW_SUPERKBC_KERNEL			;R30
		Call	Suspend_KBC		;R30
endif	;NEW_SUPERKBC_KERNEL			;R30
		call	Save_Mouse
		call	Save_FDC
		call	Save_COMA
		call	Save_COMB
		call	Save_FPU
		call	Suspend_VGA

;R33 - start
if	BIOS_SUPPORT_686
		Call	Check_P6_A20_Status
endif	;BIOS_SUPPORT_686
;R33 - end
	; Save all memory data

		mov	ax,ZV_Temp_Stack
		call	Save_BASEMem			; Save for temp stack

		call	Disable_SMM_Map
		call	Save_VRAM
ifdef	SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
		call	Save_Base_DRAM		;R11
endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
ifndef	NO_ZV_REALTIME_MESSAGE
		Call	Suspend_Status
endif	;NO_ZV_REALTIME_MESSAGE
ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
		call	Save_Base_DRAM
endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
		call	Save_Ext_DRAM
		call	Save_Shadow
		call	Enable_SMM_Map
ifdef	ONBOARD_MODEM_CARD			;R08
		Call	Suspend_Modem		;R08
endif	;ONBOARD_MODEM_CARD			;R08
ifdef	PNP_BIOS				;R08
	ifndef	NO_ISA_PNP			;R54
	ifndef	ZV_DONT_SAVE_PNP		;R26
		Call	Suspend_PnP_Device	;R08
	endif	;ZV_DONT_SAVE_PNP		;R26
	endif	;NO_ISA_PNP			;R54
endif	;PNP_BIOS				;R08

	; Save stack pointer & save SMBASE

		mov	word ptr es:[ebx+SS_Save],ss
		mov	dword ptr es:[ebx+ESP_Save],esp
		call	Save_SMBASE

	; Shutdown byte with NMI off

		mov	al,0Fh NMI_OFF
		mov	ah,ZV_Resume_Byte
		call	E_Set_CMOS

ifdef	NO_ZV_REALTIME_MESSAGE
ifndef	SMM_Show_String
	; To exit SMM for show suspend message

		Call	Restore_SMI_STATE

		mov	edi,ebx
		add	edi,0ff00h
		xor	eax,eax
		mov	es:[edi],eax		; clear I/O trap & halt restart
		mov	ax,Seg Dgroup
		mov	es:[edi+0ach],eax	; CS for exit SMM
		mov	ax,offset Resume_From_SMI
		mov	es:[edi+0f0h],eax	; IP for exit SMM

		RSM				; Exit SMM

	; Here is exit from SMM & system is in real mode ..
Show_Address:
endif	;SMM_Show_String

		mov	ax,ZV_Temp_Stack
		mov	ss,ax
		mov	esp,offset ZV_STACK_TOP

		Call	Set_Full_On_SMM

ifndef	NO_ZV_MESSAGE_DISPLAY
		call	F000_Get_PM_RAM_Seg
		mov	ds,ax
		xor	ax,ax
		mov	es,ax
		Call	F000_Enable_CRT

	; To Show the message before power off

		mov	si,offset Suspend_ZV_MSG
		call	SMM_ZV_Display_MSG

endif	;NO_ZV_MESSAGE_DISPLAY
endif	;NO_ZV_REALTIME_MESSAGE

ifdef	ZV_Suspend_Beep_loop				;R29
		mov	cx,ZV_Suspend_Beep_loop		;R29
Suspend_Beep_loop:					;R29
		push	cx				;R29
		call	PM_Beep				;R29
		pop	cx				;R29
		loop	Suspend_Beep_loop		;R29
else	;ZV_Suspend_Beep_loop				;R29
ifndef	No_ZV_Suspend_Beep				;R21
		call	PM_Beep
		call	PM_Beep
		call	PM_Beep
		call	PM_Beep
		call	PM_Beep
endif	;No_ZV_Suspend_Beep				;R21
endif	;ZV_Suspend_Beep_loop				;R29

		POST_CODE	55h

	; Begin to Shutdown the system

		call	CT_0V_Shutdown
	@@:
		call	PM_Beep
		jmp	short @B

E_Suspend_0V	ENDP

;R34 - start
ifdef	NEW_SUPERVGA_KERNEL
SAVE_BEFORE_PROCESS	Proc	Near
		Extrn	VGA_ON_BEFORE_SAVE:near
		Call	VGA_ON_BEFORE_SAVE
		ret
SAVE_BEFORE_PROCESS	Endp
endif	;NEW_SUPERVGA_KERNEL
;R34 - end

;R43 F000_Get_PM_RAM_Seg:
;R43		F000_call	Get_PM_RAM_Seg
;R43		ret
;R43
;R43F000_Enable_CRT:
;R43		push	ds			;R22
;R43		Call	F000_Get_PM_RAM_Seg	;R22
;R43		mov	ds,ax			;R22
;R43		F000_call	Enable_CRT
;R43		pop	ds			;R22
;R43		ret

;R32F000_A20_ON:
;R32		F000_Call	A20_ON
;R32		ret
;R32B ;R32A - Start
;R32B ifdef	Resume_Turn_on_A20
;R43 F000_A20_ON:
;R43 		F000_Call	A20_ON
;R43 		ret
;R32B endif	;Resume_Turn_on_A20
;R32B ;R32A - End

;R43 ;R33 - start
;R43 if	BIOS_SUPPORT_686
;R43 Check_P6_A20_Status	Proc	Near
;R43
;R43 		mov	ah,P6_A20_Status	;assume A20 is high
;R43 		mov	al,byte ptr es:[ebx+Port92_Save]
;R43 		test	al,02h
;R43 		jnz	short A20M_Is_High
;R43
;R43 		mov	al,byte ptr es:[ebx+Save_8042_Output]
;R43 		test	al,02h
;R43 		jnz	short A20M_Is_High
;R43
;R43 		xor	ah,ah			;A20 is low
;R43 A20M_Is_High:
;R43 		mov	al,P6_A20_CMOS NMI_OFF
;R43 		call	E_Get_CMOS
;R43 		and	al,not P6_A20_Status
;R43 		or	ah,al
;R43 		mov	al,P6_A20_CMOS NMI_OFF
;R43 		call	E_Set_CMOS
;R43
;R43 		ret
;R43 Check_P6_A20_Status	endp
;R43 endif	;BIOS_SUPPORT_686
;R43 ;R33 - end
;R43
;R43 SMM_ZV_Display_MSG	proc	near
;R43
;R43 		push	ds
;R43 		push	si
;R43
;R43 		push	cs
;R43 		pop	ds
;R43
;R43 		mov	bp,sp
;R43 		sub	bp,DATAAREASIZE
;R43 		mov	byte ptr CALLTYPE[bp],SMM_CALL
;R43
;R43 		mov	word ptr Color_Offset[bp],offset VGA_Buffer
;R43 		mov	byte ptr MONOCHROME[bp],1
;R43
;R43 		mov	ax,3				; Clear screen
;R43 		F000_Call	Video_Func
;R43
;R43 		mov	si,offset E_Border_0V_Str
;R43 		call	F_Display_String
;R43 		pop	si
;R43
;R43 		call	F_Display_String
;R43
;R43 		pop	ds
;R43 		ret
;R43 SMM_ZV_Display_MSG	endp
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43
;R43 Suspend_Status	Proc	Near
;R43
;R43 		push	ebx
;R43
;R43 		Call	F000_Enable_CRT
;R43
;R43 	ifdef	Special_Save_VGA_status			;R06
;R43 		Call	Ct_Special_restore_VGA		;R06
;R43 	endif	;Special_Save_VGA_status		;R06
;R43
;R43 		mov	si,offset Suspend_ZV_MSG
;R43 		call	SMM_ZV_Display_MSG
;R43
;R43 		pop	ebx
;R43 		ret
;R43
;R43 Suspend_Status	Endp
;R43
;R43 Resume_Status	Proc	Near
;R43
;R43 		push	ebx
;R43
;R43 		Call	F000_Enable_CRT
;R43
;R43 		mov	si,offset Resume_ZV_MSG
;R43 		call	SMM_ZV_Display_MSG
;R43
;R43 		pop	ebx
;R43 		ret
;R43
;R43 Resume_Status	Endp
;R43
;R43 Show_Transfer_MSG	Proc	Near
;R43
;R43 		push	ds
;R43
;R43 		push	cs
;R43 		pop	ds
;R43
;R43 		Call	F_Display_String
;R43 		mov	si,offset Transfer_MSG
;R43 		Call	F_Display_String
;R43
;R43 		pop	ds
;R43 		ret
;R43
;R43 Show_Transfer_MSG	Endp
;R43
;R43 Transfer_OK_MSG	Proc	Near
;R43
;R43 		push	ds
;R43
;R43 		push	cs
;R43 		pop	ds
;R43
;R43 		Call	F_Display_String
;R43 		mov	si,offset Transferred_MSG
;R43 		Call	F_Display_String
;R43
;R43 		pop	ds
;R43 		ret
;R43
;R43 Transfer_OK_MSG	endp
;R43
;R43 ;[]========================================================================[]
;R43 ;
;R43 ;	Border for suspend/resume message
;R43 ;
;R43 ;[]========================================================================[]
;R43 ZV_Msg_Y	EQU	3
;R43 ZV_Msg_Y1	EQU	8
;R43 ZV_Msg_Y2	EQU	13
;R43 E_Border_0V_Str:
;R43 			db	V_CHG_COLOR,00h
;R43 			db	V_NORMAL
;R43 		BORDER1	<,0,0,79,24,Empty_Border+NO_BORDER>
;R43
;R43 			db	V_CHG_COLOR,0A0h
;R43 			db	V_NORMAL
;R43 		BORDER1	<,12,ZV_Msg_Y-1,68,ZV_Msg_Y+2,Empty_Border+NO_BORDER>
;R43 		BORDER1	<,12,ZV_Msg_Y1-1,68,ZV_Msg_Y1+2,Empty_Border+NO_BORDER>
;R43 ;R15		BORDER1	<,20,ZV_Msg_Y2-1,60,ZV_Msg_Y2+8,Empty_Border+NO_BORDER>
;R43 		BORDER1	<,16,ZV_Msg_Y2-1,64,ZV_Msg_Y2+8,Empty_Border+NO_BORDER>	;R15
;R43
;R43 		  	db	V_CHG_COLOR,00h
;R43 			db	V_NORMAL
;R43 		BORDER1	<,13,ZV_Msg_Y,67,ZV_Msg_Y+1,Empty_Border+NO_BORDER>
;R43 		BORDER1	<,13,ZV_Msg_Y1,67,ZV_Msg_Y1+1,Empty_Border+NO_BORDER>
;R43 ;R15		BORDER1	<,21,ZV_Msg_Y2,59,ZV_Msg_Y2+7,Empty_Border+NO_BORDER>
;R43 		BORDER1	<,17,ZV_Msg_Y2,63,ZV_Msg_Y2+7,Empty_Border+NO_BORDER>	;R15
;R43
;R43 		POS	<,14,ZV_Msg_Y>
;R43 ;R02			db	'Award NoteBIOS v4.51GP(tm) Save To Disk Manager '
;R43 ;R39			db	'Award NoteBIOS v4.51PGM(tm) Save To Disk Manager '	;R02
;R43 			db	'Award EliteBIOS v4.51GPM Save To Disk Manager '	;R39
;R43
;R43 ;R36		POS	<,14,ZV_Msg_Y+1>
;R43 ;R36			db	'Copyright (c) Award Software International, Inc. 1996 '
;R43 		POS	<,14,ZV_Msg_Y+1>						;R36
;R43 			db	'Copyright (c) Award Software International, Inc. 1998 ';R36
;R43
;R43 		POS	<,37,ZV_Msg_Y1>
;R43 			db	'Status'
;R43
;R43 		POS	<,36,ZV_Msg_Y2>
;R43 			db	'Progress'
;R43 		POS	<,22,ZV_Msg_Y2+2>
;R43 			db	'System Information  : '
;R43 		POS	<,22,ZV_Msg_Y2+4>
;R43 			db	'Conventional Memory : '
;R43 		POS	<,22,ZV_Msg_Y2+6>
;R43 			db	'Extended Memory     : '
;R43 			db	0
;R43
;R43 ;[]========================================================================[]
;R43 ;
;R43 ;	Zero-Volt Resume message
;R43 ;
;R43 ;[]========================================================================[]
;R43 		PUBLIC	Resume_ZV_MSG
;R43 Resume_ZV_MSG:
;R43 		POS	<,16,ZV_Msg_Y1+1>
;R43 			db	V_CHG_COLOR,000h
;R43 			db	V_REVERSE
;R43 			db	' Resume from disk in progress.  Please wait....  '
;R43 			db	0
;R43
;R43 ;[]========================================================================[]
;R43 ;
;R43 ;	Zero-Volt Suspend message
;R43 ;
;R43 ;[]========================================================================[]
;R43 Suspend_ZV_MSG:
;R43 		POS	<,16,ZV_Msg_Y1+1>
;R43 			db	V_CHG_COLOR,000h
;R43 			db	V_REVERSE
;R43 			db	'   Save to disk in progress.  Please wait....    '
;R43
;R43 		POS	<,44,ZV_Msg_Y2+2>
;R43 Transferred_MSG:
;R43 			db	V_NORMAL
;R43 ;R15			db	' Transferred  '
;R43 			db	' Transferred 100% '		;R15
;R43 ;R11 - start
;R43 ifdef	SAVE_BASE_DRAM_BEFORE_MESSAGE
;R43 		POS	<,44,ZV_Msg_Y2+4>
;R43 			db	V_NORMAL
;R43 ;R15			db	' Transferred  '
;R43 			db	' Transferred 100% '		;R15
;R43 endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE
;R43 ;R11 - end
;R43 			db	0
;R43
;R43 Transfer_MSG:
;R43 			db	V_REVERSE
;R43 			db	V_BLINK
;R43 ;R15			db	' Transferring '
;R43 			db	' Transferring  5% '		;R15
;R43 			db	0
;R43
;R43 Base_Mem_POS:
;R43 		POS	<,44,ZV_Msg_Y2+4>
;R43 			db	0
;R43
;R43 Ext_Mem_POS:
;R43 		POS	<,44,ZV_Msg_Y2+6>
;R43			db	0
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43
;R43 ;[]==================================================================[]
;R43 ;
;R43 ; Procedure Name: VIDEO_STATE
;R43 ;
;R43 ;	This routine is save/restore Video state
;R43 ;
;R43 ; Saves: All
;R43 ; Input:
;R43 ;	 AL = 1   save Video state
;R43 ;	 AL = 2   restore Video state
;R43 ;
;R43 ; Output:
;R43 ;	 none
;R43 ;
;R43 ; [Note]:
;R43 ;
;R43 ; Author: Daniel Huang
;R43 ; Date: December, 05, 1995
;R43 ;
;R43 ; Name	| Date		| Description
;R43 ; -----------------------------------------------------------------
;R43 ; DNL	| 12/05/95	| Initial version for notebook
;R43 ;[]==================================================================[]
;R43 		Public	VIDEO_STATE
;R43 VIDEO_STATE	Proc	Near
;R43
;R43 		pushad
;R43 		push	ds
;R43 		push	es
;R43
;R43 		mov	bx,ZV_Temp_Stack
;R43 		mov	es,bx
;R43 ;R10 ifdef	VBE_10
;R43 ifndef	NO_VESA_BIOS_SUPPORT				;R10
;R43 		mov	dl,al
;R43 		mov	ax,4f04h
;R43 ;R09		mov	bx,offset VIDEO_BUFFER
;R43 ;R09 - start
;R43 		xor	ebx,ebx
;R43 		mov	bx,ZV_Temp_Stack
;R43 		shl	ebx,4
;R43 		add	ebx,offset VIDEO_BUFFER
;R43 		shr	ebx,4
;R43 		mov	es,bx
;R43 		xor	bx,bx
;R43 ;R09 - end
;R43 		mov	cx,0Fh
;R43 ;R10 else	;VBE_10
;R43 else	;NO_VESA_BIOS_SUPPORT				;R10
;R43 		mov	ah,1Ch
;R43 		mov	bx,offset VIDEO_BUFFER
;R43 		mov	cx,07h
;R43 ;R10 endif	;VBE_10
;R43 endif	;NO_VESA_BIOS_SUPPORT				;R10
;R43 		F000_Call	VIDEO_FUNC
;R43
;R43 		pop	es
;R43 		pop	ds
;R43 		popad
;R43
;R43 		ret
;R43
;R43 VIDEO_STATE	Endp
;R43
;R43 ;[]=======================================================================[]
;R43 ;
;R43 ; Save_8042:
;R43 ;
;R43 ; 		This routine is used to save the status of the keyboard
;R43 ;		before power off.
;R43 ;
;R43 ; Saves :	all but flags
;R43 ;
;R43 ; Input :	ES = G_RAM
;R43 ;		DS = PM Save area
;R43 ;
;R43 ; Output :	None
;R43 ;
;R43 ;[]=======================================================================[]
;R43 		ASSUME	DS:G_RAM
;R43 Save_8042	Proc	Near
;R43
;R43 	; Clear 8042 Output Buffer.
;R43
;R43 		call	Clear_8042_OBF
;R43
;R43 	; Save 8042 Command Byte.
;R43
;R43 		mov	al,020h		;Read Command Byte
;R43 		out	064h,al
;R43 	@@:
;R43 		in	al,064h
;R43 		test	al,02h		;InputBuffer Full
;R43 		jnz	short @B
;R43 	@@:
;R43 		in	al,064h
;R43 		test	al,01h		;OutputBuffer Full
;R43 		jz	short @B
;R43 		in	al,060h
;R43 ;R30		mov	BYTE PTR es:[ebx+Save_8042_Command],al
;R43 ;R32		mov	bh,al		;R30
;R43 ;R32B		mov	BYTE PTR es:[ebx+Save_8042_Command],al	;R32
;R43 		mov	bh,al		;R32B
;R43
;R43 	; Save 8042 Output Port state.
;R43
;R43 		mov	al,0D0h		;Read output port
;R43 		out	064h,al
;R43 	@@:
;R43 		in	al,064h
;R43 		test	al,02h		;InputBuffer Full
;R43 		jnz	short @B
;R43 	@@:
;R43 		in	al,064h
;R43 		test	al,01h		;OutputBuffer Full
;R43 		jz	short @B
;R43 		in	al,060h
;R43 ;R30		mov	BYTE PTR es:[ebx+Save_8042_Output],al
;R43 ;R32		mov	bl,al		;R30
;R43 		or	al,02h					;R32
;R43 ;R32B		mov	BYTE PTR es:[ebx+Save_8042_Output],al	;R32
;R43 		mov	bl,al		;R32B
;R43
;R43 	; Disable 8042 A20 gate line for reset.
;R43
;R43 		mov	al,0FDh		;Pulse A20 low to high
;R43 		out	064h,al		;at KBC
;R43 	@@:
;R43 		in	al,064h
;R43 		test	al,02h		;InputBuffer Full
;R43 		jnz	short @B
;R43
;R43 ;R30 ifdef	NEW_SUPERKBC_KERNEL			;R03
;R43 ;R30 		Call	Suspend_KBC		;R03
;R43 ;R30 endif	;NEW_SUPERKBC_KERNEL			;R03
;R43
;R43 		ret
;R43 Save_8042	Endp

;[]==================================================================[]
;
; Save_Mouse:
;
;		This routine is used to save mouse status, resolution,
;		sample rate
;
;Input    :	ES = G_RAM
;		DS = PM Save area
;
;Output   :	None
;
;[]==================================================================[]
		ASSUME	DS:G_RAM
Save_Mouse	PROC	NEAR

	       	test	byte ptr G_RAM:[HARDWARE],00000100b
		jz 	short Exit_Mouse_Save	; check if mouse exist

		push	ebx
	@@:
		call	Clr_OBF_IBF_AUX
		mov	ax,0c206h		;Extended command
		mov	bh,00h			;Get status
		call	Pointing_Device_Call
		jc	short @B

		mov	ch,bl
		pop	ebx
		mov	byte ptr es:[ebx+Save_Mouse_State],ch
		mov	byte ptr es:[ebx+Save_Mouse_Resolution],cl

	; Get sampling rate index value

		mov	si,6
	@@:
		cmp	cs:[Samplrate+si],dl
		je	@F
		dec	si
		jne	@B
	@@:
		mov	dx,si
		mov	byte ptr es:[ebx+Save_Mouse_Sample_Rate],dl

Exit_Mouse_Save:

		ret

Save_Mouse	ENDP

;[]==================================================================[]
;
; Pointing_Device_Call:
;
;		This routine is used to call the INT15 for PS2 mouse.
;
; Saves    :
;
; Input    :
;
;
; Output   :
;
;[]==================================================================[]

Pointing_Device_Call	PROC	NEAR
		pushf
		FCALL	Multi_Service
		cli
		ret
Pointing_Device_Call	ENDP

;--------------------------------------------------------------------
;
; Mouse sampl-reate translate table
;
;--------------------------------------------------------------------
Samplrate	label	byte			; reports per second
		db	0ah	; 00		; 10 reports/second
		db	14h	; 01		; 20 reports/second
		db	28h	; 02		; 40 reports/second
		db	3ch	; 03		; 60 reports/second
		db	50h	; 04		; 80 reports/second
		db	64h	; 05		; 100 reports/second
		db	0c8h	; 06		; 200 reports/second

;[]===============================================================[]
;
; Save_COMA:
;
;		Routine to save COM 1 status.
;
; Saves    :	None
;
; Input    :	DS = PM Save area
;		ES = G_RAM
;
; Output   :	None
;
;[]==================================================================[]
;R42		ASSUME	DS:G_RAM
Save_COMA	PROC	NEAR

		push	ds				;R42
		call	F000_Get_PM_RAM_Seg		;R42
		mov	ds,ax				;R42
;R42		mov	dx,G_RAM:[COMM_PORT_ADDRS]	;Get COM port address
		mov	dx,ds:[COMA_ADDRS]		;R42
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		mov	esi,ebx
		add	esi,offset COMA_Status
		call	Ct_Save_COMA

;R42		mov	dx,G_RAM:[COMM_PORT_ADDRS]	;Get COM port address
		mov	dx,ds:[COMA_ADDRS]		;R42
		call	Save_COM_Port

	@@:
		pop	ds				;R42

		ret
Save_COMA	ENDP

;[]===============================================================[]
;
; Save_COMB:
;
;		Routine to save COM 2 status.
;
; Saves    :	None
;
; Input    :	DS = PM_RAM
;		ES = G_RAM
;
; Output   :	None
;
;[]==================================================================[]
;R42		ASSUME	DS:G_RAM
Save_COMB	PROC	NEAR

		push	ds				;R42
		call	F000_Get_PM_RAM_Seg		;R42
		mov	ds,ax				;R42
;R42		mov	dx,G_RAM:[COMM_PORT_ADDRS+2]	;Get COM port address
		mov	dx,ds:[COMB_ADDRS]		;R42
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		mov	esi,ebx
		add	esi,offset COMB_Status
		call	Ct_Save_COMB

;R42		mov	dx,G_RAM:[COMM_PORT_ADDRS+2]	;Get COM port address
		mov	dx,ds:[COMB_ADDRS]		;R42
		call	Save_COM_Port

	@@:
		pop	ds				;R42

		ret
Save_COMB	ENDP

;[]===============================================================[]
;
; Save_COM_Port:
;
;		Routine to save COMM port status.
;
;Saves    :	None
;
;Input    :	DX = COMM port address.
;		SI = COMM port status save offset.
;
;Output   :	None
;
;[]==================================================================[]
		ASSUME	DS:G_RAM
Save_COM_Port	PROC	NEAR

		Call	Clear_COMM_Int

		add	dx,3			; Get LCR address
		in	al,dx			; Get LCR value
		mov	BYTE PTR es:[esi],al	; Save LCR value
		and	al,not 80h		; DLAB=0
		out	dx,al

		sub	dx,2			; Get IER address
		in	al,dx			; Get IER value
		mov	BYTE PTR es:[esi+3],al	; Save IER value

		add	dx,3			; Get MCR address
		in	al,dx			; Get MCR value
		mov	BYTE PTR es:[esi+4],al	; Save MCR value

		inc	dx			; Get LSR address
		in	al,dx			; Get LSR value
		mov	BYTE PTR es:[esi+5],al	; Save LSR value

		sub	dx,4			; Get IER address
		xor	al,al			; Disable all interrupt
		out	dx,al

		add	dx,2			; Get LCR address
		in	al,dx
		or	al,080h			; DLAB=1
		out	dx,al

		sub	dx,3			; Divisor latch low address
		in	al,dx			; Get divisor latch low byte
		mov	BYTE PTR es:[esi+1],al	; Save divisor latch low byte

		inc	dx			; Divisor latch high address
		in	al,dx			; Get divisor latch high byte
		mov	BYTE PTR es:[esi+2],al	; Save divisor latch high byte

		add	dx,2			;R08
		in	al,dx			;R08
		and	al,not 80h		;R08 DLAB=0
		out	dx,al			;R08
;R31 start
		dec	dx
		in	al,dx
		mov	BYTE PTR es:[esi+7],al	; Save FIFO status
;R31 end

		ret
Save_COM_Port	ENDP

;[]===============================================================[]
;
; Clear_COMM_Int:
;
;		Routine to clear COMM port interrupt.
;
;Saves    :	DX
;
;Input    :	DX = COMM port address.
;
;Output   :	None
;
;[]==================================================================[]
Clear_COMM_Int	PROC	NEAR
		pusha
		xor	cx,cx
	@@:
		inc	dx
		inc	dx
		in	al,dx
		test	al,1
		jnz	short @F
		dec	dx
		dec	dx
		in	al,dx
		loop	short @B
	@@:
		popa
		ret
Clear_COMM_Int	ENDP

;[]===============================================================[]
;
; Save_FDC:
;		Routine to save floppy controller status.
;
; Input    :	DS = PM Save area
;		ES = G_RAM
;
; Output   :	None
;
;[]==================================================================[]
FDC_DOR			EQU	3F2H
FDC_DSR			EQU	3F4H
FDC_MSR			EQU	3F4H
FDC_DATA		EQU	3F5H
FDC_CCR			EQU	3F7H
FDC_POWER_DOWN		EQU	40H		;power down command
FDC_SW_RESET		EQU	80H		;software reset command

		ASSUME	DS:G_RAM
Save_FDC	PROC	NEAR

		mov	esi,ebx
		add	esi,offset Save_FDC_3F2
		call	Ct_Save_FDC

		mov	al,FDC_POWER_DOWN
		mov	dx,FDC_DSR
		out	dx,al

		mov	cx,4000h
		call	Small_Delay

		ret

Save_FDC	ENDP

;[]========================================================================[]
;
; Save_FPU:
;
; 	Save co-processor status.
;
; Entry:	DS = PM Save area
;		ES = G_RAM
;
; Exit:
;
;[]=========================================================================[]
		ASSUME	DS:G_RAM
Save_FPU	PROC	NEAR

	; Save coprocessor status

		test	G_RAM:[Hardware],2		; check if 387 exists?
		jz	short @F

		mov	eax,cr0
		push	eax
		or	al,1				; Set PE bit
		mov	cr0,eax
		jmp	$+2

	; Now start saving in variable area

		db	66h
		fnsave	es:[ebx+FPU_Status]

		pop	eax
		mov	cr0,eax				; Restore PE bit

	@@:

		ret
Save_FPU	ENDP

;[]===============================================================[]
;
; Save_8259:
;
;		Routine to Save 8259 state both master and slave PIC.
;
; Saves    :	None
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
; Note	   :	The following is save 8259 buffer location brief
;
;		Master ICW1:	Save_8259_Area+0
;		Master ICW2:	Save_8259_Area+1
;		Master ICW3:	Save_8259_Area+2
;		Master ICW4:	Save_8259_Area+3
;		Master OCW1:	Save_8259_Area+4
;		Master OCW2:	Save_8259_Area+5
;		Master OCW3:	Save_8259_Area+6
;		Reserve    :	Save_8259_Area+7
;		Slave ICW1 :	Save_8259_Area+8
;		Slave ICW2 :	Save_8259_Area+9
;		Slave ICW3 :	Save_8259_Area+10
;		Slave ICW4 :	Save_8259_Area+11
;		Slave OCW1 :	Save_8259_Area+12
;		Slave OCW2 :	Save_8259_Area+13
;		Slave OCW3 :	Save_8259_Area+14
;		Reserve    :	Save_8259_Area+15
;
;[]==================================================================[]
		ASSUME	DS:G_RAM
Save_8259	PROC	NEAR

;R28 - start
		mov	al,0Ah NMI_OFF
		call	F000_GET_CMOS
		mov	byte ptr es:[ebx+Save_8259_Area+07h],al		;CMOS addr=0Ah

		mov	al,0Bh NMI_OFF
		call	F000_GET_CMOS
		mov	byte ptr es:[ebx+Save_8259_Area+0Fh],al		;CMOS addr=0Bh
;R28 - end

	; Initial the default value when shadow 8259 is not support.

	; Slave pic
		mov	byte ptr es:[ebx+Save_8259_Area+08h],11h	;icw1
		mov	byte ptr es:[ebx+Save_8259_Area+0ah],02h	;icw3
		mov	byte ptr es:[ebx+Save_8259_Area+0bh],01h	;icw4
		mov	byte ptr es:[ebx+Save_8259_Area+0dh],20h	;ocw2
		mov	byte ptr es:[ebx+Save_8259_Area+0eh],08h	;ocw3
	; Master pic
		mov	byte ptr es:[ebx+Save_8259_Area]  ,11h		;icw1
		mov	byte ptr es:[ebx+Save_8259_Area+2],04h		;icw3
		mov	byte ptr es:[ebx+Save_8259_Area+3],01h		;icw4
		mov	byte ptr es:[ebx+Save_8259_Area+5],20h		;ocw2
		mov	byte ptr es:[ebx+Save_8259_Area+6],0bh		;ocw3


	; Check 8259 difference Windows & DOS

		mov	cx,7008h
		in	al,64h
		test	al,8
		jnz	short @F
		mov	cx,5850h
	@@:
		mov	byte ptr es:[ebx+Save_8259_Area+09h],ch	; Slave icw2
		mov	byte ptr es:[ebx+Save_8259_Area+1],cl	; Master icw2

		call	CT_Save_8259
Save_IRQ_Mask:

	; Save 8259 mask value and mask all IRQ.

		in	al,A8259+1			; read IMR
		mov	es:[ebx+Save_8259_Area+04h],al
		in	al,B8259+1			; read IMR
		mov	es:[ebx+Save_8259_Area+0ch],al

	; Mask all IRQ.

		mov	al,0ffh
		out	A8259+1,al
		out	B8259+1,al

		ret
Save_8259	ENDP

;R28 - start
ifndef	DONT_RELEASE_E000_FOR_PCI
F000_GET_CMOS	Proc	near
		F000_Call	GET_CMOS
		ret
F000_GET_CMOS	Endp
endif	;DONT_RELEASE_E000_FOR_PCI
;R28 - end

;[]===============================================================[]
;
; Save_8254:
;
;		Routine to save 8254 for suspend.
;
; Saves    :	None
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
;[]==================================================================[]
Read_Back_Command	EQU	0CEH
		ALIGN	4
Save_8254	PROC	NEAR

	; Flush counters

		mov	cx, 4
	@@:
		mov	dx, DATA8254
		in	al, dx
		in	al, dx
		inc	dx
		in	al, dx
		in	al, dx
		inc	dx
		in	al, dx
		in	al, dx
		loop	short @B

		push	ebx
		mov	edi,ebx
		add	edi,offset Timer_8254_Save
		mov	dx,DATA8254		; Get counter 0 address.
		mov	al,02h			; Select counter 0
		mov	cx,3

Read_8254_Loop:
		push	ax
		push	cx
		xor	si,si
		xor	cx,cx
		xor	bx,bx
		or	al,0c0h			; Read back command
Read_8254_Loop1:
		out	CTRL8254,al
		xchg	ah,al
		in	al,dx
		xchg	ah,al
		push	ax
		test	ah,10h			; Is LSB need to read ?
		jz	short @F
		in	al,dx
		mov	bl,al
	@@:
		test	ah,20h			; Is MSB need to read ?
		jz	short @F
		in	al,dx
		mov	bh,al
	@@:
		cmp	bx,cx
		jbe	short @F
		mov	cx,bx
	@@:
		pop	ax
		dec	si
		jnz	short Read_8254_Loop1

		mov	es:[edi],ah		;Save counter state
		inc	di
		mov	es:[edi],cl		;Save LSB
		inc	di
		mov	es:[edi],ch		;Save MSB
		inc	di

		pop	cx
		pop	ax
		shl	al,1			; Select next counter
		inc	dx			; next counter port address
		loop	Read_8254_Loop

		pop	ebx
		ret
Save_8254	ENDP

;[]===============================================================[]
;
; Save_8237:
;
;		Routine to Save DMA controller for suspend.
;
; Saves    :	ES,DS
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
;[]==================================================================[]
Save_8237	PROC	NEAR

		push	ebx
		mov	edi,ebx
		add	edi,offset DMA_Page_Save

		mov	al, 00		; Any junk data will do.
		out	0ch,al		; clear flip/flop pointer to slave.
		out	0d8h,al		; clear flip/flop pointer to master.

		mov	dx,0		; save dma1 address and count registers
		mov	cx,8
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		in	al,dx
		stos	byte ptr es:[edi]
		inc	dx
		loop	short @B

		mov	dx,0c0h		; save dma2 address and count registers
		mov	cx,8
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		in	al,dx
		stos	byte ptr es:[edi]
		add	dx,2
		loop	short @B

		mov	dx,81h		; start from port 81h
		mov	cx,16
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		inc	dx
		loop	short @B

		mov	dx,094h
		mov	cx, 3
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		inc	dx
		loop	short @B

		mov	dx,098h
		in	al,dx
		stos	byte ptr es:[edi]
		mov	dx,09Ch
		mov	cx,4
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		inc	dx
		loop	short @B

		mov	dx,0ah		; save dma1 all mask register
		in	al,dx
		stos	byte ptr es:[edi]
		mov	dx,0d4h		; save dma1 all mask register
		in	al,dx
		stos	byte ptr es:[edi]

		mov	dx,0420h	; save s/g descriptor table pointers
		mov	cx,4
	@@:
		in	eax,dx
		stos	dword ptr es:[edi]
		add	dx,4
		loop	short @B

		mov	dx,0434h	; save s/g descriptor table pointers
		mov	cx,3
	@@:
		in	eax,dx
		stos	dword ptr es:[edi]
		add	dx,4
		loop	short @B

		mov	dx,0481h	; save high page registers
		mov	cx,3
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		inc dx
		loop	short @B

		mov	dx,0487h
		in	al,dx
		stos	byte ptr es:[edi]

		mov	dx,0489h
		mov	cx,3
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		inc	dx
		loop	short @B

		pop	ebx
		ret
Save_8237	ENDP

;R43 ;[]===============================================================[]
;R43 ;
;R43 ; Save_Chipset:
;R43 ;
;R43 ;		Routine to Save chipset register for suspend.
;R43 ;
;R43 ; Saves    :	ES,DS
;R43 ;
;R43 ; Input    :	ES = PM Save area
;R43 ;
;R43 ; Output   :	None
;R43 ;
;R43 ;[]==================================================================[]
;R43 		Public	Save_Chipset			;R13
;R43 Save_Chipset	proc	near
;R43
;R43 		push	ebx
;R43 		mov	edi,ebx
;R43 		add	edi,offset Chipset_State_Save
;R43 		mov	si,offset Suspend_Chipset_Table
;R43
;R43 		cld
;R43 Save_Chipset_Loop:
;R43
;R43 		mov	cx,word ptr cs:[si]
;R43 		mov	bx,word ptr cs:[si+2]
;R43 		cmp	cx,0ffffh
;R43 		je	short End_Save_Chipset
;R43 	@@:
;R43 		F000_call	Get_CT
;R43 		stos	byte ptr es:[edi]
;R43 		inc	cx
;R43 		dec	bx
;R43 		jne	short @B
;R43 		add	si,4
;R43 		jmp	short Save_Chipset_Loop
;R43
;R43 End_Save_Chipset:
;R43 		pop	ebx
;R43 		ret
;R43 Save_Chipset	endp

ifndef	NEW_SUPERVGA_KERNEL				;R01
;[]===============================================================[]
;
; Suspend_VGA:
;
;	Subroutine for save VGA status .
;
; Entry:
;
;	ES = Segment for save buffer.
;
; Exit:
;
; Note:
;	The following is standard VGA status save offset in buffer.
;
;		00H	    : sequencr index
;		01H,02H	    : CRTC address
;		03H	    : CRTC index
;		04H	    : graphic index
;		05H	    : attributes index
;		06H	    : Feature control
;		07H - 0AH   : sequencr reg 1 - 4
;		0BH	    : VGA Misc. Register
;		0CH - 24H   : CRTC 0 - 18h
;		25H - 38H   : attribute  0 - 13h
;		39H - 41H   : VGA graphic control register 0 - 8
;		42H	    : VGA DAC register R/W status
;		43H	    : VGA pel address
;		44H	    : VGA pel mask
;		45H	    : VGA (Attribute index 14h) color select register
;		46H - 0146H : VGA DAC register
;
;[]==================================================================[]
Suspend_VGA	PROC	NEAR

;
; Save standard VGA registers
;
		push	ebx
		mov	edi,ebx
		add	edi,offset VGA_State_Save

		mov	dx,3C4h			; VGA sequencr index
		in	al,dx
		stos	byte ptr es:[edi]	;[00]: sequencr index

		call	Get_CRTC_Addr		; VGA CRTC index
		mov	ax,dx
		stos	word ptr es:[edi]	;[01,02]: CRTC address

		in	al,dx
		stos	byte ptr es:[edi]	;[03]: CRTC index

		mov	dx,3CEh			; VGA graphic index
		in	al,dx
		stos	byte ptr es:[edi]	;[04]: graphic index

		mov	dx,3C0h			; VGA attributes index
		in	al,dx
		stos	byte ptr es:[edi]	;[05]: attributes index

		mov	dx,3CAh			; Feature control read register
		in	al,dx
		stos	byte ptr es:[edi]	;[06]: Feature control

		mov	cx,4
		mov	ah,1
		mov	dx,3C4h
		call	Rep_Save_VGA		;[07 - 0A]: sequencr reg 1 - 4

		mov	dx,3CCh			; VGA Misc. Register read
		in	al,dx
		stos	byte ptr es:[edi]	;[0B]: VGA Misc. Register

		mov	cx,19h
		xor	ah,ah
		call	Get_CRTC_Addr
		call	Rep_Save_VGA		;[0C - 24]: CRTC 0 - 18h

		mov	cx,14h
		xor	ah,ah
	@@:
		call	Get_VGA_Att
		stos	byte ptr es:[edi]	;[25 - 38]: attribute  0 - 13h
		inc	ah
		loop	short @B

		mov	cx,9
		xor	ah,ah
		mov	dx,3CEh
		call	Rep_Save_VGA		;[39 - 41]: VGA graphic 0 - 8

		mov	dx,3C7h
		in	al,dx			; VGA DAC state reg
		inc	dx
		and	al,1
		stos	byte ptr es:[edi]	;[42]: VGA DAC reg R/W status
		in	al,dx			; VGA pel address
		jz	short @F
		dec	al
	@@:
		stos	byte ptr es:[edi]	;[43]: VGA pel address

		mov	dl,0C6h
		in	al,dx
		stos	byte ptr es:[edi]	;[44]: VGA pel mask

		mov	ah,14h
		call	Get_VGA_Att
		stos	byte ptr es:[edi]	;[45]: VGA Att 14 color select

		call	Wait_VRetrace
		mov	cx,100h
		xor	al,al
		mov	dx,3C7h
		out	dx,al			; VGA pel address
		inc	dx
		inc	dx
	@@:
		in	al,dx
		stos	byte ptr es:[edi]
		in	al,dx
		stos	byte ptr es:[edi]
		in	al,dx
		stos	byte ptr es:[edi]
		loop	short @B		;[46 - 146] VGA DAC register
;
; Save VGA extended register
;
		call	CT_Save_VGA
		pop	ebx

		ret

Suspend_VGA	ENDP

;[]========================================================================[]
;Procedure:	Save_VRAM
;
;Function :	Save Video RAM for Zero-Volt-Suspend.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;Note	  :	1. Called by Suspend_0V
;		2. The stack is in segment 0000h
;		3. Save location = start location + 1056KB
;[]========================================================================[]
Save_VRAM	PROC	NEAR

		push	ebx
		push	ds

	; Disable CRT display

		call	Reset_VGA_FF
		mov     dx,03c0h
		xor	al,al
		out     dx,al

		Call	Ct_Save_VRAM
		jnc	short Save_VRAM_ok

;
; Save Video RAM
;
		mov     dx,03c4h
		mov     ax,0406h	; Enable chain four mode
		call	Set_VGA_Reg

		mov     dx,03ceh
		mov     ax,0500h
		call	Set_VGA_Reg
		mov     ax,0601h        ; memory mapping select to a000h,128k.
		call	Set_VGA_Reg

		push	es

		mov     dx,03ceh
		mov	ax,0400h		; Set plane 0
		call	Set_VGA_Reg

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_VRAM_Sector

	@@:
		mov	ax,0A000h
		mov	ds,ax
		xor	esi,esi
		mov	ah,30h			; Write command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer
		mov	ax,0B000h
		mov	ds,ax
		xor	esi,esi
		add	ebx,(64*1024)/512
		mov	ah,30h			; Write command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer

		mov     dx,03ceh
		mov	ah,04h
		call	Get_VGA_Reg
		and	al,3
		cmp	al,3			; Is plane 3 ?
		jae	short @F
		inc	al			; Next plane ..
		call	Set_VGA_Reg
		add	ebx,(64*1024)/512	; Next start sector ..
		jmp	short @B
	@@:

		pop	es
Save_VRAM_ok:
		pop	ds
		pop	ebx
		ret
Save_VRAM	ENDP
endif	;NEW_SUPERVGA_KERNEL				;R01

;[]========================================================================[]
;Procedure:	Save_SMBASE
;
;Function :	Save SMBASE for the CPU was reseted by chipset
;		during system reume.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;Note	  :	Called by Suspend_0V
;[]========================================================================[]
Save_SMBASE	PROC	NEAR

		push	es
		push	ds
		push	ebx

		push	es
		pop	ds
		mov	esi,ebx
		add	esi,offset SMI_Entry

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_SMBASE_Sector
		mov	ah,30h			; Write command
		mov	al,(32*1024)/512	; Sector Count
		call	HDD_Transfer

		pop	ebx
		pop	ds
		pop	es

		ret
Save_SMBASE	ENDP

;R43 ;[]========================================================================[]
;R43 ;Procedure:	Save_Shadow
;R43 ;
;R43 ;Function :	Save Shadow RAM C0000h-FFFFFh
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	ES,DS
;R43 ;
;R43 ;Note	  :	Called by Suspend_0V
;R43 ;[]========================================================================[]
;R43 Save_Shadow	PROC	NEAR
;R43 		push	ds
;R43 		push	es
;R43 		push	ebx
;R43
;R43 		mov	al,0
;R43 		call	CT_AllShadow_RW
;R43
;R43 		mov	ax,0c000h
;R43 	@@:
;R43 		call	CT_Skip_ZV_Shadow
;R43 		je	short Skip_ZV_Shadow_Save
;R43
;R43 		call	Save_BASEMem
;R43
;R43 Skip_ZV_Shadow_Save:
;R43
;R43 		add	ax,1000h
;R43 		cmp	ax,0000h
;R43 		jne	short @B
;R43
;R43 		pop	ebx
;R43 		pop	es
;R43 		pop	ds
;R43 		ret
;R43 Save_Shadow	ENDP
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Save_BASEMem
;R43 ;
;R43 ;Function :	Save Base DRAM (below 1M) to HDD.
;R43 ;
;R43 ;Input	  :	AX = Base memory segment for save.
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	DS,ES
;R43 ;
;R43 ;Note	  :	1. System is in SMM.
;R43 ;		2. Save location = start location + 32KB + AX shl 4
;R43 ;
;R43 ;[]========================================================================[]
;R43 Save_BASEMem	PROC	NEAR
;R43 		push	ds
;R43 		push	es
;R43 		push	ax
;R43 		push	ebx
;R43
;R43 		mov	ds,ax
;R43
;R43 		call	Get_ZV_HDD_Loc
;R43 		add	ebx,ZV_HDD_BASEMEM_Sector
;R43 		shr	ax,5
;R43 		and	eax,0780h
;R43 		add	ebx,eax			; Start sector
;R43
;R43 		xor	esi,esi
;R43 		mov	ah,30h			; Write command
;R43 		mov	al,(64*1024)/512	; Sector Count
;R43 		call	HDD_Transfer
;R43
;R43 		pop	ebx
;R43 		pop	ax
;R43 		pop	es
;R43 		pop	ds
;R43 		ret
;R43 Save_BASEMem	ENDP
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Save_Base_DRAM
;R43 ;
;R43 ;Function :	Save Base DRAM (640K) to HDD.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	ALL
;R43 ;
;R43 ;Note	  :	1. System is in SMM.
;R43 ;		2. called by Suspend_0V
;R43 ;[]========================================================================[]
;R43 Save_Base_DRAM	proc	near
;R43
;R43 ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		push	ebx
;R43 		mov	si,offset Base_Mem_POS
;R43 		Call	Show_Transfer_MSG
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43 endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
;R43
;R43 		mov	ax,0000h
;R43 	@@:
;R43 		cmp	ax,ZV_Temp_Stack	; If this segment is current
;R43 		je	short skip_Save_Base	; Stack then skip save it.
;R43 		call	Save_BASEMem
;R43 skip_Save_Base:
;R43 		add	ax,1000h
;R43 ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE		;R15
;R43 ifndef	NO_ZV_REALTIME_MESSAGE			;R15
;R43 		Call	Show_Base_Percent	;R15
;R43 endif	;NO_ZV_REALTIME_MESSAGE			;R15
;R43 endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE		;R15
;R43 		cmp	ax,0a000h
;R43 		jb	short @B
;R43
;R43 ifndef	SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		mov	si,offset Base_Mem_POS
;R43 		Call	Transfer_OK_MSG
;R43 		pop	ebx
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43 endif	;SAVE_BASE_DRAM_BEFORE_MESSAGE		;R11
;R43
;R43 		ret
;R43 Save_Base_DRAM	endp
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Save_Ext_DRAM
;R43 ;
;R43 ;Function :	Save Extended memory to HDD.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	All
;R43 ;
;R43 ;Note	  :	1. System is in SMM.
;R43 ;		2. Called by Suspend_0V.
;R43 ;		3. Extended memory save location = start location + 1536KB
;R43 ;
;R43 ;[]========================================================================[]
;R43
;R43 Save_Ext_DRAM	proc	near
;R43
;R43 		push	es
;R43 		push	ds
;R43 		push	ebx
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		mov	si,offset Ext_Mem_POS
;R43 		Call	Show_Transfer_MSG
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43
;R43 		call	Get_ZV_HDD_Loc
;R43 		add	ebx,ZV_HDD_EXTMEM_Sector
;R43
;R43 	; Get extended memory size
;R43
;R43 		call	Get_EXT_Memory
;R43 ;R14		shr	cx,6			; 64K block
;R43
;R43 		mov	esi,1024*1024
;R43 		xor	ax,ax
;R43 		mov	ds,ax
;R43 	@@:
;R43 		mov	ah,30h			; Write command
;R43 		mov	al,(64*1024)/512	; Sector Count
;R43 		call	HDD_Transfer
;R43 		add	ebx,(64*1024)/512
;R43 		add	esi,64*1024
;R43 ifndef	NO_ZV_REALTIME_MESSAGE			;R15
;R43 		Call	Show_ext_Percent	;R15
;R43 endif	;NO_ZV_REALTIME_MESSAGE			;R15
;R43 		loop	short @B
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		mov	si,offset Ext_Mem_POS
;R43 		Call	Transfer_OK_MSG
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43 		pop	ebx
;R43 		pop	ds
;R43 		pop	es
;R43
;R43 		ret
;R43 Save_Ext_DRAM	endp
;R43
;R43 ;R15 - start
;R43 Show_Base_Percent	Proc	Near
;R43
;R43 		pushad
;R43
;R43 		shr	ax,12
;R43 		mov	bl,10
;R43 		mul	bl
;R43 		jmp	short Show_Percent
;R43
;R43 Show_Base_Percent	Endp
;R43
;R43 Show_Ext_Percent	Proc	Near
;R43
;R43 		pushad
;R43
;R43 		mov	ax,word ptr PAGE_START[bp]
;R43 		sub	ax,cx
;R43 		inc	ax
;R43 		mov	bx,100
;R43 		mul	bx
;R43 		mov	bx,word ptr PAGE_START[bp]
;R43 		div	bx
;R43 Show_Percent:
;R43 		mov	byte ptr CURSOR_X[bp],58
;R43 		F000_call	AX_To_DEC2
;R43 		F000_Call	Show_SIX_DIGIT
;R43 		mov	al,'%'
;R43 		F000_call	Display_Char
;R43 Show_Percent_Exit:
;R43 		popad
;R43 		ret
;R43 Show_Ext_Percent	Endp
;R43 ;R15 - end

;R12 - start
ifndef	NO_STR_SUPPORT
;[]========================================================================[]
;
; E_Resume_5V:
;
;	Resume system from Five-Volt-Suspend.
;
;
;[]=========================================================================[]

		PUBLIC	E_Resume_5V
E_Resume_5V	PROC	FAR

		cld

	; Clear shutdown byte with NMI off

		mov	al,0Fh NMI_OFF
		mov	ah,0
		call	E_Set_CMOS

		mov	al,0ffh
		out	A8259+1,al
		out	B8259+1,al

	; Turn off speaker

		in	al,61h
		and	al,0fch				; turn off speaker
		or	al,0ch
		out	61h,al

		call	CT_System_Wakeup

;R32		Call	F000_A20_ON
		Call	F000_A20_ON			;R32B

		mov	ax,G_RAM
		mov	ds,ax

		call	PM_Beep

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

		Call	Restore_SMI_STATE
		Call	Restore_Original_SMBASE

	; Restore chipset state

		call	Restore_Chipset
		Call	Restore_Ct_device

if	BIOS_SUPPORT_686		  		;R46
;R47   		Call	Restore_L2Cache 		;R46
   		Call	Restore_L2Cache_Reg 		;R47
		Call	Update_P6code			;R55

endif	;BIOS_SUPPORT_686				;R46

	; Restore peripherial devices

;R18	ifdef	AUDIO_KERNEL
ifndef	No_Save_Sound				;R57
		Call	Restore_Sound
endif	;No_Save_Sound				;R57
;R18	endif	;AUDIO_KERNEL
ifdef	NEW_SUPERIO_KERNEL
ifndef	DONT_SAVE_SUPER_IO	;R35
		Call	Restore_Super_IO
endif	;DONT_SAVE_SUPER_IO	;R35
endif	;NEW_SUPERIO_KERNEL
		call	Restore_FPU
;R32B ifndef	Dont_Save_8042_Status		;R25
;R32B		call	Restore_8042
;R32B endif	;Dont_Save_8042_Status		;R25
ifdef	NEW_SUPERKBC_KERNEL			;R45
ifndef	No_resume_KBC_In_STR			;R53
		Call	Resume_KBC		;R45
endif	;No_resume_KBC_In_STR			;R53
endif	;NEW_SUPERKBC_KERNEL			;R45
		call	Restore_Mouse
		call	Restore_FDC
		call	Restore_COMA
		call	Restore_COMB
		call	Ct_5V_Resume_VGA
ifndef	UseHWVGASuspend				;R59
		call	Resume_VGA
endif	;UseHWVGASuspend			;R59

	ifndef	NO_STR_PASSWORD_CHECK			;R16
		Call	Ct_Enable_CRT			;R16
		Call	Ck_Resume_Password		;R16
	endif	;NO_STR_PASSWORD_CHECK			;R16
	; Restore all the saved I/O port

		call	Restore_8254
		call	Restore_8237
		call	Restore_8259

		mov	al,BYTE PTR es:[ebx+Port61_Save]
		out	61h,al
;R32B		mov	al,BYTE PTR es:[ebx+Port92_Save]
;R32B		out	92h,al

	; Clear 8042 output buffer

		call	Clear_8042_OBF

		mov	dx,ds:[COMM_PORT_ADDRS]		;Get COM port address
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		Call	Clear_COMM_Int
@@:
		mov	dx,ds:[COMM_PORT_ADDRS+2]	;Get COM port address
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		Call	Clear_COMM_Int
@@:
		Call	Reset_HDD			;R46
		Call	Set_PIO_Mode			;R60

	; Restore stack pointer

		mov	esp,dword ptr es:[ebx+ESP_Save]
		mov	ax,word ptr es:[ebx+SS_Save]
		mov	ss,ax

		Call	Restore_SMI_STACK
;R32B - start
		pop	ax
		out	92h,al
		pop	bx
 		call	Restore_8042
;R32B - end

		pop	gs
		pop	fs
		pop	es
		pop	ds
		popad

		ret
E_Resume_5V	ENDP

;R46 - start
if	BIOS_SUPPORT_686
	     	Public 	Save_L2Cache_Reg
Save_L2Cache_Reg	Proc	near

		push	ebx
		mov	edi,ebx
		add	edi,offset L2Cache_Save
		mov	si,offset L2Cache_Reg_Tbl

		cld
		xor	ecx,ecx
Save_L2Cache_Loop:
		mov	cx,word ptr cs:[si]
		mov	bx,word ptr cs:[si+2]
		cmp	cx,0ffffh
		je	short End_Save_L2Cache
	@@:
		RDMSR
		stos	Dword ptr es:[edi]

		inc	cx
		dec	bx
		jne	short @B
		add	si,4
		jmp	short Save_L2Cache_Loop

End_Save_L2Cache:
		pop	ebx
		ret

Save_L2cache_Reg	endp

		Public	Restore_L2Cache_Reg
Restore_L2Cache_Reg	Proc	near
		push	ds
		push	ebx

		push	es
		pop	ds
		mov	esi,ebx
		add	esi,offset L2Cache_Save
		mov	di,offset L2Cache_Reg_Tbl
		xor	ecx,ecx

Restore_L2Cache_Loop:

		mov	bx,word ptr cs:[di+2]
		mov	cx,word ptr cs:[di]
		cmp	cx,0ffffh
		je	short End_Restore_L2Cache
		xor	edx,edx
	@@:
		lods	Dword ptr ds:[esi]
		WRMSR
		inc	cx
		dec	bx
		jne	short @B
		add	di,4
		jmp	short Restore_L2Cache_Loop

End_Restore_L2Cache:

		pop	ebx
		pop	ds
		ret
Restore_L2cache_REg	endp

L2Cache_Reg_TBL:
		DW	2ah,1	   	;EBL_CR_POWERON
		DW     	88h,4		;BBL_CR_D0 - D3
		DW     	116h,1		;BBL_CR_ADDR
		dw	118h,1		;BBL_CR_DECC
		DW     	119h,1		;BBL_CR_CTL
		DW     	11Eh,1		;BBL_CR_CTL3
		DW     	40ch,2		;BBL_CR_MC4_CTL
		DW     	0ffffh

endif	;BIOS_SUPPORT_686			;R47

;R60 Reset_HDD	Proc	Near
;R60 		cmp     ds:[SECTOR_PER_BLOCK_0],0	;R47
;R60 		je	short No_Reset_HDD		;R47
;R60
;R60 		mov	dx,3f6h
;R60 		mov	al,4
;R60 		out	dx,al
;R60
;R60 		xor	cx,cx
;R60 		loop	$
;R60 		mov	al,8
;R60 		out	dx,al
;R60
;R60 		mov	dx,1f6h
;R60 @@:
;R60 		mov	al,0a0h
;R60 		out	dx,al
;R60 		inc	dl
;R60 		in	al,dx
;R60 		dec	dl
;R60 		test	al,80h
;R60 		jnz	short @B
;R60
;R60 		mov	al,0a0h
;R60 		out	dx,al
;R60
;R60 		inc	dl
;R60 @@:
;R60 		in	al,dx
;R60 		test	al,80h
;R60 		jnz	short @B
;R60
;R60 		mov	dx,1f2h
;R60 		mov	al,ds:[SECTOR_PER_BLOCK_0]
;R60 		out	dx,al
;R60
;R60 		mov	dx,1f7h
;R60 		mov	al,0c6h
;R60 		out	dx,al
;R60 No_Reset_HDD:						;R47
;R60
;R60 		ret
;R60 Reset_HDD	Endp

;R47endif	;BIOS_SUPPORT_686
;R47;R46 - end
		ALIGN	4
		Public	Restore_SMI_STACK
Restore_SMI_STACK	Proc	Near

		pop	dx		;Restore Return Address

		mov	esi,ebx
		add	esi,offset SMM_Temp_Buffer
		mov	edi,ebx
		add	edi,esp

		mov	cx,offset STACK_TOP
		sub	cx,sp
@@:
		lods	byte ptr es:[esi]
		stos	byte ptr es:[edi]
		loop	short @b

		push	dx
		ret

Restore_SMI_STACK	Endp

;R16 - start
ifndef	NO_STR_PASSWORD_CHECK
		Public	Ck_Resume_Password
Ck_Resume_Password	Proc	Near
		push	ds			;R48
		Call	Save_GRAM
		Call	Disable_SMM_Map
 		mov	al,01h
		Call	Video_state
		Call	Save_Screen

		sub	sp,DATAAREASIZE		; reserve stack size for setup
		mov	bp,sp
		push	es
		push	ebx
		Call	Setup_GRAM
		F000_call	Read_Cmos_To_Stack

		mov	byte ptr CALLTYPE[bp],SMM_CALL
		mov	word ptr Color_Offset[bp],offset VGA_Buffer
		mov	byte ptr MONOCHROME[bp],1

		mov	al,2
		call	Fproc_Verify_Password

		pop	ebx
		pop	es
		add	sp,DATAAREASIZE
		Call	Restore_Screen
 		mov	al,02h
		Call	Video_state
		Call	Enable_SMM_Map
		Call	Restore_GRAM
		pop	ds			;R48
		ret

Ck_Resume_Password	Endp

Save_GRAM	Proc	Near

		push	ds
		push	es
		pop	ds

		xor	esi,esi
		mov	edi,ebx

	;;block 1: save 0:0 - 0:5FFFh to SMBASE:00000h - SMBASE:5FFFh

		mov	ecx,6000h / 4
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

	;;block 2: save 0:E000h - 0:FFFFh to SMBASE:06000h - SMBASE:7FFFh

		add	esi,08000h

		mov	ecx,2000h / 4
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

		pop	ds
		ret
Save_GRAM	Endp

Restore_GRAM	Proc	Near

		push	ds
		push	es
		pop	ds

		xor	edi,edi
		mov	esi,ebx

	;;block 1: restore SMBASE:00000h - SMBASE:5FFFh to 0:0 - 0:5FFFh

		mov	ecx,6000h / 4
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

	;;block 2: restore SMBASE:06000h - SMBASE:7FFFh to 0:E000h - 0:FFFFh

		add	edi,08000h

		mov	ecx,2000h / 4
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B

		pop	ds
		ret
Restore_GRAM	Endp

Setup_GRAM	Proc	Near

		push	ds

	;; restore Original Int 10h,int 15h, int 16h interrupt vector

		call	F000_Get_PM_RAM_Seg
		mov	ds, ax
		mov	eax,dword ptr ds:INT10_Save

		mov	dx,G_RAM
		mov	ds,dx
		mov	dword ptr ds:INT10,eax

		mov	ax,0F000h
		shl	eax,16
		mov	ax,offset Multi_Service
		mov	dword ptr ds:INT15,eax

		mov	ax,offset KEYBOARD
		mov	dword ptr ds:INT16,eax

		pop	ds
		ret

Setup_GRAM	Endp

Save_Screen	Proc	Near

		push	ds
		push	es
		push	ebx

		mov	ax,4F02h
		mov	bx,8003h		;Set Mode 3h
		F000_Call	Video_Func

		pop	ebx
		pop	es

		push	es
		pop	ds

		mov	esi,0B8000h
		mov	edi,004000h

	;;block 1: save B800:0 - B800:1FFFh to 0:4000h - 0:5FFFh

		mov	ecx,2000h / 2
@@:
		lods	word ptr ds:[esi]
		stos	word ptr es:[edi]
		loop	short @B

		pop	ds
		ret

Save_Screen	Endp

Restore_Screen	Proc	near

		push	ds

		push	es
		pop	ds

		mov	edi,0B8000h
		mov	esi,004000h

	;;block 1: Restore 0:04000h - 0:5FFFh to B800:0 - B800:1FFFh

		mov	ecx,2000h / 2
@@:
		lods	word ptr ds:[esi]
		stos	word ptr es:[edi]
		loop	short @B

		pop	ds
		ret
Restore_Screen	Endp

		Public	Clear_Screen
Clear_Screen	Proc	far

		push	es
		push	ax
		push	ecx
		push	edi

		xor	ax,ax
		mov	es,ax

		mov	ecx,2000h / 2
		mov	ax,0720h
		mov	edi,0B8000h
		rep	stos word ptr es:[edi]

		pop	edi
		pop	ecx
		pop	ax
		pop	es
		ret

Clear_Screen	Endp

;[]========================================================================[]
;[]========================================================================[]
		Public	Get_SMM_Key
Get_SMM_Key	Proc	far

	;;setup Temp Ketboard buffer

		push	ds
		push	es
		push	si
		push	ebx

		mov	ax,G_RAM
		mov	ds,ax
		ASSUME	DS:G_RAM

		mov	ax,ds:[KBD_BUF_LOCN]
		mov	ds:[PTR_KBD_BUF_HD],ax
		mov	ds:[PTR_KBD_BUF_TL],ax
		xor	ax,ax
		mov	si,ds:[PTR_KBD_BUF_HD]
		mov	ds:[si],ax		;clear key buffer
Get_Next_Key:
		Call	Clear_Key_Buffer
Wait_KeyIn:
		in	al,STAT8042
		test	al,OBF_8042
		jnz	short Get_Key_Data

		NEWIODELAY
		jmp	short Wait_KeyIn
Get_Key_Data:
		Call	SMI_Int9

		mov	si,ds:[PTR_KBD_BUF_HD]
		mov	ax,ds:[si]
		or	ax,ax			;Valid key ?
		jz	short Get_Next_Key	;No

		mov	bx,ds:[KBD_BUF_LOCN]
		mov	ds:[PTR_KBD_BUF_HD],bx
		mov	ds:[PTR_KBD_BUF_TL],bx

		Call	Clear_Key_Buffer

		pop	ebx
		pop	si
		pop	ds
		pop	es
		ret

Get_SMM_Key	Endp

Clear_Key_Buffer	Proc	Near

		push	ax
	;; reset port_A

		in	al,CTRL8042
		mov	ah,al
		or	al,80h
		out	CTRL8042,al
		NEWIODELAY
		mov	al,ah
		out	CTRL8042,al
		NEWIODELAY

@@:
		in	al,STAT8042
		test	al,OBF_8042
		jz	short @f

		NEWIODELAY
		in	al,DATA8042		;read again to clear
		NEWIODELAY
		jmp	short @B
@@:
		pop	ax

		ret
Clear_Key_Buffer	Endp

SMI_Int9	Proc	near

		push	ds
		push	es
		pusha

		mov	bx,G_RAM		; set data seg
		mov	ds,bx
		ASSUME	DS:G_RAM
						; process disable keyboard
		in	al,DATA8042		; READ DATA FROM 8042

; MAKE 2 BYTE VARIABLES (scan_char,temp)

		mov	bp,sp
		sub	sp,2

		mov	scan_char,al		; save scan after int 15

; check scan response

		Call	Update_Kyb_Led

		cmp	AL,KBS_OVER		; is this an overrun char?
		JNE	SHORT .D18F

		JMP	.D806			; OVERFLOW - ring bell

; check to see if there is a read id in progress

.D18F:
		MOV	AH,KB_FLAG_3		; get flag
		TEST	AH,READ_ID+LAST_AB	; check
		JE	SHORT NO_READID		; no read id in progress
		JS	SHORT FIRST_ID		; looking for 1st byte

		AND	AH,NOT LAST_AB		; reset flags
		CMP	AL,ID_101_2		; is this the 2nd id byte
		JNE	SHORT EX_READID		; if not, just clear flag

		OR	AH,E101_KEY		; set 101 keyboard flag
		TEST	AH,FORCE_NUM		; should we set num lock
		JZ	SHORT EX_READID		; if not, just return
		OR	SHFT_STAT,NUM_LK	; set num lock flag
		MOV	KB_FLAG_3,AH		; restore flag
		Call	Update_Kyb_Led
		JMP	SHORT QWIK_EXIT		; leave

FIRST_ID:
		AND	AH,NOT(READ_ID+LAST_AB)	; reset flags
		CMP	AL,ID_101_1		; is this the first id byte

		JNE	SHORT EX_READID		; if not, just clear flag
		OR	AH,LAST_AB		; if yes, set LAST_AB flag

EX_READID:
		MOV	KB_FLAG_3,AH		; restore flag
QWIK_EXIT:
		JMP	.D86A

NO_READID:
		CMP	AL,0E0H			; is this an E0 char
		JNE	SHORT TRY_E1

		OR	KB_FLAG_3,LAST_E0+E101_KEY	; set E0 flag
		JMP	.D86A_EXIT		; return without reseting flag

TRY_E1:
		CMP	AL,0E1H			; is this an E1 char
		JNE	SHORT NO_E

		OR	KB_FLAG_3,LAST_E1+E101_KEY	; set E1 flag
.DE1_E0:
		JMP	.D86A_EXIT		; return without reseting flag

NO_E:
		MOV	TEMP,0

; get values from 'keys' table

		mov	si,seg Keys
		mov	es,si
		mov	si,offset DGROUP:Keys	; setup pointer in table
		mov	dl,al			; save scan code in dl
		and	ax,07fh
		shl	ax,1
		shl	ax,1
		add	si,ax			; si = pointer to 'keys' table

; check groups and start process

		mov	dh,KB_FLAG_3		; get kb flag for later use

; check for shift (treat make/break shift the same)

		xor	ax,ax
		mov	al,es:[si]		; get key type from table

		cmp	al,SHIFT
		jne	short keyt_1		; skip : shift

		test	dh,LAST_E1		; are we in a E1 sequence
		jne	short .de1_e0		; return without resetting e1

		test	dh,LAST_E0		; is this an E0
		je	short keyt_ret		; if not, exit

		test	byte ptr es:[si]+1,ALT+CTRL	; if this is alt or ctrl
		jne	short keyt_ret			; continue processing normal
		jmp	short qwik_exit			; else if shift, throw away

; process break codes

keyt_1:
		test	dl,80h			; dl contains scan code
		jz	short keyt_3		; skip : it is a make key

		and	dl,07fh			; dl = make scan code

		cmp	al,TOGGLE
		je	short keyt_2		; cont : this is a toggle key

		cmp	dl,INS_KEY
		jne	short keyt_ret_brk	; cont : this is the insert key

; indicate toggle key released

keyt_2:
		mov	al,es:+1[si]
		not	al
		and	kbd_flg1,al

		jmp	short keyt_ret_brk

; check for if we should end hold state

keyt_3:
		test	KBD_FLG1,HOLD
		jz	short keyt_ret		; hold active

		cmp	dl,NUM_KEY
		jz	short keyt_ret		; process key but don't end hold

		cmp	dl,SYS_KEY
		jz	short keyt_ret		; process key but don't end hold

		test	SHFT_STAT,CTRL
		jnz	short keyt_5		; release hold if <ctrl> on

		cmp	dl,CAPS_KEY
		jz	short keyt_ret		; process key but don't end hold

		cmp	dl,SCRL_KEY
		jz	short keyt_ret		; process key but don't end hold

keyt_5:
		and	KBD_FLG1,NOT HOLD	; END HOLD STATE AND EAT CHARACTER

keyt_ret_brk:
		mov	ax,BREAK		; return break code

; jump to routine for key type

keyt_ret:
		mov	bx,ax			; get type
		cmp	bx,BREAK		; check for value in bound
		jb	short go_jmp		; good value

		mov	bx,BREAK		; error
go_jmp:
		shl	bx,1			; word offset
		jmp	word ptr cs:jmptable[bx]	; jmp to routine

		ALIGN	4
jmptable:	dw	offset	SHIFT_S		; SHIFT
		dw	offset	ALPHA_S		; ALPHA
		dw	offset	ASCII_S		; ASCII
		dw	offset	FUNC_S		; FUNCTION
		dw	offset	KEYP_S		; KEYPAD
		dw	offset	TOG_S		; TOGGLE
		dw	offset	NUM_S		; NUMERIC
		dw	offset	F11_HND		; F11_F12
		dw	offset	.D86A		; BREAK

; process shift:

; update flag on shift state

shift_s:
		mov	al,es:+1[si]		; get bit mask
		mov	ah,al			; save template
		test	scan_char,80h		; check  make/break
		je	short .d24c		; goto make

		not	al			; set break
		and	SHFT_STAT,al		; clear flag

		test	ah,ALT+CTRL		; is this an ALT or CTRL key
		JE	SHORT .D260		; no, we are done

		TEST	DH,LAST_E0		; is this a right shift key
		JE	SHORT LEFT_BREAK

		AND	KB_FLAG_3,AL		; clear right shift key
		JMP	SHORT .D260

LEFT_BREAK:
		ror	al,2			; change template
		AND	KBD_FLG1,AL		; clear left shift key
		JMP	SHORT .D260

.D24C:
		OR	SHFT_STAT,AL		; set make
		TEST	AL,ALT+CTRL		; is this an ALT or CTRL key?
		JE	SHORT .D260		; no, we are done

		TEST	DH,LAST_E0		; is this an E0 shift (right)
		JE	SHORT LEFT_MAKE

		OR	KB_FLAG_3,AL		; set right shift key flag
		JMP	SHORT .D260

LEFT_MAKE:
		shr	al,2			; change template
		OR	KBD_FLG1,AL		; set left shift key flag

; CHECK FOR END OF ALT INPUT

.D260:
		CMP	SCAN_CHAR,0B8H
		JE	SHORT NOT_D86A_L1
.D86A_L1:
		JMP	.D86A			; DONE : END OF ALT INPUT
NOT_D86A_L1:

; if(kchar = getd(ALT_INPUT,0)) /*does it exist ? */

		MOV	AL,ALT_INPUT
		OR	TEMP,AL			; SET CHARACTER VALUE
		JZ	SHORT .D86A_L1		; DONE

; scan = 0; putd(ALT_INPUT,0,0);

		XOR	AX,AX
		MOV	SCAN_CHAR,AL
		MOV	ALT_INPUT,AL		; 0
		JMP	.D7BA			; SAVE VALUE

; PROCESS ALPHA:

; CHECK FOR "SPACE"

ALPHA_S:
		CMP	SCAN_CHAR,57
		JNE	SHORT .D2A3		; NOT SPACE

		MOV	TEMP,20H		; SET "SPACE" VALUE
		JMP	SHORT .D310

; CHECK FLAG FOR FLAVOR (ALT, CNTR, ECT)

.D2A3:
		TEST	SHFT_STAT,ALT
		JNE	SHORT .D310

.D2CB:		TEST	SHFT_STAT,CTRL
		JE	SHORT .D2EC

		MOV	AL,es:+3[SI]		; ctrl code
		MOV	TEMP,AL			; set TEMP to code from table
		JMP	SHORT .D310

.D2EC:
		MOV	AL,es:+1[SI]		; GET ALPHA VALUE
		MOV	TEMP,AL

		TEST	SHFT_STAT,CAPS_LK
		JE	SHORT .D30F

		AND	TEMP,0DFH		; MAKE UPPER CASE

.D30F:
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JE	SHORT .D310

		XOR	TEMP,20H		; SWITCH CASE
.D310:
		JMP	SWITCH_DONE

; PROCESS NON ALPHA ASCII CHARACTERS
; starting with the speed switching combination

ASCII_S:
		MOV	AL,SHFT_STAT		; check for ctrl alt +,- V2.08
		AND	AL,ALT+CTRL

; CHECK FLAG FOR FLAVOR (ALT, CNTR, ECT)

.D31EB:
		TEST	SHFT_STAT,ALT
		JE	SHORT .D336		; jmp if not ALT

		CMP	SCAN_CHAR,0FH		; is this a tab
		JNE	SHORT .D335_2

		MOV	SCAN_CHAR,165		; set code
		JMP	SHORT .D335

; put in checks for  keypad / and keypad RETURN

.D335_2:
		TEST	DH,LAST_E0		; is this extended code
		JE	SHORT .D335		; if not, finished

		CMP	SCAN_CHAR,01CH		; keypad RETURN
		JNE	SHORT .D335_1		; next

		MOV	SCAN_CHAR,166		; set scan code
		JMP	SHORT .D335

.D335_1:
		CMP	SCAN_CHAR,035H		; keypad /
		JNE	SHORT .D335		; done

		MOV	SCAN_CHAR,164		; set scan code

.D335:
		CMP	SCAN_CHAR,084H		; is this in old range
		JBE	SHORT .D335_A
		JMP	.D310			; if not leave code as 0
.D335_A:
		MOV	TEMP,0F0H		; set extended function
		JMP	.D310			; yes, 101, ALTs defined

.D336:
		TEST	SHFT_STAT,CTRL		; ctrl characters?
		JE	SHORT .D356

		mov	al,es:+3[si]		; ctrl code

		CMP	SCAN_CHAR,0FH		; is this a tab
		JNE	SHORT .D336_C		; check next case

		MOV	SCAN_CHAR,094H		; tab is extended function
.D336_F:
		MOV	AL,0			; set extended code
		JMP	SHORT .D336_B

.D336_C:
		CMP	SCAN_CHAR,04AH		; is this keypad -
		JNE	SHORT .D336_G		; no, check next case

		MOV	SCAN_CHAR,142		; ctrl - is extended function
		JMP	SHORT .D336_F

.D336_G:
		CMP	SCAN_CHAR,04EH		; is this keypad +
		JNE	SHORT .D336_D		; no, check extended keys

		MOV	SCAN_CHAR,144		; ctrl + is extended function
		JMP	SHORT .D336_F

.D336_D:
		TEST	DH,LAST_E0		; alternate function
		JE	SHORT .D336_B		; if not, go home

		CMP	SCAN_CHAR,035H		; is this keypad '/'
		JNE	SHORT .D336_A		; if not, check next case

		MOV	SCAN_CHAR,149		; set scan code
		JMP	SHORT .D336_F

.D336_A:
		CMP	SCAN_CHAR,01CH		; is this keypad RETURN
		JNE	SHORT .D336_B

.D336_E:
		MOV	SCAN_CHAR,0E0H		; set prefix code

.D336_B:
		MOV	TEMP,AL			; set TEMP to code from table
		JMP	SWITCH_DONE

.D356:
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JE	SHORT .D368		; jmp if no shift

		mov	al,es:+2[si]		; shift code

		TEST	DH,LAST_E0		; is this alternate key
		JE	SHORT .D336_B		; if not, finish

		CMP	AL,03FH 		; is this '?' (shift /)
		JNE	SHORT .D368_A		; no, test for keypad RETURN
						; yes, get unshifted code
.D368:
		mov	al,es:+1[si]		; unshifted code
		TEST	DH,LAST_E0		; is this alternate key

		JE	SHORT .D336_B		; if not, finish

		CMP	AL,02FH			; is this a '/'
		JE	SHORT .D336_E		; yes, set prefix code

.D368_A:
		CMP	AL,0DH			; is this keypad RETURN
		JNE	SHORT .D336_B		; return normal scan code

		JMP	SHORT .D336_E		; set prefix code

; PROCESS NUMERIC

NUM_S:


.D375:
		TEST	SHFT_STAT,ALT
		JNE	SHORT .D375_A
		JMP	.D336			; CHECK STATES

.D375_A:
		ADD	SCAN_CHAR,118		; make alt #
		JMP	SWITCH_DONE

; PROCESS TOGGLE

TOG_S:
		mov	al,es:+1[si]		; CHECK IF ALREADY SET
		TEST	KBD_FLG1,AL
		JE	SHORT .D3AE		; NOPE

		CMP	SCAN_CHAR,046H		; <CTRL><SCROLL LOCK>?
		JNE	SHORT .D86A_L4		; SKIP

		TEST	SHFT_STAT,CTRL
		JE	SHORT .D86A_L4		; SKIP

.D3AE:
		OR	KBD_FLG1,AL		; SET BIT

.D3E8:
		CMP	SCAN_CHAR,58
		JNE	SHORT .D45F		; NOPE

		TEST	SHFT_STAT,CTRL
		JNE	SHORT .D86A_L4
		XOR	SHFT_STAT,CAPS_LK	; CHANGE FLAG
		Call	Update_Kyb_Led

.D86A_L4:
		JMP	.D86A			; DONE

; CHECK FOR NUM LOCK

.D45F:
		CMP	SCAN_CHAR,69
		JNE	SHORT .D4E3		; SKIP : NOT NUM LOCK

		TEST	DH,LAST_E1		; is this in a E1 sequence
		JNE	SHORT HOLD_IT		; this is Pause

		TEST	DH,E101_KEY		; is this a 101
		JNE	SHORT .D4CC		; yes, this is just num lock

		TEST	SHFT_STAT,CTRL
		JE	SHORT .D4CC		; SKIP : NOT CONTROL

HOLD_IT:

.D4B2:
		TEST	KBD_FLG1,HOLD
		JNE	SHORT .D4B2		; LOOP
.D4B1_EXIT:
		JMP	.D87A			; RETURN : END OF INT 9

.D4CC:
		XOR	SHFT_STAT,NUM_LK
		Call	Update_Kyb_Led
		JMP	SHORT .D86A_L3		; DONE

; CHECK FOR SCROLL LOCK

.D4E3:
		CMP	SCAN_CHAR,70
		JNE	SHORT TOG_DEL		; SKIP

		TEST	DH,LAST_E0		; is this ctrl Pause
		JNE	SHORT .D4E3_A		; yes, this is break

		TEST	DH,E101_KEY		; is this a 101
		JNE	SHORT .D555		; then this is only scroll lock

		TEST	SHFT_STAT,CTRL
		JE	SHORT .D555		; SKIP : NOT CONTROL
.D4E3_A:
		MOV	BX,KBD_BUF_LOCN		; clear keyboard buffer
		MOV	PTR_KBD_BUF_HD,BX
		MOV	PTR_KBD_BUF_TL,BX
		MOV	BIOS_BRK,80H

		MOV	SCAN_CHAR,0
		JMP	SWITCH_DONE

.D555:
		XOR	SHFT_STAT,SCRL_LK
		Call	Update_Kyb_Led

.D86A_L3:
		JMP	.D86A			; DONE

; PROCESS <DEL>

TOG_DEL:
		CMP	SCAN_CHAR,83
		JNE	SHORT TOG_PRTS		; NOT <DEL>

ALT_DEL:
		TEST	DH,LAST_E0		; is this alternate del
		JZ	SHORT .D86A_L3		; if not, alt del not defined

		MOV	SCAN_CHAR,163		; return valid scan code
		JMP	SHORT .D7A6_L1

TOG_DEL_1:
		TEST	DH,LAST_E0		; is this alternate del
		JZ	SHORT NOT_ADEL

		MOV	TEMP,0E0H		; yes, use E0 prefix

NOT_ADEL:
		TEST	SHFT_STAT,CTRL
		JZ	SHORT NOT_CTRL_DEL

		MOV	SCAN_CHAR,147		; scan code
		JMP	SHORT .D7A6_L1

NOT_CTRL_DEL:
		TEST	SHFT_STAT,NUM_LK
		JE	SHORT .D5DD		; SKIP : NOT NUM LOCK

		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JNE	SHORT .D7A6_L1

.D5D4:
		TEST	DH,LAST_E0		; is this alternate del
		JNZ	SHORT .D7A6_L1		; then leave prefix = E0
		MOV	TEMP,'.'		; <SHIFT><DEL> = '.'
		JMP	SWITCH_DONE

.D5DD:
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JNE	SHORT .D5D4

.D7A6_L1:
		JMP	SWITCH_DONE		; LONG JUMP

; CHECK FOR PRINT SCREEN - changed for 101 keyboard

TOG_PRTS:
		CMP	SCAN_CHAR,55		; check for print screen
		JNE	SHORT .D7A6_L1		; SWITCH DONE : NOT PRINT SCREEN

NON_101_PRNT:
		TEST	SHFT_STAT,ALT		; is it ALT *
		JE	SHORT PRT_101_A		; not ALT

		MOV	TEMP,0F0H		; set extended prefix
		JMP	SWITCH_DONE

PRT_101_A:
		TEST	DH,E101_KEY		; is this a 101
		JE	SHORT PRT_84

		TEST	SHFT_STAT,CTRL		; is it CTRL *
		JE	SHORT .D628		; not CTRL

		MOV	SCAN_CHAR,096H		; set extended function
		JMP	SWITCH_DONE

PRT_84:
		TEST	SHFT_STAT,CTRL
		JE	SHORT .D60E		; NOT CONTROL

PRT_CTRL:
		MOV	SCAN_CHAR,72H
		JMP	SWITCH_DONE

.D60E:
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JE	SHORT .D628

		JMP	.D870

.D628:
		MOV	TEMP,'*'		; <PRT SC>
		JMP	SWITCH_DONE

; PROCESS KEYPAD

KEYP_S:
		TEST	SHFT_STAT,ALT
		JE	SHORT .D68C		; NOT ALT

		TEST	DH,LAST_E0		; is this one of the alternate keys
		JE	SHORT .D634_1		; if not, numeric enter

		ADD	SCAN_CHAR,050H		; convert to ALT key
		JMP	SWITCH_DONE		; return keystroke

.D634_1:
		MOV	AL,ALT_INPUT		; PROCESS ALT - numeric enter
		MOV	BL,10
		MUL	BL			; ax=ALT_INPUT*10
		mov	bl,es:+2[si]
		AND	BX,255
		SUB	BX,48			; bx= next digit
		ADD	AX,BX			; ax=ALT_INPUT*10+bx
		MOV	ALT_INPUT,AL		; save

.D86A_L2:
		JMP	.D86A			; DONE : LONG JUMP

.D68C:
		TEST	DH,LAST_E0		; is this an alternate keypad
		JZ	SHORT NOT_AKEY		; jmp if not
		MOV	TEMP,0E0H		; set alternate prefix

NOT_AKEY:
		TEST	SHFT_STAT,CTRL
		JE	SHORT .D6AD		; NOT CONTROL

		mov	al,es:+3[si]

.D68C_A:
		MOV	SCAN_CHAR,AL
		JMP	SWITCH_DONE

.D6AD:
		TEST	SHFT_STAT,NUM_LK
		JE	SHORT .D6D7		; NOT NUM LOCK

		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JNE	SHORT .D6E0

.D6CB:
		TEST	DH,LAST_E0		; is this alternate
		JNZ	SHORT .D6EA		; V3.00 . ,finished if it is

		mov	al,es:+2[si]		; otherwise return ASCII
		MOV	TEMP,AL
		JMP	SWITCH_DONE

.D6D7:
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JNE	SHORT .D6CB

.D6E0:
		CMP	SCAN_CHAR,76		; keypad 5
		JNE	SHORT .D6EA

		MOV	TEMP,0F0H		; set prefix code
		JMP	SHORT SWITCH_DONE	; send character

.D6EA:
		CMP	SCAN_CHAR,82		; Insert
		JNE	SHORT SWITCH_DONE

		mov	al,es:+1[si]		; if Insert, set flags
		TEST	KBD_FLG1,AL
		JNE	SHORT .D86A_L2		; DONE

		OR	KBD_FLG1,AL
		XOR	SHFT_STAT,INS_LK
.D7A6_L5:
		JMP	SHORT SWITCH_DONE

; PROCESS F11 and F12 - V2.09

F11_HND:
		ADD	SCAN_CHAR,52		; make ALT code
		TEST	SHFT_STAT,ALT
		JNZ	SHORT .D777		; return alt code

		SUB	SCAN_CHAR,2		; make ctrl code
		TEST	SHFT_STAT,CTRL
		JNZ	SHORT .D777		; return ctrl code

		SUB	SCAN_CHAR,2		; make shift code
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT
		JNZ	SHORT .D777		; return shift code

		SUB	SCAN_CHAR,2		; make unshifted code
		JMP	SHORT .D777		; return unshifted code

; PROCESS FUNCTION

FUNC_S:
		TEST	SHFT_STAT,ALT		; alt function?
		JE	SHORT .D74F

		ADD	SCAN_CHAR,45		; return alt scan code
		JMP	SHORT .D777

.D74F:
		TEST	SHFT_STAT,CTRL		; ctrl function
		JE	SHORT .D76B

		ADD	SCAN_CHAR,35		; return ctrl scan code
		JMP	SHORT .D777

.D76B:
		TEST	SHFT_STAT,LT_SHFT + RT_SHFT	; shifted function
		JE	SHORT .D777

		ADD	SCAN_CHAR,25		; return shift scan code

.D777:

; SWITCH DONE

SWITCH_DONE:
		CMP	SCAN_CHAR,0FFH
		JNE	SHORT .D86A_0
		JMP	.D86A		; DONE
.D86A_0:
		CMP	TEMP,0FFH
		JNE	SHORT .D86A_1
		JMP	.D86A		; DONE
.D86A_1:

; SAVE VALUE

.D7BA:
		MOV	CH,SCAN_CHAR		; SCAN CODE
		MOV	CL,TEMP			; CHARACTER

		CALL	INSERT_CHAR		; try to insert character
		JE	SHORT .D806		; if zero, then buffer overflow

		AND	KB_FLAG_3, NOT (LAST_E1+LAST_E0)	; clear the E1
						; and E0 flags
		JMP	SHORT KBD_INT_RET	; RETURN : END OF INT 9

; BUFFER OVERFLOW : RING BELL

.D806:
		AND	KB_FLAG_3, NOT (LAST_E1+LAST_E0)
		JMP	.D870			; don't send another END_OF_INT

; DONE : RETURN

.D86A:
		AND	KB_FLAG_3, NOT (LAST_E1+LAST_E0)	; clear the E1
						; and E0 flags

.D86A_EXIT:
.D870:
		F000_call	kyb_enable
.D87A:

; RETURN FROM INT 9

KBD_INT_RET:
		MOV	SP,BP

		popa
		pop	es
		pop	ds

		ret

SMI_Int9	Endp

Update_Kyb_Led	Proc	Near

; Update the keyboard LED's
; Changed in V2.09 to only use ax and cx registers

; ENTRY
; DS = 40H

; EXIT
; NONE

; MODIFIES	CX
; CHECK FLAGS

		pushf				;R08
		CLI
		PUSH	AX			; save ax
		MOV	AL,SHFT_STAT
		AND	AL,70H			; get the state of the led keys
		MOV	CL,4
		SHR	AL,CL

		MOV	AH,KB_FLAG_2
		AND	AH,7			; get the actual led settings

		CMP	AL,AH			; check to see if the leds are right
		JE	SHORT .D9FD		; NO CHANGE NEEDED

		AND	KB_FLAG_2,0F8H		; update kb_flag_2 for new leds
		OR	KB_FLAG_2,AL		; with value from current led state

		PUSH	AX			; save led settings from al

		MOV	AL,LED_CMD		; SEND LED COMMAND
		F000_Call	KB_Out
		POP	AX			; get led settings
		JNE	SHORT .D9E9		; jump if there is an error

		F000_Call	KB_Out
		JE	SHORT .D9FD		; jump if there is an error

.D9E9:
		MOV	AL,KB_ENABLE		; SEND KEYBOARD ENABLE
		F000_Call	KB_Out

.D9FD:
		POP	AX			; restore
		popf				;R08
		RET

Update_Kyb_Led	Endp

INSERT_CHAR	PROC	NEAR
; tries to place character into buffer - fails if buffer full

; INPUT
; CH = scan code to be placed on buffer
; CL = ascii code to be placed in buffer
; DS = 40H

; OUTPUT
; Zero flag = 1 - if failed
;	    = 0 - if successful

; MODIFIES	   AX,SI

		MOV	AX,PTR_KBD_BUF_TL	; check for end of buffer
		ADD	AX,2
		CMP	AX,KBD_BUFEND_LOCN
		JNE	SHORT .D7F3		; NOPE

		MOV	AX,KBD_BUF_LOCN		; SET TO START

.D7F3:
		CMP	AX,PTR_KBD_BUF_HD	; MORE ROOM IN BUFFER
		JE	SHORT .D7F3_1		; NO, exit with z=1

; ADD CHARACTER TO BUFFER

		MOV	SI,PTR_KBD_BUF_TL
		MOV	[SI],CX			; PUT CODE & CHAR IN BUFFER
		MOV	PTR_KBD_BUF_TL,AX	; UPDATE TAIL
.D7F3_1:
		RET

INSERT_CHAR	ENDP
endif	;NO_STR_PASSWORD_CHECK
;R16 - end
endif	;NO_STR_SUPPORT
;R12 - end

;[]========================================================================[]
;
; E_Resume_0V:
;
;	Resume system from Zero-Volt-Suspend.
;
;
;[]=========================================================================[]
		Public	E_Resume_0V
E_Resume_0V	PROC	FAR

		cld

	; Clear shutdown byte with NMI off

		mov	al,0Fh NMI_OFF
		mov	ah,0
		call	E_Set_CMOS

		mov	al,0ffh
		out	A8259+1,al
		out	B8259+1,al

	; Turn off speaker

		in	al,61h
		and	al,0fch				; turn off speaker
		or	al,0ch
		out	61h,al

		call	CT_System_Wakeup

;R32		Call	F000_A20_ON
;R32B ifdef	Resume_Turn_on_A20				;R32A
		Call	F000_A20_ON			;R32A
;R32B endif	;Resume_Turn_on_A20				;R32A

		mov	ax,G_RAM
		mov	ds,ax

ifndef	No_ZV_Suspend_Beep				;R21
		call	PM_Beep
endif	;No_ZV_Suspend_Beep				;R21

		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax

	; Restore all memory data

		call	Restore_SMBASE
;R07A ifdef	Fix_NT_Problem				;R07
;R07A 		call	Restore_Mouse		;R07
;R07A endif	;Fix_NT_Problem				;R07
ifdef	Restore_mouse_befor_DRAM 		;R48
		call	Restore_Mouse		;R48
endif	;Restore_mouse_befor_DRAM		;R48
		call	Disable_SMM_Map
ifndef	NO_ZV_REALTIME_MESSAGE
		Call	Resume_Status
endif	;NO_ZV_REALTIME_MESSAGE
		call	Restore_Shadow
		call	Restore_Ext_DRAM
		call	Restore_Base_DRAM
;R19 - start
ifdef	Patch_VGA_Resume_Garbage
		pushad
		pushf
		f000_call	disable_CRT
		popf
		popad
endif	;Patch_VGA_Resume_Garbage
;R19 - end
		call	Restore_VRAM
		call	Enable_SMM_Map

;R24 - start
ifdef	VGA_resume_special_patch
		call	VGA_special_patch
endif	;VGA_resume_special_patch
;R24 - end

	; Restore for temp stack area

		mov	ax,ZV_Temp_Stack
		call	Restore_BASEMem

	; Restore chipset state

		call	Restore_Chipset
		Call	Restore_Ct_device	;R03

	; Restore peripherial devices

;R18 ifdef	AUDIO_KERNEL				;R08
ifndef	No_Save_Sound				;R57
		Call	Restore_Sound		;R08
endif	;No_Save_Sound				;R57
;R18 endif	;AUDIO_KERNEL				;R08
ifdef	NEW_SUPERIO_KERNEL			;R05
ifndef	DONT_SAVE_SUPER_IO	;R35
		Call	Restore_Super_IO	;R05
endif	;DONT_SAVE_SUPER_IO	;R35
endif	;NEW_SUPERIO_KERNEL			;R05
		call	Restore_FPU
;R30 ifndef	Dont_Save_8042_Status		;R25
;R30 		call	Restore_8042
;R30 endif	;Dont_Save_8042_Status		;R25
;R32B 		call	Restore_8042		;R32

ifdef	NEW_SUPERKBC_KERNEL			;R30
		Call	Resume_KBC		;R30
endif	;NEW_SUPERKBC_KERNEL			;R30
;R07A ifndef	Fix_NT_Problem				;R07
ifndef	Restore_mouse_befor_DRAM 		;R48
		call	Restore_Mouse
endif	;Restore_mouse_befor_DRAM 		;R48
;R07A endif	;Fix_NT_Problem				;R07
		call	Restore_FDC
		call	Restore_COMA
		call	Restore_COMB
		call	Resume_VGA
ifdef	PNP_BIOS				;R08
	ifndef	NO_ISA_PNP			;R54
	ifndef	ZV_DONT_SAVE_PNP		;R26
		Call	Restore_PnP_Device	;R08
	endif	;ZV_DONT_SAVE_PNP		;R26
	endif	;NO_ISA_PNP			;R54
endif	;PNP_BIOS				;R08
ifdef	ONBOARD_MODEM_CARD			;R08
		Call	Restore_Modem		;R08
endif	;ONBOARD_MODEM_CARD			;R08

	; Restore all the saved I/O port

		call	Restore_8254
		call	Restore_8237
		call	Restore_8259

		mov	al,BYTE PTR es:[ebx+Port61_Save]
		out	61h,al
;R32B		mov	al,BYTE PTR es:[ebx+Port92_Save]
;R32B		out	92h,al

	; Clear 8042 output buffer

		call	Clear_8042_OBF

		mov	dx,ds:[COMM_PORT_ADDRS]		;Get COM port address
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		Call	Clear_COMM_Int
@@:
		mov	dx,ds:[COMM_PORT_ADDRS+2]	;Get COM port address
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		Call	Clear_COMM_Int
@@:
	; Restore stack pointer

		mov	ss,word ptr es:[ebx+SS_Save]
		mov	esp,dword ptr es:[ebx+ESP_Save]

;R32		pop	bx			;R30
;R32 		call	Restore_8042		;R30
;R32B - start
		pop	ax
		out	92h,al
		pop	bx
 		call	Restore_8042
;R32B - end

		pop	gs
		pop	fs
		pop	es
		pop	ds
		popad

		ret
E_Resume_0V	ENDP

;R43 PM_Beep		Proc	Near
;R43
;R43 ifdef	Beep_Len				;R37
;R43 		mov	bl,Beep_Len		;R37
;R43 else	;Beep_Len				;R37
;R43 		mov	bl,8
;R43 endif	;Beep_Len				;R37
;R43 		mov	cx,350h
;R43 		F000_call	SND_SPKR_TONE
;R43 	@@:
;R43 		NEWIODELAY
;R43 		NEWIODELAY
;R43 		loop	@B
;R43
;R43 		ret
;R43
;R43 PM_Beep		Endp
;R43
;R43 F000_Buffer_8042_Full:
;R43 		F000_Call	Buffer_8042_Full
;R43 		ret
;R43 F000_Out_8042_Full:
;R43 		F000_call	Out_8042_Full
;R43 		ret
;R43
;R43 ;[]=======================================================================[]
;R43 ; Restore_8042:
;R43 ;
;R43 ; 		This routine is used to restore the status of the
;R43 ;		keyboard when system resume .
;R43 ;
;R43 ; Saves :	all but flags
;R43 ;
;R43 ; Input :	ES = G_RAM
;R43 ;		DS = PM Save area
;R43 ;
;R43 ; Output :
;R43 ;
;R43 ;[]=======================================================================[]
;R43 		ASSUME	DS:G_RAM
;R43 Restore_8042	PROC	NEAR
;R43
;R43 Reset_8042:
;R43
;R43 		call	Clear_8042_OBF		; Clear 8042 OBF,IBF
;R43
;R43 IFDEF	RES_KBD_RESET
;R43
;R43 	; Soft reset the 8042.
;R43
;R43 		mov	al,0AAH
;R43 		out	64H,al
;R43
;R43 		call	F000_Buffer_8042_Full
;R43 		jnz	short Reset_8042
;R43
;R43 	; Wait for response in Output Buffer limit up to 25mS.
;R43
;R43 		call	F000_Out_8042_Full
;R43 		jz	short Reset_8042
;R43
;R43 		in	al,60H
;R43 		cmp	al,55H				;Is It Successful ?
;R43 		jnz	short Reset_8042
;R43
;R43 ENDIF	;RES_KBD_RESET
;R43
;R43 ;R30 ifdef	NEW_SUPERKBC_KERNEL			;R03
;R43 ;R30 		Call	Resume_KBC		;R03
;R43 ;R30 endif	;NEW_SUPERKBC_KERNEL			;R03
;R43
;R43 	; Restore 8042 Output Port.
;R43
;R43 		mov	al,0D1H
;R43 		out	64H,al
;R43 		call	F000_Buffer_8042_Full
;R43
;R43 ;R30		mov	al,BYTE PTR es:[ebx+Save_8042_Output]
;R43 ;R32		mov	al,bl			;R30
;R43 ;R32B		mov	al,BYTE PTR es:[ebx+Save_8042_Output]	;R32
;R43 		mov	al,bl			;R32B
;R43 		out	60H,al
;R43 		call	F000_Buffer_8042_Full
;R43 		jnz	short RESET_8042
;R43
;R43 	; Restore 8042 Command Byte.
;R43
;R43 		mov	al,60H
;R43 		out	64H,al
;R43 		call	F000_Buffer_8042_Full
;R43
;R43 ;R30		mov	al,BYTE PTR es:[ebx+Save_8042_Command]
;R43 ;R32		mov	al,bh			;R30
;R43 ;R32B		mov	al,BYTE PTR es:[ebx+Save_8042_Command]	;R32
;R43 		mov	al,bh			;R32B
;R43 		out	60H,al
;R43 		call	F000_Buffer_8042_Full
;R43 		jnz	short RESET_8042
;R43
;R43 	; Enable the keyboard interface.
;R43
;R43 		mov	al,0AEH
;R43 		out	64H,al
;R43 		call	F000_Out_8042_Full
;R43 		in	al,60H
;R43
;R43 IFDEF	RES_KBD_SELF_TEST
;R43
;R43 ;---------------------------------------------------------------------------
;R43 ;
;R43 ;	8042 is now functioning, reset keyboard.
;R43 ;
;R43 ;---------------------------------------------------------------------------
;R43
;R43 		call	F000_Buffer_8042_Full
;R43
;R43 		mov	al,0FFH				;KYBRST = 0FFH.
;R43 		out	60H,al
;R43
;R43 	; Wait for ACK response.
;R43
;R43 		call	F000_Out_8042_Full
;R43 		in	al,60H
;R43
;R43 	; Wait for BAT Completion Code response up to 500mS.
;R43
;R43 		call	F000_Out_8042_Full
;R43 		in	al,60H
;R43
;R43 ENDIF	;RES_KBD_SELF_TEST
;R43
;R43
;R43 IFNDEF	RES_NO_KBD_LED_UPDATE
;R43 ;---------------------------------------------------------------------------
;R43 ;
;R43 ;	Restore keyboard LED's.
;R43 ;	Note: this should be fixed when 8042 support
;R43 ;	is available to read flags.
;R43 ;	Recover flags in BIOS data area.
;R43 ;
;R43 ;---------------------------------------------------------------------------
;R43
;R43 		mov	al,G_RAM:[SHFT_STAT]
;R43
;R43 		shr	al,4
;R43 		and	al,07h
;R43 		push	ax
;R43
;R43 	; Issue Set Mode Command.
;R43
;R43 		call	F000_Buffer_8042_Full
;R43 		mov	al,0EDH				;Set mode indicators = 0EDH.
;R43 		out	60H,al
;R43
;R43 	; Wait for ACK response.
;R43
;R43 		call	F000_Out_8042_Full
;R43 		in	al,60H
;R43
;R43 	; Write option byte.
;R43
;R43 		call	F000_Buffer_8042_Full
;R43 		pop	ax
;R43 		out	60h,al
;R43
;R43 	; Wait for ACK response.
;R43
;R43 		call	F000_Out_8042_Full
;R43 		in	al,60H
;R43
;R43 ENDIF	;RES_NO_KBD_LED_UPDATE
;R43
;R43 Clear_8042_OBF:
;R43
;R43 	; Clear 8042 Output Buffer.
;R43
;R43 		in	al,60h
;R43 		mov	cx,02000h
;R43 		call	Small_Delay
;R43
;R43 		in	al,STAT8042
;R43 		test	al,OBF_8042
;R43 		jnz	short Clear_8042_OBF
;R43
;R43 		ret
;R43
;R43 Restore_8042	ENDP

;[]==================================================================[]
;
; Restore_Mouse:
;
;		This routine is used to restore the PS/2 mouse state.
;
; Saves    :	all but flags
;
; Input    :	ES = G_RAM
;		DS = PM Save area
;
; Output   :
;
; [Note]
;
;	The power to the mouse is turned off during suspend. In order
;	to bring the mouse back to the normal, we need to save the 3 bytes
;	mouse status before suspend and then restore after resume.
;
;[]==================================================================[]
		ASSUME	DS:G_RAM
Restore_Mouse	PROC	NEAR

	       	test	byte ptr G_RAM:[Hardware],00000100b	; mouse exist ?
		jz 	Exit_Restore_Mouse

	; Restore mouse state
		push	ebx
	@@:
		call	Clr_OBF_IBF_AUX
		mov	ax,0c201h				; Reset Mouse
		call	Pointing_Device_Call
		jc	short @B
		pop	ebx

		test	BYTE PTR es:[ebx+Save_Mouse_State],40h	; remote
		jz	short rms_1

		push	ebx
	@@:
		call	Clr_OBF_IBF_AUX
		mov	al,0F0h
		F000_call	out_aux
		jnz	short @B

		pop	ebx
rms_1:
		test	BYTE PTR es:[ebx+Save_Mouse_State],10h	; scale 1:1
		jz	short rms_2

		push	ebx
	@@:
		call	Clr_OBF_IBF_AUX
		mov	ax,0c206h				; set scal 2:1
		mov	bh,2
		call	Pointing_Device_Call
		jc	short @B

		pop	ebx
rms_2:
	; Restore mouse resolution
	@@:
		push	ebx
		call	Clr_OBF_IBF_AUX
		mov	ax,0c203h
		mov	bh,BYTE PTR es:[ebx+Save_Mouse_Resolution]
		call	Pointing_Device_Call
		pop	ebx
		jc	short @B

	; Restore mouse sampling rate
	@@:
		push	ebx
		call	Clr_OBF_IBF_AUX
		mov	ax,0c202h
		mov	bh,BYTE PTR es:[ebx+Save_Mouse_Sample_Rate]
		call	Pointing_Device_Call
		pop	ebx
		jc	short @B

	; Enable/Disable pointing device
		test	BYTE PTR es:[ebx+Save_Mouse_State],20h	; was enabled?
		jz	short rms_0

		push	ebx
		push	cx				;R07A
		mov	cx,100				;R07A
	@@:
		dec	cx				;R07A
		jz	short rms_0_1			;R07A

;R07A		call	Clr_OBF_IBF_AUX
		mov	ax,0c200h
		mov	bh,1
		call	Pointing_Device_Call
		jc	short @B
rms_0_2:						;R07A
		pop	cx				;R07A
		pop	ebx
rms_0:

		call	Clr_OBF_IBF_AUX

Exit_Restore_Mouse:

		ret
;R07A start
rms_0_1:
		mov	al, 0F4h	 		; Enable Aux Device command
		call	kbdSend2Mouse
		jmp	short rms_0_2
;R07A end

Restore_Mouse	ENDP
;R07A start
kbdSend2Mouse  PROC  NEAR
		push	ax
		mov	al, 0D4h			; Send to AuxDevice command
		call	kbdWait4IBE			; Wait for Input Buffer Empty
		out	064h, al
		call	kbdWait4IBE			; Wait for Input Buffer Empty
		in	al, 060h			; Flush Output Buffer
		pop	ax				; Get Data to be sent
		out	060h, al
		call	kbdWait4OBF			; Wait for Output Buffer Full
		ret
kbdSend2Mouse  ENDP

kbdWait4IBE  PROC  NEAR
		push	ax
@@:		in	al, 064h			; Read 8042 status
		test	al, 2		    		; Is Input Buffer Empty?
		jnz	short @B			; Jmp if no
		pop	ax
		ret
kbdWait4IBE  ENDP

kbdWait4OBF  PROC  NEAR
		push	ax
@@:		in	al, 064h			; Read 8042 status
		test	al, 1			    	; Is Output Buffer Full?
		jz	short @B			; Jmp if no
		pop	ax
		in	al, 060h			; Read Output Buffer data
		ret
kbdWait4OBF  ENDP
;R07A end


;[]===============================================================[]
;
; Clr_OBF_IBF_AUX:
;
;	Clear 8042 OBF, IBF and mouse OBF
;
; Saves    :	None
;
; Input    :	None
;
; Output   :	None
;
;[]===============================================================[]
Clr_OBF_IBF_AUX	PROC	NEAR
		xor	cx,cx
	@@:
		in	al,STAT8042
		test	al,OBF_8042+IBF_8042+OBF_AUX
		in	al,DATA8042
		jz	short @F
		loop	short @B
	@@:
		ret

Clr_OBF_IBF_AUX	ENDP

;[]===============================================================[]
;
; Restore_COMA:
;
; 		Routine to restore COM 1 status.
;
; Saves    :	None
;
; Input    :	DS = PM Save area
;		ES = G_RAM
;
; Output   :	None
;
;[]==================================================================[]
;R42		ASSUME	DS:G_RAM
Restore_COMA	PROC	NEAR

		push	ds				;R42
		call	F000_Get_PM_RAM_Seg		;R42
		mov	ds,ax				;R42
;R42		mov	dx,G_RAM:[COMM_PORT_ADDRS]	;Get COM port address
		mov	dx,ds:[COMA_ADDRS]		;R42
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		mov	esi,ebx
		add	esi,offset COMA_Status
		call	Restore_COMPort

	@@:
		pop	ds				;R42

		ret
Restore_COMA	ENDP

;[]===============================================================[]
;
; Restore_COMB:
;
;		Routine to restore COM 2 status.
;
;Saves    :	None
;
;Input    :	ES = G_RAM
;		DS = PM Save area
;
;Output   :	None
;
;[]==================================================================[]
;R42		ASSUME	DS:G_RAM
Restore_COMB	PROC	NEAR

		push	ds				;R42
		call	F000_Get_PM_RAM_Seg		;R42
		mov	ds,ax				;R42
;R42		mov	dx,G_RAM:[COMM_PORT_ADDRS+2]	;Get COM port address
		mov	dx,ds:[COMB_ADDRS]		;R42
		or	dx,dx				;check if address good
		jz	short @F			;skip if not, no action

		mov	esi,ebx
		add	esi,offset COMB_Status
		call	Restore_COMPort

	@@:
		pop	ds				;R42

		ret
Restore_COMB	ENDP

;[]===============================================================[]
;
; Restore_COMPort:
;
;		Restore COMM port status.
;
;Input    :	DX = COMA (3F8H) or COMB (2F8H)
;		DS = PM Save area
;		SI = COMM port status save offset in PM_RAM.
;
;Output   :	None
;
;Preserve :	None
;
;[]===============================================================[]
		ASSUME	DS:G_RAM
Restore_COMPort	PROC	NEAR

;R23 - start
		add	dx,5
		in	al,dx
		newiodelay
		cmp	al, 0ffh		;R57
		je	short NoComRestore	;R57
		inc	dx
		in	al,dx
		newiodelay
		sub	dx,6
;R23 - end
		Call	Clear_COMM_Int

		add	dx,3			; Get LCR address
		mov	al,BYTE PTR es:[esi]
		or	al,80h			; DLAB=1
		out	dx,al

		sub	dx,3			; Divisor latch low address
		mov	al,BYTE PTR es:[esi+1]
		out	dx,al			; Restor divisor latch low byte

		inc	dx			; Divisor latch high address
		mov	al,es:[esi+2]
		out	dx,al			; Restor divisor latch high byte

;R31		inc	dx			; FIFO control
;R31		mov	al,es:[esi+7]
;R31		out	dx,al
;R31 start
		inc	dx
		xor	bl,bl
		mov	al,es:[esi+7]		; Restore FIFO status
		and	al,0c0h
		cmp	al,0c0h
		jne	short NO_FIFO
		mov	bl,1
NO_FIFO:
		mov	al,bl
		out	dx,al
;R31 end

		inc	dx			; Get LCR address
		mov	al,es:[esi]
		and	al,not 80h		; DLAB=0
		out	dx,al

		sub	dx,3			; Get THR address
		mov	al,BYTE PTR es:[esi+6]
		out	dx,al			; Restor THR value

		inc	dx			; Get IER address
		mov	al,BYTE PTR es:[esi+3]
		out	dx,al			; Restor IER value

		add	dx,2			; Get LCR address
		mov	al,BYTE PTR es:[esi]
		out	dx,al			; Restor LCR value

		inc	dx			; Get MCR address
		mov	al,BYTE PTR es:[esi+4]
		out	dx,al			; Restore MCR value

		inc	dx			; Get LSR address
		mov	al,BYTE PTR es:[esi+5]
		out	dx,al			; Restor LSR value
NoComRestore:					;R57
		ret
Restore_COMPort	ENDP

;[]===============================================================[]
;
; Restore_FDC:
;
;	Routine to restore floppy controller status.
;
;	Saves  	:	None
;
;	Input	:	DS = PM Save area
;			ES = G_RAM
;
;	Output  :	None
;
;[]==================================================================[]
		ASSUME	DS:G_RAM
Restore_FDC	PROC	NEAR

	; Reset floppy controller

		mov	al,FDC_SW_RESET

		mov	dx,FDC_DSR
		out	dx,al

		mov	cx,4000h
		call	Small_Delay

	; Release Floppy Disk Controller reset and enable interrupts.

		mov	al,0ch
		mov	dx,FDC_DOR
		out	dx,al

		mov	cx,4000h
		call	Small_Delay

		mov	dx,FDC_MSR
		in	al,dx			;Clear IRQ in status register.

		mov	cx,4000h
		call	Small_Delay

		inc	dx			;Clear IRQ on 82077.
		in	al,dx

		mov	cx,4000h
		call	Small_Delay

		in	al,dx			;Twice clears status bit 6.

	; Restore data rate

		Call	Ct_Restore_FDC

	; send EOI to clear any IRR

 		mov	al,20h
		out	0a0h,al
		out	020h,al

		ret

Restore_FDC	ENDP

;[]========================================================================[]
;
; Restore_FPU:
;
; 	Restore co-processor status.
;
; Entry:	DS = PM Save area
;		ES = G_RAM
;
; Exit:
;
;[]=========================================================================[]
		ASSUME	DS:G_RAM
Restore_FPU	PROC	NEAR

		test	G_RAM:[Hardware],2		; check if 387 exists?
		jz	short @F

	; Reset FPU

		mov	al,0
		out	0f1h,al
		finit

	; Restore co-processor registers

		mov	eax,cr0
		push	eax
		or	al,1				; Set PE bit
		mov	cr0,eax
		jmp	$+2

		db	66h
		fnrstor	es:[ebx+FPU_Status]		; restreo 387 register

		pop	eax
		mov	cr0,eax				; Restore PE bit

	@@:

		ret
Restore_FPU	ENDP

;R43 ;[]===============================================================[]
;R43 ;Procedure:	Large_Delay
;R43 ;Function :	Delay loop
;R43 ;Input    :	AX = delay loop count.
;R43 ;Output   :	None
;R43 ;Preserve :	ALL
;R43 ;[]===============================================================[]
;R43 		Public	Large_Delay
;R43 Large_Delay	PROC	NEAR
;R43
;R43 		push	ax
;R43 		push	cx
;R43
;R43 Large_Delay_Loop:
;R43 		mov	cx,4000h
;R43 	@@:
;R43 		NEWIODELAY
;R43 		loop	short @B
;R43 		dec	ax
;R43 		jnz	short Large_Delay_Loop
;R43
;R43 		pop	cx
;R43 		pop	ax
;R43
;R43 		ret
;R43 Large_Delay	ENDP
;R43
;R43 ;[]===============================================================[]
;R43 ;Procedure:	Small_Delay
;R43 ;Function :	Delay loop
;R43 ;Input    :	CX = delay loop count.
;R43 ;Output   :	None
;R43 ;Preserve :	ALL
;R43 ;[]===============================================================[]
;R43 Small_Delay	Proc	Near
;R43 		push	cx
;R43 	@@:
;R43 		NEWIODELAY
;R43 		loop	short @B
;R43 		pop	cx
;R43 		ret
;R43 Small_Delay	Endp

;[]===============================================================[]
;
; Restore_8259:
;
;		Routine to reinitial & restore 8259 for resume.
;
; Saves    :	None
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
; Note	   :	The following is save 8259 buffer location brief
;
;		Master ICW1:	Save_8259_Area+0
;		Master ICW2:	Save_8259_Area+1
;		Master ICW3:	Save_8259_Area+2
;		Master ICW4:	Save_8259_Area+3
;		Master OCW1:	Save_8259_Area+4
;		Master OCW2:	Save_8259_Area+5
;		Master OCW3:	Save_8259_Area+6
;		Reserve    :	Save_8259_Area+7
;		Slave ICW1 :	Save_8259_Area+8
;		Slave ICW2 :	Save_8259_Area+9
;		Slave ICW3 :	Save_8259_Area+10
;		Slave ICW4 :	Save_8259_Area+11
;		Slave OCW1 :	Save_8259_Area+12
;		Slave OCW2 :	Save_8259_Area+13
;		Slave OCW3 :	Save_8259_Area+14
;		Reserve    :	Save_8259_Area+15
;
;[]==================================================================[]
		ASSUME	DS:G_RAM
Restore_8259	PROC	NEAR

	;
	; Restore slave pic
	;
		mov	al,es:[ebx+Save_8259_Area+8]
		out	B8259,al		; icw1
		mov	al,es:[ebx+Save_8259_Area+9]
		out	B8259+1,al		; icw2
		mov	al,es:[ebx+Save_8259_Area+0ah]
		out	B8259+1,al		; icw3
		mov	al,es:[ebx+Save_8259_Area+0bh]
		out	B8259+1,al		; icw4

		mov	al,es:[ebx+Save_8259_Area+0ch]
		out	B8259+1,al		; ocw1

		mov	al,es:[ebx+Save_8259_Area+0dh]
		and	al,not 18h
		out	B8259,al		; ocw2

		mov	al,es:[ebx+Save_8259_Area+0eh]
		and	al,not 10h
		or	al,08h
		out	B8259,al		; pic2 ocw3
	;
	; Restore master pic
	;
		mov	al,es:[ebx+Save_8259_Area]
		out	A8259,al		; icw1
		mov	al,es:[ebx+Save_8259_Area+1]
		out	A8259+1,al		; icw2
		mov	al,es:[ebx+Save_8259_Area+2]
		out	A8259+1,al		; icw3
		mov	al,es:[ebx+Save_8259_Area+3]
		out	A8259+1,al		; icw4

		mov	al,es:[ebx+Save_8259_Area+4]
		out	A8259+1,al		; ocw1

		mov	al,es:[ebx+Save_8259_Area+5]
		and	al,not 18h
		out	A8259,al		; ocw2

		mov	al,es:[ebx+Save_8259_Area+6]
		and	al,not 10h
		or	al,08h
 		out	A8259,al		; pic1 ocw3

		mov	cx,20h
                mov     al,END_OF_INT
	@@:
                out     A8259,al
                out     B8259,al
		loop	short @B

;R28 - start

		mov	ah,es:[ebx+Save_8259_Area+0Fh]	;CMOS addr=0Bh
		mov	al,0Bh NMI_OFF
		call	F000_SET_CMOS

		mov	ah,es:[ebx+Save_8259_Area+07h]	;CMOS addr=0Ah
		mov	al,0Ah NMI_OFF
		call	F000_SET_CMOS
;R28 - end

		ret
Restore_8259	ENDP

;R28 - start
ifndef	DONT_RELEASE_E000_FOR_PCI
F000_SET_CMOS	Proc	near
		F000_Call	SET_CMOS
		ret
F000_SET_CMOS	Endp
endif	;DONT_RELEASE_E000_FOR_PCI
;R28 - end

;[]===============================================================[]
;
; Restore_8254:
;
;		Routine to restore 8254 for resume.
;
; Saves    :	None
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
;[]==================================================================[]
Restore_8254	PROC	NEAR

		push	ds
		push	ebx

		push	es
		pop	ds

		mov	esi,ebx
		add	esi,offset Timer_8254_Save
		xor	bl,bl				; Select channel 0
		mov	cx,3				; 3 channels
		mov	dx,DATA8254

Rest_8254_Loop:

		lods	byte ptr ds:[esi]
		and	al,3fh
		or	al,bl				; That is for counter ?
		out	CTRL8254, al
		mov	ah,al
		lods	byte ptr ds:[esi]
		test	ah,10h
		jz	short @F
		out	dx,al
	@@:
		lods	byte ptr ds:[esi]
		test	ah,20h
		jz	short @F
		out	dx,al
	@@:
		add	bl,40h
		inc	dx				; Next channel
		loop	short Rest_8254_Loop

		pop	ebx
		pop	ds

		ret
Restore_8254	ENDP

;[]===============================================================[]
;
; Restore_8237:
;
;		Routine to restore DMA controller for resume.
;
; Saves    :	None
;
; Input    :	ES = PM Save area
;
; Output   :	None
;
;[]==================================================================[]
Restore_8237	PROC	NEAR
		push	ds

		push	es
		pop	ds
		mov	esi,ebx
		add	esi,offset DMA_Page_Save

		mov	al,00		; Any junk data will do.
		out	0ch,al		; clear flip/flop pointer to slave.
		out	0d8h,al		; clear flip/flop pointer to master.

		mov	dx,0		; restore dma1 address and count registers
		mov	cx,8
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		lods	byte ptr ds:[esi]
		out	dx,al
		inc	dx
		loop	short @B

		mov	dx,0c0h		; restore dma2 address and count registers
		mov	cx,8
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		lods	byte ptr ds:[esi]
		out	dx,al
		add	dx,2
		loop	short @B

		mov	dx,081h		; start from port 81h
		mov	cx,16
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		inc	dx
		loop	short @B

		mov	dx,094h
		mov	cx,3
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		inc	dx
		loop	short @B

		mov	dx,098h
		lods	byte ptr ds:[esi]
		out	dx,al

		mov	dx,09Ch
		mov	cx,4
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		inc	dx
		loop	short @B

		mov	dx,0ah		; restore dma1 all mask register
		lods	byte ptr ds:[esi]
 		and	al,0Fh		; kill the other bits.
		out	dx,al		; Write all bits command.

		mov	dx,0d4h		; restore dma2 all mask register
		lods	byte ptr ds:[esi]
 		and	al,0Fh		; kill the other bits.
		out	dx,al		; Write all bits command.

		mov	dx,0420h	; restore s/g descriptor table pointers
		mov	cx,4
	@@:
		lods	dword ptr ds:[esi]
		out	dx,eax
		add	dx,4
		loop	short @B

		mov	dx,0434h	; restore s/g descriptor table pointers
		mov	cx,3
	@@:
		lods	dword ptr ds:[esi]
		out	dx,eax
		add	dx,4
		loop	short @B

		mov	dx,0481h	; restore high page registers
		mov	cx,3
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		inc	dx
		loop	short @B

		mov	dx,0487h
		lods	byte ptr ds:[esi]
		out	dx,al

		mov	dx,0489h
		mov	cx,3
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al
		inc	dx
		loop	short @B

		pop	ds
		ret
Restore_8237	ENDP

;R43 ;[]===============================================================[]
;R43 ;
;R43 ; Restore_Chipset:
;R43 ;
;R43 ;		Routine to restoree chipset register for resume.
;R43 ;
;R43 ; Saves    :	ES,DS
;R43 ;
;R43 ; Input    :	ES = PM Save area
;R43 ;
;R43 ; Output   :	None
;R43 ;
;R43 ;[]==================================================================[]
;R43 		Public	Restore_Chipset			;R13
;R43 Restore_Chipset	proc	near
;R43
;R43 		push	ds
;R43 		push	ebx
;R43
;R43 		push	es
;R43 		pop	ds
;R43 		mov	esi,ebx
;R43 		add	esi,offset Chipset_State_Save
;R43 		mov	di,offset Suspend_Chipset_Table
;R43
;R43 Restore_Chipset_Loop:
;R43
;R43 		mov	bx,word ptr cs:[di+2]
;R43 		mov	cx,word ptr cs:[di]
;R43 		cmp	cx,0ffffh
;R43 		je	short End_Restore_Chipset
;R43 	@@:
;R43 		lods	byte ptr ds:[esi]
;R43 		F000_call	Set_CT
;R43 		inc	cx
;R43 		dec	bx
;R43 		jne	short @B
;R43 		add	di,4
;R43 		jmp	short Restore_Chipset_Loop
;R43
;R43 End_Restore_Chipset:
;R43
;R43 		pop	ebx
;R43 		pop	ds
;R43 		ret
;R43 Restore_Chipset	endp

ifndef	NEW_SUPERVGA_KERNEL				;R01
;[]===============================================================[]
;
; Resume_VGA:
;
;	Subroutine for restore VGA status .
;
; Entry:
;
;	ES = Segment of VGA state save buffer.
;
; Exit:
;
; Note:
;	The following is standard VGA status save offset in buffer.
;
;		00H	    : sequencr index
;		01H,02H	    : CRTC address
;		03H	    : CRTC index
;		04H	    : graphic index
;		05H	    : attributes index
;		06H	    : Feature control
;		07H - 0AH   : sequencr reg 1 - 4
;		0BH	    : VGA Misc. Register
;		0CH - 24H   : CRTC 0 - 18h
;		25H - 38H   : attribute  0 - 13h
;		39H - 41H   : VGA graphic control register 0 - 8
;		42H	    : VGA DAC register R/W status
;		43H	    : VGA pel address
;		44H	    : VGA pel mask
;		45H	    : VGA (Attribute index 14h) color select register
;		46H - 0146H : VGA DAC register
;
;[]==================================================================[]
Resume_VGA	PROC	NEAR

		push	ds

		push	es
		pop	ds

		mov	esi,ebx
		add	esi,offset VGA_State_Save
;
; Restore VGA extended register
;
		call	CT_Restore_VGA
;
; Restore standard VGA register
;
		mov	dx,3C4h
		mov	esi,ebx
		add	esi,offset TSR_Save
		mov	cx,4
		mov	ah,1
		call	Rep_Restore_VGA		; Restore Sequencer Register

		mov	dx,3C2h
		mov	al,es:[ebx+VGA_Misc_Save]
		out	dx,al			; 3C2h, VGA misc out reg

		mov	dx,es:[ebx+CRTC_Address_Save]
		mov	ax,1100h		; Disable CRTC 0-7 lock
		call	Set_VGA_Reg

		mov	esi,ebx
		add	esi,offset CRTC_Save
		mov	cx,19h
		xor	ah,ah
		call	Rep_Restore_VGA		; Restore CRTC registers 0 - 18h

		mov	dx,3CEh
		mov	esi,ebx
		add	esi,offset GDC_Save
		mov	cx,9
		xor	ah,ah
		call	Rep_Restore_VGA		; Restore GDC 0 - 8

		mov	esi,ebx
		add	esi,offset ATC_Save
		xor	ah,ah
		mov	cx,14h
		call	Reset_VGA_FF
		mov	dx,3C0h
	@@:
		mov	al,ah
		out	dx,al
		lods	byte ptr ds:[esi]
		out	dx,al			; Restore ATC 0 - 13h
		inc	ah
		loop	short @B

		mov	dx,es:[ebx+CRTC_Address_Save]
		add	dl,6
		mov	al,es:[ebx+Feature_Control_Save]
		out	dx,al			; Restore Feature control
		push	dx

		mov	dx,3C4h
		mov	al,es:[ebx+TSR_Index_Save]
		out	dx,al			; Restore TSR index

		mov	dx,es:[ebx+CRTC_Address_Save]
		mov	al,es:[ebx+CRTC_Index_Save]
		out	dx,al			; Restore CRTC index

		mov	dx,3CEh
		mov	al,es:[ebx+GDC_Index_Save]
		out	dx,al			; Restore GDC index

		pop	dx
		in	al,dx
		mov	dx,3C0h
		mov	al,es:[ebx+ATC_Index_Save]
		out	dx,al			; Restore ATC index

		mov	ch,14h
		mov	cl,es:[ebx+Color_Select_Save]
		call	Set_VGA_Att		; Restore color select

		mov	al,es:[ebx+PEL_Mask_Save]
		mov	dx,03C6h
		out	dx,al			; Restore PEL Mask

		call	Wait_VRetrace
		mov	esi,ebx
		add	esi,offset DAC_Save
		mov	dx,3C8h
		xor	al,al
		out	dx,al			; port 3C8h, VGA pel address
		inc	dx
		mov	cx,100h
	@@:
		lods	byte ptr ds:[esi]
		out	dx,al			; Restore DAC
		lods	byte ptr ds:[esi]
		out	dx,al			; Restore DAC
		lods	byte ptr ds:[esi]
		out	dx,al			; Restore DAC
		loop	short @B

		mov	dx,3C7h
		mov	al,es:[ebx+DAC_State_Save]
		test	al,1
		mov	al,es:[ebx+PEL_Address_Save]
		jnz	short @F
		inc	dx
	@@:
		out	dx,al			; Restore PEL R/W State

		pop	ds
		ret

Resume_VGA	ENDP

;[]========================================================================[]
;Procedure:	Restore_VRAM
;
;Function :	Restore Video RAM for resume from Zero-Volt-Suspend.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;Note	  :	1. Called by Resume_0V
;		2. The stack is in segment 0000h
;		3. Save location = start location + 1088KB
;[]========================================================================[]
Restore_VRAM	PROC	NEAR

		push	ebx
		push	ds

	; Disable CRT display

		call	Reset_VGA_FF
		mov     dx,03c0h
		xor	al,al
		out     dx,al

		Call	Ct_Restore_VRAM
		jnc	short Restore_VRAM_ok

;
; Restore Video RAM
;
		mov     dx,03c4h
		mov     ax,0406h		; Enable chain four mode
		call	Set_VGA_Reg

		mov     dx,03ceh
		mov     ax,0500h
		call	Set_VGA_Reg

		mov     ax,0601h        	; memory mapping select to a000h,128k.
		call	Set_VGA_Reg

		push	es

		mov     dx,03c4h
		mov     ax,0201h		; Start plane 0
		call	Set_VGA_Reg

		call	Get_ZV_HDD_Loc		; Start sector
		add	ebx,ZV_HDD_VRAM_Sector
	@@:
		xor	edi,edi
		mov	ax,0A000h
		mov	es,ax
		mov	ah,20h			; Read command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer
		mov	ax,0B000h
		mov	es,ax
		xor	edi,edi
		add	ebx,(64*1024)/512	; Next start sector ..
		mov	ah,20h			; Read command
		mov	al,(64*1024)/512	; Sector Count
		call	HDD_Transfer

		mov     dx,03c4h
		mov	ah,02h
		call	Get_VGA_Reg
		and	al,0fh
		cmp	al,8			; Is plane 3 ?
		je	short @F
		shl	al,1			; Next plane ..
		call	Set_VGA_Reg
		add	ebx,(64*1024)/512	; Next start sector ..
		jmp	short @B
	@@:

		pop	es
Restore_VRAM_ok:
		pop	ds
		pop	ebx

		ret
Restore_VRAM	ENDP

;[]==================================================================[]
;
; Subroutine for read VGA register
;
; Entry:
;	AH = Index
;	DX = VGA port
;
; Exit:
;	AL = Read value
;
;[]==================================================================[]
		public	Get_VGA_Reg
Get_VGA_Reg	proc	near
		xchg	ah,al
		out	dx,al
		inc	dl
		xchg	ah,al
		in	al,dx
		dec	dl
		ret
Get_VGA_Reg	endp

;[]==================================================================[]
;
; Subroutine for write VGA register
;
; Entry:
;	AH = index
;	DX = VGA port
;
; Exit:
;
;[]==================================================================[]
		Public	Set_VGA_Reg
Set_VGA_Reg	proc	near
		xchg	ah,al
		out	dx,al
		inc	dl
		xchg	ah,al
		out	dx,al
		dec	dl
		ret
Set_VGA_Reg	endp

;[]==================================================================[]
;[]==================================================================[]
		Public	Rep_Save_VGA
Rep_Save_VGA	proc	near

	@@:
		call	Get_VGA_Reg
		stos	byte ptr es:[edi]
		inc	ah
		loop	short @B

		ret
Rep_Save_VGA	endp

;[]==================================================================[]
;[]==================================================================[]
		Public	Rep_Restore_VGA
Rep_Restore_VGA	proc	near

	@@:
		lods	byte ptr ds:[esi]
		call	Set_VGA_Reg
		inc	ah
		loop	short @B

		ret
Rep_Restore_VGA	endp

;[]==================================================================[]
;[]==================================================================[]
		Public	Get_VGA_Att
Get_VGA_Att	proc	near

		push	dx
		mov	dx,3C0h
		in	al,dx
		push	ax			; Save PAS status

		call	Reset_VGA_FF

		mov	al,ah
		out	dx,al
		inc	dl
		in	al,dx
		dec	dl
		mov	bl,al

		call	Reset_VGA_FF

		pop	ax			; Restore PAS status
		out	dx,al
		mov	al,bl
		pop	dx

		ret
Get_VGA_Att	endp

;[]==================================================================[]
;[]==================================================================[]
		Public	Set_VGA_Att
Set_VGA_Att	proc	near

		mov	dx,3C0h
		in	al,dx
		push	ax			; Save PAS status

		call	Reset_VGA_FF
		mov	ax,cx
		mov	dx,3C0h
		xchg	ah,al
		out	dx,al
		xchg	ah,al
		out	dx,al
		call	Reset_VGA_FF

		pop	ax
		out	dx,al			; Restore PAS status

		ret
Set_VGA_Att	endp

;[]==================================================================[]
;
; Routine for reset VGA attribute register access Flip/Flop
;
;[]==================================================================[]
		Public	Reset_VGA_FF
Reset_VGA_FF	proc	near
		push	ax
		push	dx
		mov	dx,3BAh
		in	al,dx
		mov	dl,0DAh
		in	al,dx
		pop	dx
		pop	ax
		ret
Reset_VGA_FF	endp

;[]==================================================================[]
;
; Routine for get CRTC register address 3D4H or 3B4H
;
;[]==================================================================[]
		Public	Get_CRTC_Addr
Get_CRTC_Addr	proc	near
		push	ax
		mov	dx,3cch
		in	al,dx
		mov	dx,3d4h
		test	al,1
		jnz	short @F
		mov	dx,3b4h
	@@:
		pop	ax
		ret
Get_CRTC_Addr	endp

;[]==================================================================[]
;
; Routine to wait for CRT vertical retrace
;
;[]==================================================================[]
		Public	Wait_VRetrace
Wait_VRetrace	proc    near

		push	cx
		push    dx
		call	Get_CRTC_Addr
		add     dx,06h
		xor	cx,cx
	@@:
		in      al,dx
		test    al,08h
		jz	short @F
		loop	short @B
	@@:
		xor	cx,cx
	@@:
		in      al,dx
		test    al,08h
		jnz	short @F
		loop	short @B
	@@:
		pop     dx
		pop	cx

		ret

Wait_VRetrace	endp
endif	;NEW_SUPERVGA_KERNEL				;R01

;[]========================================================================[]
;Procedure:	Restore_SMBASE
;
;Function :	Restore SMBASE for the CPU was reseted by chipset
;		during system reume.
;
;Input	  :	None
;
;Output   :	None
;
;Preserve :	ES,DS
;
;Note	  :	Called by Suspend_0V
;[]========================================================================[]
Restore_SMBASE	Proc	Near

		pop	ebp

		mov	ax,ZV_Temp_Stack
		mov	ss,ax
		mov	esp,offset ZV_STACK_TOP

		push	es
		push	ebx

		mov	edi,ebx
		add	edi,offset SMI_Entry

		call	Get_ZV_HDD_Loc
		add	ebx,ZV_HDD_SMBASE_Sector
		mov	ah,20h			; Read command
		mov	al,(32*1024)/512	; Sector Count
		call	HDD_Transfer

		pop	ebx
		pop	es
		mov	esp,dword ptr es:[ebx+ESP_Save]
		mov	ax,word ptr es:[ebx+SS_Save]
		mov	ss,ax

		push	ebp

		ret
Restore_SMBASE	Endp

;R43 ;[]========================================================================[]
;R43 ;Procedure:	Restore_Shadow
;R43 ;
;R43 ;Function :	Restore Shadow RAM C0000h-FFFFFh
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	DS,ES
;R43 ;
;R43 ;Note	  :	Called by Resume_0V
;R43 ;[]========================================================================[]
;R43 Restore_Shadow	PROC	NEAR
;R43 		push	ds
;R43 		push	es
;R43 		push	ebx
;R43
;R43 		mov	al,1
;R43 		call	CT_AllShadow_RW
;R43
;R43 		mov	ax,0c000h
;R43 	@@:
;R43 		call	CT_Skip_ZV_Shadow
;R43 		je	short Skip_ZV_Shadow_Restore
;R43
;R43 		call	Restore_BASEMem
;R43
;R43 Skip_ZV_Shadow_Restore:
;R43
;R43 		add	ax,1000h
;R43 		cmp	ax,0000h
;R43 		jne	short @B
;R43
;R43 		pop	ebx
;R43 		pop	es
;R43 		pop	ds
;R43 		ret
;R43 Restore_Shadow	ENDP
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Restore_BASEMem
;R43 ;
;R43 ;Function :	Restore Base DRAM (below 1M) from HDD.
;R43 ;
;R43 ;Input	  :	AX = Base memory segment for restore.
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	DS,ES
;R43 ;
;R43 ;Note	  :	1. System is in SMM.
;R43 ;		2. Save location = start location + 32KB + AX shl 4
;R43 ;
;R43 ;[]========================================================================[]
;R43 Restore_BASEMem	PROC	NEAR
;R43
;R43 	; Restore Memory 00000h-0ffffh
;R43
;R43 		push	ds
;R43 		push	es
;R43 		push	ax
;R43 		push	ebx
;R43
;R43 		mov	es,ax
;R43
;R43 		call	Get_ZV_HDD_Loc
;R43 		add	ebx,ZV_HDD_BASEMEM_Sector
;R43 		shr	ax,5
;R43 		and	eax,0780h
;R43 		add	ebx,eax			; Start sector
;R43
;R43 		xor	edi,edi
;R43 		mov	ah,20h			; Read command
;R43 		mov	al,(64*1024)/512	; Sector Count
;R43 		call	HDD_Transfer
;R43 		pop	ebx
;R43 		pop	ax
;R43 		pop	es
;R43 		pop	ds
;R43
;R43 		ret
;R43 Restore_BASEMem	ENDP
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Restore_Base_DRAM
;R43 ;
;R43 ;Function :	Restore Base DRAM (640K) from HDD.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	All
;R43 ;
;R43 ;Note	  :	1. System is in SMM.
;R43 ;		2. called by Resume_0V
;R43 ;
;R43 ;[]========================================================================[]
;R43 Restore_Base_DRAM	proc	near
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		push	ebx
;R43 		mov	si,offset Base_Mem_POS
;R43 		Call	Show_Transfer_MSG
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43
;R43 		mov	ax,0000h
;R43 	@@:
;R43 		cmp	ax,ZV_Temp_Stack	; If this segment is current
;R43 		je	short skip_Restore_Base	; Stack then skip restore it.
;R43 		call	Restore_BASEMem
;R43 skip_Restore_Base:
;R43 		add	ax,1000h
;R43 ifndef	NO_ZV_REALTIME_MESSAGE			;R15
;R43 		Call	Show_Base_Percent	;R15
;R43 endif	;NO_ZV_REALTIME_MESSAGE			;R15
;R43 		cmp	ax,0a000h
;R43 		jb	short @B
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		mov	si,offset Base_Mem_POS
;R43 		Call	Transfer_OK_MSG
;R43 		pop	ebx
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43 		ret
;R43 Restore_Base_DRAM	endp
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Restore_Ext_DRAM
;R43 ;
;R43 ;Function :	Restore Extended memory from HDD.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Preserve :	All
;R43 ;
;R43 ;Note	  :	1. System is in SMM.
;R43 ;		2. called by Resume_0V
;R43 ;		3. Extended memory save location = start location + 1536KB
;R43 ;
;R43 ;[]========================================================================[]
;R43 Restore_Ext_DRAM	proc	near
;R43
;R43 		push	ds
;R43 		push	es
;R43 		push	ebx
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		mov	si,offset Ext_Mem_POS
;R43 		Call	Show_Transfer_MSG
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43
;R43 		call	Get_ZV_HDD_Loc
;R43 		add	ebx,ZV_HDD_EXTMEM_Sector	; Start sector
;R43
;R43 	; Get extended memory size
;R43
;R43 		call	Get_EXT_Memory
;R43 ;R14		shr	cx,6				; 64K block
;R43
;R43 		mov	edi,1024*1024
;R43 		xor	ax,ax
;R43 		mov	es,ax
;R43 	@@:
;R43 		mov	ah,20h				; Read command
;R43 		mov	al,(64*1024)/512		; Sector Count
;R43 		call	HDD_Transfer
;R43 		add	ebx,(64*1024)/512
;R43 		add	edi,64*1024
;R43 ifndef	NO_ZV_REALTIME_MESSAGE			;R15
;R43 		Call	Show_ext_Percent	;R15
;R43 endif	;NO_ZV_REALTIME_MESSAGE			;R15
;R43 		loop	short @B
;R43
;R43 ifndef	NO_ZV_REALTIME_MESSAGE
;R43 		mov	si,offset Ext_Mem_POS
;R43 		Call	Transfer_OK_MSG
;R43 endif	;NO_ZV_REALTIME_MESSAGE
;R43 		pop	ebx
;R43 		pop	es
;R43 		pop	ds
;R43
;R43 		ret
;R43 Restore_Ext_DRAM	endp
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Get_EXT_Memory
;R43 ;
;R43 ;Function :	To return extended memory size.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	CX = Extended memory size (K Byte).
;R43 ;
;R43 ;[]========================================================================[]
;R43
;R43 		Public	Get_EXT_Memory
;R43 Get_EXT_Memory	proc	near
;R43 ;R14		mov	al,EXT_MEMORY NMI_OFF
;R43 ;R14		call	E_Get_CMOS
;R43 ;R14		mov	cl,al
;R43 ;R14		mov	al,EXT_MEMORY+1 NMI_OFF
;R43 ;R14		call	E_Get_CMOS
;R43 ;R14		mov	ch,al
;R43 ;R14 - start
;R43 		push	es
;R43 		mov	si,seg ExtMem128Mb
;R43 		mov	es,si
;R43 		mov	si,offset ExtMem128Mb
;R43 		mov	ecx,dword ptr es:[si+08h]
;R43 ;R38 - start
;R43 ifdef	ACPI_Support
;R43 		mov	si,offset ACPITableAddress
;R43 		cmp	dword ptr es:[si],-1
;R43 		je	short ACPI_off
;R43 		add	ecx,dword ptr es:[si+08h]
;R43 		mov	si,offset ACPINVSAddress
;R43 		add	ecx,dword ptr es:[si+08h]
;R43 ACPI_off:
;R43 endif	;ACPI_Support
;R43 ;R38 - end
;R43 		shr	ecx,16				;64K block
;R43 		mov	word ptr PAGE_START[bp],cx	;R15
;R43 		pop	es
;R43 ;R14 - end
;R43 		ret
;R43 Get_EXT_Memory	endp
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Disable_SMM_Map
;R43 ;
;R43 ;Function :	Disable SMBASE map function for access the memory which
;R43 ;		locate same with SMBASE.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Note     :	The memory is unvisible within SMM mode when the location is
;R43 ;		same with SMBASE.
;R43 ;	     **	We must assign new stack (0000-0FFFF) in here because
;R43 ;		the SMBASE is disable.
;R43 ;
;R43 ;[]========================================================================[]
;R43 Disable_SMM_Map	proc	near
;R43
;R43 		pop	ebp			; save return address
;R43
;R43 		mov	dx,ss
;R43 		mov	ecx,esp
;R43
;R43 		mov	ax,ZV_Temp_Stack
;R43 		mov	ss,ax			; New stack pointer
;R43 		mov	esp,offset ZV_STACK_TOP	; = 0000H:FFF0H
;R43
;R43 		push	dx
;R43 		push	ecx
;R43
;R43 	; Disable SMBASE
;R43
;R43 		call	CT_SMBASE_Off
;R43
;R43 		push	ebp			; Restore return address
;R43
;R43 		ret
;R43 Disable_SMM_Map	endp
;R43
;R43 ;[]========================================================================[]
;R43 ;Procedure:	Enable_SMM_Map
;R43 ;
;R43 ;Function :	Re-enable SMBASE map function for access the memory which
;R43 ;		locate same with SMBASE.
;R43 ;
;R43 ;Input	  :	None
;R43 ;
;R43 ;Output   :	None
;R43 ;
;R43 ;Note	  :  **	We must assign old stack in here.
;R43 ;
;R43 ;[]========================================================================[]
;R43 Enable_SMM_Map	proc	near
;R43
;R43 		pop	ebp			; save return address
;R43
;R43 	; Enable SMBASE
;R43
;R43 		call	CT_SMBASE_On
;R43
;R43 	; Assign old stack pointer
;R43
;R43 		pop	ecx
;R43 		pop	dx
;R43 		mov	ss,dx
;R43 		mov	esp,ecx
;R43
;R43 		push	ebp			; Restore return address
;R43
;R43 		ret
;R43
;R43 Enable_SMM_Map	endp
;R43
;R43 ;R27 start
;R43 Get_HDD_Port_Base:
;R43 		push	ax
;R43 		push	ds
;R43 		call	F000_Get_PM_RAM_Seg
;R43 		mov	ds,ax
;R43 		mov	dx,1f0h
;R43 		test	byte ptr ds:[ZV_HDD_Scheme],2	;check on primary?
;R43 		jz	short @F
;R43 		sub	dl,80h
;R43 @@:
;R43 		pop	ds
;R43 		pop	ax
;R43 		ret
;R43 ;R27 end
;R43
;R43 ;[]===============================================================[]
;R43 ;
;R43 ; HDD_Transfer :
;R43 ;
;R43 ;	The routine does data transfer to/from HDD.
;R43 ;
;R43 ; Entry:
;R43 ;	AH = 30h  write
;R43 ;          = 20h  read
;R43 ;	AL = sector count.
;R43 ;       DS:SI = Address for writing.
;R43 ;       ES:DI = Address for reading.
;R43 ;       CX = cylinder number.
;R43 ;       DH = Head number.
;R43 ;       DL = starting sector number.
;R43 ;
;R43 ; Exit:
;R43 ;	JNC = successful. JC = failed
;R43 ;       ESI Or EDI updated pointer after the Write / Read operation.
;R43 ;
;R43 ; Note:
;R43 ;
;R43 ;[]==================================================================[]
;R43 ;R27 Hdd_Port0		EQU	01f0h	; Data port.
;R43 Hdd_Register		EQU	03f6h	; Hdd register.
;R43 Hdd_Rdy			EQU	40h	; Drive ready bit.
;R43 Hdd_Busy		EQU	80h	; Drive busy bit.
;R43 Hdd_Drq			EQU	08h	; Drive DRQ bit.
;R43 Hdd_Seek_Cmd		EQU	70h	; Drive seek command.
;R43 Write_command		EQU	30h	; Hdd write multi-sector command.
;R43 Read_command		EQU	20h	; Hdd read multi-sector command.
;R43
;R43 		Public	HDD_Transfer
;R43 HDD_Transfer	proc	near
;R43
;R43 		pushad
;R43
;R43 		call	Get_HDD_Parm		; Get the Location parameter
;R43
;R43 		push	eax
;R43 		push	ecx
;R43 		push	dx
;R43 		push	bp
;R43
;R43 		mov	ebp,esp			; Get stack top.
;R43 Resend_HDD_Cmd:					;R17A
;R43 		call	Test_CTLR_Busy
;R43
;R43 		mov	al,[bp+3]
;R43 ;R27		mov	dx,Hdd_Port0+6		; DX = 1F6h
;R43 		call	Get_HDD_Port_Base	;R27
;R43 		add	dl,6			;R27
;R43 		out	dx,al
;R43 		call	Test_CTLR_Busy		;R17
;R43 		call	Test_HDD_Rdy
;R43
;R43 ; Feed the task file of HDD with relevent values.
;R43
;R43 		mov	al,[bp+8]
;R43 ;R27		mov	dx,Hdd_Port0+2		; Sector count reg.(1F2)
;R43 		call	Get_HDD_Port_Base	;R27
;R43 		add	dl,2			;R27
;R43 		out	dx,al
;R43
;R43 		mov	al,[bp+2]
;R43 		inc	dx			; Starting sector number.(1F3)
;R43 		out	dx,al
;R43
;R43 		mov	al,[bp+4]
;R43 		inc	dx			; Cylinder low.(1F4)
;R43 		out	dx,al
;R43
;R43 		mov	al,[bp+5]
;R43 		inc	dx			; Cylinder high.(1F5)
;R43 		out	dx,al
;R43
;R43 		inc	dx			; SDH reg.(1F6)
;R43 		mov	al,[bp+3]		;R17
;R43 		out	dx,al			;R17
;R43 		push	dx			;R17
;R43 		call	Test_CTLR_Busy		;R17
;R43 		call	Test_HDD_Rdy		;R17
;R43 		pop	dx			;R17
;R43
;R43 ;Now we flash the command.
;R43
;R43 		mov	al,[bp+9]
;R43 		inc	dx			; Get command reg.(1F7)
;R43 		out	dx,al			; Flash the command.
;R43
;R43 ;R29 start
;R43 		newiodelay
;R43 		call	Test_CTLR_Busy
;R43 		in	al,dx
;R43 		test	al,1
;R43 		jnz	short error_xfer
;R43 ;R29 end
;R43 		mov	ah,3			;R17A
;R43 		xor	cx,cx			;R17A
;R43 	@@:
;R43 		NEWIODELAY			;R20
;R43 		NEWIODELAY			;R20
;R43 		in	al,dx
;R43 		test	al,HDD_DRQ
;R43 ;R17A		jz	short @B
;R43 ;R17A start
;R43 		jnz	short HDD_Cmd_OK
;R43 		loop	@B
;R43 		dec	ah
;R43 		jnz	short @B
;R43 		test	al,HDD_DRQ
;R43 		jz	short Resend_HDD_Cmd
;R43 HDD_Cmd_OK:
;R43 ;R17A end
;R43
;R43 ;Now we need to find out if it is read or write command.
;R43
;R43 		mov	al,[bp+9]
;R43 		cmp	al,Write_command
;R43 		jz	fill_buffer
;R43
;R43 ;It is a read command so we need to read the buffer.
;R43
;R43 read_buffer:
;R43 		xor	ecx,ecx			; 32 bit type uses ecx.
;R43 		mov	cx,100h
;R43 ;R27		mov	dx,Hdd_Port0		; Get Data register.(1F0)
;R43 		call	Get_HDD_Port_Base	;R27
;R43 		cld
;R43 		push	edi
;R43 		ALIGN	4
;R43 		db	67h			; Address size over-ride.
;R43 		rep 	insw
;R43 		pop	edi
;R43 		xor	eax,eax
;R43 		mov	ax,200h
;R43 		add	edi,eax
;R43 		add	dx,7
;R43 	@@:
;R43 		in	al,dx
;R43 		test	al,HDD_BUSY
;R43 		jnz	short @B
;R43 		in	al,dx
;R43 		test	al,HDD_DRQ
;R43 		jnz	read_buffer
;R43 		jmp	done_xfer
;R43
;R43 fill_buffer:
;R43 		xor	ecx,ecx
;R43 		mov	cx,100h
;R43 ;R27		mov	dx,Hdd_Port0		; Get Data register.
;R43 		call	Get_HDD_Port_Base	;R27
;R43 		cld
;R43 		push	esi
;R43 		ALIGN	4
;R43 		db	67h			; Address size over-ride.
;R43 		rep 	outsw
;R43 		pop	esi
;R43 		xor	eax, eax
;R43 		mov	ax, 200h
;R43 		add	esi, eax
;R43 		add	dx,7
;R43 	@@:
;R43 		in	al,dx
;R43 		test	al,HDD_BUSY
;R43 		jnz	short @B
;R43 		in	al,dx
;R43 		test	al,HDD_DRQ
;R43 		jnz	fill_buffer
;R43
;R43 done_xfer:
;R43 ;R27		mov	dx,Hdd_Port0+1		; Get Error register.
;R43 ;R29		call	Get_HDD_Port_Base	;R27
;R43 ;R29		inc	dl			;R27
;R43 ;R29		in	al,dx
;R43 ;R29		or	al,al
;R43 ;R29		jz	no_error_xfer
;R43 		jmp	short no_error_xfer	;R29
;R43
;R43 error_xfer:
;R43 		stc
;R43 		POST_CODE	0edh
;R43 		jmp	$
;R43
;R43 no_error_xfer:
;R43 		call	Test_CTLR_Busy		;R29
;R43 		pop	bp
;R43 		pop	dx
;R43 		pop	ecx
;R43 		pop	eax
;R43 		popad
;R43 		ret
;R43 HDD_Transfer	endp
;R43
;R43 ;===========================================================================
;R43 ;FUNC:  TEST_HDD_RDY
;R43 ;
;R43 ;DESC:  Tests if the HDD controller is ready to accept commands.
;R43 ;
;R43 ;IN:    None
;R43 ;
;R43 ;OUT:   None
;R43 ;===========================================================================
;R43 Test_CTLR_Busy:
;R43 ;R27		mov	dx,Hdd_Port0+7
;R43 		call	Get_HDD_Port_Base	;R27
;R43 		add	dl,7			;R27
;R43 	@@:
;R43 		in	al,dx			; Get Status value.
;R43 		test	al,HDD_BUSY
;R43 		jz	short @F
;R43 		mov	cx,40h
;R43 		call	Small_Delay
;R43 		jmp	short @B
;R43
;R43 	@@:
;R43 		ret
;R43
;R43 Test_HDD_Rdy	proc	near
;R43
;R43 ;R27		mov	dx,Hdd_Port0+7
;R43 		call	Get_HDD_Port_Base	;R27
;R43 		add	dl,7			;R27
;R43 	@@:
;R43 		in	al,dx			; Get Status value.
;R43 		test	al,HDD_RDY		; HDD_BUSY
;R43 		jnz	short @F
;R43 		mov	cx,40h
;R43 		call	Small_Delay
;R43 		jmp	short @B
;R43 	@@:
;R43
;R43 		ret
;R43 Test_HDD_Rdy	endp
;R43
;R43 ;[]===============================================================[]
;R43 ;
;R43 ; Get_HDD_Parm
;R43 ;
;R43 ;	The routine to return HDD location parameter for R/W.
;R43 ;
;R43 ; Entry:
;R43 ;	EBX = absolute sector number.
;R43 ;
;R43 ; Exit:
;R43 ;       CX = cylinder number.
;R43 ;       DH = Head number.
;R43 ;       DL = starting sector number.
;R43 ;
;R43 ; Note:
;R43 ;
;R43 ;[]==================================================================[]
;R43 Get_HDD_Parm	Proc	Near
;R43
;R43 		push	ds
;R43 		push	ax
;R43 		push	ebx
;R43
;R43 		call	F000_Get_PM_RAM_Seg
;R43 		mov	ds,ax
;R43
;R43 ;R27		call	Check_LBA_Mode
;R43 ;R27		jne	short @F
;R43 ;R27 start
;R43 		mov	dl,ds:[ZV_HDD_Scheme]
;R43 		shr	dl,2
;R43 		and	dl,3
;R43 		cmp	dl,1			;HDD is LBA mode?
;R43 		jne	short @F		;No,jump to Large or Normal mode
;R43 ;R27 end
;R43
;R43 		mov	dl,bl
;R43 		mov	cl,bh
;R43 		shr	ebx,16
;R43 		mov	ch,bl
;R43 		mov	dh,bh
;R43 		and	dh,0fh
;R43 		or	dh,0E0H			; LBA SDH
;R43 ;R27 start
;R43 		test	byte ptr ds:[ZV_HDD_Scheme],1	;check on master
;R43 		jz	short ZV_HDD_on_master		;Yes,jump
;R43 		or	dh,10h				;set to slave
;R43 ZV_HDD_on_master:
;R43 ;R27 end
;R43
;R43 		jmp	short End_Get_HDD_Parm
;R43 @@:
;R43
;R43 		xor	ecx,ecx
;R43 		mov	ax,bx
;R43 		shr	ebx,16
;R43 		mov	dx,bx
;R43 		mov	cx,word ptr ds:[Cylinder_Sector]
;R43 		div	cx			; Get Cylinder
;R43 		mov	cx,ax
;R43 		mov	ax,dx
;R43 		mov	bl,byte ptr ds:[Head_Sector]
;R43 		div	bl
;R43 		mov	dl,ah
;R43 		inc	dl
;R43
;R43 ;R27		call	Check_LRG_Mode		;R04
;R43 ;R27		jne	short @F		;R04
;R43 ;R27 start
;R43 ;R27A		mov	dl,ds:[ZV_HDD_Scheme]
;R43 ;R27A		shr	dl,2
;R43 ;R27A		and	dl,3
;R43 ;R27A		cmp	dl,2			;HDD is large mode?
;R43 		mov	bl,ds:[ZV_HDD_Scheme]	;R27A
;R43 		shr	bl,2			;R27A
;R43 		and	bl,3			;R27A
;R43 		cmp	bl,2			;R27A;HDD is large mode?
;R43 		jne	short @F		;No,jump to Large or Normal mode
;R43 ;R27 end
;R43 		shr	al,1			;R04 head/2
;R43 		shl	cx,1			;R04 cylinder*2
;R43 @@:						;R04
;R43 		and	al,0fh
;R43 		or	al, 0A0h		; sector size = 512 bytes
;R43 ;R27 start
;R43 		test	byte ptr ds:[ZV_HDD_Scheme],1	;check on master
;R43 		jz	short ZV_HDD_on_master0		;Yes,jump
;R43 		or	al,10h				;set to slave
;R43 ZV_HDD_on_master0:
;R43 ;R27 end
;R43 		mov	dh,al
;R43
;R43 End_Get_HDD_Parm:
;R43
;R43 		pop	ebx
;R43 		pop	ax
;R43 		pop	ds
;R43 		ret
;R43 Get_HDD_Parm	endp
;R43
;R43 ;R27Check_LBA_Mode	PROC	NEAR
;R43 ;R27
;R43 ;R27;R04 - start
;R43 ;R27		push	bx
;R43 ;R27		mov	bl,1			;LBA mode value
;R43 ;R27		call	Get_HDD_Mode
;R43 ;R27		pop	bx
;R43 ;R27		ret
;R43 ;R27Check_LRG_Mode:
;R43 ;R27		push	bx
;R43 ;R27		mov	bl,2			;LRG mode value
;R43 ;R27		call	Get_HDD_Mode
;R43 ;R27		pop	bx
;R43 ;R27		ret
;R43 ;R27Get_HDD_Mode:
;R43 ;R27;R04 - end
;R43 ;R27		push	ax
;R43 ;R27		push	ds
;R43 ;R27		mov	ax,G_RAM
;R43 ;R27		mov	ds,ax
;R43 ;R27		ASSUME	DS:G_RAM
;R43 ;R27		mov	al,HDD_MODE_FLAG
;R43 ;R27		and	al,3
;R43 ;R27;R04		cmp	al,1
;R43 ;R27		cmp	al,bl			;R04
;R43 ;R27		pop	ds
;R43 ;R27		pop	ax
;R43 ;R27		ret
;R43 ;R27Check_LBA_Mode	ENDP
;R43
;R43 ;[]===============================================================[]
;R43 ;
;R43 ; Get_ZV_HDD_Loc:
;R43 ;
;R43 ;	The routine to return ZV partition
;R43 ;
;R43 ; Entry:	NONE
;R43 ; Exit:
;R43 ;		EBX = absolute sector number of 0V-Suspend partition.
;R43 ;
;R43 ; Note:
;R43 ;
;R43 ;[]==================================================================[]
;R43 		Public	Get_ZV_HDD_Loc
;R43 Get_ZV_HDD_Loc	proc	near
;R43 		push	ds
;R43 		push	ax
;R43 		call	F000_Get_PM_RAM_Seg
;R43 		mov	ds,ax
;R43		mov	ebx,dword ptr ds:ZV_HDD_Sector
;R43		pop	ax
;R43		pop	ds
;R43		ret
;R43 Get_ZV_HDD_Loc	endp

ifdef	NO_ZV_REALTIME_MESSAGE
;[]========================================================================[]
;
;	Border for suspend/resume message
;
;[]========================================================================[]
ZV_Msg_Start_Y	EQU	8
E_Border_0V_Str:
		POS	<,28,ZV_Msg_Start_Y>
			db	V_WARN,'   Award Software, Inc.   '

			db	V_REVERSE
			db	V_BLINK
		BORDER1	<,0,ZV_Msg_Start_Y+2,79,ZV_Msg_Start_Y+6,1+Empty_Border>
			db	0

;[]========================================================================[]
;
;	Zero-Volt Suspend message
;
;[]========================================================================[]
Suspend_ZV_MSG:
		POS	<,5,ZV_Msg_Start_Y+4>
			db	V_REVERSE
			db	'Your system information has been saved, '
			db	'The system is shutting down. '
			db	0

endif	;NO_ZV_REALTIME_MESSAGE

;[]===============================================================[]
;Procedure:	Restore_SMI_STATE
;
;Function :	Routine to restore system state
;
;Input    :	DS = PM_RAM
;
;Output   :	None
;[]==================================================================[]
		Public	Restore_SMI_STATE
Restore_SMI_STATE	Proc	Near

		push	ds
		push	es
		Call	Get_SMBASE_ADD
		mov	ebx,eax
		xor	ax,ax
		mov	es,ax
		mov	ds,ax
		mov	esi,ebx
		mov	edi,ebx
		add	esi,offset BIOS_Entry_Save
		add	edi,offset Intel_SMM_State
		mov	cx,200h/4
		cld
@@:
		lods	dword ptr ds:[esi]
		stos	dword ptr es:[edi]
		loop	short @B
		pop	es
		pop	ds
		ret
Restore_SMI_STATE	ENDP

;R43 		Public	Get_SMBASE_ADD
;R43 Get_SMBASE_ADD	Proc	Near
;R43
;R43 ifndef	P6_BIOS_ONLY
;R43 		F000_call	Check_Cyrix_Cpu
;R43 		jnz	short Not_Cy
;R43
;R43 		push	cx
;R43
;R43 		mov	cl,0CDh
;R43 		Call	F000_Get_Cyrix
;R43 		mov	bh,al
;R43
;R43 		mov	cl,0CEh
;R43 		Call	F000_Get_Cyrix
;R43 		mov	bl,al
;R43 		shl	ebx,16
;R43
;R43 		mov	cl,0CFh
;R43		Call	F000_Get_Cyrix
;R43 		and	al,0F0h
;R43 		mov	bh,al
;R43 		sub	ebx,8000h
;R43 		mov	eax,ebx
;R43
;R43 		pop	cx
;R43 		ret
;R43 Not_Cy:
;R43 endif	;P6_BIOS_ONLY
;R43
;R43 		call	Get_SMBASE_Seg
;R43 		ret
;R43
;R43 Get_SMBASE_ADD	Endp
;R43
;R43 E_GET_CMOS	PROC	NEAR
;R43 		ALIGN	4
;R43 		OUT	CMOS,AL			; address to interface
;R43 		jcxz	short $+2
;R43 		jcxz	short $+2
;R43 		ALIGN	4
;R43 		IN	AL,CMOS+1
;R43 		jcxz	short $+2
;R43 		jcxz	short $+2
;R43 		RET
;R43 E_GET_CMOS	ENDP
;R43
;R43 E_SET_CMOS	PROC	NEAR
;R43  		ALIGN	4
;R43  		OUT	CMOS,AL			; address to interface
;R43  		jcxz	short $+2
;R43  		jcxz	short $+2
;R43  		xchg	al,ah			;ah=index,al=value
;R43  		ALIGN	4
;R43 		OUT	CMOS+1,AL		; and output it
;R43  		jcxz	short $+2
;R43 		jcxz	short $+2
;R43  		RET
;R43 E_SET_CMOS	ENDP
;R43
;R43 F_Display_String:
;R43 		F000_Call	Display_String
;R43 		ret

;R08 - start
ifdef	ONBOARD_MODEM_CARD
;R08A Modem_BASE			=	ONBOARD_MODEM_CARD
;R08A Receiver_Port			=	Modem_Base	;0 0 0	R
;R08A Transmitter_Port		=	Modem_Base	;0 0 0  W
;R08A Interrupt_Enable		=	Modem_Base + 1	;0 0 1	R/W
;R08A Interrupt_Identification	=	Modem_Base + 2	;0 1 0	R
;R08A Line_Control			=	Modem_Base + 3	;0 1 1  R/W
;R08A Modem_Control			=	Modem_Base + 4	;1 0 0	R/W
;R08A Line_Status 			=	Modem_Base + 5	;1 0 1  R/W
;R08A Modem_Status 			=	Modem_Base + 6	;1 1 0  R/W
;R08A Scratch_Pad			=	Modem_Base + 7	;1 1 1	R/W

Time_out_Value			=	2000h
Skip_Number			=	5

Suspend_Modem	Proc	Near

		push	es
		push	ds
		push	ebx

;R08A - start
		mov	ax,G_RAM
		mov	ds,ax

		mov	si,offset COMM_PORT_ADDRS
		xor	cx,cx
@@:
		cmp	cl,4
		jae	short No_Modem_Exist

		lodsw
		or	ax,ax
		jz	short No_Modem_Exist

		inc	cl
		mov	dx,ax
		add	dx,6			;Modem_Status
		in	al,dx
;R14		or	al,al
		and	al, 30h		;R14
		cmp	al, 30h		;R14
;R14		jz	short @B
		jne	short @B	;R14

		dec	cl		;R14B
		sub	dx,6
		mov	gs,dx
		mov	fs,cx
;R08A - end
		xor	ax,ax
		mov	es,ax

		mov	edi,ebx
		add	edi,offset Modem_Device_Save

		mov	cx,100
		xor	al,al
	@@:
		push	cx
		push	ax

		call	Read_Modem_Register
		mov	eax,ds:[bx]
		stos	dword ptr es:[edi]

		pop	ax
		inc	al
		pop	cx
		loop	short @B

No_Modem_Exist:					;R08A
		pop	ebx
		pop	ds
		pop	es
		ret

Suspend_Modem	Endp

Restore_Modem	Proc	Near

		push	es
		push	ds
		push	ebx

;R08A - start
		mov	ax,G_RAM
		mov	ds,ax

		mov	si,offset COMM_PORT_ADDRS
		xor	cx,cx
@@:
		cmp	cl,4
		jae	short No_Modem_Restore

		lodsw
		or	ax,ax
		jz	short No_Modem_Restore

		inc	cl
		mov	dx,ax
		add	dx,6			;Modem_Status
		in	al,dx
;R14		or	al,al
		and	al, 30h		;R14
		cmp	al, 30h		;R14
;R14		jz	short @B
;R14A		jne	short @f	;R14
		jne	short @B	;R14A

		dec	cl		;R14B
		sub	dx,6
		mov	gs,dx
		mov	fs,cx
;R08A - end

		xor	ax,ax
		mov	es,ax
		mov	ds,ax

		mov	esi,ebx
		add	esi,offset Modem_Device_Save

		mov	cx,100
		xor	al,al
	@@:
		push	cx
		push	ax

		lods	dword ptr ds:[esi]
		cmp	al,'E'
		je	short No_exist
		mov	ebx,eax
		pop	ax
		push	ax
		call	Write_Modem_Register

		push	ds
		Call	Read_Modem_Register
		pop	ds
	No_exist:
		pop	ax
		inc	al
		pop	cx
		loop	short @B

No_Modem_Restore:				;R08A
		pop	ebx
		pop	ds
		pop	es
		ret

Restore_Modem	Endp

Write_Modem_Register	Proc	Near

		push	es
		push	ds
		push	esi
		push	ax

		mov	si,offset Send_Data
@@:
		lods	byte ptr cs:[si]
		or	al,al
		jz	short @F

		Call	Write_COMM_Byte
		jmp	short @B
@@:
		pop	ax
		pop	esi

		push	esi
		push	ax

;R08B		Call	AX_TO_DEC2
		Call	_AX_TO_DEC2		;R08B

		push	ax
		or	ah,ah
		jz	short @F

		mov	al,ah
		Call	Write_COMM_Byte
@@:
		pop	ax
		or	al,al
		jz	short @F

		Call	Write_COMM_Byte
@@:
		mov	al,'='
		Call	Write_COMM_Byte

		mov	al,bl
		Call	Write_COMM_Byte

		mov	al,bh
		Call	Write_COMM_Byte

		shr	ebx,16
		mov	al,bl
		Call	Write_COMM_Byte

		mov	al,0dh
		Call	Write_COMM_Byte

		pop	ax
		pop	esi
		pop	ds
		pop	es
		ret

Write_Modem_Register	Endp


Read_Modem_Register	Proc	Near

		push	es
		push	edi
		push	ax

		mov	bx,offset Send_Data
@@:
		mov	al,cs:[bx]
		inc	bx
		or	al,al
		jz	short @F

		Call	Write_COMM_Byte
		jmp	short @B
@@:
		pop	ax
		push	ax

;R08B		Call	AX_TO_DEC2
		Call	_AX_TO_DEC2		;R08B

		push	ax
		or	ah,ah
		jz	short @F

		mov	al,ah
		Call	Write_COMM_Byte
@@:
		pop	ax
		or	al,al
		jz	short @F

		Call	Write_COMM_Byte
@@:
		mov	al,'?'
		Call	Write_COMM_Byte

		mov	al,0dh
		Call	Write_COMM_Byte

		mov	ax,ZV_Temp_Stack
		mov	ds,ax

		mov	di,offset VIDEO_BUFFER
@@:
		Call	Read_COMM_Byte
		jc	short End_Data

		or	al,al
		jz	short @B
		cmp	al,1fh
		jbe	short @B

		stosb
		jmp	short @B
End_Data:
		mov	bx,di
		sub	bx,Skip_Number

		pop	ax
		pop	edi
		pop	es
		ret

Read_Modem_Register	Endp


Write_COMM_Byte	Proc	Near

		mov	ah,01
;R08A		mov	dx,1
		mov	dx,fs				;R08A
		pushf
		Far_Call	<offset COMM_VECT>,<seg COMM_VECT>

		ret

Write_COMM_Byte	Endp

Read_COMM_Byte	Proc	Near

	;set modem control DTR

;R08A		mov	dx,Modem_Control
		mov	dx,gs				;R08A
		add	dx,4				;R08A
		mov	al,00000001b
		out	dx,al
		NEWIODELAY

	;Wait for DSR or TIME-OUT

;R08A		mov	dx,Modem_Status
		add	dx,2				;R08A
		mov	al,20h
		mov	ah,20h
		mov	cx,Time_out_Value
		Call	Wait_For_Port
		jc	short i_Fail_Return

	;check DR ot TIME-OUT

;R08A		mov	dx,Line_Status
		sub	dx,1				;R08A
		mov	al,01h
		mov	ah,01h
		mov	cx,Time_out_Value
		Call	Wait_For_Port
		jc	short i_Fail_Return

;R08A		mov	dx,Receiver_Port
		sub	dx,5				;R08A
		in	al,dx
		NEWIODELAY
		clc
i_Fail_Return:
		ret

Read_COMM_Byte	Endp


;R08B AX_TO_DEC2	Proc	Near
_AX_TO_DEC2	Proc	Near			;R08B

		push	bx

		mov	bl,al
		mov	ah,'0'
		mov	bh,10
Next_Check:
		cmp	bl,bh
		jb	short @F

		sub	bl,bh
		inc	ah
		or	bl,bl
		jnz	short Next_Check
@@:
		mov	al,bl
		add	al,'0'

		pop	bx
		ret

;R08B AX_TO_DEC2	Endp
_AX_TO_DEC2	Endp				;R08B

Wait_For_Port	Proc	Near

		push	bx
		mov	bl,al
Wait_For_Bit:
		in	al,dx
		and	al,bl
		cmp	al,ah
		clc
		je	short @F

		dec	cx
		jnz	short Wait_For_Bit
		stc
@@:
		pop	bx
		ret
Wait_For_Port	Endp

Send_Data:
		db	'ATS',0
endif	;ONBOARD_MODEM_CARD
;R08 - end
;R24 - start
ifdef	VGA_resume_special_patch
VGA_special_patch proc	near
		pusha
		mov	dx,3BAh
		in	al,dx
		mov	dl,0DAh
		in	al,dx
		mov     dx,03c0h
		xor	al,al
		out     dx,al
		popa
		ret
VGA_special_patch endp
endif	;VGA_resume_special_patch
;R24 - end
endif	;Notebook_Power_Management

ECODE		ENDS

		END
