;	[]===========================================================[]
;
;	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
;----------------------------------------------------------------------------
;R05	04/08/99 BAR 	Support Cyrix SMI flash.
;R01A	03/15/99 BAR 	Fixed Error.
;R04	03/12/99 BAR 	Suport Windows NT update BIOS.
;R03 	03/08/99 BAR	Reserve 8K bufer .
;R02    02/26/99 BAR    Support 32bit address to update Flash.
;R01	02/03/99 BAR 	Support Flash_Part_Erase .
;R00	01/28/99 BAR	Support update ESCD DMI in SMM mode.
;			define switch "Flash_IN_SMBASE"

ifdef	MASM611
.MODEL  SMALL, BASIC
OPTION	PROC: PRIVATE
endif	;MASM611

.386p
		PAGE	56,132
		TITLE	SMIFlash.ASM   --   FLash write Interface
.XLIST

		INCLUDE	BIOS.CFG
		INCLUDE	COMMON.EQU
		INCLUDE	COMMON.MAC
		INCLUDE	PNP.EQU	;;;;
		INCLUDE	BTROMSEG.EQU			;R01
		INCLUDE	DMI.EQU				;R01
ifdef	Flash_IN_SMBASE

		extrn	Open_PM_RAM:near		;PMU.ASM
		extrn	Close_PM_RAM:near		;PMU.ASM
		extrn	Get_PM_RAM_Seg:near		;PMU.ASM
		extrn	Issue_SW_SMI:near
		extrn	Flash_sw_smi:near		;;;;;
	
		extrn	SMI_Handler_Start:near
		extrn	SMI_Handler_End:near
		extrn	SMI_Handler_Len:ABS
	
		extrn	Ct_Buffer_Request:near
		extrn	Check_16Bit_Stack:near
		extrn	Ct_Save_Shadow:near
		extrn	Ct_Restore_Shadow:near
ifdef NT_FLASH						;R04
		extrn	Ct_Enable_Flash:far		;R04
		extrn	Ct_Disable_Flash:far		;R04
else; NT_FLASH						;R04
		extrn	Ct_Enable_Flash:near
endif; NT_FLASH						;R04
	
		extrn	GDTR1:near
		extrn	ESCD_INDEX:abs
		extrn	F0DATA_INDEX:abs
		extrn	A20_On:near
		extrn	A20_Off:near
		extrn	A20_Byte:near
		extrn	Check_A20_AndRecord:near
;R05 endif;	Flash_IN_SMBASE

Flash_Reser_Size	EQU	20
;R05 - starts
		COMPILE_FOR_CYRIXSMI	=	1
		include	cyrixsmi.inc	;include SMI_STRUCT
SMRAM_EAX		EQU	[bp + _EaxSave]
SMRAM_EBX		EQU	[bp + _EbxSave]
SMRAM_ECX		EQU	[bp + _EcxSave]
SMRAM_EDX		EQU	[bp + _EdxSave]
SMRAM_ESI		EQU	[bp + _EsiSave]
SMRAM_EDI		EQU	[bp + _EdiSave]
;R05 - ends
;R05 
;R05 SMRAM_EAX		EQU	07fd0h		;SMI cpu autosave eax offset
;R05 SMRAM_AH		EQU	07fd1h		;R04
;R05 SMRAM_ECX		EQU	07fd4h
;R05 SMRAM_EDX		EQU	07fd8h
;R05 SMRAM_EBX		EQU	07fdch
;R05 SMRAM_EBP		EQU	07fe4h
;R05 SMRAM_ESI		EQU	07fe8h
;R05 SMRAM_EDI		EQU	07fech
SMRAM_EFLAG		EQU	07ff4h

Func_Flash_to_Reg	        EQU	0
Func_Erase			EQU	1
Func_Write_To_Buffer		EQU	2
Func_Program			EQU	3
;R01 - start
Func_PartErase			EQU	4
Func_BIOS_Inf			EQU	6	;R04
Func_Auto_Flash			EQU	7	;R04
Func_Erase_point  		EQU	8	;R04
Func_Write_point  		EQU	9	;R04
Func_Delay			EQU	10	;R04
Func_Buffer_offset		EQU	11	;R04
Func_End_of_Buffer_offset	EQU	12	;R04
;R04 Func_Erase_point  		EQU	5
;R04 Func_Write_point  		EQU	6
;R04 Func_Delay			EQU	7
;R04 Func_Buffer_offset		EQU	8
;R04 Func_End_of_Buffer_offset	EQU	9
;R01 - start
;R01 Func_Erase_point  		EQU	4
;R01 Func_Write_point  		EQU	5
;R01 Func_Delay			EQU	6
;R01 Func_Buffer_offset		EQU	7
Flash_Counter		EQU	word ptr [bp - 1]	;R04

endif;	Flash_IN_SMBASE					;R05

Reallocate	macro	LableName
_&LableName	label	near
LableName	EQU 	$ - offset SMI_FLASH_START
		ENDM

G_RAM		SEGMENT	USE16 AT 0

		ORG	04H*4
		INCLUDE	SEG_0.INC

		ORG	400H
		INCLUDE	G_RAM.INC

G_RAM		ENDS

PM_RAM		SEGMENT	USE16 AT 0 	; define PM RAM segment

		ORG	0
		INCLUDE	PM_RAM.INC

PM_RAM		ENDS

.LIST


DGROUP		GROUP	FCODE
FCODE		SEGMENT	USE16 DWORD Public 'CODE'
		ASSUME	CS:DGROUP

ifdef	Flash_IN_SMBASE
;[]==================================================[]
;Procedure:	Flash_Service
;Function :	Flash read/write interface
;Input    :	DS:SI = point to buffer 
;		ES:DI = point to buffer
;		CX = length
;Output   :	CF = 0 successful
;		CF = 1 fail
;Registers:
;Note	  :
;[]==================================================[]
		Public	Flash_Service
Flash_Service	Proc	near
		cli
		pushad
		push	ebp

		xor	eax,eax
		call	Ct_Buffer_Request	;buffer request for saving status
		shl	eax,1
		call	Check_16Bit_Stack	;16-bit stack ?
		jz	short _16_bit_stack	;jump if 16-bit stack
		sub	esp, eax		;reduce stack for saving status
		mov	ebp, esp		;status buffer index
		jmp	short Flash_Service1
_16_bit_stack:
		sub	sp, ax
		movzx	ebp, sp
Flash_Service1:

		call	Ct_Save_Shadow		;save shadow status
;R01 - start
		cmp	bl,2			;Is flash part Erase ?
		jne	short Not_Part_Erase
ifndef NT_FLASH					;R01A
		call	Ct_Enable_Flash		;R01A;can not disable F000 shadow
endif; NT_FLASH					;R01A
		call	Flash_PartErase_service	
		jmp	short Flash_Service3
Not_Part_Erase:
;R01 - start
		or	bl,bl			;Is flash Read ?
		jnz	Short IS_Flash_Write	;No ,skip.
		
		call	Flash_Read_service
		jmp	short Flash_Service3
IS_Flash_Write:
ifndef NT_FLASH
		call	Ct_Enable_Flash		;can not disable F000 shadow
endif; NT_FLASH
		call	Flash_Write_service
Flash_Service3:
		pushf				;save flag
		call	Ct_Restore_Shadow	;restore shadow status
		popf				;
		lahf
		mov	ch,ah			;keep flag in ch
		xor	eax, eax
		call	Ct_Buffer_Request
		shl	eax,1
		add	esp,eax

		mov	ah,ch			;keep flag in ch
		sahf				;retrun flag
		pop	ebp
		popad
		ret
Flash_Service	Endp

;[]==================================================[]
;Procedure:	Flash_Service
;Function :	Flash read/write interface
;Input    :	DS:SI = point to buffer 
;		ES:DI = point to buffer
;		CX = length
;Output   :	eax,ebx,ecx,edx
;		
;Registers:
;Note	  :
;	Flash_Read_Service apper software SMI then
;	SMI_FLASH_Handler copy data to register (eax,ecx,edx,ebx) 16 bytes
;	when return from SMM mode we can move data to ES:DI
;[]==================================================[]
		Public	Flash_Read_Service
Flash_Read_Service	Proc	near
		cli
		jcxz	short Flash_Read_Service_Ret
		pushad
		mov	al,SMI_FlashRead
		call	Set_SMI_Type
		add	cx,15			;keep min read 16 byte
		shr	cx,4			;min 16 bytes
Read_SMBASE_Buffer_Loop:
		push	cx		
		mov	cx,16
		call	Flash_SW_SMI
		call	Move_Reg_To_Buffer
		pop	cx
		loop	Read_SMBASE_Buffer_Loop

		xor	al,al
		call	Set_SMI_Type
		popad
Flash_Read_Service_Ret:
		clc
		ret

Flash_Read_Service	ENDP
;[]==================================================[]
;	Transfer Rsgister to buffer
;Input    :	DS:SI = point to source buffer 
;Output   :	EBX,ECX,EBP,EDI
;
;Note     :
; Used 32bits register transfer data from SMM mode
;[]==================================================[]

Move_Reg_To_Buffer	Proc	NEAR
		db 66h			;32 bits data precommand
		stosd	
		mov	eax,ecx
		db 66h			;32 bits data precommand
		stosd	
		mov	eax,edx
		db 66h
		stosd 
		mov	eax,ebx
		db 66h
		stosd	
		add	si,16		;add source pointer
		ret
Move_Reg_To_Buffer	ENDP
;[]==================================================[]
;Procedure:	Flash_Write_Service
;Function :	Flash write interface
;Input    :	DS:SI = point to source buffer 
;		ES:DI = point to buffer
;		CX = length
;Output   :
;		
;Registers:
;Note	  :
;	Flash_Read_Service apper software SMI then
;	SMI_FLASH_Handler copy data to register (eax,ecx,edx,ebx) 16 bytes
;	when return from SMM mode we can move data to ES:DI
;[]==================================================[]

		Public	Flash_Write_Service
Flash_Write_Service	Proc	near
		cli
		jcxz	short Flash_Write_Service_Ret
		pushad

		mov	al,SMI_FlashErase
		call	Set_SMI_Type
		call	Flash_SW_SMI		;Erase Flash block cx = size
		jc	short Flash_Write_Service_Fail
ifndef	NT_FLASH
		add	cx,255			;
		shr	cx,8			;min 256 bytes
Write_Flash_Buffer_Loop:
		push	cx
		mov	al,SMI_FlashWrite
		call	Set_SMI_Type

	;--- Write data to SMBASE Buffer ---
		push	ebp			;Transfer data to reg use 
		push	edi			;ebx,ecx,edi,ebp register
		mov	cx,256/16		;once transfer 16 bytes
Write_Flash_Buffer_Loop_1:
;R04		push	cx
		pushad				;R04
		call	Transfer_data_to_Reg
		call	Flash_SW_SMI		;transfer data to buffer
		popad				;R04
;R04		pop	cx
		add	di,16
		add	si,16			;R04
		loop	Write_Flash_Buffer_Loop_1
		pop	edi
		pop	ebp
		mov	cx,256			;min program size
		mov	al,SMI_FlashProgram	;Program min = 256 bytes
		call	Set_SMI_Type
		call	Flash_SW_SMI
		pop	cx
		jc	short Flash_Write_Service_Fail
		add	di,256				;next block
		loop	Write_Flash_Buffer_Loop
;R04 - start
else;	NT_FLASH
		mov	al,SMI_Auto_Flash
		call	Set_SMI_Type
		add	cx,4095			;
		shr	cx,12			;min 4096 bytes
Write_Flash_Buffer_Loop:
		push	cx
	;--- Write data to SMBASE Buffer ---
		mov	cx,4096/16		;once transfer 16 bytes
Write_Flash_Buffer_Loop_1:
		pushad
		call	Transfer_data_to_Reg
		call	Flash_SW_SMI		;transfer data to buffer
		popad
		add	di,16
		add	si,16
		loop	Write_Flash_Buffer_Loop_1
		pop	cx
		jc	short Flash_Write_Service_Fail
		loop	Write_Flash_Buffer_Loop
endif;	NT_FLASH
;R04 - end
Flash_Write_Service_Fail:
		popad
Flash_Write_Service_Ret:
		ret

Flash_Write_Service	ENDP

;[]==================================================[]
;	Transfer Data to Rsgister
;Input    :	DS:SI = point to source buffer 
;Output   :	EBX,ECX,EBP,EDI
;
;Note     :
; Used 32bits register transfer data into SMM mode
;[]==================================================[]
Transfer_data_to_Reg	PROC	Near
		db	66h 		;32 bits data precommand
		lodsd
		mov	ebx,eax
		db	66h
		lodsd
		mov	ecx,eax
		db	66h
		lodsd
;R04		mov	ebp,eax
 		mov	edx,eax		;R04 save data in bit 16-31
 		shl	eax,16		;R04
		push	eax		;R04
		db	66h
		lodsd
;R04 		mov	edi,eax
 		mov	esi,eax		;R04
		pop	eax		;R04
		ret
Transfer_data_to_Reg	ENDP
;R01 - start
;[]==================================================[]
;Procedure:	Flash_PartErase_Service
;Function :	Flash Part erase interface
;Input    :	EDI = point to erase address
;		CX = Erase length
;Output   :
;		
;Registers:
;Note	  :
;		Only transfer EDI,ECX to smbase
;[]==================================================[]

		Public	Flash_PartErase_Service
Flash_PartErase_Service	Proc	near
		cli
		jcxz	short Flash_PartErase_Service_Ret
		pushad
		mov	al, SMI_FlashPartErase
		call	Set_SMI_Type
		call	Flash_SW_SMI		;Erase Flash block cx = size
		jc	short Flash_PartErase_Service_Fail
Flash_PartErase_Service_Fail:
		popad
Flash_PartErase_Service_Ret:
		ret
Flash_PartErase_Service	ENDP
;R01 - end

;[]==================================================[]
;	
;Procedure:	Set_SMI_Type
;Input    :	GS is Bios selecter
;		Al = SMI type
;Output   :  	None
;		
;Registers:
;Note	  :
;		Real mode    GS = 0F000H
;		Protect mode GS = Bios selecter
;[]==================================================[]

Set_SMI_Type	PROC	Near
		pushad
		push	ax
		call	Open_PM_RAM
		pop	ax
		mov	si,(((PM_RAM_SEGMENT  and 0FFFH )SHL 4) + Offset Software_SMI_Type)
		mov	gs:[si],al
		call	Close_PM_RAM
		popad
		ret
Set_SMI_Type	ENDP

endif	;Flash_IN_SMBASE

FCODE		ENDS


DGROUP		GROUP	@DATAC
@DATAC		SEGMENT	USE16 DWORD COMMON 'DATAC'
		ASSUME	CS:DGROUP
@DATAC		ENDS

XGROUP		GROUP	XCODE
XCODE		SEGMENT USE16 PARA PUBLIC 'XCODE'
		ASSUME	CS:XGROUP,ES:XGROUP
		ASSUME	DS:PM_RAM

ifdef	Flash_IN_SMBASE
;[]=======================================================================[]
;
; 		Flash SMI service routine
;Now use 4 type software SMI (	SMI_Type_Flash_Read,
;			      	SMI_Type_Flash_Erase,
;			     	SMI_Type_Flash_Write,
;				SMI_Type_Flash_Program)
;!!! Note : SMI_FLASH_HANDLER routine must be head of SMI_FLASH_START !!!
;[]========================================================================[]

	Public SMI_FLASH_START
SMI_FLASH_START:
		Public	SMI_FLASH_Handler
SMI_FLASH_Handler	PROC	Near
Reallocate	SMI_FLASH_Handler_offset
		cli
		push	PM_RAM_SEGMENT
		pop	ds
		push	SEG DGROUP
		pop	gs
;R04 - start
ifdef NT_FLASH
		in	al,0b2h
		cmp	al,0ffh	
		je	@F
		jmp	From_IO_Port
@@:
endif; NT_FLASH
;R04 - end

		mov	al,[Software_SMI_Type]	;0 - read  ,1 - Erase 
From_IO_Port:					;R04
		and	al,07h			;2 - Write ,3 - Program
						;4 - part erase ;R01
		call	SMI_Sub_Function
		cmp	cs:[_CpuBrandOffset],0		;R05
		jz	Cyrix_CPU_SMI			;R05
		lahf
		mov	cs:[SMRAM_EFLAG],ah	;return to caller flag
		ret
;R05 - start
Cyrix_CPU_SMI:
		lahf
		mov	cs:[Cyrix_EFLAG],ah	;return to caller flag
		ret
;R05 - ends

SMI_FLASH_Handler	ENDP

;[]==================================================[]
;
;[]==================================================[]
Load_Register:
		push	bp			;R05
		mov	bp,cs:[_CpuBrandOffset]	;R05
		mov	edi,cs:[SMRAM_EDI]
		mov	esi,cs:[SMRAM_ESI]
		mov	ebx,cs:[SMRAM_EBX]
		mov	edx,cs:[SMRAM_EDX]
		mov	ecx,cs:[SMRAM_ECX]
		mov	eax,cs:[SMRAM_EAX]
		pop	bp			;R05
		ret

;[]==================================================[]
;	SMI_Sub_Function
;Input :	ax	= function offset
;Output:	none
;[]==================================================[]
SMI_Sub_Function	Proc	Near
		push	ax
		call	Get_SubFunction_Offset
		call	ax
		pop	ax
		ret
SMI_Sub_Function	ENDP

;[]==================================================[]
;	Get_Jump_Function_Offset
;Input :	al 	= subfuncation number
;Output: 	ax 	= function offset
;[]==================================================[]
Get_SubFunction_Offset	Proc	Near
		push	si
		mov	si,offset Flash_FUNC_TBL_offset
ifdef	APM_IN_SMBASE
		add	si,SMI_Handler_Len + APM_Handler_Len
else;	APM_IN_SMBASE
		add	si,SMI_Handler_Len
endif;	APM_IN_SMBASE
		xor	ah,ah
		shl	ax,01		;SubFuncation
		add	si,ax			;offset  = ax * 2 + Handler len
		mov	ax,word ptr cs:[si]	;move function offset to ax
		pop	si
		ret
Get_SubFunction_Offset	ENDP

;[]==================================================[]
;Procedure:	SMI_Flash_Read
;Function :
;Input    :	SI 	 = Read flash Address (line address)
;		Distinct = eax,ebx,ecx,edx
;		Length   = 16 bytes
;Output   :	CF = 0 successful
;		CF = 1 fail
;Registers:
;Note	  :
;[]==================================================[]
Flash_Read_hendler	proc	near
Reallocate	Flash_Read_offset
		cli
ifdef NT_FLASH						;R04
		call	far ptr Ct_Enable_Flash		;can not disable F000 shadow;R04
endif; NT_FLASH						;R04
		call	Set_Read_Address
		mov	cx,16/4
Flash_Read_loop:
		db 67h
		lodsd
		db 66h
		stosd
		loop	short Flash_Read_loop
ifdef NT_FLASH						;R04
		call	Ct_Disable_Flash		;R04
endif; NT_FLASH						;R04
		clc
		ret
Flash_Read_hendler	ENDP
;[]=============================================[]
; Set Read Flash Address
;Input    :	None
;Output   :	None
;Note	  :
;	Always use high address to read flash data.
;	Read flash data to resgister, then Flash_Read_Serivce
;	mov from eax,ecx,edx,ebx to es:di 
;
;[]=============================================[]
Set_Read_Address:
		call	Load_Register
		push	cs
		pop	es
		xor	ax,ax
		mov	ds,ax
ifndef		ESCD_32bits			;R02
		and	esi,0ffffh		;source read from high address
		or	esi,0ffff0000h		; F000H
endif;		ESCD_32bits			;R02
;R05		mov	edi,SMRAM_EAX
		movzx	edi,cs:[_CpuBrandOffset];R05
		add	di,_EaxSave		;R05
		ret
		
;[]========================================================================[]
;Procedure:	SMI_Flash_Erase
;Function :	Flash Block Erase
;Input    :	ES:DI = Erase address
;		CX = length
;Output   :	CF = 0 successful
;		CF = 1 fail
;Registers:
;Note	  :
;[]========================================================================[]
Erase_Flash_hendler	proc	near
Reallocate	Erase_Flash_offset
		pushad
		cli
		cmp	byte ptr gs:[0E05AH],-1	
		stc				;set fail
		je	short Flash_Erase_exit
ifdef NT_FLASH						;R04
		call	far ptr Ct_Enable_Flash		;R04
endif; NT_FLASH						;R04
		call	Set_Erase_Address
		mov	al,Func_Delay		;get delay offset
		call	Get_SubFunction_Offset	;return offset
		mov	dx,ax

		mov	ax,Func_Erase_point	;Flash  Erase
		call	SMI_Sub_Function
Flash_Erase_exit:
ifdef NT_FLASH					;R04
		call	Ct_Disable_Flash	;R04
endif; NT_FLASH					;R04
		popad
		ret

Erase_Flash_hendler	ENDP
;[]=============================================[]
;	   Set Erase Address
;Input    :	None
;Output   :	None
;Note	  :
;
;[]=============================================[]
Set_Erase_Address:
		call	Clear_Counter_Index
		call	Load_Register
		xor	ax,ax		;High address (4G mapping address)
		mov	es,ax		;High address
		mov	gs,ax		;High address
ifndef		ESCD_32bits			;R02
		and	edi,0ffffh	;High address
		or	edi,0ffff0000h	;High address
endif;		ESCD_32bits			;R02
		and	esi,0ffffh	;High address
		ret

;[]========================================================================[]
;Procedure:	Reg_to_buffer
;Function :
;Input    :	ebx,ecx,ebp,esi
;		Distinct = SMBAE Buffer
;Output   :	
;		
;Registers:
;Note	  :
;[]========================================================================[]
Reg_To_Buffer	proc	near
Reallocate	Reg_To_Buffer_offset
		call	Set_Buffer_Address
		call	Move_Data		;R05
;R05 		mov	eax,cs:[SMRAM_EBX]	
;R05 		db 66h
;R05 		stosd
;R05 		mov	eax,cs:[SMRAM_ECX]
;R05 		db 66h
;R05 		stosd
;R05 		mov	eax,cs:[SMRAM_EDX]
;R05 		mov	ebx, cs:[SMRAM_EAX+2]	
;R05 		mov	ax,bx	
;R05 		db 66h
;R05 		stosd
;R05 		mov	eax,cs:[SMRAM_ESI]
;R05 		db 66h				;data is 32 bits
;R05 		stosd				;address is 16 bits
		mov	ax,es:[si]
		add	ax,16
		mov	es:[si],ax		;index + 16 => point to next buffer
Reg_To_Buffer_Ret:
		ret

Reg_To_Buffer	ENDP
;[]=============================================[]
;	   Set Buffer  Address
;Input    :	None
;Output   :	None
;Note	  :
;[]=============================================[]
Set_Buffer_Address:
		push	cs
		pop	es			
		mov	ax,Func_Buffer_offset
		call	Get_SubFunction_Offset
		mov	di,ax			;es:di = buffer address
		add	ax,256			; to save length
		mov	si,ax			
		mov	ax,es:[si]		;read last address
		add	di,ax			;pointer to next addr
		ret
;[]========================================================================[]
;Procedure:	Flash_Write
;Function :
;Input    :	source = SMBAE buffer
;		DI = point to distinct buffer (use high address)
;Output   :	CF = 0 successful
;		CF = 1 fail
;Registers:
;Note	  :
;[]========================================================================[]
Flash_Write_hendler	proc	near
Reallocate	Flash_Write_offset
		cli
		pushad
ifdef NT_FLASH						;R04
		call	far ptr Ct_Enable_Flash		;R04
endif; NT_FLASH						;R04
		call	Set_program_Address

		mov	al,Func_Delay		;get delay offset
		call	Get_SubFunction_Offset	;return offset
		mov	dx,ax

		mov	ax,Func_Write_point	;Flash Write
		call	SMI_Sub_Function
Flash_Write_exit:
ifdef NT_FLASH						;R04
		call	Ct_Disable_Flash		;R04
endif; NT_FLASH						;R04
		popad
		ret

Flash_Write_hendler	ENDP
;[]=============================================[]
;	   Set Program Address
;Input    :	None
;Output   :	None
;Note	  :
;[]=============================================[]
Set_program_Address:
		call	Load_Register
		push	cs				;set source
		pop	ds
		call	Clear_Counter_Index
		xor	ax,ax
		mov	es,ax		;High address (4G mapping address)
		mov	gs,ax		;High address 
ifndef		ESCD_32bits		;R02
		and	edi,0ffffh	;High address 
		or	edi,0ffff0000h	;High address 
endif;		ESCD_32bits		;R02
		and	esi,0ffffh	;High address
		ret
;R01 - start
;[]========================================================================[]
;Procedure:	Flash_PartErase
;Function :
;Input    :	source = SMBAE buffer
;		EDI = point to erase address
;		CX  = erase length
;Output   :	CF = 0 successful
;		CF = 1 fail
;Registers:
;Note	  :
;[]========================================================================[]
Flash_PartErase_hendler	proc	near
Reallocate	PartErase_Flash_offset
ifdef DMI_ENABLED	
		cli
		pushad
		cmp	byte ptr gs:[0E05AH],-1	
		stc				;set fail
		je	short Flash_PartErase_exit
		;--- copy data to buffer ---
		call	Set_PartErase_Address
		mov	esi,edi		;erase
		mov	bx,si
		movzx	edi,ax		;smbase buffer 8k
		cmp	si, ESCD_Data_Seg
		jae	Is_ESCD_Area
		mov	si, DMI_OFFSET
		sub	bx, DMI_OFFSET
		jmp	short Back_Other_Area
Is_ESCD_Area:
		mov	si, ESCD_Data_Seg
		sub	bx, ESCD_Data_Seg
Back_Other_Area:
		add	bx, di
		push	esi			;store erase parmeter block
		push	cx
		mov	ecx, DMI_STORAGE_SIZE /4
		db 67h
		rep	movsd
		pop	cx			;reload erase length	
		;--- Clear Part data by buffer ---
		mov	di,bx			;clear address
		mov	al,0FFH
		db 67h
		rep	stosb
		;--- Erase Flash ---
		pop	edi			;reload erase block
ifdef NT_FLASH						;R01A
		call	far ptr Ct_Enable_Flash		;R01A can not disable F000 shadow
endif; NT_FLASH						;R01A

		mov	al,Func_Delay		;get delay offset
		call	Get_SubFunction_Offset	;return offset
		mov	dx,ax

		xor	ax,ax
		mov	es,ax
		push	edi
		mov	ax,Func_Erase_point	;Flash  Erase
		call	SMI_Sub_Function
		pop	edi
		;--- Rewrite data from buffer ---

		mov	cx, DMI_STORAGE_SIZE
		call	Get_SMBASE_Buffer
		movzx	esi,ax

		push	cs
		pop	ds
		mov	cx, DMI_STORAGE_SIZE
		mov	ax,Func_Write_point	;Flash Write
		call	SMI_Sub_Function
ifdef NT_FLASH						;R01A
		call	Ct_Disable_Flash		;R01A can not disable F000 shadow
endif; NT_FLASH						;R01A

Flash_PartErase_exit:
		popad
endif; DMI_ENABLED	
		ret

Flash_PartErase_hendler	ENDP
;[]=============================================[]
;	   Set PartErase Address
;Input    :	None
;Output   :	None
;Note	  :
;[]=============================================[]
ifdef DMI_ENABLED	
Set_PartErase_Address:
		call	Load_Register
		push	cs				;set source
		pop	es
		xor	ax,ax
		mov	ds,ax		;High address (4G mapping address)
		mov	gs,ax		;High address 
		or	edi,0fff00000h
		call	Get_SMBASE_Buffer
		ret
;R04 endif; DMI_ENABLED	

Get_SMBASE_Buffer:
		mov	ax, Func_End_of_Buffer_offset
		call	Get_SubFunction_Offset	;return offset
		add	ax, 4FFh	;more byte resver.
		and	ax, 0ff00H
		ret
		

endif; DMI_ENABLED	
;R04 - start
;[]========================================================================[]
;Procedure:	Auto_Flash_Handler
;Function :
;Input    :	EDI = point to erase address (Flash Write)
;		EBX,ECX,EBP,ESI		     (Wrte data)
;		ESI = point to erase address (Flash Read)
;Output   :	CF = 0 successful
;		CF = 1 fail
;		EAX,ECX,EDX,EBX		     (Flash Read)
;Registers:
;Note	  :
;[]========================================================================[]
Auto_Flash_Handler	proc	near
Reallocate	Auto_Flash_offset
		cli
		pushad
		call	Get_SMBASE_Buffer
		mov	bp,ax
		and	edi,0fffh
		jnz	Not_first_IN
		mov	Flash_Counter, 0
Not_first_IN:
		add	ax,Flash_Counter
		movzx	edi,ax
		push	cs
		pop	es
		call	Move_Data
		add	Flash_Counter, 010h		;Counter + 16 byte
		cmp	Flash_Counter, 01000h
		jne	Auto_Flash_exit
ifdef NT_FLASH						;R04
		call	far ptr Ct_Enable_Flash		;can not disable F000 shadow;R04
endif; NT_FLASH						;R04
		call	Set_Auto_Flash_Address

		mov	al,Func_Delay		;get delay offset
		call	Get_SubFunction_Offset	;return offset
		mov	dx,ax

		mov	ax,Func_Write_point	;Flash Write
		call	SMI_Sub_Function

ifdef NT_FLASH						;R04
		call	Ct_Disable_Flash		;R04
endif; NT_FLASH						;R04
Auto_Flash_exit:
		popad
		ret

Auto_Flash_Handler	ENDP
;[]=============================================[]
;	   Set Auto Flash Address
;Input    :	None
;Output   :	None
;Note	  :
;[]=============================================[]
Set_Auto_Flash_Address:
		call	Load_Register
		mov	cx,4096
		and	di,0f000h	;start address at FFFxx000h
		push	cs		;set source
		pop	ds
		xor	ax,ax
		mov	es,ax		;High address (4G mapping address)
		mov	gs,ax		;High address 
		call	Get_SMBASE_Buffer
		movzx	esi,ax
		ret
;[]=============================================[]
;[]=============================================[]
Move_Data	Proc	near
		push	bp			;R05
		mov	bp,cs:[_CpuBrandOffset]	;R05
		mov	eax,cs:[SMRAM_EBX]
		db 66h
		stosd
		mov	eax,cs:[SMRAM_ECX]
		db 66h
		stosd
		mov	eax,cs:[SMRAM_EDX]
;R05		mov	ax,cs:[SMRAM_EAX+2]
		mov	ebx,cs:[SMRAM_EAX+2]	;R05
		mov	ax,bx			;R05
		db 66h
		stosd
		mov	eax,cs:[SMRAM_ESI]
		db 66h				;data is 32 bits
		stosd				;address is 16 bits
		pop	bp			;R05
		ret
Move_Data	endp
;[]========================================================================[]
;Procedure:	BIOS_Information_Handler
;Function :
;Input    :	SMI_Type = 2E
;		AH = sunfuncation
;Output   :	CF = 0 successful
;		CF = 1 fail
;		EAX,ECX,EDX,EBX
;Registers:
;Note	  :
;[]========================================================================[]
BIOS_Information_Handler	proc	near
Reallocate	BIOS_Information_offset
;R05		movzx	ax,byte ptr cs:[SMRAM_AH]
		mov	bp,cs:[_CpuBrandOffset]		;R05
		mov	ebx,cs:[SMRAM_EAX]		;R05
		movzx	ax,bh				;R05
		add	ax, Before_Subfunc_Number
		call	SMI_Sub_Function
		ret
;[]==================================[]
;	SubFunction 0
;Input    :	ah = 0 Get Support SMI MAX Subfunc
;Output   :	AL = Max_Subfunc
;[]==================================[]
SubFunc0:
Reallocate SubFunc_0_Offset
		xor	eax,eax
		mov	al,MAX_SMI_SubFunc
		mov	cs:[SMRAM_EAX],eax
		clc
		ret
;[]==================================[]
;	SubFunction 1
;Input    :	ah = 0 Get BIOS size
;Output   :	AL = Return Bios size
;[]==================================[]
SubFunc1:	 			;Return_BIOS_Size
Reallocate SubFunc_1_Offset
	BIOS_Size	=	1
ifdef Flash_2M_support
	BIOS_Size	=	2
endif; Flash_2M_support
ifdef Flash_4M_support
	BIOS_Size	=	4
endif; Flash_4M_support
		xor	eax,eax
		mov	al,BIOS_Size
BIOS_Inf_Exit:
		clc	
		mov	cs:[SMRAM_EAX],eax
		ret

BIOS_Information_Handler	endp
;R04 - end
;R01 - end
;[]=============================================[]
;	   Clear Counter Index
;Input    :	None
;Output   :	None
;Note	  :
;[]=============================================[]
Clear_Counter_Index:
		mov	ax,Func_Buffer_offset
		call	Get_SubFunction_Offset		;buffer offset
		mov	si,ax
		xor	ax,ax
		mov	cs:[si+256],ax			;clear counter for next
		ret
;[]=============================================[]
;	   Clear Counter Index
;Input    :	None
;Output   :	None
;Note	  :
;[]=============================================[]
	public		EEPROM_Wait_10ms
EEPROM_Wait_10ms	proc	near
Reallocate      SMI_EEPROM_Delay_offset
		push	bx
		push	cx
		xor	bx, bx

		push	ax			; save ax.

		ALIGN	4
EEPROM_WR_OUTER_LP:
EEPROM_WR_INNER_LP:
EEPROM_WR_STATE_0:	IN	al,61H
		test	al,010H
		jz	SHORT EEPROM_WR_STATE_0

		ALIGN	4
EEPROM_WR_STATE_1:	in	al,61H
		test	al,010H
		jnz	SHORT EEPROM_WR_STATE_1
		loop	SHORT EEPROM_WR_INNER_LP

		or	bx,bx
		jz	SHORT EEPROM_WR_EXIT
		dec	bx
		jmp	SHORT EEPROM_WR_OUTER_LP

EEPROM_WR_EXIT:	pop	AX			; restore ax

		pop	cx
		pop	bx
		ret
EEPROM_Wait_10ms	endp

;[]=============================================[]
;	Flash  Erase/Write interface buffer
;
;[]=============================================[]
		Public	SMI_FLASH_ENTRY_POINT
SMI_FLASH_ENTRY_POINT	label	near
Reallocate	SMI_FLASH_ENTRY_POINT_offset
 		include	ROMLEN.INC
ifdef	Flash_2M_support
 		DB	_2M_EEPROM_LEN DUP (0)
else;	Flash_2M_support
 		DB	_1M_EEPROM_LEN DUP (0)
endif;	Flash_2M_support
;[]=============================================[]
;	Flash  Erase/Write interface buffer
;
;reservation 256 bytes + 15 bytes for Flash Read/Write Buffer
;  	DB 	(256 + 15) dup(0)
;[]=============================================[]

		ALIGN	16
SMI_FLASH_Buffer:
Reallocate	Flash_Buffer_offset
		db	256	dup(0)
Transfer_Counter:
Reallocate	Transfer_Counter_offset
		dw	0

Public 	SMI_FLASH_WRITE_ENTRY_POINT

		ALIGN	4
	public 	Flash_FUNC_TBL
Flash_FUNC_TBL:
Reallocate      Flash_FUNC_TBL_offset
		DW	Flash_Read_offset		;00
		DW	Erase_Flash_offset		;01
		DW	Reg_To_Buffer_offset		;02
		DW	Flash_Write_offset		;03
		DW	PartErase_Flash_offset		;R01
		DW	0				;R04
		DW	BIOS_Information_offset	    	;R04
		DW	Auto_Flash_offset		;R04
		DW	SMI_FLASH_ENTRY_POINT_offset
SMI_FLASH_WRITE_ENTRY_POINT:				  
		DW	SMI_FLASH_ENTRY_POINT_offset
SMI_EEPROM_Delay_Entry:
		DW	SMI_EEPROM_Delay_offset	
		DW	Flash_Buffer_offset
		DW	Transfer_Counter_offset
		DW	Flash_SMBASE_Buffer_offset	;R01
;R04 - start
Before_Subfunc_Number	EQU ($-Flash_FUNC_TBL)/2
SMI_Sub_Func_Start:
		DW	SubFunc_0_Offset
		DW	SubFunc_1_Offset
MAX_SMI_SubFunc		EQU ($ - SMI_Sub_Func_Start)/2
;R04 - end
	Public	NO_OF_Flash_CALL
;R04 NO_OF_Flash_CALL  EQU ($-Flash_FUNC_TBL)/2-1
NO_OF_Flash_CALL  EQU ($-Flash_FUNC_TBL)/2		;R04

SMBASE_Buffer:						;R01
Reallocate	Flash_SMBASE_Buffer_offset		;R01
	Public SMI_FLASH_END
SMI_FLASH_END:
	Public Flash_Handler_Len
;R03 Flash_Handler_Len	equ	( SMI_FLASH_End - SMI_FLASH_START )
Flash_Handler_Len	equ	( SMI_FLASH_End - SMI_FLASH_START + 024ffh) ;R03

endif	;Flash_IN_SMBASE

XCODE		ENDS

		END
