;	[]===========================================================[]
;
;	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
;----------------------------------------------------------------------------
;R13	04/30/99 RIC	Add "No_EDO_Support" definition.
;R12	04/06/99 RIC	Add "VCM_Support" definition for Virtual Channel SDRAM.
;R10A	03/19/99 RIC	Fixed that AT Power hang in C0h in 686A chip.
;R11	03/18/99 RIC	Support the SMBus of 596B chip.
;R10	02/26/99 RIC	Fix taht 686A RTC Timer is dead in BIOS SETUP when RTC
;			was cleared.
;R08A	02/11/99 RIC	Fix that Onchip CMOS of new VT686A is unstable in
;			PowerOn.
;R09	02/05/99 RIC	Control selection GPO1/2 or SUSA#/B# for new 686A.
;R08 	02/05/99 RIC	Protect RTC 0Dh write for new 686A chip and remove
;			R06 code(no use code in new 686A chip).
;R06A	01/12/99 RIC	Fix that Onchip CMOS of VT596A is unstable in PowerOn.
;R07	01/21/99 RIC	Fix that system sometimes hang/reset or not WakeUp
;			in S1 in VT686A chip.
;R06	01/12/99 RIC	Fix that Onchip CMOS of VT686A is unstable in PowerOn.
;R05	01/04/99 ADS	Add "Chassis_Intrasion_ITEM" define for customer request. 
;R04	11/26/98 RIC	Modify the Throttling Reg to 24bit from 32bit
;			for HCT test fail in Throttling Duty Cycle
;R03	11/09/98 RIC	Fix that Trend Anti-Virus replace F0000-F4800 area.
;			So move Get_Set_Ct_OR, Get_Set_Ct_AND from chippost
;R02	10/28/98 RIC	Support SMBus of new SouthBridge VT686 chip.
;R01	08/18/98 RIC	Always Disable 61h Port to ISA Bus
;			and add "Have_61h_Port_Decode" define.
;R00	08/05/98 RIC	Initialization.

.386p
		PAGE    56,132
		TITLE   CHIPSET  -- 586 ISA/PCI ROM/BIOS

		INCLUDE BIOS.CFG
		INCLUDE POST.EQU
		INCLUDE COMMON.MAC
		INCLUDE POST.MAC
		INCLUDE CPU.EQU
		INCLUDE CT_TABLE.EQU
		INCLUDE BTROMSEG.EQU
		INCLUDE CHIPSET.EQU

ifndef  compress_code
		extrn   Move_Codes:near
endif   ;compress_code

G_RAM           SEGMENT USE16 AT 0

		ORG     04H*4
		INCLUDE SEG_0.INC

		ORG     400H
		INCLUDE G_RAM.INC

G_RAM           ENDS


ifdef   COMPRESS_CODE
		INCLUDE 8259.equ
		INCLUDE 8254.equ
		INCLUDE 8237.equ
		INCLUDE mathcop.equ
		INCLUDE PORT61.EQU

DGROUP          GROUP   @DATAC
@DATAC          SEGMENT USE16 DWORD COMMON 'DATAC'
		ASSUME  CS:DGROUP,DS:DGROUP
		org     1600h
else    ;COMPRESS_CODE
DGROUP          GROUP   FCODE
FCODE           SEGMENT USE16 PARA PUBLIC 'CODE'
		ASSUME  CS:DGROUP,DS:DGROUP
endif   ;COMPRESS_CODE

;[]===========================================================[]
;
; Procedure Name: Ct_Very_Early_Init
;       This routine is used to program the system to a known state.
;
;
; Saves: SP,BP , no stack available
;
; Input: None
;Output: None
;
; [Note]:  User must do following jobs
;       1. Save warm boot flag if no PCI Reset support
;       2. Disable cache & shadows
;       3. Initial some special registers if needed
;[]===========================================================[]

		ALIGN	4
		public  Ct_Very_Early_Init
Ct_very_Early_Init      proc    near

		shl     esp,16			; Save SP

	;---------------------------------------;
       	;   Init Registers by Follow Table	;
	;---------------------------------------;
		mov     si,offset DGROUP:Early_Init_Tbl
        @@:
		mov     cx,word ptr cs:[si]
		Rom_Call Get_Ct
		and     al,cs:[si+2]
		or      al,cs:[si+3]
		Rom_Call Set_Ct
		add     si,4
		cmp     si,offset DGROUP:Early_Init_Tbl_End
		jne     short @B

	;-----------------------;
	; Clear PCI IRQ Triger	;
	;-----------------------;
		mov     dx, 4d0h		; Clear PCI IRQ Level/Edge
		xor     al, al			;
		out     dx, al			;
		inc     dl			;
		out     dx, al			;

ifndef	VT686					;R11 - starts
  IFDEF	SMBus_Port
		;---------------------------------------;
		; Porgram SMBus_Port for 596/596A/596B	;
		;---------------------------------------;
		mov	cx, VT596 + 08h
		Rom_Call	Get_Ct
		cmp	al, 10h			; if 596B(Reversion ID >= 10h)
		jb	short Not_596B		; No, jmp !
		
		mov	cx, VT586_ACPI + 90h		;596B
		mov	al, (SMBus_Port AND 0FFh)	;596B
		Rom_Call Set_Ct				;596B
		mov	cx, VT586_ACPI + 91h		;596B
		mov	al, (SMBus_Port shr 8)		;596B
		Rom_Call Set_Ct				;596B
		mov	cx, VT586_ACPI + 0D2h		;596B
		mov	al, 001h			;596B
		Rom_Call Set_Ct				;596B
		jmp	short SMbus_Prog_End
	Not_596B:
		mov	cx, VT586_ACPI + 80h		;596/596A
		mov	al, (SMBus_Port AND 0FFh)	;596/596A
		Rom_Call Set_Ct				;596/596A
		mov	cx, VT586_ACPI + 81h		;596/596A
		mov	al, (SMBus_Port shr 8)		;596/596A
		Rom_Call Set_Ct				;596/596A
		mov	cx, VT586_ACPI + 84h		;596/596A
		mov	al, 007h			;596/596A
		Rom_Call Set_Ct				;596/596A
	SMbus_Prog_End:
  ENDIF;SMBus_Port
endif;	VT686					;R11 - ends
	;-------------------------------;
	;  If do RTC/CMOS Protection ?	;
	;-------------------------------;
IFNDEF	VT686					;R10
ifndef	NO_ATX_Judgement
    IFNDEF	AT_ATX_Power_Judgement_Jumpless
      ifndef	Always_ATX_Power
		;***************************************;
		;  ATX => CMOS Protect, AT => Skip	;
		;***************************************;
	  if	Power_Type_Judge_In_GPI_7_0	NE	00h
		mov	dx, ACPI_Port + 48h
		in	al, dx
		test	al, Power_Type_Judge_In_GPI_7_0
	  endif;Power_Type_Judge_In_GPI_7_0	NE	00h
	  if	Power_Type_Judge_In_GPI_15_8	NE	00h
		mov	dx, ACPI_Port + 49h
		in	al, dx
		test	al, Power_Type_Judge_In_GPI_15_8
	  endif;Power_Type_Judge_In_GPI_15_8	NE	00h
	  if	Power_Type_Judge_In_GPI_21_16	NE	00h
		mov	dx, ACPI_Port + 4Ah
		in	al, dx
		test	al, Power_Type_Judge_In_GPI_21_16
	  endif;Power_Type_Judge_In_GPI_21_16	NE	00h

	  ifdef	ATX_High_AT_Low_In_GPI		; If ATX power ?
		jz	short @F		; No,jmp!
	  endif;	ATX_High_AT_Low_In_GPI		; (1:ATX, 0:AT)
	  ifdef	ATX_Low_AT_High_In_GPI		; If ATX power ?
		jnz	short @F		; No,jmp!
	  endif;	ATX_Low_AT_High_In_GPI		; (0:ATX, 1:AT)
	  ifndef	ATX_High_AT_Low_In_GPI
	  ifndef	ATX_Low_AT_High_In_GPI
		mov	dx, ACPI_Port + 05h	; Doing a Sequence let
		mov	al, 040h		; AT Power to work properly
		out	dx, al			; in CMOS Protection Mode.
		mov	al, 0C0h		;
		out	dx, al			;
		mov	al, 080h		;
		out	dx, al			;
	  endif;	ATX_Low_AT_High_In_GPI
	  endif;	ATX_High_AT_Low_In_GPI
      endif;	Always_ATX_Power

    ELSE;	AT_ATX_Power_Judgement_Jumpless
		mov	dx,ACPI_Port + 01h	;
		in	al,dx	       		;
		test	al,80h			; Is ATX power ?
		jz	short @f		; No,jump
    ENDIF;	AT_ATX_Power_Judgement_Jumpless

		;*******************************;
		;   Set RTC/CMOS Protection	;
		;*******************************;
		mov	cx, VT586_ACPI + 41h	
		rom_call	Get_Ct		; Protect RTC/CMOS
		or	al, 04h			;
		rom_call	Set_Ct		;
    IFNDEF	AT_ATX_Power_Judgement_Jumpless	;
      ifndef	Always_ATX_Power
	  ifndef	ATX_High_AT_Low_In_GPI
	  ifndef	ATX_Low_AT_High_In_GPI
		mov	dx, ACPI_Port + 05h	
		mov	al, 000h
		out	dx, al			
	  endif;	ATX_Low_AT_High_In_GPI
	  endif;	ATX_High_AT_Low_In_GPI
      endif;	Always_ATX_Power
    ENDIF;	AT_ATX_Power_Judgement_Jumpless	;
@@:
      IFDEF	Detect_ATX_Power_By_CMOS_Bank2
		mov	al, 90h			;
		out	72h, al			;
		mov	al, 55h			;
		out	73h, al			;
		mov	al, 90h			;
		out	72h, al			;
		in	al, 73h			;
		cmp	al, 55h			; Is ATX power ?
		je	short Not_AT_Power	; Yes,jump
		mov	cx, VT586_ACPI + 41h	
		rom_call	Get_Ct		; Disable Protect RTC/CMOS
		and	al,not 04h		;
		rom_call	Set_Ct		;
	Not_AT_Power:
      ENDIF;	Detect_ATX_Power_By_CMOS_Bank2
endif;	NO_ATX_Judgement
ENDIF;	VT686					;R10

;R10A - starts
IFDEF	VT686
ifndef	NO_ATX_Judgement
    IFNDEF	AT_ATX_Power_Judgement_Jumpless
      ifndef	Always_ATX_Power
		;***************************************;
		;  ATX => CMOS Protect, AT => Skip	;
		;***************************************;
	  if	Power_Type_Judge_In_GPI_7_0	NE	00h
		mov	dx, ACPI_Port + 48h
		in	al, dx
		test	al, Power_Type_Judge_In_GPI_7_0
	  endif;Power_Type_Judge_In_GPI_7_0	NE	00h
	  if	Power_Type_Judge_In_GPI_15_8	NE	00h
		mov	dx, ACPI_Port + 49h
		in	al, dx
		test	al, Power_Type_Judge_In_GPI_15_8
	  endif;Power_Type_Judge_In_GPI_15_8	NE	00h
	  if	Power_Type_Judge_In_GPI_21_16	NE	00h
		mov	dx, ACPI_Port + 4Ah
		in	al, dx
		test	al, Power_Type_Judge_In_GPI_21_16
	  endif;Power_Type_Judge_In_GPI_21_16	NE	00h

	  ifdef	ATX_High_AT_Low_In_GPI		; If ATX power ?
		jnz	short Is_ATX_Power	; Yes,jmp!
		mov	al, 0dh			; Set CMOS 0D[7] to 1
		out	70h, al			;
		in	al, 71h			;
		and	al,not 80h		;
		out	71h, al			;
		jmp	short Is_AT_Power	;
	Is_ATX_Power:				;
	  endif;	ATX_High_AT_Low_In_GPI		; (1:ATX, 0:AT)
	  ifdef	ATX_Low_AT_High_In_GPI		; If ATX power ?
		jnz	short Is_ATX_Power	; Yes,jmp!
		mov	al, 0dh			; Set CMOS 0D[7] to 1
		out	70h, al			;
		in	al, 71h			;
		and	al,not 80h		;
		out	71h, al			;
		jmp	short Is_AT_Power	;
	Is_ATX_Power:				;
	  endif;	ATX_Low_AT_High_In_GPI		; (0:ATX, 1:AT)
      endif;	Always_ATX_Power
    ENDIF;	AT_ATX_Power_Judgement_Jumpless
endif;	NO_ATX_Judgement
ENDIF;	VT686
;R10A - ends

;R05 - start
ifdef	Have_Chassis_Intrasion_Item
		mov	al, Chassis_Intr_CMOS
		out	70h, al
		in	al, 71h
		test	al, Chassis_Intr_CMOS_Bit
		jz	short no_chassis_intrasion

		mov	cx, VT596 + 59h 
		rom_call   Get_Ct 
		or	al, 04h	  
		rom_call   Set_Ct 
no_chassis_intrasion:
endif;	Have_Chassis_Intrasion_Item
;R05 - end
;R08 ;R06 - starts
;R08 ifdef	VT686
;R08 	SetCMOS_0Ah:
;R08 		mov al,0ah			; Set CMOS 0A[7] to 1
;R08 		out 70h,al			;
;R08 		in al,71h			;
;R08 		or al,80h			;
;R08 		out 71h,al			;
;R08 
;R08 		mov	cx, VT586_ACPI + 42h	; 42h[4]
;R08 		rom_call	Get_Ct		; Get CMOS 0A[7] status
;R08 		test	al, 10h			;
;R08 		jz short SetCMOS_0Ah
;R08 endif;	VT686
;R08 ;R06 - ends
;R08A - starts
ifdef	VT686
	SetCMOS_0Dh:
		mov	al, 0dh			; Set CMOS 0D[7] to 1
		out	70h, al			;
		in	al, 71h			;
		or	al, 80h			;
		out	71h, al			;

		mov	cx, VT586_ACPI + 42h	; 42h[4]
		rom_call Get_Ct			; Get CMOS 0D[7] status
		test	al, 10h			;
		jz	short SetCMOS_0Dh
endif;	VT686
;R08A - ends
;R06A - starts
ifdef	VT596A
		mov	cx,2000h
	SetCMOS_0Ah:
		mov al,0ah			; Set CMOS 0A[7] to 1
		out 70h,al			;
		in al,71h			;
		or al,80h			;
		out 71h,al			;

		loop short SetCMOS_0Ah
endif;	VT596A
;R06A - ends
Is_AT_Power:					;R10A

		shr     esp,16			; Restore SP

		ret
Ct_very_Early_Init      endp

		ALIGN   4
Early_Init_Tbl:
	;-------------------------------;
	;      index    AND  OR		;
	;-------------------------------;
	dw VT586+047h			; [7]: Dis/*En Use INIT as CPU Reset
	db	  0BFh,0A0h	        ; [6]: *Dis/En Delay Transaction
					; [5]: Dis/*En 4D0/4D1 Port
	dw VT586 + 040h
	db		0FDH,000h       ; Set ROM *1 / 0 Wait State

	dw VT692 + 050h			; [4]: Dis/*En Defer Retry When HLOCK Active
	db              0FFH,010h       ;

	dw VT692 + 051h			; [5]: DRAM Read Request Rate *3T/2T
	db              0DDH,000Dh	; [3]: TRDY special function
 					; [2]: 1/*4 Level CPU-DRAM Prefetche Buffer
 					; [1]: *1/4 Level CPU-DRAM PostWrite Buffer
					; [0]: Dis/*En Concurrect PCI Master/Host Operation

	dw VT692 + 052h			; [4-0]: Set Snoop Stall Count
	db              0E0H,08h       	;	 to 01000b

;R11	dw VT692 + 061h
;R11	db		000H,000h       ; Disable C shadow
;R11
;R11	dw VT692 + 062h
;R11	db		000H,000h       ; Disable D shadow
;R11
;R11	dw VT692 + 063h			; [7-4]: *Dis/En E & F shadow
;R11	db		000H,000h       ; [3-2]: *Dis/En Memory Hole
					; [1-0]: *Dis/En SMRAM

	dw VT692 + 06Ah			; [7-0]: Refresh counter
ifdef	VCM_Support			;R12 - starts
	db		000H,000        ; Disable Refresh
else;	VCM_Support			;R12 - ends
	ifdef	No_EDO_Support		;R13 - starts
	db		000H,000        ; (67-1)h * 16 + 32 CPUCLK
	else;	No_EDO_Support		;R13 - ends
	db		000H,067        ; (67-1)h * 16 + 32 CPUCLK
	endif;	No_EDO_Support		;R13
endif;	VCM_Support			;R12

	dw VT692 + 06Bh
	db              000H,001h       ; [0]: Dis/*En Multi-page

	dw VT692 + 06Ch			; [7]: *En/Dis Fast DRAM write pipeline
	db              07fH,000h       ;

	dw VT692 + 071h			; [3]: Dis/*En PCI Burst
	db		000H,008h       ;

	dw VT692 + 075h			; [7]: PCI Arbitration Mechanism
	db		000H,080h	; [6]: *REQ/Frame -based Arbitration Mode
					; [3-0]: Disable PCI Master Bus TimeOut

	dw VT692 + 076h			; [7]: Dis/*En PCI Retry Disconnect
	db		0CFH,080h       ; [5-4]: Disable PCI Master Grant

	dw VT586 + 041h
	db		0FFh,001h       ; [0]: Dis/*En ISA Refresh

	dw VT586 + 043h
	db		000H,030h       ; Set 128K ROM

	dw VT586 + 04Ah
ifdef	Disable_SD_Bus
	db		0BFh,000h       ; XD Bus
else;	Disable_SD_Bus
	db		0FFh,040h       ; SD Bus
endif;	Disable_SD_Bus

ifndef	Have_61h_Port_Decode		;R01 - starts
	dw VT586 + 05Ch
	db		000h,040h       ; En/*Disable 61 Port to XD Bus
endif;	Have_61h_Port_Decode		;R01 - ends

ifdef	ENABLE_SERIRQ			; [3]: Dis/*En VT596 serial IRQ
	dw VT596 + 068h			;
	db            	000H,008h 	;
endif;	ENABLE_SERIRQ			;

;R08Aifdef	VT686				;R08
;R08A	dw VT686 + 077h			;R08 Protect RTC 0Dh write
;R08A	db            	0FFH,002h 	;R08
;R08Aendif;	VT686				;R08
	;---------------------------------------;
	; Enable VIA chip Internal RTC/PS2/KBC	;
	;---------------------------------------;
	dw VT586 + 05Ah
	db		0F8h,RTC_PS2_KBC

	dw	VT586_ACPI + 48h		; Set ACPI IObase to Reg48h,49h
	db		(ACPI_Port AND 00FFh),(ACPI_Port AND 00FFh)
	dw	VT586_ACPI + 49h
	db		(ACPI_Port shr 8),(ACPI_Port shr 8)

	dw	VT586_ACPI + 41h		; [7]: Dis/*En ACPI IObase
;R04	db		0FFh,088h		; [3]: Set 32bit ACPI timer
	db		0FFh,080h		; [3]: Set 24bit ACPI timer ;R04

  ifdef	VT686					;R07 - start
	dw	VT586_ACPI + 54h		; [4]: Power Well Select =>
	db		0FFh,010h		;      SUSST1/*GPO3
  endif;VT686					;R07 - end

  ifdef	SMBus_Port
    IFDEF	VT686					;R02
	dw	VT586_ACPI + 90h			;R02
	db		0FFh,(SMBus_Port AND 0FFh)	;R02
	dw	VT586_ACPI + 91h			;R02
	db		0FFh,(SMBus_Port shr 8)		;R02
	dw	VT586_ACPI + 0D2h			;R02
	db		0FFh,001h			;R02
;R11    ELSE;	VT686					;R02
;R11	dw	VT586_ACPI + 80h
;R11	db		0FFh,(SMBus_Port AND 0FFh)
;R11	dw	VT586_ACPI + 81h
;R11	db		0FFh,(SMBus_Port shr 8)
;R11	dw	VT586_ACPI + 84h
;R11	db		0FFh,007h
    ENDIF;	VT686					;R02
  endif;SMBus_Port

	;---------------------------------------;
	;   Enable GPI0-GPI21 / GPO0-GPO30	;
	;---------------------------------------;
		;***********************;	;R09
		;   Enable GPO1/GPO2	;	;R09
		;***********************;	;R09
ifdef	VT686					;R09
  ifdef	USE_GPO1				;R09
	dw	VT586_ACPI + 054h		;R09	
	db		0FFh,004h		;R09	
  endif;USE_GPO1				;R09
  ifdef	USE_GPO2				;R09
	dw	VT586_ACPI + 054h		;R09	
	db		0FFh,008h		;R09	
  endif;USE_GPO2				;R09
endif;	VT686					;R09
		;***************************************;
		;   Enable GPI0/GPO[7-1]/GPI[12-8]	;
		;***************************************;
if	GPIO_Control_74_Val	NE	01h
	dw	VT586 + 74h			; Select GPIO / Chip
	db		GPIO_Control_74_Val,GPIO_Control_74_Val
endif;	GPIO_Control_74_Val	NE	01h
		;***********************;
		;   Enable GPO[23-15]	;
		;***********************;
if	GPO_Control_75_Val	NE	00h
	dw	VT586 + 75h			; Select GPIO / Chip
	db		GPO_Control_75_Val,GPO_Control_75_Val
endif;	GPO_Control_75_Val	NE	00h
		;***********************;
		;   Enable GPO[26-24]	;
		;***********************;
if	GPO_Control_76_Val	NE	00h
	dw	VT586 + 76h			; Select GPIO / Chip
	db		000h,GPO_Control_76_Val
endif;	GPO_Control_76_Val	NE	00h

Early_Init_Tbl_End:


;[]===========================================================[]
;
; Procedure Name: Pci_Early_Init
;       This routine is used to program the system to a known state.
;
; Saves: SP,BP , no stack available
;
; Input: None
;Output: None
;[]===========================================================[]

		public  Pci_Early_Init
Pci_Early_Init  proc    near
		ret
Pci_Early_Init  endp

ifdef   PM_SUPPORT

;[]========================================================================[]
;Procedure:     Ct_Sleep_Detect
;
;Function :     Tell BIOS kernal whether it is a resume process or not
;
;Input    :     None
;
;Output   :     NZ - resume from sleep/suspend
;		ZR - normal reset
;
;Note     :     1. called every time the CPU is reset/shutdown
;		2. Stack "NOT" available
;[]========================================================================[]
		Public  Ct_Sleep_Detect
Ct_Sleep_Detect Proc    Near
		xor     al,al
		ret
Ct_Sleep_Detect Endp
endif   ;PM_SUPPORT

ifndef	CompileForBootROM
		public  A20_Byte
A20_Byte        label   byte
		db      00010001b       ;bit0 = 0 - normal gate A20
					;       1 - fast 92 port support
					;bit 7 =0 - normal turning cache
					;       1 - early turning cache
					;bit 6 =0 - normal CPU clock detect
					;       1 - special CPU clock detect
					;bit 5 =0 - normal refresh wait
					;       1 - using CPU loop wait if
					;           BIOS shadow is disabled
					;bit 4 =1 - Don't set CPU cache on/off
					;           If system is in protected
					;           mode

ifdef ACPI_SUPPORT
;[]========================================================================[]
;RestoreContext
; Entry: AL=Sleep Type 
; Exit:  NONE
; Destroy : 
;[]========================================================================[]
		public	RestoreContext
RestoreContext	Proc	Near
		ret
RestoreContext	Endp
;[]========================================================================[]
;
; Entry:Nothing 
; Exit: DS=Segment of waking vector
;	SI=Offset of waking vector
; Destroy : AX,DX
;[]========================================================================[]
		public	GetWakingVector
GetWakingVector	Proc	Near
		ret
GetWakingVector	Endp
endif	;ACPI_SUPPORT
endif;	CompileForBootROM

CONFIG_ADDR     equ     0CF8h
;---------------------------------------------------------------
; Get_Ct(Get_PCI):
;       Reads a value directly from the chipset register.
;
; Input  :      CX = Index register to read
; Output :      AL = Value read
; Destory:      EAX, DX
;---------------------------------------------------------------
		public  Get_Ct, Get_PCI, Get_PMU
Get_Ct          proc    near
Get_PCI:
Get_PMU:
		mov     ax, 8000h		;enable PCI config.
		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
		mov     dl, 0FCh		;start from 0CFCh
		mov     al, cl
		and     al, 03h
		add     dl, al			;byte index to read
		in      al, dx
		ret
Get_Ct          endp

;---------------------------------------------------------------
; Set_Ct(Set_PCI):
;       Changes a value in the chipset register.
; Input  :      CX = Index register to change
;		AL = Value to change
; Output :      None
; Destory:      EAX, ECX, DX
;
;---------------------------------------------------------------
		public  Set_Ct,Set_PCI,Set_PMU
Set_Ct          proc    near
Set_PCI:
Set_PMU:
		xchg    ax, cx
		shl     ecx, 16          ;save write value
		xchg    ax, cx           ;restore cx
		mov     ax, 8000h        ;enable PCI config.
		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
		mov     dl, 0FCh	 ;start from 0CFCh
		mov     al, cl
		and     al, 03h
		add     dl, al           ;byte index to read
		shr     ecx, 16          ;restore value
		mov     ax, cx
		out     dx, al
		ret

Set_Ct          endp

;---------------------------------------------------------------
; Get_Set_Ct:
;       Read one chipset register value and set it back.
; Input  :      CX = register index
;		BL = value to AND
;		BH = value to OR
; Output :      None
; Destroy:      EAX, ECX, DX
;---------------------------------------------------------------
		public  Get_Set_Ct
		public  Get_Set_PMU
Get_Set_Ct      proc    near
Get_Set_PMU:

		call    Get_Ct
		and     al, bl			;AND data
		or      al, bh			;OR data
		call    Set_Ct
		ret

Get_Set_Ct      endp

ifndef	CompileForBootROM
;R03 - starts
;[]==============================================================[]
; Get_Set_Ct_OR(Get_Set_PCI_OR):
;	OR a value in the chipset register.
; Input  :	CX = Index register to change
;		bl = Value to change (OR)
; Output :	None
; Destory:	EAX, ECX, DX
;
;[]==============================================================[]
		Public	Get_Set_Ct_OR, Get_Set_PMU_OR
Get_Set_Ct_OR	proc	near
Get_Set_PMU_OR:
		call    Get_Ct
		or      al, bl			;OR data
		call    Set_Ct
		ret
Get_Set_Ct_OR	endp

;[]==============================================================[]
; Get_Set_Ct_AND(Get_Set_PCI_AND):
;	AND a value in the chipset register.
; Input  :	CX = Index register to change.
;		bl = Value to change (AND)
; Output :	None
; Destory:	EAX, ECX, DX
;
;[]==============================================================[]
		Public	Get_Set_Ct_AND, Get_Set_PMU_AND
Get_Set_Ct_AND	proc	near
Get_Set_PMU_AND:
		call    Get_Ct
		and     al, bl			;AND data
		call    Set_Ct
		ret
Get_Set_Ct_AND	endp
;R03 - end

;input: CX -- index port
                public  Get_PMIO
Get_PMIO     proc    near
		push	dx
		mov	eax, 80000000h + VT586_ACPI + 48h
		mov	dx, 0cf8h
		out	dx, eax
		mov	dl, 0fch
		in	ax, dx
		mov	dx, ax
		and	dx, NOT 03h
		add	dl, cl
		in	al, dx
		pop	dx
                ret
Get_PMIO      endp

;input  AL -- value
;input: CX -- index port
                public  Set_PMIO
Set_PMIO     proc    near
		pusha
		mov	bl, al
		mov	eax, 80000000h + VT586_ACPI + 48h
		mov	dx, 0cf8h
		out	dx, eax
		mov	dl, 0fch
		in	ax, dx
		mov	dx, ax
		and	dx, NOT 03h
		add	dl, cl
		mov	al, bl
		out	dx, al
		popa
                ret
Set_PMIO      endp


;[]==============================================================[]
;CT_SPEED:
;       Programming speed switchwing for particular hardware design.
;Saves: ALL but flags
;Input:
;    b0 of al = 0 : to low speed
;             = 1 : to high speed
;Output:none
;
;[Notes] 1. Program chipset registers for speed change
;        2. This function can be disabled by MODBIN
;[]==============================================================[]
		align 4
		public  Ct_Speed
Ct_Speed        proc    near

ifndef	NO_SPEED_ITEM
		pusha
	;-----------------------------------------------;
	;   Control Turbo LED by GPO (Low => TurnOn)	; For 596 Chipset
	;-----------------------------------------------;
    ifdef	Turbo_LED_Control_By_GPO_Low
		pushad

		mov	bh,al			; AL bit0 : 0 => Low Speed
						; AL bit0 : 1 => High Speed
                and	bh,01h
		xor	bh,01h			; BH bit0 : 1 => Low Speed
						; BH bit0 : 0 => High Speed

	if	Turbo_LED_Control_By_GPO_Low	LE	7
		shl	bh,Turbo_LED_Control_By_GPO_Low
		mov	cl, 4Ch			;
		call	Get_PMIO		;
		and	al,not (01h shl Turbo_LED_Control_By_GPO_Low)	
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; Low (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	endif;	Turbo_LED_Control_By_GPO_Low	LE	7

	if	Turbo_LED_Control_By_GPO_Low	LE	15
	  if	Turbo_LED_Control_By_GPO_Low	GE	8
		shl	bh,(Turbo_LED_Control_By_GPO_Low-8)
		mov	cl, 4Dh			;
		call	Get_PMIO		;
		and	al,not (01h shl (Turbo_LED_Control_By_GPO_Low-8))	
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; Low (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	  endif;Turbo_LED_Control_By_GPO_Low	GE	8
	endif;	Turbo_LED_Control_By_GPO_Low	LE	15

	if	Turbo_LED_Control_By_GPO_Low	LE	23
	  if	Turbo_LED_Control_By_GPO_Low	GE	16
		shl	bh,(Turbo_LED_Control_By_GPO_Low-16)
		mov	cl, 4Eh			;
		call	Get_PMIO		;
		and	al,not (01h shl (Turbo_LED_Control_By_GPO_Low-16))
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; Low (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	  endif;Turbo_LED_Control_By_GPO_Low	GE	16
	endif;	Turbo_LED_Control_By_GPO_Low	LE	23

	if	Turbo_LED_Control_By_GPO_Low	LE	30
	  if	Turbo_LED_Control_By_GPO_Low	GE	24
		shl	bh,(Turbo_LED_Control_By_GPO_Low-24)
		mov	cl, 4Fh			;
		call	Get_PMIO		;
		and	al,not (01h shl (Turbo_LED_Control_By_GPO_Low-24))
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; Low (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	  endif;Turbo_LED_Control_By_GPO_Low	GE	24
	endif;	Turbo_LED_Control_By_GPO_Low	LE	30

		popad
    endif;	Turbo_LED_Control_By_GPO_Low

	;-----------------------------------------------;
	;   Control Turbo LED by GPO (High => TurnOn)	; For 596 Chipset
	;-----------------------------------------------;
    ifdef	Turbo_LED_Control_By_GPO_High
		pushad

		mov	bh,al			; AL bit0 : 0 => Low Speed
						; AL bit0 : 1 => High Speed
		and	bh,01h			; BH bit0 : 0 => Low Speed
						; BH bit0 : 1 => High Speed

	if	Turbo_LED_Control_By_GPO_High	LE	7
		shl	bh,Turbo_LED_Control_By_GPO_High
		mov	cl, 4Ch			;
		call	Get_PMIO		;
		and	al,not (01h shl Turbo_LED_Control_By_GPO_High)	
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; Low (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	endif;	Turbo_LED_Control_By_GPO_High	LE	7

	if	Turbo_LED_Control_By_GPO_High	LE	15
	  if	Turbo_LED_Control_By_GPO_High	GE	8
		shl	bh,(Turbo_LED_Control_By_GPO_High-8)
		mov	cl, 4Dh			;
		call	Get_PMIO		;
		and	al,not (01h shl (Turbo_LED_Control_By_GPO_High-8))	
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; High (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	  endif;Turbo_LED_Control_By_GPO_High	GE	8
	endif;	Turbo_LED_Control_By_GPO_High	LE	15

	if	Turbo_LED_Control_By_GPO_High	LE	23
	  if	Turbo_LED_Control_By_GPO_High	GE	16
		shl	bh,(Turbo_LED_Control_By_GPO_High-16)
		mov	cl, 4Eh			;
		call	Get_PMIO		;
		and	al,not (01h shl (Turbo_LED_Control_By_GPO_High-16))
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; High (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	  endif;Turbo_LED_Control_By_GPO_High	GE	16
	endif;	Turbo_LED_Control_By_GPO_High	LE	23

	if	Turbo_LED_Control_By_GPO_High	LE	30
	  if	Turbo_LED_Control_By_GPO_High	GE	24
		shl	bh,(Turbo_LED_Control_By_GPO_High-24)
		mov	cl, 4Fh			;
		call	Get_PMIO		;
		and	al,not (01h shl (Turbo_LED_Control_By_GPO_High-24))
		or	al,bh			; Assign GPIO? to :
		call	Set_PMIO		; High (Input AL bit0 = 1)
						; High(Input AL bit0 = 0)
	  endif;Turbo_LED_Control_By_GPO_High	GE	24
	endif;	Turbo_LED_Control_By_GPO_High	LE	30

		popad
    endif;	Turbo_LED_Control_By_GPO_High

	;-----------------------------------------------;
	;  Turbo Speed Function by Chipset Throttling	;
	;-----------------------------------------------;
  IFNDEF	Turbo_SW_NOT_Control_By_Chipset
                test    al,1                    ;turbo pin close
                jz      short Yes_Low		;
                mov	cl, 10h			;
		mov	al, 10h			;
		call	Set_PMIO		;
		mov	cx, 14h			;
		call	Get_PMIO		;
		jmp	short Ct_Speed_Ret	;
Yes_Low:					;
		mov	cl, 10h			;
		mov	al, 18h			;
		call	Set_PMIO		;
		mov	cl, 14h			;
		call	Get_PMIO		;
Ct_Speed_Ret:					;
  ENDIF;	Turbo_SW_NOT_Control_By_Chipset
		popa
endif;	NO_SPEED_ITEM
		ret
Ct_Speed        endp

;[]==============================================================[]
;CT_A20:
;       Chipset Fast Gate A20 support
;Saves: all but flags
;Input: AL - 0ddh : turn A20 off
;          - 0dfh : turn A20 on
;Output:carry clear - fast gate A20 ok
;       carry set   - fast gate A20 not support
;[Notes] 1. This function is used to turn on/off chipset's fast
;           gate A20 support.
;        2. If chipset did not support fast A20 , this routine
;           should return carry flag, otherwise clear carry.
;[]==============================================================[]
		public  Ct_A20
Ct_A20          proc    near
FAST_A20_ON       EQU   00000010B
FAST_A20_OFF      EQU   NOT FAST_A20_ON

		mov     ah, al			; save input
		in      al, 92H			; read A20 status
		NEWIODELAY
		and     al, NOT FAST_A20_ON     ; assume A20 off
		test    ah, 00000010b           ; is it a call to turn off?
		jz      short a20_1             ; yes, so go write value

		or      al, FAST_A20_ON         ; assume A20 on
a20_1:
		out     92H, al
		NEWIODELAY
		clc
		ret
Ct_A20          endp

;[]==============================================================[]
;Int8_Hook:
;       Special process for every time tick.
;Save  : all but flags
;Input : DS:G_RAM
;Output: none
;Note  : 1. This routine will be called after execute INT 1CH
;        2. You can use this routine to do some power management
;           or other special function
;[]==============================================================[]
		Public  Int8_Hook
Int8_Hook       Proc    Near
		ret
Int8_Hook       Endp
endif;	CompileForBootROM

ifndef	CompileForBootROM
;[]==============================================================[]
;Int15_4f_Hook:
;       Special process for every key stroke.
;Save  : all but flags
;Input : DS:G_RAM
;Output: none
;Note  : 1. This routine will be called after execute INT 15H
;           function 4fH
;        2. You can use this routine to check hotkey or other
;           power management.
;        3. You must reutrn carry if this routine do nothing or
;           this key-stroke is unuseful.
;[]==============================================================[]
		Public  Int15_4f_Hook
Int15_4f_Hook   Proc    Near
		stc
		ret
Int15_4f_Hook   Endp

endif;	CompileForBootROM

ifdef   COMPRESS_CODE
;[]===================================================================[]
;Move codes from source to destionation area
;Input : SI - source , DI - destination , CX - No. of words to move
;Output: none
;[]===================================================================[]
		public  Move_Codes
Move_Codes      proc    near
		mov     ds,si
		mov     es,di
		xor     si,si
		xor     di,di
		cld
		rep     movsw
		ret
Move_Codes      endp

IF2
        IF (($ - Ct_Very_Early_Init) GT (0f80bh-0f600h))
		%OUT ERROR, CHIPRUN.ASM code size too large
		.ERR
        ENDIF
ENDIF

@DATAC          ENDS
else    ;COMPRESS_CODE
FCODE           ENDS
endif   ;COMPRESS_CODE
		END


