;	[]===========================================================[]
;
;	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.
;
;	[]===========================================================[]
;

		PAGE	60,132
		TITLE	PNPPOST  -- Plug and Play POST
;----------------------------------------------------------------------------
;Rev	Date	 Name	Description
;----------------------------------------------------------------------------
;R139	04/22/99 TNY	Delete ICH SMBus node if B0-stepping.
;R116D	04/13/99 MCH	Fixed R116C coding mistake.
;R138	03/22/99 PAL	Add ESS1869 onboard PNP sound chip Disable function
;R116C	03/18/99 MCH	Added "ACPI_IRQ_Auto_Assign_Selectable" define with
;			"ACPI_IRQ_Selectable" to choose Auto/Manual assign IRQ.
;R137	12/28/98 RAY	Support switch: SHADOW_UNIT_64K
;R136	12/16/98 RCH	Added "NO_ISA_BUS" switch support to eliminate DMA
;			setup items
;R135	11/30/98 MIL    Fixed Some MediaGx M/B hang-up POST BFh Stage, after
;			We clear the CMOS data area.
;R134	11/16/98 RAY	no more "extrn Reserve_Irq_For_PciBootDev:near"
;R133	11/02/98 KEN	Fixed bug that the ESCD is contained corrupt data,
;			after running NVRAM.EXE to clear ESCD and reboot.
;R132	11/02/98 RAY	Use MASM 6.x to compile this file
;R131	10/30/98 RAY	Support switch: MULTI_LANGUAGE_SUPPORT so that this file
;			becomes common for 4.5 & 4.6
;R130	09/29/98 KVN	Release DMI and ESCD pool in flash ROM when not define
;			"ESCD_SUPPORT" and "FLASH_SUPPORT" in BIOS.CFG
;R116B	09/23/98 RIC	Change VIA ACPI IRQ assign algorithm to Auto-assigned.
;			So add "ACPI_IRQ_Selectable" define for old algorithm.
;R118A	09/04/98 KEN	Restored the codes masked by R118 and added declaration
;			"SHOW_ISAPNP_M1" to show ISA/PNP card at the first
;			screen of POST that is the same as the old BIOS did.
;R129	08/20/98 KEN	1. Add declaration of "NO_ISA_PNP" to unsupport ISA/PNP
;			   cards for the system doesn't contain ISA bus.
;			2. Supplement declaration of "ESCD_SUPPORT".
;----	08/19/98 KEN	No codes' modification for this revision actually,
;			just group routines for future implementation of
;			new declaration of "NO_ISA_PNP" and supplement of
;			declaration of "ESCD_SUPPORT".
;			Old files are backup as PNP0819.ZIP.
;R128	08/18/98 RCH	In order to get IRQ 3 & 4 for onboard serial ports
;			when they are set to "auto". Change the priority
;			of IRQ 3 & 4 to the lowest.
;R103B	08/12/98 RCH	Fixed system hang up if flash type is unknown.
;			for switch "No_show_Updata_Escd_Msg"
;R127	07/02/98 RCH	Added Midi IRQ assignment control for CMI8330 audio
;			chip.
;R126	06/15/98 TNY	Support onboard NCR810 ROM's memory node of ACPI.
;R125	06/11/98 DNL	Added USB memory usage report for ACPI BIOS to prevent
;			"Unreported memory" for HCT 7.5
;R124	05/25/98 KEN	Added PNP_IRQ_MAP record for the reference of the "AUTO"
;			feature of super I/O serial ports.
;R123	03/10/98 RCH	Added SB-LINK BIOS interface for Creative PCI audio
;			support, please note that till now only Piix4
;			platform support this feature.
;R122	02/17/98 DRS	486 MB plugs 1M DRAM , it will halt in POST_65S
;R116A	02/11/98 RIC	Do not assign the IRQ of ACPI SCI used(or other special)
;			for PnP ISA card if ACPI enabled in VIA VT586B chip
;			(Because SCI IRQ is selectable).
;R103A	02/09/98 RCH	Fixed BIOS still show "unknown flash type" even the
;			switch "No_show_Updata_ESCD_Msg" is defined when use
;			EEPROM instead of flash memory.
;R121	01/13/98 KEN	Added some codes to verify that the CSN is assigned
;			successfully at "Assign_CSN" routine for isolation
;			verification.
;R120	01/12/98 TNY	Qualify "Build_PIIX4_SMBus_Node" hook for PIIX4.
;R119	01/12/98 RCH	Rewrite dynamic node report method to have various
;			combinations of adding device nodes. The old method
;			will have wrong device node if the building order
;			is changed.
;R118	01/07/98 KEN	Removed the codes to show ISA/PNP cards to
;			"Show_System_Cfg" in "XFILE.ASM".
;R117	01/06/98 RCH	Added optional feature with IRQ selectable for each
;			PCI slots if define "PCI_IRQ_SELECTABLE"
;R114B	01/02/98 LAW	change flag setting
;R116	12/29/97 TNY	Do not assign IRQ9 for PnP ISA card if ACPI enabled.
;R114A	12/26/97 LAW	Clear screen after show PNP card
;R115	12/24/97 RIC	Add "IRQ9_Not_Available_For_ISA" define for some chip
;			can't share IRQ9 with SCI of ACPI to ISA.
;R114	12/18/97 LAW	change "EPA_LOGO_Use_Graphics" with "FULL_SCREEN_LOGO"
;			switch to "Graphics_post"
;R113	12/01/97 LAW	Show PNP Card MSG use display_char of Setup.asm when
;			define "EPA_LOGO_Use_Graphics"
;R112	11/03/97 KEN	Fixed bug that the size of PCI/VGA BIOS is larger than
;			32KB and the record of ESCD is incorrect.
;R111	07/18/97 KEN	Fixed bug that the length of the motherboard device
;			nodes is exceed the LARGEST_SIZE of PNPBIOS reporting.
;			and cause the Win95 report error in device manager.
;R110	06/25/97 RCH	Added "SPECIAL_PnP_IRQ_ORDER" to re-define IRQ assign-
;			ment for PnP devices.
;R109	06/25/97 RCH	Added memory usage report for switch "COMBINE_ISA_ROM"
;			to prevent "Unreport memory" for SCT.
;	05/30/97 RCH	Clean up revision comment for readability, The old
;			file backuped as pnppost.530
;R108	05/29/97 KVN	Added a new segment for store more BIOS code
;R107	04/30/97 RCH	Fixed chipset with PIIX4 updating ESCD every booting
;			if installed Creative audio DOS driver with ICU
;R106	04/30/97 AVN	Added show 'UnKnowable EEPROM Type' for auto detect
;			EEPROM function only.
;R105	04/15/97 RAY	Add switch: Temp_No_Flash_Support for Cyrix GX86,
;			because in this moment, there still have problems
;			supporting flash on this chip !
;R104	04/14/97 DNL	Some pnp OS (like win95) will change pnp card's read
;			data port address by itself, so we need search port
;			address again
;R103	03/12/97 KVN	Add "No_show_Updata_ESCD_Msg" definition
;R102	02/19/97 RCH	Fixed SCT 5.3 "unreport memory" error if USB legacy
;			support is enabled.
;R101	02/03/97 DNL	Added codes for zero-volte suspend/resume function
;R100	01/27/97 KEN	Fixed bug that the system hang-up at POST 63h, when PCI
;			SIG testing card is installed and running its testing
;			program. The causation is that the ESCD is destroyed,
;			since its memory decoding bits (value gotten with
;			writing 0FFFFFFFFh to configuration space) are not set
;			fully, so its request size we adjust is incorrect and
;			process it as the size above 64MB.
;			Another bug is that its PCI function is not sequential.
;R99	01/14/96 TNY	Add ACPI and SMBus controller report address.
;R98	12/20/96 RCH	The SCT v5.xx reports "unreported memory" for PCI
;			devices that need ROM space but without ROM requesting
;			implemented in config. space 30H-33H. Chips like NCR
;			810/860, AHA7850/60/70 have the same problem.
;R97	12/12/96 RCH	Create correct ESCD data for onboard memory over 64Mb
;			to prevent ESCD updated every boots. Also update for
;			PCI memory boundary over 64Mb
;R96	11/30/96 RCH	BIOS didn't build correct ESCD data for PCI I/O
;			requested size beyond 32 bytes.
;R95	11/15/96 RAY	Move some codes to a new ASM file called PNPE0.ASM
;			which will be linked to address at E0000-E7FFF to
;			save E8000-EFFFF area.
;R94	09/09/96 TNY	Fix alignment error in Natoma with 8M DRAM & 180Mhz.
;R93	09/06/96 RIC	Add Special_PNP_Audio_Init hook for some special
;			Onboard PnP Sound Chip,like YAMAHA YMF711.
;R92	08/20/96 RCH	Reserve a IRQ for PCI boot device to avoid too many
;			IRQs occupied by PnP/ISA cards before PnP devices
;			resource assignment if define switch IRQ_FOR_BOOTDEV
;R91	08/19/96 RAY	Bug:
;
;			  System hangs if:
;
;			     Cirrus Logic FAX/MODEM card plugged
;			     Onboard COM port is set to 3F8h
;
;			Reason:
;
;			  This PnP card request IO port 3F8h as its first
;			  priority resource setting.
;
;			    IO_DSP 1,3F8h,3F8h,0,8
;
;			  This means that it request IO port 3F8h-3FFh only.
;			  Thus the Alignment field is meaningless and usually
;			  it is filled with "0"
;
;			  However, our PnP BIOS use this "ALIGNMENT" as a
;			  looping condition and thus cause itself to enter
;			  a infinite loop if onboard COM port is set to 3F8h
;
;R90	08/12/96 KVN	Add new DMI spec 2.0 support
;R89	08/12/96 KEN	Call Write_ESCD_Shadow at PNP_Final_Init, for later
;			process ESCD with shadow.
;R76A	08/08/96 KEN	Check sIoPort descriptor, not just sIoPortFixed
;			descriptor for super I/O device node.
;R88	08/05/96 RAY	Add BIOS.CFG option: UMB_AREA_SETUP which allow setup
;			to skip UMB area which is used by legacy devices
;
;			Note: If this option is added, please also add 2 setup
;			      items: UMB_BASE_ITEM & UMB_LEN_ITEM which tells
;			      the base address & length of the legacy area
;			      correspondingly.
;
;R65A	07/30/96 KEN	Fixed coding mistake for PNP ROM assignment in non-PCI
;			BIOS.
;R87	07/25/96 KVN	Fixed P6 update data pool be destroy during update DMI
;			data
;R86	07/19/96 KEN	Patch GVC FAX/MODEM bug, since this card cause the BIOS
;			consume very long time to get its resource byte.
;R85	06/26/96 KEN	Fixed both TBS-2000 and AHA3985 installed, POST will
;			hang up at POST 52h when AHA3985 ROM executed.
;R84	05/30/96 KEN	Patch on-board ES1868 bugs when it is contained blank
;			resource data for MicroStar SiS5596 M/B.
;R83	05/14/96 KVN	Fixed function 50h reture value error on 16 bits protect mode
;R82	05/11/96 RCH	Fixed IRQ 5 & 7 can not be assigned for PnP/ISA card
;R81	05/06/96 RCH	Fixed WIN/95 can not find COM & LPT ports due to later
;			super I/O initialization
;R80	05/06/96 RAY	Fix coding mistake
;R79	05/03/96 RCH	Fixed OPTi924 can not set 220H for sound system by
;			1. Change priority of sound & scsi resource assign
;			2. Skip I/O 220H unique checking
;R78	04/30/96 KEN	Added PNP/OS setup item checking, and skip
;			non-bootable device initializing if it's enabled.
;			Note: If enabled PnP OS , BIOS only assign resource
;			      for boot-device and let WIN/95 to assign
;			      resource for it.
;R77	04/19/96 KEN	Fixed bug when get PNP card resouce, if high speed
;			CPU installed.
;R76	04/19/96 KEN	Add hook for other modules to get onboard COM/LPT I/O
;			port address.
;R75	04/11/96 KEN	Fixed bug in processing PNP card of CREATIVE CT2504.
;			This bug appear when switch ECP/DMA and reboot many
;			times. Then the card's configuration will be abnormal.
;			The reason is: If jump to "No_Fix_Config" after calling
;			"Query_CfgData" in "Proc_PnpCard" routine, then will
;			cause the pointer of resource information to be
;			incorrect, so recall "Find_LogicDev" to solve this
;			problem.
;R74	04/05/96 KEN	Don't assign I/O port as 110h for ISA/PNP card, since
;			this address is always occupied by 3Com 3C509B.
;			Otherwise, the configuration utility of 3C509B won't
;			find its adapter or hang up while running.
;R73	03/26/96 KEN	Force the PCI bridge device (class code 06h) occupied
;			a dummy function record in ESCD, since the old version
;			CM (ver 1.23) of Intel ICU DOS driver will show message
;			as "Active device resource conflict" if no this function
;			record in ESCD.
;R72	02/08/96 KEN	Added checking PCI IDE resources.
;R67A	02/02/96 KVN	Added BIOS information for DMI structure
;R71	01/31/96 KEN	PNP ROM use separate data to avoid to conflict with
;			PCI kernal.
;R70	01/25/96 KEN	Temporarily fixed AMD InterWave PNP sound card problem.
;			Since we cannot fully assign DMA for all devices.
;R69	01/17/96 KEN	Individual reset ESCD process.
;R68	01/12/96 KEN	Support updating ESCD with high memory (below 4GB).
;R67	01/11/96 KVN	Added BIOS information for DMI structure
;R66A	12/29/95 KEN	Fixed coding mistake.
;R66	12/28/95 RCH	The EISA ID can read from port 0C80H directly
;R53A	12/28/95 KVN	Fixed Floppy B drive motor on while check device
;R65	12/28/95 KEN	Manage I/O port with 4 bytes unit and UMB with 4KB unit
;			to solve two IBM Token-Ring cards installed problem.
;R48B	12/26/95 KEN	The ID is readable for motherboard in EISA system.
;R48A	12/16/95 RCH	Support ESCD run-time function for EISA systems
;R64	12/14/95 KEN	Fix processing Type/SubType record size error.
;R61A	12/14/95 KEN	Fix coding mistake.
;R63	12/12/95 RCH	Special patch for ORION/PnP
;R06A	12/08/95 KEN	Re-call Ct_Record_Resource for PCIPOST to record
;			UMB map, otherwize the ROM image of PCI card will
;			overwrite the PNP ROM.
;R62	11/29/95 KEN	Fixed the IDE device of Creative ViBRA16S PNP card
;			assigned I/O port as 376h and will conflict with
;			on-chip secondary IDE in windows 95.
;R61	11/27/95 KEN	Fixed IBM Token-Ring card configuration utility problem,
;			since it update its resource data for modification.
;R59B	11/24/95 KEN	Fixed coding mistake.
;R60	11/21/95 KEN	Patch the resource information of Ensoniq PNP sound card
;			with START_DF and no END_DF problem.
;R59A	11/17/95 KEN	Fixed coding mistake.
;R59	11/10/95 KEN	Assign AT device resource with compatible IRQ.
;R58	11/09/95 KEN	Fixed some PNP card can't get serial id correctly,
;			since it can't wake-up immediately after sleep.
;			(e.g. Tamarack TC3099)
;R57	11/09/95 KEN	Patch TC4145 Token Ring Card checksum error.
;R56	10/27/95 KEN	Initailizing PNP sequence with device type priority.
;			Backup file as PNPPOST.R56
;R55	10/23/95 KEN	Support force configuration with non-conflict ESCD.
;			Backup file as PNPPOST.R55
;R54	10/23/95 RAY	Support Audio devnode
;R53	10/20/95 KVN	Fixed VGA screen to be destroyed on some VGA card (e.g.
;			Tseng-4000) when all Floppy type set NONE.
;R52	10/19/95 KEN	Add clear PNP card register routine, since the SMC795
;			EtherNet card can't be inactive and its default I/O
;			port address 240h-25Fh will confict with W83787F
;			Configuration Port(250h).
;R51	10/18/95 RCH	Fixed on-chip PCI/IDE didn't recorded in ESCD if the
;			configuration space is in the second function of
;			PCI/ISA bridge ( SiS 551X , TRITON etc..)
;R50	10/18/95 RCH	Complete NEW_PNP_SETUP progrmming, the old can not
;			assign IRQ correctly according to setup CMOS.
;----	10/17/95 KEN	No modification for this revision, just add some
;			comments for routine head and let the codes be looked
;			more clearly.
;R49E	10/13/95 KEN	Fix coding error.
;R49D	10/13/95 KEN	Don't record I/O address 3F6h, 376h. Since this will
;			occupy 3F0-3F8h, and floppy can't allocate I/O.
;R49C	10/12/95 KEN	Re-display PNP card id string.
;R49B	10/12/95 KEN	Fix floppy detection fail.
;R49A	10/12/95 KEN	Fix coding error.
;R49	10/06/95 KEN	Support PnP Super I/O.
;R48	09/28/95 RCH	Added EISA/PnP function
;R47	09/27/95 RCH	Use same routine to check resource of LPT & COM ports
;R46	09/27/95 RCH	The length of parallel ports are 8 , not 4, and the
;			maximum number of LPT ports are 3 , not 4
;R45A	09/25/95 RCH	Don't assign 200H & 220H for general I/O card
;R45	09/22/95 KEN	Re-definition RD_DATA table, and patch I/O 220h.
;R44	09/21/95 KEN	Add NEW_PNP_SETUP definition.
;R43	09/18/95 RCH	Move PnP string and display routine from PNPKERNL.ASM
;			to save space for F-segment
;R42	09/18/95 RCH	Sort ESCD data for EISA system
;R41	09/14/95 TNY	Add Ct_Irq12_Chk routine in pnpchip.asm if define
;			IRQ12_CHIPSET_QUALIFY , because some chipset can't
;			release IRQ12 after KBC initialed.
;R40	09/14/95 KEN	Skip I/O 200h allocation, if the card can choice other
;			I/O port address.
;R32F	09/07/95 KEN	Fix coding mistake. This cause the IBM Token-Ring
;			card diagnostic program and Award Flash utility work
;			incorrectly, and seems the 8254 counter be destroyed.
;R38A	08/28/95 KEN	Fix coding mistake.
;R39	08/22/95 DNL	Kill duplicate codes
;R38	08/21/95 KEN	Manage I/O port above 800h, since most of Token Ring
;			cards request I/O port above 800h.
;R32E	08/15/95 KEN	Fix coding mistake for DX contained RD_DATA port
;			address be destroyed.
;R37	08/10/95 KEN	Fix system hang problem when install OS/2 Warp and
;			CS4232 present.
;R36	08/09/95 KEN	Modify the comparative method for board ESCD.
;R35A	08/07/95 KEN	Loss CURRENT_BUS_NO at some procedure.
;R32D	08/07/95 KEN	Fix coding mistake.
;R35	08/04/95 RCH	Record PCI devices behind PCI-TO-PCI bridge to fix
;			ICU error reporting
;R34	08/03/95 RCH	Replace all Get_CfgSpace and Set_CfgSpace with EGet_
;			CfgSpace and ESet_CfgSpace to reduce code size
;R32C	08/01/95 KEN	Don't show any message about fixed-config.
;R33	07/28/95 RCH	Driver for 3C509 of 3COM hang while warm booting,if
;			the I/O is selected as 300H and non-PnP config. is
;			selected. Note this is temporary solution, if the
;			I/O is not 300H , system still hang, but the default
;			is 300H for the driver.
;R32B	07/28/95 KEN	Show M/B devices changed message.
;R21B	07/27/95 KEN	I/O port manage above 400h to 7FFh according to FIC request.
;R32A	07/26/95 KEN	Skip fixed-config if M/B device changed by SETUP.
;R21A	07/26/95 KEN	Resume I/O port management with 8 bytes unit, to match
;			Intel CM management method.
;R32	07/25/95 KEN	Support fixed-config for ISA/PNP devices, when these
;			devices no changed since last booting.
;R31	07/07/95 KEN	Mask the resources used by M/B device before ISA/PNP
;			and PCI devices initializing.
;R30	07/05/95 KEN	Re-structure device node index method.
;R29	07/05/95 RCH	Ethernet card 3C509B system hang while warm booting
;			cause by R04A, but this patch will cause Crystal
;			4232 sound card failed while warm booting, we still
;			need to find out what is the exactly solution
;R28	07/01/95 KEN	Support dynamic Get/Set devnode
;R27	07/01/95 KEN	Modify the initializing of ISA/PnP devices before PCI
;			devices.
;R26A	06/28/95 KEN	Incorrect bit for game port.
;R26	06/20/95 KEN	Skip 200h-207h I/O port if game port present.
;R25	06/20/95 KEN	Fix the CS4232 corrupt resource information problem.
;R24	06/15/95 KEN	Fix bug when process PCI/ECD/FF for Multi-Function PCI.
;R23	06/13/95 KVN	Reduce Post_func_call and F000_call code size
;R22	06/13/95 KEN	Skip device processing if its resource information
;			corrupt, since the resource information of Crystal
;			CS4232 sound card will be corrupt at warm-boot.
;R21	06/13/95 KEN	Modify resource management for I/O port according to
;			Phoenix BIOS method to match the process for Crystal
;			CS4232 sound card, modification as follow:
;			1. Don't assign I/O port address above 3FFh.
;			2. Manage I/O port with 4 bytes one unit.
;R20	06/13/95 KEN	Modify the EISA function disable bit of ESCD to match
;			the ESCD spec definition. The relative bits are "Device
;			lock bit", "EISA function disable bit" and "ECD disable
;			bit".
;R19	06/13/95 KEN	Fix coding error in Update_CfgData routine.
;R17A	06/13/95 KEN	Fix R17 coding error when process "Dependent Function".
;R18	06/07/95 KEN	Get largest device nodes size with actual enabled
;			device nodes, since Win95 PnP_BIOS test fail if not
;			found the size of device node matching the largest
;			node size.
;R16A	06/06/95 RCH	Don't show "Fail" message if ESCD failed
;R17	06/01/95 KEN	Fix bug when one logical device of ISA/PNP card request
;			multi-set same kind resources, since our BIOS will
;			assign the multi-set resources with the same value.
;			For examples the Crystal CS4232.
;R16	05/29/95 KEN	Add NO_DISP_ESCD_FAIL option to skip display updating
;			ESCD fail.
;R15	05/29/95 KEN	Fix bug when I/O or memory request size with zero
;			and IRQ, DMA mask with zero for some ISA/PNP cards,
;			for example the AM79C961KC network card request memory
;			length with zero.
;R14	05/19/95 KEN	Fix bug for PCI/IDE ESCD record, when PCI/IDE have
;			memory request/record.
;R13	05/18/95 KEN	Add ISA/PnP card configuration information to ESCD.
;R12	05/15/95 KEN	Add system device nodes information to M/B ESCD.
;R11	05/11/95 KEN	Add display updating ESCD status.
;R10	05/11/95 KEN	Update CFGDATA to support creating ESCD in POST.
;R04A	05/03/95 KEN	1. Alway check assigned CSN not only warm-boot, since
;			   Setup-reboot have the same problem.
;			2. Check the READ_DATA port of assigned CSN with
;			   RDDATA_PORT table, then we can skip some confused
;			   ports.
;R09	05/03/95 KEN	Fix display ID string bug when the ID string contain
;			value with zero. example the Crystal CS4232 card.
;R08	05/03/95 KEN	Remove RDDATA_PORT table from PNPCHIP to PNPPOST,
;			and don't use 203h, 223h since these ports cause
;			unknown problem with Crystal ISA/PnP card.
;R07A	05/02/95 KEN	Correct solution for R07
;R07	05/01/95 RCH	Solve system hange at POST 0BH while warm booting
;			(This is temporary solution)
;			for some PCI/VGA cards
;R01A	04/25/95 KEN	Fix R01 coding error, since the Win95 record system
;			resource with slot number above 10h, and that will
;			be removed as PCI device ESCD.
;R06	04/21/95 RAY	Reason: All PCI cards initializaion are done before
;				PNP_BootDev_Init & Create_Resource_Map will
;				be called in PciRom_After_Init
;			Therefore: Create_Resource_Map & Ct_Record_Resource
;				   no longer needed in PNP_BootDev_Init
;R05	04/21/95 RAY	Also reference PS2 mouse for Resource Map
;R04	04/21/95 KEN	Different process for PnP_Early_Init when warm boot.
;R03	04/21/95 KEN	Remove procedure to call PnP ROM later.
;R02	04/20/95 KEN	Fix bug for DX register be destroyed in Init_PnP_ROM.
;R01	04/19/95 KEN	Add PCI card information to ESCD
;R00	10/01/94 KEN	Initial Revision

;R132 - starts
ifdef	MASM611
.MODEL  SMALL, BASIC
OPTION	PROC: PRIVATE
endif	;MASM611
;R132 - ends

.386P

.XLIST
;[]========================================================================[]
;
;	Include file definition
;
;[]========================================================================[]

		INCLUDE BIOS.CFG
		INCLUDE BSETUP.INC			;R114A
ifdef	NEW_PNP_SETUP
CLEAR_ESCD_OPTION	EQU	1
endif	;NEW_PNP_SETUP
		INCLUDE COMMON.EQU
		INCLUDE COMMON.MAC
		INCLUDE CMOS.EQU
		INCLUDE PNP.EQU
IF	BUS_TYPE EQ EISA_BUS
		INCLUDE EISA.EQU
ENDIF;	BUS_TYPE EQ EISA_BUS
.LIST

;[]========================================================================[]
;
;	External label definition
;
;[]========================================================================[]

;R131 - starts
ifdef	MULTI_LANGUAGE_SUPPORT
		DECLARE_MULTI_LANGUAGE		;macro to declare externals
		extrn	Disp_CS_Language:near
endif	;MULTI_LANGUAGE_SUPPORT
;R131 - ends

ifdef	DMI_ENABLED				;R108
ifdef	FLASH_SUPPORT	;R130
		extrn	build_dmi_pool:near	;R108
		extrn	Xcall_proc:near 	;R108
endif	;FLASH_SUPPORT	;R130
endif;	DMI_ENABLED				;R108
ifdef	PNP_BIOS

;R123 - start
ifdef	SB_LINK_SUPPORT
		extrn	PciDmaChns:near
endif;	SB_LINK_SUPPORT
;R123 - end

		extrn	E_F000_Shadow_W:near			;R109
		extrn	E_F000_Shadow_R:near			;R109
;R119 ifdef	COMBINE_ISA_ROM 				;R109
;R119		extrn	Onboard_Other_RomNode:near		;R109
;R119 endif;	COMBINE_ISA_ROM 				;R109
		extrn	LastMbNodeShared:near			;R119

ifdef	PCI_BUS
	ifdef	ACPI_SUPPORT				;R125
;R126	ifdef	USB_SUPPORT				;R125
;R126		extrn	USB_MEMORY:NEAR 		;R125
;R126	endif	;USB_SUPPORT				;R125
		extrn	Combined_Rom1:near		;R126
		extrn	Combined_Rom_End:near		;R126
	endif	;ACPI_SUPPORT				;R125
;R119  ifdef	USB_SUPPORT
;R119		extrn	Usb_MemNode:near
;R119  endif;	USB_SUPPORT
;R109		extrn	F000_Shadow_W:near
;R109		extrn	F000_Shadow_R:near
;R119		extrn	EndOf_MbRom_Node:near
;R119		extrn	Onboard_Scsi_RomNode:near
;R119		extrn	MbRom_Node:near
ifdef	ACPI_Support					;R116
		extrn	ACPI_option_Item:near		;R116
 ifdef	VT586_ACPI					;R116A For VIA VT586B chip
  IFDEF	ACPI_IRQ_Selectable				;R116B
		extrn	Ct_Update_PNP_IRQ_Map:Near	;R116A For VIA VT586B chip
   ifdef ACPI_IRQ_Auto_Assign_Selectable		;R116C
		extrn	Assign_ACPI_IRQ_Item:near	;R116C
   endif;ACPI_IRQ_Auto_Assign_Selectable		;R116C
  ENDIF;ACPI_IRQ_Selectable				;R116B
 endif; VT586_ACPI					;R116A For VIA VT586B chip
endif;	ACPI_Support					;R116

ifdef	Add_PIIX4_SMBus_Node
		extrn	Get_PCI:near
		extrn	PIIX4_SMBus_IONode:near
endif;	Add_PIIX4_SMBus_Node

;R139 - statr
ifdef	ICH
		extrn	Get_PCI:near
		extrn	ICH_SMBus_IONode:near
endif;	ICH
;R139 - end

endif;	PCI_BUS

ifndef	NO_ISA_PNP					;R129
ifdef	PNP_OS_SELECTABLE
		extrn	OS_Setup_Item:near
endif;	PNP_OS_SELECTABLE
endif	;NO_ISA_PNP					;R129

		EXTRN	Ct_PNP_Early_Init:near	;PNPCHIP.ASM
		EXTRN	Ct_ReAlloc_Resource:near;PNPCHIP.ASM
		EXTRN	Ct_Record_Resource:near ;PNPCHIP.ASM
		EXTRN	Ct_Get_Resource_Map:near;PNPCHIP.ASM
		EXTRN	Ct_Set_Resource_Map:near;PNPCHIP.ASM
		EXTRN	DEF_IRQ_MAP:word	;PNPCHIP.ASM
		EXTRN	DEF_DMA_MAP:byte	;PNPCHIP.ASM
		EXTRN	DEF_IO_MAP:byte 	;PNPCHIP.ASM
		EXTRN	DEF_IO_MAP_L:abs	;PNPCHIP.ASM
		EXTRN	Get_CMOS:near		;ATORGS.ASM
		EXTRN	Set_CMOS:near		;ATORGS.ASM
		EXTRN	Get_OptionROM_Map:near	;ATORGS.ASM
		EXTRN	Wait_Refresh:near	;ATORGS.ASM
		EXTRN	R_MOD_CK:near		;ATBASE.ASM
ifdef	ESCD_SUPPORT
		EXTRN	DEFAULT_ESCD:byte	;PNPCHIP.ASM
		EXTRN	DEFAULT_ESCD_L:abs	;PNPCHIP.ASM
;R129		EXTRN	PNP_BIOS_Real:far	;PNPBIOS.ASM
ifdef	ESCD_M2
		extrn	Write_ESCD_Shadow:near
endif	;ESCD_M2
endif	;ESCD_SUPPORT
		EXTRN	PNP_BIOS_Real:far	;R129;PNPBIOS.ASM
		EXTRN	PNP_RD:word		;PNPKERNL.ASM
		EXTRN	LAST_CSN:byte		;PNPKERNL.ASM
		EXTRN	NODES_INDEX:word	;PNPBIOS.ASM
		EXTRN	NODES_PROC:word 	;PNPBIOS.ASM
		EXTRN	TOTAL_NODES:byte	;PNPKERNL.ASM
		EXTRN	LARGEST_SIZE:word	;PNPKERNL.ASM
		EXTRN	Ct_Buffer_Request:near	;PNPCHIP.ASM
		EXTRN	Ct_Save_Shadow:near	;PNPCHIP.ASM
		EXTRN	Ct_Restore_Shadow:near	;PNPCHIP.ASM
		EXTRN	Ct_Shadow_Write:near	;PNPCHIP.ASM
		EXTRN	Ct_Set_Shadow:near	;PNPCHIP.ASM
ifdef	PCI_BUS
;R134		extrn	Reserve_Irq_For_PciBootDev:near
		EXTRN	PCI_IDE_EXIST:abs	;PCIPOST.ASM
		EXTRN	PCI_IRQ_MAP:abs 	;PCIPOST.ASM
		EXTRN	AGet_CfgSpace_Byte:near ;PCI1A.ASM
		EXTRN	AGet_CfgSpace_Word:near ;PCI1A.ASM
		EXTRN	AGet_CfgSpace_Dword:near ;PCI1A.ASM
		EXTRN	ASet_CfgSpace_Dword:near ;PCI1A.ASM
		extrn	CURRENT_BUS_NO:ABS
		extrn	TOTAL_BUS_NO:ABS

		EXTRN	Ct_Pci_Escd:near	;PNPCHIP.ASM
endif	;PCI_BUS
		extrn	Display_String:near	;SETUP.ASM
ifdef	IRQ12_CHIPSET_QUALIFY
		EXTRN	Ct_Irq12_Chk:near
endif;	IRQ12_CHIPSET_QUALIFY
ifdef	ESCD_SUPPORT				;R129
ifdef	CLEAR_ESCD_OPTION
		extrn	Reset_Escd_Item:near
;R130		extrn	F000_GetItem_Value:near
		extrn	Write_Item_Value:near
endif	;CLEAR_ESCD_OPTION
endif	;ESCD_SUPPORT				;R129
		extrn	F000_GetItem_Value:near	;R130
ifdef	NEW_PNP_SETUP
		extrn	PnP_Control_Item:near	;PNPFEAT.ASM
		extrn	IrqItem_Table:near	;PNPFEAT.ASM
;R136		extrn	DmaItem_Table:near	;PNPFEAT.ASM
		extrn	ESCD_IRQ:abs		;PCIPOST.ASM
		extrn	ESCD_DMA:abs		;PCIPOST.ASM
ifdef	UMB_AREA_SETUP
		extrn	UMB_BASE_ITEM:Near
		extrn	UMB_LEN_ITEM:Near
endif	;UMB_AREA_SETUP
endif	;NEW_PNP_SETUP
		extrn	Aux_Addrs:word		;ATORGS.ASM
		extrn	Aux_Prn_Addrs:word	;ATORGS.ASM
		extrn	Test_COMM:near		;CPINSTAL.ASM
		extrn	Test_LPT:near		;CPINSTAL.ASM
		extrn	NO_OF_NODE_TBL:ABS
		extrn	Special_PNP_Audio_Init:near	;AUDIO.ASM
endif	;PNP_BIOS

;[]========================================================================[]
;
;	Low memory init (1st 64k)
;
;[]========================================================================[]


G_RAM		SEGMENT USE16 AT 0

		ORG	04H*4
		INCLUDE SEG_0.INC

		ORG	400H
		INCLUDE G_RAM.INC

		ORG	2000h
		INCLUDE PNPDATA.INC

IF BUS_TYPE EQ EISA_BUS
		ORG	4000H
TEMP_ESCD	db	4096 dup (?)

ADDRSIZE	STRUC
RecAddr 	dw	?
RecSize 	dw	?
ADDRSIZE	ENDS

		ORG	5000H
ADDR_ARRAY	db	(256 * (SIZE ADDRSIZE)) dup (?)

endif; BUS_TYPE EQ EISA_BUS

		ORG	7C00H
BOOT		LABEL	FAR

G_RAM		ENDS

ifdef	Notebook_Power_Management
SM_RAM		SEGMENT USE16 AT 0
		INCLUDE SM_RAM.INC
SM_RAM		ENDS

ZV_Temp_Stack	SEGMENT USE16 AT 0
		org	2000h
PnP_Temp_Buffer LABEL	WORD
ZV_Temp_Stack	ENDS
endif	;Notebook_Power_Management

		extrn	F000_call_proc:near
		extrn	F000_VECT:near
		extrn	RET_E_SEG:near
		extrn	F000_Wait_Refresh:near
		extrn	F000_Get_Cmos:near

EGROUP		GROUP	ECODE
ECODE		SEGMENT USE16 DWORD PUBLIC 'ECODE'
		ASSUME	CS:EGROUP,DS:G_RAM

IFDEF	PNP_BIOS

;************************************************************************
;*									*
;*		GENERAL PNP BIOS MODULE 				*
;*									*
;************************************************************************

;[]========================================================================[]
;Procedure:	PNP_System_Nodes
;Function :
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	PNP_System_Nodes
		ALIGN	4
PNP_System_Nodes	proc	near
		ret
PNP_System_Nodes	endp

;[]========================================================================[]
;Procedure:	PNP_BootDev_Init
;Function :	Assign system resources for the all PNP cards.
;Input	  :	None
;Output   :	None
;[]========================================================================[]

ifndef	NO_ISA_PNP					;R118A
ifdef	SHOW_ISAPNP_M1					;R118A
PnP_Init_Msg	db	0Dh, 0Ah, 0Dh, 0Ah
		db	"Initializing Plug and Play Cards...", 0Dh, 0Ah, 0
Card_Msg	db	"Card-"
Card_Num_Pos	equ	$ - Card_Msg
		db	"00 "
Card_Msg_L equ	$ - Card_Msg
endif	;SHOW_ISAPNP_M1					;R118A
endif	;NO_ISA_PNP					;R118A

		public	PNP_BootDev_Init
		ALIGN	4
PNP_BootDev_Init	proc	near

ifdef	Add_PIIX4_SMBus_Node
		call	Build_PIIX4_SMBus_Node
endif;	Add_PIIX4_SMBus_Node

;R139 - start
ifdef	ICH
 		call	Build_ICH_SMBus_Node
endif;	ICH
;R139 - end

ifndef	NO_ISA_PNP					;R118A
ifdef	SHOW_ISAPNP_M1					;R118A
		pusha
		push	ds
		push	es

		mov	ax, G_RAM
		mov	ds, ax
		mov	es, ax
		call	PNP_Disp_Card

; Let OEM to record resource assigned by PnP card

;R118Aifndef	NO_ISA_PNP					;R129
;R118A		call	Wait_For_Key
;R118Aendif	;NO_ISA_PNP					;R129
		pop	es
		pop	ds
		popa
endif	;SHOW_ISAPNP_M1					;R118A
		call	Wait_For_Key			;R118A
endif	;NO_ISA_PNP					;R118A
		ret
PNP_BootDev_Init	endp

;[]========================================================================[]
;Procedure:	PNP_Disp_Card
;Function :	Display all PNP cards found by system BIOS
;Input	  :	none
;Output   :	none
;[]========================================================================[]

ifndef	NO_ISA_PNP					;R118A
ifdef	SHOW_ISAPNP_M1					;R118A
		ALIGN	4
PNP_Disp_Card	proc	near

; Display initializing PnP cards message

		xor	cx, cx
		mov	cl, ds:TEMP_LAST_CSN	;PnP cards found in early init
		or	cx, cx
;R114A		jz	short Disp_Card_Exit
		jz	Disp_Card_Exit				;R114A

		push	cx
		push	ds
		push	cs
		pop	ds
;R114ifdef EPA_LOGO_Use_Graphics				;R113
ifdef	Graphics_Post						;R114
;R114A		extrn	Switch_LOGO_To_Text:near		;R113
;R114A		call	Switch_LOGO_To_Text			;R113
		test	byte ptr EQUIPMENT[bp],DT_MONO		;R114A
		jnz	short @F				;R114A
		mov	ax, 3h					;R114A
		int	10h					;R114A
		or	byte ptr Post_Temp_Byte[bp],Text_POST	;R114A
		mov	byte ptr EPALOGO_FLAG[bp], 0ffh 	;set flag
	@@:
endif;	Graphics_Post						;R114
;R114endif;	EPA_LOGO_Use_Graphics				;R113
		mov	si, offset EGROUP:PnP_Init_Msg
ifndef No_show_Updata_Escd_Msg
		call	Disp_String
endif ;No_show_Updata_Escd_Msg
		mov	si, offset EGROUP:Card_Msg
		mov	di, offset STR_BUFFER
		mov	cx, Card_Msg_L
		rep	movsb
		pop	ds
		pop	cx

		mov	dx, ds:TEMP_PNP_RD	;RD_DATA port address
		mov	byte ptr ds:CSN_CNT, 1	;CSN start

; all PnP cards loop
; CX = ISA/PnP card numbers
; DX = READ_DATA port address

Disp_Card_Loop:
		push	cx

		mov	al, ds:CSN_CNT
		call	Set_Wake_CSN		;current card to config mode

		mov	di, offset STR_BUFFER + Card_Num_Pos
		call	Trans_AL

		mov	word ptr ds:STR_BUF_POINT, offset STR_BUFFER + Card_Msg_L

; Get serial identifier

		call	Get_SerialId
		jc	short Disp_Next_Card

; Scan ID string loop

Scan_String_Loop:
		call	Get_Resource_Block
		jc	short Disp_Next_Card

		cmp	ah, sEndTag
		je	short Disp_Next_Card	;end resource information
		cmp	ah, lAnsiIdString
		jne	short Scan_String_Loop

		mov	di, ds:STR_BUF_POINT

		cmp	cx, 40
		jbe	short @f
		mov	cx, 40
@@:
		lodsb
		cmp	al, 20h
		jb	short @f
		stosb
		loop	short @b
@@:
		mov	ax, 0A0Dh		;CrLf
		stosw
		xor	al, al			;end string
		stosb
		mov	si, offset STR_BUFFER
ifndef No_show_Updata_Escd_Msg
		call	Disp_String
endif ;No_show_Updata_Escd_Msg

Disp_Next_Card:
		call	Force_Sleep
		pop	cx
		inc	byte ptr ds:CSN_CNT	;next CSN
		loop	short Disp_Card_Loop

Disp_Card_Exit:
		ret
PNP_Disp_Card	endp
endif	;SHOW_ISAPNP_M1					;R118A
endif	;NO_ISA_PNP					;R118A

;[]========================================================================[]
;Procedure:	PNP_OptROM_Init
;Function :	Far call all PNP expansion ROM
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	PNP_OptROM_Init
		ALIGN	4
PNP_OptROM_Init proc	near

ifndef	NO_ISA_PNP					;R129
		pusha
		push	ds
		push	es

		mov	ax, G_RAM
		mov	ds, ax
		mov	cx, PnpRomMap_L
		mov	si, offset PnpRomMap
		mov	bx, 0C000h
PnP_OptROM_Loop:
		lodsb
		or	al, al
		jz	short @f
		push	bx
		push	cx
		push	si
		push	ds
		mov	dx, bx
		add	dx, 400h
		F000_Call	R_Mod_Ck
		pop	ds
		pop	si
		pop	cx
		pop	bx
@@:
		add	bx, 400h
		loop	short PnP_OptROM_Loop

		pop	es
		pop	ds
		popa
endif	;NO_ISA_PNP					;R129

		ret
PNP_OptROM_Init endp

;[]========================================================================[]
;Procedure:	PNP_Final_Init
;Function :	1. Process M/B ESCD.
;		2. Create PCI ESCD.
;		3. Remove un-exist ESCD.
;		4. Update ESCD if necessary.
;Input	  :	None
;Output   :	None
;[]========================================================================[]

;R131 ifdef	ESCD_SUPPORT					;R129
;R131 ifndef	Temp_No_Flash_Support
;R131 Update_Escd_Msg db	"Updating ESCD ... ", 0
;R131 else	;Temp_No_Flash_Support
;R131 Update_Escd_Msg db	0
;R131 endif	;Temp_No_Flash_Support
;R131 Success_Msg	db	"Success", 0Dh, 0Ah, 0
;R131 Fail_Msg	db	"Fail"
;R131 CrLf_Msg	db	0Dh, 0Ah, 0
;R131 endif	;ESCD_SUPPORT					;R129
;R131 ifdef	AUTO_DETECT_EEPROM_ID
;R131 EEPROM_Fail_Msg db	"Unknown Flash Type"
;R131 		db	0Dh,0Ah,0h
;R131 endif;	AUTO_DETECT_EEPROM_ID

;R131 - starts
ifdef	ESCD_SUPPORT
DEFINE_MSG	Update_Escd_Msg
ifndef	Temp_No_Flash_Support
		db	"Updating ESCD ... "
endif	;Temp_No_Flash_Support
		db	0

DEFINE_MSG	Success_Msg
		db	"Success", 0Dh, 0Ah, 0

DEFINE_MSG	Fail_Msg
ifdef	DISP_ESCD_FAIL
		db	'Fail'
endif	;DISP_ESCD_FAIL
CrLf_Msg	db	0Dh, 0Ah, 0
endif	;ESCD_SUPPORT

ifdef	AUTO_DETECT_EEPROM_ID
DEFINE_MSG	EEPROM_Fail_Msg
		db	"Unknown Flash Type", 0Dh, 0Ah, 0
endif;	AUTO_DETECT_EEPROM_ID
;R131 - ends

		public	PNP_Final_Init
		ALIGN	4
PNP_Final_Init	proc	near
		pushad
		push	ds
		push	es
		pushf
		cli

		mov	ax, G_RAM
		mov	ds, ax
		mov	es, ax

;R123 - start
ifdef SB_LINK_SUPPORT
	;Record available DMA channels in shadow for SBLINK run-time usage
		call	E_F000_Shadow_W ;shadow write able

		mov	al, ds:DMA_MAP	;get available DMA channels

		push	es

		push	0F000H		;F-segment
		pop	es
		mov	byte ptr es:PciDmaChns,al;save DMA channels in shadow RAM

		pop	es
		call	E_F000_Shadow_R ;shadow read only
endif; SB_LINK_SUPPORT
;R123 - end

ifdef	ESCD_SUPPORT					;R129
		call	Create_MbEscd
		mov	bx, offset ESCD_BUFFER
		mov	si, bx
		xor	al, al			;mother board slot number
		call	Scan_SlotEscd
		jc	short Update_MbEscd
		mov	di, offset CurrentEscd
		call	Cmp_BrdEscd
		jnc	short No_Update_MbEscd
		mov	bx, offset ESCD_BUFFER
		call	Remove_EscdBrd
Update_MbEscd:
		mov	si, offset CurrentEscd
		call	Add_EscdBrd
		xor	al, al
		mov	di, offset EscdBrdMap
		call	Set_EscdBrd
		mov	di, offset NewEscdBrdMap
		call	Set_EscdBrd
		jmp	short Check_MbEscd_Exit
No_Update_MbEscd:
		mov	di, offset OldEscdBrdMap
		xor	al, al
		call	Reset_EscdBrd
Check_MbEscd_Exit:

ifdef	PCI_BUS
		mov	byte ptr CURRENT_BUS_NO[bp],0	;start from bus 0
NextBus_PciEscd:

		xor	ch, ch			;PCI device number
Check_PciEscd_Loop:
		push	cx

Chk_NextFunc:

		call	Check_VendorID
		jc	short Check_PciEscd_Next

		mov	di, offset CurrentEscd
		call	F000_Ct_Pci_Escd
		jnc	short @f

		call	Create_PciEscd

@@:
		call	Proc_PciEscd

Check_PciEscd_Next:
		pop	cx
		add	ch, 08			;next PCI device
		jnc	short Check_PciEscd_Loop

		inc	byte ptr CURRENT_BUS_NO[bp]	;next PCI bus
		mov	al,byte ptr CURRENT_BUS_NO[bp]
		cmp	al,TOTAL_BUS_NO[bp]
		jbe	short NextBus_PciEscd

endif	;PCI_BUS

; check non-installed PCI card, but still record in ESCD

Check_OldPciMap:
		mov	bx, offset ESCD_BUFFER
		mov	di, offset OldEscdBrdMap
		mov	cx, 64
		xor	al, al
		xor	ah, ah			;removing flag
Remove_EmptyPci_Loop:
		call	Query_EscdBrd
		jnc	short @f
		mov	si, bx
		call	Scan_SlotEscd
ifdef	PCI_BUS
		call	Chk_PciEscd
		jnc	short Remove_EmptyEscd
endif	;PCI_BUS
		call	Chk_PnPEscd
		jc	short @f
Remove_EmptyEscd:
		call	Remove_EscdBrd
		or	ah, 0FFh		;removing flag
@@:
		inc	al
		loop	short Remove_EmptyPci_Loop
		or	ah, ah
		jnz	short Update_PciEscd

; Check new PCI record

Check_NewPciMap:
		mov	di, offset NewEscdBrdMap
		mov	cx, 8
		xor	al, al
		repe	scasb
		je	short Check_PciEscd_Exit	;not need to update ESCD

Update_PciEscd:
endif	;ESCD_SUPPORT					;R129

ifdef	AUTO_DETECT_EEPROM_ID
		push	ds
		push	0f000h
		pop	ds
		cmp	byte ptr ds:[0e05ah],-1
		jne	short EEPROM_Type_Found
ifndef No_show_Updata_Escd_Msg				;R103A
		push	cs
		pop	ds
		mov	si,offset EEPROM_Fail_Msg
;R131		call	Disp_String
;R131 - starts
ifdef	MULTI_LANGUAGE_SUPPORT
		call	Disp_CS_Language
else	;MULTI_LANGUAGE_SUPPORT
		call	Disp_String
endif	;MULTI_LANGUAGE_SUPPORT
;R131 - ends

endif; No_show_Updata_Escd_Msg				;R103B
		pop	ds
;R103B endif; No_show_Updata_Escd_Msg				;R103A
		jmp	short EEPROM_Type_Not_Found
EEPROM_Type_Found:
		pop	ds
endif;	AUTO_DETECT_EEPROM_ID

ifdef	ESCD_SUPPORT					;R129
		mov	ax, 0F000h
		mov	es, ax
		push	ds
		mov	ax, cs
		mov	ds, ax
		mov	si, offset EGROUP:Update_Escd_Msg
ifndef No_show_Updata_Escd_Msg
;R131		call	Disp_String
;R131 - starts
ifdef	MULTI_LANGUAGE_SUPPORT
		call	Disp_CS_Language
else	;MULTI_LANGUAGE_SUPPORT
		call	Disp_String
endif	;MULTI_LANGUAGE_SUPPORT
;R131 - ends
endif ;No_show_Updata_Escd_Msg
		pop	ds

IF BUS_TYPE EQ EISA_BUS
		call	Sort_Escd_Buffer
endif;BUS_TYPE EQ EISA_BUS

ifndef	Temp_No_Flash_Support
		call	Post_Set_Escd
		mov	si, offset EGROUP:Success_Msg
		jnc	short @f
ifdef	DISP_ESCD_FAIL
		mov	si, offset EGROUP:Fail_Msg
else;	DISP_ESCD_FAIL
		mov	si, offset EGROUP:CrLf_Msg
endif;	DISP_ESCD_FAIL

@@:
		mov	ax, cs
		mov	ds, ax
ifndef No_show_Updata_Escd_Msg
;R131		call	Disp_String
;R131 - starts
ifdef	MULTI_LANGUAGE_SUPPORT
		call	Disp_CS_Language
else	;MULTI_LANGUAGE_SUPPORT
		call	Disp_String
endif	;MULTI_LANGUAGE_SUPPORT
;R131 - ends
endif ;No_show_Updata_Escd_Msg
endif	;Temp_No_Flash_Support

Check_PciEscd_Exit:
endif	;ESCD_SUPPORT					;R129

ifdef	DMI_ENABLED
ifdef	FLASH_SUPPORT	;R130
;R108  EXTRN build_dmi_pool:near
;R108  call  build_dmi_pool
	Xcall  build_dmi_pool		;R108
endif	;FLASH_SUPPORT	;R130
endif	;DMI_ENABLED

ifdef	ESCD_SUPPORT
ifdef	ESCD_M2
		mov	ax, G_RAM
		mov	ds, ax
		mov	si, offset ESCD_BUFFER
		mov	ax, 0F000h
		mov	es, ax
		F000_call	Write_ESCD_Shadow
endif	;ESCD_M2
endif	;ESCD_SUPPORT

ifdef	AUTO_DETECT_EEPROM_ID
EEPROM_Type_Not_Found:
endif;	AUTO_DETECT_EEPROM_ID
		popf
		pop	es
		pop	ds
		popad
		ret
PNP_Final_Init	endp

;[]========================================================================[]
;Procedure:	PNP_IPL_Init
;Function :
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	PNP_IPL_Init
		ALIGN	4
PNP_IPL_Init	proc	near
		ret
PNP_IPL_Init	endp

;[]========================================================================[]
;Procedure:	Init_CfgData
;Function :	Initialize default values for CFGDATA structure
;Input	  :	ES:DI = point to CFGDATA data structure
;Output   :	None
;[]========================================================================[]

		ALIGN	4
		Public	Init_CfgData
Init_CfgData	proc	near
		push	ax
		push	cx
		push	di
		mov	cx, (SIZE CFGDATA)
		xor	al, al
		rep	stosb
		pop	di
		pop	cx
		pop	ax
		ret
Init_CfgData	endp

;[]========================================================================[]
;Procedure:	Record_CfgData
;Function :	Record resouces with specified CFGDATA
;Input	  :	ES(DS):DI = point to CFGDATA structure
;Output   :	None
;[]========================================================================[]

		ALIGN	4
		Public	Record_CfgData
Record_CfgData	proc	near
		pushad

; Record memory 24 configuration data

		xor	cx, cx
Record_Mem24:
		mov	cl, ds:[di].Mem24CfgCount
		jcxz	short Record_Mem32
		xor	ax, ax
Record_Mem24_Loop:
		push	ax
		push	cx
		mov	bl, (SIZE MEMCFGDATA)
		mul	bl
		mov	bx, ax
		mov	eax, ds:[bx+di].Mem24Cfg.MemBase
		mov	edx, ds:[bx+di].Mem24Cfg.MemLength
		call	Record_Mem_Map
		pop	cx
		pop	ax
		inc	al
		loop	short Record_Mem24_Loop

; Record memory 32 configuration data

Record_Mem32:
		mov	cl, ds:[di].Mem32CfgCount
		jcxz	short Record_IO
		xor	ax, ax
Record_Mem32_Loop:
		push	ax
		push	cx
		mov	bl, (SIZE MEMCFGDATA)
		mul	bl
		mov	bx, ax
		mov	eax, ds:[bx+di].Mem32Cfg.MemBase
		mov	edx, ds:[bx+di].Mem32Cfg.MemLength
		call	Record_Mem_Map
		pop	cx
		pop	ax
		inc	al
		loop	short Record_Mem32_Loop

; Record I/O port configuration data

Record_IO:
		mov	cl, ds:[di].IoCfgCount
		jcxz	short Record_IRQ
		xor	ax, ax
Record_IO_Loop:
		push	ax
		push	cx
		mov	bl, (SIZE IOCFGDATA)
		mul	bl
		mov	bx, ax
		xor	dx, dx
		mov	ax, ds:[bx+di].IoCfg.IoBase
		mov	dl, ds:[bx+di].IoCfg.IoLength
		call	Record_IO_Map
		pop	cx
		pop	ax
		inc	al
		loop	short Record_IO_Loop

; Record IRQ configuration data

Record_IRQ:
		mov	cl, ds:[di].IrqCfgCount
		jcxz	short Record_DMA
		xor	ax, ax
Record_IRQ_Loop:
		push	ax
		push	cx
		mov	bl, (SIZE IRQCFGDATA)
		mul	bl
		mov	bx, ax
		mov	al, ds:[bx+di].IrqCfg.IrqNum
		call	Record_IRQ_Map
		pop	cx
		pop	ax
		inc	al
		loop	short Record_IRQ_Loop

; Record DMA configuration data

Record_DMA:
		mov	cl, ds:[di].DmaCfgCount
		jcxz	short Record_CfgData_Exit
		xor	ax, ax
Record_DMA_Loop:
		push	ax
		push	cx
		mov	bl, (SIZE DMACFGDATA)
		mul	bl
		mov	bx, ax
		mov	al, ds:[bx+di].DmaCfg.DmaNum
		call	Record_DMA_Map
		pop	cx
		pop	ax
		inc	al
		loop	short Record_DMA_Loop

Record_CfgData_Exit:
		popad
		ret
Record_CfgData	endp

ifdef	PCI_BUS

;R109 - start
ifdef	COMBINE_ISA_ROM
;Input	: EDI - ROM address occupied
		public	Build_OtherRomNode
Build_OtherRomNode	proc	near

		call	Build_OnboardRomNode		;R119

;R119		pushad
;R119		push	ds
;R119		push	es
;R119		call	E_F000_Shadow_W
;R119
;R119		mov	eax,edi
;R119		shr	eax,4
;R119		mov	ds,ax				;seg. of ROM
;R119		cmp	word ptr ds:[0],0AA55H		;ROM signature
;R119		jne	short No_OtherRom
;R119
;R119		movzx	cx,byte ptr ds:[2]		;get ROM size
;R119		or	cx,cx
;R119		jz	short No_OtherRom
;R119		shl	cx,9				;byte size
;R119
;R119		mov	ax,0F000H
;R119		mov	ds,ax
;R119		mov	es,ax
;R119
;R119		mov	eax,edi 			;get ROM address
;R119
;R119		mov	di,offset EndOf_MbRom_Node
;R119ChkNextDsp:
;R119		cmp	word ptr ds:[di],0079H		;DSP ?
;R119		je	short GoBuild_OtherRom		;yes , move data
;R119		inc	di				;check next until
;R119		inc	di
;R119		jmp	short ChkNextDsp		;DSP found
;R119
;R119GoBuild_OtherRom:
;R119		mov	si,offset Onboard_Other_RomNode
;R119
;R119		push	cx
;R119		mov	cx,12				;length to copy
;R119		rep	movsb
;R119		pop	cx
;R119
;R119		mov	word ptr [di-4],cx		;set size of ROM
;R119		mov	dword ptr [di-8],eax		;set addr. of ROM
;R119
;R119		mov	ax,0079H			;END_DSP
;R119		stosw
;R119		stosw
;R119		stosw
;R119
;R119		mov	si,offset MbRom_Node
;R119		add	word ptr [si],12		;modify length
;R119		call	Check_Node_Size 		;R111
;R119
;R119No_OtherRom:
;R119
;R119		call	E_F000_Shadow_R
;R119		pop	es
;R119		pop	ds
;R119		popad
		ret
Build_OtherRomNode	endp
endif;	COMBINE_ISA_ROM
;R109 - end

;Input	: EDI - ROM address occupied
		public	Build_OnboardRomNode
Build_OnboardRomNode	proc	near
		pushad

;R119 - start
		mov	eax,edi 			;ROM address
		shr	eax,4
		mov	ds,ax				;seg. of ROM
		cmp	word ptr ds:[0],0AA55H		;ROM signature
		jne	short No_OnboardRom

		movzx	ebx,byte ptr ds:[2]		;get ROM size
		or	bx,bx
		jz	short No_OnboardRom
		shl	ebx,9				;byte size

		call	Build_MbRomDynamicNode		;build ROM node

No_OnboardRom:
;R119 - end

;R119		push	ds
;R119		push	es
;R119		call	E_F000_Shadow_W 		;R109
;R119 ;R109		F000_CALL F000_Shadow_W
;R119
;R119		mov	eax,edi
;R119		shr	eax,4
;R119		mov	ds,ax				;seg. of ROM
;R119		cmp	word ptr ds:[0],0AA55H		;ROM signature
;R119		jne	short No_OnboardRom
;R119
;R119		movzx	cx,byte ptr ds:[2]		;get ROM size
;R119		or	cx,cx
;R119		jz	short No_OnboardRom
;R119		shl	cx,9				;byte size
;R119
;R119		mov	ax,0F000H
;R119		mov	ds,ax
;R119		mov	es,ax
;R119
;R119		mov	eax,edi 			;get ROM address
;R119
;R119		mov	di,offset EndOf_MbRom_Node
;R119		cmp	word ptr ds:[di],0079H		;DSP ?
;R119		jne	short No_OnboardRom		;no , don't move data
;R119
;R119		mov	si,offset Onboard_Scsi_RomNode
;R119
;R119		mov	word ptr [si+8],cx		;set size of ROM
;R119		mov	dword ptr [si+4],eax		;set addr. of ROM
;R119
;R119		mov	cx,12				;length to copy
;R119		rep	movsb
;R119
;R119		mov	ax,0079H			;END_DSP
;R119		stosw
;R119		stosw
;R119		stosw
;R119
;R119		mov	si,offset MbRom_Node
;R119		add	word ptr [si],12		;modify length
;R119		call	Check_Node_Size 		;R111
;R119
;R119 No_OnboardRom:
;R119
;R119		call	E_F000_Shadow_R 		;R109
;R119 ;R109		F000_CALL F000_Shadow_R
;R119		pop	es
;R119		pop	ds
		popad
		ret
Build_OnboardRomNode	endp

;R119 ;R111 - start
;R119 ; Input:	ES = F000
;R119 Check_Node_Size:
;R119		push	ax
;R119		mov	ax, [si]
;R119		cmp	ax, es:LARGEST_SIZE
;R119		jbe	short @f
;R119		mov	es:LARGEST_SIZE, ax
;R119 @@:
;R119		pop	ax
;R119		ret
;R119 ;R111 - end
endif;	PCI_BUS

ifdef	Add_PIIX4_SMBus_Node
		public	Build_PIIX4_SMBus_Node
Build_PIIX4_SMBus_Node	proc	near
		pushad
		push	ds
		push	es
		call	E_F000_Shadow_W 		;R109
;R109		F000_CALL F000_Shadow_W

;R120 - start
		mov	cx,(PIIX_ID shl 8) + 00h
		F000_call Get_PCI
		cmp	al,86h
		jne	short B0_Stepping

		mov	cx,(PIIX_ID shl 8) + 01h
		F000_call Get_PCI
		cmp	al,80h
		jne	short B0_Stepping

		mov	cx,(PIIX_ID shl 8) + 02h
		F000_call Get_PCI
		cmp	al,10h
		jne	short B0_Stepping

		mov	cx,(PIIX_ID shl 8) + 03h
		F000_call Get_PCI
		cmp	al,71h
		jne	short B0_Stepping
;R120 - end

		mov	cx,(PIIX_ID shl 8) + 08h
		F000_call Get_PCI
		or	al,al
		jnz	short B0_Stepping

		mov	ax,0F000H
		mov	es,ax

		mov	di,offset PIIX4_SMBus_IONode

		mov	ax,0079H			;END_DSP
		stosw
		stosw
		stosw

B0_Stepping:

		call	E_F000_Shadow_R 		;R109
;R109		F000_CALL F000_Shadow_R
		pop	es
		pop	ds
		popad
		ret
Build_PIIX4_SMBus_Node	endp
endif;	Add_PIIX4_SMBus_Node

;R139 - start
ifdef	ICH
Build_ICH_SMBus_Node	Proc	Near
		pushad
		push	ds
		push	es
		call	E_F000_Shadow_W

		mov	cx,(PIIX_ID shl 8) + 08h
		F000_call Get_PCI
		or	al,al
		jnz	short ICH_B0

		mov	ax,0F000H
		mov	es,ax

		mov	di,offset ICH_SMBus_IONode

		mov	ax,0079H			;END_DSP
		stosw
		stosw
		stosw

	ICH_B0:

		call	E_F000_Shadow_R
		pop	es
		pop	ds
		popad
		ret
Build_ICH_SMBus_Node	Endp
endif;	ICH
;R139 - end

ifdef	USB_SUPPORT
;Input	: EDI - ROM address occupied
		public	Build_UsbRamNode
Build_UsbRamNode	proc	near
		pushad

;R126;R125 - start
;R126ifdef	ACPI_SUPPORT
;R126		push	ds
;R126		push	edi
;R126		call	E_F000_Shadow_W
;R126		mov	ax,0F000h
;R126		mov	ds,ax
;R126		mov	eax,edi 			;get ROM address
;R126		shr	eax,8				;base is 256 Byte
;R126		mov	si,offset USB_MEMORY
;R126		mov	ds:[si],ax
;R126		call	E_F000_Shadow_R
;R126		pop	edi
;R126		pop	ds
;R126endif	;ACPI_SUPPORT
;R126;R125 - end
;R119  - start
							;EDI = ROM addr.
		mov	ebx,2000h			;ROM size
		call	Build_MbRomDynamicNode
;R119 - end

;R119		push	ds
;R119		push	es
;R119		call	E_F000_Shadow_W 		;R109
;R119 ;R109		F000_CALL F000_Shadow_W
;R119
;R119		mov	ax,0F000H
;R119		mov	ds,ax
;R119		mov	es,ax
;R119
;R119		mov	eax,edi 			;get ROM address
;R119
;R119		mov	di,offset EndOf_MbRom_Node
;R119 Search_EndDsp:
;R119		cmp	word ptr ds:[di],0079H		;DSP ?
;R119		je	short Set_UsbNode		;yes, go build node
;R119							;for USB
;R119		inc	di				;next address
;R119		inc	di
;R119		jmp	short Search_EndDsp		;find DSP
;R119
;R119 Set_UsbNode:
;R119		mov	si,offset Usb_MemNode
;R119
;R119		mov	dword ptr [si+4],eax		;set addr. of ROM
;R119
;R119		mov	cx,12				;length to copy
;R119		rep	movsb
;R119
;R119		mov	ax,0079H			;END_DSP
;R119		stosw
;R119		stosw
;R119		stosw
;R119
;R119		mov	si,offset MbRom_Node
;R119		add	word ptr [si],12		;modify length
;R119		call	Check_Node_Size 		;R111
;R119
;R119		call	E_F000_Shadow_R 		;R109
;R119 ;R109		F000_CALL F000_Shadow_R
;R119		pop	es
;R119		pop	ds
		popad
		ret
Build_UsbRamNode	endp
endif;	USB_SUPPORT

;R119 - start
;Function: Build Dynamic
;Input	 : EDI - ROM address occupied
;	   ebx - ROM size
;Output  : none
		public	Build_MbRomDynamicNode
Build_MbRomDynamicNode	proc	near
		pushad

		push	ds
		push	es

		push	ebx
		call	E_F000_Shadow_W
		pop	ebx

		mov	ax,0F000H
		mov	ds,ax
		mov	es,ax

		mov	eax,edi 			;get ROM address

;R126 - start
ifdef	ACPI_SUPPORT
		pushad

		mov	si,offset Combined_Rom1 	;start from ROM 1
		sub	si,4
	@@:
		add	si,4
		cmp	si,offset Combined_Rom_End	;last ROM node ?
		je	Skip_Combined_Rom_Node		;yes, no available
							;node
		cmp	word ptr ds:[si],0		;node occupied
		jne	short @B			;yes, search next node

		mov	eax,edi 			;get ROM address
		shr	eax,8				;base is 256 Byte
		mov	ds:[si],ax

		mov	eax,ebx 			;get ROM size
		shr	eax,8				;base is 256 Byte
		mov	ds:[si+2],ax

Skip_Combined_Rom_Node:
		popad
endif	;ACPI_SUPPORT
;R126 - end

		mov	di,offset LastMbNodeShared
Search_MbNode:
		cmp	word ptr [di+6],000FH		;available for change
		je	short Change_MbNode		;node usage ?

		sub	di,12				;previous node
		jmp	short Search_MbNode		;find next node

Change_MbNode:
		cmp	dword ptr [di+4],0F0000H	;first F0000H node ?
		je	short NoAvailableMbNode 	;no node changed

	;Adding current ROM size to previous node
		mov	ecx,dword ptr [di+8]		;ROM size
		add	dword ptr [di-4],ecx		;previous node size

		mov	dword ptr [di+4],eax		;set addr. of ROM
		mov	dword ptr [di+8],ebx		;ROM size

NoAvailableMbNode:

		call	E_F000_Shadow_R
		pop	es
		pop	ds

		popad
		ret
Build_MbRomDynamicNode	endp
;R119 - end

;[]========================================================================[]
;Procedure:	Parse_Tag
;Function :	Parse resource information
;Input	  :	AH = TAG name
;		ES:DI = point to CFGDATA structure
;		DS:SI = point to TAG contain
;		CX = TAG length
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		Public	TAG_CODE
TAG_CODE	label	byte
		db	sIrqFormat
		db	sDmaFormat
		db	sIoPort
		db	sIoPortFixed
		db	lMem24
		db	lMem32
		db	lMemFixed
		Public	TAG_CODE_L
TAG_CODE_L	equ	$ - TAG_CODE

;[]========================================================================[]
;Procedure:	Proc_sIrqFormat_Cfg
;Function :	Add IRQ resource information to CFGDATA
;Input	  :	DS:DI = CFGDATA address
;		DS:SI = IRQ description block
;		DH = IRQ information
;		DL = IRQ channel number
;Output   :	none
;[]========================================================================[]

Proc_sIrqFormat_Cfg:
		mov	al, ds:[di].IrqCfgCount
		mov	bl, (SIZE IRQCFGDATA)
		mul	bl
		mov	bx, ax
		mov	ds:[bx+di].IrqCfg.IrqNum, dl
		mov	ds:[bx+di].IrqCfg.IrqInfo, dh
		inc	byte ptr ds:[di].IrqCfgCount
		ret

;[]========================================================================[]
;Procedure:	Proc_sDmaFormat_Cfg
;Function :	Add DMA resource information to CFGDATA
;Input	  :	DS:DI = CFGDATA address
;		DS:SI = DMA description block
;		DH = DMA information
;		DL = DMA channel number
;Output   :	none
;[]========================================================================[]

Proc_sDmaFormat_Cfg:
		mov	al, ds:[di].DmaCfgCount
		mov	bl, (SIZE DMACFGDATA)
		mul	bl
		mov	bx, ax
		mov	ds:[bx+di].DmaCfg.DmaNum, dl
		mov	ds:[bx+di].DmaCfg.DmaInfo, dh
		inc	byte ptr ds:[di].DmaCfgCount
		ret

;[]========================================================================[]
;Procedure:	Proc_sIoPort_Cfg
;Function :	Add I/O port resource information to CFGDATA
;Input	  :	DS:DI = CFGDATA address
;		DS:SI = I/O port description block
;		AX = I/O port address
;		DH = I/O port information
;		DL = I/O port length
;Output   :	none
;[]========================================================================[]

Proc_sIoPort_Cfg:
		push	ax
		mov	al, ds:[di].IoCfgCount
		mov	bl, (SIZE IOCFGDATA)
		mul	bl
		mov	bx, ax
		pop	ax
		mov	ds:[bx+di].IoCfg.IoBase, ax
		mov	ds:[bx+di].IoCfg.IoLength, dl
		mov	ds:[bx+di].IoCfg.IoInfo, dh
		inc	byte ptr ds:[di].IoCfgCount
		ret

;[]========================================================================[]
;Procedure:	Proc_lMem24_Cfg
;Function :	Add memory 24 resource information to CFGDATA
;Input	  :	DS:DI = CFGDATA address
;		DS:SI = memory 24 description block
;		EAX = memory base address
;		EDX = memory length
;		CH = memory information
;Output   :	none
;[]========================================================================[]

Proc_lMem24_Cfg:
		push	ax
		mov	al, ds:[di].Mem24CfgCount
		mov	bl, (SIZE MEMCFGDATA)
		mul	bl
		mov	bx, ax
		pop	ax
		mov	ds:[bx+di].Mem24Cfg.MemBase, eax
		mov	ds:[bx+di].Mem24Cfg.MemLength, edx
		mov	ds:[bx+di].Mem24Cfg.MemCtrl, ch
		inc	byte ptr ds:[di].Mem24CfgCount
		ret

;[]========================================================================[]
;Procedure:	Proc_lMem32_Cfg
;Function :	Add memory 32 resource information to CFGDATA
;Input	  :	DS:DI = CFGDATA address
;		DS:SI = memory 32 description block
;		EAX = memory base address
;		EDX = memory length
;		CH = memory information
;Output   :	none
;[]========================================================================[]

Proc_lMem32_Cfg:
		push	ax
		mov	al, ds:[di].Mem32CfgCount
		mov	bl, (SIZE MEMCFGDATA)
		mul	bl
		mov	bx, ax
		pop	ax
		mov	ds:[bx+di].Mem32Cfg.MemBase, eax
		mov	ds:[bx+di].Mem32Cfg.MemLength, edx
		mov	ds:[bx+di].Mem32Cfg.MemCtrl, ch
		inc	byte ptr ds:[di].Mem32CfgCount
		ret

;[]========================================================================[]
;Procedure:	Get_Tag_Name
;Function :	Get TAG name and length from specified resource block
;Input	  :	DS:SI = pointer of resouce block
;Output   :	DS:SI = next point to resorce block
;		AH = tag name
;		AL = original tag name value
;		CX = tag length
;[]========================================================================[]
		public	Get_Tag_Name
		ALIGN	4
Get_Tag_Name	proc	near
		lodsb
		xor	cx, cx
		test	al, 80h
		jnz	short @f
		mov	ah, al
		shr	ah, 3
		mov	cl, al			;TAG length in small tag
		and	cl, 07
		jmp	short Get_Tag_Name_Exit
@@:
		mov	ah, al
		lodsb
		mov	cl, al
		lodsb
		mov	ch, al
		mov	al, ah
Get_Tag_Name_Exit:
		ret
Get_Tag_Name	endp

;[]========================================================================[]
;Procedure:	Record_IRQ_Map
;Function :	Record IRQ resource
;Input	  :	DS = G_RAM
;		AL = IRQ level
;Output   :	None
;[]========================================================================[]
		public	Record_IRQ_Map
		ALIGN	4
Record_IRQ_Map	proc	near
		push	ax
		push	cx
		mov	cl, al
		and	cl, 0Fh
		mov	ax, 0FFFEh
		rol	ax, cl
		and	ds:IRQ_MAP, ax
		pop	cx
		pop	ax
		ret
Record_IRQ_Map	endp

;R124 - start
;[]========================================================================[]
;Procedure:	Record_PNP_IRQ_Map
;Function :	Record IRQ resource assigned with ISA/PNP cards
;Input	  :	DS = G_RAM
;		AL = IRQ level
;Output   :	None
;[]========================================================================[]
		public	Record_PNP_IRQ_Map
		ALIGN	4
Record_PNP_IRQ_Map	proc	near
		push	ax
		push	cx
		mov	cl, al
		and	cl, 0Fh
		mov	ax, 0FFFEh
		rol	ax, cl
		and	ds:PNP_IRQ_MAP, ax
		pop	cx
		pop	ax
		ret
Record_PNP_IRQ_Map	endp
;R124 - end

;[]========================================================================[]
;Procedure:	Record_DMA_Map
;Function :	Record DMA resource
;Input	  :	DS = G_RAM
;		AL = DMA chanel
;Output   :	None
;[]========================================================================[]
		public	Record_DMA_Map
		ALIGN	4
Record_DMA_Map	proc	near
		push	ax
		push	cx
		mov	cl, al
		and	cl, 07h
		mov	al, 0FEh
		rol	al, cl
		and	ds:DMA_MAP, al
		pop	cx
		pop	ax
		ret
Record_DMA_Map	endp

;[]========================================================================[]
;Procedure:	Record_IO_Map
;Function :	Record I/O port resource
;Input	  :	DS = G_RAM
;		AX = I/O port base address
;		DX = I/O port length
;Output   :	None
;[]========================================================================[]
		public	Record_IO_Map
		ALIGN	4
Record_IO_Map	proc	near

		cmp	ax, 3F6h
		jne	short @f
		and	byte ptr ds:SPECIAL_IO_MAP, 0FDh
		jmp	short Record_IO_Exit
@@:
		cmp	ax, 376h
		jne	short @f
		and	byte ptr ds:SPECIAL_IO_MAP, 0FEh
		jmp	short Record_IO_Exit
@@:
		cmp	ax, 100h
		jb	short Record_IO_Exit
		cmp	ax, IO_RANGE
		ja	short Record_IO_Exit
@@:
		push	ax
		push	bx
		push	cx
		push	dx
		sub	ax, 100h
		add	dx, ax
		dec	dx			;ending address
		and	ax, IO_MASK		;start addr (n bytes unit)
@@:
		mov	bx, ax
		shr	bx, IO_SHIFT		;n bytes per bit
		mov	cx, bx
		and	cl, 07			;bit position
		shr	bx, 3			;byte position
		mov	ch, 0FEh
		rol	ch, cl
		and	ds:IO_MAP[bx], ch	;point to I/O map
		add	ax, IO_UNIT
		cmp	ax, dx
		jbe	short @b
		pop	dx
		pop	cx
		pop	bx
		pop	ax
Record_IO_Exit:
		ret
Record_IO_Map	endp

;[]========================================================================[]
;Procedure:	Record_Mem_Map
;Function :	Record memory resource
;Input	  :	DS = G_RAM
;		EAX = base address
;		EDX = length
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Record_Mem_Map	proc	near
		pushad
		cmp	eax, 0C0000h
		jb	short Record_Mem_Exit
		cmp	eax, 0E0000h
		jb	short Record_Umb
		cmp	eax, ds:EXTMEM_BASE
		jb	short Record_Mem_Exit

; Record extended memory

Record_ExtMem:
		add	eax, edx
		test	eax, 001FFFFFh	;force next point to 2MB bounary
		jz	short @f
		add	eax, 00200000h
@@:
		and	eax, 0FFE00000h
		mov	ds:EXTMEM_BASE, eax
		jmp	short Record_Mem_Exit

; Record Upper Memory Block

Record_Umb:
		add	edx, eax	;end address
		mov	ecx, eax

		shr	ecx, 12 	;convert to 4KB unit
		and	cl, 01Fh
		test	dx, 0FFFh
		jz	short @f
		add	edx, 1000h
@@:
		shr	edx, 12 	;convert to 4KB unit
		and	dl, 01Fh
		mov	ch, dl
@@:
		mov	edx, 0FFFFFFFEh
		rol	edx, cl
		and	dword ptr ds:UMB_MAP, edx
		and	dword ptr ds:PNPROM_MAP, edx
		inc	cl
		cmp	cl, ch
		jb	short @b
Record_Mem_Exit:
		popad
		ret
Record_Mem_Map	endp

;[]========================================================================[]
;Procedure:	POST_Get_Node
;Function :	Get system device node to RES_BUFFER
;Input	  :	none
;Output   :	AX = return code
;[]========================================================================[]

		ALIGN	4
POST_Get_Node	proc	near
		push	0F000h			;BiosSelector
		push	1			;Control
		push	0			;DevNodeBufSeg
		push	offset RES_BUFFER +2	;DevNodeBufOff
		push	0			;NodeSeg
		push	offset RES_BUFFER	;NodeOff
		push	0001			;Get System Device Node
		FAR_CALL	<offset PNP_BIOS_Real>, 0F000h
		add	sp, 14
		ret
POST_Get_Node	endp

		ALIGN	4
Create_Proc	label	word
		dw	offset EGROUP:Create_sIrqFormat
		dw	offset EGROUP:Create_sDmaFormat
		dw	offset EGROUP:Create_sIoPort
		dw	offset EGROUP:Create_sIoPortFixed
		dw	offset EGROUP:Create_lMem24
		dw	offset EGROUP:Create_lMem32
		dw	offset EGROUP:Create_lMemFixed

;[]========================================================================[]
;Procedure:	Create_sIrqFormat
;Function :	Create IRQ resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Create_sIrqFormat:
		mov	ax, ds:[si]		;IRQ channel mask
		mov	dh, 1			;high true edge sensitive
		cmp	cl, 2			;IRQ info present ?
		je	short @f
		mov	dh, ds:[si+2]		;IRQ information
@@:
		mov	cx, 16
		xor	dl, dl
Create_sIrqFormat_Loop:
		test	al, 01
		jz	short @f
		push	ax
		push	cx
		push	dx
		call	Proc_sIrqFormat_Cfg
		pop	dx
		pop	cx
		pop	ax
@@:
		inc	dl
		shr	ax, 1
		loop	short Create_sIrqFormat_Loop
		ret

;[]========================================================================[]
;Procedure:	Create_sDmaFormat
;Function :	Create DMA resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

Create_sDmaFormat:
		mov	al, ds:[si]		;DMA channel mask
		mov	dh, ds:[si+1]		;DMA information
		mov	cx, 8
		xor	dl, dl
Create_sDmaFormat_Loop:
		test	al, 01
		jz	short @f
		push	ax
		push	cx
		push	dx
		call	Proc_sDmaFormat_Cfg
		pop	dx
		pop	cx
		pop	ax
@@:
		inc	dl
		shr	al, 1
		loop	short Create_sDmaFormat_Loop
		ret

;[]========================================================================[]
;Procedure:	Create_sIoPort
;Function :	Create I/O port resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

Create_sIoPort:
		mov	ax, ds:[si+1]		;I/O port base address
		mov	dl, ds:[si+6]		;I/O port length
		or	dl, dl
		jz	short @f
		mov	dh, ds:[si]		;I/O port information
		call	Proc_sIoPort_Cfg
@@:
		ret

;[]========================================================================[]
;Procedure:	Create_sIoPortFixed
;Function :	Create Fixed I/O port resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

Create_sIoPortFixed:
		mov	ax, ds:[si]		;I/O port base address
		and	ax, 03FFh		;decode 10 bit
		mov	dl, ds:[si+2]		;I/O port length
		or	dl, dl
		jz	short @f
		xor	dh, dh
		call	Proc_sIoPort_Cfg
@@:
		ret

;[]========================================================================[]
;Procedure:	Create_lMem24
;Function :	Create memory 24 resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

Create_lMem24:
		xor	eax, eax
		xor	edx, edx
		mov	cl, 8
		mov	ax, ds:[si+1]		;minimum base address
		shl	eax, cl 		;convert to 32-bit address
		mov	dx, ds:[si+7]		;range length
		shl	edx, cl 		;convert to 32-bit size
		call	Proc_lMem24_Cfg
		ret

;[]========================================================================[]
;Procedure:	Create_lMem32
;Function :	Create memory 32 resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

Create_lMem32:
		mov	eax, ds:[si+1]		;minimum base address
		mov	edx, ds:[si+13] 	;range length
		call	Proc_lMem32_Cfg
		ret

;[]========================================================================[]
;Procedure:	Create_lMemFixed
;Function :	Create Fixed memory resource information to CFGDATA
;Input	  :	DS(ES):SI = point to description block
;		DS(ES):DI = point to CFGDATA
;Output   :	none
;[]========================================================================[]

Create_lMemFixed:
		mov	eax, ds:[si+1]		;minimum base address
		mov	edx, ds:[si+5]		;range length
		call	Proc_lMem32_Cfg
		ret

;[]========================================================================[]
;Procedure:	Disp_String
;Function :	Display string (terminated with null)
;Input	  :	DS:SI = pointer of string
;Output   :	none
;[]========================================================================[]

		public	Disp_String
		ALIGN	4
Disp_String	proc	near
		lodsb
		or	al, al
		jz	short @f
		call	Display_Char
		jmp	short Disp_String
@@:
		ret
Disp_String	endp

;[]========================================================================[]
;Procedure:	Display_Char
;Function :	Display one character
;Input	  :	AL = character
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Display_Char	proc	near
		mov	ah, 0Eh
		int	10h
		ret
Display_Char	endp

ifndef	NO_ISA_PNP					;R118A
ifdef	SHOW_ISAPNP_M1					;R118A
;[]========================================================================[]
;Procedure:	Disp_ID_String
;Function :	Scan "Identifier string(ANSI)" tag from specified resource
;		block and display it
;Input	  :	DS:SI = pointer of resource block
;		ES:DI = pointer of string buffer
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Disp_ID_String	proc	near
		push	ax
		push	cx
		push	si
@@:
		call	Get_Tag_Name
		cmp	ah, sEndTag
		je	Scan_ID_Exit
		cmp	ah, lAnsiIdString
		je	Scan_ID_Found
		add	si, cx
		jmp	short @b
Scan_ID_Found:
		jcxz	short Scan_ID_Exit
		cmp	cx, 40
		jbe	short @f
		mov	cx, 40
@@:
		rep	movsb
Scan_ID_Exit:
		mov	ax, 0A0Dh
		stosw
		xor	al, al
		stosb
		mov	si, offset STR_BUFFER
ifndef No_show_Updata_Escd_Msg
		call	Disp_String
endif ;No_show_Updata_Escd_Msg
		pop	si
		pop	cx
		pop	ax
		ret
Disp_ID_String	endp

;[]========================================================================[]
;Procedure:	Trans_AL
;Function :	Convert AL contain to ASCII and store to memory buffer
;Input	  :	AL = value
;		ES:DI = buffer to store
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Trans_AL	proc	near
		push	ax
		mov	ah, al
		shr	al, 4
		add	al, 30h
		cmp	al, 39h
		jbe	short @f
		add	al, 7
@@:
		stosb
		mov	al, ah
		and	al, 0Fh
		add	al, 30h
		cmp	al, 39h
		jbe	short @f
		add	al, 7
@@:
		stosb
		pop	ax
		ret
Trans_AL	endp
endif	;SHOW_ISAPNP_M1					;R118A
endif	;NO_ISA_PNP					;R118A

ifdef	NEW_SUPERIO_KERNEL
;[]========================================================================[]
; Input:	AL = device number
;			00 = COM1
;			01 = COM2
;			02 = LPT
; Output:	CF = 0 device found
;			AX = I/O port address
;		CF = 1 device not found
;[]========================================================================[]
		public	Get_Node_IO
		ALIGN	4
Get_Node_IO	proc	near
		push	ds
		push	si
		push	bx
		push	cx
		push	dx

		cmp	al, Device_Index_Num
		jae	short Search_Node_Fail

		xor	ah, ah
		shl	ax, 2				;*4
		mov	bx, offset EGROUP:Device_Index
		add	bx, ax
		mov	dx, cs:[bx]			;device id 0/1
		mov	bx, cs:[bx+2]			;device id 2/device no

		xor	ax, ax
		mov	ds, ax
		mov	word ptr ds:RES_BUFFER, ax	;node number
Search_Node_Loop:
		call	POST_Get_Node
		or	ax, ax
		jnz	short Search_Node_Fail		;get node error ?

		mov	si, offset RES_BUFFER+2
		cmp	word ptr ds:[si+3], dx
		jne	short Search_Node_Next
		cmp	byte ptr ds:[si+5], bl
		jne	short Search_Node_Next
		or	bh, bh
		jz	short Search_Node_Match
		dec	bh
Search_Node_Next:
		cmp	byte ptr es:RES_BUFFER, 0FFh	;last node
		jne	short Search_Node_Loop

Search_Node_Fail:
		mov	ax, -1				;none
		stc
Search_Node_Exit:
		pop	dx
		pop	cx
		pop	bx
		pop	si
		pop	ds
		ret
Search_Node_Match:
		lea	si, ds:[si+12]		;alocated resource start
@@:
		call	Get_Tag_Name
		cmp	ah, sEndTag		;end resource information
		je	short Search_Node_Fail
		cmp	ah, sIoPortFixed	;fixed I/O port descriptor
		je	short Search_Node_Success
		cmp	ah, sIoPort		;I/O port descriptor
		je	short @f
		add	si, cx			;next resource block
		jmp	short @b
@@:
		inc	si

Search_Node_Success:
		mov	ax, ds:[si]
		clc
		jmp	short Search_Node_Exit
Get_Node_IO	endp

Device_Index	label	byte
;			device ID 0, 1, 2, device no
		db	41h, 0D0h, 05, 0			;COM1
		db	41h, 0D0h, 05, 1			;COM2
		db	41h, 0D0h, 04, 0			;LPT
Device_Index_Num	equ	($ - offset Device_Index)/4

endif	;NEW_SUPERIO_KERNEL

		Public	F000_Ct_Set_Shadow
F000_Ct_Set_Shadow:
		F000_call	Ct_Set_Shadow
		ret
		Public	F000_Ct_Buffer_Request
F000_Ct_Buffer_Request:
		F000_call	Ct_Buffer_Request
		ret
ifdef	PCI_BUS
F000_Ct_Pci_Escd:
		F000_call	Ct_Pci_Escd
		ret
endif	;PCI_BUS

ifndef	NO_ISA_PNP					;R129
;************************************************************************
;*									*
;*		PROCESS ISA/PNP MODULE					*
;*									*
;************************************************************************

		ALIGN	4
		Public	Clear_PnpReg
Clear_PnpReg	proc	near
		push	ax
		push	cx
		push	si

		xor	ah, ah
		mov	si, offset EGROUP:MEM24_REG
		mov	cx, MEM24_REG_L
@@:
		lods	byte ptr cs:[si]
		call	Set_Pnp_Reg
		inc	al
		call	Set_Pnp_Reg
		loop	short @b

		mov	si, offset EGROUP:MEM32_REG
		mov	cx, MEM32_REG_L
@@:
		lods	byte ptr cs:[si]
		call	Set_Pnp_Reg
		inc	al
		call	Set_Pnp_Reg
		inc	al
		call	Set_Pnp_Reg
		inc	al
		call	Set_Pnp_Reg
		loop	short @b

		mov	si, offset EGROUP:IO_REG
		mov	cx, IO_REG_L
@@:
		lods	byte ptr cs:[si]
		call	Set_Pnp_Reg
		inc	al
		call	Set_Pnp_Reg
		loop	short @b

		mov	si, offset EGROUP:IRQ_REG
		mov	cx, IRQ_REG_L
@@:
		lods	byte ptr cs:[si]
		call	Set_Pnp_Reg
		loop	short @b

		mov	ah, 04
		mov	si, offset EGROUP:DMA_REG
		mov	cx, DMA_REG_L
@@:
		lods	byte ptr cs:[si]
		call	Set_Pnp_Reg
		loop	short @b

		pop	si
		pop	cx
		pop	ax
		ret
Clear_PnpReg	endp

;[]========================================================================[]
;Procedure:	Prog_PnPDev
;Function :	Program PnP device with CFGDATA buffer
;Input	  :	DS:DI = point to CFGDATA buffer
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Prog_PnPDev
Prog_PnPDev	proc	near
		pushad

; Program memory 24 configuration registers

		xor	cx, cx
Prog_Mem24Reg:
		mov	cl, ds:[di].Mem24CfgCount
		jcxz	short Prog_Mem32Reg
		xor	ax, ax
Prog_Mem24Reg_Loop:
		push	ax
		push	cx
		mov	si, offset EGROUP:MEM24_REG
		add	si, ax
		mov	bl, (SIZE MEMCFGDATA)
		mul	bl
		mov	bx, ax
		mov	eax, ds:[bx+di].Mem24Cfg.MemBase
		mov	edx, ds:[bx+di].Mem24Cfg.MemLength

		shr	eax, 8
		shr	edx, 8
		push	ax
		mov	cl, al			;save AL
		mov	al, cs:[si]		;memory base high register
		call	Set_PnP_Reg
		mov	ah, cl			;restore AL
		inc	al			;memory base low register
		call	Set_PnP_Reg

		inc	al
		push	ax
		push	dx
		mov	dx, ds:TEMP_PNP_RD
		call	Get_PnP_Reg		;memory control
		pop	dx
		mov	ch, al
		pop	ax
		pop	bx
		add	bx, dx			;upper limit address
		test	ch, 01			;check range length/upper limit
		jnz	short @f
		dec	dx
		not	dx
		mov	bx, dx			;range length
@@:
		mov	ah, bh
		inc	al			;memory upper limit high
		call	Set_PnP_Reg
		mov	ah, bl
		inc	al			;memory upper limit low
		call	Set_PnP_Reg
		pop	cx
		pop	ax
		inc	al
		loop	short Prog_Mem24Reg_Loop

; Program memory 32 configuration registers

Prog_Mem32Reg:
		mov	cl, ds:[di].Mem32CfgCount
		jcxz	short Prog_IoReg
		xor	ax, ax
Prog_Mem32Reg_Loop:
		push	ax
		push	cx
		mov	si, offset EGROUP:MEM32_REG
		add	si, ax
		mov	bl, (SIZE MEMCFGDATA)
		mul	bl
		mov	bx, ax
		mov	eax, ds:[bx+di].Mem32Cfg.MemBase
		mov	edx, ds:[bx+di].Mem32Cfg.MemLength

		push	eax
		push	bx
		mov	ebx, eax
		mov	al, cs:[si]		;memory base high register
		mov	cx, 4
@@:
		rol	ebx, 8
		mov	ah, bl
		call	Set_PnP_Reg		;memory base address
		inc	al
		loop	short @b
		pop	bx

		push	ax
		push	dx
		mov	dx, ds:TEMP_PNP_RD
		call	Get_PnP_Reg		;memory control
		pop	dx
		mov	ch, al
		pop	ax
		pop	ebx
		add	ebx, edx		;upper limit address
		test	ch, 01			;check range length/upper limit
		jnz	short @f
		dec	edx
		not	edx
		mov	ebx, edx		;range length
@@:
		mov	cx, 4
@@:
		rol	ebx, 8
		mov	ah, bl
		inc	al
		call	Set_PnP_Reg		;memory upper limit
		loop	short @b
		pop	cx
		pop	ax
		inc	al
		loop	short Prog_Mem32Reg_Loop

; Program I/O port configuration registers

Prog_IoReg:
		mov	cl, ds:[di].IoCfgCount
		jcxz	short Prog_IrqReg
		xor	ax, ax
Prog_IoReg_Loop:
		push	ax
		push	cx
		mov	si, offset EGROUP:IO_REG
		add	si, ax
		mov	bl, (SIZE IOCFGDATA)
		mul	bl
		mov	bx, ax
		xor	dx, dx
		mov	ax, ds:[bx+di].IoCfg.IoBase
		mov	dl, ds:[bx+di].IoCfg.IoLength

		mov	dl, al
		mov	al, cs:[si]		;I/O port base address high
		call	Set_PnP_Reg
		inc	al			;I/O port base address low
		mov	ah, dl
		call	Set_PnP_Reg
		pop	cx
		pop	ax
		inc	al
		loop	short Prog_IoReg_Loop

; Program IRQ configuration registers

Prog_IrqReg:
		mov	cl, ds:[di].IrqCfgCount
		jcxz	short Prog_DmaReg
		xor	ax, ax
Prog_IrqReg_Loop:
		push	ax
		push	cx
		mov	si, offset EGROUP:IRQ_REG
		add	si, ax
		mov	bl, (SIZE IRQCFGDATA)
		mul	bl
		mov	bx, ax
		mov	al, ds:[bx+di].IrqCfg.IrqNum
		call	Record_PNP_IRQ_Map	;R124

		mov	ah, al
		mov	al, cs:[si]		;IRQ level register
		call	Set_PnP_Reg
		inc	al			;IRQ type register
		mov	ah, 02			;high true edge
		call	Set_PnP_Reg
		pop	cx
		pop	ax
		inc	al
		loop	short Prog_IrqReg_Loop

; Program DMA configuration registers

Prog_DmaReg:
		mov	cl, ds:[di].DmaCfgCount
		jcxz	short Prog_PnPDev_Exit
		xor	ax, ax
Prog_DmaReg_Loop:
		push	ax
		push	cx
		mov	si, offset EGROUP:DMA_REG
		add	si, ax
		mov	bl, (SIZE DMACFGDATA)
		mul	bl
		mov	bx, ax
		mov	al, ds:[bx+di].DmaCfg.DmaNum

		mov	ah, al
		mov	al, cs:[si]		;DMA channel register
		call	Set_PnP_Reg
		pop	cx
		pop	ax
		inc	al
		loop	short Prog_DmaReg_Loop

; All configuration programed

Prog_PnPDev_Exit:
		popad
		ret
Prog_PnPDev	endp

; Configuration registers address definition

MEM24_REG	label	byte
		db	40h
		db	48h
		db	50h
		db	58h
MEM24_REG_L	equ	$ - offset MEM24_REG

MEM32_REG	label	byte
		db	76h
		db	80h
		db	90h
		db	0A0h
MEM32_REG_L	equ	$ - offset MEM32_REG

IO_REG		label	byte
		db	60h
		db	62h
		db	64h
		db	66h
		db	68h
		db	6Ah
		db	6Ch
		db	6Eh
IO_REG_L	equ	$ - offset IO_REG

IRQ_REG 	label	byte
		db	70h
		db	72h
IRQ_REG_L	equ	$ - offset IRQ_REG

DMA_REG 	label	byte
		db	74h
		db	75h
DMA_REG_L	equ	$ - offset DMA_REG

;[]========================================================================[]
;Procedure:	Init_PnP_ROM
;Function :	Check UMB memory assigned and Far call expansion ROM
;Input	  :	ES(DS):DI = point to CFGDATA buffer
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Init_PnP_ROM	proc	near
		pusha
		push	ds
		push	es
		mov	di, offset CfgBuffer
		xor	cx, cx
		mov	cl, ds:[di].Mem24CfgCount
		lea	si, ds:[di].Mem24Cfg
Init_PnPROM_Loop1:
		push	cx
		xor	ch, ch
		jcxz	short Init_PnPROM_Next
		xor	ax, ax
Init_PnPROM_Loop2:
		push	ax
		push	cx
		push	si
		push	di
		push	ds
		mov	ah, SIZE MEMCFGDATA
		mul	ah
		mov	bx, ax
		mov	edx, ds:[bx+si].MemLength
		mov	ebx, ds:[bx+si].MemBase
		cmp	ebx, 0C8000h
		jb	short @f
		cmp	ebx, 0E0000h
		jae	short @f
		mov	cl, 14
		shr	ebx, cl
		shr	edx, cl
		and	bx, 07
		mov	al, ds:CSN_CNT
Record_PnpRomMap:
		mov	ds:PnpRomMap[bx], al
		inc	bl
		cmp	bl, dl
		jb	short Record_PnpRomMap
@@:
		pop	ds
		pop	di
		pop	si
		pop	cx
		pop	ax
		inc	al
		loop	short Init_PnPROM_Loop2
Init_PnPROM_Next:
		pop	cx
		or	ch, ch
		jnz	short @f
		inc	ch
		mov	cl, ds:[di].Mem32CfgCount
		lea	si, ds:[di].Mem32Cfg
		jmp	short Init_PnPROM_Loop1
@@:
		pop	es
		pop	ds
		popa
		ret
Init_PnP_ROM	endp

;[]========================================================================[]
;Procedure:	Reset_Devices
;Function :	Reset all PnP cards
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	Reset_Devices
		ALIGN	4
Reset_Devices	proc	near
		push	ax
		mov	al, CFG_CTRL
		mov	ah, 07
		call	Set_PnP_Reg
		pop	ax
		ret
Reset_Devices	endp

;[]========================================================================[]
;Procedure:	Wait_For_Key
;Function :	All PnP cards enter "Wait for Key" state.
;Input	  :	None
;Output   :	None
;[]========================================================================[]

		ALIGN	4
		Public	Wait_For_Key
Wait_For_Key	proc	near
		push	ax
		mov	al, CFG_CTRL
		mov	ah, 02
		call	Set_PnP_Reg
		pop	ax
		ret
Wait_For_Key	endp

;[]========================================================================[]
;Procedure:	Initiation_Key
;Function :	Issue Initiation Key to all PnP cards
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	Initiation_Key
		ALIGN	4
Initiation_Key	proc	near

; Reset LFSR to default value

		xor	al, al
		mov	dx, PNP_ADDR
		out	dx, al
		IODELAY
		out	dx, al
		IODELAY

; Send Initiation Key values
; Formula:	X0 = 6Ah
;		Xn+1[m] = Xn[m+1]
;		Xn+1[7] = Xn[0] XOR Xn[1]
;		m = 0...6 (bit)
;		n = 0...31 (byte)

		mov	ah, LFSR_INIT		; LFSR initial value
		mov	cx, 32			; 32 bytes writed
@@:
		mov	al, ah
		out	dx, al
		IODELAY

		shr	al, 1
		and	al, 1
		xor	ah, al			; Xn[0] XOR Xn[1]

		ror	ah, 1			; Xn+1[m] = Xn[m+1]
						; Xn+1[7] = Xn[0] XOR Xn[1]
		loop	short @b

		ret
Initiation_Key	endp

;[]========================================================================[]
;Procedure:	Isolation
;Function :	Isolate one PnP device
;Input	  :	DX = READ_DATA port address
;Output   :	CF = 0	: isolation successful
;		CF = 1	: no other PnP device to be isolated
;[]========================================================================[]
		public	Isolation
		ALIGN	4
Isolation	proc	near
		push	ax
		push	bx
		push	cx

; Send Wake[0] command, force all not yet isolated PnP devices to enter
; Isolation state

		call	Force_Sleep		;all PnP enter sleep state

; Set READ_DATA port

		mov	ax, dx
		call	Set_READ_DATA

; Delay 1 msec prior to first read

		call	Delay_1ms

; Perform 64 bits serial read
; Checksum formula:
;		X0 = 6Ah
;		Xn+1[m] = Xn[m+1]
;		Xn+1[7] = Xn[0] XOR Xn[1] XOR SerialData

		mov	cx, 64
		mov	bl, LFSR_INIT
		mov	bh, 0FFh		; flag for no 55AAh received
S_Isolate_Loop:
		mov	al, bl
		shr	al, 1
		and	al, 1
		xor	bl, al			; Xn[0] XOR Xn[1]
		call	Delay_250us
		call	Read_One_Bit
		cmp	ax, 55AAh
		jne	short @f
		mov	al, 1
		xor	bh, bh
		jmp	short Next_Bit
@@:
		mov	al, 0
Next_Bit:
ifdef	PROC_SPECIAL_ISAPNP			;R138
		call	Save_Serial_ID_Bit	;R138
endif	;PROC_SPECIAL_ISAPNP			;R138
		xor	bl, al			; Xn[0] XOR Xn[1] XOR SerialData
		ror	bl, 1			; Xn+1[7] =
						; Xn[0] XOR Xn[1] XOR SerialData
		loop	short S_Isolate_Loop

; Check no 55AAh received

		or	bh, bh
		jnz	short Isolate_Fail

; Read checksum byte

		mov	cx, 8
Checksum_Loop:
		call	Delay_250us
		call	Read_One_Bit
		cmp	ax, 55AAh
		jne	short @f
		stc
		jmp	short Next_Sum
@@:
		clc
Next_Sum:
		rcr	bh, 1
		loop	short Checksum_Loop

		clc				; successful
		jmp	short @f
Isolate_Fail:
		stc				; fail
@@:
		pop	cx
		pop	bx
		pop	ax
		ret
Isolation	endp
;R138 -start
ifdef	PROC_SPECIAL_ISAPNP

;[]========================================================================[]
;Procedure:	Save_Serial_ID_Bit
;Function :	Save every serial bit during ISOLATION 
;		to SERIAL_ID[0] ~ SERIAL_ID[7]
;		(ps: Don't save checksum 8 bits)
;
;Input	  :	AL , CX
;Output   :	SERIAL_ID[0] ~ SERIAL_ID[7]
;[]========================================================================[]
Byte_Mask_Count	EQU	00111000b
Bit_Mask_Count	EQU	00000111b

Save_Serial_ID_Bit	proc	near

		pusha

		dec	cl
		mov	bl,cl

		xor	bl,0FFh			; NOT cx
		and	bl,Byte_Mask_Count	
		shr	bl,3
		movzx	si,bl			; SI pointer

		xor	cl,0FFh			
		and	cl,Bit_Mask_Count
	
		mov 	ah,01				;;;clear bit
		shl	ah,cl				;;;
		xor	ah,0FFh				;;;
		and	byte ptr ds:SERIAL_ID[si],ah	;;;

		shl	al,cl				;;;set bit
		or	byte ptr ds:SERIAL_ID[si],al

		popa
		ret

Save_Serial_ID_Bit	endp

endif	;PROC_SPECIAL_ISAPNP
;R138 - end

;[]========================================================================[]
;Procedure:	Read_One_Bit
;Function :	Read one bit in Isolation procedure
;Input	  :	DX = READ_DATA port address value
;Output   :	AX = value read
;[]========================================================================[]
		public	Read_One_Bit
Read_One_Bit	proc
		push	dx
		push	dx
		mov	dx, PNP_ADDR
		mov	al, S_ISOLATE
		out	dx, al
		IODELAY
		pop	dx
		in	al, dx
		IODELAY
		mov	ah, al
		mov	dx, PNP_ADDR
		mov	al, S_ISOLATE
		out	dx, al
		IODELAY
		pop	dx
		in	al, dx
		IODELAY
		ret
Read_One_Bit	endp

;[]========================================================================[]
;Procedure:	Get_SerialId
;Function :	Read serial ID in first 9 bytes of information register
;Input	  :	AL = CSN
;		ES = G_RAM
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Get_SerialId
Get_SerialId	proc	near
		push	ax
		push	cx
		push	di
		mov	di, offset SERIAL_ID
		mov	cx, 9
		mul	cl
		add	di, ax
@@:
		call	Get_Resource_Byte
		jc	short @f
		stosb
		loop	short @b
		clc
@@:
		pop	di
		pop	cx
		pop	ax
		ret
Get_SerialId	endp

;[]========================================================================[]
;Procedure:	Find_LogicDev
;Function :	Find logical device ID in resource information data block
;		and match the CSN/Logical Device Number
;Input	  :	AL = CSN number
;		AH = Logical Device Number
;Output   :	CF = 1 specified logical device not found
;		CF = 0 logical device found
;			DS:SI = Logical Device ID string
;			STR_BUFFER = ANSI string of card		;R118
;[]========================================================================[]
		public	Find_LogicDev
		ALIGN	4
Find_LogicDev	proc	near
		push	ax
		push	bx
		xor	bl, bl
		mov	bh, ah
		call	Force_Sleep
		call	Set_Wake_CSN
		call	Get_SerialId
		jc	short Find_LogicDev_Fail
;R118 - start
Find_Card_String:
		call	Get_Resource_Block
		jc	short Find_LogicDev_Fail
		cmp	ah, lAnsiIdString
		jne	short @f
		call	Get_PNP_String
@@:
		cmp	ah, sEndTag
		je	short Find_LogicDev_Fail
		cmp	ah, sLogicDevId
		je	short Find_LogicDev_Cont
		jmp	short Find_Card_String
;R118 - end
Find_LogicDev_Loop:
		call	Get_Resource_Block
		jc	short Find_LogicDev_Fail
		cmp	ah, sEndTag
		jne	short @f
Find_LogicDev_Fail:
		pop	bx
		pop	ax
		stc
		ret
@@:
Find_LogicDev_Cont:					;R118
		cmp	ah, sLogicDevId
		jne	short Find_LogicDev_Loop
		cmp	bl, bh
		je	short @f
		inc	bl
		jmp	short Find_LogicDev_Loop
@@:
		pop	bx
		pop	ax
		clc
		ret
Find_LogicDev	endp

;R118 - start
;[]========================================================================[]
;Procedure:	Get_LogicDev_String
;Function :	Find logical device ID string in resource information data
;		block and match the CSN/Logical Device Number
;Input	  :	AL = CSN number
;		AH = Logical Device Number
;Output   :	CF = 1 specified logical device not found
;		CF = 0 logical device found
;			STR_BUFFER = ANSI string of logical device
;[]========================================================================[]

		public	Get_LogicDev_String
Get_LogicDev_String	proc	near
		pusha

		call	Find_LogicDev
		jc	short Get_LogicDev_String_Fail
Get_LogicDev_String_Loop:
		call	Get_Resource_Block
		jc	short Get_LogicDev_String_Fail

		cmp	ah, sEndTag
		je	short Get_LogicDev_String_Exit
		cmp	ah, sLogicDevId
		je	short Get_LogicDev_String_Exit

		cmp	ah, lAnsiIdString
		jne	short Get_LogicDev_String_Loop

		call	Get_PNP_String

Get_LogicDev_String_Exit:
		popa
		clc
		ret

Get_LogicDev_String_Fail:
		popa
		stc
		ret
Get_LogicDev_String	endp

;Input: 	CX = string length
;		DS:SI = source
;Output:	STR_BUFFER = destination

Get_PNP_String:
		pusha
		mov	di, offset STR_BUFFER

		cmp	cx, 40
		jbe	short @f
		mov	cx, 40
@@:
		lodsb
		cmp	al, 20h
		jb	short @f
		stosb
		loop	short @b
@@:
		xor	al, al			;end string
		stosb
		popa
		ret

		public	Wake_All_Cards
Wake_All_Cards:
		call	Wait_For_Key
		call	Delay_1ms
		call	Initiation_Key
		ret
;R118 - end

;[]========================================================================[]
;Procedure:	Get_Resource_Block
;Function :	Get one item resource informations from resource data register
;Input	  :	DX = READ_DATA port address
;		DS, ES = G_RAM
;Output   :	AH = tag name
;		AL = original tag name value
;		CX = tag length
;		DS:SI = resource data
;[]========================================================================[]
		public	Get_Resource_Block
		ALIGN	4
Get_Resource_Block	proc	near
		push	di
		mov	di, offset RES_BUFFER
		call	Get_Resource_Block1
		jnc	short @f
		pop	di
		ret
@@:
		mov	si, offset RES_BUFFER
		call	Get_Tag_Name
		pop	di
		clc
		ret

Get_Resource_Block1:
		call	Get_Resource_Byte	;get Item Name
		jc	short Get_ResBlock_Fail
		cmp	al, 0FFh
		je	short Get_ResBlock_Fail

		stosb

		xor	cx, cx
		test	al, 80h 		;check small/large item
		jnz	short @f		;jump if large item

		and	al, 07
		mov	cl, al			;TAG length in small item
		jmp	short Get_ResBlock_Cont

@@:
		call	Get_Resource_Byte	;Large item length byte low
		jc	short Get_ResBlock_Fail
		stosb
		mov	cl, al
		call	Get_Resource_Byte	;Large item length byte high
		jc	short Get_ResBlock_Fail
		stosb
		mov	ch, al

Get_ResBlock_Cont:
		jcxz	short Get_ResBlock_Exit

		push	cx
		cmp	cx, RES_BUFFER_L-3
		jbe	short Get_ResBlock_Loop
		mov	cx, RES_BUFFER_L-3
Get_ResBlock_Loop:
		call	Get_Resource_Byte
		jc	short Get_ResBlock_Fail1
		stosb
		loop	short Get_ResBlock_Loop
		pop	cx

		sub	cx, RES_BUFFER_L-3
		jbe	short Get_ResBlock_Exit
@@:
		call	Get_Resource_Byte
		jc	short Get_ResBlock_Fail
		loop	short @b
		jmp	short Get_ResBlock_Fail
Get_ResBlock_Fail1:
		pop	cx
Get_ResBlock_Fail:
		stc
		ret
Get_ResBlock_Exit:
		clc
		ret
Get_Resource_Block	endp

;[]========================================================================[]
;Procedure:	Get_Resource_Byte
;Function :	Get one byte resource information from resource data register
;Input	  :	DX = READ_DATA port address
;Output   :	AL = Resource data read
;[]========================================================================[]
		public	Get_Resource_Byte
		ALIGN	4
Get_Resource_Byte	proc	near
		push	cx
		push	dx
		mov	dx, PNP_ADDR
		mov	al, STS_REG
		out	dx, al
		jmp	short $+2
		pop	dx
		mov	cx, 20
@@:
		in	al, dx
		test	al, 1
		jnz	short @f
		call	Delay_250us
		loop	short @b
		pop	cx
		stc
		ret
@@:
		mov	al, RES_DATA
		call	Get_PnP_Reg
		pop	cx
		clc
		ret
Get_Resource_Byte	endp

;[]========================================================================[]
;Procedure:	Set_READ_DATA
;Function :	Set READ_DATA port address for PnP card
;Input	  :	AX = Port address value
;Output   :	None
;[]========================================================================[]
		public	Set_READ_DATA
		ALIGN	4
Set_READ_DATA	proc	near
		push	ax
		shr	ax, 2
		mov	ah, al
		xor	al, al			; "Set RD_DATA port" register
		call	Set_PnP_Reg
		pop	ax
		ret
Set_READ_DATA	endp

;[]========================================================================[]
;Procedure:	Assign_CSN
;Function :	Assign a CSN for current isolated PnP card
;Input	  :	AL = CSN
;R121;Output   :	None
;Output   :	CF = 0 set CSN successful				;R121
;		CF = 1 set CSN fail					;R121
;[]========================================================================[]
		public	Assign_CSN
		ALIGN	4
Assign_CSN	proc	near
		push	ax
		mov	ah, al
		mov	al, CSN_REG		; CSN register
		call	Set_PnP_Reg
;R121 - start
; Check CSN set correctly
		NEWIODELAY
		call	Get_PnP_Reg
		cmp	al, ah
		clc				; set CSN successful
		je	short @f
		stc				; set CSN fail
@@:
;R121 - end
		pop	ax
		ret
Assign_CSN	endp

;[]========================================================================[]
;Procedure:	Force_Sleep
;Function :	Force all PnP cards to enter sleep state
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	Force_Sleep
		ALIGN	4
Force_Sleep	proc	near
		push	ax
		xor	al, al
		call	Set_Wake_CSN
		push	cx
		mov	cx, 10
@@:
		call	Delay_1ms
		loop	short @b
		pop	cx
		pop	ax
		ret
Force_Sleep	endp

;[]========================================================================[]
;Procedure:	Set_Wake_CSN
;Function :	Issue Wake[CSN] command for the corresponding PnP card
;		to enter configure mode
;Input	  :	AL = CSN
;Output   :	None
;[]========================================================================[]
		public	Set_Wake_CSN
		ALIGN	4
Set_Wake_CSN	proc	near
		push	ax
		mov	ah, al
		mov	al, WAKE_CSN		; WAKE[CSN] register
		call	Set_PnP_Reg
		pop	ax
		ret
Set_Wake_CSN	endp

;[]========================================================================[]
;Procedure:	Get_PnP_Reg
;Function :	Read PnP card control register
;Input	  :	AL = PnP regiser index
;		DX = READ_DATA port address
;Output   :	AL = value read
;[]========================================================================[]
		public	Get_PnP_Reg
		ALIGN	4
Get_PnP_Reg	proc	near
		push	dx
		mov	dx, PNP_ADDR
		out	dx, al
		NEWIODELAY
		pop	dx
		in	al, dx
		ret
Get_PnP_Reg	endp

;[]========================================================================[]
;Procedure:	Set_PnP_Reg
;Function :	Write PnP card control register
;Input	  :	AL = PnP regiser index
;		AH = value to write
;Output   :	None
;Registers:
;Note	  :
;[]========================================================================[]
		public	Set_PnP_Reg
		ALIGN	4
Set_PnP_Reg	proc	near
		push	dx
		mov	dx, PNP_ADDR
		out	dx, al
		NEWIODELAY
		xchg	al, ah
		mov	dx, PNP_WR
		out	dx, al
		NEWIODELAY
		xchg	al, ah
		pop	dx
		ret
Set_PnP_Reg	endp

;[]========================================================================[]
;Procedure:	Delay_1ms
;Function :	Delay 1 msec for PnP card after reset, first read in isolation
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	Delay_1ms
		ALIGN	4
Delay_1ms	proc	near
		push	bx
		push	cx
		xor	bx, bx
		mov	cx, WAIT_PNP_1MS
		call	F000_Wait_Refresh
		pop	cx
		pop	bx
		ret
Delay_1ms	endp

;[]========================================================================[]
;Procedure:	Delay_250us
;Function :	Delay 250 usec for very time read in isolation procedure
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	Delay_250us
		ALIGN	4
Delay_250us	proc	near
		push	bx
		push	cx
		xor	bx, bx
		mov	cx, WAIT_PNP_250US
		call	F000_Wait_Refresh
		pop	cx
		pop	bx
		ret
Delay_250us	endp

;[]========================================================================[]
;Procedure:	Check_Special_IRQ
;Function :	Check special IRQ request according to special I/O port
;Input	  :	DS:SI = IRQ description block
;		DS:DI = CFGDATA address
;Output   :	CF = 0	no special IRQ
;		CF = 1	special IRQ
;			AX = first process IRQ mask
;[]========================================================================[]

SPECIAL_IRQ_MASK	equ	1111111101000111b
Special_IRQ	label	byte
		dw	3F8h,0000000000010000b		;COM1/IRQ4
		dw	2F8h,0000000000001000b		;COM2/IRQ3
		dw	3E8h,0000000000010000b		;COM3/IRQ4
		dw	2E8h,0000000000001000b		;COM4/IRQ3
		dw	3BCh,0000000010000000b		;LPT1/IRQ7
		dw	378h,0000000010000000b		;LPT2/IRQ7
		dw	278h,0000000000100000b		;LPT3/IRQ5
Special_IRQ_L	equ	($ - offset Special_IRQ)/4

		ALIGN	4
Check_Special_IRQ	proc	near
		push	bx
		push	cx
		push	si

		movzx	cx, byte ptr ds:[di].IoCfgCount
		jcxz	short No_Special_IRQ

		lea	bx, ds:[di].IoCfg

Check_Special_IRQ_Loop:
		push	cx

		mov	ax, ds:[bx].IoBase

		mov	cx, Special_IRQ_L
		mov	si, offset EGROUP:Special_IRQ
Scan_Special_IRQ_Loop:
		cmp	ax, cs:[si]
		jne	short @f

		pop	cx
		mov	ax, cs:[si+2]
		stc
		jmp	short Check_Special_IRQ_Exit

@@:
		add	si, 4
		loop	short Scan_Special_IRQ_Loop

		pop	cx
		add	bx, SIZE IOCFGDATA
		loop	short Check_Special_IRQ_Loop

No_Special_IRQ:
		clc

Check_Special_IRQ_Exit:
		pop	si
		pop	cx
		pop	bx
		ret
Check_Special_IRQ	endp

;R127 - start
;Function : Check if assign IRQ for PnP specific device
;Input	  : none
;Output   : carry set = skip IRQ assignment
;	    non-carry = don't skip
PnPDevIrq_Cntl	proc	near

ifdef	CTRL_CMI8330_MIDI_IRQ
 ifdef	MIDI_IRQ_CMOS				;by CMOS setup ?
	test	byte ptr ds:PNP_FLAG, 80H	;assign IRQ for Midi ?
	jnz	short NotCmi8330Chip		;yes
 endif; MIDI_IRQ_CMOS

	cmp	byte ptr ds:LOGIC_DEV_CNT, 1	;Midi logical device 1 ?
	jne	short NotCmi8330Chip

	pusha
	push	es
	mov	si, offset SERIAL_ID		;serial number of device
	mov	al, ds:CSN_CNT
	xor	ah, ah
	mov	cx, 9				;length of serial ID
	mul	cl
	add	si, ax

	mov	di, offset CMI8330_SerID	;CMI sound card serial ID
	push	cs
	pop	es

	rep	cmpsb
	pop	es
	popa

	jnz	short NotCmi8330Chip
	stc					;skip IRQ assignment
	ret

NotCmi8330Chip:
endif;	CTRL_CMI8330_MIDI_IRQ

	clc					;assign IRQ as normal
	ret

ifdef	CTRL_CMI8330_MIDI_IRQ
 CMI8330_SerID	db	0dh,0a9h,00h,01h,00h,01h,00h,01h,8dh
endif;	CTRL_CMI8330_MIDI_IRQ
PnPDevIrq_Cntl	endp
;R127 - end

;[]========================================================================[]
;Procedure:	Proc_sIrqFormat
;Function :	Process IRQ resource information
;Input	  :	DS:SI = IRQ description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_sIrqFormat
Proc_sIrqFormat proc	near

		cmp	word ptr ds:[si], 0
		je	short Proc_sIrqFormat_Success
		cmp	byte ptr ds:[di].IrqCfgCount, IRQREG_NUM
		jae	short Proc_sIrqFormat_Fail

;R127 - start
		call	PnPDevIrq_Cntl
		jc	short Proc_sIrqFormat_Success	;skip IRQ assign
;R127 - end

		xor	dh, dh
		cmp	byte ptr ds:[si-1], 22h ;IRQ info present?
		je	short @f
		mov	dh, ds:[si+2]
@@:
		call	Check_Special_IRQ
		jnc	short Proc_No_Special_Irq
		and	ax, ds:[si]			;prefer IRQ
		call	Query_IRQ_Map
		mov	dl, al
		jnc	short Proc_sIrqFormat_End
		mov	bx, NOT SPECIAL_IRQ_MASK
		jmp	short @f
Proc_No_Special_Irq:
		mov	bx, -1			;no IRQ limitation
@@:
		mov	ax, ds:[si]
		and	ax, bx
		call	Query_IRQ_Map
		mov	dl, al
		jnc	short Proc_sIrqFormat_End
		mov	ax, ds:[si]
		not	bx
		and	ax, bx
		call	Query_IRQ_Map
		mov	dl, al
		jnc	short Proc_sIrqFormat_End

Proc_sIrqFormat_Fail:
		stc
		ret
Proc_sIrqFormat_End:
		call	Record_IRQ_Map
		call	Proc_sIrqFormat_Cfg
Proc_sIrqFormat_Success:
		clc
		ret
Proc_sIrqFormat endp

;[]========================================================================[]
;Procedure:	Proc_sDmaFormat
;Function :	Process DMA resource information
;Input	  :	DS:SI = DMA description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_sDmaFormat
Proc_sDmaFormat proc	near
		cmp	byte ptr ds:[si], 0
		je	short Proc_sDmaFormat_Success
		cmp	byte ptr ds:[di].DmaCfgCount, DMAREG_NUM
		jae	short Proc_sDmaFormat_Fail

		mov	dh, ds:[si+1]		;DMA info
		mov	al, ds:[si]
		call	Query_DMA_Map
		mov	dl, al
		jnc	short @f
Proc_sDmaFormat_Fail:
		stc
		ret
@@:
		call	Record_DMA_Map
		call	Proc_sDmaFormat_Cfg
Proc_sDmaFormat_Success:
		clc
		ret
Proc_sDmaFormat endp

;Check if special I/O port needed
;Input : ax - I/O port neede
;Output: zero	  - special I/O needed
;	 not zero - not special I/O need
;Note  : Now, we assume 200H ( for game port ) & 220H ( for sound chip )
;
		ALIGN	4
Special_IO_Port proc	near
		cmp	ax, 0200H
Yes_SpcIO:
		ret
Special_IO_Port endp

;[]========================================================================[]
;Procedure:	Proc_sIoPort
;Function :	Process I/O port resource information
;Input	  :	DS:SI = I/O port description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_sIoPort
Proc_sIoPort	proc	near
		cmp	byte ptr ds:[si+6], 0
		je	short Proc_sIoPort_Success
		cmp	byte ptr ds:[di].IoCfgCount, IOREG_NUM
		jae	short Proc_sIoPort_Fail

		mov	ax, ds:[si+1]		;minimum base address

;R132		movzx	cx, ds:[si+5]		;base alignment
;R132		movzx	dx, ds:[si+6]		;range length
		movzx	cx, byte ptr ds:[si+5]	;base alignment	;R132
		movzx	dx, byte ptr ds:[si+6]	;range length	;R132
Try_NextIO_Range:
		call	Special_IO_Port 	;Is special port needed ?
		jne	short Assign_It

;If needed I/O is 200H and it is not unified , don't assign 200H for it
;because it is standard game port
		cmp	ax, ds:[si+3]		;Is maximum base address 200h,too ?
		je	short Assign_It 	;yes , assign 200H for it

;Try next I/O range for it
		jmp	short NextIO_Chk

Assign_It:
;I/O is allow to assign

		call	Query_IO_Map
		jnc	short NeedIO_Ok

NextIO_Chk:
;current I/O is not acceptable , so check next base address

		or	cx, cx			;Alignment=0
		jz	short Proc_sIoPort_Fail ;yes, skip!

		add	ax, cx			;next I/O base address
		cmp	ax, ds:[si+3]		;maximum base address
		jbe	short Try_NextIO_Range
No_IO_Available:
Proc_sIoPort_Fail:
		stc
		ret
NeedIO_Ok:
@@:
		call	Record_IO_Map
		mov	dh, ds:[si]		;I/O info
		call	Proc_sIoPort_Cfg
;R132 Proc_sIoPort_Success:
Proc_sIoPort_Success	Label	Near		;R132

		clc
		ret
Proc_sIoPort	endp

;[]========================================================================[]
;Procedure:	Proc_sIoPortFixed
;Function :	Process Fixed I/O port resource information
;Input	  :	DS:SI = Fixed I/O port description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_sIoPortFixed
Proc_sIoPortFixed	proc	near
		cmp	byte ptr ds:[si+2], 0
		je	short Proc_sIoPort_Success
		cmp	byte ptr ds:[di].IoCfgCount, IOREG_NUM
		jae	short Proc_sIoPortFixed_Fail

		mov	ax, ds:[si+0]		;base address
		xor	dx, dx
		mov	dl, ds:[si+2]		;range length
		call	Query_IO_Map
		jc	short Proc_sIoPortFixed_Fail
		call	Record_IO_Map
		xor	dh, dh
		call	Proc_sIoPort_Cfg
		clc
		ret
Proc_sIoPortFixed_Fail:
		stc
		ret
Proc_sIoPortFixed	endp

;[]========================================================================[]
;Procedure:	Proc_lMem24
;Function :	Process memory 24 resource information
;Input	  :	DS:SI = memory 24 description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_lMem24
Proc_lMem24	proc	near
		cmp	word ptr ds:[si+7], 0
		je	short Proc_lMem24_Success

		cmp	byte ptr ds:[di].Mem32CfgCount, 0 ;mixed not allow
		jne	short Proc_lMem24_Fail
		cmp	byte ptr ds:[di].Mem24CfgCount, MEM24REG_NUM
		jae	short Proc_lMem24_Fail

		xor	eax, eax
		xor	ebx, ebx
		xor	ecx, ecx
		xor	edx, edx
		mov	cl, 8
		mov	ax, ds:[si+1]		;minimum base address
		shl	eax, cl 		;convert to 32-bit address
		mov	bx, ds:[si+3]		;maximum base address
		shl	ebx, cl 		;convert to 32-bit address
		mov	dx, ds:[si+7]		;range length
		shl	edx, cl 		;convert to 32-bit size
		mov	cx, ds:[si+5]		;base alignment
		xor	cl, cl			;force zero bit0-7
		or	cx, cx
		jnz	short @f
		mov	ecx, 10000h		;64KB alignment
@@:
		call	Query_Mem_Map
		jnc	short @f
		add	eax, ecx
		cmp	eax, ebx
		jbe	short @b
Proc_lMem24_Fail:
		stc
		ret
@@:
		call	Record_Mem_Map
		mov	ch, ds:[si]		;memory information
		call	Proc_lMem24_Cfg
Proc_lMem24_Success:
		clc
		ret
Proc_lMem24	endp

;[]========================================================================[]
;Procedure:	Proc_lMem32
;Function :	Process memory 32 resource information
;Input	  :	DS:SI = memory 32 description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_lMem32
Proc_lMem32	proc	near
		cmp	dword ptr ds:[si+13], 0
		je	short Proc_lMem32_Success

		cmp	byte ptr ds:[di].Mem24CfgCount, 0 ;mixed not allow
		jne	short Proc_lMem32_Fail
		cmp	byte ptr ds:[di].Mem32CfgCount, MEM32REG_NUM
		jae	short Proc_lMem32_Fail

		mov	eax, ds:[si+1]		;minimum base address
		mov	ebx, ds:[si+5]		;maximum base address
		mov	edx, ds:[si+13] 	;range length
		mov	ecx, ds:[si+9]		;base alignment
@@:
		call	Query_Mem_Map
		jnc	short @f
		add	eax, ecx
		cmp	eax, ebx
		jbe	short @b
Proc_lMem32_Fail:
		stc
		ret
@@:
		call	Record_Mem_Map
		mov	ch, ds:[si]		;memory information
		call	Proc_lMem32_Cfg
;R132 Proc_lMem32_Success:
Proc_lMem32_Success	Label	Near		;R132
		clc
		ret
Proc_lMem32	endp

;[]========================================================================[]
;Procedure:	Proc_lMemFixed
;Function :	Process Fixed memory resource information
;Input	  :	DS:SI = Fixed memory description block
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Proc_lMemFixed
Proc_lMemFixed	proc	near
		cmp	dword ptr ds:[si+5], 0
		je	short Proc_lMem32_Success

		cmp	byte ptr ds:[di].Mem24CfgCount, 0 ;mixed not allow
		jne	short Proc_lMemFixed_Fail
		cmp	byte ptr ds:[di].Mem32CfgCount, MEM32REG_NUM
		jae	short Proc_lMemFixed_Fail

		mov	eax, ds:[si+1]		;minimum base address
		mov	edx, ds:[si+5]		;range length

		call	Query_Mem_Map
		jnc	short @f
Proc_lMemFixed_Fail:
		stc
		ret
@@:
		call	Record_Mem_Map
		mov	ch, ds:[si]		;memory information
		call	Proc_lMem32_Cfg
		clc
		ret
Proc_lMemFixed	endp

;[]========================================================================[]
;Procedure:	Release_IRQ_Map
;Function :	Release IRQ resource
;Input	  :	DS = G_RAM
;		AL = IRQ level
;Output   :	None
;[]========================================================================[]

		ALIGN	4
		Public	Release_IRQ_Map
Release_IRQ_Map proc	near
		push	ax
		push	cx
		mov	cl, al
		and	cl, 0Fh
		mov	ax, 0001
		rol	ax, cl
		or	ds:IRQ_MAP, ax
		pop	cx
		pop	ax
		ret
Release_IRQ_Map endp

;[]========================================================================[]
;Procedure:	Release_IO_Map
;Function :	Release I/O port resource
;Input	  :	DS = G_RAM
;		AX = I/O port base address
;		DX = I/O port length
;Output   :	None
;[]========================================================================[]

		ALIGN	4
		Public	Release_IO_Map
Release_IO_Map	proc	near

		cmp	ax, 3F6h
		jne	short @f
		or	byte ptr DS:SPECIAL_IO_MAP, 02
		jmp	short Release_IO_Map_Exit
@@:
		cmp	ax, 376h
		jne	short @f
		or	byte ptr DS:SPECIAL_IO_MAP, 01
		jmp	short Release_IO_Map_Exit
@@:
		cmp	ax, 0100h
		jb	short Release_IO_Map_Exit
		cmp	ax, IO_RANGE
		ja	short Release_IO_Map_Exit

		push	ax
		push	bx
		push	cx
		push	dx
		sub	ax, 100h
		add	dx, ax
		dec	dx			;ending address
		and	ax, IO_MASK		;start addr(n bytes unit)
@@:
		mov	bx, ax
		shr	bx, IO_SHIFT		;n bytes per bit
		mov	cx, bx
		and	cl, 07			;bit position
		shr	bx, 3			;byte position
		mov	ch, 01
		rol	ch, cl
		or	ds:IO_MAP[bx], ch	;point to I/O map
		add	ax, IO_UNIT		;n bytes unit
		cmp	ax, dx
		jbe	short @b
		pop	dx
		pop	cx
		pop	bx
		pop	ax
Release_IO_Map_Exit:
		ret
Release_IO_Map	endp

;[]========================================================================[]
;Procedure:	Release_Mem_Map
;Function :	Release memory resource
;Input	  :	DS = G_RAM
;		EAX = base address
;		EDX = length
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Release_Mem_Map
Release_Mem_Map proc	near
		pushad
		cmp	eax, 0C0000h
		jb	short Release_Mem_Map_Exit
		cmp	eax, 0E0000h
		jb	short Release_Umb_Map
		cmp	eax, ds:EXTMEM_BASE
		ja	short Release_Mem_Map_Exit

; Release extended memory

Release_ExtMem_Map:
		test	eax, 001FFFFFh	;force point to 2MB bounary
		jz	short @f
		add	eax, 00200000h
@@:
		and	eax, 0FFE00000h
		mov	dword ptr ds:EXTMEM_BASE, eax
		jmp	short Release_Mem_Map_Exit

; Release Upper Memory Block

Release_Umb_Map:
		add	edx, eax	;end address
		mov	ecx, eax

		shr	ecx, 12 	;convert to 4KB unit
		and	cl, 01Fh
		test	dx, 0FFFh
		jz	short @f
		add	edx, 1000h
@@:
		shr	edx, 12 	;convert to 4KB unit
		and	dl, 01Fh
		mov	ch, dl
@@:
		mov	edx, 1
		rol	edx, cl
		or	ds:UMB_MAP, edx
		or	ds:PNPROM_MAP, edx
		inc	cl
		cmp	cl, ch
		jb	short @b
Release_Mem_Map_Exit:
		popad
		ret
Release_Mem_Map endp

;[]========================================================================[]
;Procedure:	Query_IRQ_Map
;Function :	Query IRQ resource
;Input	  :	DS = G_RAM
;		AX = IRQ channel mask
;Output   :	CF = 0	successful
;			AL = IRQ channel number
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Query_IRQ_Map
Query_IRQ_Map	proc	near
		push	cx
		push	dx
		and	ax, ds:IRQ_MAP

;R117 - start
 ifdef	PCI_IRQ_SELECTABLE
		and	ax, ds:FIXED_IRQ_MAP	;mask IRQ reserved for PCI
 endif; PCI_IRQ_SELECTABLE
;R117 - end

;R116 - start
ifdef	ACPI_Support
 ifdef	VT586_ACPI				;R116A For VIA VT586B chip
  IFDEF	ACPI_IRQ_Selectable			;R116B
;R116C - start
   ifdef ACPI_IRQ_Auto_Assign_Selectable
		pusha				   ;R116D ;save all registers
		mov	si, offset Assign_ACPI_IRQ_Item
		call	F000_GetItem_Value
		cmp	al,1			   ;if ACPI IRQ set Auto,
		popa				   ;R116D ;restore all registers
		je	short Auto_Assign_ACPI_IRQ ;then leave!
						   ;AL=0/1/2/.. => NA/Auto/IRQxx/..
		call	Ct_Update_PNP_IRQ_Map
Auto_Assign_ACPI_IRQ:
   else; ACPI_IRQ_Auto_Assign_Selectable
;R116C - end
  		call	Ct_Update_PNP_IRQ_Map	;R116A
   endif;ACPI_IRQ_Auto_Assign_Selectable	;R116C
    ENDIF;ACPI_IRQ_Selectable			;R116B
 else;	VT586_ACPI				;R116A
	;Don't assign IRQ 9 for PnP/ISA devices if ACPI enabled
		pusha
		mov	si,offset ACPI_option_Item
		call	F000_GetItem_Value
		or	al,al				;ACPI enabled?
		popa
		jnz	short ACPI_Disabled
		and	ah,NOT 02H			;IRQ 9 not for PnP
ACPI_Disabled:
 endif; VT586_ACPI				;R116A
endif;	ACPI_Support
;R116 - end

ifdef	IRQ9_Not_Available_For_ISA		;R115
		and	ah, not 02h		;R115 Don't use IRQ9 !
endif;	IRQ9_Not_Available_For_ISA		;R115

;R110 - start
;R128 ifdef	SPECIAL_PnP_IRQ_ORDER
	push	si
	mov	si,offset PriorityPnPIrq
	mov	cx,NO_PNP_IRQ
LookForNxtIrq:
	mov	dx,cs:[si]
	and	dx,ax			;IRQ available ?
	jnz	short GetPnPIrq 	;yes
	inc	si			;next IRQ to check
	inc	si
	loop	short LookForNxtIrq
	xor	dx,dx			;no available IRQ found
GetPnPIrq:
	mov	ax,dx
	pop	si
;R128 endif;	SPECIAL_PnP_IRQ_ORDER
;R110 - end

		mov	cx, 16
		xor	dl, dl
Query_Loop:
		test	al, 01
		jnz	short @f
		inc	dl
		shr	ax, 1
		loop	short Query_Loop
		pop	dx
		pop	cx
		stc
		ret
@@:
		mov	al, dl
		pop	dx
		pop	cx
		clc
		ret
Query_IRQ_Map	endp

;R128 - start
ifndef	SPECIAL_PnP_IRQ_ORDER
PriorityPnPIrq:
		dw	1 SHL 5 	;IRQ 5
		dw	1 SHL 6 	;IRQ 6
		dw	1 SHL 7 	;IRQ 7
		dw	1 SHL 9 	;IRQ 9
		dw	1 SHL 10	;IRQ 10
		dw	1 SHL 11	;IRQ 11
		dw	1 SHL 12	;IRQ 12
		dw	1 SHL 14	;IRQ 14
		dw	1 SHL 15	;IRQ 15
		dw	1 SHL 3 	;IRQ 3
		dw	1 SHL 4 	;IRQ 4
NO_PNP_IRQ	EQU	($ - offset PriorityPnPIrq)/2
endif;	SPECIAL_PnP_IRQ_ORDER
;R128 - end

;R110 - start
ifdef	SPECIAL_PnP_IRQ_ORDER
PriorityPnPIrq:
		dw	1 SHL 3 	;IRQ 3
		dw	1 SHL 4 	;IRQ 4
		dw	1 SHL 6 	;IRQ 6
		dw	1 SHL 7 	;IRQ 7
		dw	1 SHL 9 	;IRQ 9
		dw	1 SHL 10	;IRQ 10
		dw	1 SHL 5 	;IRQ 5
		dw	1 SHL 11	;IRQ 11
		dw	1 SHL 12	;IRQ 12
		dw	1 SHL 14	;IRQ 14
		dw	1 SHL 15	;IRQ 15
NO_PNP_IRQ	EQU	($ - offset PriorityPnPIrq)/2
endif;	SPECIAL_PnP_IRQ_ORDER
;R110 - end

;[]========================================================================[]
;Procedure:	Query_DMA_Map
;Function :	Query DMA resource
;Input	  :	DS = G_RAM
;		AL = DMA channel mask
;Output   :	CF = 0	successful
;			AL = DMA channel number
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Query_DMA_Map
Query_DMA_Map	proc	near
		push	cx
		push	dx
		and	al, ds:DMA_MAP
		mov	cx, 8
		mov	dl, 7
@@:
		rol	al, 1
		test	al, 01
		jnz	short @f
		dec	dl
		loop	short @b
		pop	dx
		pop	cx
		stc
		ret
@@:
		mov	al, dl
		pop	dx
		pop	cx
		clc
		ret
Query_DMA_Map	endp

;[]========================================================================[]
;Procedure:	Query_IO_Map
;Function :	Query I/O port resource
;Input	  :	DS = G_RAM
;		AX = base address
;		DX = length
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Query_IO_Map
Query_IO_Map	proc	near

		pusha
		cmp	ax, 3F6h
		jne	short @f
		test	byte ptr ds:SPECIAL_IO_MAP, 02
		jz	short Query_IO_Fail
		jmp	short Query_IO_Success
@@:
		cmp	ax, 376h
		jne	short @f
		test	byte ptr ds:SPECIAL_IO_MAP, 01
		jz	short Query_IO_Fail
		jmp	short Query_IO_Success
@@:
		cmp	ax, 100h
		jb	short Query_IO_Fail
		cmp	ax, IO_RANGE
		ja	short Query_IO_Success
@@:
		sub	ax, 100h
		add	dx, ax
		dec	dx			;ending address
		and	ax, IO_MASK		;start addr (n bytes unit)
@@:
		mov	bx, ax
		shr	bx, IO_SHIFT		;n bytes per bit
		mov	cx, bx
		and	cl, 07			;bit position
		shr	bx, 3			;byte position
		mov	ch, 01
		rol	ch, cl
		test	ds:IO_MAP[bx], ch
		jz	short Query_IO_Fail
		add	ax, IO_UNIT
		cmp	ax, dx
		jbe	short @b
Query_IO_Success:
		clc
		jmp	short Query_IO_Exit
Query_IO_Fail:
		stc
Query_IO_Exit:
		popa
		ret
Query_IO_Map	endp

;[]========================================================================[]
;Procedure:	Query_Mem_Map
;Function :	Query memory resource
;Input	  :	DS = G_RAM
;		EAX = base address
;		EDX = range length
;Output   :	CF = 0	successful
;		CF = 1	fail
;[]========================================================================[]

		ALIGN	4
		Public	Query_Mem_Map
Query_Mem_Map	proc	near
		pushad
ifdef	SHADOW_UNIT_64K			;R137
		cmp	eax, 0D0000h	;R137
else	;SHADOW_UNIT_64K		;R137
		cmp	eax, 0C0000h
endif	;SHADOW_UNIT_64K		;R137
		jb	short Query_Mem_Fail
		cmp	eax, 0E0000h
		jb	short Query_Umb
		cmp	eax, ds:EXTMEM_BASE
		jb	short Query_Mem_Fail

; Query extended memory

Query_ExtMem:
		jmp	short Query_Mem_Success

; Query Upper Memory Block

Query_Umb:
		add	edx, eax		;end address plus one
		mov	ecx, eax

		shr	ecx, 12 		;convert to 4KB unit
		and	cl, 01Fh
		test	dx, 0FFFh		;check in 4KB boundry
		jz	short @f
		add	edx, 1000h		;add 4KB size
@@:
		shr	edx, 12 		;convert to 4KB unit
		and	dl, 01Fh
		mov	ch, dl
@@:
		mov	edx, 01
		shl	edx, cl
		test	ds:UMB_MAP, edx
		jz	short Query_Mem_Fail
		inc	cl
		cmp	cl, ch
		jb	short @b
Query_Mem_Success:
		clc
		jmp	short Query_Mem_Exit
Query_Mem_Fail:
		stc
Query_Mem_Exit:
		popad
		ret
Query_Mem_Map	endp

ifdef	Notebook_Power_Management
		Public	Suspend_PnP_Device
Suspend_PnP_Device	Proc	Near

		push	ebx
		push	es
		push	ds

	;; First check whick PnP card is working

		xor	ax,ax
		mov	es,ax
		mov	edi,ebx
		add	edi,offset PNP_Device_Save

		mov	ax,seg LAST_CSN
		mov	ds,ax
		mov	bx,offset LAST_CSN
		mov	cl,ds:[bx]
		or	cl,cl
		jz	No_Pnp_Card

	;; Now, set all PnP cards in sleep state

		call	Wait_For_Key
		call	Delay_1ms
		call	Reset_Devices
		call	Delay_1ms
		call	Initiation_Key

		Call	Force_Sleep
; Read to 'CSN register' to identifier to CSN=01

		mov	bx, 20Bh
@@:
; Issue Wake[1] command

		mov	al, 1			; CSN=1
		call	Set_Wake_CSN

		mov	dx, PNP_ADDR		; PnP index
		mov	al, CSN_REG		; CSN register
		out	dx, al
		jmp	short $+2
		mov	dx, bx			; assumed READ_DATA
		in	al, dx
		jmp	short $+2
		cmp	al, 1			; CSN
		je	short Check_ID
Next_RDDATA:
		add	bx, 4			; next port address
		cmp	bx, 3FFh
		jbe	short @b
		mov	bx, 203h
Check_ID:
		mov	dx,bx
		mov	ax,bx
		stos	word ptr es:[edi]

		xor	al, al			; for CSN
@@:
		inc	al
		call	Assign_CSN
		call	Isolation
		jnc	short @b		; isolate next PnP card

		call	Force_Sleep		;all PnP enter sleep state

	;; Now, get READ_DATA port address

		xor	cx,cx
		mov	bx,offset LAST_CSN
		mov	cl,ds:[bx]

		mov	ax,ZV_Temp_Stack
		mov	ds,ax
		mov	si,offset PnP_Temp_Buffer

		mov	al,1
Get_PnP_Data:
		push	cx
		push	ax

		xor	ah,ah
Save_Next_Logic_Device:
		call	Find_LogicDev
		jc	short Save_Logic_Device_End

		stos	word ptr es:[edi]

		push	ax

		mov	al, LOGIC_DEV
		call	Set_PnP_Reg

		mov	cx,80h - 30h
		mov	al,30h
@@:
		push	ax

		Call	Get_PnP_Reg
		stos	byte ptr es:[edi]

		pop	ax
		inc	al
		loop	short @B

		pop	ax
		inc	ah
		jmp	short Save_Next_Logic_Device
Save_Logic_Device_End:

		pop	ax
		inc	al
		pop	cx
		loop	short Get_PnP_Data

		mov	al,0FFh
		stos	byte ptr es:[edi]
No_Pnp_Card:

		pop	ds
		pop	es
		pop	ebx

		ret

Suspend_PnP_Device	Endp

		Public	Restore_PnP_Device
Restore_PnP_Device	Proc	Near

		push	ebx
		push	es
		push	ds

		mov	ax,seg LAST_CSN
		mov	es,ax

		mov	di,offset LAST_CSN
		cmp	byte ptr es:[di],0
		je	short No_Pnp_Card_Restore

	;; First check whick PnP card is working

		xor	ax,ax
		mov	ds,ax

		mov	esi,ebx
		add	esi,offset PNP_Device_Save

	;; Now, set all PnP cards in sleep state

		call	Wait_For_Key
		call	Delay_1ms
		call	Reset_Devices
		call	Delay_1ms
		call	Initiation_Key

		Call	Force_Sleep

		lods	word ptr ds:[esi]
		mov	dx,ax

		xor	al, al			; for CSN
@@:
		inc	al
		call	Assign_CSN
		call	Isolation
		jnc	short @b		; isolate next PnP card

		call	Force_Sleep		;all PnP enter sleep state

	;; Now, get READ_DATA port address

Set_PnP_Data:
		lods	byte ptr ds:[esi]
		cmp	al,0FFh
		je	short Restore_Logic_Device_End

		call	Set_Wake_CSN
		lods	byte ptr ds:[esi]
		mov	ah,al
		mov	al, LOGIC_DEV
		call	Set_PnP_Reg

		mov	cx,80h - 30h
		mov	ah,30h
@@:
		lods	byte ptr ds:[esi]
		xchg	al,ah
		Call	Set_PnP_Reg
		xchg	al,ah
		inc	ah
		loop	short @B

		jmp	short Set_PnP_Data
Restore_Logic_Device_End:

		call	Wait_For_Key
		call	Delay_1ms
No_Pnp_Card_Restore:
		pop	ds
		pop	es
		pop	ebx

		ret

Restore_PnP_Device	Endp
endif	;Notebook_Power_Management

ifdef	ESCD_SUPPORT					;R129
;************************************************************************
;*									*
;*		PROCESS ISA/PNP RELATED TO ESCD MODULE			*
;*									*
;************************************************************************

;[]========================================================================[]
;Procedure:	Verify_CfgData
;Function :	Verify CFGDATA range contained in resource information
;Input	  :	DS:DI = CFGDATA
;		DS:CHOICE_BUFFER = resource information block
;Output   :	CF = 0 successful, correct CFGDATA
;		CF = 1 fail, incorrect CFGDATA
;[]========================================================================[]

		ALIGN	4
		Public	Verify_CfgData
Verify_CfgData	proc	near
		pusha

; Verify Mem24 configuration data

		mov	dh, ds:[di].Mem24CfgCount
		or	dh, dh
		jz	short Verify_Mem24_Exit

		lea	bx, ds:[di].Mem24Cfg
		mov	si, offset CHOICE_BUFFER
Verify_Mem24_Loop:
		call	Get_Tag_Name
		cmp	ah, sEndTag		;end resource information
		je	Verify_CfgData_Fail
		cmp	ah, lMem24
		jne	short Verify_Mem24_Next

		movzx	eax, word ptr ds:[si+1]
		shl	eax, 8
		cmp	ds:[bx].MemBase, eax
		jb	Verify_CfgData_Fail

		movzx	eax, word ptr ds:[si+3]
		shl	eax, 8
		cmp	ds:[bx].MemBase, eax
		ja	Verify_CfgData_Fail

		add	si, cx
		add	bx, SIZE MEMCFGDATA
		dec	dh
		jnz	short Verify_Mem24_Loop
		jmp	short Verify_Mem24_Exit

Verify_Mem24_Next:
		add	si, cx
		jmp	short Verify_Mem24_Loop

Verify_Mem24_Exit:

; Verify Mem32, MemFixed configuration data

		mov	dh, ds:[di].Mem32CfgCount
		or	dh, dh
		jz	short Verify_Mem32_Exit

		lea	bx, ds:[di].Mem32Cfg
		mov	si, offset CHOICE_BUFFER
Verify_Mem32_Loop:
		call	Get_Tag_Name
		cmp	ah, sEndTag		;end resource information
		je	Verify_CfgData_Fail
		cmp	ah, lMem32
		jne	short @f

		mov	eax, ds:[si+1]
		cmp	ds:[bx].MemBase, eax
		jb	Verify_CfgData_Fail
		mov	eax, ds:[si+5]
		cmp	ds:[bx].MemBase, eax
		ja	Verify_CfgData_Fail
		jmp	short Verify_Mem32_Cont

@@:
		cmp	ah, lMemFixed
		jne	short Verify_Mem32_Next

		mov	eax, ds:[si+1]
		cmp	ds:[bx].MemBase, eax
		jne	Verify_CfgData_Fail

Verify_Mem32_Cont:
		add	si, cx
		add	bx, SIZE MEMCFGDATA
		dec	dh
		jnz	short Verify_Mem32_Loop
		jmp	short Verify_Mem32_Exit

Verify_Mem32_Next:
		add	si, cx
		jmp	short Verify_Mem32_Loop

Verify_Mem32_Exit:

; Verify I/O port configuration data

		mov	dh, ds:[di].IoCfgCount
		or	dh, dh
		jz	short Verify_Io_Exit

		lea	bx, ds:[di].IoCfg
		mov	si, offset CHOICE_BUFFER
Verify_Io_Loop:
		call	Get_Tag_Name
		cmp	ah, sEndTag		;end resource information
		je	Verify_CfgData_Fail
		cmp	ah, sIoPort
		jne	short @f

		mov	ax, ds:[si+1]
		cmp	ds:[bx].IoBase, ax
		jb	Verify_CfgData_Fail
		mov	ax, ds:[si+3]
		cmp	ds:[bx].IoBase, ax
		ja	Verify_CfgData_Fail
		jmp	short Verify_Io_Cont

@@:
		cmp	ah, sIoPortFixed
		jne	short Verify_Io_Next

		mov	ax, ds:[si]
		cmp	ds:[bx].IoBase, ax
		jne	Verify_CfgData_Fail

Verify_Io_Cont:
		add	si, cx
		add	bx, SIZE IOCFGDATA
		dec	dh
		jnz	short Verify_Io_Loop
		jmp	short Verify_Io_Exit

Verify_Io_Next:
		add	si, cx
		jmp	short Verify_Io_Loop

Verify_Io_Exit:

; Verify IRQ configuration data

		mov	dh, ds:[di].IrqCfgCount
		or	dh, dh
		jz	short Verify_Irq_Exit

		lea	bx, ds:[di].IrqCfg
		mov	si, offset CHOICE_BUFFER
Verify_Irq_Loop:
		call	Get_Tag_Name
		cmp	ah, sEndTag		;end resource information
		je	short Verify_CfgData_Fail
		cmp	ah, sIrqFormat
		jne	short Verify_Irq_Next

		push	cx
		mov	ax, ds:[si]
		mov	cl, ds:[bx].IrqNum
		inc	cl
		shr	ax, cl
		pop	cx
		jnc	short Verify_CfgData_Fail

		add	si, cx
		add	bx, SIZE IRQCFGDATA
		dec	dh
		jnz	short Verify_Irq_Loop
		jmp	short Verify_Irq_Exit

Verify_Irq_Next:
		add	si, cx
		jmp	short Verify_Irq_Loop

Verify_Irq_Exit:

; Verify DMA configuration data

		mov	dh, ds:[di].DmaCfgCount
		or	dh, dh
		jz	short Verify_Dma_Exit

		lea	bx, ds:[di].DmaCfg
		mov	si, offset CHOICE_BUFFER
Verify_Dma_Loop:
		call	Get_Tag_Name
		cmp	ah, sEndTag		;end resource information
		je	short Verify_CfgData_Fail
		cmp	ah, sDmaFormat
		jne	short Verify_Dma_Next

		push	cx
		mov	al, ds:[si]
		mov	cl, ds:[bx].DmaNum
		inc	cl
		shr	al, cl
		pop	cx
		jnc	short Verify_CfgData_Fail

		add	si, cx
		add	bx, SIZE DMACFGDATA
		dec	dh
		jnz	short Verify_Dma_Loop
		jmp	short Verify_Dma_Exit

Verify_Dma_Next:
		add	si, cx
		jmp	short Verify_Dma_Loop

Verify_Dma_Exit:

; All CFGDATA range contained in resource information

		clc
		jmp	short Verify_CfgData_Exit

; CFGDATA range mismatch with resource information

Verify_CfgData_Fail:
		stc

Verify_CfgData_Exit:
		popa
		ret
Verify_CfgData	endp

;[]========================================================================[]
;Procedure:	Find_PnpEscd
;Function :	Find PnP record in ESCD
;Input	  :	CSN_CNT
;		DS, ES = G_RAM
;Output   :	CF = 0 PnP device ESCD found
;			SI = point to ESCD board record
;		CF = 1 PnP device ESCD not found
;[]========================================================================[]

		ALIGN	4
		Public	Find_PnpEscd
Find_PnpEscd	proc	near
		push	ax
		push	di
		mov	al, byte ptr ds:CSN_CNT
		mov	ah, 9
		mul	ah
		add	ax, offset SERIAL_ID
		mov	di, ax
		mov	si, offset ESCD_BUFFER
		call	Scan_PnpId
		pop	di
		pop	ax
		ret
Find_PnpEscd	endp

;[]========================================================================[]
;Procedure:	Check_Disable
;Function :	Check device disable record in ESCD Free Format Data
;Input	  :	DS:SI = point to ESCD board record
;		AL = function number
;Output   :	CF = 0 function enable
;		CF = 1 function disable
;[]========================================================================[]

		ALIGN	4
		Public	Check_Disable
Check_Disable	proc	near
		push	ax
		push	cx
		push	si
		call	Find_EcdFF
		mov	cl, al
		mov	ax, 01
		shl	ax, cl
		test	word ptr ds:[si+5].fwECDFuncsDisabled, ax
		clc
		jz	short @f
		stc
@@:
		pop	si
		pop	cx
		pop	ax
		ret
Check_Disable	endp

;[]========================================================================[]
;Procedure:	Copy_EscdFunc
;Function :	Copy function block in ESCD
;Input	  :	DS:SI = source function block
;		CurrentEscdPoint
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Copy_EscdFunc
Copy_EscdFunc	proc	near
		push	cx
		push	si
		push	di
		mov	di, ds:CurrentEscdPoint
		mov	cx, ds:[si].wFuncSize
		add	cx, 2			;function length word
		rep	movsb
		mov	ds:CurrentEscdPoint, di
		pop	di
		pop	si
		pop	cx
		ret
Copy_EscdFunc	endp

;[]========================================================================[]
;Procedure:	Scan_PnpId
;Function :	Scan PnP serial ID in ESCD
;Input	  :	DS(ES):SI = point to ESCD block
;		DS(ES):DI = point to PnP serial ID
;Output   :	CF = 0 PnP device ESCD found
;			DS(ES):SI = point to ESCD board record
;		CF = 1 PnP device ESCD not found
;[]========================================================================[]

		ALIGN	4
Scan_PnpId	proc	near
		push	cx
		push	di

		xor	cx, cx
		mov	cl, ds:[si+08]		;total board count
		jcxz	short Scan_PnpId_Fail

		add	si, 12			;point to 1st board record
Scan_PnpId_Loop:
		push	cx
		push	si
		push	di

		call	Chk_PnpEscd
		jc	short Scan_Next_PnpId

		call	Find_EcdFF
		jc	short Scan_Next_PnpId

		add	si, 5+17		;func head and ECDFF head length
		mov	cx, 8
		repe	cmpsb
		jne	short Scan_Next_PnpId
		pop	di
		pop	si
		pop	cx
		clc
		jmp	short Scan_PnpId_Exit

Scan_Next_PnpId:
		pop	di
		pop	si
		pop	cx
		add	si, ds:[si]		;point to next board record
		loop	short Scan_PnpId_Loop
Scan_PnpId_Fail:
		stc
Scan_PnpId_Exit:
		pop	di
		pop	cx
		ret
Scan_PnpId	endp

;[]========================================================================[]
;Procedure:	Find_EcdFF
;Function :	Find ECD Free Format data in ESCD board record
;Input	  :	DS(ES):SI = point to ESCD board record
;Output   :	CF = 0 ECD Free Format data found
;			SI = point to ECD Free Format function block
;		CF = 1 not found
;[]========================================================================[]

		ALIGN	4
Find_EcdFF	proc	near
		add	si, 12			;ESCD board header length
Find_EcdFF_Loop:
		cmp	word ptr ds:[si], 0		;board end
		stc
		je	short Find_EcdFF_Exit
		cmp	byte ptr ds:[si+4], 0C0h	;free form data
		jne	short @f
		cmp	dword ptr ds:[si+6], 'GFCA'     ;ECD free form sign
		clc
		je	short Find_EcdFF_Exit
@@:
		add	si, ds:[si]			;function length
		add	si, 2				;exclusive length word
		jmp	short Find_EcdFF_Loop
Find_EcdFF_Exit:
		ret
Find_EcdFF	endp

;[]========================================================================[]
;Procedure:	Create_PnpEcdFF
;Function :	Create ISA/PNP card ECD free format data
;Input	  :	CurrentEscdPoint
;		CSN_CNT
;Output   :	CurrentEscdPoint
;[]========================================================================[]

		ALIGN	4
		Public	Create_PnpEcdFF
Create_PnpEcdFF proc	near
		call	Find_PnpEscd
		jc	short @f
		call	Find_EcdFF
		call	Copy_EscdFunc
		mov	ax, ds:[si].wFuncSize
		add	ax, 2
		add	ds:CurrentEscd.wBrdSize, ax
		mov	di, ds:CurrentEscdPoint
		jmp	short Create_PnpEcdFF_Exit
@@:
		push	ds
		mov	bx, ds:CurrentEscdPoint
		mov	di, bx
		mov	si, offset EGROUP:EscdFuncHead
		mov	cx, EscdFuncHead_L
		add	ds:CurrentEscd.wBrdSize, cx
		push	cs
		pop	ds
		rep	movsb
		mov	cx, EcdFFHead_L
		add	es:CurrentEscd.wBrdSize, cx
		add	es:[bx].wFuncSize, cx
		mov	si, offset EGROUP:EcdFFHead
		push	di
		rep	movsb
		pop	si
		pop	ds

; SI point to ECD free format data head

		mov	byte ptr ds:[si].bBrdType, 10h	;ISA/PNP board type
		or	byte ptr ds:[bx].bFuncInfo, ECD_FF
		mov	cx, 8
		add	ds:CurrentEscd.wBrdSize, cx
		add	ds:[bx].wFuncSize, cx
		add	ds:[si].bEcdFFSize, cl
		mov	al, ds:CSN_CNT
		mov	ah, 9
		mul	ah
		mov	si, offset SERIAL_ID
		add	si, ax
		rep	movsb
Create_PnpEcdFF_Exit:
		xor	al, al
		mov	cx, 4
		add	ds:CurrentEscd.wBrdSize, cx
		rep	stosb
		mov	ds:CurrentEscdPoint, di
		ret
Create_PnpEcdFF endp

;[]========================================================================[]
;Procedure:	Proc_PnpEscd
;Function :	Process ISA/PNP card ESCD
;Input	  :	CSN_CNT
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Proc_PnpEscd
Proc_PnpEscd	proc	near
		call	Find_PnpEscd
		jc	short Add_New_PnpEscd

		mov	al, ds:[si].bSlotNum
		mov	di, offset OldEscdBrdMap
		call	Reset_EscdBrd

		mov	di, offset CurrentEscd
		call	Cmp_BrdEscd
		jc	short @f
		mov	cl, ds:CSN_CNT
		mov	ax, 0FFFEh
		rol	ax, cl
		and	ds:ERROR_FLAG, ax
		ret

@@:
		mov	di, offset EscdBrdMap
		call	Reset_EscdBrd

		mov	bx, offset ESCD_BUFFER
		call	Remove_EscdBrd

Add_New_PnpEscd:

		mov	bx, offset ESCD_BUFFER
		mov	di, offset EscdBrdMap
		mov	si, offset CurrentEscd
		mov	cx, 63
		mov	al, 1
Add_PnpEscd_Loop:
		call	Query_EscdBrd
		jnc	short @f
		inc	al
		loop	short Add_PnpEscd_Loop
		jmp	short Proc_PnpEscd_Exit
@@:
		mov	ds:[si].bSlotNum, al
		call	Add_EscdBrd
		mov	di, offset EscdBrdMap
		call	Set_EscdBrd
		mov	di, offset NewEscdBrdMap
		call	Set_EscdBrd
Proc_PnpEscd_Exit:
		ret
Proc_PnpEscd	endp
endif	;ESCD_SUPPORT					;R129
endif	;NO_ISA_PNP					;R129

ifdef	ESCD_SUPPORT					;R129
;************************************************************************
;*									*
;*		PROCESS ESCD MODULE					*
;*									*
;************************************************************************

		Public	EscdBrdHead
EscdBrdHead	label	byte
		dw	EscdBrdHead_L		;board length
		db	?			;slot number
		db	?			;reserved
		db	4 dup(0)		;compressed board ID
		dw	4040h			;ID and slot information
		db	0			;minor rev of CFG file ext
		db	0			;major rev of CFG file ext
		Public	EscdBrdHead_L
EscdBrdHead_L	equ	$ - EscdBrdHead

		Public	EscdFuncHead
EscdFuncHead	label	byte
		dw	3			;function length
		db	01			;selection size
		db	0			;selection data
		db	0			;function information
		Public	EscdFuncHead_L
EscdFuncHead_L	equ	$ - EscdFuncHead

EcdFFHead	label	byte
		db	16			;ECDFF length
		db	'ACFG'                  ;ECDFF form sign
		db	01			;ECDFF minor version
		db	02			;ECDFF major version
		db	04			;ECDFF board type(PCI)
		db	?			;reserved
		dw	0			;disable bit-map
		dw	0			;error status bit-map
		dw	0			;re-configurable bit-map
		db	2 dup(?)		;reserved
EcdFFHead_L	equ	$ - EcdFFHead


IF BUS_TYPE EQ EISA_BUS
;sort the ESCD buffer by upwarding ( ie. from slot 0 )
;Input	: DS - segment of ESCD buffer
;Output : none
		ALIGN	4
Sort_Escd_Buffer	proc	near
		push	es

		push	ds
		pop	es		;point es to ESCD buffer
		cld

;clear array
		mov	di,offset ADDR_ARRAY
		mov	cx,256 * SIZE ADDRSIZE
		xor	ax,ax
		rep	stosb

;copy ESCD header
		mov	cx,SIZE ESCD_CFGHDR
		mov	di,offset TEMP_ESCD
		mov	si,offset ESCD_BUFFER
		rep	movsb

;Fill ADDR_SIZE array by reading ESCD buffer
		mov	si,offset ESCD_BUFFER
		movzx	cx,ds:[si].bBrdCnt		;get board count
		jcxz	short No_Escd_Record
		add	si,SIZE ESCD_CFGHDR		;first board's offset

Next_Board_Scan:
		push	cx				;save board count
		movzx	bx,ds:[si].bSlotNum		;get offset
		shl	bx,2
		add	bx,offset ADDR_ARRAY

		mov	cx,ds:[si].wBrdSize	;get size
		mov	ds:[bx].RecSize,cx	;size
		mov	ds:[bx].RecAddr,si	;offset

		add	si,cx			;next board's offset

		pop	cx
		loop	short Next_Board_Scan


;Now sorting ESCD data from ESCD_BUFFER into sorted TEMP_ESCD
		mov	cx,256			;total 256 records to copy
		mov	di,(offset TEMP_ESCD)+ SIZE ESCD_CFGHDR
		mov	bx,offset ADDR_ARRAY

Next_Exist_Board:
		push	cx
		mov	cx,ds:[bx].RecSize
		jcxz	short Chk_Next_Board

		mov	si,ds:[bx].RecAddr

		rep	movsb

Chk_Next_Board:
		pop	cx
		add	bx,SIZE ADDRSIZE		;next array
		loop	short Next_Exist_Board


;Copy back ESCD data from TEMP_ESCD into ESCD_BUFFER
		mov	di,offset ESCD_BUFFER
		mov	cx,ds:[di].wEscdSize
		mov	si,offset TEMP_ESCD
		rep	movsb

No_Escd_Record:

		pop	es
		ret
Sort_Escd_Buffer	endp
endif;BUS_TYPE EQ EISA_BUS

;[]========================================================================[]
;Procedure:	Xlat_Escd_CfgData
;Function :	Translate one ESCD function record to CFGDATA
;Input	  :	DS(ES):SI = point to ESCD function block
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	ZF = 0 CFGDATA buffer not empty
;		ZF = 1 CFGDATA buffer empty
;[]========================================================================[]

		ALIGN	4
		Public	Xlat_Escd_CfgData
Xlat_Escd_CfgData	proc	near
		pushad

		call	Init_CfgData

		lodsw				;function length
		or	ax, ax			;zero length indicate brd end
		jz	short Xlat_Escd_Exit	;jmp if board end
		xor	ax, ax
		lodsb				;selection length
		add	si, ax			;point to func entry info

		lodsb				;function entry information

		mov	bx, offset EGROUP:XlatEscdTbl
		mov	cx, 7
Xlat_Escd_Loop:
		shr	al, 1
		jnc	short @f

		push	ax
		push	bx
		push	cx
		call	word ptr cs:[bx]
		pop	cx
		pop	bx
		pop	ax

@@:
		add	bx, 2			;next function entry
		loop	short Xlat_Escd_Loop

Xlat_Escd_Exit:
		mov	al, ds:[di].Mem24CfgCount
		or	al, ds:[di].Mem32CfgCount
		or	al, ds:[di].IoCfgCount
		or	al, ds:[di].IrqCfgCount
		or	al, ds:[di].DmaCfgCount
		popad
		ret
Xlat_Escd_CfgData	endp

XlatEscdTbl	label	word
		dw	offset EGROUP:XlatTypeSubType
		dw	offset EGROUP:XlatMemory
		dw	offset EGROUP:XlatIrq
		dw	offset EGROUP:XlatDma
		dw	offset EGROUP:XlatPortRange
		dw	offset EGROUP:XlatPortInit
		dw	offset EGROUP:XlatFreeForm

;[]========================================================================[]
;Procedure:	XlatTypeSubType
;Function :	Translate Type/Sub-Type ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatTypeSubType proc	near
		xor	cx, cx
		mov	cl, ds:[si]		;length of string field
		inc	cx
		add	si, cx			;point to next function entry
		ret
XlatTypeSubType endp

;[]========================================================================[]
;Procedure:	XlatMemory
;Function :	Translate memory ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatMemory	proc	near
		mov	eax, ds:[si+2]		;3 bytes start address (divided
						;by 100h)
		shl	eax, 8			;*100h
		xor	edx, edx
		mov	dx, ds:[si+5]		;2 bytes size (divided by 400h)
		shl	edx, 10 		;*400h

		mov	cx, ds:[si]
		and	ch, 0Ch 		;decode control
		cmp	ch, 04
		jbe	short @f

		call	Proc_lMem32_Cfg
		jmp	short XlatMemoryMore
@@:
		call	Proc_lMem24_Cfg
XlatMemoryMore:

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		add	si, 7			;next memory entry
		jmp	short XlatMemory
@@:
		add	si, 7			;next function entry
		ret
XlatMemory	endp

;[]========================================================================[]
;Procedure:	XlatIrq
;Function :	Translate IRQ ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatIrq 	proc	near
		mov	al, ds:[si]		;get irq chanel
		and	al, 0Fh

		mov	dl, al
		call	Proc_sIrqFormat_Cfg

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		add	si, 2			;next irq entry
		jmp	short XlatIrq
@@:
		add	si, 2			;next function entry
		ret
XlatIrq 	endp

;[]========================================================================[]
;Procedure:	XlatDma
;Function :	Translate DMA ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatDma 	proc	near
		mov	al, ds:[si]		;get dma chanel
		and	al, 07h

		mov	dl, al
		call	Proc_sDmaFormat_Cfg

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		add	si, 2			;next dma entry
		jmp	short XlatDma
@@:
		add	si, 2			;next function entry
		ret
XlatDma 	endp

;[]========================================================================[]
;Procedure:	XlatPortRange
;Function :	Translate Port Range ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatPortRange	proc	near
		mov	ax, ds:[si+1]		;get I/O port address
		xor	dx, dx
		mov	dl, ds:[si]		;length
		and	dl, 1Fh
		inc	dx

		call	Proc_sIoPort_Cfg

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		add	si, 3			;next I/O entry
		jmp	short XlatPortRange
@@:
		add	si, 3			;next function entry
		ret
XlatPortRange	endp

;[]========================================================================[]
;Procedure:	XlatPortInit
;Function :	Translate Port initialization ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatPortInit	proc	near
		push	di
		mov	di, si
		xor	ax, ax
		mov	cl, ds:[si]
		and	cl, 03
		mov	al, 1
		shl	al, cl
		test	byte ptr ds:[si], 04		;bit 2
		jz	short @f
		add	al, al
@@:
		add	al, 3
		add	si, ax			;next function entry
		test	byte ptr ds:[di], 80h	;more entries follow?
		pop	di
		jnz	short XlatPortInit
		ret
XlatPortInit	endp

;[]========================================================================[]
;Procedure:	XlatFreeForm
;Function :	Translate Free Format data ESCD item to CFGDATA
;Input	  :	DS(ES):SI = point to corresponding ESCD item
;		DS(ES):DI = point to CFGDATA buffer
;Output   :	DS(ES):SI = point to next ESCD item
;[]========================================================================[]

		ALIGN	4
XlatFreeForm	proc	near
		xor	ax, ax
		lodsb

		add	si, ax
		ret

XlatFreeForm	endp

;[]========================================================================[]
;Procedure:	Decode_ESCD
;Function :	Translate ISA card resource info in ESCD to Resource Map
;Input	  :	DS:SI = point to ESCD block
;Output   :	none
;[]========================================================================[]
		public	Decode_ESCD
		ALIGN	4
Decode_ESCD	proc	near

		xor	cx, cx
		mov	cl, ds:[si+08]		;total board count
		jcxz	short Decode_ESCD_Exit

; Decode all boards loop

		add	si, 12			;point to 1st board record
Decode_Board_Loop:
		call	Chk_PnpEscd		;
		jnc	short Next_Board	;skip if ISA/PNP record
		call	Chk_PciEscd		;
		jnc	short Next_Board	;skip if PCI record
		call	Chk_MbEscd		;
		jnc	short Next_Board	;
		call	Decode_BrdEscd		;
Next_Board:
		add	si, ds:[si]		;add board length
						;point to next board
		loop	short Decode_Board_Loop

Decode_ESCD_Exit:
		ret
Decode_ESCD	endp

;[]========================================================================[]
;Procedure:	Decode_BrdEscd
;Function :	Translate one board ESCD to CFGDATA and record resources
;Input	  :	DS:SI = point to board ESCD block
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Decode_BrdEscd
Decode_BrdEscd	proc	near
		pusha

; Clear temporary resource map

		mov	di, G_RAM
		mov	es, di

; Decode all functions loop

		add	si, 12			;point to 1st function
Decode_Func_Loop:
		cmp	word ptr ds:[si], 0	;function length
		je	short Decode_Func_Exit
		mov	di, offset CfgBuffer
		call	Xlat_Escd_CfgData
		call	Record_CfgData
		add	si, ds:[si]		;add function length
						;point to next function
		add	si, 2			;word of function length
		jmp	short Decode_Func_Loop

Decode_Func_Exit:

; Update system resource map with temporary resource map

		popa
		ret
Decode_BrdEscd	endp

;[]========================================================================[]
;Procedure:	Create_MbEscd
;Function :	Create M/B ESCD with system device node
;Input	  :	none
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Create_MbEscd
Create_MbEscd	proc	near
		pusha
		push	ds
		push	es

		mov	ax, cs
		mov	ds, ax
		xor	ax, ax
		mov	es, ax
		mov	word ptr es:RES_BUFFER, ax
		mov	bx, offset CurrentEscd

; BX point to board record start
; create board header

		mov	di, bx
		mov	si, offset EGROUP:EscdBrdHead
		mov	cx, EscdBrdHead_L
		rep	movsb


IF BUS_TYPE EQ EISA_BUS
;Set manufacture & product ID
		push	di				; Save di
		push	ds

	;Read manfacture & product ID
		mov	dx,0c80H
		in	eax,dx

		mov	di, G_RAM
		mov	ds, di
		mov	di, bx
		mov	dword ptr [di].wCompBrdID, eax
		and	byte ptr [di].sIDSlotInfo, 10111111b ;readable ID
		pop	ds				; Restore data segment
		pop	di				; Restore di
ENDIF ;BUS_TYPE EQ EISA_BUS

Create_MbFunc_Loop:
		call	POST_Get_Node
		or	ax, ax
		jnz	short Create_MbEscd_End

		push	bx

		push	di
		mov	si, offset EGROUP:EscdFuncHead
		mov	cx, EscdFuncHead_L
		rep	movsb
		pop	bx

; BX point to function record start

		call	Create_MbFunc
		mov	ax, es:[bx].wFuncSize
		add	ax, 2

		pop	bx

		add	es:[bx].wBrdSize, ax

Create_MbEscd_Next:
		cmp	byte ptr es:RES_BUFFER, 0FFh
		jne	short Create_MbFunc_Loop

Create_MbEscd_End:
		mov	cx, 4
		add	es:[bx].wBrdSize, cx
		xor	al, al
		rep	stosb			;record board end

Create_MbEscd_Exit:

;R135	- starts
ifdef	VSA_VGA
		newiodelay
		newiodelay
endif	;VSA_VGA
;R135	- ends

		pop	es
		pop	ds
		popa
		ret
Create_MbEscd	endp

;[]========================================================================[]
;Procedure:	POST_Set_Escd
;Function :	Set ESCD in POST
;Input	  :	none
;Output   :	AX = return code
;[]========================================================================[]

		ALIGN	4
		Public	POST_Set_Escd
POST_Set_Escd	proc	near
		push	0F000h			;BiosSelector
		push	0F000h			;EscdSelector
		push	0			;EscdBufSeg
		push	offset ESCD_BUFFER	;EscdBufOff
		push	0043h			;Get ESCD
		FAR_CALL	<offset PNP_BIOS_Real>, 0F000h
		add	sp, 10
		or	ax, ax
		jnz	short @f
		clc
		ret
@@:
		stc
		ret
POST_Set_Escd	endp

;[]========================================================================[]
;Procedure:	Create_MbFunc
;Function :	Create one M/B ESCD function
;Input	  :	none
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Create_MbFunc	proc	near
		push	ds
		xor	ax, ax
		mov	ds, ax

		push	bx
		push	di

		mov	di, offset CfgBuffer
		call	Init_CfgData

		mov	si, offset RES_BUFFER+2+12
Create_CfgData_Loop:
		call	Get_Tag_Name
		cmp	ah, sEndTag
		je	short Create_CfgData_Exit
		push	si
		push	cx
		push	cx
		mov	bx, offset EGROUP:TAG_CODE
		mov	dx, offset EGROUP:Create_Proc
		mov	cx, TAG_CODE_L
@@:
		cmp	cs:[bx], ah
		je	short @f
		inc	bx
		inc	dx
		inc	dx
		loop	short @b
		pop	cx
		jmp	short Create_CfgData_Next
@@:
		pop	cx
		mov	bx, dx
		call	word ptr cs:[bx]
Create_CfgData_Next:
		pop	cx
		pop	si
		add	si, cx
		jmp	short Create_CfgData_Loop
Create_CfgData_Exit:
		pop	di
		pop	bx
		mov	si, offset CfgBuffer
		call	Xlat_CfgData_Escd
		pop	ds
		ret
Create_MbFunc	endp

;[]========================================================================[]
;Procedure:	Xlat_CfgData_Escd
;Function :	Translate CFGDATA to one ESCD function
;Input	  :	DS(ES):SI = point to CFGDATA buffer
;		DS(ES):DI = address to store ESCD
;		DS(ES):BX = point to ESCD function head
;Output   :	none
;[]========================================================================[]

		Public	Xlat_CfgData_Escd
Xlat_CfgData_Escd	proc	near
		push	dx

		xor	cx, cx

; Translate MEMCFGDATA to ESCD

		mov	cl, ds:[si].Mem24CfgCount
		jcxz	short Xlat_Mem24_Exit
		or	byte ptr es:[bx].bFuncInfo, MEM_ENTRY
		push	si
		lea	si, ds:[si].Mem24Cfg
Xlat_Mem24_Loop:
		mov	al, ds:[si].MemCtrl
		mov	ah, al
		shr	ah, 3			;data size
		and	ah, 03
		test	ah, 02			;8 and 16 bit support ?
		jz	short @f
		dec	ah
@@:
		or	ah, 04				;24bit decode size
		and	al, 03				;cache, ROM/RAM
		or	al, 00011000b			;type as other
		or	al, 80h 			;more entry
		stosw					;memory information
		mov	eax, ds:[si+1].MemBase
		stosw					;memory base
		mov	al, byte ptr ds:[si+3].MemBase
		stosb					;memory base
		mov	eax, ds:[si].MemLength
		shr	eax, 10
		stosw					;memory range
		add	word ptr es:[bx].wFuncSize, 7	;memory record size
		add	si, (SIZE MEMCFGDATA)
		loop	short Xlat_Mem24_Loop
		pop	si
Xlat_Mem24_Exit:

		call	Xlat_Mem32_DataNode

; Translate IRQCFGDATA to ESCD

		mov	cl, ds:[si].IrqCfgCount
		jcxz	short Xlat_Irq_Exit
		or	byte ptr es:[bx].bFuncInfo, IRQ_ENTRY
		push	si
		lea	si, ds:[si].IrqCfg
Xlat_Irq_Loop:
		mov	ah, 80h 			;more entry, edge
		mov	al, byte ptr ds:[si].IrqInfo
		and	al, 0Fh
		cmp	al, 04
		jb	short @f
		or	ah, 20h 			;level
@@:
		mov	al, ds:[si].IrqNum
		and	al, 0Fh
		or	al, ah
		stosb
		xor	al, al
		stosb					;IRQ ESCD reserved
		add	word ptr es:[bx].wFuncSize, 2	;irq record size
		add	si, (SIZE IRQCFGDATA)
		loop	short Xlat_Irq_Loop
		pop	si
		and	byte ptr es:[di-2], 7Fh 	;clear more entry
Xlat_Irq_Exit:

; Translate DMACFGDATA to ESCD

		mov	cl, ds:[si].DmaCfgCount
		jcxz	short Xlat_Dma_Exit
		or	byte ptr es:[bx].bFuncInfo, DMA_ENTRY
		push	si
		lea	si, ds:[si].DmaCfg
Xlat_Dma_Loop:
		mov	al, ds:[si].DmaNum
		and	al, 0Fh
		or	al, 80h 			;more entry
		stosb

		xor	al, al
		mov	ah, ds:[si].DmaInfo
		test	ah, 03				;check 8 bit transfer
		jz	short @f
		or	al, 00000100b			;16 bit transfer
@@:
		shr	ah, 1				;reserve bit6,5
		and	ah, 00110000b			;dma speed
		or	al, ah
		stosb					;dma info

		add	word ptr es:[bx].wFuncSize, 2	;dma record size
		add	si, (SIZE DMACFGDATA)
		loop	short Xlat_Dma_Loop
		pop	si
		and	byte ptr es:[di-2], 7Fh 	;clear more entry
Xlat_Dma_Exit:

; Translate IOCFGDATA to ESCD

		mov	cl, ds:[si].IoCfgCount
		jcxz	short Xlat_Io_Exit
		or	byte ptr es:[bx].bFuncInfo, IO_ENTRY
		push	si
		lea	si, ds:[si].IoCfg
Xlat_Io_Loop:

;The I/O maxium size of ESCD is 32 bytes, split into different units
;if I/O size bigger than 32 bytes.
		mov	ah, ds:[si].IoLength	;io length
		mov	dx, ds:[si].IoBase	;io base

Next_32ByteDnode:
		mov	al,ah			;get byte count
		cmp	al,20H			;more than 32 bytes ?
		jb	short Below_32ByteDnode

		mov	al, 20h 		;set 32 bytes I/O

Below_32ByteDnode:
		dec	al
		or	al, 80h 		;more entry
		stosb				;I/O port length
		xchg	ax,dx			;get I/O address in AX
		stosw				;setup I/O addr.
		xchg	ax,dx			;restore I/O addr. in DX

		add	word ptr es:[bx].wFuncSize, 3	;io record size

		add	dx,20H			;next 32-byte
		sub	ah,20H			;for next 32-byte
		jc	short Next_IoBaseDnode
		jnz	short Next_32ByteDnode

Next_IoBaseDnode:

		add	si, (SIZE IOCFGDATA)
		loop	short Xlat_Io_Loop
		pop	si
		and	byte ptr es:[di-3], 7Fh 	;clear more entry
Xlat_Io_Exit:
		pop	dx
		ret
Xlat_CfgData_Escd	endp

;[]========================================================================[]
;Procedure:	Xlat_Mem32_DataNode
;Function :	Translate CFGDATA to one ESCD function
;Input	  :	DS(ES):SI = point to CFGDATA buffer
;		DS(ES):DI = address to store ESCD
;		DS(ES):BX = point to ESCD function head
;Output   :	none
;[]========================================================================[]
Xlat_Mem32_DataNode	proc	near
		mov	cl, ds:[si].Mem32CfgCount
		jcxz	short Xlat_Mem32_Exit
		or	byte ptr es:[bx].bFuncInfo, MEM_ENTRY
		push	si
		lea	si, ds:[si].Mem32Cfg
Xlat_Mem32_Loop:
		push	dword ptr ds:[si].MemLength	;Mem. length
		push	dword ptr ds:[si].MemBase	;Mem. base

		cmp	dword ptr ds:[si].MemLength,0	;R122
		je	short Xlat_Mem32_Cont		;R122

Next_64MbEscd:
		mov	al, ds:[si].MemCtrl
		mov	ah, al
		shr	ah, 3				;data size
		and	ah, 03
		test	ah, 02				;8 and 16 bit support ?
		jz	short @f
		dec	ah
@@:
		or	ah, 08				;32bit decode size
		and	al, 03				;cache, ROM/RAM
		or	al, 00011000b			;type as other
		or	al, 80h 			;more entry
		stosw					;memory information

		mov	eax, ds:[si+1].MemBase
		stosw					;memory base
		mov	al, byte ptr ds:[si+3].MemBase
		stosb					;memory base
		mov	eax, ds:[si].MemLength
		cmp	eax,64*1024*1024		;over 64Mb ?
		jb	short Not_Over64Mb
		sub	dword ptr ds:[si].MemLength,64*1024*1024
		add	dword ptr ds:[si].MemBase,64*1024*1024
		xor	eax,eax 			;set 64Mb max.
Not_Over64Mb:
		push	eax
		shr	eax, 10
		stosw					;memory range
		add	word ptr es:[bx].wFuncSize, 7	;memory record size
		pop	eax
		or	eax,eax 			;need continue ?
		jz	short Next_64MbEscd		;build mem. left

Xlat_Mem32_Cont:					;R121
		pop	dword ptr ds:[si].MemBase	;Mem. base
		pop	dword ptr ds:[si].MemLength	;Mem. length

		add	si, (SIZE MEMCFGDATA)

		loop	short Xlat_Mem32_Loop
		pop	si
Xlat_Mem32_Exit:
		test	byte ptr es:[bx].bFuncInfo, MEM_ENTRY
		jz	short @f
		and	byte ptr es:[di-7], 7Fh 	;clear more entry
@@:
		ret
Xlat_Mem32_DataNode	endp

ifdef	PCI_BUS
;[]========================================================================[]
;Procedure:	Create_PciEscd
;Function :	Create PCI board ESCD
;Input	  :	CH = device number (upper 5 bits)
;		ES:DI = point to data buffer for creating PCI ESCD
;Output   :	CF = 0 PCI ESCD created
;		CF = 1 no PCI ESCD created
;[]========================================================================[]

		ALIGN	4
Create_PciEscd	proc	near
		pusha
		push	ds
		push	es

		mov	ax, cs
		mov	ds, ax

; create board header
; BX point to board record start

		mov	bx, di
		push	cx
		mov	si, offset EGROUP:PciEscdBrdHead
		mov	cx, EscdBrdHead_L
		rep	movsb
		pop	cx

		push	cx
Create_PciFunc_Loop:
		call	Check_VendorID
		jnc	short @f
		test	ch, 07
		jnz	short Next_PciEscd_Func
		jmp	short Create_PciEscd_End
@@:

; create function header
; SI point to function record start

		push	di
		push	cx
		mov	si, offset EGROUP:EscdFuncHead
		mov	cx, EscdFuncHead_L
		add	es:[bx].wBrdSize, cx
		rep	movsb
		pop	cx
		pop	si

; check PCI VGA, IDE

		mov	cl, 0Ah
		call	EGet_CfgSpace_Word
		cmp	ah, 06
		je	short Create_Next_Func
		cmp	ax, 0001h		;VGA
		je	short @f
		cmp	ax, 0300h		;VGA
		je	short @f
		cmp	ax, 0301h		;XGA
		jne	short Check_PciIde
@@:
		call	Create_PciVga
		jmp	short Create_Next_Func
Check_PciIde:
		cmp	ax, 0101h		;IDE
		jne	short @f
		call	Create_PciIde
		jmp	short Create_Next_Func
@@:
		call	Create_PciOther
Create_Next_Func:
		or	byte ptr es:[si].bFuncInfo, FUNC_DISABLE

@@:
		test	ch,07h			;alread a multi-function space?
		jnz	short @F		;yes, go point to next function
		mov	cl,0Eh			;read header type
		call	EGet_CfgSpace_Byte	;read header type
		test	al,80H			;multi-function support?
		jz	short Create_PciEscd_End	;not multi-function card
@@:
Next_PciEscd_Func:
		inc	ch
		test	ch, 07
		jnz	short Create_PciFunc_Loop

Create_PciEscd_End:
		pop	cx
		call	Create_PciEcdFF

		push	cx
		mov	cx, 4
		add	es:[bx].wBrdSize, cx
		xor	al, al
		rep	stosb			;record board end
		pop	cx

Create_PciEscd_Exit:
		pop	es
		pop	ds
		popa
		ret
Create_PciEscd	endp

PciEscdBrdHead	label	byte
		dw	EscdBrdHead_L
		db	?
		db	?
		db	4 dup(0)
		dw	4060h
		db	0
		db	0

;[]========================================================================[]
;Procedure:	Proc_PciEscd
;Function :	Process PCI board ESCD
;Input	  :	none
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Proc_PciEscd	proc	near
		pusha

		mov	di, offset CurrentEscd
		mov	si, offset ESCD_BUFFER
		xor	cx, cx
		mov	cl, ds:[si].bBrdCnt
		add	si, 12			;ESCD head length
		jcxz	short Add_New_PciEscd

Found_PciEscd_Loop:
		call	Chk_PciEscd
		jnc	short Cmp_Old_PciEscd
@@:
		add	si, ds:[si].wBrdSize
		loop	short Found_PciEscd_Loop
		jmp	short Add_New_PciEscd

Cmp_Old_PciEscd:
		call	Cmp_BrdEscd
		jc	short @b

		mov	al, ds:[si].bSlotNum
		mov	di, offset OldEscdBrdMap
		call	Reset_EscdBrd
		jmp	short Proc_PciEscd_Exit

Add_New_PciEscd:
		mov	si, di
		mov	di, offset EscdBrdMap
		mov	al, 10h
@@:
		call	Query_EscdBrd
		jnc	short @f
		inc	al
		cmp	al, 40h
		jb	short @b
		jmp	short Proc_PciEscd_Exit
@@:
		mov	ds:[si].bSlotNum, al
		mov	di, offset EscdBrdMap
		call	Set_EscdBrd
		mov	di, offset NewEscdBrdMap
		call	Set_EscdBrd
		mov	bx, offset ESCD_BUFFER
		call	Add_EscdBrd
Proc_PciEscd_Exit:
		popa
		ret
Proc_PciEscd	endp

Check_If_PciVga proc	near
		push	ax

		push	cx
		mov	cl,0AH			;read class code
		call	EGet_CfgSpace_Word
		pop	cx

		cmp	ax, 0001h		;VGA
		je	short @f
		cmp	ax, 0300h		;VGA
		je	short @f
		cmp	ax, 0301h		;XGA
@@:
		pop	ax
		ret
Check_If_PciVga endp

;[]========================================================================[]
;Procedure:	Build_PciMemEscd
;Function :	Build I/O ESCD for PCI devices
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:SI = point to function record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]
Build_PciMemEscd	proc	near

		mov	cl, 04h 		;command register
		call	EGet_CfgSpace_Word
		test	al, 00000010b		;memory present?
		jz	PciMem_Exit
		mov	cl, 10h 		;base address register
Create_PciMem_Loop:
		call	EGet_CfgSpace_Dword
		test	al, 1			;I/O, memory indicator
		jnz	Create_Next_PciMem
		test	eax, 0FFFFFFF0h
		jz	Create_Next_PciMem

		call	Check_If_PciVga 	;check if PCI/VGA card ?
		jnz	short Not_PciVgaCard

		cmp	eax, 100000h		;below 1M ?
		jb	Create_Next_PciMem	;yes,skip ESCD building
Not_PciVgaCard:

		push	ecx
		push	eax			;save original mem. addr.

	;Get requested memory size
		push	eax
		mov	eax, -1
		call	ESet_CfgSpace_Dword	;write PCI
		call	EGet_CfgSpace_Dword	;read PCI
		and	eax, 0FFFFF000h
		jnz	short @f
		mov	eax, 0FFFFF000h 	;minimum 4k
@@:
		call	Validate_MemSize
		not	eax
		inc	eax
		mov	ecx,eax 		;now ecx=memory size
		pop	eax

Next_PciMem_Addr:

		shr	eax, 8			;divid 100h
		or	byte ptr es:[si].bFuncInfo, MEM_ENTRY
		mov	byte ptr es:[di].bMemInfo, 10011001b
		mov	byte ptr es:[di].bMemType, 00001010b
		mov	word ptr es:[di].bMemBase0, ax
		shr	eax, 16
		mov	byte ptr es:[di].bMemBase2, al

		mov	eax,ecx
		cmp	eax,64*1024*1024	;over 64Mb size ?
		jb	short Not_OverPci64Mb
		sub	ecx,64*1024*1024
		xor	eax,eax 		;set 64M maximum
Not_OverPci64Mb:

		push	eax			;save value
		shr	eax, 10 		;divid 400h
		mov	word ptr es:[di].bMemSize0, ax

		mov	ax, 7
		add	di, ax			;memory information length
		add	es:[bx].wBrdSize, ax
		add	es:[si].wFuncSize, ax
		pop	eax			;restore value
		or	ecx,ecx 		;zero length
		jz	short Finish_MemEscd	;yes
		or	eax,eax 		;over 64Mb ?
		jnz	short Finish_MemEscd	;no
						;yes,next address
		pop	eax			;get original base address
		push	eax			;balance stack

		add	eax,64*1024*1024	;next base address
		jmp	short Next_PciMem_Addr
Finish_MemEscd:

		pop	eax			;restore value
		pop	ecx
		call	ESet_CfgSpace_Dword	;restore register


Create_Next_PciMem:
		add	cl, 4
		cmp	cl, 28h
		jb	Create_PciMem_Loop

PciMem_Exit:
		ret
Build_PciMemEscd	endp

Validate_MemSize:
		push	edx
		push	eax
		push	cx
		shr	eax, 12
		mov	edx, 0FFFFF000h
		mov	cx, 20
@@:
		shr	eax, 1
		jnc	short @f
		shl	edx, 1
		loop	short @b
@@:
		pop	cx
		pop	eax
		or	eax, edx
		pop	edx
		ret

;[]========================================================================[]
;Procedure:	Build_PciIrqEscd
;Function :	Build I/O ESCD for PCI devices
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:SI = point to function record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]
Build_PciIrqEscd	proc	near

		mov	cl, 3Ch
		call	EGet_CfgSpace_Byte
		or	al, al
		jz	short PciIrq_Exit
		cmp	al, 0fh
		ja	short PciIrq_Exit
		or	al, 01100000b		;last entry, level, sharable
		stosb				;IRQ information
		xor	al, al			;reserved byte
		stosb
		mov	ax, 2
		add	es:[bx].wBrdSize, ax
		add	es:[si].wFuncSize, ax
		or	byte ptr es:[si].bFuncInfo, IRQ_ENTRY
PciIrq_Exit:

		ret
Build_PciIrqEscd	endp

;[]========================================================================[]
;Procedure:	Build_PciIoEscd
;Function :	Build I/O ESCD for PCI devices
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:SI = point to function record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]
Build_PciIoEscd proc	near
		push	dx

		mov	cl, 04h 		;command register
		call	EGet_CfgSpace_Word
		test	al, 00000001b		;I/O present?
		jz	PciIoEscd_Exit
		mov	cl, 10h 		;base address register

Create_PciIo_Loop:

		call	EGet_CfgSpace_Dword
		test	al, 1			;I/O, memory indicator
		jz	short No_Io_Request
		test	ax, 0FFFCh		;valid I/O loc. assigned
		jz	short No_Io_Request
		push	eax			;save I/O location

		and	ax, 0FFFCh
		mov	dx,ax			;save start I/O addr.

		push	cx
		mov	cl,0AH			;read PCI class code
		call	EGet_CfgSpace_Word
		pop	cx
		cmp	ax,0101H		;PCI/IDE ?
		jne	short Not_PciIdeCard	;no
						;yes
		cmp	dx,400H 		;don't build ESCD for I/O
		jb	short Next_IoBase	;below 400H
Not_PciIdeCard:

		or	byte ptr es:[si].bFuncInfo, IO_ENTRY

		mov	eax, -1 		;write -1 to get alignment
		call	ESet_CfgSpace_Dword	;write register
		call	EGet_CfgSpace_Dword	;read resgiter
		and	ax, 0FFFCh		;valie I/O request ?
		jnz	short Not_4ByteIO	;yes
		mov	ax, 0FFFCh		;no set 4 bytes min.
Not_4ByteIO:
		call	Validate_IoSize
		not	ax
		inc	ax

Next_32Byte:
		push	cx
		mov	cl,al
		cmp	ax,20H			;more than 32 bytes ?
		jb	short Below_32Byte

		mov	cl, 20h 		;set 32 bytes I/O

Below_32Byte:
		dec	cl
		or	cl, 80h 		;more entry
		mov	es:[di].bPortInfo, cl	;I/O port length
		pop	cx
		mov	word ptr es:[di].wPortAddr, dx	;setup I/O addr.

		push	ax
		mov	ax, 3			;I/O information length
		add	di, ax
		add	es:[bx].wBrdSize, ax
		add	es:[si].wFuncSize, ax
		pop	ax

		add	dx,20H			;next 32-byte
		sub	ax,20H			;for next 32-byte
		jc	short Next_IoBase
		jnz	short Next_32Byte

Next_IoBase:

		pop	eax			;restore I/O location
		call	ESet_CfgSpace_Dword	;restore register

No_Io_Request:

Create_Next_PciIo:
		add	cl, 4
		cmp	cl, 28h
		jb	short Create_PciIo_Loop

		test	byte ptr es:[si].bFuncInfo, IO_ENTRY
		jz	short PciIoEscd_Exit
		and	byte ptr es:[di-3].bPortInfo, 01111111b
PciIoEscd_Exit:

		pop	dx
		ret
Build_PciIoEscd endp

Validate_IoSize:
		push	dx
		push	ax
		push	cx
		shr	ax, 2
		mov	dx, 0FFFCh
		mov	cx, 14
@@:
		shr	ax, 1
		jnc	short @f
		shl	dx, 1
		loop	short @b
@@:
		pop	cx
		pop	ax
		or	ax, dx
		pop	dx
		ret

;[]========================================================================[]
;Procedure:	Create_PciOther
;Function :	Create PCI function ESCD
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:SI = point to function record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]

		ALIGN	4
Create_PciOther proc	near

; create PCI memory

Create_PciMem:
		call	Build_PciMemEscd

; create PCI ROM

Create_PciRom:

		test	byte ptr es:[si].bFuncInfo, MEM_ENTRY
		jz	short @f
		and	byte ptr es:[di-7].bMemInfo, 01111111b
@@:

; create PCI IRQ

Create_PciIrq:
		call	Build_PciIrqEscd

; create PCI I/O

Create_PciIo:

		call	Build_PciIoEscd

Create_PciOther_Exit:
		ret
Create_PciOther endp

;[]========================================================================[]
;Procedure:	Create_PciVga
;Function :	Create PCI/VGA function ESCD
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:SI = point to function record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]

		ALIGN	4
Create_PciVga	proc	near

; create PCI memory

Create_VgaMem:
		push	si
		push	cx
		mov	cx, VgaMemFunc_L
		add	es:[bx].wBrdSize, cx
		add	es:[si].wFuncSize, cx
		or	byte ptr es:[si].bFuncInfo, MEM_ENTRY
		mov	si, offset EGROUP:VgaMemFunc
		push	di				;R112
		rep	movsb
;R112 - start
		pop	si
		push	es
		mov	ax, 0C000h
		mov	es, ax
		movzx	ax, byte ptr es:[2]
		shr	ax, 1
		pop	es
		mov	word ptr es:[si+VgaBiosData+5], ax
;R112 - end
		pop	cx
		pop	si

		call	Build_PciMemEscd

Create_VgaMem_Exit:
		test	byte ptr es:[si].bFuncInfo, MEM_ENTRY
		jz	short @f
		and	byte ptr es:[di-7].bMemInfo, 01111111b
@@:

; create PCI IRQ

Create_VgaIrq:
		call	Build_PciIrqEscd

; create PCI I/O

Create_VgaIo:
		push	si
		push	cx
		mov	cx, VgaIoFunc_L
		add	es:[bx].wBrdSize, cx
		add	es:[si].wFuncSize, cx
		or	byte ptr es:[si].bFuncInfo, IO_ENTRY
		mov	si, offset EGROUP:VgaIoFunc
		rep	movsb
		pop	cx
		pop	si

		call	Build_PciIoEscd

Create_PciVga_Exit:
		ret
Create_PciVga	endp

VgaMemFunc	label	byte
	MEMESCD 10011001b, 00000000b, 0A0000h, 020000h	;A0000-BFFFF
VgaBiosData	equ	$ - VgaMemFunc			;R112
	MEMESCD 10011000b, 00000000b, 0C0000h, 8000h	;C0000-C7FFF
VgaMemFunc_L	equ	$ - VgaMemFunc

VgaIoFunc	label	byte
	IOESCD	10000000b, 3B0h, 0Ch		;3B0-3BB
	IOESCD	10000000b, 3C0h, 20h		;3C0-3DF
VgaIoFunc_L	equ	$ - VgaIoFunc

;[]========================================================================[]
;Procedure:	Create_PciIde
;Function :	Create PCI/IDE function ESCD
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:SI = point to function record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]

		ALIGN	4
Create_PciIde	proc	near

; create PCI memory

Create_IdeMem:
		call	Build_PciMemEscd

		test	byte ptr es:[si].bFuncInfo, MEM_ENTRY
		jz	short @f
		and	byte ptr es:[di-7].bMemInfo, 01111111b
@@:

; create PCI IRQ

Create_IdeIrq:
		push	si
		push	cx
		mov	cx, IdeIrqFunc_L
		add	es:[bx].wBrdSize, cx
		add	es:[si].wFuncSize, cx
		or	byte ptr es:[si].bFuncInfo, IRQ_ENTRY
		mov	si, offset EGROUP:IdeIrqFunc
		rep	movsb
		pop	cx
		pop	si

; create PCI I/O

Create_IdeIo:
		push	si
		push	cx
		mov	cx, IdeIoFunc_L
		add	es:[bx].wBrdSize, cx
		add	es:[si].wFuncSize, cx
		or	byte ptr es:[si].bFuncInfo, IO_ENTRY
		mov	si, offset EGROUP:IdeIoFunc
		rep	movsb
		pop	cx
		pop	si

		call	Build_PciIoEscd

Create_PciIde_Exit:
		ret
Create_PciIde	endp

IdeIrqFunc	label	byte
	IRQESCD 10000000b, 14			;IRQ14
	IRQESCD 00000000b, 15			;IRQ15
IdeIrqFunc_L	equ	$ - IdeIrqFunc

IdeIoFunc	label	byte
	IOESCD	10000000b, 1F0h, 10h		;1F0-1FF
	IOESCD	10000000b, 3F6h, 1		;3F6
	IOESCD	10000000b, 170h, 10h		;170-17F
	IOESCD	10000000b, 376h, 1		;376
IdeIoFunc_L	equ	$ - IdeIoFunc

;[]========================================================================[]
;Procedure:	Create_PciEcdFF
;Function :	Create PCI ECD Free Format data
;Input	  :	CH = device number (upper 5 bits)
;		ES:BX = point to board record start
;		ES:DI = point to data buffer for creating PCI function
;Output   :	ES:DI = point to next data buffer for creating PCI function
;[]========================================================================[]

; create ECD free format data

		ALIGN	4
Create_PciEcdFF proc	near
		push	cx
		push	di
		mov	si, offset EGROUP:EscdFuncHead
		mov	cx, EscdFuncHead_L
		add	es:[bx].wBrdSize, cx
		rep	movsb
		mov	dx, di
		pop	si
		push	si
		mov	cx, EcdFFHead_L
		add	es:[bx].wBrdSize, cx
		add	es:[si].wFuncSize, cx
		mov	si, offset EGROUP:EcdFFHead
		rep	movsb
		pop	si
		pop	cx

; SI point to function header

		push	dx
		or	byte ptr es:[si].bFuncInfo, ECD_FF
		and	ch, 0F8h		;clear function number
		mov	dx, 1
Create_PciEcdFF_Loop:
		call	Check_VendorID
		jnc	short @f
		test	ch, 07
		jnz	short Next_PciEcdFF_Func
		jmp	short Create_PciEcdFF_Exit1
@@:


		push	ax			;vendor ID
		mov	al,CURRENT_BUS_NO[bp]	;bus number
		stosb				;bus number
		mov	al, ch
		stosb				;device/function number
		mov	cl, 02			;device ID
		call	EGet_CfgSpace_Word
		stosw				;device ID
		pop	ax
		stosw				;vendor ID
		xor	ax, ax
		stosw				;reserved

		test	ch,07h			;alread a multi-function space?
		jnz	short @F		;yes, go point to next function
		mov	cl,0Eh			;read header type
		call	EGet_CfgSpace_Byte	;read header type
		test	al,80H			;multi-function support?
		jz	short Create_PciEcdFF_Exit	;not multi-function card
@@:
		inc	dx
Next_PciEcdFF_Func:
		inc	ch
		test	ch, 07
		jnz	short Create_PciEcdFF_Loop

Create_PciEcdFF_Exit1:
		dec	dx
Create_PciEcdFF_Exit:
		pop	ax
		xchg	ax, di
		shl	dx, 3			;*8
		add	es:[bx].wBrdSize, dx
		add	es:[si].wFuncSize, dx
		add	es:[di].bEcdFFSize, dl		;ECD FF size
		xchg	ax, di
		ret
Create_PciEcdFF endp

;[]========================================================================[]
;Procedure:	Check_VendorID
;Function :	Check PCI device exist
;Input	  :	CH = device number (upper 5 bits)
;Output   :	CF = 0 PCI device found
;		CF = 1 PCI device not found
;[]========================================================================[]

Check_VendorID:
		xor	cl, cl
		call	EGet_CfgSpace_Word
		cmp	ax, 0FFFFh
		je	short Check_VendorID_Fail
		or	ax, ax
		jz	short Check_VendorID_Fail
		clc
		ret
Check_VendorID_Fail:
		stc
		ret
endif	;PCI_BUS

;[]========================================================================[]
;Procedure:	Create_EscdBrdMap
;Function :	Create EscdBrdMap with original ESCD
;Input	  :	DS:SI = point to ESCD block
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Create_EscdBrdMap
Create_EscdBrdMap	proc	near
		pusha
		push	ds
		push	es
		mov	ax, G_RAM
		mov	es, ax
		xor	al, al
		mov	di, offset EscdBrdMap
		mov	cx, EscdBrdMap_L
		rep	stosb
		xor	cx, cx
		mov	cl, ds:[si].bBrdCnt	;board count
		jcxz	short Create_EscdBrdMap_Exit	;R133
		add	si, 12			;length of ESCD header
Create_EscdBrdMap_Loop:
		mov	al, ds:[si].bSlotNum
		mov	di, offset EscdBrdMap
		call	Set_EscdBrd
		mov	di, offset OldEscdBrdMap
		call	Set_EscdBrd

ifdef	PCI_BUS
		call	Chk_PciEscd
		jnc	short @f
endif	;PCI_BUS
		call	Chk_PnpEscd
		jc	short Create_EscdBrdMap_Next
@@:
		mov	di, offset PnpEscdBrdMap
		call	Set_EscdBrd
Create_EscdBrdMap_Next:
		add	si, ds:[si]
		loop	short Create_EscdBrdMap_Loop
Create_EscdBrdMap_Exit:					;R133
		pop	es
		pop	ds
		popa
		ret
Create_EscdBrdMap	endp

;[]========================================================================[]
;Procedure:	Set_EscdBrd
;Function :	Set bit of EscdBrdMap with board number
;Input	  :	ES:DI = point to EscdBrdMap
;		AL = board number
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Set_EscdBrd	proc	near
		push	ax
		push	bx
		push	cx
		xor	bx, bx
		mov	bl, al
		shr	bl, 3
		and	al, 07
		mov	cl, al
		mov	al, 01
		rol	al, cl
		or	es:[bx+di], al
		pop	cx
		pop	bx
		pop	ax
		ret
Set_EscdBrd	endp

;[]========================================================================[]
;Procedure:	Reset_EscdBrd
;Function :	Reset bit of EscdBrdMap with board number
;Input	  :	ES:DI = point to EscdBrdMap
;		AL = board number
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Reset_EscdBrd
Reset_EscdBrd	proc	near
		push	ax
		push	bx
		push	cx
		xor	bx, bx
		mov	bl, al
		shr	bl, 3
		and	al, 07
		mov	cl, al
		mov	al, 0FEh
		rol	al, cl
		and	es:[bx+di], al
		pop	cx
		pop	bx
		pop	ax
		ret
Reset_EscdBrd	endp

;[]========================================================================[]
;Procedure:	Query_EscdBrd
;Function :	Query board number empty in EscdBrdMap
;Input	  :	ES:DI = point to EscdBrdMap
;		AL = board number
;Output   :	CF = 0 board number empty
;		CF = 1 board number occupied
;[]========================================================================[]

		ALIGN	4
Query_EscdBrd	proc	near
		push	ax
		push	bx
		push	cx
		xor	bx, bx
		mov	bl, al
		shr	bl, 3
		and	al, 07
		mov	cl, al
		mov	al, 01
		rol	al, cl
		test	es:[bx+di], al
		clc
		jz	short @f
		stc
@@:
		pop	cx
		pop	bx
		pop	ax
		ret
Query_EscdBrd	endp

;[]========================================================================[]
;Procedure:	Remove_EscdBrd
;Function :	Remove one board record from global ESCD
;Input	  :	DS:BX = ESCD start
;		DS:SI = current ESCD board block
;Output   :	none
;[]========================================================================[]

		ALIGN	4
		Public	Remove_EscdBrd
Remove_EscdBrd	proc	near
		push	bx
		push	cx
		push	si
		push	di
		push	es

		push	ds
		pop	es
		dec	byte ptr ds:[bx].bBrdCnt	;board count
		mov	cx, ds:[bx]		;ESCD length
		sub	cx, ds:[si]		;board_l - current_l
		mov	ds:[bx], cx		;new ESCD length
		sub	bx, si			;length prior to current board
		sub	cx, bx			;board_l - current_l - prior_l
		mov	di, si			;destination
		add	si, ds:[si]		;source
		rep	movsb

		pop	es
		pop	di
		pop	si
		pop	cx
		pop	bx
		ret
Remove_EscdBrd	endp

;[]========================================================================[]
;Procedure:	Add_EscdBrd
;Function :	Add one board record to global ESCD
;Input	  :	DS:BX = ESCD start
;		DS:SI = current ESCD board block
;Output   :	none
;[]========================================================================[]

		ALIGN	4
Add_EscdBrd	proc	near
		push	bx
		push	cx
		push	si
		push	di
		push	es

		push	ds
		pop	es
		mov	di, bx			;ESCD start
		add	di, ds:[bx]		;original ESCD length
		sub	di, 2			;checksum word
		mov	cx, ds:[si]		;board length
		add	ds:[bx], cx		;new ESCD length
		inc	byte ptr ds:[bx].bBrdCnt	;board count
		rep	movsb

		pop	es
		pop	di
		pop	si
		pop	cx
		pop	bx
		ret
Add_EscdBrd	endp

;[]========================================================================[]
;Procedure:	Scan_SlotEscd
;Function :	Scan board record position in ESCD with slot number
;Input	  :	DS:SI = point to ESCD start
;		AL = slot number
;Output   :	CF = 0 slot ESCD found
;			DS:SI = point to slot ESCD block
;		CF = 1 no slot ESCD found
;[]========================================================================[]

		ALIGN	4
Scan_SlotEscd	proc	near
		push	cx
		xor	cx, cx
		mov	cl, ds:[si].bBrdCnt	;board count
		jcxz	short Scan_SlotEscd_Fail	;R133
		add	si, 12			;length of ESCD header
@@:
		cmp	ds:[si].bSlotNum, al	;slot number
		clc
		je	short @f
		add	si, ds:[si]		;board length
		loop	short @b
Scan_SlotEscd_Fail:					;R133
		stc
@@:
		pop	cx
		ret
Scan_SlotEscd	endp

;[]========================================================================[]
;Procedure:	Chk_MbEscd
;Function :	Check whether or not M/B ESCD
;Input	  :	DS:SI = point to ESCD board block
;Output   :	CF = 0 ESCD board found
;		CF = 1 not ESCD board
;[]========================================================================[]

		ALIGN	4
Chk_MbEscd	proc	near
		cmp	byte ptr ds:[si].bSlotNum, 0
		clc
		je	short @f
		stc
@@:
		ret
Chk_MbEscd	endp

;[]========================================================================[]
;Procedure:	Chk_PnpEscd
;Function :	Check whether or not ISA/PNP ESCD
;Input	  :	DS:SI = point to ESCD board block
;Output   :	CF = 0 ESCD board found
;		CF = 1 not ESCD board
;[]========================================================================[]

		ALIGN	4
Chk_PnPEscd	proc	near
		push	ax
		mov	al, 10h 		;PnP board type
		call	Chk_BrdType
		pop	ax
		ret
Chk_PnPEscd	endp

;[]========================================================================[]
;Procedure:	Chk_PciEscd
;Function :	Check whether or not PCI ESCD
;Input	  :	DS:SI = point to ESCD board block
;Output   :	CF = 0 ESCD board found
;		CF = 1 not ESCD board
;[]========================================================================[]

		ALIGN	4
Chk_PciEscd	proc	near
		push	ax
		mov	al, 04			;PCI board type
		call	Chk_BrdType
		jnc	short @f
		mov	al, 40h 		;PCI Bridge board type
		call	Chk_BrdType
@@:
		pop	ax
		ret
Chk_PciEscd	endp

;[]========================================================================[]
;Procedure:	Chk_BrdType
;Function :	Check board type with ECD F/F
;Input	  :	DS:SI = point to ESCD board block
;		AL = board type
;Output   :	CF = 0 ESCD board found
;		CF = 1 not ESCD board
;[]========================================================================[]

		ALIGN	4
Chk_BrdType	proc	near
		push	si
		add	si, 12			;ESCD board header length
Chk_BrdType_Loop:
		cmp	word ptr ds:[si], 0		;board end
		stc
		je	short Chk_BrdType_Exit
		cmp	byte ptr ds:[si+4], 0C0h	;free form data
		jne	short @f
		cmp	dword ptr ds:[si+6], 'GFCA'     ;ECD free form sign
		jne	short @f
		cmp	byte ptr ds:[si+12], al 	;baord type
		clc
		je	short Chk_BrdType_Exit
@@:
		add	si, ds:[si]			;function length
		add	si, 2
		jmp	short Chk_BrdType_Loop
Chk_BrdType_Exit:
		pop	si
		ret
Chk_BrdType	endp

;[]========================================================================[]
;Procedure:	Cmp_BrdEscd
;Function :	Compare two block of board ESCD information
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;[]========================================================================[]

		ALIGN	4
Cmp_BrdEscd	proc	near
		pusha
		mov	ax, ds:[si]		;board length
		cmp	ax, es:[di]
		jne	short Cmp_BrdEscd_Fail
		add	si, 12			;point to 1st function
		add	di, 12
Cmp_BrdEscd_Loop:
		mov	ax, ds:[si]		;function length
		cmp	ax, es:[di]
		jne	short Cmp_BrdEscd_Fail
		or	ax, ax
		jz	short Cmp_BrdEscd_Success	;jmp if board end

		xor	ax, ax
		mov	al, ds:[si+2]		;selection length
		cmp	al, es:[di+2]
		jne	short Cmp_BrdEscd_Fail
		add	ax, 3			;function length word
						; + selection length byte

		add	si, ax
		add	di, ax

		mov	al, ds:[si]		;function info
		mov	ah, es:[di]
		and	ax, 7F7Fh		;discard disable bit
		cmp	al, ah
		jne	short Cmp_BrdEscd_Fail
		inc	si			;point to function entry
		inc	di
		mov	bx, offset EGROUP:CmpEscdTbl
		mov	cx, 8
Cmp_FuncEscd_Loop:
		shr	al, 1
		jnc	short @f

		push	ax
		push	bx
		push	cx
		call	word ptr cs:[bx]
		pop	cx
		pop	bx
		pop	ax
		jc	short Cmp_BrdEscd_Fail
@@:
		add	bx, 2			;next function entry
		loop	short Cmp_FuncEscd_Loop
		jmp	short Cmp_BrdEscd_Loop

Cmp_BrdEscd_Success:
		clc
		popa
		ret

Cmp_BrdEscd_Fail:
		stc
		popa
		ret
Cmp_BrdEscd	endp

CmpEscdTbl	label	word
		dw	offset EGROUP:CmpTypeSubType
		dw	offset EGROUP:CmpMemory
		dw	offset EGROUP:CmpIrq
		dw	offset EGROUP:CmpDma
		dw	offset EGROUP:CmpPortRange
		dw	offset EGROUP:CmpPortInit
		dw	offset EGROUP:CmpFreeForm
		dw	offset EGROUP:CmpEISAFuncDisabled

;[]========================================================================[]
;Procedure:	CmpTypeSubType
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpTypeSubType	proc	near
		xor	cx, cx
		mov	cl, ds:[si]		;length of string field
		inc	cx
		add	si, cx			;point to next function entry
		clc
		ret
CmpTypeSubType	endp

;[]========================================================================[]
;Procedure:	CmpMemory
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpMemory	proc	near

		push	si
		push	di
		add	si, 2			;point to start address
		add	di, 2
		mov	cx, 5
		repe	cmpsb
		pop	di
		pop	si
		jne	short CmpMemoryFail

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		test	byte ptr es:[di], 80h	;more entries follow?
		jz	short CmpMemoryFail
		add	si, 7			;next memory entry
		add	di, 7
		jmp	short CmpMemory
@@:
		test	byte ptr es:[di], 80h	;more entries follow?
		jnz	short CmpMemoryFail
		add	si, 7			;next function entry
		add	di, 7
		clc
		ret
CmpMemoryFail:
		stc
		ret
CmpMemory	endp

;[]========================================================================[]
;Procedure:	CmpIrq
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpIrq		proc	near

		mov	al, ds:[si]
		mov	ah, es:[di]
		and	ax, 0F0Fh		;reserve IRQ channel number
		cmp	al, ah
		jne	short CmpIrqFail

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		test	byte ptr es:[di], 80h	;more entries follow?
		jz	short CmpIrqFail
		add	si, 2			;next irq entry
		add	di, 2
		jmp	short CmpIrq
@@:
		test	byte ptr es:[di], 80h	;more entries follow?
		jnz	short CmpIrqFail
		add	si, 2			;next function entry
		add	di, 2
		clc
		ret
CmpIrqFail:
		stc
		ret
CmpIrq		endp

;[]========================================================================[]
;Procedure:	CmpDma
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpDma		proc	near

		mov	al, ds:[si]
		mov	ah, es:[di]
		and	ax, 0707h		;reserve DMA channel number
		cmp	al, ah
		jne	short CmpDmaFail

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		test	byte ptr es:[di], 80h	;more entries follow?
		jz	short CmpDmaFail
		add	si, 2			;next dma entry
		add	di, 2
		jmp	short CmpDma
@@:
		test	byte ptr es:[di], 80h	;more entries follow?
		jnz	short CmpDmaFail
		add	si, 2			;next function entry
		add	di, 2
		clc
		ret
CmpDmaFail:
		stc
		ret
CmpDma		endp

;[]========================================================================[]
;Procedure:	CmpPortRange
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpPortRange	proc	near
		mov	al, ds:[si]
		mov	ah, es:[di]
		and	ax, 0F0Fh		;reserve port length
		cmp	al, ah
		jne	short CmpPortRangeFail
		mov	ax, ds:[si+1]		;base address
		cmp	ax, es:[di+1]
		jne	short CmpPortRangeFail

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		test	byte ptr es:[di], 80h	;more entries follow?
		jz	short CmpPortRangeFail
		add	si, 3			;next port range entry
		add	di, 3
		jmp	short CmpPortRange
@@:
		test	byte ptr es:[di], 80h	;more entries follow?
		jnz	short CmpPortRangeFail
		add	si, 3			;next function entry
		add	di, 3
		clc
		ret
CmpPortRangeFail:
		stc
		ret
CmpPortRange	endp

;[]========================================================================[]
;Procedure:	CmpPortInit
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpPortInit	proc	near

		xor	ax, ax
		mov	cl, ds:[si]		;data size
		and	cl, 03			;00-byte, 01-word, 10-dword
		mov	al, 1			;1 byte
		shl	al, cl
		test	byte ptr ds:[si], 04	;bit 2 mask value present?
		jz	short @f
		add	al, al			;double data size
@@:
		add	al, 3			;length of port info, address

		xor	dx, dx
		mov	cl, es:[di]		;data size
		and	cl, 03			;00-byte, 01-word, 10-dword
		mov	dl, 1			;1 byte
		shl	dl, cl
		test	byte ptr es:[di], 04	;bit 2 mask value present?
		jz	short @f
		add	dl, dl			;double data size
@@:
		add	dl, 3			;length of port info, address

		cmp	ax, dx			;total length
		jne	short CmpPortInitFail

		test	byte ptr ds:[si], 80h	;more entries follow?
		jz	short @f
		test	byte ptr es:[di], 80h	;more entries follow?
		jz	short CmpPortInitFail
		add	si, ax			;next port init entry
		add	di, ax
		jmp	short CmpPortInit
@@:
		test	byte ptr es:[di], 80h	;more entries follow?
		jnz	short CmpPortInitFail
		add	si, ax			;next function entry
		add	di, ax
		clc
		ret
CmpPortInitFail:
		stc
		ret
CmpPortInit	endp

;[]========================================================================[]
;Procedure:	CmpFreeForm
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpFreeForm	proc	near
		xor	cx, cx
		mov	cl, ds:[si]		;length
		cmp	cl, es:[di]
		jne	short CmpFreeFormFail
		inc	cx
		push	cx
		push	si
		push	di
		repe	cmpsb
		pop	di
		pop	si
		pop	cx
		jne	short CmpFreeFormFail

		add	si, cx			;next function entry
		add	di, cx
		clc
		ret
CmpFreeFormFail:
		stc
		ret
CmpFreeForm	endp

;[]========================================================================[]
;Procedure:	CmpEISAFuncDisabled
;Function :	Cmp_BrdEscd sub-routine
;Input	  :	DS:SI = source block
;		ES:DI = destination block
;Output   :	CF = 0 match
;		CF = 1 unmatch
;		DS:SI = next pointer
;		ES:DI = next pointer
;[]========================================================================[]

		ALIGN	4
CmpEISAFuncDisabled	proc	near
		clc
		ret
CmpEISAFuncDisabled	endp

ifdef	PCI_BUS
;PCI Routines for calling in E-segment
Eget_CfgSpace_Byte:
		push	bx
		mov	bh,CURRENT_BUS_NO[bp]
		F000_Call	AGet_CfgSpace_Byte
		pop	bx
		ret
Eget_CfgSpace_Word:
		push	bx
		mov	bh,CURRENT_BUS_NO[bp]
		F000_Call	AGet_CfgSpace_Word
		pop	bx
		ret

Eget_CfgSpace_DWord:
		push	bx
		mov	bh,CURRENT_BUS_NO[bp]
		F000_Call	AGet_CfgSpace_DWord
		pop	bx
		ret

ESet_CfgSpace_DWord:
		push	bx
		mov	bh,CURRENT_BUS_NO[bp]
		F000_Call	ASet_CfgSpace_DWord
		pop	bx
		ret
endif	;PCI_BUS

else	;ESCD_SUPPORT					;R129

;[]========================================================================[]
;Procedure:	Decode_MbNode
;Function :	Decode and record resources of motherboard device nodes
;Input	  :	None
;Output   :	None
;[]========================================================================[]
		public	Decode_MbNode
Decode_MbNode	proc	near
		pusha
		push	ds
		push	es

		xor	ax, ax
		mov	ds, ax
		mov	es, ax
		mov	word ptr ds:RES_BUFFER, ax	;initial value to
							; get device node
Decode_MbNode_Loop:
		call	POST_Get_Node
		or	ax, ax				;any error?
		jnz	short Decode_MbNode_End

		mov	di, offset CfgBuffer
		call	Init_CfgData

		mov	si, offset RES_BUFFER+2+12	;resource data start
Decode_MbData_Loop:
		call	Get_Tag_Name			;AH = tag name
							;CX = data block length
		cmp	ah, sEndTag
		je	short Decode_MbData_Exit

		push	si				;current resource data
							; pointer
		push	cx				;data block length

		push	cx
		mov	bx, offset EGROUP:TAG_CODE
		mov	dx, offset EGROUP:Create_Proc
		mov	cx, TAG_CODE_L
@@:
		cmp	cs:[bx], ah
		je	short @f
		inc	bx
		inc	dx
		inc	dx
		loop	short @b
		pop	cx
		jmp	short Decode_MbData_Next

@@:
		pop	cx

		mov	bx, dx
		call	word ptr cs:[bx]

Decode_MbData_Next:
		pop	cx
		pop	si
		add	si, cx				;next data block
		jmp	short Decode_MbData_Loop

Decode_MbData_Exit:
		call	Record_CfgData

Decode_MbNode_Next:
		cmp	byte ptr ds:RES_BUFFER, 0FFh	;device node end
		jne	short Decode_MbNode_Loop

Decode_MbNode_End:
		pop	es
		pop	ds
		popa
		ret
Decode_MbNode	endp
endif	;ESCD_SUPPORT					;R129

ENDIF	;PNP_BIOS

ECODE		ENDS
		END
