;	[]===========================================================[]
;
;	NOTICE: THIS PROGRAM BELONGS TO AWARD SOFTWARE INTERNATIONAL(R)
;	        INC. IT IS CONSIDERED A TRADE SECRET AND IS NOT TO BE
;	        DIVULGED OR USED BY PARTIES WHO HAVE NOT RECEIVED
;	        WRITTEN AUTHORIZATION FROM THE OWNER.
;
; 	[]===========================================================[]
;

;----------------------------------------------------------------------------
;Rev	Date	 Name	Description
;----------------------------------------------------------------------------
;R187	04/29/99 BAR	Add READCOM.INC in XGROUP.
;			For post run AutoLoad awdflash.exe used.
;R186	04/20/99 KVN	Support ATAPI device (LS120/ZIP) bootable in Boot Block.
;			This function available only boot block size over 16k
;			and BIOS.CFG should define "Support_ATAPI_In_BOOTROM"
;R185	04/19/99 STV	Changed save CMOS data to flash area for "Support_CMOS_Backup_Data"
;R180B	03/23/99 RCH	The BIOS can not handle checksum of whole BIOS for
;			2Mb flash if the compressed system BIOS is too small.
;			Added a switch to skip this checksum
;R184	03/12/99 BAR 	Suport Windows NT update BIOS.
;			Always add BIOS ID in bootblock  0FFE8h ,
;			for AWDFLASH.EXE check it .
;R157A  03/12/99 MIL	For SIS 620 ACPI S3 Function Support.
;R183	01/30/99 RCH	Added AMD/K7 CPU support.
;R182	01/22/99 KVN	Fixed boot block not decompress combine ROM except
;			system BIOS.This case occur at 2MB BIOS and system
;			BIOS compressed size less than 64K
;R159B	01/13/98 RIC	Add "Ct_Preset_In_Decompress_Area_After_Jumpless"
;			definition.
;R180A	01/08/99 KVN	Fixed R180 coding mistake.That will cause system always
;			run into boot block in some BIOS
;r181	01/08/99 MCH	Added the loop checking routine for the manufacturers
;			to debug first 32K RAM data signal response is correct
;			or not and output the error data to DEBUG_PORT if the
;			error found until first 32K RAM data is all correct!
;			Define "Debug_1st_32K_RAM_Data_Signal" for effective.
;R180	01/06/99 KVN	Added a checksum for whole BIOS to avoid POST hang.
;			This case is occured when BIOS use awdflash to updated
;			and power off or reset during processing.
;			This function should use CBROM v1.30 and MODBIN v4.50.75
;R179	12/31/98 JSN	Fixed post hang up at 0Ah when Cyrix MII 333GP CPU(66X4)
;			plugged.
;R151A	12/18/98 KVN	Forced to put memory sizing code (chipboot.asm) into
;			the first 8K when boot block area is 16KB.That can add
;			chipboot code area for larger.
;R178	12/16/98 RCH	Flush memory fail LED by sending GPO ourput if no
;			memory is installed for specific customer request.
;R177	12/07/98 KEN	Fixed bug if AMD K6-2 CPU and USB keyboard are installed
;			and the ACPI function is enabled, the system sometimes
;			reset automatically at POST_61s while BIOS decompressing
;			ACPI table.
;			The causation is that the system enter SMM mode during
;			protected mode, then SS is destroyed when exit SMM mode.
;R176	11/25/98 MIL	Added CPU ID for Cyrix MXi CPU.
;R171C	10/28/98 KVN	Fixed decompress error in store type.This mean is
;			compressed signature is '-lh0-' then only hard copy
;			compressed data to target buffer and don't decompress
;			it. This patch will fix system hang up if switch
;			"PPGA_370_CPU_ONLY" is used.
;R175	09/29/98 KVN	Release DMI and ESCD pool in flash ROM when not define
;			"ESCD_SUPPORT" and "FLASH_SUPPORT" in BIOS.CFG
;R174A  09/04/98 KVN    Fixed R174 bug
;R174	09/04/98 KVN	Added E05A_Flag bit0 for graphics POST.
;			Don't fix 16th color for POST message in graphics
;			POST when BIOS.CFG define "No_Show_Graphic_POST_MSG"
;R173	08/24/98 BAR	Added define "Show_Post_Error_Code" to report IDE device has changed.
;			Added define "Show_IDE_Changed_Message"
;R172	08/10/98 KVN	Support KBC ROM combined into main BIOS
;R171B	08/04/98 KVN	Fixed update new BIOS code to old (before 7/23) then
;			always run boot block code if use Intel flash ROM(i.e.
;			boot block be protected)
;R171A	07/23/98 KVN	Fixed Awdflash.EXE execute fail by R171
;R171	07/23/98 KVN	Change method of decompressing in protect mode
;R170	06/29/98 KVN	Added a new switch for chaintech (2A6ILC39)
;R169	06/22/98 KVN	Fixed always run memory sizing code in bootrom when
;			define "BootExt_Extra_Size"
;R164b	06/05/98 MAX	Support CMOS default value save to 2M ROM Flash function
;R164a	06/01/98 MAX	Fixed by 1M ROM 4k Unit Only
;R168   06/01/98 MIL	Change Cyrix MediaGXm Series CPU detection algorithm.
;			Because the GXm CPU support "RDTSC" instruction.
;R167	05/21/98 KVN	If system not found AWARD external code (XGROUP) in 2MB
;			BIOS then will execute boot block POST to avoid system
;			always hang at 0C8h.This is flash ROM first 128k be
;			crashed but last 128k is OK.
;R166	05/18/98 KVN	Fixed compressed code table(0:6000) will be destroyed
;			when one of combined option ROM size over 64k.That will
;			cause POST hang at decompress or execute BootBlock code.
;R165	05/08/98 RIC	Disable C0000-FFFFFh cacheable before enabled P6 L1
;			cache.
;R164	05/06/98 MAX	Support CMOS default value save to Flash function.This
;			function will save CMOS value to flash every time when
;			you change setup value and save it to CMOS.That let you
;			can load it to CMOS if CMOS value is fail or checksum
;			error.The feature will added a hot key (f2) in post error
;			message (POST 78) let you can choise which load CMOS
;			from BIOS setup default or previous setup change value
;			If you want to use it just define "CMOS_Default_in_Flash EQU 1"
;			in BIOS.CFG
;R163	04/28/98 MAX	Fixed CMOS backup to Flash ROM function bug.Added define
;                       "FLASH_CMOS_Size" function in BOOTROM.ASM
;R162	04/24/98 MAX	Support CMOS backup to Flash ROM function.This function
;			will create 2 hot key (F6-Save CMOS to BIOS and
;			F7-Load CMOS from BIOS) in kernel page of setup screen
;			If you want to to use it just define "Backup_CMOS_to_FLASH EQU 1"
;			in BIOS.CFG
;R159A	04/16/98 TNY	Fix "Record_PWRON_Status" and "Jumpless_Support"
;			conflict. Because PWRON status lost after reset.
;R161	03/20/98 KVN	Modify some code to save more bootblock space.
;R160	03/10/98 DNL	Reduce ACPI S4/BIOS code size to save more space
;R159	03/06/98 TNY	Add Ct_Decompress_Hook in decompress area.
;			Option:Ct_Preset_In_Decompress_Area
;R158	02/25/98 DNL	Added ACPI S4/BIOS support
;R157	02/24/98 DNL	Added ACPI S3 state support
;R156	02/11/98 TNY	Move Jumpless code to BootROM.asm (Decompress Area)
;R155B	02/05/98 RAY	Tulip Only
;			----------
;
;			The un-used bytes of the Tulip's 'BCPOEM' structure
;			should be left 'Zero's
;
;R155A	02/04/98 RAY	Tulip Only
;			----------
;
;			Move the Tulip Structure out of the Boot Block to the
;			decompressing code area
;
;R153A	02/02/98 DRS	Save codes
;R155	01/22/98 TNY	Remove BCPOEM_Table to bootrom from extrom.
;R154A	01/21/98 DRS	Fixed difficult size of awdflash.exe header
;R154	01/19/98 DRS	Support run awdflash.exe during POST
;R153	01/19/98 DRS	Support new version 6.0 awdfalsh.exe can directly
;			run in Non-DOS conditions
;			This new function just support Bootblock_16K_Support
;R152	12/31/97 RCH	Change year of copyright from 1997 to 1998
;R151 	12/24/97 MIL	Added "Chipboot_In_External_Boot_Block" define, for
;			move chipboot code to first 8k Boot Block Area.
;R150A	12/08/97 DRS	Some chipset don't want support run PCI/AGP VGA in bootblock
;R150	12/08/97 DRS	Support 16K_8K_8K_Unit of 2M Flash run PCI/AGP
;			Vga in bootblock
;R146B	12/06/97 MIL	Added Cyrix MediaGXm CPU ID.
;R149	11/17/97 RAY	Add flag for the new CBROM.EXE to distinguish the old
;			BIOS & the new BIOS
;R148	08/07/97 DNL	Return compressed code original size by EDX register
;R147 	07/09/97 MIL	Added Patch to Fix BIOS's in boot block can't boot
;			from FDD (for Media GX86).
;R146A	07/03/97 MIL	Added Cyrix MediaGXm CPU ID.
;R146	07/01/97 MIL	Added Cyrix MediaGXi CPU ID.
;R78A	06/20/97 KVN	Remove Earlyio.asm to another location for avoid
;			BootBlock code space overflow
;R143A	06/17/97 KVN	Should clear bus or some chipset will detect error
;			when no plug DRAM.
;R145	05/29/97 LAW	added "BEEP_FOR_NO_RAM"
;R144	05/21/97 KVN	Fix up beep sound frequence not fix if CPU clock is
;			different when memory, VGA or floppy error during POST
;R143	04/12/97 RCH	Change first 256Kb memory testing method to speed up
;			POST.
;R142	03/28/97 RCH	Fixed system sometimes hang at C6H if Cyrix CPU at
;			75Mhzx2 and NEC/SDRAM module for special defined
;			"PATCH_FOR_PR200_SDRAM"
;R138A	03/25/97 RCH	Restore code modified by R138 , it cause DRAM refresh
;			lost.
;R141	03/25/97 RCH	Change year of copyright from 1996 to 1997
;R140	03/24/97 RCH	Align 16 for label "*BBSS*" searching to speed up
;			booting for 2M flash and Pentium Pro platform.
;R139	03/24/97 RAY	Do not clear the warm boot flag if we support PCI RESET
;R138	03/23/97 TNY	We should not program 8237 and 8254 before DRAM sizing
;			, because it cause DRAM sizing hang randonly.(ex:intel chip)
;R104D	02/14/97 RCH	DX will be destroied and lost CPU ID for non-SMI 486
;			if define SLOW_RTC_PATCH
;R137A	02/14/97 KVN	Fixed no show full screen logo bug on 2M BIOS and you
;			combine logo pattern at first area
;R133A	01/24/96 RCH	Support M2 CPU become standard feature
;R137	01/15/97 KVN	Remove P6 micro code to ROM driver pool from 0E000h
;			POST location
;R136	01/10/97 KVN	Fix CIRRUS LOGIC CL-GD5422-80QC-D VGA card cause system
;			hang while initial in boot block POST.Because it will
;			call 0F000h:0F065h (video vector address).
;R135	01/09/97 RCH	Add support both Pentium Pro and Klamath CPUs in one
;			BIOS. Note: It need 3 swtich in BIOS.CFG
;				BOTH_P6_KLAMATH_CPU	EQU	1
;				KLAMATH_CPU_ONLY	EQU	1
;				P6_BIOS_ONLY		EQU	1
;
;R134	01/09/97 DNL	Add switch Special_Early_Init to invoke Ct_Very_Early_Init
;			code size to small problem.
;R133	12/13/96 RCH	Temporary support M2 CPU, This code must be modified
;			after receiving sample.
;R132	12/11/96 RAY	Add switch Very_Very_Early_Init to invoke Ct_Very_Early_Init
;			for some chipsets to enable the ISA decoding before
;			we access any ISA ports. Note that there are some
;			PCI-To-ISA bridges has a default value of ISA disabled.
;R131	12/11/96 RAY	Add Cyrix Gx86 CPU ID
;R130	12/03/96 RCH	The WB cache problem has been fixed on B0 stepping,so
;			enable WB cache for newer revision of KLAMATH CPUs
;			to speed up POST.
;R104C	11/30/96 TNY	Add "SLOW_RTC_PATCH_Delay" option for 2c4l6r31.bin.
;R104B	11/19/96 TNY	Fix some M/B RTC always failed, so we add some delay
;			to patch it.
;R129A	10/21/96 AVN	Fixed Coding Error, Cause 16K BootBlock Cannot Call
;			Extern_execute1/Extern_execute2
;R129	10/16/96 AVN	To Support Different BootBlock For
;			INTEL 2M EEPROM	: 16K BootBlock
;			SST 2M EEPROM	: 16K BootBlock
;			ATMEL 2M EEPROM	: 16K BootBlock
;			AMD 2M EEPROM	: 16K BootBlock
;			MXIC 2M EEPROM	:  8K BootBlock
;R128	10/09/96 RCH	Added Klamath CPU support
;R127	10/08/96 RCH	Change year of copyright from 1995 to 1996
;R126	10/07/96 RCH	Create a new file "P6UPD.INC" to put P6 micro code
;R125	10/01/96 AVN	Fixed if INTEL 28F002BXT boot fail, for awdflash.exe
;			can detect Enable/Disable_Extra_1MBIOS_Hook Correct.
;R124	09/19/96 RCH	Don't initial KBC if not use KBC to control 2M flash
;R108D	09/04/96 KVN	Fixed awdflash.exe update new BIOS then hang at 0C3h
;			when use INTEL 28F001BX-T flash rom
;R104A	08/23/96 KVN	Change another pattern to check CMOS access ready or not
;			for "2A4KDAKA" and "2A4KDAKB".Because its CMOS default
;			value is 0
;R123	08/21/96 KVN	Move some Boot Block code (0E000-0FFFFh) to external
;			Boot Block (0C000-0DFFFh) area for 2MB BIOS to avoid
;			8K Boot Block size overflow
;R122	08/19/96 KVN	Added 2MB flash 16K boot block support
;R121	08/16/96 KVN	Fixed 2M bios with FULL_SCREEN_LOGO hang at 0c3h bug
;R108C	08/15/96 KVN	Fixed coding mistake
;R120A	07/29/96 RCH	Fixed error coding of R120 , that cause chipset not
;			wrap around for E-segment will enter bootblock.
;			Chipsets like ALI1487/89.
;R120	07/26/96 RCH	Some motherboards (use INTEL's chipset) can not read
;			data in E-segment if both BIOSCS# and ISA have ROM
;			decoding.
;R119	07/22/96 RCH	The production revision of P6 is 0617H , so swap the
;			patch codes for 0617H & 0612H, put 0617H in flash
;			block and let end user to update by INTEL's utility
;R118	07/20/96 RAY	For supporting 2M flash, some M/B vendors connect
;			the flash A17 to KB controller's pin. Thus we have
;			to enable KB controller before we can program the
;			A17(KB pin) to low so as to access the extra 1M
;			ROM.
;R117	07/08/96 KVN	Change P6 data pool offset and size.
;R116	07/01/96 KVN	Support 2MB ROM BIOS
;R115	06/17/96 RCH	Some super I/Os' FDD is disabled , BIOS's in boot
;			block need to enable it for booting access, otherwise
;			can not boot from FDD to update normal BIOS.(chips
;			like SMC669,UMC8669 ...)
;R114	06/17/96 RCH	Fixed bootblock BIOS for P6 can not boot from FDD
;			to update normal BIOS.
;R113	06/01/96 RCH	Put code into alignment to prevent system hang at
;			memory size for higher speed CPU
;R111B	05/30/96 AVN	For Custom Chipset (LYNX ect ...) Issue Hardware Reset
;			And Memory Bank Value Default is None, Cause Lose
;			WarmBoot flag, So Move the Function After Memory Sizing.
;R111A	05/25/96 RCH	Clear CMOS location of PCI reset flag as soon as
;			possible to prevent wrong warm booting by last
;			uncompleted booting.
;R112	05/25/96 RCH	Rewrite code of first 256kb memory testing routine
;			to reduce time for P6 system
;R106A	05/13/96 RCH	More delay for 6x86 CPU to fix L2 cache can not found
;			sometimes.
;R111	05/11/96 RCH	Added PCI reset function support to prevent PCI master
;			devices hang while warm booting.
;R110	05/02/96 DNL	Added codes for notebook power management
;R108B	04/30/96 KVN	Don't destroy AX otherwise only decompress two compressed
;			code if BIOS compressed size below 64K
;R107A	04/24/96 RIC	Add define 'VLSI_Special_Reset_Delay' for Special
;			delay For VLSI Lynx chipset,because using Cyrix CPU
;			will halt in post_code '05' for some mainboard.
;R108A	04/23/96 KVN	Added some code to compatible old BIOS version for INTEL
;			flash ROM update
;R109	04/22/96 KVN	Fixed execute warm boot routine when press CTRL-ALT-Del
;			then sudden press hard reset switch or power off and
;			power on right now
;R108	04/22/96 KVN	Fixed BIOS checksum error if BIOS update to support DMI
;			function on INTEL flash rom
;R107	04/12/96 RIC	Special delay For VLSI Lynx chipset,because using
;			Cyrix CPU will halt in post_code '05'.
;R106	04/11/96 RCH	Some chipsets (like i430VX) sometimes hang up after
;			memory sizing if 6X86 133Mhz used. Add a delay loop
;			to fix it if define DELAY_FOR_6X86_PWRON
;R105	04/09/96 KVN	Added P6 BIOS update feature
;R104	04/02/96 RCH	Fixed some RTCs (like SAMSUNG/6818A) ready too slow
;			while power on, it cause CPU type can not be recorded
;			properly. please define SLOW_RTC_PATCH.
;R102C	03/28/96 KVN	Fixed R102B only for define FULL_SCREEN_LOGO
;R102B	03/27/96 KVN	Fixed bug for execute awdflash.exe v5.1 hang if support
;			full-page 640X464 logo
;R103	03/14/96 KVN	Fixed always execute bootrom code of memory sizing
;R102A	02/15/96 KVN	Fixed bug for execute awdflash.exe hang
;R102	02/14/96 KVN	Added 640x480 logo display
;R101	02/08/96  KVN	Change BIOS revision for setup default display title
;			string of MODBIN.EXE
;R100	02/02/96 RCH	The ALI/152X chipset should set chipset register to
;			turn on L1 cache and this bit should be set after
;			CPU L1 cache is turon.
;R99	02/01/96 RIC    Special Reset For VLSI Lynx chipset.
;R98	12/12/95 RCH	Special patch for ORION/PnP
;R97	12/09/11 RCH	P6 don't have 16bytes buffer , so change method for
;			supporting PnP/ESCD.
;R96	12/07/95 TNY	Add QUALIFY_L2_CACHE_ON_DECOMPRESS for VIA570 special.
;R95	12/04/95 RCH	Cyrix have a wrong CPU ID and it need BIOS to support
;			it.
;R94	11/23/95 KVN	Fixed system hang if modify ct_memory_presence routine
;R93	11/17/95 RCH	Don't use E1H to do delay, use NEWIODELAY instead
;R92    10/18/95 KVN	Added revision number for modbin
;R91    10/18/95 RCH	Added Cyrix 5x86 4x clock (133Mhz) support
;R90	10/18/95 KVN	Added MXIC FLASH PnP feature support
;R89	09/13/95 RCH	Added TI486 DX4 CPU support , the value is 81H in DIR0
;			because this CPU is same as CxDx4 , so use same CPU
;			value in CMOS
;R88	07/06/95 KVN	Disable M1 LINBRST bit of CCR3 before turn on cpu_cache
;R87	07/05/95 RCH	Some chipsets can not turn on L1 cache alone with
;			some special cases.
;R86	06/16/95 RAY	Add individual control switches to each level CPU
;R85	06/14/95 RCH	Remove some CPUs table and detected them with CPUID
;			instruction in CPU.ASM
;R84	06/14/95 KVN	Fixed checksum bug when be compressed size over 64KB
;R63A	06/14/95 RCH	Fixed error coding for 586 CPU
;R83	06/13/95 RCH	Some M/Bs (like VIA/570) failed on warm boot or exit
;			from setup while M1 CPU plugged and linear burst is
;			on.
;R73A	06/12/95 DNL	Move linear burst function to CPU.ASM
;R82	06/09/95 DNL	Added Cyrix M1 CPU 4 clock mode support
;R81	06/07/95 RCH	Added INTEL P55CT support
;R80    06/05/95 RCH	Added INTEL P6 CPU support
;R79	05/31/95 RAY	Some Cyrix CPU return ID with value 00h, e.g. M6
;			engineering samples
;R78	05/30/95 RCH	Some super IO contain RTC & KBC should be programmed
;			just after power on
;R77	05/24/95 RCH	Move codes to atorgs.asm due to some M/Bs hang up
;			while warmboot from OS2 for WB CPU
;R76	05/22/95 KVN	Add Expand subroutine offset for AWDFLASH.EXE utility
;R75	05/20/95 RAY	Add Cyrix DX4 support
;R74	05/17/95 AVN	Fixed Routine Address Had Change If Modify Chiprun.asm
;			And FLASH_ROUTINE_HEAD Was Index Old Address Because
;			Can't Rewrite By Use INTEL BOOTBLOCK ROM.
;			FLASH_ROUTINE_HEAD Move To Chiprun.asm
;R73	05/09/95 DNL	Added Cyrix M1 CPU linear burst function support
;R72	04/27/95 KVN	Fixed BootBlock ROM Ckecksum Fail Boot From FDD Can't
;			Run Autoexec.bat.
;R71A	04/27/95 DNL	Fixed Cyrix CPU type detection incorrect bug
;R71	04/17/95 RCH	Support Cyrix M1 CPU become stanard feature, also
;			rewrite CPU detection for M6/M7
;R70	03/15/95 DNL	Added CYRIX M9 CPU support
;R69	03/15/95 RCH	Don't issue memory write before memory sizing ,
;			otherwise UMC/890 system hang at POST_5s after
;			hardware reset with SST flash ROM.
;R68	03/10/95 KVN	Fix keyboard service (int 16) error
;R67	02/28/95 DNL	Don't destroy ES register during expand compression BIOS
;			, because that can't find VGA BIOS
;R66	02/23/95 AVN	Added New Flash Utility in chiprun.asm
;R65	02/23/95 KVN	"sti" when call int16 func0
;R64	02/07/95 KVN	Boot block bios support Keyboard
;R63	01/10/95 RAY	Add No_386_Support & No_586_Support option
;R61	01/09/95 RCH	Added INTEL P5T CPU support,it's P5 overdrive
;R60	01/07/95 RCH	Added INTEL P54CT CPU support,it's P54C overdrive
;R59	01/06/95 DNL	Added U5 non_cache CPU support
;R58	12/29/94 RCH	Added more stepping number for IBM 486DL3 CPU
;R54	11/30/94 RCH	Added CYRIX M1 CPU support. There are four clock modes
;			of this CPU , we don't support 4/1 mode now.
;R52A	11/30/94 RCH	Also disable PENTIUM parity check

		PAGE	56,132
		TITLE	BOOTROM  -- 386 ROM/BIOS BASE
.386P
;[]---------------------------------------------------------------------[]
;
;  Boot Block BIOS module
;
;  This module will be complied and linked to a 64Kb executable file
;  -BOOTROM.EXE . This module should be a basic bootable ROM module
;  to floppy drive for 1M & 2M flash or be a loader for 2M flash to
;  load Award flash utility (AWDFLASH.EXE) to program flash with
;  proper BIOS when the flash is crashed.
;
;  This module is part of system BIOS. The tool MODBIN.EXE will
;  extract some codes at top of this module and merge it into top
;  of 128KB BIOS image. The codes include bootblock (8Kb for 1M flash,
;  16Kb for 2M flash) , Decompress engine (4Kb) and Memory sizing
;  (4Kb). MODBIN also compress the raw BIOS ( ORIGINAL.BIN ) and
;  merge it into bottom of 128KB BIOS image to form a completed
;  compressed BIOS image.
;
;[]---------------------------------------------------------------------[]

		INCLUDE BIOS.CFG
		INCLUDE COMMON.MAC
		INCLUDE ATORGS.MAC
		INCLUDE POST.MAC

		INCLUDE CMOS.EQU
		INCLUDE COMMON.EQU
		INCLUDE 8042.EQU
		INCLUDE 8254.EQU
		INCLUDE 8259.EQU
		INCLUDE 8237.EQU
		INCLUDE 82077.EQU
		INCLUDE MATHCOP.EQU
		INCLUDE port61.EQU
		INCLUDE akbrd.EQU
		INCLUDE adisk.EQU
		INCLUDE cpu.EQU
		include	BtRomSeg.equ			;R90
		include	bsetup.inc			;R102

		extrn	Get_Ct:Near
		extrn	Set_Ct:Near
		extrn	Get_Set_Ct:Near
		extrn	Move_Codes:Near

Error_Flag		EQU	byte ptr [bp]
	KbdCtrl_Err	EQU	00000001b
	KeyBoard_Err	EQU	00000010b

COMPRESSED_UNKNOW_BYTE	EQU	3
;R186 SPURIOUS_INT_HDLR	EQU	IRET_VECT
BootPOST_STK		EQU	1000h
BootPOST_data		EQU	0c00h
CR			EQU	0dh
LF			EQU	0ah

GAPRINT			EQU	NOT FALSE
ORG_OFFSET		EQU	0E000h			; OFFSET OF OVERLAY

;amount of time to wait for head settle, per unit in parameter
;table = 1 ms.
WAIT_FDU_HEAD_SETTLE	EQU	33		; 1 ms in 30 micro units.
;amount of time to wait for completion interrupt from NEC.
;1.5 seconds.
WAIT_FDU_INT_LO		EQU	050000			; 1.5 secs in 30 micro units.
WAIT_FDU_INT_HI		EQU	0

;Time to wait while waiting for each byte of NEC results = .5
;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
WAIT_FDU_RESULTS_LO	EQU	16667		; .5 seconds in 30 micro units.
WAIT_FDU_RESULTS_HI	EQU	0

;amount of time to wait for motor spin up, per unit in
;parameter table = 1/8th of second.
WAIT_FDU_8THS	EQU	4167	; 125,000/30 = 1/8th second in 30 micro units.

;Time to wait in between sending each byte of command to NEC =
;.5 seconds. .5 seconds = 500,000 us.  500,000/30 = 16,667.
WAIT_FDU_SEND_LO	EQU	16667		; .5 secons in 30 us units.
WAIT_FDU_SEND_HI	EQU	0

		INCLUDE EXP.EQU                         ; some equates

UpdateCRC	macro
		push	ax
		push	bx
		push	si

		mov	si,ax
		mov	ax,word ptr ds:crc
		xor	ax,si
		and	ax,00ffh
		mov	si,ax
		shl	si,1
		mov	bx,word ptr crctable[si]
		mov	ax,word ptr ds:crc
		shr	ax,8
		xor	ax,bx
		mov	word ptr ds:crc,ax

		pop	si
		pop	bx
		pop	ax
	ENDM

;
; The following data segment for data decompression is needed in very early
; POST stage and could be discarded completely after decompression job is
; done. The segment is now hard coded as 3000h and could be relocated to
; anywhere of base memory area. The size of this segment is about 22K.
;

EXP_DATA	SEGMENT	USE16 AT 3000H

;R171	ORG	3000H



	Header                  db      255 dup(?)
	namelen			db	? ; Note! one byte long only


	SrcSegment		dw	?
	SrcOffset		dw	?


	TgtSegment		dw	?
	TgtOffset		dw	?

	ExpSegment		dw	?
	ExpOffset		dw	?

	crctable                dw      (UCHAR_MAX+1) dup(?)
	crc                     dw      ?
	bitbuf                  dw      ?
	compsize                dd      ?
	origsize                dd      ?
	left                    dw      (2 * NC - 1) dup(?)
	right                   dw      (2 * NC - 1) dup(?)
	buf                     db      ?
	c_len                   db      NC dup(?)
	pt_len                  db      NPT dup(?)
	blocksize               dw      ?
	c_table                 dw      4096 dup(?)
	pt_table                dw      256 dup(?)

	subbitbuf               dw      ?
	bitcount                dw      ?
	buffer                  db      DICSIZ dup(?);
	headersize              db      ?
	headersum               db      ?
	file_crc                dw      ?
	temp_name               dw      ?	; store pointer to filename
	j			dw	?	; remaining bytes to copy
	temp_param		dw	?	; for storing temp parameter
	count			dw	17 dup(?)
	weight			dw	17 dup(?)
	start			dw	18 dup(?)
	vmask			dw	?
	avail			dw	?
	nchar			dw	?
	nextcode		dw	?
	jutbits			dw	?
	len			dw	?
	i			dw	?
	k			dw	?
	p			dw	?	; pointer
	s_i			dw	?	; static i
;R171 start
	Expand_GDTR		dw	?	;8*2			; LIMIT
	Expand_GDTR_Addr	dd	?	;offset Expand_GDT	;address of GDT

;----- null descriptor
	Expand_GDT		dd	?	;0
				dd	?	;0

	Expand_INDEX	=	((OFFSET $ - OFFSET Expand_GDT)/8) SHL 3
	Expand_GDT1_1		dd	?	;0ffffh
	Expand_GDT1_2		dd	?	;08f9300h
;R171 end
;R177 - start
	DATA0_INDEX	=	((OFFSET $ - OFFSET Expand_GDT)/8) SHL 3
	DATA0			db	8 dup(?)
;R177 - end

EXP_DATA	ENDS

SEG_0		SEGMENT	USE16 AT 0

		org	10h
		INCLUDE SEG_0.INC

SEG_0		ENDS

G_RAM		SEGMENT USE16 AT 0

		ORG	400H
		INCLUDE G_RAM.INC

		ORG	412h
Floppy_CMOS_Type	Label	Byte

		ORG	7C00H
BOOT		LABEL	FAR

G_RAM		ENDS

;R186 start
BootExt_Off		EQU	0
DecmpCode_Off		EQU	2
Extract_Off		EQU	10
CleanUpBaseMemory_Off	EQU	12
Expand_Off		EQU	14

ifdef	Bootblock_16K_Support
Chipboot_In_External_Boot_Block   equ	1
endif	;Bootblock_16K_Support

if	BootROM_Code	eq	2
ifdef	Bootblock_16K_Support
		public	Extern_execute1
		public	Extern_execute2
ifndef	No_Support_PCI_VGA_in_Bootblock
		public	InitPciVga
		public	PCI_Procedure
endif	;No_Support_PCI_VGA_in_Bootblock
endif	;Bootblock_16K_Support
		extrn	Snd_Spkr:near
		extrn	Get_CMOS:near
		extrn	Set_CMOS:near
		extrn	CPU_CACHE:near
		extrn	Display_Str:near
;R186 end

DGROUP		GROUP	FCODE
FCODE		SEGMENT	USE16 DWORD PUBLIC 'CODE'
		ASSUME	CS:DGROUP,DS:EXP_DATA

ifdef	Flash_2M_support			;R122
 ifdef	Bootblock_16K_Support			;R129
	;Reserve space for 16K boot block ( 2M flash )
		DB	0c000h dup (0ffh)	;R122
 else;	Bootblock_16K_Support			;R129
	;Reserve space for 8K boot block especially for MX2000PPC 2M flash
		DB	0e000h dup (0ffh)	;R129
 endif;	Bootblock_16K_Support			;R129
else	;Flash_2M_support			;R122
	;Reserve space for 8K boot block ( 1M flash )
		DB	0e000h dup (0ffh)
endif	;Flash_2M_support			;R122

;R105 start
ifdef	P6_BIOS_ONLY
ifdef	FLASH_SUPPORT	;R175
		org	P6_Block_Start_Seg
	;2Kb data block reserved for P6 class micro update, Note that this
	;space can be updated by Intel's CHECKUP utility to flash newest
	;micro code for current CPU plugged. Detailed see INT 15H function
	;0D042H in p6update.asm
		include	P6UPD.INC		;R126

endif	;FLASH_SUPPORT	;R175
endif	;P6_BIOS_ONLY
;R105 end
;R90		org	0c000h
;[]------------------------------------------------------------------[]
; 	Start of Decompress Engine
;[]------------------------------------------------------------------[]
	;Location of decompress engine, it is only 4Kb space reserved.
	;Normally it is at 06000H for 2M (16K/8K/8K) flash and
	;0B000H for 1M (8K/4K/4K) flash memory
		org	Decompress_Code_Seg	;R90

		db	'= Award Decompression Bios =',0

	; subroutines

;R108A start
;!!!!!!!!!!! Don't move this section code for compatible old BIOS !!!!!!!!!!!
	Expand_To_RAM	proc	near
	;
	; Enable the shadow area we want to expand our data to,
	; copy data from temp buffer to this area according to 'origsize'
	; shadow this area then write protect this area.
	; EAX : Original (Uncompressed) file size
	; ES : Segment of Expansion area
	; DI : starting offset of Expansion area
	; DS : Segment of target buffer area
	; SI : starting offset of target buffer area
	; NOTE !!! : This could be a cross-segment far call
	;

	; Please use the parameters passed in to determine how many pages
	; of shadow memory you have to 'SHADOW'
	; This sample does not bother to check by simply using 32K of E000 segment


	; copy from buffer to shadow memory

		shr	eax,1
Expand_Loop:
		mov	cx,8000h
		cmp	eax,8000h
		jae	short @F
		mov	cx,ax
@@:
		rep	movsw
		mov	cx,ds
		add	ch,10h		;next segment
		mov	ds,cx
		mov	cx,es
		add	ch,10h		;next segment
		mov	es,cx
		sub	eax,8000h
		ja	short Expand_Loop
		ret

	Expand_To_RAM	endp
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;R108A end

	CleanUpBaseMemory	proc	near
	;
	; clean up the temp buffer we used for data storage before boot
	; clear the whole segment of 3000h where we used for data area
	; also clear the whole segment of 8000h where TgtSegment located at.
	;

		nop			;R108A !!!!! Don't move !!!!!
		mov	ax,ds
		mov	es,ax
		xor	di,di
		mov	cx,2000h	;32Kb to clear
		xor	eax,eax
		rep	stosd

;R108A start
;!!!!!!!!!!! Don't move this section code for compatible old BIOS !!!!!!!!!!!
		jmp	@F
		mov	es,ax
		xor	di,di
		mov	cx,4000h
		xor	eax,eax
		rep	stosd

		cmp	dword ptr origsize,10000h ; more than 64K ?
		jbe	short @F

		mov	ax,TGT_SEGMENT	; then we need to clean up another segment
		add	ax,1000h
		mov	es,ax
		xor	di,di
		mov	cx,4000h
		xor	eax,eax
		rep	stosd
	@@:
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;R108A end

		ret

	CleanUpBaseMemory	endp


	FwriteCRC	proc	near
	;
	; Input : CX -- number of bytes to write to output file
	;

		push	ax
		push	bx
		push	dx

		push	cx

		push	es
		push	si
		mov	ax,word ptr TgtSegment
		mov	es,ax
		mov	bx,word ptr TgtOffset
		mov	si,offset buffer
	FWCRC_0:
		mov	al,ds:[si]
		mov	es:[bx],al
		inc	si
		inc	bx
		loop	short FWCRC_0
		mov	word ptr TgtOffset,bx
		or	bx,bx	; if bx is zero means we need to change segment
		jnz	short @F
		add	word ptr TgtSegment,1000h
	@@:
		pop	si
		pop	es

		pop	cx
		cmp	ax,cx
		jb	short FWCRC_Err

                inc     cx
                mov     bx,offset buffer

	FWCRC_1:

		movzx	ax,byte ptr [bx]
		dec	cx
		jcxz	short FWCRC_2

		UpdateCRC

		inc	bx
		jmp	short FWCRC_1

	FWCRC_Err:

	FWCRC_2:

		pop	dx
		pop	bx
		pop	ax

		ret

	FwriteCRC	endp



	FillBuf		proc	near	; shift bitbuf n bits left, read n bits
	;
	; Input : AX
	; Output : None
	;
		pusha

		mov	word ptr temp_param,ax	; save
		mov	cx,ax
		mov	ax,word ptr bitbuf
		shl	ax,cl
		mov	word ptr bitbuf,ax

	FB_1:
		mov	ax,word ptr temp_param
		cmp	ax,word ptr bitcount
		jbe	short FB_3
		sub	ax, word ptr bitcount
		mov	word ptr temp_param, ax
		push	ax
		mov	ax, word ptr subbitbuf
		pop	cx	; pop out temp_param
		shl	ax,cl
		or	word ptr bitbuf, ax

		cmp	dword ptr compsize,0
		je	short FB_2
		dec	dword ptr compsize
		push	es
;R171		mov	ax,word ptr SrcSegment
;R171		mov	es,ax
		mov	bx,word ptr SrcOffset
;R171		movzx	ax,byte ptr es:[bx]
		call	Get_Exp_Src_Byte				;R171
		mov	word ptr subbitbuf,ax
		inc	word ptr SrcOffset
		jnz	short @F				;R84
;R171B start
		mov	cx,cs				;get code segment
		cmp	cx,2000h			;In POST?
		mov	cx,word ptr SrcSegment		;load real mode segment
		jne	short Add_SrcSegment
		test	ch,0f0h				;is old BIOS call?
		jz	short Set_SrcSegment_Descrp	;No,jump
Add_SrcSegment:
;R171B end
		add	word ptr SrcSegment,1000h		;R84
Set_SrcSegment_Descrp:					;R171B
;R171 start
		mov	ecx,Expand_GDT1_2
		rol	ecx,8
		xchg	cl,ch
		inc	cx
		xchg	cl,ch
		ror	ecx,8
		mov	Expand_GDT1_2,ecx
;R171 end
@@:								;R84
		pop	es

		jmp	short @F
	FB_2:
		mov	word ptr subbitbuf,0
	@@:
		mov	word ptr bitcount,CHAR_BIT
		jmp	short FB_1
	FB_3:
		mov	ax, word ptr bitcount
		sub	ax, word ptr temp_param
		mov	word ptr bitcount,ax
		push	ax

		mov	ax, word ptr subbitbuf
		pop	cx
		shr	ax,cl

		or	word ptr bitbuf, ax

		popa

		ret

	FillBuf		endp

	GetBits		proc	near

	;
	; Input : AX
	; Output : AX
	;

		push	cx
		push	bx

		mov	cx,BITBUFSIZ
		sub	cx,ax
		mov	bx,ax		; save a copy for later use

		mov	ax,word ptr bitbuf
		shr	ax,cl

		push	ax	; save returned result

		mov	ax,bx		; restore original parameter
		call	FillBuf

		pop	ax	; returned value

		pop	bx
		pop	cx

		ret

	GetBits		endp


	InitGetBits	proc	near

		mov	word ptr bitbuf,0
		mov	word ptr subbitbuf,0
		mov	word ptr bitcount,0

		mov	ax,BITBUFSIZ
		call	FillBuf	; with parameter pass-in BITBUFSIZ (16)

		ret

	InitGetBits	endp

	HufDecodeStart	proc	near

		call	InitGetBits
		mov	word ptr blocksize,0

		ret

	HufDecodeStart	endp

	DecodeStart	proc	near

		call	HufDecodeStart
		mov	word ptr j,0	; remaining bytes to copy

		ret

	DecodeStart	endp

	InitLocalVars	proc	near

		push	bx

		mov	word ptr i,0
		mov	word ptr k,0
		mov	word ptr len,0
		mov	word ptr jutbits,0
		mov	word ptr avail,0
		mov	word ptr nextcode,0
		mov	word ptr vmask,0

		xor	bx,bx
	ILV_1:
		cmp	bx,34
		jae	short ILV_2
		mov	word ptr count[bx],0
		mov	word ptr weight[bx],0
		mov	word ptr start[bx],0
		add	bx,2
		jmp	short ILV_1
	ILV_2:
		mov	word ptr start[34],0

		pop	bx

		ret

	InitLocalVars	endp

	MakeTable	proc	near
	;
	; Input : BX, SI, DX, DI
	; Output :
	;

		pusha

		call	InitLocalVars	; init local variables and arrays

		push	bx
		mov	bx,2
	MT_1:
		cmp	bx,32
		ja	short MT_2
		mov	word ptr count[bx],0
		inc	bx
		inc	bx
		jmp	short MT_1
	MT_2:
		pop	cx		; get nchar parameter to cx

		push	cx		; save nchar for later use
		xor	bx,bx
	MT_3:
		cmp	bx,cx
		jae	short MT_4
		push	si
		add	si,bx
		movzx	ax,byte ptr [si]
		shl	ax,1		; adjust to word index
		mov	si,ax
		inc	word ptr count[si]
		pop	si
		inc	bx
		jmp	short MT_3
	MT_4:
		mov	word ptr start[2],0	; adjust to word index (from 1 to 2)

		mov	bx,1
	MT_5:
		cmp	bx,16
		ja	short MT_6
		mov	cx,16
		sub	cx,bx
		push	bx
		shl	bx,1
		mov	ax,word ptr count[bx]
		shl	ax,cl
		add	ax,word ptr start[bx]
		mov	word ptr start[bx+2],ax
		pop	bx
		inc	bx
		jmp	short MT_5
	MT_6:
		mov	ax,1
		shl	ax,16
		cmp	ax,word ptr start[34]
		je	short MT_7

	MT_Err:

		jmp	MT_Exit		; bye ! now
	MT_7:
		mov	cx,16
		sub	cx,dx
		mov	word ptr jutbits,cx
		mov	bx,1
	MT_8:
		cmp	bx,dx
		ja	short MT_9
		push	bx			; save bx
		shl	bx,1			; adjust to word index
		mov	ax,word ptr start[bx]
		mov	cx,word ptr jutbits
		shr	ax,cl
		mov	word ptr start[bx],ax
		pop	bx			; get original index
		mov	cx,dx
		sub	cx,bx
		mov	ax,1
		shl	ax,cl
		push	bx			; save index
		shl	bx,1			; adjust to word index
		mov	word ptr weight[bx],ax
		pop	bx			; get original index
		inc	bx
		jmp	short MT_8
	MT_9:
		cmp	bx,16
		ja	short MT_10
		mov	cx,16
		sub	cx,bx
		mov	ax,1
		shl	ax,cl
		push	bx			; save original index
		shl	bx,1			; adjust to word index
		mov	word ptr weight[bx],ax
		pop	bx			;restore original index
		inc	bx
		jmp	short MT_9
	MT_10:
		mov	cx,word ptr jutbits
		mov	bx,dx
		inc	bx
		shl	bx,1			; adjust to word index
		mov	ax,word ptr start[bx]
		shr	ax,cl
		mov	bx,ax		; store in bx for var i
		mov	ax,1
		shl	ax,16
		cmp	bx,ax
		je	short MT_12
		mov	cx,dx
		mov	ax,1
		shl	ax,cl
	MT_11:
		cmp	bx,ax
		je	short MT_12
		push	bx		; save original index
		shl	bx,1		; adjust to word index
		add	bx,di	 	; di contains the offset of array table
		mov	word ptr [bx],0
		pop	bx
		inc	bx
		jmp	short MT_11
	MT_12:
		pop	cx		; restore nchar

		; from this point we start using global variable for result
		; storing. We might consider to change to use global variable
		; instead of pushing/poping a lot of registers later.

		mov	word ptr avail,cx
		mov	word ptr nchar,cx	; move this line to the upper
						; part of this subroutine
		mov	cx,15
		sub	cx,dx
		mov	ax,1
		shl	ax,cl
		mov	word ptr vmask,ax
		xor	bx,bx			; BX stand for variable ch
	MT_13:
		cmp	bx,word ptr nchar
		jae	MT_Exit
		movzx	ax,byte ptr [bx+si]	; si contains the offset of
						; array bitlen
		mov	word ptr len,ax
		cmp	word ptr len,0
		je	MT_20			; continue looping
		push	bx			; bx contains value of variable ch
		mov	bx,word ptr len
		shl	bx,1			; adjust to word index
		mov	ax,word ptr start[bx]
		add	ax,word ptr weight[bx]
		mov	word ptr nextcode,ax
		cmp	word ptr len,dx		; dx contains the value of tablebits
		ja	short MT_15
		mov	bx,word ptr len
		shl	bx,1			; adjust to word index
		mov	ax,word ptr start[bx]
		pop	bx			; now bx contains the value of ch

	MT_14:
		cmp	ax,word ptr nextcode
		jae	MT_19
		push	di
		add	di,ax
		add	di,ax		; adjust to word index
		mov	word ptr [di],bx
		pop	di
		inc	ax
		jmp	short MT_14

	MT_15:

		; stack is not yet balanced

		; Now BX stored in the stack still contains value of var ch

		mov	bx,word ptr len
		shl	bx,1			; adjust to word index
		mov	ax,word ptr start[bx]
		mov	word ptr k,ax
		mov	cx,word ptr jutbits
		shr	ax,cl
		mov	bx,ax
		shl	bx,1			; adjust to word index
		add	bx,di
		mov	word ptr p,bx	; get the pointer of table[k>>jutbits]
		mov	bx,word ptr len
		sub	bx,dx
		mov	word ptr i,bx
	MT_16:
		cmp	word ptr i,0
		je	short MT_18
		mov	bx,word ptr p
		cmp	word ptr [bx],0
		jne	short MT_17
		mov	bx,word ptr avail
		shl	bx,1			; adjust to word index
		mov	word ptr right[bx],0
		mov	word ptr left[bx],0
		mov	bx,word ptr p
		mov	ax,word ptr avail
		mov	word ptr [bx],ax
		inc	ax
		mov	word ptr avail,ax
	MT_17:
		mov	ax,word ptr k
		mov	bx,word ptr vmask
		and	ax,bx
		jz	short MT_17_1

		; the following 5 lines of code are converted from "p = &right[*p]"

		mov	bx,word ptr p
		mov	ax,word ptr [bx]
		shl	ax,1		; adjust to word index
;		mov	bx,word ptr right
		mov	bx,offset right
		add	bx,ax
		mov	word ptr p,bx
		jmp	short MT_17_2
	MT_17_1:
		; the following 5 lines of code are converted from "p = &left[*p]

		mov	bx,word ptr p
		mov	ax,word ptr [bx]
		shl	ax,1		; adjust to word index
;		mov	bx,word ptr left
		mov	bx,offset left
		add	bx,ax
		mov	word ptr p,bx

	MT_17_2:
		mov	ax,word ptr k
		shl	ax,1
		mov	word ptr k,ax
		dec	word ptr i
		jmp	short MT_16

	MT_18:
		pop	bx		; get ch back, and stack now is balanced
		xchg	ax,bx
		mov	bx,word ptr p
		mov	word ptr [bx],ax
		xchg	ax,bx

	MT_19: ; to here BX should contains the value of var ch

		push	bx
		mov	bx,word ptr len
		shl	bx,1		; adjust to word index
		mov	ax,word ptr nextcode
		mov	word ptr start[bx],ax
		pop	bx

	MT_20:
	      	inc	bx
		jmp	MT_13
	MT_Exit:
		popa

		ret

	MakeTable	endp

	ReadCLen	proc	near
	;
	; Input : None
	; Output : None
	;

		pusha

		mov	ax,CBIT
		call	GetBits

		cmp	ax,0
		jne	short RCL_3

		mov	ax,CBIT
		call	GetBits		; AX contains the value of var c

		mov	cx,NC
	RCL_1:
		mov	bx,NC
		sub	bx,cx
		mov	byte ptr c_len[bx],0
		loop	short RCL_1

		mov	cx,4096
	RCL_2:
		mov	bx,4096
		sub	bx,cx
		mov	di,bx
		shl	di,1		; prepare word index
		mov	word ptr c_table[di],ax
		loop	short RCL_2
		jmp	RCL_Exit

	RCL_3:
		mov	dx,ax		; AX carry result of n, save n
		mov	si,0		; i
	RCL_4:
		cmp	dx,si		; dx -> n, si -> i
		jbe	RCL_10

		mov	cx,word ptr BITBUFSIZ
		sub	cx,8
		mov	bx,word ptr bitbuf
		shr	bx,cl
		shl	bx,1		; prepare word index
		mov	di,word ptr pt_table[bx]	; c
		cmp	di,NT
		jb	short RCL_7
		mov	cx,word ptr BITBUFSIZ
		sub	cx,9
		mov	bx,1
		shl	bx,cl	; BX is used to store MASK temporarily
	RCL_5:
		mov	ax,word ptr bitbuf
		and	ax,bx
		jz	short RCL_6
		shl	di,1	; prepare word index
		mov	di,word ptr right[di]
		jmp	short RCL_6_1
	RCL_6:
		shl	di,1	; prepare word index
		mov	di,word ptr left[di]
	RCL_6_1:
		shr	bx,1
		cmp	di,NT
		jae	short RCL_5
	RCL_7:
		movzx	ax,byte ptr pt_len[di]
		call	FillBuf

		cmp	di,2
		ja	short RCL_9
		cmp	di,0
		jne	short RCL_7_1
		mov	di,1
		jmp	short RCL_8
	RCL_7_1:
		cmp	di,1
		jne	short RCL_7_2

		mov	ax,4	; prepare input for GetBits
		call	GetBits	; get a result from AX
		add	ax,3
		mov	di,ax
		jmp	short RCL_8
	RCL_7_2:
		mov	ax,CBIT
		call	GetBits
		add	ax,20
		mov	di,ax
	RCL_8:	; while (--c >= 0) c_len[i++] = 0
		dec	di
		cmp	di,0
		js	short RCL_4
		mov	byte ptr c_len[si],0
		inc	si
		jmp	short RCL_8
	RCL_9:
		mov	ax,di
		sub	ax,2
		mov	byte ptr c_len[si],al
		inc	si
		jmp	RCL_4

	RCL_10:	; when i >= n
		cmp	si,NC
		jae	short RCL_11
		mov	byte ptr c_len[si],0
		inc	si
		jmp	short RCL_10
	RCL_11:
		mov	bx,NC			; bx -- parameter 1
		mov	si,offset c_len		; prepare parameter 2
		mov	dx,12			; dx -- parameter 3
		mov	di,offset c_table	; prepare parameter 4
		call	MakeTable

	RCL_Exit:

		popa

		ret

	ReadCLen	endp

	ReadPtLen	proc	near
	;
	; Input : SI->nn(int), AX->nbit(int), DI->i_special(int)
	; Output : None
	;

		pusha

		push	ax		; save nbits for later use

		call	GetBits
		mov	dx,ax		; save n

		cmp	dx,0
		pop	ax
		jne	short RPL_3_1
		call	GetBits		; get a result put it in AX for var c

		xor	bx,bx
	RPL_1:
		cmp	bx,si
		jae	short RPL_2
		mov	byte ptr pt_len[bx],0
		inc	bx
		jmp	short RPL_1

	RPL_2:

		xor	bx,bx

	RPL_3:

		cmp	bx,512		; word index
		jae	RPL_Exit	; bye !
		mov	word ptr pt_table[bx],ax
		add	bx,2		; moving pointer 1 word forward
		jmp	short RPL_3

	RPL_3_1:

		xor	bx,bx		; i

	RPL_4:
		cmp	bx,dx		; i < n ?
		jae	RPL_10

		mov	cx,BITBUFSIZ
		sub	cx,3
		mov	ax, word ptr bitbuf
		shr	ax,cl

		push	di		; save parameter since we want to use di
		mov	di,ax  		; save for later var c referencing

		cmp	di,7
		jne	short RPL_6

		mov	cx,BITBUFSIZ
		sub	cx,4
		mov	ax,1
		shl	ax,cl		; variable mask is ready

	RPL_5:

		mov	cx,word ptr bitbuf
		and	cx,ax
		jz	short RPL_6
		shr	ax,1
		inc	di
		jmp	short RPL_5

	RPL_6:	; fillbuf((c < 7) ? 3 : c - 3)
		mov	ax,3
		cmp	di,7
		jb	short RPL_7
		mov	ax,di
		sub	ax,3
	RPL_7:
		call	FillBuf

		mov	ax,di
		mov	byte ptr pt_len[bx],al
		inc	bx

		pop	di
		cmp	bx,di
;		jne	short RPL_10
		jne	short RPL_4
		mov	ax,2
		call	GetBits

	RPL_8:
		dec	ax
		cmp	ax,0
		js	short RPL_4	; loop back
		mov	byte ptr pt_len[bx],0
		inc	bx
		jmp	short RPL_8

	RPL_10: ; while (i >= n)

		cmp	bx,si		; while (i < nn) loop
		jae	short RPL_11
		mov	byte ptr pt_len[bx],0
		inc	bx
		jmp	short RPL_10
	RPL_11:
		mov	bx,si		; prepare parameter for MakeTable call
		mov	si,offset pt_len
		mov	dx,8
		mov	di,offset pt_table
		call	MakeTable

	RPL_Exit:

		popa


		ret

	ReadPtLen	endp

	DecodeC		proc	near
	;
	; Input	: None
	; OutPut : AX
	;

		push	bx
		push	cx
		push	si
		push	di

		cmp	word ptr blocksize,0
		jne	short DC_1
		mov	ax,16
		call	GetBits
		mov	word ptr blocksize,ax

		mov	si,NT
		mov	ax,TBIT
		mov	di,3
		call	ReadPtLen	; NT, TBIT, 3

		call	ReadCLen

		mov	si,NP
		mov	ax,PBIT
		mov	di,-1
		call	ReadPtLen	; NP, PBIT, -1

	DC_1:
		dec	word ptr blocksize
		mov	cx,BITBUFSIZ
		sub	cx,12
		mov	ax, word ptr  bitbuf
		shr	ax,cl
		mov	bx,ax		; used as index
		shl	bx,1		; adjust to word index
		mov	ax, word ptr c_table[bx]
		mov	si,ax		; use SI to represent J

		cmp	ax,NC
		jb	short DC_4
		mov	ax,1
		mov	cx,BITBUFSIZ
		sub	cx,13
		shl	ax,cl
	DC_2:
		; variable  MASK is stored in AX
		mov	bx, word ptr bitbuf
		and	bx,ax
		mov	bx,si		; get variable j, prepare word index
		jnz	short DC_3
		shl	bx,1		; adjust to word index
		mov	si,word ptr left[bx]
		jmp	short DC_3_1
	DC_3:
		shl	bx,1		; adjust to word index
		mov	si,word ptr right[bx]
	DC_3_1:
		shr	ax,1
		cmp	si,NC
		jae	short DC_2

	DC_4:
		movzx	ax,byte ptr c_len[si]
		call	FillBuf
		mov	ax,si	; value  to be returned

	DC_Exit :

		pop	di
		pop	si
		pop	cx
		pop	bx
		ret

	DecodeC		endp

	DecodeP		proc	near
	;
	; Input : None
	; Output : BX
	;

		push	ax
		push	cx
		push	si

		mov	cx,BITBUFSIZ
		sub	cx,8
		mov	ax, word ptr  bitbuf
		shr	ax,cl
		mov	bx,ax		; used as index
		shl	bx,1		; adjust to word index
		mov	ax, word ptr pt_table[bx]
		mov	si,ax		; use SI to represent J

		cmp	ax,NP
		jb	short DP_4

		mov	cx,BITBUFSIZ
		sub	cx,9
		mov	ax,1
		shl	ax,cl
	DP_1:
		; variable  MASK is stored in AX
		mov	bx, word ptr bitbuf
		and	bx,ax
		mov	bx,si		; get variable j, prepare word index
		jnz	short DP_2
		shl	bx,1		; adjust to word index
		mov	si,word ptr left[bx]
		jmp	short DP_3
	DP_2:
		shl	bx,1		; adjust to word index
		mov	si,word ptr right[bx]
	DP_3:
		shr	ax,1
		cmp	si,NP
		jae	short DP_1
	DP_4:
		movzx	ax,byte ptr pt_len[si]
		call	FillBuf

		cmp	si,0
		je	short DP_5
		mov	cx,si
		dec	cx
		mov	ax,1
		shl	ax,cl
		mov	cx,ax		; store temp result
		mov	ax,si
		dec	ax
		call	GetBits
		add	ax,cx
		mov	si,ax
	DP_5:
		mov	bx,si


	DP_Exit:

		pop	si
		pop	cx
		pop	ax

		ret

	DecodeP		endp


	Decode		proc	near
	;
	; Input : CX and Buffer
	;

		pusha

;		xor	bx,bx		; i
		mov	bx,word ptr s_i
		xor	si,si		; r
	D_2:
		dec	word ptr j	; remaining bytes to copy to
		cmp	word ptr j,0
		js	short D_3
		mov	al,byte ptr buffer[bx]
		mov	byte ptr buffer[si],al
		inc	bx
		mov	ax,DICSIZ
		dec	ax
		and	bx,ax
		inc	si
		cmp	si,cx		;
		jne	short D_2
		mov	word ptr s_i,bx	; save
		popa
		ret
	D_3:
		call	DecodeC		; return result in AX

		cmp	ax,UCHAR_MAX
		ja	short D_4
		mov	byte ptr buffer[si],al
		inc	si
		cmp	si,cx
		jne	short D_3
		mov	word ptr s_i,bx		; save
		popa
		ret

	D_4:	; j = c - (UCHAR_MAX + 1 - THRESHOLD)

		sub	ax,UCHAR_MAX
		dec	ax
		add	ax,THRESHOLD
		mov	word ptr j, ax

		mov	ax,si
		call	DecodeP		; return result in BX
		sub	ax,bx
		dec	ax
		mov	bx,ax
		mov	ax,DICSIZ
		dec	ax
		and	bx,ax		; i = BX

	D_4_1:
		dec	word ptr j
		cmp	word ptr j, 0
		js	short D_3
		mov	al,byte ptr buffer[bx]
		mov	byte ptr buffer[si],al
		mov	ax,DICSIZ
		dec	ax
		inc	bx
		and	bx,ax		; i = BX
		inc	si
		cmp	si,cx
		je	short D_6	; bye now!
		jmp	short D_4_1	; go back to while loop


;	D_5:
;		jmp	short D_3


	D_6:
		mov	word ptr s_i,bx	; save
		popa

		ret

	Decode		endp

		public	Extract
	Extract		proc	near

		pusha

	; Get file name string starting point


	; save file name length

		mov	bx,NAMELENIDX
		mov	bl,byte ptr Header[bx]
		mov	byte ptr namelen,bl

	; print message on screen


	; compress/decompress method recognition

		mov	word ptr crc,INIT_CRC
		movzx	dx,byte ptr Header[3]	; get mrthod
		mov	byte ptr Header[3],20h	; fill with blank


	; decompress starts here

		call	DecodeStart

	Ex_1:
		cmp	dword ptr origsize,0
		je	short Ex_3
		mov	ecx,DICSIZ	; assume origsize is smalller than DIGSIZ
		cmp	dword ptr origsize, DICSIZ
		ja	short @F
		mov	ecx,dword ptr origsize
	@@:
		push	ecx

		call	Decode	; with parameter cx and buffer

		call	FwriteCRC	; with buffer, cx andOutFileHandle

		; display '.' to tell user the program is running


		pop	ecx
		mov	eax,dword ptr origsize
		sub	eax,ecx
		mov	dword ptr origsize,eax
		jmp	short Ex_1

	Ex_3:

		popa

		ret

	Extract		endp

;R108A start
;[]==============================================================[]
;
; Expand:
;
;Saves:	NONE
;
;Entry:	ES : SEGMENT of Source Data
;	BX : OFFSET of Source Data
;	DX : Segment of Expand Data buffer
;
;Exit:	NONE
;
;Author: Award
;Date:   11/16/94
;
;[]==============================================================[]
		ASSUME	CS:DGROUP,DS:EXP_DATA
		public	Expand		;R186
Expand		proc	near
;R171		push	ax
		push	eax		;R171
		push	bx

		push	es		; save source segment

;R171;R137 start
;R171;----- Get decompress code address and store to Temp Expand pool
;R171	mov	di,Temp_EXP_Seg
;R171	mov	ds,di
;R171	mov	di,Temp_EXP_Off
;R171	mov	word ptr ds:[di],offset Expand
;R171	cmp	byte ptr es:[bx+12h],40h		;Is decomress segment?
;R171	jne	short Not_POST_USE			;No,goto decompress
;R171	cmp	byte ptr es:[bx+11h],0			;already record?
;R171	jne	short Record_to_buffer			;No,goto record
;R171;R137A	cmp	word ptr ds:[di+4],0			;already record?
;R171	cmp	dword ptr ds:[di+4],0			;R137A already record?
;R171	jne	short Not_POST_USE			;Yes,goto decompress
;R171Record_to_buffer:
;R171	movzx	dx,byte ptr es:[bx+011h]
;R171	sub	es:[bx+1],dl		;recalculate checksum
;R171	mov	byte ptr es:[bx+11h],0	;mask decompress segment to 4000h
;R171	inc	dx
;R171	shl	dx,2
;R171	add	di,dx
;R171	mov	ds:[di],bx
;R171	mov	cx,es
;R171	mov	ds:[di+2],cx
;R171		movzx	ecx,byte ptr es:[bx]
;R171		add	ecx,es:[bx+7]
;R171		add	ecx,COMPRESSED_UNKNOW_BYTE	;unknow bytes
;R171	jmp	@F
;R171Not_POST_USE:
;R171;---------------------------------------------------
;R171;R137 end
; Init data segment registers

		mov     ds,dx

; Initialize EXP_DATA segment, in case there's garbage left

		push	ds
		pop	es
		xor	di,di
		mov	cx,4000h
		xor	ax,ax
		repz	stosw

; Read compressed data from segment:offset

		pop	es
		push	es

		mov	word ptr SrcSegment, es
		mov	word ptr SrcOffset,bx
;R171 start
		xor	ecx,ecx
		mov	dword ptr Expand_GDT,ecx		;clear null descriptor
		mov	dword ptr Expand_GDT+4,ecx	;clear null descriptor from offset 4

		lea	cx,Expand_GDT
		ror	ecx,4
		mov	ax,ds
		add	cx,ax
		rol	ecx,4
;R177		mov	word ptr Expand_GDTR,8*2
		mov	word ptr Expand_GDTR,8*3	;R177
		mov	dword ptr Expand_GDTR_Addr,ecx

		mov	dword ptr Expand_GDT1_1,0ffffh
		mov	ax,es
		movzx	ecx,ah				;hi base
		ror	ecx,8
		mov	cl,al				;ms base
		or	ecx,8f9300h			;access and HiLimit
		mov	dword ptr Expand_GDT1_2,ecx
;R177 - start
		mov	dword ptr DATA0, 0000FFFFh
		mov	dword ptr DATA0+4, 008F9300h
;R177 - end

;----- Get decompress code address and store to Temp Expand pool
		push	gs
		mov	di,Temp_EXP_Seg
		mov	gs,di
		mov	di,Temp_EXP_Off
		mov	word ptr gs:[di],offset Expand
		add	bx,12h
		call	Get_Exp_Src_Byte		;get es:[bx+12h] to AL
		sub	bx,12h
		cmp	al,40h
		jne	short Not_POST_USE		;No,goto decompress
		add	bx,11h
		call	Get_Exp_Src_Byte		;get es:[bx+11h] to AL
		sub	bx,11h
		or	al,al				;= 0?
		jne	short Record_to_buffer		;No,goto record
		cmp	dword ptr gs:[di+4],0		;already record?
		jne	short Not_POST_USE		;Yes,goto decompress
Record_to_buffer:
		movzx	dx,al
		inc	bx
		call	Get_Exp_Src_Byte		;get es:[bx+1] to AL
		sub	al,dl
		call	Set_Exp_Src_Byte		;set es:[bx+1] to AL
		dec	bx
		xor	al,al
		add	bx,11h
		call	Set_Exp_Src_Byte		;get es:[bx+11h] to AL
		sub	bx,11h
		inc	dx
		shl	dx,2
		add	di,dx
		mov	gs:[di],bx
		mov	cx,es
		mov	gs:[di+2],cx
		call	Get_Exp_Src_Byte		;get es:[bx] to AL
		movzx	ecx,al
		add	bx,7
		call	Get_Exp_Src_Dword		;get es:[bx+7] to EAX
		sub	bx,7
		add	ecx,eax
		add	ecx,COMPRESSED_UNKNOW_BYTE	;unknow bytes
		pop	gs				;balance stack
		jmp	@F
Not_POST_USE:
		pop	gs
;---------------------------------------------------
;R171 end
;R172 start
ifdef KBC_ROM_in_BIOS
;--------------- Check Is KBC ROM? -----------------
		add	bx,4			;signature offset of system
						;configuration block
		call	Get_Exp_Src_Dword	;get es:[bx+4] to EAX
		sub	bx,4			;reset BX
		cmp	eax,711c8ee3h
		jne	short Not_KBC_ROM
		add	bx,12			;offset pointer to start of
						;keyboard controller header
		call	Get_Exp_Src_Dword	;get es:[bx+4] to EAX
		sub	bx,12			;reset BX
		push	bx
		movzx	ecx,ax
		add	bx,ax
		add	bx,2			;offset of code size value
		call	Get_Exp_Src_Byte	;get KBC ROM size to AL
		pop	bx
		movzx	eax,al			;code size set to EAX
		xchg	al,ah			;mul 256
		mov	al,8			;keyboard controller code header size
		add	ecx,eax
		jmp	@F
Not_KBC_ROM:
endif ;KBC_ROM_in_BIOS
;R172 end

; Temp Target Segment, Offset

; make CRC table

		call	MakeCRCTable

; read header

		call	ReadHeader
;R171C		jc      short @F        ; error, something wrong
		jc      @F        	;R171C; error, something wrong

		mov	ax,ExpSegment
		mov	TgtSegment,ax
		mov	ax,ExpOffset
		mov	TgtOffset,ax
;-- calculate compressed total size and return when decompress complete
		mov	ecx,compsize		;compressed size
		xor	eax,eax
		mov	al,headersize		;compressed header size
		add	ecx,eax
		add	ecx,COMPRESSED_UNKNOW_BYTE	;unknow bytes
		mov	edx,origsize		;R148
		push	edx			;R148
		push	ecx

;R137 start
;check data is store type or compress type
;R171C		cmp	byte ptr es:[bx+5],'0'		;Is store type?
;R171C start
		push	bx
		add	bx,5				;offset 5 ('-lh0-' or '-lh5-')
		call	Get_Exp_Src_Byte		;get compress or store type value
		pop	bx
		cmp	al,'0'				;Is store type?
;R171C end
		jne	short Not_Store			;No,jump
		push	ds
		push	si
		push	bx
;R171C		pop	si
		mov	di,ExpOffset
		movzx	ax,byte ptr headersize		;compressed header size
		add	ax,2				;store unknow bytes
;R171C		add	si,ax
		add	bx,ax				;R171C
		mov	cx,word ptr compsize		;compressed size
		mov	ax,ExpSegment
;R171C		push	es
;R171C		pop	ds
		mov	es,ax
;R171C		rep	movsb				;move data to target
;R171C start
		add	cx,3				;transfer to dword unit
		shr	cx,2				;-------
Get_Store_Data_Loop:
		call	Get_Exp_Src_Dword		;get compress or store type value
		add	bx,4				;next data offset
		stosd					;store to buffer
		loop	Get_Store_Data_Loop
		pop	bx				;restore BX
;R171C end
		pop	si
		pop	ds
		jmp	short Expand_Over
Not_Store:
;R137 end

		push	word ptr TgtSegment
		push	word ptr TgtOffset
		push	dword ptr origsize

; extract content from compressed file
		call	Extract

		pop	dword ptr origsize
		pop	word ptr TgtOffset
		pop	word ptr TgtSegment

Expand_Over:						;R137
; clean up temp target buffer, so that no garbage left in user's base memory
; if data decompression stub is called before memory testing, then
; we don't need to call this cleanup routine.
		call	CleanUpBaseMemory

		pop	ecx		;return compressed total size
		pop	edx		;R148

; done, exit.

		clc
@@:
		pop	es
		pop	bx
;R171		pop	ax
		pop	eax		;R171
		ret

expand	endp
;R108A end
;R108D start
MakeCRCTable	proc	near
;
; Input : None
; Destroy : None
; Modify Global Variable : CRCTABLE[]
;

		push    cx
		push    bx
		push    ax
		push    si

		mov     si,offset crctable
		mov     cx,100h         ; for (i = 0; i <= 0xff; i++)
MCRCT_1:
		mov     ax,100h
		sub     ax,cx           ; r = i;
		push    ax              ; save index

MCRCT_2:
		mov     bx,0            ; for (j = 0; j < 8; j++)
MCRCT_2_1:
		test    ax,1            ; (r & 1)
		jz      short MCRCT_3

		shr     ax,1
		xor     ax,CRCPOLY
		jmp     short MCRCT_4
MCRCT_3:
		shr     ax,1
MCRCT_4:
		inc     bx
		cmp     bx,8
		jb      short MCRCT_2_1

		pop     bx	; pop out saved index to !!! REG BX !!! so that
				; we won't destroy AX

		mov     word ptr [si+bx],ax
		inc	si	; since this is an array of word, we increase bx
				; and si respectively so that totaly make up a 2
				; bytes increment.

		loop    short MCRCT_1

		pop     si
		pop     ax
		pop     bx
		pop     cx

		ret

MakeCRCTable	endp

FreadCRC	proc	near
;
; Globally parameters passing : Header, Headersize, InpFileHandle
; Modify global variable: origsize
;

		push	ax
		push	bx
		push	cx
		push	dx

		movzx   cx,byte ptr Headersize

		push	es
		push	si
;R171		mov	ax,word ptr SrcSegment
;R171		mov	es,ax
		mov	bx,word ptr SrcOffset
		mov	si,offset Header
FCRC_0:
;R171		movzx	ax,byte ptr es:[bx]
		call	Get_Exp_Src_Byte				;R171
		mov	byte ptr ds:[si],al
		inc	bx
		inc	si
		loop	short FCRC_0

		mov	ax,bx
		sub	ax,word ptr ds:SrcOffset	; how many bytes we have read ?
		mov	word ptr ds:SrcOffset,bx
		pop	si
		pop	es

		mov     byte ptr Headersize,al
		mov     cx,ax           		; save a copy
		add     word ptr origsize,ax
		inc     cx
		mov     bx,offset Header
FCRC_1:
		movzx	ax,byte ptr [bx]
		dec     cx
		jcxz    short FCRC_2

		UpdateCRC

		inc     bx				; increment pointer
		jmp     short FCRC_1
FCRC_2:

		pop	dx
		pop	cx
		pop	bx
		pop	ax

		ret

FreadCRC	endp

CalcHeadersum	proc	near
;
; Input : None
; Output : AX
; Destroy : AX
; Global variable : None
;
		push	bx
		push	cx
		push	dx

		mov	ax,0	; clear sum
		movzx	cx,byte ptr headersize
CH_1:
		movzx	bx,byte ptr headersize
		sub	bx,cx
		movzx	dx,byte ptr header[bx]
		add	ax,dx
		loop	short CH_1

		pop	dx
		pop	cx
		pop	bx

		and	ax,0ffh

		ret

CalcHeadersum	endp

GetFromHeader	proc	near
;
; Input	  : BX -- from
;	    CX -- count
; Output  : EAX
; Destroy : EAX
;

		push	bx
		push	edx
		push	si

		xor	eax,eax	; prepare unsigned long variable output

		dec	bx
		inc	cx

GFH_1:

		dec	cx
		jcxz	short GFH_2

		shl	eax,8
		mov	si,bx
		add	si,cx
		movzx	edx,byte ptr header[si]
		add	eax,edx		; little endian
		jmp	short GFH_1

GFH_2:

		pop	si
		pop	edx
		pop	bx

		ret

GetFromHeader	endp


ReadHeader	proc	near
;
; Input : None
; Output : Carry Set - several reason might cause the carry flag be set
;			1. header size is 0
;			2. header check sum is not correct
;			3. data pattern does not match in some specific
;			   location.
;        : Carry clear - header size is not 0
;


		pusha

; read in headersize byte


		push	es
;R171		mov	ax,word ptr SrcSegment
;R171		mov	es,ax
		mov	bx,ds:SrcOffset
;R171		movzx	ax,byte ptr es:[bx]
		call	Get_Exp_Src_Byte				;R171
		inc	word ptr ds:SrcOffset
		mov	byte ptr headersize,al
		pop	es

		cmp     byte ptr headersize,0
		jne     short   RH_2

RH_1:
		stc
		jmp     RH_Exit

RH_2:

		; read in headersum byte

		push	es
;R171		mov	ax,word ptr SrcSegment
;R171		mov	es,ax
		mov	bx,ds:SrcOffset
;R171		movzx	ax,byte ptr es:[bx]
		call	Get_Exp_Src_Byte				;R171
		inc	word ptr ds:SrcOffset
		mov	byte ptr headersum,al
		pop	es


		call    FreadCRC       ; CRC not used

		call    CalcHeadersum

; compare headersum and result of CalcHeadersum

		cmp	al,byte ptr headersum
		je	short @F
		jmp	short RH_1

@@:
		mov	bx,5
		mov	cx,4
		call	GetFromHeader
		mov	dword ptr compsize,eax

		mov	bx,9
		mov	cx,4
		call	GetFromHeader
		mov	dword ptr origsize,eax

		mov	bx,13
		mov	cx,2
		call	GetFromHeader
		mov	word ptr ExpOffset,ax

		mov	bx,15
		mov	cx,2
		call	GetFromHeader
		mov	word ptr ExpSegment,ax

		cmp	byte ptr Header[17],20h	; check specific spot of header
		jne	short RH_1

		cmp	byte ptr Header[18],01h ; check specific spot of header
		jne	short RH_1

		movzx	bx,byte ptr headersize
		sub	bx,5
		mov	cx,2
		call	GetFromHeader
		mov	word ptr file_crc,ax	; truncate upper word

		mov	bx,NAMELENIDX
		mov	bl,byte ptr Header[bx]
		mov	ax,OUTFILENAME
		add	bx,ax
		mov	byte ptr Header[bx],'$'	; assembly version
		mov	byte ptr Header[bx+1],0	; assembly version

		clc

RH_Exit:

		popa

		ret

ReadHeader	endp
;R108D end
;R171 start
;[]------------------------------------------------------------------[]
;Get_Exp_Src_Byte : Get decompressed source data from SrcSegment:BX
;
;Input : SrcSegment = source data of segment
;	 BX = source data of offset
;	 DS = expand data of segment
;Output: AX = get source data to AL and clear AH
;[]------------------------------------------------------------------[]
Enter_Expand_Prot:
		push	ecx
;R171A start
		mov	cx,cs				;get code segment
		cmp	cx,2000h			;In POST?
;R171B		je	short In_POST			;Yes,jump
;--------------- for AWDFLASH.EXE ----------------
;R171B		mov	ax,word ptr SrcSegment		;load real mode segment
;R171B		mov	es,ax				;to ES
;R171B start
		mov	cx,word ptr SrcSegment		;load real mode segment
		jne	short Not_In_POST		;Yes,jump
		test	ch,0f0h				;is old BIOS call?
		jz	short In_POST			;No,jump
Not_In_POST:
		mov	es,cx				;to ES
;R171B end
		jmp	short EEP_Ret
In_POST:
;R171A end
;---------------- Enter Protect Mode ----------------
                lgdt    fword ptr ds:Expand_GDTR	;load descriptor table

                mov     ecx,cr0
                or      cl,1			;enable protected mode
                mov     cr0,ecx

;R177		jmp	short $+2		;clear prefetch

;R177 - start
ifndef	MP_SUPPORT
		mov	cx, DATA0_INDEX		;segment 0 at POST
		mov	ss, cx
endif	;MP_SUPPORT
;R177 - end
		mov	cx,Expand_INDEX
		mov	es,cx

;---------------- Leave Protect Mode ----------------
                mov     ecx,cr0
                and     cl, NOT 1
                mov     cr0,ecx

;R177		jmp	short $+2		;flush queue
;R177 - start
ifndef	MP_SUPPORT
		xor	cx, cx			;stack segment 0 at POST
		mov	ss, cx
endif	;MP_SUPPORT
;R177 - end
EEP_Ret:					;R171A
		pop	ecx
		ret

Get_Exp_Src_Byte:
		push	es

		call	Enter_Expand_Prot
		movzx	ax,byte ptr es:[bx]

		pop	es
		ret

Set_Exp_Src_Byte:
		push	es

		call	Enter_Expand_Prot
		mov	es:[bx],al

		pop	es
		ret

Get_Exp_Src_Dword:
		push	es

		call	Enter_Expand_Prot
		mov	eax,dword ptr es:[bx]

		pop	es
		ret
;R171 end

;[]------------------------------------------------------------------[]
; 	End of Decompress Engine
;[]------------------------------------------------------------------[]

; There is not enough space in memory sizing area (maximum is 4Kb only)
; ,so move some codes to here. The decompress engine only take about
; 2.5Kb
;R156 - start
ifdef	Jumpless_Support
ifdef	Jumpless_in_Decompress_Area
	JUMPLESS_FOR_BOOTROM_ASM	equ	1
		public	Set_Clock	;R186
		include	JUMPLESS.INC
endif	;Jumpless_in_Decompress_Area
endif	;Jumpless_Support
;R156 - end

;R159 - start
ifdef	Ct_Preset_In_Decompress_Area
	   	public	Ct_Decompress_Hook		;R186
	   	extrn	Ct_Decompress_Hook_End:near	;R186
		include	CHIPBOOT.INC
endif;	Ct_Preset_In_Decompress_Area
;R159 - end

		public	Bootrom_C000_End
Bootrom_C000_End:
;R108 start
		align	16		;R140
		db	'*BBSS*'	;Boot Block structure signature
;R186BootExt_Off	EQU	0
;R186DecmpCode_Off	EQU	2
;R186Extract_Off	EQU	10
;R186CleanUpBaseMemory_Off	EQU	12
;R186Expand_Off	EQU	14				;R108A
	dw	External_BootRom_Seg	;location of memory sizing
	dw	Decompress_Code_Seg	;location of decompress engine
	dw	WholeBootRomStart_Seg
	dw	ROMDrive_Limit_Seg	;boundary address of merged ROMs
					;it is used for cbrom.exe to calculate
					;maximum available space for ROMs
	dw	ESCD_Data_Seg		;entry point of PnP data block
	dw	offset DGROUP:Extract
	dw	offset DGROUP:CleanUpBaseMemory
	dw	offset DGROUP:Expand   	;R108A, entry point of decompress
;R108 end
ifdef	Flash_2M_support					;R116
ifndef	Chipboot_In_External_Boot_Block				;R186
  	extrn	Enable_Extra_1MBIOS_Hook:near			;R186
  	extrn	Disable_Extra_1MBIOS_Hook:near			;R186
;R186 start
else	;Chipboot_In_External_Boot_Block
  	public	Enable_Extra_1MBIOS_Hook
  	public	Disable_Extra_1MBIOS_Hook
;R186 end
endif	;Chipboot_In_External_Boot_Block			;R186
	;Entry point for enabling hardware decode for lower 128K ROM space
  	dw	offset DGROUP:Enable_Extra_1MBIOS_Hook	;R116

	;Entry point for disabling hardware decode for lower 128K ROM space
  	dw	offset DGROUP:Disable_Extra_1MBIOS_Hook	;R116
else	;Flash_2M_support						;R149
  	dw	?						;R149
  	dw	?						;R149
endif	;Flash_2M_support					;R116
  	db	1	;Flag for CBROM.EXE to check		;R149
  			; whether it is a old or new BIOS	;R149
  			; 0FFh = old BIOS			;R149

ifdef	Bootblock_16K_Support					;R153
ifdef	Automatic_Load_Awdflash					;R153
		dw	offset DGROUP:Read_Fdd_File_To_Memory	;R153
endif	;Automatic_Load_Awdflash				;R153
endif	;Bootblock_16K_Support					;R153

;R164bifndef Flash_16K_8K_8K_Unit	  ;R164a
;R185 ifdef	    Support_CMOS_Backup_Data    ;R164
;R185 FLASH_CMOS_Size	equ	(80h-10h)               ;
;R185 		align	16
;R185 		db	FLASH_CMOS_Sign	        ;R164a;signature
;R185 		db	FLASH_CMOS_Size	        ;R163;Flash CMOS size byte
;R185          	db      1 dup (?)               ;R163;ROM_CMOS_CHECKSUM
;R185 ;R164a		db	FLASH_CMOS_Sign	        ;R163;signature
;R185 		db	FLASH_CMOS_Size dup (?)	;R163;CMOS backup area
;R185 endif	    ;Support_CMOS_Backup_Data   ;R164
;R164bendif       ; Flash_16K_8K_8K_Unit	  ;R164a
;R163		db	'*MM*'		;CMOS backup structure signature
;R163		db	70h dup (?)	;CMOS backup area
;R164endif ;Backup_CMOS_to_FLASH
;R162 end

;R122 start
;---- 2MB bios external 8k boot block area ----
ifdef	Flash_2M_support

;R155A - start
ifdef	BCPOEM_Table
BcpOemTbl:
		align	16
	db	"BCPOEM"		;header
	db	01h			;major version
	db	00h			;minor version
	dw	001ah			;size of struct
	db	"TULIP"			;OEMID
	dw	0059h			;SYSTEM ID
	dw	0000h			;reserved
	db	00h			;reserved
	dw	0000h			;reserved
	dw	0000h			;reserved
	dw	0000h			;reserved
;		align	16
	db	"TLPINF"				;identifier
	db	01h					;major version
	db	03h					;minor version
	dw	0112h					;size of struct
	db	6 dup (0ffh)				;network address
	db	10 dup (0ffh)				;serial nr of the system
	db	10 dup (0ffh)				;serial nr of the board
	dw	0ffffh					;board info
BCPOEM_Start:
	db	0ah,0dh,"Copyright (C) 1998 Tulip (R) Computers.",0ah,0dh ;copyright
	db	"All Rights Reserved.",0ah,0dh,0ah,0dh	;"	"
BCPOEM_L	equ	($ - BCPOEM_Start)
;R155B	db	(149 - BCPOEM_L) dup(?)			;"	"
	db	(149 - BCPOEM_L) dup (0)		;"	"	;R155B
;	db	53h	dup(0)				;
BCPOEM_CheckSum:
	db	03h					;checksum sign-on
	db	20h dup (0ffh)				;system vendor
	db	20h dup (0ffh)				;system name
	db	10h dup (0ffh)				;slot info
	dw	0000h					;password
	dw	0aa54h					;factory value
	db	0ffh					;PCA checksum
	db	0ffh					;EOL checksum
BCPOEM_SIZE	EQU	($ - offset BcpOemTbl)
endif;	BCPOEM_Table
;R155A - end
		dw	?			;R180 for checksum

ifdef	Bootblock_16K_Support			;R129
;R186 Chipboot_In_External_Boot_Block   equ	1	;R151A
	;Lower 8K boot block for 2M flash (16K/8K/8K)
		org	0C000h
COMPILE_FOR_BOOTROM_ASM	=	1		;R129
		extrn	BootBlock_Expand:near	;R186
		extrn	B_GDTR1:near		;R186
		extrn	B_DATA1_INDEX:ABS	;R186
		include	BOOTROM.INC		;R129
		ret				;R129
COMPILE_FOR_BOOTROM_ASM	=	2		;R129
		include	BOOTROM.INC		;R129
		ret				;R129

	;INT 1AH service routines for scanning PCI/VGA while booting from
	;boot block.
		extrn	A_GDTR:near		;R186
		include	btpci1a.inc		;R150

ifdef	Chipboot_In_External_Boot_Block   	;R151
		include	chipboot.asm            ;R151
endif	;Chipboot_In_External_Boot_Block        ;R151

ifdef	Automatic_Load_Awdflash			;R153
;R186 start
;R187		public	LOAD_AWDFLASH
		public	LOAD_AWDFLASH_Str	;R187
		public	LOAD_AWDFLASH_LEN
		public	STACKSIZE
		public	BT_INITIAL_PARA1
		public	READ_FDD_FILE_TO_MEMORY
		public	STACKSIZE
		public	AWD_STACKSIZE
		public	BT_INITIAL_PARA2
;R186 end
		include	ReadCOM.INC		;R153
endif	;Automatic_Load_Awdflash		;R153

;R155A - starts
;
; The Original Tulip "BCPOEM" Structure is removed from here
;
;R155A - ends

else;	Bootblock_16K_Support			;R129
	;Top 8K boot block for 2M flash (16K/8K/8K) or 1M flash
;R186		org	0E000h			;R129
endif;	Bootblock_16K_Support			;R129

;R129 ;R123 start
;R129 ifdef	Flash_2M_support
;R129 Extern_execute1:
;R129 ifdef	A17_From_KB_Pin						;R124
;R129 		call	Enable_KB_Controller
;R129 endif;	A17_From_KB_Pin						;R124
;R129
;R129 Temp_Extra_BIOS_Addres	EQU	8000h
;R129 		push	2000h
;R129 		call	Enable_Extra_1MBIOS_Hook
;R129 		mov	esi,0
;R129 		jnz	short @F	;real mode address
;R129 		mov	esi,0fff00000h	;protect mode high address
;R129 @@:
;R129 		movzx	ecx,cx
;R129 		shl	ecx,4
;R129 		or	esi,ecx
;R129 		cld
;R129 ;---------------- Enter Protect Mode ----------------
;R129                 mov     ax,cs
;R129                 mov     ds,ax
;R129                 assume  ds:dgroup
;R129
;R129                 lgdt    fword ptr DGROUP:B_GDTR1
;R129
;R129                 mov     eax,cr0
;R129                 or      al,1
;R129                 mov     cr0,eax
;R129
;R129 		jmp	short $+2		;clear prefetch
;R129
;R129                 mov     ax,B_DATA1_INDEX
;R129                 mov     ds,ax                   ; ds = 00000000h
;R129 		mov	es,ax
;R129
;R129 		mov	edi,(Temp_Extra_BIOS_Addres shl 4)
;R129 		mov	ecx,8000h
;R129 		db	67h
;R129 		rep	movsd
;R129
;R129 ;---------------- Leave Protect Mode ----------------
;R129                 mov     eax,cr0
;R129                 and     al, NOT 1
;R129                 mov     cr0,eax
;R129 		jmp	short $+2
;R129 		push	2000h
;R129 		call	Disable_Extra_1MBIOS_Hook
;R129 		ret
;R129
;R129 Extern_execute2:
;R129 ;----- decompress first extra BIOS area (0C000h) -----
;R129 		mov	bx,Temp_Extra_BIOS_Addres
;R129 		mov	es,bx
;R129 		xor	bx,bx
;R129 		xor	cx,cx
;R129 Expand_ROM_loop:
;R129 		add	bx,cx
;R129 		call	BootBlock_Expand
;R129 		jnc	short Expand_ROM_loop
;R129
;R129 ;----- decompress secondary extra BIOS area (0D000h) -----
;R129 		mov	bx,es
;R129 		add	bx,1000h
;R129 		mov	es,bx
;R129 		xor	bx,bx
;R129 		xor	cx,cx
;R129 Expand_ROM_loop1:
;R129 		add	bx,cx
;R129 		call	BootBlock_Expand
;R129 		jnc	short Expand_ROM_loop1
;R129 		ret
;R129 endif	;Flash_2M_support
;R129 ;R123 end



endif	;Flash_2M_support
;R122 end
;R186		org	0E000h
;R186 start
ifdef	Bootblock_16K_Support
ifdef	Support_ATAPI_In_BOOTROM
CDROM_Drive		equ	85C0h
LS120_Drive		equ	8080h
ZIP_Drive		equ	80A0h

;[]==================================================================[]
;
; Procedure Name: Scan_ATAPI_Drive
;
;
; Input:
;
; Output:
;
;	CARRY SET IF ERROR
;	CARRY CLEAR IF SUCCESS
;
;[]==================================================================[]
Detect_ATAPI_MSG	db	CR,LF,'Detecting IDE ATAPI device ...'
Detect_ATAPI_MSG_LEN	EQU	$ - offset Detect_ATAPI_MSG
Pass_MSG			db	'Pass',CR,LF,LF
Pass_MSG_LEN		EQU	$ - offset Pass_MSG
Fail_MSG		db	'Fail'
Fail_MSG_LEN		EQU	$ - offset Fail_MSG

		public	Scan_ATAPI_Drive
Scan_ATAPI_Drive	proc	near

;----- Fill IRQ 14 and IRQ 15 vector address -----
		mov	ax,SEG_0
		mov	es,ax
		mov	word ptr es:[HD_INT],offset INT_HDISK
		mov	ax,cs
		mov	word ptr es:[HD_INT+2],ax
		mov	word ptr es:[INT77],offset INT_HDISK1
		mov	word ptr es:[INT77+2],ax
;-------------------------------------------------

	;Display message for auto-detection ATAPI
		lea	ax,Detect_ATAPI_Msg
		mov	cx,Detect_ATAPI_Msg_Len
		mov	dx,0ff01h
		call	Display_Str
		
		call	BT_Turn_on_IDE_Port
		call	Decide_Boot_ATAPI_Locate
		ret
Scan_ATAPI_Drive	endp

;[]==================================================================[]
;
; Procedure Name: Decide_Boot_ATAPI_Locate
;
;
; Input:
;
; Output:
;
;	CARRY SET IF ERROR
;	CARRY clear if success and BL is drive number of location
;
;[]==================================================================[]
Found_LS120_MSG		db	'  Found LS120, '
Found_LS120_MSG_LEN	EQU	$ - offset Found_LS120_MSG
Found_ZIP_MSG		db	'  Found ZIP, '
Found_ZIP_MSG_LEN	EQU	$ - offset Found_ZIP_MSG

Decide_Boot_ATAPI_Locate:
		xor	bl,bl			;start from drive 0
Scan_ATAPI_Loop:
		call	BT_IDE_Detect
		jc	short Scan_ATAPI_Next

		cmp	ax,LS120_Drive
		je	short Is_Boot_Device
		cmp	ax,ZIP_Drive
		jne	short Scan_ATAPI_Next
Is_Boot_Device:
		push	bx
		and	bl,3			;isolate useful bits
		or	bl,4			;drive exist flag
		cmp	ax,ZIP_Drive
		lea	ax,Found_LS120_Msg
		mov	cx,Found_LS120_Msg_Len
		jne	short @F
		or	bl,40h			;indicate ZIP drive
		lea	ax,Found_ZIP_Msg
		mov	cx,Found_ZIP_Msg_Len
@@:
		push	bx
		mov	dx,0ff01h
		call	Display_Str
		pop	bx

		mov	ax,G_RAM
		mov	ds,ax
		mov	ds:[ATAPI_Byte],bl
		call	Query_boot
		lea	ax,Pass_Msg
		mov	cx,Pass_Msg_Len
		jnc	short SAD_show
		mov	byte ptr ds:[ATAPI_Byte],0	;clear ATAPI byte
		lea	ax,Fail_Msg
		mov	cx,Fail_Msg_Len
SAD_show:
		pushf
		mov	dh,0feh
		call	Display_Str
		popf
		pop	bx
		jnc	SAD_Good_Exit
Scan_ATAPI_Next:
		inc	bl			;next drive letter
		cmp	bl,4			;over max drive?
		jb	short Scan_ATAPI_Loop	;No,continue ...
		stc				;set error flag
SAD_Good_Exit:
		ret

;[]==================================================================[]
;
; Procedure Name: BT_IDE_Detect
;
;
; Saves:
; Input:
;
;	BL FOR DISK drive 0,1.....
;
; Output:
;
;	CARRY SET IF ERROR
;	CARRY CLEAR IF SUCCESS
;	AX     = ATAPI device type
;
;[]==================================================================[]
BT_IDE_Detect:
		push	ds			; save registers
		push	es
		push	cx
		push	dx
		push	ax
		push	bx

		mov	dx,1f7h			;1F7h port
ifdef	Support_4_IDE
		test	bl,2			;Is secondary channel?
		jz	short @F		;No,jump
		sub	dl,80h			;modulate port to 177h
@@:
endif	;Support_4_IDE
		mov	ah,0a0h			;assume master drive(AL=0A0h)
		test	bl,01h			;Is detect master drive?
		jz	short @F		;No,jump
		mov	ah,0b0h			;set is slave drive(AL=0B0h)
@@:
		xor	cx,cx			;count loop
Set_Drive_Scheme_Loop:
		dec	dx			;dx=1X6h
		mov	al,ah			;
		out 	dx,al			;set port value
		newiodelay
		inc	dx			;1x7h
		in	al,dx			;get status value
		newiodelay
		test	al,80h
		jz	short Ctrl_Idle
		loop	Set_Drive_Scheme_Loop
Ctrl_Idle:
		test	al,20h			;check have connected drive?
		jnz	short exit_with_error	;None drive then skip...

		mov	ax,8000h		; check for bit 7 = 0
		mov	bh,15
		xor	cx,cx
		extrn	Wait_For_Port:near
		call	Wait_For_Port
		or	ah,ah
		jnz	short exit_with_error

;----- discard garbage data if have -----
		xor	cx,cx			;64k counter
@@:
		in	al,dx			;get status
		newiodelay
		test	al,8			;any remain data
		jz	short @F		;no,skip
		sub	dl,7			;set to data port
		in	ax,dx			;read garbage data
		add	dl,7			;set to status port
		loop	@B			;next loop
@@:
;------------------------------------------
		pop	bx
		push	bx
		mov	al,0a0h			;assume master drive(AL=0A0h)
		test	bl,01h			;Is detect master drive?
		jz	short @F		;No,jump
		mov	al,0b0h			;set is slave drive(AL=0B0h)
@@:
		dec	dx			;1x6h
		out 	dx,al			;set port value
		newiodelay
; Identify drive
		inc	dx			;1x7h
		mov	al,ATAPI_Identify_Cmd	;Set CDROM identify command
		out	dx,al			;send command
		newiodelay

		mov	ax,8000h
		mov	bh,15			;15 seconds
		xor	cx,cx
		call	wait_for_port
		or	ah,ah
		jnz	short exit_with_error
		mov	ax,101h			;check status error bit
		xor	bh,bh			;wait for 0.5 second
		mov	cx,33333/2
		call	wait_for_port		;check it
		or	ah,ah
		jz	short exit_with_error
		mov	ax,808h			;wait DRQ
		mov	bh,1
		xor	cx,cx
		call	wait_for_port
		or	ah,ah
		jnz	short exit_with_error

		sub	dl,7			;1x0h
		in	ax,dx			;get word 0
		mov	bx,ax			;store word 0 to BX
		mov	cx,100h-1		;get word 1-255
@@:
		in	ax,dx
		loop	@B

		push	bx

		mov	ax,8000h
		mov	bh,5			;5 seconds time out
		xor	cx,cx
		call	wait_for_port

		pop	ax
		and	ax,0dfe0h		;isolate bits for used bits of ATAPI
		clc
		jmp	short BID_Exit
exit_with_error:
		xor	ax,ax			;for return
		stc
BID_Exit:
		pop	bx
		pop	es			;discard original AX for return
		pop	dx
		pop	cx
		pop	es
		pop	ds
		ret

;[]==================================================================[]
;
; Procedure Name: Query_boot
;
;
; Saves:
; Input:
;
;
; Output:
;
;	CARRY SET IF ERROR
;	CARRY CLEAR IF SUCCESS
;
;[]==================================================================[]
Boot_ATAPI_MSG		db	'try to Boot from it ... '
Boot_ATAPI_MSG_LEN	EQU	$ - offset Boot_ATAPI_MSG
Query_boot:
		push	ds

		lea	ax,Boot_ATAPI_Msg
		mov	cx,Boot_ATAPI_Msg_Len
		mov	dh,0feh
		call	Display_Str

		xor	ah,ah
		xor	dl,dl
		int	13h
		jc	short ATAPI_Boot_Exit

Read_Again:
		xor	bx,bx			;segment 0 for BOOT buffer
		mov	es,bx
		mov	ax,0201h
		lea	bx,Boot
		mov	cx,1			; get first sector
		xor	dx,dx		       	; drive A:
		int	13h		       	; media read OK ?
		jnc	short ATAPI_Boot_Exit
		cmp	ah,6			;media change?
		je	short Read_Again
		stc
ATAPI_Boot_Exit:
		pop	ds
		ret

;[]==================================================================[]
;
; Procedure Name: INT_HDISK
;
; IRQ 14 service routine
;
;[]==================================================================[]
INT_HDISK	PROC	FAR			; fixed disk interrupt vector must
						; be at fixed location for SPEEDSTOR
		PUSH	AX
		PUSH	DS
		ASSUME	DS:G_RAM		; N3.03
		MOV	AX,G_RAM		; set segment to BIOS data areaN3.03
		MOV	DS,AX
		OR	HDC_INT,0ffh
		PUSH	DX
		MOV	DX,1f7h
Clear_IRQ1415:					;R27
		IN	AL,DX			; CLEAR CONTROLLER (CONNER)
		POP	DX
		NEWIODELAY
		MOV	AL,END_OF_INT		; IRQ14 CLEAR
		OUT	B8259,AL
		NEWIODELAY
		OUT	A8259,AL
		MOV	AX,9100H
		POP	DS
		INT	15H
		POP	AX
		IRET

INT_HDISK	ENDP

		public	INT_HDISK1
INT_HDISK1	PROC	FAR			; fixed disk interrupt vector must
						; be at fixed location for SPEEDSTOR
		PUSH	AX
		PUSH	DS
		ASSUME	DS:G_RAM		; N3.03
		MOV	AX,G_RAM		; set segment to BIOS data areaN3.03
		MOV	DS,AX
		OR	HDC_INT,0c0h
		PUSH	DX
		MOV	DX,177h
		jmp	short Clear_IRQ1415

INT_HDISK1	ENDP

endif	;Support_ATAPI_In_BOOTROM
endif	;Bootblock_16K_Support
;R186 end

FCODE		ENDS

endif	;BootROM_Code				;R186
if	BootROM_Code	eq	1		;R186
SPURIOUS_INT_HDLR	EQU	IRET_VECT	;R186
		extrn	Expand:near		;R186

DGROUP		GROUP	@DATAC
@DATAC		SEGMENT	USE16 DWORD COMMON 'DATAC'
		ASSUME	CS:DGROUP,DS:DGROUP

		org	0
ORG_START:
		PUBLIC	CODE_START
CODE_START:
CopyRit_Msg:
		DB	'Award BootBlock BIOS v1.0',CR,LF
		DB	'Copyright (c) 1998, Award Software, Inc.',CR,LF;R127;R141;R152
CopyRit_Msg_Len	EQU	$ - offset CopyRit_Msg

;R90 start
BBSS_Label:					;R108
		db	'*BBSS*'	;Boot Block structure signature
BBSS_Label_Len	EQU	$-offset BBSS_Label	;R108
ifdef	Flash_2M_support					;R125
		dw	6699h					;R125
		dw	offset DGROUP:Enable_Extra_1MBIOS_Hook	;R125
		dw	offset DGROUP:Disable_Extra_1MBIOS_Hook	;R125
endif	;Flash_2M_support					;R125
;R108		dw	External_BootRom_Seg
;R108		dw	Decompress_Code_Seg
;R108		dw	WholeBootRomStart_Seg
;R108		dw	ROMDrive_Limit_Seg
;R108		dw	ESCD_Data_Seg
;R90 end
;R76 start
		CK_ORG	0E056h
		dw	offset DGROUP:Expand
;R76 end
;R108ifdef FULL_SCREEN_LOGO				;R102C
		CK_ORG	0E058h			;R102C
		db	55h			;R102C
;R108endif ;FULL_SCREEN_LOGO				;R102C
ifdef	Flash_2M_support			;R116
		CK_ORG	0E059h			;R116
		db	5ah			;R116 2M BIOS signature
endif	;Flash_2M_support			;R116

;R174 start
E05A_Flag	=	0
;R174A ifndef	No_Show_Graphic_POST_MSG
ifdef	No_Show_Graphic_POST_MSG	;R174A
E05A_Flag	=	E05A_Flag+00000001b	;No_Show_Graphic_POST_MSG of flag
endif;	No_Show_Graphic_POST_MSG
		CK_ORG	0E05ah
		db	E05A_Flag
;R174 end

		CK_ORG	0E05Bh
	    	PUBLIC	RST_VECT
RST_VECT	LABEL	NEAR
RST_VECT_NEAR	LABEL	NEAR

;[]==============================================================[]
;
; REDO:
;
;	This routine is called by the reset vector at F000:E05B
;	after a power-up. It determines whether this is a virtual
;	shutdown or a normal boot. If it is a normal boot, we
;	juggle a few cache's and then go on to POST.
;
;Saves:	NONE
;
;Entry:	NONE
;Exit:	NONE
;
;Author: Award
;Date:   04/18/90
;
; Name | Date	    | Description
; ---------------------------------------------------------------
; TIM | 18-Apr-90   | Update to 4.0
;
;[]==============================================================[]
  		align	4
		PUBLIC	REDO
REDO		PROC	NEAR
		mov	gs,dx			; gs = cpu type
;
;	Test if this was a virtual shutdown.
;

		cli
		cld

		mov	ax,cs				;R132
		mov	ss,ax				;R132

ifdef	Very_Very_Early_Init				;R132
		extrn	Ct_Very_Early_Init:Near		;R132
		ROM_CALL Ct_Very_Early_Init		;R132
endif	;Very_Very_Early_Init				;R132

;R78 - start
;Some super IO chips that contain RTC & KBC but they are disabled at power on
;BIOS need to program registers as early as possible

		jmp	PWRON_Rtc_Kbc_Init
PWRON_Rtc_Kbc_Exit:
;R78 - end

;R132		mov	ax,cs
;R132		mov	ss,ax
;R132
;R132		in	al,STAT8042		; was this a user or prog reset ?
;R132		NEWIODELAY
;R132		test	al,4
;R132		jnz	short @F

ifdef	PM_SUPPORT
	;Detect if it is resumed from sleep state ( suspend to DRAM )
		extrn	CT_Sleep_Detect:near
		rom_call	CT_Sleep_Detect
		jnz	short @F		; virtual shutdown...
endif	;PM_SUPPORT

	;Identify CPU vendor and it's type and also save it in CMOS for POST
	;usage.
		mov	dx,gs			; dx = CPU ID
		rom_call	CPU_Detect

;R157 - start
ifdef	ACPI_SUPPORT
ifdef	S3_SUPPORT
		include	acpi.inc
		include	acpi_ct.inc
ifNdef	SIS5595_ID				;R157A
		extrn	Turn_On_ACPI_IO:near
		Rom_Call	Turn_On_ACPI_IO

		mov	dx, PM1a_CNT_BLK + 1	;Get suspend type register
		in	al, dx			;Read this register
		cmp	al, 0ffh		;If not valid IO, jump out.
		je	short Not_Resume_From_Sx
		and	al, SLP_TYPE_MASK	;Isolate sleep type bits
		cmp	al,S3
		extrn	Resume_From_S3:near
		jne	short Not_Resume_From_Sx
		jmp	Resume_From_S3
;R157A - starts
else	;SIS5595_ID
		mov	cx,APC_R+06h
		Rom_Call	Get_Ct
		test	al,20h
		jz	short Not_Resume_From_Sx
		extrn	Resume_From_S3:near
		jmp	Resume_From_S3
endif	;SIS5595_ID
;R157A - ends
Not_Resume_From_Sx:
endif	;S3_SUPPORT
endif	;ACPI_SUPPORT
;R157 - end

ifndef	PCI_RESET_SUPPORT					;R139
;R109 start
	;Clear warm boot flag
		mov	ax,G_RAM
		mov	ds,ax
		mov	word ptr ds:[USER_REBOOT],0
;R109 end
endif	;PCI_RESET_SUPPORT					;R139
@@:

;Program chipset registers before POST
		POST_CODE 0c0h
		mov	sp,0F80Bh	;return to F000:F80B after call
ifndef	Very_Very_Early_Init				;R132
		extrn	Ct_Very_Early_Init:Near
		jmp	Ct_Very_Early_Init
else	;Very_Very_Early_Init				;R132
		ret					;R132
endif	;Very_Very_Early_Init				;R132

REDO		ENDP

;R66 - start
;R74		ALIGN	8
;R74FLASH_ROUTINE_HEAD	db	'AWDFLASH'
;R74		extrn	KBC_12V_Control:near
;R74		extrn	Ct_ROM_Write_Enable:near
;R74		extrn	Ct_ROM_Write_Disable:near
;R74		extrn	Ct_Enable_ROM_Decode:near
;R74		extrn	Ct_Init:near
;R74		extrn	CT_Disable_ROM_Shadow:near
;R74		extrn	CT_Enable_ROM_Shadow:near
;R74		extrn	Ct_Special_REG_Save:near
;R74		extrn	Ct_After_Program:near
;R74		DW	Offset	DGROUP:KBC_12V_Control
;R74		DW	Offset	DGROUP:Ct_ROM_Write_Enable
;R74		DW	Offset	DGROUP:Ct_ROM_Write_Disable
;R74		DW	Offset	DGROUP:Ct_Enable_ROM_Decode
;R74		DW	Offset	DGROUP:Ct_Init
;R74		DW	Offset	DGROUP:CT_Disable_ROM_Shadow
;R74		DW	Offset	DGROUP:CT_Enable_ROM_Shadow
;R74		DW	Offset	DGROUP:Ct_Special_REG_Save
;R74		DW	Offset	DGROUP:Ct_After_Program
;R66 - end

		align	16
;R94 Chipboot_start:
ifndef	Chipboot_In_External_Boot_Block		     	;R151
;;;;;ifdef	Bootblock_16K_Support				;R186
ifdef	Flash_2M_support				;;;;;
  		public	Enable_Extra_1MBIOS_Hook	;R186
  		public	Disable_Extra_1MBIOS_Hook	;R186
endif	;Flash_2M_support				;;;;;
;;;;;endif	;Bootblock_16K_Support				;R186
		include	chipboot.asm
;R186 start
else	;Chipboot_In_External_Boot_Block
		extrn	CT_MEMORY_PRESENCE:near
		extrn	Ct_Early_Shadow_System_Bios:near
  		extrn	Enable_Extra_1MBIOS_Hook:near
  		extrn	Disable_Extra_1MBIOS_Hook:near
;R186 end
endif	;Chipboot_In_External_Boot_Block                ;R151

ifndef Reallocate_EarlyIO				;R78A
		include	earlyio.asm			;R78
endif ;Reallocate_EarlyIO				;R78A

	;Start memory detection ( chipset memory configuration programming )
		public	MEMORY_PRESENCE
MEMORY_PRESENCE:

ifdef	Special_Early_Init				;R134
		Rom_Call	Ct_Early_Init		;R134
endif	;Special_Early_Init				;R134
	;Program necessary CPU registers ( in cpurun.asm )
		rom_call	CPU_Init

;R73 - start
;R73A		mov	al,CMOS_AWARD_2 NMI_OFF
;R73A		Rom_Call Get_CMOS
;R73A		and	al,CPU_TYPE_MASK
;R73A		cmp	al,TYPE_M1
;R73A		jne	_Not_M1
;R73A
;R73A		Rom_Call	Enable_Linear_Burst
;R73A_Not_M1:
;R73 - end
;R77		mov	al,FALSE
;R77		rom_call	CPU_Cache

		mov	eax,cr0
		and	ax,NOT 4		;disable 80x87 emulation
		mov	cr0,eax

;-------- Original POST 3 -------------
;
;	Disable CMOS interrupts
;

;	CMOS REGISTER 0B: Default is all interrupts turned off,
;	date is in BCD format, time is in 24-hour mode, daylight savings
;	time is disabled.

		mov	al,0bh NMI_OFF
		mov	ah,10b
		rom_call	Set_CMOS		; set register B to its default

;	CMOS REGISTER 0A: Default is stage divider at 32.768 kHz, divider
;	output at 1.024 Khz, interrupting every 976.562 microseconds

		mov	al,0ah NMI_OFF		; set register A to its default
		mov	ah,26h
		rom_call	Set_Cmos

;R138A - start
;
;	Initialize various chips...
;	That includes DMA controller (8237),Interrupt controller(8259) and
;	Timer counter(8254)

		mov	ax,0f000h		;segment address
		mov	ds,ax

		mov	si,offset DGROUP:SYS_INITS
		mov	cx,SIZE_SYS_INITS
		cld

;
;	Initialize everything except for DMA page registers
;

ch0_dma_init:
		lodsw				; get the port
		mov	dx,ax			; put in correct reg

		lodsb				; get byte to ouput
		out	dx,al

		IODELAY

		loop	short ch0_dma_init

;
;	Initialize page registers
;

		mov	cx,0fh
		mov	dx,81h
		xor	ax,ax

init_pg_regs:
		IODELAY

		out	dx,al
		inc	dx

		loop	short init_pg_regs
;R138A - end

;R111 - start
ifdef	PCI_RESET_SUPPORT
;Don't destroy value of shutdown byte CMOS
		mov	al,0fh NMI_OFF
		Rom_call Get_Cmos
		cmp	al,0AAH		;warm booting
		je	short Not_Resume
endif;	PCI_RESET_SUPPORT
;R111 - end

		mov	al,0fh NMI_OFF
;R160 ifdef	Notebook_Power_Management			;R110
if	STD_Function		EQ	1		;R160
;R158 ZV_Resume_Byte	EQU	1Dh				;R110
		Rom_call	Get_Cmos		;R110
		cmp	al,ZV_Resume_Byte		;R110
		je	short Not_Resume		;R110
;R158 - start
ifdef	ACPI_SUPPORT
ifdef	S4_SUPPORT
		cmp	al,S4_Resume_Byte
		je	short Not_Resume
endif	;S4_SUPPORT
endif	;ACPI_SUPPORT
;R158 - end
		mov	al,0fh NMI_OFF			;R110
endif	;STD_Function		EQ	1		;R160
;R160 endif	;Notebook_Power_Management			;R110
		xor	ah,ah
		rom_call	Set_Cmos
Not_Resume:						;R110
;--------------------------------------

;[]==============================================================[]
;	FORCE_COLDBOOT_ON_RESET: BIOS will force system to cold boot
;	if someone press the reset button during the warm boot. Since
;	warm boot flag will not be able to be cleared until POST_99,
;	this will provide a way to wipe out warm boot flag by
;	pressing reset button. The reason we have to use CMOS is
;	because memory is not initialized yet, we can not just
;	clear the warm boot flag. The warm boot flag will be cleared
;	until memory is initialized. Also, since we initial keyboard
;	in POST_5S, this is the latest place that keyboard status
;	flag remains valid.
;[]==============================================================[]

		mov	al, CMOS_OVERRIDE NMI_OFF
		rom_call	Get_CMOS
		mov	ah,al			; save CMOS info in ah

		in	al,STAT8042		; check if power on reset
		NEWIODELAY
		or	ah,COLD_BOOT		; assume not power on reset

		test	al,04			; cold boot?
		jnz	short p5_0		; no...

		and	ah,NOT COLD_BOOT	; power on reset, reset flag
p5_0:
		mov	al, CMOS_OVERRIDE NMI_OFF
		rom_call	Set_CMOS

;R159A - start
IFNDEF	Ct_Preset_In_Decompress_Area_After_Jumpless	;R159B
 ifdef	Ct_Preset_In_Decompress_Area
	   	extrn	Ct_Decompress_Hook:near		;R186
	   	jmp	Ct_Decompress_Hook
	   	public	Ct_Decompress_Hook_End		;R186
Ct_Decompress_Hook_End:
 endif;	Ct_Preset_In_Decompress_Area
ENDIF;	Ct_Preset_In_Decompress_Area_After_Jumpless	;R159B
;R159A - end

;R156 - start
ifdef	Jumpless_in_Decompress_Area
		mov	di,offset DGROUP:@F
		extrn	Set_Clock:near		;R186
		jmp	Set_Clock
     @@:
endif	;Jumpless_in_Decompress_Area
;R156 - end

IFDEF	Ct_Preset_In_Decompress_Area_After_Jumpless	;R159B
 ifdef	Ct_Preset_In_Decompress_Area			;R159B
	   	jmp	Ct_Decompress_Hook		;R159B
Ct_Decompress_Hook_End:					;R159B
 endif;	Ct_Preset_In_Decompress_Area			;R159B
ENDIF;	Ct_Preset_In_Decompress_Area_After_Jumpless	;R159B

;R159A;R159 - start
;R159Aifdef	Ct_Preset_In_Decompress_Area
;R159A	   	jmp	Ct_Decompress_Hook
;R159ACt_Decompress_Hook_End:
;R159Aendif;	Ct_Preset_In_Decompress_Area
;R159A;R159 - end

		POST_CODE 0C1H

;R111B ;R111A - start
;R111B ifdef	PCI_RESET_SUPPORT
;R111B ;Clear warm boot flag stored in CMOS for next warm reset
;R111B 		mov	ax,G_RAM
;R111B 		mov	ds,ax
;R111B 		assume	ds:G_RAM
;R111B
;R111B 		mov	word ptr ds:USER_REBOOT, 0   	; not warm boot
;R111B
;R111B 		mov	al,0FH NMI_OFF
;R111B 		rom_call Get_Cmos
;R111B 		cmp	al,0AAH
;R111B 		jne	short Not_WarmBoot
;R111B
;R111B 		mov	word ptr ds:USER_REBOOT, CTRL_ALT_DEL	; warm boot
;R111B
;R111B 		;clear warm boot flag
;R111B 		mov	al,0FH NMI_OFF
;R111B 		xor	ah,ah
;R111B 		rom_call Set_Cmos
;R111B Not_WarmBoot:
;R111B endif;	PCI_RESET_SUPPORT
;R111B ;R111A - end

;R90		mov	ax,0fb00h
;R103		mov	ax,(0f000h+External_BootRom_Seg shr 4)	;R90
;R108		mov	ax,(0f000h+(External_BootRom_Seg and 0f000h) shr 4)	;R103
;R108 start
	;Search header of external memory sizing code
		rom_call	Search_BBSS_label	;Get BBSS table offset
		or	si,si				;have found?
		jz	short BootRom_MEMORY_PRESENCE	;No,jump to BootBlock memory sizing

	;Header found , get address of memory sizing code
		mov	bx,si				;save SI to BX
		mov	ax,cs:[si+BootExt_Off]		;Get BootExt code offset
		and	ax,0f000h			;-------------------
		shr	ax,4				;transfer to become segment
		add	ax,0f000h			;-------------------
;R108 end
		mov	ds,ax			;segment address of memory sizing
	;Do memory sizing code checksum checking
		xor	ah,ah			;zero checksum
		xor	si,si			;start from byte 0
;;		mov	cx,0fffh		;total code size to check
		mov	cx,0fffh+Extra_MemSizing_Space	;;
ifdef	BootExt_Extra_Size			;R169
		add	cx,BootExt_Extra_Size	;R169
endif	;BootExt_Extra_Size			;R169
@@:						;4kb-1
		lodsb
		add	ah,al			;sum up
		loop	short @B		;next byte
		cmp	ah,[si]			;checksum ok ?
;R108		jne	short @F
		jne	short BootRom_MEMORY_PRESENCE		;R108

	;Checksum is okay , execute memory detection
;R94		lea	si,DGROUP:CT_MEMORY_PRESENCE
;R94		sub	si,offset DGROUP:Chipboot_Start
;R94;R90		add	si,0b000h
;R94		add	si,External_BootRom_Seg			;R90
;R103		mov	si,External_BootRom_Seg			;R94
;R108		mov	si,External_BootRom_Seg and 0f000h	;R103
;R108 start
		mov	ax,cs:[bx+BootExt_Off] ;Get BootExt code offset
		and	ax,0f000h
ifdef	BootExt_Extra_Size			;R169
		add	ax,BootExt_Extra_Size	;R169
endif	;BootExt_Extra_Size			;R169
		mov	si,ax		       ;store to SI
;R108 end
		add	si,MEMORY_PRESENCE_OFFSET		;R94
		mov	si,cs:[si]				;R94
		mov	sp,offset DGROUP:RTN_ADD
		jmp	si		      	;execute memory detection
		align	4					;R113
RTN_ADD:
		dw	offset DGROUP:Memory_Pres_Ret
;R108 @@:

	;External memory sizing code is bad or not found , Use internal
	;memory sizing code to detect memory configuration
BootRom_MEMORY_PRESENCE:					;R108
		ROM_CALL	CT_MEMORY_PRESENCE
		align	4					;R113
Memory_Pres_Ret:

;R138A;R138 - start
;R138A;
;R138A;	Initialize various chips...
;R138A;
;R138A
;R138A		mov	ax,0f000h
;R138A		mov	ds,ax
;R138A
;R138A		mov	si,offset DGROUP:SYS_INITS
;R138A		mov	cx,SIZE_SYS_INITS
;R138A		cld
;R138A
;R138A;
;R138A;	Initialize everything except for DMA page registers
;R138A;
;R138A
;R138Ach0_dma_init:
;R138A		lodsw				; get the port
;R138A		mov	dx,ax			; put in correct reg
;R138A
;R138A		lodsb				; get byte to ouput
;R138A		out	dx,al
;R138A
;R138A		IODELAY
;R138A
;R138A		loop	short ch0_dma_init
;R138A
;R138A;
;R138A;	Initialize page registers
;R138A;
;R138A
;R138A		mov	cx,0fh
;R138A		mov	dx,81h
;R138A		xor	ax,ax
;R138A
;R138Ainit_pg_regs:
;R138A		IODELAY
;R138A
;R138A		out	dx,al
;R138A		inc	dx
;R138A
;R138A		loop	short init_pg_regs
;R138A;R138 - end
;R111B - start
ifdef	PCI_RESET_SUPPORT
;Clear warm boot flag stored in CMOS for next warm reset
		mov	ax,G_RAM
		mov	ds,ax
		assume	ds:G_RAM

		mov	word ptr ds:USER_REBOOT, 0   	; not warm boot

		mov	al,0FH NMI_OFF
		rom_call Get_Cmos
		cmp	al,0AAH
		jne	short Not_WarmBoot

		mov	word ptr ds:USER_REBOOT, CTRL_ALT_DEL	; warm boot

		;clear warm boot flag
		mov	al,0FH NMI_OFF
		xor	ah,ah
		rom_call Set_Cmos
Not_WarmBoot:
endif;	PCI_RESET_SUPPORT
;R111B - end

;----------- Base memory test original in POST_8S -----------------

	;save warm boot flag
		mov	ax,G_RAM
		mov	ds,ax
		ASSUME	DS:G_RAM
		mov	bx,word ptr ds:USER_REBOOT	;save flag

;R143ifdef	P6_BIOS_ONLY						;R112
;Test first 256Kb memory , Send endless beep if DRAM is bad

ifndef	beep_for_no_ram				;R145
		xor	eax,eax			;pattern to test
else;	beep_for_no_ram				;R145
		mov	eax,00ff55aah		;R145
endif;	beep_for_no_ram				;R145
;r181 - start
ifdef	Debug_1st_32K_RAM_Data_Signal
		xor	al,al			;OUT zero(correct) data
		out	DEBUG_PORT,al		;to debug_port first

Compare_1st_32K_RAM_loop:
		xor	eax,eax			;fix pattern to test
		mov	bh,0E4h			;mark the flag first, says E4h
endif;	Debug_1st_32K_RAM_Data_Signal
;r181 - end

		xor	dx,dx			;start from first 64k
Next_64K_Test:
		mov	es,dx			;segment to test
		cld

	;fill the first 32Kb memory with pattern
;R143A		mov	cx,4000H		;64k to write pattern
		mov	cx,2000h		;64k to read pattern	;R143A
		xor	di,di
		rep	stosd

	;fill the second 32Kb memory with inversed pattern
		not	eax			;R143A
		mov	cx,2000H		;R143A
		rep	stosd			;R143A

	;Check the first 32Kb memory contents
		not	eax			;R143A
;R143A		mov	cx,4000h		;64k to read pattern
;r181 - start
ifdef	Debug_1st_32K_RAM_Data_Signal
		or	dx,dx				;first 32K?
		jnz	short Not_1st_32K_RAM_Debug	;not, then leave
		mov	cx,8000h		;read first 32K pattern
		xor	di,di
@@:		mov	bl,es:[di]		;get it into BL
		cmp	al,bl			;compare it
		jne	short found_RAM_error	;error occured!
		inc	di			;check next byte
		loop	short @b

		cmp	al,bh			;the flag is changed?(BL=E4h?)
		je	short Compare_1st_32K_RAM_loop ;if all correct,AL<>BH!

		mov	bh,al			;save AL(original pattern) by BH
		mov	al,0C1h			;restore original POST CODE C1h
		out	DEBUG_PORT,al
		mov	al,bh			;restore AL by BH
		jmp	short Check_2nd_32K_RAM ;leave to check by normal routine

found_RAM_error:
		mov	bh,al			;save AL(original pattern) by BH
		mov	al,bl			;OUT the error data
		out	DEBUG_PORT,al		;to debug_port
		mov	al,bh			;restore AL by BH
		inc	di			;check next byte
		loop	short @b		;go back to continue comparing
		jmp	short Compare_1st_32K_RAM_loop ;still error? compare again!

Not_1st_32K_RAM_Debug:
endif;	Debug_1st_32K_RAM_Data_Signal
;r181 - end

		mov	cx,2000h		;64k to read pattern	;R143A
		xor	di,di
		rep	scasd
		jnz	short Beep_Out		;error occured		;R143A

ifdef	Debug_1st_32K_RAM_Data_Signal		;r181
Check_2nd_32K_RAM:				;r181
endif;	Debug_1st_32K_RAM_Data_Signal		;r181

	;Check the second 32Kb memory contents
		not	eax			;R143A
		mov	cx,2000h		;R143A
		rep	scasd			;R143A

		jnz	short Beep_Out		;error occured		;R143A

		add	dh,10H			;next segment
		cmp	dh,40H			;256K address ?
		jne	short Next_64K_Test

		jmp	short Ok_256K

Beep_Out:

;Send beep thru speaker
;R178 - start
 ifdef	LED_FLUSH_IF_NO_MEMORY
		mov	bl, GPO_LOW_IF_MEMORY_OK
    		ROM_CALL GPO_Toggle
 endif;	LED_FLUSH_IF_NO_MEMORY
;R178 - end

		mov	bl,1			; beep on override
		ROM_CALL Snd_Spkr


		xor	cx,cx			; wait a moment
		loop	short $

		jmp	short Beep_Out		;endless loop

;R178 - start
ifdef	LED_FLUSH_IF_NO_MEMORY
;Function : Toggle Output GPO
;Input    : BL - GPO pin to set low (0=GPO0, 1=GPO1 ,....)
;Output   : none
Gpo_Toggle	proc	near
	;calculate which bit to toggle
		mov	cl,bl
		and	cl,07h
		mov	bh,01h
		shl	bh,cl

	;calculate which register to set
		mov	dl,bl
		shr	dl,3
		add	dl,34h	    	;from reg. 34H for GPO
		mov	dh,PM_IO	;PM I/O port
		in	al,dx
		NEWIODELAY
		xor	al,bh		;toggle output to GPO
		out	dx,al
		ret
Gpo_Toggle		endp
endif;	LED_FLUSH_IF_NO_MEMORY
;R178 - end

Ok_256K:
ifdef	beep_for_no_ram				;R145
		xor	eax,eax			;pattern to test
		xor	dx,dx			;start from first 64k

		mov	es,dx			;segment to test
		cld

		mov	cx,0ffffH		;64k to write pattern
		xor	di,di
		rep	stosd

endif;	beep_for_no_ram				;R145

;R143else;	P6_BIOS_ONLY						;R112
;R143
;R143		xor	di,di
;R143		mov	es,di
;R143		mov	cx,4000h
;R143		mov	eax,3c3cc3c3h
;R143		rep	stosd
;R143
;R143;Beep speaker if first 64k is bad
;R143
;R143		mov	cx,4000h
;R143		xor	di,di
;R143		rep	scasd
;R143		jnz	P8_9
;R143endif;	P6_BIOS_ONLY						;R112

		mov	word ptr ds:USER_REBOOT,bx	;restore flag

		mov	ax,G_RAM
		mov	ds,ax
		ASSUME	DS:G_RAM

;Clear setup and override flag						;R69
		and	byte ptr POST_FLAG,NOT (SETUP_ON+OVERRIDE_ON)	;R69

ifdef	Bootblock_16K_Support						  ;R154
ifdef	Automatic_Load_Awdflash						  ;R154
		and	byte ptr POST_FLAG,NOT (AWDFLASH_ON+AWD_Str_Show) ;R154
endif	;Automatic_Load_Awdflash					  ;R154
endif	;Bootblock_16K_Support						  ;R154


ifndef	PCI_RESET_SUPPORT					;R111A
;	Clear warm boot flag if reset button pressed

		mov	al, CMOS_OVERRIDE NMI_OFF	; al = CMOS index
		mov	ah,al				; ah = CMOS index
		rom_call	Get_Cmos

		test	al,COLD_BOOT			; cold boot?
		jnz	short p8_1			; no...

		mov	word ptr ds:[USER_REBOOT],0	; reset warm boot flag in RAM
p8_1:
;----- 11/25/94 RCH	Don't clear cold boot flag in CMOS
;		and	al,NOT COLD_BOOT		; clear warm boot flag
;
;		xchg	al,ah				; al = index, ah = value
;		rom_call	Set_Cmos
endif;	PCI_RESET_SUPPORT					;R111A

;	Here we both reset the parity flag as well as save
;	the reset flag after we have destroyed the 40: area.

		mov	si,word ptr ds:USER_REBOOT
		mov	word ptr ds:USER_REBOOT,si

;	Disable parity checking

		in	al,SYS1
		or	al,PARITY_CHECK_OFF
		NEWIODELAY
		out	SYS1,al

;R143ifndef	P6_BIOS_ONLY						;R112
;R143;	Clear 256K (4 x 64K) of memory.
;R143
;R143		xor	bx,bx			; bx = segment counter
;R143
;R143		ALIGN	4
;R143p8_2:
;R143		xor	di,di
;R143		mov	es,bx
;R143		mov	ecx,4000h
;R143		xor	eax,eax
;R143		rep	stosd			; clear using dwords
;R143
;R143		add	bx,1000h		; next 64k chunk
;R143		cmp	bx,4000h		; done with 256k?
;R143		jne	short p8_2			; no...
;R143
;R143;	Reenable parity
;R143;	Intensive parity checking the first 64K...
;R143;
;R143; Algorithm is:
;R143;
;R143; di = 0;					// beginning of segment
;R143; for (bx = 1; bx != 201h; bx +=100) {		// first we test low byte then high byte (0001h then 0100h)
;R143;	for (es = 0; es < 4000h; es += 1000h) {	// then we test first 256K
;R143;		es:[di] = 0;			// set background of 0000h
;R143;		es:[di] = bx;			// write test pattern
;R143;		bx = 5a5ah;			// reset to random in case bus transfer does nothing.
;R143;		bx = es:[di];			// read back
;R143;		if parity_error() halt_system();// port 61 bit 7 shows parity error
;R143;
;R143;		es:[di] = 0ffffh		// set background of 0ffffh
;R143;		es:[di] = bx;			// write test pattern
;R143;		bx = 5a5ah			// reset to random in case bus transfer does nothing.
;R143;		bx = es:[di];			// read test pattern
;R143;
;R143;		if parity_error() halt_system();// port 61 bit 7 shows parity
;R143;	}
;R143; }
;R143
;R143p8_3:
;R143		xor	di,di			; di = mem. pointer
;R143		mov	es,di			; es = test segment
;R143		mov	bx,1			; bx = test pattern
;R143
;R143		align	4
;R143
;R143;	First test on 0000h.
;R143
;R143p8_31:
;R143		mov	word ptr es:[di],0	; 0 background
;R143		mov	word ptr es:[di],bx	; write pattern
;R143
;R143		mov	bx,5a5ah		; reset bx
;R143		mov	bx,word ptr es:[di]
;R143
;R143;	Second test on 0ffffh
;R143
;R143p8_32:
;R143		mov	word ptr es:[di],0ffffh	; 1 background
;R143		mov	word ptr es:[di],bx	; write pattern
;R143
;R143		mov	bx,5a5ah		; reset bx
;R143		mov	bx,word ptr es:[di]
;R143
;R143		mov	es,di			; reset test segment
;R143
;R143		add	bx,100h			; next test high byte
;R143
;R143		cmp	bx,201h			; done?
;R143		jnz	short p8_31		; no
;R143
;R143p8_33:
;R143
;R143;	Test the validity of the first 64k of memory
;R143
;R143p8_4:
;R143		mov	eax,0aa55aa55h		; eax = test pattern
;R143		xor	ebx,ebx			; ebx = clear pattern
;R143		xor	dx,dx			; dx  = segment
;R143
;R143p8_40:
;R143		mov	es,dx
;R143
;R143		mov	ecx,4000h
;R143		ALIGN	4
;R143
;R143;	Test the validity of 64k of memory
;R143
;R143p8_41:
;R143		stosd				; save test pattern
;R143		mov	dword ptr es:[di],ebx	; change bus state
;R143		cmp	dword ptr es:[di-4],eax	; did it change?
;R143		jne	short p8_9		; yes, memory error...
;R143
;R143		mov	dword ptr es:[di-4],ebx	; clear	memory
;R143		loop	short p8_41
;R143
;R143		clc
;R143		jmp	short p8_91		; memory good
;R143
;R143p8_9:
;R143		mov	bl,1			; beep on override
;R143		ROM_CALL Snd_Spkr
;R143		xor	cx,cx
;R143		loop	short $
;R143		jmp	short P8_9
;R143
;R143p8_91:
;R143endif;	P6_BIOS_ONLY						;R112
		lahf
		mov     word ptr ds:[Init_Err_Flg],IEF_IN_POST
		and     byte ptr ds:[Init_Err_flg],NOT IEF_TO_ENTER_SETUP

		mov	word ptr ds:USER_REBOOT,si ; restore reset flag
		sahf
;--------------------------------------------------------------------

;R120 - start
;---------------- Enter Protect Mode ----------------
                mov     ax,cs
                mov     ds,ax
                assume  ds:dgroup

                lgdt    fword ptr A_GDTR	;load descriptor table

                mov     eax,cr0
                or      al,1			;enable protected mode
                mov     cr0,eax

		jmp	short $+2		;clear prefetch

                mov     ax,B_DATA1_INDEX
                mov     ds,ax                   ; ds = 00000000h
		mov	es,ax			; es = ds

	;There are two locations to access E0000H ROM space, one is 0E0000H
	;and another is 0FFFE0000H. Some chipsets can not access onboard ROM
	;space at 0E0000H if any device also use the space on ISA bus. To
	;solve this problem , we need to change address to 0FFFE0000H
	;to read BIOS contents at 0E0000H space.
		mov	esi,0000e0000h		;E-segment address
;R120A		cmp	dword ptr ds:[2],'5hl-'	;signature of compressed code
		cmp	dword ptr ds:[esi+2],'5hl-';signature of compressed code;R120A
		je	short GoCopy_E000Code	;use 0E0000H to access ROM

		or	esi,0fff00000h		;wrap-around of E-segment
						;use 0FFFE0000H space
GoCopy_E000Code:

;move entire BIOS from E0000h-FFFFFh to ram 10000h-2FFFFh
		mov	edi,10000H		;buffer at 1000:0
;R120A		mov	ecx,10000h		;copy 128Kb to buffer
		mov	ecx,8000h		;copy 128Kb to buffer;R120A
ifdef	PATCH_FOR_PR200_SDRAM					;R142
Next_DwordCopy:						    	;R142
 		align	16					;R142
		lods	dword ptr [esi]		;load dword	;R142
		stos	dword ptr [edi]		;store dword	;R142
		loop	short Next_DwordCopy			;R142
else;	PATCH_FOR_PR200_SDRAM					;R142
		db	67h
		rep	movsd
endif;	PATCH_FOR_PR200_SDRAM					;R142

;---------------- Leave Protect Mode ----------------
                mov     eax,cr0
                and     al, NOT 1
                mov     cr0,eax

		jmp	short $+2		;flush queue
;R120 - end

;R120
;R120;move entire bios to ram 10000h-2FFFFh
;R120		mov	ax,0e000h
;R120		mov	ds,ax
;R120
;R120		mov	ax,1000h
;R120		mov	es,ax
;R120
;R120		xor	si,si
;R120		xor	di,di
;R120		mov	cx,4000h
;R120		rep	movsd
;R120
;R120		mov	ax,0f000h
;R120		mov	ds,ax
;R120		mov	ax,02000h
;R120		mov	es,ax
;R120		mov	cx,4000h
;R120		rep	movsd

	;Execute BIOS in RAM for performace purpose
		FAR_JMP	<offset DGROUP:@F>,2000h	;jump to RAM address
@@:
	;Setup temporary stack pointer at 0:1000H
		xor	ax,ax
		mov	ss,ax
		mov	sp,BootPOST_STK		;temp ss:sp

;R83 - start
IF	BIOS_SUPPORT_586			;R86
;R88 ifdef	M1_CPU_OFF_BEFORE_DECOMPRESS
;Don't turn on CPU cache if M1 linear burst already on

		mov	al,FIXED_DISK_STEP NMI_OFF
		call	Get_Cmos
		and	al,CPU_TYPE_MASK
		cmp	al,TYPE_M1
		jne	short Not_M1

;R88 start
		call	UNlock_Cyrix

		mov	cl,0c3h
		Call	Get_Cyrix
		and	al,not 04h		; set M1 LINBRST bit of CCR3
		Call	Set_Cyrix

		Call	Lock_Cyrix
;R88 end
;R88		mov	al,0c3h
;R88		out	22h,al
;R88		in	al,23h
;R88		test	al,04H		;linear burst already enabled ?
;R88		jnz	short No_Cpu_CacheOn

Not_M1:
;R88 endif;	M1_CPU_OFF_BEFORE_DECOMPRESS
ENDIF	;BIOS_SUPPORT_586			;R86
;R83 - end

;R87 - start
ifdef	QUALIFY_L1_CACHE_ON_DECOMPRESS
		extrn	Ct_Qualify_L1_Cache:near
		call	Ct_Qualify_L1_Cache		;allow L1 cache to
		jc	short No_Cpu_CacheOn		;turn on ?
endif;	QUALIFY_L1_CACHE_ON_DECOMPRESS
;R87 - end

	;Turn CPU cache to speed up decompress
		mov	al,TRUE				;enable L1 cache
		call	CPU_Cache

;R100 - start
ifdef	SET_L1_BIT_BEFORE_CPUCACHE
		extrn	Enable_Ct_L1_Bit:near
		call	Enable_Ct_L1_Bit		;turn on L1 cache
endif;	SET_L1_BIT_BEFORE_CPUCACHE
;R100 - end


;R96 - start
ifdef	QUALIFY_L2_CACHE_ON_DECOMPRESS
                extrn   Ct_Enable_L2_Cache:Near
		mov	al, TRUE
                call    Ct_Enable_L2_Cache
endif	;QUALIFY_L2_CACHE_ON_DECOMPRESS
;R96 - end


No_Cpu_CacheOn:							;R83

;[]==============================================================[]
;
;	BIOS checksum verify
;
;[]==============================================================[]

		POST_CODE 0ch

		mov	ax,1000h		;point to 0E000H
		mov	ds,ax
		mov	bx,ds:[9]	     	;R84
		mov	cx,ds:[7]	     	;get compressed size
		add	cl,ds:[0]	     	;add header size
		adc	ch,0
		adc	bx,0		     	;R84
		add	cx,COMPRESSED_UNKNOW_BYTE
;R84 start
		adc	bx,0
		jz	short @F	;compressed size bigger than 64Kb ?
					;yes
		mov	bx,cx		;the code size remainder in next 64kb
		xor	cx,cx		;code size to sum up for first 64Kb
@@:					;it is 64Kb
;R84 end
		xor	si,si
		xor	ah,ah
@@:
		lodsb
		add	ah,al		;sum up checksum
		loop	short @B
;R84 start
		or	bx,bx		;compressed BIOS bigger than 64kb ?
		jz	short @F	;no, less than 64Kb

		mov	cx,bx		;code size in next 64Kb
		mov	bx,ds		;setup next 64Kb segment address
		add	bx,1000h	;next 64Kb
		mov	ds,bx
		xor	bx,bx		;mark for no next 64Kb
		jmp	short @B	;continue to do checksum sum up
@@:
;R84 end
		cmp	ah,[si]
		jne	BIOS_cksm_error
;R90		mov	ax,2b00h
;R108		mov	ax,(2000h+Decompress_Code_Seg shr 4)	;R90
;R108 start
		call	Search_BBSS_label		;Get BBSS table offset
		or	si,si				;have found?
		jz	short BIOS_cksm_error		;No,jump to checksum error routine
		mov	ax,cs:[si+DecmpCode_Off]	;Get decompress code offset
;R108C		shr	eax,4
		shr	ax,4				;R108C
		add	ax,2000h			;transfer to become segment
;R108 end
		mov	ds,ax
		xor	ah,ah
		xor	si,si
;R90		mov	cx,1fffh
;;		mov	cx,0fffh				;R90
		mov	cx,0fffh-Extra_MemSizing_Space	;;
Checksum_loop:
		lodsb
		add	ah,al
		loop	Checksum_loop
		cmp	ah,[si]
		jne	short BIOS_cksm_error

ifdef	K7_CPU_SUPPORT						;R183
	;Reserve for K7 initialization				;R183
else;	K7_CPU_SUPPORT						;R183

;R128 - start
ifdef	KLAMATH_CPU_ONLY

;R130 - start
	;enable WB cache for B0 and later stepping of Klamath CPUs
		mov	eax,1	       	;eax = 1 to read CPU ID
		db	0fh,0A2h       	;CPU ID instruction
;R135 - start
ifdef	BOTH_P6_KLAMATH_CPU
	;set write back cache for Pentium Pro and non-A0 stepping for Klamath
	;CPU.
		mov	cl,al
		mov	eax,06060606H	;set memory type to WB in lower 32bit
		cmp	cl,30h		;Pentium PRO ?
		jb	short Yes_B0Above
		cmp	cl,32H	       	;Klamath B0 stepping and above ?
		jae	short Yes_B0Above
else;	BOTH_P6_KLAMATH_CPU
;R135 - end

		cmp	al,32H	       	;B0 stepping and above ?
		mov	eax,06060606H	;set memory type to WB in lower 32bit
		jae	short Yes_B0Above
endif;	BOTH_P6_KLAMATH_CPU				;R135
;R130 - end

;Enable write through of 0-640K for Klamath CPU due to bug
		mov	eax,04040404H	;set memory type to WT in lower 32bit
Yes_B0Above:				;R130
		mov	edx,eax 	;higher 32bit
		mov	ecx,250H	;address(250H) for 0-512K
		WRMSR
		mov	cl,58H		;address(258H) for 512K-640K
		WRMSR

;R165 - start
		xor	eax, eax	; Disable C0000 - FFFFFh Cacheable
		mov	edx, eax	;
		mov	cl, 59h		;
		WRMSR			;
		mov	cl, 68h		;
@@:					;
		WRMSR			;
		inc	cl		;
		cmp	cl, 6Fh		;
		jbe	short @B	;
;R165 - end

;Enable caching for memory
		mov	eax,00000C00h
		xor	edx,edx
		mov	cl,0ffH 	;address(2ffH) to enable caching
		WRMSR

		WBINVD
		mov	eax,cr3
		mov	cr3,eax 	;Invalidate TLB by loading CR3.
endif;	KLAMATH_CPU_ONLY
;R128 - end
endif;	K7_CPU_SUPPORT						;R183

		POST_CODE	0C3h
		call	Expand_Bios

;R98 - start
ifdef	ORION_ESCD_PATCH
;Copy ESCD buffer from ROM into temporary memory(0:4000H) due to system hang
;while reading ESCD for ORION chipset
		pusha
		push	ds
		push	es
		mov	ax,0fd00H		;segment of ESCD
		mov	ds,ax
		mov	ax,0400H		;tempory segment
		mov	es,ax
		xor	si,si
		xor	di,di
		mov	cx,1000H		;4k buffer
		rep	movsb
		pop	es
		pop	ds
		popa

endif;	ORION_ESCD_PATCH
;R98 - end

		jmp	short @F		;checksum is good
BIOS_cksm_error:
	;Shadow original BIOS image for booting from boot block
		mov	ax,1000h	       	;original ROM code
@@:	 					;good check, ax = 5000H
		mov	ds,ax			;setup source for shadowing

		POST_CODE	0C5h
	;The source data segment is 5000H if checksum is good.
	;the contents in this area is decompressed by routine "Expand_Bios".
	;And segment is 1000H for shadowing original BIOS image if checksum
	;is bad. BIOS will shadow bootblock and boot from it.
		call	Ct_Early_Shadow_System_Bios	;syshadow system BIOS

;R96 - start
ifdef	QUALIFY_L2_CACHE_ON_DECOMPRESS
		mov	al,FALSE
		call	Ct_Enable_L2_Cache
endif	;QUALIFY_L2_CACHE_ON_DECOMPRESS
;R96 - end

		mov	al,FALSE
		call	CPU_Cache

	;BIOS decide where to go from here.
	;If BIOS checksum is good, this address F80DH is shadowed by
	;decompressed code, BIOS will execute code in ATORGS.ASM(PUP_WAIT1).
	;And "BootBlock_POST" will be executed if checksum is bad.

		FAR_JMP	0f80dh,0f000h

;R108 start
;[]=====================================================[]
;Input  : NONE
;Output : SI = 0 not found otherwise is founded
;[]=====================================================[]
Search_BBSS_label:
		mov	ax,cs
		mov	ds,ax
		mov	es,ax
;R140		mov	ax,0e000h-BBSS_Label_Len	;search start address
ifdef	Flash_16K_8K_8K_Unit						;R140
		mov	ax,0c000h-16  			;start address	;R140
else;	Flash_16K_8K_8K_Unit						;R140
		mov	ax,0e000h-16  			;address;R140
endif;	Flash_16K_8K_8K_Unit						;R140
		cld
Search_BBSS_label_loop:
		mov	si,ax
		lea	di,BBSS_Label
		mov	cx,BBSS_Label_Len
		rep	cmpsb
		jz	short Found_BBSS_label		;If found then going
;R140		dec	ax				;search next address
		sub	ax,16				;R140
		jnz	short Search_BBSS_label_loop
		xor	si,si			;Not found,clear ESI high word
Found_BBSS_label:
		ret
;R108 end

;R88 start
UNlock_Cyrix:
		mov	cl,0C3h
		Call	Get_Cyrix
		or	al,10h
		Call	Set_Cyrix
		ret

Lock_Cyrix:
		mov	cl,0C3h
		Call	Get_Cyrix
		and	al,not 10h
		Call	Set_Cyrix
		ret

Get_Cyrix:
		mov	al,cl
		out	22h,al
		NEWIODELAY
		in	al,23h
		NEWIODELAY
		ret

Set_Cyrix:
		xchg	cl,al		;get index
		out	22h,al
		NEWIODELAY
		xchg	cl,al		;get data
		out	23h,al
		NEWIODELAY
		ret
;R88 end
		ALIGN	4
		public	SND_SPKR	;R186
SND_SPKR	PROC	NEAR
; RETURNS CX 0

		MOV	CX,533H
SND_SPKR_TONE:
		MOV	AL,0B6H
		OUT	CTRL8254,AL
		MOV	AX,CX
		NEWIODELAY
		OUT	DATA8254+2,AL
		MOV	AL,AH
		NEWIODELAY
		OUT	DATA8254+2,AL
		IN	AL,SYS1
		MOV	AH,AL
		OR	AL,3
		NEWIODELAY
		OUT	SYS1,AL
;R144		XOR	CX,CX

@@:					;R144
		mov	cx,5000h	;R144
		ALIGN	4
B_WAIT:
ifndef	LED_FLUSH_IF_NO_MEMORY		;R178
		newiodelay		;R144
		newiodelay		;R144
		newiodelay		;R144
		newiodelay		;R144
endif;	LED_FLUSH_IF_NO_MEMORY		;R178
		LOOP	SHORT B_WAIT


		DEC	BL
;R144		JNZ	SHORT B_WAIT
		jnz	short @B	;R144

		MOV	AL,AH
		OUT	SYS1,AL
		RET
SND_SPKR	ENDP

;R71 - start
CYCPUDEF	STRUC
		db	?	;first CPU device ID
		db	?	;second CPU device ID
		dw	?	;Cyrix CPU type
CYCPUDEF	ENDS

Cyrix_M1_M9_Tbl:
;R86  - starts
IF	BIOS_SUPPORT_586
  		CYCPUDEF <30H,32H,CPU_M1_1>	;CPU_M1_1 1/1
  		CYCPUDEF <31H,33H,CPU_M1_2>	;CPU_M1_2 2/1
  		CYCPUDEF <35H,37H,CPU_M1_3>	;CPU_M1_3 3/1
  		CYCPUDEF <34H,36H,CPU_M1_4>	;CPU_M1_4 4/1
  		CYCPUDEF <21H,23H,CPU_M1_2>	;CPU_M1_2 2/1	;R95
;R133Aifdef	TEMP_M2_SUPPORT					;R133
  		CYCPUDEF <51H,59H,CPU_M1_2>	;CPU_M1_2 2/1	;R133
;R133A 		CYCPUDEF <52H,5AH,CPU_M1_2>	;CPU_M1_2 2.5/1	;R133
  		CYCPUDEF <52H,5AH,CPU_M1_3>	;CPU_M1_3 2.5/1	;R133A
  		CYCPUDEF <53H,5BH,CPU_M1_3>	;CPU_M1_3 3/1	;R133
  		CYCPUDEF <54H,5CH,CPU_M1_4>	;CPU_M1_4 3.5/1	;R133
  		CYCPUDEF <55H,5DH,CPU_M1_4>	;CPU_M1_4 4/1	;R179
;R133Aendif;	TEMP_M2_SUPPORT					;R133
ifdef	CPU_Support_Above_GXM                          		;R168
  		CYCPUDEF <40H,41H,CPU_CYRIX_GXM>;CPU_CYRIX_GXM	;R168
  		CYCPUDEF <42H,43H,CPU_CYRIX_GXM>;CPU_CYRIX_GXM	;R168
  		CYCPUDEF <44H,45H,CPU_CYRIX_GXM>;CPU_CYRIX_GXM	;R168
  		CYCPUDEF <46H,47H,CPU_CYRIX_GXM>;CPU_CYRIX_GXM	;R168
  		CYCPUDEF <71H,71H,CPU_M1_2>	;CPU_CYRIX_MXi	;R176
endif	;CPU_Support_Above_GXM                          	;R168

ENDIF	;BIOS_SUPPORT_586

IF	BIOS_SUPPORT_486
  		CYCPUDEF <2cH,2eH,CPU_M9S_4>	;CPU_M9S_4 4/1	;R91
  		CYCPUDEF <29H,2bH,CPU_M9S_2>	;CPU_M9S_2 2/1
  		CYCPUDEF <2dH,2fH,CPU_M9S_3>	;CPU_M9S_3 3/1
  		CYCPUDEF <12H,12H,CPU_486S>	;M6
  		CYCPUDEF <13H,13H,CPU_486S2>	;M6_2
  		CYCPUDEF <1aH,1aH,CPU_M7S>	;M7
  		CYCPUDEF <1bH,1bH,CPU_M7S2>	;M7_2
  		CYCPUDEF <1fH,1fH,CPU_CYRIX_DX4>
  		CYCPUDEF <81H,81H,CPU_CYRIX_DX4>;TiDX4		;R89
  		CYCPUDEF <45H,47H,CPU_M9S_3>	;GX86 3/1	;R131
  		CYCPUDEF <44H,46H,CPU_M9S_4>	;GX86 4/1	;R131
  		CYCPUDEF <41H,41H,CPU_M9S_4>	;GX86 6/1	;R146
  		CYCPUDEF <40H,40H,CPU_M9S_4>	;GX86 6/1	;R146A
  		CYCPUDEF <42H,43H,CPU_M9S_4>	;MediaGxM	;R146B
ENDIF	;BIOS_SUPPORT_486
		db	0			;end of table
;R86  - ends

;R86 ifndef	P6_BIOS_ONLY						;R80
;R86 ifndef	No_586_Support
;R86   		CYCPUDEF <30H,32H,CPU_M1_1>	;CPU_M1_1 1/1
;R86   		CYCPUDEF <31H,33H,CPU_M1_2>	;CPU_M1_2 2/1
;R86 ;R82  		CYCPUDEF <34H,36H,CPU_M1_3>	;CPU_M1_3 3/1
;R86   		CYCPUDEF <35H,37H,CPU_M1_3>	;R82 CPU_M1_3 3/1
;R86   		CYCPUDEF <34H,36H,CPU_M1_4>	;R82 CPU_M1_4 4/1
;R86 endif;	No_586_Support
;R86 ifndef	CPU_586_ONLY
;R86   		CYCPUDEF <29H,2bH,CPU_M9S_2>	;CPU_M9S_2 2/1
;R86   		CYCPUDEF <2dH,2fH,CPU_M9S_3>	;CPU_M9S_3 3/1
;R86   		CYCPUDEF <12H,12H,CPU_486S>	;M6
;R86   		CYCPUDEF <13H,13H,CPU_486S2>	;M6_2
;R86   		CYCPUDEF <1aH,1aH,CPU_M7S>	;M7
;R86   		CYCPUDEF <1bH,1bH,CPU_M7S2>	;M7_2
;R86   		CYCPUDEF <1fH,1fH,CPU_CYRIX_DX4>	;R75
;R86 endif;	CPU_586_ONLY
;R86 endif;	P6_BIOS_ONLY						;R80
;R86 		db	0			;end of table
;R71 - end

CPU_TYPE_TABLE:
CPUDEF	STRUC
;R11		db	?	;CPU type
		dw	?	;R11 CPU type
		dw	?	;Minmum value of CPU ID
		dw	?	;Maximum value of CPU ID
CPUDEF	ENDS

;R86  - starts
IF	BIOS_SUPPORT_386
  		CPUDEF	<CPU_386DX,PS_386DX_MIN,PS_386DX_MAX>
  		CPUDEF	<CPU_386SX,PS_386SX_MIN,PS_386SX_MAX>
  		CPUDEF	<CPU_386SL,0340H,034FH>
ENDIF	;BIOS_SUPPORT_386

IF	BIOS_SUPPORT_486
  		CPUDEF	<CPU_486S,CX_486S_MIN,CX_486S>
  		CPUDEF	<CPU_486S2,CX_486S2,CX_486S2>

  		CPUDEF	<CPU_486DX,PS_486DX_MIN,PS_486DX_MAX>
  		CPUDEF	<CPU_486SX,PS_486SX_MIN,PS_486SX_MAX>
  		CPUDEF	<CPU_486SX2,PS_486DXP_MIN,PS_486DXP_MAX>
ENDIF	;BIOS_SUPPORT_486

		; this item must always be last in table
  		CPUDEF	<CPU_UNKNOWN,PS_UNKNOWN_MIN,PS_UNKNOWN_MAX>

IF	BIOS_SUPPORT_IBM_CPU
IBM_CPU_TYPE_TABLE:
  		CPUDEF	<CPU_IBM386SLC,0A301h,0A301h>
  		CPUDEF	<CPU_IBM486SLC2,0A421h,0A422h>
  		CPUDEF	<CPU_IBM486DLC3,08438h,0843Fh>
  		CPUDEF	<CPU_UNKNOWN,PS_UNKNOWN_MIN,PS_UNKNOWN_MAX>
ENDIF	;BIOS_SUPPORT_IBM_CPU
;R86  - ends

;R86  ifdef	P6_BIOS_ONLY						;R80
;R86  ;R85  		CPUDEF	<CPU_P6,0600H,06FFH>			;R80
;R86  else;	P6_BIOS_ONLY						;R80
;R86
;R86  ifndef	No_586_Support							;R63
;R86  ;R85		CPUDEF	<CPU_P55CT,1640H,164FH>				;R81
;R86  ;R85  		CPUDEF	<CPU_586,1520H,152FH>				;R61
;R86  ;R85  		CPUDEF	<CPU_586,1540H,154FH>				;R60
;R86  ;R85  		CPUDEF	<CPU_586,PS_586_MIN,PS_586_MAX>			;R09
;R86  endif	;No_586_Support							;R63
;R86
;R86  ifndef	CPU_586_ONLY							;R55
;R86  ;R85  		CPUDEF	<CPU_P24C,1480h,148Fh>				;R27A
;R86  ;R85  		CPUDEF	<CPU_P24C,0480h,048Fh>				;R27
;R86  ;R27  		CPUDEF	<CPU_M7S,0480h,0480h>				;R24
;R86  ;R71  		CPUDEF	<CPU_M7S,0490h,0490h>				;R16
;R86  ;R71  		CPUDEF	<CPU_M9S_2,0020h,002Fh>				;R70
;R86  ;R23  		CPUDEF	<CPU_486DX2S,PS_486DX2S_MIN,PS_486DX2S_MAX>	;R10
;R86  ;R23  		CPUDEF	<CPU_486SXS,PS_486SXS_MIN,PS_486SXS_MAX>	;R10
;R86  ;R23		CPUDEF	<CPU_486SXS,042Ah,042Ah>			;R22
;R86  ;R23  		CPUDEF	<CPU_486DXS,PS_486DXS_MIN,PS_486DXS_MAX>	;R10
;R86  ;R23  		CPUDEF	<CPU_486DXS,0460h,0460h>			;R21
;R86  ;R85  		CPUDEF	<CPU_586,PS_586_MIN,PS_586_MAX>			;R09
;R86
;R86  ifndef	No_386_Support							;R63
;R86    		CPUDEF	<CPU_386DX,PS_386DX_MIN,PS_386DX_MAX>
;R86    		CPUDEF	<CPU_386SX,PS_386SX_MIN,PS_386SX_MAX>
;R86  ;R20  		CPUDEF	<CPU_386SL,PS_386SL_MIN,PS_386SL_MAX>
;R86    		CPUDEF	<CPU_386SL,0340H,034FH>				;R20
;R86  endif	;No_386_Support							;R63
;R86
;R86  ;R11  		CPUDEF	<CPU_IBM386SLC,0A301h,0A301h>
;R86  ;R11  		CPUDEF	<CPU_IBM486SLC2,0A421h,0A421h>
;R86
;R86  ;R13  		CPUDEF	<CPU_486S,CX_486S,CX_486S>			;R07
;R86  ;R71  		CPUDEF	<CPU_486S,CX_486S_MIN,CX_486S>			;R13	;R07
;R86  ;R71  		CPUDEF	<CPU_486S2,CX_486S2,CX_486S2>			;R07
;R86
;R86    		CPUDEF	<CPU_486S,CX_486S_MIN,CX_486S>			;R79
;R86    		CPUDEF	<CPU_486S2,CX_486S2,CX_486S2>			;R79
;R86
;R86    		CPUDEF	<CPU_486DX,PS_486DX_MIN,PS_486DX_MAX>
;R86    		CPUDEF	<CPU_486SX,PS_486SX_MIN,PS_486SX_MAX>
;R86    		CPUDEF	<CPU_486SX2,PS_486DXP_MIN,PS_486DXP_MAX>
;R86  ;R85  		CPUDEF	<CPU_P24T,PS_P24T_MIN,PS_P24T_MAX>		;R01
;R86  endif;	CPU_586_ONLY							;R55
;R86  endif;	P6_BIOS_ONLY						;R80
;R86
;R86  ;R71 ;R54 - start
;R86  ;R71 ifdef	CYRIX_M1_SUPPORT
;R86  ;R71   		CPUDEF	<CPU_M1_1,3000H,30FFH>	;clock mode 1/1 , PLL
;R86  ;R71   		CPUDEF	<CPU_M1_1,3200H,32FFH>	;clock mode 1/1 , static
;R86  ;R71   		CPUDEF	<CPU_M1_2,3100H,31FFH>	;clock mode 2/1 , PLL
;R86  ;R71   		CPUDEF	<CPU_M1_2,3300H,33FFH>	;clock mode 2/1 , static
;R86  ;R71   		CPUDEF	<CPU_M1_3,3400H,34FFH>	;clock mode 3/1 , PLL
;R86  ;R71 ;;;;  		CPUDEF	<CPU_M1_4,3500H,35FFH>	;clock mode 4/1 , PLL
;R86  ;R71 endif;	CYRIX_M1_SUPPORT
;R86  ;R71 ;R54 - end
;R86
;R86  		; this item must always be last in table
;R86    		CPUDEF	<CPU_UNKNOWN,PS_UNKNOWN_MIN,PS_UNKNOWN_MAX>
;R86  ifdef	IBM_CPU_SUPPORT							;R34
;R86  IBM_CPU_TYPE_TABLE:							;R11
;R86    		CPUDEF	<CPU_IBM386SLC,0A301h,0A301h>			;R11
;R86  ;R15  		CPUDEF	<CPU_IBM486SLC2,0A421h,0A421h>			;R11
;R86    		CPUDEF	<CPU_IBM486SLC2,0A421h,0A422h>	;R15
;R86  ;R58  		CPUDEF	<CPU_IBM486DLC3,08438h,08439h>			;R11
;R86    		CPUDEF	<CPU_IBM486DLC3,08438h,0843Fh>			;R58
;R86    		CPUDEF	<CPU_UNKNOWN,PS_UNKNOWN_MIN,PS_UNKNOWN_MAX>	;R11
;R86  endif;	IBM_CPU_SUPPORT							;R34

;=============================================================================
;FUNC:	CPU_DETECT
;
;DESC:	Handles the detection of the type of CPU based on two factors:
;
;	  (1) the power-up CPU description and
;	  (2) whether a math coprocessor is installed.
;
;	Since a math coprocessor cannot be detected without RAM, the second
;	part of this test (AL = 1) cannot be completed until RAM is
;	initialized.
;
;IN:	AL	00 = Early detect (DX = power-up CPU id)
;		01 = Late detect (detect NCP extensions)
;OUT:	NONE
;
;SAVES:	NONE + NO STACK
;
;BY:	T. Lewis
;DATE:	3 September 1991
;=============================================================================
		PUBLIC	CPU_DETECT
CPU_DETECT	PROC	NEAR

;=============================================================================
;
; Using either the power-up CPU description or a hard-code value, determine
; the CPU type and put it in CMOS where it can be used later.
;
;=============================================================================

		mov	es,sp

;R49 - start
ifdef	SPECIAL_FOR_POWERON
		extrn	Ct_For_PowerOn:near
		rom_call	Ct_For_PowerOn
endif;	SPECIAL_FOR_POWERON
;R49 - end

;R19 - start
ifdef	PCI_BUS
		xchg	si,dx			;save DX
		extrn	Pci_Early_Init:near
		rom_call	Pci_Early_Init
		xchg	si,dx			;save DX
endif;	PCI_BUS
;R19 - end

;R104 - start
ifdef	SLOW_RTC_PATCH
;Some RTCs not ready at this moment , so check the CMOS byte for storeing
;CPU type is ok or not. If not, system stop , until ok.

		xchg	si,dx			;save DX	;R104D
		POST_CODE	0CFH		;check CMOS
		xchg	si,dx			;save DX	;R104D

ifdef	SLOW_RTC_PATCH_Delay			;R104C
		mov	cx,05000H		;R104B
	@@:					;R104B
		NEWIODELAY			;R104B
		loop	short @B		;R104B
endif;	SLOW_RTC_PATCH_Delay			;R104C

Loop_Cmos:
		mov	al,CMOS_AWARD_2 NMI_OFF	; al = CMOS location
		mov	ah,al
		out	CMOS,al
		NEWIODELAY
;R104A		xor	al,al
		mov	al,55h			;R104A
		out	CMOS+1,al

		xchg	ah,al
		out	CMOS,al
		NEWIODELAY
		in	al,CMOS+1
;R104A		or	al,al			;value correct
		cmp	al,55h			;R104A
		jnz	short Loop_Cmos
;R104A start
		mov	al,CMOS_AWARD_2 NMI_OFF	; al = CMOS location
		out	CMOS,al
		NEWIODELAY
		xor	al,al
		out	CMOS+1,al
;R104A end
endif;	SLOW_RTC_PATCH
;R104 - end

;R30 - start
;Set CPU cache to write through mode
;R30A		mov	eax,cr0
;R30A		and	eax,NOT CR0_NW
;R30A		mov	cr0,eax
;R30 - end

		mov	al,CMOS_AWARD_2	NMI_OFF	; al = CMOS loc
;R11		mov	ah,NOT_CPU_TYPE_MASK	; ah = mask
		xor	ah,ah			;R11
		rom_call	ROM_AND_CMOS		; turn off ID bits

		mov	al,OVERRIDE NMI_OFF			;R11
;R50A		mov	ah,NOT CLOCK_MODE			;R11
;R57A		mov	ah,NOT (CLOCK_MODE +(SMICPU SHR 8))		;R50A
		mov	ah,NOT (CLOCK_MODE+((SMICPU+WBCPU) SHR 8))	;R57A
		rom_call	ROM_AND_CMOS				;R11

;R71 - start
;First Check if cyrix CPU plugged or not
		xchg	dx,bp			;save DX

		xor	ax,ax
		sahf
		mov	ax,5
		mov	bx,2
		div	bl
		lahf
		cmp	ah,2			;=2 for CYRIX CPU ?
		jne	short Not_Cy_CpuS	;yes cyrix CPUs

		mov	al,0feh			;DIR 0
		out	22h,al
		in	al,23H			;read CPU device ID
;R71A		mov	si,offset Cyrix_M1_M9_Tbl

		or	al,al			;R79
		jz	short Not_Cy_CpuS	;R79

		mov	si,offset DGROUP:Cyrix_M1_M9_Tbl	;R71A

Check_Next_Cy:
		cmp	byte ptr cs:[si],0   	;last CPU ?
		je	short Not_Cy_CpuS

		cmp	cs:[si],al		;first ID match ?
		je	short Yes_Cy_Cpus
		cmp	cs:[si+1],al		;first ID match ?
		je	short Yes_Cy_Cpus

		add	si,4			;next CPU type
		jmp	short Check_Next_Cy

Yes_Cy_Cpus:
		mov	bx,cs:[si+2]		;get CPU type

;R106 - start
ifdef	 DELAY_FOR_6X86_PWRON
;Delay for a while if M1 CPU plugged , otherwise some chipset
;hang after memory sizing
		mov	al,bl			;CPU type
		and	al,CPU_TYPE_MASK	;
		cmp	al,TYPE_M1		;6x86 CPU ?
		jne	short Not_M1Cpu		;no, skip it

		xor	cx,cx
Wait_6x86:							   ;R106A
		NEWIODELAY					   ;R106A
		loop	short Wait_6x86	      	;delay for a while ;R106A
;R106A		loop	short $			;delay for a while
Not_M1Cpu:
endif;	DELAY_FOR_6X86_PWRON
;R106 - end

		xchg	dx,bp			;restore DX
 		jmp	Set_Cpu_Type
Not_Cy_CpuS:

		xchg	dx,bp			;restore DX

;R71 - end

;Translate CPU dx value to our CPU type definition
		mov	si,offset DGROUP:CPU_TYPE_TABLE; cs:si = table
;R86ifdef	IBM_CPU_SUPPORT							;R34
IF	BIOS_SUPPORT_IBM_CPU						;R86
		test	dx,1000000000000000b		;R11 IBM CPU ?
		jz	short ctd_1			;R11
		mov	si,offset DGROUP:IBM_CPU_TYPE_TABLE	;R11
ENDIF	;BIOS_SUPPORT_IBM_CPU						;R86
;R86endif;	IBM_CPU_SUPPORT							;R34
ctd_1:
;R11		mov	al,cs:[si]
;R11		cmp	dx,cs:[si+1]		; too low?
		mov	ax,cs:[si]		;R11
		cmp	dx,cs:[si+2]		;R11
		jb	short ctd_11		; yes...

;R11		cmp	dx,cs:[si+3]		; too high?
		cmp	dx,cs:[si+4]		;R11
		jbe	short ctd_12		; no...
ctd_11:
;R11		add	si,5			; next entry
		add	si,6			; R11
		jmp	short ctd_1		; go back

ctd_12:
;R11		mov	ah,al			; ah = CPU type
		mov	bx,ax			; R11 bx = CPU type

ctd_9:
;R71 ;R70 - start
;R71 	;DL = 28h or 2Ah  (1/1)
;R71 	;     29h or 2Bh  (2/1)
;R71 	;     2Dh or 2Fh  (3/1)
;R71 	;     2Ch or 2Eh  (4/1)
;R71 	;Now, we only support 2X & 3X mode for M1sc (03/15/95)
;R71
;R71 		cmp	bx,CPU_M9S_2
;R71 		jne	short Not_M9
;R71
;R71 		and	dl,11111101b
;R71 		cmp	dl,29h			;2 clock mode ?
;R71 		je	short Not_M9		;Yes
;R71
;R71 		mov	bx,CPU_M9S_3
;R71 Not_M9:
;R71 ;R70 - end
Set_Cpu_Type:					;R71

;R86 ifndef	CPU_586_ONLY							;R55
IF	BIOS_SUPPORT_486		;R86
;R33A - start
		xor	eax,eax
		db	064h,0d6h		;U5 unique instruction
		cmp	eax,0ab6b1b07h		;U5?
		jne	short Not_U5		;no, it isn't U5
						;yes, its U5
		mov	bx,CPU_U5		;set U5 ID in CMOS
Not_U5:						;no, it isn't U5
;R33A - end
ENDIF	;BIOS_SUPPORT_486		;R86
;R86 endif;	CPU_586_ONLY							;R55

		mov	ah,bl			;R11
		mov	al,CMOS_AWARD_2 NMI_OFF	; al = CMOS location
		rom_call	ROM_OR_CMOS

		mov	ah,bh			;R11
		mov	al,CMOS_OVERRIDE NMI_OFF;R11
		rom_call	ROM_OR_CMOS		;R11

;R59 - start
IF	BIOS_SUPPORT_486			;R86
ifdef	U5_Non_Cache
		cmp	bx,CPU_U5
		jne	short @F

		;turn off 486 CPU internal cache
		mov eax,cr0
		or  eax,CR0_CD+CR0_NW
		mov cr0,eax
		WBINVD
@@:
endif	;U5_Non_Cache
ENDIF	;BIOS_SUPPORT_486			;R86
;R59 - end

;R63A ifdef	;No_586_Support		      				;R63
ifndef	No_586_Support							;R63A
;R52 - start
;R85		cmp	bx,CPU_586		;PENTIUM CPU ?
;R85		jne	short @F
;R85
;R85;R52A - start
;R85;Disable PENTIUM parity check in TR1 register
;R85                mov     eax,2
;R85                mov     ecx,eax
;R85                xor     edx,edx
;R85                WRMSR
;R85;R52A - end
;R85
;R85		;disable auto-halt mode by set bit 6 of TR12
;R85		mov	ecx,0eh
;R85		RDMSR
;R85		xor	edx,edx
;R85		mov	eax,40h
;R85		WRMSR
;R85@@:
;R52 - end
endif	;No_586_Support							;R63

		mov	sp,es
		ret

CPU_DETECT	ENDP

;R120 - start
;Descriptor table for protected access
		public	A_GDTR			;R186
A_GDTR:
		dw	8*3			; LIMIT
		dw	offset DGROUP:B_GDT1
		dw	0fh			; in 0F000h segment
;R120 - end

;R116 start
		public	B_GDTR1			;R186
B_GDTR1:					; global descriptor table register
		dw	8*3			; LIMIT
		dw	offset DGROUP:B_GDT1
		dw	02h			; in 0F000h segment

B_GDT1:						; null descriptor
		dw	0			; limit
		dw	0			; base
		db	0			; hibase
		db	0			; access
		db	0			; hilimit
		db	0			; msbase

B_DATA1_DT:					; ds - first 64k segment
		public	B_DATA1_INDEX		;R186
B_DATA1_INDEX	=	((OFFSET B_DATA1_DT - OFFSET B_GDT1)/8) SHL 3
		dw	0ffffh			; limit
		dw	0			; base data segment points to
		db	0			; hibase	; 00000000
		db	93h			; access
		db	08fh			; hilimit (4GB)
		db	0			; msbase
;R116 end
Expand_Bios	Proc	Near
;R116 start
ifdef	Flash_2M_support
;R123
;R123		call	Enable_KB_Controller		;R118
;R123
;R123Temp_Extra_BIOS_Addres	EQU	8000h
;R123		push	2000h
;R123		call	Enable_Extra_1MBIOS_Hook
;R123		mov	esi,0
;R123		jnz	short @F	;real mode address
;R123		mov	esi,0fff00000h	;protect mode high address
;R123@@:
;R123		movzx	ecx,cx
;R123		shl	ecx,4
;R123		or	esi,ecx
;R123		cld
;R123;---------------- Enter Protect Mode ----------------
;R123                mov     ax,cs
;R123                mov     ds,ax
;R123                assume  ds:dgroup
;R123
;R123                lgdt    fword ptr B_GDTR1
;R123
;R123                mov     eax,cr0
;R123                or      al,1
;R123                mov     cr0,eax
;R123
;R123		jmp	short $+2		;clear prefetch
;R123
;R123                mov     ax,B_DATA1_INDEX
;R123                mov     ds,ax                   ; ds = 00000000h
;R123		mov	es,ax
;R123
;R123		mov	edi,(Temp_Extra_BIOS_Addres shl 4)
;R123		mov	ecx,8000h
;R123		db	67h
;R123		rep	movsd
;R123
;R123;---------------- Leave Protect Mode ----------------
;R123                mov     eax,cr0
;R123                and     al, NOT 1
;R123                mov     cr0,eax
;R123		jmp	short $+2
;R123		push	2000h
;R123		call	Disable_Extra_1MBIOS_Hook
;R129		call	Extern_execute1		;R123
;R129A ifndef	Bootblock_16K_Support			;R129
ifdef	Bootblock_16K_Support			;R129A
		extrn	Extern_execute1:near	;R186
		call	Extern_execute1		;R129A
else;	Bootblock_16K_Support			;R129A
COMPILE_FOR_BOOTROM_ASM	=	1		;R129
		include	BOOTROM.INC		;R129
endif;	Bootblock_16K_Support			;R129
endif	;Flash_2M_support
;R116 end


;R180 start
ifndef	NO_WHOLE_BIOS_IMAGE_CHECKSUM		;R180B
		xor	ah,ah
		xor	cx,cx			;R180A
ifdef	Flash_2M_support
		mov	bx,8000h		;first extern block of 2MB bios
		mov	ds,bx
		xor	si,si			;offset start = 0
@@:
		lodsb
		add	ah,al			;sum up checksum
		loop	short @B
		mov	bx,ds
		cmp	bh,90h			;last extern block of 2MB bios?
		jae	short @F		;Yes,skip
		add	bh,10h			;second extern block of 2MB bios
		mov	ds,bx
		jmp	short @B
@@:
endif	;Flash_2M_support
		mov	bx,1000h		;first block of 2MB bios
		mov	ds,bx
		xor	si,si			;offset start = 0
		cld
@@:
		lodsb
		add	ah,al			;sum up checksum
		loop	short @B
		cmp	bh,20h			;last block of 2MB bios?
		jae	short @F		;Yes,skip
		add	bh,10h			;second block of 2MB bios
		mov	ds,bx
		mov	cx,(Decompress_Code_Seg and 0f000h)+0ffeh	;last count
		jmp	short @B
@@:
		cmp	ah,[si]			;compare checksum byte
		jne	BIOS_cksm_error		;not equte then skip
endif;	NO_WHOLE_BIOS_IMAGE_CHECKSUM		;R180B
;R180 end

;R102 start
;----- Clear Expand pool data
		mov	bx,Temp_VGA_Seg
		mov	es,bx
		mov	word ptr es:[Temp_VGA_Off+4],0ffffh
;--------------------------------
;R102 end
		xor	al,al		;clear expand flag

		mov	bx,1000h
		mov	es,bx
		xor	bx,bx
;R102		call	Expand
		call	BootBlock_Expand	;R102
;R84 start
		jc	short @F
		test	ecx,0ffff0000h
		jz	short @F
		mov	bx,2000h
		mov	es,bx
		mov	bx,1		;checksum byte
		jmp	short Expand_else
@@:
;R84 end
		rcl	al,1
		mov	bx,2000h
		mov	es,bx
		xor	bx,bx
;R102		call	Expand
		call	BootBlock_Expand	;R102
		rcl	al,1
		cmp	al,3		;have any compressed bios?
		jne	short @F	;Yes,jump
		mov	ax,1000h	;return bios location segment
		stc			;No Base bios
		ret
@@:
		or	al,al			;Have any else bios?
;R182 start
ifdef	Flash_2M_support
		jnz	short Expand_else_Over
else	;Flash_2M_support
;R182 end
		jnz	short Expand_exit	;No,jump
endif	;Flash_2M_support			;R182
;-------------- Expand else Rom Driver ----------------
Expand_else:
		add	bx,cx
;R102		call	Expand

call	BootBlock_Expand	;R102
;R166		jnc	short Expand_else
		jc	short Expand_else_Over	;R166
		test	ecx,0ffff0000h		;R166
		jz	short Expand_else	;R166
Expand_else_Over:				;R166
;R116 start
ifdef	Flash_2M_support
;R123;----- decompress first extra BIOS area (0C000h) -----
;R123		mov	bx,Temp_Extra_BIOS_Addres
;R123		mov	es,bx
;R123		xor	bx,bx
;R123		xor	cx,cx
;R123Expand_ROM_loop:
;R123		add	bx,cx
;R123		call	BootBlock_Expand
;R123		jnc	short Expand_ROM_loop
;R123
;R123;----- decompress secondary extra BIOS area (0D000h) -----
;R123		mov	bx,es
;R123		add	bx,1000h
;R123		mov	es,bx
;R123		xor	bx,bx
;R123		xor	cx,cx
;R123Expand_ROM_loop1:
;R123		add	bx,cx
;R123		call	BootBlock_Expand
;R123		jnc	short Expand_ROM_loop1
;R129		call	short Extern_execute2	;R123
;R129A ifndef	Bootblock_16K_Support			;R129
ifdef	Bootblock_16K_Support			;R129A
		extrn	Extern_execute2:near	;R186
		call	short Extern_execute2	;R129A
else;	Bootblock_16K_Support			;R129A
COMPILE_FOR_BOOTROM_ASM	=	2		;R129
		include	BOOTROM.INC		;R129
endif;	Bootblock_16K_Support			;R129
		jz	BIOS_cksm_error		;R167
endif	;Flash_2M_support
;R116 end
;------------------------------------------------------
Expand_exit:
		mov	ax,5000h	;return bios location segment
		clc
		ret
Expand_Bios	Endp

;R108A;[]==============================================================[]
;R108A;
;R108A; Expand:
;R108A;
;R108A;Saves:	NONE
;R108A;
;R108A;Entry:	ES : SEGMENT of Source Data
;R108A;	BX : OFFSET of Source Data
;R108A;	DX : Segment of Expand Data buffer		;R102C
;R108A;
;R108A;Exit:	NONE
;R108A;
;R108A;Author: Award
;R108A;Date:   11/16/94
;R108A;
;R108A;[]==============================================================[]
		ASSUME	CS:DGROUP,DS:EXP_DATA
;R108A;R102 Expand		proc	near
;R108A;R102A Expand		proc	far		;R102
;R108AExpand		proc	near			;R102A
;R108A		push	ax
;R108A		push	bx
;R108A
;R108A		push	es		; save source segment
;R108A
;R108A; Init data segment registers
;R108A
;R108A;R108ifdef FULL_SCREEN_LOGO				;R102C
;R108A		mov     ds,dx			;R102C
;R108A;R108else ;FULL_SCREEN_LOGO				;R102C
;R108A;R108		mov     ax,exp_data		; point DS to data segment
;R108A;R108		mov     ds,ax
;R108A;R108endif ;FULL_SCREEN_LOGO				;R102C
;R108A
;R108A; Initialize EXP_DATA segment, in case there's garbage left
;R108A
;R108A		push	ds
;R108A		pop	es
;R108A		xor	di,di
;R108A		mov	cx,4000h
;R108A		xor	ax,ax
;R108A		repz	stosw
;R108A
;R108A; Read compressed data from segment:offset
;R108A
;R108A		pop	es
;R108A		push	es				;R67
;R108A
;R108A		mov	word ptr SrcSegment, es
;R108A		mov	word ptr SrcOffset,bx
;R108A
;R108A; Temp Target Segment, Offset
;R108A
;R108A;R102A start
;R108A;R108ifndef FULL_SCREEN_LOGO				;R102C
;R108A;R108		mov	word ptr TgtSegment,TGT_SEGMENT
;R108A;R108		mov	word ptr TgtOffset,0
;R108A;R108endif ;FULL_SCREEN_LOGO				;R102C
;R108A;R102A end
;R108A
;R108A; make CRC table
;R108A
;R108A		call	MakeCRCTable
;R108A
;R108A; read header
;R108A
;R108A		call	ReadHeader
;R108A		jc      short @F        ; error, something wrong
;R108A
;R108A;R102 start
;R108A;R108ifdef FULL_SCREEN_LOGO				;R102C
;R108A		mov	ax,ExpSegment		;R102C
;R108A		mov	TgtSegment,ax		;R102C
;R108A		mov	ax,ExpOffset		;R102C
;R108A		mov	TgtOffset,ax		;R102C
;R108A;R108endif ;FULL_SCREEN_LOGO				;R102C
;R108A;R102 end
;R108A;-- calculate compressed total size and return when decompress complete
;R108A		mov	ecx,compsize		;compressed size
;R108A		xor	eax,eax
;R108A		mov	al,headersize		;compressed header size
;R108A		add	ecx,eax
;R108A		add	ecx,COMPRESSED_UNKNOW_BYTE	;unknow bytes
;R108A		push	ecx
;R108A
;R108A		push	word ptr TgtSegment
;R108A		push	word ptr TgtOffset
;R108A		push	dword ptr origsize
;R108A
;R108A; extract content from compressed file
;R108A
;R108A;R108		call	Extract
;R108A;R108 start
;R108A		push	ds			;R108
;R108A		push	es			;R108
;R108A		call	Search_BBSS_label	;R108
;R108A		pop	es			;R108
;R108A		pop	ds			;R108
;R108A;R108		shr	esi,16			;Restore BBSS sign offset
;R108A		mov	ax,cs:[si+Extract_Off]	;Get extract routine offset
;R108A		shl	esi,16			;store it again for next call extract
;R108A		call	ax			;call to extract
;R108A;R108 end
;R108A
;R108A		pop	dword ptr origsize
;R108A		pop	word ptr TgtOffset
;R108A		pop	word ptr TgtSegment
;R108A
;R108A;R102A start
;R108A;R108ifndef FULL_SCREEN_LOGO				;R102C
;R108A;R108;
;R108A;R108; Enable the shadow area we want to expand our data to,
;R108A;R108; copy data from temp buffer to this area according to 'origsize'
;R108A;R108; shadow this area then write protect this area.
;R108A;R108; EAX : Original (Uncompressed) file size
;R108A;R108; ES : Segment of Expansion area
;R108A;R108; DI : starting offset of Expansion area
;R108A;R108; DS : Segment of target buffer area
;R108A;R108; SI : starting offset of target buffer area
;R108A;R108; NOTE !!! : This could be a cross-segment far call
;R108A;R108;
;R108A;R108
;R108A;R108		push	ds
;R108A;R108
;R108A;R108		mov	eax,dword ptr origsize
;R108A;R108
;R108A;R108		mov	si,word ptr ExpSegment
;R108A;R108		mov	es,si
;R108A;R108		mov	di,word ptr ExpOffset
;R108A;R108		mov	si,word ptr TgtOffset
;R108A;R108		mov	cx,word ptr TgtSegment
;R108A;R108		mov	ds,cx	; NOTE! DS is not pointing to data segment
;R108A;R108
;R108A;R108		call	Expand_To_RAM		; could be a far call
;R108A;R108
;R108A;R108		pop	ds
;R108A;R108endif ;FULL_SCREEN_LOGO				;R102C
;R108A;R108;R102A end
;R108A
;R108A; clean up temp target buffer, so that no garbage left in user's base memory
;R108A; if data decompression stub is called before memory testing, then
;R108A; we don't need to call this cleanup routine.
;R108A
;R108A;R108		call	CleanUpBaseMemory
;R108A;R108 start
;R108A		shr	esi,16			;Restore BBSS sign offset
;R108A		mov	ax,cs:[si+CleanUpBaseMemory_Off]	;Get extract routine offset
;R108A		shl	esi,16			;store it again for next call extract
;R108A		call	ax			;call to extract
;R108A;R108 end
;R108A		pop	ecx		;return compressed total size
;R108A
;R108A; done, exit.
;R108A
;R108A		clc
;R108A@@:
;R108A		pop	es			;R67
;R108A		pop	bx
;R108A		pop	ax
;R108A		ret
;R108A
;R108Aexpand	endp

;R102 start
		public	BootBlock_Expand	;R186
BootBlock_Expand:
	cmp	dword ptr es:[bx+0fh],40000000h		;is vga logo pattern
	jne	short @F				;No,skip
	mov	si,Temp_VGA_Seg
	mov	ds,si
	mov	ds:[Temp_VGA_Off],bx
	mov	si,es
	mov	ds:[Temp_VGA_Off+2],si
	lea	si,Expand
	mov	ds:[Temp_VGA_Off+4],si
;R121 start
;R166	xor	ch,ch
;R166	mov	cl,es:[bx]
;R166	add	cx,es:[bx+7]
;R166	add	cx,COMPRESSED_UNKNOW_BYTE
	movzx	ecx,byte ptr es:[bx]		;R166
	add	ecx,es:[bx+7]			;R166
	add	ecx,COMPRESSED_UNKNOW_BYTE	;R166
;R121 end
	ret
@@:
;R102A	push	cs
;R108ifdef FULL_SCREEN_LOGO				;R102C
	mov	dx,Exp_Data_Seg			;R102C
;R108endif ;FULL_SCREEN_LOGO				;R102C
;R108A	call	near ptr Expand
;R108A start
		push	ax			;R108B
		push	es
		call	Search_BBSS_label
		pop	es
		push	es			;R171
		mov	ax,es			;R171
		shr	ax,12			;R171
		mov	es,ax			;R171
		mov	ax,cs:[si+Expand_Off]	;Get extract routine offset
		call	ax			;call to extract
		pop	es			;R171
		pop	ax			;R108B
;R108A end
	ret
;R102 end

;R108DMakeCRCTable	proc	near
;R108D;
;R108D; Input : None
;R108D; Destroy : None
;R108D; Modify Global Variable : CRCTABLE[]
;R108D;
;R108D
;R108D		push    cx
;R108D		push    bx
;R108D		push    ax
;R108D		push    si
;R108D
;R108D		mov     si,offset crctable
;R108D		mov     cx,100h         ; for (i = 0; i <= 0xff; i++)
;R108DMCRCT_1:
;R108D		mov     ax,100h
;R108D		sub     ax,cx           ; r = i;
;R108D		push    ax              ; save index
;R108D
;R108DMCRCT_2:
;R108D		mov     bx,0            ; for (j = 0; j < 8; j++)
;R108DMCRCT_2_1:
;R108D		test    ax,1            ; (r & 1)
;R108D		jz      short MCRCT_3
;R108D
;R108D		shr     ax,1
;R108D		xor     ax,CRCPOLY
;R108D		jmp     short MCRCT_4
;R108DMCRCT_3:
;R108D		shr     ax,1
;R108DMCRCT_4:
;R108D		inc     bx
;R108D		cmp     bx,8
;R108D		jb      short MCRCT_2_1
;R108D
;R108D		pop     bx	; pop out saved index to !!! REG BX !!! so that
;R108D				; we won't destroy AX
;R108D
;R108D		mov     word ptr [si+bx],ax
;R108D		inc	si	; since this is an array of word, we increase bx
;R108D				; and si respectively so that totaly make up a 2
;R108D				; bytes increment.
;R108D
;R108D		loop    short MCRCT_1
;R108D
;R108D		pop     si
;R108D		pop     ax
;R108D		pop     bx
;R108D		pop     cx
;R108D
;R108D		ret
;R108D
;R108DMakeCRCTable	endp
;R108D
;R108DFreadCRC	proc	near
;R108D;
;R108D; Globally parameters passing : Header, Headersize, InpFileHandle
;R108D; Modify global variable: origsize
;R108D;
;R108D
;R108D		push	ax
;R108D		push	bx
;R108D		push	cx
;R108D		push	dx
;R108D
;R108D		movzx   cx,byte ptr Headersize
;R108D
;R108D		push	es
;R108D		push	si
;R108D		mov	ax,word ptr SrcSegment
;R108D		mov	es,ax
;R108D		mov	bx,word ptr SrcOffset
;R108D		mov	si,offset Header
;R108DFCRC_0:
;R108D		movzx	ax,byte ptr es:[bx]
;R108D		mov	byte ptr ds:[si],al
;R108D		inc	bx
;R108D		inc	si
;R108D		loop	short FCRC_0
;R108D
;R108D		mov	ax,bx
;R108D		sub	ax,word ptr ds:SrcOffset	; how many bytes we have read ?
;R108D		mov	word ptr ds:SrcOffset,bx
;R108D		pop	si
;R108D		pop	es
;R108D
;R108D		mov     byte ptr Headersize,al
;R108D		mov     cx,ax           		; save a copy
;R108D		add     word ptr origsize,ax
;R108D		inc     cx
;R108D		mov     bx,offset Header
;R108DFCRC_1:
;R108D		movzx	ax,byte ptr [bx]
;R108D		dec     cx
;R108D		jcxz    short FCRC_2
;R108D
;R108D		UpdateCRC
;R108D
;R108D		inc     bx				; increment pointer
;R108D		jmp     short FCRC_1
;R108DFCRC_2:
;R108D
;R108D		pop	dx
;R108D		pop	cx
;R108D		pop	bx
;R108D		pop	ax
;R108D
;R108D		ret
;R108D
;R108DFreadCRC	endp
;R108D
;R108DCalcHeadersum	proc	near
;R108D;
;R108D; Input : None
;R108D; Output : AX
;R108D; Destroy : AX
;R108D; Global variable : None
;R108D;
;R108D		push	bx
;R108D		push	cx
;R108D		push	dx
;R108D
;R108D		mov	ax,0	; clear sum
;R108D		movzx	cx,byte ptr headersize
;R108DCH_1:
;R108D		movzx	bx,byte ptr headersize
;R108D		sub	bx,cx
;R108D		movzx	dx,byte ptr header[bx]
;R108D		add	ax,dx
;R108D		loop	short CH_1
;R108D
;R108D		pop	dx
;R108D		pop	cx
;R108D		pop	bx
;R108D
;R108D		and	ax,0ffh
;R108D
;R108D		ret
;R108D
;R108DCalcHeadersum	endp
;R108D
;R108DGetFromHeader	proc	near
;R108D;
;R108D; Input	  : BX -- from
;R108D;	    CX -- count
;R108D; Output  : EAX
;R108D; Destroy : EAX
;R108D;
;R108D
;R108D		push	bx
;R108D		push	edx
;R108D		push	si
;R108D
;R108D		xor	eax,eax	; prepare unsigned long variable output
;R108D
;R108D		dec	bx
;R108D		inc	cx
;R108D
;R108DGFH_1:
;R108D
;R108D		dec	cx
;R108D		jcxz	short GFH_2
;R108D
;R108D		shl	eax,8
;R108D		mov	si,bx
;R108D		add	si,cx
;R108D		movzx	edx,byte ptr header[si]
;R108D		add	eax,edx		; little endian
;R108D		jmp	short GFH_1
;R108D
;R108DGFH_2:
;R108D
;R108D		pop	si
;R108D		pop	edx
;R108D		pop	bx
;R108D
;R108D		ret
;R108D
;R108DGetFromHeader	endp
;R108D
;R108D
;R108DReadHeader	proc	near
;R108D;
;R108D; Input : None
;R108D; Output : Carry Set - several reason might cause the carry flag be set
;R108D;			1. header size is 0
;R108D;			2. header check sum is not correct
;R108D;			3. data pattern does not match in some specific
;R108D;			   location.
;R108D;        : Carry clear - header size is not 0
;R108D;
;R108D
;R108D
;R108D		pusha
;R108D
;R108D; read in headersize byte
;R108D
;R108D
;R108D		push	es
;R108D		mov	ax,word ptr SrcSegment
;R108D		mov	es,ax
;R108D		mov	bx,ds:SrcOffset
;R108D		movzx	ax,byte ptr es:[bx]
;R108D		inc	word ptr ds:SrcOffset
;R108D		mov	byte ptr headersize,al
;R108D		pop	es
;R108D
;R108D		cmp     byte ptr headersize,0
;R108D		jne     short   RH_2
;R108D
;R108DRH_1:
;R108D		stc
;R108D		jmp     RH_Exit
;R108D
;R108DRH_2:
;R108D
;R108D		; read in headersum byte
;R108D
;R108D		push	es
;R108D		mov	ax,word ptr SrcSegment
;R108D		mov	es,ax
;R108D		mov	bx,ds:SrcOffset
;R108D		movzx	ax,byte ptr es:[bx]
;R108D		inc	word ptr ds:SrcOffset
;R108D		mov	byte ptr headersum,al
;R108D		pop	es
;R108D
;R108D
;R108D		call    FreadCRC       ; CRC not used
;R108D
;R108D		call    CalcHeadersum
;R108D
;R108D; compare headersum and result of CalcHeadersum
;R108D
;R108D		cmp	al,byte ptr headersum
;R108D		je	short @F
;R108D		jmp	short RH_1
;R108D
;R108D@@:
;R108D		mov	bx,5
;R108D		mov	cx,4
;R108D		call	GetFromHeader
;R108D		mov	dword ptr compsize,eax
;R108D
;R108D		mov	bx,9
;R108D		mov	cx,4
;R108D		call	GetFromHeader
;R108D		mov	dword ptr origsize,eax
;R108D
;R108D		mov	bx,13
;R108D		mov	cx,2
;R108D		call	GetFromHeader
;R108D		mov	word ptr ExpOffset,ax
;R108D
;R108D		mov	bx,15
;R108D		mov	cx,2
;R108D		call	GetFromHeader
;R108D		mov	word ptr ExpSegment,ax
;R108D
;R108D		cmp	byte ptr Header[17],20h	; check specific spot of header
;R108D		jne	short RH_1
;R108D
;R108D		cmp	byte ptr Header[18],01h ; check specific spot of header
;R108D		jne	short RH_1
;R108D
;R108D		movzx	bx,byte ptr headersize
;R108D		sub	bx,5
;R108D		mov	cx,2
;R108D		call	GetFromHeader
;R108D		mov	word ptr file_crc,ax	; truncate upper word
;R108D
;R108D		mov	bx,NAMELENIDX
;R108D		mov	bl,byte ptr Header[bx]
;R108D		mov	ax,OUTFILENAME
;R108D		add	bx,ax
;R108D		mov	byte ptr Header[bx],'$'	; assembly version
;R108D		mov	byte ptr Header[bx+1],0	; assembly version
;R108D
;R108D		clc
;R108D
;R108DRH_Exit:
;R108D
;R108D		popa
;R108D
;R108D		ret
;R108D
;R108DReadHeader	endp

;R64 start
;[]==============================================================[]
;
;KBD_VECT:
;
;	Compatibility ORG for Int 16h. Calls routine in
;	KEYBOARD.ASM
;
;Saves:	NONE
;
;Entry:	NONE
;Exit:	NONE
;
;Author: Award
;Date:   04/18/90
;
; Name | Date	    | Description
; ---------------------------------------------------------------
; TIM | 18-Apr-90   | Update to 4.0
;
;[]==============================================================[]

KBD_VECT	PROC	NEAR
		push	ds
		push	bx

		cli					;R68
		mov	bx,G_RAM		; set data seg
		mov	ds,bx
		ASSUME	DS:G_RAM

		or	ah,ah
		jz	short Func00
		cmp	ah,10H				;R68
		je	short Func00			;R68
		cmp	ah,1
		je	short Func01
		cmp	ah,11H				;R68
		je	short Func01			;R68
;R72 start
		cmp	ah,2
		je	short Func02
		cmp	ah,12h
		je	short Func12
;R72 end
		jmp	short Kbd_vect_exit
Func00:
		sti					;R65
		newiodelay				;R68
		cli					;R68
		mov	bx,G_RAM:[Ptr_Kbd_Buf_Hd]
		cmp	bx,G_RAM:[Ptr_Kbd_Buf_Tl]
		je	short Func00
		mov	ax,G_RAM:[bx+400h]
		add	bx,2
		cmp	bx,G_RAM:[KBD_BUFEND_LOCN]
		jne	short @F
		mov	bx,G_RAM:[KBD_BUF_LOCN]
@@:
		mov	G_RAM:[Ptr_Kbd_Buf_Hd],bx
		jmp	short Kbd_vect_exit
Func01:
		mov	bx,G_RAM:[Ptr_Kbd_Buf_Hd]
		cmp	bx,G_RAM:[Ptr_Kbd_Buf_Tl]
		je	short Kbd_vect_exit
		mov	ax,G_RAM:[bx+400h]
;R72 start
		jmp	short Kbd_vect_exit
Func12:
		xor	ah,ah
Func02:
		mov	al,G_RAM:[SHFT_STAT]
;R72 end
Kbd_vect_exit:
		sti					;R68
		pop	bx
		pop	ds
		retf	2
KBD_VECT	ENDP




; This routine handles the interrupts generated by the keyboard
;
; ENTRY: NONE
; EXIT:  NONE
KBDINT_VECT	PROC	NEAR
		sti				; enable int
		cld

		push	ds
		pusha

		mov	bx,G_RAM		; set data seg
		mov	ds,bx
		ASSUME	DS:G_RAM

		cli
		in	al,DATA8042		; READ DATA FROM 8042

		stc				; set carry flag - in case of iret
		mov	ah,04fh			; set function call
		int	15h			; do it
		jnc	short qwik_exit		; somebody else handled scan code
		sti
		test	al,80h
		jz	short Is_make_code
		cmp	al,0aah			;Is Left Shift break code?
		jne	short @F
		and	byte ptr G_RAM:[SHFT_STAT],not 2
		jmp	short qwik_exit
@@:
		cmp	al,0b6h			;Is Right Shift break code?
		jne	short qwik_exit
		and	byte ptr G_RAM:[SHFT_STAT],not 1
		jmp	short qwik_exit
Is_make_code:
		mov	bl,al
		xor	bh,bh
		shl	bx,1
		add	bx,offset DGROUP:KEYS
		mov	ah,cs:[bx]
		cmp	ah,LT_SHFT
		jne	short @F
		or	byte ptr G_RAM:[SHFT_STAT],2
		jmp	short qwik_exit
@@:
		cmp	ah,RT_SHFT
		jne	short Not_Shift_Key
		or	byte ptr G_RAM:[SHFT_STAT],1
		jmp	short qwik_exit
Not_Shift_Key:
		test	byte ptr G_RAM:[SHFT_STAT],3
		jz	short @F
		mov	ah,cs:[bx+1]
@@:
		xchg	al,ah

		mov	bx,G_RAM:[Ptr_Kbd_Buf_Tl]
		mov	G_RAM:[bx+400h],ax
		add	bx,2
		cmp	bx,G_RAM:[KBD_BUFEND_LOCN]
		jne	short @F
		mov	bx,G_RAM:[KBD_BUF_LOCN]
@@:
		cmp	bx,G_RAM:[Ptr_Kbd_Buf_Hd]
		je	short qwik_exit
		mov	G_RAM:[Ptr_Kbd_Buf_Tl],bx
qwik_exit:
		cli
		mov	al,END_OF_INT		; END_OF_INT
		out	A8259,al
		sti

		popa
		pop	ds
		iret
KBDINT_VECT	ENDP

SYS_REQ		EQU	4
KEYS:
		DB	0,	0	;	00	(0)	scan	codes	start	with	1
		DB	1BH,	1BH	;	01	(1)	esc	key
		DB	'1',	'!'	;	02	(2)	1	key
		DB	'2',	'@'	;	03	(3)	2	KEY
		DB	'3',	'#'	;	04	(4)	3	KEY
		DB	'4',	'$'	;	05	(5)	4	key
		DB	'5',	'%'	;	06	(6)	5
		DB	'6',	'^'	;	07	(7)	6
		DB	'7',	'&'	;	08	(8)	7
		DB	'8',	'*'	;	09	(9)	8
		DB	'9',	'('	;	0A	(10)	9
		DB	'0',	')'	;	0B	(11)	0
		DB	'-',	'_'	;	0C	(12)	-
		DB	'=',	'+'	;	0D	(13)	=
		DB	8,	8	;	0E	(14)	bksp
		DB	9,	0	;	0F	(15)	tab	key
		DB	'q',	'Q'	;	10	(16)	q
		DB	'w',	'W'	;	11	(17)	w
		DB	'e',	'E'	;	12	(18)	e
		DB	'r',	'R'	;	13	(19)	r
		DB	't',	'T'	;	14	(20)	t
		DB	'y',	'Y'	;	15	(21)	y
		DB	'u',	'U'	;	16	(22)	u
		DB	'i',	'I'	;	17	(23)	i
		DB	'o',	'O'	;	18	(24)	o
		DB	'p',	'P'	;	19	(25)	p
		DB	'[',	'{'	;	1A	(26)	[
		DB	']',	'}'	;	1B	(27)	]
		DB	CR,	CR	;	1C	(28)	CR
		DB	CTRL,	0FFH	;	1D	(29)	ctrl	key
		DB	'a',	'A'	;	1E	(30)	a
		DB	's',	'S'	;	1F	(31)	s
		DB	'd',	'D'	;	20	(32)	d
		DB	'f',	'F'	;	21	(33)	f
		DB	'g',	'G'	;	22	(34)	g
		DB	'h',	'H'	;	23	(35)	h
		DB	'j',	'J'	;	24	(36)	j
		DB	'k',	'K'	;	25	(37)	k
		DB	'l',	'L'	;	26	(38)	l
		DB	';',	':'	;	27	(39)	COMMA
		DB	27H,	22H	;	28	(40)	'
		DB	60H,	'~'	;	29	(41)	`
		DB	LT_SHFT,0FFH	;	2A	(42)	left	SHIFT
		DB	'\',	'|'	;	2B	(43)	\
		DB	'z',	'Z'	;	2C	(44)	z
		DB	'x',	'X'	;	2D	(45)	x
		DB	'c',	'C'	;	2E	(46)	c
		DB	'v',	'V'	;	2F	(47)	v
		DB	'b',	'B'	;	30	(48)	b
		DB	'n',	'N'	;	31	(49)	n
		DB	'm',	'M'	;	32	(50)	m
		DB	',',	'<'	;	33	(51)
		DB	'.',	'>'	;	34	(52)	.
		DB	'/',	'?'	;	35	(53)	/	101
		DB	RT_SHFT,0FFH	;	36	(54)	right	SHIFT
		DB	0,	0FFH	;	37	(55)	prnt	scrn
		DB	ALT,	0FFH	;	38	(56)	alt	key
		DB	' ',	' '	;	39	(57)	sp
		DB	CAPS_LK,0FFH	;	3A	(58)	caps	lk
		DB	0FFH,	0FFH	;	3B	(59)	f1
		DB	0FFH,	0FFH	;	3C	(60)	f2
		DB	0FFH,	0FFH	;	3D	(61)	f3
		DB	0FFH,	0FFH	;	3E	(62)	f4
		DB	0FFH,	0FFH	;	3F	(63)	f5
		DB	0FFH,	0FFH	;	40	(64)	f6
		DB	0FFH,	0FFH	;	41	(65)	f7
		DB	0FFH,	0FFH	;	42	(66)	f8
		DB	0FFH,	0FFH	;	43	(67)	f9
		DB	0FFH,	0FFH	;	44	(68)	f10
		DB	NUM_LK,	0FFH	;	45	(69)	num	lk
		DB	SCRL_LK,0FFH	;	46	(70)	scrl	lk
		DB	1,	'7'	;	47	(71)	home
		DB	1,	'8'	;	48	(72)	up	arrow	101
		DB	1,	'9'	;	49	(73)	pg	up
		DB	'-',	'-'	;	4A	(74)	-	101
		DB	1,	'4'	;	4B	(75)	lft	arrow
		DB	1,	'5'	;	4C	(76)	5	101
		DB	1,	'6'	;	4D	(77)	rt	arrow
		DB	'+',	'+'	;	4E	(78)	+	101
		DB	1,	'1'	;	4F	(79)	end
		DB	1,	'2'	;	50	(80)	dn	arrow	101
		DB	1,	'3'	;	51	(81)	pg	dn
		DB	INS_LK,	'0'	;	52	(82)	ins	101
		DB	0,	0FFH	;	53	(83)	del	101
		DB	SYS_REQ,0FFH	;	54	(84)	SYS	KEY
		DB	0FFH,	0FFH	;	55	(85)	E0	-	V2.09
		DB	'\',	'|'	;	56	(86)	\
		DB	0FFH,	0FFH	;	57	(87)	f11	-	V2.09
		DB	0FFH,	0FFH	;	58	(88)	f12	-	V2.09
;R64 end

FDPARMS		STRUC
		FD_SPECIFY_1	DB	0DFH	;00: 1st Specify byte
		FD_SPECIFY_2	DB	002H	;01: 2nd Specify byte
		FD_MOTOR_OFF	DB	025H	;02: motor wait before turn off.
		FD_SEC_SIZE	DB	002H	;03: 128 * 2^N bytes per sector
		FD_EOT		DB	009H	;04: End of track
		FD_NORMAL_GAP	DB	02AH	;05: GAP length
		FD_DTL		DB	0FFH	;06: data length, if 03: = 0
		FD_FORMAT_GAP	DB	050H	;07: gap length for format
		FD_FILL		DB	0F6H	;08: fill byte for format
		FD_HEAD_WAIT	DB	00FH	;09: milliseconds for head settle time
		FD_MOTOR_ON	DB	008H	;10: 1/8 of seconds for motor spin up.
		FD_LAST_CYL	DB	027H	;11: # of last cylinder
		FD_XFER_RATE	DB	080H	;12: Xfer rate, as sent to port.
FDPARMS		ENDS
		public	FD_BIOS_PARMS		;for map file
FD_BIOS_PARMS	LABEL	BYTE
	; 00   01   02   03   04   05   06   07   08   09   10   11   12
FDPARMS	<0AFH,002H,025H,002H,012H,01BH,0FFH,06CH,0F6H,00FH,008H,04FH,000H>
FDPARMS	<0DFH,002H,025H,002H,00FH,01BH,0FFH,054H,0F6H,00FH,008H,04FH,000H>
FDPARMS	<0DFH,002H,025H,002H,009H,02AH,0FFH,050H,0F6H,00FH,008H,04FH,080H>
FDPARMS	<0DFH,002H,025H,002H,009H,02AH,0FFH,050H,0F6H,00FH,008H,027H,040H>
;Above:  1st row = high capacity media in HIGH capacity 3 1/2" drive.
;	 2nd row = high capacity media in HIGH capacity 5 1/4" drive.
;	 3rd row = low capacity media in HIGH capacity 3 1/2" drive.
;	 4th row = low capacity media in HIGH capacity 5 1/4" drive.

;		     CMOS type,	40:8bh,	40:90h
Disk_Parms:	DB	40h,	09h,	17h,	10h,28h	;1.44Mb in 1.44Mb drive
Disk_Parm_Width	EQU	$ - offset Disk_Parms
		DB	20h,	09h,	15h,	0ah,28h	;1.2Mb in 1.2Mb drive
		DB	40h,	89h,	97h,	01h,28h	;720Kb in 1.44Mb drive
		DB	20h,	49h,	74h,	01h,01h	;360Kb in 1.2Mb drive
Disk_Parms_End	Label	Near

		EVEN				; TABLE
DIX_DMA_TABLE	LABEL	BYTE			; duplicate dmacodes...
		DB	46H			; read operation.
		DB	4AH			; write operation
		DB	42H			; verify operation.

;R161		EVEN				; TABLE
;R161DIGP_DRIVE_TABLE	LABEL	BYTE
;R161	; bit index:  bit 2-1 = xfer rate, bit 0 = 40/80 track flag
;R161		DB	04			; 000b: 500 Kbs, 40 track = table 4-1
;R161		DB	04			; 001b: 500 Kbs, 80 track = table 4-1
;R161		DB	02			; 010b: 300 Kbs, 40 track = table 2-1
;R161		DB	02			; 011b: 300 Kbs, 80 track = table 2-1
;R161		DB	01			; 100b: 250 Kbs, 40 track = table 1
;R161		DB	04			; 101b: 250 Kbs, 80 track = table 4-1
;R161		DB	04			; 110b: illegal, 40 track = table 4-1
;R161		DB	04			; 111b: illegal	80 track = table 4-1
;R161
;R161		EVEN				; TABLE
;R161DIWD_LUT	LABEL	BYTE
;R161		DB	000H			; 0: invalid
;R161		DB	000H			; 1: invalid
;R161		DB	070H			; 2: 300 kbs, d-step, determined
;R161		DB	010H			; 3: 500 kbs, determined
;R161		DB	090H			; 4: 250 kbs, determined
;R161		DB	090H			; 5: 250 kbs, single step, determined
;R161
;R161		EVEN				; TABLE
;R161FUMB_BIT_TABLE	LABEL	BYTE
;R161;		value	index = bit 3 = +300 kbs/-250 kbs
;R161;			   	bit 2 = +double step
;R161;			   	bit 1 = +determined
;R161;			   	bit 0 = +80 track.
;R161;
;R161		DB	00H			; 0000 = 250, undetermined, 40 track.
;R161		DB	07H			; 0001 = 250, undetermined, 80 track.
;R161		DB	03H			; 0010 = 250, determined,   40 track
;R161		DB	07H			; 0011 = 250, determined,   80 track
;R161		DB	00H			; 0100 = 250, undetermined, 40 track
;R161		DB	07H			; 0101 = 250, undetermined, 80 track
;R161		DB	03H			; 0110 = 250, determined,   40 track.
;R161		DB	07H			; 0111 = 250, determined,   80 track.
;R161
;R161		DB	07H			; 1000 = 300, -dstep,  undetermined.
;R161		DB	07H			; 1001 = 300, -dstep,  undetermined.
;R161		DB	07H			; 1010 = 300, -dstep,  determined.
;R161		DB	07H			; 1011 = 300, -dstep,  determined.
;R161		DB	01H			; 1100 = 300, +dstep,  undetermined.
;R161		DB	01H			; 1101 = 300, +dstep,  undetermined.
;R161		DB	04H			; 1110 = 300, +dstep,  determined.
;R161		DB	04H			; 1111 = 300, +dstep,  determined.
;R161
;R161		EVEN				; TABLE
;R161GAM_TABLE	LABEL	BYTE
;R161		DB	000H			; cmos bad or out of range.
;R161		DB	093H			; cmos = type 1, 250 kbs
;R161		DB	015H			; cmos = type 2, 500 kbs
;R161		DB	097H			; cmos = type 3, 250 kbs
;R161		DB	017H			; cmos = type 4, 500 kbs
;R161
;R161		EVEN				; TABLE
;R161NUM_DRIVE_TABLES LABEL	BYTE
;R161		DB	1			; CMOS type 0
;R161		DB	1			;  type 1
;R161		DB	2			;  type 2
;R161		DB	1			;  type 3
;R161		DB	2			;  type 4 (1.44)
;R161		DB	3			;  LOCAL type 5 (2.88)
;R161		DB	017H			; cmos = type 4, 500 kbs

		public	DSK_VECT		;for map file
DSK_VECT	PROC	NEAR

;R186 start
ifdef	Support_ATAPI_In_BOOTROM
ifdef	Bootblock_16K_Support
		push	ds				;save DS
		push	G_RAM				;DS=G_RAM
		pop	ds
		test	byte ptr ds:[ATAPI_Byte],4	;have ATAPI device exist?
		pop	ds
		jz	short Std_Floppy		;Not boot from ATAPI device
		extrn	Std_Atapi:near
		call	Std_Atapi
		retf	2
Std_Floppy:
endif	;Bootblock_16K_Support
endif	;Support_ATAPI_In_BOOTROM
;R186 end
		STI
		PUSH	SI
		PUSH	DS
		PUSH	ES
		PUSH	DI
		CLD
		PUSH	DX
		PUSH	CX
		PUSH	BX
		PUSH	AX

		MOV	AX,CS
		MOV	DS,AX
		ASSUME	DS:DGROUP		; dgroup must be here

		MOV	AX,G_RAM		; variables.
		MOV	ES,AX			; ES for addressing data area
		ASSUME	ES:G_RAM		; STAYS IN EFFECT THROUGH CODE
						; SEG_0
		PUSH	BP
		MOV	BP,SP
		OR	BP_FLAGS,200H		; SET INT FLAG ON BECAUSE OF
						; DOS CODE AT 70:XXXX
		or	dl,dl			; if isn't call drive A function
		jnz	D_ILLEGAL_FUNCTION	; then return bad command
		CMP	BP_OPCODE,1
		JA	SHORT D_NOT_FUNC_0_OR_1	; function > 2, then jump
		JE	SHORT D_FUNC_1		; function == 1, then jump
						; else fall thru to zero.
;FUNCTION 0:  Reset drives.

		MOV	G_RAM:[FD_OP_RESULT],0	; clear previous errors.
		CALL	RESETDRIVES		; reset the drives
		JMP	short D_NORMAL_RET	; exit to caller.

D_FUNC_1:					; FUNCTION 1:  Get status of last operation.
		MOV	AH,G_RAM:[FD_OP_RESULT]	; previous status to ah
		JMP	short D_NORMAL_RET   	; exit to caller.

D_NOT_FUNC_0_OR_1:
		MOV	G_RAM:[FD_OP_RESULT],0	; functions = 2 clear previous errors
		CMP	BP_OPCODE,2		; if function = 2
		JE	DISK_IO_XFER
		CMP	BP_OPCODE,8		; if function = 8
		jne	short Func_Above_8
		mov	al,G_RAM:[Floppy_CMOS_Type]	; functions = 2 clear previous errors
		xor	ah,ah
		mov	BP_OFFSET,ax
		mov	di,SEG_0
		mov	es,di
		lea	di,DISK_PARM_PTR
		mov	ax,es:[di+2]
		mov	BP_ES,ax
		mov	ax,es:[di]
		mov	BP_DI,ax
		mov	al,11
		call	get_parm
		mov	BP_CYLINDER,al
		mov	al,4
		call	get_parm
		mov	BP_SECTOR,al
		mov	BP_HEAD,1
		mov	BP_DRIVE,1
		xor	ah,ah			; no errors
		jmp	short D_NORMAL_RET
Func_Above_8:
		cmp	BP_OPCODE,15h
		jne	short @F
		mov	ah,2			; no change line support
		jmp	short D_CLEAR_CARRY
@@:
		cmp	BP_OPCODE,16h
		jne	short @F
		xor	ah,ah
		jmp	short D_CLEAR_CARRY
@@:
		cmp	BP_OPCODE,17h
		jne	short @F
		mov	BP_AL,0
		xor	ah,ah
		jmp	short D_CLEAR_CARRY
@@:
D_ILLEGAL_FUNCTION:
		MOV	AH,1			; error code
D_NORMAL_RET:
		MOV	G_RAM:[FD_OP_RESULT],AH	; record results in case
						; next call is function 1.
D_CHECK_CARRY:
		OR	BP_FLAGS,+1		; assume error.MASM5 REMOVED
		OR	AH,AH			; if AH is zero, indicate
		JNZ	SHORT DISKIO_EXIT	; okay by clearing carry flag
D_CLEAR_CARRY:
		AND	BP_FLAGS,0FFFEH		; else clear flags.MASM5 REMOVED
DISKIO_EXIT:
		MOV	BP_RET_CODE,AH		; put Ah on stack, so it will
						; be popped off.
		MOV	SP,BP			; not necessary, but leave in
						; in case we want to add local
						; variables in future.
		POP	BP			; recover bp
		POP	AX
		POP	BX
		POP	CX
		POP	DX
		POP	DI
		POP	ES
		POP	DS
		POP	SI

		IRET

DSK_VECT	ENDP

ifndef Dont_set_F065_for_BootBlock		;R170
		CK_ORG  0F065h			;R136
		iret				;R136
endif ;Dont_set_F065_for_BootBlock		;R170

;!!!!!!!!!!!!!!  LEVEL 2 PROCEDURES:  The Function calls  !!!!!!!!!!!!!!!!

;[]---------------------------------------------------------------------------
;These procedures have permission to read any of BP_REGISTERS.  They
;can also change any BP_REGISTERS except BP_OPCODE,BP_RET_CODE and BP_FLAGS
;These procedures can destroy any registers except BP and Segment registers.
;[]---------------------------------------------------------------------------

DISK_IO_XFER	PROC	NEAR

		MOV	AL,BP_DRIVE		; get drive
		CALL	TURNONMOTOR		; turn on motor and wait
				   		; if not already on.

		CALL	READ_AND_CLEAR_DCL	; check the dcl
						; note: destroys al
		OR	AH,AH			; exit if active
		JZ	SHORT DIX_DCL_OK
		JMP	DIX_FAILURE 		; abort operation if disk
						; change line was active,
						; if we could clear it.
DIX_DCL_OK:

;----Prepare and send a SPECIFY command to controller----

		XOR	AL,AL
		CALL	GET_PARM
		MOV	BL,AL			; FIRST SPECIFY BYTE - DF
		MOV	AL,1
		CALL	GET_PARM
		MOV	BH,AL			; SECOND SPECIFY BYTE - 02

		PUSH	BX			; parameters on stack
		MOV	SI,SP			; pointer to parameters
		MOV	AH,NC_SPECIFY		; specify command
		MOV	BL,NC_LEN_SPECIFY	; 3 bytes in specify command.
		CALL	SEND_COMMAND		; output specify command
		POP	BX			; clear parameters off stack.
		OR	AH,AH			; error?
		jnz	DIX_CHECK_ERROR		; see if error should abort
						; operation, or move us to
						; next transfer rate.
		MOV	AL,BP_DRIVE		; drive to al
		CALL	RESET_XFER_RATE		; choose appropriate xfer rate

		MOV	AL,BP_DRIVE		; get drive
		MOV	AH,BP_CYLINDER		; logical cylinder
		CALL	NEC_SEEK		; position head over cylinder
		OR	AH,AH
		jnz	DIX_CHECK_ERROR

;xfer size calculation:
;size of xfer = SECTORS * 128 * 2^N, where N comes from
;user parameter table.
;	128 = 2^7
;	so size of xfer = SECTORS * 2^7 * 2^N.
;			= SECTORS * 2^(7+N)
;			= SECTORS left-shifted 7+N

		MOV	AL,3			; get "N", as in 128*2^N
		CALL	GET_PARM
		MOV	CL,AL			; move to shift count reg.
		ADD	CL,7			; add 7 shifts for 128
		MOV	AL,BP_AL		; get # of sectors.
		XOR	AH,AH			; in  ax.
		SHL	AX,CL			; every shift = times 2
		DEC	AX			; DMA controller wants
						; count - 1
		PUSH	AX			; store xfer size on stack.
		PUSH	BP_ES			; store segment
		PUSH	BP_OFFSET		; store offset.

		MOV	BL,BP_OPCODE
		XOR	BH,BH
		SUB	BX,2
		MOV	AL,DGROUP:DIX_DMA_TABLE[BX]
		MOV	SI,SP
		CALL	DMA_SETUP
		ADD	SP,6			; clear the stack.
		OR	AH,AH
		jnz	short DIX_CHECK_ERROR

		MOV	AL,6			; get DTL, byte 9 of
		CALL	GET_PARM		; command.
		MOV	BH,AL
						; get gap length, byte 8
		MOV	BL,01BH			; assume 500 kbs xfer rate
		mov	ah,byte ptr G_RAM:[CURRENT_MEDIA]
		AND	AH,0C0H
		JZ	SHORT DIX_GOT_GAP_LEN
		MOV	BL,02AH			; gap length for 300, 250 kbs
DIX_GOT_GAP_LEN:
		PUSH	BX			; bytes 9 and 8 on stack.

		MOV	AL,4			; get "EOT", last track, from
		CALL	GET_PARM		; user parameter table.

		MOV	BH,AL
		MOV	AL,3			; get "N", sector size, from
		CALL	GET_PARM		; user parameter table.
		MOV	BL,AL
		PUSH	BX			; push bytes 7 and 6 on stack.

		MOV	BH,BP_SECTOR		; get "R", starting track.
		MOV	BL,BP_HEAD		; get "H", the head:  DO NOT
						; range check these-- copy protect
						; schemes.
		PUSH	BX			; push bytes 5 and 4 of command

		MOV	BH,BP_CYLINDER		; get "C",cylinder, don't range check.
		MOV	BL,BP_HEAD		; get head
		AND	BL,01H			; range check it.
		SHL	BL,2
		OR	BL,BP_DRIVE		; or in drive, it is already
						; range checked.
		PUSH	BX			; push bytes 3 and 2 of command.
		MOV	AH,NC_READ		; assume a read or verify command
		MOV	BL,NC_LEN_RW
		MOV	SI,SP			; pointer to rest of parameters.
		CALL	SEND_COMMAND
		ADD	SP,8			; clear stack
		OR	AH,AH
		JNZ	SHORT DIX_CHECK_ERROR
		CALL	WAIT_FOR_RESULTS	; wait for interrupt, read status
DIX_CHECK_ERROR:
		OR	AH,AH			; see if error
		JZ	SHORT DIX_SUCCESS

DIX_FAILURE:
		MOV	BP_AL,0			; no sectors xferred.
		JMP	SHORT DIX_EXIT		;
DIX_SUCCESS:
		MOV	CX,BP_SEC_CYL		; cx=starting sector, cylinder
		MOV	DH,BP_HEAD		; dh=starting head
		CALL	CALC_XFER_SIZE		; new about drive capabilities
		MOV	BP_AL,AL		; or current media.
		XOR	AH,AH			; successful operation.
DIX_EXIT:
		JMP	D_NORMAL_RET

DISK_IO_XFER	ENDP

;[]----------------------------------------------------------------------
;RESET_XFER_RATE:	Checks to see if current xfer rate is the one
;			we want, and updates it if it isn't.
;	INPUT:	AL=drive
;	OUTPUT:
;		All registers preserved.
;[]----------------------------------------------------------------------

RESET_XFER_RATE	PROC	NEAR
		PUSH	AX
		PUSH	DX

		mov	al,G_RAM:[CURRENT_MEDIA]; get xfer rate for this drive
		ROL	Al,2			; shift to position for port.
		AND	AL,03H			; all other bits = 0
		MOV	DX,FDC_CTRL_IN		; point to xfer controller.

		CLI				; suspend interrupts, so
						; xfer rate and reflection
						; stay in sync.
		OUT	DX,AL			; out new xfer rate.
		STI

		POP	DX
		POP	AX
		RET
RESET_XFER_RATE	ENDP

;[]------------------------------------------------------------------------
;READ_AND_CLEAR_DCL:  Reads disk change line, if active, attempts to clear
;		      it.
;INPUT:  AL = drive #, MOTOR MUST ALREADY BE RUNNING FOR VALID RESULTS.
;OUTPUT:  AH=0 if disk change line not active
;	     6 if was active, but we successfully clear it.
;	     80h if active, and unable to clear it.
;	     CURRENT_MEDIA is set to unestablished.
;	May destroy any other register.
;[]------------------------------------------------------------------------

		align	4			;R08
READ_AND_CLEAR_DCL	PROC	NEAR
		CALL	READ_DCL		; read the change line
						; ah=code, al preserved.
		MOV	AH,0			; assume ok, SAVE FLAGS
		JZ	SHORT RACD_EXIT		; exit if okay

		CALL	CLEAR_DCL

		CALL	READ_DCL
		MOV	AH,ST_MEDIACHANGE	; assume we cleared it.
		JZ	SHORT RACD_EXIT
		MOV	AH,ST_TIMEOUT		; can't clear it.
RACD_EXIT:	RET

READ_AND_CLEAR_DCL	ENDP

;[]----------------------------------------------------------------------
;READ_DCL:  Reads the disk change line status
;	INPUT:  AL=drive #.
;		Motor is running, drive is already selected.
;	OUTPUT: AH=80h if drive active, 0 if inactive
;		ZFLAG = ZR if inactive
;			NZ if active
;	All other registers preserved.
;[]----------------------------------------------------------------------

		ALIGN	4			; N3.03
READ_DCL	PROC	NEAR
		PUSH	DX
		XCHG	AH,AL			; save drive # in ah
		MOV	DX,FDC_CTRL_IN		; CHECK STATUS
		IN	AL,DX
		XCHG	AH,AL			; drive # back to al
		AND	AH,80H			; SET ZERO FLAG
		POP	DX
		RET
READ_DCL	ENDP

;[]----------------------------------------------------------------------
;clear_dcl:	Attempts to clear disk change line by doing:
;		1. reset
;		2. seek to track 1
;		3. seek to track 0
;
;	INPUT:  Motor must be running, with appropriate drive selected.
;		AL=drive #
;	OUTPUT: none
;	May destory any general registers
;[]----------------------------------------------------------------------

		ALIGN	4			; 303A
CLEAR_DCL	PROC	NEAR

		PUSH	AX			; save drive # in al
		CALL	RESETDRIVES
		POP	AX			; recover drive #.
;		MOV	AH,1			; seek to track 1
		MOV	AH,4			; jsz
		PUSH	AX			; save drive # in al
		CALL	NEC_SEEK
		POP	AX			; recover drive #
		XOR	AH,AH
		CALL	NEC_SEEK
		RET
CLEAR_DCL	ENDP

;[]----------------------------------------------------------------------
;NEC_SEEK:	Moves read head to the requested cylinder.  Recalibrates
;		drive if drive has not yet been recalibrated.  Will take
;		care of double stepping if necessary.
;	INPUT:	AL=Drive #
;		AH=Logical Track #  (not the double-stepped number)
;		CURRENT_MEDIA, bit 5 = +double step bit.
;		NEED_RECAL, bit 0-1 to indicate if this drive needs
;			recalibration.
;		CURCYL to tell us if we are already on the requested drive.
;	OUTPUT:
;	 	AH=error code if unable to complete seek.
;		AH=0 if successfuly seek operation.
;		CURCYL = New physical clinder
;		NEED_RECAL, recalibrate bit for this drive set.
;	May destroy any general register.
;[]----------------------------------------------------------------------

		ALIGN	4
NEC_SEEK	PROC	NEAR

		MOV	BL,1			; create mask for testing
		MOV	CL,AL			; seek status recalibrate bit
		SHL	BL,CL			; for this drive.

		TEST	G_RAM:[NEED_RECAL],BL	; fall thru if this
		JNZ	SHORT NS_DO_SEEK	; drive needs recal.

		OR	G_RAM:[NEED_RECAL],BL	; set bit, so next seek
						; will not recalibrate.
		MOV	DX,AX			; track, drive to dx.
		XOR	AH,AH			; cylinder will be 0 after
		CALL	SET_CURCYL		; recalibrate.
		MOV	CX,2			; NEC returns error on
						; recal after 77 step pulses,
						; so we made need to recal
						; twice.
NS_RECAL_LOOP:	PUSH	CX			; save loop counter
		PUSH	DX			; save track, pass drive
		MOV	SI,SP			; to SEND_COMMAND
		MOV	AH,NC_RECAL		; recalibrate command.
		MOV	BL,NC_LEN_RECAL		; 2 byte command.
		CALL	SEND_COMMAND
		POP	DX			; recover track, drive.
		POP	CX			; recover loop counter
		OR	AH,AH
		JNZ	SHORT NS_EXIT		; can't send command.
		PUSH	CX			; save loop counter
		PUSH	DX			; save drive & track
		CALL	SENSESTATINT		; check status
		POP	DX			; recover drive, track.
		POP	CX			; recover loop counter
		OR	AH,AH			; check for error.
		LOOPNZ	SHORT NS_RECAL_LOOP	; try again if error.

		JNZ	SHORT NS_EXIT		; if 2 errors, its a genuine
						; error.
		MOV	AX,DX			; ax=cylinder,drive.
		OR	AH,AH			; if cylinder = 0, impose
		JNZ	SHORT NS_DO_SEEK	; head settle time now,
		CALL	HEAD_SETTLE_TIME	; since seek will skip this.
		JMP	SHORT NS_SUCCESS

NS_DO_SEEK:	MOV	BX,AX			; save track.
		TEST	byte ptr G_RAM:[CURRENT_MEDIA],020H	; double stepping?
		JZ	SHORT NS_GOT_CYL
		SHL	BH,1			; then double cylinder.

NS_GOT_CYL:	CALL	GET_CURCYL
		CMP	AH,BH
		JE	SHORT NS_SUCCESS	; no need to seek.
		MOV	AH,BH
		CALL	SET_CURCYL

		PUSH	BX			; drive and track on stack
		MOV	SI,SP			; ss:[si] points to args.
		MOV	AH,NC_SEEK		; ah=seek command
		MOV	BL,NC_LEN_SEEK		; 3 byte command
		CALL	SEND_COMMAND
		POP	BX			; recover drive and track
		OR	AH,AH
		JNZ	SHORT NS_EXIT		; unable to send seek.
		PUSH	BX			; save drive, cylinder
		CALL	SENSESTATINT		; get RESULTS of operation.
		POP	BX			; recover drive track.
		OR	AH,AH
		JNZ	SHORT NS_EXIT		; exit if error.
		MOV	AX,BX			; drive to al
		CALL	HEAD_SETTLE_TIME
NS_SUCCESS:	XOR	AH,AH			; indicate no error.
NS_EXIT:	RET
NEC_SEEK	ENDP

;[]----------------------------------------------------------------------
;HEAD_SETTLE_TIME:	imposes head settle time for drive.
;	INPUT:	AL=drive, ES=0
;	OUTPUT: none
;	may destroy any general register.
;[]----------------------------------------------------------------------

HEAD_SETTLE_TIME	PROC	NEAR

		MOV	BX,AX			; save drive #
		MOV	AL,9			; get head settle time
		CALL	GET_PARM

		MOV	DL,WAIT_FDU_HEAD_SETTLE
						; units in a millisecond
		MUL	DL			; calculate # of 30 micro
		MOV	CX,AX			; units in AX milliseconds
		XOR	BX,BX			; bx:cx=wait time.
		CALL	WAIT_REFRESH		; perform wait.

		RET

HEAD_SETTLE_TIME	ENDP

;[]----------------------------------------------------------------------
;ERROR_CHECK:  Checks the return codes for the NEC to see if any errors
;	     occurred.  If it detects any, then it translates them
;	     into the BIOS error code.
;	INPUT:  FDC_RET_CODES
;	OUTPUT: AH=0 if no errors,
;		AH=error code if error occurred.

ERROR_CHECK	PROC	NEAR
; SEG_0

		MOV	BL,G_RAM:FDC_RET_CODES[0]	; get ST0
		AND	BL,0C0H			; bits 7 and 6 = 0
		MOV	AH,ST_OK		; if normal termination
		JE	SHORT EC_EXIT		; occurred.

		CMP	BL,40H			; Invalid command
		MOV	AH,ST_BADNEC		; or FDD ready line changed.
		JNZ	SHORT EC_EXIT		; blame it on controller.

		MOV	BL,G_RAM:FDC_RET_CODES[1]	; get ST1
		TEST	BL,84H			; user asked for sector > EOT
		MOV	AH,ST_RNF		; or NEC couldn't find ID
		JNZ	SHORT EC_EXIT		; field that matched.

		TEST	BL,20H			; read an ID or data
		MOV	AH,ST_BADCRC		; field, but the CRC
		JNZ	SHORT EC_EXIT		; didn't add up.

		TEST	BL,10H			; DMA was too slow
		MOV	AH,ST_BADDMA		; too keep up with NEC
		JNZ	SHORT EC_EXIT

		TEST	BL,2			; write protect tab
		MOV	AH,ST_WRITEPROT		; was in place.
		JNZ	SHORT EC_EXIT

		TEST	BL,1			; wasn't able to find
		MOV	AH,ST_BAM		; any address mark at all.
		JNZ	SHORT EC_EXIT

		MOV	AH,ST_BADNEC		; everything else, blame
						; on the controller.
EC_EXIT:
		RET
ERROR_CHECK	ENDP

;[]----------------------------------------------------------------------[]
;RESETDRIVES:	Performs a reset of the controller, returning it to a
;		known state.
;	INPUT: none
;	OUTPUT: AH=0 if no error, 20h if controller error, 80h if
;		timeout while issuing specify command.
; called by hrdskio too...
;
;[]----------------------------------------------------------------------[]
		PUBLIC	RESETDRIVES		; * AHDSK.ASM
RESETDRIVES	PROC	NEAR
		PUSH	DS
		CLI				; stop interrupts while changing
						; port 3F2h, so MOTOR_ON_IND
						; stays in sync.

		MOV	AX,G_RAM
		MOV	DS,AX
		ASSUME	DS:G_RAM

		MOV	AL,G_RAM:[MOTOR_ON_IND]	; don't shut off any motors
		ROL	AL,4			; or change selected bits.
		AND	AL,NOT 04H		; -RESET bit, active low
		OR	AL,8			; +DMA

		MOV	DX,FDC_CTRL_OUT
		OUT	DX,AL
		MOV	G_RAM:[NEED_RECAL],0	; recalibrate on next seek
		MOV	CX,WAITCPU_RESET_ON

@wdw1:
		NEWIODELAY			;R93
;R93		out	0e1h,ax
		loop	short @wdw1

		OR	AL,4			; refresh off.
		OUT	DX,AL			; dx = FDC_CTRL_OUT
		IODELAY
		STI				; reset over,

		CALL	SENSESTATINT		; SENSESTATINT();
		MOV	AH,ST_BADNEC		; assume bad controller
		CMP	G_RAM:[FDC_RET_CODES],0C0H	; check if controller
		JNE	SHORT RD_EXIT		; detected change in ready

		XOR	AL,AL			; get 1st specify byte
		CALL	GET_PARM
		MOV	BL,AL
		MOV	AL,1			; get 2nd specify byte
		CALL	GET_PARM
		MOV	BH,AL
		PUSH	BX			; push args on stack.
		MOV	SI,SP			; pointer to args.
		MOV	AH,NC_SPECIFY		; 3=specify command.
		MOV	BL,NC_LEN_SPECIFY	; 3 byte command.
		CALL	SEND_COMMAND
		POP	BX			; clear stack
RD_EXIT:	XOR	AL,AL			; clear al, error code in ah.
		POP	DS
		ASSUME	DS:NOTHING		; ASS-U-ME NEEDS TO BE CLEAR
		RET
RESETDRIVES	ENDP

;[]----------------------------------------------------------------------
;SENSESTATINT:	Called after a SEEK, RECALIBRATE or RESET of the controller.
;		It:
;			1.  Waits for interrupt from controller
;			2.  Sends a Sense interrupt status command to
;			    get ST0, which it stores in FDC_RET_CODES.
;			3.  Evaluates ST0 for SEEK error.
;		INPUT: none
;		OUTPUT: AH=0 if success
;			   80h if no interrupt or problem sending or
;			    receiving sense interrupt status.
;			   40h if bits 5 and 6 of ST0 are set, indicating
;			   an abnormal termination.
;			FDC_RET_CODES = ST0, (the RESET command wants
;			to check ST0 for itself).
;[]----------------------------------------------------------------------

SENSESTATINT	PROC	NEAR
; SEG_0
		CALL	WAITNECINT		; wait for interrupt to occur
		OR	AH,AH			; if timeout, exit.
		JNZ	SHORT S_EXIT

		MOV	AH,NC_SIS		; sense interrupt status code
		MOV	BL,NC_LEN_SIS		; 1 byte command
		CALL	SEND_COMMAND
		OR	AH,AH
		JNZ	SHORT S_EXIT

		CALL	RESULTS			; read ST0 and Present
						; cylinder number
		OR	AH,AH			; if reading error
		JNZ	SHORT S_EXIT		; return with timeout code.

		MOV	AL,G_RAM:FDC_RET_CODES[0]	; get ST0. Check for
		AND	AL,060H			; abnormal termination of
		CMP	AL,060H			; seek command.
		MOV	AH,ST_BADSEEK
		JE	SHORT S_EXIT

		XOR	AH,AH			; return success

S_EXIT:		RET

SENSESTATINT	ENDP

		PAGE
;[]----------------------------------------------------------------------
;WAITNECINT: 	Waits for the controller to generate an IRQ6, which will
;		cause INT 0Dh to set bit 7 of NEED_RECAL.
;
;		INPUT:  NEED_RECAL, bit 7.
;		OUTPUT: AH=0 if interrupt occurred.
;			AH=80h if interrupt didn't occur, or if INT 15h
;			function 9001h returned with carry flag set.
;			NEED_RECAL, bit 7 = 0.
;[]----------------------------------------------------------------------

WAITNECINT	PROC	NEAR

		MOV	DI,OFFSET G_RAM:NEED_RECAL	; set now, in case int 15
						; sets carry. CODE WILL BREAK
						; WITHOUT THIS
		MOV	AX,9001H
		CLC
		INT	15H
		sti				;R07
		MOV	AH,ST_TIMEOUT		; assume timeout.
		JC	SHORT W_EXIT

		MOV	AH,80H			; check top bit
		MOV	BH,WAIT_FDU_INT_HI	; outer loop counter
		MOV	CX,WAIT_FDU_INT_LO	; inner loop counter
		CALL	WAIT_FOR_MEM		; returns ah=80h or 0h

W_EXIT:		AND	BYTE PTR G_RAM:[DI],NOT 80H	; di = NEED_RECAL
		TEST	AH,80H
		JZ	W_RET
		STC
W_RET:		RET
WAITNECINT	ENDP

;[]----------------------------------------------------------------------
;RESULTS:	Reads status bytes back from NEC controller and
;		stores them into FDC_RET_CODES array.
;	INPUT: none
;	OUTPUT: FDC_RET_CODES
;		AH=80h if timeout while waiting for Status port
;		    to give us RQM or direction bit is wrong.
;		AH=ST_BADNEC if more than 7 bytes.
;		Other general registers may be destroyed.
;[]----------------------------------------------------------------------

RESULTS		PROC	NEAR

		MOV	DI,OFFSET G_RAM:FDC_RET_CODES

R_NEXT_BYTE:	MOV	CX,WAIT_FDU_RESULTS_LO	; length of time for
		MOV	BH,WAIT_FDU_RESULTS_HI	; RQM and direction set.
		MOV	AX,0C0C0H		; RQM is bit 7, dir bit 6.
		MOV	DX,NEC_STAT_PORT	; of port 3F4h.
		CALL	WAIT_FOR_PORT		; ah=80h if timeout, 0 otherwise.
		OR	AH,AH
		JNZ	SHORT R_EXIT

		INC	DX			; dx is now NEC_DATA_PORT
		IN	AL,DX			; es:[di] = status port.
		STOSB				; inc di

		push	cx
		mov	cx,20
@wdw2:
		NEWIODELAY			;R93
;R93		out	0e1h,ax
		loop	short @wdw2
		pop	cx

		MOV	DX,NEC_STAT_PORT	; get back dx
		IN	AL,DX			; read the status port.
		XOR	AH,AH			; assume no error, save flag
		TEST	AL,10H			; more?
		JE	SHORT R_EXIT		; quit if no more.
		MOV	AH,ST_BADNEC		; assume error.
		CMP	DI,OFFSET FDC_RET_END	; if we still have room for
		JBE	SHORT R_NEXT_BYTE	; more codes, go get them.
R_EXIT:
		RET
RESULTS		ENDP

;[]----------------------------------------------------------------------
;TURNONMOTOR:	Turns on motor and SELECTS drive.  In addition,
;		it also will impose a motor start up delay if
;		the motor was not already spinning.
;	INPUT:	AL=drive number.
;
;[]----------------------------------------------------------------------

TURNONMOTOR	PROC	NEAR

		XOR	CH,CH			; ch = 0, assume drive
						; is already running
		MOV	BH,1			; bh=mask for drive.
		MOV	CL,AL
		SHL	BH,CL

		CLI				; interrupts off so that
						; MOTOR_ON_IND stays in synch
						; with port 3f2h

		MOV	BL,G_RAM:[MOTOR_ON_IND]	; get current port 3f2h
		TEST	BL,BH			; is motor already running?
		JNZ	SHORT M_UP_COUNT
		INC	CH			; flag that motor is just
						; now being turned on.
M_UP_COUNT:	MOV	G_RAM:[MOTOR_OFF_WAIT],0FFH	; putd(MOTOR_OFF_WAIT,0xff,0)

		MOV	AH,BL			; ah=old motor status
		AND	AH,3			; save currently running drvs.
		MOV	CL,4			; shift to upper nibble for
		SHL	AH,CL			; port 3f2,
		MOV	DL,AH			; save in dl for now.
		AND	BL,0CFH			; Clear drive select
		MOV	AH,AL			; drive to ah
		SHL	AH,CL			; shift drive to upper nibble
		OR	BL,BH			; or in the new motor
		OR	BL,AH			; OR in the new drive select
		MOV	G_RAM:[MOTOR_ON_IND],BL	; update motor status

		MOV	AH,DL			; assemble port 3f2h in
		MOV	DL,10H			; ah register.
		MOV	CL,AL
		OR	AH,AL			; or in drive select
		SHL	DL,CL
		OR	AH,DL			; or in the new motor
		OR	AH,0CH			; or no reset, use DMA
		XCHG	AH,AL
		MOV	DX,FDC_CTRL_OUT
		OUT	DX,AL			; out to controller
		STI				; allow interrupts, now that
						; port 3F2h and MOTOR_ON_IND
						; are the same again.

		OR	CH,CH			; if motor already running
		JE	SHORT M_NO_WAIT		; don't wait.

		MOV	AX,090FDH		; give multitasker a chance
		CLC				; to bypass motor spin up.
		INT	15H
		sti				;R07
		JNC	SHORT M_DO_WAIT		; if no multi-tasker, do wait.

M_NO_WAIT:	RET

M_DO_WAIT:	MOV	AX,10			; J = getparm(10);
		CALL	GET_PARM
		TEST	G_RAM:[MOTOR_ON_IND],80H	; read operation
		JE	SHORT M_READ_OP		; use shorter minimum

		CMP	AL,7			; write or format, ensure
		JA	SHORT M_CALC_WAIT	; 1 second minimum

		MOV	AX,8
		JMP	SHORT M_CALC_WAIT

M_READ_OP:					; read, read verify
		OR	AL,AL			; no motor spin up ok on
		JZ	SHORT WAIT_OVER		; reads if DOS does retries.

		CMP	AL,4			; ensure 5/8 second spin up.
		JA	SHORT M_CALC_WAIT

		MOV	AX,5

M_CALC_WAIT:	XOR	AH,AH			; ax=1/8 sec. units.
		MOV	CX,WAIT_FDU_8THS	; located in the CS!!
						; in 1/8 of a second
		MUL	CX			; dx:ax=wait_refresh micro units to wait
		MOV	CX,AX			; bx:cx = dx:ax
		MOV	BX,DX
		CALL	WAIT_REFRESH
WAIT_OVER:	RET

TURNONMOTOR	ENDP

;[]----------------------------------------------------------------------
;CALC_XFER_SIZE:  Calculates the number of sectors that were transferred.
;	INPUT: CH=starting cylinder
;	       CL=starting sector
;	       DH=starting head
;		FDC_RET_CODES[3] = ending cylinder
;		FDC_RET_CODES[4] = ending head
;		FDC_RET_CODES[5] = ending sector.
;	OUTPUT:  AL=sectors xferred.
;
;[]----------------------------------------------------------------------

CALC_XFER_SIZE	PROC	NEAR

; The return codes supplied by the FDC point to the sector AFTER
; the last one transferred.  If the last sector transferred was
; the last sector on the track, the head and possibly the cylinder
; will be moved up, and sector set to 1.

		MOV	AL,4
		CALL	GET_PARM
		MOV	AH,AL			; ah=EOT
		MOV	AL,G_RAM:FDC_RET_CODES[5]	; al=ending sector.
		SUB	AL,CL			; al=end-start, may be
						; negative number.
		CMP	DH,G_RAM:FDC_RET_CODES[4]	; did head advance?
		JE	SHORT CXS_HEAD_SAME	; check cylinder if not
		ADD	AL,AH			; al=end-start + EOT
		JMP	SHORT CXS_EXIT		; if head different, cylinder
						; can't have advanced.
CXS_HEAD_SAME:	CMP	CH,G_RAM:FDC_RET_CODES[3]	; did cylinder advance?
		JE	SHORT CXS_EXIT		; exit if not
		SHL	AH,1			; ah=EOT*2
		ADD	AL,AH			; al=end-start + (EOT*2)
CXS_EXIT:	RET				;
CALC_XFER_SIZE	ENDP

		PAGE
;[]----------------------------------------------------------------------
;DMA_SETUP:	set up 8237 for disk transfer
;	input -	AL=command.
;		SS:SI = offset
;		SS:SI+2 = segment
;		SS:SI+4 = size of xfer, in bytes - 1 for DMA
;	output:
;		AH=0 if no error
;		AH=09 if DMA boundary error.
;[]----------------------------------------------------------------------

DMA_SETUP	PROC	NEAR

; --- QEMM/WINDOWS FIX ---
; Occasionally, complete sectors were being written with wrong data.
; The problem occurs when (1) we DMA from paged memory, and (2) the
; ES:BX value plus sectors would overlap the "linear" 64K boundary
; (detected by BIOS here), and (3) the transfer also overlaps the 64K
; "physical" boundary in the target (EMS) paged RAM.  We note that the
; DMAC writes to "physical" RAM, so when BIOS programs the DMAC with a
; "linear" value, QEMM must reprogram a "physical" address into the
; DMAC.  Furthermore, if a 64K "physical" boundary would be crossed,
; then QEMM needs to supply a temporary buffer, then trap the FDC
; completion interrupt and copy the data to the final target (EMS) RAM.
; QEMM has a state-machine bug here:
; (a) DOS asks BIOS to DMA several sectors across a 64K boundary,
;     (As this RAM is paged, this is a "linear 64K boundary", and
;      does not necessarily correspond to a "physical" 64K boundary).
; (b) BIOS unconditionally programs DMAC according to BIOS request.
; (c) QEMM traps then reprograms DMAC for the actual "physical" address,
;     noting the special case here that it also (coincidental to #a)
;     will cross a 64K "physical" boundary.
; (d) BIOS then checks and determines the "linear" boundary problem,
;     and aborts with error "9" (DMA BOUNDARY FAULT).
; (e) DOS then changes its request to read only the 1st sector. (The
;     2nd sector would actually cross the 64K boundary, and DOS reads
;     that one to an internal 70: buffer, then writes it to the user's
;     RAM location).
; (f) BIOS honors DOS's request for 1 sector, programs the DMAC.
; (e) QEMM reprograms the DMAC for the "physical" address.
; (g) BIOS programs the FDC and the (correct) data transfer occurs.
; (h) QEMM (incorrectly) remembers that it was double-buffering (to
;     solve #c, which is no longer an issue), and overwrites the
;     freshly DMAd data with old data from a temporary buffer.
; -----------------------
; There is a work-around for QEMM's problem, which should be harmless
; to the BIOS.  Since writing to the DMAC triggers QEMM, we should only
; do so when we actually intend to do DMA.  In other words, we should
; check for the DMA boundary situation, and abort prior to (needlessly)
; programming the DMAC.
;
;
;---------------------------------
;
; Prior to setting up DMA, confirm that segment overflow won't occur.
;
; The DMA controller only has a 16-bit address register, so will wrap
; to the bottom of the 64K segment if too many bytes are transferred.
; Calculation: translate original ES:BX to a value with format X000:MNPQ
; Then figure out if the desired sectors (512 bytes per) would require
; a final address at X001:RSPQ (ie, incremented segment #).
;

		PUSH	DX

		MOV	DX, SS:[SI+2]		; Expand SEG to 20 bits
		MOV	BL, DH			;
		SHL	DX, 4			;
		SHR	BL, 4			; SEG SHL(4) ---> BL:AX

		ADD	DX, SS:[SI]		; Get SEG SHL(4)+OFFSET
		ADC	BL, 0			;

		ADD	DX, SS:[SI+4]		; Plus #bytes to xfer-1

		MOV	AH, 9			; Assume seg overflow
		JC	SHORT DS_EXIT		; Jump if wrap (bad)

		SUB	DX, SS:[SI+4]		; Restore to start addr

	; All is ok

		CLI
		OUT	DMA_PORT+12,AL		; set the first/last f/f
		IODELAY
		OUT	DMA_PORT+11,AL		; output the mode byte

		SIODELAY			; COMPUADD

		XCHG	AX, DX			; (saved byte)

		OUT	DMA_PORT+4,AL		; output low 2 nibbles of
		XCHG	AL,AH			; address
		IODELAY
		OUT	DMA_PORT+4,AL		; out high 2 nibbles of
		IODELAY				; address.

		XCHG	AX,BX			; save ax, send highest
		OUT	PAGE_PORT,AL		; nibble to page reg
		SIODELAY			; PCMOS

;R147	- starts
ifdef	VSA_VGA
		MOV	DX,481H			;
		MOV	AL,0                    ;
		OUT	DX,AL                   ;
endif	;VSA_VGA
;R147	- ends


		MOV	AX,SS:[SI+4]		; and amount to transfer

		SIODELAY			; PCMOS
		OUT	DMA_PORT+5,AL		; send LSB of xfer to DMA
		MOV	AL,AH
		IODELAY
		OUT	DMA_PORT+5,AL		; send MSB of xfer to DMA
		IODELAY
		STI

		MOV	AL,2			; initialize diskette channel
		OUT	DMA_PORT+10,AL

		XOR	AX,AX			; no error
DS_EXIT:
		POP	DX			;
		RET

DMA_SETUP	ENDP

;[]----------------------------------------------------------------------
;SEND_COMMAND:  Sends a complete command sequence to the NEC controller.
;	INPUT:
;		AH=Command
;		SS:SI=parameters for command
;		BL=number of bytes (maximum of 7)
;	OUTPUT:
;		AH=0 if all bytes sent successfully
;		   80h if timeout error.
;		May destroy any general register.
; DESTROYS CX
;[]----------------------------------------------------------------------

SEND_COMMAND	PROC	NEAR

SC_NEXT_BYTE:
		PUSH	AX			; save value in ah
		MOV	DX,NEC_STAT_PORT
		MOV	BH,WAIT_FDU_SEND_HI	; amount of tme to allow
		MOV	CX,WAIT_FDU_SEND_LO	; for RQM and direction .
		MOV	AX,0C080H		; check bits 6,7 = 10b.
		CALL	WAIT_FOR_PORT		; wait til RQM is on.
		POP	CX			; recover value from stack.
		OR	AH,AH			; if TIMEOUT
		JNZ	SHORT SC_EXIT		; abort operation.

		MOV	AL,CH			; al=output data.
		IODELAY
						; prepare post-write wait.
		INC	DX			; point to data register
		OUT	DX,AL			; send the data
		IODELAY
		DEC	DX			; point back to status

		DEC	BL			; any more bytes to send?
		JZ	SHORT SC_SUCCESS	; exit if done.

		MOV	AH,SS:[SI]		; get next parameter to send
		INC	SI			; point to parameter after this one
		JMP	SHORT SC_NEXT_BYTE
SC_SUCCESS:
		XOR	AX,AX			; ah=0, operation a success
SC_EXIT:
		RET
SEND_COMMAND	ENDP

;[]----------------------------------------------------------------------
;wait_for_results:  This routine called after a read/write/verify or
;		    format command has been issued.  IT:
;			1.  Waits for completion interrupt from controller.
;			2.  Reads status bytes to FDC_RET_CODES
;			3.  Checks FDC_RET_CODES for any errors.
;			4.  Translates NEC errors into BIOS error interface.
;		INPUT:  none.
;		OUTPUT:	FDC_RET_CODES
;			AH=error code if some sort of failure
;			AH=0 if no error.
;[]----------------------------------------------------------------------

WAIT_FOR_RESULTS	PROC	NEAR

		CALL	WAITNECINT
		PUSH	AX			; save RESULTS
		CALL	RESULTS			; always read RESULTS to clean up
		MOV	BH,AH			; save RESULTS
		POP	AX			; recover RESULTS from WAITNECINT
		OR	AH,AH			; see if timeout from RESULTS.
		JNZ	SHORT WFR_EXIT

		MOV	AH,BH			; get return code from RESULTS
		OR	AH,AH			; if non-zero, exit.
		JNZ	SHORT WFR_EXIT
		CALL	ERROR_CHECK		; check for errors, convert NEC
WFR_EXIT:
		RET				; errors to BIOS errors.
WAIT_FOR_RESULTS	ENDP

;[]----------------------------------------------------------------------
;GET_CURCYL:  gets CURCYL variable for drive in al
;	INPUT:  AL= drive #,ES=0
;	OUTPUT: If drive 0, AH=0:494
;		else if drive 1, AH=0:495
;	All other registers preserved.
;[]----------------------------------------------------------------------
GET_CURCYL	PROC	NEAR
		MOV	AH,G_RAM:[CURCYL]
		OR	AL,AL
		JZ	SHORT GC_EXIT
		MOV	AH,G_RAM:CURCYL[1]
GC_EXIT:
		RET
GET_CURCYL	ENDP

;[]----------------------------------------------------------------------
;SET_CURCYL:  sets CURCYL variable for drive in al
;	INPUT:  AL= drive #,ES=0
;	OUTPUT: If drive 0, 0:494=AH
;		else if drive 1, 0:495=AH
;	All other registers preserved.
;[]----------------------------------------------------------------------

SET_CURCYL	PROC	NEAR
		OR	AL,AL			; is it drive 1
		JNZ	SHORT SC_DRIVE_1	; jump if it is
		MOV	G_RAM:[CURCYL],AH	; update drive 0
		JMP	SHORT SCC_EXIT		; return
SC_DRIVE_1:	MOV	G_RAM:CURCYL[1],AH	; update drive 1
SCC_EXIT:	RET
SET_CURCYL	ENDP

;[]-----------------------------------------------------------------------
;GET_PARM - ROUTINE RETRIEVES THE DISK PARAMETER BLOCK PTR AT INT 1EH
;	  - AND USES IT TO RETURN PARAMETER WHOSE INDEX IS PASSED
;	INPUT:
;		AL = INDEX
;	OUTPUT:
;		AL=VALUE
;		AH=0, in case we want to use value as a word operand
;[]-----------------------------------------------------------------------

		PUBLIC	GET_PARM
GET_PARM	PROC	NEAR
		PUSH	DS
		PUSH	SI
		mov	si,G_RAM
		mov	ds,si
		xor	ah,ah
		mov	si,ax
		add	si,offset cs:FD_BIOS_PARMS
		mov	al,cs:[si]
		POP	SI
		POP	DS
		ASSUME	DS:NOTHING
		RET
GET_PARM	ENDP

		include	cpurun.asm

		CK_ORG	0F600h
;***********************************************************************;
;									;
;	The following code reserve for Ct_Very_Early_Init		;
;									;
;			<<< Don't Use Please... >>>			;
;									;
;***********************************************************************;

		CK_ORG	0F80BH
		dw	offset DGROUP:MEMORY_PRESENCE	;do memory detection

		CK_ORG	0F80DH

;R97 - start
ifdef	P6_BIOS_ONLY
		jmp	short BootBlock_POST
                CK_ORG  0F820H
		include	CtEscdRd.inc
endif;	P6_BIOS_ONLY
;R97 - end

		public	BootBlock_POST
BootBlock_POST	PROC	Near
		cli
		cld

		mov	bp,BootPOST_data		;BootBlock data area
		mov	Error_Flag,0			;Clear Error_Flag

;[]==============================================================[]
;
;	Initialize various chips...
;
;[]==============================================================[]

		POST_CODE 01h

; Clear base memory area (0000:0000 - 9000:FFFFh)
		xor	bx,bx
		xor	di,di
		xor	ax,ax
		cld
@@:
		mov	es,bx
		mov	cx,8000h
		rep	stosw
		add	bx,1000h
		cmp	bx,0a000h
		jb	short @B

;[]==============================================================[]
;
;	Initial keyboard controller
;
;[]==============================================================[]

		POST_CODE 05h

		in	al,STAT8042
		test	al,4
		jnz	Post5_Exit
;
;	Clear 8042 interface...
;

		call	Enable_KB_Controller	;R118
		jmp	Post5_Exit		;R118

Enable_KB_Controller	label	near		;R118

		xor	cx,cx
p5_11:
		in	al,STAT8042		; see if any data
		NEWIODELAY

		test	al,IBF_8042+OBF_8042	; any input and/or output?
		jz	short p5_2_1		; no, next part of test

		test	al,OBF_8042		; input?
		jz	short p5_12		; no, just keep waiting

		in	al,DATA8042		; yes, clear out data
		NEWIODELAY
p5_12:
		loop	short p5_11
		jmp	short p5_91		; failure of 8042

p5_2_1:

;
;	Tell 8042 to do self-test
;
		mov	bl,10

p5_2:
		mov	al,TEST_KBRD
		out	STAT8042,al		; send self-test cmd.
		NEWIODELAY

		call	Buffer_8042_Full	; wait for buffer to clear
		jnz	short p5_91		; failure of 8042

		call	Out_8042_Full		; wait for 8042 output to be full
		jz	short p5_91		; yes, error...

		in	al,DATA8042
		NEWIODELAY

		cmp	al,055h			; any errors on keyboard ctlr?
		je	short p5_911
		dec	bl
		jnz	short P5_2
p5_911:

; Auto-switch delay

		mov	cx,8000h
		loop	short $

;
;	Set 8042 command byte
;
p5_3:
		mov	al,60h			; 60h = write 8042 command byte
		out	STAT8042,al
		NEWIODELAY

		call	Buffer_8042_Full	; wait for input buffer to be empty

		jnz	short p5_91		; timeout error...

		mov	al,45h			; AT interface, keyboard enabled, system flag
		out	DATA8042,al
		NEWIODELAY

		call	Buffer_8042_Full	; wait for input buffer to be empty
		jnz	short p5_91		; timeout error...

		mov	al,ENABLE_KBRD		;enable keyboard
		out	STAT8042,al
		newiodelay

		call	Buffer_8042_Full	; wait for input buffer to be empty

		jmp	short @F

;
;	Return with an error
;
p5_91:
		or	Error_Flag,KbdCtrl_Err
@@:

;
;	Keyboard self-test
;

		mov	dl,15			; bl = number of retries
p5_4:

		mov	al,0adh			; disable keyboard interface
		call	Out_8042
		call	Buffer_8042_Full	; wait still command received

		in	al,DATA8042
		NEWIODELAY

		mov	al,KB_RESET		; kbd self test cmd
		out	DATA8042,al
		NEWIODELAY

		call	Buffer_8042_Full	; wait still command received
		jnz	short p5_91_1

		call	Out_8042_Full		; wait still output buffer full
		jz	short p5_91_1

		xor	bx,bx
		mov	cx,256*2		; wait 512*30 microseconds = 6.7 milliseconds
		call	Wait_Refresh

		in	al,DATA8042		; get returned value...
		NEWIODELAY

		cmp	al,KB_ACK		; ack?
		je	short p5_41		; yes...

p5_40:
		dec	dl			; retries left?
		jnz	short p5_4		; yes...
		jmp	short p5_91_1

;
;	Check return code
;
p5_41:

		mov	cx,10
delay_for_kbd_reset:
		push	cx
		xor	bx,bx
		mov	cx,256*2		; wait 512*30 microseconds = 6.7 milliseconds
		call	wait_refresh
		pop	cx

		call	Out_8042_Full		; wait for output buffer to be full

		loopz	delay_for_kbd_reset	; R126

		in	al,DATA8042
		NEWIODELAY
		cmp	al,0aah			; all OK?

		jne	short p5_40		; no, error
;
;	Return with no error
;
p5_9:
		jmp	short Keybord_Init_Exit
p5_91_1:
		or	Error_Flag,KeyBoard_Err
Keybord_Init_Exit:

		mov	al,0aeh			; enable keyboard interface
		call	Out_8042
		call	Buffer_8042_Full	; wait til command received

		retn				;R118

Post5_Exit:

;[]==============================================================[]
;
;	Initialize int. vectors (0-77h) to the spurious interrupt
;	handler. Then initialize 00h-1fh to their proper places.
;
;[]==============================================================[]

		POST_CODE 12

		mov	ax,cs
		mov	ds,ax

;R161 start
;
;	Initialize vectors 00-77h to SPURIOUS_INT_HDLR
;

		shl	eax,16			;store code segment to high word
		mov	ax,offset DGROUP:SPURIOUS_INT_HDLR
		mov	cx,78h
		xor	di,di			;di = start of segment
		mov	es,di			;es = first segment
		rep	stosd			;reset all Int vector
		mov	dword ptr es:[1fh*4],0	;set int 1fh = 0 to indicate
						;no extended characters installed.
;R161 end
;
;	Initialize vectors 00-1fh to the real handlers
;

;R161		mov	cx,20h
;R161		mov	ax,cs
;R161		mov	si,offset DGROUP:Int_Tbl
;R161		xor	di,di			; di = start of segment
;R161		mov	es,di			; es = first segment
;R161p10_21:		movsw				; load next offset
;R161		stosw				; load segment in ax
;R161		loop	short p10_21
;R161		mov	word ptr es:[di-2],0	; set int 1fh segment = 0 to indicate
;R161						; no extended characters installed.
;R161 start
		lea	si,DGROUP:Int_Tbl
p10_21:
		lodsb				;load next offset
		cmp	al,0ffh			;over?
		je	short Init_Vect_Over	;Yes,skip
		movzx	di,al			;get vector number
		shl	di,2			;set to coresspond offset
		movsw				;load offset from DS:[SI]
		mov	ax,cs			;get segment
		stosw				;load segment
		jmp	short p10_21		;next cycle
Init_Vect_Over:
;R161 end

;R161;
;R161;	Initialize vectors 20h-6fh to the spurious interrupt handler
;R161;
;R161
;R161p10_1:
;R161		shl	eax,10h
;R161
;R161		mov	ax, offset DGROUP:Iret_vect
;R161		mov	ecx,50h			; cx = number of vectors
;R161		rep	stosd			; store all vectors...
;R161
;R161;
;R161;	Initialize vectors 70h-77h to the spurious interrupt handler
;R161;
;R161		mov	ax,offset DGROUP:SPURIOUS_INT_HDLR
;R161		mov	ecx,8			; cx = number of vectors
;R161		rep	stosd			; store all vectors...

		mov	al,10111100b		;Enable IRQ 0,1,6
		out	a8259+1,al
		sti

;[]==============================================================[]
;
;	Initial VGA bios controller
;	Display bios version and company name
;
;[]==============================================================[]

		POST_CODE 0dh

ifndef	No_Support_PCI_VGA_in_Bootblock		;R150A
ifdef	Bootblock_16K_Support			;R150
		extrn	InitPciVga:near		;R186
		call	InitPciVga		;R150 Check PCI/AGP Vga
endif	;Bootblock_16K_Support			;R150
endif	;No_Support_PCI_VGA_in_Bootblock	;R150A

	;Initial VGA chip if installed

		mov	ax,0c000h		;Video ROM segment address
		mov	ds,ax
		cmp	word ptr ds:[0],0aa55h	;Video ROM existed ?
		je	short Video_found	;yes, Initial VGA card

	;Send beep out if no VGA found
		cli
		mov	dx,102h
;
; 	Long beeps
;
LONG_B:		MOV	BL,6
		CALL	SND_SPKR

		LOOP	SHORT $
		DEC	DH
		JNZ	SHORT LONG_B
;
;	Short beeps
;
SHORT_B:	MOV	BL,1
		CALL	SND_SPKR

		LOOP	SHORT $
		DEC	DL
		JNZ	SHORT SHORT_B

		LOOP	SHORT $
		LOOP	SHORT $

		sti
		jmp	short Video_init_skip
Video_found:
	;VGA found, initial it by calling address c000:0003
		push	bp
		db	09ah		;far call instrution code
		dw	3		;far call offset
		dw	0c000h		;far call segment
		pop	bp

		mov	ax,3		;clear screen and set mode 3
		int	10h

	;Display copyright message
		lea	ax,CopyRit_Msg
		mov	cx,CopyRit_Msg_Len
		xor	dx,dx
		call	Display_Str
Video_init_skip:

;[]==============================================================[]
;
;	Report error
;
;[]==============================================================[]

		lea	ax,BIOS_CKSM_ERROR_MSG
		mov	cx,BIOS_CKSM_ERROR_MSG_Len
		mov	dx,0ff01h
		call	Display_Str

		test	Error_Flag,KbdCtrl_Err
		jz	short @F
		lea	ax,KCTRL_ERR_MSG
		mov	cx,KCTRL_ERR_MSG_Len
		mov	dx,0ff01h
		call	Display_Str
@@:
		test	Error_Flag,KeyBoard_Err
		jz	short @F
		lea	ax,KBD_ERR_MSG
		mov	cx,KBD_ERR_MSG_Len
		mov	dx,0ff01h
		call	Display_Str
@@:

;[]==============================================================[]
;
;	Scan floppy and media capacity
;
;[]==============================================================[]

		POST_CODE 41h

;R186 start
ifdef	Bootblock_16K_Support
ifdef	Support_ATAPI_In_BOOTROM
		extrn	Scan_ATAPI_Drive:near
		call	Scan_ATAPI_Drive
		jnc	Goto_Boot
endif	;Support_ATAPI_In_BOOTROM
endif	;Bootblock_16K_Support
;R186 end
	;Enable floppy controller for onboard super I/O for booting
		call	Enable_SuperIO_Fdd		;in earlyio.asm ;R115

;R114 - start
ifdef	P6_BIOS_ONLY
;disable local APIC , otherwise IRQ can not generate properly due to
;APIC enabled in P6 CPU.
		mov	ecx,27			;MSR index 27
		RDMSR
		and	ah,NOT 08H		;disable CPU APIC
		WRMSR
endif;	P6_BIOS_ONLY
;R114 - end

	;Display message for auto-detection floppy media
		lea	ax,Detect_Disk_Msg
		mov	cx,Detect_Disk_Msg_Len
		mov	dx,0ff01h
		call	Display_Str

		mov	ax,G_RAM
		mov	ds,ax
		assume	ds:G_RAM

		mov	byte ptr ds:[DCAPABILITY],6  	;40:8fh
New_Scan:
;Set drive parameter table
		mov	ax,offset cs:FD_BIOS_PARMS
		cli
		mov	word ptr ds:[Disk_Parm_Ptr],ax
		mov	word ptr ds:[Disk_Parm_Ptr+2],cs
		sti

		xor	ax,ax
		mov	es,ax				; set to load at 0:offset Boot

		lea	di,cs:Disk_Parms
		lea	si,cs:Media_MSG
Next_Drive:
		mov	ah,cs:[di]			;Force drive A is 1.2 MB
;Set drive capacity
		mov	al,FLOPPY_TYPE NMI_OFF	;al = FLOPPY_TYPE CMOS index
		call	Set_Cmos
		shr	al,4
		mov	byte ptr ds:[Floppy_CMOS_Type],al

		mov	al,cs:[di+1]
		mov	MOST_RECENT_RATE,al    		;40:[8bh]
		mov	al,cs:[di+2]
		mov	CURRENT_MEDIA,al       		;40:[90h]

Read_again:
		cmp	si,offset cs:Media_MSG
		jne	short Scan_Start
		xor	ah,ah
		int	13h				; reset disk
		jnc	short Reset_OK

No_Floppy:
	;Show message for Floppy drive not found
		lea	ax,Floppy_err_Msg
		mov	cx,Floppy_err_Msg_Len
		mov	dx,0ff01h
		call	Display_Str

	;Endless beep out if floppy drive not found
@@:
		mov	bl,1			; beep on override
		mov	cx,300h
		call	SND_SPKR_TONE
		xor	cx,cx
		loop	short $
		jmp	short @B

	;Boot to Floppy if media found
Reset_OK:
		mov	ax,0201h   		; read boot record
		lea	bx,Boot			; location to put boot sector
		mov	cx,1	   		; set to read one sector
		xor	dx,dx	   		; drive A:
		int	13h			; read sector
		jnc	short Scan_Start	; read OK ?

		cmp	ah,40h			; error code 40H, bad seek
		je	short No_Floppy
		cmp	ah,80h			; time out ?
		je	short Disk_Fail
Scan_Start:
		xor	ah,ah
		int	13h		    	; reset disk

	;read the maximum sector to check media type
	; 17th sector for 1.44Mb , 10th sector for 1.2Mb
		mov	ax,0201h
		lea	bx,Boot
		mov	cx,word ptr cs:[di+3]	; get maximum sector
		xor	dx,dx		       	; drive A:
		int	13h		       	; media read OK ?
		jnc	short Scan_Disk_Exit   	; Yes,jump

		add	di,Disk_Parm_Width	; try next media type
		cmp	di,offset cs:Disk_Parms_End	;end of media table ?
		je	short Disk_Fail		; nothing found
		add	word ptr ds:[Disk_Parm_Ptr],size FD_BIOS_PARMS
		add	si,Media_MSG_LEN
		jmp	Next_Drive
Disk_Fail:
	;Display message for no bootable media found
		lea	ax,Bad_Disk_Msg
		add	ax,19
		mov	cx,Bad_Disk_Msg_Len
		sub	cx,19
		call	Disk_Fail_Routine

		cmp	di,offset cs:Disk_Parms_End
		je	short @F
		jmp	Read_again
@@:
		jmp	New_Scan

Scan_Disk_Exit:
	;Display media capacity
		lea	ax,Disk_Msg
		mov	cx,Disk_Msg_Len
		mov	dx,0ff02h
		call	Display_Str

		mov	ax,si
		mov	cx,Media_Msg_Len
		mov	dx,0fe00h
		call	Display_Str

		assume	ds:NOTHING

Goto_Boot:					;R186
;[]==============================================================[]
;
;	OS Boot or force from floppy read a sector to program flash
;
;[]==============================================================[]

		mov	ax,G_RAM
		mov	ds,ax
		assume	ds:G_RAM

; Setup BIOS memory 40: area
		mov	word ptr G_RAM:[HARDWARE],21h		;install hardware
		mov	word ptr G_RAM:[SIZE_SYSRAM],280h	;memory size = 640 Kb
		mov	word ptr G_RAM:[CON_LLINE],18h		;Video rows

		mov	word ptr G_RAM:[KBD_BUF_LOCN],1eh	;Kbd buffer start offset pointer
		mov	word ptr G_RAM:[KBD_BUFEND_LOCN],3eh	;Kbd buffer end offset pointer

; clear any pending keystroke and kb queue buffer
		mov	word ptr G_RAM:[Ptr_Kbd_Buf_Hd],offset Buf_For_Kbd-400h
		mov	word ptr G_RAM:[Ptr_Kbd_Buf_Tl],offset Buf_For_Kbd-400h
		in	al,DATA8042

		POST_CODE 0ffh
		int	19h

BootBlock_POST	ENDP

		public	Display_Str	;R186
Display_Str	Proc	Near

;	Entry :	AX - String offset
;		CX - String length
;		DH - Display row position, if = 0ffh then this row plus DL
;						0feh then don't move cursor
;		DL - Display column position

		push	es
		push	ax
		push	bx
		push	bp

		mov	bp,ax
		mov	bx,7
		cmp	dh,0feh
		jb	short Not_Special
		push	cx
		push	dx
		mov	ah,3
		int	10h
		pop	ax
		je	short @F
		add	dh,al
		xor	dl,dl

		cmp	dh,24
		jbe	short @F
		push	bx
		push	dx
		mov	ax,601h
		mov	bh,7
		xor	cx,cx
		mov	dx,184fh
		int	10h
		pop	dx
		pop	bx
		mov	dh,24
@@:
		pop	cx
Not_Special:
		mov	ax,0f000h
		mov	es,ax
		mov	ax,1301h
		int	10h

		pop	bp
		pop	bx
		pop	ax
		pop	es
		ret
Display_Str	EndP

;R161INT_TBL:	DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; DIVIDE BY ZERO
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT01
;R161		DW	OFFSET DGROUP:NMI_VECT		; INT02
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; SINGLE STEP
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT04
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; PRINT SCREEN
;R161		DW	OFFSET DGROUP:LOADALL		; INVALID OP-CODE
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT07
;R161
;R161VECTOR_TABLE:	DW	OFFSET DGROUP:TIMER_VECT	; INT08
;R161		DW	OFFSET DGROUP:KBDINT_VECT	; INT09
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT0A
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT0B
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT0C
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT0D
;R161		DW	OFFSET DGROUP:DSKINT_VECT	; INT0E
;R161		DW	OFFSET DGROUP:SPURIOUS_INT_HDLR	; INT0F
;R161
;R161INT_TBL_HALF:	DW	OFFSET DGROUP:IRET_VECT		; INT10
;R161		DW	OFFSET DGROUP:EQ_VECT		; INT11
;R161		DW	OFFSET DGROUP:MEM_SZ_VECT	; INT12
;R161		DW	OFFSET DGROUP:DSK_VECT		; INT13
;R161		DW	OFFSET DGROUP:IRET_VECT		; INT14
;R161		DW	OFFSET DGROUP:Multi_Service	; INT15
;R161		DW	OFFSET DGROUP:KBD_VECT		; INT16
;R161		DW	OFFSET DGROUP:IRET_VECT		; INT17
;R161		DW	OFFSET DGROUP:IRET_VECT		; INT18
;R161		DW	OFFSET DGROUP:INT19_VECT	; INT19
;R161;R150		DW	OFFSET DGROUP:IRET_VECT		; INT1A
;R161		DW	OFFSET DGROUP:INT1A_VECT 	; INT1A	;R150
;R161		DW	OFFSET DGROUP:IRET_VECT		; INT1B
;R161		DW	OFFSET DGROUP:IRET_VECT		; INT1C
;R161		DW	OFFSET DGROUP:IRET_VECT		; INT1D
;R161		DW	OFFSET DGROUP:FD_BIOS_PARMS	; INT1E
;R161		DW	0				; INT1F

;R161 start
INT_TBL:	db	2				; INT02
		DW	OFFSET DGROUP:NMI_VECT		; INT02 offset
		db	6				; INT06
		DW	OFFSET DGROUP:LOADALL		; INVALID OP-CODE
		db	8				; INT08
		DW	OFFSET DGROUP:TIMER_VECT	; INT08 offset
		db	9				; INT09
		DW	OFFSET DGROUP:KBDINT_VECT	; INT09 offset
		db	0eh				; INT0E
		DW	OFFSET DGROUP:DSKINT_VECT	; INT0E offset
		db	11h				; INT11
		DW	OFFSET DGROUP:EQ_VECT		; INT11 offset
		db	12h				; INT12
		DW	OFFSET DGROUP:MEM_SZ_VECT	; INT12 offset
		db	13h				; INT13
		DW	OFFSET DGROUP:DSK_VECT		; INT13 offset
		db	15h				; INT15
		DW	OFFSET DGROUP:Multi_Service	; INT15 offset
		db	16h				; INT16
		DW	OFFSET DGROUP:KBD_VECT		; INT16 offset
		db	19h				; INT19
		DW	OFFSET DGROUP:INT19_VECT	; INT19 offset
		db	1Ah				; INT1A
		DW	OFFSET DGROUP:INT1A_VECT 	; INT1A offset
		db	1Eh				; INT1E
		DW	OFFSET DGROUP:FD_BIOS_PARMS	; INT1E offset
		db	0ffh				; over
;R161 end

IRET_VECT	PROC	NEAR
		IRET
IRET_VECT	ENDP

;********************************************************
;Name:   	equip
;Entry:  	INT 11H
;Input:
;Output: 	(ax) = equipment configuration as follows
;   	    	bit 0=1= diskette drive(s) configured
;   	    	bit 1 not used
;   	    	bit 2,3 (=00=64k,=01=128k,=10=192k,=11=256k) ram installed
;   	    	bit 4,5 =IPL video mode
;   	    	        =00=unused
;   	    	    	   =01=40x25 BW using color controller
;   	    	    	   =02=80x25 BW using color controller
;   	    	    	   =03=80x25 BW using BW controller
;   	    	bit 6,7 =number of diskette drives
;
;   	    	    	   =00=1 drive
;   	    	    	   =01=2 drives
;   	    	    	   =10=3 drives
;   	    	    	   =11=4 drives
;   	    	bit 8 unused
;   	    	bit 9,10,11 = number of RS232 cards configured
;   	    	bit 12 = game controller configured
;   	    	bit 13 not used
;   	    	bit 14,15 number of printers configured
;
;	EAX bit 24 set (=1) means Weitek Abacus coprocessor present
;
;Description:
;
;equip will:
;1. 	save environment
;2. 	return the equipment flag from memory word location 0:410h.
;3. 	restore environment
;4. 	return to POI
;*******************************************************

EQ_VECT		PROC	NEAR
		PUSH	DS			; save DS
		ASSUME	DS:G_RAM		; N3.03
		MOV	AX,G_RAM		; segment selector
		MOV	DS,AX
		MOV	AX,[HARDWARE]	; and get current settings
		POP	DS
		IRET
EQ_VECT		ENDP

;*****************************************
;Name:   	Memory_Size
;Entry:  	INT 12H
;Input:  	none
;Output: 	ax=number of 1K blocks
;Description:
;
;Memory_Size will:
;1. 	save environment
;2. 	return the memory size from memory word location 0:413h
;3. 	restore environment
;4. 	return to POI
;************************************************

MEM_SZ_VECT	PROC	NEAR
		PUSH	DS			; save DS
		ASSUME	DS:G_RAM		; N3.03
		MOV	AX,G_RAM		; segment selector
		MOV	DS,AX
		MOV	AX,[SIZE_SYSRAM]	; and get current settings
		POP	DS
		IRET
MEM_SZ_VECT	ENDP

;[]==============================================================[]
;
;NMI_VECT:
;
;	Compatibility ORG for NMI handler.
;
;Saves:	NONE
;Entry:	NONE
;Exit:	NONE
;[]==============================================================[]
NMI_VECT	PROC	NEAR
comment %

;R14		jmp	Check_In_Post
		jmp	Check_In_Post1	;R14
Normal_Nmi:

		PUSH	AX

		extrn	Clear_Ibm_Parity:near
		call	Clear_Ibm_Parity

ifndef	NO_PARITY_DURING_MEM_SIZING
		push	dx
		POST_CODE 0B1H
		pop	dx
endif;	NO_PARITY_DURING_MEM_SIZING

IF BUS_TYPE EQ EISA_BUS
                call    Eisa_NMI_Chk
ENDIF ;BUS_TYPE

		MOV	AL,0FH NMI_OFF		; release nmi - no parity
		CALL	GET_CMOS

		; CLEAR PARITY, CHECK PARITY AH HAS OLD PORT READ

		IN	AL,SYS1			; get value from port
		MOV	AH,AL			; save value

		CALL	CLEAR_PARITY		; 303A

		TEST	AH,PARITY_CHECK		; and see if parity
		JNE	SHORT NMI_1

		MOV	AL,AH			; set status again
		NEWIODELAY
		OUT	SYS1,AL			; CLEARING OF PARITY BITS

		MOV	AL,0FH NMI_ON
		CALL	GET_CMOS

		POP	AX
		IRET

		ALIGN	4			; N3.03
NMI_1:
	;AX IS ON STACK FROM ABOVE
		PUSH	BX
		PUSH	CX
		PUSH	DX
		PUSH	DI
		PUSH	SI
		PUSH	DS			; FOR POSSIBLE RETURN LATER
	; first set stack to first 64k
		PUSH	AX			; save value from 8042
						; previous value is in ah!!
		MOV	AL,DISABLE_KBRD		; disable keyboard
		OUT	STAT8042,AL
		CALL	BUFFER_8042_FULL	; and wait

		IN	AL,DATA8042		; get current setting
		NEWIODELAY
		MOV	AL,0C0H
		OUT	STAT8042,AL
		CALL	BUFFER_8042_FULL	; and wait
		CALL	OUT_8042_FULL

		MOV	AX,G_RAM
		MOV	DS,AX			; set segment
		ASSUME	DS:G_RAM

		MOV	AL,[CON_MODE]	; and get crt mode
		INT	10H			; clear screen

		POP	AX			; recover value
		PUSH	AX			; SAVE IN CASE F1 KEY PRESSED

		TEST	AL,IOCHANNEL_CHECK	; parity error?
		JZ	SHORT T1		; NO, PARITY ERROR

		MOV	SI,OFFSET DGROUP:IO_PAR_ERR

		TEST	AL,MEMORY_CHECK
		JZ	SHORT T2

		CALL	WR_STR_TTY		; PRINT THIS MESSAGE
		; FALL THROUGH AND PRINT OTHER MESSAGE

T1:		MOV	SI,OFFSET DGROUP:PL_PAR_ERR
T2:		CALL	WR_STR_TTY

		MOV	AL,0EFH NMI_OFF		; disable nmi
		OUT	CMOS,AL

		CALL	ENABLE_PARITY

		MOV	DX,[SIZE_SYSRAM]	; get amount of memory and
		SHR	DX,1			; in 64k banks
		MOV	DI,DX			; and save
		XOR	BX,BX			; see where error is

		ALIGN	4			; N3.03
LL1:		MOV	DS,BX
		ASSUME	DS:NOTHING

		XOR	SI,SI
		MOV	CX,8000H
		CALL	ENABLE_PARITY		; set parity toggle

		CLD
		REP	LODSW

		IN	AL,SYS1			; see if error in bank
		AND	AL,PARITY_CHECK		; PARITY
		JNZ	SHORT LL2		; this bank has error

		ADD	BX,1000H		; bank address
		DEC	DX
		JNZ	SHORT LL1		; next bank

LL2:		MOV	SI,OFFSET DGROUP:STRSEGMENT
		CALL	WR_STR_TTY

		CMP	DI,BX			; see if error found
		JE	SHORT LL3

		PUSH	BX
		CALL	PRINT_HEX
		POP	BX

		CALL	ENABLE_PARITY
		JMP	SHORT NMI_USER_OPTION

LL3:		MOV	SI,OFFSET DGROUP:PAR_UNKNOWN	; N3.03
		CALL	WR_STR_TTY

NMI_USER_OPTION:
		MOV	SI,OFFSET DGROUP:NMI_OPTION_MSG
		CALL	WR_STR_TTY

NMI_USER_WAIT:
		;POP	AX	ON STACK FROM NMI_1, WHO CARES NOW...
		XOR	AH,AH
		INT	16H
		CMP	AH,3BH			; WAIT FOR 'F1' KEY
		JE	SHORT NMI_PROCESS_F1
		CMP	AH,3CH			; WAIT FOR 'F2' KEY
		JE	SHORT NMI_PROCESS_F2
		MOV	SI,OFFSET DGROUP:NMI_HALT_MSG
		CALL	WR_STR_TTY

		POST_CODE 0B2h 			;E1H confuse with setup code
SYSTEM_HALT:	STI
		HLT
		JMP	SHORT SYSTEM_HALT

NMI_PROCESS_F1:					; NOTE: DUPLICATE PREVIOUS IRET
		;SET FLAG
; AL IS RECOVERED FROM ABOVE TO MAKE SURE THAT WE DON'T DISABLE IO CHECK
; FOR AUTOSWITCH CARDS WHEN WE DIDN'T MEAN TO.
; WE MUST FIRST ESTABLISH THE OLD ENABLE BITS,
; SEE IF THERE IS A NEW ENABLE BIT, THEN SET THE DISABLE/ENABLE BITS
; DON'T FORGET THE REV0/REV1 LOGIC FOR NEAT...REV0 KIND OF WORKS REV1 WORKS
; REVERSE LOGIC PLACEMENT OF ENABLE/DISABLE BITS TO XOR
;
		CALL	CLEAR_PARITY		; DON'T RE-ENABLE
		MOV	CH,AL			; SAVE FROM IMMENENT DESTRUCTION
		AND	CH,NOT 0CH		; GET RID OF ENABLE BITS
		POP	AX			; RESTORE FROM NMI_1
		MOV	AL,AH			; FIRST VALUE IS SAVED IN AH!!!
		AND	AH,00CH			; GET OLD ENABLE BITS
		AND	AL,0C0H			; GET NEW CHECK BIT(S)
; CHECK BITS AND ENABLE BITS APPEAR TO BE REVERSED WITH REV 0
		SHR	AL,4			; ROTATE TO ENABLE POSITION
		MOV	BL,AL			; SWAP BITS 3 2
		SHR	BL,1			; MOVE BIT 3 TO BIT 2
		AND	BL,04H			; MASK BIT 2
		SHL	AL,1			; MOVE BIT 2 TO BIT 3
		AND	AL,08H			; MASK BIT 3
		OR	AL,BL			; PLACE BITS
		OR	AL,AH			; PUT OLD DISABLED BIT(S) INTO AL
						; DISABLED BITS ARE 1
		OR	AL,CH			; PUT OTHER BITS FROM SYS1 IN PLACE
		OUT	SYS1,AL			; PLACE ON PORT

		MOV	AL,0EH NMI_ON
		CALL	GET_CMOS		; RE-ENABLE NMI

		POP	DS			; RESTORE ENVIRONMENT FROM NMI_1
		POP	SI
		POP	DI
		POP	DX
		POP	CX
		POP	BX
		POP	AX			; RESTORE FROM NMI_HDLR ENTRY
		STI				; JUST IN CASE
		IRET

NMI_PROCESS_F2:
		;POP	AX	ON STACK FROM NMI_1, WHO CARES NOW...
%
		JMP	REDO
NMI_VECT	ENDP

;***********************************************************************
;
;	The following code emulate LOADALL instruction on 386 processor
;
;***********************************************************************

;[]==============================================================[]
;
;LOADALL:
;
; Emulation of 286 opcode 0F 05 - LOADALL instruction.
;
; The LOADALL instruction is an undocumented function of the 286, designed
; to aid Intel in debugging the 286.  This opcode is NOT implemented on the
; 386, and executing a LOADALL instruction on the 386 results in an
; invalid-opcode fault, exception #6.
;
; (We are prompted to emulate LOADALL because some hackers at MicroSoft
; used it in OS2, causing it to crash on 386s.)
;
; The LOADALL instruction loads all 286 registers from a user prepared
; table at 800:0.  This includes the descriptor caches, lending to a
; variety of weird things that can be done.  We concentrate on 2 of the
; more useful things, since it is impossible to emulate the instruction
; exactly.  (Impossible, unless Intel has hidden an equivalent 386
; instruction somewhere).
;
; 1) The CPU can be made to address regions of RAM above 1M while still
;    in REAL MODE, simply by forcing DS/ES segment register descriptor
;    caches to point above 1M.  Note the visible selector portion (the
;    16 bit segment register value) need not contain anything valid or
;    consistent with its associated cache.  Until the segment register
;    is reloaded, the CPU will adhere to the Limit/Base/Access-Rights
;    values in the cache.
;
;    Our treatment of this case:
;	- Load all general registers per table
;	- Assume SS remains in REAL space, loading the SELECTOR
;	  (ignoring descriptor cache) from the table
;	- Deduce whether DS/ES is to use the SELECTOR (ie, REAL compatible)
;	  or the LIMIT/BASE/ACCESS descriptor cache (ie, PROTECTED).
;	  We determine this by evaluating if the BASE points to the same
;	  physical location as the SELECTOR.
;	    --If so, the SELECTOR is REAL-compatible; we use it "as is".
;	    --Else, we use the LIMIT/BASE/ACCESS cache value, by creating
;	      a temporary GDT, entering PROTECTED mode, loading DS/ES
;	      via the temporary GDT, then returning to REAL mode.  Note
;	      this will in general leave the visible segment register with
;	      a value different than the user's table value.  But it works
;	      ok, since the L/B/A value is what the user wants.  Note als0,
;	      the instant the user reloads that segment register, the L/B/A
;	      is reloaded by the CPU with REAL-compatible values.
;	- Assume CS remains in REAL space, loading the SELECTOR
;	  (ignoring descriptor cache) from the table (upon exit, via IRET)
;	- All special PROTECTED mode support registers (TSSR,TR,LDTR,GDTR)
;	  are preserved, not updated, except GDT.  Since we trash GDTR
;	  by building a temporary GDT, we do load it per table entry.
;
; 2) The CPU can be put into PROTECTED MODE, with all registers pre-loaded.
;    There is no real benefit to entering PROTECTED MODE via this
;    unconventional method, unless something very weird is being done.
;    If so, we probably don't emulate it correctly anyway.
;
;    Our treatment of this case is much simpler than the 1st.  We load
;    up all registers from the table, trusting that the GDT reference
;    is valid (and that, if the GDT is in an odd-MegaByte bank, the
;    gate A20 has been enabled by the user).
;
;
; The LOADALL table has this format:
;
; Physical address (Hex)	CPU Register
; --------------		----------------
; 800-805			none
; 806-807			MSW
; 808-815			none
; 816-817			TR   (selector)
; 818-819			FLAGS
; 81A-81B			IP
; 81C-81D			LDTR  (selector)
; 81E-81F			DS
; 820-821			SS
; 822-823			CS
; 824-825			ES
; 826-827			DI
; 828-829			SI
; 82A-82B			BP
; 82C-82D			SP
; 82E-82F			BX
; 830-831			DX
; 832-833			CX
; 834-835			AX
; 836-838,839,83A-83B 		ES descriptor cache: base, access, limit
; 83C-83E,83F,840-841		CS descriptor cache: base, access, limit
; 842-844,845,846-847		SS descriptor cache: base, access, limit
; 848-84A,84B,84C-84D		DS descriptor cache: base, access, limit
; 84E-850,851,852-853		GDTR          cache: base, xxxxxx, limit
; 854-856,857,858-59		LDT           cache: base, xxxxxx, limit
; 85A-85C,85D,85E-85F		IDTR          cache: base, xxxxxx, limit
; 860-862,863,864-865		TSS           cache: base, xxxxxx, limit
;
;[]==============================================================[]

        	PUBLIC	LOADALL
LOADALL		PROC	NEAR

;
; Did a LOADALL instruction cause this INT6 ?
;

		PUSH	BP
		MOV	BP, SP
		PUSH	SI
		PUSH	DS
		LDS	SI, DWORD PTR SS:[BP+2]
		CMP	WORD PTR DS:[SI], 050FH
		JE	SHORT DO_LOADALL

; Maybe 0F 04 - Kill CPU?

		CMP	WORD PTR DS:[SI], 040FH		; 286 KILL-CPU opcode
		JE	SHORT KILL_CPU

; Maybe fault from LOCK instruction?

		CMP	BYTE PTR DS:[SI], 0F0H		; LOCK opcode
		JE	SHORT INT6_INC

; Maybe invalid REP/REPNE ?

		CMP	BYTE PTR DS:[SI], 0F2H
		JE	SHORT INT6_INC

; Maybe invalid REPE ?

		CMP	BYTE PTR DS:[SI], 0F3H
		JNE	SHORT INT6_EXIT

INT6_INC:
		INC	SI
		MOV	WORD PTR SS:[BP+2], SI

INT6_EXIT:
; Well, maybe somebody did INT6 just for fun.

		POP	DS
		POP	SI
		POP	BP
		IRET

KILL_CPU:
		JMP	KILL_MACHINE


Loadall_GDTaddr	DW	4*8		;limit GDT
		DD	800h		;base address for GDT index 00h

Loadall_GDT	DW	0FFFFh,0,9B0Fh,0;index 08h BIOS (CS)-descriptor
		DW	0,0,0,0		;index 10h USER (ES)-descriptor
		DW	0,0,0,0		;index 18h USER (DS)-descriptor

DO_LOADALL:
		xor	ax,ax
		mov	ds,ax			;DS set to loadall image
		mov	es,ax			;ES set to loadall image
		mov	ss,word ptr ds:[820h]	;set SS:SP to user stack
		mov	sp,word ptr ds:[82Ch]
		push	word ptr ds:[818h]	;put flag -> [SP]
		push	word ptr ds:[822h]	;    CS	  -> [SP-2]
		push	word ptr ds:[81Ah]	;    IP   -> [SP-4] for IRET
;
		mov	di,808h			;preserve user's MSW
		mov 	si,offset DGROUP:loadall_GDT
		mov	cx,3*8
		cld
		rep	movs byte ptr [di],cs:[si] ;temporary GDT into ldallbuf
;
		mov	dx,word ptr ds:[806h]	;save machine status word
;
		mov	si,word ptr ds:[836h][4];ES_limit0_15 to loadall_table
		mov	word ptr ds:[810h],si
		mov	si,word ptr ds:[836h][0];ES_base0_15 to loadall_table
		mov	word ptr ds:[812h],si
		mov	bl,byte ptr ds:[836h][2];ES_base16_23
		mov	bh,93h			;ES_access
		mov	word ptr ds:[814h],bx	;put into loadall_table
		xchg	bl,bh			;ES_access into BL
;						;ES_base16_23 into BH

		mov	di,word ptr ds:[848h][4];DS_limit0_15 to loadall_table
		mov	word ptr ds:[818h],di
		mov	di,word ptr ds:[848h][0];DS_base0_15 to loadall_table
		mov	word ptr ds:[81Ah],di
		mov	cl,byte ptr ds:[848h][2];DS_base16_23
		mov	ch,93h			;DS_access
		mov	word ptr ds:[81Ch],cx	;put into loadall_table
		xchg	cl,ch			;DS_access into BL
;						;DS_base16_23 into BH
		test	bh,0F0h			;ES_base20_23 > 1M byte?
		jnz 	short load_a1		;if above, check (DS)-base next
		test	si,0Fh			;ES_base0_3, aligned 16?
		jnz	short load_a1		;not paragraph aligned
;						;(ES) is within real
		shr	si,4			;aaaaaaaa:aaaa0000 >> 4
		xor	bl,bl
		shl	bx,4			;0000aaaa:00000000 << 4
		or	si,bx			;(SI) has ES_real
		mov	es,si			;load ES segment register real
;
load_a1:
		test	ch,0F0h			;DS_base20_23 > 1M byte?
		jnz 	short load_a2		;if above, check (DS)-base next
		test	di,0Fh			;DS_base0_3, aligned 16?
		jnz	short load_a2		;not paragraph aligned
;						;(ES) is within real
		shr	di,4			;aaaaaaaa:aaaa0000 >> 4
		xor	cl,cl
		shl	cx,4			;0000aaaa:00000000 << 4
		or	di,cx			;(DI) has DS_real
		mov	ds,di			;load DS segment register real
;
load_a2:
		mov	al,bl			;if DS and ES already set up real,
						; we are done
		or	al,cl
		jz	short load_a_iret

		lgdt	fword ptr cs:[Loadall_GDTaddr] ;prepare for protected mode
		smsw	ax
		or	ax,01h			;set PE_BIT in MSW for prot mode
		lmsw	ax

		db	0EAh			;FAR_JMP $+4,8
		dw	DGROUP:$+4              ;flush queue and load CS selector
		dw	8                       ; and cache

		or	bl,bl			;ES already loaded for real mode?
		jz	short load_a3		;yes - no need to load ES-cache

		mov	ax,10h			;index for ES-descriptor
		mov 	es,ax			;load ES selector and cache

load_a3:
		or	cl,cl			;DS already loaded for real mode?
		jz	short load_a_exit	;yes - no need to load DS-cache

		mov	ax,18h			;index for DS-descriptor
		mov 	ds,ax			;load DS selector and cache
	;
load_a_exit:
		mov	eax,cr0
		and	al,0F0h			;turn off protected mode
		and 	dl,0Eh			;and set status from user MSW's
		or	al,dl
		mov	cr0,eax

		db	0EAh			;FAR_JMP $+4,0F000h
		dw	DGROUP:$+4              ;flush queue and load CS selector
		dw	0F000h
	;
load_a_iret:
		xor	ax,ax
		mov	fs,ax			;using (FS), DS,ES cant be touched
						; here
		pop	word ptr fs:[81Ah]	;restore user's IP from stack
		add	sp,2			;no need to restore cs
		pop	word ptr fs:[818h]	;restore user's flags fro stack
		mov	ss,ax
		mov	sp,826h
		popa				;lodall general registers
		mov	sp,word ptr ss:[82Ch]	;set user stack pointer seperately
		sub	sp,6			;set SP to flags,CS,IP for IRET
		mov	ss, word ptr ss:[820h]	;set user stack segment
		iret
LOADALL		ENDP

;Function : IRQ0 ( INT 8 ) service routine for timer tick
		public	TIMER_VECT		;for map file
TIMER_VECT	PROC	NEAR

		STI
		PUSH	DS			; some app. programs that use
						; 1CH as timer ticks
		PUSH	SI			; require that DS,AX,DX are
						; saved at time of 1CH
		MOV	SI,G_RAM		; so have to (see below)
		MOV	DS,SI
		ASSUME	DS:G_RAM
		MOV	SI,OFFSET LOW_8254_CNT	; address them
		ADD	WORD PTR [SI],1
		ADC	WORD PTR [SI+2],0
		CMP	WORD PTR [SI+2],18H	; see if next day
		JNE	SHORT T3
		CMP	WORD PTR [SI],0B0H
		JNE	SHORT T3
		MOV	WORD PTR [SI],0		; clear time and set overflow
		MOV	WORD PTR [SI+2],0
		MOV	BYTE PTR [SI+4],1
T3:		POP	SI			; recover si
		PUSH	AX
		PUSH	DX			; diskette time out check
		cmp	BYTE PTR DS:[MOTOR_OFF_WAIT],0
		je	SHORT T4

		DEC	BYTE PTR DS:[MOTOR_OFF_WAIT]
		JNZ	SHORT T4
		AND	BYTE PTR DS:[MOTOR_ON_IND],0F0H	; drive run flags
		MOV	DX,3F2H			; and kill controller
		MOV	AL,0CH
		OUT	DX,AL

T4:		INT	1CH			; do user timer tick

		CLI
;------ stop interrupts before iret
		MOV	AL,END_OF_INT		; CLEAR 8259
		OUT	A8259,AL		; and clear interrupt
		POP	DX
		POP	AX
		POP	DS
		IRET
TIMER_VECT	ENDP

;Function : IRQ service routine for floppy access
DSKINT_VECT	PROC	NEAR
		PUSH	AX
		PUSH	DS
		MOV	AX,G_RAM
		MOV	DS,AX
		ASSUME	DS:G_RAM
		OR	NEED_RECAL,80H

		MOV	AL,END_OF_INT	;End Of interrupt
		OUT	A8259,AL	;8259
		MOV	AX,9101H	;call "interrupt complete" function
		POP	DS
		INT	15h
		POP	AX
		IRET
DSKINT_VECT	ENDP

KILL_MACHINE:	MOV	AL,0FEH		;reset CPU
		OUT	STAT8042,AL
SHUT_HLT:	CLI
		HLT
		JMP	SHORT SHUT_HLT

;[]==============================================================[]
;
;INT19_VECT:
;
;	Read O/S boot block in at 0000:7C00h and jumps to it.
;
;Saves:	NONE
;Entry: NONE
;Exit:	NONE
;
;[]==============================================================[]

		public	INT19_VECT		;for map file
INT19_VECT	PROC	NEAR

;R153 -start
ifdef	Bootblock_16K_Support
ifdef	Automatic_Load_Awdflash
		include	ReadCom.EQU		;R187
;R186 start
;R187		extrn	LOAD_AWDFLASH:near
		extrn	LOAD_AWDFLASH_Str:near	;R187
		extrn	LOAD_AWDFLASH_LEN:ABS
;R187		extrn	STACKSIZE:ABS
		extrn	BT_INITIAL_PARA1:Far
		extrn	READ_FDD_FILE_TO_MEMORY:Far
;R187		extrn	AWD_STACKSIZE:ABS
		extrn	BT_INITIAL_PARA2:Far
;R186 end

	Load_Again:

		lea	ax,Load_Awdflash_Str ;R187		; Show string
;R187		lea	ax,Load_Awdflash		; Show string
		mov	cx,Load_Awdflash_Len
		mov	dx,0FF01h
		call	Display_Str

		push	sp
 		push	bp

		sub	sp,STACKSIZE
		mov	bp,sp

		;--------------------------------
		;During BOOTBLOCK ....

		fcall	Bt_Initial_Para1

		fcall	Read_Fdd_File_To_Memory		; No error ?
		jnc	short Load_Awdflash_OK		; YES

	Get_Key_Again:

		add	sp,STACKSIZE
 		pop	bp
		pop	sp

		xor	ah,ah				;wait ENTER key
		int	16h
		cmp	ah,1ch
		jne	short Get_Key_Again

		jmp	short Load_Again

	Load_Awdflash_OK:

 		pop	bp
		pop	sp

		;Modify SS/SP/BP for run awdflash.exe
;R187		mov	ax,2000h 			; SS:SP
		mov	ax,Awd_Source_Value	;R187
		mov	ss,ax
		mov	sp,0FFFFh

		sub	sp,AWD_STACKSIZE		; BP
		mov	bp,sp

		; Initial some value for awdflash.exe
		fcall	Bt_Initial_Para2

	;------------------------------------------
	; Now, awdflash.exe in ss:Assign_COM_Buf_Segment(2000h)
	;------------------------------------------
	; Assume Size of header is 200h

;R187		mov	ax,2000h
		mov	ax,Awd_Source_Value	;R187
;R154A		add	ax,20h
		mov	ds,ax				;R154A
		add	al,byte ptr ds:[08h]  		;R154A
		push	ax				;Segment
		push	word ptr 0
		retf

endif	;Automatic_Load_Awdflash
endif	;Bootblock_16K_Support
;R153 -end

ifndef	Automatic_Load_Awdflash			;R153A

new_dsk:
		xor	dx,dx
		mov	es,dx			; set to load at 0:offset Boot

		mov	bx,offset Boot		; location to load boot sector
		mov	cx,1			; set to read one sector

		xor	ax,ax
		int	13h			; reset disk

		mov	ax,0201h		; read boot record
		int	13h			; read disk
		jc	short Boot_fail

		call	Check_Boot_Record	; check boot sector valid ?
		jc	short Boot_fail		; invalid boot sector.
		jmp	far ptr Boot  		; go to boot code
Boot_Fail:
		lea	ax,Bad_Disk_Msg		; boot failed
		mov	cx,Bad_Disk_Msg_Len
		call	Disk_Fail_Routine
		xor	ax,ax			; g_ram
		jmp	short new_dsk

endif	;Automatic_Load_Awdflash		;R153A

Disk_Fail_Routine:

		mov	dx,0ff01h
		call	Display_Str

	;Beep out if no bootable media
		mov	bl,2			; beep on override
		mov	cx,1700h
		call	SND_SPKR_TONE
		xor	cx,cx
		loop	short $
		mov	bl,5			; beep on override
		mov	cx,3000h
		call	SND_SPKR_TONE

	;wait for "Enter" key to continue
endless:
		xor	ah,ah			;wait ENTER key
		int	16h
		cmp	ah,1ch
		jne	short endless

		ret


INT19_VECT	ENDP

;[]==============================================================[]
;
;CHECK_BOOT_RECORD:
;
;	Checks to see if boot record read from disk or diskette
;	is valid.
;
;
;Saves:	NONE
;
;Entry: DI	0 = floppy, 1 = fixed
;	DS:BOOT	boot record
;
;Exit:	C	Set if invalid boot record
;
;Author: Award
;Date:   04/18/90
;
; Name | Date	    | Description
; ---------------------------------------------------------------
; TIM | 18-Apr-90   | Initial revision
;
;[]==============================================================[]

CHECK_BOOT_RECORD PROC	NEAR
		push	bx
		push	cx

		mov	ax,word ptr ds:[Boot]	; read the 1st word

		cmp	al,5			; if 1st byte is an add op
		jbe	short cbr_fail		; then its invalid.

		mov	cx,8			; check for formatted diskette
		xor	bx,bx			; by seeing if 1st 9 are same.

		ALIGN	4
check_formatted:
		inc	bx			; have a fill pattern if they
		inc	bx			; haven't been written to.)
		cmp	ax,word ptr ds:Boot[bx]
		loope	short check_formatted

		clc				; success
		jne	short cbr_exit

cbr_fail:
		stc

cbr_exit:
		pop	cx
		pop	bx
		ret
CHECK_BOOT_RECORD ENDP

;[]=============================================================[]
; Procedure Name:	buffer_8042_full
;	Check for 8042 input buffer full
; Saves:
; Inputs:	none
; Output:	al = status register value
;		zf = 0 : input buffer full
;		zf = 1 : no input buffer full
; Destroy:	al, cx
; Author:	Ken Chen
; Date: 	06/21/90
;
; Rev	| Name	| Date		| TPR#	| Description
; ------+-------+---------------+-------+-----------------------
; 1.00	| Ken	| 06/21/90	| NEW	| Initial revision
;
;[]=============================================================[]
		PUBLIC	BUFFER_8042_FULL
BUFFER_8042_FULL PROC	NEAR

		xor	cx,cx
inrck1:
		in	al,STAT8042
		NEWIODELAY

		and	al,IBF_8042
		loopnz	short inrck1
		ret
BUFFER_8042_FULL ENDP

;[]=============================================================[]
; Procedure Name:	out_8042
;
;	Output a command to 8042 port 64h
;
; Inputs:	al = command byte
; Output:	zf = 0 : keyboard controller error
;		zf = 1 : successful
; Destroy:	ax, cx
; Author:	Ken Chen
; Date: 	06/21/90
;
; Rev	| Name	| Date		| TPR#	| Description
; ------+-------+---------------+-------+-------------------------------------
; 1.00	| Ken	| 06/21/90	| NEW	| Initial revision
;
;[]=============================================================[]
		PUBLIC	OUT_8042
OUT_8042	PROC	NEAR

		mov	ah,al			; save al
		call	Buffer_8042_Full	; wait till buffer empty, then
		jnz	out_8042_ret

		mov	al,ah
		out	STAT8042,al		; send command
		call	Buffer_8042_Full
out_8042_ret:
		ret
OUT_8042	ENDP

;[]=============================================================[]
; Procedure Name:	out_8042_full
;	Check for 8042 output buffer full
; Saves:
; Inputs:	none
; Output:	al = status register value
;		zf = 0 : output buffer full
;		zf = 1 : no output buffer full
; Destroy:	ax, cx
; Author:	Ken Chen
; Date: 	06/21/90
;
; Rev	| Name	| Date		| TPR#	| Description
; ------+-------+---------------+-------+-------------------------------------
; 1.00	| Ken	| 06/21/90	| NEW	| Initial revision
;
;[]=============================================================[]
		PUBLIC	OUT_8042_FULL
OUT_8042_FULL	PROC	NEAR
		mov	ah,12
otrck:
		xor	cx,cx
inrck:
		in	al,STAT8042
		NEWIODELAY

		test	al,OBF_8042
		jnz	short onret

		loop	short inrck

		dec	ah
		jnz	short otrck
onret:
		ret
OUT_8042_FULL	ENDP

;[]=============================================================[]
;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
;   	INPUT: BX:CX = number of refresh periods to wait
;     	       (refresh periods = 1 per 30 microseconds on most machines)
;	OUTPUT: BX:CX destroyed.
;
;	SAVES:	AX (except when NO STACK)
;
;	NOTES:	This routine can be (and is) used with no stack. When
;		used this way, AX is assumed to be destroyed.
;
;[]=============================================================[]

		PUBLIC	WAIT_REFRESH
WAIT_REFRESH	PROC	NEAR
		PUSH	AX			; save ax.

		ALIGN	4
WR_OUTER_LP:
WR_INNER_LP:
WR_STATE_0:	IN	AL,SYS1
		TEST	AL,010H
		JZ	SHORT WR_STATE_0

		ALIGN	4
WR_STATE_1:	IN	AL,SYS1
		TEST	AL,010H
		JNZ	SHORT WR_STATE_1
		LOOP	SHORT WR_INNER_LP

		OR	BX,BX
		JZ	SHORT WR_EXIT
		DEC	BX
		JMP	SHORT WR_OUTER_LP

WR_EXIT:	POP	AX			; restore ax
		RET
WAIT_REFRESH	ENDP

;[]=============================================================[]
;WAIT_FOR_MEM:	Waits for a bit at a specified memory location pointed
;		to by ES:[DI] to become set.
;INPUT:
;	AH=Mask to test with.
;	ES:[DI] = memory location to watch.
;	BH:CX=Number of memory refresh periods to delay.
;		(normally 30 microseconds per period.)
;OUTPUT:
;	AH=  0 if got pattern.
;	    80h if timeout.
;	DX= preserved
;	AL,BH:CX destroyed.
;	BL preserved.
;[]=============================================================[]

		ALIGN	4			; 303A
		public	WAIT_FOR_MEM		;R186
WAIT_FOR_MEM	PROC	NEAR

;WFM_LONG:  Wait for memory when refresh pulse is long (80Us to 5 Ms)

WFML_OUTER_LP:	OR	CX,CX			; if 1st entry,
		JNZ	SHORT WFML_CHECK_MEM_HI	; begin testing
		OR	BH,BH			; check outer counter
		JZ	SHORT WFML_TIMEOUT	; then were done.
		DEC	BH

		ALIGN	4
WFML_CHECK_MEM_HI:
		TEST	ES:[DI],AH
		JNE	SHORT WFML_GOT_BIT	; got the bit
		IN	AL,SYS1		; wait for lo to hi
		TEST	AL,010H			; transition on memory
		JNZ	SHORT WFML_CHECK_MEM_HI	; refresh.

		ALIGN	4
WFML_CHECK_MEM_LO:
		TEST	ES:[DI],AH
		JNE	SHORT WFML_GOT_BIT	; got the bit
		IN	AL,SYS1		; wait for lo to hi
		TEST	AL,010H			; transition on memory
		JZ	SHORT WFML_CHECK_MEM_LO	; refresh.

		LOOP	SHORT WFML_CHECK_MEM_HI
		JMP	WFML_OUTER_LP

WFML_TIMEOUT:	MOV	AH,80H			; fail
		JMP	SHORT WFML_EXIT

WFML_GOT_BIT:	XOR	AH,AH			; success
WFML_EXIT:	RET
WAIT_FOR_MEM	ENDP

;[]=============================================================[]
;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
;		go on.
;INPUT:
;	AH=Mask for isolation bits.
;	AL=pattern to look for.
;	DX=Port to test for
;	BH:CX=Number of memory refresh periods to delay.
;		(normally 30 microseconds per period.)
;OUTPUT:
;	AH=  0 if got pattern.
;	    80h if timeout.
;	AL= Last read of port.
;	DX= preserved
;	BH:CX destroyed.
;	BL preserved.
;[]=============================================================[]

		ALIGN	4			; 303A
		public	WAIT_FOR_PORT		;R186
WAIT_FOR_PORT	PROC	NEAR

;WFP_LONG:  WAIT FOR PORT, if refresh cycle is long. (81Us to 5 ms range)

		PUSH	BX			; save outer counter.
						; and BL register.
		MOV	BH,AL			; matching pattern to bh.
WFPL_OUTER_LP:
		OR	CX,CX			; if 1st entry,
		JNZ	SHORT WFPL_CHECK_HI	; begin testing
		POP	CX			; get outer counter off stack
		DEC	CH			; decrement it.
		PUSH	CX			; back on stack, preserving
						; original bl.
		CMP	CH,0FFH			; if ch was just, zero
		JZ	SHORT WFPL_TIMEOUT	; then were done.
		XOR	CX,CX
		ALIGN	4			; 303A
WFPL_CHECK_HI:
		IN	AL,DX			; read port
		MOV	BL,AL			; save it.
		AND	AL,AH			; isolate bits.
		CMP	AL,BH			; check for match.
		JE	SHORT WFPL_GOT_PATTERN	; got the bit
		IN	AL,SYS1		; wait for hi to lo
		TEST	AL,010H			; transition on memory
		JNZ	SHORT WFPL_CHECK_HI	; refresh.

		ALIGN	4			; 303A
WFPL_CHECK_LO:
		IN	AL,DX			; read port
		MOV	BL,AL			; save it.
		AND	AL,AH			; isolate bits.
		CMP	AL,BH			; check for match.
		JE	SHORT WFPL_GOT_PATTERN	; got the bit
		IN	AL,SYS1		; wait for lo to hi
		TEST	AL,010H			; transition on memory
		JZ	SHORT WFPL_CHECK_LO	; refresh.

		LOOP	SHORT WFPL_CHECK_HI
		JMP	WFPL_OUTER_LP

WFPL_TIMEOUT:	MOV	AH,80H			; fail
		JMP	SHORT WFPL_EXIT

WFPL_GOT_PATTERN:
		XOR	AH,AH			; success

WFPL_EXIT:	MOV	AL,BL			; recover last read of port.
		POP	BX			; preserve bl.
		RET
WAIT_FOR_PORT	ENDP

;---------------- Error Message String -----------------------
Floppy_err_MSG:
			DB	'Drive A error. System halt',CR,LF
Floppy_err_MSG_LEN	EQU	$ - offset Floppy_err_MSG

BAD_DISK_MSG:
		DB	'DISK BOOT FAILURE, INSERT SYSTEM DISK AND PRESS ENTER'
BAD_DISK_MSG_LEN	EQU	$ - offset BAD_DISK_MSG

KCTRL_ERR_MSG:
ifndef	Show_Post_Error_Code						;R173
			db	'Keyboard controller error'
else;	Show_Post_Error_Code						;R173
			db	' 303 Keyboard controller error'	;R173
endif;	Show_Post_Error_Code						;R173

KCTRL_ERR_MSG_LEN		EQU	$ - offset KCTRL_ERR_MSG

KBD_ERR_MSG:
ifndef	Show_Post_Error_Code						;R173
			db	'Keyboard error or no keyboard present'
else;	Show_Post_Error_Code						;R173
			db	' 301 Keyboard error or no keyboard present'	;R173
endif;	Show_Post_Error_Code						;R173
KBD_ERR_MSG_LEN		EQU	$ - offset KBD_ERR_MSG

BIOS_CKSM_ERROR_MSG:
ifndef	Show_Post_Error_Code						;R173
			db	'BIOS ROM checksum error'
else;	Show_Post_Error_Code						;R173
			db	' 114 BIOS ROM checksum error'		;R173
endif;	Show_Post_Error_Code						;R173
BIOS_CKSM_ERROR_MSG_LEN	EQU	$ - offset BIOS_CKSM_ERROR_MSG

Detect_Disk_MSG		db	CR,LF,'Detecting floppy drive A media...'
Detect_Disk_MSG_LEN	EQU	$ - offset Detect_Disk_MSG

Disk_MSG		db	'Drive media is : '
Disk_MSG_LEN		EQU	$ - offset Disk_MSG

Media_MSG		db	'1.44Mb',CR,LF
Media_MSG_LEN		EQU	$ - offset Media_MSG
			db	'1.2Mb ',CR,LF
			db	'720Kb ',CR,LF
			db	'360Kb ',CR,LF

;[]========================================================================[]
;Name:   	Multi_service - Cassette_IO and 286 virtual mode extensions
;Entry:  	INT 15H
;Input:  	see individual functions
;Output: 	see individual functions
;Description:
;1. 	save environment
;2. 	perform function
;3. 	restore environment
;4. 	return to POI
;[]========================================================================[]
		PUBLIC	Multi_Service
		ALIGN	4
Multi_Service	PROC	far
		cmp	ah,90h
		jne	short @F
		xor	ah,ah
		sti
		ret	2
@@:
		cmp	ah,91h
		jne	short @F
		xor	ah,ah
@@:
		iret
Multi_Service	ENDP

ifdef Reallocate_EarlyIO				;R78A
		include	earlyio.asm			;R78A
endif ;Reallocate_EarlyIO				;R78A

;R150 - start
INT1A_VECT 	proc	far

ifndef	No_Support_PCI_VGA_in_Bootblock		;R150A
ifdef	Bootblock_16K_Support
 		cmp	ah,0B1h		;pci func ?
		jne	short @f
		extrn	PCI_Procedure:near	;R186
		jmp	PCI_Procedure
@@:
endif	;Bootblock_16K_Support
endif	;No_Support_PCI_VGA_in_Bootblock       	;R150A

   		stc
		iret

INT1A_VECT 	endp
;R150 - end

;R99-start
ifdef VLSI_Special_Reset
Special_RST_VECT:
		shl	edx,10h		;Save dx (cpu type).

;Set 82C543 Reg04h bit0,1,2
		mov     eax,80000804H  ;Set 82C543 Register Base Index=04.
		mov     dx,0CF8H
		out     dx,eax
		mov     dl,0FCH        ;
		in      al,dx
		mov     bl,al          ;Index = 04; bit 0,1,2 set 1.
		or      bl,07H         ;Enable (1)I/O Access
		mov     al,04H	       ;       (2)Memory Access
		mov     dl,0F8H        ;       (3)Bus Master
		out     dx,eax
		mov     dl,0FCH
		mov     al,bl
		out     dx,al
ifdef VLSI_Special_Reset_Delay		;R107A
;Enabled E000 & F000 Segment (BIOS ROM) for VLSI Lynx Chipset.
		mov	eax,80000858h	;Set 82C543 Register Base Index=58.
		mov	dx,0CF8H
		out	dx,eax
		mov	dl,0FEH		;Index=Index+2.
		in	al,dx
		mov	bl,al		;Index = 5A; bit 7,6,5 set 1.
		or	bl,0E0H		;enable E000 & F000 ROM.
		mov	al,58H
		mov	dl,0F8H
		out	dx,eax
		mov	dl,0FEH
		mov	al,bl
		out	dx,al

		xor	cx,cx		;R107
		loop	$		;R107
endif ;VLSI_Special_Reset_Delay		;R107A

		shr	edx,10h		;restor dx (cpu type)
		FAR_JMP <offset DGROUP:RST_VECT>,0F000H
endif ;VLSI_Special_Reset
;R99-end


;R184 ifdef	Bootblock_16K_Support			;R153
		CK_ORG	0FFE8h 			;R153
		db	BIOS_ID			;R153
;R184 endif	;Bootblock_16K_Support			;R153


		CK_ORG  0FFF0h
;CPU start running from here ( CPU reset )
;R99-start
ifdef VLSI_Special_Reset
                JMP     Special_RST_VECT
		db	90h	;nop
		db	90h	;nop
else ;VLSI_Special_Reset
                FAR_JMP <offset DGROUP:RST_VECT>,0F000H
endif ;VLSI_Special_Reset
;R99-end
;R92 start
		db	'*MRB*'		;modbin revision byte
;R101		dd	0
;		dd	1		;R101
;MRB value = 2 for new default password set it by MODBIN.EXE v4.50.60 or later
		dd	2
;R92 start

@DATAC		ENDS
endif	;BootROM_Code			;R186
;R186		END	RST_VECT
		END			;R186
