;	[]===========================================================[]
;
;	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
;----------------------------------------------------------------------------
;R105A	04/20/99 TNY	Add IT8888F DMA channel programming followed by ITE.
;R105	04/16/99 TNY	Fix IT8888F (P2I bridge) MISA can not work.
;R82B	04/02/99 RCH	Fixed PCI/SCSI option ROM can not be initialized if
;			the VGA device number is 0CH and the SCSI device
;			number is 08H.
;
;R105	04/02/99 ATY	Fixed system hang up on Post Card "0B",Because PCIBus
;			must to clear in Base Addresses 5. 
;R102A	04/01/99 TNY	"PCI_IRQ_SELECTABLE" only set INTA-D to be selectable.
;R104	03/26/99 RCH	Fixed system hang up while AHA2940/SCSI and RTL8139
;			/LAN are plugged together on ALi chipset.
;			
;R103	03/26/99 TNY	Fix W83628F (P2I bridge) port 80h decode fail
;			problem.
;R102	03/25/99 RAY	Add slot5 to slot9 support for PCI_IRQ_SELECTABLE
;R101	03/22/99 RAY	Disable the IO resource assigned to P2P bridge if
;			no IO request is found behind this bridge.
;
;			This is added to solved the problem of Intel's
;			440BX & 440LX AGP bridge, which is not fully decoded,
;			will have problem installing NT4.0 with S3 PCI VGA
;
;			Note:
;			----
;			To disable a P2P bridge address, we simply use a
;			method of assigning a base IO address of 0F000h to
;			the bridge but with a limit of ZERO. 
;
;R100	03/18/99 RCH	Don't assign IRQ 9 for built-in audio controller to
;			Patch VIA/686 south bridge bug. System will hang up
;			while installing Win98 if the audio use IRQ 9.
;R64B	03/18/99 MCH	Added "ACPI_IRQ_Auto_Assign_Selectable" define with
;			"ACPI_IRQ_Selectable" to choose Auto/Manual assign IRQ.
;R92C	03/18/99 TNY	Fixed coding error.
;R99	03/16/99 RAY	NO "Check_M1_CPU" if it is not 586 BIOS
;R98	03/15/99 TNY	Set PCI Latency time to be 20h (not 40h) for fixing
;			some VGA card compability issue.
;R97	03/11/99 RCH	Added Intel/ICH0 IDE controller checking.
;R96	03/09/99 RCH	1. Added Boot from LAN devices with Bootstrap Entry
;			   Vector (BEV) boot ROM support.
;			2. Fixed BIOS can not boot from Intel/559 boot ROM
;			   if the PnP/BEV Boot is enabled.
;R91A	03/08/99 KVN	Fixed lan_command byte restore wrong data.That reason
;			is the lann_command byte be temp stored in XGROUP, but
;			Xgroup will be clear in POST_82S, so it always restore
;			zero.Now we put it to stack of POST
;R95	03/04/98 JSN	Fixed Mylex DAC960 RAID controller card cannot work
;			successfully while the PS/2 mouse is not plugging and
;			used flash 2M support.		
;R78A	03/04/99 KVN	Dont set IDE DMA capable status for all of IDE drive
;			that avoid ZIP read fail in NT with DMA driver (installed
;			service pack 4)
;R92B	03/03/99 TNY	Fixed R92 coding error.
;R85A	03/01/99 RIC	Fixed that VGA ROM added by CBROM can't be search in
;			follow case:
;			1. Add VGA ROM by using old CBROM.
;			2. VGA ID don't match with VGA ROM added by CBROM.
;			   (If VGA ID don't match with VGA ROM added by CBROM,
;			    BIOS will use first VGA ROM added by CBROM.)
;R92A	03/01/99 RCH	Fixed legacy USB not working after PCI ROM scanning
;			if the shadow unit is 64KB.
;R94	02/23/99 RCH	Fixed Avance Logic ALG2301 PCI VGA card failed with
;			ROM scanning. This card decode VGA ROM at address
;			0C0000H when command register is on even though the 
;			ROM decode enable bit in config. space 30H is off.
;R93A	02/22/99 RCH	Also mask IRQ 14 of 8259 for first IDE channel.
;R93	02/11/99 RCH	Added a switch to mask 8259 for IRQ 15 if on-chip
;			second IDE channel is disabled for PIIX platforms.
;R92	02/10/99 TNY	Fix VGA BIOS corrupted if ISA VGA plugged. 
;			(SHADOW_UNIT_64K)
;R91	01/10/99 RAY	Add BIOS.CFG swith: PciLanROM_Control. This switch
;			allows the user to decide whether to invoke the onboard
;			LAN chip's ROM or not
;
;R90	02/10/99 RAY	Support ISA VGA for chipset having shadow unit 
;			64K
;R82A	02/10/99 RIC	Fixed that some VGA card use C8000-CFFFF address on
;			over 32K VGA BIOS.(ex: RIVA TNT AGP card)
;			It will cause other PCI ROM to hang in POST 52h.
;			So assign 64K(Don't assign 48K) for over 32K VGA BIOS
;			using.
;R89	02/08/99 RCH	Added AMD-750 IDE controller checking for release IRQ 14
;			& IRQ 15 if controller is disabled. 
;
;R88	02/05/99 RCH 	Assign IRQ to PCI-TO-PCI bridge if requested.
;R87	01/27/99 RCH	Added STPC IDE controller checking for release IRQ 14
;			& IRQ 15 if controller is disabled. Also change
;			memory space address to F0000000H for PCI devices
;			due to no fully address decode.
;R68A	01/27/99 RAY	R68 Fix legacy-ISA's ROM shadowed fail which will 
;			cause all ISA PnP ROM space to be forced to shadowed.
;			This is reported by a IBM token ring card cannot work
;			properly.
;
;R86	01/21/99 MCH	Added "No_Assign_IRQ5_For_PCILAN" define to avoid
;			PCI LAN Card work in IRQ5 failure with some chipsets.
;R85	01/20/99 RCH	Check option header (0AA55H) first then verify ROM
;			checksum to save POST time if the ROM image is
;			invalid.
;R84	01/15/99 KVN	Fixed ROM size return from decompress to be destroy.
;R81A	01/13/99 MCH	Fixed the coding error.
;R83	01/13/99 RAY	Use Big real mode instead of protected mode during
;			serching for VGA BIOS. Some M/B hangs here!
;
;R82	12/28/98 RAY	1. Add SHADOW_UNIT_64K switch for chipsets supporting
;			   shadow in terms of 64K Unit.
;
;			   Note: This swith only applies to PCIP_NEW.ASM
;				 NOT PCIPOST.ASM
;
;			2. Kill the switch: CT_SHADOW_RW_HOOK_SUPPORT so that
;			   from now on if you want to use PCIP_NEW.ASM, you
;			   have to provide "Ct_Shadow_RW" & "Ct_Shadow_RW"
;			   in the F000 Segment of PCICHIP.ASM
;
;R81	12/23/98 MCH	Fixed for most PCI/VGA have random dots/lines in the
;			screen while starting to install Win95/98 if Cyrix
;			6x86 M1/M2 CPU is used with PCI Peer Concurrency and
;			OnChip USB is enabled in VIA/VPX chipsets platform.
;			It needs to add "Patch_MX_CPU_For_PCI_Peer_Con_USB"
;			define in the BIOS.CFG for effectiveness.
;R80	12/22/98 RCH	Fixed wrong device node report for option ROM size
;			is not match with shadow unit if the shadow unit is
;			64KByte.
;R63B	12/25/98 AVN	Fixed SiS 5600/530/620 when IDE channel disable and
;			IRQ cannot release, because channel enable bits had
;			swap.
;R79	12/14/98 TNY	Add "WHITNEY_SPECIAL" option.
;			Reason:
;				It is exhibited to be truned on command register 
;			before I/O & memory address assigned, otherwise the
;			system will hang-up.
;R78	12/09/98 KVN	Force set IDE DMA status register of capable bits for
;			windows NT service pack 4 to properly check DMA
;R77	12/09/98 TNY	Fix cache line size register of P2P bridge always be
;			2. (it should be 8)
;R76	12/08/98 RCH	Added Intel/ICH IDE controller checking.
;R57C	12/02/98 MIL	Enable Master bit for Cyrix CX55x0 Onboard P2P bridge.
;R75	12/02/98 MIL	Added code for Cyrix CX55x0 Chipset IDE Device.
;			Fixed IRQ 14/15 was assigned for PCI card when the
;			Two IDE Channel doesn't disable.
;R74	11/24/98 JMS	Fix can't use CD-ROM when use CMD CAS-646U IDE Card
;R73A	11/23/98 TNY	Fix R73 cause P6-Dual-P system hang in POST31.
;R73	11/19/98 ATY	Fixed bug that the AMD K6/3D CPU sometimes reset
;			during POST in SiS5598, when USB legacy support is
;			enabled.
;			The causation is that the SS is destroyed when entry
;			and leave SMI during protected mode period.
;R72	11/16/98 RAY	No more	Reserve_Irq_For_PciBootDev
;R71	11/16/98 TNY	Some PCI/IDE card is not class ide card, so we can
;			assign resource to it as real PCI card.
;			(like CMD CAS-646U)
;R70	11/16/98 RCH	Temporarily patch system hang if the PPGA 370 CPU
;			(CPUID=0665H) is configured with clock ratio 6
;			(400Mhz) or 6.5(433Mhz)
;R39C	11/10/98 LAW	fixed more level 3 bus VGA select error and onboard P2P
;			PCI VGA cannot select turn on
;R69	11/09/98 JKY	Patch 3COM cardbus card in dos , assign card is bus 7
;R68	11/05/98 RAY	Fix legacy-ISA's ROM shadowed fail.
;R63A	10/22/98 AVN	Support IRQ 14/15 was assigned for PCI card to all
;			SiS chipset.
;R56E	10/21/98 RCH	Clear PME# status for PCI MODEM card with class code
;			078000H to support Wake-On-Ring feature.
;
;R56D	10/08/98 RCH	Rewrite routine for clearing PME# status to support
;			other devices (like MODEM etc.)
;
;R65A	10/06/98 AVN	Move code to CHIPPOST.ASM to avoid check SiS6306 AGP
;			share/local memory repeat, if other P2P card plug.
;R67	10/06/98 RAY	Some M/B wants to reserved E000h IO space for
;			their customers.
;
;			Solution
;			--------
;			Add compiler variable "PCI_IO_LIMIT" for BIOS.CFG
;			to config the top IO address which is appropriate.
;			In this case, add "PCI_IO_LIMIT EQ 0E000h" in
;			BIOS.CFG.
;
;			Note: this variable only applies to the new PCIPOST.ASM
;			      i.e. PCIP_NEW.ASM
;
;R66	10/02/98 RAY	Some M/B maker share the same "SCSI onboard BIOS"
;			for 2 different M/B w/ and w/o SCSI devices.
;			However the SCSI_SLOT location for the non-SCSI
;			device is a P2P bridge.
;
;			Here in the BIOS we do a checking for storage device
;			before we disable the device on that SLOT
;
;R64A	10/02/98 RIC	Add "No_ACPI_IRQ_Auto_Assign" definition for R64 code.
;R65	09/23/98 AVN	Support SiS6306 AGP to check share/local memory using.
;R64	09/23/98 RIC	Change ACPI IRQ assign algorithm to Auto-assigned.
;			(This function is only support in VIA SouthBridge now)
;			If you want to use old algorithm, please define:
;			1."No_ACPI_IRQ_Auto_Assign" for disabled new algorithm.
;			2."ACPI_IRQ_Selectable" for enabled old algorithm.
;R63	09/22/98 RCH	Fixed IRQ 14/15 was assigned for PCI card when the
;			HDD is installed on secondary channel and there is
;			no device on primary channel for SiS chipset.
;R56C	09/22/98 RIC	Fix that WOL hang in POST 0Dh in some VIA mainboard
;			(with 596 SouthBridge).
;R62	09/18/98 RCH	Open IRQ 6 as available IRQ for PCI devices. If
;			platform need this feature, the value of
;			"AVAILABLE_PCI_IRQ" must be modifed also to have IRQ 6
;			available for assignment .
;R21C	09/11/98 RAY	Fixed ISA occupied address temporary shadowed
;			we invoking PCI ROM.
;
;			This bug was found when PCI SCSI & the M-System chip
;			were both installed. If the M-System(ISA) area was
;			shadowed, the system would hang up inside the SCSI
;			ROM since the M-System area was not only ROM but
;			some direct memory-map storage on the chip.
;
;R57B	08/27/98 RCH	Don't turn on bus master bit during PCI devices
;			I/O & memory scanning to avoid system hang up for
;			Sis5571 with 128MB SDRAM installed and the COGNEX
;			capture card is used.
;R61	08/21/98 RCH	Added a switch to support onboard PCI VGA located on
;			PCI bus above "0" and the chipset support AGP.
;	Note : "R22C" & "R21B" are used to fix working failure for
;		"IBM ISA/PnP Token-Ring LAN card"
;R22C	08/21/98 RAY	Do not report device node for ISA ROM which size is
;			not matched with the shadow size
;
;R21B	08/21/98 RAY	Temporary removed the changes that R21 & R21A had been
;			made since they caused the ROM area assigned by ISA PnP
;			being shadowed.
;
;			Due to R21 & R21A fixed the combination of M-System
;			ROM & PCI SCSI ROM conflict & this kind of combination
;			is comparatively less that ISA PnP devices with ROM.
;			Further investigation on this will be carried out to
;			fix this combination.
;
;R56B	08/19/98 TNY	Always clear PME status is plugged LAN card support
;			PME#.
;			Method:
;				Rx(34h) is the power-management capabilities
;			pointer. And the Cap register bit 31-27 is the
;			PME-Support register ( 0 = No PME# supported).
;			If PME# supported , we can R/W the Cap register bit 47
;			to clear the PME status.
;R60	08/12/98 STV	Added ACARD SCSI ID for Force_ROM_For_Some_Devices func.
;R59	08/11/98 RCH	Patch system hang up while scanning onboard C&T 6XXXX
;			VGA ROM register if Intel MMO module for 430TX is
;			used.
;R52B	08/10/98 AVN	Fixed when USB legacy support disable, no IRQ assign
;			USB host control.
;			The cause is that USB class code had destroy and the
;			class code will same as alternative VGA type.
;			So when define 'PCI_VGA_IRQ_SETUP_ITEM' and disable
;			VGA IRQ in setup, that the USB IRQ is disable too.
;			The correct solution save USB class code.
;R58	08/06/98 RAY	Fixed PCI memory space conflict when VGA in bus 0 and
;			a lots of PCI cards behind P2P bridge with much memory
;			space requested.
;R56A	08/05/98 TNY	1.Fix some chipset WOL fail.
;			2.Fix WOL fail if two 558 LAN card plugged.
;R52A	08/03/98 ATY	Fixed IRQ bug.If defined "ONBOARD_VGA_NEED_IRQ"
;						 "PCI_VGA_IRQ_SETUP_ITEM"
;			and			 "No_Assign_IRQ_If_USB_Disable"
;			after "VGA" Item choose "Disable",but "USB" Item is
;			"Enable",In boot mean is show "NA".
;R57A	07/29/98 RCH	Fixed USB legacy keyboard not working caused by R57
;R57	07/29/98 RCH	Don't turn on bus master bit before assigning resource
;			for PCI devices. It cause system hang up when COGNEX
;			MVS 8100 is plugged and system memory is 128Mb for
;			SiS5571 chipset.
;R56	07/28/98 TNY	Clear PCI LAN card's power-on status register
;			for fixing power-on fail next time.
;R55	07/23/98 KVN	Change method of decompressing in protect mode
;R54	07/21/98 STV	Fixed combination tow vga bios can't init.
;R53	07/16/98 KEN	Added delay between two memory write/read at routine
;			"Prepare_LMEM_Resource", otherwise the UMB will be
;			recognized as all RAM occupied if some ISA cards
;			installed.(e.g. Simple's PC card reader/writer)
;R52	07/08/98 AVN	Fixed when USB host disable and POST still reserve
;			one IRQ for USB host.
;R51A	07/08/98 AVN	R51 just patch question, now it is no usefully.
;			Beacuse the correct solution was found out.
;R51	07/02/98 AVN	For SiS5591/5595 with ACER CDROM driver (DOS version
;			vide-cdd.sys) will hang, if IRQ routine reg. no any
;			IRQ10 assing, so we let IRQ10 can be firstly assign.
;R50	06/26/98 RCH	Disabled VGA ROM space decode immediately after
;			VGA BIOS is copied to buffer to fix display failure
;			for CirrusLogic CL7555 PCI VGA card.
;R49	06/03/98 TNY	Fix both AGP VGA card and P2P VGA card plugged, the
;			AGP VGA card always is the highest priolity display.
;R48	06/02/98 TNY	Add "ASSIGN_ONE_IRQ_FOR_PCI_IF_PnPOS_YES" option.
;R47A	05/26/98 JSN	Fixed error code.
;R47	05/26/98 JSN	Fixed VIA/Ali chipset system reboot while use AHA SCSI
;			pci card at POST_52s when the CPU is AMD K6/3D and
;			the USB	keyboard is plugged.
;			The causation is that the SMI is issued while the
;			system is resided in protected mode.
;			The solution is that using flat mode. 			reading and writing.
;R46    05/22/98 ADS    Added "AGP_V3000_Card_Awlays_Assign_IRQ" to fix this
;			AGP VGA card hang in Win95 with no assign IRQ.
;R45	05/08/98 RCH	Fixed device(DAC960PG) using i960RP as I/O processor
;			lose option ROM initialization.
;R39B	05/08/98 TNY	Reduce code size.
;R39A	05/07/98 TNY	Improve FirstInitAGP_Item for user to select to init
;			AGP ,PCI slot and Onboard PCI vga.
;R44	05/07/98 RCH	Fixed VGA can not work if it's ROM size is bigger
;			than 32Kb for MediaGX platform
;R43	05/05/98 JDN	Fixed codes for Cardbus can't initial
;R42	04/21/98 TNY	Patch MATROX VR card.
;			It's a VGA P2P card, we found the P2P's ending prefetchr
;			egister must be modified: Rx(26) = 0 &
;			Rx(27) = and not 08h.
;R41	04/17/98 RAY	Skip checking the device ID for NCR SCSI ROM for the
;			below 2 reasons:
;
;			1. NCR/Symbios can supports all series of NCR/Symbios
;			   SCSI device by one ROM
;			2. Some Symbios SCSI card will have a ROM with device
;			   ID different from the ID on chip
;
;R40	04/01/98 ATY	Solved SiS5598 of Onboard vga to hang in "BF".
;R39	03/31/98 RAY	Add support for users to select from which VGA card
;			(AGP or PCI) should the BIOS initialize
;
;R38	03/31/98 RAY	Add ONBOARD_VGA_P2P[BP] for PCICHIP.ASM to report a
;			onboard VGA which goes thru a onboard P2P. Just fill
;			ONBOARD_VGA_P2P[BP] with the P2P bridge's device(func)
;			number to inform the PCI kernel.
;
;			Note: It applies only to VGA P2P on Bus 0
;
;R37	03/29/98 RAY	Add external definitions to fix old PnP setup
;			compiling error.
;
;R36	03/24/98 RCH	BIOS scan all PCI ROMs from bus 0 up to maximum bus
;			number. Most of Raid cards are incorporated with a
;			P2P bridge and the bus number assigned is higher
;			than bus 0. In order to let user can select booting
;			from Raid first instead of normal SCSI card on the
;			bus 0, a switch "RAID_BOOT_OPTION" is used to reach
;			this goal and user also have choice in the setup
;			screen.
;R35	03/20/98 RCH	Fixed system can not boot from SCSI drive if 3COM LAN
;			boot ROM is executed before SCSI ROM initials.
;			It's 3COM's boot ROM problem. BIOS just patch it.
;			It is optional, need switch "LAST_INIT_FOR_LAN_ROM"
;R34A	03/20/98 RAY	Fix Loop too long
;
;			R34 caused the "loop Next_P2P_Request" instruction to
;			jump to a label offset > 128 bytes. Use CMP & JNE
;			instead !
;
;R34	03/19/98 RAY	Problem fixed:
;
;			When a lot of P2P are plugged, the IO range will
;			confict.
;
;R33	03/12/98 KVN	Added ChipAwayVirus ROM to F000 shadow
;R22B	03/10/98 RCH	Patch system failure if VGA ROM is larger than 32Kb
;			and working with LAN card under Win95 after
;			suspend/resume.
;R32	03/10/98 RAY	Force the base request register B1 to be 0 if that
;			base register request a I/O space. This is added to
;			to prevent some "BAD" PCI devices which report a
;			unreasonable value but in fact they need resources
;
;R09A	03/06/98 RCH	More modifications for Trend ChipAway anti-virus
;			support, Skip ChipAway ROM initial if user disable
;			in CMOS setup screen.
;
;R31	03/06/98 RAY	The Intel 440LX AGP P2P bridge do not fully decode the
;			I/O space. When the I/O range of this bridge is set to
;			B000h-BFFFFh(when the total I/O request of Bus 0
;			including P2P is 4000h), it will cause the S3 775 VGA
;			card to have a blank screen(except the mouse cursor)
;			under NT4.0 with the VGA device driver installed.
;
;			We patch this by trying to prevent the bridge's I/O
;			range to be set to B000-BFFF
;
;			Remark: This happens only in this PCIP_NEW.ASM because
;				the old PCIPOST.ASM "hard coded" the I/O range
;				of a P2P bridge
;
;R30	02/27/98 KVN	Public the routine: E000_A20_Off
;R29	02/26/98 RIC	Fixed that the IRQ of USB can't release when USB
;			disabled in "USB_IRQ_SELECTABLE" define.
;R21A 	02/17/98 STV	The Shadow set enable but not enable.
;R28	02/16/98 TNY	Disable 3Eh(0) Parity Errre Response of AGP bridge
;			followed by  Intel.
;R27	02/02/98 KGN	Add defin No_C8_DF_Shadow_Item for save F000 Code
;			remove C800-DFFF shadow menuitem from bfeature
;R26	02/02/98 PAL	Fixed error when shadow unit use 32k
;R25	01/22/98 JSN	Fixed easy hang at 0b for Ali + ET6000 + AHA 2940W
;R19A	01/14/98 RAY	Fixed compiler error in if MOUSE_IN_XGROUP is defined
;
;R24	01/14/98 STV    Fixed bug. When PCI BIOS size > 64k ,post later shadow
;			change error.
;R22A	01/14/98 RCH	Fixed wrong size of ROM device node if option ROM size
;			is bigger than 16Kb
;R23	01/13/98 STV	Added all isa rom func for CBROM /isa.
;			i.e : 1.cbrom /isa [Filename]
;			      2.cbrom /isa [Filename] [xxxx:0]
;R22	01/13/98 RCH	Intel/558 LAN and AHA/2940 SCSI working under Win95
;			will cause a yellow caution if system enter and exit
;			suspend mode. This only happen on Win95 and no problem
;			on Win98.
;R21 	01/08/98 PAL	Fixed SCSI option rom hangs in combination with M-SYSTEMS
;R20	01/06/98 RCH	Added optional feature with IRQ selectable for each
;			PCI slots if define "PCI_IRQ_SELECTABLE"
;R19	01/03/98 STV	Fixed Mylex DAC960 RAID controller card cannot work
;			successfully while the PS/2 mouse is not plugging,
;			the card will set to disable automatically while
;			without PS/2 mouse.PS/2 mouse plugging flag isn't
;			config_table+5 ,so change to SYSTEM1_BYTE(bit 2).
;			Config_Table+5 is EBDA flag. See atorgs.asm
;R13A	12/24/97 STV	Release Added LAN card Support by cbrom /lan
;			& Fixed LAN card boot ENABLE/DISABLE
;R18	12/24/97 RCH	Fixed error coding that cause system RAM 40:BA become
;	 	        always 0FFH and system always boot from LAN even LAN
;		        is not first boot priority.
;R17	12/23/97 RAY	Problem:
;
;			  Some onboard VGA will hang up randomly if the
;			  onboard VGA ROM is not plugged and at the same
;			  time the ROM image is added to the BIOS using
;			  CBROM.EXE.
;
;			  This occurs in Quantas's LX M/B with ATI-RAGE
;
;			Solution:
;
;			   We should disable the ROM completely(write 0 to
;			   register location 30h) when we do not find any
;			   valid ROM images both from high address & from
;			   C000:0000h
;
;R16	12/23/97 RAY	Add [BP] for current class code
;R15	12/23/97 RCH	Fixed S3/868 hang up while working on AGP platform
;			with 16Mb Aperture size selected. It is caused by
;			this VGA requesting 32Mb memory space but actually
;			decode 64Mb space.
;R14	12/23/97 RAY	Fix Adaptec's ROM which support all 78x0 devices
;			cannot be invoked by the new CBROM algorithm
;R13	12/18/97 STV	Added LAN card Support by cbrom /lan
;R12	12/16/97 RAY	To record the assigned PCI IRQs in F000 shadow RAM
;			for the IRQ routing table(both INT 1Ah & MS IRQ
;			Routing table) to reference.
;			This is to to fix the ICU hang up problem
;R11	12/16/97 RAY	Some PCI device report a value of FFFFFFFFh at 30h
;			This version of BIOS will treat it as "ROM required"
;R10	12/16/97 RCH	Fixed system hang up while initial PCI/VGA ROM if
;			Rendition Verite V2200 is installed and Cyrix M1 or
;			M2 is used with VIA/VPX chipset.
;R09	12/05/97 PAL	Added Trend_AntiVirus Support by cbrom /vrs
;R08	12/05/97 TNY	Set IRQ9 to be the last of IRQ_Order table.
;			To fix some PCI card behaving abnormally in Win95 if
;			IRQ9 assigned.
;R07	12/01/97 RAY	Some VGA ROM images don't includes the PCI Vendor ID
;			& Device ID. Thus when we seek for VGA image, we have
;			a default image that points to the first image that
;			added with "CBROM /VGA"
;
;R02B	11/17/97 RAY	Fix "CBROM /PCI" does not work with 1M BIOS
;R06	11/15/97 RAY	Symtom:
;
;			  Some PCI devices do not decode address A8. When we
;			  assign I/O space to these kind of devices at address
;			  using A8, they will fail to decode the correct
;			  address.
;
;			Solution:
;
;			  No matter it is in bus 0 or not, we assign I/O
;			  space with 1K alignment.
;
;R05	11/14/97 RAY	Add Open_IDE_2nd_Channel
;
;R04	11/14/97 RAY	Move Routine: Reserve_Irq_For_PciBootDev to XGROUP
;
;R03	11/14/97 RAY	Modify the algorithm for searching combined NCR SCSI
;			ROM
;
;R02A	11/14/97 RAY	Problem fixed:
;			When apply both /NCR & /AHA to old CBROM.EXE, NCR SCSI
;			ROM is not loaded
;
;R02	11/13/97 RAY	Add new CBROM.EXE support
;		 STEVEN	Since this function is very code is complicated,
;			I clear all the Rxx for easy debugging. From now on,
;			any changes to this file should add Rxx.

ifdef	MASM611
.MODEL  SMALL, BASIC
OPTION	PROC: PRIVATE
endif	;MASM611

.386P

		PAGE	56, 132
;.XLIST
		INCLUDE BIOS.CFG
		include	COMMON.EQU
		INCLUDE COMMON.MAC
		include	bsetup.inc
		include	fshadow.equ

ifndef	NO_PNP_PCI_AUTO
ifdef	PNP_BIOS
		PNP_PCI_AUTO	EQU	1
endif	;PNP_BIOS
endif;	NO_PNP_PCI_AUTO

ifdef	PCI_BUS

;R59 - start
  PATCH_ONBOARD_CT_6XXXX_VGA	=	0
 ifdef	NO_SCAN_ONBOARD_VGA_ROM
  PATCH_ONBOARD_CT_6XXXX_VGA	=	1
 endif;	NO_SCAN_ONBOARD_VGA_ROM
;R59 - end

IRQ12_LAST_FOR_PCI	EQU	1
SET_MPIRQ_TBL	=	0

ifdef	MP_SUPPORT
ifdef	NEW_INTEL_IOAPIC
SET_MPIRQ_TBL	=	1
endif;	NEW_INTEL_IOAPIC
endif;	MP_SUPPORT

endif;	PCI_BUS
;R13A start
ifdef	LAN_BOOT_SUPPORT
		extrn	LanBoot_Item:near
endif	;LAN_BOOT_SUPPORT
;R13A end


ifdef	PNP_BIOS
		include	PNP.EQU
endif	;PNP_BIOS

		Public	NCR_810_FOUND

PUSH_ALL	MACRO
		push	ds
		push	es
		pushad
		ENDM

POP_ALL		MACRO
		popad
		pop	es
		pop	ds
		ENDM

;[]================================================================[]
;			EQUATES
;[]================================================================[]

TEMP_AREA		EQU	3000H

CLASS_VGA		EQU	03h
ALT_CLASS_VGA		EQU	0001h
CLASS_IDE		EQU	0101h
CLASS_SCSI		EQU	0100h
CLASS_PP_BRIDGE		EQU	0604H

CLASS_USB		EQU	0C03h

PCI_VGA_CLASS		EQU	03H
NORMAL_VGA_CLASS	EQU	0001H

CIRRUS_VENDOR_ID	EQU	1013H
NCR_VENDOR_ID		EQU	1000h
DEVICE_NCR810		EQU	0001h
DEVICE_NCR860		EQU	0006h
ADAPTEC_VENDOR_ID	EQU	9004h

DEVICE_AHA7850		EQU	5078h
DEVICE_AHA7860		EQU	6078h
DEVICE_AHA7870		EQU	7078h
DEVICE_AHA7880		EQU	8078h
DEVICE_AHA7895		EQU	7895H

BusLogic_VENDOR_ID	EQU	104bh
DEVICE_BA81C15		EQU	8130h

ACARD_VENDOR_ID		EQU	1191h
DEVICE_ACARD6710	EQU	8002h

AMD_VENDOR_ID		EQU	1022h
DEVICE_AMD974_SCSI	EQU	2020h

;[]================================================================[]
;		BP definitions
;[]================================================================[]

STACK_LOC	=	ITEMSTAT_BUF
DEFINE_STACK	MACRO	VAR_NAME, VAR_LEN
		Public	VAR_NAME
	VAR_NAME  = STACK_LOC
	STACK_LOC = STACK_LOC + VAR_LEN
		ENDM

DEFINE_STACK	START_PCI_DEV		, 1
DEFINE_STACK	END_PCI_DEV		, 1

DEFINE_STACK	AVAILABLE_PREFET_START	, 4
DEFINE_STACK	AVAILABLE_MEM_START	, 4
DEFINE_STACK	AVAILABLE_IO_START	, 4

DEFINE_STACK	PREFET_MEM_BUF_PTR	, 2
DEFINE_STACK	HMEM_BUF_PTR		, 2
DEFINE_STACK	IO_BUF_PTR		, 2
DEFINE_STACK	LMEM_BUF_PTR		, 2
DEFINE_STACK	BASE_REQ_BUF_PTR	, 2
DEFINE_STACK	PCI_VGA_DEVICE_BUF_PTR	, 2

DEFINE_STACK	CURRENT_DEVICE_ID	, 2
DEFINE_STACK	CURRENT_VENDOR_ID	, 2
DEFINE_STACK	CURRENT_CLASS_CODE	, 2
DEFINE_STACK	CURRENT_SLOT		, 1
DEFINE_STACK	CURRENT_BUS_NO		, 1
DEFINE_STACK	TOTAL_BUS_NO		, 1
DEFINE_STACK	DEVICE_CLASS_FLAG 	, 1	;R35
LAN_NOW		EQU	080H		      	;R35
LAN_FOUND	EQU	040H		       	;R35
RAID_FIRST	EQU	020H			;R36

;------------------------------------------------------------
;
;	LMEM_RESOURCE[bp]
;
;each bit describes 4K ROM(Shadow RAM) area
;  starting from C8000h - DF000h
;  i.e. bit 0 = 1 means C8000h-C8FFFh is occupied
;	    1 = 1	C9000h-C9FFFh is occupied
;	.
;	.
;	.
;
;------------------------------------------------------------

DEFINE_STACK	LMEM_RESOURCE		, 4
DEFINE_STACK	AVAIL_LMEM_ADDR		, 4
DEFINE_STACK	TARGET_AVAIL_LMEM	, 4
DEFINE_STACK	LMEM_FOR_ROM_FLG	, 1
DEFINE_STACK	NEED_ASSIGN_LMEM_FLAG	, 1
DEFINE_STACK	LMEM_BEFORE_ROM		, 4
DEFINE_STACK	LMEM_RESERVED		, 4

DEFINE_STACK	PCI_VGA_INFO		, 2		;bus/dev+Fun No.
DEFINE_STACK	PCI_VGA_FOUND		, 1
		VGA_DEVICE_EXIST	EQU	0AAh
DEFINE_STACK	VGA_BIOS_LENGTH		, 1
;R38 - starts
;-------------------------------------------------------------
;for Ct_PCI_VGA_IDSEL to report a onboard VGA P2P device no.
;Just fill ONBOARD_VGA_P2P[BP] with the P2P bridge's device(func)
;number to inform the PCI kernel.
;-------------------------------------------------------------
DEFINE_STACK	ONBOARD_VGA_P2P		, 1
;R38 - ends

DEFINE_STACK	NCR_810_FOUND		, 1
		NCR_SCSI_FOUND		EQU	0BBh
		INVOKE_NCR_CBROM	EQU	0AAh
DEFINE_STACK	COMBINED_PCI_ROM_NEED	, 1
DEFINE_STACK	CBROM_BP_START		, 2
DEFINE_STACK	CBROM_BP_END		, 2
DEFINE_STACK	CBROM_BUF_START		, 4
DEFINE_STACK	CBROM_BUF_END		, 4
DEFINE_STACK	PCI_CBROM_TEMP		, 1
DEFINE_STACK	PCI_CBROM_ADDR		, 4

DEFINE_STACK	RESERVE_PCIIRQ		, 1
DEFINE_STACK	PCI_IRQ_ASSIGNED	, 2
DEFINE_STACK	PCI_IRQ_MAP		, 2
DEFINE_STACK	PCIIRQ  		, 32		;need 16*2 bytes
							;PCI available IRQ no. 1,2,4,4
							;low byte = IRQ No. 0-15
							;high byte = INT No. 1-16
DEFINE_STACK	PCI_IDE_EXIST		, 1
DEFINE_STACK	PCI_IDE_FOUND		, 1
		IDE_EXIST		EQU	0AAH	;flag for PCI/IDE found

DEFINE_STACK	ESCD_IRQ		, 2
DEFINE_STACK	ESCD_DMA		, 1

;R13 start
;R13A	ifdef	LAN_BOOT_SUPPORT
;R13A	DEFINE_STACK	LAN_ROM_NEED		, 1
;R13A	DEFINE_STACK	LAN_CARD_ID		, 4
;R13A	endif	;LAN_BOOT_SUPPORT
;R13 end
;[]================================================================[]
;[]================================================================[]

MAX_SUB_BUS		EQU	16
BUS_TREE_STRUC		STRUC
  Host_Slot		db	?
  P2PB_BusNo		db	?
  P2PB_DevFucNo		db	?
  Sub_Buses		db	MAX_SUB_BUS dup (?)
  TotalMemReq		dd	?
  TotalPfMemReq		dd	?
  TotalIOReq		dd	?
  TotalLMemReq		dd	?
  Bus_IO_Start		dd	?
  Bus_Mem_Start		dd	?
  Bus_PfMem_Start	dd	?
BUS_TREE_STRUC		ENDS
SIZE_BUS_TREE_STRUC	EQU	(SIZE BUS_TREE_STRUC)

VGA_INFO_STRUC		STRUC
	VGA_DevNum	db	?
	VGA_BusNum	db	?
	OnboardVGA	db	?
			db	?	;dummy byte
	VGA_ID		dd	?
VGA_INFO_STRUC		ENDS
SIZE_VGA_INFO_STRUC	EQU	(SIZE VGA_INFO_STRUC)

IRQ_REQ_STRUC		STRUC
	IntPin		db	?
	IrqReqDevNum	db	?
	IrqReqBusNum	db	?
	HostSlot	db	?
			dd	?	;dummy dword
IRQ_REQ_STRUC		ENDS
SIZE_IRQ_REQ_STRUC	EQU	(SIZE IRQ_REQ_STRUC)

TEMP_PCI_REQ_BUF	SEGMENT USE16 AT 5000h
P2P_TREE_INFO		Label	Byte
			db	(MAX_SUB_BUS * SIZE_BUS_TREE_STRUC) dup (?)
PCI_VGA_DEVICE_BUF	Label	Byte
			db	16*SIZE_VGA_INFO_STRUC dup (?)
TEMP_BASE_REQ_BUF	Label	Byte
TEMP_PCI_REQ_BUF	ENDS

MEMIO_BUF		STRUC
	MemIO_Req	dd	0
	Cfg_Loc		dw	0
	MemIo_Info	db	0
	Bus_Num		db	0
MEMIO_BUF		ENDS
SIZE_MEMIO_BUF		EQU	SIZE MEMIO_BUF

PCI_REQ_BUF	SEGMENT USE16 AT 4000h
BUF_SIZE	EQU	6*8*32		;max 32 devices
					;each device has max 8 functions
					;each function request max 6 Mem base
IO_BUF		db	(BUF_SIZE * SIZE_MEMIO_BUF) dup (?)
HMEM_BUF	db	(BUF_SIZE * SIZE_MEMIO_BUF) dup (?)
LMEM_BUF	db	(BUF_SIZE * SIZE_MEMIO_BUF) dup (?)
PREFET_MEM_BUF	db	(BUF_SIZE * SIZE_MEMIO_BUF) dup (?)

PCI_REQ_BUF	ENDS

VIRTUAL_HMEM_BASE	EQU	0A0h
VIRTUAL_PFMEM_BASE	EQU	0A8h
VIRTUAL_BUS0_PFMEM_BASE	EQU	0B0h
VIRTUAL_IO_BASE		EQU	0A1h

G_RAM		SEGMENT USE16 AT 0

		ORG	04H*4
		INCLUDE SEG_0.INC

		ORG	400H
		INCLUDE G_RAM.INC
ifdef	PNP_BIOS
		ORG	2000h
		INCLUDE PNPDATA.INC
endif	;PNP_BIOS

G_RAM		ENDS

		extrn	xcall_proc:near
		extrn	X_GetItem_Value:Near

.LIST

IFE	COMPILE_FOR_E0 EQ 1

;R33ifdef	Trend_AntiVirus				;R09
;R33		extrn	F000_Shadow_R:near	;R09
;R33		extrn	F000_Shadow_W:near	;R09
;R33		extrn	Virus_Used_Shadow:near	;R09
;R33		extrn	Virus_Item:near		;R09A
;R33endif;	Trend_AntiVirus				;R09

ifdef	PCI_BUS

	ifdef	PNP_BIOS
		extrn	Build_OnboardRomNode:near
	 ifdef	COMBINE_ISA_ROM
		extrn	Build_OtherRomNode:near
	 endif;	COMBINE_ISA_ROM
	 ifndef	NEW_PNP_SETUP
	 ifdef	PNP_PCI_AUTO
		extrn	PnP_Auto_Item:near
	 endif	;PNP_PCI_AUTO
	 endif	;NEW_PNP_SETUP
	endif;	PNP_BIOS

	ifdef	Cardbus_support
		extrn	Cardbus_Init:near
	endif	;Cardbus_support

	IF	SET_MPIRQ_TBL
		extrn	IO_Int_Entry16:near
	ENDIF	;SET_MPIRQ_TBL

		extrn	Pci_Class_Code:near
IF	BIOS_SUPPORT_586				;R99
		extrn	Check_M1_Cpu:near
ENDIF	;BIOS_SUPPORT_586				;R99
		extrn	Unlock_Cyrix:near
		extrn	lock_Cyrix:near
		extrn	F000_Set_Cyrix:near

		extrn	F000_call_proc:near
		extrn	Post_call_proc:near
		extrn	POST_func_end:Near
		extrn	POST_VECT:Near

		extrn	Vga_Snoop_Item:near

		extrn	Ct_OnChip_IDE_Chk:near
	ifdef	ONBOARD_NCR_SETUPABLE
		extrn	Scsi_Item:near
	endif	;ONBOARD_NCR_SETUPABLE

		extrn	AGet_CfgSpace_Byte:near
		extrn	AGet_CfgSpace_Word:near
		extrn	AGet_CfgSpace_Dword:near
		extrn	ASet_CfgSpace_Byte:near
		extrn	ASet_CfgSpace_Word:near
		extrn	ASet_CfgSpace_Dword:near
		extrn	Move_Codes:Near
		extrn	GetItem_Value:Near
		extrn	F000_GetItem_Value:near

		extrn	F000_Shadow_W:near
		extrn	F000_Shadow_R:near
		extrn	E000_64k_Shadow_RW:Near
		extrn	E000_64k_Shadow_R:Near
		extrn	C000_Shadow_RW:near		;chipset.asm
		extrn	C000_Shadow_R:near		;chipset.asm
		extrn	C800_Shadow:near		;chipset.asm
		extrn	CC00_Shadow:near		;chipset.asm
		extrn	D000_Shadow:near		;chipset.asm
		extrn	D400_Shadow:near		;chipset.asm
		extrn	D800_Shadow:near		;chipset.asm
		extrn	DC00_Shadow:near		;chipset.asm

		extrn	PCI_SLOT_CFG:near		;chipset.asm
		extrn	Ct_Shadow_Unit:Near		;pcichip.asm
		extrn	Ct_C8_To_DF_RW:Near		;pcichip.asm
		extrn	Ct_C8_To_DF_R:Near		;pcichip.asm
		extrn	Ct_PCI_Info:Near		;pcichip.asm
		extrn	Ct_Special_PCI_Device:Near	;pcichip.asm
		extrn	Ct_Set_PciIrq:near		;pcichip.asm
		extrn	IrqRout_Table:near		;pcichip.asm
	ifndef	NEW_PNP_SETUP
		extrn	PciIrq_Item:near		;pcichip.asm
	endif	;NEW_PNP_SETUP
		extrn	Ct_Disable_Shadow:Near		;pcichip.asm

;R82	ifdef	CT_SHADOW_RW_HOOK_SUPPORT
		extrn	Ct_Shadow_R:near		;pcichip.asm
		extrn	Ct_Shadow_RW:near		;pcichip.asm
;R82	endif	;CT_SHADOW_RW_HOOK_SUPPORT

	ifndef	NO_PCI_IDE_CARD
		extrn	PCI_IDE_IRQ:near		;pcifeat.asm
		extrn	First_IDE_INT:near		;pcifeat.asm
		extrn	Second_IDE_INT:near		;pcifeat.asm
	endif	;NO_PCI_IDE_CARD

	ifndef	NO_PCI_IDE_2ND_CONTROL
		extrn	Second_IDE_channel:near		;bfeature.asm
	endif	;NO_PCI_IDE_2ND_CONTROL

		extrn	Ct_PCI_VGA_IDSEL:near		;pcichip.asm

	ifdef	CT_SPEICAL_PCI_VGA
		extrn	Set_Ct_For_PciVga:near
	endif	;CT_SPEICAL_PCI_VGA

		extrn	Ct_Special_Copy_PCI_VGA:near

	ifdef	SPECIAL_PCI_IDE_PRG
		extrn	CT_PRI_PCI_IDE_PRG:near		;pcichip.asm
		extrn	CT_SEC_PCI_IDE_PRG:near		;pcichip.asm
	endif	;SPECIAL_PCI_IDE_PRG

ifndef	No_C8_DF_Shadow_Item			;R27
		extrn	C800_Item:near
		extrn	CC00_Item:near
		extrn	D000_Item:near
		extrn	D400_Item:near
		extrn	D800_Item:near
		extrn	DC00_Item:near
endif	;No_C8_DF_Shadow_Item			;R27

	ifdef	Combined_Other_PCI_ROM
		extrn	Ct_If_Combined_ROM_Needed:near
	endif	;Combined_Other_PCI_ROM

	ifdef	MULTI_HOST_BRIDGE
		extrn	Ct_Set_Mult_PciBus:near
	endif	;MULTI_HOST_BRIDGE

                extrn    GDTR1:fword
                extrn    code1_dt:near
                extrn    data1_dt:near
                extrn    data1_index:abs

		extrn	fProc_Pci_IO_Mem_Init:far

	IF	MSIRQROUT_SUPPORT
		extrn	MsPciIrqTbl:Near
	ENDIF	;MSIRQROUT_SUPPORT
		extrn	PciIrqTbl_Size:Near

		extrn	IRQ_REQ_BUF:Near
		extrn	IRQ_REQ_BUF_PTR:Near

		extrn	fProc_PciRom_Before_Init:Far

		extrn	POST_decompress:near
		extrn	A20_On:Near
		extrn	A20_Off:Near

;R72 ifdef	PNP_BIOS
;R72 		extrn	fProc_Reserve_Irq_For_PciBootDev:far	;R04
;R72 endif;	PNP_BIOS

;R36 - start
ifdef	RAID_BOOT_OPTION
		extrn	RaidBoot_Item:near
endif;	RAID_BOOT_OPTION
;R36 - end

;R91A	ifdef	PciLanROM_Control				;R91
;R91A		extrn	LAN_COMMAND_WORD:word			;R91
;R91A	endif	;PciLanROM_Control				;R91

endif	;PCI_BUS

		extrn	BootEntryTbl:near		;R96
		extrn	BootEntryEnd:near		;R96
		extrn	R_Mod_Ck:near	       		;R23
		extrn	F_C000_Shadow_R:near		;R82

DGROUP		GROUP	FCODE
FCODE		SEGMENT USE16 PARA PUBLIC 'CODE'
		ASSUME	CS:DGROUP

ifdef	PCI_BUS
;[]==============================================================[]
;
;Note : Don't destroy following codes , because it will be executed
;	while warm booting
;
;Reset_PciMaster:
;	Clear bit 2 (master bit ) of PCI command register
;
;Saves: all
;
;Input : none
;
;Output: None
;
;[]==============================================================[]
		public	Reset_PciMaster
Reset_PciMaster	proc	near

ifndef	PCI_RESET_SUPPORT

		pushad

		xor	bh, bh			;start from bus 0
Scan_Nxt_BusMs:
		xor	cx, cx			;start from devic 0 , func. 0

Scan_Nxt_Master:

ifdef	Cx5510_PCI_REG
		cmp	ch, Cx5510_PCI_REG	;if Cyrix Cx5510 chipset
		je	Next_Dev		;
endif;	Cx5510_PCI_REG

		xor	cl, cl
		call	AGet_CfgSpace_Word	;get vendor ID
		cmp	ax, -1			;legal vendor ?
		je	Next_Dev

		mov	cl, 4
		call	AGet_CfgSpace_Byte	;get command register
		and	al, NOT 04H		;disable master bit
		call	ASet_CfgSpace_Byte	;Set command register

		mov	cl, 0bh
		call	AGet_CfgSpace_Byte	;get class code
		cmp	al, 02			;is PCI LAN ?
		jne	No_PCI_LAN

		mov	cl, 04h
		xor	al, al
		call	ASet_CfgSpace_Byte	;clear command register.
No_PCI_LAN:

Next_Dev:
		call	Get_Nxt_Device		;CH return next device to do
		jnc	Scan_Nxt_Master

		inc	bh			;next bus
		cmp	bh, 4			;total 4 buses
		jb	Scan_Nxt_BusMs

		popad

endif;	PCI_RESET_SUPPORT

		ret

Reset_PciMaster	endp

ifndef	PCI_RESET_SUPPORT
;[]================================================================[]
;Get_Next_Device:
;	This routine is used to get next device no to treat
;Input	:	CH - Slot identification Number
;Output :	NC : CH - Next Slot ID numbuer
;		CF : All slot & function spaces has scanned
;[]================================================================[]
		ALIGN	4
Get_Nxt_Device	proc	near

		test	ch, 07h			;alread a multi-function space?
		jnz	@F			;yes, go point to next function

		mov	cl, 0Eh			;read header type
		call	AGet_CfgSpace_Byte	;read header type
		test	al, 80H			;multi-function support?
		jnz	@F			;yes, multi-function card!
		and	ch, NOT 111B		;mask function bits	;R57
		add	ch, 7			;point to next device!
	@@:
		add	ch, 1			;point to next function space
		jc	@F			;already overflow!

	ifdef	CONFIG_MECHANISM_1
		cmp	ch, (31 SHL 3)		;exceed maximum device?
	else	;CONFIG_MECHANISM_1
		cmp	ch, (15 SHL 3)		;exceed maximum device?
	endif	;CONFIG_MECHANISM_1

		ja	@F			;yes, tell caller error!

		clc				;success return
		ret
	@@:
		stc				;error return
		ret

Get_Nxt_Device	endp
endif;	PCI_RESET_SUPPORT

;[]================================================================[]
;[]================================================================[]
		Public	fProc_Get_CfgSpace_Byte
fProc_Get_CfgSpace_Byte	Proc	Far
		call	Get_CfgSpace_Byte
		retf
fProc_Get_CfgSpace_Byte	Endp
Get_CfgSpace_Byte	Proc	Near
		push	bx
		mov	bh, CURRENT_BUS_NO[bp]
		call	AGet_CfgSpace_Byte
		pop	bx
		ret
Get_CfgSpace_Byte	Endp

;-----------------------
;-----------------------
		Public	fProc_Get_CfgSpace_Word
fProc_Get_CfgSpace_Word	Proc	Far
		call	Get_CfgSpace_Word
		retf
fProc_Get_CfgSpace_Word	Endp
Get_CfgSpace_Word	Proc	Near
		push	bx
		mov	bh, CURRENT_BUS_NO[bp]
		call	AGet_CfgSpace_Word
		pop	bx
		ret
Get_CfgSpace_Word	Endp

;-----------------------
;-----------------------
		Public	fProc_Get_CfgSpace_Dword
fProc_Get_CfgSpace_Dword	Proc	Far
		call	Get_CfgSpace_Dword
		retf
fProc_Get_CfgSpace_Dword	Endp
Get_CfgSpace_Dword	Proc	Near
		push	bx
		mov	bh, CURRENT_BUS_NO[bp]
		call	AGet_CfgSpace_Dword
		pop	bx
		ret
Get_CfgSpace_Dword	Endp

;-----------------------
;-----------------------
		Public	fProc_Set_CfgSpace_Byte
fProc_Set_CfgSpace_Byte	Proc	Far
		call	Set_CfgSpace_Byte
		retf
fProc_Set_CfgSpace_Byte	Endp
Set_CfgSpace_Byte	Proc	Near
		push	bx
		mov	bh, CURRENT_BUS_NO[bp]
		call	ASet_CfgSpace_Byte
		pop	bx
		ret
Set_CfgSpace_Byte	Endp

;-----------------------
;-----------------------
		Public	fProc_Set_CfgSpace_Word
fProc_Set_CfgSpace_Word	Proc	Far
		call	Set_CfgSpace_Word
		retf
fProc_Set_CfgSpace_Word	Endp
Set_CfgSpace_Word	Proc	Near
		push	bx
		mov	bh, CURRENT_BUS_NO[bp]
		call	ASet_CfgSpace_Word
		pop	bx
		ret
Set_CfgSpace_Word	Endp

;-----------------------
;-----------------------
		Public	fProc_Set_CfgSpace_Dword
fProc_Set_CfgSpace_Dword	Proc	Far
		call	Set_CfgSpace_Dword
		retf
fProc_Set_CfgSpace_Dword	Endp
Set_CfgSpace_Dword	Proc	Near
		push	bx
		mov	bh, CURRENT_BUS_NO[bp]
		call	ASet_CfgSpace_Dword
		pop	bx
		ret
Set_CfgSpace_Dword	Endp

;[]================================================================[]
;[]================================================================[]
		ALIGN	4
		Public	Pci_IO_Mem_Init
Pci_IO_Mem_Init Proc	Near

		call	fProc_Pci_IO_Mem_Init
		ret

Pci_IO_Mem_Init Endp

;--------------------------------------------------------------------
;if any shadow segment is not used
;  ---> call hook in PCICHIP.ASM to disable it
;
;if any shadow segment is originally not available for PCI ROM
;  ---> if setup setting is set to ENABLE
;		do nothing
;	else
;		call hook in PCICHIP.ASM to disable it
;--------------------------------------------------------------------
		ALIGN	4
		public	Disable_UnUsed_Shadow
Disable_UnUsed_Shadow	Proc	Near

		POST_FUNC_CALL EDisable_UnUsed_Shadow
		ret

Disable_UnUsed_Shadow	Endp

;---------------------------------------------------------------------------
;
;		copy ROM image from SI:0 --> DI:0
;
;Input	:	SI = source segment
;		DI = Destination segment
;		AL <> 0 : copy size depends on ROM size in SI:2
;		   == 1 : copy size = input CX (no. of 4K)
;
;---------------------------------------------------------------------------
		ALIGN	4
		Public	Copy_ROM
Copy_ROM	Proc	Near

		POST_FUNC_CALL ECopy_Rom
		ret

Copy_ROM	Endp

;R82 ;[]============================================================[]
;R82 ;Input	:	CL = Request Memory spaces with size = CL * 4K
;R82 ;		     e.g. CL = 1 --> request 4K bytes
;R82 ;
;R82 ;Output	:	AL = 1 --> NC : AVAIL_LMEM_ADDR[bp] = availbale address
;R82 ;			   CF : No address available
;R82 ;[]============================================================[]
;R82 		ALIGN	4
;R82 		ASSUME	DS:NOTHING
;R82 		Public	Get_Available_LMEM
;R82 Get_Available_LMEM	Proc	Near
;R82 
;R82 		POST_FUNC_CALL EGet_Available_LMEM
;R82 		ret
;R82 
;R82 Get_Available_LMEM	Endp

;[]============================================================[]
;Enter Protected Mode with DS point to 00000000h
;[]============================================================[]
		ALIGN	4
		Public	Enter_Protect_Mode
Enter_Protect_Mode	Proc	Near

                mov     ax, cs
                mov     ds, ax
                assume  ds:dgroup

                lgdt    fword ptr GDTR1

                mov     eax, cr0
                or      al, 1
                mov     cr0, eax

;R47   		jmp	$+2			; flush queue

                mov     ax, DATA1_INDEX
                mov     ds, ax			; ds = 00000000h
ifndef	MP_SUPPORT				;R73A
		mov	ss, ax			;R73
endif;	MP_SUPPORT				;R73A

		ret

Enter_Protect_Mode	Endp

;[]============================================================[]
;[]============================================================[]
		ALIGN	4
		Public	Leave_Protect_Mode
Leave_Protect_Mode	Proc	Near

                mov     eax, cr0
                and     al, NOT 1
                mov     cr0, eax
;R47   		jmp	$+2			; flush queue
ifndef	MP_SUPPORT				;R73A
		xor	ax, ax			;R73
		mov	ss, ax			;R73
endif;	MP_SUPPORT				;R73A

		ret

Leave_Protect_Mode	Endp

;[]============================================================[]
;Input	:	CH - Slot identification Number
;Output :	AX - VENDER ID
;Destroy:	AX
;[]============================================================[]
		Public	fProc_Get_Vendor_ID
fProc_Get_Vendor_ID	Proc	Far
		call	Get_Vendor_ID
		retf
fProc_Get_Vendor_ID	Endp
		ALIGN	4
		ASSUME	DS:NOTHING
		public	Get_Vendor_ID
Get_Vendor_ID	Proc	Near

		push	cx
		xor	cl, cl			;Vendor ID
		call	Get_CfgSpace_Word

		cmp	ax, -1			;valid vendor ID
		stc
		je	Yes_Invalid
		clc
Yes_Invalid:
		pop	cx
		ret

Get_Vendor_ID	Endp

;[]============================================================[]
;Input	:	CH - Slot identification Number
;Output :	AX - DEVICE ID
;Destroy:	AX
;[]============================================================[]
		Public	fProc_Get_Device_ID
fProc_Get_Device_ID	Proc	Far
		call	Get_Device_ID
		retf
fProc_Get_Device_ID	Endp
		ALIGN	4
		ASSUME	DS:NOTHING
		Public	Get_Device_ID
Get_Device_ID	Proc	Near

		push	cx
		mov	cl, 02			;Device ID
		call	Get_CfgSpace_Word
		pop	cx
		ret

Get_Device_ID	Endp

;[]==============================================================[]
;PciRom_After_Init:
;	Force shadow RAM readonly after option ROM initialization
;Saves: all
;Input : none
;Output: None
;[]==============================================================[]
		ALIGN	4
		public	PciRom_After_Init
PciRom_After_Init	proc	near

		POST_FUNC_CALL EPciRom_After_Init
		ret

PciRom_After_Init	endp

;[]==============================================================[]
;PciRom_Before_Init:
;	special treatment before option initialization
;Saves: all
;Input : none
;Output: None
;[]==============================================================[]
		ALIGN	4
		public	PciRom_Before_Init
PciRom_Before_Init	proc	near

		call	fProc_PciRom_Before_Init

;R13 start
;R13A	ifdef	lan_boot_support
;R13A			mov	dword ptr LAN_CARD_ID[bp],0		;clear LAN device&vendor ID
;R13A
;R13A			mov	di,(8+1)*4
;R13A			post_func_call	post_decompress			;combined lan rom ?
;R13A			jc	short No_LAN_ROM			;yes!
;R13A			push	es
;R13A			push	4000h
;R13A			pop	es
;R13A			mov	bx,es:[18h]
;R13A			mov	ax,es:[bx+4]				;get vendor id
;R13A			shl	eax,16
;R13A			mov	ax,es:[bx+6]				;get device id
;R13A			pop	es
;R13A			mov	LAN_CARD_ID[bp], eax			;save vendor&device id
;R13A	No_LAN_ROM:
;R13A	endif	;lan_boot_support
;R13 end

		ret

PciRom_Before_Init	endp

;R05 - starts
ifdef	SUPPORT_PCISLOT_IDE
		Public	Open_8673
Open_8673	proc	near

		mov	dx, 108h
		mov	al, 04Ah
		out	dx, al
		NEWIODELAY
		mov	al, 06Ch
		out	dx, al
		NEWIODELAY

		mov	al, cl
		out	dx, al
		NEWIODELAY
		inc	dl
		in	al, dx
		NEWIODELAY

		ret

Open_8673	endp

		Public	Set_8673
Set_8673	proc	near

		xchg	al, cl
		mov	dx, 108h
		out	dx, al
		NEWIODELAY
		inc	dl
		xchg	al, cl
		out	dx, al
		NEWIODELAY
		mov	dx, 108h
		mov	al, 034h
		out	dx, al
		NEWIODELAY

		ret

Set_8673	endp
endif;	SUPPORT_PCISLOT_IDE
;R05 - ends

endif	;PCI_BUS

FCODE		ENDS

;--------------------------------------------------------------
;--------------------------------------------------------------
;----- The following codes will be located at E000 ! ----------
;----- The following codes will be located at E000 ! ----------
;----- The following codes will be located at E000 ! ----------
;----- The following codes will be located at E000 ! ----------
;--------------------------------------------------------------
;--------------------------------------------------------------
EGROUP		GROUP	ECODE
ECODE		SEGMENT USE16 PARA PUBLIC 'ECODE'
		ASSUME	CS:EGROUP, DS:G_RAM, ES:EGROUP

ifdef	PCI_BUS

;--------------------------------------------------------
;Input	:	SI = C800 - DF80
;		CL =  number of 4K to mark
;--------------------------------------------------------
		ALIGN	4
		ASSUME	DS:NOTHING
		Public	Mark_Addr_Not_Available
Mark_Addr_Not_Available	Proc	Near

		mov	eax, 1
		shl	eax, cl
		dec	eax

		mov	cx, si
		mov	cl, ch
		sub	cl, 0C8h
		shl	eax, cl
		or	LMEM_RESOURCE[bp], eax

		ret

Mark_Addr_Not_Available	Endp

;---------------------------------------
;Input : SI - segment to check
;Output: zero set  - ROM existed
;	 not zero  - ROM no existed
;---------------------------------------
		Public	Check_ROM_Exist
Check_ROM_Exist	proc	near
		mov	ds, si
		mov	ax, ds:[0]
		iodelay
		cmp	ax, 0AA55h			;ROM signature?
		ret
Check_ROM_Exist	endp

		Public	Rom_In_Terms_of_4K
Rom_In_Terms_of_4K	Label	Near

		mov	cl, ds:[2]			;ROM size in 512K
		test	cl, 07h				;size < 4K
		jz	@F				;no, continue!
		add	cl, 08h				;  to 4K
	@@:
		shr	cl, 3				;in terms of 4K
		ret

;-------------------------------------------
;-------------------------------------------
		ALIGN	4
		Public	Invalidate_Shadow_Seg
Invalidate_Shadow_Seg	Proc	Near
;R82 - starts
ifdef	SHADOW_UNIT_64K

		mov	eax, LMEM_RESOURCE[bp]
;R90		xor	al, al			;Free C8 - CF
		test	eax, 00FFFF00h		;D0-DF contain legacy stuff?
		jz	No_Legacy_At_D
		or	eax, 00FFFF00h		;invalidate the whole D Segment

	No_Legacy_At_D:

		mov	LMEM_RESOURCE[bp], eax
		ret

else	;SHADOW_UNIT_64K
;R82 - ends
		F000_CALL Ct_Shadow_Unit
		mov	edi, 00Fh
		cmp	cx, 4000h
		mov	cl, 4
		je	@F
		mov	edi, 0FFh
		mov	cl, 8
	@@:

	;------------------------------------
	_A_A:
		test	LMEM_RESOURCE[bp], edi
		jz	_B_B
		or	LMEM_RESOURCE[bp], edi
	_B_B:

		shl	edi, cl
		test	edi, 0FF000000h
		jz	_A_A
	;------------------------------------

		ret

endif	;SHADOW_UNIT_64K				;R82

Invalidate_Shadow_Seg	Endp

;---------------------------------------
;---------------------------------------
E000_A20_On	Proc	Near
		push	ds
		F000_CALL A20_On
		pop	ds
		ret
E000_A20_On	Endp

;---------------------------------------
;---------------------------------------
		public	E000_A20_Off		;R30
E000_A20_Off	Proc	Near
		push	ds
		F000_CALL A20_Off
		pop	ds
		ret
E000_A20_Off	Endp

;[]================================================================[]
;Function : Far call to write PCI double word value
;Input  : CX - device + function number	, CURRENT_BUS_NO[bp] = bus No.
;Output : none
;[]================================================================[]
		Public	F000_Set_CfgSpace_Dword
F000_Set_CfgSpace_Dword	proc	near
		call	fProc_Set_CfgSpace_Dword
		ret
F000_Set_CfgSpace_Dword	endp

;[]================================================================[]
;Function : Far call to write PCI word value
;Input  : CX - device + function number	, CURRENT_BUS_NO[bp] = bus No.
;Output : none
;[]================================================================[]
		Public	F000_Set_CfgSpace_word
F000_Set_CfgSpace_word	proc	near
		call	fProc_Set_CfgSpace_word
		ret
F000_Set_CfgSpace_word	endp

;[]================================================================[]
;Function : Far call to write PCI byte value
;Input  : CX - device + function number	, CURRENT_BUS_NO[bp] = bus No.
;Output : none
;[]================================================================[]
		Public	F000_Set_CfgSpace_Byte
F000_Set_CfgSpace_Byte	proc	near
		call	fProc_Set_CfgSpace_Byte
		ret
F000_Set_CfgSpace_Byte	endp

;[]================================================================[]
;Function : Far call to read PCI double word value
;Input  : CX - device + function number	, CURRENT_BUS_NO[bp] = bus No.
;Output : none
;[]================================================================[]
		Public	F000_Get_CfgSpace_Dword
F000_Get_CfgSpace_Dword	proc	near
		call	fProc_Get_CfgSpace_Dword
		ret
F000_Get_CfgSpace_Dword	endp

;[]================================================================[]
;Function : Far call to read PCI word value
;Input  : CX - device + function number	, CURRENT_BUS_NO[bp] = bus No.
;Output : none
;[]================================================================[]
		Public	F000_Get_CfgSpace_word
F000_Get_CfgSpace_word	proc	near
		call	fProc_Get_CfgSpace_word
		ret
F000_Get_CfgSpace_word	endp

;[]================================================================[]
;Function : Far call to read PCI Byte value
;Input  : CX - device + function number	, CURRENT_BUS_NO[bp] = bus No.
;Output : none
;[]================================================================[]
		Public	F000_Get_CfgSpace_Byte
F000_Get_CfgSpace_Byte	proc	near
		call	fProc_Get_CfgSpace_Byte
		ret
F000_Get_CfgSpace_Byte	endp

;[]============================================================[]
;Input	:	CH - Slot identification Number
;Output :	AX - VENDER ID
;Destroy:	AX
;[]============================================================[]
		ALIGN	4
		ASSUME	DS:NOTHING
		Public	F000_Get_Vendor_ID
F000_Get_Vendor_ID	Proc	Near

		call	fProc_Get_Vendor_ID
		ret

F000_Get_Vendor_ID	Endp

;[]==============================================================[]
;EPciRom_After_Init:
;	Force shadow RAM readonly after option ROM initialization
;Saves: all
;Input : none
;Output: None
;[]==============================================================[]
		ALIGN	4

EPciRom_After_Init	proc	near

		PUSH_ALL

IF	RELEASE_E000_FOR_PCI
	;Enable E0000-E7FFF shadow RAM read/write because we have
	;to release this area for PCI ROM

		F000_CALL E000_64k_Shadow_RW
ENDIF	;RELEASE_E000_FOR_PCI

;R21		push	dword ptr LMEM_BEFORE_ROM[bp]

;R21		mov	eax, LMEM_BEFORE_ROM[bp]
;R21		mov	edx, LMEM_RESOURCE[bp]
;R21		not	eax
;R21		and	edx, eax
;R21		mov	LMEM_BEFORE_ROM[bp], edx

;R21B - starts
;R68A		push	dword ptr LMEM_BEFORE_ROM[bp]
;R21C		mov	eax, LMEM_BEFORE_ROM[bp]
;R21C		mov	edx, LMEM_RESOURCE[bp]
;R21C		not	eax
;R21C		and	edx, eax
;R21C		mov	LMEM_BEFORE_ROM[bp], edx
;R21C - starts
		mov	eax, LMEM_BEFORE_ROM[bp]
		or	eax, LMEM_RESOURCE[bp]
		mov	LMEM_BEFORE_ROM[bp], eax
;R21C - ends
;R21B - ends

	;init NON-Compliance ROMs on all Buses

		call	Non_PCI_Compliance_ROM
		jc	@F			;CF = Already shadow

		call	Shadow_C8_To_DF
		call	Dis_Shadow_Not_Avail
	@@:

		ALIGN	4
;R21		pop	dword ptr LMEM_BEFORE_ROM[bp]
;R68A		pop	dword ptr LMEM_BEFORE_ROM[bp]	;R21B

		call	Init_ISA_roms_addr		;R23

	;special for NCR's SCSI devices


	;init Compliance ROMs on all Buses
;R35 - start
ifdef	LAST_INIT_FOR_LAN_ROM
	;scan non LAN devices
		mov	byte ptr DEVICE_CLASS_FLAG[bp],0
		call	PCI_Compliance_ROM

	;check if LAN card found
		test	byte ptr DEVICE_CLASS_FLAG[bp],LAN_FOUND
		jz	short NoLanRomScan
	;scan LAN devices
		or	byte ptr DEVICE_CLASS_FLAG[bp],LAN_NOW
endif;	LAST_INIT_FOR_LAN_ROM
;R35 - end

		call	PCI_Compliance_ROM
NoLanRomScan:						;R35

		call	Init_NCR810_ROM

	ifdef	COMBINE_ISA_ROM
		call	Init_Other_ROMs
	endif;	COMBINE_ISA_ROM

		call	init_isa_roms			;R23

;R21B		call	Shadow_C8_To_DF			;R21A
		call	Shadow_C8_To_DF			;R68

;R82	ifndef	CT_SHADOW_RW_HOOK_SUPPORT
;R82		F000_CALL Ct_C8_To_DF_R
;R82	else	;CT_SHADOW_RW_HOOK_SUPPORT
		call	Shadow_C8_To_DF_R
;R82	endif	;CT_SHADOW_RW_HOOK_SUPPORT

		call	Invalidate_Shadow_Seg		;invalidate whole shadow seg
							;i.e. shadow unit = 16K(32K)
							;     ==> invalidate whole
							;	  16k(32k) even if it
							;	  is not totally used!
		mov	si, 1
		call	EDisable_UnUsed_Shadow

;R82 - starts
ifdef	SHADOW_UNIT_64K
ifdef	USB_SUPPORT
;R92B;R92		cmp	byte ptr LMEM_RESERVED[bp], 0	;C8-CF reserved by USB?
;R92B;R92		jne	@F				;yes!
;R92B;R92 - start
;R92B		test	byte ptr LMEM_RESERVED[bp],0f0h	;C8-CF reserved by USB?	
;R92B		jnz	short @F 			;yes!	;R92A
;R92B;R92A		jz	@F				;yes!	
;R92B;R92 - end
;R92B	;Set shadow write-protected, if no USB legacy occupied C-segment.
;R92B		call	F_C000_Shadow_R
;R92B	@@:
;R92B - start
		cmp	byte ptr PCI_VGA_FOUND[bp], VGA_DEVICE_EXIST ;PCI VGA existed
		jne	short @F
;R92C		test	byte ptr LMEM_RESERVED[bp],0fh	;C8-CF reserved by USB?	
		test	byte ptr LMEM_RESERVED[bp],0ffh	;C8-CF reserved by USB?	;R92C
		jnz	short @F 			;yes!
	;Set shadow write-protected, if no USB legacy occupied C-segment.
		call	F_C000_Shadow_R	
	@@:
;R92B - end
endif	;USB_SUPPORT
endif	;SHADOW_UNIT_64K
;R82 - endif

;Enable/Disable VGA Palette snoop according to setup

		cmp	byte ptr PCI_VGA_FOUND[bp], VGA_DEVICE_EXIST ;PCI VGA existed
		jne	No_PciVga_Found

		mov	si, offset Vga_Snoop_Item
		call	F000_GetItem_Value
		or	al, al
		jz	No_VgaSnoop

		mov	cx, PCI_VGA_INFO[bp]	;ah = bus no. al=dev+fun no
		mov	bh, ch			;bus no.
		xchg	ch, cl
		mov	cl, 04H			;command register
		F000_CALL Aget_CfgSpace_Word
		or	al, 20H			;enable VGA snoop
		F000_CALL ASet_CfgSpace_Word
No_VgaSnoop:
No_PciVga_Found:

IF	RELEASE_E000_FOR_PCI
;--------------------------------------------------------------
;clear the un-used E0000-E7FFF shadow RAM to FFh for EMM386 UMB
;--------------------------------------------------------------

		mov	al, LMEM_RESOURCE[bp+3]	;save for atbase.asm
						;to check if E000 shadow RAM
						; occupied by PCI ROM
		mov	si, offset E000_USED_BY_PCI
		mov	cs:[si], al

		mov	cx, 08000h		;32k to clear
		mov	di, 0E000h		;starting from E000h
	@@:
		or	al, al
		jz	@F
		shr	al, 1
		add	di, 100h		;update starting addr. to clr
		sub	cx, 1000h		;add 4k more to clear
		jmp	@B
	@@:
		or	ch, ch
		jz	No_Need_Clear_E0
		mov	es, di			;Clear shadow with 0FFh
		xor	di, di			;Clear shadow with 0FFh
		cld				;Clear shadow with 0FFh
		mov	al, -1			;Clear shadow with 0FFh
		rep	stosb			;Clear shadow with 0FFh

	No_Need_Clear_E0:

		F000_CALL E000_64k_Shadow_R

ENDIF	;RELEASE_E000_FOR_PCI

		mov	byte ptr LMEM_FOR_ROM_FLG[bp], 1

;R33;R09 - start
;R33ifdef	Trend_AntiVirus
;R33		pushad
;R33;R09A		push	di
;R33		push	es
;R33		push	ds
;R33
;R33;R09A - start
;R33		mov	si,offset Virus_Item	;virus protection setup item
;R33		call	F000_GetItem_Value	;read CMOS setting
;R33		or	al,al			;virus protection enabled ?
;R33		jnz	Not_trend		;no skip virus ROM initial
;R33;R09A - end
;R33
;R33		mov	di, (07h+1)*4		;Cbrom /vrs number ID
;R33		call	POST_decompress		;Decompress to 4000:0
;R33		jc	Not_trend
;R33
;R33		push	4000h
;R33		pop	ds
;R33		mov	cl, ds:[2]     		;get rom size of 4000:2
;R33		pop	ds
;R33		push	ds			;balance stack	;R09A
;R33
;R33		mov	al, cl
;R33		shr	cl, 3			;patch 4k rom size
;R33		and	al, 07h
;R33		or	al, al
;R33		jz	short @f
;R33		inc	cl
;R33	@@:
;R33		call	EGet_Available_LMEM	;ask for LOW MEM
;R33		jc	Not_trend		;no shadow available
;R33
;R33		push	cx
;R33		dec	cx
;R33		mov	eax, 0FFFFFFFEh
;R33		shl	eax, cl
;R33		not	eax
;R33
;R33		mov	ecx, AVAIL_LMEM_ADDR[bp]
;R33		shr	ecx, 12
;R33		sub	cl, 0C8h
;R33		shl	eax, cl
;R33		or	LMEM_RESERVED[bp], eax
;R33
;R33		push	0f000h
;R33		pop	es
;R33		F000_call	F000_Shadow_W		;Get a space to save
;R33		mov	si, offset Virus_Used_Shadow	;used shadow
;R33
;R33;Enable using shadow block that can be read and write
;R33;R26		pop	cx
;R33;R26		push	cx
;R33
;R33;R26 - statr
;R33		F000_call Ct_Shadow_Unit
;R33		mov	di, 0fch
;R33		mov	ax, 4
;R33		cmp	cx, 4000h
;R33		je	short @F
;R33		mov	di, 0f8h
;R33		mov	ax, 8
;R33@@:
;R33;R26 - end
;R33;record region of shadow
;R33
;R33		mov	ebx, AVAIL_LMEM_ADDR[bp]
;R33		shr	ebx, 12			;BL is Trend_AntiVirus start
;R33		mov	bh, bl
;R33;R26		and	bh, 0fch		;BH is shadow open start
;R33
;R33		push	di			;R26
;R33		pop	cx			;R26
;R33		and	bh, cl			;R26
;R33
;R33		mov	dl, bl
;R33
;R33		pop	cx			;R26
;R33		push	cx			;R26
;R33
;R33		add	dl, cl			;DL is Trend_AntiVirus end
;R33		mov	dh, dl
;R33
;R33		push	ax			;R26
;R33
;R33		mov	ah, dl
;R33		and	ah, 03h
;R33		or	ah, ah
;R33		jz	short @f
;R33		inc	dh			;DH is shadow end
;R33	@@:
;R33		pop	cx    			;R26Get AX value
;R33		push	bx
;R33	@@:
;R33		pushad
;R33		mov	dh, bh
;R33		F000_Call	Ct_Shadow_RW
;R33		popad
;R33		mov	ah, bh
;R33;R26		add	bh, 04h
;R33		add	bh, cl			;R26
;R33		cmp	bh, dh
;R33		jb	short @b
;R33		pop	bx
;R33		mov	al, bh
;R33		mov	es:[si], ax	 	;store ax to Virus_Used_Shadow
;R33
;R33		F000_call	F000_Shadow_R
;R33
;R33		pop	cx
;R33		shl	ecx, 11			;Move times by word
;R33		mov	si,4000h		;SI: Source SEG
;R33		mov	edi,AVAIL_LMEM_ADDR[bp]	;EDI: available shadow RAM
;R33		shr	edi,4			;DI: destination SEG
;R33		F000_CALL Move_Codes
;R33		call 	Init_ROM		;invoke virus ROM
;R33
;R33Not_trend:					;R09A
;R33		pop	ds			;R09A
;R33		pop	es
;R33;R09A		pop	di
;R33	     	popad
;R33;R09ANot_trend:
;R33endif; Trend_AntiVirus
;R33;R09 - end

		call	PatchRomAlignMent		;R22
;R78A		call	Set_IDE_DMA_Capable		;R78
;R91 - starts
	ifdef	PciLanROM_Control
		call	Restore_Onboard_PCI_Lan
	endif	;PciLanROM_Control
;R91 - ends
		POP_ALL

		ret

EPciRom_After_Init	endp

;R91 - starts
ifdef	PciLanROM_Control
		PUBLIC	Restore_Onboard_PCI_Lan
Restore_Onboard_PCI_Lan	PROC	near

		mov	byte ptr CURRENT_BUS_NO[bp], 0
		mov	ch, (Onboard_PCI_LAN) shl 3	;device/function number
		mov	cl, 04h				;register = 4 (command)
;R91A		mov	ax,Xgroup_Segment
;R91A		mov	ds,ax
;R91A		lea	si,LAN_COMMAND_WORD		;get offset
;R91A		mov	ax,[si]				;restore value in AX
		mov	ax,POST_Stack_Temp_Word[bp]	;R91A restore value in AX
		call	fProc_Set_CfgSpace_Word

		ret

Restore_Onboard_PCI_Lan	ENDP
endif	;PciLanROM_Control
;R91 - ends

;R78A;R78 start
;R78ASet_IDE_DMA_Capable	proc	far
;R78A
;R78A		xor	bh,bh			;bus 0
;R78A		xor	ch,ch			;start device 0,function 0
;R78ASIDC_Loop:
;R78A		mov	cl,0ah			;offset 0Ah (class code)
;R78A		F000_call	AGet_CfgSpace_Word
;R78A		cmp	ax,0ffffh		;invalid?
;R78A		je	short Next_Device	;Yes,skip
;R78A
;R78A		cmp	ax,101h			;IDE device?
;R78A		jne	short Next_Device	;Yes,skip
;R78A
;R78A		mov	cl,20h			;offset 20h (DMA base port)
;R78A		F000_call	AGet_CfgSpace_Word
;R78A		and	ax,0fff0h		;isolate useful bits
;R78A		jz	short Next_Device	;invalid then skip
;R78A
;R78A		mov	dx,ax			;DX = base port
;R78A		and	dx,0fff0h		;isolate useful bits
;R78A		add	dl,2			;set to status register of primary
;R78A		in	al,dx			;get original data
;R78A		or	al,60h			;set drive 0,1 DMA capable
;R78A		out	dx,al			;send to port
;R78A
;R78A		add	dl,8			;set to status register of secondary
;R78A		in	al,dx			;get original data
;R78A		or	al,60h			;set drive 0,1 DMA capable
;R78A		out	dx,al			;send to port
;R78ANext_Device:
;R78A		inc	ch			;next device and function
;R78A		jnz	short SIDC_Loop		;not exceed then continue
;R78A
;R78A		ret
;R78ASet_IDE_DMA_Capable	endp
;R78A;R78 end

;R23 START
;[]==============================================================[]
;INIT_ISA_ROMS_ADDR:
;Input : none
;Output: None
;NOTE:This func is CBROM /isa with assign address.(40A0h to 40A3h)
;[]==============================================================[]
		ALIGN	4
INIT_ISA_ROMS_ADDR	proc	near
		push	ds
		push	es
		push	bp

		mov	bx,Temp_EXP_Seg			;cbrom table segment
		mov	es,bx
		mov	di,(0a0h+1)*4			;cbrom /isa table offset
							;start
next_isa_rom_addr:
		push	di
		mov	ebx,es:[di+Temp_EXP_Off]
		or	ebx,ebx
		jz	short No_rom_exit
		cmp	bx,0ffffh
		je	short No_rom_exit

		call	combined_isa_addr	;cbrom /isa compress address
		cli
		call	E000_A20_On
		call	E000_Enter_Prot_mode		;enter protected mode
		call	E000_Back_Real_Mode		;R47
		xor	edx,edx
		mov	dx, ds:[ebx+0fh]		;assign address(offset)
		shl	edx, 4
		mov	AVAIL_LMEM_ADDR[bp], edx
		mov	word ptr ds:[ebx+0fh], 0	;clear offset to decompress
;R47		call	E000_Back_Real_Mode
		call	E000_A20_Off

		or	edx,edx				;have address?
		jz	short No_rom_exit

		call	post_decompress
		call	get_rom_size
		call	lmem_flg_mask
		test	eax,LMEM_RESOURCE[bp]
		jnz	short No_rom_exit
		or	LMEM_RESOURCE[bp], eax
		call	copy_rom_shadow_init
No_rom_exit:
		pop	di
		add	di, 4
		cmp	di, (0a3h+1)*4		     ;cbrom /isa table offset
						     ;end
		jb	next_isa_rom_addr

		pop	bp
		pop	es
		pop	ds
		ret
INIT_ISA_ROMS_ADDR	endp
;[]==============================================================[]
;INIT_ISA_ROMS:
;Input : none
;Output: None
;NOTE:This func is CBROM /isa not assign address.(40A4h to 40A7h)
;[]==============================================================[]
		ALIGN	4
Init_ISA_ROMS	proc	near
		push	ds
		push	es
		push	bp

		mov	bx,Temp_EXP_Seg		     ;cbrom table segment
		mov	es,bx
		mov	di,(0a4h+1)*4		     ;cbrom /isa table offset
						     ;start
next_isa_rom:
		push	di
		mov	ebx,es:[di+Temp_EXP_Off]
		or	ebx,ebx
		jz	short No_isa_rom_exit
		cmp	bx,0ffffh
		je	short No_isa_rom_exit

		call	post_decompress
		call	get_rom_size
		call	EGet_Available_LMEM 		;request low mem
		jc	No_isa_rom_exit			;no shadow available
		call	copy_rom_shadow_init
No_isa_rom_exit:
		pop	di
		add	di, 4
		cmp	di, (0a7h+1)*4		      ;cbrom /isa table offset
						      ;end
		jb	short next_isa_rom

		pop	bp
		pop	es
		pop	ds
		ret
Init_ISA_ROMS	endp
;[]==============================================================[]
;combined_isa_addr:
;Input : DI : cbrom number. e.g -> 40A0h , DI = (0A0h+1)*4
;Output: EBX : physical address
;[]==============================================================[]
		ALIGN	4
combined_isa_addr	proc	near
;R55ifdef	Flash_2M_support
;R55		mov	ebx, 160000h			;extra option ROM temp address
;R55		cmp	es:[di+Temp_EXP_Off+2], 8000h	;first segment
;R55		je	@F				;Yes, skip
;R55		add	ebx, 10000h			;set to next sgment (170000h)
;R55@@:
;R55		add	bx, es:[di+Temp_EXP_Off]	;set to physical address
;R55else	;Flash_2M_support
;R55		xor	ebx, ebx
;R55		mov	bx, es:[di+Temp_EXP_Off+2]
;R55		shl	ebx, 4
;R55		add	bx, es:[di+Temp_EXP_Off]	;set to physical address
;R55endif	;Flash_2M_support
		mov	ebx,es:[di+Temp_EXP_Off]	;R55
ifdef	Flash_2M_support				;R55
		add	ebx,0e0000h			;R55
endif	;Flash_2M_support				;R55
		ret
combined_isa_addr	endp
;[]==============================================================[]
;get_rom_size:
;Input : NONE
;Output: CL : ROM size (at 4k)
;[]==============================================================[]
		ALIGN	4
get_rom_size	proc	near
		push	4000h
		pop	ds
		mov	cl,ds:[2]			;ROM size
		shr	cl,3
		and	al, 07h
		or	al, al
		jz	short @f
		inc	cl
@@:
		ret
get_rom_size	endp
;[]==============================================================[]
;copy_rom_shadow_init:Copy ROM at 4000:0 to shadow(AVAIL_LMEM_ADDR[bp])
;		      & initiation
;Input : NONE
;Output: NONE
;[]==============================================================[]
		ALIGN	4
copy_rom_shadow_init	proc	near
		mov	edi, AVAIL_LMEM_ADDR[bp]
		shr	edi, 4
		push	di

		mov	si, 4000h
		xor	al, al
		call	ECopy_ROM			;copy rom to shadow

		pop	bx
		mov	dx, bx
		push	bp
		F000_call	R_Mod_Ck		;init rom
		pop	bp
		ret
copy_rom_shadow_init	endp
;[]==============================================================[]
;lmem_flg_mask:
;Input : CL -> rom size (at 4k)
;Output: EAX -> need shadow address(e.g c800 at 0000000f)
;[]==============================================================[]
		ALIGN	4
lmem_flg_mask	proc	near
		mov	edi, AVAIL_LMEM_ADDR[bp]
		shr	edi, 4

		dec	cl
		mov	eax, 0FFFFFFFEh
		shl	eax, cl
		not	eax

		mov	cx, di
		shr	cx, 8
		sub	cl, 0C8h
		shl	eax, cl
		ret
lmem_flg_mask	endp
;R23 END

;R22 - start
;Function : Report device node for the option ROM have smaller ROM size than
;	    shadow unit.
;Input    : none
;Output   : none
;Note     : This routine is used to patch mishandling device driver of Intel
;	    LAN chip 82558 while Win95 enter and exit suspend mode if there
;	    is option ROM and the size is not aligned with shadow unit.
PatchRomAlignMent	proc	near
ifdef	PNP_BIOS
		mov	esi,0E0000H - (2*1024)	;start from high UMB

Next2KbRomChk:
		ror	esi, 4			;get segment address
		mov	ds,si			;setup segment
		rol	esi, 4			;restore esi

		cmp	word ptr ds:[0],0AA55H	;option ROM
		je	short OptionRomYes

NoPatchAlignForISA:							;R22C

		sub	esi, 2*1024		;next 2Kb
;R22B		cmp	esi, 0C8000H		;lowest ROM address
		cmp	esi, 0C0000H		;lowest ROM address;R22B
		jb	short PatchRomExit
		jmp	short Next2KbRomChk

OptionRomYes:

;R22C - starts
ifndef	NO_ISA_BUS				;R80
	;Only build device node for PCI option ROM.
		mov	bx, ds:[18h]
		cmp	dword ptr ds:[bx], 'RICP';It's a PCI option ROM ?
		jne	NoPatchAlignForISA	;no, no patch needed
						;yes, patch it.
endif;	NO_ISA_BUS				;R80
;R22C - ends

	;ROM found, check it if align with shadow unit
		movzx	edi,byte ptr ds:[2]	;get ROM size
		shl	edi,9

		add	edi,esi			;start address

;R82 - starts
ifdef	SHADOW_UNIT_64K
		mov	ecx, 010000h
		mov	edx, 0FFFF0000h
else	;SHADOW_UNIT_64K
;R82 - ends
		xor	ecx,ecx
		F000_call Ct_Shadow_Unit 	;shadow unit in cx
		mov	ebx,esi			;ROM address

;R82;R80 - start
;R82		mov	edx,0FFFF0000H		;assume 64KB shadow unit
;R82		or	cx, cx			;64KB unit ?
;R82		jz	short Not16KUnit
;R82;R80 - end

		mov	dx, 08000h		;assume 32k unit
		cmp	ch,40h			;16k unit ?
		jne	short Not16KUnit
		or	dh,40h
Not16KUnit:
endif	;SHADOW_UNIT_64K			;R82
;R80		and	bx,dx
		and	ebx, edx		;R80 mask bits for size check
ChkRomSize:	  				;R22A
		add	ebx,ecx
		cmp	ebx,edi			;R22A size over one shadow
		jb	short ChkRomSize	;R22A unit ?

		sub	ebx,edi			;remainder size to declare
		jz	short PatchRomExit	;ROM size is aligned

		extrn	Build_MbRomDynamicNode:near
		call	Build_MbRomDynamicNode 	;build ROM node

PatchRomExit:

endif;	PNP_BIOS
		ret
PatchRomAlignMent	endp
;R22 - end

ifdef	COMBINE_ISA_ROM
;-----------------------------------------------------------
;Function : Initial option ISA ROM added by switch /other
;
;Input    : none
;
;Output   : LMEM_RESOURCE[bp] modified by option ROM size
;-----------------------------------------------------------
Init_Other_ROMs	proc	near

		pushad

		mov	edi, 800h			; 1800:0

	Scan_Other_Combine_Isa_ROM:

		push	edi

		call	Find_Valid_ROM_Image 	 	;any of them valid?
		jc	No_OtherRom			;no valid !

	;if it is a PCI ROM, skip it

		mov	di, word ptr ds:[18h]
		cmp	dword ptr ds:[di], 'RICP'
		je	No_OtherRom

		mov	byte ptr LMEM_FOR_ROM_FLG[bp], 1;shadow RAM for ROM

		mov	cl, ds:[2]			;get ROM size
		xor	ch, ch
		shr	cx, 3				;by 4k unit
		adc	cx, 0
		push	cx				;save rom size

		push	dword ptr LMEM_RESOURCE[bp]
		call	EGet_Available_LMEM     	;ask for LOW MEM
		pop	dword ptr LMEM_RESOURCE[bp]
		pop	cx				;restore rom size
		jc	No_OtherRom			;no shadow available

;R09	ifdef	Trend_AntiVirus
;R09
;R09		pop	edi
;R09		push	edi
;R09		cmp	di, 1C00h
;R09		jne	Not_Trend
;R09
;R09		pushad
;R09		push	cx
;R09
;R09		dec	cx
;R09		mov	eax, 0FFFFFFFEh
;R09		shl	eax, cl
;R09		not	eax
;R09
;R09		mov	ecx, AVAIL_LMEM_ADDR[bp]
;R09		shr	ecx, 12
;R09		sub	cl, 0C8h
;R09		shl	eax, cl
;R09		or	LMEM_RESERVED[bp], eax
;R09
;R09		pop	cx
;R09		popad
;R09
;R09	Not_Trend:
;R09	endif	;Trend_AntiVirus

		mov	edi, AVAIL_LMEM_ADDR[bp]	;EDI: available shadow RAM
		shr	edi, 4				;DI: destination SEG

		mov	al, 1				;copy according to CX
		call	ECopy_ROM			;copy ROM to shadow

		call 	Init_ROM			;invoke NCR810 ROM

	;Recalculate available low memory size due to ROM size changed

		mov	eax, AVAIL_LMEM_ADDR[bp]
		mov	TARGET_AVAIL_LMEM[bp], eax
		shr	eax, 4
		call	Recalibrate_LMEM_For_ROM

ifdef	PNP_BIOS
	;build memory used by Motherboard to prevent SCT test failure
		mov	edi, AVAIL_LMEM_ADDR[bp]	;EDI: available shadow RAM
		call	Build_OtherRomNode
endif;	PNP_BIOS

No_OtherRom:

		pop	edi
		add	di, 0080h
		cmp	di, 2000h
		jb	Scan_Other_Combine_Isa_ROM

		popad
		ret

Init_Other_ROMs	endp
endif;	COMBINE_ISA_ROM

;[]==============================================================[]
;Pci_CbRom_decompress:
;
;Description:
;
;
;Input : compress_bp_start = option ROM start index (depand on CBROM.EXE utility)
;	 compress_bp_end = option ROM end index (depand on CBROM.EXE utility)
;        decompress_add_start = device and vender ID store buffer start address
;Output: None
;
;  - 200000h (start)
;  |	VGA Drive Rom Vendor & Device ID and potect_mode address
;  |	Index.
;  - 20002fh (end)
;  - 200030h (start)
;  |	VGA Drive Rom Vendor & Device ID and potect_mode address
;  |	Index.
;  - 2000A0h (end)
;  - 200100h (start)
;  |
;  |
;  |	All VGA & PCI Device ROM decompress pool.
;  |
;  |
;  -
;[]==============================================================[]
		ALIGN	4
		Public	fProc_Pci_CbRom_decompress
fProc_Pci_CbRom_decompress	Proc	Far

		push	ds
		push	es
		mov	esi, 200100h			;temp store decompress code address start
		mov	ax, CBROM_BP_START[bp]
		mov	di, ax
		mov	edx, CBROM_BUF_START[bp]

Decomp_PCI_Loop:

		push	edx
		push	esi				;push temp store decompress code address start to stack
		push	di
		call	POST_decompress			;decompress cbrom pool
		pop	di
		pop	esi				;pop temp store decompress code address start from stack
		pop	edx
		jc	NO_PCI_TABLE

		push	ebx			;R84 store original ROM size
		mov	bx, Temp_EXP_Seg
		mov	es, bx
;R55	ifdef	Flash_2M_support
;R55		mov	ebx, 160000h			;extra option ROM temp address
;R55		cmp	es:[di+Temp_EXP_Off+2], 8000h	;first segment
;R55		je	@F				;Yes, skip
;R55		add	ebx, 10000h			;set to next sgment (170000h)
;R55	@@:
;R55		add	bx, es:[di+Temp_EXP_Off]	;set to physical address
;R55	else	;Flash_2M_support
;R55		xor	ebx, ebx			;R02B
;R55		mov	bx, es:[di+Temp_EXP_Off+2]	;R02B
;R55		shl	ebx, 4				;R02B
;R55		mov	bx, es:[di+Temp_EXP_Off]
;R55	endif	;Flash_2M_support
		call	combined_isa_addr		;R55
		pop	ebx			;R84 restore original ROM size
		push	di
		push	es
		push	edx
		push	esi				;push temp store decompress code address start to stack

;-----------------------           -----------------------------

		push	ebx			;R84 store original ROM size
		cli
		call	E000_A20_On
		call	E000_Enter_Prot_mode		;enter protected mode
;R47A		call	E000_Back_Real_Mode		;R47
		mov	ax, ds
		mov	es, ax
		call	E000_Back_Real_Mode		;R47A
;R84		mov	ecx, es:[ebx+0bh]
		pop	ecx			;R84 restore original ROM size
		add	ecx, 3
		and	ecx, not 3
		mov	esi, 40000h
		pop	edi				;pop temp store decompress code address start from stack

		pop	edx
		mov	ebx, 40000h
		mov	bx, ds:[esi+18h]		;point to PCIR offset
		mov	eax, ds:[ebx+4]			;get Vendor and Device ID from option ROM
		mov	es:[edx], eax			;store to temp buffer
		mov	es:[edx+4], edi			;store physical address to temp buffer
		add	edx, 8

		shr	ecx, 2
		cld
;R07 - starts
		cmp	byte ptr PCI_CBROM_TEMP[bp], 0
		jne	@F
		cmp	dword ptr ds:[70000h], 0AA55h
		je	@F
		pushad
		mov	edi, 70000h
 		db	67h
 		rep	movsd				;move original option ROM code to
		popad
	@@:
;R07 - ends
 		db	67h
 		rep	movsd				;move original option ROM code to
							;protect mode temp address from 200100h
		push	edi

;R47		call	E000_Back_Real_Mode
		call	E000_A20_Off
;----------------------------------------------------
		pop	esi
		pop	es
		pop	di
NO_PCI_TABLE:
		add	di, 4
		mov	ax, CBROM_BP_END[bp]
		cmp	di, ax
		jb	Decomp_PCI_Loop

		cmp	byte ptr PCI_CBROM_TEMP[bp], -1	;is't PCI flag for pci_cbrom_decompress subroutine
		jne	Pci_CbRom_decompress_End

	;-------------------------------

		mov	ax, 800h

	Compatible_Move:

		push	ax

		mov	ds, ax
		cmp	ds:[0], 0AA55h			;800:0h have pci Decice rom ?
		jne	No_ROM_Here

		push	ds
		push	esi
		mov	bx, ds:[18h]
		mov	eax, ds:[bx+4]

;R03		cmp	ax, NCR_VENDOR_ID
;R03		jne	@F
;R03		and	eax, 0FFFFh
;R03	@@:
		mov	cx, ds:[2]
		shl	cx, 9
		push	eax
		push	cx
		call	E000_Enter_Prot_Mode
		call	E000_Back_Real_Mode		;R03
		pop	cx
		pop	eax
		pop	edi
		pop	si
		movzx	esi, si
		shl	esi, 4

		mov	dword ptr ds:[edx], eax
		mov	dword ptr ds:[edx+4], edi
		add	edx, 8				;R02A
	@@:
		mov	eax, ds:[esi]
		mov     ds:[edi], eax
		add	edi, 4
		add	esi, 4
		loop	@B

		push	edi
;R03		call	E000_Back_Real_Mode
		pop	esi

	No_ROM_Here:

		pop	ax
		cmp	ax, 1000h
		mov	ax, 1000h
		jne	Compatible_Move

	Pci_CbRom_decompress_End:

		pop	es
		pop	ds
		ret

fProc_Pci_CbRom_decompress	endp

;[]-------------------------------------------------------------------[]
;Function : Build PCI/IRQ routing table for Microsoft specification
;Input    : none
;Output   : none
;[]-------------------------------------------------------------------[]
		public	Build_MsPciIrq
Build_MsPciIrq	proc	near

IF	MSIRQROUT_SUPPORT

		F000_CALL F000_Shadow_W

		mov	si, offset MsPciIrqTbl
		mov	ax, SEG MsPciIrqTbl
		mov	ds, ax

IF	USB_ONBOARD
		pushad
		mov	ax, 0B109h		;read word
		mov	bx, USB_ONBOARD		;bus, dev & func no
		xor	di, di			;reg 0 (Vendor ID)
		int	1Ah			;invoke PCI read
		cmp	cx, 0FFFFh		;USB controller exist?
		popad
		jne	@F			;yes!

		sub	word ptr ds:[si+6], 16	;change the table size
		mov	di, offset PciIrqTbl_Size
		sub	word ptr ds:[di], 16
	@@:
ENDIF	;USB_ONBOARD

		mov	cx, [si+6]		;No. of byte for checksum
		cld
		xor	ah, ah			;initial
NextMsPciByte:
		lodsb
		add	ah, al
		loop	NextMsPciByte

		not	ah			;invert byte to zero checksum
		inc	ah
		mov	si, (offset MsPciIrqTbl)+31;checksum location
		mov	[si], ah		;save checksum value

		F000_CALL F000_Shadow_R

ENDIF	;MSIRQROUT_SUPPORT

		ret

Build_MsPciIrq	endp

IF	RELEASE_E000_FOR_PCI
		Public	E000_USED_BY_PCI
E000_USED_BY_PCI	db	0
ENDIF	;RELEASE_E000_FOR_PCI

;R82 ifdef	CT_SHADOW_RW_HOOK_SUPPORT
;[]==============================================================[]
;Shadow_C8_To_DF_R:
;	Force all shadow to read only after all PCI ROM done
;Input:		none
;Output:	none
;[]==============================================================[]
		ALIGN	4
Shadow_C8_To_DF_R:
;R82 - starts
ifdef	SHADOW_UNIT_64K
	ifdef	USB_SUPPORT
		test	dword ptr LMEM_RESERVED[bp], 00FFFF00h	;reserved by others?
		jnz	@F
	endif	;USB_SUPPORT
		pushad
		mov	dx, 0D000h
		F000_CALL Ct_Shadow_R
		popad
	@@:
		ret

else	;SHADOW_UNIT_64K
;R82 - starts

		pushad
		F000_CALL Ct_Shadow_Unit		;shadow unit in CX
		mov	dx, 0C800h			;start segment
		mov	bx, cx				;size in byte
		shr	bx, 4				;convert to segment
		mov	eax, 0000000Fh			;mask value
		mov	cl, 4				;shift value
		cmp	bx, 400h			;size in 16KB?
		je	Shadow_C8_To_DF_R_Loop
		mov	eax, 000000FFh			;mask value
		mov	cl,  8				;shift value

Shadow_C8_To_DF_R_Loop:

	ifdef	USB_SUPPORT				;R82
		test	LMEM_RESERVED[bp], eax		;reserved by others?
		jnz	Shadow_C8_To_DF_R_Next
	endif	;USB_SUPPORT				;R82

		pushad
		F000_CALL Ct_Shadow_R
		popad

Shadow_C8_To_DF_R_Next:

		shl	eax, cl
		add	dx, bx
		test	eax, 0FF000000h			;E000 arrived?
		jz	Shadow_C8_To_DF_R_Loop

		popad
		ret

endif	;SHADOW_UNIT_64K			;R82
;R82 endif	;USB_SUPPORT

;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
		ALIGN	4
Shadow_C8_To_DF	Proc	Near
;R82 - starts
ifdef	SHADOW_UNIT_64K

		cmp	byte ptr LMEM_BEFORE_ROM[bp], 0FFh		;R90
		je	@F						;R90
		F000_call C000_Shadow_RW
	@@:								;R90

	ifdef	USB_SUPPORT
		test	dword ptr LMEM_RESERVED[bp], 00FFFF00h
		jnz	@F
	endif	;USB_SUPPORT

		mov	si, 0D000h
		mov	di, TEMP_AREA
		mov	al, 1
		mov	cx, 16
		pusha
		call	ECopy_ROM
		mov	dx, 0D000h
		F000_call Ct_Shadow_RW
		popa

		xchg	si, di
		call	ECopy_ROM
	@@:
		ret

else	;SHADOW_UNIT_64K
;R82 - ends
		mov	si, 0C800h
		mov	di, TEMP_AREA

		call	GG

	ifndef	USB_SUPPORT
		F000_CALL Ct_C8_To_DF_RW
	endif	;USB_SUPPORT

		mov	si, TEMP_AREA

		mov	di, 0C800h

	ifdef	USB_SUPPORT

		F000_CALL Ct_Shadow_Unit		;shadow unit in CX
		mov	bx, cx				;size in byte
		shr	bx, 4				;convert to segment
		mov	al, 1				;flag for Copy_ROM
		mov	edx, 0000000Fh			;mask value
		mov	cx, 4				;size 4KB*4=16KB
		cmp	bx, 400h			;size in 16KB?
		je	Shadow_C8_To_DF_Loop
		mov	edx, 000000FFh			;mask value
		mov	cx,  8				;size 8KB*4=32KB

	Shadow_C8_To_DF_Loop:

		test	LMEM_RESERVED[bp], edx		;reserved by others?
		jnz	Shadow_C8_To_DF_Next

		pushad
		mov	dx, di				;DX=seg to R/W shadow
		F000_CALL Ct_Shadow_RW
		popad

		pushad
		call	ECopy_ROM
		popad

	Shadow_C8_To_DF_Next:

		add	si, bx				;next source segment
		add	di, bx				;next dest. segment
		shl	edx, cl				;next mask value

		test	edx, 0FF000000h			;E000 arrived?
		jz	Shadow_C8_To_DF_Loop

		ret
	endif	;USB_SUPPORT

	GG:
		mov	al, 1
		mov	cx, 24
		call	ECopy_ROM

		ret

endif	;SHADOW_UNIT_64K				;R82

Shadow_C8_To_DF	Endp

;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
		ALIGN	4
Request_LMEM_For_ROM	Proc	Near

		mov	byte ptr LMEM_FOR_ROM_FLG[bp], 1; 1 = request addr.
							;     for ROM init
		jmp	@F

Recalibrate_LMEM_For_ROM	Label	Near

		mov	byte ptr LMEM_FOR_ROM_FLG[bp], 2; 2 = request addr.
							;     for run time
	@@:
		push	cx
		mov	ds, ax
		call 	Rom_In_Terms_of_4K

		call	EGet_Available_LMEM		;request low mem
		pop	cx

		ret

Request_LMEM_For_ROM	Endp

;--------------------------------------------------------------------
;After setting the shadow segment C8-DF to be R/W, we have to unshadow
;those segments which is originally not avaible for LMEM. This is very
;critical for PCI devices which request low memory & ROM init at the
;same time
;--------------------------------------------------------------------
Dis_Shadow_Not_Avail	Proc	Near

		pushad

		push	dword ptr LMEM_RESOURCE[bp]
;R21		push	dword ptr LMEM_BEFORE_ROM[bp]
;R21		pop	dword ptr LMEM_RESOURCE[bp]
		push	dword ptr LMEM_BEFORE_ROM[bp]		;R21B
		pop	dword ptr LMEM_RESOURCE[bp]		;R21B

		xor	dword ptr LMEM_RESOURCE[bp], -1
		xor	si, si
		call	EDisable_UnUsed_Shadow
		pop	dword ptr LMEM_RESOURCE[bp]

		popad
		ret

Dis_Shadow_Not_Avail	Endp

ifndef	No_C8_DF_Shadow_Item			;R27
		ALIGN	4
Shadow_Items:
		dw	offset DGROUP:C800_Item
		dw	offset DGROUP:CC00_Item
		dw	offset DGROUP:D000_Item
		dw	offset DGROUP:D400_Item
		dw	offset DGROUP:D800_Item
		dw	offset DGROUP:DC00_Item
endif	;No_C8_DF_Shadow_Item			;R27

;--------------------------------------------------------------------
; Input:	BL = queried VGA BIOS size (512b unit)
; Output:	flags affected
;--------------------------------------------------------------------
Query_VGA_Size	proc	near

		push	ds
		push	ax
		mov	ax, 0C000h
		mov	ds, ax
		cmp	word ptr ds:[0], 0AA55h	;VGA BIOS exist?
		jne	@F			;skip if no VGA BIOS
		cmp	byte ptr ds:[2], bl	;compare BIOS size
		pop	ax
		pop	ds
		ret
	@@:
		cmp	al, bl			;no VGA BIOS, so always less
						; than BL
		pop	ax
		pop	ds
		ret

Query_VGA_Size	endp

;--------------------------------------------------------------------
;if any shadow segment is not used
;  ---> call hook in PCICHIP.ASM to disable it
;
;if any shadow segment is originally not available for PCI ROM
;  ---> if setup setting is set to ENABLE
;		do nothing
;	else
;		call hook in PCICHIP.ASM to disable it
;--------------------------------------------------------------------
		ALIGN	4
		Public	fPROC_Disable_UnUsed_Shadow		;R82
fPROC_Disable_UnUsed_Shadow	Proc	FAR			;R82
		call	EDisable_UnUsed_Shadow			;R82
		ret						;R82
fPROC_Disable_UnUsed_Shadow	Endp				;R82
EDisable_UnUsed_Shadow	Proc	Near
;R82 - starts
ifdef	SHADOW_UNIT_64K

		mov	eax, 00FFFF00h
	ifdef	USB_SUPPORT
		test	LMEM_RESERVED[bp], eax	;reserved by others?
		jnz	@F
	endif	;USB_SUPPORT

		test	LMEM_RESOURCE[bp], eax	;D0000 used?
		jz	Dis_It			;no, disable shadow

		test	LMEM_BEFORE_ROM[bp], eax;originally available for PCI?
		jz	@F			;ZF = available & is
	Dis_It:
		pushad
		mov	dx, 0D000h
		F000_CALL Ct_Disable_Shadow
		popad
	@@:
		ret

else	;SHADOW_UNIT_64K
;R82 - starts
		mov	bx, 4			;assume shadow unit=16k
		mov	eax, 0000000Fh		;each time 16K
		F000_CALL Ct_Shadow_Unit	;check chipset shadow unit
		cmp	cx, 4000h		;really 16k unit?
		je	@F			;yes, go on
		mov	bx, 8			;set shadow unit=32k
		mov	eax, 000000FFh		;each time 32K
	@@:

		mov	cx, bx
		mov	dx, 0C800h		;starting from C800h
ifndef	No_C8_DF_Shadow_Item			;R27
		mov	di, offset Shadow_Items
endif	;No_C8_DF_Shadow_Item			;R27

	Keep_Disable_Shadow:

;R82ifdef	CT_SHADOW_RW_HOOK_SUPPORT
ifdef	USB_SUPPORT				;R82
		test	LMEM_RESERVED[bp], eax	;reserved by others?
		jnz	@f
endif	;USB_SUPPORT

		test	LMEM_RESOURCE[bp], eax	;this segment used?
		jz	Dis_It			;no, disable shadow

		test	LMEM_BEFORE_ROM[bp], eax;this segment originally
						;  available for PCI?
		jz	@F			;ZF = available & is
						;      used up by PCI ROM
						;so, let it stay shadowed

		or	si, si			;should check setup setting?
		jz	Dis_It			;no need, go ahead disable

		call	Chk_Setup_Shdw_Setting	;setup set shadow?
		jnz	@F			;yes, do not disable

	Dis_It:

		cmp	dx, 0D000h
		jae	No_Check_VGA_BIOS
		mov	bl, 60h
		call	Query_VGA_Size
		ja	@f
		cmp	dx, 0CC00h
		jae	No_Check_VGA_BIOS
		mov	bl, 40h
		call	Query_VGA_Size
		ja	@f

	No_Check_VGA_BIOS:

		pushad
		F000_CALL Ct_Disable_Shadow
		popad
	@@:
		shr	cx, 1
		add	di, cx
		shl	cx, 1

		add	dh, cl			;point to next shadow unit
		shl	eax, cl

		test	eax, 0FF000000h
		jz	Keep_Disable_Shadow

		ret
endif	;SHADOW_UNIT_64K			;R82

EDisable_UnUsed_Shadow	Endp

Chk_Setup_Shdw_Setting	Proc	Near

		pushad
ifndef	No_C8_DF_Shadow_Item			;R27
		mov	si, cs:[di]
		call	F000_GetItem_Value
		or	al, al
else	;No_C8_DF_Shadow_Item			;R27
		xor	al, al			;R27
endif	;No_C8_DF_Shadow_Item			;R27
		popad
		ret

Chk_Setup_Shdw_Setting	Endp

;[]================================================================[]
;[]================================================================[]
Init_ROM	Proc	Near

		PUSH_ALL
		mov	ah, CURRENT_BUS_NO[bp]		;bus number
		mov	al, ch				;device & func number
		mov	word ptr ds:[0], 3
		mov	ds:[2], es

	;------------------------------------------------------------
	;save the original ROM size in BX & push it into stack
	;------------------------------------------------------------
;R24		movzx	ebx, byte ptr es:[2]		;ROM size in 512K unit
;R24		shl	bx, 9				;in terms of byte
		movzx	ebx, byte ptr es:[2]		;R24 ROM size in 512K unit
		shl	ebx, 9				;R24 in terms of byte
;R24		push	bx				;save ROM size
		push	ebx				;R24 save ROM size
		push	es				;save ES

		call	dword ptr ds:[0]

	;------------------------------------------------------------
	;1. restore the original ROM size
	;2. compare with the new ROM size
	;3. if (NEW_SIZE < OLD_SIZE) clear the rest of the shadow RAM
	;------------------------------------------------------------
		pop	es
;R24		pop	bx			;original size in BX
		pop	ebx			;R24 original size in EBX
;R24		movzx	di, byte ptr es:[2]	;new size in CX
;R24		shl	di, 9			;in terms of byte
		movzx	edi, byte ptr es:[2]	;R24 new size in ECX
		shl	edi, 9			;R24 in terms of byte
						;DI=starting addr. to clear
;R24		sub	bx, di			;diff. in BX
		sub	ebx, edi		;diff. in EBX
		jbe	short @F		;if no diff then skip
;R24		mov	cx, bx			;no. of bytes in CX
		mov	ecx, ebx		;R24 no. of bytes in ECX
		mov	al, 0ffh		;PATTERN=0FFh
		cld
		rep	stosb
	@@:
		POP_ALL
		ret

Init_ROM	Endp

;-------------------------------------------------------------------------
;Input	:	CH = device & function number
;
;Output	:	CF : no ROM is needed
;		     reg. 30h set to 0
;		NC : ROM needed
;		     EAX = value of register 30h
;-------------------------------------------------------------------------
		ALIGN	4
Check_If_ROM_Needed	Proc	Near

		call	F000_Get_Device_ID  		;device ID in AX
		mov	CURRENT_DEVICE_ID[bp], ax

		call	F000_Get_Vendor_ID		;retrieve vendor ID
		mov	CURRENT_VENDOR_ID[bp], ax
		jc	No_ROM_Needed			;skip

;R16		call	Chk_If_Class_VGA  		;is it a VGA card?
;R16 - starts
		mov	cl, 0AH				;get class code
		call	F000_Get_CfgSpace_Word		;get class code
		mov	CURRENT_CLASS_CODE[bp], ax
		call	Chk_If_Class_VGA_1
;R16 - ends
		je	No_ROM_Needed			;yes, skip!

;R13A start
ifdef	lan_boot_support
		mov	ax,CURRENT_CLASS_CODE[bp]
		cmp	ah,02h				;is it a LAN card?
		jne	short not_lan_card		;No, skip!

		mov	si,offset LanBoot_Item
		call	F000_GetItem_Value
		or	al,al				;Lan boot disabled ?
		jz	No_ROM_Needed			;don't assign if disabled
not_lan_card:
endif	;lan_boot_support
;R13A end

		mov	cl, 04h				;if command word=0
		call	F000_Get_CfgSpace_Word		; it means this cfg
		or	ax, ax				; space has been
		jz	No_ROM_Needed			; killed in POST 0Bh
		or	al, 07H				;enable MEM, I/O
		call	Check_Master_Needed		;enable master or not?
		jnc	@F
		and	al, not 04h
	@@:
		call	F000_Set_CfgSpace_Word

		mov	cl, 30h				;Expansion. ROM Base Addr. reg.
		call	F000_Get_CfgSpace_Dword

ifdef	Combined_Other_PCI_ROM
		mov	byte ptr COMBINED_PCI_ROM_NEED[bp], 0
		F000_CALL Ct_If_Combined_ROM_Needed	;does this device have
							;a Combined ROM ?
		jne	No_Need_Combined_ROM		;no need !

		mov	eax, 0FFFF0001h
		mov	byte ptr COMBINED_PCI_ROM_NEED[bp], 0AAH

No_Need_Combined_ROM:
endif	;Combined_Other_PCI_ROM

;R13 start
;R13A	ifdef	lan_boot_support
;R13A			mov	byte ptr LAN_ROM_NEED[bp],0
;R13A
;R13A			mov	edx, LAN_CARD_ID[bp]
;R13A			cmp	dword ptr CURRENT_DEVICE_ID[bp], edx	;LAN card?
;R13A			jne	short No_Need_LAN_ROM			;yes!
;R13A
;R13A			mov	eax,0FFFF0001h
;R13A			mov	byte ptr LAN_ROM_NEED[bp],0AAH
;R13A	No_Need_LAN_ROM:
;R13A	endif	;lan_boot_support
;R13 end

		call	Force_ROM_For_Some_Devices

;The value read is 0fffffffeh after writing -1 to 960RP expansion ROM
;base register.
		cmp	ax, 0ffffh			;invalid value
;R11		je	No_RomRequired
		je	No_ROM_Needed			;R11
		or	eax, eax			;non-zero value
;R11		jz	No_RomRequired
		jz	No_ROM_Needed			;R11
		or	al, 01H				;ROM needed
No_RomRequired:

		test	al, 01h				;Need PCI ROM?
		jz	No_ROM_Needed			;no, skip!
RomNeeded:
		clc
		ret
No_ROM_Needed:
		stc
		ret

Check_If_ROM_Needed	Endp

Seek_PCI_CbROM_1	Proc	Near
		mov	dword ptr CBROM_BUF_START[bp], 200030h	;PCI device ROM Index start add
		mov	dword ptr CBROM_BUF_END[bp], 200100h	;PCI device ROM Index end add
		call	Seek_PCI_CbROM				;find pci device rom from decompress pool
		cmp	dword ptr PCI_CBROM_ADDR[bp], 0
		ret
Seek_PCI_CbROM_1	Endp

		public	Seek_PCI_CbROM
Seek_PCI_CbROM	Proc	Near				;find pci rom

		pushf
		pushad

		cli
		call	E000_A20_On

		mov	edi, CBROM_BUF_START[bp]
		mov	dword ptr PCI_CBROM_ADDR[bp], 0
		call	E000_Enter_Prot_mode
		call	E000_Back_Real_Mode

	Seek_Next_CbROM:

		mov	ax, ds:[edi]			;AX = ROM's vendor ID
		cmp	ax, CURRENT_VENDOR_ID[bp]	;vendor ID matched ?
		jne	ID_Not_Match			;no !
;R03 - starts
		cmp	byte ptr NCR_810_FOUND[bp], INVOKE_NCR_CBROM
							;Seeking NCR ROM ?
		je	ID_Match			;yes! No need to
							;check device ID
;R03 - ends
		mov	ax, ds:[edi+2]			;AX = ROM's device ID
;R14		cmp	ax, CURRENT_DEVICE_ID[bp]	;both IDs matched ?
;R14 - starts
		mov	dx, CURRENT_DEVICE_ID[bp]
		cmp	ax, 0078h
		jne	@F
		xor	dh, dh
	@@:
		cmp	dx, ax
;R14 - ends
		je	ID_Match			;yes !

	ID_Not_Match:

		add	edi, 8
		cmp	edi, CBROM_BUF_END[bp]
		jb	Seek_Next_CbROM
		jmp	Seek_PCI_CbROM_End

	ID_Match:

		mov	eax, ds:[edi+4]
		mov	PCI_CBROM_ADDR[bp], eax		;compress start

	Seek_PCI_CbROM_End:

		call	E000_A20_Off
		popad
		popf
		ret

Seek_PCI_CbROM	Endp

Force_ROM_For_Some_Devices	Proc	Near

		cmp	dword ptr CURRENT_DEVICE_ID[bp], \
			(ADAPTEC_VENDOR_ID shl 16) + DEVICE_AHA7850
;R60		jne	Force_ROM_Exit
;R60 start
		je	short Set_ROM_Needed

		cmp	dword ptr CURRENT_DEVICE_ID[bp], 11918002h	;ACARD SCSI ID
		je	short Set_ROM_Needed

		jmp	short Force_ROM_Exit
;R60 end

	Set_ROM_Needed:

		mov	eax, 0FFFF0001h

	Force_ROM_Exit:

		ret

Force_ROM_For_Some_Devices	Endp

;[]================================================================[]
;[]================================================================[]
		ALIGN	4
Non_PCI_Compliance_ROM	Proc	Near

		xor	bx, bx
		mov	byte ptr CURRENT_BUS_NO[bp], 0	;from bus 0

NextBusNonComplianceROM:

		push	bx
		call	Prepare_PCI_Device_No
		pop	bx

		mov	ch, START_PCI_DEV[BP] 		;starting function

	Next_ROM_Func:

		push	cx

		call	Check_If_ROM_Needed  		;ROM needed?
		jc	No_ROM_Func			;no, skip

	;-------------------------------------------------------
	;if A20 to A31 = 1 (i.e. image can be mapped to hi addr)
	;   then skip
	;-------------------------------------------------------

		test	eax, 0FFF00000h			;Map to High addr.?
		jnz	No_ROM_Func			;yes, skip

	;---------------------------------------
	;check if any low addr. available
	;  according to image size in offset 02h
	;---------------------------------------

		push	cx				;save CX
		shr	eax, 12				;ROM size
		not	al				;  in terms of 4K
		inc	al				;  in terms of 4K
		mov	cl, al				;  in terms of 4K
		call	EGet_Available_LMEM 		;request low mem
		pop	cx				;restore CX
		jc	No_ROM_Func			;no low addr. is
							; avaiable
	;---------------------------------------
	;enable this ROM and map it to low addr.
	;---------------------------------------

		mov	eax, AVAIL_LMEM_ADDR[bp]
		mov	cl, 30h
		or	al, 1
		call	F000_Set_CfgSpace_Dword

	;--------------------------------------------------------
	;1. copy ROM image from ROM area to 3000:0 - 4000:0
	;      e.g if ROM map to C800:0 then copy it into 3800:0
	;
	;2. keep record of the image
	;	- destination segment
	;	- device & function number
	;--------------------------------------------------------

		push	1000h
		pop	ds
		add	bx, 8

		mov	esi, eax
		shr	esi, 4
		mov	ds:[bx], si		;destination ROM address
		mov	di, si
		sub	di, (0C000h-1000h)
		mov	ds:[bx+2], di		;source temp address
		mov	ds:[bx+4], ch		;device & function no.

		xor	al, al
		call	ECopy_ROM

	No_ROM_Func:

		pop	cx				;restore slot ID

		call	Disable_PCI_ROM

		call	Get_Next_Device	 		;CH=next device
		jnc	Next_ROM_Func

		call	Get_Next_Bus
		jbe	NextBusNonComplianceROM

;---------------------------------------------------

		clc
		or	bx, bx
		jz	@F

		push	bx
		call	Shadow_C8_To_DF
		call	Dis_Shadow_Not_Avail
		pop	bx

	Init_Next_Low_ROM:

		push	1000h
		pop	ds
		mov	di, ds:[bx]
		mov	si, ds:[bx+2]
		mov	ch, ds:[bx+4]			;device & func number
		xor	al, al
		call	ECopy_ROM

		call	Init_ROM	      		;call this ROM

		sub	bx, 8
		jnz	Init_Next_Low_ROM
		stc
	@@:
		ret

Non_PCI_Compliance_ROM	Endp

;[]================================================================[]
;[]================================================================[]
		ALIGN	4
PCI_Compliance_ROM	Proc	Near

		mov	byte ptr CURRENT_BUS_NO[bp], 0	;from bus 0

;R36 - start
ifdef	RAID_BOOT_OPTION
	;BIOS scan PCI ROMs from bus 0 if user disable "Raid boot first"
	;and scan from highest PCI bus number if it is enabled.
		mov	si,offset RaidBoot_Item
		call	F000_GetItem_Value	;get CMOS setting
		or	al,al			;Raid boot first ?
		jz	short PciCRomStart	;no, scan from bus 0

	;mark a flag for scan ROM from higher bus number
		or	byte ptr DEVICE_CLASS_FLAG[bp],RAID_FIRST

		mov	al, byte ptr TOTAL_BUS_NO[bp]	;maximum bus number
		mov	byte ptr CURRENT_BUS_NO[bp], al	;bus # to start

PciCRomStart:
endif;	RAID_BOOT_OPTION
;R36 - end

NextBusComplianceROM:

		call	Prepare_PCI_Device_No

		mov	ch, START_PCI_DEV[BP] 		;starting function

;------------------------------------------------------------

	Next_Compliance_ROM:

		push	cx				;save slot ID

;R35 - start
ifdef	LAST_INIT_FOR_LAN_ROM
		mov	cl, 0AH		       	;get class code
		call	F000_Get_CfgSpace_Word
		cmp	ah,02H			;LAN device ?
		jne	short NotLanCard 	;no, Initial option ROM

	;mark flag for LAN card found
		or	byte ptr DEVICE_CLASS_FLAG[bp],LAN_FOUND

	;check if initial LAN ROM needed

		test	byte ptr DEVICE_CLASS_FLAG[bp],LAN_NOW
		jz	short End_This_ROM_Func	;don't scan LAN ROM

NotLanCard:
endif;	LAST_INIT_FOR_LAN_ROM
;R35 - end

	;---------------------------------
	;To see if this Cfg space need ROM
	;---------------------------------

		call	Check_If_ROM_Needed
		jc	End_This_ROM_Func		;no, skip!

	;---------------------------------
	;if A20 to A31 = 0 then skip
	;---------------------------------

		test	eax, 0FFF00000h
		jz	End_This_ROM_Func

	;--------------------------------------------
	;search for a valid image & copy it to 3000:0
	;--------------------------------------------

		mov	dword ptr PCI_CBROM_ADDR[bp], 0
		call	Find_PCI_ROM_Image
		jnc	_ROM_Found

		call	Check_If_NCR_SCSI
		jnc	End_This_ROM_Func
		call	Seek_PCI_CbROM_1
		je	End_This_ROM_Func
		call	Find_PCI_ROM_Image
		jc	End_This_ROM_Func			;CF: no image found

	_ROM_Found:

		call	Invoke_PCI_ROM

	End_This_ROM_Func:

		pop	cx				;restore slot ID

		call	Disable_PCI_ROM

		call	Get_Next_Device	   		;CH=next device
		jnc	Next_Compliance_ROM

;R36 - start
ifdef	RAID_BOOT_OPTION

		test	byte ptr DEVICE_CLASS_FLAG[bp],RAID_FIRST
		jz	short NormalRomScan		;scan from high bus ?

		sub	byte ptr CURRENT_BUS_NO[bp], 1	;next bus #
		jnc	NextBusComplianceROM		;to check ROM
		jmp	short PciCRomExit
NormalRomScan:
endif;	RAID_BOOT_OPTION
;R36 - end

		call	Get_Next_Bus
		jbe	NextBusComplianceROM

PciCRomExit:						;R36

;------------------------------------------------------------

		ret

PCI_Compliance_ROM	Endp

Invoke_PCI_ROM	Proc	Near

	;--------------------------------------------
	;Now the valid image is copied into 3000:0
	;  find low memory resource for this image
	;  according to byte 2 (init size)
	;--------------------------------------------

		mov	ax, 3000h
		push	dword ptr LMEM_RESOURCE[bp]
		call	Request_LMEM_For_ROM
		pop	dword ptr LMEM_RESOURCE[bp]
		jc	Invoke_PCI_ROM_End			;CF: no LMEM available!

		call	Check_If_NCR_SCSI
		jc	_GG_
		mov	byte ptr NCR_810_FOUND[bp], 0
	_GG_:

	;------------------------------------
	;copy image from 3000:0 to shadow RAM
	;------------------------------------

		mov	si, 3000h
		mov	edi, AVAIL_LMEM_ADDR[bp]
		shr	edi, 4
		xor	al, al
		call	ECopy_ROM

;R96 - start
		call	SaveInt18_19Vect	;save INT 18 & 19 vector
						;for later comparison	
;R96 - end

		call	Init_ROM	 		;call this ROM

		call	PnpBevChk		;R96 record BEV in buffer

	;--------------------------------
	;update the LMEM_RESOURCE[bp]
	;  according to the run time size
	;--------------------------------

		mov	eax, AVAIL_LMEM_ADDR[bp]
		mov	TARGET_AVAIL_LMEM[bp], eax
		shr	eax, 4
		call	Recalibrate_LMEM_For_ROM

	Invoke_PCI_ROM_End:

		ret

Invoke_PCI_ROM	Endp

;R96 - start
;
;Function : Save vector of INT 18H & 19H for later comparison
;Input    : none
;Output   : none
;
SaveInt18_19Vect	proc	near

		push	ds

		push	G_RAM				;BIOS data area
		pop	ds
		assume	ds:G_RAM

		mov	eax, dword ptr ds:[INT18]	;get current INT 18
		mov	dword ptr PCIIRQ[bp+24], eax	;save vector of INT18

		mov	eax, dword ptr ds:[INT19]	;get current INT 19
		mov	dword ptr PCIIRQ[bp+28], eax	;save vector of INT19

		pop	ds
		ret
SaveInt18_19Vect	endp

;Function : Check if PCI option ROM support PnP expansion Header
;Input    : es : segment of PCI option ROM
;Output   : record BEV(Bootstrap Entry Vector) in BIOS buffer
;
PnpBevChk	proc	near
		push	ds
		pushad

		push	G_RAM				;BIOS data area
		pop	ds
		assume	ds:G_RAM

	;Don't record BEV if the INT 18H or INT 19H is trapped
		mov	eax, dword ptr ds:[INT18]	;get current INT 18
		cmp	dword ptr PCIIRQ[bp+24], eax	;check if INT18 trapped ?
		jne	short NotPnPHeader

		mov	eax, dword ptr ds:[INT19]	;get current INT 19
		cmp	dword ptr PCIIRQ[bp+28], eax	;check if INT19 trapped ?
		jne	short NotPnPHeader


		mov	bx, es:[001AH]	;get offset of PnP expansion header
					;structure
		cmp	dword ptr es:[bx], 'PnP$';signature ?
		jne	short NotPnPHeader	 ;no header


		mov	ax, word ptr es:[bx+001AH];Bootstrap Entry Vector
		or	ax, ax		;BEV exist ?
		jz	short NotPnPHeader

	;Record BEVs
		    
		push	ax		
		F000_CALL F000_Shadow_W	;F-segment shadow R/W

		push	0F000H
		pop	ds		;setup data segment to F-segment

		pop	ax
		mov	si, offset BootEntryTbl

	GetAvailableBev:
		cmp	dword ptr ds:[si], 0	;empty BEV ?
		je	short SaveCurrentBEV

		add	si, 4			;next BEV table
		cmp	si, offset BootEntryEnd	;BEV table full ?
		je	short BEVTblFull	;yes

		jmp	short GetAvailableBev	;search next empty BEV table


	SaveCurrentBEV:

		mov	ds:[si], ax	;offset address
		mov	ds:[si+2], es	;segment address

	BEVTblFull:

		F000_CALL F000_Shadow_R	;F-segment shadow readonly

	NotPnPHeader:
		
		popad
		pop	ds
		ret
PnpBevChk	endp
;R96 - end

		Public	Check_If_NCR_SCSI
Check_If_NCR_SCSI	Proc	Near

		pusha

		cmp	word ptr CURRENT_VENDOR_ID[bp]\
			, NCR_VENDOR_ID			;NCR vendor ID?
		jne	Its_Not_NCR_Device		;no, skip

		cmp	word ptr CURRENT_DEVICE_ID[bp]\
			, DEVICE_NCR860			;NCR/860 ?
		je	@F				;yes !

		cmp	word ptr CURRENT_DEVICE_ID[bp]\
			, DEVICE_NCR810			;NCR 810 ?
		je	@F				;yes !

		call	Check_If_Class_SCSI		;SCSI ?
		je	@F				;yes !

	Its_Not_NCR_Device:

		stc
	@@:
		popa

		ret

Check_If_NCR_SCSI	Endp

;[]================================================================[]
;Details:
;
;    1. In the early stage of POST, the combined NCR810 ROM was copied
;	onto temporary RAM at location 0:8000 & 7000:0
;    2. If NCR810 device is not found, goto 4
;	If the image is not valid(checksum fail or no AA55) goto 4
;    3. Copy one of the two images into shadow RAM
;       Invoke that ROM
;	set flag: NCR_810_FOUND[bp]
;	goto 6
;    4. Clear flag: NCR_810_FOUND[bp] --> no NCR SCSI ROM has been invoked
;    5. End
;
;[]================================================================[]
Init_NCR810_ROM	Proc	Near

		cmp	byte ptr NCR_810_FOUND[bp], NCR_SCSI_FOUND
		jne	No_NCR_ROM			;NCR not exist !

;R03		mov	dword ptr CURRENT_DEVICE_ID[bp], \
;R03			NCR_VENDOR_ID shl 16

		mov	byte ptr NCR_810_FOUND[bp], INVOKE_NCR_CBROM	;R03
		mov	word ptr CURRENT_VENDOR_ID[bp], NCR_VENDOR_ID	;R03
		call	Seek_PCI_CbROM_1
		je	No_NCR_ROM

;R03		mov	byte ptr NCR_810_FOUND[bp], INVOKE_NCR_CBROM
		call	Find_PCI_ROM_Image
		jc	No_NCR_ROM

		call	Invoke_PCI_ROM

	ifdef	PNP_BIOS
		mov	edi, AVAIL_LMEM_ADDR[bp]	;EDI: available shadow RAM
		call	Build_OnboardRomNode
	endif;	PNP_BIOS

	No_NCR_ROM:

		ret

Init_NCR810_ROM	Endp

;[]============================================================[]
;Input	:	CL = Request Memory spaces with size = CL * 4K
;		     e.g. CL = 1 --> request 4K bytes
;
;Output	:	AL = 1 --> NC : AVAIL_LMEM_ADDR[bp] = availbale address
;			   CF : No address available
;[]============================================================[]
		ALIGN	4						;R82
		Public	fPROC_Get_Available_LMEM			;R82
fPROC_Get_Available_LMEM	Proc	FAR				;R82
		call	EGet_Available_LMEM				;R82
		ret							;R82
fPROC_Get_Available_LMEM	Endp					;R82
		ALIGN	4
		ASSUME	DS:NOTHING
		Public	EGet_Available_LMEM
EGet_Available_LMEM	Proc	Near

		push	ds
		push	es
		pushad

		mov	bl, LMEM_FOR_ROM_FLG[bp]

		or	cl, cl
		jz	No_LMem
		cmp	cl, 24
		ja	No_LMem

		mov	eax, 1
		shl	eax, cl
		dec	eax

		or	bl, bl
		jz	Find_LMem
		mov	cl, 1

	Find_LMem:

		test	dword ptr LMEM_RESOURCE[bp], eax
		jz	LMem_Available

IF	RELEASE_E000_FOR_PCI
;----------------------------------------------------------------------
;if it is a request for initialization of ROM, we shoud also take
;E0000-E7FFF into consideration
;----------------------------------------------------------------------
		or	bl, bl
 		jz	@F
 		shl	eax, cl
 		jnc	Find_LMem
 		jmp	No_LMem
 	@@:
ENDIF	;RELEASE_E000_FOR_PCI

		shl	eax, cl
		test	eax, 0FF000000h
		jz	Find_LMem

	No_LMem:

		stc
		jmp	Shadow_RAM_Manager_Exit

	LMem_Available:

		mov	edx, eax
		push	eax
		mov	dword ptr AVAIL_LMEM_ADDR[bp], 0C8000h
	@@:
		shr	eax, 1
		jc	@F
		add	dword ptr AVAIL_LMEM_ADDR[bp], 1000h
		jmp	@B
	@@:
		pop	eax

;-----------------------------------------------------------------
;if it is a request for run time ROM, we have to return the same
;addr as its was assigned when last time the device request for
;addr. for initialization
;-----------------------------------------------------------------

		cmp	bl, 2				;request for run
							;  time ROM ?
		jne	Not_Recal_Lmem			;no, skip
		push	eax
		mov	eax, AVAIL_LMEM_ADDR[bp]	;target addr reached?
		cmp	eax, TARGET_AVAIL_LMEM[bp]	;target addr reached?
		pop	eax
		je	Not_Recal_Lmem			;yes, leave !
		shl	eax, cl				;esle, point to next
		jmp	Find_LMem			;4K and try again

	Not_Recal_Lmem:

		or	LMEM_RESOURCE[bp], edx		;update resource

		clc

Shadow_RAM_Manager_Exit:

		popad
		pop	es
		pop	ds

		ret

EGet_Available_LMEM	Endp

;-----------------------------------------------------------------
;-----------------------------------------------------------------
Prepare_PCI_Device_No	Proc	Near

		pushad
		push	ds

		call	Check_If_Bus_0
		mov	ax, 1000h
		jne	@F

		F000_CALL Ct_PCI_Info
	@@:
		shl	al, 3			;from first device func 0
		shl	ah, 3
		or	ah, 07h			;to last device func 7
		mov	START_PCI_DEV[BP], al
		mov	END_PCI_DEV[BP], ah

		pop	ds
		popad
		ret

Prepare_PCI_Device_No	Endp

;---------------------------------------------------------------------------
;
;		copy ROM image from SI:0 --> DI:0
;
;Input	:	SI = source segment
;		DI = Destination segment
;		AL <> 0 : copy size depends on ROM size in SI:2
;		   == 1 : copy size = input CX (no. of 4K)
;
;---------------------------------------------------------------------------
		ALIGN	4
		Public	ECopy_ROM
ECopy_ROM	Proc	Near

		push	cx

		push	si
		pop	ds
		push	di
		pop	es

	;----------------------------------------------
	;calculate CX = number of 4K codes to be copied
	;----------------------------------------------

		or	al, al
		jnz	@F

		xor	ch, ch
		call	Rom_In_Terms_of_4K
	@@:

	;------------------------------------------------
	;each time copy 4K codes until all codes finished
	;------------------------------------------------

		push	ds
		push	es

	Copy_ROM_Init_Code:

		push	cx			;copying:
		mov	cx, 400h		;each time 4k
		xor	si, si
		xor	di, di
		cld
		rep	movsd

		mov	ax, ds			;DS:
		add	ah, 01h			; point to next 4K
		mov	ds, ax			; point to next 4K

		mov	ax, es			;ES:
		add	ah, 01h			; point to next 4K
		mov	es, ax			; point to next 4K

		pop	cx
		loop	Copy_ROM_Init_Code

		pop	es
		pop	ds

	;-------------------------------------------

		pop	cx
		ret

ECopy_ROM	Endp

;-------------------------------------------------------------------
;Output	:	1. CURRENT_BUS_NO[bp] = CURRENT_BUS_NO[bp] + 1
;		   AL = CURRENT_BUS_NO[bp]
;		2. If NC & NZ(i.e. JBE), maximum Bus No. reached
;-------------------------------------------------------------------
		Public	Get_Next_Bus
Get_Next_Bus	Proc	Near

		mov	al, byte ptr CURRENT_BUS_NO[bp]
		inc	al
		mov	byte ptr CURRENT_BUS_NO[bp], al
		cmp	al, byte ptr TOTAL_BUS_NO[bp]
		ret

Get_Next_Bus	Endp

;[]================================================================[]
;Get_Next_Device:
;	This routine is used to get next device no to treat
;Input	:	CH - Slot identification Number
;Output :	NC : CH - Next Slot ID numbuer
;		CF : All slot & function spaces has scanned
;[]================================================================[]
		ALIGN	4
		Public	Get_Next_Device
Get_Next_Device	proc	near

		test	ch, 07h			;alread a multi-function space?
		jnz	@F			;yes, go point to next function

		mov	cl, 0Eh			;read header type
		call	F000_Get_CfgSpace_Byte	;read header type
		cmp	al, 0FFh
		je	Func0_No_Dev
		test	al, 80H			;multi-function support?
		jnz	@F			;yes, multi-function card!

	Func0_No_Dev:

		and	ch, NOT 111B		;mask function bits	;R57
		add	ch, 7			;point to next device!
	@@:
		add	ch, 1			;point to next function space
		jc	@F			;already overflow!
		cmp	ch, END_PCI_DEV[BP]	;exceed maximum device?
		ja	@F			;yes, tell caller error!

		clc				;success return
		ret
	@@:
		stc				;error return
		ret

Get_Next_Device	endp

;[]==============================================================[]
;[]==============================================================[]
		Public	If_MultiFunc_Dev
If_MultiFunc_Dev	Proc	Near

		test	ch, 07h			;alread a multi-function space?
		jnz	Is_MultiFunc_Card	;yes, go point to next function

		mov	cl, 0Eh			;read header type
		call	F000_Get_CfgSpace_Byte	;read header type
		test	al, 80H			;multi-function support?
		jz	Not_MultiFunc_Card	;multi-function not supported!

Is_MultiFunc_Card:

		inc	ch
		test	ch, 07h
		jz	End_Of_MultiFunc
		clc
		ret

End_Of_MultiFunc:
Not_MultiFunc_Card:

		stc
		ret

If_MultiFunc_Dev	Endp

;R72 ;----------------------------------------------------------------------
;R72 ;Function : Reserve a IRQ for PCI boot device to sure system can boot
;R72 ;	    from boot device ( like SCSI etc..)
;R72 ;Input    : none
;R72 ;Output   : none
;R72 ;----------------------------------------------------------------------
;R72 		public	Reserve_Irq_For_PciBootDev
;R72 Reserve_Irq_For_PciBootDev	proc	near
;R72
;R72 ifdef	PNP_BIOS
;R72 		call	fProc_Reserve_Irq_For_PciBootDev	;R04
;R72 endif;	PNP_BIOS
;R72 		ret						;R04
;R72 ;R04
;R72 ;R04	The origingal code was moved to XGROUP
;R72 ;R04
;R72
;R72 Reserve_Irq_For_PciBootDev	endp

;R04 ifdef	NEW_PNP_SETUP
;R04 ifdef	IRQ_FOR_BOOTDEV
;R04 BooDev_ClsCode:
;R04 		dd	010000H			;SCSI
;R04 		dd	010400H			;RAID
;R04 		dd	018000H			;other mass storage controller
;R04 		dd	0			;end of table
;R04 endif;	IRQ_FOR_BOOTDEV
;R04 endif;	NEW_PNP_SETUP

;[]================================================================[]
;Check_Master_Needed:
;	This routine is used to check enable master or not.
;	Because some card cannot enable master.
;Output :	NC : enable master
;		CF : disable master
;[]================================================================[]
		ALIGN	4
		Public	Check_Master_Needed
Check_Master_Needed	proc	near

		pushad
		xor	cl, cl			;read vendor & device ID
		call	F000_Get_CfgSpace_Dword

	ifdef	Disable_AMD2000_Master
		cmp	eax, 20001022h		;Is AMD LAN card exist?
		je	No_Need_Master		;yes !
	endif;	Disable_AMD2000_Master
		cmp	eax, 23011005h		;Advance 2301 VGA?
		je	No_Need_Master		;yes !

		popad
		clc				;master bit can be enabled!
		ret

	No_Need_Master:

		popad
		stc				;master bit cannot be enabled!
		ret

Check_Master_Needed	endp

;[]==============================================================[]
;[]==============================================================[]
		Public	Chk_If_Class_VGA
Chk_If_Class_VGA	Proc	Near

		xor	cl, cl			;vendor ID
		call	F000_Get_CfgSpace_Word
		or	ax, ax			;invalid ID
		mov	ax, -1
		jnz	Not_Invalid
		or	ax, ax
		jmp	@F
Not_Invalid:

		push	cx
		mov	cl, 0AH			;Class Code
		call	F000_Get_CfgSpace_Word
		pop	cx

;R43ifdef	Cardbus_support
;R43		cmp	ax, 0607h		;check is cardbus?
;R43		jne	Not_Cardbus
;R43		cmp	cx, Cardbus_SlotID[bp]	;check had init or not
;R43		je	Not_Cardbus		;had init?
;R43		call	Cardbus_Init
;R43Not_Cardbus:
;R43endif	;Cardbus_support

		Public	Chk_If_Class_VGA_1
Chk_If_Class_VGA_1	Label	Near
;R43 - start
ifdef	Cardbus_support
		cmp	ax, 0607h		;check is cardbus?
		jne	Not_Cardbus
		cmp	cx, Cardbus_SlotID[bp]	;check had init or not
		je	Not_Cardbus		;had init?
		call	Cardbus_Init
Not_Cardbus:
endif	;Cardbus_support
;R43 - end
		cmp	ax, 0300H		;VGA ?
		je	@F			;yes
		cmp	ax, 0301H		;XGA ?

		je	@F			;yes, go initial it!
		cmp	ax, ALT_CLASS_VGA	;alternative VGA type?
	@@:
		ret

Chk_If_Class_VGA	Endp

;[]==============================================================[]
;[]==============================================================[]
		Public	Check_If_Class_SCSI
Check_If_Class_SCSI	Proc	Near

		call	Chk_If_Class_VGA
		cmp	ax, CLASS_SCSI
		ret

Check_If_Class_SCSI	Endp

;======================================================================
;Input	:	EDI = ROM locations
;
;		      e.g. EDI=(7000h shl 16) + 0800h
;			   means ther are 2 images, one at 0:8000h
;			   the other at 7000:0
;
;Output :	CF = ROM Invalid by one of the following reasons:
;
;		     1.	ROM checksum error
;		     2. No 55AAH
;
;		NC = ROM valid
;
;		SI = SEG of ROM location (0800h or 7000h)
;======================================================================
		Public	Find_Valid_ROM_Image
Find_Valid_ROM_Image	Proc	Near

		mov	cx, 2

	Try_Next_SCSI_Image:

;R85 - start
		mov	ds, di			;R85A 
		cmp	word ptr ds:[0], 0AA55h	;valid ROM image?
		jne	short @F		;no, it's invalid

ifndef	NO_CKSUM_FOR_CBROM
	ifndef	ONBOARD_ScsiChip
		push	cx
		mov	si, di			;image checksum 
		call	Cksm_ROM		;check if image valid
		pop	cx
	endif;	ONBOARD_ScsiChip
endif;	NO_CKSUM_FOR_CBROM

		jz	short SCSI_ROM_Valid
;R85 - end

;R85		push	cx
;R85		mov	si, di
;R85		call	Cksm_ROM		;check if image valid
;R85		pop	cx
;R85
;R85ifndef	NO_CKSUM_FOR_CBROM
;R85	ifndef	ONBOARD_ScsiChip
;R85		jnz	@F			;no image available
;R85	endif;	ONBOARD_ScsiChip
;R85endif;	NO_CKSUM_FOR_CBROM
;R85
;R85		cmp	word ptr ds:[0], 0AA55h	;valid ROM image?
;R85		je	SCSI_ROM_Valid	;yes, valid
	@@:
		shr	edi, 16
		loop	Try_Next_SCSI_Image

	SCSI_ROM_Invalid:

		stc
		ret

	SCSI_ROM_Valid:

		clc
		ret

Find_Valid_ROM_Image	Endp

;[]=======================================================[]
;Input	:	SI = segment location of a ROM image
;Output	:	ZF - checksum good
;		NZ - checksum bad
;[]=======================================================[]
		Public	Cksm_ROM
Cksm_ROM	Proc	Near

		push	si
		push	bx
		push	cx

		mov	ds, si
		xor	bl, bl
		xor	si, si

		mov	cl, ds:[2]
		xor	ch, ch
		shl	cx, 9
	@@:
		lodsb
		add	bl, al
		loop	@B
		or	bl, bl			;image valid ?

		pop	cx
		pop	bx
		pop	si
		ret

Cksm_ROM	Endp

;===========================================================
;Input	:	None
;Output	:	CF - no ROM image found
;		NC - ROM image found and is copied to 3000:0
;===========================================================
		ALIGN	4
		Public	Find_PCI_ROM_Image
Find_PCI_ROM_Image	Proc	Near

		cli
		push	ebx
		push	cx

		xor	esi, esi
		xchg	esi, PCI_CBROM_ADDR[bp]
		or	esi, esi
		jnz	EnterProtectMode

ifdef	Combined_Other_PCI_ROM
		cmp	byte ptr COMBINED_PCI_ROM_NEED[bp], 0AAH
		mov	byte ptr COMBINED_PCI_ROM_NEED[bp], 0
		jne	NoCombineROM
		F000_CALL Ct_If_Combined_ROM_Needed	;EDI=image location
		push	cx
		call	Find_Valid_ROM_Image		;any of them valid?
		pop	cx
		jc	NoCombineROM			;none of them valid !
		movzx	esi, si
		shl	esi, 4				;location at 32bit
		jmp	EnterProtectMode		;   address

	NoCombineROM:
endif	;Combined_Other_PCI_ROM

;R13 start
;R13A	ifdef	lan_boot_support
;R13A			cmp	byte ptr LAN_ROM_NEED[bp], 0AAH	;need lan card rom
;R13A			mov	byte ptr LAN_ROM_NEED[bp], 0
;R13A			jne	short Nolanrom			;yes!
;R13A
;R13A			push	cx
;R13A			mov	di,(8+1)*4
;R13A			call	post_decompress			;decompres lan rom
;R13A			pop	cx
;R13A			jc	short Nolanrom
;R13A			mov	esi,40000h			;rom at 4000:0
;R13A			jmp	EnterProtectMode
;R13A	Nolanrom:
;R13A	endif	;lan_boot_support
;R13 end

		mov	cl, 30h				;ROM addr. reg.
		call	F000_Get_CfgSpace_Dword		;write register
		or	eax, eax
		jz	No_Image_Exist
		mov	esi, eax
		or	al, 1
		call	F000_Set_CfgSpace_Dword		;write register

	EnterProtectMode:

		push	cx

	ifdef	PCI_LAN_PATCH
	;--------------------------------------------------------------
	;disable I/O & memory space for PCI/LAN chip to prevent
	;system hang while warm booting without PCI reset
	;--------------------------------------------------------------
		mov	cl, 0bh				;get class code
		call	F000_Get_CfgSpace_Byte
		cmp	al, 02H				;LAN chip ?
		jne	Not_LanChip
		mov	cl, 4
		call	F000_Get_CfgSpace_Byte		;write register
		and	al, NOT 03H			;disable I/O & Mem.
		call	F000_Set_CfgSpace_Byte		;write register
	Not_LanChip:
	endif;	PCI_LAN_PATCH

		xor	cl, cl				;read vendor & device
		call	F000_Get_CfgSpace_Dword		;ID
		mov	ebx, eax			;save in EBX
		pop	cx

	;When capture card (PLX PCI9060SD) plugged, skip!

		cmp	ebx, 906d10b5h			;Is capture card (PLX PCI9060SD)
		je	No_Image_Exist			;Yes, skip!

		call	E000_A20_On
		call	E000_Enter_Prot_mode		;enter protected mode
		call	E000_Back_Real_Mode 		;R47

	Find_Next_Image:

		mov	edi, esi
		xor	eax, eax			;EDI poiny to PCI
		mov	ax, word ptr ds:[esi+18h]	;  data structure
		add	edi, eax			;

		cmp	word ptr ds:[esi], 0AA55h	;correct signature?
		jne	No_Image_Exist			;no, skip this one

	;check valid PCI data structure signature

		cmp	dword ptr ds:[edi], 'RICP'
		jne	Copy_30000h

		cmp	byte ptr NCR_810_FOUND[bp], INVOKE_NCR_CBROM
		je	Copy_30000h

	;check valid Vendor ID

		cmp	word ptr ds:[edi+04h], bx
		jne	Not_Valid_Image

;R41 - starts
		cmp	bx, NCR_VENDOR_ID
		jne	Not_Ncr_Rom
		cmp	word ptr CURRENT_CLASS_CODE[bp], CLASS_SCSI
		je	Chk_Code_Type
	Not_Ncr_Rom:
;R41 - ends

	;check valid Device ID

		mov	eax, ebx
		shr	eax, 16				;get device ID
		cmp	word ptr ds:[edi+06h], 0078h
		jne	@F
		xor	ah, ah
	@@:
		cmp	word ptr ds:[edi+06h], ax
		jne	Not_Valid_Image

	;check valid code type

	Chk_Code_Type:					;R41

		cmp	byte ptr ds:[edi+14h], 0
		jne	Not_Valid_Image

	;valid image found, copy to 30000h

	Copy_30000h:

		push	cx
		xor	ecx, ecx
		mov	cl, ds:[esi+2]			;init size

		shl	ecx, 7				;in terms of dword
		mov	edi, 30000h

	;-------------------------------------------------------------
	;if this is a NCR SCSI ROM image, kill 0:8000 to let the
	;ROM be invoked using the PCI standard way !
	;-------------------------------------------------------------

	@@:
		mov	eax, ds:[esi]
		mov	ds:[edi], eax
		add	edi, 4
		add	esi, 4
		loop	@B

	Copy_30000_End:

		pop	cx

;R47		call	E000_Back_Real_Mode
		call	Disable_PCI_ROM

		clc
		jmp	PCI_Image_Exit1

	Not_Valid_Image:

		test	byte ptr ds:[edi+15h], 80h	;last image?
		jnz	No_Image_Exist			;yes

		xor	eax, eax
		mov	ax, word ptr ds:[edi+10h]
		shl	eax, 9				;in terms of bytes
		add	esi, eax
		jmp	Find_Next_Image

	No_Image_Exist:

		stc					;indicates no ROM image

PCI_Image_Exit:

		pushf
;R47		call	E000_Back_Real_Mode
		call	E000_A20_Off
		popf

PCI_Image_Exit1:

		pop	cx

	;------------------------------------------
	;Restore I/O & memory space for LAN chip
	;------------------------------------------
	ifdef	PCI_LAN_PATCH

		pushf
		push	cx
		mov	cl, 0bh			;get class code
		call	F000_Get_CfgSpace_Byte
		cmp	al, 02H			;LAN chip ?
		jne	Not_LanChip1
		mov	cl, 4
		call	F000_Get_CfgSpace_Byte	;write register
 		or	al, 03H			;disable I/O & Mem.
		and	al, NOT 04h		;clear Master bit
		call	F000_Set_CfgSpace_Byte	;write register

	Not_LanChip1:

		pop	cx
		popf

	endif;	PCI_LAN_PATCH

		pop	ebx

		ret

Find_PCI_ROM_Image	Endp

;[]================================================================[]
;Function : Disable memory space for PCI adaptor ROM
;Input    : none
;Output   : none
;[]================================================================[]
		Public	fProc_Disable_PCI_ROM
fProc_Disable_PCI_ROM	Proc	Far
		call	Disable_PCI_ROM
		retf
fProc_Disable_PCI_ROM	Endp
		ALIGN	4
		Public	Disable_PCI_ROM
Disable_PCI_ROM	Proc	Near

		push	eax
		mov	cl, 30h			;Expansion. ROM Base Addr. reg.
		call	F000_Get_CfgSpace_Dword
		and	al, not 01h
		call	F000_Set_CfgSpace_Dword
		pop	eax
		ret

Disable_PCI_ROM	Endp

;[]============================================================[]
;Input	:	CH  - Device number in upper 5 bits
;		      Function number in lower 3 bits
;Output :	EAX - Class Code
;Destroy:	EAX
;[]============================================================[]
		ALIGN	4
		Public	Get_Class_Code
Get_Class_Code	Proc	Near

		push	cx
		mov	cl, 08			;Class Code + Revision ID
		call	F000_Get_CfgSpace_DWord
		pop	cx
		ret

Get_Class_Code	Endp

;[]============================================================[]
;Input	:	CH - Slot identification Number
;Output :	AX - DEVICE ID
;Destroy:	AX
;[]============================================================[]
		ALIGN	4
		ASSUME	DS:NOTHING
		Public	F000_Get_Device_ID
F000_Get_Device_ID	Proc	Near

		F000_CALL Get_Device_ID
		ret

F000_Get_Device_ID	Endp

endif	;PCI_BUS

;[]============================================================[]
;[]============================================================[]
E_GDTR1:					; global descriptor table register
		dw	8*2			; LIMIT
		dw	offset EGROUP:E_GDT1
		dw	0Eh			; in 0E000h segment

E_GDT1:						; null descriptor
		dw	0			; limit
		dw	0			; base
		db	0			; hibase
		db	0			; access
		db	0			; hilimit
		db	0			; msbase

E_DATA1_DT:					; ds - first 64k segment
E_DATA1_INDEX	=	((OFFSET E_DATA1_DT - OFFSET E_GDT1)/8) SHL 3
		dw	0ffffh			; limit
		dw	0			; base data segment points to
		db	0			; hibase	; 00000000
		db	93h			; access
		db	08fh			; hilimit (4GB)
		db	0			; msbase

;==========================================================================
;Function : Enter CPU protected mode in E-segment with 4GB space accessable
;Input    : none
;Output   : DS - point to data descriptor with starting address 0
;==========================================================================
		public	E000_Enter_Prot_mode
E000_Enter_Prot_mode	proc	near

		push	eax

;---------------- Enter Protect Mode ----------------

                mov     ax, cs
                mov     ds, ax

                lgdt    fword ptr ds:E_GDTR1

                mov     eax, cr0
                or      al, 1
                mov     cr0, eax

;R47		jmp	$+2		;clear prefetch

                mov     ax, E_DATA1_INDEX
                mov     ds, ax			; ds = 00000000h
ifndef	MP_SUPPORT				;R73A
		mov	ss, ax			;R73
endif;	MP_SUPPORT				;R73A

		pop	eax
		ret

E000_Enter_Prot_mode	endp

;======================================================
;Function : Go back to real mode from protected mode
;Input    : none
;Output   : none
;======================================================
		public	E000_Back_Real_Mode
E000_Back_Real_Mode	proc	near

		push	eax
                mov     eax, cr0
                and     al, NOT 1
                mov     cr0, eax
;R47		jmp	$+2		;clear prefetch
ifndef	MP_SUPPORT			;R73A
		xor	ax, ax		;R73
		mov	ss, ax		;R73
endif;	MP_SUPPORT			;R73A
		pop	eax
		ret

E000_Back_Real_Mode	endp

;======================================================
;======================================================
		Public	Check_If_Bus_0
Check_If_Bus_0	Proc	Near
		cmp	byte ptr CURRENT_BUS_NO[bp], 0
		ret
Check_If_Bus_0	Endp

ECODE		ENDS

ENDIF	;COMPILE_FOR_E0 EQ 1

IF	COMPILE_FOR_E0 EQ 1
ifdef	PCI_BUS

		extrn	Check_If_Bus_0:near

ifndef	NO_PCI_IDE_2ND_CONTROL
		extrn	Second_IDE_channel:near		;bfeature.asm
endif;	NO_PCI_IDE_2ND_CONTROL
		extrn	F000_Set_Cyrix:near
		extrn	lock_Cyrix:near
		extrn	Unlock_Cyrix:near

		extrn	Pci_Class_Code:near
ifndef	NO_PCI_IDE_CARD
		extrn	PCI_IDE_IRQ:near		;pcifeat.asm
		extrn	First_IDE_INT:near		;pcifeat.asm
		extrn	Second_IDE_INT:near		;pcifeat.asm
endif	;NO_PCI_IDE_CARD
		extrn	PCI_SLOT_CFG:near		;chipset.asm

		extrn	F000_GetItem_Value:near
		extrn	F000_call_proc:near
		extrn	Ct_Special_PCI_Device:Near	;pcichip.asm
		extrn	Ct_Special_Copy_PCI_VGA:near
		extrn	Ct_Set_PciIrq:near		;pcichip.asm
		extrn	Ct_PCI_VGA_IDSEL:near		;pcichip.asm
		extrn	Ct_OnChip_IDE_Chk:near
IF	BIOS_SUPPORT_586				;R99
		extrn	Check_M1_Cpu:near
ENDIF	;BIOS_SUPPORT_586				;R99
		extrn	C000_Shadow_RW:near		;chipset.asm
		extrn	C000_Shadow_R:near		;chipset.asm
		extrn	Ct_Shadow_RW:near		;R82
		extrn	F_C000_Shadow_RW:near
		extrn	F_C000_Shadow_R:near
		extrn	E000_Move_Codes:Near
		extrn	Ct_C8_To_DF_RW:Near
		extrn	Ct_C8_To_DF_R:Near
		extrn	Ct_Disable_Shadow:Near
		extrn	Ct_Shadow_Unit:Near
		extrn	Disable_UnUsed_Shadow:Near
		extrn	AGet_CfgSpace_Byte:near
		extrn	AGet_CfgSpace_Word:near
		extrn	AGet_CfgSpace_Dword:near
		extrn	ASet_CfgSpace_Byte:near
		extrn	ASet_CfgSpace_Word:near
		extrn	ASet_CfgSpace_Dword:near

		extrn	F000_Get_Device_ID:near
		extrn	F000_Get_Vendor_ID:near
		extrn	CHECK_IF_CLASS_SCSI:near
		extrn	CHECK_MASTER_NEEDED:near
		extrn	CHECK_ROM_EXIST:near
		extrn	CHK_IF_CLASS_VGA:near
		extrn	Chk_If_Class_VGA_1:Near
		extrn	CKSM_ROM:near
		extrn	DISABLE_PCI_ROM:near
		extrn	E000_BACK_REAL_MODE:near
		extrn	E000_ENTER_PROT_MODE:near
		extrn	ECOPY_ROM:near
		extrn	EGet_Available_LMEM:near
		extrn	F000_GET_CFGSPACE_BYTE:near
		extrn	F000_GET_CFGSPACE_DWORD:near
		extrn	F000_GET_CFGSPACE_WORD:near
		extrn	F000_SET_CFGSPACE_BYTE:near
		extrn	F000_SET_CFGSPACE_DWORD:near
		extrn	F000_SET_CFGSPACE_WORD:near
		extrn	F000_GET_VENDOR_ID:near
		extrn	GET_CLASS_CODE:near
		extrn	GET_NEXT_BUS:near
		extrn	GET_NEXT_DEVICE:near
		extrn	IF_MULTIFUNC_DEV:near

		extrn	INVALIDATE_SHADOW_SEG:near
		extrn	MARK_ADDR_NOT_AVAILABLE:near
		extrn	ROM_IN_TERMS_OF_4K:near

ifndef	NEW_PNP_SETUP
		extrn	PciIrq_Item:near
endif;	NEW_PNP_SETUP

ifdef	SUPPORT_PCISLOT_IDE
		extrn	Open_8673:near
		extrn	Set_8673:near
endif;	SUPPORT_PCISLOT_IDE

ifdef	PCI_LATENCY_SELECTABLE
		extrn	Pci_Latency_Item:near
endif;	PCI_LATENCY_SELECTABLE

	ifdef	CONFIG_MECHANISM_1
		extrn	Get_Max_PciBus:near
	endif	;CONFIG_MECHANISM_1
		extrn	F000_Shadow_W:Near
		extrn	F000_Shadow_R:Near

		extrn	E000_64k_Shadow_RW:Near
		extrn	E000_64k_Shadow_R:Near
		extrn	Find_Valid_ROM_Image:Near

	ifdef	VSA_VGA					;R44
		extrn	Ct_Gx_C8_To_DF_RW:near		;R44
		extrn	Ct_GxDisable_Shadow:near	;R44
	endif;	VSA_VGA					;R44

;R52 - start
	ifdef	USB_SUPPORT
	ifdef	No_Assign_IRQ_If_USB_Disable
		extrn	USB_ITEM:near
;R52B		extrn	USB_Legacy_Item:near		;R52A
	endif;	No_Assign_IRQ_If_USB_Disable
	endif;	USB_SUPPORT
;R52 - end

	ifdef	USB_IRQ_SELECTABLE
		extrn	UsbIrq_Item:near
		ifdef	VT586_USB			;R29 for VIA chip
		extrn	ONBD_USB_Item:near		;R29 for VIA chip
		endif;	VT586_USB			;R29 for VIA chip
	endif	;USB_IRQ_SELECTABLE

		extrn	Seek_PCI_CbROM:Near

endif	;PCI_BUS

DGROUP		GROUP	FCODE
FCODE		SEGMENT USE16 PARA PUBLIC 'CODE'
FCODE		ENDS

EGROUP		GROUP	ECODE
ECODE		SEGMENT USE16 PARA PUBLIC 'ECODE'
		ASSUME	CS:EGROUP, DS:G_RAM, ES:EGROUP

ifdef	PCI_BUS
;[]================================================================[]
;Release_Shadow_From_PCI_VGA:
;	This routine is used to check if VGA BIOS has been condensed
;	after VGA BIOS had been initialed. And reprepare LMEM_RESOURCE[bp]
;[]================================================================[]
		ALIGN	4
		public	Release_Shadow_From_PCI_VGA
Release_Shadow_From_PCI_VGA	proc	near

		call	fProc_Release_Shadow_From_PCI_VGA
		ret

Release_Shadow_From_PCI_VGA	endp

;[]================================================================[]
;Before_PciVGARomInit:
;	This routine is used to set PCI/VGA to special state
;	Before VGA/ROM initial
;Input  : none
;Output : none
;[]================================================================[]
		Public		Before_PciVGARomInit
Before_PciVGARomInit	proc	near

		call	fProc_Before_PciVGARomInit
		ret

Before_PciVGARomInit	endp

;[]============================================================[]
;[]============================================================[]
fProc_Find_VGA_ROM_Image	Proc	Far

		push	cx				;R17

	;Enable I/O & memory decoding for VGA ROM scan	;R94
		mov	cl, 04h		      		;R94
		mov	al, 07H				;R94
 		call	F000_Set_CfgSpace_Byte		;R94

;R59 - start
if  PATCH_ONBOARD_CT_6XXXX_VGA
	;Don't scan VGA ROM register is C&T 6xxxx VGA is used with
	;Intel MMO module.
		F000_CALL Ct_PCI_VGA_IDSEL		;CL=onboard PCI VGA
		cmp	ch, cl				;onboard VGA slot ?
		jne	short NotOnboardVgaSlot

		cmp	byte ptr ds:[si].VGA_BusNum, 0	;get VGA bus number
		je	short UseMergeVgaROM

NotOnboardVgaSlot:

endif; PATCH_ONBOARD_CT_6XXXX_VGA
;R59 - end
		mov	cl, 30h
 		call	F000_Get_CfgSpace_DWord

	Set_VGA_ROM_Addr:

		mov	esi, eax
		or	al, 01h
 		call	F000_Set_CfgSpace_DWord

		call	E000_Enter_Prot_Mode
		call	E000_Back_Real_Mode		;No valid VGA ROM;R83

		cmp	word ptr ds:[esi], 0AA55h	;ROM existed ?
		je	ROM_Exist			;yes

;R83		call	E000_Back_Real_Mode		;No valid VGA ROM

		cmp	esi, 0C0000h			;have we try C0000h
		mov	eax, 0C0000h			;map ROM to C0000h
		jne	Set_VGA_ROM_Addr		;No, try again!

		xor	eax, eax			;R17
 		call	F000_Set_CfgSpace_DWord		;R17

;R54 ;R07 - starts
;R54 		mov	edi, 7000h			;Find a ROM image in
;R54 		call	Find_Valid_ROM_Image		;  7000h
;R54 		mov	esi, 70000h			;
;R54 		jnc	@F				;NC = Valid ROM image
;R54 ;R07 - ends

UseMergeVgaROM:						;R59

		mov	dword ptr CBROM_BUF_START[bp], 200000h	;compress bp start
		mov	dword ptr CBROM_BUF_END[bp], 200030h	;compress bp end
;R54 start
		call	F000_Get_Device_ID  		;device ID in AX
		mov	CURRENT_DEVICE_ID[bp], ax
		call	F000_Get_Vendor_ID		;retrieve vendor ID
		mov	CURRENT_VENDOR_ID[bp], ax
;R54 end
		call	Seek_PCI_CbROM
		mov	esi, PCI_CBROM_ADDR[bp]		;copy vga rom
		or	esi, esi			;find rom
;R54		jz	No_Video_Rom
;R54 start
		jnz	short @F			;yes
		mov	edi, 7000h			;Find a ROM image in
		call	Find_Valid_ROM_Image		;  7000h
		mov	esi, 70000h			;
 		jc	short No_Video_Rom		;CF = Unvalid ROM image
;R54 end
	@@:							;R07
		call	E000_Enter_Prot_mode
		call	E000_Back_Real_Mode		;No valid VGA ROM;R83

	ROM_Exist:

	;----------------------------------------------------------------
	;copy VGA BIOS from high MEM into RAM at address 3000:0
	;----------------------------------------------------------------

		mov	edi, 030000h

		mov	cl, ds:[esi+2]
		xor	ch, ch
		shl	cx, 7
	@@:
		mov	eax, ds:[esi]
	ifndef	PCI_RESET_SUPPORT
		mov	ebx, ds:[esi]
		cmp	eax, ebx
		jnz	@B
	endif	;PCI_RESET_SUPPORT
	ifdef	VT586_ACPI
		mov	ebx, ds:[esi]
		cmp	eax, ebx
		jnz	@B
	endif	;VT586_ACPI
		mov	ds:[edi], eax
		add	edi, 4
		add	esi, 4
		loop	@B

;R83		call	E000_Back_Real_Mode

		pop	cx				;R17

	;Disable ROM decode for fixing CirrusLogic CL7555 PCI VGA bug
		mov	cl, 30h				;R50
 		call	F000_Get_CfgSpace_Byte		;R50
		and	al,NOT 01H			;R50
 		call	F000_Set_CfgSpace_Byte		;R50

		clc
		retf

	No_Video_Rom:

		pop	cx				;R17
		stc
		retf

fProc_Find_VGA_ROM_Image	Endp

		Public	Move_VGA_BIOS_To_C000
Move_VGA_BIOS_To_C000	Proc	Near
		ret
Move_VGA_BIOS_To_C000	Endp
endif	;PCI_BUS

ECODE		ENDS

ifdef	PCI_BUS
		extrn	fProc_Get_Vendor_ID:far
		extrn	fProc_Get_Device_ID:far
		extrn	fProc_Get_CfgSpace_Byte:far
		extrn	fProc_Get_CfgSpace_Word:far
		extrn	fProc_Get_CfgSpace_Dword:far
		extrn	fProc_Set_CfgSpace_Byte:far
		extrn	fProc_Set_CfgSpace_Word:far
		extrn	fProc_Set_CfgSpace_Dword:far
		extrn	fProc_Disable_PCI_ROM:far
		extrn	post_call_proc:near
		extrn	IrqRout_Table:Near
		extrn	CPU_Cache:near

		extrn	Set_Cyrix:Near
		extrn	Move_Codes:Near

		extrn	Ct_PCI_Info:Near

	ifndef	ALWAYS_LEVEL_PCI_IRQ
		extrn	PCI_IRQ_Method:near		;pcifeat.asm
	endif;	ALWAYS_LEVEL_PCI_IRQ

	ifdef	PCI_VGA_IRQ_SETUP_ITEM
		extrn	Assign_Pci_IRQ_Item:Near
	endif	;PCI_VGA_IRQ_SETUP_ITEM

	ifdef	ONBOARD_ScsiChip
		extrn	Onboard_Scsi_Item:near
	endif	;ONBOARD_ScsiChip

		extrn	fProc_Pci_CbRom_decompress:far
		extrn	Check_If_NCR_SCSI:Near

	ifdef	SCSI_IRQ_TO_336_SIRQ3
		extrn	Set_336_Sirq3:near
	endif;	SCSI_IRQ_TO_336_SIRQ3

	ifdef	M1523B_USB
		extrn	M1523B_USB_Irq:Near
	endif;	M1523B_USB

	ifdef	ITE8330G_USB
		extrn	ITE8330G_USB_Irq:Near
	endif;	ITE8330G_USB

;R20 - start
 ifdef	PCI_IRQ_SELECTABLE
		extrn	Slot1_IRQ:near	;CMOS setup for slot 1
		extrn	Slot2_IRQ:near	;CMOS setup for slot 2
  ifndef	TWO_PCI_SLOT_ONLY
		extrn	Slot3_IRQ:near	;CMOS setup for slot 3
   ifndef	THREE_PCI_SLOT_ONLY
		extrn	Slot4_IRQ:near	;CMOS setup for slot 4
   endif;	THREE_PCI_SLOT_ONLY
  endif;	TWO_PCI_SLOT_ONLY
;R102A;R102 - starts
;R102A  IF	SLOT5_EXIST
;R102A		extrn	Slot5_IRQ:Near	;CMOS setup for slot 5
;R102A  ENDIF	;SLOT5_EXIST
;R102A  IF	SLOT6_EXIST
;R102A		extrn	Slot6_IRQ:Near	;CMOS setup for slot 6
;R102A  ENDIF	;SLOT6_EXIST
;R102A  IF	SLOT7_EXIST
;R102A		extrn	Slot7_IRQ:Near	;CMOS setup for slot 7
;R102A  ENDIF	;SLOT7_EXIST
;R102A  IF	SLOT8_EXIST
;R102A		extrn	Slot8_IRQ:Near	;CMOS setup for slot 8
;R102A  ENDIF	;SLOT8_EXIST
;R102A  IF	SLOT9_EXIST
;R102A		extrn	Slot9_IRQ:Near	;CMOS setup for slot 9
;R102A  ENDIF	;SLOT9_EXIST
;R102A;R102 - ends
		extrn	IrqRout_1stSlot:near
		extrn	SlotId_1stSlot:near
 endif;	PCI_IRQ_SELECTABLE
;R20 - end

		extrn	PCI_IRQ_RECORD:word		;R12
 		extrn	Get_PCI_IRQ_Record_Lo:word	;R12
 		extrn	Get_PCI_IRQ_Record_Hi:word	;R12

		extrn	SYSTEM1_BYTE:near		;R19
		extrn	CONFIG_TABLE:near		;R19
		extrn 	Reserve_Ebda_1Kb:near		;R19

 ifndef	NEW_PNP_SETUP					;R37
	ifdef	PNP_PCI_AUTO				;R37
		extrn	PnP_Auto_Item:near		;R37
	endif	;PNP_PCI_AUTO				;R37
 endif	;NEW_PNP_SETUP					;R37

	ifdef	AGP_SLOTID				;R39
		extrn	FirstInitAGP_Item:near		;R39
	endif	;AGP_SLOTID				;R39

 ifdef	ACPI_SUPPORT					;R64
   IFDEF	VT586_ACPI				;R64
	ifndef	No_ACPI_IRQ_Auto_Assign			;R64A
		extrn	ACPI_option_Item:near		;R64
	ifdef	ACPI_IRQ_Selectable			;R64B
	ifdef	ACPI_IRQ_Auto_Assign_Selectable		;R64B
		extrn	Assign_ACPI_IRQ_Item:near	;R64B
   	endif;	ACPI_IRQ_Auto_Assign_Selectable		;R64B
	endif;	ACPI_IRQ_Selectable			;R64B
	endif;	No_ACPI_IRQ_Auto_Assign			;R64A
   ENDIF;	VT586_ACPI				;R64
 endif;	ACPI_SUPPORT					;R64

		extrn	fPROC_Get_Available_LMEM:FAR	;R82
		extrn	fPROC_Disable_Unused_Shadow:FAR	;R82
ifdef	PciLanROM_Control				;R91
		extrn	PciLanROM_Item:near		;R91
endif	;PciLanROM_Control				;R91

endif	;PCI_BUS

XGROUP		GROUP	XCODE
XCODE		SEGMENT USE16 PARA PUBLIC 'XCODE'
		ASSUME	CS:XGROUP, ES:XGROUP

ifdef	PCI_BUS
		Public	IRQ_REQ_BUF
		Public	IRQ_REQ_BUF_PTR
IRQ_REQ_BUF	db	256 dup (0)
IRQ_REQ_BUF_PTR	dw	offset IRQ_REQ_BUF

;[]================================================================[]
;Function : Scan all PCI devices and assign I/O , memory space and
;	    IRQ for PCI/IDE if required
;Input  : none
;Output : none
;[]================================================================[]
		ALIGN	4
		Public	fProc_Pci_IO_Mem_Init
fProc_Pci_IO_Mem_Init	Proc	Far

		PUSH_ALL

		call	EnableL1Cache			;R70
;R70		mov	al, TRUE
;R70		call	X_CPU_Cache

		call	Init_Variables

 		call	Assign_IRQ_For_PCI_IDE

		call	Open_IDE_2nd_Channel			;R05

		call	Scan_MemIO_Req

ifdef	M1543							;R25
		out	80h,al 					;R25
		out	80h,al 					;R25
endif	;M1543							;R25

		call	Record_Max_Bus_No

		call	Determine_Device_Resource

		call	Scan_PCI_VGA

		mov	byte ptr NEED_ASSIGN_LMEM_FLAG[bp], 0AAh
		call	Determine_Device_Resource

		call	Sort_IRQ_Requests

		call	Disable_Slot_IDE

		call	Patch_PCI_Card			;R42

		mov	al, FALSE
		call	X_CPU_Cache

		POP_ALL
		retf

fProc_Pci_IO_Mem_Init	Endp

;R70 - start
;Function : Enable CPU L1 cache for fast PCI devices initializations
;Input    : none
;Output   : none
EnableL1Cache	proc	near

if	BIOS_SUPPORT_686
	;Don't turn no CPU L1 cache if PPGA370 CPU is plugged and
	;the clock ratio is 6 or 6.5. Otherwise system hang up in rountine
	;"Scan_MemIO_Req".
		mov	eax,1			;read cache isze
		db	0Fh,0A2h		;OP code: CPUID
		and	ax, 0FFFH
		cmp	ax, 0665H		;Medocino(PPGA/370) CPU ?
		jne	short NoPpga370Cpu	;no

		mov	ecx, 2AH 		;power on config. register
		RDMSR				;read MSR
		shr	eax, 22			;get clock ratio in AL bit3-0
		and	al, 0fH			;only low nibble useful
		cmp	al, 1011B		;ration is 6.
		je	short SkipL1Cache
		cmp	al, 1111B		;ration is 6.5.
		je	short SkipL1Cache
NoPpga370Cpu:
endif;	BIOS_SUPPORT_686

		mov	al, TRUE
		call	X_CPU_Cache
SkipL1Cache:

		ret
EnableL1Cache	endp
;R70 - end

;R42 - start
;[]============================================================[]
;[]============================================================[]
Patch_PCI_Card	Proc	near

		call	Patch_P2P_Matrox
ifndef	VT596						;R56C
		call	Patch_LanBoot			;R56
endif;	VT596						;R56C

		call	Patch_CMD646U_PCIIDE		;R74

ifdef	MOON_ISA					;R103
		call	Patch_W83628F			;R103
		call	Patch_IT8888F			;R105
endif;	MOON_ISA					;R103

		ret
Patch_PCI_Card	Endp

;R103 - start
;R105 - start
;Function : It is for enable IT8888F (P2I bridge) subtractive.
;Input    : none
;Output   : none
Patch_IT8888F	Proc	Near

		mov     dx,1283H                ;vendor ID
		mov     cx,8888H                ;device ID
		xor     si,si                   ;first device
		mov     ax,0b102H               ;find PCI device func. call
		int     1AH
		jc      short @F

; Now	: BH = Bus Identification Number (0...255)
;	  BL = Device Number in upper 5 bits
;	       Function Number in lower 3 bits

ifdef	ICH
	;ICH's MISA must be connected to AD22, the following code
	;can prevent system hang with Rom Emulator Debug Card(IT8888).
		and	bl,11111000b
		or	bl,(22-16) shl 3
endif;	ICH
;R105A - start
		push	bx
		mov	ch,bl
		mov	cl,57h
		F000_CALL AGet_CfgSpace_Byte
		or	al,0c0h			;enable DMA cahnnel
		F000_CALL ASet_CfgSpace_Byte
		pop	bx
;R105A - end
		mov	ch,bl
		mov	cl,50h
		F000_CALL AGet_CfgSpace_Byte
		or	al,01h
		F000_CALL ASet_CfgSpace_Byte
	@@:

		ret
Patch_IT8888F	Endp
;R105 - end

ifdef	MOON_ISA
;Function : It is for enable W83628F (P2I bridge) port 80h decode.
;Input    : none
;Output   : none
Patch_W83628F	Proc	Near

		mov     dx,1050H                ;vendor ID
		mov     cx,0628H                ;device ID
		xor     si,si                   ;first device
		mov     ax,0b102H               ;find PCI device func. call
		int     1AH
		jc      short @F

; Now	: BH = Bus Identification Number (0...255)
;	  BL = Device Number in upper 5 bits
;	       Function Number in lower 3 bits
		mov	ch,bl
		mov	cl,80h
		F000_CALL AGet_CfgSpace_Byte
		or	al,10h
		F000_CALL ASet_CfgSpace_Byte
	@@:

		ret
Patch_W83628F	Endp
endif;	MOON_ISA
;R103 - end

;R74 - start
Patch_CMD646U_PCIIDE	Proc	Near
		xor     si,si                   ;first device
	SetNative:
		mov     dx,1095H                ;vendor ID
		mov     cx,0646H                ;device ID
		mov     ax,0b102H               ;find PCI device func. call
		int     1AH
		jc      short Not_CMD_646U

; Now	: BH = Bus Identification Number (0...255)
;	  BL = Device Number in upper 5 bits
;	       Function Number in lower 3 bits

		mov	ch,bl
		mov	cl,09h
		F000_CALL AGet_CfgSpace_Byte

		or	al,0fh

		F000_CALL ASet_CfgSpace_Byte

		inc	si			;next device
		jmp	short SetNative

	Not_CMD_646U:
		ret
Patch_CMD646U_PCIIDE	Endp
;R74 - end

;R56 - start
;Function : Clear PME# status of Intel 558 LAN chip.
;	    The PME# keep at low state while the system is power-on by
;	    LAN. BIOS need to clear PME# status to make PME# to high
;	    state for next wake-on-lan.
;Input    : none
;Output   : none
		public	Patch_LanBoot		;R56A
Patch_LanBoot	Proc	near

;R56D	xor     si,si                   ;first device
;R56D
;R56D	Clear_PME:				;R56A
;R56D
;R56D;R56B		mov     dx,8086H                ;vendor ID
;R56D;R56B		mov     cx,1229H                ;device ID, Intel 558 LAN card
;R56D;R56B		mov     ax,0b102H               ;find PCI device func. call
;R56D
;R56D;R56B - start
;R56D		mov     ecx,00020000h           ;find class code (Network)
;R56D		mov     ax,0b103H               ;find PCI device func. call
;R56D;R56B - end
;R56D
;R56D		int     1AH
;R56D		jc      short Not_WOL_Card
;R56D
;R56D;R56B		mov	ch,bl			;device + function No.
;R56D;R56B		mov	cl,0e1h			;PME# status register
;R56D;R56B		F000_CALL AGet_CfgSpace_Byte
;R56D;R56B		F000_CALL ASet_CfgSpace_Byte	;write to clear PME# status
;R56D
;R56D;R56B - start
;R56D
;R56D		push	bx			;save Bus No + Device No + Func No
;R56D		mov	ch,bl			;device + function No.
;R56D		mov	cl,34h			;PME# point register
;R56D		F000_CALL AGet_CfgSpace_Byte
;R56D		pop	bx			;get Bus No + Device No + Func No
;R56D		mov	ch,bl
;R56D		mov	cl,al
;R56D		add	cl,3
;R56D
;R56D		push	bx			;save Bus No + Device No + Func No
;R56D		push	cx			;save Register index
;R56D		F000_CALL AGet_CfgSpace_Byte
;R56D		pop	cx			;get Register index
;R56D		pop	bx			;get Bus No + Device No + Func No
;R56D
;R56D		test	al,11111000b		;PMC bit 31-27 if any bit is
;R56D		jz	short No_PME_Support	;not 0 then PME# not supported
;R56D
;R56D		add	cl,2
;R56D
;R56D		F000_CALL AGet_CfgSpace_Byte
;R56D		F000_CALL ASet_CfgSpace_Byte	;write to clear PME# status
;R56D
;R56D	No_PME_Support:
;R56D;R56B - end
;R56D
;R56D		inc	si			;R56A next device
;R56D		jmp	short Clear_PME		;R56A
;R56D
;R56D	Not_WOL_Card:

;R56D - start
;R56E ifdef	CLEAR_PCI_MODEM_PME
		mov     ecx,00078000h           ;find class code (Communication)
		call	ClearPMEStatus		;clear PME# status
;R56E endif;	CLEAR_PCI_MODEM_PME

		mov     ecx,00020000h           ;find class code (Network)
		call	ClearPMEStatus		;clear PME# status
;R56D - end

		ret
Patch_LanBoot	endp
;R56 - end


;R56D - start
;
;Function : Clear PME# status by Read & Write PMCSR register
;Input    : ecx - class code in lower three bytes
;Output   : none
;
ClearPMEStatus	proc	near

		xor     si,si                   ;first device

	Clear_PME:

		mov     ax,0b103H               ;find PCI device func. call

		int     1AH
		jc      short ClassNotFind

		mov	di, 34H			;PME# capability register
		mov	ax, 0b108H		;PCI byte read in CL
		int	1AH			;PCI BIOS interface

		or	cl, cl			;PME support ?
		jz	short No_PME_Support

		add	cl, 3			;Power Management Capabilities
		movzx	di, cl			;PCI index register
		mov	ax, 0b108H		;PCI byte read
		int	1AH			;PCI BIOS interface

		test	cl,11111000b		;PMC bit 31-27 if any bit is
		jz	short No_PME_Support	;not 0 then PME# not supported

		add	di,2			;Power Management Control/
						;status register

	;Read & Write PMCSR register to clear PME# status, the PME status
	;is at bit 7 of Cap_Ptr+05H
		mov	ax, 0b108H		;PCI byte read
		int	1AH			;PCI BIOS interface

		mov	ax, 0b10BH		;PCI byte write
		int	1AH			;PCI BIOS interface

	No_PME_Support:

		inc	si			;next device
		jmp	short Clear_PME		;

	ClassNotFind:

		ret
ClearPMEStatus	endp
;R56D - end

Patch_P2P_Matrox	Proc	near
;Disable PCI bursting if CIRRUS 5424 is plugged
		mov     dx,1014H                ;P2P vendor ID
		mov     cx,0022H                ;P2P device ID
		xor     si,si                   ;first device
		mov     ax,0b102H               ;find PCI device func. call
		int     1AH
		jc      short Not_P2P_Matrox

; Now	: BH = Bus Identification Number (0...255)
;	  BL = Device Number in upper 5 bits
;	       Function Number in lower 3 bits

;Check P2P MATROX VGA card(VR card) for sure?
		mov	ch,bl
		mov	cl,19h
		F000_CALL AGet_CfgSpace_Byte
		mov	bh,al			;Now al= Matrox bus No.
		mov	cx,(01 SHL 11)+00h
		F000_CALL AGet_CfgSpace_Word
		cmp	ax,102bh		;Matrox Vendor ID
		jne	short Not_P2P_Matrox

		mov	cx,(01 SHL 11)+02h
		F000_CALL AGet_CfgSpace_Word
		cmp	ax,0519h		;Matrox Device ID
		jne	short Not_P2P_Matrox

		mov     dx,1014H                ;P2P vendor ID
		mov     cx,0022H                ;P2P device ID
		xor     si,si                   ;first device
		mov     ax,0b102H               ;find PCI device func. call
		int     1AH

		mov	ch,bl
		mov	cl,26h
		xor	al,al
		F000_CALL ASet_CfgSpace_Byte

		mov	ch,bl
		mov	cl,27h
		F000_CALL AGet_CfgSpace_Byte
		and	al,not 08h
		F000_CALL ASet_CfgSpace_Byte

Not_P2P_Matrox:
		ret
Patch_P2P_Matrox	Endp
;R42 - end

;[]============================================================[]
;[]============================================================[]
Sort_IRQ_Requests	Proc	Near
		push	ds
		mov	ax, SEG IRQ_REQ_BUF
		mov	ds, ax
		mov	si, offset IRQ_REQ_BUF
		call	Sort_PCI_Request
		pop	ds
		ret
Sort_IRQ_Requests	Endp

;[]================================================================[]
;Input	     :	None
;Description :	To clear all variables needed for the PCI initializations
;[]================================================================[]
Init_Variables	Proc	Near

	xor	eax, eax
	mov	TOTAL_BUS_NO[bp], al	;initial total bus no. = 0
	mov	CURRENT_BUS_NO[bp], al	;initial bus no. = 0
	mov	CURRENT_SLOT[bp], al	;slot no. of host bridge
	mov	VGA_BIOS_LENGTH[bp], al
	mov	PCI_IDE_EXIST[bp], al
	mov	CURRENT_BUS_NO[bp], al
	mov	PCI_VGA_FOUND[bp], al
	mov	NCR_810_FOUND[bp], al
	mov	LMEM_RESOURCE[bp], eax
	mov	PCI_IRQ_ASSIGNED[bp], ax
	mov	NEED_ASSIGN_LMEM_FLAG[bp], al

	mov	byte ptr ONBOARD_VGA_P2P[bp], -1	;R38

	call	Prepare_PCI_Bus_Info				;R05

	call	Prepare_LMEM_Resource

	mov	word ptr BASE_REQ_BUF_PTR[bp], offset TEMP_BASE_REQ_BUF
	mov	word ptr PCI_VGA_DEVICE_BUF_PTR[bp], offset PCI_VGA_DEVICE_BUF

	push	SEG TEMP_PCI_REQ_BUF
	pop	ds
	call	Clear_PCI_Req_Buffer

	call	CMOS_Setup_IRQ_Resource

	ret

Init_Variables	Endp

;[]============================================================[]
;Input	:	AL = 0 : Prepare Memory below 1M resources
;Output	:	AL = 0 --> Output None
;[]============================================================[]
		ALIGN	4
Prepare_LMEM_Resource	Proc	Near

		push	ds
		push	es
		pushad

;-----------------------

ifdef	SHADOW_UNIT_64K							;R82
		mov	si, 0D000h		;scan from D0000h	;R82
else	;SHADOW_UNIT_64K						;R82
		mov	si, 0C800h		;scan from C8000h
endif	;SHADOW_UNIT_64K						;R82

;Occupied low memory resource if VGA BIOS is bigger than 32kb

	;=====================
	Scan_ROM:

		POST_FUNC_CALL Check_ROM_Exist		;check if ROM existed?
		je	ISA_ROM_Found			;yes, go record	this

							;  seg. as used!
	;=====================
		xor	di, di

	Chk_RW:

ifndef	No_Chk_LMEM_RW
		cmp	dword ptr ds:[di], -1
		jne	Addr_Can_W
	ifdef PROTECH_RAM_DISK_CARD
		push	word ptr ds:[di]
	endif ;PROTECH_RAM_DISK_CARD

		mov	ah, 0A5h
		mov	byte ptr ds:[di], ah		;write pattern
		NEWIODELAY				;R53
		cmp	byte ptr ds:[di], ah		;read pattern

	ifdef PROTECH_RAM_DISK_CARD
		pop	word ptr ds:[di]
	endif ;PROTECH_RAM_DISK_CARD

		je	Addr_Can_W
endif	;No_Chk_LMEM_RW

		add	di, 4			;next 4 bytes
		cmp	di, 800h
		jb	Chk_RW
		jmp	No_ROM_Here

	Addr_Can_W:

		mov	cl, 1				;mark 4k not available
		call	X_Mark_Addr_Not_Available
		jmp	No_ROM_Here

	;=====================
	ISA_ROM_Found:

		POST_FUNC_CALL Rom_In_Terms_of_4K
		push	cx
		call	X_Mark_Addr_Not_Available	;record it
		pop	cx

		xor	ch, ch				;point to next addr.
		shl	cx, 8				;  according to ROM
		add	si, cx				;  size
		jmp	@F

	No_ROM_Here:

		add	si, 80h				;next 2k to scan
	@@:
	ifdef	SEANIX_SPECIAL_PCIPOST
		out	80h, al
	endif	;SEANIX_SPECIAL_PCIPOST
		cmp	si, 0E000h			;end of address?
		jb	Scan_ROM			;no, continue!

	ifdef	PNP_BIOS
		push	G_RAM
		pop	ds
		assume	DS:G_RAM

		mov	edx, dword ptr ds:UMB_MAP
		not	edx
		shr	edx, 8
		or	dword ptr LMEM_RESOURCE[bp], edx

	endif	;PNP_BIOS

;-----------------------
;R90 - starts
	ifdef	SHADOW_UNIT_64K
		call	If_Any_VGA_BIOS_Exist		;ISA/VGA exist ?
		jne	NoIsaVGAExist
		mov	byte ptr LMEM_RESOURCE[bp], 0FFh
	NoIsaVGAExist:
	endif	;SHADOW_UNIT_64K
;R90 - ends
		call	X_Invalidate_Shadow_Seg	;invalidate whole shadow seg
						;i.e. shadow unit = 16K(32K)
						;     ==> invalidate whole
						;	  16k(32k) even if it
						;	  is not totally used!

 		push	dword ptr LMEM_RESOURCE[bp]
 		pop	dword ptr LMEM_BEFORE_ROM[bp]

		popad
		pop	es
		pop	ds

		ret

Prepare_LMEM_Resource	Endp

;[]================================================================[]
;  Prepare variables for PCI configurations according to Bus No.
;  such as:
;	1. Memory & IO range
;	2. Device No. range
;	3. Temporary ROM address
;[]================================================================[]
Prepare_PCI_Bus_Info	Proc	Near

		pushad
		push	ds
		push	SEG TEMP_PCI_REQ_BUF
		pop	ds

		call	See_If_Bus_0
		je	Bus0_Info

		mov	al, CURRENT_BUS_NO[bp]
		call	Get_Bus_Info_Offset

 		mov	eax, ds:[si].Bus_PfMem_Start
 		mov	AVAILABLE_PREFET_START[bp], eax
		mov	ebx, ds:[si].Bus_IO_Start
		mov	esi, ds:[si].Bus_Mem_Start
		mov	ax, 1000h
		jmp	Update_PCI_Info

;-----------------------------------------------------
;call chipset dependent routine to get informations
;-----------------------------------------------------
Bus0_Info:
		push	ds
		F000_CALL Ct_PCI_Info
		pop	ds

		mov	ebx, ds:[TotalMemReq]
		add	ebx, ds:[TotalPfMemReq]
		cmp	ebx, 18000000h
		jae	@F
ifdef	STPC_IDE	     				;R87
		mov	ebx, 08000000h	;from F0000000H	;R87
else;	STPC_IDE	     				;R87
		mov	ebx, 18000000h
endif;	STPC_IDE	     				;R87
	@@:
;R58 - starts
		test	ebx, 03FFFFFFh
		jz	short Min64MBound
		and	ebx, not 03FFFFFFh
		add	ebx, 04000000h
	Min64MBound:
;R58 - ends

;R67 - starts
ifndef	PCI_IO_LIMIT
	PCI_IO_LIMIT	=	0EFFFh + 1
endif	;PCI_IO_LIMIT
;R67 - ends
		mov	esi, 0F8000000h
		sub	esi, ebx
;R67		mov	ebx, 0F000h
		mov	ebx, PCI_IO_LIMIT		;R67
		sub	ebx, ds:[TotalIOReq]

;-----------------------------------------------------
;write informations into [BP] area
;-----------------------------------------------------
Update_PCI_Info:

		shl	al, 3			;from first device func 0
		shl	ah, 3
		or	ah, 07h			;to  last device func 7
		mov	START_PCI_DEV[BP], al
		mov	END_PCI_DEV[BP], ah

		mov	AVAILABLE_MEM_START[bp], esi
		mov	AVAILABLE_IO_START[bp], ebx
		pop	ds
		popad
		ret

Prepare_PCI_Bus_Info	Endp

;------------------------------------------------------------------
;
;Input	   :	TOTAL_BUS_NO[bp]
;
;Updated   :	Routine: Get_Max_PciBus in F000 will be hard-coded
;
;Destroyed :	DS, BX, DX, EAX, CX
;
;Note	   :	We put the max bus no. info into shadow RAM
;		by hard coding the routine: Get_Max_PciBus
;		which is simply "mov cl, ??'. The machine code of
;		this instruction is "db 0B1h, ??h"
;
;		By calling this routine during run time (PCI1A.ASM
;		& PCI32.ASM), we will get the maximum bus number in CL
;
;------------------------------------------------------------------
Record_Max_Bus_No	Proc	Near

	ifdef	CONFIG_MECHANISM_1
		push	ds
;R12		F000_CALL F000_Shadow_W
		call	X_F000_Shadow_W			;R12
		mov	ax, SEG Get_Max_PciBus
		mov	ds, ax
		mov	si, offset Get_Max_PciBus
		mov	bl, 0B1h
ifndef	Patch_3COMCardbus_InDOS				;R69
		mov	bh, TOTAL_BUS_NO[bp]
else	;Patch_3COMCardbus_InDOS			;R69
		mov	bh, Patch_3COMCardbus_InDOS	;R69
endif	;Patch_3COMCardbus_InDOS			;R69
		mov	ds:[si], bx
;R12		F000_CALL F000_Shadow_R
		call	X_F000_Shadow_R			;R12
		pop	ds
	endif	;CONFIG_MECHANISM_1

		ret

Record_Max_Bus_No	Endp

;--------------------------------------------------------------------
;Input	:	CURRENT_BUS_NO[bp] - Bus to be scanned
;
;Description :	To scan & record all base request of all PCI devices
;		on the PCI bus describe by CURRENT_BUS_NO[bp]. We
;		record all the base requests in a buffer in segment
;		TEMP_PCI_REQ_BUF.
;
;		If any one device on the bus is a P2P bridge, this
;		routine will issue a RECURSIVE call to itself. Thus we
;		need a boundary condition such that this recursive
;		mechanism will come to an end.
;		The boundary condition is:
;
;		  --- THERE IS NO P2P BRIDGE DEVICE ON THE BUS ---
;
;		For the stored base requests in TEMP_PCI_REQ_BUF, they
;		are only stored according to the sequence which they
;		are read. We will further analyse these records in the
;		following manner:
;
;		  1. divide these records according to their bus number
;		     (described in the data structure), move them to another
;		     buffer(PCI_REQ_BUF).
;		  2. Sort the base request in PCI_REQ_BUF in a decreasing
;		     order.
;		  3. Assign resource to them
;		  4. repeat step 1-3 until we reach the maximum bus no.
;
;--------------------------------------------------------------------
Scan_MemIO_Req	Proc	Near

		push	ecx

	;----------------------------------------------------------------
	;Clear all P2P devices on current Bus so that every P2P device
	;(if any) can be access correctly
	;----------------------------------------------------------------

		call	Clear_P2P

		call	Prepare_PCI_Bus_Info
		mov	ch, START_PCI_DEV[BP]

	Next_Pci_Dev_On_This_Bus:

		call	Update_Slot_No

		push	cx			;save device & function no.

	;-----------------------------------------------------
	;If (Device needs no resources)
	;	Skip;
	;If (this device is a P2P Bridge)
	;   {
	;	issue a recursive call to itself
	;	"call Scan_MemIO_Req"
	;   }
	;Else
	;   Record the requests of this device into buffer
	;Endif;
	;-----------------------------------------------------

		call	X_Get_Device_ID  		;device ID in AX
		mov	CURRENT_DEVICE_ID[bp], ax
		shl	eax, 16
		call	X_Get_Vendor_ID 		;retrieve vendor ID
		mov	CURRENT_VENDOR_ID[bp], ax
		jc	Device_No_Request		;skip if no vendor ID !
		or	eax, eax
		jz	Device_No_Request

		mov	cl, 0AH				;get class code
		call	X_Get_CfgSpace_Word		;get class code
		mov	CURRENT_CLASS_CODE[bp], ax	;R16
		cmp	ax, 0601H			;PCI-ISA bridge?
		je	Device_No_Request		;skip it
		cmp	ax, CLASS_PP_BRIDGE		;PP bridge ?
		jne	Go_Analyse_Device		;No! Go to record
							; requests
	;-----------------------------------------------------
	;If this device is a P2P Bridge, issue a recursive
	;call to itself "call Scan_MemIO_Req"
	;-----------------------------------------------------

		inc	byte ptr TOTAL_BUS_NO[bp]	;of course we need to
							;increase total bus
							;number by 1
		mov	cl, 18h
;R98		mov	eax, 407F0000h			;assume subordinate=7Fh
		mov	eax, 207F0000h			;assume subordinate=7Fh ;R98
		mov	al, CURRENT_BUS_NO[bp]		;set bus number:
		mov	ah, TOTAL_BUS_NO[bp]		;   pri. bus, 2nd bus
							;   & max. sub bus
		call	X_Set_CfgSpace_DWord

		call	Patch_Platform_P2P_Bridge

		mov	al, CURRENT_BUS_NO[bp]
		call	Record_P2P_Info

		call	Record_IRQ_Request	        ;R88

		push	ax				;save bus number
		push	word ptr START_PCI_DEV[bp]
		mov	al, TOTAL_BUS_NO[bp]
		mov	CURRENT_BUS_NO[bp], al		;new bus number
		call	Scan_MemIO_Req			;issue recursive call
		pop	word ptr START_PCI_DEV[bp]
		pop	ax				;restore bus number

		mov	CURRENT_BUS_NO[bp], al

		mov	cl, 1Ah				;program reg 1Ah
		mov	al, TOTAL_BUS_NO[bp]		;for the maximum
		call	X_Set_CfgSpace_Byte		;subordinate bus number

		jmp	Device_No_Request		;end of this P2P bridge

	;-----------------------------------------------------
	;If this device is normal PCI device,
	;Record the requests of this device into buffer
	;-----------------------------------------------------

	Go_Analyse_Device:

		mov	bl, 08h			;cache line size = 08h
		call	Prg_Device_Latency	;to program the latency timer

		call	Skip_IDE_Base_Request	;special for IDE devices
		jc	Device_No_Request	;skip some IDE vendor

		pusha				;someone may want to skip
		F000_CALL Ct_Special_PCI_Device	; resources for specific device
		popa				; or slot
		jc	Device_No_Request	;CF = skip this device

		call	Check_If_BusTek_Bt946C	;Special for BusLogic's non PCI
						;compliance device exist
		jc	Device_No_Request	;CF = this device found !

		call	Record_NCR_Device	;record if NCR SCSI exist or not
						;stored at NCR_810_FOUND[bp]

		call	Record_IRQ_Request	;record IRQ requests information
						;in TEMP_PCI_REQ_BUF:IRQ_REQ_BUF

		push	ax			;save class code
		mov	cl, 3cH			;Disable IRQ number, some dev
		mov	al, 0ffH		;has a default value
		call	X_Set_CfgSpace_Byte
		pop	ax			;restore class code

		call	X_Disable_PCI_ROM	;disable the ROM

		call	Record_Base_Requests	;record requests
		jc	Device_No_Request	;CF=This device killed

	;enable IO, MEM, Master and clear status

		mov	cl, 04h			;Command Register
		mov	eax, 0F0000003H		;enable I/O & Mem. decode;R57
ifdef	VSA_VGA							  ;R57C
		mov	eax, 0F0000007H		;enable I/O & Mem ;R57C
endif	;VSA_VGA                                ; & Master bit    ;R57C
;R57		mov	eax, 0F0000007H
;R57		POST_FUNC_CALL Check_Master_Needed	;enable master or not?
;R57		jnc	@F
;R57		and	al, not 04h
;R57	@@:

;R94 - start
	;Disable I/O & memory decode in command register to prevent
	;unconditional memory address decode at 0C0000H for Avance Logic
	;VGA card.
		cmp	word ptr CURRENT_CLASS_CODE[bp], 0300H	;VGA ?
		je	short DisableCmdReg

		cmp	word ptr CURRENT_CLASS_CODE[bp], 0301H	;XGA ?
		je	short DisableCmdReg

		cmp	word ptr CURRENT_CLASS_CODE[bp], ALT_CLASS_VGA	
		je	short DisableCmdReg

		jmp	short NotVGADev

	DisableCmdReg:
		xor	al, al				;disable I/O & Mem.
	NotVGADev:
;R94 - end

;R94 ;R79 - starts
;R94 ifdef	WHITNEY_SPECIAL					
;R94 		cmp	byte ptr current_bus_no[bp], 0
;R94 		jne	_OIU
;R94 		cmp	ch, ONBOARD_PCI_VGA
;R94 		jne	_OIU
;R94 		xor	al, al
;R94 	_OIU:
;R94 endif;	WHITNEY_SPECIAL					
;R94 ;R79 - ends

		call	X_Set_CfgSpace_DWord

	;-----------------------------------------------------

	Device_No_Request:

		pop	cx			;restore device & function no.

		call	X_Get_Next_Device	;CH point to next device
		jnc	Next_Pci_Dev_On_This_Bus;CF = no more device

	This_Bus_End_Here:

		call	Include_Subordinate_Reqests

		pop	ecx

	;--------------------------------------------------------------
	;if we are now in Bus 0, that means we are going to return
	;to caller:fProc_Pci_IO_Mem_Init. We should append a dummy
	;base request to TEMP_PCI_REQ_BUF:TEMP_BASE_REQ_BUF to indicate
	;the end of all base requests
	;--------------------------------------------------------------

		call	See_If_Bus_0
		jne	@F
		mov	dh, 0FFh
		call	Append_Base_Request
	@@:

		ret

Scan_MemIO_Req	Endp

;======================================================================
;
;Update CURRENT_SLOT[bp]
;
;This information is going to be added to the IRQ request buffer
;informations so that we can retrieve the correct IRQ routing
;when assigning IRQs for devices.
;
;Input	:	CURRENT_BUS_NO[bp] = bus number
;		CH 		   = Dev & Func number
;
;Update	:	CURRENT_SLOT[bp] = 1, 2, 3 .... N
;		CURRENT_SLOT[bp] = 0FFh means this ID select or slot
;				   is not defined in the routing table
;
;======================================================================
Update_Slot_No	Proc	Near

	;-------------------------------------------
	;There are 2 cases that we do not need to
	;update the slot number, i.e.
	;
	;	1. when we are not in Bus 0
	;	2. when we are not in Function 0
	;-------------------------------------------

		call	See_If_Bus_0		;in bus 0 ?
		jne	No_Slot_Update		;no, skip update slot number
		test	ch, 00000111b		;in function 0 ?
		jnz	No_Slot_Update		;no, skip update slot number

	;-------------------------------------------
	;Search in table: PCI_SLOT_CFG for entry
	;matches CH & then update the index into
	;CURRENT_SLOT[bp].
	;
	;CURRENT_SLOT[bp] will be set to 0FFh
	;if no entry is found matched.
	;-------------------------------------------

		push	cx
		push	ax
		push	ds

		push	SEG PCI_SLOT_CFG
		pop	ds
		mov	si, offset PCI_SLOT_CFG
		mov	byte ptr CURRENT_SLOT[bp], 0FFh
		xor	ah, ah

		shr	ch, 3

	Search_Next_SLot:

		mov	al, byte ptr ds:[si]
		cmp	al, 0FFh
		je	Slot_Not_Specified
		cmp	al, ch
		je	Slot_Num_Found
		inc	si
		inc	ah
		jmp	Search_Next_SLot

	Slot_Num_Found:

		mov	byte ptr CURRENT_SLOT[bp], ah

	Slot_Not_Specified:

		pop	ds
		pop	ax
		pop	cx

	No_Slot_Update:

		ret

Update_Slot_No	Endp

;======================================================================
;Input	:	CURRENT_BUS_NO[bp] = bus number
;		CH 		   = Dev & Func number
;		BL 		   = Cache Line Size
;======================================================================
Prg_Device_Latency	Proc	Near

		push	ax
	ifdef	PCI_LATENCY_SELECTABLE
		call	Get_Latency_Value
		mov	al, 08H				;cache line = 08H
	else;	PCI_LATENCY_SELECTABLE
;R98		mov	ah, 40h				;latency = 40H
		mov	ah, 20h				;latency = 20H ;R98
	endif;	PCI_LATENCY_SELECTABLE
		mov	cl, 0cH
		mov	al, bl
		call	X_Set_CfgSpace_Word
		pop	ax
		ret

Prg_Device_Latency	Endp

ifdef	PCI_LATENCY_SELECTABLE
;----------------------------------------------------
;Function : Read latency timer value set by user
;Input    : none
;Output   : AH - latency timer value
;----------------------------------------------------
Get_Latency_Value	proc	near
		push	si
		mov	si, offset Pci_Latency_Item	;get latency value
		call	X_GetItem_Value
		mov	ah, al
		pop	si
		ret
Get_Latency_Value	endp
endif;	PCI_LATENCY_SELECTABLE

;======================================================================
;======================================================================
Record_NCR_Device	Proc	Near

		pusha

;R03	ifdef	ONBOARD_NCR_SETUPABLE
;R03		call	Check_Onboard_SCSI_Slot		;check if onboard slot
;R03		jc	@F
;R03	endif;	ONBOARD_NCR_SETUPABLE

		POST_FUNC_CALL Check_If_NCR_SCSI
		jc	@F

		mov	byte ptr NCR_810_FOUND[bp], NCR_SCSI_FOUND
	@@:
		popa

		ret

Record_NCR_Device	Endp

;======================================================================
;======================================================================
Check_If_BusTek_Bt946C	Proc	Near

	call	See_If_Bus_0
	jne	@F
	cmp	word ptr CURRENT_VENDOR_ID[bp], 104Bh	;Bustek vendor ID?
	jne	@F
	cmp	byte ptr CURRENT_DEVICE_ID[bp+1], 10h	;PCI compliance card?
	jae	@F					;larger than 10h
							;  --> compliance
	call	Prg_BusTek_BT946C
	stc
	ret
@@:
	clc
	ret

Check_If_BusTek_Bt946C	Endp

;======================================================================
;======================================================================
Prg_BusTek_BT946C	Proc	Near

		pushad
		mov	cl, 10h
		xor	eax, eax			;disable I/O decode
		call	X_Set_CfgSpace_DWord

;Find available I/O port for BT-946C

		push	cx

		mov	si, offset BT_946C_IO_ADDR
Check_Next_Io:
		mov	dx, cs:[si]		;get I/O port
		or	dx, dx			;last I/O
		jz	No_Avail_Io
		mov	cx, 4			;total four ports to check
Inc_Io_Port:
		in	al, dx
		IODELAY
		mov	ah, al
		in	al, dx			;data changed -> I/O not available
		IODELAY
		cmp	ah, al
		jne	Next_IO_Addr
		cmp	al, 0ffh		;should be 0ffH if I/O available
		jne	Next_IO_Addr
		inc	dx
		loop	Inc_Io_Port
		mov	dx, cs:[si]		;get I/O port
		jmp	No_Avail_Io

Next_IO_Addr:
		inc	si
		inc	si
		jmp	Check_Next_Io

No_Avail_Io:
		pop	cx
		mov	cl, 10h			;set I/O for PCI device
		xor	eax, eax
		mov	ax, dx			;set I/O port value
		or	ax, ax			;no I/O port available ?
		jz	No_IO_Assign
		or	al, 1			;enable I/O
No_IO_Assign:
		call	X_Set_CfgSpace_DWord

		mov	cl, 04
		mov	al, 07
		call	X_Set_CfgSpace_Byte

		call	X_Disable_PCI_ROM
Prg_BT946C_End:
		popad
		ret

Prg_BusTek_BT946C	Endp

		ALIGN	4
BT_946C_IO_ADDR:
		DW 	0330h
		DW 	0334h
		DW 	0230h
		DW 	0234h
		DW 	0130h
		DW 	0134h
		dw	0

;------------------------------------------------------------------
;PLATFORM's P2P did a wrong definition of "master abort mode".
;BIOS do a patch for it to prevent reading garbage of configuration
;space behind the P2P
;
;Input	:	dword ptr CURRENT_DEVICE_ID[bp]
;------------------------------------------------------------------
Patch_Platform_P2P_Bridge	Proc	Near

		cmp	CURRENT_DEVICE_ID[bp], (1285H SHL 16)+1000h
							;PLATFROM's P2P bridge ?
		jne	Not_Platform_P2P		;no !

		mov	cl, 3eH
		call	X_Get_CfgSpace_Byte
		or	al, 20H				;report master abort
		call	X_Set_CfgSpace_Byte

	Not_Platform_P2P:

		ret

Patch_Platform_P2P_Bridge	Endp

;-------------------------------------------------------------
;Scan all the P2P bridge on current bus & reset it !
;-------------------------------------------------------------
Clear_P2P	Proc	Near

		pushad
		xor	ch, ch

	Clr_Next_PP:

		call	X_Get_Vendor_ID 	;retrieve vendor ID
		jc	Not_P2P_B		;skip if no vendor ID !
		call	If_PP_Bridge		;check if P2P bridge
		jc	Not_P2P_B		;no !

	;-------------------------------------------------------------
	;write 40H then 00H to P2P controller to reset P2P for fixing
	;AHA3940 rebooting problem
	;-------------------------------------------------------------

		mov	cl, 3Eh
		mov	al, 40h
		call	X_Set_CfgSpace_Byte
		xor	al, al
		call	X_Set_CfgSpace_Byte

	;Clear Bus number

		mov	cl, 18h
		xor	eax, eax
		call	X_Set_CfgSpace_DWord

		mov	cl, 04h
		call	X_Set_CfgSpace_Byte

	Not_P2P_B:

		call	X_Get_Next_Device
		jnc	Clr_Next_PP

	End_Clr_P2P:

		popad

		ret

Clear_P2P	Endp

;---------------------------------------------------------------------
;Input : CH : PCI device no.
;Output: NZ : not PCI-TO-PCI bridge
;	 ZF : it's PP bridge
;---------------------------------------------------------------------
		ALIGN	4
If_PP_Bridge	proc	near
		push	eax
		mov	cl, 0AH				;get class code
		call	X_Get_CfgSpace_Word		;get class code
		cmp	ax, CLASS_PP_BRIDGE		;PP bridge ?
		pop	eax
		ret
If_PP_Bridge	endp

;======================================================================
;======================================================================
Record_Base_Requests	Proc	Near

		push	ds
		pushad

		push	SEG TEMP_PCI_REQ_BUF	;point to buffer
		pop	ds

		call	Record_VGA_Devices	;record VGA devices info.

		mov	cl, 10h			;start from 1st base addr.

	Analyse_Next_Base:

		push	cx
		call	Analyse_Base_Request	;return eax & dl
		jc	This_Base_Done		;no space required

		cmp	dl, 2			;need memory space below 1M ?
		jne	short @F		;no
 		call	See_If_Bus_0		;check if bus 0
		jne	_Kill_Dev		;Only allow on bus 0 if
	@@:					;requested mem. space below 1M
		test	eax, 0C0000000h
		jnz	_Kill_Dev

	;----------------------
	;Put Reqest Into Buffer
	;----------------------

		mov	dh, CURRENT_BUS_NO[bp]
		call	Append_Base_Request

	;------------------------------------------------
	;accumulate total request
	;------------------------------------------------

		push	ax
		mov	al, CURRENT_BUS_NO[bp]
		call	Get_Bus_Info_Offset
		pop	ax

		cmp	dl, 2			;need memory space below 1M ?
		je	This_Base_Done

  		mov	bx, TotalIOReq		;size for I/O total request
		cmp	dl, 1			;need I/O space ?
		je	@F			;yes

  		mov	bx, TotalPfMemReq	;size for total Prefetch Mem.
		cmp	dl, 8			;need prefetch memory space ?
		je	@F			;yes

		mov	bx, TotalMemReq		;size for total Memory request
	@@:
		add	ds:[si+bx], eax

	;------------------------------------------------

	This_Base_Done:

		pop	cx

		cmp	dl, 4			;need 64bit address space ?
		jne	@F			;no
		add	cl, 4			;yes, skip next DWORD
	@@:
		add	cl, 4			;check next base address

		cmp	cl, 28h			;last base address ?
		jne	@F			;no, go next base addr. check
		mov	cl, 30h			;check option ROM request
	@@:
		cmp	cl, 30h
		jbe	Analyse_Next_Base
		clc

	Record_Base_Requests_End:

		popad
		pop	ds

		ret

	_Kill_Dev:

		pop	cx
		call	Kill_This_CfgSpace
		stc
		jmp	Record_Base_Requests_End

Record_Base_Requests	Endp

;[]=====================================================================[]
;Input	:	AL = bus number
;Output	:	SI - Offset of Bus Info
;[]=====================================================================[]
Get_Bus_Info_Offset	Proc	Near

		push	ax
		push	cx
		mov	cl, SIZE_BUS_TREE_STRUC
		mul	cl
		mov	si, ax
		pop	cx
		pop	ax
		ret

Get_Bus_Info_Offset	Endp

;-----------------------------------------------------------------
;Input	     :  Information of this base request
;		EAX - Size of this base request
;		DL  - the first 4 bit of this base request
;		DH  - bus no of this base request
;		CX  - Device & function no. of this base request
;
;Description :	To append a base request information into the
;		TEMP_PCI_REQ_BUF segment according to the a pointer
;		value stored in BASE_REQ_BUF_PTR[bp]
;-----------------------------------------------------------------
Append_Base_Request	Proc	Near

		push	di
		mov	di, BASE_REQ_BUF_PTR
		push	ds
		push	SEG TEMP_PCI_REQ_BUF
		pop	ds
		call	Store_Base_Request
		pop	ds
		pop	di

		ret

Append_Base_Request	Endp

;-------------------------------------------------------------
;Input	     :  Information of this base request
;		EAX - Size of this base request
;		DL  - the first 4 bit of this base request
;		DH  - bus no of this base request
;		CX  - Device & function no. of this base request
;-------------------------------------------------------------
Store_MEM_Base_Request	Label	Near

		push	di
		mov	di, HMEM_BUF_PTR
		jmp	@F

;----------------------------------------------------------------
;Input	     :  Information of this base request
;		EAX - Size of this base request
;		DL  - the first 4 bit of this base request
;		DH  - bus no of this base request
;		CX  - Device & function no. of this base request
;----------------------------------------------------------------
Store_PfMEM_Base_Request	Label	Near

		push	di
		mov	di, PREFET_MEM_BUF_PTR
		jmp	@F

;----------------------------------------------------------------
;Input	     :  Information of this base request
;		EAX - Size of this base request
;		DL  - the first 4 bit of this base request
;		DH  - bus no of this base request
;		CX  - Device & function no. of this base request
;----------------------------------------------------------------
Store_LMEM_Base_Request	Label	Near

		push	di
		mov	di, LMEM_BUF_PTR
		jmp	@F

;----------------------------------------------------------------
;Input	     :  Information of this base request
;		EAX - Size of this base request
;		DL  - the first 4 bit of this base request
;		DH  - bus no of this base request
;		CX  - Device & function no. of this base request
;----------------------------------------------------------------
Store_IO_Base_Request	Label	Near

		push	di
		mov	di, IO_BUF_PTR
	@@:
		push	ds
		push	SEG PCI_REQ_BUF
		pop	ds
		call	Store_Base_Request
		pop	ds
		pop	di
		ret

;----------------------------------------------------------------
;Input	     :  Information of this base request
;		EAX - Size of this base request
;		DL  - the first 4 bit of this base request
;		DH  - bus no of this base request
;		CX  - Device & function no. of this base request
;		DS -  Segment of the request buffer
;		DI -  [bp+di] as a pointer to point to the current
;		      available address for storing the request
;
;Description :	To store a base request information into the
;		segment DS according to the a pointer value stored in
;		[bp+di]
;----------------------------------------------------------------
Store_Base_Request	Proc	Near

		push	si
		mov	si, [bp+di]

		mov	ds:[si].MemIO_Req, eax
		mov	ds:[si].Cfg_Loc, cx
		mov	ds:[si].MemIo_Info, dl
		mov	ds:[si].Bus_Num, dh

		add	word ptr [bp+di], SIZE MEMIO_BUF
		pop	si
		ret

Store_Base_Request	Endp

;-------------------------------------------------------------
;-------------------------------------------------------------
Include_Subordinate_Reqests	Proc	Near

		push	ds
		pushad

		push	SEG TEMP_PCI_REQ_BUF
		pop	ds

		mov	al, CURRENT_BUS_NO[bp]
		call	Get_Bus_Info_Offset

	;-------------------------------------------------------
	;Includes all subordinate buses requests
	;-------------------------------------------------------

		mov	bx, Sub_Buses
		mov	cx, MAX_SUB_BUS

	Include_Next_Sub_Bus_Req:

		mov	al, ds:[si+bx]
		or	al, al
		jz	No_More_Sub_Bus

		push	cx
		push	si

		mov	di, si
		call	Get_Bus_Info_Offset

		mov	eax, ds:[si].TotalMemReq
		add	ds:[di].TotalMemReq, eax
		mov	eax, ds:[si].TotalPfMemReq
		add	ds:[di].TotalPfMemReq, eax
		mov	eax, ds:[si].TotalIOReq
		add	ds:[di].TotalIOReq, eax

		pop	si
		pop	cx

		inc	bx
		loop	Include_Next_Sub_Bus_Req

	No_More_Sub_Bus:

	;-----------------------------------------------------

		mov	al, CURRENT_BUS_NO[bp]
		call	Get_Bus_Info_Offset

		mov	di, offset P2P_Request_Tbl
;R34A		mov	cx, No_Of_P2P_Request

	Next_P2P_Request:

		pusha

	;-------------------------------------------------------
	;Set current bus request to max alignment
	;-------------------------------------------------------

;R34		mov	bx, cs:[di]	;BX=TotalMemReq/TotalIOReq/TotalPfMemReq
;R34
;R34		mov	ecx, ds:[si+bx]	;ECX=TotalXXReq
;R34		mov	eax, cs:[di+2]	;[DI+2]=Minimum request for one bus
;R34		shr	eax, 1		;shift right in the first place
;R34 - starts
		mov	bx, cs:[di].TotalReqLoc	;BX=TotalMemReq/TotalIOReq/TotalPfMemReq
		mov	ecx, ds:[si+bx]		;ECX=TotalXXReq
		mov	eax, cs:[di].MinP2PReq	;[DI+2]=Minimum request for one bus
;R34 - ends

;R101	;---------------------------------------------------
;R101	;If MEM or Prefetch memory, do not set a minimum
;R101	;request for it
;R101	;---------------------------------------------------
;R101
;R101		cmp	bx, TotalIOReq
;R101		je	@F
		or	ecx, ecx
		jnz	@F
		xor	eax, eax
		jmp	End_Align_Req
	@@:
	;---------------------------------------------------

;R34	Try_Next_Align:
;R34
;R34		shl	eax, 1		;shift left
;R34		cmp	ecx, eax	;this request enough ?
;R34		jbe	Go_Align_Req	;yes, enough !
;R34		cmp	eax, cs:[di+6]	;max request reached ?
;R34					;  [DI+6]=Maximum request for one bus
;R34		jne	Try_Next_Align	;not yet !
;R34
;R34		mov	eax, cs:[di+10]	;[DI+10]=mask
;R34		and	eax, ecx	;Clear low bits of ECX & result in EAX
;R34 - starts
	Try_Next_Align:

		cmp	ecx, eax		;this request enough ?
		jbe	Go_Align_Req		;yes, enough !

		push	cx
		mov	cl, cs:[di].P2pReqShift
		shl	eax, cl
		add	eax, cs:[di].P2pReqAdd
		pop	cx
		cmp	eax, cs:[di].MaxP2PReq
		jne	Try_Next_Align		;not yet !

		mov	eax, cs:[di].P2PReqMask
		and	eax, ecx	;Clear low bits of ECX & result in EAX
;R34 - ends

	Go_Align_Req:

;R31 - starts
ifdef	AGP_SLOTID
	;-------------------------------------------------------------
	;The Intel 440LX AGP P2P bridge do not fully decode the I/O space.
	;When the I/O range of this bridge is set to B000h-BFFFFh(when the
	;total I/O request of Bus 0 including P2P is 4000h), it will cause
	;the S3 775 VGA card to have a blank screen(except the mouse cursor)
	;under NT4.0 with the VGA device driver installed.
	;
	;The below patch is to fix the above problem. It works because,
	;in a Intel AGP platform, the AGP bridge is always the first
	;I/O device needed to be assigned (since it is decoded to
	;device 1).
	;-------------------------------------------------------------

		call	See_If_Bus_0		;aligning BUS 0 ?
		jne	Continue_Align_Req	;no, skip
		cmp	bx, TotalIOReq		;aligning I/O ?
		jne	Continue_Align_Req	;no, skip
		cmp	eax, 4000h		;total I/O = 4000h ?
		jne	Continue_Align_Req	;no, skip
		add	eax, 2000h		;set total I/O = 6000h
						; to prevent AGP I/O range
						; as B000-BFFF or A000-AFFF
	    Continue_Align_Req:
endif	;AGP_SLOTID
;R31 - ends
		mov	ds:[si+bx], eax	;put aligned request back into buffer

	End_Align_Req:

	;-------------------------------------------------------
	;Create Virtual Base Request for the primary bus to treat
	;the whole bridge resource as just a base request
	;-------------------------------------------------------

		or	si, si				;in bus 0 ?
		jz	No_Virtual_Base			;yes, skip virtual requst !

	;-------------------------------------------------------
	;if total P2P request is none, we post a request of
	;value=00000001h to the request buffer. Our resource
	;assign procedure will write 0FFF00000h to the resource
	;register of the PPB which means DISABLED
	;-------------------------------------------------------
		or	eax, eax
		jnz	@F
		mov	al, 1
	@@:
	;-------------------------------------------------------

 		mov	dh, ds:[si].P2PB_BusNo		;DH=bus loc of PPB
 		mov	ch, ds:[si].P2PB_DevFucNo	;CH=Dev&func loc of PPB
;R34 - starts
		mov	cl, cs:[di].VirtReqReg		;CL=which reg to be set
		mov	dl, cs:[di].VirtReqType		;DL=what kind of request
		or	dh, dh				;PPB at bus 0 ?
		jnz	@F				;no !
		mov	dl, cs:[di].VirtReqType1	;another kind of request
	@@:
;R34 - ends
;R34		mov	cl, cs:[di+14]			;CL=which reg to be set
;R34		mov	dl, cs:[di+15]			;DL=what kind of request
;R34		or	dh, dh				;PPB at bus 0 ?
;R34		jnz	@F				;no !
;R34		mov	dl, cs:[di+16]			;another kind of request
;R34	@@:
 		call	Append_Base_Request		;put this request into
							;buffer
	No_Virtual_Base:

		popa

		add	di, P2P_Request_Tbl_Data_Len
		cmp	di, offset P2P_Request_Tbl_End	;R34A
		jne	Next_P2P_Request		;R34A
;R34A		loop	Next_P2P_Request

		popad
		pop	ds
		ret

Include_Subordinate_Reqests	Endp

;R34 - starts
P2P_REQ_LIMIT	STRUC
		TotalReqLoc	dw	?
		MinP2PReq	dd	?
		MaxP2PReq	dd	?
		P2PReqMask	dd	?
		P2pReqAdd	dd	?
		P2pReqShift	db	?
		VirtReqReg	db	?
		VirtReqType	db	?
		VirtReqType1	db	?
P2P_REQ_LIMIT	ENDS
P2P_Request_Tbl_Data_Len	EQU	(SIZE P2P_REQ_LIMIT)

P2P_Request_Tbl	Label	Near

     P2P_REQ_LIMIT <TotalMemReq, 000100000h, 080000000h, 0FFF00000h, 0, 1,\
		    20h, VIRTUAL_HMEM_BASE, VIRTUAL_HMEM_BASE>

     P2P_REQ_LIMIT <TotalPfMemReq, 000100000h, 080000000h, 0FFF00000h, 0, 1,\
		    24h, VIRTUAL_PFMEM_BASE, VIRTUAL_BUS0_PFMEM_BASE>

     P2P_REQ_LIMIT <TotalIOReq, 000001000h, 00000D000h, 00000D000h, 1000h, 0,\
		    1Ch, VIRTUAL_IO_BASE, VIRTUAL_IO_BASE>

P2P_Request_Tbl_End	Label	Near	;R34A

;R34A No_Of_P2P_Request	EQU	($ - (offset P2P_Request_Tbl)) / P2P_Request_Tbl_Data_Len
;R34 - ends

;R34 P2P_Request_Tbl	Label	Near
;R34
;R34 		dw	TotalMemReq
;R34 		dd	000100000h
;R34 		dd	080000000h
;R34 		dd	0FFF00000h
;R34 		db	20h
;R34 		db	VIRTUAL_HMEM_BASE
;R34 		db	VIRTUAL_HMEM_BASE
;R34
;R34 P2P_Request_Tbl_Data_Len	EQU	($ - (offset P2P_Request_Tbl))
;R34
;R34 		dw	TotalPfMemReq
;R34 		dd	000100000h
;R34 		dd	080000000h
;R34 		dd	0FFF00000h
;R34 		db	24h
;R34 		db	VIRTUAL_PFMEM_BASE
;R34 		db	VIRTUAL_BUS0_PFMEM_BASE
;R34
;R34 		dw	TotalIOReq
;R34 		dd	000001000h
;R34 		dd	000008000h
;R34 		dd	00000F000h
;R34 		db	1Ch
;R34 		db	VIRTUAL_IO_BASE
;R34 		db	VIRTUAL_IO_BASE
;R34
;R34 No_Of_P2P_Request	EQU	($ - (offset P2P_Request_Tbl)) / P2P_Request_Tbl_Data_Len

;[]=====================================================================[]
;[]=====================================================================[]
Determine_Device_Resource	Proc	Near

		push	ds
		pushad

		push	SEG TEMP_PCI_REQ_BUF
		pop	ds

		mov	byte ptr CURRENT_BUS_NO[bp], 0

	Assign_Next_Bus_Resources:

		push	ds
		push	SEG PCI_REQ_BUF
		pop	ds
		call	Clear_PCI_Req_Buffer
		pop	ds

		mov	word ptr IO_BUF_PTR[bp], offset IO_BUF
		mov	word ptr HMEM_BUF_PTR[bp], offset HMEM_BUF
		mov	word ptr LMEM_BUF_PTR[bp], offset LMEM_BUF
		mov	word ptr PREFET_MEM_BUF_PTR[bp], offset PREFET_MEM_BUF

		mov	si, offset TEMP_BASE_REQ_BUF

	Fetch_Stored_Req:

		mov	ah, ds:[si].Bus_Num
		cmp	ah, -1
		je	End_Fetch_Req
		cmp	ah, CURRENT_BUS_NO[bp]
		jne	No_Fetch

		mov	dh, ds:[si].Bus_Num
		mov	dl, ds:[si].MemIo_Info
		mov	cx, ds:[si].Cfg_Loc
		mov	eax, ds:[si].MemIO_Req

		mov	di, offset Store_IO_Base_Request
		test	dl, 01h
		jnz	_Put

		mov	di, offset Store_LMEM_Base_Request
		test	dl, 02h
		jnz	_Put

		mov	di, offset Store_PfMEM_Base_Request
		test	dl, 08h
		jnz	_Put

		mov	di, offset Store_MEM_Base_Request
	_Put:
		call	di

	No_Fetch:

		add	si, SIZE MEMIO_BUF
		jmp	Fetch_Stored_Req

	End_Fetch_Req:

		call	Prepare_PCI_Bus_Info

		push	ds
		push	SEG PCI_REQ_BUF
		pop	ds

		cmp	byte ptr NEED_ASSIGN_LMEM_FLAG[bp], 0AAh
		jne	@F
 		call	Assign_Mem_Below_1M
		jmp	End_Assign_One_Bus
	@@:
		call	Assign_Mem_Above_1M
		call	Assign_Prefectchable_Memory
 		call	Assign_IO_Space

	End_Assign_One_Bus:

		pop	ds

		cmp	byte ptr NEED_ASSIGN_LMEM_FLAG[bp], 0AAh
		je	@F
		POST_FUNC_CALL Get_Next_Bus
		jbe	Assign_Next_Bus_Resources
	@@:

		popad
		pop	ds
		ret

Determine_Device_Resource	Endp

;[]=====================================================================[]
;Input	:	AL & CURRENT_BUS_NO[bp] - Bus location of P2P Bridge
;		CX 			- DEV & FUNC no. of P2P Bridge
;		TOTAL_BUS_NO[bp]	- The Bus no. should this P2P
;					  expand to
;[]=====================================================================[]
Record_P2P_Info	Proc	Near

		push	ds
		pushad

		push	SEG TEMP_PCI_REQ_BUF
		pop	ds

	;Attach a subordinate bus for it's mother bus

		call	Get_Bus_Info_Offset
		add	si, Sub_Buses

		push	cx
		mov	cx, MAX_SUB_BUS
	@@:
		cmp	byte ptr ds:[si], 0
		je	@F
		inc	si
		loop	@B
	@@:
		pop	cx
		mov	al, TOTAL_BUS_NO[bp]
		mov	byte ptr ds:[si], al

	;Record the Bus, Device & Function number of this P2P bridge

		call	Get_Bus_Info_Offset
		mov	al, CURRENT_SLOT[bp]
		mov	ds:[si].Host_Slot, al
		mov	al, CURRENT_BUS_NO[bp]
		mov	ds:[si].P2PB_BusNo, al
		mov	ds:[si].P2PB_DevFucNo, ch

		popad
		pop	ds
		ret

Record_P2P_Info	Endp

;R71 - start
;-------------------------------------------------
;Input:
;	CURRENT_VENDOR_ID[bp]
;	CURRENT_DEVICE_ID[bp]
;Output:
;	CF: True PCI IDE Card
;	NC: Not True PCI IDE Card
;-------------------------------------------------
SearchTruePCIIde:
		pushad
		mov	si, offset TruePCIIdeTbl
	NextTruePciIde:
		mov	eax,cs:[si]

		cmp	dword ptr CURRENT_DEVICE_ID[bp],eax
		je	short @F
		add	si,4
		cmp	byte ptr cs:[si],0ffh
		jne	short NextTruePciIde
		clc
		popad
		ret

	@@:
		stc
		popad
		ret
;-------------------------------------------------
;		(VENDOR_ID shl 16) + DEVICE_ID
;-------------------------------------------------
TruePCIIdeTbl:
		dd	(1095h shl 16) + 0646h	;CMD CSA-646U
		db	0ffh
;R71 - end

;----------------------------------------------------------------
;Special for PCI IDE devices:
;
;  if device <> PCI/IDE
;     continue assign IO/MEM for this device
;  else
;     1. Promise PCI/IDE: Disable PCI ROM
;     2. VIA PCI/IDE    : continue assign IO/MEM for this device
;
;Input	:	AX = Class Code
;		CURRENT_VENDOR_ID[bp]
;		CURRENT_DEVICE_ID[bp]
;----------------------------------------------------------------
Skip_IDE_Base_Request	Proc	Near

		push	ax
		cmp	ax, CLASS_IDE		;its a PCI IDE?
		jne	Not_IDE_Base		;no !

;R71 - start
		call 	SearchTruePCIIde
		jc	short Not_IDE_Base
;R71 - end

	;enable I/O for PCI/IDE

		mov	cl, 04h			;Command Register
		mov	al, 07h
		call	X_Set_CfgSpace_Byte

	;assign I/O 03001H for master IDE at space 20H, so far BIOS
	;always set fixed I/O address

		call	X_Get_CfgSpace_Byte
		test	al, 04H			;master IDE ?
		jz	Not_Master_Ide

		mov	cl, 20H
		mov	eax, 0F001H
		call	X_Set_CfgSpace_DWord

	Not_Master_Ide:

		mov	ax, CURRENT_VENDOR_ID[bp]
		cmp	ax, 105Ah		;Promise PCI/IDE need to
		jne	@F			;disable PCI ROM before
		call	X_Disable_PCI_ROM
	@@:
		cmp	ax, 1106H		;VIA PCI/IDE ?
		je	Not_IDE_Base		;don't skip for VIA IDE
		pop	ax
		stc				;STC = do not assign anything
		ret				;      for IDE!

	Not_IDE_Base:

		pop	ax
		clc
		ret

Skip_IDE_Base_Request	Endp

;[]----------------------------------------------------------------------[]
;Input	:	CX - device, function no.
;		CL - base reg no.
;Ouput	:	CF - No request
;		NC - request value in EAX
;		     request type in DL : 0/4 --> Memory Space 32bit/64bit
;					  1 -->	I/O Space
;					  2 --> Memory below 1M
;					  8 --> Prefetch Memory Space
;
;		e.g. EAX = 00010000h, DL = 00h
;				------------>>>> 64K Memory Space
;		     EAX = 00000400h, DL = 01h
;		     		------------>>>> 1K I/O Space
;
;[]----------------------------------------------------------------------[]
Analyse_Base_Request	Proc	Near

	;write 0FFFFFFFFh into request register
	;   IO/MEM request will be reflected in the same register

		mov	eax, -1
		call	X_Set_CfgSpace_DWord
		call	X_Get_CfgSpace_Dword
;R104 ifndef	WHITNEY_SPECIAL				;R79
;R104 		push	eax
;R104 		xor	eax, eax
;R104 		call	X_Set_CfgSpace_DWord
;R104 		pop	eax
;R104 endif;	WHITNEY_SPECIAL				;R79
;R105 - start
ifdef	Special_Bas_Addr_Section_For_PCIBus		
		push	eax			     
		xor	eax, eax		     
		call	X_Set_CfgSpace_DWord	     
		pop	eax			     
endif;	Special_Bas_Addr_Section_For_PCIBus					
;R105 - end
		cmp	cl, 30h	       	;option ROM checking
		jne	Skip_Checking_ROM

;R45 - start
	;The old i960RP always report "0" in bit0 of register 30H that
	;cause BIOS missing ROM assign for the device(SCSI) using this
	;CPU as I/O processor.
		cmp	eax, -1		;no ROM needed ?
		je	No_Base

		and	eax, 0FFFFFF00H	;invalid ROM requirement
		jz	No_Base

		or	al, 01H		;force ROM needed
;R45 - end

		test	al, 01h	       	;option ROM needed ?
		jz	No_Base		;no

		test	eax, 0FFF00000h	;only support high address decoding
		jz	No_Base

		call	Check_Invalid_Base
		jc	No_Base

		and	eax, 0FF000000h	;assign high address for option ROM

	Skip_Checking_ROM:

	;save IO/MEM info in DL

		mov	dl, al

		call	See_If_Bus_0
		je	Scaning_Bus0

		and	dl, 0Fh
		cmp	dl, 08h
		je	Prefetchable_Mem_Req

	Scaning_Bus0:

		and	dl, 07h
		test	dl, 01H			;Need I/O ?
		jnz	Io_Yes

	;----------------------------------------------------
	;	DL > 4 or DL = 3 are invalid requests !!!
	;----------------------------------------------------

		cmp	dl, 04h			;unreasonable value?
		ja	No_Base			;yes, error!
	Io_Yes:
		cmp	dl, 03h			;unreasonable value?
		je	No_Base			;yes, error!

	Prefetchable_Mem_Req:

	;check if unreasonable request
	;if request unreasonable --> skip it

		mov	esi, 0FFFFFFF0H		;MEM req: bit 0123 read only
		mov	edi, 0FFFFF000h		;MEM req: min = 4K bytes

		test	dl, 01h			;I/O request?
		jz	@F			;no

;R06		mov	esi, 0FFFFFFFCh
;R06		mov	edi, 0FFFFFF00h
;R06		call	See_If_Bus_0
;R06		je	@F			;yes
		mov	si, 0FFFCh		;I/O : bit 01 read only	;R06
		mov	di, 0FC00h
	@@:

		call	Patch_PCI_Base_Request

		test	eax, esi		;unreasonable value?
		jz	No_Base			;yes, error!

	;if request size <= our minimun --> set to minimun

		and	eax, edi

	;if it is a Low Memory request, set A20 to A31 to be high

		cmp	dl, 02h
		jne	@F
		or	eax, 0FFF00000h
	@@:

	;if it is a I/O request, set high word to be FFFFh

		test	dl, 01h
		jz	@F
;R32		and	dl, 03h
		and	dl, 01h				;R32
		or	eax, 0FFFF0000h
	@@:
		call	Check_Invalid_Base
		jc	No_Base			; CF:not a valid request

		not	eax
		inc	eax

		clc
		ret

	No_Base:

		stc
		ret

Analyse_Base_Request	Endp

;======================================================================
;======================================================================
Patch_PCI_Base_Request	Proc	Near

	;set requesting memory space to 8Mb instead of 4Mb for Matrox
	;due to hardware decoding with 8Mb

		test	dl, 01h					;I/O request?
		jnz	Not_Patch_Matrox

		cmp	word ptr CURRENT_VENDOR_ID[bp], 102Bh	;Matrox?
		jne	Not_Patch_Matrox			;no
		test	eax, 000FFF000h
		jz	Not_Patch_Matrox
		mov	edi, 0FF000000h

	Not_Patch_Matrox:

	;set requesting memory space to 64Mb instead of 32Mb for S3/968
	;due to hardware decoding with 64Mb

		test	dl, 01h					;I/O request?
		jnz	Not_S3Vga968

		cmp	dword ptr CURRENT_DEVICE_ID[bp], 53338880H;S3/868 chip ?;R15
		je	short NotFullyDecodeMemSpace				;R15

		cmp	dword ptr CURRENT_DEVICE_ID[bp], 533388F0H	;S3 968 chip ?
		jne	Not_S3Vga968

	NotFullyDecodeMemSpace:							;R15

		test	eax, 003FFF000H				;request 32M?
		jz	Not_S3Vga968
		mov	edi, 0FC000000h				;set 64Mb

	Not_S3Vga968:

		ret

Patch_PCI_Base_Request	endp

;======================================================================
;======================================================================
Check_Invalid_Base	Proc	Near

		push	ebx
		push	edx

		call	Get_First_Zero		;EBX=1st "0" loc. from left
		jc	Invalid_Base		;CF=All ONEs
		call	Get_First_Non_Zero	;EDX=1st "1" loc. from left
		jc	Invalid_Base		;CF=All ZEROs
		cmp	ebx, edx
		ja	Invalid_Base

	Valid_Base:

		clc
		jmp	Check_Invalid_Base_End

	Invalid_Base:

		stc

	Check_Invalid_Base_End:

		pop	edx
		pop	ebx
		ret

Check_Invalid_Base	Endp

;======================================================================
;======================================================================
Get_First_Zero	Proc	Near
		mov	ebx, 80000000h
	@@:
		test	eax, ebx
		jz	@F
		shr	ebx, 1
		jnz	@B
		stc
		ret
	@@:
		clc
		ret
Get_First_Zero	Endp

;======================================================================
;======================================================================
Get_First_Non_Zero	Proc	Near
		mov	edx, 80000000h
	@@:
		test	eax, edx
		jnz	@F
		shr	edx, 1
		jnz	@B
		stc
		ret
	@@:
		clc
		ret
Get_First_Non_Zero	Endp

;-------------------------------------------------------------
;Input	:	DS : PCI_REQ_BUF
;		CH : device number in upper 5 bits
;		CL : function number in lower 3 bits
;-------------------------------------------------------------
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Kill_This_CfgSpace	Proc	Near

;---------------------
;1. destroy cfg space
;---------------------

		push	cx

	;---------- disable MEM, I/O & Master -------------

		mov	cl, 04h			;PCI command register
		xor	ax, ax
		call	X_Set_CfgSpace_Word

	;----------- kill register 10h to 24h -------------

		mov	cl, 10h
	@@:
		xor	eax, eax
		call	X_Set_CfgSpace_DWord
		add	cl, 4
		cmp	cl, 24h
		jbe	@B

	;-------------- kill ROM decoding -----------------

		call	X_Disable_PCI_ROM

		pop	cx

;----------------------------------------------------------
;2. set all request of this cfgspace(CX) in buffer to -1
;----------------------------------------------------------

		push	si

		mov	si, (offset TEMP_PCI_REQ_BUF)\
			    - SIZE_MEMIO_BUF

;-------------------

	Keep_Killing:

		add	si, SIZE_MEMIO_BUF		;point to next request
		or	[si].MemIO_Req, 0		;all req in this buf done?
		jz	_Killed				;yes, exit this buffer

		cmp	byte ptr [si+Cfg_Loc+1], ch	;is this req to be killed?
		jne	Keep_Killing			;no, skip it

		mov	al, CURRENT_BUS_NO[bp]
		cmp	byte ptr [si].Bus_Num, al	;is this req to be killed?
		jne	Keep_Killing			;no, skip it

		mov	[si].MemIO_Req, -1		;mark request killed
		jmp	Keep_Killing			;continue to next request

	_Killed:

;-------------------

		pop	si
		ret

Kill_This_CfgSpace	Endp

;[]================================================================[]
;[]================================================================[]
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Assign_Prefectchable_Memory	Proc	Near

		push	ds

		mov	si, offset PREFET_MEM_BUF
		call	Sort_PCI_Request

		mov	edi, AVAILABLE_PREFET_START[bp]
		call	Assign_From_Buff

		pop	ds

		ret

Assign_Prefectchable_Memory	Endp

;[]================================================================[]
;[]================================================================[]
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Assign_Mem_Above_1M	Proc	Near

		push	ds

		mov	si, offset HMEM_BUF		;sort all requests
		call	Sort_PCI_Request 		; in decreasing order

		mov	si, offset HMEM_BUF		;SI --> request buffer
		mov	edi, AVAILABLE_MEM_START[bp]	;EDI = Mem addr. start
		call	Assign_From_Buff      		;assign memory
							;  according to buffer
		pop	ds
		ret

Assign_Mem_Above_1M	Endp

;-------------------------------------------------------------
;-------------------------------------------------------------
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Assign_IO_Space	Proc	Near

		push	ds
		mov	si, offset IO_BUF		;SI --> request buffer
		call	Sort_PCI_Request  	 	;sort in decreasing order

		mov	edi, AVAILABLE_IO_START[bp]	;EDI = I/O addr. start

		call	Assign_From_Buff   		;assign IO according
							;     to buffer
		pop	ds
		ret

Assign_IO_Space	Endp

;-------------------------------------------------------------
;-------------------------------------------------------------
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Assign_Mem_Below_1M	Proc	Near

		push	ds

		mov	si, offset LMEM_BUF	;SI --> request buffer
		call 	Sort_PCI_Request  	;sort in decreasing order

		call 	Assign_From_Buff

		call	X_Invalidate_Shadow_Seg	;invalidate whole shadow seg
						;i.e. shadow unit = 16K(32K)
						;     ==> invalidate whole
						;	  16k(32k) even if it
						;	  is not totally used!
		pop	ds
		ret

Assign_Mem_Below_1M	Endp

;-------------------------------------------------------------
;Input	:	DS  = PCI_REQ_BUF
;		SI  = buffer location in PCI_REQ_BUF
;		EDI = available address location
;-------------------------------------------------------------
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Assign_From_Buff	Proc	Near
Assign_Continue:
		mov	cx, [si].Cfg_Loc		;dev & func no.
;R57A - start
ifndef	NO_EARLY_MASTER_ENABLE				;R57B
	;Enable bus master bit while assigning resource to fix USB controller
	;not functioning during POST
		push	cx
		mov	cl, 04H
		call	X_Get_CfgSpace_Byte		;read from cfg space
		test	al, 04H				;bus master enabled ?
		jnz	short BMEnabled
		or	al, 04H				;enable bus master
		call	X_Set_CfgSpace_Byte		;write into cfg space
BMEnabled:
		pop	cx
endif;	NO_EARLY_MASTER_ENABLE				;R57B
;R57A - end

		mov	eax, [si].MemIO_Req		;value to be assigned
		mov	bl, [si].MemIo_Info		;mem/io info

		or	eax, eax			;end of buffer?
		jz	End_Assign_From_Buf		;yes, exit!

		cmp	eax, -1				;Cfg been killed?
		je	Assign_Next_Req			;yes, skip this one!

;-------- if [si].MemIo_Info = 2,  assign memory below 1M -----------------

		cmp	bl, 02h				;request mem < 1M?
		jne	Assign_HMem_IO			;no, go try I/O or Mem > 1M

		push	cx				;save dev, func no
		shr	eax, 12				;mem. in terms of 4K
		mov	cl, al				;param in CL
		mov	byte ptr LMEM_FOR_ROM_FLG[bp], 0;indicate get LMEM for memory usage
		POST_FUNC_CALL EGet_Available_LMEM 	;request low mem
		pop	cx				;restore dev, func no
		jc	@F				;CF -> mem not available

		mov	eax, AVAIL_LMEM_ADDR[bp]	;EAX = addr.
		call	X_Set_CfgSpace_DWord		;write into cfg space
		jmp	Assign_Next_Req			;assign next request
	@@:
		call	Kill_This_CfgSpace		;kill this cfg Space!
		jmp	Assign_Next_Req			;assign next request

;------------------ assign memory above 1M, I/O request -----------------
Assign_HMem_IO:

	;-------------------------------------------------------
	;a request of value=00000001h means the total P2P request
	;is none, we clear AL so that it won't affect the next
	;available resource
	;-------------------------------------------------------

		cmp	eax, 1
		jne	@F
		xor	al, al
	@@:

		xchg	eax, edi			;eax to be written

		call	Assign_Resource_For_P2P
		jc	Assign_Next_Req

		test	bl, 01h				;IO request?
		jz	_789				;no
		and	eax, 0FFFFh			;fix to 16 bits	for IO
		or	al, 01h				;set bit0=1 for I/O
	_789:

		call	X_Set_CfgSpace_DWord		;write into cfg space

;R94 ;R79 - starts
;R94 ifdef	WHITNEY_SPECIAL					
;R94 		pushad
;R94 		cmp	byte ptr current_bus_no[bp], 0
;R94 		jne	_IOU
;R94 		cmp	ch, ONBOARD_PCI_VGA
;R94 		jne	_IOU
;R94 		cmp	cl, 14h
;R94 		jne	_IOU
;R94 		mov	cl, 04h
;R94 		mov	al, 03h
;R94 		call	X_Set_CfgSpace_Byte		;write into cfg space
;R94 	_IOU:
;R94 		popad
;R94 endif;	WHITNEY_SPECIAL					
;R94 ;R79 - ends

		and	al, not 01h			;restore bit0=0
		add	edi, eax			;add to available space

		cmp	bl, 04h				;mem. 64-bit address?
		jne	Assign_Next_Req			;no!
		add	cl, 04h				;set upper 32bit
		xor	eax, eax			;    address to 0
		call	X_Set_CfgSpace_DWord

	Assign_Next_Req:

		add	si, SIZE_MEMIO_BUF
		jmp	Assign_Continue

	End_Assign_From_Buf:

		ret

Assign_From_Buff	Endp

;======================================================================
;Input	:	BL = what kind of request
;			VIRTUAL_HMEM_BASE
;			VIRTUAL_PFMEM_BASE
;			VIRTUAL_BUS0_PFMEM_BASE
;			VIRTUAL_IO_BASE
;		EAX = Available resource
;		EDI = Amount of resource needed
;		CH & CL = resource register to be set
;
;Output	:	CF - It is a P2P resource & assignment is done
;		NC - not a P2P resource
;======================================================================
Assign_Resource_For_P2P	Proc	Near

		push	ds
		push	si

		mov	si, Bus_Mem_Start
		cmp	bl, VIRTUAL_HMEM_BASE
		je	Assigning_P2P

		mov	si, Bus_PfMem_Start
		cmp	bl, VIRTUAL_BUS0_PFMEM_BASE
		je	Assigning_P2P
		cmp	bl, VIRTUAL_PFMEM_BASE
		je	Assigning_P2P

		mov	si, Bus_IO_Start
		cmp	bl, VIRTUAL_IO_BASE
		clc
		jne	Not_Assigning_P2P

	Assigning_P2P:

	;------------------------------

		pusha

		mov	bx, si

		push	eax
		mov	cl, 19h
		call	X_Get_CfgSpace_Byte
		call	Get_Bus_Info_Offset
		pop	eax

		push	SEG TEMP_PCI_REQ_BUF
		pop	ds
		mov	ds:[si+bx], eax

		popa

	;------------------------------

		cmp	bl, 0A1h
		je	Assigning_P2P_IO

	Assigning_P2P_Mem:

		or	edi, edi			;P2P request = 0
		jnz	@F				;no !
		mov	eax, 0000FFFFh			;disable the resource
		call	X_Set_CfgSpace_DWord		;write into cfg space
		jmp	Finish_Assign_Resource_For_P2P
	@@:
		ror	eax, 16
		call	X_Set_CfgSpace_Word		;write into cfg space
		ror	eax, 16
		inc	cl
		inc	cl
		add	edi, eax			;add to available space
		mov	eax, edi
		dec	eax
		ror	eax, 16
		call	X_Set_CfgSpace_Word		;write into cfg space

		jmp	Finish_Assign_Resource_For_P2P

	Assigning_P2P_IO:
;R101 - starts
		or	edi, edi			;P2P request = 0
		jnz	@F				;no !
		mov	ax, 000FFh			;disable the resource
		call	X_Set_CfgSpace_Word		;write into cfg space
		jmp	End_Assign_P2P_IO
	@@:
;R101 - ends
		ror	ax, 8
		call	X_Set_CfgSpace_Byte		;write into cfg space
		inc	cl
		rol	ax, 8
		add	di, ax				;add to available space
		mov	ax, di
		dec	ax
		ror	ax, 8
		call	X_Set_CfgSpace_Byte		;write into cfg space

	End_Assign_P2P_IO:				;R101

;R77		mov	bl, 02h			;Cache Line size = 2
		mov	bl, 08h			;Cache Line size = 8  ;R77
		call	Prg_Device_Latency

	;-----------------------------------------------
	;enable SERR#
	;-----------------------------------------------

		mov	cl, 3eH
		call	X_Get_CfgSpace_Byte
		and	al, 00100000b
;R28		or	al, 00000111b			;ISA enable
		or	al, 00000110b			;ISA enable	;R28
		call	X_Set_CfgSpace_Byte

	;-----------------------------------------------
	;-----------------------------------------------

	ifdef	CHIPSET_PATCH_AHA3940
	;This register should set to 1 ( Why ? )
		mov	cl, 40H
		mov	al, 3		;disable POST write
		call	X_Set_CfgSpace_Byte
		mov	cl, 44H
		mov	ax, 1111H
		call	X_Set_CfgSpace_Word
	endif;	CHIPSET_PATCH_AHA3940

	;-----------------------------------------------
	;enable I/O , memory & master
	;-----------------------------------------------

		mov	cl, 04H
		mov	ax, 0107H
		call	X_Set_CfgSpace_Word

;R65A ;R65 - start
;R65A ifdef	SHARE_SIS6306
;R65A
;R65A 		pushad
;R65A 		;-------- enabled p2p vga
;R65A
;R65A 		mov	ch, AGP_SLOTID
;R65A 		mov	cl, 3Eh
;R65A  		call	X_Get_CfgSpace_Byte
;R65A 		or	al, 08h				;P2P VGA enabled
;R65A  		call	X_Set_CfgSpace_Byte
;R65A
;R65A 		;-------- enabled VGA password
;R65A
;R65A 		mov	dx,03c4h
;R65A 		mov	ax,8605h
;R65A 		call	set_vga_reg
;R65A
;R65A 		;-------- read register 0dh bit.0
;R65A
;R65A 		mov	al,0dh
;R65A 		call	get_vga_reg
;R65A 		xor	bx, bx
;R65A 		test	al,01h				;shared memory or not ?
;R65A 		jz	short Share_6306_Absence	;yes !
;R65A 		mov	bl, 40h
;R65A
;R65A Share_6306_Absence:
;R65A 		mov	cx,(SIS530_ID)+63h
;R65A 		F000_Call Aget_CfgSpace_Byte
;R65A 		and	al, NOT 40h
;R65A 		or	al, bl
;R65A 		F000_Call Aset_CfgSpace_Byte
;R65A 		;------- disabled VGA password
;R65A
;R65A 		mov	dx,03c4h
;R65A 		mov	ax,0005h
;R65A 		call	set_vga_reg
;R65A
;R65A 		;------- disabled p2p vga
;R65A
;R65A 		mov	ch, AGP_SLOTID
;R65A 		mov	cl, 3Eh
;R65A  		call	X_Get_CfgSpace_Byte
;R65A 		and	al, NOT 08h			;P2P VGA enabled
;R65A  		call	X_Set_CfgSpace_Byte
;R65A 		popad
;R65A endif	;SHARE_SIS6306
;R65A ;R65 - end

	Finish_Assign_Resource_For_P2P:

		stc

	Not_Assigning_P2P:

		pop	si
		pop	ds
		ret

Assign_Resource_For_P2P	Endp

;R65A ;R65 - start
;R65A ;
;R65A ; Subroutine for read VGA register
;R65A ;
;R65A get_vga_reg	proc	near
;R65A 		out	dx,al
;R65A 		inc	dl
;R65A 		in	al,dx
;R65A 		dec	dl
;R65A 		ret
;R65A get_vga_reg	endp
;R65A
;R65A ;
;R65A ; Subroutine for write VGA register
;R65A ;
;R65A set_vga_reg	proc	near
;R65A 		out	dx,al
;R65A 		inc	dl
;R65A 		xchg	ah,al
;R65A 		out	dx,al
;R65A 		dec	dl
;R65A 		xchg	ah,al
;R65A 		ret
;R65A set_vga_reg	endp
;R65A ;R65 - end

;-------------------------------------------------------------
;Input	:	ds : PCI_REQ_BUF
;		si : point to offset of buffer to be sorted
;Output	:	None
;-------------------------------------------------------------
		ALIGN	4
		ASSUME	DS:PCI_REQ_BUF
Sort_PCI_Request	Proc	Near

		push	si
		push	di
Next_Bubble:
		cmp	dword ptr [si], 0
		je	End_Sort_PCI_Request

		mov	di, si
		add	di, 8
	@@:
		mov	eax, [si]
		mov	ebx, [si+4]
		mov	ecx, [di]
		mov	edx, [di+4]

		or	ecx, ecx
		je	End_This_Bubble

		cmp	eax, ecx
		jae	Greater_Or_Equal

		xchg	ecx, eax
		xchg	ebx, edx

		mov	[si], eax
		mov	[si+4], ebx
		mov	[di], ecx
		mov	[di+4], edx

	Greater_Or_Equal:

		add	di, SIZE_MEMIO_BUF
		jmp	@B

	End_This_Bubble:

		add	si, SIZE_MEMIO_BUF
		jmp	Next_Bubble

End_Sort_PCI_Request:

		pop	di
		pop	si

		ret

Sort_PCI_Request	Endp

;-----------------------------------
;Input	:	DS = PCI_REQ_BUF
;-----------------------------------
		ALIGN	4
Clear_PCI_Req_Buffer	Proc	Near

		push	ds
		pop	es
		xor	di, di
		cld
		xor	ax, ax
		mov	cx, 8000h
		rep	stosw

		ret

Clear_PCI_Req_Buffer	Endp

;[]==============================================================[]
;PciRom_Before_Init:
;	special treatment before option initialization
;Saves: all
;Input : none
;Output: None
;[]==============================================================[]
		Public	fProc_PciRom_Before_Init
fProc_PciRom_Before_Init	Proc	Far

		mov	byte ptr PCI_CBROM_TEMP[bp], -1		;set pci flag for pci_cbrom_decompress subroutine
		mov	word ptr CBROM_BP_START[bp], (86h+1)*4	;option ROM start index of PCI device (from 86h)
		mov	word ptr CBROM_BP_END[bp], (0A0h+1)*4	;option ROM end index of PCI device (to 0A0h)
		mov	dword ptr CBROM_BUF_START[bp], 200030h	;PCI device and vender ID start address for decompress use
		call	fProc_Pci_CbRom_decompress

	ifdef	PNP_BIOS
		call	ESCD_IRQ_Resource
	endif	;PNP_BIOS

		call	Assign_IRQ_For_All_PCI

	 ifdef	ACPI_SUPPORT			;R64
	   IFDEF	VT586_ACPI		;R64
		ifndef	No_ACPI_IRQ_Auto_Assign	;R64A
		call	Assign_ACPIIrq		;R64
		endif;	No_ACPI_IRQ_Auto_Assign	;R64A
	   ENDIF;	VT586_ACPI		;R64
	 endif;	ACPI_SUPPORT			;R64

		call	Prg_Onboard_ScsiChip
;R91 - starts
	ifdef	PciLanROM_Control
		call	Prg_Onboard_PCI_Lan
	endif	;PciLanROM_Control
;R91 - ends
		retf

fProc_PciRom_Before_Init	Endp

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%%%%%%                                                          %%%%%%
;%%%%%%                VGA related routines                      %%%%%%
;%%%%%%                                                          %%%%%%
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;======================================================
;======================================================
Record_VGA_Devices	Proc	Near

		call	X_Chk_If_Class_VGA_1
		jne	No_Store_VGA

		mov	si, PCI_VGA_DEVICE_BUF_PTR[bp]
		add	word ptr PCI_VGA_DEVICE_BUF_PTR[bp], SIZE_VGA_INFO_STRUC

		mov	eax, CURRENT_DEVICE_ID[bp]
		mov	ds:[si].VGA_ID, eax

		mov	ds:[si].VGA_DevNum, ch

		mov	al, CURRENT_BUS_NO[bp]
		mov	ds:[si].VGA_BusNum, al

;R38		call	See_If_Bus_0
;R38		jne	@F
;R38		F000_CALL Ct_PCI_VGA_IDSEL		;CL=onboard PCI VGA
;R38		cmp	ch, cl
;R38		jne	@F
;R38		mov	byte ptr ds:[si].OnboardVGA, 0Fh
;R38	@@:
 		align	8				;R40
;R38 - starts
		mov	byte ptr ds:[si].OnboardVGA, 8	;8 = normal init
							;    priority
;--------------------------------------------------------------
;We add a new variable ONBOARD_VGA_P2P[bp] (defaults 0FFh)
;if the onboard VGA is on BUS 0, the Ct_PCI_VGA_IDSEL should
;leave ONBOARD_VGA_P2P[bp] as 0FFh which is initialized as
;0FFh in rotuine Init_Variables. Therefore we use 0FFh for
;comparing bus 0's onboard VGA.
;
;--------------------------------------------------------------

		F000_CALL Ct_PCI_VGA_IDSEL

		mov	bl, 10				;comparing sequence
		mov	bh, -1				;for checking bus 0
		call	See_If_Bus_0			;bus 0?
		je	@F				;yes !

		push	si
		call	Get_Bus_Info_Offset		;get p2p info in SI
		cmp	byte ptr ds:[si].P2PB_BusNo, 0	;level 2 Bus ?
		mov	bh, ds:[si].P2PB_DevFucNo	;BH for comparing level
							;  2 onboard VGA
		pop	si
;R39C		jne	End_Store_VGA			;not level 2 Bus !
;R39C							; i.e. it is neither
;R39C							;      bus 0 nor level
;R39C							;      2 bus.
		jne	short @f			;R39C

;R39 - starts
	ifdef	AGP_SLOTID
		cmp	bh, AGP_SLOTID
		jne	@F

		push	si
		mov	si, offset FirstInitAGP_Item
		call	X_GetItem_Value
;R39A		or	al, al
		cmp	al,2				;R39A
		pop	si
		jnz	@F
		mov	byte ptr ds:[si].OnboardVGA, 6	;6 = higher init
		jmp	End_Store_VGA			;    priority
	endif	;AGP_SLOTID
;R39 - ends

	@@:

;R49 - start
ifndef	AGP_NOT_USED					;R61
	ifdef	AGP_SLOTID
;R39C		cmp	bh, -1				;Is bus = 0 ?
;R39C		je	short Not_Bridge_Card		;Yes, skip !
;R39C - start
ifdef	ONBOARD_VGA_PRIORITY_SELECT
		cmp	ONBOARD_VGA_P2P[bp], bh
		jne	short @f
		cmp	ch, cl
		je	Not_Bridge_Card
	@@:
endif;	ONBOARD_VGA_PRIORITY_SELECT
;R39C - end
		cmp	bh, AGP_SLOTID			;Is AGP VGA ?
		je	short Not_Bridge_Card		;Yes, skip !
		push	si
		mov	si, offset FirstInitAGP_Item
		call	X_GetItem_Value
		or	al,al				;Is PCI first ?
		pop	si
		jnz	short Not_Bridge_Card
		mov	byte ptr ds:[si].OnboardVGA, 5	;5 = higher init
		jmp	End_Store_VGA			;    priority
	Not_Bridge_Card:
	endif	;AGP_SLOTID
endif;	AGP_NOT_USED					;R61
;R49 - end

		cmp	ONBOARD_VGA_P2P[bp], bh
		jne	End_Store_VGA
		cmp	ch, cl
		jne	End_Store_VGA
;R39A - starts
	ifdef	ONBOARD_VGA_PRIORITY_SELECT

		mov	bl,10				;R39C
;R39B		mov	bl,10
;R39B		mov	ah, ONBOARD_VGA_P2P[bp]
;R39B		mov	al, cl
;R39B		cmp	ax, -1				;Is onboard VGA
;R39B		je	@F				;no !

		push	si
		extrn	FirstInitAGP_Item:near
		mov	si, offset DGROUP:FirstInitAGP_Item
		call	X_GetItem_Value
		cmp	al,1
		pop	si
		jnz	@F
		mov	bl, 6
	@@:
	endif	;ONBOARD_VGA_PRIORITY_SELECT

		mov	byte ptr ds:[si].OnboardVGA, bl
;R39A - ends
;R39A		mov	byte ptr ds:[si].OnboardVGA, 10	;10 = lower init
							;     priority
	End_Store_VGA:

;R38 - ends

	No_Store_VGA:

		ret

Record_VGA_Devices	Endp

;======================================================================
;======================================================================
		ALIGN	4
Scan_PCI_VGA	Proc	Near

		push	ds
		pushad

		mov	byte ptr PCI_CBROM_TEMP[bp], 0		;set VGA flag for pci_cbrom_decompress subroutine
		mov	word ptr CBROM_BP_START[bp], (80h+1)*4	;option ROM start index of VGA device (from 86h)
		mov	word ptr CBROM_BP_END[bp], (86h+1)*4	;option ROM end index of VGA device (to 0A0h)
		mov	dword ptr CBROM_BUF_START[bp], 200000h	;VGA device and vender ID start address for decompress use
		call	fProc_Pci_CbRom_decompress

	;----------------------------------------------------------------
	; DS point to TEMP_PCI_REQ_BUF
	;----------------------------------------------------------------

		push	SEG TEMP_PCI_REQ_BUF
		pop	ds

	;----------------------------------------------------------------
	;PCI_VGA_DEVICE_BUF_PTR[bp] has a initial value of
	;'offset PCI_VGA_DEVICE_BUF', every PCI display device found will
	;cause this [bp] to increase a value of SIZE_VGA_INFO_STRUC
	;
	;  if [bp] value = initial value ===> no PCI VGA device exist
	;
	;  if VGA device found --> [bp] value <> initial value
	;			   [bp] value point to a empty entry
	;----------------------------------------------------------------

		mov	si, offset PCI_VGA_DEVICE_BUF	;SI -> top of buffer
		mov	di, PCI_VGA_DEVICE_BUF_PTR[bp]	;DI -> end of buffer
		cmp	di, si			;no VGA device found ?
		je	No_PCI_Display		;yes, skip it

	;----------------------------------------------------------------
	;We sort the PCI VGA buffer according to its bus num. & dev, func
	;no. in a decreasing order. Therefore the smallest(last) one
	;described in the buffer will be the one we should invoke.
	;----------------------------------------------------------------

		call	Sort_PCI_Request

	;----------------------------------------------------------------
	;1. We disable from the top of the buffer every VGA device until
	;   the one we should invoked.
	;
	;2. By subtracting the pointer DI by SIZE_VGA_INFO_STRUC, we
	;   disable VGA devices from SI to (DI-SIZE_VGA_INFO_STRUC).
	;
	;3. If C000 already had a valid ROM found, that means the ISA VGA is
	;   used instead. So step 2 should be skipped, i.e. we should disable
	;   all PCI VGAs found
	;----------------------------------------------------------------

		call	If_Any_VGA_BIOS_Exist	;ISA/VGA exist ?
		je	@F			;yes

		sub	di, SIZE_VGA_INFO_STRUC	;start from second VGA device
	@@:
		mov	al, ds:[si].VGA_BusNum	;get bus number
		mov	CURRENT_BUS_NO[bp], al
		mov	ch, ds:[si].VGA_DevNum	;get device & function number

		cmp	si, di			;last VGA device ?
		je	@F			;yes, it is finished

 		mov	cl, 04h			;disable I/O, MEM decode
		xor	ax, ax
 		call	X_Set_CfgSpace_Word

		add	si, SIZE_VGA_INFO_STRUC	;next VGA device
		jmp	@B
	@@:

	;----------------------------------------------------------------
	;Now, SI point to the VGA which should be invoked. If this value
	;is the same as the initial value of PCI_VGA_DEVICE_BUF_PTR[bp],
	;that means all PCI VGA are disabled
	;----------------------------------------------------------------

		cmp	si, PCI_VGA_DEVICE_BUF_PTR[bp]
		je	No_PCI_Display

	;----------------------------------------------------------------
	;Enable the path of the VGA device if it is decoded thru
	;P2P bridges
	;
	; i.e. we should enable bit3 of reg3Eh (VGA enable) of each P2P
	;      that the display device go thru
	;----------------------------------------------------------------

		push	word ptr CURRENT_BUS_NO[bp]
		push	cx
	@@:
		or	al, al				;AL = bus no
		je	@F
		call	Get_Bus_Info_Offset
		mov	al, ds:[si].P2PB_BusNo
		mov	CURRENT_BUS_NO[bp], al
  		mov	ch, ds:[si].P2PB_DevFucNo
		mov	cl, 3Eh
 		call	X_Get_CfgSpace_Byte
		or	al, 08h				;P2P VGA enabled
 		call	X_Set_CfgSpace_Byte
		mov	al, CURRENT_BUS_NO[bp]
		jmp	@B
	@@:
		pop	cx
		pop	word ptr CURRENT_BUS_NO[bp]

	;----------------------------------------------------------------
	;Set flag for PCI VGA being found:
	;
	;  1. byte ptr PCI_VGA_FOUND[bp] --> VGA_DEVICE_EXIST(=0AAh)
	;  2. word ptr PCI_VGA_INFO[bp]  --> High byte = bus no.
	;				     Low byte = dev & func no.
	;----------------------------------------------------------------

 		mov	byte ptr PCI_VGA_FOUND[bp]\
			, VGA_DEVICE_EXIST		;set VGA found flag!
 		mov	al, ch				;Low byte = dev & func no.
 		mov	ah, CURRENT_BUS_NO[bp]		;High byte = bus no.
 		mov	PCI_VGA_INFO[bp], ax

	;----------

		mov	eax, ds:[si].VGA_ID

		call	Record_Set_Mode3_VGA

 		call	Patch_S3_765			;patch for VGA

	ifdef 	ALIm152x_Special_Define
		call	Patch_ALIm152x_VGA
	endif	;ALIm152x_Special_Define

	ifndef	PCI_RESET_SUPPORT
		call	Patch_CT65548
 		jnc	No_Need_Video_Rom
	endif	;PCI_RESET_SUPPORT

		call	fProc_Find_VGA_ROM_Image
		jc	short No_Need_Video_ROM		;R17

		mov	si, 03000h
		call	Move_Video_Image_To_C000

	No_Need_Video_ROM:

;R17		call	X_Disable_PCI_ROM
		xor	eax, eax			;R17
		mov	cl, 30h				;R17
 		call	X_Set_CfgSpace_DWord		;R17

	No_PCI_Display:

		popad

;R07 		call	Process_Combined_VGA

		pop	ds

		ret

Scan_PCI_VGA	Endp

;======================================================
;======================================================
If_Any_VGA_BIOS_Exist	Proc	Near

		push	ds
		push	0C000h
		pop	ds
		cmp	word ptr ds:[0], 0AA55h		;ISA VGA exist?

		jne	@F

		push	si
		mov	si, 0C000h
		POST_FUNC_CALL Cksm_ROM
		pop	si
	@@:

		pop	ds
		ret

If_Any_VGA_BIOS_Exist	Endp

;[]============================================================[]
;Function : Patch for special PCI/VGA to avoid compatibility
;Input    : CH - device+function number
;	    EAX = device ID & vendor ID
;output   : none
;[]============================================================[]
Patch_S3_765	proc	near

		push	eax

;R81 - start
ifdef	Patch_MX_CPU_For_PCI_Peer_Con_USB
	;Disable Write gathering for M1/M2 CPU if both USB & PCI peer
	;concurrency are enabled simutaneously.
		extrn	Peer_Con_Item:near
		extrn	ONBD_USB_Item:near
		push	eax
		mov	si, offset DGROUP:Peer_Con_Item
		call	X_GetItem_Value
		or	al, al		;Peer Concurrency enabled ?
		pop	eax
		jz	short Dont_Disable_6x86_Write_Gathering

		push	eax
		mov	si, offset DGROUP:ONBD_USB_Item
		call	X_GetItem_Value
		or	al, al		;USB enabled ?
		pop	eax
;R81A		jnz	Disable_6x86_Write_Gathering
		jz	short Disable_6x86_Write_Gathering	;R81A
Dont_Disable_6x86_Write_Gathering:
endif;	Patch_MX_CPU_For_PCI_Peer_Con_USB
;R81 - end

;R10 - starts
	ifdef	PATCH_VERITE_V2200_FOR_MX_CPU
		cmp	eax, (1163h SHL 16)+2000h	;Rendition V2200 ?
		je	Disable_6x86_Write_Gathering
	endif;	PATCH_VERITE_V2200_FOR_MX_CPU
;R10 - ends

	;The S3/765 PCI/VGA don't support display buffer write gathering
	;function. So , force disabling this function if 6x86 CPU used.

		cmp	eax, (5333H SHL 16) + 8811H
		jne	Not_S3Vga

		mov	cl, 8			;revision number
		call	X_Get_CfgSpace_Byte
		cmp	al, 054H		;S3/765 ?
		jne	Not_S3Vga

	;Disable write gathering function for 6x86 CPU

	Disable_6x86_Write_Gathering:

IF	BIOS_SUPPORT_586				;R99
		POST_FUNC_CALL Check_M1_Cpu 	;check if 6x86 CPU
		jne	Not_S3Vga		;skip if not 6x86

		F000_CALL Unlock_Cyrix		;open cyrix register locked

		mov	cl, 0dch		;RCR0
		mov	al, 01H			;no write gathering
		F000_CALL Set_Cyrix

		F000_CALL lock_Cyrix		;lock cyrix CPU register access
ENDIF	;BIOS_SUPPORT_586				;R99

Not_S3Vga:
		pop	eax
		ret

Patch_S3_765	Endp

ifndef	PCI_RESET_SUPPORT
;======================================================
;Input : eax - device ID & vendor ID
;      : CH - device+function number
;output: carry set - Don't use shadow RAM
;	 non carry - use shadow RAM instead of video ROM
;======================================================
		align	4
Patch_CT65548	proc	near

		pushad
		push	ds

		cmp	eax, (102CH shl 16) + 00DCh	;C&T 65548 VGA?
		jne	No_VideROM			;no

		call	X_C000_Shadow_RW
		F000_CALL C000_Shadow_R

		call	If_Any_VGA_BIOS_Exist
		clc
		je	Chk_Video_Exit

	No_VideROM:

		stc

	Chk_Video_Exit:

		pop	ds
		popad
		ret

Patch_CT65548	endp
endif	;PCI_RESET_SUPPORT

;======================================================
;======================================================
ifdef	PATCH_VGA_USE_2E8h_PORT
Patch_VGA_USE_2E8h	proc	near

		mov	byte ptr SIO_COM_SETTING[bp], 0
		cmp	eax, (3d3dH shl 16) + 0004h	;Permedia 3Dlabs
		jne	No_Use_2E8h			;no
		mov	byte ptr SIO_COM_SETTING[bp], 40h

	No_Use_2E8h:

		ret

PATCH_VGA_USE_2E8h	endp
endif;	PATCH_VGA_USE_2E8h_PORT

ifdef 	ALIm152x_Special_Define
;======================================================
;Input : eax - device ID & vendor ID
;      : CH - device+function number
;======================================================
Patch_ALIm152x_VGA	Proc	Near

	ifdef	ONBOARD_PCI_VGA
		push	ax

		call	See_If_Bus_0
		jne	@F

		cmp	ch, (ONBOARD_PCI_VGA) SHL 3
		jne	@F

		mov	cl, 04h
		xor	ax, ax
		call	X_Set_CfgSpace_Word
	@@:
		pop	ax
	endif	;ONBOARD_PCI_VGA

		ret

Patch_ALIm152x_VGA	Endp
endif	;ALIm152x_Special_Define

;======================================================
;
; Some VGA cards need to be set to mode 3 when warm reset
;
;Input : eax - device ID & vendor ID
;      : CH - device+function number
;======================================================
Record_Set_Mode3_VGA	Proc	Near

		push	ds
		push	eax

		push	G_RAM
		pop	ds
		mov	si, offset System_Flag
;R18		mov	byte ptr ds:[si], not VGA_NEED_SET_MODE3
		and	byte ptr ds:[si], not VGA_NEED_SET_MODE3	;R18

		ror	eax, 16			;AX = Vendor ID

		cmp	ax, 5333H		;S3 PCI/VGA ?
		je	Yes_SpcVga

		cmp	ax, 1002H		;ATI PCI/VGA ?
		je	Yes_SpcVga

		cmp	ax, 1039H		;SiS PCI/VGA ?
		je	Yes_SpcVga

		cmp	ax, CIRRUS_VENDOR_ID
		jne	@F

	Yes_SpcVga:

		or	byte ptr ds:[si], VGA_NEED_SET_MODE3
	@@:

		pop	eax
		pop	ds

		ret

Record_Set_Mode3_VGA	Endp

;R07 ;[]==============================================================[]
;R07 ;[]==============================================================[]
;R07 Process_Combined_VGA	Proc	Near
;R07
;R07 		call	If_Any_VGA_BIOS_Exist		;any VGA ?
;R07 		je	VgaBiosAlready			;yes, so no onboard!
;R07
;R07 		mov	edi, 7000h
;R07 		POST_FUNC_CALL Find_Valid_ROM_Image
;R07 		jc	VgaBiosAlready
;R07
;R07 		mov	si, 7000h
;R07 		call	Move_Video_Image_To_C000
;R07
;R07 	VgaBiosAlready:
;R07
;R07 		ret
;R07
;R07 Process_Combined_VGA	Endp

;[]---------------------------------------------------------------[]
; Input	:	si = segment contain the VGA BIOS
;[]---------------------------------------------------------------[]
Move_Video_Image_To_C000	Proc	Near

;R82 - starts
		push	ecx		;save device number	;R82B

		call	X_C000_Shadow_RW

		mov	ds, si
		mov	cl, ds:[2]

	ifndef	SHADOW_UNIT_64K
		cmp	cl, 40h
		jbe	@F

		pusha
		mov	dx, 0C800h
		call	X_Ct_Shadow_RW
		mov	dx, 0CC00h
		call	X_Ct_Shadow_RW
		popa
	@@:
	endif	;SHADOW_UNIT_64K

		mov	VGA_BIOS_LENGTH[bp], cl
		shl	cx, 8 			;in terms of word
		mov	di, 0C000h
		call	X_Move_Codes
		call	Record_Resource_For_Big_VGA

		pop	ecx		;restore device number	;R82B

		ret

Move_Video_Image_To_C000	Endp
;R82 - ends

;R82		push	si
;R82		call	X_C000_Shadow_RW
;R82		mov	di, 0C000h
;R82		mov	cx, 4000h		;32k to move
;R82		call	X_Move_Codes
;R82		pop	si
;R82
;R82		mov	ds, si
;R82		mov	al, byte ptr ds:[2]
;R82		mov	byte ptr VGA_BIOS_LENGTH[bp], al
;R82
;R82		cmp	byte ptr ds:[2], 40h	;VGA BIOS size =< 32k
;R82		jbe	VgaBios32k		;yes, skip the following !
;R82
;R82	;----- Copy the rest of the VGA codes other than 32k -----
;R82
;R82		push	si
;R82
;R82		call	X_C000_Shadow_RW
;R82 ifdef	VSA_VGA								;R44
;R82		F000_CALL Ct_Gx_C8_To_DF_RW	;enable C8-DF shadow R/W;R44
;R82 else;	VSA_VGA								;R44
;R82		F000_CALL Ct_C8_To_DF_RW	;enable shadow R/W
;R82 endif;	VSA_VGA								;R44
;R82
;R82	;------------------------------------------------------------------
;R82	;Fill unused shadow RAM with 0FFH to prevent SCT "unreport memory"
;R82	;if VGA ROM size is bigger than 32Kb
;R82
;R82		push	es
;R82		push	0c800h		;destination segment address
;R82		pop	es
;R82
;R82		xor	di, di		;start from offset zero
;R82		mov	ax, 0FFFFH
;R82		mov	cx, 32*1024/2	;32kb to fill
;R82		rep	stosw		;fill shadow RAM pattern 0FFH
;R82		pop	es
;R82
;R82	;------------------------------------------------------------------
;R82
;R82		mov	cl, ds:[2]		;get code size to copy
;R82		sub	cl, 40h			;code size other than 32k
;R82		xor	ch, ch
;R82		shl	cx, 8 			;in terms of word
;R82		add	si, 800h		;starting from 32k
;R82		mov	di, 0C800h		;copy to C800:0
;R82		call	X_Move_Codes
;R82
;R82		pop	si
;R82
;R82		call	Record_Resource_For_Big_VGA
;R82
;R82	;--- trying to disable the shadow not used for VGA bios -----
;R82
;R82		shr	cx, 4
;R82
;R82	KeepDisShd:
;R82
;R82	;Disable unused shadow RAMs , except the area used by VGA ROM
;R82		pusha
;R82 ifdef	VSA_VGA								;R44
;R82		F000_CALL Ct_GxDisable_Shadow				;R44
;R82 else;	VSA_VGA								;R44
;R82		F000_CALL Ct_Disable_Shadow
;R82 endif;	VSA_VGA								;R44
;R82		popa
;R82
;R82		add	dh, ch
;R82		cmp	dh, 0E0h
;R82		jne	KeepDisShd
;R82
;R82	;-----------------------
;R82
;R82	VgaBios32k:
;R82
;R82		ret
;R82
;R82Move_Video_Image_To_C000	Endp

;R82 - starts
;-----------------------------------------------------
;input	:	ds = VGA ROM image location
;output	:	None
;-----------------------------------------------------
Record_Resource_For_Big_VGA	Proc	Near

		mov	al, ds:[2]			;VGA BIOS size
		sub	al, 40h				;VGA BIOS size =< 32k
		jbe	VgaLessThan32K			;no !

		call	Request_C8_For_VGA
	ifndef	SHADOW_UNIT_64K
		call	X_Invalidate_Shadow_Seg
	endif	;SHADOW_UNIT_64K

	VgaLessThan32K:

		ret

Record_Resource_For_Big_VGA	Endp

Request_C8_For_VGA	Proc	Near

		test	al, 07h				;size < 4K
		jz	@F				;no, continue!
		add	al, 08h				;  to 4K
	@@:
		shr	al, 3				;in terms of 4K
		mov	cl, al
		and	dword ptr LMEM_RESOURCE[bp], 0FFFFFF00h
		mov	byte ptr LMEM_FOR_ROM_FLG[bp], 1
		call	fPROC_Get_Available_LMEM	;request low mem
		ret

Request_C8_For_VGA	Endp
;R82 - ends

;R82 ;-----------------------------------------------------
;R82 ;input	:	si : VGA ROM image location
;R82 ;output	:	dx : upper boundary addr for VGA
;R82 ;		cx : shadow unit = 8000h/4000h
;R82 ;-----------------------------------------------------
;R82 Record_Resource_For_Big_VGA	Proc	Near
;R82 
;R82		mov	ds, si
;R82		mov	bl, ds:[2]		;VGA BIOS size
;R82		cmp	bl, 40h			;VGA BIOS size =< 32k
;R82		jbe	_JBRDE			;no !
;R82
;R82		call	X_Ct_Shadow_Unit	;check chipset for shadow unit size
;R82		mov	dx, 0D000h		;disable shadow: starting from D000
;R82		cmp	ch, 80h			;shadow unit 32k ?
;R82		je	@F			;yes !
;R82		cmp	bl, 60h			;VGA BIOS >= 48k ?
;R82		ja	@F			;yes !
;R82		mov	dh, 0CCh		;disable shadow: starting from CC00
;R82	@@:
;R82	;-----------------------
;R82
;R82		mov	eax, 0Fh		;assume C800-CBFF used
;R82		cmp	dh, 0CCh		;really the case ?
;R82		je	@F			;yes !
;R82		mov	al, 0FFh		;CC00-CFFF also used !
;R82	@@:
;R82		or	LMEM_RESOURCE[bp], eax	;update resources
;R82	_JBRDE:
;R82		ret
;R82
;R82Record_Resource_For_Big_VGA	Endp

;[]================================================================[]
; This routine is used to check if VGA BIOS has been condensed
; after VGA BIOS had been initialed. And reprepare LMEM_RESOURCE[bp]
;[]================================================================[]
fProc_Release_Shadow_From_PCI_VGA	Proc	Far
;R82 - starts
		pushad
		push	ds

		mov	al, VGA_BIOS_LENGTH[bp]
		cmp	al, 40h
		jbe	No_Release_C8

		and	dword ptr LMEM_RESOURCE[bp], 0FFFFFF00h

		mov	ax, 0C000h
		mov	ds, ax
		mov	al, ds:[2]
		sub	al, 40h
		jbe	No_Release_C8

		call	Request_C8_For_VGA

	No_Release_C8:

		mov	eax, LMEM_BEFORE_ROM[bp]
		or	LMEM_RESOURCE[bp], eax

ifndef	SHADOW_UNIT_64K					;R82A
		post_func_call	Invalidate_Shadow_Seg	;R82A
endif;	SHADOW_UNIT_64K					;R82A

		xor	si, si
		call	fPROC_Disable_Unused_Shadow

		pop	ds
		popad

		ret

fPROC_Release_Shadow_From_PCI_VGA	Endp
;R82 - ends

;R82		pushad
;R82		push	ds
;R82		push	dword ptr LMEM_BEFORE_ROM[bp]
;R82
;R82		call	X_Ct_Shadow_Unit	;check chipset for shadow unit size
;R82
;R82		mov	dx, 0F20h
;R82		cmp	cx, 4000h
;R82		je	@F
;R82		mov	dx, 0FF40h
;R82	@@:
;R82		mov	cl, VGA_BIOS_LENGTH[bp]
;R82
;R82		cmp	cl, 40h
;R82		jbe	RePrepare_Exit
;R82
;R82		mov	ax, 0C000H
;R82		push	ax
;R82		pop	ds
;R82
;R82		mov	ch, ds:[2]
;R82		cmp	ch, 40h
;R82		jae	@F
;R82		mov	ch, 40h
;R82	@@:
;R82		cmp	cl, ch
;R82		jbe	RePrepare_Exit
;R82		mov	eax, 0FFFFFFFFh
;R82		sub	cl, 40h
;R82
;R82		mov	bl, dh
;R82		cmp	cl, dl
;R82		jbe	@F
;R82		shl	bl, 4
;R82		or	bl, dh
;R82	@@:
;R82		not	bl
;R82		and	al, bl
;R82
;R82		sub	ch, 40h
;R82		mov	bl, 0
;R82		jbe	@F
;R82		mov	bl, dh
;R82		cmp	ch, dl
;R82		jbe	@F
;R82		shl	bl, 4
;R82		or	bl, dh
;R82	@@:
;R82		call	VGA_release_shadow_fill
;R82		or	al, bl
;R82
;R82		and	LMEM_RESOURCE[bp], eax
;R82		and	LMEM_BEFORE_ROM[bp], eax
;R82		xor	si, si
;R82
;R82		F000_CALL Disable_Unused_Shadow
;R82
;R82RePrepare_Exit:
;R82		pop	dword ptr LMEM_BEFORE_ROM[bp]
;R82		mov	eax, LMEM_BEFORE_ROM[bp]
;R82		or	LMEM_RESOURCE[bp], eax
;R82
;R82		pop	ds
;R82		popad
;R82		retf
;R82
;R82fProc_Release_Shadow_From_PCI_VGA	Endp

VGA_release_shadow_fill	Proc	near

		pushad
		cld

		mov	al, ch	  	;ch = VGA size(now) - 32kbyte
		add	al, 40h
		shl	ax, 9
		mov	di, ax		;di = will fill start point

ifndef	SHADOW_UNIT_64K						;R82
		cmp	cl, 20h		;if original VGA bios > 48k
		ja	unit_32k	;

		call	X_Ct_Shadow_Unit	;check chipset for shadow unit size
		cmp	cx, 4000h
		jne	unit_32k

		mov	cx, 0c000h	;cx = C000 - VGA bios end
		sub	cx, di
	   	jmp	@F
endif	;SHADOW_UNIT_64K					;R82
	unit_32k:
		mov	cx, di		;cx = 10000 - VGA bios end
		not	cx
		inc	cx
	@@:
		mov	ax, 0C000H
		mov	es, ax
		mov	al, 0ffh		;Fill the shadow (no use) = 0ffh
		rep	stosb
	@@:
		popad
		ret

VGA_release_shadow_fill	Endp

;[]================================================================[]
;
; This routine is used to set PCI/VGA to special state
; Before VGA/ROM initial
;
; Input  : none
; Output : none
;
;[]================================================================[]
fProc_Before_PciVGARomInit	Proc	Far

ifndef	No_Clear_Command_Res_Bit7

		pushad

;-------------------------------------------------------------------------;
;Enable address/data stepping for VGA card to fix VGA ROM initial failure
;for Acer's ATI/Mach32 card

		mov	cx, PCI_VGA_INFO[bp]	;ch = bus no. cl=dev+fun no
		or	cx, cx			;VGA found ?
		jz	No_PciVgaFound

		mov	CURRENT_BUS_NO[bp], ch	;bus number
		mov	ch, cl			;CH = device+func no.

	ifdef	No_Clear_Command_Res_Bit7_When_Trident975

		call	X_Get_Vendor_ID
		cmp	ax, 1023h		; Trident975 Vender ID
		jnz	@F

		call	X_Get_Device_ID
		cmp	ax, 9750h		; Trident975 Device ID
		jz	No_PciVgaFound
	@@:
	endif;	No_Clear_Command_Res_Bit7_When_Trident975

		mov	cl, 04H			;command register
		call	X_Get_CfgSpace_Word
		or	al, 80H			;enable address/data stepping
		call	X_Set_CfgSpace_Word

No_PciVgaFound:
;-------------------------------------------------------------------------;

		popad

endif;	No_Clear_Command_Res_Bit7

		retf

fProc_Before_PciVGARomInit	Endp

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&                                                         &&&&&&
;&&&&&&               IRQ related routines                      &&&&&&
;&&&&&&                                                         &&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

;======================================================================
;======================================================================
Record_IRQ_Request	Proc	Near

		cmp	byte ptr CURRENT_SLOT[bp], 0FFh
		je	No_Record_IRQ_Request

		push	ds
		pusha
		push	SEG TEMP_PCI_REQ_BUF
		pop	ds

		push	ax			;save class code
		mov	cl, 3DH			;read interrupt pin
		call	X_Get_CfgSpace_Byte
		mov	bl, al			;temp put interrupt pin in BL
		pop	ax			;restore class code

		or	bl, bl			;no IRQ needed ?
		jz	No_IRQ_Req		;0 = no need !
		cmp	bl, 00000100b		;invalid value ?
		ja	No_IRQ_Req		;maximum value is 4 for INT D

		call	Check_No_Irq_Device	;device don't need IRQ?
		jc	No_IRQ_Req		;CF = don't need IRQ !

		mov	al, bl			;put interrupt pin in AL

	;******************************************************

		mov	bl, CURRENT_SLOT[bp]
		mov	bh, CURRENT_BUS_NO[bp]

	;---------------------------------------------------

		push	cx
		push	bx
	@@:
		or	bh, bh			;Bus 0 device?
		jz	@F			;yes, skip

		call	Get_P2P_IrqRoute	;get correct routing
						;for device go thru
						;1 level of P2P bridge
						;input AL = original INT#
						;output AL = INT# on P2P bridge

		push	ax			;get p2p info offset
		mov	al, bh
		call	Get_Bus_Info_Offset
		pop	ax

  		mov	ch, ds:[si].P2PB_DevFucNo
		mov	bh, ds:[si].P2PB_BusNo
		jmp	@B
	@@:
		mov	cl, bl			;current slot index
		call	Get_IrqRouting 		;input : AL - interrupt pin
						;output: AL - interrupt pin routed
		pop	bx
		pop	cx

	;---------------------------------------------------

		push	SEG IRQ_REQ_BUF
		pop	ds
		mov	di, offset IRQ_REQ_BUF_PTR
		mov	si, ds:[di]
		add	word ptr ds:[di], SIZE_IRQ_REQ_STRUC

		mov	ds:[si].IntPin, al
		mov	ds:[si].IrqReqDevNum, ch
		mov	ds:[si].IrqReqBusNum, bh
		mov	ds:[si].HostSlot, bl

	;******************************************************

	No_IRQ_Req:

		popa
		pop	ds

	No_Record_IRQ_Request:

		ret

Record_IRQ_Request	Endp

;[]==============================================================[]
;Check_No_Irq_Device:
;	Check device if it need IRQ or not
;Saves: all
;Input :
;	 CH - PCI device No.
;	 AX - Class code
;Output: carry set - No IRQ required
;	 no  carry - IRQ required
;[]==============================================================[]
Check_No_Irq_Device 	proc	near

		pushad

;R71 - start
		call 	SearchTruePCIIde
		jc	SureAssignIRQ
;R71 - end

		cmp	ax, CLASS_IDE			;its a PCI IDE?
		je	Should_Not_Assign_IRQ

	SureAssignIRQ:					;R71

	;---------------------------------------------------------
	;Somebody want to have a setup item to decide whether IRQ
	;should be assigned fo USB controller or not
	;---------------------------------------------------------
;R52 - start
	ifdef	USB_SUPPORT
	ifdef	No_Assign_IRQ_If_USB_Disable
		cmp	ax, CLASS_USB			;USB Class code
		jne	short Not_UsbDev		;no,

		push	ax				;R52B
		mov	si,offset USB_ITEM
	 	call	X_GetItem_Value
		or	al,al
		pop	ax				;R52B
		jz	short Should_Not_Assign_IRQ		;no IRQ for USB !
;R52B		mov	si,offset USB_Legacy_ITEM	;R52A
;R52B		call	X_GetItem_Value			;R52A
;R52B		or	al,al				;R52A
;R52B		jz	short Should_Not_Assign_IRQ	;R52A
;R52B		jmp	Should_Assign_IRQ		;R52A

Not_UsbDev:
	endif;	No_Assign_IRQ_If_USB_Disable
	endif;	USB_SUPPORT
;R52 - end
	ifdef	USB_IRQ_SELECTABLE

		cmp	ax, CLASS_USB			;USB Class code
		jne	NotUsbDev			;no,

		ifdef	VT586_USB			;R29 - starts
			; for VIA chip !
		mov	si, offset ONBD_USB_Item	; Get CMOS value
	 	call	X_GetItem_Value
	 	or	al, al				; If USB enable ?
		jnz	Should_Not_Assign_IRQ		; No, Jmp !
		endif;	VT586_USB			;R29 - ends

		mov	si, offset UsbIrq_Item		;get CMOS value
	 	call	X_GetItem_Value
	 	or	al, al				;enable IRQ for USB ?
		jz	Should_Not_Assign_IRQ		;no IRQ for USB !
		jmp	Should_Assign_IRQ
	NotUsbDev:

	endif	;USB_IRQ_SELECTABLE

	;---------------------------------------------------------
	;Somebody do not want IRQ for VGA devices
	;---------------------------------------------------------
	ifdef	NO_ASSIGN_PCIVGA_IRQ

		call	X_Chk_If_Class_VGA_1		;is it a VGA card?
		je	Should_Not_Assign_IRQ		;yes, skip IRQ

	endif	;NO_ASSIGN_PCIVGA_IRQ

ifdef  AGP_V3000_Card_Awlays_Assign_IRQ		;R46 - start
		pushad
		xor	cl, cl			;vendor ID
		CALL	X_Get_CfgSpace_Word
		cmp	ax,12d2h
		jz	short  check_Assign_IRQ_?
		mov	cl, 02			;device ID
		CALL	X_Get_CfgSpace_Word
		cmp	ax,0018h
		popad
		jnz	Should_Assign_IRQ
		jmp	short not_AGP_V3000_Card
check_Assign_IRQ_?:
		popad
not_AGP_V3000_Card:
endif; AGP_V3000_Card_Awlays_Assign_IRQ		;R46 - end
	;---------------------------------------------------------
	;Somebody want to have a setup item to decide whether IRQ
	;should be assigned fo VGA devices or not
	;---------------------------------------------------------
	ifdef	PCI_VGA_IRQ_SETUP_ITEM
		call	X_Chk_If_Class_VGA_1		;is it a VGA card?
		jne	NotVgaDev			;no !

		mov	si, offset Assign_Pci_IRQ_Item	;read the item value
		call	X_GetItem_Value
		or	al, al				;IRQ needed ?
		jnz	Should_Assign_IRQ		;yes !

	   ;---------------------------------------------------------
	   ;set 0FFH to prevent default IRQ No. in 3CH is in 0-15
	   ;like ET3000 , it's default is 15 and bit7-4 is read only
	   ;---------------------------------------------------------
		mov	cl, 3CH				;IRQ No.
		mov	al, 0ffH
		call	X_Set_CfgSpace_Byte		;write PCI byte
		call	X_Get_CfgSpace_Byte		;read PCI byte
		cmp	al, 0FH				;bit7-4 read only
		jne	@F
		xor	al, al				;write 00H
		call	X_Set_CfgSpace_Byte		;write PCI byte
	@@:
		jmp	Should_Not_Assign_IRQ

	NotVgaDev:

	endif	;PCI_VGA_IRQ_SETUP_ITEM

	Should_Assign_IRQ:

		clc
		jmp	@F

	Should_Not_Assign_IRQ:

		stc
	@@:
		popad
		ret

Check_No_Irq_Device 	endp

;[]========================================================================[]
;Procedure  :	CMOS_Setup_IRQ_Resource
;
;Input	    :	None
;
;Output	    :	None
;
;Description:	1. PCIIRQ[BP] format:
;
;		       INT no. (1-16)	    IRQ no.
;		   +------------------+-------------------+
;		 1 |                  |     IRQ 14        |  0
;		   +------------------+-------------------+
;		 3 |                  |     IRQ 15        |  2
;		   +------------------+-------------------+
;		 5 |                  | 1st Available IRQ |  4
;		   +------------------+-------------------+
;		 7 |                  | 2nd Available IRQ |  6
;		   +------------------+-------------------+
;		 9 |                  | 3rd Available IRQ |  8
;		   +------------------+-------------------+
;		11 |                  | 4th Available IRQ | 10
;		   +------------------+-------------------+
;			  .                          .
;			  .                          .
;		   IRQ no.
;		   -------
;		   Indicates the available IRQ channels of 8259
;
;		   The Award PCI BIOS will fill the 1st-nth Available IRQs
;		   according to setup settings. IRQ 14 & 15 will always be
;		   placed in offset 0 & 2.
;
;		   INT no.
;		   -------
;		   lmost all PCI chipsets provides only a few interrupt pins
;		   for the PCI devices. The number of interrupt pins varies
;		   from chip to chip.
;
;		   Example:
;
;		   +------------------------+------------------------+
;		 5 |         1              |         10             |  4
;		   +------------------------+------------------------+
;		 7 |         2              |         11             |  6
;		   +------------------------+------------------------+
;		 9 |         0              |         09             |  8
;		   +------------------------+------------------------+
;
;		   This example tell us that INT pin 1/2 has been assigned
;		   with IRQ 10/11. IRQ 09 is still available
;
;		2. This routine will prepare the available IRQs for
;		   the code follows to assign to PCI devices.
;
;		   PCIIRQ[BP+n] n=0, 2, 4... will be placed with Available IRQs
;					   according to CMOS SETUP
;		   PCIIRQ[BP+m] m=1, 3 will be initialized to 0FFh indicates
;				      that IRQ 14, 15 are available exclusively
;				      for PCI IDE
;				m=5, 7..	will be initialized to to indicate
;					the corresponding IRQ is not yet
;					assigned to any other device
;
;[]========================================================================[]
CMOS_Setup_IRQ_Resource	Proc	Near

	;Copy available PCI IRQs into stack area

		mov	word ptr PCIIRQ[bp+0], 0ff0EH	;IRQ 14 for IDE

	ifdef	Special_IRQ_For_Second_IDE
		mov	word ptr PCIIRQ[bp+2], 0ff00H+\
			Special_IRQ_For_Second_IDE
	else	;Special_IRQ_For_Second_IDE
		mov	word ptr PCIIRQ[bp+2], 0ff0FH	;IRQ 15 for IDE
	endif	;Special_IRQ_For_Second_IDE

		mov	si, 4

ifndef	NEW_PNP_SETUP
		mov	ax, SEG PciIrq_Item
		mov	ds, ax
		mov	di, offset PciIrq_Item

	Next_PciIrq:

		cmp	word ptr ds:[di], -1		;end of PCI IRQ item ?
		je	EndPci_Irq

		push	si
		mov	si, ds:[di]
		call	X_GetItem_Value
		pop	si

		or	al, al				;bad IRQ ?
		jz	Next_Cmos_Irq			;skip it

		xor	ah, ah
		mov	word ptr PCIIRQ[bp+si], ax
		inc	si
		inc	si				;next IRQ
Next_Cmos_Irq:

		add	di, 2				;next available IRQ offset

		jmp	Next_PciIrq
endif	;NEW_PNP_SETUP

	EndPci_Irq:

		mov	word ptr PCIIRQ[bp+si], 00AAH	;last available IRQ

		ret

CMOS_Setup_IRQ_Resource	Endp

ifdef	PNP_BIOS
;[]==============================================================[]
;[]==============================================================[]
		Public	ESCD_IRQ_Resource
ESCD_IRQ_Resource	Proc	Near

		push	ds
		push	es

	;-------------------------------------------------------------------
	;Up to this moment, the ESCD tells us what IRQs are available & they
	;are stored in G_RAM:[SYSTEM_MAP+IRQ_MAP]. In addition, installation
	;of COM, LPT ports are also done. So we issue a call to subroutine
	;"Create_Resource_Map" in PNPPOST.ASM to exclude the IRQs used up by
	;COM/LPT ports!
	;-------------------------------------------------------------------

		mov	ax, G_RAM
		mov	ds, ax
		mov	es, ax
		ASSUME	DS:G_RAM

ifdef	NEW_PNP_SETUP
		call	New_PnP_Setup_IRQ_Resource
else	;NEW_PNP_SETUP
	ifdef	PNP_PCI_AUTO
		call	Old_PnP_Setup_IRQ_Resource
	endif	;PNP_PCI_AUTO
endif	;NEW_PNP_SETUP

		pop	es
		pop	ds

		ret

ESCD_IRQ_Resource	Endp

;R04 - starts
;----------------------------------------------------------------------
;Function : Reserve a IRQ for PCI boot device to sure system can boot
;	    from boot device ( like SCSI etc..)
;Input    : none
;Output   : none
;----------------------------------------------------------------------
		Public	fProc_Reserve_Irq_For_PciBootDev
fProc_Reserve_Irq_For_PciBootDev	Proc	Far

;Don't assign IRQ 5 for PCI or PnP devices if Ensoniq PCI sound card installed
;Note : This sound card need two IRQs , the first one is assigned by normal
;	PCI INT pin, another is direct using ISA's IRQ 5.

		pushad
		push	ds
		mov     dx, 1274h		;vendor ID
		mov	cx, 5000h		;device ID
		xor     si, si			;first device
		mov     ax, 0b102H		;find PCI device func. call
		int     1AH
		jc	Not_EnsoniqPciSound	;device found ?

	;enable SERR# for DOS sound blaster compatible

		mov	ch, bl				;device number
		mov	cl, 05h
		F000_CALL AGet_CfgSpace_Byte
		or	al, 01H				;enable SERR#
		F000_CALL ASet_CfgSpace_Byte

	ifdef	RESERVE_IRQ5_FOR_PCI_AUDIO
	;device found !
		mov	ax, G_RAM
		mov	ds, ax
		ASSUME	DS:G_RAM

		and	byte ptr ds:IRQ_MAP, NOT 20H;don't assign IRQ 5
	endif;	RESERVE_IRQ5_FOR_PCI_AUDIO
						;for PCI or PnP/ISA
Not_EnsoniqPciSound:

		pop	ds
		popad

ifdef	NEW_PNP_SETUP
ifdef	IRQ_FOR_BOOTDEV
		pushad
		push	ds

		mov	byte ptr RESERVE_PCIIRQ[bp], 0	;assume no IRQ reserved

	;scan if SCSI card plugged

		mov	si, offset BooDev_ClsCode

	Check_NextBootDev:

		mov	ecx, cs:[si]
		or	ecx, ecx
		jz	No_BootPci

		push	si
		xor     si, si			;first device
		mov     ax, 0b103H		;find PCI class code
		int     1AH
		pop	si

		add	si, 4			;next class code
		or	ah, ah			;device found ?
		jnz	Check_NextBootDev

	;boot device found , reserve a IRQ

		mov	ax, G_RAM
		mov	ds, ax
		ASSUME	DS:G_RAM

		mov	dx, word ptr ds:IRQ_MAP
	ifdef	AVAILABLE_PCI_IRQ
		and	dx, AVAILABLE_PCI_IRQ
	else	;AVAILABLE_PCI_IRQ
		and	dx, 0001111010100000b
	endif	;AVAILABLE_PCI_IRQ

		mov	si, offset PciIrq_BootDevOrder

	Chk_Nxt_PciIRq:

		mov	cl, cs:[si]		;get IRQ No. to check
		cmp	cl, -1			;end of table
		je	No_Irq_ForPci

		inc	si
		mov	ax, 1
		shl	ax, cl
		test	dx, ax
		jz	Chk_Nxt_PciIRq

		mov	byte ptr RESERVE_PCIIRQ[bp], cl	;save IRQ in buffer

	No_Irq_ForPci:
	No_BootPci:

		pop	ds
		popad

endif;	IRQ_FOR_BOOTDEV
endif;	NEW_PNP_SETUP

		retf

fProc_Reserve_Irq_For_PciBootDev	Endp

ifdef	NEW_PNP_SETUP
ifdef	IRQ_FOR_BOOTDEV
BooDev_ClsCode:
		dd	010000H			;SCSI
		dd	010400H			;RAID
		dd	018000H			;other mass storage controller
		dd	0			;end of table
endif;	IRQ_FOR_BOOTDEV
endif;	NEW_PNP_SETUP
;R04 - ends

;[]==============================================================[]
;[]==============================================================[]
ifdef	NEW_PNP_SETUP
New_PnP_Setup_IRQ_Resource	Proc	Near

		call	Get_Reserved_IRQ

		mov	dx, word ptr ds:IRQ_MAP
		call	Check_Ide_Exist			;check IDE devices

		cmp	byte ptr PCIIRQ[bp+1], 0FFh	;primary IDE
		je	@F

		and	dh, 10111111b
	@@:
		cmp	byte ptr PCIIRQ[bp+3], 0FFh	;secondary IDE
		je	@F

		and	dh, 01111111b
	@@:
	ifdef	AVAILABLE_PCI_IRQ
		and	dx, AVAILABLE_PCI_IRQ
	else	;AVAILABLE_PCI_IRQ
		and	dx, 0001111010100000b
	endif	;AVAILABLE_PCI_IRQ

		call	Assign_IRQ_Special

		mov	si, 4			;start from 3rd IRQ

		mov	di, offset ASSIGN_PCI_IRQ_TBL

Check_Available_IRQ:

		mov	bx, dx
		movzx	cx, byte ptr cs:[di]
		cmp	cx, 00ffh			;Is table's end ?
		je	ASSIGN_PCI_IRQ_EXIT
		push	cx
		mov	ax, 16
		sub	ax, cx
		xchg	al, cl
		shl	bx, cl
		pop	cx
		jnc	@f

		mov	PCIIRQ[bp+si], cx		;assign correct IRQ
;R20 - start
 ifdef	PCI_IRQ_SELECTABLE
		call	Chk_FixedPciIrq	  	;check if any fixed IRQ
					  	;for PCI by user
 endif;	PCI_IRQ_SELECTABLE
;R20 - end

;R48 - start
ifdef	ASSIGN_ONE_IRQ_FOR_PCI_IF_PnPOS_YES
		pusha
		push	si
		extrn	OS_Setup_Item:near
		mov	si,offset DGROUP:OS_Setup_Item
		call	X_GetItem_Value	;read PnP OS CMOS setting
		or	al,al
		jz	short Not_PnP_OS
		pop	si
		mov	ax,PCIIRQ[bp+4]		;get first IRQ
		mov	PCIIRQ[bp+si],ax	;assign correct IRQ
		jmp	short Yes_PnP_OS
	Not_PnP_OS:
		pop	si
	Yes_PnP_OS:
		popa
endif;	ASSIGN_ONE_IRQ_FOR_PCI_IF_PnPOS_YES
;R48 - end

		add	si, 2
@@:
		inc	di
		jmp	Check_Available_IRQ

ASSIGN_PCI_IRQ_EXIT:

		mov	word ptr PCIIRQ[bp+si], 00AAh
		ret

New_PnP_Setup_IRQ_Resource	Endp

ASSIGN_PCI_IRQ_TBL	Label	Byte
	ifndef	NO_RELEASE_IRQ15_FOR_PCI
		db	15
	endif;	NO_RELEASE_IRQ15_FOR_PCI
PciIrq_BootDevOrder	Label	Near
;R51A ifdef	First_Assign_IRQ10			;R51
;R51A 		db	10			;R51
;R51A 		db	11			;R51
;R51A else;	First_Assign_IRQ10			;R51
		db	11
		db	10
;R51A endif;	First_Assign_IRQ10			;R51
;R08		db	 9
		db	12
		db	14
	ifdef	PCIIRQ34_first_When_free
		db	 3
		db	 4
	endif	;PCIIRQ34_first_When_free
		db	 5
		db	 7
	ifndef	PCIIRQ34_first_When_free
		db	 3
		db	 4
	endif	;PCIIRQ34_first_When_free
		db	 9			;R08
		db	 6			;R62 IRQ 6
		db    0ffh

endif	;NEW_PNP_SETUP

;[]==============================================================[]
;[]==============================================================[]
ifndef	NEW_PNP_SETUP
ifdef	PNP_PCI_AUTO
Old_PnP_Setup_IRQ_Resource	Proc	Near
		mov	si, offset PnP_Auto_Item
		call	X_GetItem_Value	    		;should we use manaul
		or	al, al				;override or ESCD ?
		jz	No_PnP_Auto		;manually override!

		mov	dx, word ptr ds:IRQ_MAP
		call	Check_Ide_Exist			;check IDE devices
		cmp	byte ptr PCIIRQ[bp+1], 0FFh	;primary IDE
		je	@F

		and	dh, 10111111b
	@@:
		cmp	byte ptr PCIIRQ[bp+3], 0FFh	;secondary IDE
		je	@F

		and	dh, 01111111b
	@@:
	ifdef	AVAILABLE_PCI_IRQ
		and	dx, AVAILABLE_PCI_IRQ
	else	;AVAILABLE_PCI_IRQ
		and	dx, 0001111010100000b
	endif	;AVAILABLE_PCI_IRQ

	ifdef	IRQ12_LAST_FOR_PCI
		push	dx			;save available IRQ
		and	dh, NOT 10H		;mask IRQ 12
	endif;	IRQ12_LAST_FOR_PCI

		mov	si, 4			;start from 3rd IRQ
		mov	cx, 16

Check_Available_IRQ:

		shl	dx, 1
		jnc	@f
		dec	cx
		mov	PCIIRQ[bp+si], cx
		inc	cx
		add	si, 2
	@@:
		loop	Check_Available_IRQ

	ifdef	IRQ12_LAST_FOR_PCI
		pop	dx			;save available IRQ
		test	dh, 10H			;IRQ 12 available
		jz	No_Irq12
		mov	cx, 12
		mov	PCIIRQ[bp+si], cx	;IRQ 12 is available
		add	si, 2			;next IRQ offset
	No_Irq12:
	endif;	IRQ12_LAST_FOR_PCI

		mov	word ptr PCIIRQ[bp+si], 00AAh

	No_PnP_Auto:

		ret
Old_PnP_Setup_IRQ_Resource	Endp
endif	;PNP_PCI_AUTO
endif	;NEW_PNP_SETUP

		ASSUME	DS:NOTHING

;-----------------------------------------------------------------
;Function : Put reserved IRQ to buffer for PCI assignment
;Input    : DS:G_RAM
;Output   : none
;-----------------------------------------------------------------
		ASSUME	DS:G_RAM
Get_Reserved_IRQ	proc	near

ifdef	NEW_PNP_SETUP
ifdef	IRQ_FOR_BOOTDEV
		mov	cl, byte ptr RESERVE_PCIIRQ[bp]	;get IRQ
		or	cl, cl				;IRQ reserved ?
		jz	No_IRQReserved

		mov	ax, 1
		shl	ax, cl
		or	word ptr ds:IRQ_MAP, ax
No_IRQReserved:
endif;	IRQ_FOR_BOOTDEV
endif;	NEW_PNP_SETUP
		ret

Get_Reserved_IRQ	endp

;---------------------------------------------------------------------------
;Function : Assign IRQ for onboard SCSI that don't route IRQ thru PCI-TO-ISA
;	    controller but route to super I/O's IRQIN
;Input    : dx - available IRQ for PCI devices
;Output   : none
;---------------------------------------------------------------------------
Assign_IRQ_Special	proc	near

ifdef	SCSI_IRQ_TO_336_SIRQ3
		push	bx
		push	si

		xor	al, al			;disable routing for 336
		POST_FUNC_CALL Set_336_Sirq3

ifdef	ONBOARD_ScsiChip
;Disable I/O and memory access for onboard device due to setup
		mov	si, offset Onboard_Scsi_Item
		call	X_GetItem_Value
		or	al, al			;disabled ?
		jz	Scsi_Disabled	;don't assign IRQ if disabled
endif;	ONBOARD_ScsiChip

		mov	si, offset IRQ_Order
Next_IRQorder:
		mov	cl, cs:[si]		;get IRQ No. order
		or	cl, cl			;end of table
		jz	Scsi_Disabled	;no IRQ available

		mov	bx, 1
		shl	bx, cl
		test	dx, bx			;IRQ available
		jnz	IRQ_GotIt

		inc	si
		inc	si			;get next IRQ order

		jmp	Next_IRQorder

IRQ_GotIt:
		not	bx
		and	dx, bx			;occupy IRQ

	;Program IRQ in configuration

 		mov	ch, (ONBOARD_ScsiChip_SLOT SHL 3)
		mov	al, cl			;IRQ number
		mov	cl, 3CH
		call	X_Set_CfgSpace_Byte

		mov	al, cs:[si+1]		;value to write for I/O chip
		POST_FUNC_CALL Set_336_Sirq3
Scsi_Disabled:
		pop	si
		pop	bx

endif;	SCSI_IRQ_TO_336_SIRQ3

ifdef	M1523B_USB
		POST_FUNC_call M1523B_USB_Irq
endif;	M1523B_USB

ifdef	ITE8330G_USB
		POST_FUNC_call ITE8330G_USB_Irq
endif;	ITE8330G_USB

		ret

Assign_IRQ_Special	endp

ifdef	SCSI_IRQ_TO_336_SIRQ3
	IRQ_INVERT	=	10H	;invert IRQ for PCI
 ifdef	IRQ_NO_INVERT
	IRQ_INVERT	=	00H	;no inverted IRQ for PCI
 endif;	IRQ_NO_INVERT
;			IRQ No. , Value to write
IRQ_Order	db	11	, (11001011b OR IRQ_INVERT) 	;IRQ 11
		db	10	, (11001010b OR IRQ_INVERT) 	;IRQ 10
;R08		db	 9	, (11001001b OR IRQ_INVERT) 	;IRQ 9
		db	12	, (11001111b OR IRQ_INVERT) 	;IRQ 12 (use IRQ15/SIRQ1 pin)
		db	 5	, (11000101b OR IRQ_INVERT)	;IRQ 5
		db	 7	, (11000111b OR IRQ_INVERT)	;IRQ 7
		db	 3	, (11000011b OR IRQ_INVERT)	;IRQ 3
		db	 4	, (11000100b OR IRQ_INVERT)	;IRQ 4
		db	 9	, (11001001b OR IRQ_INVERT) 	;IRQ 9 ;R08
		db	 0	, 0		;end of table

endif;	SCSI_IRQ_TO_336_SIRQ3

;-----------------------------------------------------------------------
;Function : Check on-chip IDE channels enabled or disabled
;	    Force IRQ 14 & 15 to not available if enabled
;Input    : BX - bit 15 = mask of IRQ 15 , 1-available , 0-not available
;	         ....
;Output   : BX
;-----------------------------------------------------------------------
Check_Piix_Ide	proc	near

;R63 - start
SIS_IDE_DEVICE	=	0				;R63A
ifdef	SiS5513_IDE					;R63A
SIS_IDE_DEVICE	=	SiS5513_IDE			;R63A
IDE_REG_SWAP	=	0				;R63B
endif;	SiS5513_IDE					;R63A
ifdef	SIS5591_IDE					;R63A
SIS_IDE_DEVICE	=	SiS5591_IDE			;R63A
IDE_REG_SWAP	=	0				;R63B
endif;	SIS5591_IDE					;R63A
ifdef	SIS5601_IDE					;R63A
SIS_IDE_DEVICE	=	SiS5601_IDE			;R63A
IDE_REG_SWAP	=	1				;R63B
endif;	SIS5601_IDE					;R63A
ifdef	SIS530_IDE					;R63A
SIS_IDE_DEVICE	=	SiS530_IDE			;R63A
IDE_REG_SWAP	=	1				;R63B
endif;	SIS530_IDE					;R63A
ifdef	SIS620_IDE					;R63A
SIS_IDE_DEVICE	=	SIS620_IDE			;R63A
IDE_REG_SWAP	=	1				;R63B
endif;	SIS620_IDE					;R63A
;R63A ifdef	SiS5513_IDE
if	SIS_IDE_DEVICE					;R63A
	;Mask IRQ 14 & 15 if SiS IDE ports are not disabled
		push	bx

		xor	bh, bh				;bus 0
;R63A		mov	cx,(SiS5513_IDE SHL 8) + 04AH	;IDE control register
;R63B		mov	cx,(SIS_IDE_DEVICE SHL 8)+04AH	;R63A IDE control register
		mov	cx,(SIS_IDE_DEVICE)+04AH	;R63B IDE control register
		F000_CALL AGet_CfgSpace_Byte

		pop	bx
if	IDE_REG_SWAP	EQ 1				;R63B
		test	al, 010b			;R63B channel 0 enabled ?
else;	IDE_REG_SWAP					;R63B
		test	al, 100b			;channel 0 enabled ?
endif;	IDE_REG_SWAP					;R63B
		jz	short ChkChannel1

		and	bh, NOT 40H			;IRQ 14 not available

ChkChannel1:
if	IDE_REG_SWAP	EQ 1				;R63B
		test	al, 100b			;R63B channel 1 enabled ?
else;	IDE_REG_SWAP					;R63B
		test	al, 010b			;channel 1 enabled ?
endif;	IDE_REG_SWAP					;R63B
		jz	short Sis5513_Exit

		and	bh, NOT 80H			;IRQ 15 not available

Sis5513_Exit:

;R63A endif;	SiS5513_IDE
endif;	SIS_IDE_DEVICE					;R63A
;R63 - end

;R87 - start
ifdef	STPC_IDE
		push	bx

		xor	bh, bh				;bus 0
		mov	cx,(STPC_IDE SHL 8)+048H	;IDE control register
		F000_CALL AGet_CfgSpace_Byte

		pop	bx
		test	al, 04H		 		;IDE 0 disabled ?
		jnz	short ChkChannel1

		and	bh, NOT 40H			;IRQ 14 not available

ChkChannel1:
		test	al, 08H				;IDE 1 disabled ?
		jnz	short StpcIDE_Exit

		and	bh, NOT 80H			;IRQ 15 not available

StpcIDE_Exit:
endif;	STPC_IDE
;R87 - end

;R89 - start
ifdef	COBRA_IDE1
		push	bx

		xor	bh, bh				;bus 0
		mov	cx, COBRA_IDE1+040H		;IDE control register
		F000_CALL AGet_CfgSpace_Byte

		pop	bx
		test	al, 02H		 		;IDE 0 disabled ?
		jz	short ChkChannel1

		and	bh, NOT 40H			;IRQ 14 not available

ChkChannel1:
		test	al, 01H				;IDE 1 disabled ?
		jz	short StpcIDE_Exit

		and	bh, NOT 80H			;IRQ 15 not available

StpcIDE_Exit:
endif;	COBRA_IDE1
;R89 - end

ifdef	PIIX_IDE

		push	bx

		mov	si, offset Piix_IdeTbl	;point to IDE table

	Chk_NxtPiix:

		mov	cx, word ptr cs:[si]	;get device ID
		cmp	cx, -1			;last of table
		je	Piix_NotFound

		push	si
		mov     dx, 8086H                ;Intel vendor ID
		xor     si, si                   ;first device
		mov     ax, 0b102H               ;find PCI device func. call
		int     1AH
		pop	si
		jnc     Yes_Piix3

		add	si, 2			;next device
		jmp	Chk_NxtPiix

	Piix_NotFound:

		pop	bx
		jmp	Piix3_Exit

	Yes_Piix3:

		mov	ch, bl			;device & function number
		mov	cl, 40H			;register for IDE
		F000_CALL AGet_CfgSpace_Dword

		pop	bx
		test	ah, 80H			;1st channel IDE enabled?
;R93A - start
 ifdef	MASK_IRQ14_IF_IDE1_DISABLE
		jnz	short IDE1_Enabled

	;mask 8259 for IRQ 14
		pushf
		cli
		in	al, 0A1H		;B8259+1
		NEWIODELAY
		or	al, 40H			;mask IRQ 14
		out	0A1H, al
		popf
		jmp	short Check_2nd
 else;	MASK_IRQ14_IF_IDE1_DISABLE
;R93A - end

		jz	Check_2nd
;R93A - start
 endif;	MASK_IRQ14_IF_IDE1_DISABLE

	IDE1_Enabled:
;R93A - end
		and	bh, NOT 40H		;IRQ 14 is not available

	Check_2nd:

		shr	eax, 16			;for 2nd IDE
		test	ah, 80H			;1st channel IDE enabled?
;R93 - start
 ifdef	MASK_IRQ15_IF_IDE2_DISABLE
		jnz	short IDE2_Enabled

	;mask 8259 for IRQ 15
		pushf
		cli
		in	al, 0A1H		;B8259+1
		NEWIODELAY
		or	al, 80H
		out	0A1H, al
		popf
		jmp	short Piix3_Exit
 else;	MASK_IRQ15_IF_IDE2_DISABLE
;R93 - end
		jz	short Piix3_Exit
;R93 - start
 endif;	MASK_IRQ15_IF_IDE2_DISABLE

	IDE2_Enabled:
;R93 - end
		and	bh, NOT 80H		;IRQ 15 is not available

	Piix3_Exit:

endif	;PIIX_IDE

;R75 - start
ifdef	CYRIX_IDE
CYRIX_IDE_DEVICE	=	CYRIX_IDE

	;Mask IRQ 14 & 15 if CYRIX IDE ports are not disabled
		push	bx

		xor	bh, bh				;bus 0
		mov	cx,(CYRIX_IDE_DEVICE SHL 8)+05BH;IDE control register
		F000_CALL AGet_CfgSpace_Byte

		pop	bx
		test	al, 00001000b			;channel 0 enabled ?
		jz	short ChkChannel1

		and	bh, NOT 40H			;IRQ 14 not available

	ChkChannel1:
		test	al, 00010000b			;channel 1 enabled ?
		jz	short Cyrix_Ide_Exit

		and	bh, NOT 80H			;IRQ 15 not available

	Cyrix_Ide_Exit:
endif;	CYRIX_IDE
;R75 - end

		ret

Check_Piix_Ide	endp

ifdef	PIIX_IDE
Piix_IdeTbl:
		dw	7010H		;IDE of PIIX3
		dw	7111H		;IDE of PIIX4
		dw	2411H		;IDE of ICH	;R76
		dw	2421H		;IDE of ICH0	;R97
		dw	-1		;end of table
endif	;PIIX_IDE

;-----------------------------------------------------------------------
;Input : DX - IRQ mapping
;Output: DX - IRQ mapping
;-----------------------------------------------------------------------
Check_Ide_Exist	proc	near

;check if first channel IDE devices connected

		push	bx
		mov     bx, dx			;save IRQ map

		call	Check_Piix_Ide

		mov	dx, 1f4h			;first channel
		call	Check_Port_Exist
		jne	No_Irq14
		and	bh, 10111111b		;mask IRQ 14
No_Irq14:

;check if second channel IDE devices connected

		mov	dl, 74h			;second channel
		call	Check_Port_Exist
		jne	No_Irq15
		and	bh, 01111111b		;mask IRQ 15
No_Irq15:
		mov	dx, bx			;restore IRQ map

	;Set available IRQs back for PnP card
		mov	word ptr ds:IRQ_MAP, bx

		pop	bx
		ret

Check_Ide_Exist	endp

endif	;PNP_BIOS

;[]==============================================================[]
;Input  : dx - port to check
;Output : zero set - port existed
;[]==============================================================[]
Check_Port_Exist proc	near

		mov	al, 0aah
		mov	ah, al
		out	dx, al
		NEWIODELAY
		not	al
		in	al, dx
		cmp	ah, al
		ret

Check_Port_Exist endp

;[]==============================================================[]
;Get_IrqRouting:
;	Get IRQ routing information
;Saves: all except AL
;Input : AL - interrupt pin to assign 1-INT A , 2-INT B , 3-INT C
;	      4-INT D
;	 CL - slot index 0-slot 1 , 1-slot 2, 2-slot 3 , 3-slot 4
;Output: AL - PCI INT Number
;
;[]==============================================================[]
Get_IrqRouting	proc	near
		push	si
		push	cx
		push	ax

		push	ds
		push	SEG IrqRout_Table		;data segment
		pop	ds

		xor	ch, ch
		shl	cl, 2			;which PCI slot ?
		mov	si, cx
		add	si, offset IrqRout_Table;IRQ routing table
		mov	ecx, ds:[si]		;get routed IRQ
	@@:
		dec	al
		jz	@F
		shr	ecx, 8
		jmp	@B
	@@:
		pop	ds

		pop	ax
		mov	al, cl	     		;new IRQ routed
		pop	cx
		pop	si

		ret

Get_IrqRouting	endp

;[]-------------------------------------------------------------------------[]
;Input  : AL - interrupt pin , 1-INTA , 2-INTB , 3-INTC , 4-INTD
;	  CH - device No.
;Output : AL - interrupt pin , 1-INTA , 2-INTB , 3-INTC , 4-INTD
;Note : Devices on P2P bus the IRQ routing should following table to implement
;	IRQs.
;	Device No.  	INT on Device 	INT on Connector
;	-----------	--------------	----------------
;	0, 4, 8, 12    	INTA 		INTA
;	16, 20, 24, 28 	INTB		INTB
;			INTC		INTC
;			INTD		INTD
;	------------------------------------------------
;	1, 5, 9, 13    	INTA 		INTB
;	17, 21, 25, 29 	INTB		INTC
;			INTC		INTD
;			INTD		INTA
;	------------------------------------------------
;	2, 6, 10, 14   	INTA 		INTC
;	18, 22, 26, 30 	INTB		INTD
;			INTC		INTA
;			INTD		INTB
;	------------------------------------------------
;	3, 7, 11, 15   	INTA 		INTD
;	19, 23, 27, 31 	INTB		INTA
;			INTC		INTB
;			INTD		INTC
;[]-------------------------------------------------------------------------[]
Get_P2P_IrqRoute 	proc	near

	ifdef	VT597_PP	;For VIA VP3 Chip

		pushad
		xor	bh, bh			;bus number
		mov	cx, VT597 + 8		;chip revision ID
		F000_CALL AGet_CfgSpace_Byte	;read VP3 revision
		cmp	al, 02h			;
		popad
		jae	No_Special_Routing

		cmp	bh, 1
		jne	No_Special_Routing
		ret

	No_Special_Routing:

	endif	;VT597_PP	;For VIA VP3 Chip

		push	cx

		shr	ch, 3
		and	ch, 03H
		add	al, ch		;set new INT pin
		cmp	al, 4
		jbe	@F
		sub	al, 4
	@@:
		pop	cx
		ret

Get_P2P_IrqRoute 	endp

;[]==============================================================[]
;[]==============================================================[]
Assign_IRQ_For_PCI_IDE	Proc	Near

;Most of chipset support on-chip IDE , so don't assign IRQ 14 & 15 for
;add-in PCI/IDE card if on-chip IDE is enabled.
		call	X_Ct_OnChip_IDE_Chk    		;on-chip IDE enable
		jnc	OnChipIde_Enabled		;yes, enabled

ifndef	NO_PCI_IDE_CARD
	;First check if PCI/IDE plugged
	;Don't assign IRQ 14 & 15 if PCI/IDE is connected to ISA

		mov	si, offset PCI_IDE_IRQ
		call	X_GetItem_Value
		cmp	al, 1				;ISA IRQ for PCI ?
		je	Last_Slot_IDE

		mov	bx, SEG PCI_SLOT_CFG		;setup item in F-seg
		mov	ds, bx
		mov	bx, offset PCI_SLOT_CFG
		mov	byte ptr CURRENT_SLOT[bp], 0	;init current slot
Try_Slot_IDE:
		mov	ch, ds:[bx]
		cmp	ch, 0ffh			;last PCI slot ?
		je	Last_Slot_IDE
		shl	ch, 3				;device no. at upper 5 bits

	ifdef	BUILD_IN_IDE_IDSEL
		call	See_If_Bus_0
		jne	Not_Built_In_IDE
		cmp	ch, BUILD_IN_IDE_IDSEL		;built in IDE ?
		je	Chk_Next_Slot_1			;yse, skip to next device No.
	Not_Built_In_IDE:
	endif	;BUILD_IN_IDE_IDSEL

Try_Slot_IDE_1:

		call	X_Get_Vendor_ID      		;check if valid PCI device ?
		jc	Chk_Next_Slot			;No PCI device

	ifdef SPECIAL_PCI_IDE_PRG
		F000_CALL CT_PRI_PCI_IDE_PRG
	endif; SPECIAL_PCI_IDE_PRG

		call	Check_PciIde  			;Is PCI/IDE card ?
		jnc	Chk_Next_Slot			;No, do nothing

;Don't assign IRQ 14 & 15 for PCI/IDE if it don't need IRQ , that is the
;content of 3dH is zero
		mov	cl, 3dH				;interrupt pin
		call	X_Get_CfgSpace_Byte
		or	al, al				;need IRQ ?

		jz	Chk_Next_Slot

		mov	cl, CURRENT_SLOT[bp]		;current slot index
		call	Assign_Pci_IDE			;assign IRQ 14 & 15 for PCI
		jmp	Last_Slot_IDE

Chk_Next_Slot:
		call	X_If_MultiFunc_Dev
		jnc	Try_Slot_IDE_1			;It is a Multi-Func card

Chk_Next_Slot_1:
		inc	bx				;next slot address
		inc	byte ptr CURRENT_SLOT[bp]	;next slot
		jmp	Try_Slot_IDE
Last_Slot_IDE:
endif	;NO_PCI_IDE_CARD

OnChipIde_Enabled:

		ret

Assign_IRQ_For_PCI_IDE	Endp

;[]==============================================================[]
;Check_PciIde:
;	Program PCI device with available IRQ
;Saves: all
;Input :
;	 CH - PCI device No.
;	 PCIIRQ - available 4 IRQs for PCI
;Output: carry set - PCI IDE found
;	 not carry - No PCI IDE found
;[]==============================================================[]
Check_PciIde 	proc	near
		pushad

		push	cx
		mov	cl, 0Ah			;Class Code + Revision ID
		call	X_Get_CfgSpace_DWord
		pop	cx

	;Fix dirty IDE chip , for example the WINBOND PCI/IDE
	;the vendor & device ID are OK , but class code is zero

		or	ax, ax			;invalid class code
		jnz	Valid_Class

		call	X_Get_Vendor_ID
		cmp	ax, 1c1cH		;WINBOND PCI/IDE ?
		je	PciIde_Exist

	Valid_Class:

		cmp	ax, CLASS_IDE		;PCI IDE ?
		jne	Not_PciIde

;R71 - start
		call 	SearchTruePCIIde
		jc	Not_PciIde
;R71 - end

	PciIde_Exist:

		stc
		jmp	PciIde_Exit

	Not_PciIde:

		clc

	PciIde_Exit:

		popad
		ret
Check_PciIde 	endp

;[]==============================================================[]
;Assign_Pci_IDE:
;	Assign IRQ 14 & IRQ 15 for PCI/IDE
;Saves: all
;Input : CH - slot device number
;	 CURRENT_SLOT[bp] - current slot number
;Output: None
;[]==============================================================[]
Assign_Pci_IDE	proc	near
ifndef	NO_PCI_IDE_CARD

		pusha

		mov	si, offset First_IDE_INT
		call	X_GetItem_Value
		inc	al

		mov	cl, CURRENT_SLOT[bp]	;slot index
		call	Get_IrqRouting		;input : AL - interrupt pin
						;output: AL - interrupt pin routed
		mov	byte ptr PCIIRQ[bp+1], al;IRQ 14 used
		mov	ah, 14			;assign IRQ 14 for IDE
	ifdef	ALWAYS_EDGE_FOR_PCI_IDE
		xor	ch, ch			;edge trigger
	else;	ALWAYS_EDGE_FOR_PCI_IDE
		call	Get_Irq_Trigger
	endif;	ALWAYS_EDGE_FOR_PCI_IDE

	ifdef	LEVEL_TO_EDGE_FOR_PCI_IDE
		mov	ch, 80H			;bit 0 - level
						;    7 - convert
	endif;	LEVEL_TO_EDGE_FOR_PCI_IDE

		call	X_Ct_Set_PciIrq

	ifndef	NO_PCI_IDE_2ND_CONTROL
		mov	si, offset Second_IDE_channel
		call	X_GetItem_Value
		or	al, al
		jz	IDE_Assign_Ok
	endif;	NO_PCI_IDE_2ND_CONTROL

		mov	si, offset Second_IDE_INT
		call	X_GetItem_Value
		inc	al

		mov	cl, CURRENT_SLOT[bp]	;slot index
		call	Get_IrqRouting 		;input : AL - interrupt pin
						;output: AL - interrupt pin routed
		mov	byte ptr PCIIRQ[bp+3], al;IRQ 14 used

	ifdef	Special_IRQ_For_Second_IDE
		mov	ah, Special_IRQ_For_Second_IDE ;Special IRQ for IDE
	else	;Special_IRQ_For_Second_IDE
		mov	ah, 15			;assign IRQ 15 for IDE
	endif	;Special_IRQ_For_Second_IDE

	ifdef	ALWAYS_EDGE_FOR_PCI_IDE
		xor	ch, ch			;edge trigger
	else;	ALWAYS_EDGE_FOR_PCI_IDE
		call	Get_Irq_Trigger
	endif;	ALWAYS_EDGE_FOR_PCI_IDE

	ifdef	LEVEL_TO_EDGE_FOR_PCI_IDE
		mov	ch, 80H			;bit 0 - level
						;    7 - convert
	endif;	LEVEL_TO_EDGE_FOR_PCI_IDE
		call	X_Ct_Set_PciIrq

IDE_Assign_Ok:
		mov	byte ptr PCI_IDE_FOUND[bp], IDE_EXIST	;mark found
		popa

endif	;NO_PCI_IDE_CARD

		ret

Assign_Pci_IDE	endp

;R05 - starts
Open_IDE_2nd_Channel	proc	near

ifdef	SUPPORT_PCISLOT_IDE

		pushad
		push	ds

		mov	ax, cs
		mov	ds, ax

		mov	si, offset Second_IDE_channel
		call	X_GetItem_Value
		mov	bl, al			;save flag

		mov	ch, START_PCI_DEV[BP] 	;start slot, func

Scan_2nd_Channel:

		push	cx

		call	Check_PciIde   		;Is PCI/IDE card ?
		jnc	Check_Next_IDE		;No,do nothing

		xor	cl, cl			;Vendor ID
		call	X_Get_CfgSpace_DWord
		mov	edx, eax
		mov	si, offset PCI_IDE_TBL
	@@:
		lodsd
		cmp	ax, 0FFFFh		;end
		je	Check_Next_IDE		;yes

		cmp	eax, edx
		je	@F

		add	si, 2
		jmp	@B
	@@:
		mov	byte ptr PCI_IDE_EXIST[bp], 03
		mov	al, bl
		or	al, 0FEh
		and	PCI_IDE_EXIST[bp], al

		lodsw
		call	ax

	ifdef SPECIAL_PCI_IDE_PRG
		F000_call	CT_SEC_PCI_IDE_PRG
	endif ;SPECIAL_PCI_IDE_PRG

	Check_Next_IDE:

		pop	cx

		call	X_Get_Next_Device		;CH return next device to do
		jnc	Scan_2nd_Channel

		pop	ds
		popad

endif;	SUPPORT_PCISLOT_IDE

		ret

Open_IDE_2nd_Channel	Endp

ifdef	SUPPORT_PCISLOT_IDE
PCI_IDE_TBL:
		dw	01095H			;CMD vendor ID
		dw	00640h			;640 device ID
		dw	offset CMD_IDE_FUNC

		dw	01060H			;UMC vendor ID
		dw	00640h			;8673 device ID
		dw	offset UMC_IDE_FUNC

		dw	0100Bh			;NS vendor ID
		dw	0D001h			;87410 device ID
		dw	offset NS_IDE_FUNC

		dw	01C1CH			;Winbond vendor ID
		dw	00001h			;device ID
		dw	offset WINBOND_IDE_FUNC

		dw	010ADH			;new Winbond vendor ID
		dw	00001h			;device ID
		dw	offset WINBOND_IDE_FUNC

		dw	1098H			;QD8580 vendor ID
		dw	0002H			;QD8580 device ID
		dw	offset QD8580_Ide_Func

		dw	1106H			;VIA      vendor ID
		dw	0561H			;VT83C561 device ID
		dw	offset VT83C561_Ide_Func

		dw	0FFFFH			;end

;Input : BL - 00 = Disable 2nd channel
;	 BL - 01 = Enable 2nd channel
CMD_IDE_FUNC:
		mov	ah,00h			;Disable 2nd Channel
		or	bl,bl
		jz	@F

		mov	ah,08h			;Enable 2nd Channel
	@@:
		mov	cl,51H
		call	X_Get_CfgSpace_Byte
		and	al,not 08h
		or	al,ah
		call	X_Set_CfgSpace_Byte

		ret

		Public	UMC_IDE_FUNC
UMC_IDE_FUNC:
;Input : BL - 00 = Disable 2nd channel
;	 BL - 01 = Enable 2nd channel
		xor	ah, ah			;Disable 2nd Channel
		or	bl, bl
		jz	@F

		mov	ah, 40h			;Enable 2nd Channel
	@@:
		mov	cl, 0B0h
		F000_Call Open_8673
		and	al, 10111111b
		or	al, ah
		F000_Call Set_8673

		ret

;Input : BL - 00 = Disable 2nd channel
;	 BL - 01 = Enable 2nd channel
NS_IDE_FUNC:
		xor	ah, ah			;Disable 2nd Channel
		or	bl, bl
		jz	@F
		mov	ah, 08h			;Enable 2nd Channel
	@@:
		mov	cl, 47H
		call	X_Get_CfgSpace_Byte
		and	al, 11110111b
		or	al, ah
		call	X_Set_CfgSpace_Byte

		ret

;Input : BL - 00 = Disable 2nd channel
;	 BL - 01 = Enable 2nd channel
WINBOND_IDE_FUNC:
		xor	ah, ah			;Disable 2nd Channel
		or	bl,bl
		jz	@F
		mov	ah, 01h			;Enable 2nd Channel
	@@:
		mov	cl, 50H
		call	X_Get_CfgSpace_Byte
		and	al, 11111110b
		or	al, ah
		call	X_Set_CfgSpace_Byte

		ret

;Input : BL - 00 = Disable 2nd channel
;	 BL - 01 = Enable 2nd channel
QD8580_Ide_Func:
		xor	ah, ah			;Disable 2nd Channel
		or	bl, bl
		jz	@F
		mov	ah, 08h			;Enable 2nd Channel
	@@:
		mov	cl, 43H
		call	X_Get_CfgSpace_Byte
		and	al, 11110111b
		or	al, ah
		call	X_Set_CfgSpace_Byte

;Disable prefetch for QD8580 PCI/IDE
		mov	cl, 44H
		call	X_Get_CfgSpace_Byte
		and	al, 0f5H		;clear bit 3 & bit 1 to disable
		call	X_Set_CfgSpace_Byte
		ret

;Input : BL - 00 = Disable 2nd channel
;	 BL - 01 = Enable 2nd channel
VT83C561_Ide_Func:
		mov	cl, 40H
		call	X_Get_CfgSpace_Byte
		and	al, 0FEh
		or	al, bl
		call	X_Set_CfgSpace_Byte
		ret
endif;	SUPPORT_PCISLOT_IDE
;R05 - ends

;[]================================================================[]
;Function : Disable PCI/IDE on slot if onboard IDE is existed and
;	    enabled.
;Input  : none
;Output : none
;[]================================================================[]
Disable_Slot_IDE	proc	near
;Most of chipset support on-chip IDE , so disable I/O in command register for
;add-in PCI/IDE card if on-chip IDE is enabled.
		call	X_Ct_OnChip_IDE_Chk		;on-chip IDE enable
		jc	OnChipIde_Existed		;no, disabled

		mov	ax, SEG PCI_SLOT_CFG		;point DS to segment F000H
		mov	ds, ax
		mov	bx, offset PCI_SLOT_CFG

		mov	byte ptr CURRENT_BUS_NO[bp], 0	;from bus 0
		mov	byte ptr CURRENT_SLOT[bp], 0	;init current slot
CTry_Slot_IDE:
		mov	ch, ds:[bx]

ifdef VT586_USB
		cmp	ch, VT586_USB_ID
		je	Chk_Next_Slot_Ide
endif ;VT586_USB

		cmp	ch, 0ffh			;last PCI slot ?
		je	CLast_Slot_IDE
		shl	ch, 3				;device no. at upper 5 bits

CTry_Slot_IDE_1:

		call	Check_PciIde			;Is PCI/IDE card ?
		jnc	Chk_Next_Slot_Ide		;No, do nothing

		mov	cl, 4				;command register
		xor	al, al				;disable I/O & Mem.
		call	X_Set_CfgSpace_Byte
		jmp	CLast_Slot_IDE

Chk_Next_Slot_Ide:
		call	X_If_MultiFunc_Dev
		jnc	CTry_Slot_IDE_1			;It is a Multi-Func card

		inc	bx				;next slot address
		inc	byte ptr CURRENT_SLOT[bp]	;next slot
		jmp	CTry_Slot_IDE
CLast_Slot_IDE:
OnChipIde_Existed:
		ret
Disable_Slot_IDE	endp

;[]==============================================================[]
;[]==============================================================[]
		Public	Assign_IRQ_For_All_PCI
Assign_IRQ_For_All_PCI	Proc	Near

	;--------------------------------------------
	;Share IRQ for PCI device if lack of IRQs
	;--------------------------------------------

		mov	si, 4				;start from 3rd IRQ
		xor	bx, bx

	Find_Mark_AA:

		cmp	byte ptr PCIIRQ[bp+si], 0AAH	;last IRQ ?
		je	Set_Last_Irq

		mov	bl, byte ptr PCIIRQ[bp+si]	;save last IRQ
		inc	si
		inc	si
		jmp	Find_Mark_AA

	Set_Last_Irq:

		mov	PCIIRQ[bp+si], bx		;save last IRQ
		inc	si
		inc	si
		cmp	si, 18				;max. 8 IRQs to use
		jbe	Set_Last_Irq
		mov	byte ptr PCIIRQ[bp+si], 0AAH	;save last IRQ mark

	;----------------------------------------------------------------

		push	ds

		mov	ax, SEG IRQ_REQ_BUF
		mov	ds, ax
		mov	di, offset IRQ_REQ_BUF_PTR
		mov	di, ds:[di]

	Assign_Next_IRQ_Req:

		sub	di, SIZE_IRQ_REQ_STRUC
		cmp	di, offset IRQ_REQ_BUF
		jb	End_All_IRQs

		mov	al, ds:[di].IrqReqBusNum
		mov	CURRENT_BUS_NO[bp], al
		mov	al, ds:[di].HostSlot
		mov	CURRENT_SLOT[bp], al
		mov	ch, ds:[di].IrqReqDevNum
		mov	al, ds:[di].IntPin
   		call	Assign_PciIrq

		jmp	Assign_Next_IRQ_Req

	End_All_IRQs:

		pop	ds

		ret

Assign_IRQ_For_All_PCI	Endp

;R91 - starts
ifdef	PciLanROM_Control

;R91A public	LAN_COMMAND_WORD
;R91A LAN_COMMAND_WORD	LABEL	WORD
;R91A 		dw	?

Prg_Onboard_PCI_Lan	PROC	NEAR

		pushad

		mov	byte ptr CURRENT_BUS_NO[bp], 0
		mov	ch, (Onboard_PCI_LAN) shl 3	;device/function number
		mov	cl, 04h				;register = 4
		call	X_Get_CfgSpace_Word

;R91A 		mov	cs:[LAN_COMMAND_WORD], ax	;save value
		mov	POST_Stack_Temp_Word[bp],ax	;R91A restore value in AX

		mov	si, offset PciLanROM_Item
		call	X_GetItem_Value
		or	al, al
		jz	@F

		mov	ch, (Onboard_PCI_LAN) shl 3	;device/function number
		mov	cl, 04h				;register = 4 (command)
		xor	ax, ax				;value = 0 (disabled)
		call	X_Set_CfgSpace_Word
	@@:
		popad
		ret

Prg_Onboard_PCI_Lan	ENDP
endif	;PciLanROM_Control
;R91 - ends

;[]==============================================================[]
;[]==============================================================[]
		Public	Prg_Onboard_ScsiChip
Prg_Onboard_ScsiChip	Proc	Near

ifdef	ONBOARD_NCR_SETUPABLE

	;Read setup value to decide to initial
	;built-in ROM for NCR or not.

		mov	si, offset Scsi_Item		;read setup value
		call	X_GetItem_Value
		or	al, al				;onboard SCSI enable?
		jnz	Ncr_Enabled			;yes , check this slot

		cmp 	ch, (ONBOARD_NCR_SLOT SHL 3)
		mov	cl, 04H
		xor	al, al
		call	X_Set_CfgSpace_Byte
		mov	byte ptr NCR_810_FOUND[bp], 0	;R03

	Ncr_Enabled:

endif	;ONBOARD_NCR_SETUPABLE

ifdef	ONBOARD_ScsiChip

		mov	byte ptr CURRENT_BUS_NO[bp], 0

	;Disable I/O and memory access for onboard device due to setup

		mov	si, offset Onboard_Scsi_Item
		call	X_GetItem_Value
		or	al, al			;disabled ?
		jnz	@F			;NZ = Enable

 		mov	ch, (ONBOARD_ScsiChip_SLOT SHL 3)
;R66 - starts
		mov	cl, 0Bh			;major class code
		call	X_Get_CfgSpace_Byte
		cmp	al, 01h	   		;Storage device ?
		jne	@F			;no !
;R66 - ends
		mov	cl, 04H
		xor	ax, ax
		call	X_Set_CfgSpace_Byte

		mov	cl, 0Eh			;read header type
		call	X_Get_CfgSpace_Byte	;
		test	al, 80H			;multi-function support?
		jz	NotMultiFunc

	;disable second function device

		inc	ch			;next function
		mov	cl, 04H
		xor	al, al
		call	X_Set_CfgSpace_Byte	;

	NotMultiFunc:
	@@:
endif	;ONBOARD_ScsiChip

		ret

Prg_Onboard_ScsiChip	Endp

;----------------------------------------------
;Output : CH - IRQ trigger
;----------------------------------------------
Get_Irq_Trigger	proc	near

	ifndef	ALWAYS_LEVEL_PCI_IRQ

		push	si
		push	ax
		mov	si, offset PCI_IRQ_Method
		call	X_GetItem_Value
		mov	ch, al
		pop	ax
		pop	si

	else;	ALWAYS_LEVEL_PCI_IRQ

		mov	ch, 1	;level trigger

	endif;	ALWAYS_LEVEL_PCI_IRQ

		ret

Get_Irq_Trigger	endp

;R20 - start

ifdef	PCI_IRQ_SELECTABLE
;Function : Check if current INT# already routed.
;Input    : al - INT#
;Output   : SI - buffer location of IRQ table found
;	    carry set   - No INT# match
;	    carry clear - INT# already used
Chk_MatchINT	proc	near
		xor	si,si

NextMatchINT:
		cmp	byte ptr PCIIRQ[bp+si],0AAH	;last IRQ ?
		je	short NoIntPin_Assigned

		cmp	byte ptr PCIIRQ[bp+si+1],al	;INT# be used ?
		clc
		je	short IntPin_Assigned

		inc	si
		inc	si				;next IRQ table
		jmp	short NextMatchINT

NoIntPin_Assigned:
		stc
IntPin_Assigned:
		ret
Chk_MatchINT	endp

  ;Table for CMOS item to get IRQ user setting for each PCI slots
  FixedIrqItem:
		dw	offset DGROUP:Slot1_IRQ	;CMOS setup for slot 1
		dw	offset DGROUP:Slot2_IRQ	;CMOS setup for slot 2
  ifndef	TWO_PCI_SLOT_ONLY
		dw	offset DGROUP:Slot3_IRQ	;CMOS setup for slot 3
   ifndef	THREE_PCI_SLOT_ONLY
		dw	offset DGROUP:Slot4_IRQ	;CMOS setup for slot 4
   endif;	THREE_PCI_SLOT_ONLY
  endif;	TWO_PCI_SLOT_ONLY
;R102A;R102 - starts
;R102A  IF	SLOT5_EXIST
;R102A		dw	offset DGROUP:Slot5_IRQ	;CMOS setup for slot 5
;R102A  ENDIF	;SLOT5_EXIST
;R102A  IF	SLOT6_EXIST
;R102A		dw	offset DGROUP:Slot6_IRQ	;CMOS setup for slot 6
;R102A  ENDIF	;SLOT6_EXIST
;R102A  IF	SLOT7_EXIST
;R102A		dw	offset DGROUP:Slot7_IRQ	;CMOS setup for slot 7
;R102A  ENDIF	;SLOT7_EXIST
;R102A  IF	SLOT8_EXIST
;R102A		dw	offset DGROUP:Slot8_IRQ	;CMOS setup for slot 8
;R102A  ENDIF	;SLOT8_EXIST
;R102A  IF	SLOT9_EXIST
;R102A		dw	offset DGROUP:Slot9_IRQ	;CMOS setup for slot 9
;R102A  ENDIF	;SLOT9_EXIST
;R102A;R102 - ends
		dw	-1			;end of table

;Table for convert CMOS setting into real IRQ number
IrqConvertTbl	db	3	;0001b(CMOS value), 0000b = "auto"
		db	4	;0010b
		db	5	;0011b
		db	7	;0100b
		db	9	;0101b
		db	10	;0110b
		db	11	;0111b
		db	12	;1000b
		db 	14	;1001b
		db	15	;1010b

;Function : Build buffer for recording reserved IRQs for each PCI slots
;Input    : none
;Output   : G_RAM:FIXED_PCI_IRQ - modified
;	    G_RAM:FIXED_IRQ_MAP
		public	fBuild_FixedIrqTbl
fBuild_FixedIrqTbl	proc	far

		push	ds
		push	es
		pusha

		mov	ax, SEG DGROUP		;point to segment F000H
		mov	ds, ax

		mov	ax,G_RAM		;buffer segment address
		mov	es,ax
		ASSUME	es:G_RAM

		call	BuildSlotIntInfo	;built INT# usage info.

		mov	bx,offset FixedIrqItem	;point to CMOS item
		mov	di,offset FIXED_PCI_IRQ	;point to buffer address

ChkSlotIrqItem:

		mov	si,cs:[bx]		;get item location
		cmp	si, -1 			;last item
		je	short ExitSlotIrq

		test	byte ptr es:[di],1111b	;INT# required ?
		jz	short NextSlotIrqSel

		call	X_GetItem_Value	  	;get CMOS value

		or	al,al			;"auto" ?
		jz	short NextSlotIrqSel

		xor	ah,ah
		dec	al
		mov	si,offset IrqConvertTbl	;CMOS value to real IRQ No.
		add	si,ax
		mov	ah,cs:[si]

		mov	cl,ah
		mov	si,1
		shl	si,cl			;shift to right bit position
		or	es:FIXED_IRQ_MAP,si	;mark reserved IRQ bits

		shl	ah,4			;IRQ No. in bit7-4
		or	es:[di],ah		;record IRQ

NextSlotIrqSel:
		inc	di			;next slot IRQ buffer
		inc	bx
		inc	bx			;next CMOS item
		add	si,4			;next slot's routing table
		jmp	short ChkSlotIrqItem
ExitSlotIrq:

		not	word ptr es:FIXED_IRQ_MAP;inverse occupied IRQ bits
		popa
		pop	es
		pop	ds
		ret
fBuild_FixedIrqTbl	endp

;Function : Fill INT# usage for each slot if the device on the slot is single
;	    function device
;Input    : DS - 0F000H
;	    ES - G_RAM
;Output   : G_RAM:FIXED_PCI_IRQ table INT# information are modified
BuildSlotIntInfo	proc	near

		mov	byte ptr CURRENT_BUS_NO[bp],0	;bus 0

		mov	si,offset IrqRout_1stSlot;point to routing
						 ;table for 1st slot
		mov	bx,offset SlotId_1stSlot
		mov	di,offset FIXED_PCI_IRQ

		mov	cx,4			;total four slots support

NextSlotIntInfo:
		push	cx
		mov	ch,ds:[bx]	       	;get device slot info
		shl	ch,3
		call	fProc_Get_Vendor_ID
		jc	short NoDeviceFound

		mov	cl,3dh			;INT#
		call	fProc_Get_CfgSpace_Byte
		or	al,al			;INT# required ?
		jz	short NoDeviceFound
		cmp	al,4
		ja	short NoDeviceFound
		xor	ah,ah
		push	si
		dec	al
		add	si,ax
		mov	al,[si]			;get INT #
		or	byte ptr es:[di],al
		pop	si
NoDeviceFound:
		inc	di
		inc	bx			;next slot ID
		add	si,4			;next slot routing
		pop	cx
		loop	short NextSlotIntInfo

		ret
BuildSlotIntInfo	endp

;Function : Check if current IRQ No. was occupied by PCI slot
;Input    : DS - G_RAM
;	  : CL - IRQ Number
;
Chk_FixedPciIrq	proc	near

		pusha

		mov	bl,cl			;save IRQ no. in BL
		mov	di,offset FIXED_PCI_IRQ
		mov	cx,4			;Max. 4 IRQs reserved

NextFixedIrq:
		mov	al,byte ptr ds:[di] 	;get reserved IRQ
		shr	al, 4			;get IRQ No.

		cmp	al,bl			;IRQ match ?
		jne	short NoFixedIrqFound

		mov	ah,byte ptr ds:[di]	;get INT No.
		and	ah,1111b
		mov	byte ptr PCIIRQ[bp+si+1],ah;mark INT# occupied
		jmp	short ExitFixedIrq

NoFixedIrqFound:
		inc	di			;check next reserved IRQ

		loop	short NextFixedIrq

ExitFixedIrq:
		popa
		ret
Chk_FixedPciIrq	endp
endif;	PCI_IRQ_SELECTABLE

;R20 - end

;R64 - starts
ifdef	ACPI_SUPPORT
   IFDEF	VT586_ACPI
	ifndef	No_ACPI_IRQ_Auto_Assign			;R64A
;[]==============================================================[]
;Assign_ACPIIrq:
;	Assign IRQ for ACPI Controller
;Saves: all
;Input : none
;Output: None
;Note  : This routine will be invoked after all PCI IRQ devices
;	 are assigned properly. It scan available IRQ first,
;	 If no available IRQ, ACPI will share IRQ with other PCI
;	 device
;[]==============================================================[]
Assign_ACPIIrq	proc	near

		pusha

;R64B - start
	ifdef	ACPI_IRQ_Selectable
	ifdef	ACPI_IRQ_Auto_Assign_Selectable
		mov	si, offset Assign_ACPI_IRQ_Item
 		call	X_GetItem_Value
		cmp	al,1			;if ACPI IRQ not set Auto, leave!
		jne	short ANo_Valid_Irq	;AL=0/1/2/.. => NA/Auto/IRQxx/..
   	endif;	ACPI_IRQ_Auto_Assign_Selectable
	endif;	ACPI_IRQ_Selectable
;R64B - end

 		mov	si, offset ACPI_option_Item
 		call	X_GetItem_Value			;CMOS setting
		or	al,al				;ACPI enabled ?
		jnz	short ANo_Valid_Irq

	;scan available IRQ for ACPI controller
		xor	si, si
ACheck_Next_Irq:
		test	byte ptr PCIIRQ[bp+si], 0fh	;valid IRQ No.
		jz	ANo_Valid_Irq			;If have any available IRQ ?

		test	byte ptr PCIIRQ[bp+si+1], 0FFH	;IRQ assign flag
							;not assigned ?
		jz	short Airq_Available
ANext_Valid_Irq:
		add	si, 2				;next available IRQ
		cmp	byte ptr PCIIRQ[bp+si], 0AAH
		jne	short ACheck_Next_Irq

		sub	si, 2				;share IRQ
Airq_Available:

		mov	al, byte ptr PCIIRQ[bp+si]	;get IRQ No.

	ifdef	PNP_BIOS
		push	ax
		mov	cl, al
		mov	ax, 1
		shl	ax, cl
		or	word ptr PCI_IRQ_ASSIGNED[bp], ax
		pop	ax
	endif	;PNP_BIOS

	     	extrn	Ct_SetAcpiIrq:far		;AL = IRQ number
		call	Ct_SetAcpiIrq			;program chipset reg.


ANo_Valid_Irq:

		popa
		ret

Assign_ACPIIrq	endp
	endif;	No_ACPI_IRQ_Auto_Assign			;R64A
   ENDIF;	VT586_ACPI
endif;	ACPI_SUPPORT
;R64 - ends

;[]==============================================================[]
;Assign_PciIrq:
;	Program PCI device with available IRQ
;Saves: all
;Input : AL - interrupt number to assign 1-INT 1 , 2-INT 2 , 3-INT 3
;	      4-INT 4 ....
;	 CH - PCI device No.
;	 PCIIRQ - available 4 IRQs for PCI
;Output: None
;[]==============================================================[]
Assign_PciIrq	proc	near

		pusha

 ifdef	PCI_IRQ_SELECTABLE				;R20
	;Search if rounted INT# was used		;R20
		call	Chk_MatchINT			;R20
		jnc	short Get_It	;yes,used	;R20
 endif;	PCI_IRQ_SELECTABLE				;R20

		xor	si, si
Check_Next_Irq:
		test	byte ptr PCIIRQ[bp+si], 0fh	;valid IRQ No.
		jz	Next_Valid_Irq

		mov	ah, byte ptr PCIIRQ[bp+si+1]
		or	ah, ah				;not assigned ?
		je	Get_It

		cmp	ah, al				;alread assigned ?
		jne	Next_Valid_Irq
	Get_It:

;R100 - start
ifdef	VT686_AC97
	;Don't assign IRQ 9 for VIA/686 super south bridge built-in
	;audio controller. It is chipset's bug.
		cmp	byte ptr PCIIRQ[bp+si],09h	;IRQ is 9?
		jne	short NotIRQ9	      		;no

		cmp	ch, (VT686_AC97 SHR 8)		;on-chip audio ?
		jne	short NotIRQ9

		cmp	byte ptr PCIIRQ[bp+si+2], 09H	;last available IRQ ?
		jne	short Next_Valid_Irq		;find next available IRQ

		mov	dl, byte ptr PCIIRQ[bp+si-2]	;get previous IRQ
		mov	byte ptr PCIIRQ[bp+si],dl	;change IRQ number
		
	NotIRQ9:
endif;	VT686_AC97
;R100 - end

;R86 - start
ifdef	No_Assign_IRQ5_For_PCILAN
		push	eax			;save EAX & CX
		push	cx
		mov	cl,0Bh			;class code in offset 0Bh
		call	X_Get_CfgSpace_Byte	;get class code byte
		cmp	al,02h			;is PCI LAN ?
		pop	cx			;restore EAX & CX first
		pop	eax
		jne	short @f		;no, leave

		cmp	byte ptr PCIIRQ[bp+si],05h	;IRQ is 5?
		je	short Next_Valid_Irq		;yes, choose next IRQ

@@:
endif;	No_Assign_IRQ5_For_PCILAN
;R86 - end

		mov	byte ptr PCIIRQ[bp+si+1], al	;mark this IRQ assigned

		push	ax
		mov	al, byte ptr PCIIRQ[bp+si]	;get IRQ No.

		or	al, al				;IRQ 0 	    ?
		jnz	Not_Irq0			;No.
		mov	al, 0fh				;set IRQ 15
	Not_Irq0:

	ifdef	PNP_BIOS
		push	ax
		mov	cl, al
		mov	ax, 1
		shl	ax, cl
		or	word ptr PCI_IRQ_ASSIGNED[bp], ax
		pop	ax
	endif	;PNP_BIOS

		mov	cl, 3CH
		call	X_Set_CfgSpace_Byte
		pop	ax

		;now AL = INT number
		mov	ah, byte ptr PCIIRQ[bp+si]	;get IRQ No.
		mov	cl, CURRENT_SLOT[bp]		;slot index
		call	Get_Irq_Trigger
		call	Record_PCI_IRQ			;R12
		call	X_Ct_Set_PciIrq
		jmp	No_Valid_Irq		;finish assign

Next_Valid_Irq:
		add	si, 2				;next available IRQ
		cmp	byte ptr PCIIRQ[bp+si], 0AAH
		jne	Check_Next_Irq
No_Valid_Irq:

		popa
		ret

Assign_PciIrq	endp

;R12 - starts
Record_PCI_IRQ	Proc	Near

		pushad
		push	ds
		push	ax
		call	X_F000_Shadow_W
		pop	ax
		push	SEG PCI_IRQ_RECORD
		pop	ds
		mov	si, offset PCI_IRQ_RECORD
		mov	cl, ah
		mov	ax, 1
		shl	ax, cl
		or	word ptr ds:[si], ax

 		mov	ax, word ptr ds:[si]
 		mov	si, offset Get_PCI_IRQ_Record_Lo
 		mov	byte ptr ds:[si+1], al
 		mov	si, offset Get_PCI_IRQ_Record_Hi
 		mov	byte ptr ds:[si+1], ah

		call	X_F000_Shadow_R
		pop	ds
		popad
		ret

Record_PCI_IRQ	Endp
;R12 - ends

X_Get_Device_ID	Proc	Near
		call	fProc_Get_Device_ID
		ret
X_Get_Device_ID	Endp

X_Get_Vendor_ID	Proc	Near
		call	fProc_Get_Vendor_ID
		ret
X_Get_Vendor_ID	Endp

X_Get_CfgSpace_Byte	Proc	Near
		call	fProc_Get_CfgSpace_Byte
		ret
X_Get_CfgSpace_Byte	Endp

X_Get_CfgSpace_Word	Proc	Near
		call	fProc_Get_CfgSpace_Word
		ret
X_Get_CfgSpace_Word	Endp

X_Get_CfgSpace_Dword	Proc	Near
		call	fProc_Get_CfgSpace_Dword
		ret
X_Get_CfgSpace_Dword	Endp

X_Set_CfgSpace_Byte	Proc	Near
		call	fProc_Set_CfgSpace_Byte
		ret
X_Set_CfgSpace_Byte	Endp

X_Set_CfgSpace_Word	Proc	Near
		call	fProc_Set_CfgSpace_Word
		ret
X_Set_CfgSpace_Word	Endp

X_Set_CfgSpace_Dword	Proc	Near
		call	fProc_Set_CfgSpace_Dword
		ret
X_Set_CfgSpace_Dword	Endp

See_If_Bus_0	Proc	Near
		cmp	byte ptr CURRENT_BUS_NO[bp], 0
		ret
See_If_Bus_0	Endp

X_Disable_PCI_ROM	Proc	Near
		call	fProc_Disable_PCI_ROM
		ret
X_Disable_PCI_ROM	Endp

X_Get_Next_Device	Proc	Near
		POST_FUNC_CALL Get_Next_Device
		ret
X_Get_Next_Device	Endp

X_Chk_If_Class_VGA_1	Proc	Near
		POST_FUNC_CALL Chk_If_Class_VGA_1
		ret
X_Chk_If_Class_VGA_1	Endp


X_Mark_Addr_Not_Available	Proc	Near
		POST_FUNC_CALL Mark_Addr_Not_Available
 		ret
X_Mark_Addr_Not_Available	Endp

X_Invalidate_Shadow_Seg	Proc	Near
		POST_FUNC_CALL Invalidate_Shadow_Seg
		ret
X_Invalidate_Shadow_Seg	Endp

X_If_MultiFunc_Dev	Proc	Near
		POST_FUNC_CALL 	If_MultiFunc_Dev
		ret
X_If_MultiFunc_Dev	Endp

		Public	X_Move_Codes
X_Move_Codes	Proc	Near
		F000_CALL Move_Codes
		ret
X_Move_Codes	Endp

		Public	X_CPU_Cache
X_CPU_Cache	Proc	Near
		F000_CALL CPU_Cache
		ret
X_CPU_Cache	Endp

X_Ct_Set_PciIrq	Proc	Near
		F000_CALL Ct_Set_PciIrq
		ret
X_Ct_Set_PciIrq	Endp

X_Ct_Shadow_Unit	Proc	Near
		F000_CALL Ct_Shadow_Unit	;check chipset for shadow unit size
		ret
X_Ct_Shadow_Unit	Endp

X_C000_Shadow_RW	Proc	Near
		F000_CALL C000_Shadow_RW
		ret
X_C000_Shadow_RW	Endp

;R82 - starts
X_Ct_Shadow_RW	Proc	Near
		F000_CALL Ct_Shadow_RW
		ret
X_Ct_Shadow_RW	Endp
;R82 - ends

X_Ct_OnChip_IDE_Chk	Proc	Near
		F000_CALL Ct_OnChip_IDE_Chk    	;on-chip IDE enable
		ret
X_Ct_OnChip_IDE_Chk	Endp

;R12 - starts
		Public	X_F000_Shadow_W
X_F000_Shadow_W	Proc	Near
		F000_Call F000_Shadow_W
		ret
X_F000_Shadow_W	Endp

		Public	X_F000_Shadow_R
X_F000_Shadow_R	Proc	Near
		F000_Call F000_Shadow_R
		ret
X_F000_Shadow_R	Endp
;R12 - ends

;R19 - start
;Function : Check if PCI card need EBDA support, if yes, reserve 1Kb EBDA
;	    even PS2 mouse is not installed
;Input    : none
;Output   : none
		public	fPatch_Ebda_Usage
fPatch_Ebda_Usage	proc	far
	;Reserve 1Kb base memory if Mylex DAC960 Raid card is installed
	;and PS2 mouse is absent.
		pushad
		push	ds

		mov	ax, 0F000h
		mov	ds, ax
		mov	si, offset SYSTEM1_BYTE
		test	byte ptr [si], 04H	;PS2 mouse exist?
		jnz	short EBDA_exist		;yes!

	;Check if DAC960 card existed ?
		mov     dx, 1069h		;vendor ID (Mylex)
		mov	cx, 0010h		;device ID (DAC960 Raid)
		xor     si, si			;first device
		mov     ax, 0b102H		;find PCI device func. call
		int     1AH
		jc	short NoDac960Raid

	        f000_call	F000_Shadow_W		;enable F000 shadow R/W
		mov	si, offset CONFIG_TABLE
		or	byte ptr ds:[si+5], 04H		;set Extended BIOS
							;data area is allocated
		f000_call	F000_Shadow_R		;enable F000 shadow readonly

		mov	ax, G_RAM
		mov	ds, ax
		assume	ds:G_RAM

ifdef	MOUSE_IN_XGROUP					;R19A
		call	Reserve_Ebda_1Kb		;R19A
else	;MOUSE_IN_XGROUP				;R19A

 ifndef	Flash_2M_Support				;R95
		POST_FUNC_CALL Reserve_Ebda_1Kb		; reserve 1Kb EBDA
 else	;Flash_2M_Support				;R95
		XCALL	Reserve_Ebda_1Kb		;R95
 endif	;Flash_2M_Support				;R95
endif	;MOUSE_IN_XGROUP				;R19A

EBDA_exist:
NoDac960Raid:
		pop	ds
		popad
not_RAID:
		ret
fPatch_Ebda_Usage	endp
;R19 - end

endif	;PCI_BUS

XCODE		ENDS
ENDIF	;COMPILE_FOR_E0 EQ 1

		END
